淘先锋技术网

首页 1 2 3 4 5 6 7

目录

【单体架构】

【微服务解决哪些问题】

微服务的拆分原则

微服务使用过程中有哪些坑?

【RPC框架】

常见的网络 IO 模型

RPC 执行过程总结

【CAP原理】

如何使用 CAP 理论

【服务注册和发现】

【配置中心】

【Consul】

Consul介绍

Consul角色

Consul 内部端口

Consul工作原理

Consul集群

Raft算法


微服务:字面意思是微小的服务, 较小且独立的功能单元。微服务最早由Martin Fowler与James Lewis于2014年共同提出,微服务架构风格是一种使用一 套小服务来开发单个应用的方式途径,每个服务运行在自己的进程中,并使用轻量级机制通信,通常是HTTP API,这些服务基于业务能力构建,可以使用不同的编程语言实现,以及不同数据存储技术,并保持低限度的集中式管理。

(以上八股文摘自网络,先混个脸熟😂)

【单体架构】

具体说明微服务的作用之前,先来看看传统的单体架构的特点:

  • 开发简单直接,代码和项目集中式管理;
  • 只需要维护一个工程,节省维护系统运行的人力成本;
  • 排查问题的时候,只需要排查这个应用进程就可以了,目标性强。

随着项目功能越来越复杂,数据存储量和并发访问量越来越大,可能会出现一系列的问题,具体表现如下:

  • 在技术层面上,数据库连接数和存储可能成为系统的瓶颈,可能要面临分库分表扩容等问题。

  • 一体化架构增加了研发的成本,沟通费劲,代码管理困难,阻碍了研发效率的提升。比如说一个很大的项目需要20个人一起开发,一个小小的改动都可能会造成整个服务的不可用。

  • 一体化架构对于系统的运维也会有很大的影响。任何小的修改,都需要构建整个项目,上线变更的过程非常不灵活。

《人月神话》中总结出了随着人员的增加沟通成本呈指数增长的规律:沟通成本= n(n-1)/2。

5人项目组,需要沟通的渠道是 5*(5-1)/2 = 10

15人项目组,需要沟通的渠道是 15*(15-1)/2 = 105

50人项目组,需要沟通的渠道是 50*(50-1)/2 = 1225

150人项目组,需要沟通的渠道是 150*(150-1)/2 = 11175

【微服务解决哪些问题】

针对上面单体服务出现的问题,微服务就应运而生了,简单地说,就是把一个大的复杂的项目(服务)拆分成多个小而简单的项目,然后各个项目之间通过HTTP接口来调用。比如可以将与业务无关的公用服务抽取出来,下沉成单独的服务。

具体应该怎么拆分,就设计到微服务的拆分原则。

微服务的拆分原则

  • 原则一,做到单一服务内部功能的高内聚和低耦合。也就是说每个服务只完成自己职责之内的任务,对于不是自己职责的功能,交给其它服务来完成。
  • 原则二,需要关注服务拆分的粒度,先粗略拆分,再逐渐细化。在服务拆分的初期其实很难确定究竟要拆分成什么样。服务多了也会带来问题,像是服务个数的增加会增加运维的成本。再比如,原本一次请求只需要调用进程内的多个方法,现在则需要跨网络调用多个 RPC 服务,在性能上肯定会有所下降。
  • 原则三,拆分的过程要尽量避免影响功能迭代,也就是说要一边做产品功能迭代,一边完成服务化拆分。
  • 原则四,服务接口的定义要具备可扩展性。服务拆分之后,由于服务是以独立进程的方式部署,所以服务之间通信就不再是进程内部的方法调用,而是跨进程的网络通信了。在这种通信模型下需要注意,服务接口的定义要具备可扩展性。

基于以上原则和保证服务高可用,可以大概梳理出如下的拆分方法:

  • 稳定性。稳定的不经常改动的服务可以拆出去。
  • 可靠性。可靠性较高的服务拆分出去。
  • 高性能。会发生高并发的服务拆分出去,防止影响其它服务。

