在Proto.Actor中异步请求/重发吗?

时间:2018-09-15 17:56:10

标签: protractor actor proto.actor

我是proto.actor/actor编程的新手,我想知道是否可以实现此行为:

演员A通过异步命令询问演员B –他应该等待响应以实现请求/响应模型,但要使用任务。 演员B使用的是HTTP请求,因此这将是一些异步IO操作,因此我不希望这次被其他演员阻止,因此当10个演员在同一时间询问他时,每个请求都将排队,但是在第一次请求正在等待第二个过程,应该有机会继续。首次请求完成后,它应该在队列中具有优先级并获得对参与者A的响应。

如何获得此流程?

例如,我有3个客户端向服务询问一些数据,服务呼叫花费5秒钟,而大部分时间服务花费在IO上。在当前的实现中,我们所有请求的总时间为15秒,但我希望此过程大约需要5-6秒

 public static class ProtoTest
    {
        public static PID Service;

        public static async Task Start()
        {
            var context = new RootContext();

            var props = Props.FromProducer(() => new ClientActor());
            var serviceProps = Props.FromProducer(() => new ServiceActor());
            Service = context.Spawn(serviceProps);

            var jobs = new List<Task>();
            for (int i = 0; i < 3; i++)
            {
                string actorName = $"Actor_{i}";
                jobs.Add(Task.Run(() =>
                {
                    var client = context.SpawnNamed(props, actorName);
                    context.Send(client, new Command());
                }));
            }

            Console.ReadLine();
        }
    }

    public class ClientActor : IActor
    {
        public virtual async Task ReceiveAsync(IContext context)
        {
            if (context.Message is Command)
            {
                Console.WriteLine($"{DateTime.Now.ToLongTimeString()} START processing by {context.Self.Id}");
                var result = await context.RequestAsync<string>(ProtoTest.Service, new Query());
                Console.WriteLine($"{DateTime.Now.ToLongTimeString()} End processing by {context.Self.Id}");
            }

            return;
        }
    }

    public class ServiceActor : IActor
    {
        public async virtual Task ReceiveAsync(IContext context)
        {
            if (context.Message is Query)
            {
                // this operation is taking long time so actor could handle others in this time
                await Task.Delay(5000);

                context.Respond("result");
            }

            return;
        }
    }

1 个答案:

答案 0 :(得分:0)

参与者的核心原则之一是它不会并行执行多个操作。如果我正确地理解了您的问题,您可以做的是为您要并行运行的每个操作创建一个新的actor(actor很便宜,因此创建很多不是问题)。因此,如果角色A需要发送N条命令进行异步处理并接收传入的每个结果,则可以生成N个角色B1,B2 ... Bn(每个命令一个)并向每个角色发送请求。 B演员等待结果,然后回复给A演员。然后,每个响应将作为消息发送到参与者A的邮箱,并按照其完成的顺序依次处理。