Asp.Net Core API网关Ocelot

首先,让我们简单了解下什么是API网关?
API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。
API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。
其次,我们了解下Ocelot框架
Ocelot的目标是使用.NET运行微服务/面向服务架构,我们需要一个统一的入口进入我们的服务,提供监控、鉴权、负载均衡等机制,也可以通过编写中间件的形式,来扩展Ocelot的功能。 Ocelot是一堆特定顺序的中间件。
Ocelot框架内部集成了IdentityServer和Consul(服务注册发现),还引入了Polly来处理进行故障处理,关于Polly,可以在这篇博客中了解更多《已被.NET基金会认可的弹性和瞬态故障处理库Polly介绍》
Ocelot开源地址:https://github.com/TomPallister/Ocelot
接下来,我们就针对Ocelot的具体用法展开介绍。
这里使用的Ocelot版本为2.0,.Net Core版本2.0
1、搭建Asp.net Core WebApi项目,引用Ocelot.dll。

Nuget控制台,执行Ocelot安装。
PM>Install-Package Ocelot
GET https://api.nuget.org/v3/registration3-gz-semver2/ocelot/index.json
OK https://api.nuget.org/v3/registration3-gz-semver2/ocelot/index.json 104 毫秒
GET https://api.nuget.org/v3/registration3-gz-semver2/ocelot/page/1.5.0-unstable0134/2.0.0.json
OK https://api.nuget.org/v3/registration3-gz-semver2/ocelot/page/1.5.0-unstable0134/2.0.0.json 108 毫秒
正在还原 J:\Demo\RichCodeBox\APIGatewayApp\APIGatewayApp.csproj 的包...
GET https://api.nuget.org/v3-flatcontainer/ocelot/index.json
OK https://api.nuget.org/v3-flatcontainer/ocelot/index.json 476 毫秒
GET https://api.nuget.org/v3-flatcontainer/ocelot/2.0.0/ocelot.2.0.0.nupkg
OK https://api.nuget.org/v3-flatcontainer/ocelot/2.0.0/ocelot.2.0.0.nupkg 125 毫秒
GET https://api.nuget.org/v3-flatcontainer/identityserver4.accesstokenvalidation/index.json
GET https://api.nuget.org/v3-flatcontainer/cachemanager.core/index.json
GET https://api.nuget.org/v3-flatcontainer/cachemanager.microsoft.extensions.configuration/index.json
GET https://api.nuget.org/v3-flatcontainer/cachemanager.microsoft.extensions.logging/index.json
GET https://api.nuget.org/v3-flatcontainer/consul/index.json
GET https://api.nuget.org/v3-flatcontainer/polly/index.json
GET https://api.nuget.org/v3-flatcontainer/identityserver4/index.json
OK https://api.nuget.org/v3-flatcontainer/identityserver4.accesstokenvalidation/index.json 133 毫秒
GET https://api.nuget.org/v3-flatcontainer/identityserver4.accesstokenvalidation/2.1.0/identityserver4.accesstokenvalidation.2.1.0.nupkg
OK https://api.nuget.org/v3-flatcontainer/cachemanager.microsoft.extensions.logging/index.json 286 毫秒
OK https://api.nuget.org/v3-flatcontainer/polly/index.json 287 毫秒
OK https://api.nuget.org/v3-flatcontainer/identityserver4.accesstokenvalidation/2.1.0/identityserver4.accesstokenvalidation.2.1.0.nupkg 160 毫秒
GET https://api.nuget.org/v3-flatcontainer/cachemanager.microsoft.extensions.logging/1.1.1/cachemanager.microsoft.extensions.logging.1.1.1.nupkg
2、修改Startup程序。
/// <summary>
///
/// </summary>
/// <param name="environment"></param>
public Startup(IHostingEnvironment environment)
{
var builder = new Microsoft.Extensions.Configuration.ConfigurationBuilder();
builder.SetBasePath(environment.ContentRootPath)
.AddJsonFile("appsettings.json", false, reloadOnChange: true)
.AddJsonFile($"appsettings.{environment.EnvironmentName}.json", optional: false, reloadOnChange: true)
.AddJsonFile("configuration.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables(); Configuration = builder.Build();
}
/// <summary>
///modified:配置
/// </summary>
public IConfigurationRoot Configuration { get; } /// <summary>
/// 配置服务
/// </summary>
/// <param name="services"></param>
public void ConfigureServices(IServiceCollection services)
{
Action<ConfigurationBuilderCachePart> settings = (x) =>
{
x.WithMicrosoftLogging(log =>
{
log.AddConsole(LogLevel.Debug); }).WithDictionaryHandle();
};
services.AddOcelot(Configuration, settings);
//services.AddMvc();
} /// <summary>
/// 配置Ocelot
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
public async void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//if (env.IsDevelopment())
//{
// app.UseDeveloperExceptionPage();
//}
await app.UseOcelot();
//app.UseMvc();
}
/// <summary>
/// 入口程序
/// </summary>
/// <param name="args"></param>
public static void Main(string[] args)
{
IWebHostBuilder builder = new WebHostBuilder();
builder.ConfigureServices(s =>
{
s.AddSingleton(builder);
});
builder.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseApplicationInsights();
var host = builder.Build();
host.Run();
}
3、配置Ocelot。
我们新建一个名为configuration的json文件,配置如下:
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/values",
"DownstreamScheme": "http",
"DownstreamHost": "localhost",
"DownstreamPort": 8801,
"UpstreamPathTemplate": "/api/values",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"HttpHandlerOptions": {
"AllowAutoRedirect": false,
"UseCookieContainer": false
},
"AuthenticationOptions": {
}
},
{
"DownstreamPathTemplate": "/api/product",
"DownstreamScheme": "http",
"DownstreamPort": 8802,
"DownstreamHost": "localhost",
"UpstreamPathTemplate": "/api/product",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"AuthenticationOptions": {
}
}
],
"GlobalConfiguration": {
"RequestIdKey": "OcRequestId",
"AdministrationPath": "/admin"
}
}
在这里,我们配置了两个服务,端口分别为8801和8802的。
Ocelot支持负载均衡(提供轮询、最少访问)。Ocelot大部分功能,都可以通过中间件来完成,也可以实现和重写中间件。
Ocelot原理非常简单,这里的配置文件,体现了上游请求和下游服务间的映射关系,你可以理解为,上游是客户端直接调用的URL ,下游,则是对应我们开发的服务。
4、新增两个WebApi项目,分别为APIUserServiec和APIProductService。
| API服务 | 端口(Port) |
| APIUserServiec | 8801 |
| APIProductService | 8802 |
解决方案如下:

