当前位置: 首页 > 知识库问答 >
问题:

为什么我的服务器崩溃时,我运行超过1个几乎完全相同的java servlet?

余靖
2023-03-14

我正在tomcat 7 VPS服务器上运行2个java(7)servlet。一个servlet返回json响应,另一个servlet返回4行纯html代码

如果我只运行json响应servlet,我每天处理1200万请求(每秒约140个请求)没有问题。

目前,我在json servlet上只运行了一半的流量(每秒约70个请求)。

如果我添加返回html的servlet,当这个servlet的请求数量甚至没有达到每秒20个时,服务器响应时间会爆炸并返回错误。(所以请求的总量约为每秒90个)。

然而,如果对html servlet的请求下降到每分钟2次,一切都很好。所以看起来servlet本身没有任何错误。

我正在运行的两个servlet是:

// Loading required libraries
import java.lang.*;
import java.io.*;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import javax.sql.DataSource;
import javax.naming.*;
import java.util.Random;
import java.math.*;
import java.security.*;
import java.sql.*;

/**
 * Servlet implementation class test
 */
@WebServlet("/html")
public class html extends HttpServlet{
    private static final long serialVersionUID = 12L;

    public html() {
        super();
        // TODO Auto-generated constructor stub
    }
    private DataSource dataSource;

    public void init() throws ServletException {
        try {
            // Get DataSource
            Context initContext  = new InitialContext();
            Context envContext  = (Context)initContext.lookup("java:/comp/env");
            dataSource = (DataSource)envContext.lookup("jdbc/testdb");
            System.out.println("Obtained Cached Data Source ");

        } catch (NamingException e) {
            e.printStackTrace();
        }
    }
public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
            throws ServletException, IOException
  {

      // Get all parameters from request.

      String source = null;
      String UA = null;
      String id = null;
      String ip = null;

      source = request.getParameter("source");
      UA = request.getHeader("User-Agent");
      //is client behind something?
      ip = request.getHeader("X-FORWARDED-FOR");  
      if (ip == null) {  
           ip = request.getRemoteAddr();  
       }


      Connection conn = null;
      Statement stmt = null;
      int exit = 0;

      // Set response content type
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      try{
         // Open a connection
         conn = dataSource.getConnection();
         stmt = conn.createStatement();
         // Execute SQL query
         stmt = conn.createStatement();
         String sql;
         sql =  "SELECT data from db";
         ResultSet rs = stmt.executeQuery(sql);

         rs.next();
         String url = rs.getString("url");
         String url_src = rs.getString("url_src");



    out.println("<html>");
    out.println("<body>");
    out.println("<a href=\"url\">");
    out.println("<img src=\"url_src\"/></a>");
    out.println("</body></html>");


     long time = System.currentTimeMillis()/1000;

     Random randomGenerator = new Random();
     int randomInt = randomGenerator.nextInt(250);
     String toEnc =  ip + time + UA + randomInt; // Value to hash
     MessageDigest mdEnc = MessageDigest.getInstance("MD5"); 
     mdEnc.update(toEnc.getBytes(), 0, toEnc.length());
     id = new BigInteger(1, mdEnc.digest()).toString(16);// Hashed

     sql = "insert request";
     stmt.execute(sql);




         // Clean-up environment
         rs.close();
         stmt.close();
         conn.close();
      }catch(SQLException se){
         //Handle errors for JDBC
         se.printStackTrace();
      }catch(Exception e){
         //Handle errors for Class.forName
         e.printStackTrace();
      }finally{
         //finally block used to close resources
         try{
            if(stmt!=null)
               stmt.close();
         }catch(SQLException se2){
         }// nothing we can do
         try{
            if(conn!=null)
            conn.close();
         }catch(SQLException se){
            se.printStackTrace();
         }//end finally try
      } //end try*/

   }
}

第二个servlet是:

// Loading required libraries
import java.lang.*;
import java.io.*;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import javax.sql.DataSource;
import javax.naming.*;
import java.util.Random;
import java.math.*;
import java.security.*;
import java.sql.*;

/**
 * Servlet implementation class test
 */
@WebServlet("/json")
public class json extends HttpServlet{
    private static final long serialVersionUID = 11L;

    public json() {
        super();
        // TODO Auto-generated constructor stub
    }
    private DataSource dataSource;

