LINUX.ORG.RU

есть два tcp сокета

 


0

2

нужно понимать на каком из них возникли события и или читать/писать или закрывать все. это такое спец прокси.

вопрос: как это реализовать на golang? как тут проще и стандартней всего заюзать select/poll/epoll?

★★

Никак, в Go это не нужно, все сначала не врубаются. Пускаешь горутины, в них читаешь из сокетов. Горутины должны общаться через каналы, а вот каналы уже можно селектить встроенной инструкцией типа свича.

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

сейчас так и сделано но это не есть гуд. у меня сейчас скажем одна горутина на read, вторая на write, данные через каналы гоняют. в результате когда умирает сокет нужно гасить их к чертям - чтобы например та которая делает write - не вычитала данные из канала и не попыталась их в дохлый сокет слать

quester ★★
() автор топика
Ответ на: комментарий от WitcherGeralt

Канал можно закрыть.

мне тогда нужно еще заводить ассоциацию сокета с каналом чтобы при помирании сокета закрывать и канал…

quester ★★
() автор топика
Последнее исправление: quester (всего исправлений: 2)
Ответ на: комментарий от quester

У тебя всего два сокета же, вроде бы не проблема. И что конкретно ты отправляешь в канал? Можно передавать структуру в которой будет признак того, что сокет закрыт.

Вообще, я же не знаю что именно ты делаешь, сложно советовать.

Есть пакет syscall, в нём всё нужное. Но по-моему, затея так себе. Лучше юзать идиоматичный подход.

WitcherGeralt ★★
()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

у меня специализированная proxy. грубо говоря tcp сервер который каждый коннект к нему пробрасывает к другому tcp серверу, поэтому нужно отслеживать входящий и исходящий сокеты. сейчас у меня это раздельные горутины, но логичнее на каждый коннект запускать горутину внутри которой отслеживать уже входящий и исходящий сокеты, читать/писать данные и подыхать если какой-то из сокетов протух

quester ★★
() автор топика
Ответ на: комментарий от Harald

И сколько сотен тыщ сокетов может обрабатывать этот ваш го с таким подходом?

Не знаю про «с таким подходом», но может и миллион:

a server written in pure Go that is able to serve more than a million websockets connections with less than 1GB of ram.

gag ★★★★★
()
Ответ на: комментарий от Harald

Хотя бы nginx взять для примера

Если не проксировать, то что? Статику отдавать? В дисковую подсистему не упрёшься с такой нагрузкой? Если какие-то гигантские кеши в оперативе, то может быть ещё, конечно. Не сталкивался с такими нагрузками даже близко, с трудом себе это представляю.

Хотя в любом сетевом сервере

А если не проксировать и не статику отдавать, а какую-то полезную работу делать? Сотни тысяч каких-то тасков одновременно выполнять на одной железке, даладна? Приведи пример.

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Сотни тысяч каких-то тасков одновременно выполнять на одной железке, даладна? Приведи пример.

это может быть демон нотификации - оповещает клиента если что-то происходит

quester ★★
() автор топика
Ответ на: комментарий от quester

Это тоже мелочь какая-то. Он же про хайлоад говорит. Где собственно лоад-то? Нужно какую-то полезную работу делать, пакетики пулять — дело нехитное. Жду какого-нибудь хардкора, который держит миллион соединений и на каждое землю по разу поворачивает.

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Это тоже мелочь какая-то.

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

quester ★★
() автор топика
Ответ на: комментарий от WitcherGeralt

DNS сервер ещё, чем больше клиентов он обслуживает, тем лучше. Отдача из кэша ограничена только скоростью оперативки и сетевого соединения

Harald ★★★★★
()
Ответ на: комментарий от quester

Как-то я в упор проблемы не вижу. Ну будет у тебя две горутины и два канала, закрываешь канал на одной стороне, закрывается сокет на другой.

WitcherGeralt ★★
()

вообщем я видимо буду при коннекте запускать одну горутину в которой запускать горутины на чтение и запись через каналы и каналы уже неблокирующим select просматривать в цикле и гаситься закрывая сокеты и каналы… но это криво потому что я в цикле буду гоняться вместо того чтобы спать в ожидании события…

