欢迎光临
个人技术文档整理

.Net Core 网关Ocelot基础使用(一)

网关(Gateway)

https://github.com/ThreeMammals/Ocelot

网关(Gateway)在微服务架构中至关重要,可以将其理解为是外部客户端(前端、MVC后台等调用方)与后台服务的连接点,通过这层可以做统一的处理,比如路由、身份认证和授权、服务治理等;

网关的好处:

  • 统一入口,调用方(客户端)不在为调哪个服务而头大,统一入口即可,由网关路由到对应后台服务;
  • 统一处理公共逻辑,比如认证和授权,避免相同逻辑多处实现,易于维护;
  • 对后台服务可以做负载均衡,根据指定的负载算法找到合适的后台服务调用,而这些细节调用方都不用理会,只管调就行啦;
  • 初步过滤非法请求,可以根据配置的请求规则过滤掉非法请求;
  • 屏蔽各服务真实地址,间接保证各服务的安全

网关带来的问题:

  • 在请求过程中,多增加了一层(网关)对请求进行处理,会消耗一些性能;
  • 高并发场景,对网关性能要求高,需要开发人员要有足够的能力处理;

整体来看,在微服务架构中,网关带来的便捷和好处肯定大于自身带来的问题,所以不必纠结于此。

目前常用的网关有Kong、Tyk、Zuul、Ambassador、Ocelot等,而在.Net中比较火的是Ocelot和Kong,接下来就以Ocelot为主展开来聊聊。

 

引入Ocelot

Ocelot

使用 Ocelot

  • 新建.Net Core MVC项目, 在Program.cs文件中引用ocelot.json配置文件

     public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureAppConfiguration((hostingContext, config) =>
                    {
                        config.AddJsonFile("ocelot.json", optional: true, reloadOnChange: true)
                            .AddJsonFile($"ocelot.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true);
                    })
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>(); 
                    });
  • 在Startup.cs中配置ocelot
     public void ConfigureServices(IServiceCollection services)
            { 
                #region 注册 Ocelot 网关服务
                services.AddOcelot();
                #endregion
    
            }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
     
                //使用 Ocelot 网关服务
                app.UseOcelot();
            }

ocelot.json配置说明

