Pull to refresh

Comments 53

Стоит заметить, что последнее решение можно сильно упростить, убрав создание горутины на каждый диспатч запрос. Это уменьшит количество работы для сборщика мусора в разы.
Когда задача стоит загрузить данные от клиентов на S3, желательно использовать Pre-signed URL. Тогда не будет проблемы с узким горлышком и ожиданием пока выполнится загрузка — все делается клиентом, а на сервере остается только логика и «оркестровка» этого процесса. Весь трафик упадет на плечи Амазона.
Интересно, смог бы справиться с такой задачей (и таким же успехом) Node.js, не рассматривали его как вариант?
Довелось мигрировать одну систему с node.js на go. Теоретически, можно бы написать… Если очень коротко, то нода не справлялась.
2к запросов \ сек на ядро, для системы, которая просто сохраняет данные в базу, не очень впечатляет.
Как рекламе в банках или где-нибудь еще:

Только у нас миллион* запросов в минуту!!!
____
* на 4 серверах**
** каждый сервер с 2-х ядерным CPU
Если пойти дальше, то 10^6/60 = 16666.(6) запросов в секунду, т.е., по сути, проблему C10K смогли решить 3 серверами.
(semantic-nazi-on Рутина в русском языке совсем не то же самое, что и routine в английском. Хотя, вроде как, оба слова происходят от французского «дорожка», но в русском это обыденность, повседневность, закостенелость и прочее, а в английском — стандартная процедура или даже именно компьютерная подпрограмма. Когда Вы пишете Go-рутина, то это читается как Go-обыденность. Хрень какая-то, а не термин. Что мешает переводить как Go-процедура?)
Есть термин goroutine, в русскоязычном сообществе используется «горутина», и в данном случая я просто следую оригиналу — где автор пишет «Go routine» вместо «goroutine» (что выглядит как некая игра слов), я перевожу как «Go рутина» соответственно.

«Go-процедура» — это совсем промт-стайл будет ) Тогда уже «горутина» будет удачнее, имхо.
IMHO, это просто от безграмотности сообщества (no offence). Вместо того, чтобы подумать, какому русскому термину соответствует название, просто берётся калька. Чем гопрограмма, как предлагает neolink, хуже? Гопроцедура, гофункция. Но рутина вообще не к месту. Горутина вместо гопрограммы (гофункции, гопроцедуры) — это то же самое, что и «дорожная карта» вместо нормального слова «план».
Goprogram & goroutine -> Гопрограмма & гопрограмма. Ненавижу граммар-наци, вы тупые. Нельзя делать перевод в состоянии обдолбанности
А вы сами что курили, чтобы goprogram выдумать и багетить с того, что перевод несуществующего термина совпадает с переводом существующего? Надеюсь вы не из аплогетов «лучший перевод — тупая транслитерация»?
«IMHO», «no offence», «semantic-nazi-on»? Вы какой-то ненастоящий граммар-наци.
если брать за аналогию coroutine, то гопрограмма. Но транслитерация (горутина) звучит лучше
При чём тут Ruby on rails вообще непонятно, ребята сделали воркер для передачи json объектов в S3 и даже разбалансировали не средствами Go, для этого рельсы как бы и не нужны совсем. И я сомневаюсь что такая большая разница будет для такой задачи, они просто не умеют (или просто не хотят) работать с Ruby, а лучше работают с Go, так бы и писали сразу.

P.S. И ещё, у них же такая нагрузка не из пустоты появилась, потому разумно что на таких нагрузках можно (а может быть и нужно) переходить с Ruby на что-то менее удобное, но более производительное.
Объясните, пожалуйста, этот кусок:

func (d *Dispatcher) Run() {
    // starting n number of workers
    for i := 0; i < d.maxWorkers; i++ {
        worker := NewWorker(d.pool)
        worker.Start()
    }

    go d.dispatch()
}

Откуда взялся d.pool? В структуре Dispatcher его нет.
Скорее всего, подразумевался d.WorkerPool — код, наверняка, подчищался/упрощался для статьи, потому пролезли ошибки.
Но с самого начала наша команда знала, что мы должны написать это на Go, посколько на этапе обсуждения мы уже понимали, что эта система должна будет справляться с огромным траффиком.

Pet technology, оно же Architecture as Requirements.
Третий вариант, точно такой же как и второй, только с небольшим допущением:
func StartProcessor() {
    for {
        select {
        case job := <-Queue:
            // job.payload.UploadToS3()  // <-- STILL NOT GOOD
            go job.payload.UploadToS3()
        }
    }
}

