微服务|概念认识与相关问题

认识微服务

微服务其实是一种架构风格,我们在开发一个应用的时候这个应用应该是由一组小型服务组成,每个小型服务都运行在自己的进程内;小服务之间通过 HTTP 的方式进行互联互通。

扩展性

在单体应用中,如果要对模块进行扩展,那么需要对所有模块进行扩展。比如一个电商系统,我可能只需要扩展秒杀服务,但是在单体应用下进行扩展时其他功能也会扩展,会造成大量的资源浪费。而利用微服务可以只扩展响应服务即可。

每一个服务都是一个 web 应用,我们可以对它进行独立的部署。就比如说这个服务它的访问压力比较大,我们就可以对他进行水平的扩展。就比如说关于他这一组的服务都访问压力比较大,我们可以给他们放在一组,把他归类在一组进行水平的扩展。这样带来的一个性能的优化是最佳的。并且他们的容错率是要比我们之前的单体应用的容错率是要更高的。

62f9adb47302d

隔离性强

在我们单体应用当中,比如说我一个不相关的一个功能,它出现了 OOM 内存溢出,那么会导致我整个应用都不可用了。

那么在我们的微服务架构当中,由于我们所有的这个服务都是单独的一个 web 应用都是单独一个进程。那么假如说我是一个这个电商系统,比方说是一个电商系统,比如说积分服务它挂掉了,那么它是不影响我继续去进行购买的,不影响我商品浏览,然后下单支付等等这些主要的流程操作的。我的整个应用依然能够正常的使用。

62f9ace963dd4

微服务带来的问题

那么我们一个微服务架构,我们可以看到经过拆分,经过更细粒度更彻底的一个拆分之后,我们的这个服务会变得非常非常的多,每一个节点都是一个服务,并且经过水平的扩展、负载均衡之后,它们之间的一个调用链路会变得更加的错综的复杂。

一个业务功能之中,一般都会涉及到好几个功能模块。那么经过我们的微服务一拆分之后,有可能就会变到变成几个微服务,甚至十几个微服务。那么一一负载均衡。那甚至涉及到几十个微服务之间的相互交友。那么这么多微服务之间的调用肯定会出现一系列的问题。那么我们怎么去解决这些问题呢?

62f9b3253c072

服务治理

首先是这么多服务,如何进行管理?比如说我的订单服务,要去调用我的库存服务,有可能还要调用商品服务,然后有可能还要去调用积分服务等等。

那么这个时候我要去调用这些服务,我是不是得知道他们的一个远程服务的地址,因为不同的服务都是部署在不同的服务器,他们可能都有不同的一个 IP。那么我要调用他们是不是得知道他们的一个 IP 然后进行远程的调用?他们这些 IP 是不是会频繁的变化。就比如说库存,那么今天他的这个访问压力比较大,那么我给他换一台这个性能不是这么好的服务器,我给他换一台 IP 就变了。然后我商品可能我今天压力比较大,我给他换一台性能比较好的服务器。或者说我今天我商品压力比较大,我给他水平扩展几个,那么 IP 又多了几个。那么这些远程服务地址的 IP 我都维护在订单这里的话是不是相当麻烦,因为他们会频繁地变化。所以说在我们的微服务架构当中,就引入了一个微服务治理组件,叫做注册中心。那么这个注册中心它就可以去管理我们所有的服务,我们会将这些服务都注册到这个注册中心当中。

去注册的时候,我们提供一个名字,比如说订单是 order ,比如说商品是 product ,那么订单我去调用商品的时候,我只要知道这个商品服务的名字(product),就可以直接去调用这个服务。这样就有效的去管理了我们这些服务。

62f9b54b3cf0c

通讯

服务拆分后,服务之间的通信就不能像单体应用那样能够通过函数调用的方法进行调用了,因为函数调用是基于进程的,所以我们的服务之间是不能直接通信的。所以我们需要一个通信的框架,来实现我们的服务之间的通信。RPC和Rest是微服务最常见的两种协议,微服务内部通信一般采用RPC或者Rest进行通信,对于客户端来说主要采取Rest来进行交互。

