奥尔良粮食上的任务调用结果 [英] Result of task invocation on a grain in Orleans

查看:101
本文介绍了奥尔良粮食上的任务调用结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很长的问题我深表歉意。我一直在与奥尔良进行试验,以了解其各种特性,并且从逻辑上讲,这些问题都归根结底。

I apologize for the long question. I have been experimenting with Orleans to know about its various properties and these questions are logically under one umbrella.

第一个测试涉及每1秒从客户端向特定谷物发出请求,而谷物则需要10秒才能执行要求。代码是这样的:

The first test involved making request from client to a specific grain every 1 second while the grain takes 10 seconds to execute the requests. The code is this:

// client code
while (1)
{
    Console.WriteLine("Client giving another request");
    double temperature = random.NextDouble() * 40;
    var sensor = client.GetGrain<ITemperatureSensorGrain>(500);
    Task t = sensor.SubmitTemperatureAsync((float)temperature);
    Console.WriteLine(t.Status);
    Thread.Sleep(1000);
 }

// grain code
public Task SubmitTemperatureAsync(float temperature)
{
    long grainId = this.GetPrimaryKeyLong();
    Console.WriteLine($"{grainId} outer received temperature: {temperature}");
    Thread.Sleep(10000);

    Console.WriteLine($"{grainId} outer complete");
    return Task.CompletedTask;
}

控制台输出为:

Client giving another request
Task Status - WaitingForActivation
500 outer received temperature: 32.29987    <------------ print statement inside grain
Client giving another request     <--------------------- client continues
Task Status - WaitingForActivation  <------------------- client isn't blocked
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
Client giving another request
Task Status - WaitingForActivation
500 outer complete

由于奥尔良的谷物是单线程的,因此仅调用第一个请求,其余的请求在谷物侧排队。我对这部分的问题是:-

As grains in Orleans are single threaded, only first request is invoked and rest requests are queued on the grain side. My questions for this part are: -

在正常的C#中,当异步方法被调用时,它将在主线程上继续运行,直到启动await语句为止。等待表达式作为另一个任务并返回该任务。因此,调用方被阻塞,直到命中await语句为止。同样,这里的客户端也应该被阻塞10秒钟,之后第一个谷物请求返回一个Task。但是,这不会发生。客户端将继续计划任务而不会被阻塞。

In normal C#, when an async method is called, it continues on the main thread till it hits the await statement when it starts the awaited expression as another Task and returns that Task. So, the caller is blocked till the await statement is hit. Similarly, here too the client should be blocked for 10s after which the first request to grain returns a Task. However, that doesn't happen. The client is continuing to schedule tasks without getting blocked.


  • 那么,客户端 FireAndForget 调用谷物吗?

  • 如果是,那么他们如何取回Task对象?

  • 当客户端调用谷物对象并且运行时将Task对象带回客户端时,是否存在任何类型的阻塞?

  • So, is the call to grains from client FireAndForget?
  • If yes, then how do they get back the Task object?
  • Is there any kind of blocking involved when client makes a call to a grain object and runtime brings Task object back to the client?

第二个测试涉及从谷物向谷物发出请求,其中第二个谷物等待10秒才返回。代码是这样的:

The second test involved making request from a grain to a grain in which the second grain waits 10 seconds before returning. The code is this:

// client code
while (1)
{
    Console.WriteLine("Client giving another request");
    double temperature = random.NextDouble() * 40;
    var sensor = client.GetGrain<ITemperatureSensorGrain>(500);
    Task t = sensor.SubmitTemperatureAsync((float)temperature);
    Console.WriteLine("Client Task Status - "+t.Status);

    // make client sleep for a long time after the first request
    // because we don't want any more requests from the client
    Thread.Sleep(1000000000);
}

// outer-grain (ITemperatureSensorGrain) code
public async Task SubmitTemperatureAsync(float temperature)
{
    long grainId = this.GetPrimaryKeyLong();
    Console.WriteLine($"{grainId} outer received temperature: {temperature}");

    while(true)
    {
        Console.WriteLine("Grain sending another request");
        ITempBGrain sensor = this.GrainFactory.GetGrain<ITempBGrain>(400);
        // await sensor.SubmitTempBAsync(temperature);
        Task t = sensor.SubmitTempBAsync(temperature);
        Console.WriteLine("Grain Task Status - "+t.Status);
        Thread.Sleep(1000);
    }
}

// inner-grain (ITempBGrain) code
public Task SubmitTempBAsync(float temperature)
{
    long grainId = this.GetPrimaryKeyLong();
    Console.WriteLine($"{grainId} internal received temperature: {temperature}");
    Thread.Sleep(10000);
    Console.WriteLine($"{grainId} internal complete");
    return Task.CompletedTask;
}

控制台输出为:

Client giving another request
Client Task Status - WaitingForActivation
500 outer received temperature: 10.36764
Grain sending another request       <-------------- Outer grain prints
Grain Task Status - WaitingForActivation 
Grain sending another request  <----------- Inner grain doesn't print
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
Grain sending another request
Grain Task Status - WaitingForActivation
warn: Orleans.Runtime.CallbackData[100157]
      Response did not arrive on time in 00:00:30 for message: Request *cli/015ba7a5@d4cdc7ab->S127.0.0.1:30000:0*grn/6424EE47/000001f4 #17: . Target History is: <S127.0.0.1:30000:0:*grn/6424EE47/000001f4:>. About to break its promise.
Grain sending another request
Grain Task Status - WaitingForActivation

我在这里看到的与客户在第一个实验中发生的情况类似。因此,这些问题仍然存在。但是,这里发生了另一件事。内部谷物的控制台输出无处显示。 为什么内部谷物不执行?如果我在外部谷物代码中启用了注释行,并等待内部谷物任务,则会显示以下输出,该输出似乎有效。

What I see here is something similar to what happened with client in the first experiment. So, those questions are still there. However, here there is one more strange thing happening. The console output of inner grain appears nowhere. Why is the inner grain not executing? If I enable the commented out line in outer-grain code, and await the inner grain task, the following output appears which seems valid.

Client giving another request
Client Task Status - WaitingForActivation
500 outer received temperature: 6.332514
Grain sending another request
400 internal received temperature: 6.332514
400 internal complete
Grain sending another request
400 internal received temperature: 6.332514


推荐答案

第一部分

不,调用谷物时没有阻塞制造。 帖子进一步明确了当

First Part
No, there is no blocking when a call to a grain is made. This post further clears what happens when a grain call is made.

第二部分

虽然谷物是单线程的,但这样做是错误的假设每个谷物在奥尔良都有自己的线程。正如@Tseng所说,奥尔良使用.NET Core的异步功能。它将处理谷物,直到发生异步操作为止。然后它将线程返回到线程池。其他线程可以使用此线程来处理数据,直到异步操作完成为止。完成后,它将恢复。它不需要相同的线程(但上下文相同)。第一个谷物阻塞了线程,第二个谷物没有执行的机会。

Second Part
While it is correct that grains are single threaded, it is wrong to assume that every grain has its own thread in Orleans. As @Tseng says Orleans uses the async feature of .NET Core. It will process a grain until an async operation happens. Then it returns the thread to the thread-pool. This thread can be used by another grain to process data until the async operation is complete. When its complete, it resumes. its not necessary the same thread (but its the same context). The first grain is blocking the thread giving no chance for the second grain to execute.

感谢Tseng和Reuben Bond弄清楚了。

Thanks Tseng and Reuben Bond for making things clear.

这篇关于奥尔良粮食上的任务调用结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