博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Asp.Net Core API网关Ocelot
阅读量:6833 次
发布时间:2019-06-26

本文共 9358 字,大约阅读时间需要 31 分钟。

首先,让我们简单了解下什么是API网关?

      API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。

    API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。

其次,我们了解下Ocelot框架

 Ocelot的目标是使用.NET运行微服务/面向服务架构,我们需要一个统一的入口进入我们的服务,提供监控、鉴权、负载均衡等机制,也可以通过编写中间件的形式,来扩展Ocelot的功能。  Ocelot是一堆特定顺序的中间件。

 Ocelot框架内部集成了IdentityServer和Consul(服务注册发现),还引入了Polly来处理进行故障处理,关于Polly,可以在这篇博客中了解更多

 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程序。

///         ///         ///         ///         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();        }

  

///         ///modified:配置        ///         public IConfigurationRoot Configuration { get; }        ///         /// 配置服务        ///         ///         public void ConfigureServices(IServiceCollection services)        {            Action
settings = (x) => { x.WithMicrosoftLogging(log => { log.AddConsole(LogLevel.Debug); }).WithDictionaryHandle(); }; services.AddOcelot(Configuration, settings); //services.AddMvc(); } ///
/// 配置Ocelot /// ///
///
public async void Configure(IApplicationBuilder app, IHostingEnvironment env) { //if (env.IsDevelopment()) //{ // app.UseDeveloperExceptionPage(); //} await app.UseOcelot(); //app.UseMvc(); } ///
/// 入口程序 /// ///
public static void Main(string[] args) { IWebHostBuilder builder = new WebHostBuilder(); builder.ConfigureServices(s => { s.AddSingleton(builder); }); builder.UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup
() .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
(identityServerConfiguration); services.TryAddSingleton
(); var identityServerBuilder = services .AddIdentityServer(o => { o.IssuerUri = "Ocelot"; }) .AddInMemoryApiResources(Resources(identityServerConfiguration)) .AddInMemoryClients(Client(identityServerConfiguration)) .AddResourceOwnerValidator
(); //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网关,来访问下游的服务。

此实例源码:

欢迎大家一起研究探讨,开启你的微服务之路。

 

转载地址:http://wfikl.baihongyu.com/

你可能感兴趣的文章
右键文本文档消失——解决办法
查看>>
spring源码剖析之Spring Security安全框架
查看>>
开启关闭mysql函数功能
查看>>
运行Perl程序
查看>>
php中出现问题Call to undefined function curl_init()
查看>>
Git常用命令
查看>>
maven update project 会自动引用JAVASE1.5的问题解决办法
查看>>
Android自定义控件(一)自绘控件
查看>>
【自用】Android 得到全屏+屏幕分辨率 + (AppCompatActivity去标题栏)
查看>>
MYSQL关联查询(PHP)
查看>>
使用Log4j
查看>>
分布式日志收集框架Flume 部署说明
查看>>
string to float
查看>>
iOS开发3:UITextField控件的属性
查看>>
netty源码解析
查看>>
ODOO Unable To Find Wkhtmltopdf On This System.
查看>>
java关键字--this
查看>>
codewars065 - Backwards Read Primes
查看>>
为什么调用 FragmentPagerAdapter.notifyDataSetChanged...
查看>>
class文件加密,class文件数据库加载
查看>>