Rest:严格的说接口很规范,操作对象即为资源,对资源的四种操作(post、get、put、delete),并且参数都放在 URL 上。不严格的说 Http+json、Http+xml,常见的 http api 都可以称为 Rest 接口。在微服务中,可以选用 springBoot
restTemplate 或者 feign 进行 Rest 接口的开发。

RPC:常说的远程方法调用,就是像调用本地方法一样调用远程方法,通信协议大多采用二进制方式。RPC通常基于TCP实现,常用框架例如dubbo,netty、mina、thrift。

两者之间的差异如下:

62f9b9e00b4f2

微服务网关

不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:

  • 客户端会多次请求不同的微服务,增加了客户端的复杂性
  • 存在跨域请求,在一定场景下处理相对复杂
  • 认证复杂,每个服务都需要独立认证
  • 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施
  • 某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难

所以,我们需要通过配置微服务网关来实现客户端的访问。微服务网关是一个网关,它可以将一个或多个微服务集成到一个应用中,并且可以将这些微服务之间的调用进行转发,从而实现微服务之间的调用。

也就是在我们调用微服务的时候,它会为我们路由到不同的一个组件到路由到不同的一个服务当中去,从而为我们去把守我们整个微服务的一个大门。微服务也是中心化的,但是它不是强行的要求你去使用。

就比如说你也可以点对点的直接去访问我某一个服务,这是没有问题的。并且假如说我网关突然挂掉了,我也可以采用降级的方式降级去访问我这个服务,也就是说我不去访问网关了,我去访问我具体的那个服务。

62fc91c397a33

容错策略

在微服务中,每一个服务或者部署微服务的集群并非完全可靠的,如果一个服务挂掉了,那么可能会影响整个调用链路的正常运行,这时候我们需要实现容错策略,来解决这个问题:

容错的设计是为了解决这些问题:

  • 一个依赖服务出现故障不会严重破坏用户体验
  • 一个依赖服务出现故障不会影响到其他服务
  • 一个依赖服务出现故障不会影响到系统的可用性
  • 系统能过具备自动处理故障的能力

常用的微服务容错策略包括如下:

  1. 隔离:线程池隔离和信号隔离
  2. 超时:超过最大响应时间则释放进程
  3. 限流:限制服务的调用频率
  4. 熔断:熔断服务,当服务出现故障时,将服务降级到熔断状态,熔断状态下不再调用服务,直到服务恢复正常为止
  5. 降级:当服务出现故障时,提供其他服务的替代服务
62fc97d1927be

链路追踪

在微服务中,一个外部请求往往涉及到多个服务之间的调用,这些调用可能会出现跨越多个模块、多个中间件、多个服务器……如果一个调用出现问题,我们需要对各个服务进行排查,这需要花费大量的时间精力去排查,所以我们需要一个方法来追踪调用的链路来方便我们对请求调用进行追溯。

衡量一个接口,我们一般会看三个指标:

  1. 接口的 RT(Route-Target)是什么?
  2. 接口是否有异常响应?
  3. 接口请求慢在哪里?

一般在系统发生问题时,比如系统异常或者系统性能出现问题时,通常都是从系统记录的日志文件中找出蛛丝马脚,而对于微服务架构下的分布式部署,日志文件的分散,想从日志中查找问题工作量很大。对于用户某一次请求调用后端哪些服务,每个服务执行情况,想从日志中获得更是不可能的事。

对于传统的监控告警平台也紧针对平台资源的监控包括cpu、内存、网络带宽情况等,对业务微服务应用的指标(平均响应时间、慢端点情况等)的监控显得无从下手。

62fc9f650411b

分布式链路追踪(Distributed Tracing),就是将一次分布式请求还原成调用链路,进行日志记录,性能监控并将一次分布式请求的调用情况集中展示。比如各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等等。

62fc9f264e765

相关资料推荐

这个文档对理解微服务和分布式架构有很大的帮助:
凤凰架构

阿里云提供了脚手架和实验室还有教程,可以边动手边学习:
知行动手实验室