微服务化带来的问题和解决思路:

  • 服务接口的调用,不再是同一进程内的方法调用,而是跨进程的网络调用,这会增加接口响应时间的增加。此时就要选择高效的服务调用框架,同时接口调用方需要知道服务部署在哪些机器的哪个端口上,这些信息需要存储在一个分布式一致性的存储中,于是就需要引入服务注册中心。
  • 多个服务之间有着错综复杂的依赖关系,一旦被依赖的服务的性能出现问题,产生大量的慢请求,就会导致依赖服务的工作线程池中的线程被占满,那么依赖的服务也会出现性能问题。为了避免这种情况的发生,需要引入服务治理体系,针对出问题的服务,采用熔断、降级、限流、超时控制的方法,使得问题被限制在单一服务中,保护服务网络中的其它服务不受影响。
  • 服务拆分到多个进程后,一条请求的调用链路上涉及多个服务,那么一旦这个请求的响应时间增长或者是出现错误,就很难知道是哪一个服务出现的问题。在问题定位时,很难确认哪一个服务是源头,就需要引入分布式追踪工具以及更细致的服务端监控报表。

总结起来就是:服务拆分单独部署后,引入的服务跨网络通信的问题; 在拆分成多个小服务之后,服务如何治理的问题。需要使用RPC 框架。

微服务使用过程中有哪些坑?

  • 服务划分过细,单个服务的复杂度确实下降了,但整个系统的复杂度却上升了,因为微服务将系统内的复杂度转移为系统间的复杂度了。

  • 服务数量太多,团队效率急剧下降 
  • 调用链太长,性能下降,问题定位困难
  • 没有自动化支撑,无法快速交付
  • 没有服务治理,微服务数量多了后管理混乱

【RPC框架】

RPC (Remote Procedure Call,远程过程调用),指的是通过网络调用另一台计算机上部署服务的技术。而 RPC 框架就封装了网络调用的细节,让你像调用本地服务一样,调用远程部署的服务。 RPC 框架能够解决系统拆分后的通信问题,并且能像调用本地一样去调用远程方法。利用 RPC 不仅可以很方便地将应用架构从“单体”演进成“微服务化”, 而且还能解决实际开发过程中的效率低下、系统耦合等问题,这样可以使得系统架构整体清晰、健壮,应用可运维度增强。

比方说,电商系统中, 商品详情页面需要商品数据、评论数据还有店铺数据,如果在一体化的架构中,你只需要从 商品库、评论库、店铺库 获取数据就可以了,不考虑缓存的情况下有三次网络请求。但是,如果独立出商品服务、评论服务和店铺服务之后,那么就需要分别调用这三个服务,而这三个服务又会分别调用各自的数据库,这就是六次网络请求。如果你服务拆分的更细粒度,那么多出的网络调用就会越多,请求的延迟就会更长。

下图所示为RPC的通信流程图:

常见的网络 IO 模型

两台 PC 机之间的网络通信,实际上就是两台 PC 机对网络 IO 的操作。常见的网络 IO 模型分为四种:同步阻塞 IO(BIO)、同步非阻塞 IO(NIO)、IO 多路复用和异步非阻塞 IO(AIO)。在这四种 IO 模型中,只有 AIO 为异步 IO,其他都是同步 IO。其中,最常用的就是同步阻塞 IO 和 IO 多路复用。

IO 多路复用更适合高并发的场景,可以用较少的进程(线程)处理较多的 socket 的 IO 请 求,但使用难度比较高。在 RPC 框架的实现中,在网络通信的处理上会选择 IO 多路复用的方式。

RPC 执行过程总结

1. 服务容器负责启动,加载,运行服务提供者。
2. 服务提供者在启动时,向注册中心注册自己提供的服务,暴露自己的 IP 和端口信息。
3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
4. 注册中心返回服务提供者列表给消费者,如果有变更,注册中心将基于长连接推送给数据消费者。
5. 服务消费者,从提供这地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另外一台服务调用。
6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时发送一次统计数据到监控中心。

