什么是Ocelot?
Ocelot是一個(gè)開(kāi)源的ASP.NET Core微服務(wù)網(wǎng)關(guān),它提供了API網(wǎng)關(guān)所需的所有功能,如路由、認(rèn)證、限流、監(jiān)控等。
Ocelot是一個(gè)簡(jiǎn)單、靈活且功能強(qiáng)大的API網(wǎng)關(guān),它可以與現(xiàn)有的服務(wù)集成,并幫助您保護(hù)、監(jiān)控和擴(kuò)展您的微服務(wù)。
以下是Ocelot的一些主要功能:
- 路由管理:Ocelot允許您定義路由規(guī)則,將請(qǐng)求路由到正確的微服務(wù)。
- 認(rèn)證和授權(quán):Ocelot支持多種認(rèn)證機(jī)制,如JWT、OAuth等,并允許您定義訪問(wèn)控制策略,確保只有授權(quán)的用戶才能訪問(wèn)特定的API。
- 限流和速率限制:Ocelot提供了一些內(nèi)置的限流和速率限制功能,以確保您的服務(wù)不會(huì)受到過(guò)度的請(qǐng)求壓力。
- 監(jiān)控和日志:Ocelot可以收集和顯示各種度量指標(biāo),幫助您了解您的服務(wù)的性能和行為。此外,它還可以將日志記錄到各種日志源,以便您進(jìn)行分析和故障排除。
- 集成:Ocelot可以與現(xiàn)有的服務(wù)集成,包括Kubernetes、Consul等。
- 易于擴(kuò)展:Ocelot的設(shè)計(jì)使其易于擴(kuò)展,您可以編寫(xiě)自己的中間件來(lái)處理特定的邏輯,例如修改請(qǐng)求或響應(yīng)、添加自定義的認(rèn)證機(jī)制等。
- 可擴(kuò)展的配置:Ocelot使用JSON配置文件進(jìn)行配置,這意味著您可以輕松地根據(jù)需要進(jìn)行配置更改,而無(wú)需重新編譯代碼。
總之,Ocelot是一個(gè)功能強(qiáng)大且易于使用的API網(wǎng)關(guān),可以幫助您保護(hù)、監(jiān)控和擴(kuò)展您的微服務(wù)。
Asp .Net Core 集成 Ocelot
要在ASP.NET Core中集成Ocelot,您可以按照以下步驟進(jìn)行操作:
- 安裝Ocelot NuGet包:
在您的ASP.NET Core項(xiàng)目中,打開(kāi)終端或NuGet包管理器控制臺(tái),并運(yùn)行以下命令來(lái)安裝Ocelot的NuGet包:
dotnet add package Ocelot
- 添加Ocelot配置文件:
{
"Routes": [ //這里注意一下版本(舊版本用ReRoutes)
{
"DownstreamPathTemplate": "/api/{controller}", //下游路徑模板
"DownstreamScheme": "http", //下游方案
//"DownstreamHostAndPorts": [
// {
// "Host": "localhost",
// "Port": "5014"
// }
//], //下游主機(jī)和端口
"UpstreamPathTemplate": "/api/product/{controller}", //上游路徑模板
"UpstreamHttpMethod": [], //上游請(qǐng)求方法,可以設(shè)置特定的 HTTP 方法列表或設(shè)置空列表以允許其中任何方法
"ServiceName": "api-product-service", //請(qǐng)求服務(wù)名稱
"LoadBalancerOptions": {
"Type": "LeastConnection" //負(fù)載均衡算法:目前 Ocelot 有RoundRobin 和LeastConnection算法
}
}
],
"GlobalConfiguration": {
"BaseUrl": "http://localhost:5015", //進(jìn)行標(biāo)頭查找和替換以及某些管理配置
"ServiceDiscoveryProvider": {
"Scheme": "http",
"Host": "127.0.0.1", //你的Consul的ip地址
"Port": 8500, //你的Consul的端口
"Type": "Consul" //類型
//"ConfigurationKey": "Consul" //指定配置鍵,鍵入您的配置
}
}
}
- 配置Ocelot服務(wù):
builder.Services.AddOcelot();
在Configure
方法中配置請(qǐng)求管道并添加Ocelot中間件:
app.UseOcelot().Wait();
Ocelot 集成 Consul
要將Ocelot集成到Consul中,您可以按照以下步驟進(jìn)行操作:
- 安裝依賴項(xiàng):
在您的ASP.NET Core項(xiàng)目中,安裝Ocelot和Consul的NuGet包。您可以使用以下命令來(lái)安裝這些包:
dotnet add package Ocelot.Provider.Consul
- 配置Ocelot:
在Ocelot的配置中,您需要指定Consul作為服務(wù)發(fā)現(xiàn)和配置的提供者。在Ocelot的配置文件(例如appsettings.json)中,添加以下內(nèi)容:
{
"GlobalConfiguration": {
"BaseUrl": "http://localhost:5015", //進(jìn)行標(biāo)頭查找和替換以及某些管理配置
"ServiceDiscoveryProvider": {
"Scheme": "http",
"Host": "127.0.0.1", //你的Consul的ip地址
"Port": 8500, //你的Consul的端口
"Type": "Consul" //類型
//"ConfigurationKey": "Consul" //指定配置鍵,鍵入您的配置
}
}
}
確保將ConsulHost
和ConsulPort
設(shè)置為Consul服務(wù)器的正確地址和端口。
- 啟動(dòng)Ocelot:
在您的ASP.NET Core應(yīng)用程序中啟動(dòng)Ocelot。您可以在Startup.cs
文件中添加以下代碼:
builder.Services.AddOcelot().AddConsul();
全部代碼
Consul相關(guān)代碼
namespace MCode.Common.Extensions.Consul
{
public class ConsulOptions
{
/// <summary>
/// 當(dāng)前應(yīng)用IP
/// </summary>
public string IP { get; set; }
/// <summary>
/// 當(dāng)前應(yīng)用端口
/// </summary>
public int Port { get; set; }
/// <summary>
/// 當(dāng)前服務(wù)名稱
/// </summary>
public string ServiceName { get; set; }
/// <summary>
/// Consul集群IP
/// </summary>
public string ConsulIP { get; set; }
/// <summary>
/// Consul集群端口
/// </summary>
public int ConsulPort { get; set; }
/// <summary>
/// 權(quán)重
/// </summary>
public int? Weight { get; set; }
}
}
using Consul.AspNetCore;
using Consul;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Builder;
namespace MCode.Common.Extensions.Consul
{
public static class ConsulServiceExtensions
{
/// <summary>
/// 向容器中添加Consul必要的依賴注入
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
/// <returns></returns>
public static IServiceCollection AddMCodeConsul(this IServiceCollection services)
{
var configuration = services.BuildServiceProvider().GetRequiredService<IConfiguration>();
// 配置consul服務(wù)注冊(cè)信息
var consulOptions = configuration.GetSection("Consul").Get<ConsulOptions>();
// 通過(guò)consul提供的注入方式注冊(cè)consulClient
services.AddConsul(options => options.Address = new Uri($"http://{consulOptions.ConsulIP}:{consulOptions.ConsulPort}"));
// 通過(guò)consul提供的注入方式進(jìn)行服務(wù)注冊(cè)
var httpCheck = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服務(wù)啟動(dòng)多久后注冊(cè)
Interval = TimeSpan.FromSeconds(10),//健康檢查時(shí)間間隔,或者稱為心跳間隔
HTTP = $"http://{consulOptions.IP}:{consulOptions.Port}/health",//健康檢查地址
Timeout = TimeSpan.FromSeconds(10)
};
// Register service with consul
services.AddConsulServiceRegistration(options =>
{
options.Checks = new[] { httpCheck };
options.ID = Guid.NewGuid().ToString();
options.Name = consulOptions.ServiceName;
options.Address = consulOptions.IP;
options.Port = consulOptions.Port;
options.Meta = new Dictionary<string, string>() { { "Weight", consulOptions.Weight.HasValue ? consulOptions.Weight.Value.ToString() : "1" } };
options.Tags = new[] { $"urlprefix-/{consulOptions.ServiceName}" }; //添加
});
return services;
}
/// <summary>
/// 配置Consul檢查服務(wù)
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseConsulCheckService(this IApplicationBuilder app)
{
app.Map("/health", app =>
{
app.Run(async context =>
{
await Task.Run(() => context.Response.StatusCode = 200);
});
});
return app;
}
}
}
Cors
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MCode.Common.Extensions.Cors
{
public static class CorsServiceExtensions
{
private readonly static string PolicyName = "MCodeCors";
/// <summary>
/// 添加跨域
/// </summary>
/// <param name="services">服務(wù)集合</param>
/// <returns></returns>
public static IServiceCollection AddMCodeCors(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
//origin microsoft.aspnetcore.cors
return services.AddCors(options =>
{
options.AddPolicy(PolicyName, policy =>
{
policy.SetIsOriginAllowed(_ => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials();
});
});
}
/// <summary>
/// 使用跨域
/// </summary>
/// <param name="app">應(yīng)用程序建造者</param>
/// <returns></returns>
public static IApplicationBuilder UseMCodeCors(this IApplicationBuilder app)
{
return app.UseCors(PolicyName);
}
}
}
Swagger
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MCode.Common.Extensions.Swagger
{
/// <summary>
/// 網(wǎng)關(guān)Swagger配置
/// </summary>
public class OcelotSwaggerOptions
{
public List<SwaggerEndPoint> SwaggerEndPoints { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MCode.Common.Extensions.Swagger
{
/// <summary>
/// 網(wǎng)關(guān)Swagger配置
/// </summary>
public class OcelotSwaggerOptions
{
public List<SwaggerEndPoint> SwaggerEndPoints { get; set; }
}
}
using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MCode.Common.Extensions.Swagger
{
/// <summary>
/// Swagger配置
/// </summary>
public class SwaggerOptions
{
/// <summary>
/// 服務(wù)名稱
/// </summary>
public string ServiceName { get; set; }
/// <summary>
/// API信息
/// </summary>
public OpenApiInfo ApiInfo { get; set; }
/// <summary>
/// Xml注釋文件
/// </summary>
public string[] XmlCommentFiles { get; set; }
/// <summary>
/// 構(gòu)造函數(shù)
/// </summary>
/// <param name="serviceName">服務(wù)名稱</param>
/// <param name="apiInfo">API信息</param>
/// <param name="xmlCommentFiles">Xml注釋文件</param>
public SwaggerOptions(string serviceName, OpenApiInfo apiInfo, string[] xmlCommentFiles = null)
{
ServiceName = !string.IsNullOrWhiteSpace(serviceName) ? serviceName : throw new ArgumentException("serviceName parameter not config.");
ApiInfo = apiInfo;
XmlCommentFiles = xmlCommentFiles;
}
}
}
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
namespace MCode.Common.Extensions.Swagger
{
/// <summary>
/// Swagger 服務(wù)擴(kuò)展
/// </summary>
public static class SwaggerServiceExtensions
{
/// <summary>
/// 添加 Swagger 服務(wù)
/// </summary>
/// <param name="services"></param>
/// <param name="swaggerOptions"></param>
/// <returns></returns>
public static IServiceCollection AddMCodeSwagger(this IServiceCollection services, SwaggerOptions swaggerOptions)
{
services.AddSingleton(swaggerOptions);
SwaggerGenServiceCollectionExtensions.AddSwaggerGen(services, c =>
{
c.SwaggerDoc(swaggerOptions.ServiceName, swaggerOptions.ApiInfo);
if (swaggerOptions.XmlCommentFiles != null)
{
foreach (string xmlCommentFile in swaggerOptions.XmlCommentFiles)
{
string str = Path.Combine(AppContext.BaseDirectory, xmlCommentFile);
if (File.Exists(str)) c.IncludeXmlComments(str, true);
}
}
SwaggerGenOptionsExtensions.CustomSchemaIds(c, x => x.FullName);
c.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
Description = "請(qǐng)輸入 bearer 認(rèn)證"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearerAuth" }
},
new string[] {}
}
});
});
return services;
}
/// <summary>
/// 使用 Swagger UI
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseMCodeSwagger(this IApplicationBuilder app)
{
string serviceName = app.ApplicationServices.GetRequiredService<SwaggerOptions>().ServiceName;
SwaggerUIBuilderExtensions.UseSwaggerUI(SwaggerBuilderExtensions.UseSwagger(app), c =>
{
c.SwaggerEndpoint("/swagger/" + serviceName + "/swagger.json", serviceName);
});
return app;
}
public static IServiceCollection AddMCodeOcelotSwagger(this IServiceCollection services, OcelotSwaggerOptions ocelotSwaggerOptions)
{
services.AddSingleton(ocelotSwaggerOptions);
SwaggerGenServiceCollectionExtensions.AddSwaggerGen(services);
return services;
}
public static IApplicationBuilder UseMCodeOcelotSwagger(this IApplicationBuilder app)
{
OcelotSwaggerOptions ocelotSwaggerOptions = app.ApplicationServices.GetService<OcelotSwaggerOptions>();
if (ocelotSwaggerOptions == null || ocelotSwaggerOptions.SwaggerEndPoints == null)
{
return app;
}
SwaggerUIBuilderExtensions.UseSwaggerUI(SwaggerBuilderExtensions.UseSwagger(app), c =>
{
foreach (SwaggerEndPoint swaggerEndPoint in ocelotSwaggerOptions.SwaggerEndPoints)
{
c.SwaggerEndpoint(swaggerEndPoint.Url, swaggerEndPoint.Name);
}
});
return app;
}
}
}
MCode.ApiGateway.Program
using MCode.Common.Extensions.Swagger;
using MCode.Common.Extensions.Consul;
using MCode.Common.Extensions.Cors;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Ocelot.Provider.Consul;
using Microsoft.AspNetCore.Hosting;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseUrls(builder.Configuration.GetValue<string>("Url") ?? "");
//builder.Configuration.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("ocelot.json", false, true);
// Add services to the container.
builder.Services.AddMCodeConsul();
builder.Services.AddMCodeCors();
builder.Services.AddMCodeOcelotSwagger(new OcelotSwaggerOptions { SwaggerEndPoints = new List<SwaggerEndPoint> { new SwaggerEndPoint { Name = "api-product-service", Url= "http://localhost:5014/swagger/api-product-service/swagger.json" } } });
builder.Services.AddOcelot().AddConsul();
builder.Services.AddControllers();
var app = builder.Build();
app.UseMCodeCors();
app.UseMCodeOcelotSwagger();
app.UseConsulCheckService();
// Configure the HTTP request pipeline.
app.UseAuthorization();
app.UseOcelot().Wait();
app.Run();
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"Routes": [ //這里注意一下版本(舊版本用ReRoutes)
{
"DownstreamPathTemplate": "/api/{controller}", //下游路徑模板
"DownstreamScheme": "http", //下游方案
//"DownstreamHostAndPorts": [
// {
// "Host": "localhost",
// "Port": "5014"
// }
//], //下游主機(jī)和端口
"UpstreamPathTemplate": "/api/product/{controller}", //上游路徑模板
"UpstreamHttpMethod": [], //上游請(qǐng)求方法,可以設(shè)置特定的 HTTP 方法列表或設(shè)置空列表以允許其中任何方法
"ServiceName": "api-product-service", //請(qǐng)求服務(wù)名稱
"LoadBalancerOptions": {
"Type": "LeastConnection" //負(fù)載均衡算法:目前 Ocelot 有RoundRobin 和LeastConnection算法
}
}
],
"GlobalConfiguration": {
"BaseUrl": "http://localhost:5015", //進(jìn)行標(biāo)頭查找和替換以及某些管理配置
"ServiceDiscoveryProvider": {
"Scheme": "http",
"Host": "127.0.0.1", //你的Consul的ip地址
"Port": 8500, //你的Consul的端口
"Type": "Consul" //類型
//"ConfigurationKey": "Consul" //指定配置鍵,鍵入您的配置
}
},
"Url": "http://localhost:5015",
"Consul": {
"ConsulIP": "127.0.0.1",
"ConsulPort": "8500",
"ServiceName": "api-gateway",
"Ip": "localhost",
"Port": "5015",
"Weight": 1
},
"AllowedHosts": "*"
}
MCode.Product.Api.Program
using MCode.Product.Api;
using MCode.Common.Extensions.Consul;
using MCode.Common.Extensions.Cors;
using MCode.Common.Extensions.Swagger;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.WebHost.UseUrls(builder.Configuration.GetValue<string>("Url") ?? "");
builder.Services.AddControllers();
builder.Services.AddMCodeConsul();
builder.Services.AddMCodeCors();
builder.Services.AddMCodeSwagger(new SwaggerOptions("api-product-service", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "產(chǎn)品服務(wù)" }, new string[] { "MCode.Product.Api.xml" }));
var app = builder.Build();
app.UseAuthorization();
app.UseMCodeCors();
app.UseMCodeSwagger();
app.UseConsulCheckService();
app.MapControllers();
app.Run();
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Url": "http://localhost:5014",
"Consul": {
"ConsulIP": "127.0.0.1",
"ConsulPort": "8500",
"ServiceName": "api-product-service",
"Ip": "localhost",
"Port": "5014",
"Weight": 1
}
}
效果
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-811329.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-811329.html
到了這里,關(guān)于Net Core Ocelot+Consul實(shí)現(xiàn)網(wǎng)關(guān)、服務(wù)注冊(cè)、服務(wù)發(fā)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!