一.什么是微服务
微服务就是一些协同工作的小而自治的服务。
1. 服务要足够小
在使用微服务的时候,内聚性是一个很重要的概念。Robert C. Martion对 单一职责原则 有个论述是: 把相同原因而变化的东西聚合到一起,而把不同原因而变化的东西分离开。这个论述很好的强调了内聚性这个概念。
那么服务要多小才算足够小呢?
要考虑这些因素:服务越小,微服务架构的优点和缺点也就越明显。使用的服务越小,独立性带来的好处就越多。但是管理大量服务也会越复杂,之后会将这一复杂性。
2. 自治性
一个微服务就是一个独立的实体。它可以独立的部署在PAAS(Platform As A Service,平台即服务)上,也可以作为一个操作系统进程存在。
我们要尽量避免把多个服务部署到一台机器上。
服务之间通过网络调用进行通信,从而加强服务之间的隔离性,避免紧耦合。
这些服务应该可以彼此间独立的进行修改,并且某个服务的部署不应该引起该服务消费方的变动。
服务会暴露出API(Application Programming Interface , 应用编程接口),然后服务之间通过这些API进行通信。API的实现技术应该避免与消费方耦合,这就意味着应该选择与具体技术不相关的API实现方式,以保证技术的选择不被限制。
如果系统没有很好的解耦,那么一旦出现问题,所有的功能都将不可用。有个黄金法则是:你是否能修改一个服务并对其进行部署,而不影响其他任何服务?
为了达到解耦的目的,你需要正确的建模服务和API。
二.主要好处
它的主要好处包括:技术异构性、弹性、扩展、简化部署、与组织结构相匹配、可组合性、对可替代性的优化
1. 技术异构性
在一个由多个服务相互协作的系统中,可以在不同的服务中使用最适合该服务的技术。尝试使用一种适合所有场景的标准化技术,会使得所有的场景都无法得到很好的支持。
2.弹性
弹性工程学的一个关键概念是舱壁。如果系统中的一个组件不可用了,但并没有导致级联故障,那么系统的其他部分还可以正常运行。服务边界就是一个很显然的舱壁。
在单块系统中,如果服务不可用,那么所有功能都会不可用。
对于单块服务的系统而言,可以通过将相同的实例运行在不同的机器上来降低功能完全不可用的概率,
然而微服务系统本身就能够很好的处理服务不可用和功能降级问题。
微服务系统可以改进弹性,但你还是需要谨慎对待,因为一旦使用了分布式系统,网络会是一个问题,而且还有机器,我们需要了解问题出现时应该如何对用户进行展示。
舱壁模式:
舱壁模式(Bulkhead)隔离了每个工作负载或服务的关键资源,如连接池、内存和CPU。使用舱壁避免了单个工作负载(或服务)消耗掉所有资源,从而导致其他服务出现故障的场景。 这种模式主要是通过防止由一个服务引起的级联故障来增加系统的弹性。下图描述了实施舱壁的简单的示例场景:在左侧,微服务A,用同一个连接池去请求X和Y两个服务。如果服务X或服务的Y其中任何一个行为异常,这会影响连接池的整体行为。如果舱壁模式实现,如该图所示的右侧,即使微服务X被错误操作,只有池X将受到影响。微服务Y可以继续为应用程序提供服务.舱壁的概念在软件开发中可以被应用在隔离资源上。
而在工业中使用舱壁将船舶划分为几个部分,以便在船体破坏的情况下,可以将船舶各个部件密封起来。
泰坦尼克号沉没的主要原因之一是其舱壁设计失败,水可以通过上面的甲板倒在舱壁的顶部,最后整个船淹没
3.扩展
庞大的单块服务只能作为一个整体进行扩展。即使系统中只有一小部分存在性能问题,也需要对整个服务进行扩展。
如果使用较小的多个服务,则可以只对需要扩展的服务进行扩展,这样就可以把那些不需要扩展的服务运行在更小的,性能稍差的硬件上。
在使用类似Amazon云服务之类的平台时,也可以只对需要的服务进行扩展,从而节省成本。
4.简化部署
在有几百万行的单块应用程序中,即使只修改一行代码,也需要重新部署整个应用程序才能够发布该变更。
这种部署的影响很大,风险很高,因此相关干系人不敢轻易做部署。于是在实际操作中,部署的频率就会变的很低。
这意味着在两次发布之间我们对软件做了很多功能增强,但直到最后一刻才把这些大量的变更一次性发布到生成环境中。
这时,另外一个问题就显现出来了:两次发布之间的差异越大,出错的可能性就更大。
在微服务架构中,各个服务的部署时独立的,这样就可以更快的多特定部分的代码进行部署。
如果真的出了问题,也只会影响一个服务,并且容器快速回滚,也意味着客户可以更快的使用我们开发的新功能。
5.与组织结构相匹配
微服务的架构可以很好的将架构和组织结构相匹配,避免出现过大的代码库,从而获得理想的团队大小和生产力。
服务的所有权也可以在团队之间迁移,从而避免异地团队的出现。
6. 可组合性
分布式系统和面向服务架构 声称的主要好处是易于重用已有功能。
在微服务架构中,根据不同的目的,人们可以通过不同的方式使用同一个功能,在考虑客户如何使用该软件时,这一点尤其重要。
现在我们需要考虑的应用种类包括Web , 原生应用、移动端Web 、平板应用及可穿戴设备等,针对每一种都应该考虑如何对已有的功能进行组合来实现这些应用。
在微服务架构中,系统会开放很多接口供外部使用。当情况发生改变时,可以使用不同的方式构建应用,而整体化应用程序只能提供一个非常粗粒度的接口供外部使用。
7.可替代性的优化
使用微服务架构的团队可以在需要时轻易重写服务,或者删除不再使用的服务。当一个代码库只有几百行时,人们也不会对它有太多感情上的依赖,所以很容易替换它。
三. 面向服务的架构
SOA(Service-Oriented Architecture, 面向服务的架构)是一种设计方法,其中包含多个服务,而服务之间通过配合最终会提供一系列功能。
一个服务 通常以独立的形式存在于操作系统进程中。服务之间通过网络调用,而非采用进程内调用的方式进行通信。
它的目标是在不影响其他任何人的情况下透明的替换一个服务,只要替换之后的服务的外部接口没有太大变化即可。这种性质能够大大简化软件运维甚至软件重写的过程。
实施SOA时,会遇到这些问题:通信协议(例如SOAP)如何选择、第三方中间件如何选择、服务粒度如何确定等。
四. 其他分解技术
当你开始使用微服务时会发现,很多基于微服务的架构主要有两个优势:
首先它具有较小的粒度,其次它能够在解决问题的方法上给予你更多的选择。
那么其他的分解技术是否也有相应的好处呢?
1. 共享库
基本上所有的语言都支持将整个代码库分解成为多个库,这是一种非常标准的分解技术。这些库可以由第三方或者自己的组织提供。
不同的团队和服务可以通过库的形式共享功能。
团队可以围绕库来进行组织,但是库有一些缺点。
首先,你无法选择异构的技术。一般来说,这些库只能在同一种语言中,或者至少在同一个平台上使用。
其次,除非你使用的是动态链接库,否则每次当库有更新的时候,都需要重新部署整个进程,以至于无法独立的部署变更。
而最糟糕的影响可能是你会缺乏一个比较明显的接缝来建立架构的安全性保护措施,从而无法确保系统的弹性。
如果使用共享代码来做服务之间的通信的话,那么它会成为一个耦合点。
服务之间可以并且应该大量使用第三方库来重用公共代码,但有时候效果不太好。
2.模块
除了简单的库之外,有些语言提供了自己的模块分解技术。它们允许对模块进行生命周期管理,这样就可以把模块部署到运行的进程中,并且可以不停止整个进程的前提下对某个模块进行修改。
作为一个与具体技术相关的模块分解技术,OSGI (Open Source Gateway ,Initiative , 开放服务网关协议)值得一提。
五. 没有银弹
(没有银弹指的是没有任何一项技术或方法可使软件工程的生产力在十年内提高十倍。)
如果你之后想要使用微服务,那么你需要面对分布式系统需要面对的复杂性;
如果你过去的经验更多的是关于单块系统,那么为了得到微服务的好处,你需要在部署,测试,监控等方面做很多工作。
你还需要考虑如何扩展系统,并且保证它们的弹性。
如果你发现还需要处理类似分布式事务或者与CAP相关的问题,也不要感到惊讶。