当前位置: 首页 > news >正文

Ocelot\Consul\.NetCore的微服务应用案例

案例资料链接:https://download.csdn.net/download/ly1h1/90733765

1.效果

实现两个微服务ServerAPI1和ServerAPI2的负载均衡以及高可用。具体原理,看以下示意图。

2.部署条件

 1、腾讯云的轻量化服务器

 2、WindowServer2016 

 3、.NETCore7.0

 4、Negut 包:Consul1.7.14.7、Ocelot16.0.1、Ocelot.Provider.Conusl16.0.1

 5、.NET捆绑托管 dotnet-hosting-9.0.4-win.exe

3.开放端口

 2.1 云服务安全组端口开放

  端口:5000,是服务1

  端口:5001,是服务2

  端口:5010,是Ocelot网关

  端口:8050/8030/8031/8032,是Consul的端口

  • 8500 是核心 API 端口,必知;

  • 8030/31/32 需结合具体配置,可能是用户自定义的服务或工具端口。

2.2 服务器配置入栈站规则

3.Consul配置(部署可参考链接Consul安装部署(Windows环境)-CSDN博客)

{"datacenter": "dc1","data_dir": "C:\\consul\\data","node_name": "node-10-4-0-7","bind_addr": "0.0.0.0","advertise_addr": "10.0.4.7",(云服务内网的IP)"client_addr": "0.0.0.0","ports": {"http": 8500,"dns": 8600,"grpc": -1},"ui_config": {"enabled": true},"server": true,"bootstrap": true,"log_level": "ERROR","disable_update_check": true,"performance": {"raft_multiplier": 3,"leave_drain_time": "5s"}
}

4.Ocelot代码

4.1 Progrm.CS

using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Ocelot.Provider.Consul; // 引入 Consul 支持var builder = WebApplication.CreateBuilder(args);// 1. 配置 Kestrel 只监听 5010 端口(不绑定特定 IP)
builder.WebHost.UseUrls("http://*:5010"); // 监听所有网络接口
// 或者用 ConfigureKestrel(更灵活):
// builder.WebHost.ConfigureKestrel(serverOptions => serverOptions.ListenAnyIP(5010));// 2. 加载 Ocelot 配置
builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);// 3. 添加 Ocelot 和 Consul 支持
builder.Services.AddOcelot(builder.Configuration).AddConsul(); // 关键:注入 Consul 提供程序var app = builder.Build();// 4. 使用 Ocelot 中间件
await app.UseOcelot();
app.Run();

4.2 Ocelot.JSON

