前言
前不久看到一篇《.NET Core 在騰訊財付通的企業級應用開發實踐》,給現在研究.Net Core及想往微服務方向發展的人來了一劑強心針。於是我也就立刻去下Ocelot的源碼及去閱讀官方文檔。
Ocelot的Github地址:https://github.com/TomPallister/Ocelot
官方文檔地址:http://ocelot.readthedocs.io
環境及安裝
目前版本的Ocelot是基於.Net core 2.0開發的,所以你的項目也得是.net core2.0及以上的。
- 新建一個netcoreapp2.0 項目
dotnet new console -n ApiGateway
- 安裝Ocelot
dotnet add package Ocelot
- 編寫代碼
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服務
}
}
}
- 編寫配置文件
大家可能看到了上述代碼中使用了幾個json文件,我們將configuration.json走位Ocelot的配置文件使用,具體配置內容下面會細說
{
"ReRoutes": [],
"GlobalConfiguration": {}
}
至此,一個可運行的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網關就建立而成了,下一篇講介紹下其他功能