Skip to Content

Настройка RDP2 версии 1.25.9.x

Введение

Начиная с версии 1.25.9.x службы WebApi и RDP2 могут взаимодействовать одим из двух способов:

  1. REST-запросами по протоколу HTTP(S), способ по умолчанию;
  2. Сообщениями через шину по протоколу MQTT-over-WebSockets на базе RabbitMQ.

Взаимодействие служб WebApi и RDP2 с помощью REST-запросов

При старте служба RDP2 отправляет уведомление об используемом AddressFilter с помощью запроса PUT /api/RdpSessions/UpdateAddressFilter.

На регулярной основе служба RDP2 запрашивает все “причитающиеся” ей сессии RDP и, после обработки, отправляет состояние этих сессий обратно в WebApi. Для запроса сессий используется GET /api/RdpSessions?addressFilter={filterString}. Для отправки состояний - запрос PUT api/RdpSessions/UpdateConnectionStatuses. В этом же цикле обработки служба RDP2 уведомляет WebApi о необходимости проверить периоды простоя для машин роботов с помощью запроса GET api/RdpSessions/CheckNoRdpPeriods?addressFilter={filterString}.

При необходимости завершить сессию RDP, служба RDP2 отправляет запрос PUT api/RdpSessions/{id}/SetNeedForLogOffRDPSessionUser.

Взаимодействие служб WebApi и RDP2 по протоколу MQTT-over-WebSockets

При старте или останове служба RDP2 отправляет в шину уведомление об этом в сообщении RdpServiceNoticeMessage с RdpServiceNotice внутри:

/// <summary> /// Данные, отправляемые службой RDP2 для WebApi при старте или останове службы RDP2 /// </summary> public class RdpServiceNotice { /// <summary> /// Перечень адресов обслуживаемых службой RDP2, все доступные адреса, если значение пустое. /// </summary> public string AddressFilter { get; set; } /// <summary> /// IP-адрес машины со службой RDP2. /// </summary> public string Host { get; set; } /// <summary> /// Флаг запуска/останова службы RDP2. /// </summary> public bool IsStarted { get; set; } }

Служба WebApi, получив это сообщение, сохраняет информацию в таблице Rdp2AddressFilters и отправляет в шину полный список “причитающихся” этой службе RDP2 сессий RDP в сообщении RdpSessionDataMessage, где каждая сессия представлена классом RdpSessionData:

