.net core 3.1 基于ocelot实现API网关

Ocelot是一个用.NET Core实现的开源API网关,它功能强大,包括了:路由、请求聚合、服务发现、认证、鉴权、限流熔断,缓存等。

接下来,会使用ocelot 结合consul ,polly ,cachemanager 实现负载均衡,服务发现,限流熔断和缓存功能。(本文只做记录,就直接贴完整代码,不分别测试了)

新建ApiGateWay项目,nuget安装Ocelot,Ocelot.Provider.Consul,Ocelot.Provider.Polly,Ocelot.Cache.CacheManager

注:我这里用的ocelot版本是14.1.0 ,高版本请参考官方文档调整哈

 

 

新增ocelot.json,配置相关参数

{
  // 转发路由,数组中的每个元素都是某个服务的一组路由转发规则
  "ReRoutes": [
    {
      "ServiceName": "Summer.Webapi", //对应consul配置的ServiceName
      // Uri方案,http、https
      "DownstreamScheme": "http",
      // 下游(服务提供方)服务路由模板
      "DownstreamPathTemplate": "/api/{path}",
      // 上游(客户端,服务消费方)请求路由模板
      "UpstreamPathTemplate": "/Summer/{path}",
      "UpstreamHttpMethod": [ "Get", "Post" ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin" //轮询     
      },
      "UseServiceDiscovery": true,
      "RateLimitOptions": {
        "ClientWhitelist": [ "admin" ], // 白名单
        "EnableRateLimiting": true, // 是否启用限流
        "Period": "1m", // 统计时间段:1s, 5m, 1h, 1d
        "PeriodTimespan": 15, // 多少秒之后客户端可以重试
        "Limit": 2 // 在统计时间段内允许的最大请求数量
      },
      "QoSOptions": {
        "ExceptionsAllowedBeforeBreaking": 2, // 允许多少个异常请求
        "DurationOfBreak": 15000, // 熔断的时间,单位为毫秒
        "TimeoutValue": 5000 // 如果下游请求的处理时间超过多少则视如该请求超时
      },
      "FileCacheOptions": { // cache response data - ttl: 10s   10秒内相同url请求直接返回缓存数据
        "TtlSeconds": 10,
        "Region": ""
      }
    }
  ],
  // 全局配置,此节点的配置会覆盖ReRoutes,可以在这里设置一些通用的配置
  "GlobalConfiguration": {
    "ReRouteIsCaseSensitive": false,
    "ServiceDiscoveryProvider": {
      "Host": "localhost",
      "Port": 8500,
      "Type": "Consul" //由Consul提供服务发现
    },
    "RateLimitOptions": {
      "DisableRateLimitHeaders": false, // Http头  X-Rate-Limit 和 Retry-After 是否禁用
      "QuotaExceededMessage": "Too many requests, are you OK?", // 当请求过载被截断时返回的消息
      "HttpStatusCode": 999, // 当请求过载被截断时返回的http status
      "ClientIdHeader": "client_id" // 用来识别客户端的请求头,默认是 ClientId
    }
  }
}

在Startup.cs 中新增如下代码:

public void ConfigureServices(IServiceCollection services)
        {
            var config = new ConfigurationBuilder().AddJsonFile("ocelot.json").Build();
            services.AddOcelot(config)
                .AddCacheManager(x =>
                {
                    x.WithDictionaryHandle();
                })
                .AddConsul().AddPolly();
        }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseOcelot().Wait();
        }

配置完ApiGateway,接下来配置Webapi,每个Webapi都新增服务注册,通过consul服务发现并定时做健康检测

新增consul服务注册扩展类库 ConsulBuilder,方便各个项目引用,接下来直接贴代码:

