微服务架构学习 | 青训营笔记

75 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第四篇笔记

微服务架构

image.png

基本概念

服务(service) 一组具有相同逻辑的运行实体。
实例(instance) 一个服务中, 每个运行实体即为一个实例。
实例与进程的关系 实例与进程之间没有必然对应关系,一个实例可以对应一个或多个进程(反之不常见)
集群(cluster) 通常指服务内部的逻辑划分,包含多个实例。
常见的实例承载形式 进程、VM、k8s pod ......
有状态/无状态服务 服务的实例是否存储了可持久化的数据(例如磁盘文件)

服务注册与发现

问题:在代码层面,如何指定调用一个目标服务的地址(ip:port)?

  • hardcode:服务有多个实例,没法hardcode (记住一个服务的所有实例都是运行同一份代码),此外,服务实例ip:port本身是动态变化的。
  • DNS:本地DNS存在缓存,导致延时;负载均衡问题;不支持服务实例的探活检查;域名无法配置端口。 解决思路:新增一个统一的服务注册中心,用于存储服务名到服务实例的映射。

服务注册

将提供某个服务的模块信息(通常是这个服务的ip和端口)注册到1个公共的组件上去。
伪代码如下:

//给User服务申请1个独有的专属名字
UserNameServer = NameServer->apply('User');

//User服务下的6台docker实例启动后,都去注册自己
UserServer1 = {ip: 192.178.1.1, port: 3445}
UserNameServer->register(UserServer1);

......

UserServer6 = {ip: 192.178.1.6, port: 3445}
UserNameServer->register(UserServer6);

//给Order服务申请1个独有的专属名字
OrderNameServer = NameServer->apply('Order');

//开始注册
OrderServer1 = {ip: 192.178.1.1, port: 3446}
OrderNameServer->register(OrderServer1);

//给Search服务申请1个独有的专属名字
SearchNameServer = NameServer->apply('Search');

//开始注册
SearchServer1 = {ip: 192.178.1.1, port: 3447}
SearchNameServer->register(SearchServer1);

服务发现

新注册的服务模块能够及时的被其他调用者发现。不管是服务新增和服务删减都能实现自动发现。
伪代码如下:

//服务发现,获取User服务的列表
list = NameServer->getAllServer('User'); 

//list的内容
[    {        "ip": "192.178.1.1",        "port": 3445    },    {        "ip": "192.178.1.2",        "port": 3445    },    ......    {        "ip": "192.178.1.6",        "port": 3445    }]

//服务发现,获取Goods服务的列表
list = NameServer->getAllServer('Goods');

//list的内容
[    {        "ip": "192.178.1.1",        "port": 3788    },    {        "ip": "192.178.1.2",        "port": 3788    },    ......    {        "ip": "192.178.1.4",        "port": 3788    }]

健康检查

健康检查有多重实现方式,比如有几秒就发一次健康检查心跳,如果返回的HTTP状态不是200,那么就判断这台服务不可用,对它进行标记。也可以执行一个shell脚本,看执行的返回结果,来标记状态等等。
伪代码如下:

//服务发现,获取User服务的列表
list = NameServer->getAllServer('User'); 

//list的内容
[
    {
        "ip": "192.178.1.1",
        "port": 3445,
        "status": "success"
    },
    {
        "ip": "192.178.1.2",
        "port": 3445,
        "status": "success"
    },
    ......
    {
        "ip": "192.178.1.6",
        "port": 3445
        "status": "error" //故障,出现错误
    }
]