第01篇:分布式注册中心

西魏陶渊明 ... 2022-5-22 分布式 大约 6 分钟

# 一、什么是注册中心

什么是注册中心注册中心 往往是在分布式的应用体系下才会遇到的。对于分布式体系应用都是横向进行扩展。如下图User App这个服务,具有2台服务器 但是当用户从网关进来访问, 网关是如何知道这个 User App有几台服务及每台服务的网络地址是什么呢? 所以就需要有一个地方能收集到每台应用的地址及命名。 往往这个地方就被叫做 注册中心。分布式环境下的应用在启动时候都会向这个地方来注册自己的网络地址,及命名。

# 二、注册中心的职责

但是注册中心只能注册服务吗? 当然不是,如果仅仅只做这个事情,那么岂不是浪费了自己的资源呢? 注册中心要做到

好了,我们看下再分布式的环境下,注册中心的位置有多重要了,如果没有了注册中心,网络上的服务都是瞎子了。所以这个系统 的设计我们要重新考虑到他的可用性,以及就算注册中心挂了,各服务之间不要里面就瞎。最起码要留给注册中心一个重启的时间

好了,知道这么多,我们直接开始设计吧。

# 三、设计注册中心

# 3.1 ip地址获取

这里要注意的点是不要拿到了127.0.0.1这个本地回环地址。类似工具网络很多,这不是重点。看下就行。

public class HostUtils {
    private static String ip;
    private static String hostName;
    private static void resolveHost() throws Exception {
        InetAddress localHost = InetAddress.getLocalHost();
        hostName = localHost.getHostName();
        ip = localHost.getHostAddress();
        if (localHost.isLoopbackAddress()) {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = networkInterfaces.nextElement();
                Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
                while (inetAddresses.hasMoreElements()) {
                    InetAddress inetAddress = inetAddresses.nextElement();
                    if (!inetAddress.isLoopbackAddress() && (inetAddress instanceof Inet4Address)) {
                        ip = inetAddress.getHostAddress();
                    }
                }
            }
        }
    }
    public static String getIp() {
        return ip;
    }
    public static String getHostName() {
        return hostName;
    }
    static {
        try {
            resolveHost();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 3.2 通信协议 & 技术选型

通信协议一般为了兼容多语言环境, 最好使用的http协议。因为应用比较广泛。当然你也可以自定义协议。这里推荐一个 小编基于Netty封装的通信框架 mojito (opens new window) 这里我们主要考虑通用性,使用 http协议。因为现在微服务使用 Spring Cloud 的较多,所以我们的注册中心的框架选型使用 Spring Boot

这里我们可以使用SpringBoot的Endpoint 实现自己的扩展点,同时也可以使用服务自带的健康检查能力,进行状态监控。

下面描述下实现思路

# 3.3 交互流程

# 3.3.1 服务端能力

  • 提供服务注册接口
    • 数据可以落到数据库, 同时记录内存缓存,服务量大可以考虑使用redis
    • 同时要落到文件中, 避免数据库挂了能从文件中恢复到缓存中
  • 提供服务下线接口
    • 当服务下线,主动调用注册中心下线接口,注册中心要提供被动接受下线能力
    • 当轮训到服务状态不好,主动将服务标记为下线,当服务状态恢复重新标记为正常
  • 提供服务健康检查能力
    • 轮训已注册的机器的健康检查接口,动态更新节点状态
    • 启动定时任务,定时发送状态检查,检查客户端服务状态
  • 提供服务发现接口
    • 通过传递服务名,返回服务名对应的服务列表
  • 提供应用配置能力
    • 做到服务隔离,不要把某个服务的配置,推送到全部服务器,只需要推动到这个服务对应的节点即可
    • 能主动发起配置变更消息

# 3.3.2 客户端能力

  • 服务注册能力
    • 实现 ApplicationContextInitializer 应用启动时候读取应用配置,然后将自己注册到注册中心
    • 将注册中心的配置,同时拉下来,放到Spring配置环境
  • 服务重新或者宕机主动下线
    • 利用@PreDestroy销毁方法,或者注册Jvm Hooks程序
  • 服务发现能力
    • 根据服务名获取服务列表接口,同时缓存到本地一份
    • 如果注册中心无响应,要能使用本地缓存, 给注册中心留一个重启的时间
  • 监听服务器配置信息
  • 打开健康检查

# 四、常见的注册中心

注册中心对比 (opens new window)

# 4.1 Zookeeper

什么是ZooKeeper? (opens new window)

可以用ZooKeeper来做:统一配置管理、统一命名服务、分布式锁、集群管理。

ZooKeeper的数据结构,跟Unix文件系统非常类似,可以看做是一颗树,每个节点叫做ZNode。每一个节点可以通过路径来标识,结构图如下:

那ZooKeeper这颗"树"有什么特点呢??ZooKeeper的节点我们称之为Znode,Znode分为两种类型:

短暂/临时(Ephemeral):当客户端和服务端断开连接后,所创建的Znode(节点)会自动删除 持久(Persistent):当客户端和服务端断开连接后,所创建的Znode(节点)不会删除

另外Zookeeper提供了节点监听的能力,当节点发生变化会发起通知事件。我们可以根据这个特性做一些事情,比如节点被删除就移除注册在这个节点上的服务。

zookeepr api

# 4.2 Eureka

Eureka是干什么的? (opens new window) Eureka是SpringBoot默认的注册中心组件。没有配置的能力

# 4.3 Consul

Consul是用于服务发现和配置的工具。Consul是分布式的,高度可用的,并且具有极高的可伸缩性,而且开发使用都很简便。它提供了一个功能齐全的控制面板,主要特点是:服务发现、健康检查、键值存储、安全服务通信、多数据中心、ServiceMesh。Consul在设计上把很多分布式服务治理上要用到的功能都包含在内了。

# 4.4 Nacos

Nacos致力于发现、配置和管理微服务。Nacos提供了一组简单易用的特性集,帮助您实现动态服务发现、服务配置管理、服务及流量管理。Nacos更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构(例如微服务范式、云原生范式)的服务基础设施。Nacos支持作为RPC注册中心,例如:支持Dubbo框架;也具备微服务注册中心的能力,例如:SpringCloud框架。

# 五、总结

市面上的注册中心有以上这些,核心逻辑思路都大差不差。其中Consul和Nacos是支持配置的。如果我们开发注册中心的话,没必要研究其源码。 只有当我们要做注册中心,这个时候我们可以去研究下源码。对于一般开发使用,只要知道他是做什么的就好了。


本文由西魏陶渊明版权所有。如若转载,请注明出处:西魏陶渊明
上次编辑于: 2022年6月16日 21:10
贡献者: lxchinesszz