⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 jasonkayzk.github.io/2020/04/13/负载均衡Nginx-一些常见的问题/ 「张小凯と彼のBlog」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

HTTPS 请求跳转

如下面的配置:

location /test {
proxy_pass http://www.baidu.com/;
}

在访问 URI 为 /test 时会跳转到百度,但此时浏览器中的 URL 也会发生变化。

这是因为:向 http://www.baidu.com/ 发送请求后, Nginx 返回的是一个跳转的响应。

此后, 客户端会重新向 https://www.baidu.com/ 发送请求(此过程不再经历 Nginx)。

所以,最终浏览器发生了跳转, 而非 Nginx 的负载均衡。

问题解决

将配置中的 http 改为 https 即可。

Session 一致性

在使用 Nginx 做反向代理时,如果后端服务器是 Tomcat 等动态服务器,则可能会出现 Session 一致性问题。

即: 无法确保同一个 Session 一定对应同一个 Server;

配置网络

下面使用 Docker 来演示。

配置 IP 地址:

图片

并在 Server1 和 Server2 上启动 Tomcat。

配置 Server

在 Server 端创建 jsp 页面:

Server 1

[root@c5477d71795c ROOT]# pwd
/var/lib/tomcat/webapps/ROOT
[root@c5477d71795c ROOT]# cat index.jsp
from 172.20.1.101
<br/>
session=<%=session.getId()%>

Server 2

[root@c5477d71795c ROOT]# pwd
/var/lib/tomcat/webapps/ROOT
[root@c5477d71795c ROOT]# cat index.jsp
from 172.20.1.102
<br/>
session=<%=session.getId()%>

然后访问 http://172.20.1.101:8080/ 和 http://172.20.1.102:8080/。

可分别显示来自哪个 Server 和对应的 SessionId,并且刷新页面时 SessionId 不会变化(即使是使用 Ctrl+F5 刷新)。

配置 Nginx

修改 Nginx 的配置文件, 加入新的 upstream 配置和 server 配置。

upstream tomcat {
server 172.20.1.101:8080;
server 172.20.1.102:8080;
}

server {
......
location /cat {
proxy_pass http://tomcat/;
}
}

重启 Nginx:

[root@ce12b3b4ce00 sbin]# ./nginx -s reload

访问 http://172.20.1.10/cat 并刷新,发现 from 172.20.1.10x 一直在变化,并且session=xxx 也变化。

说明:此时 Nginx 的配置无法保证 Session 一致性!

解决方案

在 Tomcat 后面部署 Redis,MemCached 等内存数据库来保存 Session 相关信息。

本例中在 Nginx 服务器上安装 memcached 来解决 Session 一致性问题。

安装 memcached

在 Nginx 容器中使用 yum 安装:

yum install -y memcached

启动 memcached

使用 memcached 命令启动:

memcached -d -m 128m -p 11211 -l 172.20.1.10 -u root -P /tmp/

参数说明:

  • -d: 后台启动
  • -m: 缓存大小
  • -p: 端口
  • -l: IP地址
  • -P: 服务启动后系统进程 ID 存储文件的目录
  • -u: 服务器以哪个用户作为管理用户

修改 Tomcat 配置

在两台 Server 中修改 tomcat 的配置:

[root@3a53f7504511 ROOT]# vi /etc/tomcat/context.xml 

# context标签中加入下面的内容
<Manager
className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.20.1.10:11211"
sticky="false"
sessionBackupAsync="false"
lockingMode="auto"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
sessionBackupTimeout="1000"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory" />

导入 jar 包使用 yum 安装的 Tomcat 可将 jar 包放在 /usr/share/java/tomcat/ 目录下。

需要的 jar 包:

图片

Maven 依赖如下:

<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.2</version>
</dependency>

<dependency>
<groupId>com.couchbase.client</groupId>
<artifactId>couchbase-client</artifactId>
<version>1.4.11</version>
</dependency>

<dependency>
<groupId>com.googlecode</groupId>
<artifactId>kryo</artifactId>
<version>1.04</version>
</dependency>

<dependency>
<groupId>de.javakaffee</groupId>
<artifactId>kryo-serializers</artifactId>
<version>0.11</version>
</dependency>

<dependency>
<groupId>de.javakaffee.msm</groupId>
<artifactId>memcached-session-manager</artifactId>
<version>1.8.2</version>
</dependency>

<dependency>
<groupId>de.javakaffee.msm</groupId>
<artifactId>memcached-session-manager-tc7</artifactId>
<version>1.8.2</version>
</dependency>

<dependency>
<groupId>com.googlecode</groupId>
<artifactId>minlog</artifactId>
<version>1.2</version>
</dependency>

<dependency>
<groupId>de.javakaffee.msm</groupId>
<artifactId>msm-kryo-serializer</artifactId>
<version>1.8.2</version>
</dependency>

<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>reflectasm</artifactId>
<version>1.01</version>
</dependency>

<dependency>
<groupId>net.spy</groupId>
<artifactId>spymemcached</artifactId>
<version>2.11.4</version>
</dependency>

注: 如果依赖和 Tomcat 版本不对应可能会什么也不显示,此时响应码为 500。

验证

上述步骤都正确配置之后, 再次访问 http://172.20.1.10/cat 并刷新会发现 SessionId 不再变化。

文章目录
  1. 1. HTTPS 请求跳转
  2. 2. 问题解决