如何用AI技术降噪? QCon 广州“音视频架构实践”专场给你答案! 了解详情
写点什么

又拍云叶靖:基于 Docker 的云处理服务平台

  • 2016 年 11 月 15 日
  • 本文字数:4112 字

    阅读完需:约 13 分钟

10 月 20 日 -22 日,由 InfoQ 主办的 QCon 2016 全球软件开发大会上海站已成功举办。作为云 CDN 行业的代表企业,又拍云受邀出席了本次大会。又拍云系统开发工程师叶靖在“微服务实践与架构演进之路”分论坛上,发表了“基于 Docker 的云处理服务:更新、扩容与自动容错”的主题演讲。(以下为演讲实录)

大家早上好,我叫叶靖,来自杭州又拍云科技有限公司。又拍云为客户提供场景化 CDN、云存储、云处理等服务,比如针对直播,我们提供又拍直播云解决方案。我在又拍云主要负责云处理这方面的业务,所以今天的分享也和云处理有关,主要介绍又拍云基于 Docker 的云处理服务平台,我将会着重分析我们平台是怎么做服务的更新,以及我们在处理能力不够的时候是怎么扩容的;或者是当我们一台服务出现故障时候,我们是怎样快速切掉的。

总结起来,其实我们想要解决的就是三个问题:

  • 第一个问题:怎么做无宕机时间的更新——更新的时候,我的服务、我的请求不能出现任何的异常;
  • 第二个问题:怎样做自动扩容以及故障恢复,换一种说法就是怎样可以方便地提升我的处理能力,以及可以快速摘除故障的机器;
  • 第三个问题:如何方便的对请求进行改写,我们有一些需求是要对原始的请求进行一些请求的改写操作。

关键在路由

总结一下,要达到这三点,其实只要做一个东西就够了,那就是需要在云处理集群的最前面做路由。让这个路由支持无宕机时间的更新,让它支持方便进行扩容与故障摘除,也让它支持能够对请求进行改写。我今天主要是分享又拍云在做的一个东西。

首先从路由开始说起,说到服务路由,要涉及到三个概念:服务注册、服务发现和负载均衡,如下图:

服务注册就是我的容器需要主动上报我提供的服务的名字,以及所在 IP 端口这些信息;

服务发现是把服务注册的信息集中起来;

因为我们提供的容器非常多,还需要在容器之间做负载均衡。

服务发现有很多开源的工具可以用,比如 Consul、etcd 和 Apache Zookeeper。Consul 功能多一些,所以我们选型的时候选择它作为我们服务发现的工具。

在选型上,又拍云选了 Nginx,架构简图如图所示:

最下面是 Mesos,Mesos 上面跑的是容器,服务都是以容器提供的,有做图的,音频的,各种各样的服务,有一些是特殊的服务,比如可以用 Registrator 做注册服务,上报到 Consul,前面的 Nginx 主要是做负载均衡,通过 upstream 把请求代理到下面。在 Consul 中的服务地址改了以后,怎样快速反馈给 Nginx 呢?其实如果把这个解决了,这个图就可以非常好地运转起来。

这个方案要做得很简单,需要解决 Consul 的服务如何主动、方便更新到 Nginx。我们调研了一下,发现有这么几种解决方案:

第一种解决方案是用 Consul template,监听 Consul 中服务变动,当配置变动时,由模块重新生成配置,最后对 Nginx 进行 Reload 操作,让它生效。这里有一个例子,如图:

上图的框里面是一个配置的模块,中间两个括号括起来的都是一些需要被实例化的变量,当服务发生改变的时候,会生成真实的配置文件,然后用生成的真实的配置文件进行 reload 操作,Reload 是一个平滑的过程,不会对当前的请求造成任何影响,所以可以达到更新 Consul,并且把 Consul 的信息反馈给 Nginx 的目的,但是我们没有采用这个方案,因为缺点比较多。我们希望找到更好的办法,更优雅地改变 upstream,所以我们又想到第二个方案,用 DNS,这个方案非常好理解,用内部的 DNS 对 IP 进行解析,但是这个方案隐藏着更大的问题。

以上两个方案都不行,那我们想要什么方案?我们想让 Nginx 监听一个管理端口,可以通过对管理端口发指令,让它自己更新 Upstream,有没有这样的方案呢,其实是有的,下面是一个开源的 Nginx C 模块,它做的事情就是通过 HTTP 指令更新、操作、删除 upstream,如下图:

这里有个例子:

上图例子中,请求了 8080 端口,发现 502 了,因为这个时候,我们在 host 下面没有任何上游服务存在,最后给 127 的 8081 端口发送请求,要在 Nginx 动态加上两个 server 地址,他们对应的 host 就是 dyhost,第三个指令和第一个指令是完全一样的,但是结果不一样,它返回了正确的输出,并没有返回 502,说明这第二个指令中的两个地址已经生效了,这个已经完全达到了我们的目的,通过一个 HTTP 请求,改变 Nginx 的 upstram。

