首页 > 其他分享 >NetCore Ocelot

NetCore Ocelot

时间:2023-03-04 09:46:25浏览次数:38  
标签:ocelot return Ocelot NetCore public context new options

     Ocelot是一个用.NET Core实现并且开源的API网关,功能包括:路由,请求聚合,服务验证,鉴权,限流熔断,并内置了负载均衡器与Service Fabric,Buttefly Tracing集成。这些功能都只需要简单配置就可以完成。

    简单的ocelot是一堆asp.net core middleware组成的一个管道,当它拿到请求之后会用一个request builder来构造一个HttpRequestMessage发到下游的真实服务器,等下游的服务返回response之后再由一个middleware将它返回的HttpResponseMessage映射到HttpResponse上.

  

 

 

 


网关集群
只有一个网关是很危险的,也就是我们通常所将的单点,只要它挂了,所有的服务全挂。这显然无法达到高可用,所以我们也可以部署多台网关。当然这个时候再多台网关前,你还需要一台负载均衡器。

 

 

 


Consul 服务发现
在Ocelot已经支持简单的负载均衡功能,也就是当下游服务存在多个结点的时候,Ocelot能够承担起负载均衡的作用。但是它不提供健康检查,服务的注册也只能通过手动子配置文件里面添加完成。这个时候我们就可以用Consul来做服务发现,它能与Ocelot完美结合

 

 

 

 下面实战

ocelot配置信息, 这里ocelot.json是系统生成的,code中实现了多配置文件合并功能

 1、ocelot.consul.json

{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/{url}",
      "DownstreamScheme": "https",
      "DownstreamHttpMethod": "Get",
      "UpstreamHttpMethod": [ "Options", "Get", "Post", "Put", "Delete" ],
      "UpstreamPathTemplate": "/Ocelot/{url}",
      //"UpstreamHost": "localhost",//404 Not found
      "UseServiceDiscovery": true,
      "ServiceName": "serviceA",
      /*
      LeastConnection
      RoundRobin
      NoLoadBalance
      */
      "LoadBalancerOptions": {
        "Type": "CustomRandomLoadBalancer"
      },
      "QoSOptions": {
        "ExceptionsAllowedBeforeBreaking": 3,
        "DurationOfBreak": 10000, //ms
        "TimeoutValue": 10000 //ms,default 90s
      },
      "RateLimitOptions": {
        "ClientWhiteList": [ "NoLimitedAPI" ],
        "EnableRateLimiting": true,
        "Period": "10s", //1s, 5m, 1h, 1d
        "PeriodTimespan": 10, //retry after n second/seconds
        "Limit": 3
      },
      "authenticationoptions": {
        "authenticationproviderkey": "authenticationkey",
        "allowedscopes": []
      },
      //"routeclaimsrequirement": {
      //  "userrole": "admin"
      //},
      //"DownstreamHttpVersion": "",
      //"AddHeadersToRequest": {},
      //"AddClaimsToRequest": {},
      //"AddQueriesToRequest": {},
      //"RequestIdKey": "",
      //"FileCacheOptions": {
      //  "TtlSeconds": 10,
      //  "Region": "gatewaycacheregion"
      //},
      //"HttpHandlerOptions": {
      //  "AllowAutoRedirect": true,
      //  "UseCookieContainer": false,
      //  "UseTracing": true,
      //  "MaxConnectionsPerServer": 100
      //},
      //"DangerousAcceptAnyServerCertificateValidator": false,
      "Priority": 10 //priority
    }
  ]
}
ocelot.consul
 1 {
 2   "GlobalConfiguration": {
 3     "BaseUrl": "https://localhost:7000", //gateway public address
 4     "RequestIdKey": "OcRequestId",
 5     "RouteIsCaseSensitive": false,
 6     "ServiceDiscoveryProvider": {
 7       "Host": "127.0.0.1",
 8       "Port": 8500,
 9       "Type": "Consul",
10       "ConfigurationKey": "ApiGateway.Ocelot"
11     },
12     "RateLimitOptions": {
13       "ClientIdHeader": "IgnoreRateLimit", //request header key
14       "QuotaExceededMessage": "The requests has reached the quota.", //The customized prompt
15       "RateLimitCounterPrefix": "ocelotratelimit",
16       "DisableRateLimitHeaders": false,
17       "HttpStatusCode": 666
18     }
19   }
20 }
ocelot.global mutiple configuration merge