【问题】已经有 http 协议接口,或者说 RestFul 接口,为什么还要使用 RPC 技术?
【回答】在接口不多的情况下,使用 http 确实是一个明智的选择,比如在初创企业使用简洁高效的技术,先把东西做出来是最明智的选择。使用 http 协议优点:开发简单、测试也比较直接、部署方便, 利用现成的 http 协议进行系统间通讯,如果业务真的慢慢做大,系统也慢慢扩大,RPC 框架的好处就显示出来了:首先 RPC 支持长链接,通信不必每次都要像 http 一样去重复 3 次握手,减少了网络开销。其次就是 RPC 框架一般都有注册中心模块,有完善的监控管理功能,服务注册发现、服务下线、服务动态扩展等都方便操作,服务化治理效率大大提高。

【CAP原理】

  • 一致性(Consistency) 所有节点在同一时间具有相同的数据
  • 可用性(Availability) 保证每个请求不管成功或者失败都有响应
  • 分区容错(Partition tolerance)系统中任意信息的丢失或失败不会影响系统的继续运作

一个分布式系统最多同时满足一致性 (Consistency),可用性 (Availability) 和分区容忍性 (Partition Tolerance) 这三项中的两项。同时满足一致性(C)和可用性(A)就要牺牲掉容错性(P),同时满足可用性(A)和分区容错性(P)就要牺牲掉一致性(C),同时满足一致性(C)和分区容错性(P)就要牺牲掉可用性(A)。

如何使用 CAP 理论

只要有网络交互就一定会有延迟和数据丢失,而这种状况必须要能接受,还必须保证系统不能挂掉。也就是说,分区容错性(P)是前提,是必须要保证的。现在就只剩下一致性(C)和可用性(A)可以选择了: 要么选择一致性,保证数据绝对一致;要么选择可用性,保证服务可用。

  • CP 模型的分布式系统,一旦因为消息丢失、延迟过高发生了网络分区, 就影响用户的体验和业务的可用性。因为为了防止数据不一致,集群将拒绝新数据的写入,典型的应用是 ZooKeeper,Etcd 和 HBase。
  • AP 模型的分布式系统,实现了服务的高可用。用户访问系统的时候都能得到响应数据,不会出现响应错误,但当出现分区故障时,相同的读操作访问不同的节点,得到响应数据可能不一样。典型应用就比如 Cassandra 和 DynamoDB。

【服务注册和发现】

服务注册和发现的过程:

  • 客户端会与注册中心建立连接,并且告诉注册中心,它对哪一组服务感兴趣;
  • 服务端向注册中心注册服务后,注册中心会将最新的服务注册信息通知给客户端;
  • 客户端拿到服务端的地址之后就可以向服务端发起调用请求了。

有了注册中心之后,服务节点的增加和减少对于客户端就是透明的。这样,除了可以实现不重启客户端,就能动态地变更服务节点以外,还可以实现优雅关闭的功能。服务在退出的时候都需要先停掉流量再停止服务,这样服务的关闭才会更平滑。(比如说,消息队列处理器就是要将所有,已经从消息队列中读出的消息,处理完之后才能退出)

 目前业界有很多可供选择的注册中心组件,比如说 Nacos、Eureka、Consul、CoreDNS、Zookeeper。 这些注册中心的区别如下:

参考资料:高并发系统设计40问_高并发架构_架构-极客时间  

【配置中心】

一般的配置文件比如数据库的配置信息,请求三方服务的token信息等,为了安全考虑,基本是不能放到版本管理工具中的。

使用传统的配置文件有哪些弊端:

  • 静态化配置,比如 Laravel 框架中的 .env 文件;
  • 配置文件无法区分环境,比如 Yii 框架使用不同的environment配置多套配置文件,也比较麻烦;
  • 配置文件过于分散,不方便管理,而且每次上线需要手动修改容易出错;
  • 历史版本无法查看,一旦出了问题想要回滚都比较困难。

微服务配置中心能解决哪些问题?

  • 配置信息的管理
  • 配置信息的查看、读取、更新等
  • 配置信息的管理界面

主流的配置中心都有哪些?

  • Apollo是由携程开源的分布式配置中心
  • Spring Cloud Config
  • consul

【Consul】

Consul介绍

Consul是google开源的一个使用go语言开发的服务发现、配置管理中心服务。Consul 简化了分布式环境中的服务的注册和发现流程,通过 HTTP 或者 DNS 接口发现。支持外部 SaaS 提供者等,它支持如下特性:

  • 服务注册:服务实现者可以通过HTTP API或DNS方式,将服务注册到Consul。
  • 服务发现:服务消费者可以通过HTTP API或DNS方式,从Consul获取服务的IP和PORT。
  • 故障检测:支持如TCP、HTTP等方式的健康检查机制,从而当服务有故障时自动摘除。
  • K/V存储:使用K/V存储实现动态配置中心,其使用HTTP长轮询实现变更触发和配置更改。
  • 多数据中心:支持多数据中心,可以按照数据中心注册和发现服务,即支持只消费本地机房服务,使用多数据中心集群还可以避免单数据中心的单点故障。
  • Raft算法:Consul使用Raft算法实现集群数据一致性。

Consul角色

-dev: 它是开发环境下的启动命令,提供了基本的服务,方便功能的开发,

-client,也就是客户端,它是无状态的,他将HTTP和DNS请求转发到服务端集群,

-server,也就是服务端,它保存配置信息,可以搭建高可用的集群。

Consul 内部端口

TCP/8300端口:用于服务器节点。客户端通过该端口RPC协议调用服务端节点。

TCP/UDP/8301端口:用于单个数据中心所有节点之间的互相通信,即对LAN池信息的同步。它使得整个数据中心能够自动发现服务器地址,分布式检测节点故障,事件广播(如领导选举事件)。

TCP/UDP/8302端口:用于单个或多个数据中心之间的服务器节点的信息同步,即对WAN池信息的同步。它针对互联网的高延迟进行了优化,能够实现跨数据中心请求。

8500端口:基于HTTP协议,用于API接口或WEB UI访问。

8600端口:作为DNS服务器,它使得我们可以通过节点名查询节点信息。

Consul工作原理

Consul集群

官方说法,一个集群的节点应该是3个或者5个。

为什么呢?首先是过半的选举机制,因为过半就可以选举出领导者,所以必须是基数才可以,否则经常会出现选举失败的情况。再然后就是因为consul遵循的是cap 原理中的CP原则,它保证了强一致性和分区容错性,且使用的是Raft算法,虽然它保证了强一致性,但是可用性就相应的下降了,所以它的节点就不宜太多,否则节点之间的同步就会影响性能。

consul官方给出的集群架构图:

关于Consul集群部署操作步骤,参考:Consul 集群部署_consul集群部署_freesharer的博客-CSDN博客

Raft算法

解决了分布式中领导选举和一致性问题,比较出名的共识算法,比如redis哨兵模式和consul。特点:

  • 任期机制, raft是终身任期的
  • 心跳机制,它决定领导者是否能有效的和跟随者通信
  • 随机的选举超时时间
  • 先到先得
  • 过半投票机制

Raft角色:

  • Follower追随者,接受领导者发送的消息,当心跳超时时主动推荐自己为候选人
  • Candidate候选人,发送rpc消息,让其它节点投票给自己票数过半时,成为领导者
  • Leader领导者,向其它节点发送心跳,只要心跳不超时一直为领导者

Raft官网有个动画演示,可以点击查看:Raft Consensus Algorithm

更多Raft算法的资料,参考:raft算法详解_学习让人快乐呀的博客-CSDN博客