又拍云用了第三个方案大概两个月之后,感觉还是有一些问题困扰着我们,最终我们选择重新造轮子。为什么没有继续走下去,原因如下:

又拍云经验——造轮子

为了解决面临的问题,我们开始造自己的轮子。经过讨论,我们决定用 lua 建造一个符合我们需求的轮子。

介绍这个轮子之前,我简单介绍一下 Openresty 项目,它的原理就是把 Nginx、Nginx 的 lua 模块以及常用的 lua 代码,集合起来打包成一个项目,由一整个项目提供高性能 web 服务器。
下图是我们的动态负载均衡,它目前是已经开源的,由四部分组成,

  • 第一部分就是 Nginx,官方的 Nginx,没有任何改动;
  • 第二部分是 Nginx Lua 模块;
  • 第三个部分是 lua resty checkups,它是把 Nginx upstream 模块常用的功能单独抽出来,用 lua 重新实现了一遍;
  • 第四部分是 luacocket 是用于加载配置信息的。

我们造的这个轮子,有什么特点,有什么功能?

首先它是一个动态负载均衡,它的功能如下图:

第二个特点是我们以 host 区分服务,这里有一个例子,

如图我发了两个 CUR 请求,它的地址是一样的,都是 1.155 的 3130 端口,但是它的 host 不一样,最终这两个请求所到达的处理集群是不一样的,一个是拿图片的宽高信息,另一个是对图片进行缩略图等这些做图操作。

下图是我们请求的流程图:

从一开始接收请求到把 HTTP 里面的 host 解析出来,解析出来以后这里涉及到动态 lua 代码加载,当 host 解释出来以后,我们到 upstream 列表里面查后端有没有提供服务,如果有的话会进行转发。

在上图的状态里可以看到椭圆中那两个我们刚刚加进去的服务,因为有主动健康检查,如果加的是有问题的服务地址,会显示一个错误,比如我们第二个加进去的就是不存在的地址,然后这个服务就不会被 Nginx 选为可用的上游。

接下来介绍一下动态 lua 代码加载,为什么要做动态 lua 加载这个功能?

首先因为我们是一家 2B 的公司,需要方便地对客户的请求做改写;

需要执行简单的参数检查,节省带宽。

这些 lua 代码动态注入 Nginx 里,让 Nginx 执行。下图是动态 lua 加载的例子:

中间是 lua 的代码,它的意思是说我想要把 host 为 admin.upyun.com 的 DELETE 操作全部禁用,除此之外,任何你想象出来的操作都可以用 lua 代码实现,它的功能是非常强大的。我们 lua 代码也有状态页,当我们加入了 lua 代码,可以看到当前跑的 lua 代码的版本以及加载时间等信息。

上面内容讲的都是一些特性和功能,接下去主要介绍我们是怎么实现这些功能的,主要涉及到三个功能:动态的 upstream 管理怎么做、负载均衡和动态 lua 加载。

动态 upstream 是三个步骤:

  • 启动的时候通过 luasocket 从 consul 加载配置文件;
  • 第二步,加载完配置之后,Slardar 会启动一个管理端口,监听指令,
  • 接着会启动一个定时器,进行 worker 间同步。

下图是一个 upstream 管理的流程图,最开始的时候,从 Consul 加载,一个是接收端口更新指令的,然后另外一个到定时器,这个定时器不断超时查看共享内存,,如果发现共享内存里的版本与当前进程不一致,就更新到进程内部。

在了解了怎样管理 upstream、怎样做 upstream 的同步后,我们还要在 upstream 之间做负载均衡,这个主要通过 lua 的指令实现,叫 balance by lua。

Nginx 的负载均衡可以分成两步:

  • 第一步通过 upstream 的 C 模块选一个可用的后端服务的地址;
  • 第二步,会把请求代理到上一步选的后端地址。

这个指令,它的作用就是作用在 upstream 选择这步的,比如我们写在 upstream 里面,就不会再进原来 C 模块的代码,而会到我们指令后面的 lua 代码里面来,这样可以在 lua 代码里面控制这些 upstream 的选择,因为我们有 lua 版的 checkups,所以这些操作可以很好的结合起来。

主要的代码就两步,如下图

第一步就是用我们 checkups 选一个可以用的 peer,根据什么选,就是根据当前请求的 host 选;第二步是从 Consul 或 HTTP 请求 body 加载代码。

目前在又拍云内部很多项目都已经用上了这套方案,我们有这么多优势,对于性能怎样,我们做了非常简单的对比,如图所示:

上图的对比有一个地方不一样,就是圈出来的地方,左边是用 lua 做 upstream 选择的,相应的 upstream 配置会有一些变化,右边是原生 Nginx 的配置。对这样的配置进行压测,压测的结果在 QPS 峰值上没有明显差距,所以用 lua 版方案和 C 方案在性能上的损耗其实可以忽略的,可以放心用它。

最近微服务非常火,我们也做了改造,如果我们把这样的架构改成微服务,Slardar 能做什么?我想我们服务肯定是多很多,IP 端口也多很多,那 Slardar 能做什么,举一个例子。

