微服务中的服务发现与注册中心
在微服务架构中,服务实例的数量可能随着流量负载自动扩展或缩减,因此服务之间如何高效地进行通信成为一个重要问题。本篇博客将介绍服务发现的概念,并结合 Consul
和 自定义注册中心 进行实践,帮助开发者在微服务架构下高效管理服务通信。
1. 什么是服务发现?
服务发现是指微服务架构中,服务实例能够被其他服务动态定位的机制。在单体应用中,服务通常运行在固定的 IP 地址和端口上,而在微服务架构中,由于容器化和自动扩展,服务的 IP 和端口可能是动态的,导致传统的静态配置方法不再适用。
服务发现主要分为两种模式:
-
客户端服务发现(Client-side Service Discovery):客户端直接查询服务注册中心,获取可用的服务实例列表。
-
服务器端服务发现(Server-side Service Discovery):请求先经过负载均衡器或 API 网关,由它负责查询服务实例并转发请求。
2. DNS 作为服务发现方案
DNS(域名系统)是最基础的服务发现机制,它将域名解析为服务器 IP 地址,并可以结合负载均衡来管理多个实例。
DNS 的优势
-
适用于已有基础设施,不需要额外的服务发现组件。
-
广泛兼容各类客户端和服务端技术。
DNS 的局限性
-
更新不够及时:DNS 记录的缓存(TTL)可能导致客户端继续使用失效的 IP 地址。
-
负载均衡策略有限:默认的 DNS 轮询策略无法动态适应服务状态变化。
解决方案:使用 Consul 作为动态 DNS 解析服务,提供服务注册与发现功能。
3. 通过 Consul 进行服务发现
Consul
是 HashiCorp 开源的一款服务发现与健康检查工具,它支持 DNS 解析和 REST API 查询,能自动感知服务的健康状态。
(1) 启动 Consul
首先,我们需要运行 Consul 作为服务发现中心:
consul agent -dev
然后打开浏览器访问 http://127.0.0.1:8500
,查看 Consul 控制台。
(2) 注册服务到 Consul
创建 loginService.js
,作为待注册的微服务。
const express = require('express');
const app = express();
app.get('/health', (req, res) => {
res.status(200).send('OK');
});
app.listen(3000, () => {
console.log('loginService 运行在 http://127.0.0.1:3000');
});
然后创建 loginServiceRegister.js
,将 loginService
注册到 Consul:
const consul = require('consul')({ host: '127.0.0.1', port: 8500 });
const serviceId = 'login-service-3000';
consul.agent.service.register({
id: serviceId,
name: 'loginService',
address: '127.0.0.1',
port: 3000,
check: {
http: 'http://127.0.0.1:3000/health',
interval: '10s'
}
}, (err) => {
if (err) {
console.error('服务注册失败:', err);
} else {
console.log('loginService 注册成功');
}
});
运行:
node loginService.js
node loginServiceRegister.js
可以在 Consul 控制台 http://127.0.0.1:8500
查看注册的服务。
(3) 服务健康检查
在 Consul 中,健康检查是服务发现的重要部分。健康检查的作用包括:
-
确保服务正常运行。
-
发现故障时自动从可用实例列表中移除该服务。
当 loginService
停止时,Consul 控制台会标记它为 critical
,并在恢复运行后自动恢复 healthy
状态。
4. 自定义注册中心实现
除了使用 Consul 作为注册中心,我们还可以手动实现一个轻量级的服务注册中心,适用于不需要完整 Consul 功能的项目。
(1) 目录结构
microservices/
├── registry-service/ # 服务注册中心
├── catalog-service/ # 目录服务
├── shopper-service/ # 购物者前端
(2) 搭建注册中心
-
初始化注册中心项目:
mkdir registry-service && cd registry-service
npm init -y
npm install express axios
-
创建
registry-service/index.js
,提供服务注册 API:
const express = require('express');
const app = express();
app.use(express.json());
let services = {};
app.post('/register', (req, res) => {
const { name, version, ip, port } = req.body;
const serviceKey = `${name}-${version}`;
services[serviceKey] = { ip, port, lastUpdated: Date.now() };
console.log(`已注册: ${serviceKey} -> ${ip}:${port}`);
res.send({ message: '服务注册成功' });
});
app.get('/discover/:name/:version', (req, res) => {
const serviceKey = `${req.params.name}-${req.params.version}`;
res.send(services[serviceKey] || {});
});
setInterval(() => {
const now = Date.now();
for (const key in services) {
if (services[key].lastUpdated < now - 60000) {
delete services[key];
console.log(`移除过期服务: ${key}`);
}
}
}, 60000);
app.listen(4000, () => console.log('注册中心运行在 http://127.0.0.1:4000'));
5. 总结
本篇博客介绍了服务发现的基本概念,并分别使用 Consul 和自定义注册中心 进行了实现,同时增加了健康检查和过期服务清理功能。希望能帮助你在微服务架构中更好地管理服务注册与发现!🚀