服务发现
@ 晚风 · Sunday, Aug 7, 2022 · 2 分钟阅读 · 更新于 8月 7, 2022

服务发现

服务发现

侧重点在于理解服务发现原理与简单实战操作

背景

微服务分布式

定义

  • 微服务:将一个系统按业务划分成多个子系统,每个子系统都是完整的,可独立运行的,子系统间的交互可通过RPC(HTTP协议、消息队列等等)进行通信
  • 分布式:服务是分散部署在不同的机器上,通过RPC/WebService交互

关系

  • 抽象版理解

​ 分布式其实是一种手段,即把不同的服务部署于不同的机器(地区),然后这些服务协同作战。而微服务属于分布式的一种(这里其实有异,因为微服务也可以部署于同一服务器,它更强调单一职责,而不关心是否是分布的),他具有更细颗粒度的划分,重在分散能力,使每个模块都独立。分布式重在资源共享与加快计算机计算速度,同时分散压力

  • 通俗版理解

    分布式是对业务的拆分,可以分为水平拆分和垂直拆分。

    比如一个电商项目进行分布式

    • 水平拆分

      表示层:直接对接用户,一般指系统界面,用户可以进行数据录入,删除等操作

      业务层:一系列数据校验,权限校验等等流程

      数据层:与数据库交互,进行数据的增删改查

    • 垂直拆分

      根据业务进行拆分

      订单模块: 仅进行与订单相关的业务流程

      商品模块: ·····

      用户模块:····

      ······

​ 那么微服务呢?其实可以针对垂直拆分的模块进行细化拆分!

不要理解为微服务属于分布式! 这里举例只是区分 分布式微服务

进入正题


意义

​ 刚才简单介绍了分布式与微服务,那么服务发现是为了解决什么问题呢?很明显,如果是传统的服务架构,服务固定运行于一个固定的IP和端口上,如果需要调用服务,则直接利用IP+端口就可以直接访问了,但是在虚拟化与容器化时代,服务部署变得更加简单,而分布式与微服务对服务的切分使服务数量开始增长,服务实例的启动和销毁也开始变得很频繁,所以服务地址可能在不停的动态变更。

​ 调用方视角:怎么找到想调用的服务?找到了ta是不是能正常提供服务?

​ 服务方视角:我是新人,怎么让别人知道我?我要跑路了(挂掉),又怎么让别人不要再来找我?

简单流程

  • 服务启动时候进行注册
  • 查询已注册服务信息
  • 确认服务状态是否健康

服务注册:服务启动 -> 注册中心注册(ip+port) -> 定时反馈自身状态

服务发现:其他用户可通过注册中心查找到相关信息

服务注册

  • 提供某个服务的信息注册到公共的注册中心去

自己注册

服务启动:去统一的服务注册中心进行注册登记

服务运行:持续发送心跳,通知注册中心,服务正常

服务停止:去统一的服务注册中心进行注销

服务异常:不发送心跳,被服务注册中心当作异常,然后移除记录

三方注册

服务启动:三方发现有新服务,就去注册中心帮他登记

服务运行:三方进行监控,通过ping亦或其他方式进行健康检查

服务停止/异常:三方发现服务停止,就去注册中心帮他移除记录

三方注册存在的意义在于,如果服务本身发生了故障,但并没有挂掉,仍然发送心跳,会导致流量仍然打到此服务,所以不能仅凭心跳就确认服务存活,此时需要利用三方的探测/监控进行确认

服务发现

  • 新增服务/删除服务能够及时被调用者发现

客户端发现

特点

  • Client端本身实现负载均衡的功能,先从注册中心获取可用服务列表,然后通过自身负载均衡算法,选择一个最合理的服务提供者进行调用

优点

  • 客户端决定负载均衡算法,可以自由定制策略,比如轮询、加权、哈希等
  • 扩展灵活
  • 去中心化(这也是微服务的目的)

缺点

  • 和注册中心强耦合,如果更改注册中心,需要修改代码
  • 负载策略修改,需要更新所有客户端的负载均衡

服务端发现

这里负载均衡器是否属于注册中心都可以,但是他一定要和服务信息进行数据交互才能进行请求转发

特点

  • 负载均衡器独立于客户端,Client请求负载均衡器,负载均衡器与注册服务信息进行数据交互,进而选择合适的服务供客户端调用

优点

  • 客户端无需关心服务列表,以及采用什么负载策略
  • 负载策略更新或者注册中心更换,只需要负载均衡器修改即可

缺点

  • 每次请求都需要经过注册中心,注册中心压力会比较大

不知道你有没有看出来,通过对比客户端发现与服务端发现两种模式,发现多中心化去中心化总是会增加更新代价,这与分布式的数据一致性有何关系?

服务发现框架

Zookeeper Etcd Consul
原生语言 Java Go Go
算法 Paxos Raft Raft
多数据中心
健康检查
http协议 ✅(复杂)
DNS协议 ✅(复杂)

虽然对比起来,Zookeeper、Etcd不占优势,但是一个毕竟是经验丰富的长辈(旧时代的残党(Zookeeper)),一个是满身光环的新人(新时代的船(没错,船指的就是K8s)桨(Etcd)),那么接下来我们就介绍一下Consul(狗头)吧

Consul