    public void init() throws ServletException {
        try {
            // Get DataSource
            Context initContext  = new InitialContext();
            Context envContext  = (Context)initContext.lookup("java:/comp/env");
            dataSource = (DataSource)envContext.lookup("jdbc/testdb");
            System.out.println("Obtained Cached Data Source ");

        } catch (NamingException e) {
            e.printStackTrace();
        }
    }
public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
            throws ServletException, IOException
  {

      // Get all parameters from request.

      String source = null;
      String UA = null;
      String id = null;
      String ip = null;


      source = request.getParameter("source");
      UA = request.getParameter("ua");
      ip = request.getParameter("clientIP");

      Connection conn = null;
      Statement stmt = null;
      int exit = 0;

      // Set response content type
      response.setContentType("application/json");
      PrintWriter out = response.getWriter();

      try{
         // Open a connection
         conn = dataSource.getConnection();
         stmt = conn.createStatement();
         // Execute SQL query
         stmt = conn.createStatement();
         String sql;
         sql =  "SELECT * from db";
         ResultSet rs = stmt.executeQuery(sql);

         rs.next();
         String url = rs.getString("url");
         String url_src = rs.getString("url_src");



         String jsonResponse = "{\"url\":\"url\","\"media_url\":\"url_src\"}";
         out.println(jsonResponse);

         long time = System.currentTimeMillis()/1000;

         Random randomGenerator = new Random();
         int randomInt = randomGenerator.nextInt(250);
         String toEnc = ip + time + UA + randomInt; // Value to hash
         MessageDigest mdEnc = MessageDigest.getInstance("MD5"); 
         mdEnc.update(toEnc.getBytes(), 0, toEnc.length());
         id = new BigInteger(1, mdEnc.digest()).toString(16);// Hashed

         sql = "insert request";
         stmt.execute(sql);




         // Clean-up environment
         rs.close();
         stmt.close();
         conn.close();
      }catch(SQLException se){
         //Handle errors for JDBC
         se.printStackTrace();
      }catch(Exception e){
         //Handle errors for Class.forName
         e.printStackTrace();
      }finally{
         //finally block used to close resources
         try{
            if(stmt!=null)
               stmt.close();
         }catch(SQLException se2){
         }// nothing we can do
         try{
            if(conn!=null)
            conn.close();
         }catch(SQLException se){
            se.printStackTrace();
         }//end finally try
      } //end try*/

   }
}

我已经用JDBC设置了一个连接池。我有以下config.xml文件:

<?xml version='1.0' encoding='utf-8'?>
    <!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!-- The contents of this file will be loaded for each web application -->
<Context>

    <!-- Default set of monitored resources -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>

    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--
    <Manager pathname="" />
    -->

    <!-- Uncomment this to enable Comet connection tacking (provides events
         on session expiration as well as webapp lifecycle) -->
    <!--
    <Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
    -->

    <Resource name="jdbc/testdb" 
    auth="Container" 
    type="javax.sql.DataSource" 
    driverClassName="com.mysql.jdbc.Driver" 
    url="jdbc:mysql://localhost:3306/database" 
    username="username" 
    password="password" 
    maxActive="250" 
    maxIdle="60"
    minIdle="30" 
    maxWait="10000"
    poolPreparedStatements="true"
    maxOpenPreparedStatements="100"
    />


</Context>

我已经在文件/tomcat/bin/setenv中设置了环境变量或JAVA_选项。上海:

export CATALINA_OPTS="-Djava.library.path=/usr/local/apr/lib"

NORMAL="-d64 -Xmx1536m -Xms512m -server"
MAX_PERM_GEN="-XX:MaxPermSize=512m"
HEADLESS="-Djava.awt.headless=true"

JAVA_OPTS="$NORMAL $MAX_PERM_GEN $HEADLESS"
export JAVA_OPTS

我的vps有2gb的ram,4个2ghz的cpu核。我尝试过改变堆大小或MaxPermSize,但这似乎并不重要。

有人能解释一下我的配置有什么问题吗?我不明白为什么服务器只需一个servlet就可以处理这么多负载,而当流量被另一个servlet分割时,服务器就会崩溃。

谢啦

共有1个答案

钱承允
2023-03-14

Hagubear感谢您提供的信息,但问题出在这对夫妇身上。println()语句。在这个线程中[1]:不要使用系统。出来服务器端代码中的println

我发现使用这个是不好的做法。现在我只把它放进了1个。println()和服务器工作得更好。

谢谢

 类似资料:
  • 问题内容: 当我退出“活动”退出(通过“后退”按钮)时,我的应用程序崩溃。据我所知,这是在Android代码库中发生的,而不是我的,但是我并不完全相信。 这是来自adb的stacktrace: 有人有什么想法/建议吗? 问题答案: 无助,因为没有代码。还在看 造成原因:android.app.Activity.performStop(Activity.java:3575)上的java.lang.N

  • 我已经签署了一个应用程序与我创建的标志。我已经在我的手机里安装了这个apk,这是可以的,但是当我尝试打开应用程序时,它崩溃了(没有显示任何活动),并且它没有给我看日志的机会(这个对话框没有报告按钮) 问题是我在应用程序上的签名。我已经测试了其他标志和应用程序打开完美。我不能发布任何关于创建标志的信息,但只有我可以说我使用了: 其他字段为空。 主要的问题是这个应用程序是在google play中发布

  • 严重:初始化连接器[connector[HTTP/1.1-8080]]org.apache.catalina.LifecyCleException失败:尝试为组件[connector[HTTP/1.1-8080]]进行无效的生命周期转换([before_init]),该组件处于状态[INITIALIZED],位于org.apache.catalina.util.LifecyCleBase.inva

  • 认证之后,如果我调用任何方法,比如< code>os.compute()。口味()。list()或< code>os.images()。list(),我得到< code >连接超时。为什么会这样? 我在GoogleCloudsPlataform VM上设置了一个带有RDO包堆栈的OpenStack。我正在对域和项目进行身份验证。我尝试了没有项目的身份验证,方法调用没有超时,但是响应是错误的,例如,

  • 所以我对这个网站很陌生,但你们是我最后的希望。这里的目标是,用户将输入10华氏温度(输入-999停止输入),然后程序将这些温度改为摄氏。此外,用户还需要键入他们的位置。我可以输入位置,但在我点击“Enter”后,我得到: 在java.util.scanner.throwfor(未知源) 在java.util.scanner.next(未知源) 在java.util.scanner.nextint(