来自:MrLinFeng - 博客园
链接:www.cnblogs.com/mrlinfeng/p/6146866.html
(点击尾部阅读原文前往)
相关知识自行搜索,直接上干货。。。
使用的资源:
nginx主服务器一台,nginx备服务器一台,使用keepalived进行宕机切换。
tomcat服务器两台,由nginx进行反向代理和负载均衡,此处可搭建服务器集群。
redis服务器一台,用于session的分离共享。
nginx主服务器:192.168.50.133
nginx备服务器:192.168.50.135
tomcat项目服务器1:192.168.50.137
tomcat项目服务器2:192.168.50.139
redis服务器:192.168.50.140
注意访问时需要配置防火墙规则,或者关闭防火墙
首先进行的通用安装:
总的需要模拟五台服务器,使用vmware,全部使用centos6.5 64位,五台服务器全部安装jdk,我使用的是jdk1.8.
1、安装VMware虚拟机,安装linux系统,此处使用centOS6.5 64位,安装linux命令行工具,上传文件工具,此处使用SecureCRT,SecureFX 。安装教程不再赘述,百度一大堆..........
这步有问题请使劲点:www.baidu.com
2、在linux上安装jdk:
安装jdk:卸载openjdk版本,上传解压jdk,配置环境变量----参考:http://jingyan.baidu.com/article/ab0b56308966acc15afa7d18.html
一、Nginx反向代理与负载均衡:
架构图:
此时需要用到三台服务器,一台nginx服务器,两台正式部署项目的服务器:选择的是192.168.50.133主nginx和192.168.50.137,192.168.50.139两台tomcat服务器
首先在两台服务器上安装tomcat:这个也是简单,不多说
安装tomcat:
上传解压即可使用,bin目录下 startup.sh启动,shutdown.sh关闭
配置防火墙端口:vim /etc/sysconfig/iptables 编辑,开放8080端口,80端口等一些常用端口,当然后边有用到一些端口都是需要配置开放的,不建议关闭防火墙
编辑好后 service iptables restart 重新加载防火墙配置
如果是自己测试嫌配置麻烦,关闭防火墙: service iptables stop 重启后防火墙打开,即在此次开机状态下有效,完全关闭再使用 chkconfig iptables off ,即会在重启后也关闭防火墙,注意有时候服务都起了但访问出错,可能就是防火墙问题哦
启动tomcat访问:192.168.50.137:8080,192.168.50.139:8080,打开tomcat首页即成功。
然后编写测试项目,部署到两台tomcat上,eclipse新建web项目,项目名为testproject,在webapp下新建一个jsp页面为index.jsp,添加如下内容
将项目中web.xml中的访问顺序
index.jsp
上移到第一个访问
然后右键导出为war包,testproject.war,将该war包上传到两台服务器的tomcat的webapps中
然后修改tomcat的server.xml文件,在tomcat conf目录中:可以使用notepad++的插件NppFTP直接连上linux,然后使用notepad++修改文件哦,保存记得使用UTF-8无BOM格式,具体去百度吧,哈哈
修改Engine标签中,添加jvmRoute,用于标识nginx访问的是哪个服务器tomcat,137服务器标识为137Server1,139服务器标识为139Server2
在两台tomcat的server.xml文件,Host标签中添加:
,path标识访问路径,docBase为项目名,表示访问项目
此时,重新启动tomcat,访问192.168.50.137:8080,192.168.50.139:8080,显示index.jsp内容:两台服务器访问显示如下
至此,两台tomcat服务器搭建完成。
在nginx主机192.168.50.133上安装nginx:
先使用yum命令安装gcc,安装pcre,zlib,openssl:
yum install -y gcc
yum install -y pcre pcre-devel
yum install -y zlib zlib-devel
yum install -y openssl openssl-develplain
在/usr/local/目录下新建nginx-src目录,将nginx-1.8.0.tar.gz放到此处,解压
tar -zxvf nginx-1.8.0.tar.gz
进入解压后目录
依次执行命令:
./configure
make
mkae install
此时nginx安装完毕,安装目录是/usr/local/nginx,nginx默认占用80端口
其中,sbin目录为nginx执行命令,conf目录下的nginx.conf为默认加载的配置文件
启动nginx:
./sbin/nginx
关闭nginx:
./sbin/nginx -s stop
启动nginx后访问192.168.50.133:80即可访问nginx:显示nginx欢迎页
至此,nginx安装完毕。
3、反向代理与负载均衡配置
现有两台服务器,一台为192.168.50.137,一台为192.168.50.139,服务器上各有一台tomcat,端口均为8080,在192.168.50.133上有nginx,经过配置nginx,当访问192.168.50.133:80时,即可访问192.168.50.137:8080,192.168.50.139:8080中随机一台,此时192.168.50.133:80被nginx监听,当有请求时,代理到192.168.50.137:8080,192.168.50.139:8080随机一台即可,即为nginx反向代理功能,同时此时可以通过nginx将请求进行转发,保证了一个入口,将所有请求转发到两台服务器上也减轻了任何一台的负载压力,当有大量请求时,可以搭建大量服务器,在入口代理服务器上使用nginx进行转发,即是负载均衡功能。
配置即是配置nginx安装目录中conf目录下的nginx.conf文件即可:具体配置如下,重点是红色部分
启动两台tomcat,重新启动nginx:
访问192.168.50.133:80将会随机访问192.168.50.137:8080和192.168.50.139:8080其中一台。(问题:每次刷新nginx服务器地址sessionid会变,session不能共享。)
nginx轮询策略:
nginx负载均衡到多台服务器上时,默认采用轮询策略:
常见策略:
1、轮询
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况,数字越大命中率越高。
例如:轮询几率是2:1
upstream bakend {
server 192.168.0.14 weight=2;
server 192.168.0.15 weight=1;
}
2、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
例如:
upstream bakend {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}
其他策略可以自行查询学习,nginx还有很多其他可配置项,静态资源缓存,重定向等,想深入的童鞋请自行学习
nginx配置详解:http://blog.csdn.net/tjcyjd/article/details/50695922
实际问题:虽然解决了,但是不是很理解,记录一下
其中192.168.50.133:80是有外网映射的,外网55.125.55.55:5555映射到192.168.50.133:80上,此时使用55.125.55.55:5555访问,会映射到192.168.50.133:80上,然后会被转发到192.168.50.137:8080或192.168.50.139:8080,但是此时却出现图片,js,css等静态文件无法访问的情况,通过两种方法解决。
<1>.映射非80端口
让55.125.55.55:5555映射192.168.50.133的非80端口,例如55.125.55.55:5555映射192.168.50.133:5555,然后再在nginx配置文件中配置如下,注意红色加大部分:这地方不理解
此时访问55.125.55.55:5555,映射到192.168.50.133:5555上,然后转发到192.168.50.137:8080或192.168.50.139:8080上,此时静态文件均能访问。
<2>.使用域名在外网服务器上使用nginx进行转发
将55.125.55.55绑定域名为test.baidubaidu.com,此时在55.125.55.55服务器上使用nginx,
........location / {
#加入判断,如果域名为test.baidubaidu.com,转发到192.168.50.133:80,然后再进行转发,注意,此处未进行测试,貌似是这么写的,$hostname为nginx变量,可以获取域名
if($hostname = "test.baidubaidu.com" ){
proxy_pass http://192.168.50.133:80;
}
#proxy_redirect off;
#非80端口使用,目的是将代理服务器收到的用户的信息传到真实服务器上,我也不是很理解
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
add_header Access-Control-Allow-Origin *;
}........
以上即nginx反向代理与负载均衡介绍,经过此次学习,发现nginx确实是博大精深,一个配置文件搞得我不要不要的。。。
二、session共享问题:
由于nginx是随机分配请求,假设一个用户登录时访问网站登录时被分配到192.168.50.137:8080上,然后进行了登录操作,此时该服务器上就会有该用户登录的session信息,然后登陆后重定向到网站首页或个人中心时,此时如果被分配到192.168.50.139:8080上,那么这台服务器上没有该用户session信息,于是又会变成未登录状态,所以由于nginx的负载均衡会导致session共享的问题。
解决方法:
1、nginx提供了ip_hash策略,可以保持用户ip进行hash值计算固定分配到某台服务器上,然后只要是该ip则会保持分配到该服务器上,保证用户访问的是同一台服务器,那么session问题就不存在了。这也是解决session共享的一种方式,也称为黏性session。但是假设一台tomcat服务器挂了的话,那么session也会丢失。所以比较好的方案是抽取session。
2、session存在memcache或者redis中,以这种方式来同步session,把session抽取出来,放到内存级数据库里面,解决了session共享问题,同时读取速度也是非常之快。
本例中:
Redis解决session共享:
在redis服务器192.168.50.140上搭建redis,redis默认端口为6379
Redis搭建:
redis依赖gcc,先安装:
yum install -y gcc-c++
下载redis,我使用的是redis-3.2.1.tar.gz,上传至linux /usr/local/redis-src/中,解压
进入解压后目录redis-3.2.1,执行make命令进行编译
安装到目录/usr/local/redis
执行:
make PREFIX=/usr/local/redis install
安装完成之后将redis配置文件拷贝到安装目录下,redis.conf是redis的配置文件,redis.conf在redis源码目录,port默认6379。
执行命令:
cp /usr/local/redis-src/redis-3.2.1/redis.conf /usr/local/redis/
在redis安装目录启动和关闭redis:
启动:
./bin/redis-server ./redis.conf
这种启动方式叫做前端启动,必须保持在当前窗口,如果ctrl + c 退出,那么redis也就退出了,不建议使用
那么后端启动:
首先修改redis.conf中daemonize的值,打开可以看到默认是no,修改为daemonize yes,启动即可。也可以在该配置文件中修改redis默认端口6379为其他值。
关闭redis:
./bin/redis-cli shutdown
至此,redis服务器搭建完成。
tomcat与redis集成实现session共享:
环境为tomcat7 + jdk1.6的话:
在所有需要共享session的服务器的tomcat中目录下:
lib目录中添加以下三个jar包,注意版本最好一致,不然极容易出现错误,下边的测试是可用的:
conf目录中content.xml中加入:配置redis服务
环境为tomcat7 + jdk1.7或1.8的话:
在所有需要共享session的服务器的tomcat中目录下:
lib目录中添加以下三个jar包,测试通过:
conf目录中content.xml中加入:配置redis服务
根据我这测试,是jkd1.8+tomcat7,在137和139两台tomcat中加入jar包且进行如上配置:
上传jar包
修改content.xml
启动redis服务,重新启动所有tomcat,启动nginx,刷新nginx页面,两台tomcat页面可以看到sessionid值不变,关闭某台tomcat,nginx中sessionid不变,说明session是共享的。
问题:
有可能此时访问会报错,redis无法访问,这是由于redis的安全机制,默认只有127.0.0.1才能访问,在redis.conf中可以找到bind 127.0.0.1,你可以将此ip改为访问者ip,
如果有多个访问者,也可以把bind 127.0.0.1注释掉,然后在配置文件中找到protected-mode,修改protected-mode yes改为protected-mode no 关闭redis保护模式即可
详细可以参考这:http://www.cnblogs.com/liusxg/p/5712493.html
经过大牛指点:添加两个注意点:
1、按照如上配置,使用redis数据库,放入session中的对象必须要实现java.io.Serializable接口,使用memcache的可以不用实现Serializable接口
原因是:因为tomcat里使用的将session放置redis使用的工具类,是使用的jdk序列化模式存储的,这一点也是很容易理解的,session.setAttribute(String key, Object value),存储Object类型
object放入redis中又要能取出来,只能是序列化进行存储了,然后取出的时候进行反序列化。
所以我们在session中存储的任何对象,都必须实现序列化接口。
2、按照如上配置,使用redis做session存储空间时,web应用的session-time的时间单位会变成[秒],而不是原本的[分]
原因是:因为tomcat里使用的将session放置redis使用的工具类,在存储时为对tomcat容器时间做转换,
在redis中设置过期时间是使用秒作为单位的,有个命令叫expire可以设置redis键值过期时间,所以在context.xml配置文件中我们需要制定session过期时间(默认是60秒,配成1800即30分钟),这一点很重要。