无论Etcd、Consul都是用Raft算法保证一致性与高可用!

但是这里对Consul不做过多的原理介绍,主要是玩一下Consul

特点

  • 服务发现
  • 健康检查
  • K/V存储
  • 安全通讯
  • 多数据中心

端口

端口 说明
TCP/8300 8300端口用于服务器节点。客户端通过该端口RPC协议调用服务端节点
TCP/UDP/8301 8301端口用于单个数据中心所有节点之间的互相通信, 即对LAN池信息的同步。她使得整个数据中心能够自动发现服务器地址,分布式检测节点故障,事件广播(如领导选举事件)
TCP/UDP/8302 8302端口用于单个或多个数据中心之间的服务器节点的信息同步,即对WAN池信息的同步。它针对互联网的高延迟进行了优化,能够实现跨数据中心请求
8500 8500端口基于HTTP协议,用于API接口或者WEB UI访问
8600 8600端口作为DNS服务器,它使得我们可以通过节点名查询节点信息

部署

不多BB,直接用Docker-Compose玩一下

1/docker拉取consul最新镜像

docker pull consul	// 拉取镜像
docker images // 查看镜像

2/docker-compose一键启动

这里一共启动了4个consul,其中consul1 是主节点,consul2、consul3 是子节点。consul4是提供ui服务

version: '3.5'
services:
  consul1:
    image: consul:latest
    container_name: consul1
    restart: always
    command: agent -server -client=0.0.0.0 -bootstrap-expect=3 -node=consul1
    volumes:
      - /data/consul/consul1/data:/consul/data
      - /data/consul/consul1/config:/consul/config
  consul2:
    image: consul:latest
    container_name: consul2
    restart: always
    command: agent -server -client=0.0.0.0 -retry-join=consul1 -node=consul2
    volumes:
      - /data/consul/consul2/data:/consul/data
      - /data/consul/consul2/config:/consul/config
    depends_on:
      - consul1
  consul3:
    image: consul:latest
    container_name: consul3
    restart: always
    command: agent -server -client=0.0.0.0 -retry-join=consul1 -node=consul3
    volumes:
      - /data/consul/consul3/data:/consul/data
      - /data/consul/consul3/config:/consul/config
    depends_on:
      - consul1
  consul4:
    image: consul:latest
    container_name: consul4
    restart: always
    ports:
      - 8500:8500
    command: agent -client=0.0.0.0 -retry-join=consul1 -ui -node=client1
    volumes:
      - /data/consul/consul4/data:/consul/data
      - /data/consul/consul4/config:/consul/config
docker-compose -f consul_cluster.yaml up -d	// 一键启动服务

查看consul节点情况

docker exec -t consul1 consul members

访问consul界面(ip+8500)

3/服务注册

  • 启动一个http服务
python -m http.server 8001
  • 使用python进行服务注册

    # pip install python-consul
    from pprint import pprint
    
    import consul
    
    CONSUL_CONFIG = {
        "consul_host": "xxxxx",
        "consul_port": "8500"
    }
    
    SERVICE_CONFIG = {
        "name": "test1",
        "host": "xxxxx",
        "port": 8001,
    }
    
    
    class Consul(object):
        def __init__(self):
            # 建立链接
            self._consul = consul.Consul(CONSUL_CONFIG["consul_host"], CONSUL_CONFIG["consul_port"])
            self.service_name = SERVICE_CONFIG["name"]
            self.service_host = SERVICE_CONFIG["host"]
            self.service_port = SERVICE_CONFIG["port"]
    
        def register_service(self, tags=[]):
            # 注册服务
            self._consul.agent.service.register(self.service_name, self.service_name, self.service_host, self.service_port,
                                                tags,
                                                check=consul.Check().tcp(self.service_host, self.service_port, "10s", "30s",
                                                                         "30s"))  # tcp 后三个参数为 检查时间间隔,超时时间, 注销时间
    
        def get_service(self):
            services = self._consul.agent.services()
            service = services.get(self.service_name)
            if not service:
                return None, None
            addr = f"{service['Address']}-{service['Port']}"
            return service, addr
    
        def run(self):
            self.register_service()
            check = consul.Check().tcp(self.service_host, self.service_port, "10s", "30s", "30s")
            pprint(check)
            res = self.get_service()
            pprint(res)
    
    
    if __name__ == '__main__':
        Consul().run()
    
    
  • 查看注册情况

  • 关闭服务(时间过后自动注销)

4/服务发现

暂时不涉及访问控制,即不用验证即可访问节点

思考

服务发现中无论是客户端发现还是服务端发现模式,感觉都和DNS的运作原理有点相似,搜索看了一下,阿里巴巴已经有基于DNS的服务发现

关于我

❤️

姓名: lwz


性别: 男


年龄: 29


星座: 摩羯座


职业: python工程师


爱好: 秋、ps5、运动


主要的技术栈是:

  • python
  • 自动驾驶仿真验证

学习网站: leetcode


公司: 国科础石


– 2025 年 2 月 25 日更新

我的一些开源项目

等等?项目呢?不会没有吧??

其他

如果你喜欢我的开源项目或者它们可以给你带来帮助,可以赏一杯咖啡 ☕ 给我。~

It is better to attach some information or leave a message so that I can record the donation 📝, thank you very much 🙏.

社交链接