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老师公开课源码

  • 相关阅读:
    《大话数据结构》第1章 数据结构绪论 1.2 你数据结构怎么学的?
    伍迷七八月新浪微博集锦
    《大话数据结构》第9章 排序 9.7 堆排序(下)
    《大话数据结构》第3章 线性表 3.8.2 单链表的删除
    《大话数据结构》第9章 排序 9.5 直接插入排序
    《大话数据结构》第9章 排序 9.8 归并排序(上)
    《大话数据结构》第2章 算法基础 2.9 算法的时间复杂度
    《大话数据结构》第1章 数据结构绪论 1.1 开场白
    《大话数据结构》第9章 排序 9.1 开场白
    [AWS] Assign a public IP address to an EC2 instance after launched
  • 原文地址:https://www.cnblogs.com/redo/p/12616975.html
Copyright © 2011-2022 走看看