Nodejs 上使用 DNS 进行 Consul 服务发现

2024-05-27

TL;DR

大家好, 我试图从用 Express 编写的 NodeJS 前端调用 NodeJS 后端微服务,通过Consul https://www.consul.io DNS接口 https://www.consul.io/intro/getting-started/services.html#querying-services但我有错误。

我正在使用Node.js 域名解析 API https://nodejs.org/api/dns.html为唯一节点应用程序设置 dns,以便对本地 Consul DNS 接口进行后续 dns.resolve() 调用。

Target

我希望能够向我的后端服务发出 http 请求,而无需在客户端代码中连接其 IP 和端口。我也不想编写自定义代码来查询 Consul HTTP API,以便在需要调用服务时获取 ip:port 对。

Problem

问题是当我使用axios https://www.npmjs.com/package/axios(如同request https://www.npmjs.com/package/request)对后端服务进行 HTTP 调用时,我总是收到错误,因为它无法解析地址。看来 Axios 没有使用我之前设置的 dns:

dns.setServers(['127.0.0.1:8600']);

Update_1

使用 consul 的 -recursor 命令行选项将虚拟机 (/etc/resolv.conf) 的 dns 设置为 localhost e,并使用默认 dns 一切正常!我仍然想了解我只在我的 Node.js 应用程序上设置 dns 时做错了什么。

Setup

  • 1 个 FE 节点,带有一个 Nodejs 进程,运行一个带有 Express Js 的简单 Web 服务器。在 app.get('/') 路由中,它通过 consul 和 axios 对名为 be01 的后端服务进行 REST POST 调用(如 request)。
  • 2 BE 节点,带有一个 nodejs 进程,运行一个简单的 Web 服务器,并使用 Expressjs 公开 REST api。
  • 1 个 Consul 节点,Consul 作为服务器运行。
  • 每个节点都有自己的 consul 代理运行并加入到集群中。
  • TCP 端口已正确打开

This are the servers: enter image description here

This is from the Consul UI: enter image description here

在 FE 节点上运行 consul 成员我得到:

agent-server  10.0.1.7:8301  alive   server  1.0.1  2         dc1  <all>
agent-be-01   10.0.1.5:8301  alive   client  1.0.1  2         dc1  <default>
agent-be-02   10.0.1.6:8301  alive   client  1.0.1  2         dc1  <default>
agent-fe      10.0.1.4:8301  alive   client  1.0.1  2         dc1  <default>

