Contents

用OpenResty构建网关(1)—— 基础框架与网关架构

Lua语言

Lua语言是一个轻量级的脚本,号称“性能最高的脚本语言“,已经有很多地方使用到它包括nginx、wireshark、wrk、魔兽世界等游戏插件等等。Lua脚本的解释器是C语言实现的,已经有人研究过解释器,才200K左右,它轻巧紧凑,且能与C语言交互,是一种很好的胶水语言。

Lua语言的特性有如下:

  1. 类C,大小写敏感,分号可选;

  2. 变量类型可推导,作用域默认是全局的,用_G[‘varName’]可访问全局变量,可以指定为local的;

  3. nil和false是false,其他一切都是true;

  4. 函数闭包,函数可作为变量使用,函数可以有多返回值;

  5. Table为推导的,根据值,可以是数组,可以是Map;

  6. MetaTable,用来重载各种操作符。其中重载 __index 操作并结合操作符:这个语法糖,可以扩展出面向对象的范式;

  7. 利用require、dofile函数可以动态载入lua文件;

OpenResty框架

OpenResty是业界大牛章同学的作品,查过一些资料,这位大神低调自由,喜欢讲技术细节,专注写代码写文档,你说这样的程序员能在中国的典型的互联网混么,当然不可能,因为我们的牛人大多谈大架构、大体系、宏观,所以这个人被Cloudflare自由散漫的养着。居说他离开阿里的时候写的代码生成器,后来无人敢改。

废话少说,我们继续OpenResty,它是基于Nginx这个网络服务器,用lua语言扩展开的框架,大致就是在Nginx处理请求的不同阶段,嵌入执行Lua解释器。Lua脚本成了Nginx的接口,这一套东西被包装成了OpenResty这个框架,logo是一只蜂鸟,非常切意。

OpenResty在Nginx的的不同处理阶段嵌入了解释器,不同处理阶段如下图:

/OPENRESTYPHASE.png

*图片摘自https://github.com/openresty/lua-nginx-module

  1. 初始阶段(Initialization Phase):全局启动时初始化init_by_lua,nginx worker启动时的初始化init_worker_by_lua;

  2. 重写/接入阶段(Rewrite/Access Phase):set_by_lua流程分支处理判断变量初始化,rewrite_by_lua转发、重定向、缓存等功能(例如特定请求代理到外网),access_by_lua*IP 准入、接口权限等情况集中处理(例如配合 iptable 完成简单防火墙);

  3. 内容阶段(Content Phase):content_by_lua内容生成,balancer_by_lua代理内容,header_filter_by_lua响应头部过滤处理(例如添加头部信息),body_filter_by_lua响应体过滤处理(按chunk获取到内容,无法获取整体,例如完成应答内容统一成大写);

  4. 日志阶段(Log Phase):log_by_lua*会话完成后本地异步完成日志记录(日志可以记录在本地,还可以同步到其他机器)。

lua语言本身、绑定变量不赘述,openresty官网有详细说明,我讲一下在网关开发过程中一些 trick and trap:

  1. 使用lua_shared_dict 这个LRU缓存配合Redis的pub/sub机制,做配置数据加载/读取/更新;

  2. 需要做集群,开发gossip协议太复杂,节点先为自己生成UUID,再用Lua脚本向Redis竞争成为Master,先到先得,定时续命;

  3. API的质量数据收集、动态限流均采用init阶段的定时器向Redis执行Lua脚本来做,发现超阈值立即发通知,进行限流规则的变更;

  4. 尽可能使用local变量、函数,尽可能使用lua Module,用require来组织模块链接;

  5. Redis Cluster分片需要考虑业务数据分片,这里采用了按时间片分片。执行redis lua时,需要对redis的lua客户端改造,支持lua脚本load到所有cluster节点,支持按key的hash tag的slot结果寻找对应的cluster node;

  6. 采用蓄水池算法进行采样,防止内存不够用。

网关架构

整个API网关主要为了做如下几件事情:

  1. 限流:根据规则对特定的请求进行限流;

  2. 分流:根据规则对特定的请求进行分流;

  3. 数据收集:对所有请求数据进行按API标识和时间片收集采样;

  4. 降级(动态限流)

网关的整体架构如下图:

/GATEWAY_ARCH.png

后续

在这个专题的后几篇,讲把网关实现的细节关键点一一讲述。