netCore微服务学习笔记(二):NetCore Ocelot Api网关

一.API网关

  API网关是微服务架构中的唯一入口,它提供一个单独且统一的API入口用于访问内部一个或多个API。API 网关会拦截所有传入的请求,然后通过 API 管理系统(该系统负责处理各种必要的功能)将其发送出去。具有一些常见的功能包括:身份验证、路由、负载均衡、缓存、熔断限流等;

二.Ocelot简介

  Ocelot是.net下开源的API网关,它实现了包括路由,认证、授权、服务发现、负载均衡、限流熔断等功能;具体可以参照文档Ocelot;Ocelot各个功能的实现,都是通过json配置文件来实现的,配置文件基本格式如下:

{
    "Routes": [],
    "GlobalConfiguration": {}
}
配置信息包含两部分,一组路由,一个全局配置;路由作用是告诉Ocelot如何处理上游请求的对象。全局配置允许覆盖特定于路由的设置。
关于详细的配置文件,信息如下:
 1 {
 2           "DownstreamPathTemplate": "/",
 3           "UpstreamPathTemplate": "/",
 4           "UpstreamHttpMethod": [
 5               "Get"
 6           ],
 7           "DownstreamHttpMethod": "",
 8           "DownstreamHttpVersion": "",
 9           "AddHeadersToRequest": {},
10           "AddClaimsToRequest": {},
11           "RouteClaimsRequirement": {},
12           "AddQueriesToRequest": {},
13           "RequestIdKey": "",
14           "FileCacheOptions": {
15               "TtlSeconds": 0,
16               "Region": ""
17           },
18           "RouteIsCaseSensitive": false,
19           "ServiceName": "",
20           "DownstreamScheme": "http",
21           "DownstreamHostAndPorts": [
22               {
23                   "Host": "localhost",
24                   "Port": 51876,
25               }
26           ],
27           "QoSOptions": {//熔断
28               "ExceptionsAllowedBeforeBreaking": 0,
29               "DurationOfBreak": 0,
30               "TimeoutValue": 0
31           },
32           "LoadBalancer": "",//负载均衡
33           "RateLimitOptions": {//限流
34               "ClientWhitelist": [],
35               "EnableRateLimiting": false,
36               "Period": "",
37               "PeriodTimespan": 0,
38               "Limit": 0
39           },
40           "AuthenticationOptions": {//认证授权
41               "AuthenticationProviderKey": "",
42               "AllowedScopes": []
43           },
44           "HttpHandlerOptions": {
45               "AllowAutoRedirect": true,
46               "UseCookieContainer": true,
47               "UseTracing": true,
48               "MaxConnectionsPerServer": 100
49           },
50           "DangerousAcceptAnyServerCertificateValidator": false
51       }
  • DownstreamPathTemplate:下游路径匹配模板
  • UptreamPathTemplate:上游路径匹配模板即客户端访问地址匹配路径
  • Aggregates: 服务聚合配置
  •  LoadBalancer:负载均衡配置
  • AuthenticationOptions :服务认证、授权
  • RateLimitOptions:限流
  • FileCacheOptions 缓存配置
  • QosOptions:熔断处理

三.集成网关

  1.新建netcore项目命名OcelorApiGetway,在nuget中搜索并安装Ocelot;

  2.新建json配置文件,命名configuration.json,右键属性“始终复制”,配置文件基本信息如下:

 1 /*基础配置*/
 2 {
 3   "GlobalConfiguration": {
 4 
 5   },
 6   "ReRoutes": [
 7     {
 8       "DownstreamPathTemplate": "/api/values",
 9       "DownstreamScheme": "http",
10       "DownstreamHostAndPorts": [
11         {
12           "Host": "localhost",
13           "Port": 5001
14         },
15         {
16           "Host": "localhost",
17           "Port": 5002
18         }
19       ],
20       "UpstreamPathTemplate": "/api/values",
21       "UpstreamHttpMethod": [ "Get"],
22       "LoadBalancerOptions": {//负载均衡选项
23                 "Type": "RoundRobin"//轮询访问
24               }
25       }
26 
27   ]
28 }

 

  3.修改Starup文件,注册服务与管道配置: 

 1      public void ConfigureServices(IServiceCollection services)
 2         {
 3             services.AddOcelot(new ConfigurationBuilder().AddJsonFile("configuration.json")
 4                 .Build()).AddConsul().AddPolly();
 5             services.AddControllers();
 6         }
 7 
 8         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
 9         public  void Configure(IApplicationBuilder app, IWebHostEnvironment env)
10         {
11             if (env.IsDevelopment())
12             {
13                 app.UseDeveloperExceptionPage();
14             }
15 
16             app.UseHttpsRedirection();
17             app.UseOcelot();
18             app.UseRouting();
19             app.UseEndpoints(endpoints =>
20             {
21                 endpoints.MapControllers();
22             });
23              
24         }

  4.新建两个webapi项目,命名为WebApiA,WebApiB,分别新建ValuesController,添加Get方法:

        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "This is webApiA" };
        }
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "This is webApiB" };
        }        

