/************************************************************************************************** |
§案例場景:
1、服務系統負責接收外部調用請求,考慮性能問題,將此請求轉發爲異步方式執行。
即: 通過MQ將原始請求發送至後臺消息處理服務,完成業務邏輯異步Processing。
2、消息處理過程中,存在異常失敗情況,需要進行二級隊列Process
3、另外考慮到消息的完整性、一致性,需要通過事務來控制消息處理。
§分析設計:
通過命令方式,將消息的發送者、接受者、調用者分別委派到場景中的各實例對象,各部分單一職責的方式來處理,另外對於併發的消息命令、特殊命令,可以指定不同的Receiver,處理不同的業務Path.
§設計實現:
1、 設計類圖
MessageReceiver 執行消息處理操作(Receiver)
MessageCommand 消息命令(可將命令與消息分開)
IMessageInvoker 調用消息的處理方法(Invoker)
ThreadClient 創建消息並綁定消息調用者
2、 代碼實現
//ThreadClient.cs
/// <summary>
/// 創建消息並綁定消息調用者
/// </summary>
public class ThreadClient
{
public static List<Thread> _threadArray = new List<Thread>();
/// <summary>
/// 隊列參數設置
/// </summary>
public QueueSettings QueueSettings
{
get;
set;
}
public Thread Initialize(QueueSettings setting)
{
QueueSettings = setting;
Thread thread = new Thread(new ThreadStart(this.Start));
return thread;
}
/// <summary>
/// 啓動接收消息線程
/// </summary>
public void Start()
{
MessageReceiver receiver = new MessageReceiver(QueueSettings);
Command command = new MessageCommand(receiver);
IMessageInvoker invoker = new IMessageInvoker();
invoker.SetCommand(command);
invoker.ExecuteCommand();
}
}
IMessageInvoker.cs
/// <summary>
/// 調用消息的處理方法
/// </summary>
public class IMessageInvoker
{
private Command command;
public void SetCommand(Command command)
{
this.command = command;
}
public void ExecuteCommand()
{
command.Execute();
}
}
MessageReceiver.cs
/// <summary>
/// 執行消息處理操作
/// </summary>
public class MessageReceiver
{
/// <summary>
/// 隊列參數設置
/// </summary>
public QueueSettings QueueSettings
{
get;
set;
}
private DepositOrderInfo _depositInfo = null;
public MessageReceiver(QueueSettings setting)
{
QueueSettings = setting;
}
public int Process(object data)
{
#region 驗證基本參數
#endregion
#region 填充訂單明細
#endregion
#region 保存訂單
#endregion
return Consts.Success;
}
}
MessageCommand.cs
/// <summary>
/// 消息命令
/// </summary>
public class MessageCommand : Command
{
MessageReceiver _receiver;
string queuePath = string.Empty;
public MessageCommand(MessageReceiver receiver) :
base(receiver)
{
_receiver = receiver;
}
/// <summary>
/// 處理消息
/// </summary>
public override void Execute()
{
QueueSettings = _receiver.QueueSettings;
while (true)
{
try
{
queuePath = QueueHelper.GetQueuePath(QueueSettings.QueueLevel);
if (!String.IsNullOrEmpty(queuePath) && SDMSMQ.GetAllMessageCount(queuePath) > 0)
{
//接收事務型消息
//Process
}
Thread.Sleep(QueueSettings.Interval);
}
catch (Exception ex)
{
#region 發送到二級隊列
#endregion
#region 發送到監控系統
#endregion
}
}
}
}
Command.cs
/// <summary>
/// 各類消息命令基類
/// </summary>
public abstract class Command
{
protected MessageReceiver receiver;
protected QueueSettings QueueSettings;
public Command(MessageReceiver receiver)
{
this.receiver = receiver;
}
public abstract void Execute();
}
調用示例
public static List<Thread> _threadArray = new List<Thread>();
//一級隊列線程
Thread thread1 = new ThreadClient().Initialize(new QueueSettings { QueueLevel = QueueLevel.First,
Interval = Configs.GetConfig<int>("Queue1Interval") });
thread1.Start();
_threadArray.Add(thread1);
§總結:
當然,通過指定不同的命令,Process不同的消息未必要通過命令者,靈活應用其他類型模式也可以完成此過程。本例主要針對命令者給出Demo。
另外上述接受者構造器中入參QueueSettings,很多時候可作爲命令中介適配器:
public class CommandAdapterInfo
{
List<CommandAdapterInfo> CommandList = null;
public CommandAdapterInfo Create()
{
Init();
return this.CommandList.Find(delegate(CommandAdapterInfo _adapter)
{
return _adapter.CommandType == this.CommandType;
});
}
void Init()
{
this.CommandList = new List<CommandAdapterInfo>();
//提現
CommandAdapterInfo adapter = new CommandAdapterInfo();
adapter.CommandType = CommanderType.Commission;
adapter.Receiver = new CommissionMessageReceiver(adapter);
adapter.Command = new CommissionMessageCommand(adapter.Receiver);
adapter.Invoker = new CommissionMessageInvoker();
this.CommandList.Add(adapter);
//委託付款到卡
CommandAdapterInfo adapterPayToCard = new CommandAdapterInfo();
adapterPayToCard.CommandType = CommanderType.PayToCard;
adapterPayToCard.Receiver = new CommissionMessageReceiver(adapterPayToCard);
adapterPayToCard.Command = new CommissionMessageCommand(adapterPayToCard.Receiver);
adapterPayToCard.Invoker = new CommissionMessageInvoker();
this.CommandList.Add(adapterPayToCard);
}
/// <summary>
/// 命令類型
/// </summary>
public CommanderType CommandType
{
get;
set;
}
/// <summary>
/// 命令接收者
/// </summary>
public MessageReceiver Receiver
{
get;
set;
}
/// <summary>
/// 命令執行
/// </summary>
public Command Command
{
get;
set;
}
/// <summary>
/// 調用者
/// </summary>
public MessageInvoker Invoker
{
get;
set;
}
}