资料链接:https://download.csdn.net/download/ly1h1/90731290
1.效果
基于Ocelot,实现对3个微服务的轮询调用,实现不停机更新,无缝更新;
2.环境要求
1.部署环境:腾讯云的轻量化应用服务器
2.系统环境:Window Server 2016
3..net托管包:dotnet-hosting-9.0.4-win.exe
3.配置开放端口号
3.1 端口号说明:端口5000(服务1),端口5001(服务2),端口5002(服务3),端口5010(Ocelot)
3.2 在服务器管理平台上的开放以上4个端口号

2.3 配置入站规则端口号

4.服务1的代码
4.1 Program.cs
var builder = WebApplication.CreateBuilder(args);
// 添加Swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() { Title = "ServerAPI1", Version = "v1" });
});
builder.WebHost.ConfigureKestrel(serverOptions => { })
.UseUrls("http://*:5000"); // 允许所有Host
builder.Services.AddControllers();
var app = builder.Build();
// 配置Swagger
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ServerAPI1 v1"));
}
app.UseRouting();
app.MapControllers();
app.Run();
4.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 });
}
}
}
4.2 数据模型
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; }
}
}
5.服务2的代码
5.1 Program.cs
var builder = WebApplication.CreateBuilder(args);
// 添加Swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() { Title = "ServerAPI2", Version = "v1" });
});
builder.WebHost.ConfigureKestrel(serverOptions => { })
.UseUrls("http://*:5001"); // 允许所有Host
builder.Services.AddControllers();
var app = builder.Build();
// 配置Swagger
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ServerAPI2 v1"));
}
app.UseRouting();
app.MapControllers();
app.Run();
5.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() });
}
}
}
5.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; }
}
}
6.服务3的代码
6.1 Program.cs
var builder = WebApplication.CreateBuilder(args);
// 添加Swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() { Title = "ServerAPI3", Version = "v1" });
});
builder.WebHost.ConfigureKestrel(serverOptions => { })
.UseUrls("http://*:5002"); // 允许所有Host
builder.Services.AddControllers();
var app = builder.Build();
// 配置Swagger
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ServerAPI3 v1"));
}
app.UseRouting();
app.MapControllers();
app.Run();
6.2 接口
using Microsoft.AspNetCore.Mvc;
using ServerAPI3.Models;
namespace ServerAPI3.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 = "ServerAPI4", 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() });
}
}
}
6.3 数据模型
using System.ComponentModel.DataAnnotations;
namespace ServerAPI3.Models
{
public class TestModel
{
[Required]
[StringLength(100)]
public string AAA { get; set; }
[StringLength(200)]
public string BBB { get; set; }
}
}
7.Ocelot的代码
7.1 Program.cs
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
var builder = WebApplication.CreateBuilder(args);
// 强制指定 Kestrel 端口(优先级最高)
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5010); // 监听所有IP的5010端口
});
builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
builder.Services.AddOcelot(builder.Configuration);
var app = builder.Build();
await app.UseOcelot();
app.Run();
7.2 ocelot.json
{
"Routes": [
{
"DownstreamPathTemplate": "/api/values/{action}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "192.168.0.102",
"Port": 5000
}, // ServerAPI1
{
"Host": "192.168.0.102",
"Port": 5001
} ,// ServerAPI2
{
"Host": "192.168.0.102",
"Port": 5002
} // ServerAPI3
],
"UpstreamPathTemplate": "/balanced-api/values/{action}",
"UpstreamHttpMethod": [ "GET", "POST" ],
"LoadBalancerOptions": {
"Type": "RoundRobin" // 轮询策略
}
}
],
"GlobalConfiguration": {
"BaseUrl": "http://192.168.0.102:5010"
}
}
8.生成发布文件
8.1 选中发布项目,右键点击发布

8.2 选择文件发布,选择文件路径,部署模式为独立,目标运行时为win-x64。

8.3 生成publish文件

9.文件拷贝到服务器的制定目录下

10.点击5个文件夹内部的exe,即可运行;

