• .NET Core Consul Ocelot Demo


    本地环境

    Win10

    虚拟机 CentOS7

    CentOS中提前安装好 docker-compose 和 dotnet 运行环境

    WebAPI (.NET 5.0):

      NuGet:  

        Consul  (1.6.10.4)

    APIGateway(.NET 5.0):

      NuGet:

        Ocelot (17.0.0)

        Ocelot.Provider.Consul (17.0.0)

    一、Consul  集群

    使用 docker-compose.yaml 快速部署一个 Consul  集群

    version: '3'
    
    services:
      Consul-1: 
        image: consul
        command: agent -server -client=0.0.0.0 -bootstrap-expect=3 -node=Consul-1 -data-dir=/data
        volumes:
          - ./Consul-1:/data
      Consul-2:
        image: consul
        command: agent -server -client=0.0.0.0 -retry-join=Consul-1 -node=Consul-2 -data-dir=/data
        volumes:
          - ./Consul-2:/data
        depends_on:
          - Consul-1
      Consul-3:
        image: consul
        command: agent -server -client=0.0.0.0 -retry-join=Consul-1 -node=Consul-3 -data-dir=/data
        volumes:
          - ./Consul-3:/data
        depends_on:
          - Consul-1
      Consul-4:
        image: consul
        command: agent -client=0.0.0.0 -retry-join=Consul-1 -ui -node=Consul-4 -data-dir=/data  
        ports:
          - 8500:8500
        volumes:
          - ./Consul-4:/data
        depends_on:
          - Consul-2
          - Consul-3

    docker-compose up 

    启动

    win10 中访问 http://CentOSIP:8500/

     二、WebAPI 

    定义两个控制器

    using Microsoft.AspNetCore.Mvc;
    
    namespace WebAPI.Controllers
    {
        [Route("health")]
        [ApiController]
        public class healthController : Controller
        {
            public IActionResult Get() => Ok("ok");
        }
    }
    
    
    
    
    using Microsoft.AspNetCore.Mvc;
    
    namespace WebAPI.Controllers
    {
        [Route("api/Demo")]
        [ApiController]
        public class DemoController : Controller
        {
            [HttpGet]
            public IActionResult Get(string id)
            {
                return Json(new
                {
                    id = id
                });
            }
    
            [HttpPost]
            public IActionResult Post(UserDto userDto)
            {
                return Json(new
                {
                    UserName = userDto.UserName,
                    UserId = userDto.UserId
                });
            }
        }
    }

    注册 Consul  

    appsettings.json

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information"
        }
      },
      "AllowedHosts": "*",
      "Consul": {
        "ServiceId": "11111111111111",
        // 当前项目的名字,如果部署多个实例,该名字必须一致
        "ServiceName": "WebAPI",
        // 当前项目部署后的IP地址
        "ServiceIP": "192.168.214.129",
        // 当前项目部署后的端口号
        "ServicePort": 8001,
        // 当前项目部署后 Consul 调用该接口判断服务是否健康
        "ServiceHealthCheck": "http://192.168.214.129:8001/health",
    
        // Consul 的地址
        "ConsulAddress": "http://192.168.214.129:8500"
      }
    }

    安装 appsettings.json 中的 Consul 节点定义一个类型

    namespace WebAPI
    {
        public class ServiceEntity
        {
            public string ServiceId { get; set; }
            public string ServiceName { get; set; }
            public string ServiceIP { get; set; }
            public int ServicePort { get; set; }
            public string ServiceHealthCheck { get; set; }
            public string ConsulAddress { get; set; }
        }
    }

    Startup

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        ServiceEntity serviceEntity = new ServiceEntity
        {
            ServiceId = Configuration["Consul:ServiceId"],
            ServiceIP = Configuration["Consul:ServiceIP"],
            ServiceName = Configuration["Consul:ServiceName"],
            ServicePort = Convert.ToInt32(Configuration["Consul:ServicePort"]),
            ServiceHealthCheck = Configuration["Consul:ServiceHealthCheck"],
            ConsulAddress = Configuration["Consul:ConsulAddress"]
        };
        app.UseConsul(lifetime, serviceEntity);
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

    ConsulBuilderExtensions.cs

    public static class ConsulBuilderExtensions
    {
        public static IApplicationBuilder UseConsul(this IApplicationBuilder app, IHostApplicationLifetime lifetime, ServiceEntity serviceEntity)
        {
            var consulClient = new ConsulClient(x =>
            {
                x.Address = new Uri(serviceEntity.ConsulAddress);
            });
    
            var registration = new AgentServiceRegistration()
            {
                ID = Guid.NewGuid().ToString(),
                Name = serviceEntity.ServiceName,// 服务名
                Address = serviceEntity.ServiceIP, // 服务绑定IP
                Port = serviceEntity.ServicePort, // 服务绑定端口
                Check = new AgentServiceCheck()
                {
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册
                    Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔
                    HTTP = serviceEntity.ServiceHealthCheck,//健康检查地址
                    Timeout = TimeSpan.FromSeconds(5)
                }
            };
    
            // 服务注册
            consulClient.Agent.ServiceRegister(registration).Wait();
    
            // 应用程序终止时,服务取消注册
            lifetime.ApplicationStopping.Register(() =>
            {
                consulClient.Agent.ServiceDeregister(registration.ID).Wait();
            });
            return app;
        }
    }

    代码部分就完成了,打包,发布到 CentOS中

     WebAPI1 和 WebAPI2 各放一份

     其中 WebAPI2 中的 appsettings.json 中的 ServicePort 和 ServiceHealthCheck 中的端口号修改一下,两个实例启动的时候 WebAPI1 会占用

    dotnet WebAPI.dll --urls="http://*:8001"
    dotnet WebAPI.dll --urls="http://*:8002"

    启动两个 WebAPI 实例

     

     启动完成后过稍等片刻 

    等待的时间通过下面这句代码控制

    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), //服务启动多久后注册

     

     浏览器中验证一下两个节点是否 OK

    三、网关

    新建一个 WebAPI项目

    添加一个 Ocelot.json 配置文件

    {
      "Routes": [
        {
          "UpstreamPathTemplate": "/{url}",
          "UpstreamHttpMethod": [ "Get", "Post", "Put" ],
    
          "DownstreamPathTemplate": "/{url}",
          "DownstreamScheme": "http",
          "ServiceName": "WebAPI",
          "LoadBalancerOptions": {
            "Type": "LeastConnection"
          }
        }
      ],
      "GlobalConfiguration": {
        "ServiceDiscoveryProvider": {
          "Scheme": "http",
          "Host": "192.168.214.129",
          "Port": 8500,
          "Type": "PollConsul",
          "PollingInterval": 100 
        }
      }
    }

     Program.cs

    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Hosting;
    
    namespace APIGateway
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                CreateHostBuilder(args).Build().Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    })
                    .ConfigureAppConfiguration(configure => {
                        configure.AddJsonFile("Ocelot.json");
                    });
        }
    }

    StartUp.cs

    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Ocelot.DependencyInjection;
    using Ocelot.Middleware;
    using Ocelot.Provider.Consul;
    
    namespace APIGateway
    {
        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddOcelot().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();
            }
        }
    }

     只需要这么多就够了,其他的都可以删掉

    发布后部署到CentOS中

    dotnet APIGateway.dll --urls="http://*:9001"

    启动网关

     

     浏览器通过网关访问 某个 WebAPI 的实例

    Demo中通过 Consul 实现网关与 WebAPI实例 之间的解耦 

    网关不停的轮询从 Consul 中获取 WebAPI可用的实例

    只要 Consul  中还有一个 WebAPI的实力,整个服务都是OK的

  • 相关阅读:
    OpenLayers调用arcgis server发布的地图服务
    在线实用网址
    ArcGlobe点击IGlobeServerLayer图层读取信息
    vs2012编译出错“LC.exe”已退出解决方法
    DataTable反向模糊匹配查找语法
    PyCharm如何删除工程项目
    mysql错误日志目录
    下载HTMLTestRunner 地址
    python 单元测试之初次尝试
    cmd 运行 python
  • 原文地址:https://www.cnblogs.com/ansheng/p/16035028.html
Copyright © 2020-2023  润新知