Nginx + Lua + Memcache基于IP实现灰度发布
- 1. 在192.168.1.19、192.168.1.21上部署Tomcat
- 2. 在`192.168.1.20`主机上配置`Memcache`并让其支持`Lua`调用
- 3. 配置`Nginx`
- 4. 现在我测试一直只能访问旧版
- 5. 现在将某一定范围的ip值设置为1(比如整个杭州地市的ip导入到Memcache中),模拟灰度发布
- 执行过程
- 用户请求到达前端代理
Nginx
,内嵌的Lua
模块会解析Nginx
配置文件中的Lua
脚本 -
Lua
脚本会获取客户端IP
地址,查看Memcache
缓存中是否存在该键值 - 如果存在则执行
java-prod
(旧版),否则执行java-test
(新版) - 如果是
java-test
,那么location
会将请求转发至新代码集群组 - 如果是
java-prod
,那么location
会将请求转发至旧代码集群组
系统 | 服务 | 地址 |
CentOS7.4 | Nginx + Lua + Memcache | 192.168.1.20 |
CentOS7.4 | Tomcat(集群)8080_Prod版本 | 192.168.1.19 |
CentOS7.4 | Tomcat(集群)8081_Test版本 | 192.168.1.21 |
1. 在192.168.1.19、192.168.1.21上部署Tomcat
[root@centos7u4-node1 ~]# mkdir -p /soft/app && cd /soft/app
[root@centos7u4-node1 app]# wget https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.14/bin/apache-tomcat-9.0.14.tar.gz
[root@centos7u4-node1 app]# tar xf apache-tomcat-9.0.14.tar.gz
[root@centos7u4-node1 app]# yum install -y java
# 改Test版本Tomcat端口
[root@centos7u4-node2 /soft/app/apache-tomcat-9.0.14/conf]$ vim server.xml
...
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
# Tomcat集群8080_Prod版本
[root@centos7u4-node1 apache-tomcat-9.0.14]# netstat -lntp |grep java
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 1610/java
tcp6 0 0 :::8009 :::* LISTEN 1610/java
tcp6 0 0 :::8080 :::* LISTEN 1610/java
[root@centos7u4-node1 apache-tomcat-9.0.14]#
# Tomcat集群8081_Test版本
[root@centos7u4-node2 /soft/app/apache-tomcat-9.0.14/bin]$ ss -lntp |grep java
LISTEN 0 100 :::8009 :::* users:(("java",pid=3116,fd=58))
LISTEN 0 100 :::8081 :::* users:(("java",pid=3116,fd=53))
LISTEN 0 1 ::ffff:127.0.0.1:8005 :::* users:(("java",pid=3116,fd=73))
[root@centos7u4-node2 /soft/app/apache-tomcat-9.0.14/bin]$
[root@centos7u4-node1 ROOT]# vi java.jsp
<%@page import="java.text.SimpleDateFormat"%>
<%@page import="java.util.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP在页面显示实时时间</title>
</head>
<body>
<%
Date d = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String now = df.format(d);
%>
<h1>Tomcat 8080 - Prod - 旧版</h1> //8081服务器上是<h1>Tomcat 8081</h1>别的都一样
当前时间:<%=now %>
<br>
</body>
2. 在192.168.1.20
主机上配置Memcache
并让其支持Lua
调用
Nginx安装配置Lua支持:
[root@nginx_lua ~]$ yum install -y memcached
[root@nginx_lua /soft/src]$ wget https://github.com/openresty/lua-resty-memcached/archive/v0.14.tar.gz
[root@nginx_lua /soft/src]$ tar xf v0.14.tar.gz
[root@nginx_lua /soft/src]$ mkdir /soft/nginx/conf/lua
[root@nginx_lua /soft/src]$ cp /soft/src/lua-resty-memcached-0.14/lib/resty/memcached.lua /soft/nginx/conf/lua/
# 启动Memcached,并加入开机自启
[root@nginx_lua /soft/nginx/conf/lua]$ systemctl start memcached.service
[root@nginx_lua /soft/nginx/conf/lua]$ systemctl enable memcached.service
3. 配置Nginx
[root@nginx_lua /soft/nginx/conf/conf.d]$ vim lua.conf
lua_package_path "/soft/nginx/conf/lua/memcached.lua";
upstream java_prod {
server 192.168.1.19:8080;
}
upstream java_test {
server 192.168.1.21:8081;
}
server {
listen 80;
server_name 192.168.1.20;
include proxy_params;
location /ip {
default_type 'text/plain';
content_by_lua '
clientIP = ngx.req.get_headers()["x_forwarded_for"]
ngx.say("Forwarded_IP:",clientIP)
if clientIP == nli then
clientIP = ngx.var.remote_addr
ngx.say("Remote_IP:",clientIP)
end
';
}
location / {
default_type 'text/plain';
content_by_lua_file /soft/nginx/conf/lua/dep.lua;
}
location @java_test {
proxy_pass http://java_test;
}
location @java_prod {
proxy_pass http://java_prod;
}
}
[root@nginx_lua /soft/nginx/conf/conf.d]$ vim ../proxy_params
#proxy_redirect default;
# 默认情况下,NGINX在代理请求中重新定义两个头字段“Host”和“Connection”
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 要防止将头字段传递给代理服务器,可将其设置为空字符串
proxy_set_header Accept-Encoding "";
proxy_connect_timeout 30; #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 60; #后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 60; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_buffer_size 32k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 4 128k; #proxy_buffers缓冲区,网页平均在128k以下的话,这样设置
proxy_busy_buffers_size 256k; #高负荷下缓冲大小(proxy_buffers*2)
proxy_temp_file_write_size 256k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传
client_max_body_size 10m; #允许客户端请求的最大单文件字节数
client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数
[root@nginx_lua /soft/nginx/conf/conf.d]$ vim /soft/nginx/conf/lua/dep.lua
--建立memcache连接本地11211端口
local ok, err = memc:connect("127.0.0.1",11211)
--无法连接前往前端跑出错误信息
if not ok then
ngx.say("failed to connect: ",err)
return
end
--获取对象中的ip,存在则赋给res
local res, flags, err = memc:get(clientIP)
--ngx.say("value key: ",res,clientIP)
if err then
ngx.say("failed to get clientIP:",err)
return
end
--如果值为1则调用local-@java_test-新版本
if res == "1" then
ngx.exec("@java_test")
return
end
--否则调用local-@java_prod-旧版本
ngx.exec("@java_prod")
return
4. 现在我测试一直只能访问旧版
5. 现在将某一定范围的ip值设置为1(比如整个杭州地市的ip导入到Memcache中),模拟灰度发布
[root@nginx_lua ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
set 192.168.1.6 0 0 1
1
STORED
然后在访问同一个地址http://192.168.1.20/java.jsp得到了不同的显示了
# 删除这个ip有访问的是旧版的了,实现了灰度发布
[root@nginx_lua ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
set 192.168.1.6 0 0 1
1
STORED
END
delete 192.168.1.6
DELETED
quit