Добрый день! Есть клиент-серверное приложение для передачи торговой информации.Есть две проблемы:
1) Низкая производительность сервиса ( до 1500 колбеков в секунду)
2) Когда один из клиентов начинает зависать(например,проблемы с интернетом) все пользователи начинают медленнее получать данные (до 200 колбеков в секунду)
Здравствуйте, alex_2371430, Вы писали: _>Подскажите,пожалуйста,как можно решить эти проблемы
Никак. Большое количество маленьких сообщений — killing scenario для WCF. Группируй сообщения в пачки и рассылай всем 2-3 раза в секунду — уже станет полегче. С "плохим каналом у одного клиента" из коробки пожалуй ничего не сделаешь — придется ручками реализовывать очередь поставщик-потребитель и писать свой биндинг. И еще наткнешься на ограниченное кол-во одновременно подключенных клиентов — у меня после 2 тысяч одновременных колбеков все становилось совсем плохо и где-то после 4х — все умирало напрочь.
Здравствуйте, itslave, Вы писали:
I>Здравствуйте, alex_2371430, Вы писали: _>>Подскажите,пожалуйста,как можно решить эти проблемы I>Никак. Большое количество маленьких сообщений — killing scenario для WCF. Группируй сообщения в пачки и рассылай всем 2-3 раза в секунду — уже станет полегче. С "плохим каналом у одного клиента" из коробки пожалуй ничего не сделаешь — придется ручками реализовывать очередь поставщик-потребитель и писать свой биндинг. И еще наткнешься на ограниченное кол-во одновременно подключенных клиентов — у меня после 2 тысяч одновременных колбеков все становилось совсем плохо и где-то после 4х — все умирало напрочь.
Хотя по поводу своего биндинга я погорячился. Достаточно очереди поставщик-потребитель при отправке колбеков.
Из описания совсем-совсем непонятно, кто кого вызывает и как вообще все устроено.
Сервер все время пушит клиентам данные (через callback-интерфейс)? Если да — то по какому принципу? В бесконечном цикле, так часто, как успеет? Или как?
Здравствуйте, Tom, Вы писали:
Tom>А ты уверен что проблема в WCF? А не в коде который собственно эти колбэки и вызывает? Вызываются они надеюсь не последовательно а паралельно?
100% у него последовательно.
Однако распареллеливание "в лоб", через ThreadPool, убьет перфоманс быстрей последовательной отправки
И ет я про оверхед трафика молчу
Здравствуйте, scale_tone, Вы писали:
_>Из описания совсем-совсем непонятно, кто кого вызывает и как вообще все устроено.
Судя по именам методов, я догадываюсь про предметную область, а судя по постановке вопроса — про "архитектуру" _>Сервер все время пушит клиентам данные (через callback-интерфейс)? Если да — то по какому принципу? В бесконечном цикле, так часто, как успеет? Или как?
100% сервер оповещает клиентов, по наступлению некоторого события. Достаточно часто, до 300 раз в секунду.
Tom>>А ты уверен что проблема в WCF? А не в коде который собственно эти колбэки и вызывает? Вызываются они надеюсь не последовательно а паралельно? I>100% у него последовательно.
В этом и проблема
I>Однако распареллеливание "в лоб", через ThreadPool, убьет перфоманс быстрей последовательной отправки
Ты попробуй через таски, там не совсем честный ThreadPool.
Есть ещё очереди откуда таск работающий в потоке ThreadPool-а может брать таски.
Должно работать очень эффективно.
По крайней мере стоит проверить.
I>И ет я про оверхед трафика молчу
А причём тут трафик вообще? Я про последовательный/паралельный вызов колбэков...
Здравствуйте, Tom, Вы писали:
I>>Однако распареллеливание "в лоб", через ThreadPool, убьет перфоманс быстрей последовательной отправки Tom>Ты попробуй через таски, там не совсем честный ThreadPool. Tom>Есть ещё очереди откуда таск работающий в потоке ThreadPool-а может брать таски. Tom>Должно работать очень эффективно. Tom>По крайней мере стоит проверить.
А там можно выделить максимальное число потоков на обслуживание тасков? Если да — то тот жы поставщик-потребитель, только в профиль. Если нет — на нагрузках ТС(тысячи подключенных клиентов, которых надо оповестить сотни раз в секунду) оно все равно умрет. Может чуть медленее.
Tom>А причём тут трафик вообще? Я про последовательный/паралельный вызов колбэков...
А ет следующий вопрос, который задаст ТС
Здравствуйте, scale_tone, Вы писали:
_>Здравствуйте, alex_2371430, Вы писали:
_>Из описания совсем-совсем непонятно, кто кого вызывает и как вообще все устроено.
_>Сервер все время пушит клиентам данные (через callback-интерфейс)? Если да — то по какому принципу? В бесконечном цикле, так часто, как успеет? Или как?
_>Или клиент что-то спрашивает, а сервер отвечает?
Да,сервер рассылает клиентам данные (через callback-интерфейс).
Если упустить подробности:есть BlockingCollection<T> в нее добавляются объекты для отправки,есть 8 Task'ов которые обрабатывают её примерно следующим:
factory.StartNew(() => Sending(DeliveryBuffer));
public void Sending( BlockingCollection<ConvertedEntity> sendBuff)
{
foreach(var ent in sendBuff.GetConsumingEnumerable() )
{
//send update..
}
}
Решение которое мы приняли — отказ от WCF и переход на Socket'ы и ProtoBuff .NET для сериализации.Результат — до 30к апдейтов в секунду.Думаю тема более не актуальна
Здравствуйте, alex_2371430, Вы писали:
_>Здравствуйте, scale_tone, Вы писали:
_>>Здравствуйте, alex_2371430, Вы писали:
_>>Из описания совсем-совсем непонятно, кто кого вызывает и как вообще все устроено.
_>>Сервер все время пушит клиентам данные (через callback-интерфейс)? Если да — то по какому принципу? В бесконечном цикле, так часто, как успеет? Или как?
_>>Или клиент что-то спрашивает, а сервер отвечает?
_>Да,сервер рассылает клиентам данные (через callback-интерфейс). _>Если упустить подробности:есть BlockingCollection<T> в нее добавляются объекты для отправки,есть 8 Task'ов которые обрабатывают её примерно следующим: _>
Есть подозрение что в foreach у тебя лочится вся коллекция и все потоки дружно ждут, пока один из них не пробежит целый цикл.
Надо отправку одного сообщения одному клиенту выделять в отдельную задачу — тогда будет могопоточность. Но ет имха тебя не сильно спасет. Озвучь требования к количеству одновременно подключенных клиентов и к количеству событий в секунду, о которых надо оповестить клиентов.
Здравствуйте, alex_2371430, Вы писали:
_>Решение которое мы приняли — отказ от WCF и переход на Socket'ы и ProtoBuff .NET для сериализации.Результат — до 30к апдейтов в секунду.Думаю тема более не актуальна
Самопальные протоколы — это тот еще геморой. Затрахаетесь с "допиливанием" — поддержкой безопасного соединения, масштабируемость и т.д.
Поэтому, я бы рекомендовал
1. Найти низкоуровневую сетевую "сокетную" библиотеку. Они есть.
2. Реализовать на ней высоконагруженную часть, т.е. колбеки.
3. Все остальное оставить на WCF. Потом придется прикручивать секурити, ssl и т.д. — в WCF ет делается просто и легко.
Здравствуйте, alex_2371430, Вы писали:
I>>Надо отправку одного сообщения одному клиенту выделять в отдельную задачу — тогда будет могопоточность.
_>Изначально так было,но отказались от такого варианта — слишком большое количество потоков,производительность была только хуже
3й раз: очередь поставщик-потребитель, специально для такого придумана...
Здравствуйте, itslave, Вы писали:
I>Здравствуйте, alex_2371430, Вы писали:
_>>Решение которое мы приняли — отказ от WCF и переход на Socket'ы и ProtoBuff .NET для сериализации.Результат — до 30к апдейтов в секунду.Думаю тема более не актуальна I>Самопальные протоколы — это тот еще геморой. Затрахаетесь с "допиливанием" — поддержкой безопасного соединения, масштабируемость и т.д. I>Поэтому, я бы рекомендовал I>1. Найти низкоуровневую сетевую "сокетную" библиотеку. Они есть. I>2. Реализовать на ней высоконагруженную часть, т.е. колбеки. I>3. Все остальное оставить на WCF. Потом придется прикручивать секурити, ssl и т.д. — в WCF ет делается просто и легко.
Примерно так и сделали) Только: I>1. Найти низкоуровневую сетевую "сокетную" библиотеку. Они есть.
А чем плохие обычные System.Net.Sockets? I>Самопальные протоколы — это тот еще геморой. Затрахаетесь с "допиливанием" — поддержкой безопасного соединения, масштабируемость и т.д.
Здравствуйте, alex_2371430, Вы писали: _>А чем плохие обычные System.Net.Sockets?
Тем что прийдется очень многие веще реализовывать вручную. Ту же очередь поставщик-потребитель, поддержку безопасного соединения, хождение через прокси сервера, обработку ошибок, передачу креденшналов, обработку обрывов соединений и многое другое. Другими словами вы построите кучу велосипедов с квадратными колесами, убьете дофига сил и времени, чтобы сделать колеса восьмиугольными и будете жутко гордиться своими достижениями. _>ProtoBuf .net — не самопальный протокол,а протокол для сериализации от Google. http://code.google.com/p/protobuf-net/
Это я в курсе, мой камент был про использование сокетов. Померяйте оверхед сериализации ProtoBuf, я думаю он не сильно будет больше оверхеда стандартных сериализаторов. Кстате можно ышо и паковать на лету перед отправкой. Но ет уже детали.
В любом случае, если я правильно понимаю предметную область, раздачу котировок "в лоб с одного сервера на 10 000 клиентов" сделать не получится. Ни с сокетами ни с WCF.
I>Есть подозрение что в foreach у тебя лочится вся коллекция и все потоки дружно ждут, пока один из них не пробежит целый цикл.
Нет,после вызова GetConsumingEnumerable коллекция не лочится.Одновременно несколько потоков пихают в нее данные,и несколько обрабатывают.
Я не думаю что проблема в коде,скорее дело в конфигурации или каких-то хитростях WCF.При локальном подключении (сервер и клиент запущен на одной машине) скорость возрастает в 2-3 раза.
Предметную область ты понял правильно,нужно отдавать маркетдату клиентам, цель — хотя-бы 3-4к апдейтов на всех пользователей.
Здравствуйте, itslave, Вы писали:
I>Здравствуйте, alex_2371430, Вы писали: _>>А чем плохие обычные System.Net.Sockets? I>Тем что прийдется очень многие веще реализовывать вручную. Ту же очередь поставщик-потребитель, поддержку безопасного соединения, хождение через прокси сервера, обработку ошибок, передачу креденшналов, обработку обрывов соединений и многое другое. Другими словами вы построите кучу велосипедов с квадратными колесами, убьете дофига сил и времени, чтобы сделать колеса восьмиугольными и будете жутко гордиться своими достижениями.
Не посоветуешь библиотеку с указанным тобой функционалом?