一些背景
我正在做一个项目,我们有一个从 1999 年开始用 Java EE 1.4 编写的过时的非常简单的书店 Web 应用程序。但是,目的是对其进行现代化改造,以便在 Amazon AWS 等云环境中运行。我们决定从头开始重写它,使用 Spring 框架、Hibernate 和 c3p0 进行连接池。
除了 Web 应用程序,我们还有一个用于 Web 应用程序的压力工具,称为 RBE(远程浏览器模拟器)。您只需告诉 RBE 您想要多少用户,他就会为每个用户创建一个线程。每个线程随机生成 url,只要用户浏览页面(我们定义用户浏览站点 180 秒),它就会这样做。之后,它关闭了一个线程,就是这样。对于每个请求,它需要 HTML 页面源,解析出 jsessionid,然后继续下一个 url。
问题
当我为 400 个用户(即每秒 400 个请求)运行 RBE 时,我很快得到以下异常:
java.net.SocketException: Connection reset by peer
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:382)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:241)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:228)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:431)
at java.net.Socket.connect(Socket.java:527)
at sun.net.NetworkClient.doConnect(NetworkClient.java:158)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:388)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:523)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:227)
at sun.net.www.http.HttpClient.New(HttpClient.java:300)
at sun.net.www.http.HttpClient.New(HttpClient.java:317)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:970)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:911)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:836)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
at rbe.EB.getHTML(EB.java:423)
at rbe.EB.run(EB.java:324)
过了一会儿,当 RBE 尝试浏览其他子页面时,我得到:
java.net.ConnectException: Operation timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:382)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:241)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:228)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:431)
at java.net.Socket.connect(Socket.java:527)
at sun.net.NetworkClient.doConnect(NetworkClient.java:158)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:388)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:523)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:227)
at sun.net.www.http.HttpClient.New(HttpClient.java:300)
at sun.net.www.http.HttpClient.New(HttpClient.java:317)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:970)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:911)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:836)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
at rbe.EB.getHTML(EB.java:423)
at rbe.EB.run(EB.java:324)
EB.java:423)
(发生异常的地方)的代码是:
BufferedReader in = new BufferedReader( new InputStreamReader(connection.getInputStream() ) );
我的my.cnf
配置:
[mysqld]
log=/var/log/mysqld.log
max_connections = 200
log-slow-queries = /var/log/mysqld_slow_queries.log
log-error = /usr/local/mysql/data/mysql-error.log
back-log = 200
key_buffer_size=16M
max_allowed_packet=100M
interactive_timeout=30
wait_timeout=30
Tomcat相关设置server.xml
:
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" acceptCount="500" />
我还做了一个测试,并以 2 秒的延迟提供静态 html 文件,并且没有对数据库进行任何迭代。我做了这个测试,看看 Tomcat 是否不能处理 400 个并发请求。Tomcat 成功通过了这个测试。
400并发访问mysql的瓶颈是什么?这对 MySQL 来说太多了吗?