Files
hjha-server/MrWu/RabbitMQ/RpcClient.cs
xiaoou e9616125ce feat: initial commit - HJHA game server full source
6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) +
game logic (GameFix/GameDAL/ServerData) +
network layer (NetWorkMessage) +
data layer (ObjectModel) +
utilities (MrWu/Core/Config/CloudAPI/dll) +
adapters (zyxAdapter/base)

.NET 8.0 C# solution, 16 projects, 958 source files
2026-07-07 12:02:15 +08:00

249 lines
9.6 KiB
C#

/********************************
*
* 作者:吴隆健
* 创建时间: 2019/6/29 15:19:34
*
********************************/
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MrWu.Debug;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
namespace MrWu.RabbitMQ {
/// <summary>
/// RPC客户端
/// </summary>
public class RpcClient {
/// <summary>
/// 发送者
/// </summary>
private IModel channel;
private IConnection connection;
private readonly object lockObj = new object();
/// <summary>
/// rpc结果
/// </summary>
private readonly ConcurrentDictionary<string, string> respQueue = new ConcurrentDictionary<string, string>();
private RabbitConfig config;
private ushort prefetchCount;
/// <summary>
/// 消费者
/// </summary>
private EventingBasicConsumer consumer;
/// <summary>
/// 创建客户端
/// </summary>
/// <param name="config">rabbit配置</param>
/// <param name="prefetchCount">同时处理的数量</param>
internal RpcClient(RabbitConfig config, ushort prefetchCount) {
this.config = config;
this.prefetchCount = prefetchCount;
ConnectionFactory factory = new ConnectionFactory();
factory.UserName = config.username;
factory.Password = config.password;
factory.VirtualHost = config.vhost;
factory.HostName = config.host;
factory.Port = config.port;
factory.AutomaticRecoveryEnabled = true;
connection = factory.CreateConnection();
CreateChannel();
//this.CallBackTimeOutCheckTimer = new Timer(CallBackTimeoutCheck, null, 20, 20);
}
/// <summary>
/// 关闭
/// </summary>
internal void Close() {
connection.Close();
}
private void CreateChannel() {
channel = connection.CreateModel();
var queue = channel.QueueDeclare();
reply_queue = queue.QueueName;
consumer = new EventingBasicConsumer(channel);
consumer.Received += Recive;
//Debug.Debug.Log("进来两次????");
//只会同时接收prefetchCount 个数据
channel.BasicQos(0, prefetchCount, false);
channel.BasicConsume(reply_queue, true, consumer);
}
/// <summary>
/// rpc 返回值队列
/// </summary>
private string reply_queue;
/// <summary>
/// 接收到消息
/// </summary>
/// <param name="model"></param>
/// <param name="msg"></param>
private void Recive(IBasicConsumer model, BasicDeliverEventArgs msg) {
//Console.WriteLine($"MrWU.RpcClient.Recive\t{DateTime.Now:hh:mm:ss.fffffff}\t{msg?.BasicProperties?.CorrelationId}");
//ThreadPool.QueueUserWorkItem(HandleRecvMsgThreadPoolMethod, msg);
Task.Factory.StartNew(
() => {
// Debug.Debug.Log("Rpc接收到消息:" + );
if (msg.BasicProperties == null)
return;
//Debug.Debug.Log("RPC 接收到消息:" + msg.BasicProperties.CorrelationId);
if (!respQueue.TryAdd(msg.BasicProperties.CorrelationId, Encoding.UTF8.GetString(msg.Body))) {
Debug.Debug.Error("RPC发送消息失败!" + msg.BasicProperties.CorrelationId);
}
}
);
/*
if (msg?.BasicProperties != null) {
var callbackResult = Encoding.UTF8.GetString(msg.Body);
//Debug.Debug.Log("RPC 接收到消息:" + msg.BasicProperties.CorrelationId);
if(AsyncTaskList.TryGetValue(msg.BasicProperties.CorrelationId, out var tuple)) {
tuple.Item3.TrySetResult(callbackResult);
} else if(!respQueue.TryAdd(msg.BasicProperties.CorrelationId, callbackResult)) {
Debug.Debug.Error("RPC发送消息失败!" + msg.BasicProperties.CorrelationId);
}
}
*/
}
/// <summary>
/// 获取结果
/// </summary>
/// <returns></returns>
private string GetReplyResult(string corrlationId, int waitTime = 3000) {
DateTime outtime = DateTime.Now.AddMilliseconds(waitTime);
//while (true) {
// //Debug.Debug.Log("处理处理接收消息:" + Thread.CurrentThread.ManagedThreadId);
// if (respQueue.ContainsKey(corrlationId)) {
// string msg = null;
// if (respQueue.TryGetValue(corrlationId, out msg)) {
// return msg;
// } else {
// Debug.Debug.Error("RPC消息竟被别人取走??");
// return null;
// }
// } else {
// Console.WriteLine($"MrWU.RpcClient.GetReplyResult for: {corrlationId},\t{}");
// }
// if (DateTime.Now > outtime)
// return null;
// Thread.Sleep(10);
//}
while(true) {
//Debug.Debug.Log("处理处理接收消息:" + Thread.CurrentThread.ManagedThreadId);
if(respQueue.TryRemove(corrlationId, out var msg)) {
return msg;
} else {
}
if(DateTime.Now > outtime)
return null;
Thread.Sleep(10);
}
}
/// <summary>
/// call 方法
/// </summary>
/// <param name="exchange">交换机</param>
/// <param name="routingkey">路由键</param>
/// <param name="message">消息</param>
/// <param name="waitTime">超时时间 毫秒值</param>
public string Call(string exchange, string routingkey, string message, int waitTime = 3000) {
// Debug.Debug.Log("call : " + reply_queue);
string correlationId = MessagePool.GetId();// Guid.NewGuid().ToString();
try {
lock(lockObj) {
if(channel == null || channel.IsClosed) {
CreateChannel();
}
}
IBasicProperties properties = channel.CreateBasicProperties();
properties.ReplyTo = reply_queue;
properties.CorrelationId = correlationId;
//Debug.Debug.Log("rpcCall :" + correlationId);
channel.BasicPublish(exchange, routingkey, properties, Encoding.UTF8.GetBytes(message));
var ret = GetReplyResult(correlationId, waitTime);
return ret;
} catch(Exception e) {
Debug.Debug.Error("Rpc出现错误!" + e.ToString());
return null;
}
}
//ConcurrentDictionary<string, Tuple<DateTime, string, TaskCompletionSource<string>>> AsyncTaskList { get; } = new ConcurrentDictionary<string, Tuple<DateTime, string, TaskCompletionSource<string>>>();
/*
/// <summary>
/// 异步Callback
/// </summary>
/// <param name="exchange"></param>
/// <param name="routingkey"></param>
/// <param name="message"></param>
/// <param name="waitTime"></param>
/// <returns></returns>
public Task<string> AsyncCall(string exchange, string routingkey, string message, int waitTime = 3000) {
var correlationId = Guid.NewGuid().ToString();
var taskSrc = new TaskCompletionSource<string>();
try {
lock(lockObj) {
if(channel == null || channel.IsClosed) {
CreateChannel();
}
}
var properties = channel.CreateBasicProperties();
properties.ReplyTo = reply_queue;
properties.CorrelationId = correlationId;
channel.BasicPublish(exchange, routingkey, properties, Encoding.UTF8.GetBytes(message));
AsyncTaskList.TryAdd(correlationId, new Tuple<DateTime, string, TaskCompletionSource<string>>(DateTime.Now.AddMilliseconds(waitTime), message, taskSrc));
} catch(Exception ex) {
Debug.Debug.Error("Rpc出现错误!" + ex.ToString());
taskSrc.TrySetException(new Exception("AsyncCall Rpc出现错误", ex));
}
return taskSrc.Task;
}
*/
/*
Timer CallBackTimeOutCheckTimer { get; }
void CallBackTimeoutCheck(object obj) {
var now = DateTime.Now;
var outdateItems = AsyncTaskList.Where(p => p.Value.Item1 < now).ToArray();
if(AsyncTaskList.Count>0 && outdateItems.Length == AsyncTaskList.Count) {
foreach(var item in outdateItems) {
if(AsyncTaskList.TryRemove(item.Key, out var tuple)) {
//tuple.Item3.TrySetException(new TimeoutException("超时检查: " + tuple.Item2));
tuple.Item3.TrySetResult(string.Empty);
}
}
}
}
*/
}
}