.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的

posted @   乔安生  阅读(170)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示