写点什么

京东 Nginx 平台化实践

  • 2016-10-24
  • 本文字数:3275 字

    阅读完需:约 11 分钟

Nginx 是优秀的 HTTP 和反向代理服务器,京东各部门都在广泛使用,但普遍都面临着一些问题:

  1. 配置复杂,专业性强。
  2. 配置文件无法批量修改且配置变更依赖重启操作。
  3. 不同应用依赖不同模块、配置项,管理混乱。
  4. 同一应用的 Nginx 无法批量、快速扩容。

所有问题的根源在于 Nginx 是一个单机系统,虽然模块化、高性能,但在互联网高速发展的今天,像京东这样拥有大规模 Nginx、业务集群的场景下,所有问题都有可能被无限放大,针对这种现状我们设计研发了 JEN(JD EXTENDED NGINX),截止目前 JEN 已覆盖京东金融大部分核心业务,如夺宝吧,卡超市,白条等。

一、整体结构

图 1:JEN 结构图

如上图,运维通过 Web 控制台做相应的配置操作,若是分流、限流等配置,则信息入库等待 Nginx 通过 Restful API 同步规则后开始生效;若是平滑升级、重启等强运维性操作,则 Web 控制台通过控制 Ansible 对 Nginx 进行相应操作。

图 2:Nginx 和 Web 控制台多机房部署图

JEN 特点:

  1. 支持 Nginx 自动发现,分组管理,状态监控。
  2. 统一入口,通过抽象配置,简化操作管控 Nginx 集群生命周期,并支持规则批量配置,操作批量执行。
  3. 扩展了原生 Nginx 的分流、限流功能,支持规则的内存实时同步,无需修改配置文件,更无需重启 Nginx 进程。

1. 基础信息

Web 上所有的展示和操作全部基于对基础信息的计算整合,主要包含两类:

  1. 分组信息(业务线、应用、机房、Nginx IP)
  2. Nginx 属性,例如 upstream 信息,server_name,listen_port 等,主要来源 Nginx 读取 Nginx.conf 内容后的信息上报(心跳)

对于分组信息,JEN 支持以下两种方式填充:

  1. 调用外部服务的 Restful API 导入完整的基础信息。
  2. 对自动发现的 Nginx 做分组的手工编辑。

图 3:各分组间关系图

如上图,分组包括业务线、应用、机房、Nginx 共四层关系,在大规模集群环境下可以通过这种关系并结合 Nginx 属性,支持对所有操作的批量执行,如批量修改配置文件,批量升级重启等,解放生产力。

2. 规则获取

用户在 Web 控制台配置后,在 Nginx 端我们实现了全异步的模块支持定时向 Web 获取属于当前 Nginx 的规则信息,规则存储内存,即时生效,其中:

a)规则信息每个进程存储一份,避免进程间资源共享导致锁竞争。

b)版本号设计,保证规则和心跳的绝对顺序,不因丢包、延迟等网络因素导致版本错乱,而且在规则未变更时 Nginx 无需频繁解析大量规则信息而消耗 CPU 资源。

3. 安全

JEN 支持三类角色,每种角色支持不同的操作权限(默认是普通用户角色,无写权限),任何角色对 Web 的任何操作都会被记录,并在 Web 提供了入口支持多维度操作日志查询,便于审计

4. 监控

我们实现了更为全面的监控信息采集与展示,包括:

a)扩展了 tengine 的主动探测模块,支持上游服务器的平均、当前延时统计。

b)通过与 Web 的心跳保持支持 Nginx 存活状态监控。

c)支持 TCP 连接信息,in/out 流量,QPS,1xx 到 5xx 回应报文等信息监控。

以上的监控信息支持分组统计(业务线、应用、机房)和大屏展示,便于相关人员(业务,运维)实时监控应用状态。

二、分流

概念:根据请求特征(IP,header 中任意关键字)支持把某些特定请求分流到单个或多个上游服务器中,如下图:

图 4:分流示例图

分流主要适用灰度发布,ab testing 等场景,另外我们也对分流功能做了扩展,支持 Web 控制台一键启停上游服务器,便于当应用服务器需要维护或升级时,用户请求正常访问。

三、限流

京东 618 等大促,货物都提前堆积在购物车,等待零点秒杀,换成工程师的语言来说,就是前一秒的 QPS 很低,但是下一秒 QPS 非常高,流量大意味着机器负载高,若一个应用的一两台机器没有扛住,这样就会导致整个应用集群雪崩。

