Netty вопросы по реализации UDP

Сеть в Unity3D

Netty вопросы по реализации UDP

Сообщение grabedinex 27 авг 2016, 08:17

Добрых суток.
Возникла задача реализовать сервер для мультиплеерной игры.
Выбор пал на java + netty.io Посмотрел документацию, разобрал примеры запустив. И возникло несколько вопросов для тех кто знаком с этой библиотекой.

1. Вот для tcp создается 2 отдельных EventLoopGroup ,а именно: bossGroup ,workerGroup
При использовании конструкции:
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
передается только одна группа. То есть если я захочу сделать сервер на udp то будет только 1 поток обрабатывать входящие соединения?

Или я чего то не понимаю в netty.

2. Почитав в интернете все говорят что для онлайн серверов нужен только UDP и TCP совершенно не подходит для такой задачи так ли это? Выдержит ли сервер на netty + protoBuf UDP до 1-2 клиентов. + интересна работа с бд. Как обрабатывать запросы если нельзя загружать pipeline. Ведь вызов к бд сильно затормозит обработку пакета? Слышал что можно делать очередь запросов к бд и отдельный поток. Как вообще правильнее делать?

Прошу взглянуть на мой код. Собрал по примеру сервер на udp. Который даже не запускается :-? . проверял через nmap nmap -sU -p U:7777 127.0.0.1 выдает что порт закрыт. :-t

https://bitbucket.org/grabedinex/multip ... ?at=master

В последний комит слил все что есть на данном этапе.

Также мне не совсем понятно как подключить ко всему этому делу protobuf. читал документацию, пробовал делать примеры. собирал .proto файл для java. Но ведь netty не подключить к C#. Или netty на стороне клиента и не нужен и как то можно просто прикрутить protobuf к C# и посылать пакеты обычными сокетами. Тогда в C# будет .proto файл для C#. Не проверял. Сможет ли тогда java десериализовать код?
grabedinex
UNец
 
Сообщения: 11
Зарегистрирован: 15 ноя 2014, 17:37
Откуда: Екатеринбург
Skype: ldgamescom

Re: Netty вопросы по реализации UDP

Сообщение IDoNotExist 27 авг 2016, 10:31

grabedinex писал(а):1. Вот для tcp создается 2 отдельных EventLoopGroup ,а именно: bossGroup ,workerGroup
При использовании конструкции:
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
передается только одна группа.

Почему одна? Обычно делается так : b.group(bossGroup, workerGroup)

grabedinex писал(а):То есть если я захочу сделать сервер на udp то будет только 1 поток обрабатывать входящие соединения?

Для соединений больше одного потока и не нужно, основную работу на себе берет workerGroup, которая обрабатывает уже непосредственно пакеты с установленных соединений.

grabedinex писал(а):2. Почитав в интернете все говорят что для онлайн серверов нужен только UDP и TCP совершенно не подходит для такой задачи так ли это?

Данная тема уже сто раз обсуждалась на данном форуме, все зависит от задач синхронизации с сервером, серверов на TCP полным полно и они вполне себе не плохо живут, а UDP в голом виде вам скорей всего не подойдет, советую вам получше разобраться в вопросе.


grabedinex писал(а):Выдержит ли сервер на netty + protoBuf UDP до 1-2 клиентов.
Выдержит хоть миллион, но с какой скоростью он при этом будет работать это уже зависит от железа, и от оптимизации.

grabedinex писал(а):интересна работа с бд. Как обрабатывать запросы если нельзя загружать pipeline. Ведь вызов к бд сильно затормозит обработку пакета? Слышал что можно делать очередь запросов к бд и отдельный поток. Как вообще правильнее делать?

Правильнее всего воспринимать Netty именно как сервис для приема и обработки пакетов, после этого они должны передаваться в ваш собственный сервис который будет уже управлять сессиями и базой данных.

grabedinex писал(а):Также мне не совсем понятно как подключить ко всему этому делу protobuf. читал документацию, пробовал делать примеры. собирал .proto файл для java. Но ведь netty не подключить к C#. Или netty на стороне клиента и не нужен и как то можно просто прикрутить protobuf к C# и посылать пакеты обычными сокетами. Тогда в C# будет .proto файл для C#. Не проверял. Сможет ли тогда java десериализовать код?

Для C# полно protobuf библиотек, но в Unity более менее стабильно работает только данная версия. Подключаетесь обычными сокетами, сериализуете через protobuf и отправляете на сервер, все должно работать.
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Netty вопросы по реализации UDP

