Asp .Net Core 系列:集成 Ocelot+Consul实现网关、服务注册、服务发现
什么是Ocelot?
Ocelot是一个开源的ASP.NET Core微服务网关,它提供了API网关所需的所有功能,如路由、认证、限流、监控等。
Ocelot是一个简单、灵活且功能强大的API网关,它可以与现有的服务集成,并帮助您保护、监控和扩展您的微服务。
以下是Ocelot的一些主要功能:
- 路由管理:Ocelot允许您定义路由规则,将请求路由到正确的微服务。
- 认证和授权:Ocelot支持多种认证机制,如JWT、OAuth等,并允许您定义访问控制策略,确保只有授权的用户才能访问特定的API。
- 限流和速率限制:Ocelot提供了一些内置的限流和速率限制功能,以确保您的服务不会受到过度的请求压力。
- 监控和日志:Ocelot可以收集和显示各种度量指标,帮助您了解您的服务的性能和行为。此外,它还可以将日志记录到各种日志源,以便您进行分析和故障排除。
- 集成:Ocelot可以与现有的服务集成,包括Kubernetes、Consul等。
- 易于扩展:Ocelot的设计使其易于扩展,您可以编写自己的中间件来处理特定的逻辑,例如修改请求或响应、添加自定义的认证机制等。
- 可扩展的配置:Ocelot使用JSON配置文件进行配置,这意味着您可以轻松地根据需要进行配置更改,而无需重新编译代码。
总之,Ocelot是一个功能强大且易于使用的API网关,可以帮助您保护、监控和扩展您的微服务。
Asp .Net Core 集成 Ocelot
要在ASP.NET Core中集成Ocelot,您可以按照以下步骤进行操作:
- 安装Ocelot NuGet包:
在您的ASP.NET Core项目中,打开终端或NuGet包管理器控制台,并运行以下命令来安装Ocelot的NuGet包:
dotnet add package Ocelot
- 添加Ocelot配置文件:
{
"Routes": [ //这里注意一下版本(旧版本用ReRoutes)
{
"DownstreamPathTemplate": "/api/{controller}", //下游路径模板
"DownstreamScheme": "http", //下游方案
//"DownstreamHostAndPorts": [
// {
// "Host": "localhost",
// "Port": "5014"
// }
//], //下游主机和端口
"UpstreamPathTemplate": "/api/product/{controller}", //上游路径模板
"UpstreamHttpMethod": [], //上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法
"ServiceName": "api-product-service", //请求服务名称
"LoadBalancerOptions": {
"Type": "LeastConnection" //负载均衡算法:目前 Ocelot 有RoundRobin 和LeastConnection算法
}
}
],
"GlobalConfiguration": {
"BaseUrl": "http://localhost:5015", //进行标头查找和替换以及某些管理配置
"ServiceDiscoveryProvider": {
"Scheme": "http",
"Host": "127.0.0.1", //你的Consul的ip地址
"Port": 8500, //你的Consul的端口
"Type": "Consul" //类型
//"ConfigurationKey": "Consul" //指定配置键,键入您的配置
}
}
}
- 配置Ocelot服务:
builder.Services.AddOcelot();
在Configure方法中配置请求管道并添加Ocelot中间件:
app.UseOcelot().Wait();
Ocelot 集成 Consul
要将Ocelot集成到Consul中,您可以按照以下步骤进行操作:
- 安装依赖项:
在您的ASP.NET Core项目中,安装Ocelot和Consul的NuGet包。您可以使用以下命令来安装这些包:
dotnet add package Ocelot.Provider.Consul
- 配置Ocelot:
在Ocelot的配置中,您需要指定Consul作为服务发现和配置的提供者。在Ocelot的配置文件(例如appsettings.json)中,添加以下内容:
{
"GlobalConfiguration": {
"BaseUrl": "http://localhost:5015", //进行标头查找和替换以及某些管理配置
"ServiceDiscoveryProvider": {
"Scheme": "http",
"Host": "127.0.0.1", //你的Consul的ip地址
"Port": 8500, //你的Consul的端口
"Type": "Consul" //类型
//"ConfigurationKey": "Consul" //指定配置键,键入您的配置
}
}
}
确保将ConsulHost和ConsulPort设置为Consul服务器的正确地址和端口。
- 启动Ocelot:
在您的ASP.NET Core应用程序中启动Ocelot。您可以在Startup.cs文件中添加以下代码:
builder.Services.AddOcelot().AddConsul();
全部代码
Consul相关代码
namespace MCode.Common.Extensions.Consul
{
public class ConsulOptions
{
/// <summary>
/// 当前应用IP
/// </summary>
public string IP { get; set; }
/// <summary>
/// 当前应用端口
/// </summary>
public int Port { get; set; }
/// <summary>
/// 当前服务名称
/// </summary>
public string ServiceName { get; set; }
/// <summary>
/// Consul集群IP
/// </summary>
public string ConsulIP { get; set; }
/// <summary>
/// Consul集群端口
/// </summary>
public int ConsulPort { get; set; }
/// <summary>
/// 权重
/// </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服务注册信息
var consulOptions = configuration.GetSection("Consul").Get<ConsulOptions>();
// 通过consul提供的注入方式注册consulClient
services.AddConsul(options => options.Address = new Uri($"http://{consulOptions.ConsulIP}:{consulOptions.ConsulPort}"));
// 通过consul提供的注入方式进行服务注册
var httpCheck = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册
Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔,或者称为心跳间隔
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检查服务
/// </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">服务集合</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">应用程序建造者</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>
/// 网关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>
/// 网关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>
/// 服务名称
/// </summary>
public string ServiceName { get; set; }
/// <summary>
/// API信息
/// </summary>
public OpenApiInfo ApiInfo { get; set; }
/// <summary>
/// Xml注释文件
/// </summary>
public string[] XmlCommentFiles { get; set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="serviceName">服务名称</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 服务扩展
/// </summary>
public static class SwaggerServiceExtensions
{
/// <summary>
/// 添加 Swagger 服务
/// </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 = "请输入 bearer 认证"
});
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"
// }
//], //下游主机和端口
"UpstreamPathTemplate": "/api/product/{controller}", //上游路径模板
"UpstreamHttpMethod": [], //上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法
"ServiceName": "api-product-service", //请求服务名称
"LoadBalancerOptions": {
"Type": "LeastConnection" //负载均衡算法:目前 Ocelot 有RoundRobin 和LeastConnection算法
}
}
],
"GlobalConfiguration": {
"BaseUrl": "http://localhost:5015", //进行标头查找和替换以及某些管理配置
"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 = "产品服务" }, 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
}
}
效果


