文档章节

nginx+tomcat+redis实现负载平衡和session共享

汉堡OSC
 汉堡OSC
发布于 2016/09/11 21:52
字数 2501
阅读 84
收藏 0

首先是本次架构的环境,vm虚拟机中CenteOS 3台:2台tomcat,1台nginx。redis与nginx在一个机子上。

IP地址 功能 端口 设备
192.168.1.111 nginx+redis

nginx=80,

redis=6379

vm 
192.168.1.110 tomcat 8080 vm
192.168.1.108 tomcat 8080 vm
192.168.1.109 浏览器客户端 \ 笔记本

----------------------------------------------------------------------------------------------------

第一步:安装jdk,tomcat,nginx,redis

具体的安装过程这里就不细说了,都很简单,具体百度吧。

---------------------------------------------------------------------------------------------------

第二步:配置tomcat,使tomcat的session可以存放在redis中。

首先下载需要的jar包,

tomcat-redis-session-manager-1.2-tomcat-7-java-7.jar
wget地址 https://github.com/jcoleman/tomcat-redis-session-manager/downloads
---------
jedis-2.2.jar
wget地址 http://mvnrepository.com/artifact/redis.clients/jedis
----------------
commons-pool-1.6.jar
wget http://central.maven.org/maven2/commons-pool/commons-pool/1.6/commons-pool-1.6.jar
或者压缩包 http://commons.apache.org/proper/commons-pool/download_pool.cgi

注意版本号要如上,否则很大可能存在jar兼容性问题。(因为先开始我也是去下的比较新的版本commons-pool2-2.4.2和jedis-2.5但报了classNoFindException说是commons-pool缺少config内部类
然后把commons-pool换成1.6,又提示缺少commons-pool2.xxx类,懵逼一会,然后网上各种找资料,说是版本问题,但上面我说的版本是可以的。)
如果想硬刚到底(解决版本问题),可以试试以下操作:使用gradle重新编译官方资源文件为jar包
http://www.oschina.net/question/815618_194320

所有的jar包下载好后,放到tomcat/lib文件夹下,并修改tomcat/conf/context.xml文件,在根节点下添加如下内容:

<valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve" />
<manager className="com.radiadesign.catalina.session.RedisSessionManager" host="192.168.1.111" port="6379" database="0" maxInactiveInterval="60" />

注意host要改成redis服务器的地址,这里是192.168.1.111
然后wq保存就行了。
两个tomcat服务器上的tomcat使用相同方法配置。

第三步:
配置nginx的配置文件nginx.conf的upstream 和location /内容

完整的配置:

#用户 和用户组
user apache apache;
#进程数,一般设置和cpu核心数一致
worker_processes  1;
events {
     #linux下的高性能io模式
     use epoll;
    #每个进程的最大并发数
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    #sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用,
    #必须设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,以平衡磁盘与网络I/O处理速度,降低系统的uptime
    sendfile        on;
    keepalive_timeout  65;
	

	#开启gzip压缩
	gzip on;  
	gzip_comp_level 7;  
	gzip_min_length  1100; #需要压缩的最小长度  
	gzip_buffers    4 8k;  
	gzip_types      text/plain application/javascript text/css text/xml application/x-httpd-php; #指定需要压缩的文件类型  
	output_buffers  1 32k;  
	postpone_output  1460;  
	
    upstream  myserver  {
		#配置集群服务器的真实地址,weight为权重
               server   192.168.1.110:8080  weight=1;
               server   192.168.1.108:8080  weight=1;
    }


    #一个虚拟主机
    server {
        listen       80;
        server_name  localhost;
        root /var/www/html;
        
	index index.html index.htm index.jsp;

        location / {
		#允许通过的域名
		proxy_pass        http://myserver;
		#替换http请求头为真正的服务器地址
		proxy_set_header   Host             $host;
		proxy_set_header   X-Real-IP        $remote_addr;
		proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        }

        #location ~ .*.jsp$ {
	#	index index.jsp;
	#	proxy_pass http://localhost:8080;
        #}
	
	#一些静态文件的缓存设置

        #location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
		#静态文件需要放在本地目录下
	#	root         /var/www/poseidon/root/static;  
	#	access_log   off;  
        #expires      30d;
        #}
        #location ~ .*\.(js|css)?$ {
        #expires      1h;
        #}
        #error_page   500 502 503 504  /50x.html;
        #location = /50x.html {
        #   root   html;
        #}

	 #设定查看Nginx状态的地址
	 #设置之后可以通过http://localhost/NginxStatus的方式查看nginx状态
	  location /NginxStatus {
		#stub_status            on;
		access_log              on;
		auth_basic              "NginxStatus";
		auth_basic_user_file  conf/htpasswd;
	  }
    }
}

第四步:

启动redis服务器,进入redis文件夹后输入命令src/redis-server ./redis.conf

