Поделиться через


События заданий и задач пакета HPC 2016 в SignalR

События задания и задачи пакета HPC можно получать в клиенте SingalR . Существуют различные клиенты для разных языков программирования. Здесь мы рассмотрим C# пример получения событий задания и задачи.

  1. Установите Microsoft.AspNet.SignalR.Clientклиента C#.

  2. using Microsoft.AspNet.SignalR.Client и Microsoft.AspNet.SignalR.Client.Transports в коде.

  3. Затем вы создадите экземпляр HubConnection, например:

    var hubConnection = new HubConnection(url)
    

    Здесь url — "https://{имя кластера-or-ip}/hpc".

    При необходимости можно выполнить трассировку ошибок подключения.

    var hubConnection = new HubConnection(url) { TraceLevel = TraceLevels.All, TraceWriter = Console.Error };
    

    Кроме того, можно добавить обработчик ошибок, например:

    hubConnection.Error += ex => Console.Error.WriteLine($"HubConnection Exception:\n{ex}");
    

    Необходимо указать учетные данные для доступа к событиям. Здесь используется обычная проверка подлинности HTTP:

    hubConnection.Headers.Add("Authorization", BasicAuthHeader(username, password));
    
  4. Затем вы создаете объекты прокси-сервера концентратора из подключения концентратора и прослушиваете события из них.

    Для событий задания вы создаете JobEventHub и прослушиваете событие JobStateChange:

    var jobEventHubProxy = hubConnection.CreateHubProxy("JobEventHub");
    jobEventHubProxy.On("JobStateChange", (int id, string state, string previousState) =>
    {
      Console.WriteLine($"Job: {id}, State: {state}, Previous State: {previousState}");
    });
    

    Для событий задачи вы создаете TaskEventHub и прослушиваете событие TaskStateChange:

    var taskEventHubProxy = hubConnection.CreateHubProxy("TaskEventHub");
    taskEventHubProxy.On("TaskStateChange", (int id, int taskId, int instanceId, string state, string previousState) => 
    {
      Console.WriteLine($"Job: {id}, Task: {taskId}, Instance: {instanceId}, State: {state}, Previous State: {previousState}");
    });
    
  5. Затем подключитесь к серверу с помощью

    await hubConnection.Start(new WebSocketTransport())
    

    Здесь мы явно указываем WebSocketTransport. SignalR поддерживает различные способы транспорта. Но мы выбираем WebSocket. Если вы используете транспорт, отличный от WebSocket, вы не можете получить какие-либо события или не подключиться.

  6. Наконец, вы вызываете метод BeginListen в объекте прокси концентратора, чтобы начать прослушивание. Необходимо указать идентификатор задания, который требуется прослушивать события задания или задачи.

    try
    {
      await jobEventHubProxy.Invoke("BeginListen", jobId);
      await taskEventHubProxy.Invoke("BeginListen", jobId);
    }
    catch (Exception ex)
    {
      Console.Error.WriteLine($"Exception on invoking server method:\n{ex}");
      return null;
    }
    

    Блок catch перехватывает ошибки на сервере при вызове метода BeginListen. Для других ошибок при подключении к концентратору может потребоваться использовать обработчик ошибок, как на предыдущем шаге.

Весь фрагмент кода:

using Microsoft.AspNet.SignalR.Client;
using Microsoft.AspNet.SignalR.Client.Transports;

//...

string BasicAuthHeader(string username, string password)
{
    string credentials = $"{username}:{password}";
    byte[] bytes = Encoding.ASCII.GetBytes(credentials);
    string base64 = Convert.ToBase64String(bytes);
    return $"Basic {base64}";
}

async Task<HubConnection> ListenToJobAndTasks(string url, int jobId, string username, string password)
{
    var hubConnection = new HubConnection(url) { TraceLevel = TraceLevels.All, TraceWriter = Console.Error };
    hubConnection.Headers.Add("Authorization", BasicAuthHeader(username, password));
    hubConnection.Error += ex => Console.Error.WriteLine($"HubConnection Exception:\n{ex}");

    var jobEventHubProxy = hubConnection.CreateHubProxy("JobEventHub");
    jobEventHubProxy.On("JobStateChange", (int id, string state, string previousState) =>
    {
        Console.WriteLine($"Job: {id}, State: {state}, Previous State: {previousState}");
    });

    var taskEventHubProxy = hubConnection.CreateHubProxy("TaskEventHub");
    taskEventHubProxy.On("TaskStateChange", (int id, int taskId, int instanceId, string state, string previousState) =>
    {
        Console.WriteLine($"Job: {id}, Task: {taskId}, Instance: {instanceId}, State: {state}, Previous State: {previousState}");
    });

    Console.WriteLine($"Connecting to {url} ...");
    try
    {
        await hubConnection.Start(new WebSocketTransport());
    }
    catch (Exception ex)
    {
        Console.Error.WriteLine($"Exception on starting:\n{ex}");
        return null;
    }

    Console.WriteLine($"Begin to listen...");
    try
    {
        await jobEventHubProxy.Invoke("BeginListen", jobId);
        await taskEventHubProxy.Invoke("BeginListen", jobId);
    }
    catch (Exception ex)
    {
        Console.Error.WriteLine($"Exception on invoking server method:\n{ex}");
        return null;
    }

    return hubConnection;
}