zoukankan      html  css  js  c++  java
  • .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:workdemocoreSummerCore3.1Summer.WebApiinDebug etcoreapp3.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:workdemocoreSummerCore3.1Summer.ApiGatewayinDebug etcoreapp3.1> dotnet .Summer.ApiGateway.dll --urls "htt
    p://localhost:7000"

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

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

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

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

  • 相关阅读:
    MATLAB01
    Diffie-Hellman 密钥交换
    古典密码
    正则表达式
    装饰器初析
    进制转换的栈实现
    Log4j(异常日志)
    2018/6/6
    2018.1.1T19B3-u4
    2018.1.1T19-B3-U3jiangyi
  • 原文地址:https://www.cnblogs.com/redo/p/12616975.html
Copyright © 2011-2022 走看看