API网关--参考文档

API网关

概念------为什么------如何使用oclet-----内部概念(上游和下游)、路由-----ocelot内部运行原理-----如何做步骤-----ocelot配置文件介绍----路由基本使用----路由负载均衡------路由consul支持-----路由多个服务操作-----路由多个服务聚合----路由限流----路由熔断----路由缓存----路由身份验证。

什么是API网关

就是用来限制客户端访问服务端api一到门槛,在图例中已经进行了展示

什么是API

API是Application Programming Interface缩写,翻译成中文就是应用程序接口。在实际微服务中可以理解一个个功能方法。就比如你一个用户服务的微服务,可以对外提供 API 接口为,查找用户,创建用户等。

什么是网关

网关, wiki 上定义。

计算机网络中,网关(英语:Gateway)是转发其他服务器通信数据的服务器,接收从客户端发送来的请求时,它就像自己拥有资源的源服务器一样对请求进行处理

为什么要使用微服务网关

大概有4四种情况

1、聚合微服务增多,导致客户端不好维护

2、聚合微服务进行集群

2.1 增加和修改聚合微服务集群,都要修改客户端,导致客户端不稳定

2.2 服务集群,无法解决复杂均衡的问题

3、客户端访问多个聚合微服务

3.1 如果需要对客户端身份验证和授权,会导致每个服务都进行授权

3.2 如何客户端访问过大,无法限制客户端流量,导致系统宕机

3.3 如果客户端访问微服务系统,每个微服务之间进行调用。会导致耗时操作很难统计。

3.4 如果客户端访问微服务系统,如何统计客户端的调用日志

总结

1、路由

2、负载均衡

3、限流

4、认证

5、授权

6、链路监控

7、熔断降级

8、Service Fabric

如何在项目中使用API网关

API网关类型

1、Netflix Zuul +java实现

2、Kong nginx +lua脚本实现

3、Tyk go语言开发,收费版本

4、Ocelot aspnetcore开发的

如何在项目中使用Ocelot

Ocelot是什么

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

Ocelot内部概念

上游

Ocelot为上游:Upstream

下游

Ocelot下面映射的服务为下游:Downstream

主要功能

1、路由

1.1 接受客户端请求

1.2 奖客户端请求转换成下游地址

1.3 调用下游服务,并返回结果

1.4 将下游服务返回的结果返回到前端

2、认证

3、授权

4、负载均衡

5、链路监控

6、限流

7、熔断降级

8、请求聚合

9、Service Fabric

等其他功能

Ocelot文档地址

中文文档:http://www.jessetalk.cn/2018/03/19/net-core-apigateway-ocelot-docs/

英文文档:https://ocelot.readthedocs.io/en/latest/introduction/gettingstarted.html

Ocelot如何使用

条件

1、aspnetcore3.1

2、Ocelot

3、团队微服务

4、ocelot.json文件

步骤

1、创建一个空的aspnetcore3.1项目

2、通过nuget安装Ocelot

3、创建Ocelot配置文件ocelot.json

{
"ReRoutes": [],
"GlobalConfiguration": {
"BaseUrl": "https://api.mybusiness.com"
}
}

要特别注意一下BaseUrl是我们外部暴露的Url,比如我们的Ocelot运行在http://123.111.1.1的一个地址上,但是前面有一个 nginx绑定了域名http://api.jessetalk.cn,那这里我们的BaseUrl就是 http://api.jessetalk.cn

4、加载ocelot.json配置文件

 public static IHostBuilder CreateHostBuilder(string[] args) =>
          Host.CreateDefaultBuilder(args)
              .ConfigureWebHostDefaults(webBuilder =>
              {
                  webBuilder.UseStartup<Startup>();
                  webBuilder.ConfigureAppConfiguration((hostingContext, config) =>
                  {
                      // 1、加载ocelot配置文件
                      config.AddJsonFile("ocelot.aggregate.json");
                  });
              });

5、配置Ocelot依赖注入并加载配置文件

public void ConfigureServices(IServiceCollection services)
{
services.AddOcelot()
}

6、配置Ocelot中间件

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseOcelot().Wait();
}

Ocelot如何使用路由

一个路由完整配置
{
  "DownstreamPathTemplate": "/",
  "UpstreamPathTemplate": "/",
  "UpstreamHttpMethod": [
  "Get"
  ],
  "AddHeadersToRequest": {},
  "AddClaimsToRequest": {},
  "RouteClaimsRequirement": {},
  "AddQueriesToRequest": {},
  "RequestIdKey": "",
  "FileCacheOptions": {
  "TtlSeconds": 0,
  "Region": ""
  },
  "ReRouteIsCaseSensitive": false,
  "ServiceName": "",
  "DownstreamScheme": "http",
  "DownstreamHostAndPorts": [
  {
  "Host": "localhost",
  "Port": 51876,
  }
  ],
  "QoSOptions": {
  "ExceptionsAllowedBeforeBreaking": 0,
  "DurationOfBreak": 0,
  "TimeoutValue": 0
  },
  "LoadBalancer": "",
  "RateLimitOptions": {
  "ClientWhitelist": [],
  "EnableRateLimiting": false,
  "Period": "",
  "PeriodTimespan": 0,
  "Limit": 0
  },
  "AuthenticationOptions": {
  "AuthenticationProviderKey": "",
  "AllowedScopes": []
  },
  "HttpHandlerOptions": {
  "AllowAutoRedirect": true,
  "UseCookieContainer": true,
  "UseTracing": true
  },
  "UseServiceDiscovery": false
}
  • Downstream是下游服务配置

  • UpStream是上游服务配置

  • Aggregates 服务聚合配置

  • ServiceName, LoadBalancer, UseServiceDiscovery 配置服务发现

  • AuthenticationOptions 配置服务认证

  • RouteClaimsRequirement 配置Claims鉴权

  • RateLimitOptions为限流配置

  • FileCacheOptions 缓存配置

  • QosOptions 服务质量与熔断

  • DownstreamHeaderTransform头信息转发

路由基本使用
{
"DownstreamPathTemplate": "/api/post/{postId}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 80,
}
],
"UpstreamPathTemplate": "/post/{postId}",
"UpstreamHttpMethod": [ "Get"]
}
  • DownstreamPathTemplate:下游路径模板

  • DownstreamScheme:下游服务http schema

  • DownstreamHostAndPorts:下游服务的地址,如果使用LoadBalancer的话这里可以填多项

  • UpstreamPathTemplate: 上游也就是用户输入的请求Url模板

  • UpstreamHttpMethod: 上游请求http方法,可使用数组

路由负载均衡
{
  "DownstreamPathTemplate": "/api/posts/{postId}",
  "DownstreamScheme": "https",
  "DownstreamHostAndPorts": [
          {
              "Host": "10.0.1.10",
              "Port": 5000,
          },
          {
              "Host": "10.0.1.11",
              "Port": 5000,
          }
      ],
  "UpstreamPathTemplate": "/posts/{postId}",
  "LoadBalancerOptions": {
      "Type": "LeastConnection"
  },
  "UpstreamHttpMethod": [ "Put", "Delete" ]
}

LoadBalancer将决定负载均衡的算法

  • LeastConnection – 将请求发往最空闲的那个服务器

  • RoundRobin – 轮流发送

  • NoLoadBalance – 总是发往第一个请求或者是服务发现

路由Consul负载均衡

条件:

1、Ocelot.Provider.Consul

2、Consul

3、Ocelot

步骤

1、通过nuget下载Ocelot.Provider.Consul

2、添加consul依赖注入

public void ConfigureServices(IServiceCollection services)
      {
          // 1、添加网关Ocelot到ioc容器
          services.AddOcelot().AddConsul();
      }

3、路由consul配置

{
    "DownstreamPathTemplate": "/api/posts/{postId}",
    "DownstreamScheme": "https",
    "UpstreamPathTemplate": "/posts/{postId}",
    "UpstreamHttpMethod": [ "Put" ],
    "ServiceName": "product",
    "LoadBalancerOptions": {
        "Type": "LeastConnection"
    },
}
多个路由配置(多项目)

条件

1、TeamService,MemberService

2、ocelot.team.json,ocelot.member.json

步骤

1、创建ocelot.team.json,ocelot.member.json文件

2、配置动态加载ocelot.json配置文件

webBuilder.ConfigureAppConfiguration((hostingContext, config) =>
                    {
                        config
                            // .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
                            // .AddJsonFile("appsettings.json", true, true)
                            // .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
                            .AddOcelot(hostingContext.HostingEnvironment);
                        // .AddEnvironmentVariables();
                    });

会自动的加载配置文件,然后进行合并,主要用于大项目配置

3、ocelot依赖注入配置

public void ConfigureServices(IServiceCollection services)
        {
            // 1、添加网关Ocelot到ioc容器
            services.AddOcelot();
        }
路由聚合请求
{
    "ReRoutes": [
    {
    "DownstreamPathTemplate": "/",
    "UpstreamPathTemplate": "/laura",
    "UpstreamHttpMethod": [
   		 "Get"
    ],
    "DownstreamScheme": "http",
    "DownstreamHostAndPorts": [
        {
            "Host": "localhost",
            "Port": 51881
        }
    ],
    "Key": "Laura"
    },
    {
    "DownstreamPathTemplate": "/",
    "UpstreamPathTemplate": "/tom",
    "UpstreamHttpMethod": [
    "Get"
    ],
    "DownstreamScheme": "http",
    "DownstreamHostAndPorts": [
    {
    "Host": "localhost",
    "Port": 51882
    }
    ],
    "Key": "Tom"
    }
    ],
    "Aggregates": [
        {
        "ReRouteKeys": [
            "Tom",
            "Laura"
        ],
        "UpstreamPathTemplate": "/"
        }
    ]
}

当我们请求/的时候,会将/tom和/laura两个结果合并到一个response返回

{"Tom":{"Age": 19},"Laura":{"Age": 25}}

