本次演讲是由链家网基础架构部高级研发工程师刘思贤带来基于Spring Cloud的微服务实践经验分享。
内容来源: 2017年5月6日,链家网基础架构部高级研发工程师刘思贤在“Spring Cloud中国社区技术沙龙-北京站”进行《基于Spring Cloud的微服务实践》演讲分享。IT 大咖说作为独家视频合作方,经主办方和讲者审阅授权发布。
阅读字数: 2632 | 5分钟阅读
嘉宾演讲视频回顾及PPT链接: t.cn/REnMM2q
在2015年,我受朋友的邀请加入了爱油科技,担任爱油科技的架构师。爱油科技做了十年传统行业的成品油交易,开始进行互联网化的转型。它有非常重的线下业务,这些线下业务会通过信息化互联网的手段搬到线上进行一系列的改造。
我接手公司业务的时候只有一个单体应用,通过团队大约两年的维护,建设了很多不同的业务系统等。在我了解到这家公司的情况之后,和CTO讨论决定通过微服务的方式来改造整个系统。
为什么要做微服务呢?首先就要聚焦到我们当前业务的变化。
以前的业务通常是一个网站打天下,而现在各种各样的新媒体渠道成为了我们业务的重要入口,传统单一网站的形式已经不能满足我们的要求了。
对爱油科技而言,以前的业务通常是线上收单线下处理,现在这家公司的重要使命就是要把所有的业务流程搬到线上,让它流转得更有效率。
在以往的系统中,使用它的主要用户是系统管理员,他们通过后台来维护一些商品的信息等等。而在我们想要把所有业务流程搬到线上之后,它面临的变化就是业务人员需要用后台,使用后台的方式也从单一的网站转变到了APP随时办公的场景。
需求变化侵蚀架构,像熔化的反应堆芯;
被技术平台绑架,大炮打蚊子;
协作困难,牵一发而动全身。
不绑定到特定的语言和框架,可以将多种多样的语言快速实现业务最有效率地去交付业务价值为目标;
当一套微服务体系中引入多种语言的时候,必然涉及到多种语言、多种框架之间的集成。松散耦合的体系结构便于多种语言框架的集成;
简单、容易落地、方便扩展。
业务服务层服务完全对等;
业务服务层服务必须是无状态的,这能保证业务服务层的所有服务能提供对外扩展的能力;
接入层服务之间禁止相互调用;
接入层服务不能包含业务逻辑,这一层是轻和薄,面向渲染、面向输出,不面向业务逻辑的处理;
业务接口必须是RESTful风格,因为我们期望在我们的整体架构中不仅仅涵盖Java的东西,也可以涵盖其它语言的一系列服务;
所有服务必须运行在容器里。我们整体团队有限,不可能提供大量的人力物力去进行运维等操作,利用容器可以帮助我们进行服务的治理,以节约大量的资源。
在Docker整个容器技术中,我们发现Consul作为一个服务注册和发现中心,正好可以纳入到我们的体系当中,直接进行使用。
Consul的服务注册其实要比后来Spring Cloud Consul提供的Config的服务更加容易落地、更有实用性。
在这套方案中当时有些问题还没有得到很好的解决。
Consul服务注册发现与七层Nginx联动。我们期望的是当一个服务启动之后,它能够直接被Nginx的七层发现,我们不用再手工地去更改Nginx的配置。
另一个就是灰度发布的问题。因为在整个现有的Spring Cloud的里,去做一个服务发布20%的流量到一个新的版本这件事情,现在处理起来还比较困难,很难把这20%的服务标记出来。
统一管理Spring Cloud项目的配置文件;
为接入层服务下发配置。
Consul作为配置中心依然有些问题没有解决。
配置的版本化管理。一个配置修改前后的版本差异是要能够访问得到的,不然线上修改配置一旦出现问题,就无法很快地还原配置。
灰度发布。在目前Spring Cloud的基础设施中还很难允许在一个集群中20%用这个配置,80%用另一个配置。我们需要做一些定制化开发来解决这个问题。
服务层Node:Consul、Brake
接入层Node:request to zuul
PHP接入层:guzzle to zuul
我们把这种天然的业务彼此独立或隔离叫做界限上下文。在界限上下文里面,它们使用相应的统一语言描述业务。在每个领域内它们有自己的模型,围绕这个模型进行建模,它们各种有统一的语言。这样就天然地把它们拆成了成员微服务和交易微服务。
从业务到微服务的过程中,其实包含了两种消息的传递。一个最基本的观点就是,对象和对象之间消息的传递是通过方法调用来进行的。我们有同样的方法,就是一个服务去调用另外的服务,它产生的结果会作为这个服务的使用。
基于刚才领域驱动设计的观点,领域模型被放在了六边形架构的中间,所有和领域进行交互的东西都是通过六边形架构的边来进行。
还有一类是异步的消息。比如一个客户下单之后要给他创建相应的物流订单,就是一个领域内产生的消息通过领域事件的方式向另一个领域进行传播。
领域事件的传递很出现一个问题,每个不同的微服务使用不同的MQ服务,它们之间的消息怎样进行交互?
我们选用了一个消息服务的中间件,每一个需要发送事件的微服务都会维护一个Event Topic,然后再维护一个从其它领域内传来消息的Page。当一个事务提交之后,每个事件会被投到Topic里面,Topic收到消息服务中,消息服务再按照订阅关系投递到相应的Event Queue里面。它们各自消费这个Event Queue就能处理这个事件。
整个消息服务我们使用了某云计算厂商提供现成的消息服务作为我们的消息中间件。
分包/模块原则:高内聚、低耦合;
通过领域模型表达领域知识提高内聚性;
应用层使用领域模型;
防腐层提供领域层所需的实现,防止实现耦合到领域。
这时大家所说的实体变成了失血的领域模型。而对于面向对象、语言来讲,它表现业务规则、表现知识最大的表现力就是对象之间的交互。
这种更具领域知识表现力的设计方式会比事务脚本的方式更容易维护。
以界限上下文划分微服务;
领域模型表达领域知识,高内聚;
服务与服务之间通过Rest和MQ集成,低耦合。
对象存储:S3/OpenSwift,存储与计算分离;
消息服务:动态定义消息订阅及路由;
容器资源管理:Rancher、SwarmKit;
日志服务:Docker、Rsyslog、Logstash。
DevOps每个分支都会提供相应的构建,构建出的结果就是标准化的镜像,标准化镜像带来了Dev、QA、Production环境统一。
整体实施完微服务之后,给公司带来的价值是新业务最短1周上线,10人团队可以维护20余种微服务,每日数次线上发布,每周里程碑发布,全年核心业务可用性高达99.95%。
在整个微服务架构落地中,技术体系的建设至关重要。
我今天的分享就到这里,谢谢大家!