Григорий Петров: работа с сетью в Ruby

    28 сентября на конференции RubyRussia DevRel компании Evrone Григорий Петров расскажет о том, как общаются микросервисы. В сегодняшнем интервью Иван Соловьев поговорил с Григорием о теме его предстоящего выступления и не только об этом.

    image

    Расскажи о себе, чем ты занимаешься в Evrone?

    Я занимаюсь developer relations — это что-то среднее между DevRel и Technology Evangelist, разработчик, который умеет выступать на конференциях. Работа как у Робин Гуда: общаться с командами разработки внутри компании, собирать разное интересное из того, чем они занимаются, и рассказывать об этом на конференциях. Ruby Russia будет одна из первых конференций, где я буду выступать от лица компании.

    Знаю тебя как одного из организаторов различных Python конференций. Расскажи, как ты пришел в мир Ruby?

    Я никогда не уходил из мира Ruby. Один из первых моих докладов это «Python vs Ruby». Много лет назад, когда я писал на С++, мне понадобились высокоуровневые механизмы автоматизации всякого тестирования, генерации документации. Тогда я писал и на Python, и на Ruby, и немножко на PHP. Искал лучшие способы решения задач, которые у меня были.

    Насколько твой доклад будет заимствован у команд разработки внутри компании? Я знаю, ты на многих языка писал: Ruby, Python, PHP, TypeScript, JavaScript, C++ и не только.

    Доклад будет про общение микросервисов между собой по сети, используемые для этого протоколы и возникающие сложности. На самом деле, у меня долгие отношения с сеткой. Я делал Radmin, это сетевая тулза для удаленного управления. Проект NPTV (в котором я тоже работал DevRel) — это интерактивное телевидение, которое активно использовало сетку и управлялось на Ruby. Voximplant (где я снова занимался DevRel) — это программируемая телефония, где я познакомился с VoIP. Сетка мне очень близка. Я мог бы сделать доклад, основываясь на своем опыте, но так я бы принес не максимальную ценность гостям конференции, а я хочу нести максимум пользы. На этапе начальной подготовке доклада я проинтервьюировал несколько команд Evrone. Компания занимается заказной разработкой сложного и качественного софта, много команд работает над разными проектами. Мы созванивались в Zoom и общались по часу и больше. Обсуждали, что и как делают, какие сложности, какие стеки используют. Мой доклад будет наполовину про сетку, сетевые протоколы, сложности и прикладное, и наполовину о том, как оно используется в Ruby разными командами.

    У тебя большой багаж общения с разработчиками. Насколько ты считаешь работа с сетью в Ruby специфична?

    Сеть складывается из нескольких частей. В первую очередь — работа языка программирования и его экосистемы непосредственно с байтами, передаваемые по сети. Самый низкоуровневый сетевой стек. Например, тот же JS и Node используют libuv, асинхронную модель. Есть главный поток, и ты работаешь с сетью событийно. У тебя для этого есть корутины. Ты делаешь много ожиданий, делаешь ожидание для того, чтобы принять данные, делаешь ожидание для того, чтобы данные отправились. Этот один поток обеспечивает тысячи и десятки тысяч запросов в секунду.

    На этом фундаменте развиваются фреймворки, какими бы они ни были. Например, у JS нет серьезных фреймворков для работы с сеткой (с чем его и можно поздравить!). За исключением express.js, который трудно назвать полноценным фреймворком. Python перешел на похожую модель, а самый популярный фреймворк Django остался на предыдущей модели. Сейчас там некий раздрай — синхронный фреймворк, который пытается размножаться блокирующими потоками, процессами, с нависающим над этим GIL, а сбоку какие-то новые штуки, которые пытаются работать по асинхронной модели, например Django Channels. Ruby пока остается в синхронной модели и размножается процессами. Поэтому здесь соответствующая экосистема, подходы и очень сильные позиции Rails.

    В чем сила Ruby? Прежде всего в DSL, Domain specific language. Когда мы говорим про сетку, Ruby лучше всего играет на том поле, где он сильнее всего. Когда мы используем GraphQL, это значит, что библиотеки для использования GraphQL есть везде. В Ruby они будут использовать очень хороший DSL синтаксис для задания схемы. И интеграцию между этими DSL синтаксисом и DSL синтаксисам ORM в ActiveRecord. Именно этого мы можем ожидать от Ruby. При этом у нас не будет никаких асинхронных операций (await’ов), мы будем масштабироваться процессами и у нас будут соответствующие требования к серверам.

    У тебя в докладе заявлено несколько протоколов взаимодействия. Тот же JSON:API и так далее. В какую сторону ты видишь дальнейшее развитие, не скатимся ли мы все в GraphQL?

    Очень резонансный вопрос. На мой взгляд, это началось с того, что сетка медленная. Приложения в начале просты. Как правило все приложения, и Ruby, и Python, и Node, используют обычные HTTP endpoint’ы для общения. Внутри используют какой-то payload. Раньше XML, сейчас JSON. У них все хорошо первые несколько месяцев или лет, кому как повезет. Дальше бизнес начинает задавать сложные вопросы. Например, нужно получить каких-то пользователей, и для каждого пользователя получить список компаний, в которых он работает. Тут возникает проблема: если использовать просто endpoint, то это будет несколько десятков или сотен запросов, а сетка неторопливая: запрос, ответ, потерянные пакеты. Это будет чудовищно медленно и много данных надо будет передать по сети. В 100 раз больше, чем нужные данные. Наша система коллапсирует, как коллапсируют под такими запросами крупные системы бизнес автоматизаци, которые лет через 10 вырастают в монстров, где сложный вопрос из интерфейса может выполнятся минуты, часы. Все это время база на backend будет отрабатывать кучу одинаковых запросов, и по сети будет гнаться куча одинаковых запросов. Мы пытаемся решить это разными способами.

    Приведи реальные примеры таких проблем?

    Особенно отличился Facebook, у них эта проблема стоит очень остро: есть много данных, по которым они любят делать сложные запросы. Например: покажи мне тех, кто оставил комментарии к этому сообщению, и их друзей. Чтобы не делать миллионы запросов, фейсбук использует разные варианты. Например, FQL, Facebook Query Language. Собрав всю свою экспертизу они сделали GraphQL — штуку, которая позволяет делать SQL-подобные запросы на клиенте. Но это не SQL, потому что нам нельзя привязываться к базам данных, а запрос в терминах backend API. Отправляешь один запрос и получаешь один (или как там получится) ответ.

    Вторая большая проблема — что делать, если мы хотим получить много данных с бэкэнда. Например, пять тысяч пользователей или лог в 10мб. Страшно делать это все одним http запросом-ответом. Потому что если сеточка сколлапсирует, запрос придется повторять целиком, а это может длиться вечно. Возвращаюсь к фейсбуку: они сделали GraphQL, костыль над сеткой. А потом другие люди сделали HTTP/2, который решает проблему с сеткой. HTTP/2 делает одно асинхронное соединение, в рамках которого мы можем делать много мелких запросов. HTTP/2 борется с GraphQL, если у GraphQL сервера нет особенной магии, чтобы оптимизировать количество запросов к базе на backend. И в докладе мы поговорим о том, что же Ruby предлагает для этой магии. При наличии HTTP/2 GraphQL может быть не нужен. Мы можем сделать 100 запросов по HTTP/2 к нашему endpoint’у, и с точки зрения байтиков это будет не больший оверхед, чем если мы используем GraphQL. Google Protocol Buffers и gRPC подходят к этой проблеме с третьего конца. Используют бинарные транспортные протоколы, в основном HTTP/2, предлагают некую схему для api. Тут они конкурируют с обычным REST.

    На практике, в большинстве компаний, которые используют JSON, сидит программист Вася, который пишет этот JSON руками. Через полгода Вася узнает, что дату и время можно передать сотней разных способов. Начинается ужас! Но если в компании сидят хорошие разработчики, они пишут не просто JSON, а используют какой-нибудь стандарт. Используют OpenAPI или JSON Schema, все эти интересные штуки, которые конкурируют с gRPC. Весь этот современный зоопарк решает несколько озвученных проблем. А что с этим зоопарком случится в будущем, я совсем не могу предсказать. Но приглашаю разработчиков прийти и обсудить этот вопрос: что же нас ждет в ближайший год, 3, 5, 10 и какова диспозиция сил сейчас.

    Давай поговорим про будущее Ruby как языка программирования?

    Трудно предсказать будущее. Мне бы очень хотелось, чтобы в Ruby доехали хорошие типы. Ruby 3 сейчас на самой начальной стадии внедрения типов. Мне бы хотелось, чтобы этот синтаксис был красивым. Я видел пропозалы, у меня от них лысина дыбом встала. Ужасный, очень многословный синтаксис, который никто не будет использовать.

    Почему ты так считаешь?

    Я нейрофизиолог-любитель. Интуитивное мышление, которое у всех есть, любит принимать всякие странные решения. Если, например, надо написать много букв, то это плохо. Эти типы могут быть мега-клевыми, но из-за того, что придется писать в полтора раза больше кода, мы будем чувствовать эмоцию «не хочу». А мы очень чувствительны к нашим эмоциям, поэтому никто не будет этим пользоваться. Мне очень нравится, как донесли типы в Python и TypeScript: через двоеточие. Это дает минимальный оверхед. Мы написали идентификатор — посмотрели. Я точно знаю, что здесь будет число, надо поставить капкан. Разработчик пишет двоеточие и все, капкан установлен. Через пару недель, когда совершенно в другом месте он нечаянно передаст туда список или строку, капкан сработает и сэкономит разработчику несколько часов или недель отладки.

    Что бы ты еще хотел увидеть в Ruby?

    Последние несколько лет я вижу много async с корутинами. Мне это очень нравится, потому что async код с корутинами просто читать. Он понятный, позволяет запихнуть сложные штуки в простой синтаксис. Это неплохо реализовано в последнем Python и неплохо реализовано в JavaScript. Мне бы очень хотелось, чтобы и в Ruby завезли что-то такое… Собственно говоря, в Rubу есть файберы. Круто было бы добавить что-то вроде Node, чтобы можно было писать асинхронные Ruby-приложения, используя файберы или какие-то другие примитивы. А под капотом оно само использовало бы libuv или еще какие-то примитивы операционной системы для работы с сеткой.

    Или раскладывало бы что-то по потокам. Использовало бы что-то для того, чтобы конкурентно выполнять все эти сетевые запросы, запросы к базам, запросы к файловой системе. А я бы только на уровне корутин писал маленькие кусочки кода, которые выполняются по входящему запросу или таймеру, далее отдавали команды и ждали их выполнения. Далее под капотом много магии, все это выполняется параллельно, сжирает огромную амазоновскую тачку на 100% и имеет десятки тысяч запросов в секунду. В случае Go сотни тысяч запросов в секунду.

    Вернемся к типам. Это, наверное, будет постепенное внедрение типов, Gradual Typing?

    Gradual Typing — мега взлетевшая штука, которую впервые добавили в Python. Сделали так, что типы можно добавлять по чуть-чуть. На мой взгляд, возникла целая парадигма разработки, когда в начале код очень быстро пишется без типов, а затем, когда разработчик видит, что какая-то часть кода стабилизировалась, именно в эту часть кода начинают добавлять типы. Именно там, где оно стабилизировалось и надо ставить капканы, чтобы в будущем об это стабилизированое ничего не ломать. Будет круто, если для Ruby сделают что-то похожее.

    Какой вопрос ты хочешь задать Yukihiro Matsumoto на конференции?

    Я уже 4 года изучаю японский, и моего японского наверное хватит чтобы сказать ему «спасибо». Я буду тренироваться!

    Увидимся на RubyRussia!

    Регистрируйтесь, следующее повышение цены ожидается после 15 сентября, 700 участников уже с нами.

    И традиционное спасибо компаниям, которые нас поддерживают:

    Организатор — Evrone
    Генеральный партнер — Toptal
    Золотой партнер — Gett
    Серебярные партнеры — JetBrains, Bookmate и Cashwagon
    Бронзовый партнер — InSales
    RubyRussia
    0,00
    Конференция разработчиков на Ruby и RoR
    Поделиться публикацией

    Похожие публикации

    Комментарии 0

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое