Dawn's Blogs

分享技术 记录成长

0%

凤凰架构笔记 (7) 服务调用之服务发现 网关路由 客户端负载均衡

服务发现

服务发现既要高可用,又要高可靠。因为服务注册中心的地位是特殊的,不依赖其他服务,但被所有其他服务共同依赖(类似于配置中心),是系统中最基础的服务。服务注册中心一旦崩溃,整个系统都不再可用,因此,必须尽最大努力保证服务发现的可用性。

实际用于生产的分布式系统,服务注册中心都是以集群的方式进行部署的。

采用集群部署注册中心时,就会遇到 CAP 矛盾。所以注册中心分为两类,满足 AP 的注册中心满足 CP 的注册中心

  • 满足 AP 的注册中心,保证了高可用,但是注册中心内部可能会发生不一致的情况。代表如 Eureka、Redis、Nacos 等
  • 满足 CP 的注册中心,保证了一致性,但是必须经过集群之间的同步之后,才算是注册完成。代表如 Consul、Zookeeper、Etcd、Nacos 等

实现注册中心

实现注册中心,主要通过以下三种方式实现:

  • 在分布式 K/V 存储框架上自己开发的服务发现:这一类的代表为 Etcd、Zookeeper 等,需要在 CRUD 和 Watch 等 API 的基础上,自己去实现服务的注册和发现功能,还需要考虑健康检查。
  • 以基础设施来实现服务发现:代表就是 Kubernetes 的服务注册发现功能,如 Kubernetes 中采用 CoreDNS 进行服务发现。这种方案是 CP 还是 AP,取决于后端采用何种存储。
  • 专门用于服务发现的框架和工具:代表是 Eureka、Consul 和 Nacos,其中 Nacos 支持 AP 或者 CP 二选一。这类服务发现提供了专门的 API,使用这类服务发现必须有语言的支持。

网关路由

在为微服务中,路由网关又称之为 API 网关或者服务网关。作为微服务架构的入口,具有路由的功能,还可以具有认证、监控、缓存等辅助功能。

网络 I/O 模型

当发生一次网络请求发生后,将会按顺序经历,等待数据从远程主机到达缓冲区将数据从缓冲区拷贝到应用程序地址空间两个阶段。

把网络 I/O 模型分为两类,五种模型:

  • 异步 I/O:异步 I/O 中数据到达缓冲区后,不需要由调用进程主动进行从缓冲区复制数据的操作,而是复制完成后由操作系统向线程发送信号
  • 同步 I/O:
    • 阻塞 I/O:等待数据到达时就进入阻塞,直到数据到达唤醒线程,线程唤醒后将数据复制到自己的内存空间。这种方法节省 CPU 资源,但缺点就是线程休眠所带来的上下文切换。
    • 非阻塞 I/O:非阻塞 I/O 中,线程不会进入阻塞状态,而是会一直轮询直到数据到达。这种方法会浪费 CPU 资源,不常用。
    • 多路复用 I/O:多路 I/O 就是一个线程在多个描述符(一个描述符看作是一个连接)上等待,而不是每一个描述符一个线程。具体又分为 select、poll、epoll:
      • select:有数据到达后,每一次轮询所有等待的描述符,找出数据进行操作。
      • poll:本质上和 select 没有区别,但是没有最大连接数的限制,因为是基于链表的。
      • epoll:会把哪个文件描述符发生的事件(读取或者写入)通知给我们,不用轮询。
    • 信号驱动 I/O:等待数据到达后会发出信号,应用程序会自行将数据复制到自己的内存空间中。

信号驱动 I/O 和异步 I/O 的区别:

区别在于从缓冲区获取数据这个步骤,信号驱动 I/O 是应用程序自己将数据复制到自己的内存区域。而异步 I/O 是已经复制完成后,才发出信号。

BFF 网关

BFF 网关(后端前置)就是针对不同的前端提供不同的网关,而不是对所有前端提供统一无差别的服务。

image-20230609203726851

客户端负载均衡

负载均衡通常来说指的是部署在整个服务集群的前端的集中式负载均衡器(服务端负载均衡),如 Nginx、Apache 等。

但是在微服务架构中,每一种服务即充当客户端由充当服务端,而服务之间的调用是在微服务架构内部的,针对这种内部流量部署于每一个服务前端的负载均衡称之为客户端负载均衡

image-20230609212234746

客户端负载均衡与服务端负载均衡的差别:客户端均衡器是和服务实例一一对应的,而且与服务实例并存于同一个进程之内。这样做的好处:

  • 均衡器与服务之间信息交换是进程内的方法调用,不存在任何额外的网络开销。
  • 分散式的均衡器意味着天然避免了集中式的单点问题。
  • 客户端均衡器要更加灵活,能够针对每一个服务实例单独设置均衡策略等参数。

服务网格中,这种客户端负载均衡作为一个容器与应用放在同一个 Pod 中,这种被称为代理客户端负载均衡器。这样的代理负载均衡器不再受编程语言的限制,而且受到控制面的统一控制,有利于安全性和可观测性。