Qwen3 惊喜上线阿里云百炼,8款模型全开源!点击免费领取 800万 tokens! 了解详情
写点什么

京东 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:5210680

评论

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

一文带你了解Zookeeper所有核心概念

小隐乐乐

zookeeper 分布式 分布式架构

国产开源流媒体SRS4.0对视频监控GB28181的支持

潇湘落木

音视频 云直播 短视频 流媒体

实战案例丨ModelArts在数据标注、数据过滤上的应用技巧:自动分组

华为云开发者联盟

人工智能 数据 图像识别 图片 分类

一文了解JDK12 13 14 GC调优秘籍-附PDF下载

程序那些事

GC JDK14 秘籍 JDK12 JDK13

主宰操作系统的经典算法

苹果看辽宁体育

后端 操作系统

Nginx 限流配置

Bruce Duan

nginx

Spring Boot + Vue前后端分离项目,Maven自动打包整合

xcbeyond

maven 前后端分离 springboot 部署

7个获取访问者真实IP的方法,速学!!!

华为云开发者联盟

nginx 大前端 网站 IP 服务器

LeetCode 1052. Grumpy Bookstore Owner

liu_liu

算法 LeetCode

Go: 通过代码学习 Map 的设计 — Part II

陈思敏捷

map Go 语言

Java架构-Java代码规范那些事

我是苞谷

Java

week8 作业

Shawn

ARTS 第 5 周

乌拉里

Kafka两个高性价比的参数调优

我是个bug

Java 大数据 kafka

Redis系列(七):缓存只是读写回种这么简单吗?如果是,那么请你一定看看这篇文章!

z小赵

redis 分布式 高并发系统设计

推荐一款技术人必备的接口测试神器:Apifox

狂师

测试 测试驱动开发实战营 接口测试 测试框架

Linux服务器存在某进程CPU过高如何追溯其问题根源?

Nick

Java Linux centos

架构师那些不能碰的禁忌

曲水流觞TechRill

架构师

HTTPS详解

Bruce Duan

https 对称加密 非对称加密

正则表达式基础详解

懒猫

Java 正则表达式 大前端 正则

[POJ 1002] 487-3279 C++解题报告

一直AC一直爽

POJ ACM

架构师训练营第八周作业

张明森

如何消灭飞机的“黑色十分钟”,AI来帮忙

华为云开发者联盟

华为 AI 智能时代 模型 华为云

华为云FusionInsight MRS融合大数据平台进阶之路

数据湖洞见

大数据 新特性 FusionInsight 华为云 智能数据湖

IO系列——UNIX五种IO模型

Java联盟

io 多路复用 异步IO

干货分享丨玩转物联网IoTDA服务系列四-智能网关

华为云开发者联盟

物联网 智能设备 应用场景 华为云 mqtt

API接口限流

Bruce Duan

分布式限流 单体限流 限流算法

节约60%成本!虎牙直播云端大数据是怎么做到的?

腾讯云大数据

上海首批金融科技“监管沙盒”应用名单出炉 区块链技术备受青睐

CECBC

金融科技 金融监管 创新与安全 智能多元化

一个好用的工作生活平衡方式

霍太稳@极客邦科技

职场求生攻略答疑篇之 1 —— 加班沉思录

臧萌

程序员 加班

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