一、安装Lua环境及相关库
1. LuaJIT
1 | wget http://luajit.org/download/LuaJIT-2.0.5.tar.gz |
2. ngx_devel_kit和lua-nginx-module
1 | wget https://github.com/simplresty/ngx_devel_kit/archive/v0.3.1rc1.tar.gz |
3. 编译Nginx
1 | wget http://nginx.org/download/nginx-1.15.2.tar.gz |
4. 加载lua库,加入到ld.so.conf文件
1 | echo "/usr/local/LuaJIT/lib" >> /etc/ld.so.conf |
二、灰度实现
1. 灰度目标
当客户端ip为192.168.56.1
时,让其访问新发布的upstream测试实例;其他ip访问时还是老的upstream实例。相当于前者为新发布功能,后者为稳定的生产功能。
2. 灰度准备
这里使用
memcache
来存储哪些ip要访问新的,哪些ip访问稳定的老的。1
2
3
4
5
6
7
8
9
10
11yum install memcached
memcached -p11211 -u nobody -d
# 设置 灰度ip
telnet 127.0.0.1 11211
set 192.168.56.1 0 0 1
1
get 192.168.56.1
# 安装lua-resty-memcached
wget https://github.com/openresty/lua-resty-memcached/archive/v0.14.tar.gz
tar -zxvf v0.14.tar.gz -C /usr/local/src/
cp -r /usr/local/src/lua-resty-memcached-0.14/lib/resty /usr/local/LuaJIT/share/luajit-2.0.5/准备两个服务
新上线服务
与稳定生产服务
,这里使用两个tomcat来演示(如果你熟悉node 也可以使用node快速实现两个后台服务)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#测试页面
vim test.jsp
1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8" %>
2 <!DOCTYPE html>
3 <html lang="en">
4 <head>
5 | <meta charset="UTF-8">
6 | <title>Test Jsp</title>
7 </head>
8 <body>
9 | <%
10 | | Random rand = new Random();
11 | | out.println("<h1>Test server</h1>");
12 | | out.println("<h1>Random number:</h1>");
13 | | out.println(rand.nextInt(99) + 100);
14 | %>
15 </body>
16 </html>
# 两个tomcat: tomcat8080, tomcat9090,前者作为新上线服务,后者作为 稳定的生产服务;将上面的test.jsp页面分别放置到两个tomcat的ROOT下;tomcat9090 删除test.jsp中的11行,以示区别。
# 分别启动两个tomcat配置Nginx nginx.conf
1
2
3
4
5
6
7
8
9
10| location / {
| | default_type 'text/html';
| | content_by_lua_file /opt/app/lua/dep.lua;
| }
| location @server{
| | proxy_pass http://127.0.0.1:9090;
| }
| location @server_test{
| | proxy_pass http://127.0.0.1:8080;
| }编写
/opt/app/lua/dep.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28local clientIP = ngx.req.get_headers()["X-Real-IP"]
if clientIP == nil then
| clientIP = ngx.req.get_headers()["x_forwarded_for"]
end
if clientIP == nil then
| clientIP = ngx.var.remote_addr
end
local memcached = require "resty.memcached"
local memc, err = memcached:new()
if not memc then
| ngx.say("failed to instance memc:", err)
| return
end
local ok, err = memc:connect("127.0.0.1", 11211)
if not ok then
| ngx.say("failed to connect: ", err)
| return
end
local res, flags, err = memc:get(clientIP)
--ngx.say("value key: ", res, clientIP)
if err then
| ngx.say("failed to get clientIP ", err)
end
if res == "1" then
| ngx.exec("@server_test")
| return
end
ngx.exec("@server")启动Nginx,访问测试
在本机使用 curl http://127.0.0.1/test.jsp
查看效果,返回结果无 Test server 字样。
在192.168.56.1
访问 http://192.168.56.101
(此ip为Nginx 服务所在ip) 查看效果,返回结果有 Test server 字样。
三、小结
以上只是简单的针对某个 ip
做的灰度,完整的灰度,还需要企业后台灵活的管理memcache
。
另外要实现更灵活的灰度,比如根据 Cookie, header 头信息,也可以个根据这种原理来实现。