5、配置VS启动端口:

依次类推,分别设置端口。
6、启动项目。
配置多个项目启动。

F5启动项目。

再通过API网关,访问商品服务:http://localhost:5000/api/product。

常见问题:
首次在启动API网关时,触发以下错误。
Sequence contains no matching element

根据错误详细信息,可知原因是由于系统调用AddIdentityServer方法时,触发异常。

刚开始,怀疑是配置文件configuration.json文件配置导致的,Ocelot2.0版,采用官方配置仍然触发该异常,由此排除这种可能。接下来,直接从github上克隆源代码,查看。

找到触发错误的地方,
private static void AddIdentityServer(this IServiceCollection services, IIdentityServerConfiguration identityServerConfiguration, IConfigurationRoot configurationRoot)
{
services.TryAddSingleton<IIdentityServerConfiguration>(identityServerConfiguration);
services.TryAddSingleton<IHashMatcher, HashMatcher>();
var identityServerBuilder = services
.AddIdentityServer(o => {
o.IssuerUri = "Ocelot";
})
.AddInMemoryApiResources(Resources(identityServerConfiguration))
.AddInMemoryClients(Client(identityServerConfiguration))
.AddResourceOwnerValidator<OcelotResourceOwnerPasswordValidator>(); //todo - refactor a method so we know why this is happening
var whb = services.First(x => x.ServiceType == typeof(IWebHostBuilder));//这个地方触发了错误
var urlFinder = new BaseUrlFinder((IWebHostBuilder)whb.ImplementationInstance);
var baseSchemeUrlAndPort = urlFinder.Find();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(o =>
{
var adminPath = configurationRoot.GetValue("GlobalConfiguration:AdministrationPath", string.Empty);
o.Authority = baseSchemeUrlAndPort + adminPath;
o.ApiName = identityServerConfiguration.ApiName;
o.RequireHttpsMetadata = identityServerConfiguration.RequireHttps;
o.SupportedTokens = SupportedTokens.Both;
o.ApiSecret = identityServerConfiguration.ApiSecret;
}); //todo - refactor naming..
if (string.IsNullOrEmpty(identityServerConfiguration.CredentialsSigningCertificateLocation) || string.IsNullOrEmpty(identityServerConfiguration.CredentialsSigningCertificatePassword))
{
identityServerBuilder.AddDeveloperSigningCredential();
}
else
{
//todo - refactor so calls method?
var cert = new X509Certificate2(identityServerConfiguration.CredentialsSigningCertificateLocation, identityServerConfiguration.CredentialsSigningCertificatePassword);
identityServerBuilder.AddSigningCredential(cert);
}
var whb = services.First(x => x.ServiceType == typeof(IWebHostBuilder));
这就代码触发了错误,是由于表达式条件不成立,导致First发生异常,这就简单了,我们修改Main函数,
把这句代码:
var builder = new WebHostBuilder();
改成:
IWebHostBuilder builder = new WebHostBuilder();
这样,就解决了问题,API网关启动成功。另外,官方例子https://github.com/TomPallister/Ocelot/blob/develop/test/Ocelot.ManualTest/Program.cs中,写法是正确的,大家自己写的时候,注意把IWebHostBuilder换成var会引发错误。
这样,使用Ocelot框架搭建API网关的工作已经完成,尝试通过访问API网关,来访问下游的服务。
此实例源码:https://gitee.com/lichaoqiang/RichCodeBox.git
欢迎大家一起研究探讨,开启你的微服务之路。
Asp.Net Core API网关Ocelot的更多相关文章
- ASP.NET Core Api网关Ocelot的中文文档
架构图 入门 不支持 配置 路由 请求聚合 GraphQL 服务发现 微服务ServiceFabric 认证 授权 Websockets 管理 流量控制 缓存 QoS服务质量 转换Headers 转换 ...
- 初探.Net Core API 网关Ocelot(一)
一.介绍 Ocelot 是基于.NetCore实现的开源的API网关,支持IdentityServer认证.Ocelot具有路由.请求聚合.服务发现.认证.鉴权.限流熔断等功能,并内置了负载均衡器与S ...
- Net Core API网关Ocelot
Ocelot在github的地址 https://github.com/TomPallister/Ocelot , 非常给力的是在课程当天完成了.NET Core 2.0的升级,升级过程请看https ...
- [Hei-Ocelot-Gateway ].Net Core Api网关Ocelot的开箱即用版本
写在前面 很多neter都有在用Ocelot做Api网关,但是Ocelot又不像kong或者其他网关一样,开箱即用.它需要你单独开一个web项目来部署,这样很多同学都在做重复的事了. 这里[Hei.O ...
- .NET Core 微服务—API网关(Ocelot) 教程 [三]
前言: 前一篇文章<.NET Core 微服务—API网关(Ocelot) 教程 [二]>已经让Ocelot和目录api(Api.Catalog).订单api(Api.Ordering)通 ...
- .NET Core 微服务—API网关(Ocelot) 教程 [二]
上篇文章(.NET Core 微服务—API网关(Ocelot) 教程 [一])介绍了Ocelot 的相关介绍. 接下来就一起来看如何使用,让它运行起来. 环境准备 为了验证Ocelot 网关效果,我 ...
- 详解ASP.NET Core API 的Get和Post请求使用方式
上一篇文章帮助大家解决问题不彻底导致博友使用的时候还是遇到一些问题,欢迎一起讨论.所以下面重点详细讲解我们常用的Get和Post请求( 以.net core2.2的Http[Verb]为方向 ,推荐该 ...
- ASP.NET Core API 接收参数去掉烦人的 [FromBody]
在测试ASP.NET Core API 项目的时候,发现后台接口参数为类型对象,对于PostMan和Ajax的Post方法传Json数据都获取不到相应的值,后来在类型参数前面加了一个[FromBody ...
- ASP.NET CORE API Swagger+IdentityServer4授权验证
简介 本来不想写这篇博文,但在网上找到的文章博客都没有完整配置信息,所以这里记录下. 不了解IdentityServer4的可以看看我之前写的入门博文 Swagger 官方演示地址 源码地址 配置Id ...
随机推荐
- hadoop(二)搭建伪分布式集群
前言 前面只是大概介绍了一下Hadoop,现在就开始搭建集群了.我们下尝试一下搭建一个最简单的集群.之后为什么要这样搭建会慢慢的分享,先要看一下效果吧! 一.Hadoop的三种运行模式(启动模式) 1 ...
- asp.net或javascript判断是否手机访问
/// <summary> /// 判断手机用户UserAgent /// </summary> /// <returns></returns> pri ...
- WPF:获取DataGrid控件单元格DataGridCell
转载:http://blog.csdn.net/jhqin/article/details/7645357 /* ------------------------------------------- ...
- Socket简单实现数据交互及上传
声明:本文为原创,如需转载请说明出处:http://www.cnblogs.com/gudu1/p/7669175.html 首先为什么要写这个呢?因为在几个月之前我还使用Socket做一个小项目,而 ...
- 基于EF Core的Code First模式的DotNetCore快速开发框架
前言 最近接了几个小单子,因为是小单子,项目规模都比较小,业务相对来说,也比较简单.所以在选择架构的时候,考虑到效率方面的因素,就采取了asp.net+entity framework中的code f ...
- 基于Redis位图实现系统用户登录统计
项目需求,试着写了一个简单登录统计,基本功能都实现了,日志数据量小.具体性能没有进行测试~ 记录下开发过程与代码,留着以后改进! 1. 需求 1. 实现记录用户哪天进行了登录,每天只记录是否登录过,重 ...
- riot.js教程【二】组件撰写准则、预处理器、标签样式和装配方法
基本要求 一个riot标签,就是展现和逻辑的组合(也就是html和JS): 以下是编写riot标签最基本的规则: 先撰写HTML,再撰写JS,JS代码可以写在<script>标签内部,但这 ...
- 【特效】hover效果之四线动画
效果预览:http://www.gbtags.com/gb/rtreplayerpreview-standalone/3102.htm html: <div class="wrap&q ...
- BZOJ-3040-最短路(road)
Description N个点,M条边的有向图,求点1到点N的最短路(保证存在).1<=N<=1000000,1<=M<=10000000 Input 第一行两个整数N.M,表 ...
- PHP中foreach()用法汇总
这篇文章主要给大家详细介绍了PHP中foreach()用法以及相关的示例,十分的细致,有需要的小伙伴可以参考下. PHP 4 引入了 foreach 结构,和 Perl 以及其他语言很像.这只是一种遍 ...