[root@localhost redis-3.2.1]# pwd
/usr/local/redis-3.2.1
[root@localhost redis-3.2.1]#


成功启动后会看到会看到命令行打印出的数据库图形。如下:

[root@localhost redis-3.2.1]#
[root@localhost redis-3.2.1]# src/redis-server ./redis.conf
13242:M 11 Sep 21:22:57.933 * Increased maximum number of open files to 10032 (it was originally set to 1024).
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 3.2.1 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 13242
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

13242:M 11 Sep 21:22:57.940 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
13242:M 11 Sep 21:22:57.940 # Server started, Redis version 3.2.1
13242:M 11 Sep 21:22:57.940 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
13242:M 11 Sep 21:22:57.941 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
13242:M 11 Sep 21:22:57.941 * DB loaded from disk: 0.000 seconds
13242:M 11 Sep 21:22:57.941 * The server is now ready to accept connections on port 6379


在两个tomcat下分别放入测试项目(需要有登录后保存session功能,并且能在jsp页面显示当前的服务器ip---目的是能看来来nginx的轮询),这里我就不说了,自己写一个。
启动tomcat,don not forget! 是两个tomcat都启动。
启动nginx,在启动nginx之前可以先测试tomcat是否正常启动。

第五步,测试

在笔记本浏览器输入:http://192.168.1.111/EqTest/login.jsp,看到如图1所示登陆界面,再刷新一下,变成了图2所示。在nginx中使用轮询的方式负载,并没采用ip_hash的方式,所以两次请求分别是从两个tomcat服务器响应的,从图片中可以看处。

    

 

 

 

               

                    图1.登录界面一                                                         图2.刷新后的登录界面

然后是登录之后,多次刷新页面,如图3,图4所示两种结果。

 

 

 

 

                        图3.主界面                                                    图4刷新后的主界面

从上面的结果可以看出是成功的。

--------------------------------------------------------------------------------------------------------------------------------------------


在配置过程中遇到的问题:
第一:jar包版本问题,在第二步已经说明。

第二:java.lang.ClassNotFoundException: com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve
    说起来也奇怪,两个tomcat都是同样的版本apache-tomcat-7.0.70,使用的jar包也是一样的,但其中一个没遇到这个问题,另一个启动的时候查看日志遇到了这个问题。
    这到底是什么原因,我找了3个小时,期间有的说是jar包版本不对的问题,我也使用gradle对项目源码进行了重新build,然并卵啊!
    偶然的一瞬间,我发现一个问题,看contxt.xml配置文件!

<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />  
	  <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"  
	   host="10.10.49.20"  
	   port="6379"  
	   database="0"  
	   maxInactiveInterval="60" />

 发现问题了吗???!!!   redissessions和session!
       正确的配置文件应该是把redissessions改成session!

正确的配置:

<Valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve" />
	<Manager className="com.radiadesign.catalina.session.RedisSessionManager" host="192.168.1.111" port="6379" database="0" maxInactiveInterval="60" />

想在仔细想象为什么会出现这个问题?因为我也是看了网上某个人的博客配置的,他一个人错,就带偏了一部分人。
    也许他并没有错,是因为tomcat-redis-session-manager官方的项目调整了包的结构,但博客的内容不可能跟着更新。所以,这也是一种教训和经验吧。一定要以官方文档为准!!!!!       

第三:Http status 500 reids denied拒绝问题:
redis 在启动后,在浏览器输入地址测试的时候会出现以下错误:

HTTP Status 500 - DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the loopback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command 'CONFIG SET protected-mode no' from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to 'no', and then restarting the server. 3) If you started the server manually just for testing, restart it with the '--protected-mode no' option. 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside.


报错内容已经把报错原因说的很清楚了,解决方案也提供了4条。大概意思就是说:redis安全模块启用,没用bind address的情况下,非redis本机上的客户端是无法连接redis服务器的,因为默认的配置bind 的是本地回路127.0.0.1,在给出的解决方案中有2种简单易行 ,第一种修改bind地址,第二种关闭protected mode。于是乎就打开vim ./redis.conf
会看到如下两行:
bind 127.0.0.1
protected-mode yes

那么这个bind是什么意思呢?看注释部分的解释如下

# By default, if no "bind" configuration directive is specified, Redis listens
# for connections from all the network interfaces available on the server.
# It is possible to listen to just one or multiple selected interfaces using
# the "bind" configuration directive, followed by one or more IP addresses.
#
# Examples:
#
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1 ::1
#
# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the
# internet, binding to all the interfaces is dangerous and will expose the
# instance to everybody on the internet. So by default we uncomment the
# following bind directive, that will force Redis to listen only into
# the IPv4 lookback interface address (this means Redis will be able to
# accept connections only from clients running into the same computer it
# is running).