如果我跑挖@localhost -p 8600 be01.service.consul SRV在 FE 节点上我正确地得到了这个结果(如领事文档中所示 https://www.consul.io/intro/getting-started/services.html#querying-services):

root@NGINXLB:~/node8080$ dig @localhost -p 8600 be01.service.consul SRV

; <<>> DiG 9.9.5-3ubuntu0.16-Ubuntu <<>> @localhost -p 8600 be01.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43367
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 5
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;be01.service.consul.       IN  SRV

;; ANSWER SECTION:
be01.service.consul.    0   IN  SRV 1 1 8081 agent-be-02.node.dc1.consul.
be01.service.consul.    0   IN  SRV 1 1 8080 agent-be-01.node.dc1.consul.

;; ADDITIONAL SECTION:
agent-be-02.node.dc1.consul. 0  IN  A   10.0.1.6
agent-be-02.node.dc1.consul. 0  IN  TXT "consul-network-segment="
agent-be-01.node.dc1.consul. 0  IN  A   10.0.1.5
agent-be-01.node.dc1.consul. 0  IN  TXT "consul-network-segment="

;; Query time: 2 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Fri Dec 01 10:09:00 UTC 2017
;; MSG SIZE  rcvd: 246

这是 BE 服务代码:

var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var jsonParser = bodyParser.json()
var urlencodedParser = bodyParser.urlencoded({ extended: false })

app.post('/api/getUserTiles', jsonParser, function (req, res) {
  console.log("> API request for '/api/getUserTiles'");
  if (!req.body) { return res.sendStatus(400) }
  else {
    var user = req.body.user;
    console.log("User: " + user);
    res.json({
      "authorizedTiles": [
        {"tileID": "profile"}
        ,{"tileID": "search"}
        ,{"tileID": "test"}
      ],
      "email": "[email protected] /cdn-cgi/l/email-protection",
      "userName":"Max",
      "has_error": false,
      "error_message": ""
    });
  }
});

var server = app.listen(8080, function () {
  var host = server.address().address
  var port = server.address().port
  console.log("Example app listening at http://%s:%s", host, port)
})

使用 ip:port 和 curl 从 FE 调用它不会出现任何问题:

root@NGINXLB:~/node8080$ curl -d="user=Max" -X POST http://10.0.1.5:8080/api/getUserTiles
{"authorizedTiles":[{"tileID":"profile"},{"tileID":"search"},{"tileID":"test"}],"email":"[email protected] /cdn-cgi/l/email-protection","userName":"Max","has_error":false,"error_message":""}

FE 节点上的 Web 服务简单来说是这样的:

var axios = require('axios');
var dns = require('dns');
var consul = require('consul')();

dns.setServers(['127.0.0.1:8600']);
//console.log(dns.getServers());

dns.resolveSrv("be01.service.consul", function(err, records){
        console.log("\nDNS SRV query");
        if(err){
                console.log(err);
        }else{
                console.log(records);
        }
});

consul.health.service({
        "service": "be01",
        "dc": "dc1",
        "passing": true
        }, function(err, result){
                console.log("\nConsul.health.service query:");
                if(err){console.log(err); throw err;}
                else if(result.length > 0){
                        for(var i=0; i<result.length; i++){
                                console.log(result[i].Node.Address + ":" + result[i].Service.Port);
                        }
                }
});

axios.post("http://be01.service.consul/api/getUserTiles", {'user':'Max'})
  .then(function(response){
      if (response.data.has_error) {
       console.log("\nRESPONSE HAS ERROR!");
      }else {
        console.log("\nSUCCESS!");
      }
  })
  .catch(function(err) {
        console.log("\nERROR CALLING THE BE SERVICE");
  });

运行它我得到以下结果:

root@NGINXLB:~/node8080$ node app.js 

DNS SRV query
[ { name: 'agent-be-01.node.dc1.consul',
    port: 8080,
    priority: 1,
    weight: 1 },
  { name: 'agent-be-02.node.dc1.consul',
    port: 8081,
    priority: 1,
    weight: 1 } ]

Consul.health.service query:
10.0.1.5:8080
10.0.1.6:8081

ERROR CALLING THE BE SERVICE
{ Error: getaddrinfo ENOTFOUND be01.service.consul be01.service.consul:80
    at errnoException (dns.js:50:10)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:92:26)
  code: 'ENOTFOUND',
  errno: 'ENOTFOUND',
  syscall: 'getaddrinfo',
  hostname: 'be01.service.consul',
  host: 'be01.service.consul',
  port: 80,
  ...
  ...

结论

正如您所看到的,nodejs 客户端正在调用 be 服务,但尝试解析“be01.service.consul”失败。此外,它使用端口 80,而不是 Consul DNS 接口提供的 8080 或 8081。我缺少什么?


问题是 axios 正在使用dns.lookup它不使用由设置的服务器dns.setServers. dns.lookup and dns.resolve不要使用相同的机制 https://nodejs.org/api/dns.html#dns_implementation_considerations for 解决 https://github.com/nodejs/node-v0.x-archive/issues/8475#issuecomment-59536006.

在纯节点中,可能的选项是使用以下命令将域名解析为 IP:dns.resolve*在调用 axios 或类似的东西之前拦截器示例 https://github.com/axios/axios/issues/94(我没试过)。

可能更好的解决方案不是在节点中执行此操作,而是使用领事代理 https://www.consul.io/docs/agent/basics.html在本地运行以进行 dns 解析。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Nodejs 上使用 DNS 进行 Consul 服务发现 的相关文章

随机推荐

  • WildFly 8.2.0、使用反向代理的 JBossWS 生成不正确的 httpssoap:address

    我的设置是 https 上的 apache 服务器 充当在端口 8080 上响应的 WildFly 8 2 0 的反向代理 Web 服务是通过注释使用自下而上的方法创建的 生成的soap address 没有正确的协议或端口 我已修改sta
  • 添加到 HashMap 中的列表的快捷方式

    我经常需要获取一个对象列表 并根据对象中包含的值将它们分组到一个 Map 中 例如 按国家 地区获取用户和组列表 我的代码通常如下所示 Map
  • 使用 NodeJS、Express 和 Passport-ldapauth 进行 LDAP 身份验证

    我在使用标题中提到的工具 应用程序对 Active Directory 服务器进行身份验证时遇到问题 我正在使用测试AD环境发现here http www forumsys com tutorials integration how to
  • 仅使用 mod_rewrite 重定向主页

    我有一个需要重定向的网站 但我不能只重定向 目录 因为服务器上的文件夹中还有其他网站 这样做也会重定向它们 不好 因此 我的 htaccess 文件包含一堆针对各个 HTML 页面的 301 重定向 并且这些文件工作得很好 但我需要重定向主
  • 使用 Powershell 添加 IIS 8.5 自定义日志记录字段

    带有 IIS 8 5 的 Windows Server 2012 R2 允许使用增强型日志记录自定义日志字段 http www iis net learn get started whats new in iis 85 enhanced l
  • 获取Google云端硬盘文件下载URL

    继你好世界应用程序 https developers google com picker docs 并使用文件选择器 我可以获得谷歌驱动器文件信息 我想在我的网络应用程序中获取该文件 它是一个二进制文件 的下载网址 有什么办法可以用新的 j
  • 在ubuntu内核中启用cgroup cpu实时运行时

    我正在尝试在 Ubuntu 18 04 上运行的 docker 容器中使用实时调度 我已经按照给定的方法安装了实时内核here https stackoverflow com questions 51669724 install rt li
  • 将第一个数据证书导入 ColdFusion

    我尝试使用 keytool 将证书从 First Data 导入到我的 ColdFusion 9 设置中 如下所示 keytool importcert keystore MYCF9Dir runtime jre lib security
  • Angular 链接函数:$Scope 与 Scope

    在我在教程中看到的角度指令中 link function scope element attrs or link function scope element attrs 现在我知道 意味着角度服务 这在这里成立吗 scope 和scope
  • c++11 为什么这个移动构造函数不起作用?

    我已经编写了下面发布的代码 我希望能够在实例之间移动向量的内容LargeClass 正在使用移动构造函数 但我只得到副本而不是移动 为什么移动语义在这里没有按预期工作 Code include
  • Git 会删除空文件夹吗? [复制]

    这个问题在这里已经有答案了 我已提交一个项目并将其推送到我的 GitHub 帐户 该项目包含以下部分文件结构 server conf some files java lib java 和 lib 文件夹为空 从 GitHub 下载我的项目时
  • 在 C++ 中返回对象的最佳方法?

    我对 C 很菜鸟 返回对象的更好方法是什么 我来自脚本世界 其中对象始终是引用 并且正在尝试实现相同的概念 我的基础是C 中什么时候通过引用传递 什么时候通过指针传递 https stackoverflow com questions 36
  • Git Push 远程:致命:包超出允许的最大大小

    我接到了一个大项目 客户想将其添加到github 我是一点一点添加的 然后发生的事情是我太贪心了 一次添加了太多文件 现在 无论我尝试什么 我都会不断收到此错误 我怎样才能解决这个问题 我试图回滚 但也许我做错了 git push Ente
  • 为一个对象上的每个元组元素调用函数,无需递归

    我有一个类对象A可以用不同的类型调用 并在每次调用时返回更改后的 self 为了这个问题的目的A will do struct A A call const int A call const string s a 所以我有一个未知类型的元组
  • 可以让 ReSharper 在 Intellisense 中显示异常吗?

    我很喜欢 ReSharper 提供的重写智能感知行为 但是 我似乎无法让它显示异常 任何带有
  • ubuntu 的 CSS 更少(并且自动编译)? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我尝试过 simples 但现在 l
  • 在 C 中使用 lapack 计算矩阵的逆

    我希望能够计算一般的逆NxN使用 lapack 在 C C 中编写矩阵 我的理解是 在 lapack 中进行反转的方法是使用dgetri函数 但是 我无法弄清楚它的所有参数应该是什么 这是我的代码 void dgetri int N dou
  • createElement variable2

    我需要在 SharePoint 2010 中创建导航 Web 部件 我使用表格来显示 SharePoint 列表中的项目 该表格的结构如下 Column1 要显示的文本 标题 第 2 列 URL 标题链接 我似乎无法弄清楚如何实现创建 a
  • 我可以在 Orchard CMS 中使用我的 Ninject .NET 项目吗?

    我正在使用 Orchard CMS 创建一个网站 并且有一个用 Ninject 编写的外部 NET 项目 用于依赖注入 我想将其与 Orchard CMS 中的模块一起使用 我知道 Orchard 使用 Autofac 进行依赖注入 这给我
  • Nodejs 上使用 DNS 进行 Consul 服务发现

    TL DR 大家好 我试图从用 Express 编写的 NodeJS 前端调用 NodeJS 后端微服务 通过Consul https www consul io DNS接口 https www consul io intro gettin