Ceryx 动态的 NGINX

默北 NginxCeryx 动态的 NGINX已关闭评论12,1816字数 2175阅读7分15秒阅读模式

反向代理包含数百甚至上千个微服务是一个很有意思的事情,也是我们在 Sourcelair 每天都要面对的事情。这也是为什么我们今天要很高兴地宣布 Ceryx,一个动态反向代理,使用 OpenResty,Lua 和 Flask,可以代理主机上任意多的服务。它的配置是即时生效。在过去几个月里我们一直在做 Ceryx 项目。现在我们将它开源。

Ceryx文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

摘要

SourceLair,我们快速提供开发环境并努力让 web 开发可以无障碍,并使用云的力量。我们提供的一个优秀服务之一是每个项目有一个公共的 URL,它始终可用,并自动刷新你的代码。这样我们需要每小时启动和停止多用户容器,并在不停机的情况下路由每个用户的公共 URL 到当前容器。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

以前的解决方案

Ceryx 是去年我们开发的内部项目。为了找到解决我们问题的最佳方案,我们尝试了各种技术。在这条路上,我们保持 API 的稳定不受变化的影响。有一个很好的话题没有放到这里,你可以在 API Meetup Athens 找到我们的 slides。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

Twisted,MongoDBRedis

首先,我们使用基于 Twisted 自定义反向代理,Twisted 非常好用,是使用 Python 写的事件驱动的网络引擎。如果在 Redis 缓存中没有查到,服务就以 MongoDB 查询做为路由。不管是使用数据库查询,还是调用 API 添加,更新或删除路由,缓存都是流行的方式。对我们来说,它工作得很好,很快 Twisted 有了一个很好用的反向代理 API 可以使用。这个应用让我们错失的一件事情是,Twisted 在默认情况下,每个反向代理头部不能设置成你想要的,在某些情况会导致一些无效的转发。但是用它工作是很方便的。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

tproxy和Redis

在 Twisted 之后,我们又尝试了 tproxy。tproxy 是一个使用 Gevent 创建的 TCP 路由代理(第七层),Gevent 深受 Ruby 的 ProxyMachine 影响由著名的 Gunicorn 创建。我们创建了一个查找层用来替代静态路由和文件,它会查找后端的 Redis。我们从 MongoDB 彻底地分离了服务,因为路由是短暂且易于重建的。同样我们将 API 分离出来用 Flask 写了独立的服务。主要的问题是 tproxy 的开发有点被遗弃。最后一次提交是一年前。我们需要重新做一些性能优化,还有一个有趣的 bug,响应没有包含响应长度,并保持开放直到超时。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

NGINX 和 etcd

我们已经决定将代理作为一个服务而不是一个盒子,我们调研了 NGINX 和 HAProxy。因为我们非常熟悉前者并且对它的表现很满意。我们所有的前端都是一直使用 NGINX。我们创建了一个监控脚本,它监控etcd 的重要变更,并自动加载 NGINX 的配置。我们还修改了我们的 API,让它和 etcd 一起做为后端工作。这大大改善了性能。但过了几周我们发现配置的变更没有我们想像得快。NGINX 的重新加载几乎是瞬间的。但配置要花一段时间接收人工配置才能生效。导致路由更新变得缓慢。对我们来说最重要的问题是这种重新加载时间超过10秒,导致多次出现“服务已停止"页面,直到新的配置生效。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

OpenResty 和 Lua 就是我们的救星

当前,Github 记录关于他们在 NGINX 使用 Lua 脚本对 GitHub pages 进行更频繁的重载 - 之前他们大概 30 分钟重载一次。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

当我们在寻找另外一个替代品的时候,对这篇博文非常感兴趣,就开始深入研究 OpenResty - NGINX 的风情版本,使用 Lua JIT 编译,还有其他第三方 NGINX 模块。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

我们决定继续用回 Redis 作为后端,因为我们已经准备好 API ,Redis 也已经在内存中,也因此查询速度非常快。我们同时使用 Redis 进行其他服务和缓存,所以不需要再考虑其他集群。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

解决方案就是 Ceryx,现在已经开源,提供给每个人使用。这包括了 NGINX lua 脚本和 API,可以轻松的使用 Docker Compose 部署。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

把所有的一切都缝合在一起

NGINX 提供几个钩子,可以在请求的几个阶段执行 Lua 代码。Ceryx 只会在代理阶段之前采取行动 -在  "access_by_lua_file" 阶段,即是 Lua 路由器。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

此路由器会查询 NGINX 和 Redis 后端的本地内存缓存,以此确定目标主机和将会到来的主机端口,如果没找到就返回一个通配符目标。一个 Redis 查询返回一个结果时,这个结果会被缓存 5 秒,所以后续请求不会影响 Redis - 当需要静态文件(比如 CSS,JavaScript 和图像)的时候这会是一个很好的改进,这时候会同时抛出多个请求。可以通过增加缓存超时来对 Ceryx 进行量身定做,适应各个应用的需求。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

与此同时,提供一个简单的 Flask 服务,为路由和使用新路由更新 Redis 后端提供一个 CRUD API。代理和 API 服务共享相同的环境变量,用来配置 Redis,保持一致性。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

第一印象

最新的 Ceryx 发布第一周后,我们看到了其在反向代理和大幅减少休眠服务页上的巨大改进。在更多地细节上,升级前的 Ceryx,每个开发会话平均有 10 个页面浏览量,而现在我们仅仅需要 2.5 个。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

下一步

Ceryx 是在 MIT 协议下的开源项目,因此我们乐见用户贡献或者提出 bug 以及新功能请求。我们计划添加 StatsD 测量功能到 Ceryx,这样我们可以更好改进和优化一些相应的部分。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

Ceryx Github项目期待你的想法和贡献。文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/ 文章源自运维生存时间-https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/

weinxin
我的微信
微信公众号
扫一扫关注运维生存时间公众号,获取最新技术文章~
默北
  • 本文由 发表于 11/09/2015 01:00:47
  • 转载请务必保留本文链接:https://www.ttlsa.com/nginx/ceryx-a-dynamic-nginx/