在网上大多数是关于tomcat7与redis结合实现session会话共享,完全不符合现在的实际要求,由于在工作中需要完成过tomcat8负载均衡的项目,结合项目总结把实现的过程展现出来。废话不多说了,直接上干货,为了保护客户的权益,在此全部以内网IP来代替。本文先把Nginx代理功能与Tomcat8+Redis4实现session会话共享展示出来,关于数据库、Redis主从等方面下个博文会详细写出来的。
一、 项目简单需求如下:
1、 此项目是一个电商的网络商城的网站,网站是用jdk-1.8编写的
2、 实现tomcat8负载均衡的功能,一台Tomcat服务器挂掉不影响客户的正常访问
3、 商城有登录功能需要实现session会话共享
4、 数据库用mariadb+galera来实现高可用
5、 用proxysql来实现数据库的读写分离
6、 Nginx代理通过Keepalived实现高可用
说明:使用Nginx作为Tomcat的负载平衡器,Tomcat的会话Session数据存储在Redis,能够实现零宕机的7x24效果。因为将会话存储在Redis中,因此Nginx就不必配置成stick粘贴某个Tomcat方式,这样才能真正实现后台多个Tomcat负载平衡。
二、 项目实施中的改进
1、 第一次项目实施研讨会中准备使用nginx基于访问ip的hash策略
2、 第二次项目实施研讨会中准备使用是tomcat8的cluster会话保持功能
3、 第三次项目实施研讨会中准备使用的是基于memcache会话保持功能
4、 最后确定用Tomcat8+Redis4实现session会话共享
说明:关于memcache与redis的区别请大家自行上网查询,在此不浪费大家时间了
三、 网络架构简单介绍如下
主机名称 |
操作系统 |
IP地址分配 |
Nginx1.12 |
CentOS7.5 |
192.168.101.71 |
Tomcat-1 |
192.168.101.72 |
|
Tomcat-2 |
192.168.101.73 |
|
Redis4.06 |
192.168.101.74 |
四、 Nginx负载均衡功能实现
1、 centos7操作系统优化,以上是实际生产环境使用
1)vim /etc/security/limits.conf
最后添加
* soft nofile 102400
* hard nofile 102400
* soft nproc 102400
* hard nproc 102400
2) vim /etc/security/limits.d/20-nproc.conf
#加大普通用户限制 也可以改为unlimited
* soft nproc 102400
* hard nproc 102400
root soft nproc unlimited
3) vim /etc/sysctl.conf加入内容如下:
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.tcp_max_tw_buckets = 6000
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 16384 4194304
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 262144
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_keepalive_time = 30
net.ipv4.ip_local_port_range = 1024 65000
net.netfilter.nf_conntrack_max = 655350
net.netfilter.nf_conntrack_tcp_timeout_established = 1200
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
vm.overcommit_memory=1
4) 最后 sysctl -p 生效
5)修改主机名以区分各机器功能
2、nginx安装配置
1) 上传nginx-1.12.2.tar.gz到/usr/local/src
2) yum -y install gcc gcc-c++ make libtool zlib zlib-devel pcre pcre-devel openssl openssl-devel
3) useradd -s /sbin/nologin www
4) cd /usr/local/src
5) tar -zxvf nginx-1.12.2.tar.gz -C /usr/local/
6) cd /usr/local/nginx-1.12.2/
7) ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_stub_status_module --with-http_realip_module --with-http_ssl_module --with-http_gzip_static_module --with-pcre --with-http_flv_module
8) make && make install
9) ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/nginx
10) vim /etc/init.d/nginx 内容如下:
#!/bin/bash
# nginx Startup script for the Nginx HTTP Server
# chkconfig: - 85 15
# pidfile: /usr/local/nginx/logs/nginx.pid
# config: /usr/local/nginx/conf/nginx.conf
nginxd=/usr/local/nginx/sbin/nginx
nginx_config=/usr/local/nginx/conf/nginx.conf
nginx_pid=/usr/local/nginx/logs/nginx.pid
RETVAL=0
prog="nginx"
# Source function library.
. /etc/rc.d/init.d/functions
# Start nginx daemons functions.
start() {
if [ -f $nginx_pid ] ; then
echo "nginx already running...."
exit 1
fi
echo -n "Starting $prog: "
$nginxd -c ${nginx_config}
RETVAL=$?
[ $RETVAL = 0 ] && touch /var/lock/subsys/nginx
}
# Stop nginx daemons functions.
stop() {
echo -n "Stopping $prog: "
$nginxd -s stop
RETVAL=$?
[ $RETVAL = 0 ] &&rm -f /var/lock/subsys/nginx
}
# reloadnginx service functions.
reload() {
echo -n "Reloading $prog: "
$nginxd -s reload
}
# statusngnx service functions
status() {
if [ -f $nginx_pid ] ; then
echo "$prog is running"
else
echo "$prog is stop"
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
reload)
reload
;;
restart)
stop
start
;;
status)
status
;;
*)
echo "Usage: $prog {start|stop|restart|reload|status}"
exit 1
;;
esac
11) chmod +x /etc/init.d/nginx
12) chkconfig --add nginx && chkconfig nginx on
13) systemctl daemon-reload
14) mv /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.bak
15) vim /usr/local/nginx/conf/nginx.conf 内容如下:
user www www;
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
worker_rlimit_nofile 102400;
pid logs/nginx.pid;
events {
use epoll;
worker_connections 102400;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
server_tokens off;
sendfile on;
tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#Compression Settings
gzip on;
gzip_comp_level 6;
gzip_http_version 1.1;
gzip_proxied any;
gzip_min_length 1k;
gzip_buffers 16 8k;
gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
gzip_vary on;
#end gzip
# http_proxy Settings
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 75;
proxy_send_timeout 75;
proxy_read_timeout 75;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
#load balance Settings
upstream backend_tomcat {
server 192.168.101.72:8080 weight=1 max_fails=2 fail_timeout=10s;
server 192.168.101.73:8080 weight=1 max_fails=2 fail_timeout=10s;
}
#virtual host Settings
server {
listen 80;
server_name www.benet.com;
charset utf-8;
location / {
root html;
index index.jsp index.html index.htm;
}
location ~* \.(jsp|do)$ {
proxy_pass http://backend_tomcat;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
location /nginx_status {
stub_status on;
access_log off;
allow 192.168.101.0/24;
deny all;
}
}
}
16) service nginx restart 如果第一失败就再执行一次,
17) Nginx代理服务器配置是4核8G主机
18) ss -tunlp 可以查看到80端口已经对外提供服务了
3、安装、配置 tomcat
jdk版本:jdk1.8.0_131
tomcat版本: apache-tomcat-9.0.2
1)所需软件:(tomcat8.5和tomcat9 都可以,此处以tomcat9为例)
apache-tomcat-8.5.20.tar.gz 或 apache-tomcat-9.0.2.tar.gz
———————————————————————————-
jdk-8u131-linux-x64.tar.gz
———————————————————————————-
commons-pool2-2.4.2.jar
jedis-2.9.0.jar
tomcat85-session-redis-1.0.jar
———————————————————————————-
下载地址:
链接:https://pan.baidu.com/s/1c1P6Nzq 密码:13f5
参考配置:
context.xml
2)解压tomcat、jdk到指定的目录
# mkdir /app
# tar -xvf apache-tomcat-9.0.2.tar.gz -C /app/
# tar -xvf jdk-8u131-linux-x64.tar.gz -C /app/
3)指定jdk或者修改jdk环境变量:
3.1)指定JDK版本以便tomcat与jdk联接
vim /app/apache-tomcat-9.0.2/bin/catalina.sh
添加如下内容:
export JAVA_HOME=/app/jdk1.8.0_131
export JRE_HOME=/app/jdk1.8.0_131/jre
位置如下图:
3.2)修改java环境变量
(a)
在/etc/profile.d/目录下,创建一个.sh结尾的文件,
比如:
vim /etc/profile.d/jdk180.sh
添加如下内容:
export JAVA_HOME=/app/jdk1.8.0_131
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
(b)
执行该脚本文件,是JAVA环境变量生效
source /etc/profile.d/jdk180.sh
3.3)拷贝Tomcat需要的3个jar文件
将下边的三个文件拷贝至:${TOMCAT_HOME}/lib目录下
commons-pool2-2.4.2.jar、jedis-2.9.0.jar、tomcat85-session-redis-1.0.jar
$ cp ./*.jar /app/apache-tomcat-9.0.2/lib/
3.4)修改context.xml文件
$ vim /app/apache-tomcat-9.0.2/conf/context.xml
添加如下内容:参考下载文件中的context.xml文件
————————————————– 分割线 ————————————————–
<Valve className=”com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve” />
<Manager className=”com.orangefunction.tomcat.redissessions.RedisSessionManager”
host=”192.168.101.74″
port=”6379″
database=”0″
maxInactiveInterval=”60″ />
因在word文档编辑模式,此处的内容复制到context.xml文件后需要在英文输入法上把引号重新替换下
————————————————– 分割线 ————————————————–
3.5)创建测试文件:
cd /app/apache-tomcat-9.0.2/webapps/
mkdir test
vim test/index.jsp
以tomcat-1机器为例index.jsp内容如下:tomcat-2机器则直接替换相应的名称就可以了(把tomcat-1换成tomcat-2)
<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>tomcat-1</title>
</head>
<body>
<h1><font color="red">Session serviced by tomcat-1</font></h1>
<table aligh="center" border="1">
<tr>
<td>Session ID</td>
<td><%=session.getId() %></td>
<% session.setAttribute("abc","abc");%>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
<html>
3.6)启动tomcat
/app/apache-tomcat-9.0.2/bin/startup.sh
4、安装、配置 Redis(此处只是redis的简单安装配置)
4.1、下载、解压、编译:
yum -y install wget && wget http://download.redis.io/releases/redis-4.0.6.tar.gz
tar -zxvf redis-4.0.6.tar.gz -C /app/
cd /app/redis-4.0.6/
make && make install
默认配置文件位于:
/app/redis-4.0.6/redis.conf
二进制文件是编译完成后在src目录下,通过下面的命令启动Redis服务:
#ll src/redis-server
注意:这里直接执行Redis-server 启动的Redis服务,是在前台直接运行的(效果如上图),也就是说,执行完该命令后,如果Lunix关闭当前会话,则Redis服务也随即关闭。正常情况下,启动Redis服务需要从后台启动,并且指定启动配置文件。
4.2、修改配置文件,让redis以守护进程的形式后台运行
A、vim redis.conf,将daemonize属性改为yes(表明需要在后台运行)
daemonize yes
B、默认是只监听在本机的本地IP地址:127.0.0.1的6379端口,
注意:#####################################
redis4.0.6 如果注释掉默认的绑定地址 #bind 127.0.0.1,
有时会导致客户端无法链接redis-server
###########################################
添加要监听的本地IP地址:
bind 127.0.0.1 192.168.101.74
可以根据需要,修改监听端口
4.3、启动、停止 redis
启动:
格式:redis-server 配置文件
src/redis-server redis.conf
关闭指定redis
src/redis-cli -p 6379 shutdown
停止:
# src/redis-cli -p 端口 shutdown
src/redis-cli -p 6379 shutdown
或者
pkill redis-server
4.4启动Redis:
格式:redis-server 配置文件
cd /app/redis-4.0.6/ && src/redis-server redis.conf
五、访问测试页:
刷新页面,分别访问到不同的tomcat主机,但获取的session ID相同,
说明:用Redis,实现tomcat session共享 测试成功
http://192.168.101.71/test 不断刷新可以看到session ID号是相同
参考以下文档链接:
http://blog.51cto.com/yw666/1910451
http://www.enunix.com/