Комментарии 45
Спасибо за ссылку на threadpool. Сейчас то же самое используем, и пока что боролись с ограничением на потоки с помощью разных «подпорок».
0
А чем не подошли WCF сервисы? msdn.microsoft.com/en-us/library/bb398998.aspx
0
Понимаете, суть технологии Comet заключается в передаче данных клиентам по инициативе сервера, а не самих клиентов. В идеале это постоянное соединение между клиентом и сервером, и именно сервер, когда считает нужным (по возникновению какого-то серверного события, например), выдает клиенту данные. В том же примере из MSDN, который вы привели, отнюдь не сервер решает, когда данные должны быть отправлены клиенту, это решает клиент путем асинхронного вызова метода веб-сервиса. Таким образом, чтобы обеспечить обновление данных на клиенте в режиме близком к режиму реального времени, вам придется постоянно вызывать данный метод (в частности, по таймеру), проверяя, есть ли серверу чем поделиться. Недостатки такого подхода уже описаны в первом абзаце статьи.
+5
НЛО прилетело и опубликовало эту надпись здесь
В WCF есть поддержка дуплексных биндингов (через http (wsDualHttpBinding), tcp (netTcpBinding и netPeerTcpBinding) и именованные каналы), с помощью которых сервер может делать запросы к клиенту. Другой вопрос, есть в каком-нибудь js-фреймворке реализация требуемой для этого клиентской части.
+1
Спасибо большое, хороший материал. Вот только разобраться с сорсом было бы гораздо проще, нежели читать здесь.
Если у вас остался этот проектик, не могли бы выложить архив?
Если у вас остался этот проектик, не могли бы выложить архив?
+3
Скажите, это у вас в интранете или ориентировано на широкий круг пользователей?
0
Ориентировано на широкий (в перспективе даже очень широкий) круг пользователей, однако, как я уже писал, масштабный стресс-тест такого подхода провести пока не было возможности (честно говоря, мы пока не нашли подходящий способ, поэтому я в конце статьи просил поделиться наработками, если кто-то сталкивался с подобным). Лично я проверял на 25 клиентах (и сервер, и клиенты были на одной машине) при пушинге частотой до десятка раз в секунду, при этом нагрузка на CPU была настолько мизерной, что стандартным Task Manager'ом ее даже невозможно было разглядеть.
0
НЛО прилетело и опубликовало эту надпись здесь
Спасибо, за статью!
Некоторое время назад я проделал подобную работу (задача, правда, немного отличалась) и столкнулся с проблемой, что, не получается определить подсоединен ли еще клиент или уже закрыл страницу.
Может оказаться, что вы обслуживаете уже давно «мертвых» клиентов.
В моем случае, основное отличие было в том, что обновления приходили очень нерегулярно. В течении одной минуты их могло быть сотня, а потом в течении часа затишье.
Некоторое время назад я проделал подобную работу (задача, правда, немного отличалась) и столкнулся с проблемой, что, не получается определить подсоединен ли еще клиент или уже закрыл страницу.
Может оказаться, что вы обслуживаете уже давно «мертвых» клиентов.
В моем случае, основное отличие было в том, что обновления приходили очень нерегулярно. В течении одной минуты их могло быть сотня, а потом в течении часа затишье.
+1
Использование события unload для определения дисконнекта клиента является, наверное, самым очевидным решением для решения данной проблемы. Минус, правда, тоже очевиден — реконнект клиента при постбэках. Интересно узнать, как Вы решили эту проблему?
0
Эта идея хорошо сработает для переходов на другие страницы, либо для правильного закрытия окна,
но совершенно не работает при разрыве связи или других аварийных ситуациях.
Как вариант, можно периодически писать что-то (проблемы, например) в поток OutputStream. По идее, если клиент отключился, то будет ошибка и св-во IsConnected обновится.
Я не проверял этот метод, может вам будет интересно проверить.
но совершенно не работает при разрыве связи или других аварийных ситуациях.
Как вариант, можно периодически писать что-то (проблемы, например) в поток OutputStream. По идее, если клиент отключился, то будет ошибка и св-во IsConnected обновится.
Я не проверял этот метод, может вам будет интересно проверить.
0
Вы не подскажете, пока клиент ждет, можно ли отправлять другие аякс-запросы? Другими словами — сколько одновременных запросов можно слать?
+1
Это то, что вы ищите?
0
Вообще по стандарту рекомендуется открывать не более 2 соединений на домен.
В данном случае получится один гонит данные в одну сторону, другой в другую. Чтобы можно было передавать разные данные, нужно использовать мультиплексирование, например, Bayeux Protocol.
В данном случае получится один гонит данные в одну сторону, другой в другую. Чтобы можно было передавать разные данные, нужно использовать мультиплексирование, например, Bayeux Protocol.
0
Спасибо за статью! Интересная тема и написано хорошо. Возможно я невнимательный читатель, но у меня остался один вопрос. В начале вы описали задачу и все было затеяно (как я понял) с целью применть этот Comet for ASP.NET подход в своем проекте. Так вы его применили в конце концов или нет? Какие у вас были результаты? Проблемы?
0
Как раз вчера пришла спецификация, сегодня начинаем наращивать на этот Comet-скелет сухожилия и мышцы. Предварительные результаты описаны в этом комментарии. Как дойдет дело до масштабных испытаний и стрессовых нагрузок, отпишу дополнительно.
0
Ну думали про использование готовых серверов/клиенских библиотек для организации Comet взаимодействия? Есть ведь много чего, в том числие модули для nginx и вспомогательные библиотеки для клиентской стороны. Еще интересно, как расчитывали сколько потребуется ресурсов на сервер для поддержки постоянно открытых соединений.
Запросы раз в 5 секунд кстати вовсе не факт что будут создавать свое соединение, но это мелочи, для realtime действительно лучше comet или websockets (когда заработают).
Запросы раз в 5 секунд кстати вовсе не факт что будут создавать свое соединение, но это мелочи, для realtime действительно лучше comet или websockets (когда заработают).
0
О готовых решениях думал, читал. Однако Comet настолько заинтересовал, что дико захотелось реализовать самому. Кое-что из этого желания, как видим, все-таки вышло :) Что касается ресурсов, какие именно вы имеете в виду?
0
Я встерчал например что на 10000 соединений нужно 450Мб памяти, по 45Кб на соединение. По крайней мере с этого началось и двигалось в сторону уменьшения в этой статье: aleccolocco.blogspot.com/2008/10/gazillion-user-comet-server-with.html. В этой статье рассматривался Linux/C++, интересно что покажет .NET.
Мне интересно какой например нужен VPS хостинг чтобы поддерживать Comet соединения.
Мне интересно какой например нужен VPS хостинг чтобы поддерживать Comet соединения.
0
Скажите, а зачем вы делаете вот это:
newGuid = Guid.NewGuid();
if (_clientStateList.Find(s => s.ClientGuid == newGuid) == null)
Разве свежесгенерированный GUID не является уникальным во времени и пространстве? По крайней на одной и той же машине два последовательных значения GUID точно должны быть уникальны. Т.е. вторая строчка похожа на какую-то дикую перестраховку, т.к. заведомо дает true.
newGuid = Guid.NewGuid();
if (_clientStateList.Find(s => s.ClientGuid == newGuid) == null)
Разве свежесгенерированный GUID не является уникальным во времени и пространстве? По крайней на одной и той же машине два последовательных значения GUID точно должны быть уникальны. Т.е. вторая строчка похожа на какую-то дикую перестраховку, т.к. заведомо дает true.
+1
Это на всякий случай, вдруг (раз в 100 лет) программа сгенерирует Guid, который уже зарегистрирован в системе…
Как говорится — береженого…
Как говорится — береженого…
+1
Вероятность того, что значение нового Guid будет содержать одни нули или окажется равным какому-либо другому Guid, предельно мала. ©MSDN
Предельно мала, но все-таки не равна нулю.
Предельно мала, но все-таки не равна нулю.
0
Глядя на ваш код C#, у меня осталось ощущение, что на вас давит тяжкое наследие Си. Так ли это?
Я думаю, что C#-код можно было бы сократить раза в 2, подняв читабельность
Я думаю, что C#-код можно было бы сократить раза в 2, подняв читабельность
0
Скорее это пережитки не так давно покинутой предыдущей конторы с ее тоннами документации по оформлению кода. Если не сложно, укажите на конкретные места и лучшие решения — учиться, как говорится, никогда не поздно.
0
и лучшим тому подтверджением будет ссылка на архив с вашим компактным и читаемым вариантом
+1
Договорились. Только вечером, когда домой приду.
0
Привет, а вот и читаемый вариант:
www.filefront.com/15440909/skeleton.zip
Введения:
— autoproperties
— in-place init
— выкинул locker object — он не нужен, у вас карго-культ имхо.
— прикрутил read-only везде, где можно.
В методических целях и проверка guid «на существование» не нужна.
www.filefront.com/15440909/skeleton.zip
Введения:
— autoproperties
— in-place init
— выкинул locker object — он не нужен, у вас карго-культ имхо.
— прикрутил read-only везде, где можно.
В методических целях и проверка guid «на существование» не нужна.
0
В ASP.NET есть встроенная возможность для AJAX запросов UpdatePanel.По идее, можно совершенно без проблем прикрутить её к Long Polling Requests и сразу убьем двух зайцев.
При этом практически избавляемся от клиентского кода и используем стандартные механизмы ASP.NET.
При этом, конечно, можно незначительно потерять в быстродействии, если объемы большие, но о такой возможности, как минимум, стоит знать.
При этом практически избавляемся от клиентского кода и используем стандартные механизмы ASP.NET.
При этом, конечно, можно незначительно потерять в быстродействии, если объемы большие, но о такой возможности, как минимум, стоит знать.
0
как по прошествии времени проявило себя Ваше решение?
0
Спасибо за статью. При реализации появился странный баг. — при добавлении файла global.asax — второй запрос висел (первый не отпускал сервер), дело оказалось в методе Session_start. Начал копать дальше и выяснил, что не даёт освободить запрос — интерфейс System.Web.SessionState.IRequiresSessionState. Вместо его следует использовать: IReadOnlySessionState. Происходит это потому что для записи сессия доступна только одному потоку, а остальные ждут. В режиме же чтения проблема многопоточности разрешается — читать могут все.
0
Не приведёт ли к утечкам памяти то, что вы сохраняется объект HttpContext в статическое поле (по сути глобальная переменная)?
0
Класс CometClientProcessor вы имеете в виду?
0
Да
0
Могут быть утечки, если не учесть все особенности дисконнекта клиента (а здесь они не все учтены и не все совсем корректно, код старый). Можете на досуге поразмыслить, как эти утечки исключить :)
А вообще данную статью в силу непрерывно текущего времени нужно уже рассматривать как своеобразный экскурс аля «примерно вот так оно работает», т.е. исключительно для расширения кругозора. На практике давно уже можно пользоваться готовыми бесплатными решениями, коих нынче много развелось, например SignalR.
А вообще данную статью в силу непрерывно текущего времени нужно уже рассматривать как своеобразный экскурс аля «примерно вот так оно работает», т.е. исключительно для расширения кругозора. На практике давно уже можно пользоваться готовыми бесплатными решениями, коих нынче много развелось, например SignalR.
0
SignalR это, конечно, хорошо. Но открыв его исходники, становится как-то страшно.
Кода столько, как будто собственный веб-сервер написан, и к тому же он привязан к jQuery, что мне вовсе не подходит.
Утечки по идее можно обойти используя HttpContext.Current.Cache (чтобы по таймауту всё само удалялось если долго не используется).
Меня больше интересует, нет ли какой-то встроенной в asp.net альтернативы используемому здесь ThreadPool и без тех проблем описанные у вас, и к тому же чем он лучше, ведь он также создаёт поток?
Кода столько, как будто собственный веб-сервер написан, и к тому же он привязан к jQuery, что мне вовсе не подходит.
Утечки по идее можно обойти используя HttpContext.Current.Cache (чтобы по таймауту всё само удалялось если долго не используется).
Меня больше интересует, нет ли какой-то встроенной в asp.net альтернативы используемому здесь ThreadPool и без тех проблем описанные у вас, и к тому же чем он лучше, ведь он также создаёт поток?
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Comet для ASP.NET своими руками