我在tomcat 7 VPS服务器上运行2个java(7)servlet。一个servlet返回一个json响应,另一个servlet返回4行纯html代码。
如果我只运行json响应servlet,那么每天处理12,000多个请求(每秒约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.sh中设置了envirenment变量或JAVA_OPTS:
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内存,4个cpu内核为2ghz。我尝试过更改堆大小或MaxPermSize,但似乎并不重要。
有人可以向我解释我的配置错误吗?我不明白为什么服务器只用一个servlet就可以处理这么多的负载,当流量被分成另一个时崩溃。
由于
答案 0 :(得分:0)
Hagubear感谢您的信息,但问题出在out.println()语句中。在这个主题[1]中:Do not use System.out.println in server side code
我发现使用这个是不好的做法。现在我只将它放在1 out.println()中,服务器工作得更好。
感谢