Как стать автором
Обновить
128
0
Сергей @seriyPS

backend

Отправить сообщение
Ещё интересный доклад от Яндекса был на PyCon в прошлом году примерно на эту тему pycon.ru/2013/program/content/distributed-execution/ но там десятки тысяч серверов и вообще всё сложнее.
Написал, для сравнения, то-же самое на Erlang. Запускать не пробовал.
В стандартной библиотеке есть полная реализация SSH сервера, клиента и SFTP.
main([Cmd | Hosts]) ->
    Timeout = 5000,
    Master = self(),

    erlang:send_after(Timeout, self(), timeout), % запускаем таймер

    %% используем генератор списков для запуска параллельной задачи на каждый хост
    [spawn_link(fun() -> task(Host, Cmd, Master, Timeout) end) || Host <- Hosts],
    await(length(Hosts)).

task(Host, Cmd, Master, Timeout) ->
    %% использует $USER, $HOME/.ssh/id_rsa по умолчанию
    {ok, Conn} = ssh:connect(Host, 22, {}, Timeout), %тут timeout чисто номинально
    %% SSH поддерживает мультиплексирование
    {ok, Chan} = ssh_connection:session_channel(Conn, Timeout),
    success = ssh_connection:exec(Conn, Chan, Cmd, Timeout),
    Response = read_response(Conn, Chan, <<>>),
    %% отправляем результат выполнения мастеру
    Master ! {result, Host, Response}.
    

await(0) -> ok; % все результаты получены. Выходим.
await(N) ->
    receive
        {result, Host, Response} -> % пришло сообщение от одной из задач
            io:format("Host: ~s; Response: ~p~n", [Host, Response]),
            await(N - 1); % зацикливаемся
        timeout -> % пришло сообщение от таймера
            io:format("Timeout, but ~p tasks not ready!", [N])
    end.

read_response(Conn, Chan, Acc) ->
    %% рекурсивно читаем ответ команды
    receive
        {ssh_cm, Conn, {data, Chan, _, Data}} ->
            %% цикл, собираем результат выполнения команды в аккумулятор
            read_response(Conn, Chan, <<Acc/binary, Data/binary>>);
        {ssh_cm, Conn, {closed, Chan}} ->
            %% Команда отработала. Разрываем рекурсию.
            Acc
    end.

Экономия строчек на SSH-ключи, но больше места занимает вычитывание ответов.
В badoo разрешили писать не на PHP/C++?
Задержки в основном на отправке данных будет.
Если для получения данных от сервера ещё можно использовать стриминг (не уверен, что все браузеры поддерживают. Накрайняк jsonp стриминг), то для отправки событий на сервер (нажатия клавиш) придётся слать отдельный AJAX запрос на каждое событие. А это 400-600 байт оверхеда на заголовки.
Ох… В своё время забил на этот брейнфак и начал писать my_array.map(...) или my_array.forEach(...)
По моему чаще используют термин «строгая»
Как показывает практика, в таких играх нужно запускать на поле бота, если игроков мало. Т.к. человек заходит в игру, видит что там никого нет и через минуту уже уходит и не возвращается.
У меня есть сайт, который не работает без WebSocket. Какие проблемы: Android в пролёте; Около 2% посетителей, зашедших на сайт видят заглушку (т.к. нет window.WebSocket); у ~8% от тех, кто не увидел заглушку (window.WebSocket есть) не получилось подключиться со 2-й попытки (прокси?).
Так что фоллбек всё ещё имеет смысл, если 10% аудитории вам дороги (хотя для реалтайм игры AJAX фолбек скорее всего будет добавлять заметных задержек даже при использовании keep-alive).
Ну и обязательно нужно реализовать периодический пинг-понг (есть такой тип фрейма в протоколе), чтобы закрывать сокеты отвалившихся клиентов.
— How do I authenticate?
— You don't!
В мемкеше не предусмотрено авторизации впринципе. Очевидно, для повышения производительности
Вебвизору/аналитике проще, потому что на сайте УЖЕ установлен JS с домена яндекса. Так что им достаточно в URL передать зашифрованную команду «запусти виджеты аналитики/вебвизора» и всё — проксирование в общем-то и не нужно становится.
Для питона сейчас активно развивается проект github.com/davidhalter/jedi (я использую в комплекте с Emacs github.com/tkf/emacs-jedi ). Работает прекрасно, не тормозит.
Features тут jedi.jedidjah.ch/en/latest/docs/features.html
Какой-то бессмысленный проект. Заменили один транспортный уровень на другой, да ещё и с потерей части функциональности (Middleware, gzip) и не получили никаких преимуществ (пушить события с сервера не позволяет). Хоть одна объективная причина для этого была?