quester ★★
() автор топика
Последнее исправление: quester (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

как ждать событий на нескольких каналах способом иным чем опрос их в цикле через неблокирующий select?

quester ★★
() автор топика
Ответ на: комментарий от Harald

Оно ничего не делает, одно io и перекладывание байтиков. Никому с этого ни тепло, ни холодно, это лишь часть инфраструктуры. Полезную работу делает приложение.

А по твоей логике на уровне приложения в принципе никакого хайлоада быть не может. Ибо нет таких приложений, которые обслуживают миллион клиентов на одной железке одновременно, делая хоть что-то полезное.

WitcherGeralt ★★
()
Ответ на: комментарий от quester

Я бы лучше запускал не три горутины, а две и создавал два канала. В первую принимашеь входящее соединение, создаёшь каналы и запускаешь вторую, передавая каналы, во второй создаёшь соединение и поехал. Но тут нужно хитро, иначе дедлок.

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

ну да, я говорил про две без учета горутины-сервера которая входящие соединения принимает

quester ★★
() автор топика
Ответ на: комментарий от Harald

Сомневаюсь, что на нативных библиотеках будет лучше. Сделать ffi настолько медленно, насколько медленно сделали в гошке это стараться надо.

Siborgium ★★★★★
()
Ответ на: комментарий от quester

у меня специализированная proxy. грубо говоря tcp сервер который каждый коннект к нему пробрасывает к другому tcp серверу, поэтому нужно отслеживать входящий и исходящий сокеты. сейчас у меня это раздельные горутины, но логичнее на каждый коннект запускать горутину внутри которой отслеживать уже входящий и исходящий сокеты, читать/писать данные и подыхать если какой-то из сокетов протух

В TCP понятия «входящий» и «исходящий» после хендшейка исчезают. Логичнее рассматривать рассматривать один сокет как два однонаправленных. Отсюда предлагаю после создания проксёй соединений с обеими сторонами делать по горутине на поток данных. Одна горутина читает из сокета a и пишет в сокет b, другая читает из сокета b и пишет в сокет a. Если удалённая сторона закрывает соединение, то горутина это видит на читающем сокете, закрывает второй сокет на запись и подыхает. При этом обратное направление трогать не нужно, т.к. передача данных вполне может продолжаться. Можно придумать третью горутину, которая будет отслеживать состояние и гасить сокеты, тогда те две горутины должны будут проснуться и умереть, но и без этого всё будет работать.

А вот каналы здесь совершенно не при чём. Опрашивать в одном select и сокеты, и каналы в го возможности нет.

Laz ★★★★★
()
Ответ на: комментарий от WitcherGeralt

как ждать событий на нескольких каналах способом иным чем опрос их в цикле через неблокирующий select?

Да никак, это норма.

Хватит вводить людей в заблуждение, select в го блокируется, в этом его смысл.

Laz ★★★★★
()
Ответ на: комментарий от Laz

Чего? Про default ты, видимо, не в курсе.

Вообще, я не очень понял, что именно он собирался сделать, но селект в цикле это норм, а почему неблокирующий, хз.

WitcherGeralt ★★
()
Ответ на: комментарий от Laz

А вот каналы здесь совершенно не при чём

Ты предлагаешь шарить объекты между горутинами, классика говнокода. Каналы нужны как раз для того, чтобы этого не делать.

Опрашивать в одном select и сокеты, и каналы в го возможности нет

И?

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

я не очень понял, что именно он собирался сделать

Но давать советы это не помешало. Ладно, поясняю. Он хочет сделать проксю. Есть два сокета. То, что приходит на один сокет, нужно отсылать во второй, возможно, с промежуточной обработкой. Аналогично в обратном направлении. Он хочет запустить две горутины, каждая горутина обслуживает один сокет, общается со второй через два канала. При появлении данных на чтение на сокете горутина должна отправить их в канал другой горутине. При появлении данных в канале от другой горутины их нужно отправить в сокет.

Теперь по пунктам:

Чего? Про default ты, видимо, не в курсе.

В курсе, но наличие default в цикле - явный признак проблемы в дизайне. Горутины должны блокироваться, если им нечего делать.

селект в цикле это норм, а почему неблокирующий, хз.

Неблокирующий потому, что в цикле помимо селекта на канале есть ещё опрос сокета (также неблокирующий). В итоге имеем busyloop.

Ты предлагаешь шарить объекты между горутинами, классика говнокода. Каналы нужны как раз для того, чтобы этого не делать.

Сокеты в данном случае ничем принципиально не отличаются от каналов. Для статической гарантии того, что горутина a->b не будет читать из b и писать в a, можно обернуть их в Reader и Writer, но я не вижу смысла заморачиваться типизацией в го. И да, ты предлагаешь шарить каналы между горутинами, тот же говнокод в хипстерской обёртке.

И?

И отсюда проблемы с ожиданием события на канале или сокете. Когда-то давно был пакет netchan, который позволял завернуть сокет в канал и решал все эти вопросы, а заодно позволял прозрачно раскидывать горутины по сети, но что-то пошло не так. Пайк сказал, что проблемы негров шерифа не интересуют, и на netchan забили.

Laz ★★★★★
()
Ответ на: комментарий от Laz

Как-то я в упор проблемы не вижу.

я не очень понял, что именно он собирался сделать

твой высер я читать не стал.

Ой, всё

Сообщение удалено WitcherGeralt

Вот так бывает, когда вместо Talks зашёл Development.

Laz ★★★★★
()
Ответ на: комментарий от Laz

делать по горутине на поток данных

вообщем то я так и сделал, единственное что закрытие сокетов не частичное а полное и делает это внешняя горутина которая через канал ждет сигнала от них

quester ★★
() автор топика
Ответ на: комментарий от WitcherGeralt

Ибо нет таких приложений, которые обслуживают миллион клиентов на одной железке одновременно

Есть. Зачем плодить тучу серверов, если ответ сервиса порядка 50 микросекунд в однопоточном режиме.

делая хоть что-то полезное.

айти и полезное - ну так себе уточнение. все решают какую-то проблему.

stave ★★★★★
()
Ответ на: комментарий от stave

Есть

Так назови.

айти и полезное - ну так себе уточнение

Я уже дал водораздел — инфра и приложение. Приложение решает бизнес задачи — оно полезное. Инфра сама по себе бестолкова, она приложения обслуживает.

Выше был пример сервера пушей, но боюсь, что при нормальной архитектуре он тоже сам ничего делать не будет, ему будут приходить готовые сообщения, которые требуется только переслать. Это пока самое близкое к полезному в треде. Да это хайлоад, безусловно, но учитывая надутый Харальдом пафос, как я уже сказал, я жду от приложения вращения земли, а не перекладывания байтиков из сокета в сокет.

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Приложение решает бизнес задачи

Прокси-сервер путём перекладывания байтиков из сокета в сокет решает бизнес-задачи владельца бизнеса по аренде платных прокси-серверов.

Harald ★★★★★
()
Ответ на: комментарий от Harald

Если уж уходить в демагогию, то реальные бизнес-задачи там решает билинг.

Глупо как-то редефайнить термин, который изначально про приложухи. Сложно сделать что-то полезное быстрее чем за десяток-другой миллиосекунд чисто физически, так что, если можно так выразиться, junior Highload начинается уже с сотен rps. Серьёзный — это уже десятки тысяч, может быть, сотни на кластере. Само же приложение при этом никогда не будет держать никаких миллионов соединений даже близко.

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Так назови.

rtb например. очень быстро надо обслужить много запросов, причем для каждого запроса целый конвейер действий. впрочем, программирование - это всегда перекладывание байтиков.

stave ★★★★★
()
Ответ на: комментарий от WitcherGeralt

Сложно сделать что-то полезное быстрее чем за десяток-другой миллиосекунд чисто физически,

За одну миллисекунду современный процессор выполняет от двух миллионов инструкций, что-то полезное сюда впихнуть можно с большим запасом

Harald ★★★★★
()
Ответ на: комментарий от stave

Очень абстракный и бестолковый пример. «Очень быстро» — понятие сильно растяжимое, сервис ничто не обязывает работать на одной машине, и у тебя нет живого примера такого сервса. Попробуй хотя бы обосновать необходимость обслуживать миллион клиентов на одной машине, набросать набор полезных действий, которые сервис выполняет по запросу/событию, и как-то обозначить требования по времени ответа.

Но вообще этот глупый спор пора заканчивать. Я не заносил молоток над крышкой с гвозьмём, ожидая хоть каких-то вменяемых потуг что-то предъявилить и обосновать. Но раз Харадьд даже не вытается: для хайлоада вообще не нужно более пары соединений, его позиция не верна априори. Сервис может получать сколь угодно много событий из единственного соединения и утилизировать все ресурсы системы для их обработки.

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Сервис может получать сколь угодно много событий из единственного соединения

и от единственного клиента :) суровый кочковский хайлоад )

Harald ★★★★★
()
Ответ на: комментарий от WitcherGeralt

Из очереди, в которую складывает события весь кластер, например.

У тебя уже хипстеризовано мышление. 2 основных проблемы айти, и ты сходу хочешь зацепить вторую - валидацию распределенного кеша. Зачем? Мощности 1 современного сервера прямо овердохрена для решения хайлоада.

stave ★★★★★
()
Ответ на: комментарий от WitcherGeralt

Очень абстракный и бестолковый пример.

Да куда уж реальнее, торговля рекламой.

«Очень быстро» — понятие сильно растяжимое, сервис ничто не обязывает работать на одной машине

Тебе надо ответить за 10 мс, иначе ты не участвуешь. Каждая сетевая синхронизация сколько добавит к работе?

Попробуй хотя бы обосновать необходимость обслуживать миллион клиентов на одной машине, набросать набор полезных действий, которые сервис выполняет по запросу/событию, и как-то обозначить требования по времени ответа.

рукалицо

stave ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.