我正在构建一个T4模板,它将帮助人们以一致和简单的方式构建Azure队列。我想让这个自我记录,并且有点一致。
首先我将队列名称放在文件的顶部,队列名称必须是小写的,所以我添加了ToLower()
公共构造函数使用内置的StorageClient API来访问连接字符串。我已经看到了许多不同的方法,并希望得到几乎适用于所有情况的东西。 (想法?分享)
我不喜欢不需要的HTTP请求来检查队列是否已经创建,所以我做的是static bool
。我没有实现Lock(monitorObject),因为我认为不需要。
我没有使用字符串并使用逗号解析(就像大多数MSDN文档一样),而是在将对象传递到队列时对其进行序列化。
为了进一步优化,我使用JSON serializer extension method来充分利用8k限制。不确定编码是否有助于优化此
添加了重试逻辑来处理队列中出现的某些情况(请参阅html链接)
问:“DataContext”是否适用于此类名称?
问:以我的方式命名队列操作名称是不是很糟糕?
您认为我应该做出哪些其他更改?
public class AgentQueueDataContext
{
// Queue names must always be in lowercase
// Is named like a const, but isn't one because .ToLower won't compile...
static string AGENT_QUEUE_ACTION_NAME = "AgentQueueActions".ToLower();
static bool QueuesWereCreated { get; set; }
DataModel.SecretDataSource secDataSource = null;
CloudStorageAccount cloudStorageAccount = null;
CloudQueueClient cloudQueueClient = null;
CloudQueue queueAgentQueueActions = null;
static AgentQueueDataContext()
{
QueuesWereCreated = false;
}
public AgentQueueDataContext() : this(false)
{
}
public AgentQueueDataContext(bool CreateQueues)
{
// This pattern of setting up queues is from:
// ttp://convective.wordpress.com/2009/11/15/queues-azure-storage-client-v1-0/
//
this.cloudStorageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
this.cloudQueueClient = cloudStorageAccount.CreateCloudQueueClient();
this.secDataSource = new DataModel.SecretDataSource();
queueAgentQueueActions = cloudQueueClient.GetQueueReference(AGENT_QUEUE_ACTION_NAME);
if (QueuesWereCreated == false || CreateQueues)
{
queueAgentQueueActions.CreateIfNotExist();
QueuesWereCreated = true;
}
}
// This is the method that will be spawned using ThreadStart
public void CheckQueue()
{
while (true)
{
try
{
CloudQueueMessage msg = queueAgentQueueActions.GetMessage();
bool DoRetryDelayLogic = false;
if (msg != null)
{
// Deserialize using JSON (allows more data to be stored)
AgentQueueEntry actionableMessage = msg.AsString.FromJSONString<AgentQueueEntry>();
switch (actionableMessage.ActionType)
{
case AgentQueueActionEnum.EnrollNew:
{
// Add to
break;
}
case AgentQueueActionEnum.LinkToSite:
{
// Link within Agent itself
// Link within Site
break;
}
case AgentQueueActionEnum.DisableKey:
{
// Disable key in site
// Disable key in AgentTable (update modification time)
break;
}
default:
{
break;
}
}
//
// Only delete the message if the requested agent has been missing for
// at least 10 minutes
//
if (DoRetryDelayLogic)
{
if (msg.InsertionTime != null)
if (msg.InsertionTime < DateTime.UtcNow + new TimeSpan(0, 10, 10))
continue;
// ToDo: Log error: AgentID xxx has not been found in table for xxx minutes.
// It is likely the result of a the registratoin host crashing.
// Data is still consistent. Deleting queued message.
}
//
// If execution made it to this point, then we are either fully processed, or
// there is sufficent reason to discard the message.
//
try
{
queueAgentQueueActions.DeleteMessage(msg);
}
catch (StorageClientException ex)
{
// As of July 2010, this is the best way to detect this class of exception
// Description: ttp://blog.smarx.com/posts/deleting-windows-azure-queue-messages-handling-exceptions
if (ex.ExtendedErrorInformation.ErrorCode == "MessageNotFound")
{
// pop receipt must be invalid
// ignore or log (so we can tune the visibility timeout)
}
else
{
// not the error we were expecting
throw;
}
}
}
else
{
// allow control to fall to the bottom, where the sleep timer is...
}
}
catch (Exception e)
{
// Justification: Thread must not fail.
//Todo: Log this exception
// allow control to fall to the bottom, where the sleep timer is...
// Rationale: not doing so may cause queue thrashing on a specific corrupt entry
}
// todo: Thread.Sleep() is bad
// Replace with something better...
Thread.Sleep(9000);
}
答案 0 :(得分:2)
问:“DataContext”是否适合此类?
在.NET中我们有很多DataContext类,所以从某种意义上说,你希望名称能够恰当地传达类的功能,我认为XyzQueueDataContext
可以正确地传达类的功能 - 尽管你无法查询从它。
如果您希望与已接受的模式语言更加一致,Patterns of Enterprise Application Architecture会调用任何封装对网关的外部系统访问权限的类,而更多具体而言,您可能希望使用Enterprise Integration Patterns语言中的频道一词 - 这就是我要做的。
问:以我的方式命名队列操作名称是不是很糟糕吗?
嗯,肯定将队列名称与班级紧密联系。这意味着,如果您以后决定要将它们分离,则不能。
作为一般性评论,我认为这个课程可能会因为努力做得更少而受益。使用队列与管理队列不同,因此我不建议将所有队列管理代码放在那里,而是建议将CloudQueue注入到实例中。以下是我实现AzureChannel构造函数的方法:
private readonly CloudQueue queue;
public AzureChannel(CloudQueue queue)
{
if (queue == null)
{
throw new ArgumentNullException("queue");
}
this.queue = queue;
}
这更适合Single Responsibility Principle,您现在可以在自己的(可重用的)类中实现队列管理。