Занимает ли реализация отправленных событий SignalR Server поток для каждого соединения?
Когда я использую signalR, который обращается к ServerSentEvents, и я вижу в fiddler открытое соединение с сервером, ожидающим фрагментированные данные, означает ли это, что в данный момент на сервере занят поток?
Если так, то это не совсем эффективно, насколько я вижу..
Например, я бы не писал такой код на сервере, который блокирует поток:
public ActionResult ServerSentEvents
{
DateTime currentdate = DateTime.Now;
Response.ContentType = "text/event-stream";
while (currentdate.AddMinutes(1) > DateTime.Now)
{
Response.Write(string.Format("data: {0}\n\n", DateTime.Now.ToString()));
Response.Flush();
System.Threading.Thread.Sleep(1000);
}
}
Может ли быть так, что SignalR делает что-то более эффективно здесь?
3 ответа
Это выглядит как код контроллера MVC, а не код SignalR Hub
В любом случае SignalR поддерживает асинхронную среду в.NET 4.5, так что вы можете вместо этого вернуть Задачу из этого метода и иметь один фоновый поток, обрабатывающий состояние ожидания, и когда задача ожидает 1000 мс, вы продолжите эту задачу.
Вы никогда не должны иметь Thread.Sleep
в требовательном потоке это полностью убивает масштабируемость, и это является причиной того, что Frameworks, такие как Entity Framework и ADO.NET, поддерживают асинхронные операции (операция ввода-вывода, такая как Database, похожа на Thread.Sleep
)
редактировать: если вы ни по какой причине не хотите использовать SignalR, вы можете использовать Задачи из MVC 4 или AsyncController в MVC 3 и более ранних версиях. Но я бы порекомендовал SignalR, так как они делают всю сантехнику для вас
Да. (или "Возможно", в зависимости от того, как реализован SignalR.)
SSE держит сокет открытым между сервером и клиентом. Вы сказали, что не будете писать код, который делает System.Threading.Thread.Sleep(1000);
но это кажется достаточно эффективным. Когда вы переводите поток в спящий режим, он перестает использовать ядро ЦП, и другой поток получает возможность запуска на ЦП.
Возможно, что SignalR не использует один поток на клиентское соединение. Он может использовать цикл while, который циклически обрабатывает дескрипторы сокетов и пробует чтение каждого из них по очереди, но выполняется в одном потоке. (Например, PHP не поддерживает потоки, поэтому, если вы хотите запустить многопользовательский сервер, то, как вы это делаете). Эффективность - это то же самое, что и использование нитей. Но потоки - это недорогая абстракция, которая обычно делает кодирование немного проще.
Мне кажется, что вы делаете преждевременную оптимизацию. Если профилирование не показало, что узкое место - это издержки переключения контекста, когда потоки включаются и выключаются из ЦП, беспокоиться не о чем.
Ваш пример очень странный. Если это подразумевается как пример совершенно неправильного серверного кода, то его идеальный...... любой, кто обрабатывает фактическое соединение (и читает с него), зависит от того, как вы размещаете свой сервер (IIS против собственного хоста, использующего Owin).
IIS - я уверен, что для каждого соединения нет блокировки потоков. IIS обрабатывает чтение из сокета, используя что-то вроде портов завершения ввода-вывода
Owin\HttpListener - здесь я в равной степени уверен, что SignalR использует асинхронные операции для чтения из соединения (и ожидания данных). Которые под прикрытием также используют порты завершения ввода-вывода.
-> Поток не блокируется на сервере, пока соединение открыто и не получает данные от клиента...