修改两个项目中的launchSettings.json文件中的applicationUrl,分别对应5001,5002;

  5.测试运行:先启动webApiA与WebApiB项目然后运行OcelorApiGetway,如下图:

  

  四.认证和授权

  在 Ocelot API 网关中,可使用提供身份验证令牌的 IdentityServer,在 API 网关外部或内部设置身份验证服务,例如 ASP.NET Core Web API 服务。

1.新建一项目,命名“WebApiIdentityServer”,添加引用程序:通过NuGet安装 IdentityServer4 或者通过程序包管理执行 Install-Package IdentityServer4 安装依赖包。

2.新建一个Config类,管理Identity资源,代码如下:

 1 using IdentityServer4.Models;
 2 using System.Collections.Generic;
 3 namespace IdentityClientDemo
 4 {
 5     public static class IdentityClientConfig
 6     {
 7         public static IEnumerable<IdentityResource> GetIdentityResourceResources()
 8         {
 9             return new List<IdentityResource>
10             {
11                 new IdentityResources.OpenId(),
12             };
13         }
14         // scopes define the API resources in your system
15         public static IEnumerable<ApiResource> GetApiResources()
16         {
17             //api资源({资源名称}{描述})
18             return new List<ApiResource>
19             {
20                 new ApiResource("Api", "Api"),
21             };
22         }
23 
24         /// <summary>
25         /// 添加客户端
26         /// </summary>
27         /// <returns></returns>
28         public static IEnumerable<Client> GetClients()
29         {
30             return new List<Client>
31             {
32                 new Client
33                 {
34                     //客户端id,必须唯一
35                     ClientId = "client",
36                     AllowedGrantTypes = GrantTypes.ClientCredentials,//授权方式,这里采用的是客户端认证模式
37                     ClientSecrets =
38                     {
39                         new Secret("secret".Sha256())
40                     },
41                     AllowedScopes =
42                     {
43                         "Api",
44                     }
45                 }
46             };
47         }
48     }
49 }
View Code

3.在startup.class中注入服务:

 1 using Microsoft.AspNetCore.Builder;
 2 using Microsoft.AspNetCore.Hosting;
 3 using Microsoft.Extensions.Configuration;
 4 using Microsoft.Extensions.DependencyInjection;
 5 using Microsoft.Extensions.Hosting;
 6 namespace IdentityClientDemo
 7 {
 8     public class Startup
 9     {
10         public Startup(IConfiguration configuration)
11         {
12             Configuration = configuration;
13         }
14 
15         public IConfiguration Configuration { get; }
16 
17         // This method gets called by the runtime. Use this method to add services to the container.
18         public void ConfigureServices(IServiceCollection services)
19         {
20 
21             services.AddIdentityServer()
22                  .AddDeveloperSigningCredential()
23                 .AddInMemoryApiResources(IdentityClientConfig.GetApiResources())//Api资源信息
24                 .AddInMemoryClients(IdentityClientConfig.GetClients());//客户端信息
25             services.AddControllers();
26         }
27 
28         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
29         public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
30         {
31             if (env.IsDevelopment())
32             {
33                 app.UseDeveloperExceptionPage();
34             }
35 
36             app.UseHttpsRedirection();
37 
38             app.UseRouting();
39 
40             app.UseAuthorization();
41             app.UseIdentityServer();
42             app.UseEndpoints(endpoints =>
43             {
44                 endpoints.MapControllers();
45             });
46         }
47     }
48 }
View Code

4.修改launchSetting.json文件,设置applicationUrl的端口为5003:

 1 {
 2   "$schema": "http://json.schemastore.org/launchsettings.json",
 3   "iisSettings": {
 4     "windowsAuthentication": false,
 5     "anonymousAuthentication": true,
 6     "iisExpress": {
 7       "applicationUrl": "http://localhost:5003",
 8       "sslPort": 0
 9     }
10   },
11   "profiles": {
12     "IIS Express": {
13       "commandName": "IISExpress",
14       "launchBrowser": true,
15       "launchUrl": "api/Token",
16       "environmentVariables": {
17         "ASPNETCORE_ENVIRONMENT": "Development"
18       }
19     },
20     "WebApiIdentityServer": {
21       "commandName": "Project",
22       "launchBrowser": true,
23       "launchUrl": "api/Token",
24       "applicationUrl": "https://localhost:5003;http://localhost:5003",
25       "environmentVariables": {
26         "ASPNETCORE_ENVIRONMENT": "Development"
27       }
28     }
29   }
30 }
View Code

