1. 项目概述与架构设计
在现代分布式系统中,负载均衡和身份认证是两个核心组件。本项目基于.NET 8 WebAPI构建,采用YARP作为反向代理实现负载均衡,结合Redis进行会话管理和缓存,使用JWT进行身份认证,并通过Entity Framework Core与数据库交互。这种架构特别适合需要高可用性和可扩展性的企业级应用场景。
系统主要包含以下核心模块:
- YARP反向代理层:负责请求分发和健康检查
- WebAPI应用层:处理业务逻辑
- Redis缓存层:管理会话和缓存数据
- 数据库层:持久化存储业务数据
- JWT认证层:处理用户身份验证
提示:YARP(Yet Another Reverse Proxy)是微软官方推出的高性能反向代理库,特别适合.NET生态系统的负载均衡需求,相比Nginx等传统方案,它与ASP.NET Core的集成更加紧密。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. YARP负载均衡配置详解
2.1 基础配置解析
YARP的配置主要在appsettings.json中完成,下面是对示例配置的深度解析:
json复制"ReverseProxy": {
"Routes": {
"route1": {
"ClusterId": "webapiCluster",
"Match": { "Path": "{**catch-all}" }
}
},
"Clusters": {
"webapiCluster": {
"Destinations": {
"webapi1": { "Address": "http://localhost:5000" },
"webapi2": { "Address": "http://localhost:5001" }
},
"HealthCheck": {
"Active": {
"Enabled": true,
"Interval": "00:00:05",
"Timeout": "00:00:05",
"Policy": "ConsecutiveFailures",
"Path": "/health"
}
}
}
}
}
关键配置项说明:
- Routes:定义请求路由规则,示例中匹配所有路径(
{**catch-all}) - Clusters:定义后端服务集群,包含多个目标节点
- HealthCheck:配置主动健康检查,5秒间隔检查
/health端点
2.2 健康检查机制实现
健康检查是负载均衡的核心功能之一,YARP支持主动和被动两种模式。示例中配置了主动检查:
csharp复制// 健康检查端点示例
[HttpGet("health")]
public IActionResult HealthCheck()
{
// 检查数据库连接等关键依赖
var dbHealthy = _context.Database.CanConnect();
// 检查Redis连接
var redisHealthy = _redisService.Ping();
return dbHealthy && redisHealthy
? Ok()
: StatusCode(503);
}
健康检查最佳实践:
- 检查所有关键依赖(数据库、缓存等)
- 返回适当的HTTP状态码(200表示健康,503表示不可用)
- 检查逻辑要轻量,避免影响性能
- 检查频率要合理(示例中5秒是常用值)
2.3 高级配置技巧
在实际生产环境中,还需要考虑以下配置:
- 会话保持:某些场景需要保证用户请求始终路由到同一后端
json复制"SessionAffinity": {
"Enabled": true,
"Policy": "Cookie",
"FailurePolicy": "Redistribute"
}
- 负载均衡策略:默认是PowerOfTwoChoices,也可配置轮询等
json复制"LoadBalancingPolicy": "RoundRobin"
- 重试机制:处理临时故障
json复制"HttpClient": {
"MaxConnectionsPerServer": 100,
"RequestHeaderEncoding": "UTF-8"
}
3. 认证授权系统实现
3.1 JWT配置与生成
JWT配置位于appsettings.json中:
json复制"Jwt": {
"Key": "ThisIsASecretKeyForJwtSigning123456789",
"Issuer": "localhost",
"Audience": "localhost",
"ExpireMinutes": 60
}
JWT生成服务实现:
csharp复制public class JwtService
{
private readonly IConfiguration _config;
public JwtService(IConfiguration config)
{
_config = config;
}
public string GenerateJwtToken(string username, int userId, string sessionId)
{
var securityKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var credentials = new SigningCredentials(
securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, username),
new Claim("userid", userId.ToString()),
new Claim("sessionid", sessionId),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Audience"],
claims: claims,
expires: DateTime.Now.AddMinutes(
Convert.ToDouble(_config["Jwt:ExpireMinutes"])),
signingCredentials: credentials);