public class RdpSessionData { public int Id { get; set; } /// <summary> /// Имя RDP-пользователя /// </summary> public string AdminName { get; set; } // TODO: зачем 2? /// <summary> /// Имя RDP-пользователя /// </summary> public string UserName { get; set; } /// <summary> /// Пароль пользователя. /// </summary> public string Password { get; set; } /// <summary> /// Ip-адрес удаленного компьютера. /// </summary> public string Address { get; set; } /// <summary> /// Флаг поднимается автоматически, если установлен NeedNoRdpPause и на сервере нет активных сессий роботов (оркестраторных) /// Флаг сбрасывается автоматически по истечении паузы (длительность задается в NoRdpPauseDurationInSeconds). /// </summary> public bool IsNoRdpPause { get; set; } /// <summary> /// Флаг поднимается, если нужно устроить "паузу" на машине без сессий роботов (оркестраторных). /// Флаг сбрасывается автоматически после начала паузы. /// </summary> public bool NeedNoRdpPause { get; set; } /// <summary> /// Длительность паузы без сессий роботов (оркестраторных). /// </summary> public int NoRdpPauseDurationInSeconds { get; set; } = 60; /// <summary> /// Продолжать поддерживать RDP-сессию (тогда больше никто не сможет подключиться по RDP) /// Если надо подключиться по RDP отдельно, должен быть сброшен /// </summary> public bool KeepRdpSession { get; set; } public bool UserProfileLoaded { get; set; } public int AuthenticationLevel { get; set; } public bool NegotiateSecurityLayer { get; set; } public bool EnableCredSspSupport { get; set; } public int DesktopWidth { get; set; } public int DesktopHeight { get; set; } public int ColorDepth { get; set; } public bool Connected { get; set; } /// <summary> /// Последняя дата переключения true/false или false/true для Connected /// </summary> public DateTime? ConnectedChangedAt { get; set; } /// <summary> /// Последняя дата обновления Connected (не обязательно именно переключения true/false или false/true) /// </summary> public DateTime? ConnectedUpdatedAt { get; set; } public int WorkerId { get; set; } public int? RdpPort { get; set; } /// <summary> /// Переподключить сессию принудительно, даже если она подключена. /// Только для Windows RDP. /// </summary> public bool? ForceKeepRdpSession { get; set; } }

При необходимости включить или отключить сессию RDP, служба WebApi отправляет в шину сообщение RdpSessionDataMessage с одной сессией в теле.

Служба RDP2 получает из шины сообщения RdpSessionDataMessage и сохраняет во внутреннем кэше “причитающиеся” ей сессии RDP. На регулярной основе служба RDP2 проверяет состояние сессий из внутреннего кэша и, при необходимости, останавливает или запускает их. В конце каждого цикла проверки служба RDP2 отправляет в шину сообщение RdpSessionStatusesMessage со статусами каждой обслуживаемой сессии:

/// <summary> /// Информация о состоянии сессии RDP. /// </summary> public sealed class RdpSessionStatus { /// <summary> /// Id сессии. /// </summary> public int SessionId { get; set; } /// <summary> /// Подключена ли сессия. /// </summary> public bool Connected { get; set; } /// <summary> /// Время изменения подключения. /// </summary> public DateTime ConnectedChangedAt { get; set; } /// <summary> /// Время обновления подключения. /// </summary> public DateTime ConnectedUpdatedAt { get; set; } }

и сообщение RdpCheckPausePeriodsMessage со своим AddressFilter.

При необходимости завершить сессию RDP, служба RDP2 отправляет в шину сообщение RdpSetNeedForLogoffMessage с идентификатором сессии.

Для включения режима взаимодействия через шину необходимо настроить службы RabbitMQ, NGINX, WebApi и RDP2.

Настройка RabbitMQ

В консоли сервера, на котором работает RabbitMQ, необходимо выполнить следующие команды с правами пользователя-администратора (для Windows необходимо предварительно перейти в каталог C:\Program Files\RabbitMQ Server\rabbitmq_server-Версия\sbin):

rabbitmq-plugins enable rabbitmq_mqtt rabbitmq-plugins enable rabbitmq_web_mqtt

При использовании брандмауэра необходимо открыть порт tcp/15675, который используется для MQTT-over-WebSockets.

Настройка NGINX

Для проксирования запросов клиентов к службе MQTT сервера RabbitMQ необходимо добавить в конфигурацию NGINX (nginx.conf) следующее (выделено полужирным шрифтом):

http { ... upstream mqtt { server <IP или имя сервера RabbitMQ>:15675; } ... server { ... location /mqtt/ { proxy_pass http://mqtt; rewrite ^/mqtt/(.*)$ /$1 break; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } ... }

После внесения изменений в файл nginx.conf необходимо проверить правильность файла:

nginx -t

и, в случае отсутсвия ошибок, перезапустить службу NGINX.

Настройка службы WebApi

Служба WebApi может взаимодействовать со службами RDP2 одновременно двумя способами: REST-запросами и через шину сообщений, в зависимости от того, какой метод настроен для конкретной службы RDP2.

Для включения взаимодействия через шину, необходимо добавить в файл appsettings.XXX.json раздел Mqtt:

{ ... }, "Mqtt": { "Url": "wss://<IP или имя и порт сервера NGINX>/mqtt/ws", "Username": "<пользователь RabbitMQ>", "Password": "<(зашифрованный) пароль пользователя RabbitMQ>" }, ... }

Настройка службы RDP2

Для включения режима взаимодействия через шину сообщений, необходимо добавить в файл appsettings.XXX.json раздел Mqtt:

{ ... }, "Mqtt": { "Url": "wss://<IP или имя и порт сервера NGINX>/mqtt/ws", "Username": "<пользователь RabbitMQ>", "Password": "<(зашифрованный) пароль пользователя RabbitMQ>" }, ... }

В случае отсутствия раздела Mqtt или пустом значении параметра Url взаимодействие по шине сообщений будет отключено.