首页 > 其他 > 详细

20210526 ocelot + consul 集群 调用服务无法访问下游填坑

时间:2021-05-31 12:11:27      阅读:81      评论:0      收藏:0      [点我收藏+]

1 环境准备

vm下准备3台windows虚拟机  192.168.8.220 , 192.168.8.221 , 192.168.8.222

2 consul集群(2个server+1个client)

IP220电脑 consul agent -server -ui -bootstrap-expect 2 -data-dir data -node Server01 -bind 192.168.8.220 -client 0.0.0.0 &

IP221电脑 consul agent -server -ui -bootstrap-expect 2 -data-dir data -node Server01 -bind 192.168.8.221 -client 0.0.0.0 &   然后执行 consul join 192.168.8.220

IP222电脑 consul agent -ui -data-dir data -node Server03  -bind 192.168.8.222 -client 0.0.0.0 &  然后执行 consul join 192.168.8.220

这样集群就算完成了  具体consul的详细配置请自行查阅文档

3 编码阶段

3.1 ocelot网关,新建一个API的网关项目,结构如下

技术分享图片

startup.cs 文件

public void ConfigureServices(IServiceCollection services)
{
  services.AddOcelot(Configuration).AddConsul();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  app.UseOcelot().Wait();

}

program.cs 文件

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args).ConfigureAppConfiguration((host, config) =>
{
  config.AddJsonFile("ocelot.json");
}).ConfigureWebHostDefaults(webBuilder =>
{
  webBuilder.UseStartup<Startup>();
});

3.2 新建api服务,结构如下

技术分享图片

startup.cs 文件

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{

  //注入consul
  Configuration.ConsulRegister();
}

appsettings.json 文件

"Consul": {
"Address": "http://127.0.0.1:8500",
"DataCenter": "dc1",
"ServiceName": "Api01"
}

ConsulConfigurationEx.cs 文件

public static void ConsulRegister(this IConfiguration configuration, IApplicationLifetime lifetime)
{

  ConsulClient client = new ConsulClient(
    (ConsulClientConfiguration c) =>
    {
      c.Address = new Uri(configuration["Consul:Address"]); //Consul服务中心地址
      c.Datacenter = configuration["Consul:DataCenter"]; //指定数据中心,如果未提供,则默认为代理的数据中心。
    }
    );
  Console.WriteLine("IP:" + configuration["ip"].ToString());
  String ip = configuration["ip"];//部署到不同服务器的时候不能写成127.0.0.1或者0.0.0.0,因为这是让服务消费者调用的地址
  Console.WriteLine("port:" + configuration["port"].ToString());
  Int32 port = Int32.Parse(configuration["port"]);

  var registration = new AgentServiceRegistration()
  {
    ID = Guid.NewGuid().ToString(), //服务编号,不可重复
    Name = configuration["Consul:ServiceName"], //服务名称
    Port = port, //本程序的端口号
    Address = ip, //本程序的IP地址
    Check = new AgentServiceCheck()
    {
      DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(10), //服务停止后多久注销
      Interval = TimeSpan.FromSeconds(5), //服务健康检查间隔
      Timeout = TimeSpan.FromSeconds(5), //检查超时的时间
      HTTP = $"http://{ip}:{port}/ConsulHealth/Get",//健康检查地址, //检查的地址
    }
  };

  //注册
  client.Agent.ServiceRegister(registration).ConfigureAwait(true);

  //应用程序关闭时候
  lifetime.ApplicationStopping.Register(() =>
  {
    //正在注销
    client.Agent.ServiceDeregister(registration.ID).ConfigureAwait(true);
  });

}

 

ConsulHealthController.cs 文件

[ApiController]
[Route("[controller]/[action]")]
public class ConsulHealthController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("ok");
}
}

 

4 部署阶段

220电脑 启动服务 dotnet Service1.dll --urls="http://*:6001" --ip="192.168.8.220" --port=6001

221电脑 启动服务 dotnet Service2.dll --urls="http://*:6001" --ip="192.168.8.221" --port=6002

222电脑 启动网关 dotnet OcelotGateWay.dll --urls="http://*:3388" --ip="192.168.8.222" --port=3388

请求

http://192.168.8.222:3388/ConsulHealth/Get

技术分享图片

这样我们就算是成功了

 遇到几个难点,在部署consul集群时,如果指定了node节点名字,需要在系统hosts文件把对应的 ip和节点写上

如 192.168.8.220  Server01,如果没有指定节点,ocelot会使用电脑名字解析,原因就是ocelot源码处理了,

对应文件为 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>());
        }
 
本文借鉴资料
1 https://www.cnblogs.com/shanyou/p/6286207.html
2 https://www.cnblogs.com/citycomputing/p/12070909.html

 

20210526 ocelot + consul 集群 调用服务无法访问下游填坑

原文:https://www.cnblogs.com/tmacsjp/p/14814654.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!