Тогда не будет блокировки основного цикла, ожидающего следующего Job. Так и работает 3 вариант.
Действительно, я был не прав, третий вариант качественно иной.
Интересно, что это у них за мониторинг…
Штатный Amazon CloudWatch вроде бы.
А точно, давно не работал с Amazon, все забыль
Я правильно понял, что ребята с четвёртой попытки написали обычный пул воркеров с диспетчеризацией сообщений, который в C#/Java/C++ + boost можно было взять из коробки и не пыхтеть?
Почти )
Если ребята написали этот пул с третьей попытке на Go, угадайте, как бы выглядело их «не пыхтеть» на C++/boost.
Собственно, создаём пул:
boost::asio::io_service ios;

Добавляем задачи:
ios.post(&routine1); // routine -- это обычный указатель на функцию
ios.post(&routine2);
ios.post(&routine3);
...

Запускаем в несколько потоков:
std::thread t1(&boost::asio::io_service::run, &ios);
std::thread t2(&boost::asio::io_service::run, &ios);
ios.run();

Завершаем выполнение:
t1.join(); t2.join();
Миллион OS-тредов != миллион горутин.
так и не надо миллион ос-потоков, создаём сколько надо, а задачи по ним распределятся сами
ну а в итоге то что?
ну есть в бусте это. ребята вон сами написали, в гугле ещё косой десяток вариантов пула воркеров на го, некоторые даже как пакеты оформлены.
Кстати, а почему их и не использовали? И в чём проблема использование готового, хорошо-отлаженного решения?

ЗЫ в 11 стандарт у Asio протиснуться не получилось, пробуется в 17.
потому что задача стоит не сделать абстрактный пул потоков который 2 хелло ворда отправляет.
им приходят http запросы они это парсят и отправляют в S3.
но вопрос не в бусте, да если хорошенько посидеть на си это можно сделать ну раза в 2 быстрее точно, но вот где бы эти ребята взяли такого человека не понятно и сколько бы он это писал, а потом это всё отлаживал, когда оно нефига не по тому что не успевает, а потому что где-то free нет, где-то race и т.п. падает.
а тут выпил редбула, посидел вечерок и в продакшен
А вы вправду не понимаете, почему народ в своё время массово стал переходить с C++/Java на Ruby/Python и прочие решения, даже в ущерб производительности?
А вообще, автор статьи, конечно, тупил много ) Но в этом и прелесть статьи, по-моему, что автор не стыдится своих ошибок, и описывает шаг за шагом. Желание написать своё решение, а не искать готовые, видимо было вызвано по той же причине, по которой он не захотел использовать готовые инструменты (не языка, а технологии, описанные в статье).
Ребят, ну если вы тут пытаетесь доказать, что разработка многопоточных архитектур на C++/boost — это легко, просто и надежно, без надобности нарабатывать 5+ лет опыта и читать талмуды, то что-то вы важное упускаете.
Я писал многопоточный софт на boost и писал на Go — и это просто небо и земля. Пробовать обе технологии, или привязаться лишь к одной и её пропагандировать — это уже ваш выбор.
Я немного не понял, у низ Queue это обычный chan как и было раньше, как он превратился в poll «воркеров»
и почему они не использовали встроенный в go golang.org/pkg/container/heap к примеру.
Один вопрос — как человек, не осознающий что для десятка тысяч запросов в секунду нужен выделенный пул потоков, стал архитектором?
Думаю тут разгадка во фразе «мы очень недооценили количество входящих вопросов».
После первого фейла уже масштаб проблемы должен был прояснить головы. Решение же типовое безотносительно языков и фреймворков, это первое что в голову должно прийти. Люди банально не понимали как работает выбранный инструмент (особенно печально, что после 2х лет использования).

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

Ну да, естественно, ведь Эрланг, например, совсем не для этого придуман и вылизан. До 15-9 Go не доберется никогда, но великие архитекторы с самого начала знают, что писать нужно на нем.
Фраза эта да, кривовато звучит. Думаю, на деле он хотел сказать, что они хотели попробовать для этого проекта Go, вместо Ruby (как я понял, это их основной стек был), потому что нужна была большая нагрузка.

А по поводу обожание Эрланга — Go не собирается никуда добираться. Он уже и сейчас дает людям возможность быстро получать качественный результат, с которым легко и приятно работать. Это единственное, что важно в конечном итоге.
Я не знаю, что вы понимаете под «обожанием», но все же просто: нужно 15-9, concurrency и реальное время — это эрланг. Можно подвинуться в этом, и получить скорость разработки — руби. Если вдруг архитектор не пальцем деланый — эликсир.