{"Routes": [{"DownstreamPathTemplate": "/api/values/{action}","UpstreamPathTemplate": "/api/values/{action}","ServiceName": "ServerAPI","LoadBalancerOptions": {"Type": "RoundRobin"},"ServiceDiscoveryProvider": {"Type": "Consul","Host": "43.162.118.209","Port": 8500,"PollingInterval": 2000, // 每2秒从Consul拉取最新健康实例"SkipItemsWithUnhealthyStatus": true}}]
}

5.服务1代码

5.1 Program.CS

using Consul;
using Microsoft.OpenApi.Models;var builder = WebApplication.CreateBuilder(args);// 添加控制器和Swagger
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{c.SwaggerDoc("v1", new OpenApiInfo { Title = "ServerAPI1", Version = "v1" });
});// 注册Consul客户端
builder.Services.AddSingleton<IConsulClient>(new ConsulClient(c =>
{c.Address = new Uri("http://192.168.0.102:8500");
}));// 配置Kestrel(可选,根据实际需求)
builder.WebHost.UseUrls("http://*:5000");var app = builder.Build();// 健康检查端点
//app.MapGet("/health", () => Results.Ok("Healthy"));// 健康检查端点(模拟5000端口故障)
//app.MapGet("/health", (HttpContext context) =>
//{
//    var port = context.Request.Host.Port;
//    return port == 5000 ? Results.StatusCode(503) : Results.Ok("Healthy (Port: " + port + ")");
//});
//app.MapGet("/health", () => Results.Ok("Healthy (Port: 5000)"));
app.MapGet("/health", () =>
{// 基础存活检查(不依赖任何业务逻辑)return Results.Ok("Alive");
});// 注册到Consul
var consulClient = app.Services.GetRequiredService<IConsulClient>();
var registration = new AgentServiceRegistration
{ID = "ServerAPI-5000",Name = "ServerAPI",Address = "192.168.0.102",Port = 5000,Check = new AgentServiceCheck{HTTP = "http://192.168.0.102:5000/health",Interval = TimeSpan.FromSeconds(3),  // 每3秒检查一次Timeout = TimeSpan.FromSeconds(1),  // 1秒无响应视为失败DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(10) // 10秒后自动移除}
};
consulClient.Agent.ServiceRegister(registration).Wait();// 其他中间件
app.UseRouting();
app.MapControllers();// 配置Swagger(开发环境)
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ServerAPI1 v1"));
}// 路由和控制器
app.UseRouting();
app.MapControllers();// 应用停止时注销服务
app.Lifetime.ApplicationStopping.Register(() =>
{consulClient.Agent.ServiceDeregister(registration.ID).Wait();
});app.Run();

5.2 接口

    using Microsoft.AspNetCore.Mvc;using ServerAPI1.Models;namespace ServerAPI1.Controllers{[ApiController][Route("api/[controller]")][Produces("application/json")]public class ValuesController : ControllerBase{/// <summary>/// 获取服务基本信息/// </summary>[HttpGet("info")][ProducesResponseType(200)]public IActionResult GetInfo(){return Ok(new { Service = "ServerAPI1", Port = 5000 });}/// <summary>/// 计算服务 (A+B)/// </summary>/// <param name="model">输入参数</param>[HttpPost("calculate")][ProducesResponseType(200)][ProducesResponseType(400)]public IActionResult Calculate([FromBody] TestModel model){if (!ModelState.IsValid) return BadRequest(ModelState);return Ok(new { Result = 123 + 321, Input = model });}[HttpGet("getail")] // 实现 /api/values/getailpublic IActionResult Get(){return Ok("This is /api/values/getail from ServerAPI1");}[HttpGet("setail")]public IActionResult Gett(){return Ok("This is /api/values/setail from " + GetType().Assembly.GetName().Name);}}}

5.3 数据模型

using System.ComponentModel.DataAnnotations;namespace ServerAPI1.Models
{public class TestModel{[Required][StringLength(100)]public string AAA { get; set; }[StringLength(200)]public string BBB { get; set; }}
}

6.服务2代码

6.1 Program.CS

using Consul;
using Microsoft.OpenApi.Models;var builder = WebApplication.CreateBuilder(args);// 添加控制器和Swagger
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{c.SwaggerDoc("v1", new OpenApiInfo { Title = "ServerAPI2", Version = "v1" });
});// 注册Consul客户端
builder.Services.AddSingleton<IConsulClient>(new ConsulClient(c =>
{c.Address = new Uri("http://192.168.0.102:8500");
}));// 配置Kestrel(可选,根据实际需求)
builder.WebHost.UseUrls("http://*:5001");var app = builder.Build();// 健康检查端点
//app.MapGet("/health", () => Results.Ok("Healthy"));// 健康检查端点(模拟5000端口故障)
//app.MapGet("/health", (HttpContext context) =>
//{
//    var port = context.Request.Host.Port;
//    return port == 5000 ? Results.StatusCode(503) : Results.Ok("Healthy (Port: " + port + ")");
//});
//app.MapGet("/health", () => Results.Ok("Healthy (Port: 5001)"));
app.MapGet("/health", () =>
{// 基础存活检查(不依赖任何业务逻辑)return Results.Ok("Alive");
});// 注册到Consul
var consulClient = app.Services.GetRequiredService<IConsulClient>();
var registration = new AgentServiceRegistration
{ID = "ServerAPI-5001",Name = "ServerAPI",Address = "192.168.0.102",Port = 5001,Check = new AgentServiceCheck{HTTP = "http://192.168.0.102:5001/health",Interval = TimeSpan.FromSeconds(3),  // 每3秒检查一次Timeout = TimeSpan.FromSeconds(1),  // 1秒无响应视为失败DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(10) // 10秒后自动移除}
};
consulClient.Agent.ServiceRegister(registration).Wait();
// 其他中间件
app.UseRouting();
app.MapControllers();// 配置Swagger(开发环境)
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ServerAPI2 v1"));
}健康检查端点
//app.MapGet("/health", () => Results.Ok("Healthy"));// 路由和控制器
app.UseRouting();
app.MapControllers();// 应用停止时注销服务
app.Lifetime.ApplicationStopping.Register(() =>
{consulClient.Agent.ServiceDeregister(registration.ID).Wait();
});app.Run();

6.2 接口

using Microsoft.AspNetCore.Mvc;
using ServerAPI2.Models;namespace ServerAPI2.Controllers
{[ApiController][Route("api/[controller]")][Produces("application/json")]public class ValuesController : ControllerBase{/// <summary>/// 获取服务元数据/// </summary>[HttpGet("info")][ProducesResponseType(200)]public IActionResult GetInfo(){return Ok(new { Service = "ServerAPI2", Port = 8016 });}/// <summary>/// 字符串转换服务/// </summary>/// <param name="model">输入参数</param>[HttpPost("calculate")][ProducesResponseType(200)][ProducesResponseType(400)]public IActionResult Transform([FromBody] TestModel model){if (!ModelState.IsValid) return BadRequest(ModelState);return Ok(new { Result = $"{model.AAA}-{model.BBB}".ToUpper() });}[HttpGet("getail")] // 实现 /api/values/getailpublic IActionResult Get(){return Ok("This is /api/values/getail from ServerAPI2");}[HttpGet("setail")]public IActionResult Gett(){return Ok("This is /api/values/setail from " + GetType().Assembly.GetName().Name);}}
}

6.3 数据模型

    using System.ComponentModel.DataAnnotations;namespace ServerAPI2.Models{public class TestModel{[Required][StringLength(100)]public string AAA { get; set; }[StringLength(200)]public string BBB { get; set; }}}

7.发布形成Publish文件包

7.发布文件效果

8.运行Consul

8.1 显示双击文件夹内的Consul.exe

8.2 cmd进入Consul文件夹,运行指令:consul agent --config-file=C:\consul\config.json

9.运行服务

8.Publish文件夹内的Server1.exe\Server2.exe\OcelotDemo.exe,运行2个业务服务和网关服务

10.效果

相关文章:

  • 构建现代分布式云架构的三大支柱:服务化、Service Mesh 与 Serverless
  • 微软推出数款Phi 4“开放式”人工智能模型
  • 系统架构设计师:设计模式——创建型设计模式
  • 微软与Meta大幅增加人工智能基础设施投入
  • 普通 html 项目也可以支持 scss_sass
  • Anaconda中配置Pyspark的Spark开发环境
  • 【中间件】bthread_数据结构_学习笔记
  • terraform 删除资源前先校验资源是否存在关联资源
  • AJAX 实例
  • 【Linux】线程池和线程补充内容
  • Qwen3 正式发布
  • C++——入门基础(2)
  • 工 厂 模 式
  • 游戏引擎学习第252天:允许编辑调试值
  • 企业内训|智能驾驶与智能座舱技术——某汽车厂商
  • 【Qt】网络
  • Python项目源码69:Excel数据筛选器1.0(tkinter+sqlite3+pandas)
  • 《数据结构初阶》【顺序表/链表 精选15道OJ练习】
  • 【数据结构】- 栈
  • 文件操作--文件包含漏洞
  • 央行4月开展12000亿元买断式逆回购操作
  • 2024“好评中国”网络评论大赛结果揭晓
  • 跟着京剧电影游运河,京杭大运河沿线六城举行京剧电影展映
  • 这座“蚌埠住了”的城市不仅会接流量,也在努力成为文旅实力派
  • 法治日报调查直播间“杀熟”乱象:熟客越买越贵,举证难维权不易
  • 新一届中国女排亮相,奥运冠军龚翔宇担任队长