2、Add ocelot

1 builder.Services.AddOcelot()
2     .AddConsul()
3     .AddPolly();
4 
5 app.UseOcelot().Wait();
ocelot

3、添加自定义load balancer

1 builder.Services.AddOcelot()
2     .AddCustomLoadBalancer((serviceProvider, route, serviceDiscoveryProvider) => new CustomRandomLoadBalancer(serviceDiscoveryProvider.Get))
3     .AddConsul()
4     .AddPolly();
custom load balancer
 1     public class CustomRandomLoadBalancer : ILoadBalancer
 2     {
 3         private readonly Func<Task<List<Service>>> _services;
 4         private readonly Object _lock = new object();
 5         private int _index;
 6 
 7         public CustomRandomLoadBalancer(Func<Task<List<Service>>> services)
 8         {
 9             _services = services;
10         }
11 
12         public async Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext)
13         {
14            var services = await _services();
15             if (services == null)
16                 return new ErrorResponse<ServiceHostAndPort>(new ErrorInvokingLoadBalancerCreator(new Exception("Load balance algorithm error.")));
17             lock (_lock)
18             {
19                 if (services.Count == 1)
20                     return new OkResponse<ServiceHostAndPort>(services[0].HostAndPort);
21                 _index = new Random().Next(services.Count);
22                 return new OkResponse<ServiceHostAndPort>(services[_index].HostAndPort);
23             }
24         }
25 
26         public void Release(ServiceHostAndPort hostAndPort)
27         {
28         }
29     }
load balancer

4、添加中间件,设置特定header,避免限流

1 app.Use((httpContext, requestDelegate) =>
2 {
3     if (!httpContext.Request.Headers.TryGetValue("IgnoreRateLimit", out Microsoft.Extensions.Primitives.StringValues value))
4         httpContext.Request.Headers.Add("IgnoreRateLimit", "NoLimitedAPI");
5     return requestDelegate.Invoke(httpContext);
6 });
middleware

添加中间件另种方式

app.UseMiddleware<CustomMiddleware>(3);
middleware
 1    public class CustomMiddleware
 2     {
 3         private readonly RequestDelegate _requestDelegate;
 4         private Int32 _parameter { get; set; }
 5         public CustomMiddleware(RequestDelegate requestDelegate, Int32 parameter)
 6         {
 7             this._requestDelegate = requestDelegate;
 8             this._parameter = parameter;
 9         }
10 
11         public async Task InvokeAsync(HttpContext httpContext)
12         {
13             var argument = _parameter;
14             await _requestDelegate(httpContext);
15         }
16     }
custom middleware

5、集成identity server4

  identity server4 config 配置信息

 1     public class Config
 2     {
 3 
 4         public static IEnumerable<ApiScope> ApiScopes
 5             => new List<ApiScope> 
 6             { 
 7                 new ApiScope("apiscope1", "scope1"),
 8                 new ApiScope("apiscope2","scope2")
 9             };
10 
11         public static IEnumerable<ApiResource> ApiResources
12             => new List<ApiResource>
13             {
14                 new ApiResource("service1","this is service1")
15                 {
16                     Scopes= { "apiscope1" }
17                 },
18                 new ApiResource("service2","this is service2")
19                 {
20                     Scopes ={ "apiscope2" }
21                 }
22             };
23 
24         public static IEnumerable<Client> Clients 
25             => new List<Client> 
26             {
27                 new Client
28                 {
29                     ClientId = "clientId",
30                     ClientSecrets = new [] { new Secret("auth123456".Sha256()) },
31                     AllowedGrantTypes = { GrantType.ClientCredentials },
32                     AllowedScopes = new []
33                     {
34                         "apiscope1",
35                         "apiscope2",
36                         IdentityServerConstants.StandardScopes.OpenId,
37                         IdentityServerConstants.StandardScopes.Address,
38                         IdentityServerConstants.StandardScopes.Email,
39                         IdentityServerConstants.StandardScopes.Phone,
40                         IdentityServerConstants.StandardScopes.Profile
41                     },
42                     Claims = new List<ClientClaim>
43                     {
44                         new ClientClaim(IdentityModel.JwtClaimTypes.Role,"admin"),
45                         new ClientClaim(IdentityModel.JwtClaimTypes.NickName,"tom"),
46                         new ClientClaim("Emai","[email protected]")
47                     }
48                 }
49             };
50 
51         public static IEnumerable<IdentityResource> IdentityResources
52             => new List<IdentityResource>
53             {
54                 new IdentityResources.OpenId(),
55                 new IdentityResources.Profile(),
56                 new IdentityResources.Address(),
57                 new IdentityResources.Email(),
58                 new IdentityResources.Phone()
59             };
60     }
ids4 configuration
1 builder.Services.AddIdentityServer()
2     .AddDeveloperSigningCredential()
3     .AddInMemoryIdentityResources(Config.IdentityResources)
4     .AddInMemoryApiResources(Config.ApiResources)
5     .AddInMemoryApiScopes(Config.ApiScopes)
6     .AddInMemoryClients(Config.Clients);
7 
8 app.UseIdentityServer();
Ids4 configure service

  启动Ids4 dotnet run

