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

当我运行超过1个几乎相同的java servlet时,为什么我的服务器会崩溃?,java,tomcat,servlets,config,Java,Tomcat,Servlets,Config,我正在Tomcat7VPS服务器上运行2个java(7)servlet。一个servlet返回json响应,另一个servlet返回4行纯html代码 如果我只运行json响应servlet,那么每天处理1200多万个请求(每秒约140个请求)不会有问题 目前,我在json servlet上只运行了一半的流量(每秒约70个请求) 如果我添加一个返回html的servlet,那么当这个servlet的请求数甚至没有达到每秒20个时,服务器响应时间就会爆炸并返回错误。(因此请求总量约为每秒90次)

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

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

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

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

但是,如果对HTMLServlet的请求降至每分钟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*/

   }
}
我已经用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>
我的vps有2gb的ram,有4个2ghz的cpu核。我尝试过改变堆大小或MaxPermSize,但这似乎并不重要

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


谢谢你提供的信息,不过问题出在两个out.println()语句中。在此线程[1]中:

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


谢谢

您好,server.xml文件是标准的。连接器设置为:威胁数的默认值为200,这应该足够了。美国的平均响应时间为90毫秒,因此平均只需要10-15次威胁。当使用返回http响应的servlet时,您知道什么会导致服务器高负载吗?谢谢
@user3605780
您是否检查了最大连接或最大可接受连接(或类似属性)的参数?您的
acceptCount
值是多少?默认值始终为100,您可能需要更改该值。您说过您的server.xml是标准的。你不想要标准,是吗?你必须通过我发送给你的链接,找出你需要更改的链接。acceptCount确实是标准的,但是acceptCount适用于使用所有威胁的情况。有200个威胁可用,平均使用15个威胁,此设置不重要,对吗?此外,当仅使用json响应servlet时,服务器甚至不会对两倍的请求产生任何问题。数量:1)Json servlet每天只有1200多万个请求,没问题;2) json servlet 6+百万请求+http servlet每天20000个请求,没有问题;3) json servlet 6+百万请求+http servlet 1+百万请求,服务器立即中断。我检查了catalina.out文件,发现了2个错误,可能是原因:org.apache.tomcat.dbcp.dbcp.SQLNestedException:无法获得连接,池错误超时,等待org.apache.tomcat.dbcp.dbcp.dbcp.poolgDataSource.getConnection(poolgDataSource.java:114)处org.apache.tomcat.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)和:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:数据源拒绝建立连接,来自服务器的消息:“连接太多”但是流量并没有那么大,所以有可能我的连接泄漏到了某个地方吗?
<?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>
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