添加监控定时器

This commit is contained in:
zpc 2024-12-01 21:33:15 +08:00
parent 29ae49221b
commit e7ab3a8eba
13 changed files with 305 additions and 33 deletions

View File

@ -0,0 +1,11 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace CloudGaming.ExtApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class MonitorController : ControllerBase
{
}
}

View File

@ -2,6 +2,7 @@ using CloudGaming.Code.AppExtend;
using CloudGaming.Code.DataAccess.MultiTenantUtil;
using CloudGaming.Code.Filter;
using CloudGaming.Code.Game;
using CloudGaming.Code.Monitor;
using HuanMeng.DotNetCore.MiddlewareExtend;
using HuanMeng.DotNetCore.SwaggerUtile;
@ -86,6 +87,7 @@ builder.Services.AddSwaggerGen(c =>
builder.AddAppConfigClient();
//添加游戏服务
builder.AddPlayGameServer();
builder.AddMonitorConfig();
var app = builder.Build();
// Configure the HTTP request pipeline.
@ -108,7 +110,7 @@ app.UseSwaggerUI(c =>
app.UseAuthorization();
//数据库中间件
app.UseMultiTenant();
app.UseMultiTenantExt();
app.MapControllers();
app.UseMiddlewareAll();
#region

View File

@ -53,6 +53,25 @@ namespace CloudGaming.Code.AppExtend
return AppConfigs.FirstOrDefault().Value;
}
/// <summary>
/// 获取配置项
/// </summary>
/// <param name="domainName"></param>
/// <returns></returns>
public static AppConfig GetAppConfig(Guid tenantId)
{
var appConfig = AppConfigs.Where(it => it.Value.TenantId == tenantId).Select(it => it.Value).FirstOrDefault();
if (appConfig != null)
{
return appConfig;
}
if (AppConfigs.TryGetValue("default", out appConfig))
{
return appConfig;
}
return AppConfigs.FirstOrDefault().Value;
}
/// <summary>
///
/// </summary>
/// <param name="args"></param>

View File

@ -19,6 +19,9 @@
<PackageReference Include="FastMember" Version="1.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
<PackageReference Include="Quartz" Version="3.13.1" />
<PackageReference Include="Quartz.AspNetCore" Version="3.13.1" />
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.13.1" />
<PackageReference Include="Refit" Version="8.0.0" />
<PackageReference Include="Refit.HttpClientFactory" Version="8.0.0" />
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="3.9.0" />

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CloudGaming.Code.DataAccess.MultiTenantUtil;
/// <summary>
/// 多租户中间件
/// </summary>
public class MultiTenantExtMiddleware
{
private readonly RequestDelegate _next;
public MultiTenantExtMiddleware(RequestDelegate next)
{
_next = next;
}
/// <summary>
/// 根据HttpContext获取并设置当前租户ID
/// </summary>
/// <param name="context"></param>
/// <param name="_serviceProvider"></param>
/// <param name="appConfig"></param>
/// <returns></returns>
public virtual async Task Invoke(HttpContext context,
IServiceProvider _serviceProvider,
AppConfig appConfig)
{
AppConfig app = null;
if (context.Request.Headers.TryGetValue("tenantId", out var str))
{
if (Guid.TryParse(str, out Guid tenantId))
{
app = AppConfigurationExtend.GetAppConfig(tenantId);
}
}
if (app == null)
{
var host = context.Request.Host.Host;
app = AppConfigurationExtend.GetAppConfig(host);
}
if (string.IsNullOrEmpty(appConfig.Identifier))
{
app.ToAppConfig(appConfig);
}
await _next.Invoke(context);
}
}

View File

@ -58,6 +58,16 @@ namespace CloudGaming.Code.DataAccess.MultiTenantUtil
{
return app.UseMiddleware<MultiTenantTenantMiddleware>();
}
/// <summary>
/// 多租户IApplicationBuilder扩展
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseMultiTenantExt(this IApplicationBuilder app)
{
return app.UseMiddleware<MultiTenantExtMiddleware>();
}
}
}

View File

@ -7,39 +7,38 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CloudGaming.Code.DataAccess.MultiTenantUtil
namespace CloudGaming.Code.DataAccess.MultiTenantUtil;
/// <summary>
/// 多租户中间件
/// </summary>
public class MultiTenantTenantMiddleware
{
/// <summary>
/// 多租户中间件
/// </summary>
public class MultiTenantTenantMiddleware
private readonly RequestDelegate _next;
public MultiTenantTenantMiddleware(RequestDelegate next)
{
private readonly RequestDelegate _next;
public MultiTenantTenantMiddleware(RequestDelegate next)
_next = next;
}
/// <summary>
/// 根据HttpContext获取并设置当前租户ID
/// </summary>
/// <param name="context"></param>
/// <param name="_serviceProvider"></param>
/// <param name="appConfig"></param>
/// <returns></returns>
public virtual async Task Invoke(HttpContext context,
IServiceProvider _serviceProvider,
AppConfig appConfig)
{
var host = context.Request.Host.Host;
var app = AppConfigurationExtend.GetAppConfig(host);
if (string.IsNullOrEmpty(appConfig.Identifier))
{
_next = next;
}
/// <summary>
/// 根据HttpContext获取并设置当前租户ID
/// </summary>
/// <param name="context"></param>
/// <param name="_serviceProvider"></param>
/// <param name="appConfig"></param>
/// <returns></returns>
public virtual async Task Invoke(HttpContext context,
IServiceProvider _serviceProvider,
AppConfig appConfig)
{
var host = context.Request.Host.Host;
var app = AppConfigurationExtend.GetAppConfig(host);
if (string.IsNullOrEmpty(appConfig.Identifier))
{
app.ToAppConfig(appConfig);
}
await _next.Invoke(context);
app.ToAppConfig(appConfig);
}
await _next.Invoke(context);
}
}

