用stact做异步请求

时间:2011-08-29 01:28:58

标签: topshelf

道歉,如果这似乎我想要为我保存我的问题,但是我曾经偶然发现了它并且它似乎是一个方便的库来熟悉,我认为这对于手头的问题很有用

我看了一下源代码,那里有很多东西! :)不知道从哪里开始。

我需要的是一个组件(Actor?),它会定期发送异步Web请求并在本地存储结果(有些解析结果会先发生)。其他线程会在不同时间询问结果。

从我所看到的情况来看,我需要一个Scheduler,一个Fibre和一个Channel来处理将结果返回给任何请求它们的人。有点像:

private static readonly ConcurrentDictionary<Uri, ServerLoad> ServerLoads = new ConcurrentDictionary<string, ServerLoad>();
public Channel<Request<IEnumerable<ServerLoad>>> ServerLoadChannel { get; private set; 
public LoadRetriever(Inbox inbox, Fiber fiber, Scheduler scheduler, ILoadBalancerConfiguration config)
{
    this.inbox = inbox;
    this.fiber = fiber;
    this.scheduler = scheduler;

    this.scheduler.Schedule(
        0,
        config.FetchIntervalMilliSecs,
        fiber,
        () =>
            {
                foreach (var server in config.Servers)
                {
                    // need someway to send async web request to url in
                    // server.LoadRetrievalAddress and save/update result
                    // in ServerLoads dictionary
                }
            });

    this.ServerLoadChannel = new ConsumerChannel<Request<IEnumerable<ServerLoad>>>(this.fiber, 
        request => request.Respond(ServerLoads.Values));
}

}

这暂时都是理论上的,可能完全错误,我遇到的主要问题是执行异步请求(WebClient.DownloadStringAsync()和DownloadStringCompleted)。与AsyncResultChannel相反的东西

任何提示/示例/推进正确的方向将不胜感激!

(试图为stact创建一个标签,但我的声誉不够好:S)

2 个答案:

答案 0 :(得分:2)

嗯,这里有一些事情。首先,您应该创建一个Actor类,使用:

public class MyServerCoordinator : Actor 
{}

然后,该actor将加载配置并为每个服务器实例创建另一个actor。这将允许每个配置的服务器按照自己的计划检索它的信息。

然后你需要使用:

为每种类型创建一个ActorFactory
var factory = ActorFactory.Create((i,f,s) => new MyServerCoordinator(i,f,s));
var actor = factory.GetActor();

通过消息传递,您应该为要在actor之间交换的每条消息创建一个消息类,而不是使用原始CLR类型。

此外,在每个actor的构造函数中,您可以设置一个Receive循环来分别处理预定更新的请求。参与者可以通过发送请求来相互通信,其中包括响应通道给发送者。这将允许每服务器的演员与协调员交谈。

MyServerCoordinator(Inbox inbox)
{
    inbox.Loop(loop =>
    {
        loop.Receive<Request<ServerData>>(request =>
        {
            request.Respond(new ServerDataResult(_myCurrentValue)); 
            loop.Continue();
        });
    }
}

每个actor都有自己的光纤,因此不需要使用并发集合类型或任何锁定机制。 actor模型通过消息传递处理并发,因此不使用信号量等。

您还需要查看单元测试中的一些示例,以了解如何使用AnonymousActor.New()内联声明从非演员代码与actor进行交互。

答案 1 :(得分:1)

一个好的起点可能是Cashbox https://github.com/Cashbox/Cashbox。我用较旧版本的Stact编写了它,但大多数概念都应该很好。

https://github.com/Cashbox/Cashbox/blob/master/src/Cashbox/Engines/FileStorageEngine.cs是所有基于演员的魔法发生的地方。 https://github.com/Cashbox/Cashbox/blob/master/src/Cashbox/Engines/FileStorageEngine.cs#L182就是提出请求并等待回复。