Я пытаюсь понять однопоточность зерен в Microsoft Orleans. Я использовал код из здесь и немного изменил его чтобы проверить мои сценарии.
Мой клиентский код и разрозненный код сборки
static async Task Main(string[] args)
{
var siloBuilder = new SiloHostBuilder()
.UseLocalhostClustering()
.UseDashboard(options => { })
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "dev";
options.ServiceId = "Orleans2GettingStarted";
})
.Configure<EndpointOptions>(options =>
options.AdvertisedIPAddress = IPAddress.Loopback)
.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning).AddConsole());
using (var host = siloBuilder.Build())
{
await host.StartAsync();
var clientBuilder = new ClientBuilder()
.UseLocalhostClustering()
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "dev";
options.ServiceId = "Orleans2GettingStarted";
})
.ConfigureLogging(logging => logging.AddConsole());
using (var client = clientBuilder.Build())
{
await client.Connect();
var random = new Random();
string sky = "blue";
while (sky == "blue") // if run in Ireland, it exits loop immediately
{
Console.WriteLine("Client giving another request");
int grainId = random.Next(0, 500);
double temperature = random.NextDouble() * 40;
var sensor = client.GetGrain<ITemperatureSensorGrain>(grainId);
// Not awaiting this task so that next call to grain
// can be made without waiting for current call to complete
Task t = sensor.SubmitTemperatureAsync((float)temperature);
Thread.Sleep(1000);
}
}
}
}
Мой интерфейс зернистости и фактическая реализация зернистости
public interface ITemperatureSensorGrain : IGrainWithIntegerKey
{
Task SubmitTemperatureAsync(float temperature);
}
public class TemperatureSensorGrain : Grain, ITemperatureSensorGrain
{
public async Task SubmitTemperatureAsync(float temperature)
{
long grainId = this.GetPrimaryKeyLong();
Console.WriteLine($"{grainId} received temperature: {temperature}");
await Task.Delay(10000);
// Thread.Sleep(10000);
Console.WriteLine($"{grainId} complete");
// return Task.CompletedTask;
}
}
В основном я отправляю запросы к зернам каждую секунду, тогда как я разрешаю каждому вызову метода внутри зерна занимать не менее 10 секунд. Теперь, согласно однопоточному выполнению гранул и расписанию времени выполнения Орлеана, описанному здесь, Я ожидаю, что запросы будут поставлены в очередь и следующий запрос не будет обработан зерном, если текущий метод запроса не завершится. Однако консоль вывод не подтверждает этого. Вывод консоли:
Client giving another request
344 received temperature: 8.162848
Client giving another request
357 received temperature: 10.32219
Client giving another request
26 received temperature: 1.166182
Client giving another request
149 received temperature: 37.74038
Client giving another request
60 received temperature: 26.72013
Client giving another request
218 received temperature: 24.19116
Client giving another request
269 received temperature: 17.1897
Client giving another request
318 received temperature: 8.562404
Client giving another request
372 received temperature: 8.865559
Client giving another request
443 received temperature: 5.254442
Client giving another request
344 complete <-------------- The first request completed here
97 received temperature: 19.24687
Это дает понять, что следующий запрос обрабатывается зерном до завершения текущего запроса.
Вопросы:
Итак, это нарушение однопоточной модели выполнения Орлеана или я что-то здесь упускаю?
Кроме того, когда я использую Thread.sleep (10000) внутри зерна вместо Task.Delay (10000), я получаю тот же вывод консоли почти за исключением дополнительного предупреждения для каждого вызова запроса -
Task [Id=1, Status=RanToCompletion] in WorkGroup [Activation: S127.0.0.1:11111:270246987*grn/6424EE47/00000028@cafcc6a5 #GrainType=Orleans2GettingStarted.TemperatureSensorGrain Placement=RandomPlacement State=Valid] took elapsed time 0:00:10.0019256 for execution, which is longer than 00:00:00.2000000
. Означает ли это, что в идеале каждое зерно должно обрабатываться за 200 мс? Что будет, если зерна перевариться дольше?
TemperatureSensorGrain(grainId: 344)
не будет выполнять несколько ходов параллельно, ноTemperatureSensorGrain
может выполнять множество разных идентификаторов параллельно. - person Dan Wilson   schedule 25.07.2018