限流不可盲目,首先需要根据业务特点选择合适的限流算法(漏桶算法、令牌桶算法),其次需要结合历史流量、应用服务能力、营销力度等因素综合评定限流参数,最后决定以何种优雅的方式反馈用户。

Nginx 在实现上通过共享内存共享限流中间信息的方式来达到多进程间的状态统一。在 JEN 设计初衷,原本计划和分流一致,即每个进程存储一份限流规则,限流只在当前进程内限流,但不可避免的会出现如下问题:

  1. 每个进程“你限你的,我限我的”,信息不一致进而导致限流不准确。
  2. 类似用户 ID 的限流,在京东这样拥有庞大日活用户的场景下,每个进程需要开辟足够大的内存才能避免限流算法中对于红黑树节点的频繁置换,这样一来 Nginx 占用内存就会随着进程数成倍扩大。

我们的做法:

  1. 预分配共享内存,Nginx 获取到限流规则时动态适配一块共享内存。
  2. 规则共享,生效后实时同步至所有进程,规则链保证所有旧版本规则只有在当前流量更新之后才会删除,如下图:

图 5:规则链

我们在限流功能上的几点扩展:

  1. 支持错误页定制,除了返回 Nginx 静态页,还支持 302 错误页重定向,根据在 Web 控制台的配置可以重定向到任何外部链接,但 302 重定向存在一个问题:用户浏览器的 URL 和内容都发生了变更,意味着用户需要重新输入 URL 重新请求或者是重复之前的操作步骤,用户体验差可能导致用户放弃此次购买行为而转投它家。在逻辑上我们通过 Nginx 的 subrequest 机制支持返回内容发生变更而 URL 保持不变,这样一来每当用户被限流,只需重新刷新页面即可重复之前的操作步骤。

图 6:两种错误页对比
2. 通过扩展限流算法支持限流后一段时间不可用,例如按 IP 限流且某个 IP 已经触发限流,则支持该 IP 一段时间内不可访问,无需重新通过算法计算。
3. 同步实现了黑名单、白名单功能,通过白名单避免一些复杂场景下的限流“误杀”(例如 nat 网络下按 ip 限流)。

四、运维特性

运维特性主要指 Nginx 的安装、升级、配置文件修改、启停等操作,运维特性与之前介绍内容的最大区别在于需要重启操作,所以结合第三方工具 Ansible 是比较合适的想法(Ansible 相对于 Puppet 等运维工具,其迁移成本相对较小)。

在实际生产中 Ansible 和 Web 为避免单点需要集群部署,我们的方案是:Web 和 Ansible 在同一 PC 上部署,相关数据改用 DB 存储替代 Ansible 本地文件存储,通过这种简单的改造可以方便 Ansible 和 Web 这组“套件”进行扩容。

图 7:自动化运维操作逻辑图

如上图,用户通过 Web 操作控制 Ansible 对 Nginx 进行升级、重启等操作,Web 是 Nginx 操作的统一入口,这是平台化的重要意义所在,可以放弃 SSH,Shell 甚至是监控系统,开始在 JEN 自给自足了。

通过主动拉取或者是用户在页面导入、手工配置,JEN 会为所有 Nginx 存储配置文件,这样不仅原本因为每个应用都依赖不同的配置项而导致管理混乱的局面得到了改善,而且也可以方便的对配置文件做些扩展,例如历史记录追溯,配置比对,配置复用,操作回滚等。

在页面执行相关操作时,Web 会读取 Ansible 的标准输出并在页面实时展示,为了让使用者以相对友好的方式获知进度我们对 Ansible 做了优化:

  1. 丰富了标准输出的内容,尽量细化到每一个步骤。
  2. 格式化标准输出,便于 Web 获取和展示。

Nginx 在生产环境大规模部署,倘若因为一些原因导致 Nginx 大规模异常,这是我们不希望看到的,所以在可靠性方面,JEN 也提供了多种机制来保证:

1. 三层错误校验,保证只有在完全正确的情况下才会重启和更新进程,中途发生任何错误不影响线上服务

a)在 Web 填充表单时做第一层校验。

b)在目标机器做操作时做第二层检测,例如先执行 Nginx –t 校验。

