起因
事情的起因是因为咱们接口被刷了,所以需要做点安全方面的操作
然后刚好我有这方面的经验(OpenResty) 所以就接手这需求,开始设计一个属于自己的api gateway。虽然已经有成熟的开源项目,但是比较重,可能未必完全贴合我们的要求,个性化难以满足 哔哩吧啦 所以开始了踩坑之旅。
引用介绍
OpenResty官网:http://openresty.org/cn/
OpenResty最佳实践:https://moonbingbing.gitbooks.io/openresty-best-practices/content/
开发一个需求 我一般有4步, 计划、执行、检查、修复
计划:
计划也就是需求分析,初步挖掘自己要做什么,简单的分析后列出如下几个需求:
1、防止别有用心的人使用程序刷接口 可从ip入手,限制同ip的访问,毕竟ip库是要钱的 成本太高也没人会刷
2、请求头过滤、咱们的app和h5都有特别的请求头用于标识身份,虽然这个限制并没有啥暖用
3、灰度发布
第一版本,也不要求太高,先从简单的入手
本来做出我是想通过在nginx上面配置一个统一的location 然后根据动态的规则调整uri映射到后端服务,但是最终放弃了这个想法,因为对我们现成的配置改动较大,也不方便应用nginx的原生模块 如proxy_pass、upstream 最终选择维持现有的配置不变,为每一个location需要特别处理的执行阶段加入需要的处理脚本
这里引用:https://moonbingbing.gitbooks.io/openresty-best-practices/content/ngx_lua/phase.html 的介绍
set_by_lua: 流程分支处理判断变量初始化
rewrite_by_lua: 转发、重定向、缓存等功能(例如特定请求代理到外网)
access_by_lua: IP 准入、接口权限等情况集中处理(例如配合 iptable 完成简单防火墙)
content_by_lua: 内容生成
header_filter_by_lua: 响应头部过滤处理(例如添加头部信息)
body_filter_by_lua: 响应体过滤处理(例如完成应答内容统一成大写)
log_by_lua*: 会话完成后本地异步完成日志记录(日志可以记录在本地,还可以同步到其他机器)
ip防刷和请求头过滤都通过在access_by_lua阶段,设置相应的执行脚本完成
灰度发布通过 proxy_pass、upstream、balancer_by_lua 配合完成
初始化加载配置通过 init_worker_by_lua*完成
重载配置 通过配置特殊location 由后端服务主动发起
我假定读者理解nginx基本运行原理 熟悉配置,知道master与worker进程 也理解lua语言 最好还有一部分的后端编程经验
程序的大概工作流程是:
1、先必须启动后端服务(java)
2、启动nginx,启动阶段通过后端服务提供的http接口获取运行时配置,含黑名单策略,缓存服务器地址等。
nginx接收到请求,以ip加接口地址为key存入redis(使用lua脚本实现incr与expire的原子操作),当达到阈值,调用后端服务提供的添加黑名单http接口
3、后端服务监控指定的负载均衡列表的服务器的端口,发生变化时推送最新配置到nginx,或者是在手动修改权重时推送。
api gateway的配置我保存在mysql数据库,使用java与spring boot构建后端程序用于与nginx交互,提供配置或者推送配置,都是通过http接口。黑名单ip存放在redis
网友评论