Ocelot 發現服務總是失敗的解決辦法


一、問題 

今天用 Ocelot + Consul 項目,進行微服務實踐,可是 Ocelot 的發現服務總是失敗。

 

二、分析問題

2.1、分析方法:

      不得不下載了 Ocelot 源碼進行追蹤排查。

 

2.2、源碼分析

源碼對應文件為 Ocelot-develop\src\Ocelot.Provider.Consul\Consul.cs

public async Task<List<Service>> Get()
        {
            var queryResult = await _consul.Health.Service(_config.KeyOfServiceInConsul, string.Empty, true);

            var services = new List<Service>();

            foreach (var serviceEntry in queryResult.Response)
            {
                if (IsValid(serviceEntry))
                {
                    var nodes = await _consul.Catalog.Nodes();
                    if (nodes.Response == null)
                    {
                        services.Add(BuildService(serviceEntry, null));
                    }
                    else
                    {
                        var serviceNode = nodes.Response.FirstOrDefault(n => n.Address == serviceEntry.Service.Address);
                        services.Add(BuildService(serviceEntry, serviceNode));
                    }
                }
                else
                {
                    _logger.LogWarning($"Unable to use service Address: {serviceEntry.Service.Address} and Port: {serviceEntry.Service.Port} as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0");
                }
            }

            return services.ToList();
        }

        private Service BuildService(ServiceEntry serviceEntry, Node serviceNode)
        {
            return new Service(
                serviceEntry.Service.Service,
                new ServiceHostAndPort(serviceNode == null ? serviceEntry.Service.Address : serviceNode.Name, serviceEntry.Service.Port),
                serviceEntry.Service.ID,
                GetVersionFromStrings(serviceEntry.Service.Tags),
                serviceEntry.Service.Tags ?? Enumerable.Empty<string>());
        }

  

第3行,獲得已注測的健康的服務;第11行,獲得已注冊 Consul 節點的電腦。

第18行,如果當前服務與Consul節點是在同一台電腦上,則返回電腦節點 ServiceNode

第31行中的 BuildSevrice 函數完成最后的 service信息創建, 

第35行  如果找到了 ServiceNode,則返回對應的電腦名字 hostname,  如果沒找到則返回對應的 ipAddress.

就是說:服務和Consul 在同一台電腦上則返回hostname , 在不同電腦上則返回服務所在電腦的 ipAddress. 

 

 

2.3 問題根源:

是 Consul 注冊時,hostname 參數由 -node參數指定。

當服務和 Consul 在同一台電腦上時,Ocelot 最終變換成  http://hostname:port/url  的形式進行訪問。

 

三、解決問題

3.1、Consul 的配置參數注意事項

注意而 hostname 是由Consul 的 -node 參數指定的!

所以,

consul agent -server -datacenter=dc1 -bootstrap  -data-dir ./data  -ui  -node=n1 -bind 192.168.11.211 -client=0.0.0.0

  其中 -node=n1 是一個大坑。應該略去,系統會自己設置為自己的主機名字 hostname。

所以我實際上用了配置文件 node1.json,也是去掉了該項。

{
  "datacenter": "dc1",
  "data_dir": "c:/data/app/consul/node1",
  "log_level": "INFO",
  "server": true,
  "ui": true,
  "bind_addr": "192.168.11.211",
  "client_addr": "127.0.0.1",
  "advertise_addr": "192.168.11.211",
  "bootstrap_expect": 1,
  "ports":{
    "http": 8500,
    "dns": 8600,
    "server": 8300,
    "serf_lan": 8301,
    "serf_wan": 8302
    }
}

然后調用方式:

consul agent -config-dir=e:/consul/node1.json

然后用另一台服務器加入 

consul agent -data-dir /tmp/consul  -bind=192.168.11.246 -join 192.168.11.248

 

這時 Consul 的 web 管理界面為:

 

它會自動帶上主機名: HNSever 和 LGB-PC

在這兩台電腦上注冊服務后,最終會變成  http://hostname:port/ + url 模板 的形式訪問。

 

3.2、hostname 不能訪問問題修改

如果 http://hostname:port/url,還是返回   錯誤代碼 HTTP ERROR 500  訪問失敗。就是  hostname 不能轉換為 ipaddress.

所以需要修改 windows 的 hosts 文件

打開系統目錄:c:/windows/system32/drivers/etc找到hosts文件,打開hosts文件並在最后面添加一條記錄

例如:

192.168.11.248  HNServer

192.168.11.211  LGB-PC

然后就能正常的發現服務了!

 

3.3 附上 Ocelot 的配置文件  ocelot.json 

{
  "ReRoutes": [
    {
      "DownstreamPathTemplate": "/api/{url}",
      "DownstreamScheme": "http",
      "ServiceName": "ProductService",
      "UseServiceDiscovery": true,
      "LoadBalancerOptions": {
        "Type": "LeastConnection"
      },
      "UpstreamPathTemplate": "/test/{url}",
      "UpstreamHttpMethod": [ "Post", "Get" ]
    }
  ],

  "GlobalConfiguration": {
    "ServiceDiscoveryProvider": {
      "Host": "localhost",
      "Port": 8500
    }
  }
}

 

 

四、參考

Ocelot + Consul實踐

.net core Ocelot Consul 實現API網關 服務注冊 服務發現 負載均衡

netcore ocelot api網關結合consul服務發現

Windows下主機名和IP映射設置

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM