.NET Core 下的 API 网关

在这里插入图片描述

网关介绍

网关其实就是将我们写好的API全部放在一个统一的地址暴露在公网,提供访问的一个入口。在 .NET Core下可以使用Ocelot来帮助我们很方便的接入API 网关。与之类似的库还有ProxyKit,微软也发布了一个反向代理的库YARP

关于网关的介绍不多说了,网上文章也挺多的,这些都是不错的选择,听说后期Ocelot将会使用YARP来重写。本篇主要实践一下在.NET Core环境下使用Ocelot

接入使用

接口示例

先创建几个项目用于测试,创建两个默认的API项目,Api_A和Api_B,在创建一个网关项目Api_Gateway,网关项目可以选择空的模板。

现在分别在Api_AApi_B中写几个api,将默认的WeatherForecastController中返回模型WeatherForecast添加一个字段Source,用于区分是哪个API返回的数据。

using System;
namespace Api_A
{
    public class WeatherForecast
    {
        public string Source { get; set; } = "Api_A";
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
        public string Summary { get; set; }
    }
}
using System;
namespace Api_B
{
    public class WeatherForecast
    {
        public string Source { get; set; } = "Api_B";
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
        public string Summary { get; set; }
    }
}

直接使用WeatherForecastController默认方法,在路由中添加api前缀。

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Api_A.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };
        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            }).ToArray();
        }
    }
}
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Api_B.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };
        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            }).ToArray();
        }
    }
}

再分别在Api_AApi_B中添加两个控制器:ApiAControllerApiBController,然后加上几个简单的restful api

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace Api_A.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ApiAController : ControllerBase
    {
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
        [HttpGet("{id}")]
        public string Get(int id)
        {
            return $"Get:{id}";
        }
        [HttpPost]
        public string Post([FromForm] string value)
        {
            return $"Post:{value}";
        }
        [HttpPut("{id}")]
        public string Put(int id, [FromForm] string value)
        {
            return $"Put:{id}:{value}";
        }
        [HttpDelete("{id}")]
        public string Delete(int id)
        {
            return $"Delete:{id}";
        }
    }
}
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace Api_B.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ApiBController : ControllerBase
    {
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
        [HttpGet("{id}")]
        public string Get(int id)
        {
            return $"Get:{id}";
        }
        [HttpPost]
        public string Post([FromForm] string value)
        {
            return $"Post:{value}";
        }
        [HttpPut("{id}")]
        public string Put(int id, [FromForm] string value)
        {
            return $"Put:{id}:{value}";
        }
        [HttpDelete("{id}")]
        public string Delete(int id)
        {
            return $"Delete:{id}";
        }
    }
}

在这里插入图片描述
在这里插入图片描述
方便查看接口,这里添加一下swagger组件,这样我们Api_A和Api_B项目分别就有了6个接口。

接着打包docker镜像,放在docker中运行这两个api项目。这一步可以用任何你熟悉的方式,run起来即可。

docker build -t api_a:dev -f ./Api_A/Dockerfile .
docker build -t api_b:dev -f ./Api_B/Dockerfile .

build成功后,指定两个端口运行api项目。

docker run -d -p 5050:80 --name api_a api_a:dev
docker run -d -p 5051:80 --name api_b api_b:dev

Api_A指定了5050端口,通过 http://localhost:5050/swagger打开可以看到swagger文档界面,Api_B指定了5051端口,通过 http://localhost:5051/swagger打开可以看到swagger文档界面,这样就大功告成了,接下来才是重点将两个api项目配置到Api_Gateway网关项目中。

配置网关

在网关项目Api_Gateway中都添加Ocelot组件包。

Install-Package Ocelot

Ocelot中最关键的就是配置路由信息,新建一个ocelot.json配置文件,将我们的两个API接口匹配规则放进去。

{
  "Routes": [
    //ApiA
    {
      "DownstreamPathTemplate": "/api/WeatherForecast",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5050
        }
      ],
      "UpstreamPathTemplate": "/ApiA/WeatherForecast",
      "UpstreamHttpMethod": [ "Get" ]
    },
    {
      "DownstreamPathTemplate": "/api/ApiA",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5050
        }
      ],
      "UpstreamPathTemplate": "/ApiA",
      "UpstreamHttpMethod": [ "Get", "POST" ]
    },
    {
      "DownstreamPathTemplate": "/api/ApiA/{id}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5050
        }
      ],
      "UpstreamPathTemplate": "/ApiA/{id}",
      "UpstreamHttpMethod": [ "Get", "Put", "Delete" ]
    },
    //ApiB
    {
      "DownstreamPathTemplate": "/api/WeatherForecast",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5051
        }
      ],
      "UpstreamPathTemplate": "/ApiB/WeatherForecast",
      "UpstreamHttpMethod": [ "Get" ]
    },
    {
      "DownstreamPathTemplate": "/api/ApiB",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5051
        }
      ],
      "UpstreamPathTemplate": "/ApiB",
      "UpstreamHttpMethod": [ "Get", "POST" ]
    },
    {
      "DownstreamPathTemplate": "/api/ApiB/{id}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5051
        }
      ],
      "UpstreamPathTemplate": "/ApiB/{id}",
      "UpstreamHttpMethod": [ "Get", "Put", "Delete" ]
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "https://localhost:44335"
  }
}

关于配置文件中的各项具体含义,可以参考官方文档中的介绍。主要就是将DownstreamPathTemplate模板内容转换为UpstreamPathTemplate模板内容进行接口的访问,同时可以指定HTTP请求的方式等等。GlobalConfiguration中的BaseUrl为我们暴漏出去的网关地址。

设置好ocelot.json后,需要在代码中使用它,在Program.cs中添加配置文件。

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace Api_Gateway
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((context, config) =>
                {
                    config.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

Startup.cs中使用Ocelot

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
namespace Api_Gateway
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOcelot();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });
            app.UseOcelot().Wait();
        }
    }
}

完成以上操作后,我们试着去调用接口看看能否正确获取预期数据。

curl -X GET "https://localhost:44335/ApiA"
curl -X GET "https://localhost:44335/ApiB"
curl -X POST "https://localhost:44335/ApiA" -H "Content-Type: multipart/form-data" -F "value=ApiA"
curl -X POST "https://localhost:44335/ApiB" -H "Content-Type: multipart/form-data" -F "value=ApiB"
curl -X GET "https://localhost:44335/ApiA/12345"
curl -X GET "https://localhost:44335/ApiB/12345"
curl -X PUT "https://localhost:44335/ApiA/12345" -H "Content-Type: multipart/form-data" -F "value=ApiA"
curl -X PUT "https://localhost:44335/ApiB/12345" -H "Content-Type: multipart/form-data" -F "value=ApiB"
curl -X DELETE "https://localhost:44335/ApiA/12345"
curl -X DELETE "https://localhost:44335/ApiB/12345"
curl -X GET "https://localhost:44335/ApiA/WeatherForecast"
curl -X GET "https://localhost:44335/ApiB/WeatherForecast"

在这里插入图片描述
可以看到,两个项目中的接口全部可以通过网关项目暴露的地址进行中转,是不是很方便?

本篇只是简单的应用,对于Ocelot的功能远不止于此,它非常强大,还可以实现请求聚合、服务发现、认证、鉴权、限流熔断、并内置了负载均衡器,而且这些功能都是只需要简单的配置即可完成。就不一一描述了,如有实际开发需求和问题,可以查看官方文档和示例。


Ocelot一个优秀的.NET API网关框架

1 什么是Ocelot?

Ocelot是一个用.NET Core实现并且开源的API网关,它功能强大,包括了:路由、请求聚合、服务发现、认证、鉴权、限流熔断、并内置了负载均衡器与Service Fabric、Butterfly Tracing集成。

2 如何使用Ocelot?

首先,创建2个WebApi项目,WebApi01WebApi02,地址分别https://localhost:44313https://localhost:44390,其中WebApi01当作网关,WebApi02当作具体的微服务Api。

然后,将Ocelot的NuGet软件包安装到WebApi01项目中。

Ocelot

注意我这里安装的是17.0.0版本,配置方面会有点不一样。

接着,在Startup.ConfigureServices中增加services.AddOcelot;

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "Autofac.WebApi", Version = "v1" });
    });
    services.AddOcelot();
}

接着,在Startup.Configure中增加app.UseOcelot().Wait();

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Ocelot.WebApi01 v1"));
    }
    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
    app.UseOcelot().Wait();
}

接着,创建ocelot.json文件

{
  "Routes": [ //路由配置(注16.1版本将ReRoutes换成Routes)
    {
      "DownstreamPathTemplate": "/{url}", // 下游(服务提供方)服务路由模板
      "DownstreamScheme": "https", // 下游Uri方案,http、https
      "DownstreamHostAndPorts": [ // 服务地址和端口,如果是集群就设置多个
        {
          "Host": "localhost",
          "Port": 44390
        }
      ],
      "UpstreamPathTemplate": "/api/{url}", // 上游(客户端,服务消费方)请求路由模板
      "UpstreamHttpMethod": [ "GET" ] // 允许的上游HTTP请求方法,可以写多个
    }
  ],
  "GlobalConfiguration": { //全局配置
    "BaseUrl": "https://localhost:44313" //网关对外地址
  }
}

最后,在Program.CreateHostBuilder中增加AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, builder) => {
            builder.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

Ok,让我们来测试看看,https://localhost:44313/api/WeatherForecast会不会跳转https://localhost:44390/WeatherForecast。


.net web api 网关入门

  1. dotNet 5
  2. ocelot + consul

ocelot 增加consul服务发现网关访问提示404问题

ocelotconsul 配置经反复对比未发现问题,去除服务发现,恢复下游列表定义的方式网关是可用的(列表方式虽然可用,但负载均衡在站点服务不可用时仍然发送请求过去了,没有达到自动切换的效果),推断问题在ocelot注入端。

  1. 原注入ocelot方式
     services
          .AddOcelot(new ConfigurationBuilder()
               .AddJsonFile("ocelot.json", optional: false, reloadOnChange: true)
               .Build())
           .AddConsul();
  1. 需调整为
     services
          .AddOcelot()
          .AddConsul();

ocelot.json 放在 program中注入:

    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
            .AddJsonFile("ocelot.json")
            .AddEnvironmentVariables();
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

Then runs perfect as expected.

ocelot & consul nuget package

  1. Ocelot
  2. Ocelot.Provider.Consul

ocelot config

{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/{controller}/{action}",
      "UpstreamPathTemplate": "/yourPrefix/{controller}/{action}",
      "UpstreamHttpMethod": [
        "Get",
        "POST"
      ],
      "DownstreamScheme": "http",
      "UseServiceDiscovery": true,
      "ReRouteIsCaseSensitive": false,
      "ServiceName": "YourServiceName",
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      }
    },
    {
      "DownstreamPathTemplate": "/yourPrefix/{everything}",
      "UpstreamPathTemplate": "/yourPrefix/{everything}",
      "UpstreamHttpMethod": [
        "Get",
        "POST"
      ],
      "DownstreamScheme": "http",
      "UseServiceDiscovery": true,
      "ReRouteIsCaseSensitive": false,
      "ServiceName": "YourServiceName",
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      }
    }
  ],
  "GlobalConfiguration": { 
    "ServiceDiscoveryProvider": {
      "Scheme": "http",
      "Host": "localhost",
      "Port": 8500,
      "Type": "Consul"
    }
  }
}

consul services config

{
  "services": [
    {
      "id": "webapi1",
      "name": "YourServiceName",
      "tags": [ "WebApi" ],
      "address": "127.0.0.1",
      "port": 51012,
      "checks": [
        {
          "id": "AbcCheck1",
          "name": "Abc_Check",
          "http": "http://127.0.0.1:51012/weatherforecast",
          "interval": "10s",
          "tls_skip_verify": false,
          "method": "GET",
          "timeout": "1s"
        }
      ]
    },
    {
      "id": "webapi2",
      "name": "YourServiceName",
      "tags": [ "WebApi" ],
      "address": "127.0.0.1",
      "port": 51013,
      "checks": [
        {
          "id": "AbcCheck2",
          "name": "Abc1_Check",
          "http": "http://127.0.0.1:51013/weatherforecast",
          "interval": "10s",
          "tls_skip_verify": false,
          "method": "GET",
          "timeout": "1s"
        }
      ]
    }
  ]
}

Consul, Important: Run Consul as Windows Service

  1. 下载安装consul https://www.consul.io/.
    ps: 下载很慢,超过1个小时

2. sc 创建服务(创建后到服务中更改启动方式为“自动(延迟启动)”)

sc.exe create "Consul" binPath= "D:\Consul\consul.exe agent -server -ui -bootstrap-expect=1 -data-dir=D:\Consul -node=consulNode1 -client=0.0.0.0 -bind=YourLocalIP -datacenter=dc1 -config-dir=D:\Consul\consulServices.json" start= auto

注:
(1)bootstrap-expect=1, windows 单机
(2)不需要“&”带入命令行,否则windows service 启动异常。
(3)延迟自动启动,该服务不能在系统重启过程启动(可能和consul.exe系统启动过程未识别到有关)

consul健康检查

Postman 测试

  1. 下游服务全部可用时,可以轮流发送。
  2. 下游服务部分不可用时,仍然可以全部发送到可用的服务(不加consul时,ocelot就是服务不可用也发送过去了)

