这是我参与「第三届青训营 -后端场」笔记创作活动的的第四篇笔记
微服务架构
基本概念
服务(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" //故障,出现错误
}
]