6、ocelot中配置支持Ids4 authentication

 1 var authenticationProviderKey = "authenticationkey";
 2 builder.Services
 3     .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
 4     .AddIdentityServerAuthentication(authenticationProviderKey, options =>
 5     {
 6         options.Authority = "https://localhost:9000";
 7         options.RequireHttpsMetadata = false;
 8         options.ApiName = "service1";
 9         options.SupportedTokens = SupportedTokens.Both;
10         options.JwtBearerEvents = new JwtBearerEvents  
11         {
12             OnChallenge =ctx => 
13             {
14                 return Task.CompletedTask;
15             },
16             OnMessageReceived = ctx => 
17             {
18                 var token = ctx.Token;
19                 return Task.CompletedTask;
20             },
21             OnTokenValidated = ctx => 
22             {
23                 var securityToken = ctx.SecurityToken as JwtSecurityToken;
24                 var claimIdentities = ctx.Principal?.Identities;
25                 if (claimIdentities?.Any(i => i.Claims.Any(c=>c.Value.Equals("admin", StringComparison.OrdinalIgnoreCase))) ?? false)
26                     ctx.Success();
27                 else
28                     ctx.Fail("token validate failed.");
29                 return Task.CompletedTask;
30             },
31             OnAuthenticationFailed = context =>
32             {
33                 context.Fail(context.Exception);
34                 return Task.CompletedTask;
35             },
36             OnForbidden = context =>
37             {
38                 context.Fail("403 forbidden");
39                 return Task.CompletedTask;
40             }
41         };
42     });
Ocelot Ids4
app.UseAuthentication();
use authentication

7、为了避免恶意攻击避开ocelot直接访问service,在netcore api项目中同样需要添加验证

 1 builder.Services.AddAuthentication(options =>
 2 {
 3     options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
 4     options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
 5 }).AddIdentityServerAuthentication(options =>
 6 {
 7     options.Authority = "https://localhost:9000";
 8     options.ApiName = "service1";
 9     options.RequireHttpsMetadata = false;
10     options.SupportedTokens = IdentityServer4.AccessTokenValidation.SupportedTokens.Both;
11     options.Events = new JwtBearerEvents
12     {
13         OnTokenValidated = context =>
14         {
15             var token = context.SecurityToken as JwtSecurityToken;
16             var identity = context.Principal?.Identity as ClaimsIdentity;
17             if (!string.IsNullOrEmpty(token?.Issuer))
18                 context.Success();
19             else
20                 context.Fail($"Token invalid");
21             return Task.CompletedTask;
22         },
23         OnAuthenticationFailed = context =>
24         {
25             context.Fail(context.Exception);
26             return Task.CompletedTask;
27         },
28         OnForbidden = context =>
29         {
30             context.Fail("403 forbidden");
31             return Task.CompletedTask;
32         },
33         OnChallenge = context =>
34         {
35             var error = context.Error;
36             return Task.CompletedTask;
37         },
38         OnMessageReceived = context =>
39         {
40             var token = context.Token;
41             return Task.CompletedTask;
42         }
43     };
44 });
NetCore API authentication

 