View File

@ -1,6 +1,7 @@
using CloudGaming.Code.Contract;
using CloudGaming.Code.DataAccess;
using CloudGaming.Code.JY;
using CloudGaming.Code.Monitor;
using CloudGaming.DtoModel.PlayGame;
using HuanMeng.DotNetCore.Processors;
@ -125,8 +126,16 @@ public class PlayGameProcessor(IServiceProvider serviceProvider) : ThreadProcess
user.PlayGameUserNotQueue();
await user.SaveChangesAsync(dao, redis).ConfigureAwait(false);
}
if (!MonitorExtend.AppMonitorConfigs.TryGetValue(app.Identifier, out var appMonitorInfo))
{
appMonitorInfo = new DtoModel.Other.AppMonitorInfo() { };
MonitorExtend.AppMonitorConfigs.TryAdd(app.Identifier, appMonitorInfo);
}
//替换引用
appMonitorInfo.PlayGameUserInfos = gameInfoList;
//状态统计
var gameStatusStatistics = gameInfoList.GroupBy(it => it.GameStatus).ToDictionary(it => it.Key, it => it.Count());// .Select(it => new { GameStatus = it.Key, GameCount = it.Count() }).ToList();
//var gameStatusStatistics = gameInfoList.GroupBy(it => it.GameStatus).ToDictionary(it => it.Key, it => it.Count());// .Select(it => new { GameStatus = it.Key, GameCount = it.Count() }).ToList();
}
/// <summary>

View File

@ -0,0 +1,50 @@
using AgileConfig.Client;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using CloudGaming.Code.DataAccess.MultiTenantUtil;
using CloudGaming.DtoModel.Other;
using Quartz;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CloudGaming.Code.Monitor;
/// <summary>
/// 监控扩展类
/// </summary>
public static class MonitorExtend
{
/// <summary>
///
/// </summary>
public static ConcurrentDictionary<string, AppMonitorInfo> AppMonitorConfigs { get; set; } = new ConcurrentDictionary<string, AppMonitorInfo>();
public static WebApplicationBuilder AddMonitorConfig(this WebApplicationBuilder builder)
{
// 添加 Quartz 配置
builder.Services.AddQuartz(q =>
{
// 注册作业和触发器
var jobKey = new JobKey("MonitorProcessor");
q.AddJob<MonitorProcessor>(opts => opts.WithIdentity(jobKey));
q.AddTrigger(opts => opts
.ForJob(jobKey)
.WithIdentity("monitorTrigger")
.StartNow()
.WithSimpleSchedule(x => x.WithIntervalInSeconds(5).RepeatForever()));
});
// 添加 Quartz 托管服务
builder.Services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
return builder;
}
}

View File

@ -0,0 +1,28 @@
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CloudGaming.Code.Monitor;
/// <summary>
///
/// </summary>
public class MonitorProcessor : IJob
{
public MonitorProcessor(IServiceProvider serviceProvider)
{
}
public Task Execute(IJobExecutionContext context)
{
Console.WriteLine($"MessageService:");
//throw new NotImplementedException();
return Task.CompletedTask;
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CloudGaming.Code.Other
{
/// <summary>
/// 监控类
/// </summary>
public class MonitorBLL : CloudGamingBase
{
public MonitorBLL(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
}
}

View File

@ -12,7 +12,7 @@ namespace CloudGaming.DtoModel.Account.User
/// <summary>
/// 用户缓存
/// </summary>
public class UserInfoCache : UserInfo
public class UserInfoCache : UserInfo
{
/// <summary>
/// 最后一次实名认证时间

View File

@ -0,0 +1,72 @@
using CloudGaming.DtoModel.Account.User;
using CloudGaming.DtoModel.PlayGame;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CloudGaming.DtoModel.Other;
/// <summary>
/// app监控数据
/// </summary>
public class AppMonitorInfo
{
/// <summary>
/// 用户所有的游戏状态
/// </summary>
public List<PlayGameUserInfo> PlayGameUserInfos { get; set; }
/// <summary>
/// 在线人数
/// </summary>
public List<UserInfoCache> OnlineUser { get; set; }
/// <summary>
/// 用户游戏状态统计
/// </summary>
public Dictionary<PlayGameStatus, int> PlayGameStatusStatistics() => PlayGameUserInfos.GroupBy(it => it.GameStatus).ToDictionary(it => it.Key, it => it.Count());
/// <summary>
/// 今日注册人数
/// </summary>
public int TodayRegisteredUsers { get; set; }
/// <summary>
/// 今日登录人数
/// </summary>
public int TodayLoggedInUsers { get; set; }
/// <summary>
/// 当前在线人数
/// </summary>
public int CurrentOnlineUsers { get; set; }
/// <summary>
/// 当前玩游戏人数
/// </summary>
public int CurrentPlayingUsers { get; set; }
/// <summary>
/// 当前排队人数
/// </summary>
public int CurrentQueuedUsers { get; set; }
/// <summary>
/// 今日意向订单
/// </summary>
public int TodayIntendedOrders { get; set; }
/// <summary>
/// 今日支付订单
/// </summary>
public int TodayPaidOrders { get; set; }
/// <summary>
/// 今日充值金额
/// </summary>
public decimal TodayRechargeAmount { get; set; }
}