// consul服务注册扩展类
    public static class ConsulRegistrationExtensions
    {
        public static void AddConsul(this IServiceCollection service)
        {
            // 读取服务配置文件
            var config = new ConfigurationBuilder().AddJsonFile("consulconfig.json").Build();
            service.Configure<ConsulServiceOptions>(config);
        }

        public static IApplicationBuilder UseConsul(this IApplicationBuilder app)
        {
            // 获取主机生命周期管理接口
            var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();

            // 获取服务配置项
            var serviceOptions = app.ApplicationServices.GetRequiredService<IOptions<ConsulServiceOptions>>().Value;

            // 服务ID必须保证唯一
            serviceOptions.ServiceId = Guid.NewGuid().ToString();

            var consulClient = new ConsulClient(configuration =>
            {
                //服务注册的地址,集群中任意一个地址
                configuration.Address = new Uri(serviceOptions.ConsulAddress);
            });

            // 获取当前服务地址和端口,配置方式
            var uri = new Uri(serviceOptions.ServiceAddress);

            // 节点服务注册对象
            var registration = new AgentServiceRegistration()
            {
                ID = serviceOptions.ServiceId,
                Name = serviceOptions.ServiceName,// 服务名
                Address = uri.Host,
                Port = uri.Port, // 服务端口
                Check = new AgentServiceCheck
                {
                    // 注册超时
                    Timeout = TimeSpan.FromSeconds(5),
                    // 服务停止多久后注销服务
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
                    // 健康检查地址
                    HTTP = $"{uri.Scheme}://{uri.Host}:{uri.Port}{serviceOptions.HealthCheck}",
                    // 健康检查时间间隔
                    Interval = TimeSpan.FromSeconds(10),
                }
            };

            // 注册服务
            consulClient.Agent.ServiceRegister(registration).Wait();

            // 应用程序终止时,注销服务
            lifetime.ApplicationStopping.Register(() =>
            {
                consulClient.Agent.ServiceDeregister(serviceOptions.ServiceId).Wait();
            });

            return app;
        }
    }
// Consul配置模型类
    public class ConsulServiceOptions
    {
        // 服务注册地址(Consul的地址)
        public string ConsulAddress { get; set; }

        // 服务ID
        public string ServiceId { get; set; }

        // 服务名称
        public string ServiceName { get; set; }

        // 健康检查地址
        public string HealthCheck { get; set; }

        //站点地址
        public string ServiceAddress { get; set; }
    }

在Webapi 项目中引用ConsulBuilder类库,然后在Startup.cs 中新增如下代码:

 

 

 

 

 

 新增consulconfig.json ,属性设置为始终复制

{
  "ConsulAddress": "http://127.0.0.1:8500", //consul 服务器地址
  "ServiceName": "Summer.Webapi", //服务名称,ApiGateway中配置的ServiceName对应这里
  "HealthCheck": "/Health", //健康检查地址
  "ServiceAddress": "http://localhost:58420"  //webapi 地址
}

假如要启动多个webapi,拷贝代码,将ServiceAddress 改为不同的端口,然后使用命令行启动

PS D:\work\demo\core\SummerCore3.1\Summer.WebApi\bin\Debug\netcoreapp3.1> dotnet .\Summer.Webapi.dll --urls "http://loca
lhost:58420"

配置好后,开始运行,

先开启consul:  consul.exe agent -dev

然后启动多个webapi 

访问localhost:8500 ,可以看到已经服务发现两个webapi

 

测试一下是否正常运行,访问http://localhost:58420/api/user/userlist

 

 

 运行ApiGateway 

PS D:\work\demo\core\SummerCore3.1\Summer.ApiGateway\bin\Debug\netcoreapp3.1> dotnet .\Summer.ApiGateway.dll --urls "htt
p://localhost:7000"

访问http://localhost:7000/Summer/user/userlist

 

 

 可以看到,API网关已经正常映射到localhost:58420的Webapi

 

其他效果,例如负载均衡,限流熔断可以自行结合配置参数做测试

 

本文代码主要参考zilor老师公开课源码

posted @ 2020-04-02 00:02  redo  阅读(3084)  评论(7编辑  收藏  举报