OpenResty+Redis实现网关灰度发布

OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

什么是OpenResty

以下内容来自OpenResty官网

OpenResty® 是一个基于 NginxLua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

OpenResty® 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。

OpenResty® 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。

参考 组件 可以知道 OpenResty® 中包含了多少软件。

安装OpenResty

  1. 本次安装采用yum方式安装,离线安装请参考OpenResty中文官网的安装教程,离线方式安装

  2. 在yum 仓库中添加openresty的安装源

    sudo yum install yum-utils
    sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
    
  3. 安装openresty

    sudo yum install openresty
    
  4. 安装命令行工具

    sudo yum install openresty-resty
    
  5. 查看openresty 仓库中的软件包

    sudo yum --disablerepo="*" --enablerepo="openresty" list available
    

软件库

到此安装就完成了。默认安装位置在 /usr/local/openresty,该目录下包含了 luajit, lualib, nginx, openssl, pcre, zlib 这些组件。

  1. 使用脚本启动,OpenResty安装时, 已经把路径加入了/usr/bin, 并且添加了服务 /etc/init.d/openresty, 可以通过服务脚本启动
systemctl start/stop/status openresty #启动、停止、查看状态
  1. 可以通过-p参数设置工作目录,后续将会把nginx、openresty的conf、log、html都存放在该目录下
openresty -p /data/openresty-conf/

防火墙端口开放,我这边就先关闭防火墙了,在生产环境上只开放openresty的互联网端口如80、443。

然后通过访问对应openresty服务的地址或域名就看访问到欢迎页

首页

Lua Demo

后续更新Lua语法相关文章......

1、创建lua server文件夹

 mkdir lua-learn
  1. 创建lua脚本
vim test.lua

ngx.say("hello world");

3、配置nginx.conf

	在server段中添加以下代码
	lua_code_cache off;  #关闭lua缓存,在不用重启nginx也可以实时访问lua脚本
    location /lua { 
        default_type 'text/html';  
        content_by_lua_file /usr/example/lua/test.lua; 
    } 

通过访问nginx中配置lua路径即可访问到有lua编写的脚本内容

Centos7 下OpenResty ab性能测试

1.服务器说明

我这边使用另一台虚拟机向openresty服务器发起请求,以减少对openresty服务器的影响。

服务器版本CPU内存
Centos7.9 OpenResty12
Centos7.9 Httpd(ab)12

2.压力测试

安装ab工具

yum -y install httpd-tools

测试前对服务器进行配置

net.ipv4.tcp_syncookies= 1	//打开TIME-WAIT套接字重用功能,对于存在大量连接的Web服务器非常有效。 
net.ipv4.tcp_tw_reuse= 1	//减少处于FIN-WAIT-2连接状态的时间,使系统可以处理更多的连接。
net.ipv4.tcp_fin_timeout=30 //减少TCP KeepAlive连接侦测的时间,使系统可以处理更多的连接。
net.ipv4.tcp_tw_recycle= 1	//快速回收,慎用!慎用!慎用!
net.ipv4.neigh.default.gc_stale_time=120	//决定检查过期多久邻居条目
net.ipv4.conf.lo.arp_announce=2		//避免arp放大攻击
net.ipv4.icmp_echo_ignore_broadcasts = 1	//表示开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0。
net.ipv4.icmp_ignore_bogus_error_responses = 1		//开启恶意icmp错误消息保护
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0		//避免无源路由包
net.ipv4.tcp_keepalive_time = 1200		//如果对方不予应答,探测包的发送次数
net.ipv4.tcp_max_syn_backlog = 65536	//个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
net.ipv4.tcp_max_tw_buckets = 6000	//参数设置为 1 ,表示允许将TIME_WAIT状态的socket重新用于新的TCP链接,该参数默认为180000,过多的TIME_WAIT套接字会使Web服务器变慢。

#使配置生效
sysctl -p

测试命令

ab -r -c 10000 -n 100000 http://192.168.62.127/lua

测试结果

测试指标请求次数用时错误请求
1W并发10W347S0
1.5W并发15W438S6
2W并发20W517S12

OpenResty + Redis实现灰度发布

主机描述

IP描述
192.168.62.127虚拟机:OpenResty服务,Tomcat1
192.168.62.128虚拟机:Tomcat2
192.168.62.1宿主机: Redis

实现思路:

用户发起请求到openresty代理的网关,由openresty获取请求ip,然后向redis获取白名单地址,如果该请求ip为白名单ip则将流量转发到代理相对应的后端服务器上。可在redis中动态设置白名单,实现服务切换。

实现代码

local redis=require "resty.redis";

local red=redis:new();

red:set_timeout(1000);
--redis连接ip 端口
local ok,err=red:connect("10.18.63.44", 6379);
--redis 密码
ok,err=red:auth("******");

if not ok then
  ngx.say("redis 连接失败",err);
  return;
end
--请求ip
local client_ip = ngx.req.get_headers()["X-Real-IP"];
if client_ip == nil then
   client_ip = ngx.req.get_headers()["x_forwarded_for"];
end
if client_ip == nil then
   client_ip = ngx.var.remote_addr;
end


client_ip=ngx.var.remote_addr;



--redis中获取白名单
local ip_lists=red:get("grayIp");

--判断是否在白名单然后转到对应服务
if string.find(ip_lists,client_ip) == nil then
  ngx.log(ngx.INFO, "client_ip",client_ip);
  //对应的负载服务器
  ngx.exec("@server1");
else
  ngx.log(ngx.INFO, "client_ip",client_ip);
  ngx.exec("@server2");
end

local ok,err=red:close();

测试

此时redis中的ip不是客户端ip

访问openresty时获取到的白名单ip与请求ip不符,则将请求转发到127的后端应用。

然后将redis中的ip换为宿主机的ip

然后重新发起请求,请求ip与白名单ip匹配,则将流量转发到128的后端应用

至此就完成了简单的灰度发布功能。

openresty还有其他的应用场景,如:高并发的首页,可以由redis存储预加载数据,由openresty进行页面渲染。还有秒杀类功能、网关限流等。

总结

OpenResty有了nginx高并发和lua丰富的一方库和可以由开发者自定义的lua库的加持能让前端代理服务器也实现一些简单、高性能的需求,在之前的开发中需要由后端网关完成的功能,现在在openresty中就可以完成。由于lua脚本的特性支持热更新,不用频繁重启服务而影响业务。

Comment