Забавно, что весь проект по сути один файлик на 100 строк.
Зашел в топик, чтобы найти название игры, в которую играл лет 10 назад — не ошибся =)
Я в urllib2 добавлял поддержку gzip так:
class GZipProcessor(urllib2.BaseHandler):
    """A handler to add gzip capabilities to urllib2 requests
    http://techknack.net/python-urllib2-handlers/
    """
    def http_request(self, req):
        req.add_header("Accept-Encoding", "gzip")
        return req
    https_request = http_request

    def http_response(self, req, resp):
        if resp.headers.get("content-encoding") == "gzip":
            gz = GzipFile(
                        fileobj=StringIO(resp.read()),
                        mode="r"
                      )
            old_resp = resp
            resp = urllib2.addinfourl(gz, old_resp.headers, old_resp.url,
                                      old_resp.code)
            resp.msg = old_resp.msg
        return resp
    https_response = http_response


opener = urllib2.build_opener()
opener.add_handler(GZipProcessor())
opener.open("http://example.com/")

С keep-alive у urllib к сожалению всё печально. Рецепты есть, но старые и не поддерживаемые.
У нас ограничений нет. Интернет по кабелю либо по WiFi с персональными логинами/паролями. Есть гостевой WiFi в подсети — пароли развешаны свободно по офису.

Ну а для тех, у кого заблокировано, но очень хочется, всегда есть простые решения
Ппц, возможно я отстал от жизни, но для меня пост читался как «Мы решили сделать стартап, для этого мы взяли НЕНУЖНО, совместили его с НЕНУЖНО и задеплоили на НЕНУЖНО. В процессе выяснили, что НЕНУЖНО нам не совсем подходит и переехали на альтернативное НЕНУЖНО.»
Может я зря для разворачивания сервера вбиваю в консоль sudo aptitude install postgresql-server erlang nginx git logrotate postfix и после 20-30 минут редактирую конфиги.
Мне почему то кажется, что время, потраченное на изучение API и библиотек всех этих сервисов сравнимо со временем, которое нужно потратить на то, чтобы плюс-минус эквивалентное окружение научиться настраивать самому (или нагуглить подходящие HOWTO).
Особенно комично смотрится изначальное утверждение «поддерживать собственную инфраструктуру слишком дорогое удовольствие» и последующие переезды с сервиса на сервис.
Хоть скажите, не пожалели что с PaaS-ами связывались?
Можно урлы кодировать в поддомен, т.е. http://example.com/page.html подменять на http://example.com.proxy.indexisto.com/page.html — тогда достаточно подменять только абсолютные FQDN ссылки (<a href="http://..."), а относительные (<a href="/page.html") будут автоматически наследовать родительский домен и протокол.

Ну и многие сайты практикуют детектирование и выпрыгивание из айфреймов, нужно иметь в виду.
Я с PHP года 4 уже не работал, так что могу не знать нюансов, сужу по косвенным признакам… Вы написали, что переделали работу с сокетами на неблокирующую, но я нигде в коде не вижу вызовов stream_set_blocking да и read/write/fgets у вас используются так, как использовались бы с блокирующими сокетами. Мне кажется они у вас блокирующие…
Пример — вызов fgets (его вы уже выпилили) возвращает в 3-х случаях: сокет закрыт, достигнут лимит или найден "\n". Как она работает с неблокирующими сокетами вообще не представляю, но совершенно точно что нужно удостовериться, что последний символ в считанных данных это "\n".

Дальше fwrite: на неблокирующих сокетах он не обязан записывать всё, что ему сказали записать — сколько он запишет зависит от размера буферов, так что нужно делать что-то вроде
if (length($data) != ($written = fwrite($data))) {
    $data = substr($data, $written),
}
и дописывать остаток когда сокет снова станет записываемым.

Насчёт read та же фигня — в неблокирующем режиме он может вернуть хоть один байт (привет if(!$data)) хоть всё вплоть до $length. Так что всегда нужно проверять достаточно ли данных считалось и если нет — сохранять в буфер и дожидаться, пока сокет снова станет readable.

Тот факт, что сокеты у вас всё-же блокирующие, позволяет, по идее, заблокировать воркера послав, например, всего один байт, в то время как сервер делает read($fd, 10000). Хотя насчёт этого не совсем уверен, возможно в PHP там промежуточные буферы какие то есть.

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Работает в
Дата рождения
Зарегистрирован
Активность