简单解释一下,bind绑定的是本机(注意是redis所在的本机)的网卡接口的ip,只有将本地ip bind后,才可以暴露本机redis服务以供其他机器的客户端使用
如果你本地机器有多个网卡,可以多绑定,如: bind 192.168.1.111  10.0.0.1。
如果bind 是127.0.0.1,只有本地机器的客户端通过redis-cli命令可以连接redis-server。

所以要解决以上错误,有2中方法:
方案1)更改redis.conf 的bind内容为bind  xxx.xxx.xxx.xxx    注意xxx.xxx.xxx.xxx是你本机的ip。
    或者直接在bind那行的前面加个#号。
方案2)更改protected-mode yes为protected-mode no
最后重启redis服务器:src/redis-server。
怎么样,问题解决了吗?如果没解决那就对了,这里还有一个坑需要你踩:
使用src/redis-server启动的时候使用的是默认的配置文件,所以正确的姿势是:
src/redis-server   ./redis.conf
搞定!。

第一次比较正规的发博文,目的除了记录所学知识,还有就是想分享一下,把自己踩的坑分享出来,如有错误,还请不吝指出。多谢!
-----------------------------------------------------------------

参考文章:
http://blog.csdn.net/ahstusujian/article/details/47974699
http://www.oschina.net/question/815618_194320
http://blog.csdn.net/grhlove123/article/details/48047735
 

© 著作权归作者所有

共有 人打赏支持
汉堡OSC

汉堡OSC

粉丝 4
博文 28
码字总数 18342
作品 0
宝山
后端工程师
私信 提问
加载中

评论(3)

汉堡OSC
汉堡OSC

引用来自“回音才知道”的评论

强哥可以得
见笑了,学习笔记而已
回音才知道
强哥可以得
汉堡OSC
汉堡OSC
00
Nginx+Tomcat+Redis实现负载均衡、资源分离、session共享

Nginx+Tomcat+Redis实现负载均衡、资源分离、session共享 CentOS安装Nginx http://centoscn.com/CentosServer/www/2013/0910/1593.html CentOS安装Tomcat http://blog.csdn.net/zhuyinglinu......

Q317075064
2016/09/29
104
0
nginx+tomcat+redis负载均衡,实现session共享

实验环境: 基础理论 session 统一方案: 1、单机的session会话保持机制如nginx的ip-hash,如果单个机器下线,那么session将会全部丢失 2、session共享,如tomcat集群,多个应用服务器共享同...

812374156
2018/04/23
0
0
nginx+tomcat+redis

项目用 nginx+tomcat+redis 去做session共享 奇怪的是redis保存tomcat传过来session ,默认60秒就过期了 之后会存储新的session值 大家有遇到这种情况吗 用的 tomcat7 centos6.5 redis2.8.1...

一个人眺望碧海和蓝天
2016/03/19
405
2
Nginx+Tomcat+Redis实现session共享

通过Nginx作为前端的负载,把请求分发到后端的Tomcat服务器上,提高并发数;但是单纯的通过Nginx的ip_hash负载是很多问题的。只要用户一切换网络或者后端Tomcat主机宕机session就失效; 架构...

dengaosky
2017/12/22
0
0
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)

一、redis介绍 redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型...

何小帅
2018/06/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

pg_lightool基于basebackup的单表恢复和块恢复

开源软件pg_lightool,实现了基于wal日志的块恢复。详情参见博客:https://my.oschina.net/lcc1990/blog/1931485。由于wal日志中FPW的不确定性,它不能作为一个数据库恢复的解决方案。目前对...

movead
32分钟前
2
0
对比剖析Swarm Kubernetes Marathon编排引擎

Docker Native Orchestration 基本结构 Docker Engine 1.12 集成了原生的编排引擎,用以替换了之前独立的Docker Swarm项目。Docker原生集群(Swarm)同时包括了(Docker Engine \/ Daemons)...

Linux就该这么学
34分钟前
2
0
Mybatis的结果集处理

此时我们已经可以把整段的SQL语句取出,但还并没有在数据库中去执行,我们可以先来分析一下配置文件中SQL语句执行后的结果集是如何处理的。 Mybatis会将结果集按照映射配置文件中定义的映射规...

算法之名
46分钟前
23
0
Spring Boot(Spring的自动整合框架)

Spring Boot 是一套基于Spring框架的微服务框架,由于Spring是一个轻量级的企业开发框架,主要功能就是用于整合和管理其他框架,想法是将平时主流使用到的框架的整合配置预先写好,然后通过简...

花漾年华
49分钟前
2
0
Windows下条件变量的实现

条件变量是什么? 是一种同步对象。 条件变量有什么用? 用于复杂的、多线程的、多核的程序中,实现多个线程间同步任务。 条件变量与其它同步对象的区别? 与事件、互斥锁、segment等同步对象...

shzwork
50分钟前
2
1

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部