{
  "GlobalConfiguration": {
    "BaseUrl": "http://127.0.0.1:9099" //当前ocelot站点的域名
  },
  "ReRoutes": [
    {
      //万能模板:"/{url}"  ;万能模板的优先级最低,只要有其它的路由模板,其它的路由模板则会优先生效
      "UpstreamPathTemplate": "/{url}", //上游请求地址模板
      "UpstreamHttpMethod": [ //上游请求方式
        "Get",
        "Post"
      ],
      "DownstreamPathTemplate": "/{url}", //下游跳转地址模板;将用户的请求 /post/1 转发到 localhost/api/post/1
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [ //下游服务的地址,如果使用LoadBalancer(负载均衡算法配置项)的话这里可以填多项
        {
          "Host": "appliance.abc.com.cn",
          "Port": 80
        }
      ]
    },
    {
      "UpstreamPathTemplate": "/post/{postId}", //上游请求地址模板
      "UpstreamHttpMethod": [ //上游请求方式
        "Get"
      ],
      "DownstreamPathTemplate": "/api/post/{postId}", //下游跳转地址模板;将用户的请求 /post/1 转发到 localhost/api/post/1
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [ //下游服务的地址,如果使用LoadBalancer(负载均衡算法配置项)的话这里可以填多项
        {
          "Host": "localhost",
          "Port": 51876
        }
      ],
      "RequestIdKey": "",
      //Ocelot可以对下游请求结果进行缓存 ,目前缓存的功能还不是很强大。它主要是依赖于CacheManager 来实现的
      "FileCacheOptions": {
        "TtlSeconds": 0,
        "Region": "" //Region是对缓存进行的一个分区,我们可以调用Ocelot的 administration API来移除某个区下面的缓存
      },
      "ReRouteIsCaseSensitive": false,
      "ServiceName": "",
      //服务质量与熔断
      "QoSOptions": {
        "ExceptionsAllowedBeforeBreaking": 0, //允许多少个异常请求
        "DurationOfBreak": 0, // 熔断的时间,单位为秒
        "TimeoutValue": 0 //如果下游请求的处理时间超过多少秒则自如将请求设置为超时
      },
      // 将决定负载均衡的算法:LeastConnection–将请求发往最空闲的那个服务器;RoundRobin–轮流发送;NoLoadBalance–总是发往第一个请求或者是服务发现
      "LoadBalancer": "LeastConnection",
      //对请求进行限流可以防止下游服务器因为访问过载而崩溃
      "RateLimitOptions": {
        "ClientWhitelist": [], //白名单
        "EnableRateLimiting": false, //是否启用限流
        "Period": "5m", //1s, 5m, 1h, 1d
        "PeriodTimespan": 0, //多少秒之后客户端可以重试
        "Limit": 0, //在统计时间段内允许的最大请求数量
 
        //在 GlobalConfiguration下我们还可以进行以下配置
        "DisableRateLimitHeaders": false, //Http头  X-Rate-Limit 和 Retry-After 是否禁用
        "QuotaExceededMessage": "Customize Tips!", //当请求过载被截断时返回的消息
        "HttpStatusCode": 999, //当请求过载被截断时返回的http status
        "ClientIdHeader": "Test" //用来识别客户端的请求头,默认是 ClientId
      },
      //鉴权认证
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "",
        "AllowedScopes": [] //这里的Scopes将从当前 token 中的 claims中来获取,我们的鉴权服务将依靠于它来实现 。当前路由的下游API需要某个权限时,我们需要在这里声明 。和oAuth2中的scope意义一致。
      },
      //我们通过认证中的AllowedScopes 拿到claims之后,如果要进行权限的鉴别需要添加以下配置
      "RouteClaimsRequirement": {
        "UserType": "registered" //当前请求上下文的token中所带的claims如果没有 name=”UserType” 并且 value=”registered” 的话将无法访问下游服务。
      },
      "HttpHandlerOptions": {
        "AllowAutoRedirect": true,
        "UseCookieContainer": true,
        "UseTracing": true
      },
      "UseServiceDiscovery": false,
 
      //在请求头转化这里Ocelot为我们提供了两个变量:BaseUrl和DownstreamBaseUrl。
      //BaseUrl就是我们在GlobalConfiguration里面配置的BaseUrl,
      //DownstreamBaseUrl是下游服务的Url
      //请求头转化;比如我们将客户端传过来的Header中的Location值value1改为BaseUrl后传给下游
      "UpstreamHeaderTransform": {
        "Location": "value1, {BaseUrl}"
      },
      //我们同样可以将下游Header中的Location再转为DownstreamBaseUrl之后再转给客户端。
      "DownstreamHeaderTransform": {
        "Location": "{DownstreamBaseUrl}, {BaseUrl}"
      },
      //Claims转化: 例如:name=”sub” value=”usertypevalue|useridvalue”
      //Ocelot为我们提供的功能分为三段
      //第一段是Claims[sub],很好理解[] 里面是我们的claim的名称。
      //第二段是  > 表示对字符串进行拆分, 后面跟着拆分完之后我们要取的那个数组里面的某一个元素用 value[index]来表示,取第0位元素也可以直接用value。
      //第三段也是以 > 开头后面跟着我们的分隔符,在我们上面的例子分隔符是 |
      "AddHeadersToRequest": { // Claims to Headers
        "CustomerId": "Claims[sub] > value[1] > |" //Claims 为sub;对value进行|拆分;取索引为1的值
      },
      "AddClaimsToRequest": { //Claims to Claims
        "UserType": "Claims[sub] > value[0] > |", //Claims 为sub;对value进行|拆分;取索引为0的值
        "UserId": "Claims[sub] > value[1] > |" //Claims 为sub;对value进行|拆分;取索引为1的值
      },
      "AddQueriesToRequest": { // Claims to Query String
        "LocationId": "Claims[LocationId] > value" //Claims 为LocationId;取value的值
      }
    }
  ]
}

 

 

赞(1)