一个相对完整的服务部署方案至少应该考虑以下几方面问题:
横向扩展能力
合理的负载分配策略
服务节点异常的处理
传统的服务器主从结构因为在横向扩展能力上的局限性,现已不再采用。目前推荐的的集群部署均采用Nginx做为前端服务器+负载均衡器的方式。
Nginx 做为前端服务器,可以起到以下主要作用:
1) 静态资源请求分流
由于Nginx对于静态资源的处理速度远远大于tomcat, weblogic等主流应用服务器,把所有静态资源请求让Nginx进行处理可以在很大程度上减轻后端服务器的压力,从而将后端服务器处理资源尽可能的用于需要计算的请求,进而加快相应速度。
2)基于策略的负载均衡
Nginx可以灵活的跟据实际场景设置负载分发方式,即便后端服务器资源不平衡,也可以根据根据策略为不同集群后端实例施加不相等,但是合理的负载。
3)抗并发
Nginx采用异步非阻塞处理模型(epoll),在占用内存极低的情况下,默认配置就可支持15000并发请求,在经过适当优化的情况下 (非nginx 集群),甚至能够处理超过50000并发请求。(单个tomcat在处理超过300并发请求的情况下就会出现明显延迟)。
注:Nginx epoll模型实现不支持windows平台
4)为热部署/滚动部署提供可能性
Nginx本身支持热部署,改动配置只需刷新就能生效,这样可以非常容易的实现热部署。
想了解更多关于Nginx? 点这里
如果简单的按照策略分发请求,而不对session做分布式处理的话,就会出现session在某个集群节点上找不到的情况。举个例子:
集群有2个节点 N1和N2, 如果分发策略是承担50%的负载,具体请求随机分发, 那么就会出现用户登陆请求由N1处理,对应session由N1创建,N1保管, 那么当后续请求被派发到N2的时候,N2就会出现找不到session的情况,报session time out.
目前对于此问题有两种解决方案:
粘性session要求Nginx将来自于同一客户端的请求分发到同一个集群实例,这样可以大大简化应用程序对于集群部署环境进行特殊实现的难度。(不需要分布式处理session和缓存)。 但是这样的方案在需要热部署或者对于集群容错性要求很高的场景下,并不能满足需要。
分布式session使用高性能的内存存储服务,如:Redus, Memcache,集中化的存储session数据,集群实例总是从session存储服务中取得session数据,这样可以避免无法找到session的情况。 此方案需要修改session存储实现,并且因为网间访问在效率上相比内存直接存取有数量级的差别,所以会造成一定的效率下降,并且,集中化session存储会带来单点失败的问题,将session存储集群化可以解决,但明显加大了部署的复杂性。
目前框架只支持粘性session的解决方案,如果特定项目对服务的不间断性和容错性有很高的要求,可以联系研发部提供分布式session的解决方案。
对于需要在集群实例间共享访问的资源 (如用户上传的图片,文件),必须集中化管理,否则会出现资源无法找到的错误
在使用以上部署架构以后,因为应用服务的横向扩展能力大大增强(增加集群实例个数会立即提高集群处理能力), DB服务器的处理能力需要被密切关注,否则很容易成为整个集群性能最大的瓶颈。 通常来说,增加硬件,或者集群化DB是首先想到的最快速的解决方案。
1) 下载Nginx 1.14.0 (稳定版)
2)安装
[root@localhost local]# pwd //显示nginx压缩包所在路径
/usr/local
[root@localhost local]# ls //查看压缩包
nginx-1.14.0.tar.gz
[root@localhost local]# tar -zxvf nginx-1.14.0.tar.gz //解压
[root@localhost nginx-1.14.0]# make && make install //进入到nginx解压文件中执行该命令,进行编译、安装。
[root@localhost nginx]# cd sbin/ //进入到sbin目录
[root@localhost sbin]# ./nginx //启动nginx
从浏览器访问我们配置的站点ip:
[root@localhost /]# vim /usr/local/nginx/conf/nginx.conf //编辑配置文件
#设定http服务器,利用它的反向代理功能提供负载均衡支持
http {
#设定mime类型,类型由mime.type文件定义
include /etc/nginx/mime.types;
default_type application/octet-stream;
#设定日志格式
access_log /var/log/nginx/access.log;
#开启gzip压缩
gzip on;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
#设定负载均衡的服务器列表
upstream webapp {
#weigth参数表示权值,权值越高被分配到的几率越大
server 192.168.0.112:8081 weight=4;
server 192.168.0.129:8082 weight=3;
server 192.168.0.130:8083 weight=3;
ip_hash; #粘性session
}
#第一个虚拟服务器
server {
#侦听192.168.8.x的80端口
listen 80;
server_name 192.168.8.x;
location / {
proxy_pass http://webapp; #请求转向mysvr 定义的服务器列表
proxy_next_upstream http_502 http_504 error timeout invalid_header; #错误界面
proxy_set_header Host $host; #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header X-Forwarded-For $remote_addr;
}
}
}
1) 创建资源目录
[root@localhost /]# mkdir /usr/webserver/static/ROOT/ //创建资源目录
2)配置资源请求
[root@localhost /]# vim /usr/local/nginx/conf/nginx.conf //编辑配置文件
location /images/ { //配置所有请求为../images的默认请求到/usr/webserver/static/ROOT/WEB-INF/目录
alias /usr/webserver/static/ROOT/WEB-INF/;
autoindex on;
}
location /css/ { //配置所有请求为../css的默认请求到 /usr/webserver/static/ROOT/WEB-INF/css/目录
alias /usr/webserver/static/ROOT/WEB-INF/css/;
autoindex on;
}
在多台后台服务器的环境下,我们为了确保一个客户只和一台服务器通信,我们势必使用长连接。使用什么方式来实现这种连接 呢,常见的有使用nginx自带的ip_hash和jvm_route两种方式来进行配置。
1)ip_hash
nginx中的ip_hash技术能够将某个ip的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的 session,ip_hash是在upstream配置中定义的:
upstream backend {
server 192.168.12.10:8080 ;
server 192.168.12.11:9090 ;
ip_hash;
}
2) nginx_upstream_jvm_route
1/ nginx_upstream_jvm_route安装
下载地址(svn):http://nginx-upstream-jvm-route.googlecode.com/svn/trunk/
假设nginx_upstream_jvm_route下载后的路径为/usr/local/nginx_upstream_jvm_route,
(1)进入nginx源码路径
patch -p0 < /usr/local/nginx_upstream_jvm_route/jvm_route.patch
(2)./configure --with-http_stub_status_module --with-http_ssl_module --prefix=/usr/local/nginx --with-pcre=/usr/local/pcre-8.33 --add-module=/usr/local/nginx_upstream_jvm_route
(3)make & make install
2/ nginx配置
upstream tomcats_jvm_route
{
# ip_hash;
server 192.168.33.10:8090 srun_id=tomcat01;
server 192.168.33.11:8090 srun_id=tomcat02;
jvm_route $cookie_JSESSIONID|sessionid reverse;
}
3/ tomcat配置
修改192.168.33.10:8090tomcat的server.xml,
将
<Engine name="Catalina" defaultHost="localhost" >
修改为:
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat01">
同理,在192.168.33.11:8090server.xml中增加jvmRoute="tomcat02"。
#运行用户
user www-data;
#启动进程,通常设置成和cpu的数量相等
worker_processes 1;
#全局错误日志及PID文件
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
#工作模式及连接数上限
events {
use epoll; #epoll是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,可以大大提高nginx的性能
worker_connections 1024;#单个后台worker process进程的最大并发链接数
# multi_accept on;
}
#设定http服务器,利用它的反向代理功能提供负载均衡支持
http {
#设定mime类型,类型由mime.type文件定义
include /etc/nginx/mime.types;
default_type application/octet-stream;
#设定日志格式
access_log /var/log/nginx/access.log;
#sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用,
#必须设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,以平衡磁盘与网络I/O处理速度,降低系统的uptime.
sendfile on;
#tcp_nopush on;
#连接超时时间
#keepalive_timeout 0;
keepalive_timeout 65;
tcp_nodelay on;
#开启gzip压缩
gzip on;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
#设定请求缓冲
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
#设定负载均衡的服务器列表
upstream mysvr {
#weigth参数表示权值,权值越高被分配到的几率越大
#本机上的Squid开启3128端口
server 192.168.8.1:3128 weight=5;
server 192.168.8.2:80 weight=1;
server 192.168.8.3:80 weight=6;
}
server {
#侦听80端口
listen 80;
#定义使用www.xx.com访问
server_name www.xx.com;
#设定本虚拟主机的访问日志
access_log logs/www.xx.com.access.log main;
#默认请求
location / {
root /root; #定义服务器的默认网站根目录位置
index index.php index.html index.htm; #定义首页索引文件的名称
fastcgi_pass www.xx.com;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
# 定义错误提示页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /root;
}
#静态文件,nginx自己处理
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
root /var/www/virtual/htdocs;
#过期30天,静态文件不怎么更新,过期可以设大一点,如果频繁更新,则可以设置得小一点。
expires 30d;
}
#PHP 脚本请求全部转发到 FastCGI处理. 使用FastCGI默认配置.
location ~ \.php$ {
root /root;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/www/www$fastcgi_script_name;
include fastcgi_params;
}
#设定查看Nginx状态的地址
location /NginxStatus {
stub_status on;
access_log on;
auth_basic "NginxStatus";
auth_basic_user_file conf/htpasswd;
}
#禁止访问 .htxxx 文件
location ~ /\.ht {
deny all;
}
}
}
配置静态资源服务器的话,就是把一部分请求分离出来,让这些请求直接访问到服务器的磁盘目录中。
例如配置如下:
指定路径对应的目录。location可以使用正则表达式匹配。并指定对应的硬盘中的目录。如下:
location /images/ {
root /working/static/ROOT/WEB-INF/;
autoindex on;
}
location /images/ {
alias /working/static/ROOT/WEB-INF/images/;
autoindex on;
}
这个配置表示输入 localhost:80/images/wrong.png时会访问本机的/working/static/ROOT/WEB-INF/images/wrong.png; 目录。
root和alias 详解
当访问http://localhost/images/wrong.png时,root是去/working/static/ROOT/WEB-INF/image/wrong.png请求文件,alias是去/working/static/ROOT/WEB-INF/images/wrong.png请求,也就是说
root响应的路径:配置的路径+完整访问路径(完整的location配置路径+静态文件)
alias响应的路径:配置路径+静态文件(去除location中配置的路径)