上图是作图服务拆分的示意图,如果我们不进行微服务改造的话就只有中间这个作图服务,它做了所有的工作、所有的缩略图操作。改造之后,这个大的作图,会被分解成一些小的作图模块,这些小的模块,各自提供服务,当然都是以容器的形式,比如做缩略图需要硬件加速,就可以把它抽出来了,可以做很多实例,水印的可能还是按原来老路子走,就是 CPU 做,也不需要太多实例,切开以后,发现中间大的服务,虽然是不需要任何功能的,因为它只要做调度,但是它需要从 Consul 里面拿到所有微服务的地址,并且还要去做一些负载均衡,因为地址有好多个,还有做容错,还得去做定时的更新,因为这个服务的地址,可能是会更新的,更新了以后要重新拉内部的地址,这样显得中间这个做图服务就会做了很多不该属于它做的工作。为了解决这样的问题,我们在中间又加了一层 slardar。

中间加了 slardar 后,上面的作图就不需要微服务的端口,直接给我们内网的 slardar,带上你需要访问的微服务的名字,这个名字带上以后,由内网的 slardar 做路由选择,里面会维护所有微服务的地址,它会做重试、做服务的更新,从这可以看出来,我们其实是把 Consul 里面一部分服务发现的工作,给它下移到我们 slardar 里面,Consul 可能会变成一个持久化存储的角色,可能是把服务发现的角色弱化掉了,这样的话,使内网服务的层级,看起来更加的清晰。

2016 年 11 月 15 日 03:02768

评论

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

持续学习 和 灾难性遗忘

infoQ-LolitaAnn

人工智能 深度学习 5月月更

【架构学习09】——电商秒杀系统

tiger

架构实战营

位运算小妙招-求二进制序列中1的个数

芒果酱

c++ C语言 5月月更

5 月 20 日,API 网关 Apache APISIX Summit ASIA 2022 重磅来袭

Apache APISIX 中国社区

开源 API网关 Apache APISIX APISIX 网关 APISIX Summit

Druid连接池源码阅读01

石小天

【架构学习10】——毕业总结

tiger

架构实战营

C语言_标准时间与秒单位的转换

DS小龙哥

5月月更

区间合并算法

秋名山码民

算法 5月月更

趣学设计模式-代理模式

ZuccRoger

5月月更

沙利文发布《2021年中国数据库市场报告》:中国分布式数据库2021专利占全球76%

科技热闻

flask上传作品之dbm操作

上进小菜猪

flask 5月月更

『Python』题集⒋

謓泽

Python 5月月更

druid源码学习一

Nick

源码 Druid

GaussDB(for Influx)与开源企业版性能对比

华为云开发者联盟

数据库 开源 查询 写入 GaussDB(for Influx)

明道云入选爱分析2022年两份低代码研究报告

明道云

数据库连接池-Druid 源码学习(一)

wjchenge

初始化 Druid 源码、

网站开发进阶(五十四)jQuery获取父级元素、子级元素、兄弟元素方法汇总

No Silver Bullet

JQuery框架 5月月更

极狐GitLab入驻阿里云计算巢,共同提升云上开发体验

阿里云弹性计算

DevOps 计算巢

为了让女朋友运动起来,小伙儿不仅买单车还设计了智能防盗单车锁

华为云开发者联盟

stm32 华为云IoT 智能防盗单车锁 蓝牙

YUV数据分析

Loken

音视频 5月月更

kubernetes下的Nginx加Tomcat三部曲之三

程序员欣宸

Java Kubernetes 5月月更

面试突击47:死锁产生的原因有哪些?

王磊

Java 面试 java面试

druid源码阅读(一)整体概览

爱晒太阳的大白

5月月更

共同推动基础软件根技术发展,华为与中国软件行业协会签署战略合作协议

科技热闻

ptrace注入分析

小道安全

数据湖揭秘—Delta Lake

阿里云大数据AI技术

sql spark 分布式计算 关系型数据库 存储

【ELT.ZIP】OpenHarmony啃论文俱乐部——大数据框架性能优化系统

ELT.ZIP

大数据 OpenHarmony 压缩算法 ELT.ZIP

【LeetCode】乘积小于 K 的子数组Java题解

Albert

LeetCode 5月月更

来自2022年的Python 网络爬虫补充知识,HTML+JSON+爬虫场景

梦想橡皮擦

5月月更

赵海鹏:如何进行OpenHarmony音频特性架构设计和开发工作

OpenHarmony开发者社区

OpenHarmony 开发者故事 开发者说

【ELT.ZIP】OpenHarmony啃论文俱乐部——云计算数据压缩方案

ELT.ZIP

云计算 OpenHarmony 数据压缩 ELT.ZIP

「云智公开课」百度沧海·存储

「云智公开课」百度沧海·存储

又拍云叶靖:基于Docker的云处理服务平台_语言 & 开发_叶靖_InfoQ精选文章