Сообщение IDoNotExist 27 авг 2016, 10:48

grabedinex писал(а):Прошу взглянуть на мой код. Собрал по примеру сервер на udp. Который даже не запускается :-? . проверял через nmap nmap -sU -p U:7777 127.0.0.1 выдает что порт закрыт. :-t

https://bitbucket.org/grabedinex/multip ... ?at=master

https://www.youtube.com/watch?v=tsz-assb1X8 вот есть хороший урок по написанию простейшего чата, разберите для начала его.
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Netty вопросы по реализации UDP

Сообщение grabedinex 27 авг 2016, 10:57

IDoNotExist, спасибо за столь полный ответ.

IDoNotExist писал(а):Почему одна? Обычно делается так : b.group(bossGroup, workerGroup)


Да все верно. Но:
Взял пример с их сайта http://netty.io/wiki/user-guide-for-4.x.html
Скрытый текст:
EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) // (3)
.childHandler(new ChannelInitializer<SocketChannel>() { // (4)
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new DiscardServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128) // (5)
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)

// Bind and start to accept incoming connections.
ChannelFuture f = b.bind(port).sync(); // (7)

// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}


Мы создаем serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // (3)
А если я делаю так serverBootstrap.group(bossGroup, workerGroup).channel(NioDatagramChannel.class) // (3)
то получаю ошибку.
Посмотрев примеры например package io.netty.example.qotm;
Скрытый текст:
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new QuoteOfTheMomentServerHandler());

b.bind(PORT).sync().channel().closeFuture().await();
} finally {
group.shutdownGracefully();
}


я вижу что они заменили канал. И ServerBootstrap поменялся на обычный Bootstrap который не позволяет принимать больше одного NioEventLoopGroup.


Может я чего то не понимаю. Я уже окончательно запутался...

По остальному в общих чертах понятно. Про Udp и Tcp почитаю по подробней. С protoBuf посмотрю предложенный вами вариант. Хотя я собирал на примере: https://habrahabr.ru/company/infopulse/blog/265805/. И там уже есть версия для C# и protobuf там версии 3
Предложенный вами вариант я так понимаю вообще отдельный от google и является частной разработкой? как я понимаю раньше у гугла небыло поддержки C# и появился protobuf-net но теперь то они ее ввели. Могу заблуждаться. Только учусь.


p.s В примере чата из видео. Открыл в идее исходник. Посмотрел. У них тот же самый NioServerSocketChannel. Который в свою очередь реалезует интерфейс public interface ServerSocketChannel и который судя документации только для Tcp/ip
A TCP/IP ServerChannel which accepts incoming TCP/IP connections.

Какой тогда мне интерфейс, канал брать для реализации 2 EventLoopGroup по UDP
grabedinex
UNец
 
Сообщения: 11
Зарегистрирован: 15 ноя 2014, 17:37
Откуда: Екатеринбург
Skype: ldgamescom

Re: Netty вопросы по реализации UDP

Сообщение IDoNotExist 27 авг 2016, 11:47

grabedinex писал(а):Мы создаем serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // (3)
А если я делаю так serverBootstrap.group(bossGroup, workerGroup).channel(NioDatagramChannel.class) // (3)
то получаю ошибку.

Ну в принципе доля логики в этом есть, так как для UDP не требуется постоянное соединение, там просто идет прием датаграмм. Сам я UDP для netty ни разу не использовал, так как, повторюсь еще раз, UDP в сыром виде не подойдет почти ни для какой игры.

grabedinex писал(а):Предложенный вами вариант я так понимаю вообще отдельный от google и является частной разработкой? как я понимаю раньше у гугла небыло поддержки C# и появился protobuf-net но теперь то они ее ввели. Могу заблуждаться. Только учусь.

Вы все правильно поняли, но проблема в том, что разработки от Google требуют .NET 4.5, в Unity их получится запустить только с бубном, а библиотека по ссылке которую я вам дал работает без проблем, ну разве что в WebGL она работать не будет.

grabedinex писал(а):p.s В примере чата из видео. Открыл в идее исходник. Посмотрел. У них тот же самый NioServerSocketChannel. Который в свою очередь реалезует интерфейс public interface ServerSocketChannel и который судя документации только для Tcp/ip
A TCP/IP ServerChannel which accepts incoming TCP/IP connections.

