目录
Tomcat的并发配置
Nginx实现负载均衡
动静分离
redis实现session共享
Tomcat的并发配置
Tomcat 默认配置的最大请求数是 150,可以将其改大。
具体能承载多少并发,需要看硬件的配置,CPU 越多性能越高,分配给 JVM 的内存越多性能也就越高,但也会加重 GC 的负担。
操作系统对于进程中的线程数有一定的限制:
Windows 每个进程中的线程数不允许超过 2000
Linux 每个进程中的线程数不允许超过 1000
另外,在 Java 中每开启一个线程需要耗用 1MB 的 JVM 内存空间用于作为线程栈之用。
Tomcat的最大并发数是可以配置的,实际运用中,最大并发数与硬件性能和CPU数量都有很大关系的。更好的硬件,更多的处理器都会使Tomcat支持更多的并发。
Tomcat 默认的 HTTP 实现是采用阻塞式的 Socket 通信,每个请求都需要创建一个线程处理。这种模式下的并发量受到线程数的限制,但对于 Tomcat 来说几乎没有 BUG 存在了。
Tomcat 还可以配置 NIO 方式的 Socket 通信,在性能上高于阻塞式的,每个请求也不需要创建一个线程进行处理,并发能力比前者高。但没有阻塞式的成熟。
这个并发能力还与应用的逻辑密切相关,如果逻辑很复杂需要大量的计算,那并发能力势必会下降。如果每个请求都含有很多的数据库操作,那么对于数据库的性能也是非常高的。
对于单台数据库服务器来说,允许客户端的连接数量是有限制的。
并发能力问题涉及整个系统架构和业务逻辑。
系统环境不同,Tomcat版本不同、JDK版本不同、以及修改的设定参数不同。并发量的差异还是满大的。
maxThreads="1000" 最大并发数
minSpareThreads="100"///初始化时创建的线程数
maxSpareThreads="500"///一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。
acceptCount="700"// 指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理
配置实例:
<Connector port="8080" protocol="HTTP/1.1" minSpareThreads="100" maxSpareThreads="500" maxThreads="1000" acceptCount="700" connectionTimeout="20000" redirectPort="8443" />
Nginx实现负载均衡
当某个应用并发不能承载(一般300左右)的时候,应考虑应用服务器的集群。
1、使用Nginx实现负载均衡
2、使用多个Tomcat作为应用服务器
3、静态资源从Tomcat中分离
Nginx端口为8080,反向代理3个Tomcat(8288、8289、8290)。
Tomcat性能优化配置(server.xml):
<!-- 启用APR生命周期监听器,且不使用SSL -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="off" />
<!-- 创建执行器(线程池),指定线程数量 -->
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="1000" minSpareThreads="100"
maxIdleTime="60000"/>
<!-- Connector中使用线程池 -->
<Connector executor="tomcatThreadPool"
port="8290" protocol="org.apache.coyote.http11.Http11AprProtocol"
connectionTimeout="30000" redirectPort="8443" URIEncoding="UTF-8" enableLookups="false"
connectionUploadTimeout="150000" acceptCount="300" keepAliveTimeout="120000"/>
nginX配置文件:
在http节点下配置如下:
# 使用默认策略,轮询
upstream ydzwV3{
# 下面介绍几种负载均衡策略,其中轮询、weight、ip_hash是nginx内置的,可以直接使用。fair和url_hash需要第三方支持才可以使用。
# 1、轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
server localhost:8288;
server localhost:8289;
server localhost:8290; # 2、weight:指定权重,按照权重进行请求的分配。wight和访问比例成正比,适合后端服务器性能不均的情况。
# 下面的配置就会经常访问8288的服务。如果后端服务器8288 down掉,能够立刻切换到8299或者8290。如果8288再次启动,则又能回到原有的权重配置上。8288可以继续提供服务。
# server localhost:8288 weight=10;
# server localhost:8289 weight=1;
# server localhost:8290 weight=1; # 3、ip_hash:每个请求按照ip的hash结果进行分配,这样的话每个访客固定请求一个后端服务器,可以解决session没共享的问题。
# 如果8288 down掉,则依然可以访问,可能会缓存8289或者8290。如果8288启动,则会从8289或8290切换到8288。
# ip_hash;
# server localhost:8288;
# server localhost:8289;
# server localhost:8290; # 4、fair(第三方):后端服务器响应时间短的优先分配。
# fair;
# server localhost:8288;
# server localhost:8289;
# server localhost:8290; # 5、url_hash(第三方):按访问的url的hash结果来分配请求,这样相同url会分配到相同的后端服务器。适合后端服务器有缓存的情况。
# hash $request_uri;
# hash_method crc32;
# server localhost:8288;
# server localhost:8289;
# server localhost:8290;
}
在server节点下配置如下:
listen 8080;
server_name 192.168.1.233; # 这里是服务器的IP或者域名
location /ydzwV3 {
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_pass http://ydzwV3;
}
所以结果是怎样呢?
访问http://192.168.1.233:8080/ydzwV3实际上会把负载分摊到后面的3个Tomcat服务器,也就是说访问http://192.168.1.233:8080/ydzwV3可能是http://localhost:8288/ydzwV3、http://localhost:8289/ydzwV3或http://localhost:8290/ydzwV3给与的响应。
存在的问题:Session没有共享
一个典型的情况:假设进入登录页面是tomcat1基于的响应,所以验证码也会存储在tomcat1的session中。现在输入完用户名、密码和验证码,单击提交,很大可能会提示“验证码错误”,这是因为执行登录请求可能访问的是tomcat2或者tomcat3。所以需要去做Session共享(当然也可以使用ip_hash策略来解决这个问题)。
动静分离
对Nginx进行配置
通过配置location,对访问的请求进行拦截,①②都需要配置。
① 全部的请求均转发给Tomcat进行处理
location / {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_pass http://mycluster;
# 真实的客户端IP
proxy_set_header X-Real-IP $remote_addr;
# 请求头中Host信息
proxy_set_header Host $host;
# 代理路由信息,此处取IP有安全隐患
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 真实的用户访问协议
proxy_set_header X-Forwarded-Proto $scheme;
}
② 个别的请求比如:html,js,css等静态资源请求,由Nginx进行处理
#静态文件交给nginx处理
location ~ .*\.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
{
root /usr/local/webapps;
expires 30d;
}
#静态文件交给nginx处理
location ~ .*\.(js|css)?$
{
root /usr/local/webapps;
expires 1h;
}
root /usr/local/webapps; 这段代码的意思是指定Nginx访问的目录,即静态资源所在的目录。
expires 30d; 指定这些资源文件在客户端浏览器的缓存时间。30d指的是30天,1h指的是1小时。
redis实现session共享
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
实现redis session需要tomcat-redis-session-manager
说明:不同的tomcat版本会有不同的jar包。将会给到tomcat7的jar包和tomcat8的jar包。因为现在网上插件不支持tomcat8。
修改后放在tomcat/lib目录下哦,并非工程的lib目录下呢~
redis实现session是需要在tomcat端配置,
将 redis-tomcat8.jar,commons-pool2-2.4.3.jar, jedis-2.6.2.jar 放入tomcat的lib文件夹中。
修改tomcat的配置文件context.conf,
<!--
com.orangefunction.tomcat.redissessions 是自定义maven项目的报名路径,切需要与maven 中 RedisSessionManager的serializationStrategyClass值一致
-->
<!-- redis session 共享配置 ,没有密码就不写密码--> <Valve className="com.demo.redis_session.RedisSessionHandlerValve" />
<Manager className="com.demo.redis_session.RedisSessionManager"
host="127.0.0.1"
port="6379"
database="0"
password="666"
maxInactiveInterval="60" />
重启tomcat!