《微服务注册发现:Consul 介绍》中对 Consul 的基本概念和原理进行了介绍;
《微服务注册发现:Consul 部署和使用》中介绍了 consul 的部署和简单使用,以及如何做服务注册和发现。但是例子中使用的是 Service Definition 配置文件的方式进行服务注册,使用起来很不方便。
此文中将基于 Node.js 构建一个服务,并能够做到以下几点:
- 能够自动将自己注册到 consul 中
- 可以对服务进行健康检查
- 可以使用 Consul 提供的 Key/Value 存储功能作为服务的配置中心
1. 初始化 Consul 客户端
使用 Node.js 中的模块 node-consul 初始化一个 consul 客户端:
# 安装 consul 模块
$ npm install consul --save
- 创建 consul.js,初始化 consul 客户端:
- host (String, default: 127.0.0.1): 配置 Consul 地址
- port (Integer, default: 8500): 配置 Consul 端口
- secure (Boolean, default: false): 启用 HTTPS
- promisify (Boolean|Function, optional): 启动 Promise 风格,默认为 Callback ```javascript const Consul = require(‘consul’);
const consul = new Consul({ host: ‘192.168.12.131’, post: 8500, promisify: true });
<a name="igRyY"></a>
# 2. 实现服务注册与健康检查
- 在 consul.js 中进行实现服务注册和健康检查的配置:
- **name** (String): 注册的服务名称
- **id **(String, optional): 服务注册标识
- **tags **(String[], optional): 服务标签
- **address **(String, optional): 需要注册的服务地址(客户端)
- **port **(Integer, optional): 需要注册的服务端口(客户端)
- **check **(Object, optional): 服务的健康检查核心参数如下
- http (String): 健康检查路径, interval 参数为必须设置
- interval (String): 健康检查频率
- timeout (String, optional): 健康检查超时时间
- **checks **(Object[], optional): 如果有多个检查的路径,可采用对象数组形式,参数参照上面的 check
```javascript
consul.agent.service.register({
name: 'consul-client',
address: '192.168.12.1',
port: 3000,
check: {
http: 'http://192.168.12.1:3000/health',
interval: '10s',
timeout: '5s',
}
}, function(err, result) {
if (err) {
console.error(err);
throw err;
}
console.log(serviceName + ' 注册成功!');
})
3. 实现 consul 作为配置中心
Consul 的 Key/Value 功能可以做为服务的配置中心,对于项目中一些可变化的参数信息,可配置在 Consul 中,这样当数据改变时候不用因为配置的更改而导致项目还要重新发布
获取配置信息
- 这个 Key 为我们配置的路径,例如我要获取上面配置的 User 数据,Key 就为 ‘node/test’
consul.kv.get(key)
- 这个 Key 为我们配置的路径,例如我要获取上面配置的 User 数据,Key 就为 ‘node/test’
更新配置信息
- key (String): 更新的路径,例如 ‘node/test’
- value (String|Buffer): 更新的数据信息
- 注意:如果我们要更新 JSON 中的某个字段,首先我们需要先通过 consul.kv.get 读取到 JSON 对象,程序处理之后,做为 set 的第二个参数进行传递更新。
consul.kv.set('node/test', JSON.stringify(user))
4. 完整的 Node.js 服务代码
- Node 集成 consul 客户端模块 consul.js
- 初始化客户端
- 服务注册
- 将 consul 作为配置中心,读取和设置配置 ```javascript const Consul = require(‘consul’);
class ConsulConfig { constructor() { const serviceName = ‘consul-demo’; this.consul = new Consul({ host: ‘192.168.12.131’, post: 8500, promisify: true });
this.consul.agent.service.register({
name: serviceName,
address: '192.168.12.1',
port: 3000,
check: {
http: 'http://192.168.12.1:3000/health',
interval: '10s',
timeout: '5s',
}
}, function(err, result) {
if (err) {
console.error(err);
throw err;
}
console.log(serviceName + ' 注册成功!');
})
}
async getConfig(key) {
const result = await this.consul.kv.get(key);
if (!result) {
return Promise.reject(key + '不存在');
}
return JSON.parse(result.Value);
}
async getUserConfig(key) {
const result = await this.getConfig('node/test');
if (!key) {
return result;
}
return result[key];
}
async setUserConfig(key, val) {
const name = await this.getConfig('node/test');
user[key] = val;
return this.consul.kv.set('node/test', JSON.stringify(name))
}
} module.exports = ConsulConfig;
- 启动文件 app.js
- 对外提供 HTTP API 接口
- 提供健康检查接口
- 提供测试接口,读取 consul 中配置
```javascript
const http = require('http');
const ConsulConfig = require('./consul');
const consul = new ConsulConfig();
http.createServer(async (req, res) => {
const {url, method} = req;
// 测试健康检查
if (url === '/health') {
res.end('OK!');
}
// 测试动态读取数据
if (method === 'GET' && url === '/user/info') {
const user = await consul.getUserConfig();
res.end(`Hi, I'm ${user.name} , my age is ${user.age}`);
}
// 测试数据更新
if (method === 'POST' && url === '/user') {
try {
await consul.setUserConfig('age', 18) // 将 age 更改为 18
res.end('OK!');
} catch (err) {
console.error(err);
res.end('ERROR!');
}
}
}).listen(3000);
console.log('Server running at http://192.168.12.1:3000/');
5. 测试
- 注册成功后,consul UI 出现启动的 node 服务
- 测试读取配置信息接口
$ curl http://192.168.12.1:3000/user/info
Hi, I'm tom , my age is 18