1. 程式人生 > >Asp.Net Core API閘道器Ocelot

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的具體用法展開介紹。

這裡使用的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閘道器,來訪問下游的服務。

歡迎大家一起研究探討,開啟你的微服務之路。

相關推薦

Asp.Net Core APIOcelot

首先,讓我們簡單瞭解下什麼是API閘道器?       API閘道器是一個伺服器,是系統的唯一入口。從面向物件設計的角度看,它與外觀模式類似。API閘道器封裝了系統內部架構,為每個客戶端提供一個定製的API。它可能還具有其它職責,如身份驗證、監控、負載均衡、快取、請求分片與管理、靜態響應處理。    API

[Hei-Ocelot-Gateway ].Net Core ApiOcelot的開箱即用版本

![Containerizing ASP.net core API Gateways](https://img2020.cnblogs.com/blog/641760/202008/641760-20200816225054695-1519401431.png) # 寫在前面 很多neter都有在用[O

NET Core開源APIOcelot中文文件

                        &n

.NET Core開源APIOcelot中文文件

Ocelot是一個用.NET Core實現並且開源的API閘道器,它功能強大,包括了:路由、請求

.NET Core 微服務—API(Ocelot) 教程 [二]

上篇文章(.NET Core 微服務—API閘道器(Ocelot) 教程 [一])介紹了Ocelot 的相關介紹。 接下來就一起來看如何使用,讓它執行起來。 環境準備   為了驗證Ocelot 閘道器效果,我們先建立3個webapi專案:目錄api(Api.Catalog)、訂單api(Api.Or

ASP.NET Core on K8S學習之旅(13)Ocelot API接入

本篇已加入《.NET Core on K8S學習實踐系列文章索引》,可以點選檢視更多容器化技術相關係列文章。 上一篇介紹了Ingress的基本概念和Nginx Ingress的基本配置和使用,考慮到很多團隊都在使用Ocelot作為API閘道器(包括我司)做了很多限流和鑑權的工作,因此本篇介紹一下如何使用Oce

.NET Core微服務之基於Ocelot實現API服務

一、啥是API閘道器?   API 閘道器一般放到微服務的最前端,並且要讓API 閘道器變成由應用所發起的每個請求的入口。這樣就可以明顯的簡化客戶端實現和微服務應用程式之間的溝通方式。以前的話,客戶端不得不去請求微服務A(假設為Customers),然後再到微服務B(假設為Orders),然後是微服

.NET Core微服務之基於Ocelot實現API服務(續)

一、負載均衡與請求快取 1.1 負載均衡   為了驗證負載均衡,這裡我們配置了兩個Consul Client節點,其中ClientService分別部署於這兩個節點內(192.168.80.70與192.168.80.71)。   為了更好的展示API Repsonse來自哪個節點,我們更改一下

.NET Core微服務二:Ocelot API

.NET Core微服務一:Consul服務中心 .NET Core微服務二:Ocelot API閘道器 .NET Core微服務三:polly熔斷與降級   本文的專案程式碼,在文章結尾處可以下載。 本文使用的環境:Windows10 64位 + VS 2019 + .NET Core

.Net Core微服務入門全紀錄(四)——Ocelot-API(上)

# 前言 上一篇【[.Net Core微服務入門全紀錄(三)——Consul-服務註冊與發現(下)](https://www.cnblogs.com/xhznl/p/13096891.html)】已經使用Consul完成了服務的註冊與發現,實際中光有服務註冊與發現往往是不夠的,我們需要一個統一的入口來連線客戶

.Net Core微服務入門全紀錄(五)——Ocelot-API(下)

# 前言 上一篇【[.Net Core微服務入門全紀錄(四)——Ocelot-API閘道器(上)](https://www.cnblogs.com/xhznl/p/13092535.html)】已經完成了Ocelot閘道器的基本搭建,實現了服務入口的統一。當然,這只是API閘道器的一個最基本功能,它的進階功能

.net core 微服務之ApiApi Gateway)

微服務閘道器目錄 1、 微服務引子 2、使用Nginx作為api閘道器 3、自創api閘道器(重複輪子) 3.1、構建初始化 3.2、構建中介軟體 4、結語

.NET Core微服務之基於Steeltoe整合Zuul實現統一API

一、關於Spring Cloud Zuul   API Gateway(API GW / API 閘道器),顧名思義,是出現在系統邊界上的一個面向API的、序列集中式的強管控服務,這裡的邊界是企業IT系統的邊界。   Zuul 是Netflix 提供的一個開源元件,致力於在雲平臺上提供動態路由,監

基於.NET CORE微服務框架 -Api服務管理

最近也更新了surging新的版本 更新內容: 1. 擴充套件Zookeeper封裝 2. 增加服務元資料 3. 增加API閘道器 開源地址:https://github.com/dotnetcore/surging 2.軟體環境 IDE:Visual Studio 2017 1

.NET微服務體系結構中為什麼使用Ocelot實現API

為什麼要使用API閘道器而不是直接通訊?在微服務架構中,客戶端應用程式通常需要使用

spring cloud+.net core搭建微服務架構:Api(三)

前言 國慶假期,一直沒有時間更新。 根據群裡面的同學的提問,強烈推薦大家先熟悉下spring cloud。文章下面有純潔大神的spring cloud系列。 上一章最後說了,因為服務是不對外暴露的,所以在外網要訪問服務必須通過API閘道器來完成,而spring cloud 提供了現成的Api閘道器元件zuul

Ocelot一款.NET下的API介紹

在當前微服務技術盛行的年代,大家都在大談特談微服務架構,api閘道器等等配套技術,但是我們發現,大多都是java系的一些技術,那咋

Ocelot API的實現剖析

在微軟Tech Summit 2017 大會上和大家分享了一門課程《.NET Core 在騰訊財付通的企業級應用開發實踐》,其中重點是基於ASP.NET Core打造可擴充套件的高效能企業級API閘道器,以開源的API閘道器Ocelot為基礎結合自己的業務特性,當天課程只有4

spring cloud+dotnet core搭建微服務架構:Api(三)

前言 國慶假期,一直沒有時間更新。 根據群裡面的同學的提問,強烈推薦大家先熟悉下spring cloud。文章下面有純潔大神的spring cloud系列。 上一章最後說了,因為服務是不對外暴露的,所以在外網要訪問服務必須通過API閘道器來完成,而spring cloud 提供了現成的Api閘道器元件z

Angular SPA基於Ocelot API與IdentityServer4的身份認證與授權(四)

在上一講中,我們已經完成了一個完整的案例,在這個案例中,我們可以通過Angular單頁面應用(SPA)進行登入,然後通過後端的Ocelot API閘道器整合IdentityServer4完成身份認證。在本講中,我們會討論在當前這種架構的應用程式中,如何完成使用者授權。 回顧 《Angular SPA基於Oc