内容来源:2017 年 11 月 04 日,中兴高级系统架构师魏猷君在“2017厦门软件技术峰会”进行《高可靠性网络架构实践》演讲分享。IT 大咖说(微信id:itdakashuo)作为独家视频合作方,经主办方和讲者审阅授权发布。
阅读字数:4540 | 12分钟阅读
摘要
微服务是当今软件架构的流行技术,而微服务架构的设计和落地、工程化运用一直是比较困难的问题。本案例分享了一个如何在光通信网络子系统设计中,采用微服务的架构,erlang语言及otp框架进行设计及工程化运用的实践。Erlang诞生于爱立信的cs lab,otp是开放通信平台,这两者天然就是用来做通信系统设计和开发的。如今越来越多的互联网公司,如whatsapp,使用erlang开发,取得了很好的效果。本案例通过一个已经交付商用,在多省市通信网络上已经稳定运行1年多的跨地域分布式嵌入式子系统的架构设计和工程实践,为大家展示了erlang的设计理念以及其天然的微服务编程模型在工程化运用中的强大效果。
嘉宾演讲视频及PPT:http://t.cn/RrKzhbg
Erlang简介
Erlang是一门设计用来开发电信级可靠性软件,面向并发的函数式编程语言。也是一种内置支持并发、分布式以及容错的运行时环境。单单看这些定义可能不太好理解,下面我们来直接看一段代码。
-module(mapReduce)
-export([map/2,pmap/2])
map(F,L) ->
[F(I) || <- L].
pmap(F,L) ->
s = self(),
pids = map(fun(I) -> spawn(fun() -> do_f(s,F,L) end)
end, L),
gather(pids).
gather([H|T]) ->
receive
{H, Ret} ->
[Ret | gather(T)]
end;
gather([]) ->
[].
do_f(Parent, F, I) ->
parent | {self(), (catch F(I))}.
这段代码是MapReduce在Erlang中的实现,可以看到只有简单的22行代码,而且并没有用到很多第三方的库。第四行的map有F和L两个参数,F是function,L是一个队列,这行代码实际上就是将很多要执行的函数map到并发体上执行。下面的Gather是一个reduce的过程,并发体执行完成之后要将结果返回,最后再计算出答案。
现在很多人都在谈论微服务,在讲到微服务所带来的好处时通常都是说在并行开发、化整为零、提高速度等等。但是有一点被大多数人忽略了,即微服务可以充分利用多核的性能,当然这方面可能确实涉猎的人不多。
我们之前的软件开发和摩尔定律是绑在一起的,即使软件写的差一些其实也没太多关系。这主要是因为根据摩尔定律阐述,每18个月晶体管的数量会增加一倍(即性能增加一倍),CPU的价格则会下降一半。这种情况下硬件性能的提升可以有效的弥补软件性能低的问题。
但是现在情况正在慢慢发生改变,目前我们已经很少有频繁更换家用PC的CPU的需求了,这是因为CPU的主频很久没有大的提升。在计算机性能过剩的同时,现在的很多软件编程正在走向基于多核的趋势,CPU单核正在走向极限。因为摩尔定律实际上是半导体行业提出的定义,随着不断逼近半导体工艺的极限速度会慢慢下降。而现在正是快到极限的时期,这时为了能够再提升CPU的性能,多核就成了解决方案。所以现在的CPU趋势并不是让单核的能力越来越高,而是让更多的核集中在一个CPU中,这样功耗和工艺上都能取得很好的平衡。但是现在很多程序员在编程的时候没有考虑到这一点,因此经常会出现CPU的某一个核心在快速运转,其他的核心却没有动静。
这张图是双核CPU的曲线,机器上正在运行mapreduce程序用来计算一个数。刚开始的时候没有用并行的方式处理,所以两条曲线的波动很不一致。后续使用并行方式后,两条曲线的波动基本就一致了。这说明CPU的核调度其实是很合理的。
Erlang精要介绍
Erlang的语法学习很简单,基本上看一两个星期的书就能够学会。接下来要讲的这些可能无法再书中了解到的知识。
Erlang的名字来源有两个,一方面它是爱立信计算机科学实验室发明的“爱立信语言”,所以使用了爱立信的前两个字母Er。另一方面是为了纪念丹麦数学家Erlang,他电话网络分析的奠基人。
Erlang最早基于Prolog(一门逻辑推导语言,很多时候是用在人工智能上),后续又加入了samlltalk,最后还加入了容错并发分布式处理。
Erlang有两个最强大的特性,一个是高可伸缩并发性,它一个进程所占用的字节以k为单位,而且可以同时创建成千上万个进程(这里的进程指的是在Erlang虚拟机上的),所以高并发并不是问题。另一个是高可靠性,它可以实现9个9的可靠性。
就像人有三观一样,编程语言也有自己的三观。而Erlang的世界观就是一切皆并发,并发间只能通过收发消息来交互。
虽然Erlang有很多特性,但实际上这些特性都是基于“容错”这一核心价值观之上。另一方面Erlang又很简单,但需要有一定的阅历来理解这种“简单”,很多时候我们都会觉得它太死板,效率太低,可也正因为如此Erlang才能保持旺盛的生命力。
业务需求分析及领域模型
在对Erlang语言有了一定了解之后,我们接下来看一下如何用Erlang来解决实际问题。
业务分析
15年的时候我们接到有分布式APO(自动光功率优化)需求的项目, 而且需要3个月交付,时间上很紧。分布式APO子系统开发涉及到跨网元分布式计算,应用场景多,联调接口多,业务逻辑复杂。 前期评估发现我们5个人至少需要半年时间才能完成,最后实在没办法只好选择用Erlang尝试解决。
效果:三高一快零故障
最后我们实现的效果总结起来就是“三高一快零故障”。三高首先是系统可靠性高,我们进行了分布式处理,添加了4层容错机制。第一层是硬件主备的1+1保护机制。第二层是os守护进程,它会监控每个业务进程的心跳,如果发现有业务心跳停止,就会自动重启该业务进程。第三层是Erlang自身附带的OTP系统平台级别监督,前面提到过Erlang的进程非常轻量级,这些进程挂掉之后,Erlang有一个机制可以让你自定义进程重启,而且重启的时间会非常快。第四层是应用级业务状态回退,即一旦发现业务处理过程中存在异常,进程会自动回退到上一个正常状态。
三高的第二点是开发效率高,我们大概写了8千行Erlang代码,最后发现它能够实现10万行C代码的功能。
第三点是交付质量高,最后的系统测试故障率降低到50%以上,中电信CDC测试一次通过。当然测试的过程中也会有一些新的功能要开发,而我们1个人5天就完成了CDC测试新需求的开发和自测。目前这套系统现在已经部署到了多个省市的现网,运行了1年半还是零故障。
开发原则
在我们开发的过程中存在三个原则,分别是业务第一、架构中心、保持简单。下面会对他们做详细介绍。
1. 光网络通讯概要
光网络通讯和高速公路建设其实很像,首先我们手机上网的wifi信号经过路由器转换为光信号,然后光信号通过合波器聚集到一根光纤上,再通过光纤的功率放大向更远处传播。到达目的地之后使用分波器分离光纤中的不同波长,这些不同的波实际上承载着不同信息,最后这些信息会被转化为电信号,而这些电信号所到达的就有可能是某台服务器。其实我们生活中上网、上微信、打电话经历的都是这样一个过程。
APO在这个过程中起到的作用就是监测光纤上每一个波长的光功率情况。随着光纤设备的老化,光路中光的子波长功率会发生变化,可能会影响到系统业务。这就像在高速公路中行驶的车辆需要时刻注意油量,如果油量不够开不到下一个加油站,那就只能等拖车了。
还是拿高速公路为例,我们可以这样看待APO。比如说我们要组织一个自驾游,这时会定义一些站点作为集散地,到达集散地之后需要检查每辆车油量。同时还要控制每辆车在加油站所加的油量,保持每辆车的油量都差不多。最后面对这些有着不同目的地且耗油量不同的车辆,还需要对他们进行分组管理。
2. 业务第一
开发原则中的业务第一简单来说就是开发语言擅长处理的场景要和业务场景匹配。我们之前在一些硬件的驱动上使用过Erlang,后来发现并不是很合适。虽然Erlang能够很快的处理业务,但是不能控制底层硬件的计分器。当时采用的是Erlang调C的程序来解决问题,不过这实在太绕了。最后我采用了另一种方式,用Erlang自动生成C的驱动代码,这样就没有问题了。这里一开始之所以不好用,就是因为没有找对所匹配的业务点。
Erlang之所以能够用在APO中,首先APO是一个纯软件功能,不涉及一些硬件的控制。其次它的配合接口多,即需要和网关进行通讯,也需要和下面的设备通讯,这些通讯都是基于以太网和包的。另外它是跨网元通信,所以涉及到了分布式,这方面刚好是Erlang的强项。最后它的状态机复杂,而Erlang也很适合写状态机,表达的意思非常强。
很多人认为编程语言是工具,而我个人认为它不仅仅工具,更是构建业务的材料,只有合适的材料和工具才能更好的完成任务。这也是我们为什么选择Erlang的原因。第一Erlang语言诞生于电信行业,很适合电信软件开发的需求,第二Erlang的表达能力强,适合写复杂的业务逻辑,第三Erlang是居于并发编程,适合并发建模和并行开发,最后Erlang有强大的平台和丰富的库,大大提升了开发效率。
3. 架构中心
开发原则的架构中心,就是以架构为中心进行软件开发。我们在软件开发的初期采用快速原型设计方式,先对业务进行并发建模,打通消息交互流程,验证架构和算法正确性。进而对业务各个部分进行精细化设计,在分模块进行并行开发,实现业务功能。
4. 保持简单
最后是保持简单的原则,首先要架构保持简单,这样才好理解,也能够灵活应对变化。其次是技术保持简单,少用框架,少写代码,我们项目开发的过程中也曾考虑过是否要引入Erlang的自动测试框架,后来发现其实没必要,因为我们的团队构造很简单,而自动化测试框架的生成报表功能对我们来说并不实用。最后是管理保持简单,保持小团队,以获得更好的敏捷性。
掉坑逃生指南
我们的技术提升其实就是在不断的踩坑和爬出的过程中慢慢积累的,下面就和大家讲下如何有效的从掉进的坑中爬出。这里有三条建议,第一条是有效的笨办法,只要能解决问题就不要在意方法是不是够优雅。第二条是深入系统内部的关键细节,比如我们刚开始做的Erlang虚拟机,在对Shell进行调试的时候,会莫名的挂掉。后来我们从操作系统代码中发现,操作系统IO处理和Erlang虚拟机IO处理会产生冲突,这就导致问题的出现变的随机,最后还是找到公司内部的操作系统相关人员才解决了问题。 第三条是头脑风暴和技术直觉,有时实在无法解决的时候,多人一起讨论有可能会出现转机。
以上为今天的全部分享内容,谢谢大家!
推荐文章