微服务
下面系统性的介绍微服务相关的框架性知识,具体的实现方案不深入介绍。
微服务的由来
想必之前做过企业软件开发的同学,或者互联网产品的初期多半是用一个应用承载了所有的功能模块,这种我们称之为“烟囱式”的架构。当时使用这种开发模式是可以的。后面随着公司业务的不断扩大,功能也越来越多,代码变得越来越来复杂,这种架构的问题暴露了出来。比如:交付周期越来越长,因为要确定一个需求的修改点越来越困难。测试回归点越来越多,改动一个点,可能会影响到整个系统等等。系统伸缩全靠堆机器,但也只能临时性的解决问题。当遇到这种情况时,那就需要用微服务架构来解决了。
什么是微服务
在2014年Martin fowler提出了一种新的架构模式“微服务”,有兴趣的同学可以进去看看。文章地址:https://martinfowler.com/articles/microservices.html
简单地说,微服务架构主旨是将一个原本独立的系统拆分成多个小型服务。被拆分的小型服务都围绕着系统中的某一项或耦合度较高的业务功能进行构建,并且每个服务都维护着自身的数据存储,业务开发,自动化测试,以及独立部署。
将单体架构的应用拆分为多个微服务之后,分布式部署环境下会比单体应用更复杂,比如服务之间怎么发现,客户端弹性模式如何构建,服务安全等。下面一一介绍在微服务之后出现的问题,目前有哪些解决方案。具体的实践可以找相关的文章。
微服务的开发模式
微服务配置
在应用中会遇到一下经常变化的点,通常是将这些配置集中在一个类,一个文件,或者配置在另外的服务中。当然这种配置问题并不是说只有微服务才会遇到的问题,单体应用也需要可配置,只不过是在微服务环境中更加重要。比如在有多个微服务实例启动完成之后,如果手动配置,会有可能出现配置漂移等问题。解释一下配置漂移,配置漂移是指在应用发布之后,有人手动修改了某个实例的配置,然而这些配置和其他实例并不一样,这种现象称为配置漂移。
在服务配置方面我们会主要关注几个特性。分布式,配置服务是否分布式部署,会不会存在单点故障。客户端动态刷新,配置变化之后,客户端的配置是否会自动变化。版本控制,能否想git代码库一样,有版本控制。多环境,能否支持不同环境的配置隔离,比如在国际化部署中,不同的区域有不同的配置。下面介绍一些配置框架,在架构选择时候可以参考一下。里面的特性没有填写的,表示我不清楚,使用的同学可以再深入看看。
项目 |
描述 |
特性。 | |||
---|---|---|---|---|---|
分布式 | 客户端动态刷新 | 版本控制 | 多环境 | ||
Etcd | 使用Go开发的开源项目 | 支持 | |||
Eureka | 由Netflix开发 | 支持 | 支持 | ||
Consul | 由Hashicorp开发 | 支持 | 不支持 | ||
Zookeeper | Apache的项目 | 支持 | 支持 | ||
Spring Cloud Config | Spring提供的支持不同后端的通用解决方案 | 不支持 | 支持 | ||
Diamond | 淘宝开源的 | 支持 | 支持 | 不支持 | 支持 |
Disconf | 百度的 | ||||
QConf | 360的 |
服务发现
在分布式架构中,都需要找到提供服务机器的物理地址,这就是服务发现。在微服务中服务发现至关重要。首先,通过服务发现,服务消费者能够将服务的物流位置抽象出来。由于服务消费者不知道实际服务实例的物理位置,因此可以水平伸缩,也就是可以添加或者删除实例。另外,提高服务的弹性,当服务实例变得不健康时,服务发现引擎可以从移除该服务。
服务发现应该具有如下特性:高可用,点对点,负载均衡,有弹性,容错。为了满足这些特性,服务发现架构通常如下
架构选择
- Spring Cloud,可以使用Eureka作为服务发现引擎,Ribbon作为客户端负责均衡。
客户端弹性模式
客户端弹性模式是指在服务发生错误或者表现不佳时,让客户端“快速失败”,客户端免于崩溃。有四种客户端弹性模式:1.客户端负载均衡模式;2.断路器模式;3.后备模式;4.舱壁模式。下图展示了这些模式在服务调用时候所起到的作用。
架构选择
可以先用Hystrix来实现这些模式
服务网关
在微服务架构中,要实现服务调用的安全,日志记录,用户跟踪功能。如果在服务中去实现,需要开发关注非业务功能,也有可能忘记实现安全,日志等功能。如果依赖于公共组件实现方式,升级也是一个很大的问题,当基础组件变化时候,依赖的服务要重新编译发布。所以应该将这些功能抽取到一个地方去实现,即服务网关。客户端通过服务网关调用服务。
这里的服务网关存在单点故障的问题,我们将服务网关部署称为集运,前面加入一层负载均衡。
如果想区域就近访问,还可以在负载均衡前面加入一层DNS路由
架构选择
Netflix的Zuul是一个服务网关,其核心是一个反向代理中间服务器,位于尝试访问客户端和资源之间。
微服务安全
如何验证调用微服务的用户是经过授权的。可以使用Spring Cloud Security和OAth2实现微服的验证和授权。OAuth2是一个基于令牌的安全验证和授权框架。
微服务异步通信
Spring Cloud Stream是一个注解驱动的框架,可以使用多个消息平台(包括Kafka,RabbitMQ),而平台无关的实现则排除在应用程序代码之外。在应用程序中实现的都是使用Spring的接口实现。
分布式跟踪
在进行微服务拆分之后,我们需要跟踪一次请求在多个微服务的调用情况,便于后面的问题排查。要完成全链路的跟踪,需要下面3中技术:
1.关联多个服务调用
使用Spring Cloud Sleuth将关联ID添加到各个服务调用中。
2.聚合日志
使用Papertrail可以聚合多个日志到单个数据库中。
3.可视化服务调用
Zipkin是可视化工具,可以显示跨多个服务的事务流。
相关知识
服务的拆分
首先服务的拆分要遵循高内聚,低耦合。高内聚是指将需求引起变化的改动都放在一起,这样就只需要修改一个服务,不用修改多个服务。低耦合是指服务之间的变化不会相互影响,不能修改一个服务之后另外的服务要跟着改。为了使服务高内聚和低耦合,我们通过功能来拆分服务,将相关的功能都放在一起。我们用限界上下文来圈住这些功能。每个限界上下文都是有着显示边界的特定职责。注意需要从限界上下文能具有什么功能来考虑,不应该从共享数据的角度来考虑。另外限界上下文要逐步划分,首先考虑考虑比较大,粗粒度的上线文,然后当发现合适的缝隙后,再进一步划分。
CAP
分布式系统要在这三个方面取得权衡,一致性(consistency),可用性(availability)和分区容错性(partition tolerance),只能保证三个中的两个方面,这就是CAP定理。
一致性要求分布式环境中获取到的数据是完全一致的。可用性要求服务是高可用的,收到请求后服务必须返回。分区容错性是指在节点间通信失败时保证系统不受影响。
在分布是环境中,我们一定要是保证分区容错性的,剩下的就是在C和A中选择,要么是CP,要么是AP
CAP理论:https://mwhittaker.github.io/blog/an_illustrated_proof_of_the_cap_theorem/
SOA和微服务
SOA(Service-Oriented-Architecture,面向服务的架构)是一种架构方法。它是将单块应用拆分为多个服务,服务之间通过网络调用,完成一系列功能。而微服务架构可以说是这种架构的一种特定方法,它提供了完整的架构方法,如上面提到的架构模式。
MVC和微服务
在网上搜了许多文章,多数是说MVC是一种单体架构,而微服务是一种分布式的架构。对此我并不认同,MVC并不是一种单体架构,而是一种代码的组织方式,大家都知道MVC有三层分离,目的让业务逻辑更加内聚。而微服务是将复杂的业务从一个应用拆分成多个应用,但请注意,就算拆分之后的应用也会有页面,业务逻辑,以及将业务连接页面和业务逻辑的控制层,每个应用仍然可以以MVC方式来组织代码结构。
康威定律
康威定律是指组织的沟通方式决定了系统的设计。 因为我们在拆分系统时候,需要拆分成高度自治的服务,实现业务闭环,这样才能减少沟通成本,所以系统的拆分是受组织结构决定的。人月神话也给出了很简洁的答案:沟通成本 = n(n-1)/2,沟通成本随着项目或者组织的人员增加呈指数级增长。
那么能不能反康威定律呢?系统拆分好之后,组织按照系统结构来调整,这个也是可能的。最后只要保证系统高度自治,那么就调整组织结构把。最近参与了中台化项目改造,就是组织结构随着系统架构调整的例子。
墨菲定律
如果事情有变坏的可能,不管这种可能性有多小,它总会发生。
RPC和REST
上面一直讲的是REST,很多公司内部其实用的是RPC,那么这两个有什么区别呢?其实都属于服务的集成方式,可以使用任何一种方式来集成拆分之后的服务。