c)执行完毕做第三层校验,例如端口是否启动,进程数是否一致等。

2. 灰度执行

a)单个 Nginx 依次执行,有任何异常立即中断开始人工介入。

b)按百分比支持批量执行,例如某个机房的 Nginx 先升级 10%。

五、总结

以上整理了京东在 Nginx 平台化方面的一些实践,JEN 提供了统一入口管控整个 Nginx 生命周期,并支持规则的批量修改即时生效,我们希望这些实践经验能对所有读者产生帮助。

作者介绍

吴建苗,目前就职于京东金融杭州研发中心,负责 Nginx,MQ 项目,对高性能服务器开发和调优具有浓厚兴趣。欢迎沟通交流(微信号 wujm1230)。


感谢木环对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2016-10-24 17:5210409

评论

发布
暂无评论
发现更多内容

南京大学苏州校区学生代表团到访合合信息,开启“沉浸式”人工智能企业行

合合技术团队

人工智能 科技 校企合作 南京大学

Pytest 编写自动化测试用例规则

测吧(北京)科技有限公司

测试

Rust 错误处理在 GreptimeDB 的实践

Greptime 格睿科技

rust 错误 错误处理

软件测试丨Pytest 参数化与调度执行

测试人

软件测试

比特币临近10万美元回调:后市走势与关键因素解读

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 代币开发

DolphinScheduler JavaTask动态传参秘籍:轻松实现任务间数据流动

白鲸开源

开源 干货 Apache DolphinScheduler 参数传递

婚恋交友系统可上榜可语音可交友可线下婚恋可组局可打包APP小程序系统本身问题我们免费修复

多客潇潇

婚恋交友相亲APP小程序 源码交付支持二开 可语音

InDesign for Mac(id 2022中文版)

Mac相关知识分享

Comprehensive Analysis of IPQ5312 and IPQ9554: Features, Bands, Performance, and Mining Applications

wifi6-yiyi

WiFi7

技术实践 | AI 安全:通过大模型解决高危WEB应用识别问题

百度安全

Web兼容性测试思路详解

测吧(北京)科技有限公司

测试

并行区块链全解:执行原理、代表项目及技术发展周期

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 钱包开发

从孤岛到协同,集成式财务规划的未来

智达方通

数据孤岛 业财融合 集成式财务协作 财务协作

为什么不建议中小企业自己研发管理系统?

积木链小链

企业管理 数字化 ERP 中小企业

Pytest 结合数据驱动的用法详解

测吧(北京)科技有限公司

测试

Web兼容性测试思路详解

测吧(北京)科技有限公司

测试

如何使用PHP开发1688商品详情API接口

科普小能手

数据采集 1688 API 接口 1688代采 1688 API

Steinberg Cubase Pro 12 for mac(音乐创作软件)

Mac相关知识分享

SecureCRT & SecureFX 9.6 发布,新增功能概览

sysin

securecrt SecureFX

Pytest 参数化与基本装饰器用法

测吧(北京)科技有限公司

测试

AIC和ScaleFlux(锐钲)发布基于NVIDIA BlueField-3 DPU的新型存储阵列

ScaleFlux

2024年最新互联网Java面试八股文(附互联网大厂P5-P8技术栈)

采菊东篱下

程序员 java面试

2024华为云开源开发者论坛完整议程揭晓,云原生专场邀您共探前沿技术!

华为云原生团队

云计算 容器 云原生 Volcano kubeedge

Python多任务编程在软件测试中的应用

测试人

软件测试

NineData ChatDBA发布重大更新,准确率飙升

NineData

数据库 大模型 ChatGPT NineData ChatDBA

VTS:基于Apache SeaTunnel的开源向量数据迁移工具

白鲸开源

GitHub 数据集成 Apache SeaTunnel 开源、 VTS

Pytest 框架与常用操作

测吧(北京)科技有限公司

测试

Pytest框架:提升软件测试的利器

测试人

软件测试

Demo发布- ClkLog客户端集成-React Native

ClkLog

sdk 用户行为分析 开源软件 画像

用豆包MarsCode ,陪你云赏月

豆包MarsCode

Supersonic 推出混合休闲游戏开发大赛 为开发者提供丰厚资金支持与专家指导

Geek_2d6073

京东Nginx平台化实践_最佳实践_吴建苗_InfoQ精选文章