5.修改OcelotApiGetway项目中的Startup文件,添加身份认证:

 1   public class Startup
 2     {
 3         public Startup(IConfiguration configuration)
 4         {
 5             Configuration = configuration;
 6         }
 7 
 8         public IConfiguration Configuration { get; }
 9 
10         // This method gets called by the runtime. Use this method to add services to the container.
11         public void ConfigureServices(IServiceCollection services)
12         {
13 
14             services.AddOcelot(new ConfigurationBuilder().AddJsonFile("configuration.json")
15                 .Build()).AddConsul().AddPolly();
16 
17             services
18              .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
19              .AddIdentityServerAuthentication("Bearer", options =>
20              {
21                  options.Authority = "http://localhost:5003";
22                  options.RequireHttpsMetadata = false;
23                  options.ApiName = "api1";
24                  options.ApiSecret = "secret";
25              });
26 
27             services.AddControllers();
28         }
29 
30         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
31         public  void Configure(IApplicationBuilder app, IWebHostEnvironment env)
32         {
33             if (env.IsDevelopment())
34             {
35                 app.UseDeveloperExceptionPage();
36             }
37 
38             app.UseHttpsRedirection();
39             app.UseOcelot();
40             app.UseRouting();
41 
42             app.UseAuthentication();
43             app.UseAuthorization();
44 
45             //app.UseMvc();
46             app.UseEndpoints(endpoints =>
47             {
48                 endpoints.MapControllers();
49             });
50              
51         }
52     }

然后修改OcelotApiGetway中Ocelot配置文件,添加认证授权节点:

      //认证授权
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "Bearer",//需要和startup文件中的authenticationScheme 保持一致
        "AllowedScopes": []
      },

完整配置如下:

 1 /* 认证授权*/
 2 {
 3   "GlobalConfiguration": {
 4     //  "ServiceDiscoveryProvider": {
 5     //    "Host": "localhost",
 6     //    "Port": 8500,
 7     //    "Type": "Consul"
 8     //  }
 9 
10     "RateLimitOptions": {
11       "DisableRateLimitHeaders": true,
12       "QuotaExceededMessage": "Stop request plz!",
13       "HttpStatusCode": 666,
14       "ClientIdHeader": "cid"
15     }
16 
17   },
18   "ReRoutes": [
19     {
20       "DownstreamPathTemplate": "/{url}",
21       "DownstreamScheme": "http",
22       "DownstreamHostAndPorts": [
23         {
24           "Host": "localhost",
25           "Port": 5001
26         },
27         {
28           "Host": "localhost",
29           "Port": 5002
30         },
31         {
32           "Host": "localhost",
33           "Port": 5003
34         }
35       ],
36       //认证授权
37       "AuthenticationOptions": {
38         "AuthenticationProviderKey": "Bearer",
39         "AllowedScopes": []
40       },
41       "UpstreamPathTemplate": "/Service1/{url}",
42       "UpstreamHttpMethod": [ "Get", "Post" ],
43       //限流
44       "RateLimitOptions": {
45         //"ClientWhitelist": [],
46         "EnableRateLimiting": true, //Boolean值,是否启用限流,只有为true时,配置生效。
47         "Period": "1m", //限流控制的时间段,可以输入 1s(1秒),1m(1分),1h(1小时),1d(1天)
48         "PeriodTimespan": 30, //多少秒之后客户端可以重试
49         "Limit": 200 //在Period时间内最大能访问的数量。
50       },
51       //1分钟之内该api最多被访问2次,如果已经达到2次,从第2次请求结束起30秒后才能进行下一次访问。
52       "LoadBalancerOptions": {
53         "Type": "RoundRobin"
54       },
55       //熔断
56       "QoSOptions": {
57         "ExceptionsAllowedBeforeBreaking": 1, //ExceptionsAllowedBeforeBreaking 允许多少个异常请求
58         "DurationOfBreak": 5000, //DurationOfBreak 熔断的时间,单位为秒
59         "TimeoutValue": 3000 //TimeoutValue 如果下游请求的处理时间超过多少则自如将请求设置为超时
60       }
61       //3秒算一次超时(TimeoutValue:3000),然后允许的异常请求是2次(ExceptionsAllowedBeforeBreaking:1),如果达到了允许异常请求的上限就触发5秒钟的熔断时间(DurationOfBreak:5000)
62     },
63     {
64       "DownstreamPathTemplate": "/{url}",
65       "DownstreamScheme": "http",
66       "DownstreamHostAndPorts": [
67         {
68           "Host": "localhost",
69           "Port": 5003
70         }
71       ],
72       "UpstreamPathTemplate": "/service2/{url}",
73       "UpstreamHttpMethod": [ "Get", "Post" ],
74       "AuthenticationOptions": {
75         "AuthenticationProviderKey": "Bearer",
76         "AllowedScopes": []
77       }
78 
79     }
80 
81   ]
82 }
View Code

6.测试运行,启动三个API项目然后运行OcelotApiGetway,可以发现会报401 Unauthorized异常:

 

 

 然后调用WebApiIdentityServer项目中的获取token方法,并携带token再次访问:

 

 

 

 

 

 

 

可以看到能正常请求到数据;

posted @ 2021-02-20 10:55  波峰浪尖  阅读(311)  评论(0编辑  收藏  举报