А если нужно командой рукожопых джуниоров быренько запилить что-то похожее на надежный сервис — вот тут у Го самая ниша. Из которой выбраться ему не суждено.
Это ваш взгляд. В Google уже 3+ млн строк кода на Go, включая многие ключевые сервисы.

Go очень сильно берет низким порогом входа, это правда. Я, кстати, считаю это одним из минусов Эрланга — если бы освоить эрланг у меня заняло пару вечеров, как и Go, я бы конечно так или иначе попробовал Эрланг где-нибудь в pet projects. А читать кучу книг и тратить месяцы, просто чтобы узнать — хорошая технология или нет — я просто не могу. И это не оправдание, это реалии — интересных технологий пруд пруди, и время входа тут очень сильное конкурентное преимущество (но не единственное, конечно же).
Эрланг учится за две недели, за год можно выучить до 26 эрлангов.
Есть реальность — Erlang-у уже достаточно лет, чтобы индустрия могла оценить его плюсы и минусы. Как по вашему, в чём причина того, что мейнстрим выбрал C++/Java вместо Erlang?
У эрланга узкая ниша (это не язык общего пользования), но он там лучший.
Скажите, что такое «15-9»?
Эрланг доказал в продакшене «девять девяток», то есть 99.9999999% reliability. Elixir — пятнадцать.

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

А если бизнесу это как бы не особо надо, как, например, гуглу и/или автору статьи — сойдет и руби, если уметь программировать, конечно.
а что значит доказал в продакшене? по отдельно взятому софту для банкомата у которого считали время online?
да у ерланга в целом есть заточки под стояние надолго, но вот сам язык содержит много ограничений, и в конечном счете все упирается в программистов и то что получилось у эриксона не факт что получится у конкретно взятой команды.
И да сколько у вас девяток и как вы их считали (доступность полной функциональности сервиса или просто что сервис был как бы запущен) ну и что за проект
Вас в гугле забанили?

stackoverflow.com/questions/8426897/erlangs-99-9999999-nine-nines-reliability

Мы сами никак не считали, мы взлетели больше года назад и с тех пор не было ни одного отказа.

У нас эликсир, не чистый эрланг. На нем писать проще и приятней, чем на руби. Хот релоад, прекомпиляция кода, нативный код ⇐⇒ AST туда-сюда и воркеры. Но это ни при чем же, если отказ транзакции приводит к тому, что теперь курс вдвое больше и разница из своего кармана — выучишь и эрланг.

Проект FX, подробнее не могу.
> Вас в гугле забанили?
а вы мой комментарий точно прочитали? я про AXD301 как бы и писал.
и это ничего не доказывает кроме того что ерланг был 20 лет назад и то что есть одна success story. Кстати это по ссылке тоже написано.
И какая история про эликсир с 15 девятками?

> Мы сами никак не считали
ок… а откуда такой снобизм тогда?

> нативный код ⇐⇒ AST туда-сюда
а в beam jit появился? или это что-то от энтузиастов

> если отказ транзакции
что-то не понятно, это вы сейчас latency на обработку имели ввиду?

в целом традиционно ерланг хорошо справляется с перекидыванием небольших сообщений (смс, rabbitmq) и т.п. он под маршрутизацию (правда голоса) и создавался.
но я не уверен что он 69гб хипа переварит
Когда-то, в далёком 2005, был на экскурсии на одном заводе. Там в бухгалтерии бежал серверок написаный на паскале. Его как в 94 запустили, так он и бежал 11 лет без единого сбоя или перезагрузки. Так что, по вашей логике, паскаль круче. Доказано в продакшене.
Да, по моей логике (и по любой другой логике тоже) паскаль круче (для той конкретной задачи, которую решал этот серверок.)

Возможно, кто-то мог сравниться с паскалем на том конкретном сервере, но лучше, чем «бежал 11 лет без единого сбоя или перезагрузки» показателя не бывает. Это если вам ехать надо.

Если шашечки — тогда, конечно, есть куда более эзотерические варианты.
Насколько я понял суть работы Dispatcher, он:
1. Берет задачу из JobQueue
2. Берет доступный воркер из WorkerPool
3. Шлет задачу воркеру в JobChannel

А почему воркеры не могут напрямую читать задачи из JobQueue?
Sign up to leave a comment.

Articles

Change theme settings