Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 工作人员角色和Web角色之间的Azure通信_C#_Azure_Azure Web Roles_Azure Worker Roles - Fatal编程技术网

C# 工作人员角色和Web角色之间的Azure通信

C# 工作人员角色和Web角色之间的Azure通信,c#,azure,azure-web-roles,azure-worker-roles,C#,Azure,Azure Web Roles,Azure Worker Roles,嗨,我正在构建一个云服务,它(目前)有一个web和一个worker角色。我想要的工作流是:浏览器调用web角色上的webApi控制器,该控制器将消息发送到队列(或服务总线),然后由工作者角色处理。到现在为止,一直都还不错。现在,当worker角色完成处理消息时,我想调用web角色上的一个方法,然后web角色将向浏览器发出处理已完成的信号(通过signer)。请原谅,如果这不是一个合适的问题,因为这更像是一个“最佳实践”问题,而不是一个真正的问题。到目前为止,我考虑了两种方法: worker角色使

嗨,我正在构建一个云服务,它(目前)有一个web和一个worker角色。我想要的工作流是:浏览器调用web角色上的webApi控制器,该控制器将消息发送到队列(或服务总线),然后由工作者角色处理。到现在为止,一直都还不错。现在,当worker角色完成处理消息时,我想调用web角色上的一个方法,然后web角色将向浏览器发出处理已完成的信号(通过signer)。请原谅,如果这不是一个合适的问题,因为这更像是一个“最佳实践”问题,而不是一个真正的问题。到目前为止,我考虑了两种方法:

  • worker角色使用任务的进度和完成情况更新表行(在表存储中)。没有向web角色发送信号。浏览器直接(通过RESTAPI)读取轮询表存储,因此知道任务何时完成。这工作得很好(我已经测试过了),尽管我不喜欢持续轮询的方法,我希望有一个“基于事件”的解决方案。此外,一旦客户机获得进程已完成的信息,它必须执行对web api方法的附加调用,以向其他客户机(通过SignalR)广播操作已完成

  • 与信号器一起使用(参见下面的代码示例)也可以工作(已经测试过)

  • 代码示例:

    var protocol = "http";      
    var ipAddress = RoleEnvironment.Roles["XXX.YYY.Web"]
            .Instances[0]
            .InstanceEndpoints.ToArray()
            .Where(ep => ep.Value.Protocol == protocol)
            .First()
            .Value.IPEndpoint.ToString();
    
    var stringEndpoint = string.Format("{0}://{1}", protocol, ipAddress.ToString());                
    Trace.WriteLine("Retrieved endpoint address: " + stringEndpoint, "Information");            
    HubConnection connection = new HubConnection(stringEndpoint);
    IHubProxy proxy = connection.CreateHubProxy("MyWebHub");
    connection.Start().Wait();
    
    //later...
    
    proxy.Invoke("ProgressUpdated", clientId, progress);
    

    我的问题是:有没有其他(更好的)沟通方式在“员工角色->网络角色”的方向上?也就是说,当工作角色完成其处理时,是否触发web角色上的方法?web角色上的方法随后将通过信号器向所有客户端广播更新。我也看了一下,但据我所知,事件消费者仍将以工作者角色运行。

    我认为您已经有足够的知识和实施经验来实现它。我从你那里学到,使用信号器是一种很好的方法

    另一个稍有不同的方法是,我使用常量轮询,通过使用向WebRole发送
    GET
    消息


    在我看来,作为webapi服务器的一种特性,轮询是遵循web服务器设计的最合适、最可靠的方法。

    好的,经过一些额外的尝试和研究,我找到了一个可能的解决方案。。。我用的是这个代码

    AzureServiceBus.QueueClient.OnMessage((message) =>
                {
                    try
                    {
                        // Process message from queue
                        Trace.WriteLine("Message received: " + ((BrokeredMessage)message).Label);
    
                        var breezeController = new BreezeController();
                        breezeController.TestSignal();
    
                        // Remove message from queue
                        message.Complete();
                    }
                    catch (Exception)
                    {
                        // Indicates a problem, unlock message in queue
                        message.Abandon();
                    }
                });
    

    在Web角色(而不是工作者角色)的OnStart方法中,这样我就可以在Web角色中引用我的方法(在本例中为TestSignal()),但事实证明,当从这个OnMessage事件处理程序中调用IHubContext时,它总是空的,因为它属于(很可能)到不同的AppDomain,因此即使是Signal的静态集线器也没有共享。因此,我在Global.asax.cs中移动了相同的全部代码,以便它将共享相同的AppDomain,现在它可以工作了。我想我会坚持这种方式,因为我更喜欢这种方式,而不是连续投票

    问题有点晚了:),但我们实现的是指定响应队列和会话ID,web角色在将消息发送给工作者角色后将等待响应队列和会话ID。您可以对其进行调整,以避免在web角色等待worker角色回复时阻塞响应(在我们的场景中,我们特别希望等待)

    网络角色

    string sessionId = Guid.NewGuid().ToString(); 
    [...]
    // put message in sync queue
    var message = new BrokeredMessage(request)
    {
       ReplyToSessionId = sessionId
    };
    await ServiceBusConnector.Instance.SyncClient.SendAsync(message);
    
    // now listen to reply on session response queue (only accepts message on same session id)
    MessageSession session = await ServiceBusConnector.Instance.SyncResponseClient.AcceptMessageSessionAsync(sessionId);
    
    BrokeredMessage responseMessage = await session.ReceiveAsync(TimeSpan.FromMinutes(5));
    await responseMessage.CompleteAsync();
    await session.CloseAsync();
    
    Response response = responseMessage.GetBody<Response>();
    // process Worker Role's response
    
    也请点击此处,通过HttpClient直接与应用程序通信

    public class Functions
    {
        public static async Task ProcessQueueMessage([QueueTrigger("jobqueue")] Guid jobId, TextWriter log)
        {
            for (int i = 10; i <= 100; i+=10)
            {
                Thread.Sleep(400);
    
                await CommunicateProgress(jobId, i);
            }
        }
    
        private static async Task CommunicateProgress(Guid jobId, int percentage)
        {
            var httpClient = new HttpClient();
    
            var queryString = String.Format("?jobId={0}&progress={1}", jobId, percentage);
            var request = ConfigurationManager.AppSettings["ProgressNotificationEndpoint"] + queryString;
    
            await httpClient.GetAsync(request);
        }
    }
    
    公共类函数
    {
    公共静态异步任务ProcessQueueMessage([QueueTrigger(“jobqueue”)]Guid jobId,TextWriter日志)
    {
    
    对于(int i=10;对于反馈,我不是一个专家,但我认为调度程序是用于不同的目的,一般来说我不喜欢这种方法。是的,轮询工作,它涉及的web角色更少,但我仍然不认为这是最好的方式…我喜欢这种实现!以前从未想过这种模式,而且它非常简单干得好!
    public class Functions
    {
        public static async Task ProcessQueueMessage([QueueTrigger("jobqueue")] Guid jobId, TextWriter log)
        {
            for (int i = 10; i <= 100; i+=10)
            {
                Thread.Sleep(400);
    
                await CommunicateProgress(jobId, i);
            }
        }
    
        private static async Task CommunicateProgress(Guid jobId, int percentage)
        {
            var httpClient = new HttpClient();
    
            var queryString = String.Format("?jobId={0}&progress={1}", jobId, percentage);
            var request = ConfigurationManager.AppSettings["ProgressNotificationEndpoint"] + queryString;
    
            await httpClient.GetAsync(request);
        }
    }