在现代 Web 服务架构中,Tomcat 和 Nginx 是两个至关重要的组件,负责处理用户请求并实现高性能的服务。本篇博客将深入探讨这些技术的原理和部署配置方法。
Nginx应用
Nginx实现负载均衡的原理主要通过以下几个关键步骤
负载均衡原理
反向代理原理
具体过程
当使用Nginx服务器作为前端时,可以配置Nginx来进行静态页面的处理,而将动态页面请求转发给后端的Tomcat服务器来处理。由于Tomcat是轻量级应用服务器,可能无法满足所有访问量,因此需要多台Tomcat服务器,并通过Nginx的配置权重来进行负载均衡,以确保请求能够被分发到不同的Tomcat服务器上。
Nginx配置反向代理的主要参数
每个请求按时间顺序逐一分配到不同的后端服务器,如果超过了最大失败次数后(max_fails,默认1),在失效时间内(fail_timeout,默认10秒),该节点失效权重变为0,超过失效时间后,则恢复正常,或者全部节点都为down后,那么将所有节点都恢复为有效继续探测。
根据服务器的权重分配请求,权重越高的服务器获得更多的请求。优先将客户端请求调度到当前连接最少的服务器。
每个请求按访问ip的hash哈希值结果分配,将同一客户端的请求总是发往同一个后端服务器,除非该服务器不可用,可以解决session的问题。但是ip_hash如下问题:当后端服务器宕机后,session会丢失;来自同一局域网的客户端会被转发到同一个后端服务器,可能导致负载不均。
按后端服务器的响应时间来分配请求,响应时间短的优先分配。需要安装upstream_fair模块才能实现。
基于用户请求的uri做hash。和ip_hash算法类似,是对每个请求按url的hash结果分配,使每个URL定向到同一个后端服务器,但是也会造成分配不均的问题,这种模式后端服务器为缓存时比较好,可以提高后端缓存服务器的效率。
session 共享问题还可以使用sticky_cookie_insert启用会话亲缘关系,基于cookie来判断,使来自同一客户端的请求被传递到一组服务器在同一台服务器。也可用后端服务的 session 共享代替 nginx 的 ip_hash(使用后端服务器自身通过相关机制保持session同步)。
- upstream backend {
- server backend1.example.com;
- server backend2.example.com;
- sticky_cookie_insert srv_id expires=1h domain=www.xy101.com path=/;
- }
#说明:需要引入第三方sticky模块才能实现;expires:设置浏览器中保持cookie的时间;domain:定义cookie的域;path:为cookie定义路径
Nginx 四层代理配置:
./configure --with-stream和http同等级:所以一般配置位置只在http上面一段设置,
- stream {
-
- upstream appserver {
- server 192.168.80.100:8080 weight=1;
- server 192.168.80.101:8080 weight=1;
- server 192.168.80.101:8081 weight=1;
- }
- server {
- listen 8080;
- proxy_pass appserver;
- }
- }
-
- http {
- ......
动静分离原理
服务端接收来自客户端的请求中,既有静态资源也有动态资源,静态资源由Nginx提供服务,动态资源Nginx转发至后端
Nginx静态处理优势
Nginx 服务器:192.168.80.10:80
Tomcat服务器1:192.168.80.100:80
Tomcat服务器2:192.168.80.101:8080 192.168.80.101:8081
- systemctl stop firewalld
- setenforce 0
-
- #安装所需开发包和编译环境、编译器
- yum -y install pcre-devel zlib-devel openssl-devel gcc gcc-c++ make
-
- #创建程序用户,便于准确控制访问
- useradd -M -s /sbin/nologin nginx
-
- #解压nginx文件
- cd /opt
- tar zxvf nginx-1.12.0.tar.gz -C /opt/
-
- cd nginx-1.12.0/
- ./configure \
- --prefix=/usr/local/nginx \
- --user=nginx \
- --group=nginx \
- --with-file-aio \ #启用文件修改支持
- --with-http_stub_status_module \ #启用状态统计
- --with-http_gzip_static_module \ #启用 gzip静态压缩
- --with-http_flv_module \ #启用 flv模块,提供对 flv 视频的伪流支持
- --with-http_ssl_module #启用 SSL模块,提供SSL加密功能
- --with-stream #启用 stream模块,提供4层调度
- ----------------------------------------------------------------------------------------------------------
- ./configure \
- --prefix=/usr/local/nginx \ # 指定安装目录为 /usr/local/nginx
- --user=nginx \ # 指定运行 nginx 的用户为 nginx
- --group=nginx \ # 指定运行 nginx 的用户组为 nginx
- --with-file-aio \ # 启用文件异步IO支持
- --with-http_stub_status_module \ # 启用 HTTP Stub 状态模块,用于获取 nginx 的运行状态
- --with-http_gzip_static_module \ # 启用 HTTP gzip 静态压缩模块,用于对静态文件进行 gzip 压缩
- --with-http_flv_module \ # 启用 HTTP FLV 模块,提供对 FLV 视频的伪流支持
- --with-http_ssl_module \ # 启用 HTTP SSL 模块,提供 SSL 加密功能
- --with-stream # 启用 Stream 模块,提供 4 层调度功
- #编译及安装
- make && make install
-
- #软链接便于系统识别nginx操作命令
- ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
-
- #添加nginx系统服务以便系统管理启动、停止、重启
- vim /lib/systemd/system/nginx.service
- [Unit]
- Description=nginx
- After=network.target
- [Service]
- Type=forking
- PIDFile=/usr/local/nginx/logs/nginx.pid
- ExecStart=/usr/local/nginx/sbin/nginx
- ExecrReload=/bin/kill -s HUP $MAINPID
- ExecrStop=/bin/kill -s QUIT $MAINPID
- PrivateTmp=true
- [Install]
- WantedBy=multi-user.target
-
- #赋权及开启服务、开启开机自启
- chmod 754 /lib/systemd/system/nginx.service
- systemctl start nginx.service
- systemctl enable nginx.service
- #!/bin/bash
- #======编译安装nginx服务======
- #安装所需开发包和编译环境、编译器
- yum -y install pcre-devel zlib-devel openssl-devel gcc gcc-c++ make
- #创建程序用户,便于准确控制访问
- useradd -M -s /sbin/nologin nginx
-
- #解压安装包
- cd /opt
- tar zxvf nginx-1.12.0.tar.gz -C /opt/
-
- #指定安装路径、指定用户名、组名、启用模块以支持统计状态
- cd nginx-1.12.0/
- ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-file-aio --with-http_gzip_static_module --with-http_flv_module --with-http_ssl_module --with-stream
-
- #编译及安装
- make && make install
-
- #软链接便于系统识别nginx操作命令
- ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
-
- #添加nginx系统服务
- echo '[Unit]
- Description=nginx
- After=network.target
- [Service]
- Type=forking
- PIDFile=/usr/local/nginx/logs/nginx.pid
- ExecStart=/usr/local/nginx/sbin/nginx
- ExecReload=/bin/kill -s HUP $MAINPID
- ExecStop=/bin/kill -s QUIT $MAINPID
- PrivateTmp=true
- [Install]
- WantedBy=multi-user.target' > /lib/systemd/system/nginx.service
-
- #赋权及开启服务、开启开机自启
- chmod 754 /lib/systemd/system/nginx.service
- systemctl daemon-reload
- systemctl start nginx
- systemctl enable nginx
1.部署2台Tomcat 应用服务器(两台相同操作)
- systemctl stop firewalld
- setenforce 0
-
- #解压安装JDK
- tar zxvf jdk-8u91-linux-x64.tar.gz -C /usr/local/
-
- #设置JDK环境变量
- vim /etc/profile
- export JAVA_HOME=/usr/local/jdk1.8.0_91
- export JRE_HOME=${JAVA_HOME}/jre
- export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
- export PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin:$PATH
-
- #刷新配置文件,使配置生效
- source /etc/profile
-
- #解压tomcat
- tar zxvf apache-tomcat-8.5.16.tar.gz
-
- #将文件移动至/usr/local/下并重命名
- mv /opt/apache-tomcat-8.5.16/ /usr/local/tomcat
-
- #tomcat启动关闭脚本位置
- /usr/local/tomcat/bin/shutdown.sh
- /usr/local/tomcat/bin/startup.sh
-
- #重新加载服务,并开启,查看是否成功启动
- /usr/local/tomcat/bin/startup.sh
- lsof -i:8080
- netstat -ntap | grep 8080
- (1)Tomcat1 server 配置
- mkdir /usr/local/tomcat/webapps/test
- vim /usr/local/tomcat/webapps/test/index.jsp
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <html>
- <head>
- <title>JSP test1 page</title> #指定为 test1 页面
- </head>
- <body>
- <% out.println("动态页面 1,http://www.test1.com");%>
- </body>
- </html>
-
- (2)Tomcat1 server 配置
- mkdir /usr/local/tomcat/webapps/test
- vim /usr/local/tomcat/webapps/test/index.jsp
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <html>
- <head>
- <title>JSP test2 page</title> #指定为 test2 页面
- </head>
- <body>
- <% out.println("动态页面 2,http://www.test2.com");%>
- </body>
- </html>
- vim /usr/local/tomcat/conf/server.xml
- <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
- <Context docBase="/usr/local/tomcat/webapps/test" path="" reloadable="true" />
- </Host>
-
这段配置是用来定义 Tomcat 服务器的主机(Host)配置。在这里,
元素定义了 Tomcat 主机的一些属性,其中包括:
name="localhost"
: 定义了主机的名称为 "localhost"。appBase="webapps"
: 指定了存放 Web 应用程序的基本目录为 "webapps",这是 Tomcat 默认的应用程序部署目录。unpackWARs="true"
: 表示当部署 WAR 文件时,自动将其解压缩。autoDeploy="true"
: 表示自动部署 WAR 文件,如果设置为 true,则 Tomcat 会监视 appBase 目录中的新应用程序并自动部署它们。xmlValidation="false"
和 xmlNamespaceAware="false"
: 关闭对 web.xml 文件的 XML 验证,以及关闭对 XML 命名空间的感知。在
元素内部,
元素用于定义单个 Web 应用程序的上下文配置。在这里,它指定了一个名为 "test" 的Web应用程序的部署路径为根路径(""),并且启用了自动重载(reloadable="true")。
- #重启两台服务
- /usr/local/tomcat/bin/shutdown.sh
- /usr/local/tomcat/bin/startup.sh
- #准备静态页面和静态图片
- echo '
这是默认目录静态页面
' > /usr/local/nginx/html/index.html - mkdir /usr/local/nginx/html/kiki
-
- #编辑nginx配置文件
- vim /usr/local/nginx/conf/nginx.conf
-
- ......
- http {
- ......
- #gzip on;
- #后端负载服务器的地址
- upstream tomcat_server {
- server 192.168.1.20:8080 weight=1;
- server 192.168.1.30:8080 weight=1;
- }
-
- server {
- listen 80;
- server_name www.tong.com;
-
- charset utf-8;
-
- #access_log logs/host.access.log main;
-
- #配置Nginx处理动态页面请求,将 .jsp文件请求转发到Tomcat 服务器处理
- location ~ .*.jsp$ {
- proxy_pass http://tomcat_server;
- proxy_set_header HOST $host;
-
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
-
- #配置Nginx处理静态图片请求
- location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css)$ {
- root /usr/local/nginx/html/kiki;
- expires 10d;
- }
-
- location / {
- root html;
- index index.html index.htm;
- }
- ......
-
Nginx与Tomcat的结合可以实现负载均衡和动静分离,同时构建一个高性能的群集系统。
负载均衡:Nginx作为反向代理服务器,可以将请求分发到多个Tomcat服务器上,以实现负载均衡。通过配置Nginx的upstream模块,可以指定多个Tomcat服务器作为后端服务器,Nginx会根据一定的策略(如轮询、权重等)将请求分发给这些Tomcat服务器,从而提高整个系统的吞吐量和可用性。
动静分离:Nginx可以将动态请求(如JSP、Servlet等)和静态请求(如HTML、CSS、JavaScript等)分开处理。静态资源由Nginx直接响应,避免了Tomcat的负担,提高了静态资源的访问速度;动态请求则转发至Tomcat服务器进行处理,保证了动态内容的正确性。
群集系统:通过将多个Tomcat服务器与Nginx结合,可以构建一个高性能的群集系统。Nginx负责接收和分发请求,而Tomcat服务器则负责处理业务逻辑。当集群中的某个Tomcat发生故障时,Nginx可以自动将请求转发到其他正常运行的Tomcat服务器上,保证了系统的稳定性和可靠性。
总之,Nginx与Tomcat结合可以实现负载均衡、动静分离和构建高性能的群集系统,为Web应用程序提供了强大的性能和可用性支持。