需要注意的是:

  • 聚合服务目前只支持返回json

  • 目前只支持Get方式请求下游服务

  • 任何下游的response header并会被丢弃

  • 如果下游服务返回404,聚合服务只是这个key的value为空,它不会返回404

有一些其它的功能会在将来实现

  • 下游服务很慢的处理

  • 做一些像 GraphQL的处理对下游服务返回结果进行处理

  • 404的处理

路由限流
"RateLimitOptions": {
    "ClientWhitelist": [],
    "EnableRateLimiting": true,
    "Period": "5m",
    "PeriodTimespan": 1,
    "Limit": 1
}
  • ClientWihteList 白名单

  • EnableRateLimiting 是否启用限流

  • Period 统计时间段:1s, 5m, 1h, 1d

  • PeroidTimeSpan 多少秒之后客户端可以重试

  • Limit 在统计时间段内允许的最大请求数量

    在 GlobalConfiguration下我们还可以进行以下配置

"RateLimitOptions": {
  "DisableRateLimitHeaders": false,
  "QuotaExceededMessage": "Customize Tips!",
  "HttpStatusCode": 999,
  "ClientIdHeader" : "Test"
}
  • Http头 X-Rate-Limit 和 Retry-After 是否禁用

  • QuotaExceedMessage 当请求过载被截断时返回的消息

  • HttpStatusCode 当请求过载被截断时返回的http status

  • ClientIdHeader 用来识别客户端的请求头,默认是 ClientId

路由服务质量与熔断

条件

1、Ocelot.Provider.Polly

步骤

1、在ocelot上添加熔断

public void ConfigureServices(IServiceCollection services)
        {
            // 1、添加网关Ocelot到ioc容器
            services.AddOcelot(new ConfigurationBuilder().AddJsonFile("ocelot.aggregate.json").Build())
                .AddConsul()
                .AddPolly();
        }

2、添加熔断配置

熔断的意思是停止将请求转发到下游服务。当下游服务已经出现故障的时候再请求也是功而返,并且增加下游服务器和API网关的负担。这个功能是用的Pollly来实现的,我们只需要为路由做一些简单配置即可

"QoSOptions": {
    "ExceptionsAllowedBeforeBreaking":3,
    "DurationOfBreak":5,
    "TimeoutValue":5000
}
  • ExceptionsAllowedBeforeBreaking 允许多少个异常请求

  • DurationOfBreak 熔断的时间,单位为秒

  • TimeoutValue 如果下游请求的处理时间超过多少则自动将请求设置为超时

路由缓存

Ocelot可以对下游请求结果进行缓存 ,目前缓存的功能还不是很强大。它主要是依赖于CacheManager 来实现的,我们只需要在路由下添加以下配置即可

"FileCacheOptions": { "TtlSeconds": 15, "Region": "somename" }

Region是对缓存进行的一个分区,我们可以调用Ocelot的 administration API来移除某个区下面的缓存 。

路由认证(Identity Server4)

条件

1、

2、

3、

步骤

Identity Server Bearer Tokens

添加Identity Server的认证也是一样

public void ConfigureServices(IServiceCollection services)
{
    var authenticationProviderKey = "TestKey";
    var options = o =>
        {
            o.Authority = "https://whereyouridentityserverlives.com";
            o.ApiName = "api";
            o.SupportedTokens = SupportedTokens.Both;
            o.ApiSecret = "secret";
        };

    services.AddAuthentication()
        .AddIdentityServerAuthentication(authenticationProviderKey, options);

    services.AddOcelot();
}

Allowed Scopes

这里的Scopes将从当前 token 中的 claims中来获取,我们的鉴权服务将依靠于它来实现 。当前路由的下游API需要某个权限时,我们需要在这里声明 。和oAuth2中的 scope意义一致。

路由鉴权

我们通过认证中的AllowedScopes 拿到claims之后,如果要进行权限的鉴别需要添加以下配置

"RouteClaimsRequirement": {
    "UserType": "registered"
}

当前请求上下文的token中所带的claims如果没有 name=”UserType” 并且 value=”registered” 的话将无法访问下游服务。

路由请求头转化

请求头转发分两种:转化之后传给下游和从下游接收转化之后传给客户端。在Ocelot的配置里面叫做Pre Downstream Request和Post Downstream Request。目前的转化只支持查找和替换。我们用到的配置主要是 UpstreamHeaderTransform 和 DownstreamHeaderTransform

Pre Downstream Request

"Test": "http://www.bbc.co.uk/, http://ocelot.com/"

比如我们将客户端传过来的Header中的 Test 值改为 http://ocelot.com/之后再传给下游

 "UpstreamHeaderTransform": {
    "Test": "http://www.bbc.co.uk/, http://ocelot.com/"
},

Post Downstream Request

而我们同样可以将下游Header中的Test再转为 http://www.bbc.co.uk/之后再转给客户端。

"DownstreamHeaderTransform": {
    "Test": "http://www.bbc.co.uk/, http://ocelot.com/"
},

 

如有错误,欢迎您指出。
本文版权归作者和博客园共有,欢迎转载,但必须在文章页面给出原文链接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/qingyunye/p/12904384.html