123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- using Grpc.Core;
- using Microsoft.AspNetCore.SignalR;
- using Microsoft.Azure.Cosmos.Linq;
- using Microsoft.Extensions.Primitives;
- using TEAMModelOS.SDK.DI;
- using TEAMModelOS.SDK.Extension;
- using TEAMModelOS.SDK;
- namespace HTEX.Complex.Services
- {
- public class SignalRScreenServerHub : Hub<IClient>
- {
- private readonly AzureRedisFactory _azureRedis;
- public SignalRScreenServerHub(AzureRedisFactory azureRedis)
- {
- _azureRedis = azureRedis;
- }
- /// <summary>
- /// 客户连接成功时触发
- /// </summary>
- /// <returns></returns>
- public override async Task OnConnectedAsync()
- {
- var connid = Context.ConnectionId;
- var httpContext = Context.GetHttpContext();
- if (httpContext != null)
- {
- //wss://www.winteach.cn/signalr/notify?grant_type=wechat_qrcode&scene=0a75aca57536490ba00fe62e27bb8f6c&id=U2MNiCFNPPuVcw2gUI_gRA
- //wss://www.winteach.cn/signalr/notify?grant_type=bookjs_api&clientid={clientid}&id=客户端自动生成的
- httpContext.Request.Query.TryGetValue("grant_type", out StringValues grant_type);
- httpContext.Request.Query.TryGetValue("clientid", out StringValues clientid);
- var ip = GetIP(httpContext);
- await Groups.AddToGroupAsync(connid, grant_type!);
- if (!clientid.Equals(StringValues.Empty) && !grant_type.Equals(StringValues.Empty)) {
- ///连接配置,并且使用钉钉 通知。
- ///
- var client = new SignalRClient
- {
- connid = connid,
- grant_type = grant_type,
- clientid= clientid
- };
- await _azureRedis.GetRedisClient(8).StringSetAsync($"SignalRClient:connects:{connid}", client.ToJsonString());
- switch (true)
- {
- case bool when grant_type.Equals(ScreenConstant.grant_type):
- ScreenClient screenClient = null;
- var value = await _azureRedis.GetRedisClient(8).HashGetAsync($"ScreenApi:clients", client.clientid);
- if (value!=default && value.HasValue)
- {
- screenClient = value.ToString().ToObject<ScreenClient>();
- // 这里不强制设置free ,因为如果是重连,可能正在执行命令,需要等待执行完成
- //screenClient.status="free";
- screenClient.connid=connid;
- }
- else
- {
- screenClient= new ScreenClient
- {
- status=ScreenConstant.free,
- connid=connid,
- grant_type=grant_type,
- clientid= clientid,
- desc="",
- domain="",
- ip=ip,
- time= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
- weight= 0,
- duration=0,
- };
- }
- //连接成功,发送消息给客户端。
- await SendConnection(connid, new ConnectionMessageContent
- {
- clientid = clientid,
- status = ScreenConstant.free,
- grant_type = grant_type,
- content = $"连接成功"
- });
- //先检查状态是否是在忙碌,在时间戳范围里,如果不在时间戳范围,强制free。
- if (!screenClient.status!.Equals(ScreenConstant.free) &&screenClient.time + screenClient.duration < DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()) {
- screenClient.status = ScreenConstant.free;
- }
- if (screenClient.status!.Equals(ScreenConstant.free)) {
- //连接成功,马上分发任务。
- //从尾部弹出元素,队列先进先出
- var queueValue = await _azureRedis.GetRedisClient(8).ListRightPopAsync("PDFGen:Queue");
- if (queueValue!=default && queueValue.HasValue)
- {
- PDFGenQueue genQueue = queueValue.ToString().ToObject<PDFGenQueue>();
- await SendConnection(connid, new ScreenProcessMessageContent
- {
- clientid = clientid,
- status = ScreenConstant.busy,
- grant_type = grant_type,
- content =$"{queueValue.ToString()}",//从Redis中获取任务信息
- });
- screenClient.status = ScreenConstant.busy;
- screenClient.time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- //预计占用时长,并冗余5秒
- screenClient.duration= genQueue.timeout+genQueue.delay+ScreenConstant.time_excess;
- }
- }
- await _azureRedis.GetRedisClient(8).HashSetAsync($"ScreenApi:clients", client.clientid, screenClient.ToJsonString());
- break;
- }
- }
- else
- {
- await SendConnection(connid, new ConnectionMessageContent
- {
- clientid = string.Empty,
- status =ScreenConstant.error,
- grant_type = grant_type,
- content = "客户端配置错误",
- connid = connid,
- });
- }
- }
- }
- public async override Task OnDisconnectedAsync(Exception? exception)
- {
- var connid = Context.ConnectionId;
- var redisData = await _azureRedis.GetRedisClient(8).StringGetAsync($"SignalRClient:connects:{connid}");
- if (!redisData.IsNullOrEmpty)
- {
- await _azureRedis.GetRedisClient(8).KeyDeleteAsync($"SignalRClient:connects:{connid}");
- var client = redisData.ToString().ToObject<SignalRClient>();
- if (client != null)
- {
- var value = await _azureRedis.GetRedisClient(8).HashGetAsync($"ScreenApi:clients", client.clientid);
- if (value!=default && value.HasValue)
- {
- ScreenClient screenClient = value.ToString().ToObject<ScreenClient>() ;
- screenClient.status=ScreenConstant.down;
- screenClient.connid= string.Empty;
- await _azureRedis.GetRedisClient(8).HashSetAsync($"ScreenApi:clients", client.clientid, screenClient.ToJsonString());
- }
- await Groups.RemoveFromGroupAsync(connid, client.grant_type!);
- ///连接配置,并且使用钉钉 离线通知。
- }
- }
- }
- public async Task SendConnection(string connectionId, MessageBody msg)
- {
- await Clients.Client(connectionId).ReceiveConnection(msg);
- }
- public string GetIP(HttpContext httpContext)
- {
- var IpPort = httpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
- if (string.IsNullOrEmpty(IpPort))
- {
- IpPort = $"{httpContext.Connection.RemoteIpAddress}";
- }
- if (IpPort.Contains("::"))
- {
- IpPort = "127.0.0.1";
- }
- return IpPort;
- }
- }
- }
|