Files

259 lines
6.9 KiB
C#

using Autofac;
using Autofac.Extensions.DependencyInjection;
using ChessGameHost.Extension;
using ChessGameHost.Middleware;
using ChessGameService;
using Common;
using Common.Request;
using CommonService;
using JWTHelper;
using MessagePack;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Options;
using MongoRepository.Config;
using NLog.Extensions.Logging;
using NLog.Web;
using RedisHelper;
using RedisService;
using SharpAbp.Infrastructure.Api.Middleware;
using System.Text.Json;
using UserService;
using static Common.Utils.DateTimeTools;
using ChessGameHost.Services;
Environment.SetEnvironmentVariable("SERVICE_NAME",
Environment.GetEnvironmentVariable("SERVICE_NAME")
?? System.Reflection.Assembly.GetEntryAssembly()?.GetName().Name
?? "ChessGameHost");
Environment.SetEnvironmentVariable("INSTANCE_ID",
Environment.GetEnvironmentVariable("INSTANCE_ID") ?? "default");
var builder = WebApplication.CreateBuilder(args);
string instanceId = Environment.GetEnvironmentVariable("INSTANCE_ID") ?? "Unknown";
builder.Services.AddSingleton(sp => new AppInstanceId { Id = instanceId });
// Add services to the container.
builder.Services.AddControllers();
builder.Logging.AddNLog();
builder.Host.UseNLog();
builder.Configuration.AddJsonFile(Path.Combine("Config", "system.json"), optional: true);
builder.Services.Configure<MongoDbSettings>(builder.Configuration.GetSection(nameof(MongoDbSettings)));
builder.Services.AddSingleton<IMongoDbSettings>(sp => sp.GetRequiredService<IOptions<MongoDbSettings>>().Value);
builder.Services.AddSignalR(hubOptions =>
{
hubOptions.MaximumReceiveMessageSize = 64 * 1024; // 64KB
hubOptions.StreamBufferCapacity = 512;
hubOptions.ClientTimeoutInterval = TimeSpan.FromSeconds(70);
hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(15);
hubOptions.AddFilter<MovementFilter>();
hubOptions.AddFilter<HubExceptionFilter>();
}).AddJsonProtocol();
builder.Services.Configure<FormOptions>(x =>
{
x.MultipartBodyLengthLimit = 1024 * 1024 * 16;
});
builder.Services.AddMemoryCache();
builder.Services.AddControllers().AddJsonOptions(configure =>
{
configure.JsonSerializerOptions.Converters.Add(new DatetimeJsonConverter());
});
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddSingleton<IHubSend<ChessGameHub>, HubSend<ChessGameHub>>();
builder.Services.AddSingleton<IRequestApi, RequestApi>();
builder.Services.AddAutoMapper(typeof(AutoMapperConfig));
builder.Services.AddHostedService<ChessTimeoutService>();
#region Swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
{
Title = "ChessGameHost",
Description = "象棋Socket接口",
Version = "v1"
});
foreach (var xml in System.IO.Directory.GetFiles(AppContext.BaseDirectory, "*.xml"))
{
try { c.IncludeXmlComments(xml, true); } catch { }
}
});
#endregion
builder.Services.AddHostedService<ChessBotService>();
builder.Services.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy(), tags: new[] { "self" });
builder.Services.AddCors(options =>
{
options.AddPolicy("Cors", policy =>
{
policy
//.WithOrigins(urls)
.SetIsOriginAllowed(_ => true)
.AllowAnyHeader()
//.WithHeaders("x-signalr-user-agent", "content-type", "authorization")
.AllowAnyMethod()
.AllowCredentials()
;
});
});
#region jwt
builder.Services.AddCustomJwt(builder.Configuration);
#endregion
#region redis
builder.Services.AddRedisCacheSingleton(builder.Configuration);
#endregion
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
{
builder.RegisterModule<AutofacModule>();
});
#region Cap
builder.Services.AddCap(builder.Configuration);
#endregion
var app = builder.Build();
using (var scope = app.Services.CreateScope())
{
var redis = scope.ServiceProvider.GetRequiredService<IRedisService>();
var chessService = scope.ServiceProvider.GetRequiredService<IChessGameService>();
var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
try
{
redis.ClearAllLoginUserIds();
var rooms = redis.GetAllChessRooms() ?? new List<ChessGameDomain.ChessGameRoom>();
var resetRooms = 0;
var disconnectedRooms = 0;
var affectedUserIds = new HashSet<string>();
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
foreach (var room in rooms.Where(r => r?.users?.Count > 0))
{
foreach (var user in room.users.Where(u => !string.IsNullOrWhiteSpace(u.userId)))
affectedUserIds.Add(user.userId);
if (room.state != 2)
{
chessService.ExitRoom(room);
resetRooms++;
continue;
}
foreach (var user in room.users)
{
user.IsLeave = true;
user.DisconnectTime = now;
user.Cid = string.Empty;
}
redis.SetChessRoom(room);
disconnectedRooms++;
}
foreach (var userId in affectedUserIds)
await chessService.UpdateUserGameType(userId, 0);
}
catch (Exception ex)
{
logger.LogError(ex, "[Startup] 清除象棋玩家登录 cid 失败(非关键,不影响启动)");
}
}
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
}
#region Swagger
app.UseSwagger(c => c.RouteTemplate = "swagger/{documentName}/swagger.json");
app.UseSwaggerUI(c =>
{
c.RoutePrefix = "swagger";
c.SwaggerEndpoint("v1/swagger.json", "ChessGameHost v1");
});
#endregion
app.UseApiLogging();
app.UseRouting();
app.UseGlobalExceptionHandler();
app.UseStaticFiles();
app.UseCors("Cors");
app.UseAuthentication();
app.UseAuthorization();
app.MapHub<ChessGameHub>("/chessgamehub", options =>
{
options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets;
});
app.MapControllers();
app.MapHealthChecks("/health", new HealthCheckOptions
{
Predicate = _ => true,
ResponseWriter = async (context, report) =>
{
context.Response.ContentType = "application/json";
var result = new
{
status = report.Status.ToString(),
checks = report.Entries.Select(e => new
{
name = e.Key,
status = e.Value.Status.ToString(),
description = e.Value.Description,
duration = e.Value.Duration.TotalMilliseconds
}),
totalDuration = report.TotalDuration.TotalMilliseconds
};
await context.Response.WriteAsync(JsonSerializer.Serialize(result));
}
});
app.Run();