架构师小组交流会:每期选一个时下最热门的技术话题进行实践经验分享。
第三期:微服务。微服务架构以其高度的弹性、灵活性和效率的巨大提升,快速受到各领域架构师和技术决策者的关注。它的基本理念是将一个肥大的系统拆分成若干小的服务组件,组件之间的通讯采用轻量的协议完成。我们本期小组交流会来探讨一下,现在互联网公司的微服务实践情况。
嘉宾:京东章耿、原唯品会
石廷鑫
、七牛陈爱珍
本文是对此次交流的整理,分了上下两篇文章。
第一轮:自由交流
京东章耿:大家好,我是京东基础架构部平台中间件的章耿,主要负责京东的服务框架,配置中心等项目。京东11年底进行.NET转Java的技术变革,当时就提出了接口的SOA化的概念。那时京东业务发展非常快,项目越来越多,服务化是必然的趋势。京东的服务化框架是一共有两代。第一代是12年开始,我们使用开源的一个实现,用Dubbo作为RPC框架,Zookeeper 作为注册中心,那时应该算一个主流的技术选型。我们在开源的基础上做了一些易用性和功能扩展,比如说支持REST、支持kryo/thrift等序列化,服务监控等,这个框架在那时的业务规模和节点数量下面还是比较稳定的。14年初我们开始自研服务框架。为什么这么做呢?一个是之前的服务框架还是有很多可以提升的地方,不管是性能还是服务治理的一些功能,因为京东的机器数,机房也在不停的建,网络拓扑的复杂直接需要高级的服务治理功能;还有一个就是接口节点等数量级的增加,当时我们的接口规模慢慢的已经好几千了,接口的实例也几十万;另外就是用开源的有些内部系统打通比较麻烦,所以我们要做升级换代。当时也是考量了用开源的改改,还是全部自己重新做的抉择。后来觉得一个是有时间,二是觉得自己有能力做一个符合京东自己的定制化的服务框架,所以14年我们就开始自研框架,做了整整一年。15年初我们上线新版的服务框架。
我们新的注册中心,是无状态的一些节点,基于数据库做最终一致性。为什么选数据库,替换以前的Zookeeper?因为Zookeeper是树状结构,从某些维度查询它要遍历整棵数,用数据库的好处就是可以从多维度的查询分析过滤,不管是机房、 IP,都可以去查询,分析,过滤比较结果。然后Zookeeper在跨机房的时候有一个问题,它是半数节点存活才可以用,所以如果跨机房部署的话,最起码得3个机房,才能保证集群整体可用。还有Zookeeper它是强一致性的的,比较依赖网络。如果网络不好,如果跨机房断网的时候,它其实是不可用的,读都不能读,所以会带来一定的问题。以前用zookeeper注册服务端,就是写一个临时节点,等服务端死了节点自动消失的。但是你在网络一抖的时候,或者是服务端和Zookeeper之间有网络故障的时候,它其实会不小心把它摘掉,因为Zookeeper认为它死了,但其实它不一定真的死了,所以这个时候就需要有一些辅助的去判断它是不是真的死了。第一次遇到的情况是那个临时节点,后来我们是把它改成永久节点,然后定时的去telnet 它的端口,像Dubbo是直执行ls 命令,我们也是直接执行一个命令,看它有没有响应,那是第一代的时候。在JSF的框架里有一个哨兵的组件,我们的Provider会定时的发心跳,对于注册中心来说,它知道最后的心跳时间,然后定时刷到数据库里面,看哨兵的情况,如果没有哨兵,数据库里面保存一个最后心跳时间,这时候你可以用定时任务去找它,这是我们最早的一个版本。后来我们改进了,因为有时断网了,这个心跳时间就不准了。所以在每个机房还布了一套独立的程序,没心跳的同时再由它来判断是否可用,如果这个同机房的程序都连不上,我们再把它置成一个不可用的状态,双重保证。另外以前Zookeeper的时候服务列表是下发的全量列表,例如1000台加一台,下发的是1001台,而新版注册中心我们是推变化的部分,只推加1台,大大节省了数据的推送量。
RPC框架,我们内部叫杰夫,JSF,京东服务框架的简称
。
我们是用基于Netty自己研发的。为了兼容上一代版本,兼容之前的dubbo协议,所以我们也是用的无代码入侵的;我们在同一个端口支持多协议,包括自定义的JSF协议,http协议,dubbo协议等。目前
我们只有C++和J
ava的客户端,然后如果是其它语言例如Golang,python,PHP的话,我们都会让他向我们的一个HTTP的网关发请求,这个网关主要就是转发。把前面的http请求转换到后面一个JSF请求,也是基于Netty做的。序列化默认是Message Pack,是个跨语言的协议,也支持hessian,json,Java,
Protobuf等。注册中心和RPC框架直接是长连接,可以进行一个通讯。
唯品会
石廷鑫
:大家好,我是
石廷鑫
,原来在京东、唯品会,现在在宅急送。我基本上都是在仓储物流这方面。以前在亚洲一号是按照仓库的整个操作细节分成各个模块来做的
服务拆分
,
每个模块
是单独部署的。仓储的每个仓,根据种品类不一样,整个的操作流程是不一样的。但是核心的东西,
如
库存、订单管理,都是一样的,只是一些组合不一样。举个例子,小件商品上下架都要做的,但是对于大件商品,比如说大家电,基本上都不需要放架。打订单也不需要,完成配送才需要订单,实际上是到了最后才绑定订单。所以每个流程不一样,需要的组合也不一样。那时我们就想到了,把每个模块先拆出来,
主要是
用
KVM运行整个节点
,
业务
部分
就
用这
些
节点来整个串联起来。核心的东西比如说库存、订单、商品资料,基本上都是用这个简单的模块。
唯品会
的仓储
也是按这种思路来做的
。当时唯品会用的是Dropwizard,
实际上是我们用了它的一个壳,
后面
还是用
的
S
pring
,也做了一个模块,
把
S
pring
集成到一块
。
后
来Springboot
做了出来,基本上就把
Dropwizard
抛弃掉了
。
因为
Dropwizard
版本
升级
变化比较大。
但
它有一个好处,就是
Bundle
比较好,服务化拆分的时候可以根据它
的
大小进行可分可合,如果不需要拆分的时候,我们就把
Bundle
合到一块,如果需要拆分的话,就把
Bundle
再拆出来,单独这个应用是非常容易的。
我
去年到的
宅急送,我们的服务注册、服务发现、网关都使用的
Spring Cloud
的这一套。目前来说还是不错的,
基本
没发现大的毛病。
唯一的问题是
如果前期没有做好的整个数据抽取,整个报表可能会比较麻烦一些。
七牛陈爱珍:大家好,我是七牛的陈爱珍。
微服务架构的设计理念非常适合七牛的业务特点
,
每个服务只负责单一的职责。比如音视频的处理服务:音视频转码
, 音视频拼接
, 视频帧缩略图,点播流式转码,都是以微服务的方式构建,这样每个服务都拥有独立的运行环境,并且可以根据自身的业务压力情况进行独立扩展,动态的弹性扩展还可以提高资源的利用率。
一个可落地的微服务架构应该为微服务提供独立的运行环境,调度框架,注册中心,配置管理中心和监控平台。 七牛采用的是Mesos+Docker+自研调度系统的架构。Docker做环境封将,Mesos做资源调度,自研的调度系统负责对Docker进行弹性的调度。
我们使用
C
onsul做注册中心,实现服务的注册与发现。
C
onsul自带key/value存储,可通过DNS接口做服务发现,且具体健康检查的功能,并支持跨数据中心的服务发现。API Gateway 可以通过 Consul提供的DNS接口查询到服务所有的可用实例的列表信息,并将请求进行转发。流量转发具有负载均衡的功能,采用的是轮询的方式,服务发现则是基于
C
onsul做的。用户请求进来后通过Consul查询到所有可用节点的访问地址,再通过轮询的方式将请求发给后端的服务进行处理,对于返回的结果仅作转发,由请求方解释和使用。并且在API网关中带有监控的组件,对请求数,失败数等进行监控,传送到Prometheus服务器上。通过监控数据对请求进行流量控制及服务降级等相应的处理。
当需要调用多个微服务时,根据七牛云的数据处理的业务特点我们使用管道(pipeline)来进行串行的处理。每一个微服务的输出都是下一个微服务的输入,直到最后一个微服务执行结束才是最终数据处理的内容。比如上传一个视频资源后,需要做两个数据处理操作: 转成mp4资源和进行HLS切片,这种场景下不能对原资源同时执行两个数据处理的操作,必须按序执行。
第二轮:
话题
交流
主持人:服务与服务之间的依赖关系怎么管理?服务编排怎么做?把这些服务节点串起来。
唯品会
石廷鑫
:比方说不是业务的,
基础服务,如图片服务器这些
,
都是独立的。唯一相关的是下面的业务层和底下的基础服务有之间调用,还有是业务模块之间有服务的调用,在系统里是没做体现的,但是我们在服务和服务之间,就加了类似于熔断的那个默认的东西。系统之间的依赖关系,我们自己做了一个简单的系统进行维护。
S
pring cloud eureka
是都是存在内存里,我们改良过,我都改到一个数据库
。
我们交互全部都是
R
est
,我们后边还写过一套,
G
oogle protobuf。我们仓储的内部的业务模块之间
是用G
oogle protobuf来做的。我们自个做了一套虚拟化的在里边
的
。
唯品会石
廷
鑫:
我现
在
用的是
A
pache camel做编排,可以用DSL描述把服务串起来。
其实更多的是业务的流程怎么组织,怎么去把基础服务让串起来,形成一个真正大的
业务场景。
京东章耿:
目前京东大部分
一个接口一个方法就已经
是操作
多张
表了,
一般认为
是一个
比较
原
子
性的操作
了,如果再在
外面有一个东西把它包一下,
例如
把3个方法包成一个方法,
其实意义不大,
所以我们现在是没有做这方面的工作。
另外
京东
有弹性云,用的
Docker,
不过不是
你们想象中那种微服的那个Docker
用法
,京东现在用
叫“胖容器”
,更像一个虚拟机一样的一个东西。
Docker
里面运行的是一个应用,然后这个应用,它可能包含多个接口多个方法。
可能大家理解微服务的Docker用法应该是
一个容器里面,他只跑一
个独立的逻辑,对
数据
的一
个操作,
或者对
一个资源的操作。比如说下订单、
扣
库存,这两
步操作
,他可能跑了两个
容器
。
把它编排成一个
service
的这种,我们好像没有这种
。
主持人:服务拆分是怎么做的?
京东章耿:
京东现在
的服务
其实也是没拆
太细
,
主要还是业务部门自己控制服务粒度
。
京东的业务还是比较复杂的,各个应用之间
互相依赖,互相调用,每个操作基本都会涉及到很多资源的变更
,像微服务推崇的那种对单一资源的操作,基本上没有。
说实话,
这种大型互联网公司里面
的服务
根本就微不起来的,不可能像REST
ful
一样,对一个资源的一个
put post
操作基本不可能,我们现在都是力度还是由使用我们框架的
研发人员
自己定的,然后一般他们都是根据这种方法之间的一些关联性或者原子性,或者是扩展性
来进行组合或者拆分
。
所以
我们
一般叫自己
服务化框架,不叫微服务
框架。另外他们
可能还会考虑一些
服务
是否可以独立部署,拆的时候可能会考虑一下这些。
主持人:其实很多大型电商互联网也拆不开,也不能称之微服务,是那种服务力度很粗,然后每个服务号有若干个接口,其实
耦合
性很高的合在一起,相关度很高,数据都在一起
。
京东章耿:都差不多,都是业务
开发
自己来
折分
服务
粒度
的
。就像刚才
说的
下
单。
肯定是
一次
要操作好多表
的
。
业务开发认
为这是
几次表操作其实是
一个
下单的
原子
操作
,
那么他就拆到这么细了。
唯品会石
廷
鑫:我们服务不是说一个部一个,实际上它是和数据
域
相关的,都搁到一块。
唯品会石
廷
鑫:按功能分的,功能跟功能之间调用,如果不是同一个数据域里边的,还是用
R
PC来调用的。
京东章耿:那个听起来很美好,你想我们现在这样拆,都已经上万了
接口,方法基本都上十万
了。你这样拆的话,起码
乘以10
的接口,
而且这样搞
的话就得整个公司都要动用非常非常大的能力去搞好这个事情。
主持人:
单体
他如果拆成
像
市场上去提倡的那种微服务,其实他对内部的消耗是非常大的,因为我们很多的服务内部的调用,其实是非常频繁,如果都把它拆开了去独立部署的话,它其实对网络的消耗是要求非常高的。
唯品会石
廷
鑫:就是最难的点,一开始你是拆不开这个数据。
主持人:数据只要能拆开,你什么都好干。你只要能把数据
粒度
拆的很细的话,那就没问题了,那也能做的很细,
但
就是拆不开。其实好多数据都是
陈年
老表,都是很都是从原来
系统
继承下来的,就很难拆。
唯品会石
廷
鑫:所以
新
做一个系统还可以。要做这个老系统计划很难的,拆个表就要拆很多天。
京东章耿:
而且是数据量
比较少,然后逻辑比较简单的,
例如
那种创业型公司,
使用开源的方案,
这种可以很方便。
主持人:
在
双11
时
各个电商肯定会有大型的促销,
这时
服务的压力肯定
会
有很大的增长,
怎么解决服务的
伸缩的问题
?
唯品会石
廷
鑫:就像我们这边的话,
就看哪个基点的压力比较大一些,然后你多布几个基点就可以了
。现在基本上都是中泰的那个,就是S
pring cloud
那套。
扩展都是
提前先做一步。自动扩的话,就是相当于我们租了一个类似于简单的监控。就是根据他的
实例
,然后因为微服务,我们现在是S
pring cloud
,基本上都是
java -jar
,然后自己
启
就得了,反正那个
jar
,你可以放到一个公用的地,
远程java -jar
要干架就起来了,
监控
的时候根据他的量,然后随时可以
启
就行了。
京东章耿:
京东的服务发布都是挂在应用下面的,而应用发布的平台
其实
会和
各个系统打通,比如说数据库授权的系统,然后自动挂VIP的一些系统
,挂
监
控平台
,日志系统等
。然后我们还有个监控平台,监控
一些指标,例如机器情况,应用情况,还有自己业务埋点的性能等数据。至于服务是否有压力
,都
是
自己评估,自己提前扩展。
一般大促前会进行大规模的
压测,他们自己压测,然后
根据结果
自己扩就可以了。京东是没有
开
自动弹性扩展
的,
基本都
是
大促前提前申请容器,然后
提前扩
完
。
唯品会
石
廷
鑫:并发量大的业务都是放在公有云,双十一比平常多了两倍的机器,我们只买 了一个月的
云主机
。临时用几天,结束就不用了。