配置详解

负载均衡

   /*
      LeastConnection
      RoundRobin
      NoLoadBalance
      */
      "LoadBalancerOptions": {
        "Type": "CustomRandomLoadBalancer"
      }

熔断,超时

 "QoSOptions": {
        "ExceptionsAllowedBeforeBreaking": 3,
        "DurationOfBreak": 10000, //ms
        "TimeoutValue": 10000 //ms,default 90s
      }

限流

 "RateLimitOptions": {
        "ClientWhiteList": [ "NoLimitedAPI" ],
        "EnableRateLimiting": true,
        "Period": "10s", //1s, 5m, 1h, 1d
        "PeriodTimespan": 10, //retry after n second/seconds
        "Limit": 3
      }

认证

"authenticationoptions": {
        "authenticationproviderkey": "authenticationkey",
        "allowedscopes": []
      }

Consul服务发现

"ServiceDiscoveryProvider": {
      "Host": "127.0.0.1",
      "Port": 8500,
      "Type": "Consul",
      "ConfigurationKey": "ApiGateway.Ocelot"
    }

 Ocelot缓存

"FileCacheOptions": {
        "TtlSeconds": 10,
        "Region": "gatewaycacheregion"
     }
cache

 

最终效果,通过访问ocelot 定义url 负载到具体的服务实例

token

 

 ocelot api

 

 

 

 

OK, 时间紧迫,有时间详搞。

标签:ocelot,return,Ocelot,NetCore,public,context,new,options
From: https://www.cnblogs.com/qindy/p/17101176.html

相关文章

  • NetCore Ocelot 之 请求聚合 Aggregator
    Ocelot允许声明聚合路由,把多个Routes请求batch一个对象来对客户端的请求进行响应。1、ocelotconfiguration{"DownstreamPathTemplate":"/api/service1",......
  • NetCore 之 DispatchProxy
    如何使用Dispatchproxy封装RESTAPI,让API调用更简单。1、创建HttpClientDispathProxy类继承自DispatchProxypublicclassHttpClientDispathProxy<TInterface>:D......
  • NetCore JWT token
    在netcore中jwt使用场景很多,网上有很多的资料,这里不再累述,之后有机会会单独介绍,今天主要以实战为主。1、createjwttoken1publicinterfaceIJwtTokenService2......
  • NetCore Resource
    在netcore中resource的配置及应用1、创建resource资源文件   2、在容器中添加配置1builder.Services.AddLocalization(options=>options.ResourcesPath="......
  • docker下netcore内存dump
    一般开发阶段可以通过visualstudio来检查程序的内存、cup等的优化问题。vs下调试=》性能探查器,这里面大有千秋。但是好多内存问题是经过时间积累下来才暴露出来的,在生产......
  • iis7上部署netcore项目的步骤
    1、安装AspNetCoreModule托管模块(选择.NetCore3.1版本)AspNetCoreModule下载地址:https://dotnet.microsoft.com/download/dotnet-core1安装下面两个文件dotnet-sdk-3......
  • 从.net Framework4.6WPF升级到.netcore3.1/net5/6/7.0版本
    因项目需要,需将.netFramework4.6WPF升级到.netcore3.1/net5.0/6.0/7.0版本,通过很多办法解决,开始搞得一头雾水。终于,找到了办法。1、首先下载upgrade-assistant工具(.net升级......
  • .Net6 微服务之Ocelot+IdentityServer4入门看这篇就够了
    前言.Net6使用Consul实现服务注册与发现看这篇就够了.Net6使用Ocelot+Consul看这篇就够了.Net6微服务之Polly入门看这篇就够了书接上文,本文将继续建立在.N......
  • .NetCore自定义模板,发布Nuget
    1.创建模板项目框架             2.创建模板文件在项目文件夹根目录创建.template.config文件夹,在文件夹下创建新的文件:template.json  ......
  • aspnetcore 原生 DI 实现基于 key 的服务获取
    你可能想通过一个字符串或者其他的类型来获取一个具体的服务实现,那么在aspnetcore原生的MSDI中,如何实现呢?本文将介绍如何通过自定义工厂来实现。我们现在恰好有基于J......