Какой тогда мне интерфейс, канал брать для реализации 2 EventLoopGroup по UDP

Я вам настоятельно не рекомендую браться за UDP, для начала напишите что то более менее рабочее используя TCP.
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Netty вопросы по реализации UDP

Сообщение grabedinex 27 авг 2016, 11:52

IDoNotExist писал(а):Я вам настоятельно не рекомендую браться за UDP, для начала напишите что то более менее рабочее используя TCP.


Прислушаюсь. Начну делать всю логику по tcp и разбирать примеры. Прикручивать protoBuf. В конце концов если все правильно сделать, перейти с tcp на Udp будет не так уж и сложно.
grabedinex
UNец
 
Сообщения: 11
Зарегистрирован: 15 ноя 2014, 17:37
Откуда: Екатеринбург
Skype: ldgamescom

Re: Netty вопросы по реализации UDP

Сообщение IDoNotExist 27 авг 2016, 12:00

grabedinex писал(а):Прислушаюсь. Начну делать всю логику по tcp и разбирать примеры. Прикручивать protoBuf. В конце концов если все правильно сделать, перейти с tcp на Udp будет не так уж и сложно.

Там в принципе проблем особых возникнуть не должно, учитывая, что netty и разрабатывался с тем учетом, чтобы легко можно было поменять транспорт, к промеру когда мне требовалось переделать TCP на Websocket я переписал всего примерно 10 строчек кода.
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Netty вопросы по реализации UDP

Сообщение grabedinex 27 авг 2016, 22:04

Поделюсь наработками. Вдруг кто будет искать.
Полазив, почитав про архитектуру игровых серверов наткнулся на интересный материал http://gamedev.9fog.com/2012/11/05/razrabotka-vysokonagruzhennogo-igrovogo-servera-na-java-isxodnik-setevoj-chasti/ Там статьи можно полистать. Интересно рассказывает.

Но так как там netty v3 а мне хотелось самую свежую на сегодняшний день 4.1.4Final пришлось потратить много времени.
http://netty.io/wiki/new-and-noteworthy-in-4.0.html Здесь раскрываются основные отличия 3 ветки от 4.

Интересно больше то, что как утверждает автор.
Сервер с такой архитектурой
Скрытый текст:
Основная суть – создается поток-обработчик входящих соединений, и ограниченное число (по умолчанию 8 ) тредов, принимающих входящие пакеты. Очередной принятый пакет отправляется на обработку игровой логике сервера, сервер формирует ответ, и отправляет в канал нужного клиента. Все просто! :) Трудность тут одна – тредов-приемников всего 8(пусть даже 32, 64), а клиентов в сотни раз больше. Поэтому обрабатывать входящие пакеты внутри приемника никак нельзя. Там вообще категорически нельзя выполнять никакие блокирующие действия. Решение очевидно: приняли пакет, породили еще один поток, который займется обработкой и вуаля, готовы принимать следующий пакет. Никто никого не ждет, все летает. Поток-обработчик уже без всяких изысков направляет данные куда надо, данные обрабатываются игровой логикой, результат обработки отсылается клиенту, поток тут же умирает, освобождая ресурсы.


Способен показать очень хорошие показатели. Я не ожидал такого от Tcp.
Скрытый текст:
: на 4-х ядерном процессоре (по 2 треда на ядро) при онлайне 5К в любой момент времени на сервере запущено в среднем (всего!!!) 30-40 тредов. Конечно, сама игровая логика там тоже оптимизирована, и от одного клиента поступает не больше одного запроса в 10 секунд, но запас мощности там еще колоссальный, ни по каким параметрам ни в какие полки не упремся еще долго.


мой commit с переписанным вариантом под netty 4

https://bitbucket.org/grabedinex/multiplayerserverfromunity3d/commits/2f658d249dc5efcb16bf72c67fd8c25d1d5e83f3
Осталось только StringDecoder Encoder заменить на protoBuf.

p.s пока целый день разбирался с различиями 3 и 4 ветки, прочитав кучу документации, начал даже немного понимать философию нетти :)
В целом я получил ответ на свой вопрос, за что спасибо IDoNotExist. Тему можно закрывать.
grabedinex
UNец
 
Сообщения: 11
Зарегистрирован: 15 ноя 2014, 17:37
Откуда: Екатеринбург
Skype: ldgamescom


Вернуться в Сеть

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1