我正在使用Azure服务总线队列(或者如果需要,可能是某个主题),并且想知道如何将Web作业与队列一起使用。
当消息进入队列时,它表示将在Web作业中运行的进程(或从webjob启动)。这个过程可能很快,30秒,或者可能很慢,1小时等。
我是否可以为此使用单个Web作业,并以某种方式说它一次应该运行不超过10个这样的进程?
答案 0 :(得分:1)
是的,您可以使用WebJob。我创建了一个带有存储队列的简单WebJob,以指导它是如何完成的。以下工作流程一次只运行十个进程,并将所有其他请求保留在ConcurrentQueue的内存中。您将必须实现逻辑以使其出列并使用它
public class Functions
{
public delegate void CompletedProcessHandler(object sender, CompletedProcessHandlerArgs args);
static readonly Dictionary<int, CustomProcess> _dictionary =
new Dictionary<int, CustomProcess>();
static readonly ConcurrentQueue<ProcessEntity> _remaining =
new ConcurrentQueue<ProcessEntity>();
// This function will get triggered/executed when a new message is written
// on an Azure Queue called queue.
public static void ProcessQueueMessage([QueueTrigger("testqueue")] ProcessEntity msg,
TextWriter log)
{
if (_dictionary.Count <= 10)
{
var newProcess = new CustomProcess((_dictionary.Last().Key) + 1,
msg.Duration);
}
else
{
_remaining.Enqueue(msg);
}
}
public static void CompletedProcess(object sender, CompletedProcessHandlerArgs args)
{
_dictionary[Int32.Parse(args.ProcessID)].Dispose();
_dictionary.Remove(Int32.Parse(args.ProcessID));
}
}
public class CustomProcess : IDisposable
{
public event Functions.CompletedProcessHandler OnProcessCompleted;
private CancellationTokenSource _token;
private string _id;
private Timer _timer;
public CustomProcess(int i, int duration)
{
_timer = new Timer { Enabled = true, Interval = duration * 1000 };
_timer.Elapsed += Timer_Elapsed;
_id = i.ToString();
_token = new CancellationTokenSource();
Task.Factory.StartNew(() => WriteMessages());
_timer.Start();
OnProcessCompleted += Functions.CompletedProcess;
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
_token.Cancel();
OnProcessCompleted?.Invoke(this, new CompletedProcessHandlerArgs(_id));
}
private void WriteMessages()
{
while (!_token.Token.IsCancellationRequested)
{
Console.WriteLine("Test Message from process " + _id);
}
}
public void Dispose()
{
_token.Dispose();
_timer.Dispose();
}
}
public class CompletedProcessHandlerArgs : EventArgs
{
public string ProcessID { get; set; }
public CompletedProcessHandlerArgs(string ID)
{
ProcessID = ID;
}
}
public class ProcessEntity
{
public int Duration { get; set; }
}
在网络工作的app.config中,您需要提供两个应用设置
<add name="AzureWebJobsDashboard"
connectionString="DefaultEndpointsProtocol=https;AccountName=[AccountName];AccountKey=[AccountKey]" />
<add name="AzureWebJobsStorage"
connectionString="DefaultEndpointsProtocol=https;AccountName=[AccountName];AccountKey=[AccountKey]" />
程序文件是Visual Studio模板中的默认文件
public class Program
{
// Please set the following connection strings in app.config for this WebJob to run:
// AzureWebJobsDashboard and AzureWebJobsStorage
static void Main()
{
var host = new JobHost();
// The following code ensures that the WebJob will be running continuously
host.RunAndBlock();
}
}
WebJob会在消息出现时随时将其留空。由于您一次只需要运行10个消息,因此您必须将消息排入内存并等待运行过程完成,然后才能启动新消息
正如@Rick所提到的,你可以在web作业的settings.job文件中将is_Singleton属性设置为true
答案 1 :(得分:0)
是的,您可以使用Azure Service Bus Queue或Topic触发Web作业。一个很好的例子就是Visual Studio中的Service Bus快速启动项目模板。
特别是,您希望查看Web Jobs SDK提供的ServiceBusTrigger属性。
对于Web作业的可伸缩性,这将根据您的Web应用程序实例进行扩展。因此,如果您说启用了始终开启的5个Web应用实例,那么您将拥有5个Web作业实例。作为对此的补充评论,如果您只想在5个Web应用程序实例的环境中创建一个Web作业实例,则可以在settings.job文件中将 is_singleton 属性设置为true。 / p>