Asp .Net Core 系列:集成 Ocelot+Consul实现网关、服务注册、服务发现的更多相关文章
- asp.net core系列 60 Ocelot 构建服务认证示例
一.概述 在Ocelot中,为了保护下游api资源,用户访问时需要进行认证鉴权,这需要在Ocelot 网关中添加认证服务.添加认证后,ReRoutes路由会进行身份验证,并使用Ocelot的基于声明的 ...
- asp.net core系列 59 Ocelot 构建基础项目示例
一.入门概述 从这篇开始探讨Ocelot,Ocelot是一个.NET API网关,仅适用于.NET Core,用于.NET面向微服务/服务的架构中.当客户端(web站点.ios. app 等)访问we ...
- asp.net core系列 61 Ocelot 构建服务发现简单示例
一.概述 Ocelot允许指定服务发现提供程序,如Consul或Eureka. 这二个中间件是用来实现:服务治理或秒服务发现,服务发现查找Ocelot正在转发请求的下游服务的主机和端口.目前Ocelo ...
- 【目录】asp.net core系列篇
随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...
- .Net Core 商城微服务项目系列(二):使用Ocelot + Consul构建具备服务注册和发现功能的网关
1.服务注册 在上一篇的鉴权和登录服务中分别通过NuGet引用Consul这个包,同时新增AppBuilderExtensions类: public static class AppBuilderEx ...
- .net core Ocelot Consul 实现API网关 服务注册 服务发现 负载均衡
大神张善友 分享过一篇 <.NET Core 在腾讯财付通的企业级应用开发实践>里面就是用.net core 和 Ocelot搭建的可扩展的高性能Api网关. Ocelot(http:// ...
- asp.net core 系列 18 web服务器实现
一. ASP.NET Core Module 在介绍ASP.NET Core Web实现之前,先来了解下ASP.NET Core Module.该模块是插入 IIS 管道的本机 IIS 模块(本机是指 ...
- asp.net core 系列 16 Web主机 IWebHostBuilder
一.概述 在asp.net core中,Host主机负责应用程序启动和生存期管理.host主机包括Web 主机(IWebHostBuilder)和通用主机(IHostBuilder).Web 主机是适 ...
- Asp.net Core 系列之--5.认证、授权与自定义权限的实现
ChuanGoing 2019-11-24 asp.net core系列已经来到了第五篇,通过之前的基础介绍,我们了解了事件订阅/发布的eventbus整个流程,初探dapper ORM实现,并且简单 ...
- (8)ASP.NET Core3.1 Ocelot Consul服务注册与发现
1.服务注册与发现(Service Discovery) ●服务注册:我们通过在每个服务实例写入注册代码,实例在启动的时候会先去注册中心(例如Consul.ZooKeeper.etcd.Eureka) ...
随机推荐
- 3.1 IDA Pro编写IDC脚本入门
IDA Pro内置的IDC脚本语言是一种灵活的.C语言风格的脚本语言,旨在帮助逆向工程师更轻松地进行反汇编和静态分析.IDC脚本语言支持变量.表达式.循环.分支.函数等C语言中的常见语法结构,并且还提 ...
- (Good topic)哈希表:最长回文串(3.19 leetcode每日打卡)
给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串. 在构造过程中,请注意区分大小写.比如 "Aa" 不能当做一个回文字符串. 注意: 假设字符串的长度不 ...
- Android Recyclerview的item间距实现
Recyclerview中,提供了一个方法addItemDecoration给我们用于设置item的分割线 下面提供几个常见的分割线效果 注: 下面的SizeUtils是AndroidUtilCode ...
- ${pageContext.request.contextPath}的理解和用法
在做房产管理系统的时候用到了<from>标签的这个用法,这就来解释一下 ${pageContext.request.contextPath} 是JSP取得绝对路径的方法,等价于 ${pag ...
- Ubuntu安装odoo16
虽然odoo17已经在10月份发布了,但笔者并不愿意立时升级:一方面没有迫切的需要去升级,仿佛没有odoo17就没法后续的工作一样:另一方面,我倒是更希望在双数版本发布的时候再升级.为此继续使用odo ...
- Android OpenGL ES入门
1.OpenGL 和OpenGL ES OpenGL(Open Graphics Library)是一种用于渲染2D和3D图形的跨平台编程接口.OpenGL提供了一套标准的函数和接口,使开发人员能够在 ...
- javascript+php 实现blob加密视频(html video)
1.mp4地址加密为blob链接在html5的video标签展示 PHP: 1 $file_path = "...mp4"; //视频文件地址 2 ob_end_clean(); ...
- 【JMeter】使用nmon进行性能资源监控
使用nmon进行性能资源监控 目录 使用nmon进行性能资源监控 一.前言 二.nmon的下载安装 1.查看系统信息 2.查看CPU信息 2.下载 3.解压 4.一个小问题 三.在性能测试时使用命令行 ...
- 解决This application failed to start because cannot find or load the qt platform plugin 'xcb'
问题描述: 在使用linux系统训练自己的数据集合时,出现了上述问题,首先第一个想法就是先Google,但是在看了一些国内外的文章后依然没有将问题解决 问题原因: 这是由于这几天我在安装cuda.cu ...
- Java并发(二十一)----wait notify介绍
1.小故事 - 为什么需要 wait 由于条件不满足(没烟干不了活啊,等小M把烟送过来),小南不能继续进行计算 但小南如果一直占用着锁,其它人就得一直阻塞,效率太低 于是老王单开了一间休息室(调用 w ...