微服务注册发现:Consul 介绍中对 Consul 的基本概念和原理进行了介绍;
微服务注册发现:Consul 部署和使用中介绍了 consul 的部署和简单使用,以及如何做服务注册和发现。但是例子中使用的是 Service Definition 配置文件的方式进行服务注册,使用起来很不方便。

此文中将基于 Node.js 构建一个服务,并能够做到以下几点:

  • 能够自动将自己注册到 consul 中
  • 可以对服务进行健康检查
  • 可以使用 Consul 提供的 Key/Value 存储功能作为服务的配置中心

1. 初始化 Consul 客户端

使用 Node.js 中的模块 node-consul 初始化一个 consul 客户端:

  1. # 安装 consul 模块
  2. $ 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 });

  1. <a name="igRyY"></a>
  2. # 2. 实现服务注册与健康检查
  3. - 在 consul.js 中进行实现服务注册和健康检查的配置:
  4. - **name** (String): 注册的服务名称
  5. - **id **(String, optional): 服务注册标识
  6. - **tags **(String[], optional): 服务标签
  7. - **address **(String, optional): 需要注册的服务地址(客户端)
  8. - **port **(Integer, optional): 需要注册的服务端口(客户端)
  9. - **check **(Object, optional): 服务的健康检查核心参数如下
  10. - http (String): 健康检查路径, interval 参数为必须设置
  11. - interval (String): 健康检查频率
  12. - timeout (String, optional): 健康检查超时时间
  13. - **checks **(Object[], optional): 如果有多个检查的路径,可采用对象数组形式,参数参照上面的 check
  14. ```javascript
  15. consul.agent.service.register({
  16. name: 'consul-client',
  17. address: '192.168.12.1',
  18. port: 3000,
  19. check: {
  20. http: 'http://192.168.12.1:3000/health',
  21. interval: '10s',
  22. timeout: '5s',
  23. }
  24. }, function(err, result) {
  25. if (err) {
  26. console.error(err);
  27. throw err;
  28. }
  29. console.log(serviceName + ' 注册成功!');
  30. })

3. 实现 consul 作为配置中心

Consul 的 Key/Value 功能可以做为服务的配置中心,对于项目中一些可变化的参数信息,可配置在 Consul 中,这样当数据改变时候不用因为配置的更改而导致项目还要重新发布

  • 获取配置信息

    • 这个 Key 为我们配置的路径,例如我要获取上面配置的 User 数据,Key 就为 ‘node/test’
      1. consul.kv.get(key)
      image.png
  • 更新配置信息

    • key (String): 更新的路径,例如 ‘node/test’
    • value (String|Buffer): 更新的数据信息
    • 注意:如果我们要更新 JSON 中的某个字段,首先我们需要先通过 consul.kv.get 读取到 JSON 对象,程序处理之后,做为 set 的第二个参数进行传递更新。
      1. 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 });

  1. this.consul.agent.service.register({
  2. name: serviceName,
  3. address: '192.168.12.1',
  4. port: 3000,
  5. check: {
  6. http: 'http://192.168.12.1:3000/health',
  7. interval: '10s',
  8. timeout: '5s',
  9. }
  10. }, function(err, result) {
  11. if (err) {
  12. console.error(err);
  13. throw err;
  14. }
  15. console.log(serviceName + ' 注册成功!');
  16. })
  17. }
  18. async getConfig(key) {
  19. const result = await this.consul.kv.get(key);
  20. if (!result) {
  21. return Promise.reject(key + '不存在');
  22. }
  23. return JSON.parse(result.Value);
  24. }
  25. async getUserConfig(key) {
  26. const result = await this.getConfig('node/test');
  27. if (!key) {
  28. return result;
  29. }
  30. return result[key];
  31. }
  32. async setUserConfig(key, val) {
  33. const name = await this.getConfig('node/test');
  34. user[key] = val;
  35. return this.consul.kv.set('node/test', JSON.stringify(name))
  36. }

} module.exports = ConsulConfig;

  1. - 启动文件 app.js
  2. - 对外提供 HTTP API 接口
  3. - 提供健康检查接口
  4. - 提供测试接口,读取 consul 中配置
  5. ```javascript
  6. const http = require('http');
  7. const ConsulConfig = require('./consul');
  8. const consul = new ConsulConfig();
  9. http.createServer(async (req, res) => {
  10. const {url, method} = req;
  11. // 测试健康检查
  12. if (url === '/health') {
  13. res.end('OK!');
  14. }
  15. // 测试动态读取数据
  16. if (method === 'GET' && url === '/user/info') {
  17. const user = await consul.getUserConfig();
  18. res.end(`Hi, I'm ${user.name} , my age is ${user.age}`);
  19. }
  20. // 测试数据更新
  21. if (method === 'POST' && url === '/user') {
  22. try {
  23. await consul.setUserConfig('age', 18) // 将 age 更改为 18
  24. res.end('OK!');
  25. } catch (err) {
  26. console.error(err);
  27. res.end('ERROR!');
  28. }
  29. }
  30. }).listen(3000);
  31. console.log('Server running at http://192.168.12.1:3000/');

5. 测试

  • 注册成功后,consul UI 出现启动的 node 服务

image.png

  • 测试读取配置信息接口
    1. $ curl http://192.168.12.1:3000/user/info
    2. Hi, I'm tom , my age is 18