创建项目(一个server,两个webapi

server下载nuget Ocelot

创建Ocelot.json 参照地址

        {
            "ReRoutes": [//路由配置
                //万能模板的优先级最低,只要有其它的路由模板,其它的路由模板则会优先生效。
                {
                    "DownstreamPathTemplate": "/api/{url}",//下游地址
                    "DownstreamScheme": "https",//下游服务http
                    "DownstreamHostAndPorts": [//下游地址和端口
                        {
                        "Host": "localhost",
                        "Port": 44323
                        },
                        {
                        "Host": "localhost",
                        "Port": 44308
                        }
                    ],
                    "UpstreamPathTemplate": "/api/{url}",//上游地址
                    "UpstreamHttpMethod": [ "Get","Post" ],//上游请求方式
                    "LoadBalancerOptions": {
                        "Type": "RoundRobin"//添加多个HostAndPort,时候需求指定路由负载均衡,LeastConnection – 将请求发往最空闲的那个服务器 RoundRobin – 轮流发送 NoLoadBalance – 总是发往第一个请求或者是服务发现
                    },
                    "Priority":0, //优先级 对多个产生冲突的路由设置优化级
                    "Key":"ThisKey", //唯一主键,聚合(Aggregates)使用,
                    "FileCacheOptions": {//缓存
                        "TtlSeconds": 0,
                        "Region": ""
                    },
                    "AuthenticationOptions": {//认证
                        "AuthenticationProviderKey": "TestKey",
                        "AllowedScopes": []
                    }
                    "RateLimitOptions": {//限流 对请求进行限流可以防止下游服务器因为访问过载而崩溃
                        "ClientWhitelist": [],//白名单
                        "EnableRateLimiting": true,//是否限流
                        "Period": "1s",//统计时间段:1s, 5m, 1h, 1d
                        "PeriodTimespan": 1,//多少秒之后客户端可以重试
                        "Limit":2 //在统计时间段内允许的最大请求数量
                    },
                     "QoSOptions": {//服务质量与熔断,需要安装Nuget包(Ocelot.Provider.Polly) 熔断的意思是停止将请求转发到下游服务。当下游服务已经出现故障的时候再请求也是功而返,并且增加下游服务器和API网关的负担。这个功能是用的Pollly来实现的
                        "ExceptionsAllowedBeforeBreaking": 3, //允许多少个异常请求
                        "DurationOfBreak": 10, //熔断的时间,单位为秒
                        "TimeoutValue": 5000 //如果下游请求的处理时间超过多少则自如将请求设置为超时
                    },
                    "RouteClaimsRequirement": {//鉴权 通过认证中的AllowedScopes 拿到claims之后,如果要进行权限的鉴别需要添加以下配置
                        "UserType": "registered"
                    },
                    //请求头转化 UpstreamHeaderTransform 和 DownstreamHeaderTransform
                     "UpstreamHeaderTransform": {
                        "Test": "http://www.bbc.co.uk/, http://ocelot.com/",
                    },
                    "DownstreamHeaderTransform": {
                        "Location": "{DownstreamBaseUrl}, {BaseUrl}"
                    },
                     "HttpHandlerOptions": {
                        "AllowAutoRedirect": false,
                    },
                    "AddClaimsToRequest": {//Claims转化Claims转化功能可以将Claims中的值转化到请求头、Query String、或者下游的Claims中,对于Claims的转化,比较特殊的一点是它提供了一种对字符串进行解析的方法。
                        "UserType": "Claims[sub] > value[0] > |",
                        "UserId": "Claims[sub] > value[1] > |"
                    }
                },  
                {
                "DownstreamPathTemplate": "/api/values/sex/{sex}",
                "DownstreamScheme": "https",
                "DownstreamHostAndPorts": [
                    {
                    "Host": "localhost",
                    "Port": 44308
                    }
                ],
                "UpstreamPathTemplate": "/MapApi/values/sex/{sex}",
                "UpstreamHttpMethod": [ "Get" ],
                "Key": "sex"
                },
                {
                "DownstreamPathTemplate": "/api/values/name/{name}",
                "DownstreamScheme": "https",
                "DownstreamHostAndPorts": [
                    {
                    "Host": "localhost",
                    "Port": 44308
                    }
                ],
                "UpstreamPathTemplate": "/MapApi/values/name/{name}",
                "UpstreamHttpMethod": [ "Get" ],
                "Key": "name"
                },
                {
                "DownstreamPathTemplate": "/api/values/{id}",
                "DownstreamScheme": "https",
                "DownstreamHostAndPorts": [
                    {
                    "Host": "localhost",
                    "Port": 44308
                    }
                ],
                "UpstreamPathTemplate": "/MapApi/values/{id}",
                "UpstreamHttpMethod": [ "Get" ],
                "ReRouteIsCaseSensitive": true
                },
                {
                "DownstreamPathTemplate": "/api/values",
                "DownstreamScheme": "https",
                "DownstreamHostAndPorts": [
                    //{
                    //  "Host": "localhost",
                    //  "Port": 44323
                    //},
                    {
                    "Host": "localhost",
                    "Port": 44308
                    }
                ],
                "UpstreamPathTemplate": "/MapApi/values",
                "UpstreamHttpMethod": [ "Get" ],
                "QoSOptions": {//服务质量与熔断 熔断的意思是停止将请求转发到下游服务。当下游服务已经出现故障的时候再请求也是功而返,并且增加下游服务器和API网关的负担。这个功能是用的Pollly来实现的
                 "ExceptionsAllowedBeforeBreaking": 3, //允许多少个异常请求
                 "DurationOfBreak": 10, //熔断的时间,单位为秒
                 "TimeoutValue": 5000 //如果下游请求的处理时间超过多少则自如将请求设置为超时
                },
                //"HttpHandlerOptions": {
                //  "AllowAutoRedirect": false,
                //  "UseCookieContainer": false
                //},
                //"AuthenticationOptions": {
                //  "AuthenticationProviderKey": "",
                //  "AllowedScopes": []
                //}
                }
            ],
            "Aggregates": [ //聚合操作,需要在ReRotes添加Key  聚合服务目前只支持返回json 目前只支持Get方式请求下游服务 任何下游的response header并会被丢弃 如果下游服务返回404,聚合服务只是这个key的value为空,它不会返回404
                {
                "ReRouteKeys": [
                    "sex",
                    "name"
                ],
                "UpstreamPathTemplate": "/user/{sex}/{name}"
                }
            ],
            "GloabalConfiguration": {
                "RateLimitOptions": {//限流
                    "DisableRateLimitHeaders": false,//Http头  X-Rate-Limit 和 Retry-After 是否禁用
                    "QuotaExceededMessage": "Customize Tips!", // 当请求过载被截断时返回的消息
                    "HttpStatusCode": 999, //当请求过载被截断时返回的http status
                    "ClientIdHeader" : "Test" //用来识别客户端的请求头,默认是 ClientId
                }
                //  "RequestIdKey": "OcrequestId",
                //  "AdministrationPath": "/administration",
                //"BaseUrl": "https://api.mybusiness.com" 网关入口
            }
            }

添加 consul,Nuget导入Ocelot.Provider.Consul,本人重新创建了个OcelotConsul.json

        {
            "ReRoutes": [
                {
                "DownstreamPathTemplate": "/api/{url}",
                "DownstreamScheme": "http",
                "UpstreamPathTemplate": "/api/{url}",
                "UpstreamHttpMethod": [ "Get" ],
                "ServiceName": "servicea",//consul node
                "LoadBalancerOptions": {
                    "Type": "RoundRobin"//负责均衡
                },
                "UseServiceDiscovery": true
                }
            ],
            "GlobalConfiguration": {
                // "BaseUrl": "http://127.0.0.1:8887/"
                "ServiceDiscoveryProvider": {//全局地址
                "Host": "localhost",
                "Port": 8500,
                "Type": "PollConsul",
                "PollingInterval": 100
                }
            }
         }

将json文件导入项目Program.cs

         public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
               .ConfigureAppConfiguration((hostingContext, builder) =>
            {
                builder.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
                .AddJsonFile("Ocelot.json", false, true);
                //.AddJsonFile("OcelotConsul.json", false, true);
            })
                .UseStartup<Startup>();

注入服务Startup.cs

         var authenticationProviderKey = "TestKey";
            services.AddAuthentication()
                .AddJwtBearer(authenticationProviderKey, x =>
                {
                    x.Authority = "test";
                    x.Audience = "test";
                });//认证(后面详细研究)
            services.AddOcelot() //基础调用(Ocelot)
              .AddConsul()//添加Consul服务注册(需要添加Nuget Ocelot.Provider.Consul)
              .AddPolly();//服务熔断(Ocelot.Provider.Polly)

app.UseOcelot().Wait();

IdentityServer添加

Nuget IdentityServer4

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值