天天看點

Ocelot——初識基于.Net Core的API網關

前言

前不久看到一篇《.NET Core 在騰訊财付通的企業級應用開發實踐》,給現在研究.Net Core及想往微服務方向發展的人來了一劑強心針。于是我也就立刻去下Ocelot的源碼及去閱讀官方文檔。

Ocelot的Github位址:https://github.com/TomPallister/Ocelot

官方文檔位址:http://ocelot.readthedocs.io

環境及安裝

目前版本的Ocelot是基于.Net core 2.0開發的,是以你的項目也得是.net core2.0及以上的。

  1. 建立一個netcoreapp2.0 項目
dotnet new console -n ApiGateway
           
  1. 安裝Ocelot
dotnet add package Ocelot
           
  1. 編寫代碼

    Progarm.cs

using System;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;

namespace ApiGateway
{
    class Program
    {
        static void Main(string[] args)
        {
            IWebHostBuilder builder = new WebHostBuilder();

            builder.ConfigureServices(s => {
                s.AddSingleton(builder);
            });

            builder.UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseStartup<Startup>();

            var host = builder.Build();
            
            host.Run();
        }
    }
}
           

Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using CacheManager.Core;
using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
using System;

namespace ApiGateway
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddJsonFile("configuration.json")
                .AddEnvironmentVariables();

            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOcelot(Configuration); //此處添加Ocelot服務
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));

            app.UseOcelot().Wait();//此處使用Ocelot服務
        }
    }
}

           
  1. 編寫配置檔案

    大家可能看到了上述代碼中使用了幾個json檔案,我們将configuration.json走位Ocelot的配置檔案使用,具體配置内容下面會細說

{
    "ReRoutes": [],
    "GlobalConfiguration": {}
}
           

至此,一個可運作的API網關即搭建完成(雖然什麼都沒有)

Ocelot——初識基于.Net Core的API網關

配置

Ocelot的使用基本是靠配置完成,我根據官方文檔整理了一份對配置檔案的了解,請參考下面注釋

{
    "ReRoutes": [
    {//官方文檔ReRoutes全節點示例
      //Upstream表示上遊請求,即用戶端請求到API Gateway的請求
      "UpstreamPathTemplate": "/", //請求路徑模闆
      "UpstreamHttpMethod": [ //請求方法數組
        "Get"
      ],

      //Downstreamb表示下遊請求,即API Gateway轉發的目标服務位址
      "DownstreamScheme": "http", //請求協定,目前應該是支援http和https
      "DownstreamHost": "localhost", //請求服務位址,應該是可以是IP及域名
      "DownstreamPort": 51779, //端口号
      "DownstreamPathTemplate": "/", //下遊請求位址模闆
      "RouteClaimsRequirement": { //标記該路由是否需要認證
        "UserType": "registered" //示例,K/V形式,授權聲明,授權token中會包含一些claim,如填寫則會判斷是否和token中的一緻,不一緻則不準通路
      },
      //以下三個是将access claims轉為使用者的Header Claims,QueryString,該功能隻有認證後可用
      "AddHeadersToRequest": { //
        "UserType": "Claims[sub] > value[0] > |", //示例
        "UserId": "Claims[sub] > value[1] > |"//示例
      },
      "AddClaimsToRequest": {},
      "AddQueriesToRequest": {},

      "RequestIdKey": "", //設定用戶端的請求辨別key,此key在請求header中,會轉發到下遊請求中
      "FileCacheOptions": { //緩存設定
        "TtlSeconds": 15, //ttl秒被設定為15,這意味着緩存将在15秒後過期。
        "Region": "" //緩存region,可以使用administrator API清除
      },
      "ReRouteIsCaseSensitive": false, //路由是否比對大小寫
      "ServiceName": "", //服務名稱,服務發現時必填

      "QoSOptions": { //斷路器配置,目前Ocelot使用的Polly
        "ExceptionsAllowedBeforeBreaking": 0, //打開斷路器之前允許的例外數量。
        "DurationOfBreak": 0,                 //斷路器複位之前,打開的時間(毫秒)
        "TimeoutValue": 0                     //請求逾時時間(毫秒)
      },
      "LoadBalancer": "", //負載均衡 RoundRobin(輪詢)/LeastConnection(最少連接配接數)
      "RateLimitOptions": { //官方文檔未說明
        "ClientWhitelist": [],
        "EnableRateLimiting": false,
        "Period": "",
        "PeriodTimespan": 0,
        "Limit": 0
      },
      "AuthenticationOptions": { //認證配置
        "AuthenticationProviderKey": "", //這個key對應的是代碼中.AddJWTBreark中的Key
        "AllowedScopes": []//使用範圍
      },
      "HttpHandlerOptions": {
        "AllowAutoRedirect": true, //訓示請求是否應該遵循重定向響應。 如果請求應該自動遵循來自Downstream資源的重定向響應,則将其設定為true; 否則為假。 預設值是true。
        "UseCookieContainer": true //該值訓示處理程式是否使用CookieContainer屬性來存儲伺服器Cookie,并在發送請求時使用這些Cookie。 預設值是true。
      },
      "UseServiceDiscovery": false //使用服務發現,目前Ocelot隻支援Consul的服務發現
    }
    ],
    "GlobalConfiguration": {}
}
           

路由 Routing

路由是API網關的标配,Ocelot會将上遊請求(Upstream)轉發到下遊請求(Downstream)

示例:

{
    "DownstreamPathTemplate": "/api/posts/{postId}",
    "DownstreamScheme": "https",
    "DownstreamPort": 80,
    "DownstreamHost" "localhost",
    "UpstreamPathTemplate": "/posts/{postId}",
    "UpstreamHttpMethod": [ "Put", "Delete" ]
}
           

其中使用{任意字元}包覆的作為占位符變量使用,轉發請求時,會将下遊請求的{任意字元}替換為上遊請求的{任意字元}。

Ocelot的預設路由是不區分大小寫的,如果需要區分大小寫,需要增加如下配置

"ReRouteIsCaseSensitive": true
           

了解路由後一個基礎的API網關就建立而成了,下一篇講介紹下其他功能