45
Технические аспекты знакомства с девушкой в интернете Алексей Найден, Алексей Носков Evil Martians воскресенье, 16 декабря 12 г.

Технические аспекты знакоства с девушкой в Интернете

Embed Size (px)

DESCRIPTION

Обзор опыта и проблем, решенных при разработке speed-dating сайта Wannafun.ru

Citation preview

Page 1: Технические аспекты знакоства с девушкой в Интернете

Технические аспекты знакомства с девушкой в

интернетеАлексей Найден, Алексей Носков

Evil Martians

воскресенье, 16 декабря 12 г.

Page 2: Технические аспекты знакоства с девушкой в Интернете

воскресенье, 16 декабря 12 г.

Page 3: Технические аспекты знакоства с девушкой в Интернете

воскресенье, 16 декабря 12 г.

Page 4: Технические аспекты знакоства с девушкой в Интернете

Wannafun.ru• Онлайн speed dating

• Знакомство только с теми, кто в сети• Поток лиц aka «матрица»

• 3 минуты чата для принятия решения

• 48% / 52%

воскресенье, 16 декабря 12 г.

Page 5: Технические аспекты знакоства с девушкой в Интернете

Проект в цифрах

• 500 000 пользователей

• 2000 онлайн

• 2-3 события в секунду на юзера

• Более 100 http-запросов в минуту на юзера

• Более 5 000 000 чатов

• Более 45 000 000 сообщений

воскресенье, 16 декабря 12 г.

Page 6: Технические аспекты знакоства с девушкой в Интернете

На чем всё работает

ErlangEventMachine

PostgresRails

RedisResque

воскресенье, 16 декабря 12 г.

Page 7: Технические аспекты знакоства с девушкой в Интернете

воскресенье, 16 декабря 12 г.

Page 8: Технические аспекты знакоства с девушкой в Интернете

Онлайн-взаимодействия

• Знакомства: входящие/исходящие, сообщения• Контакт-лист: личные сообщения, онлайн/оффлайн

• Уведомления

воскресенье, 16 декабря 12 г.

Page 9: Технические аспекты знакоства с девушкой в Интернете

Взаимодействие с браузеромPusher (http://pusher.com/)

Push-канал к клиенту

Нет серверной логики

Faye (http://faye.jcoglan.com/)

Pub/sub

Нет серверной логики

Socket.io (http://socket.io/)

Абстракция над WebSocket, Flash и Polling

Произвольная серверная логика

воскресенье, 16 декабря 12 г.

Page 10: Технические аспекты знакоства с девушкой в Интернете

Серверная реализация socket.io• NodeJS

• На тестах падала VM — epic fail

• EventMachine

• Не было актуальной версии• Erlang

• Не было актуальной версии

воскресенье, 16 декабря 12 г.

Page 11: Технические аспекты знакоства с девушкой в Интернете

Что хорошего в Erlang

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

• Иерархия супервизоров - высокая устойчивость• Прозрачная распределенность• Бесшовный деплой

воскресенье, 16 декабря 12 г.

Page 12: Технические аспекты знакоства с девушкой в Интернете

Архитектура чат-сервера

• Соединения обслуживаются Cowboy

• Каждая сессия - отдельный процесс• Вспомогательные процессы для работы с БД, Redis

воскресенье, 16 декабря 12 г.

Page 13: Технические аспекты знакоства с девушкой в Интернете

Начало знакомства

воскресенье, 16 декабря 12 г.

Page 14: Технические аспекты знакоства с девушкой в Интернете

Одновременный ответ

воскресенье, 16 декабря 12 г.

Page 15: Технические аспекты знакоства с девушкой в Интернете

Синхронная реализация

воскресенье, 16 декабря 12 г.

Page 16: Технические аспекты знакоства с девушкой в Интернете

воскресенье, 16 декабря 12 г.

Page 17: Технические аспекты знакоства с девушкой в Интернете

Очереди задач• Resque

• Быстро работает, использует Redis

• Удобный Web UI

• Redis полезен и для других задач:

• Хранение счетчиков• Синхронизация состояния• Кэширование

воскресенье, 16 декабря 12 г.

Page 18: Технические аспекты знакоства с девушкой в Интернете

Уникальные задачи

• Сохранение сообщений• Прогрев кэша• Расчет статистики

Можно использовать Redis для блокировки

воскресенье, 16 декабря 12 г.

Page 19: Технические аспекты знакоства с девушкой в Интернете

Обычный код

Реализация: resque-lock (<= 1.0.0)

def perform return unless redis.setnx("lock", true)

# do task actionsensure redis.del "lock"end

воскресенье, 16 декабря 12 г.

Page 20: Технические аспекты знакоства с девушкой в Интернете

воскресенье, 16 декабря 12 г.

Page 21: Технические аспекты знакоства с девушкой в Интернете

Правильный код

Реализация: resque-lock (>= 1.1.0)

http://redis.io/commands/setnx

def perform now = Time.now.to_i timeout = now + 60

unless redis.setnx("lock", timeout) # Lock is active return if now <= redis.get("lock").to_i # Lock is not expired return if now <= redis.getset("lock", timeout).to_i end

# do task actions 11

redis.del "lock"end

воскресенье, 16 декабря 12 г.

Page 22: Технические аспекты знакоства с девушкой в Интернете

воскресенье, 16 декабря 12 г.

Page 23: Технические аспекты знакоства с девушкой в Интернете

Хорошие индексыХорошие = Ускоряющие необходимые запросы

create_table 'messages' do |t| t.references 'source' t.references 'destination' t.string 'body' t.timestamp 'created_at' t.timestamp 'read_at'end

# History of messages received from given userSELECT * FROM messages WHERE destination_id = ? AND source_id = ?ORDER BY created_at DESC LIMIT 10

# Unread messages of userSELECT * FROM messages WHERE destination_id = ? AND read_at IS NULLORDER BY created_at DESC LIMIT 10

воскресенье, 16 декабря 12 г.

Page 24: Технические аспекты знакоства с девушкой в Интернете

Плохие индексы# History of messages received from given useradd_index 'messages', ['source_id', 'destination_id']

# Unread messages of useradd_index 'messages', ['destination_id']

Limit -> Sort Sort Key: created_at Sort Method: top-N heapsort Memory: 25kB -> Index Scan using messages_between_users on messages Index Cond: ((source_id = ?) AND (destination_id = ?))Total runtime: 6.451 ms

Limit -> Sort Sort Key: created_at Sort Method: quicksort Memory: 26kB -> Bitmap Heap Scan on messages Recheck Cond: (destination_id = ?) Filter: (read_at IS NULL) -> Bitmap Index Scan on messages_unread Index Cond: (destination_id = ?)Total runtime: 123.983 ms

воскресенье, 16 декабря 12 г.

Page 25: Технические аспекты знакоства с девушкой в Интернете

Отличные индексы!# History of messages received from given useradd_index 'messages', ['source_id', 'destination_id', 'created_at'], :order => { 'created_at' => 'desc' }

# Unread messages of useradd_index 'messages', ['destination_id', 'created_at'], :order => { 'created_at' => 'desc' },:where => 'read_at IS NULL'

Limit -> Index Scan using messages_between_users on messages Index Cond: ((source_id = ?) AND (destination_id = ?))Total runtime: 0.209 ms

Limit -> Index Scan using messages_unread on messages Index Cond: (destination_id = ?)Total runtime: 0.183 ms

воскресенье, 16 декабря 12 г.

Page 26: Технические аспекты знакоства с девушкой в Интернете

Массивы и hstore

• Как сериализация, только лучше• Могут индексироваться

воскресенье, 16 декабря 12 г.

Page 27: Технические аспекты знакоства с девушкой в Интернете

Размер таблицcreate_table 'users_usual' do |t| t.boolean 'flag1' ... t.boolean 'flag20'end

create_table 'users_hstore' do |t| t.hstore 'flags' # gem 'activerecord-postgres-hstore'end

create_table 'users_array' do |t| t.integer_array 'flags' # gem 'activerecord-postgres-array'end

5 000 000 записей, флаги независимы, P[flag=yes] = 0.01Usual table size: 249 MBHstore table size: 219 MBArray table size: 257 MB

воскресенье, 16 декабря 12 г.

Page 28: Технические аспекты знакоства с девушкой в Интернете

ИндексированиеПоля:

Seq Scan on users_usual Filter: (flag2 AND flag7 AND flag13)Total runtime: 799.959 ms

Hstore:Bitmap Heap Scan on users_hstore Recheck Cond: (flags @> '2=>y, 7=>y, 13=>y'::hstore) -> Bitmap Index Scan on users_hstore_flags Index Cond: (flags @> '2=>y, 7=>y, 13=>y'::hstore)Total runtime: 350.778 ms

Массив:Bitmap Heap Scan on users_array Recheck Cond: (flags @> '{2,7,13}'::integer[]) -> Bitmap Index Scan on users_array_flags Index Cond: (flags @> '{2,7,13}'::integer[])Total runtime: 48.118 ms

воскресенье, 16 декабря 12 г.

Page 29: Технические аспекты знакоства с девушкой в Интернете

Кэширование последовательностей

• Выбираем последовательность на несколько шагов вперед

• Кэшируем идентификаторы в Redisid = redis.lpop(cache_key) # Get next value from cache

unless id # No cached value ids = connection.select_values some_heavy_scope.select('id').to_sql id = ids.shift

redis.multi do |r| ids.each{ |id| r.rpush cache_key, id } r.expire cache_key, 7200 # Expire cache after 2 hours endend

воскресенье, 16 декабря 12 г.

Page 30: Технические аспекты знакоства с девушкой в Интернете

воскресенье, 16 декабря 12 г.

Page 31: Технические аспекты знакоства с девушкой в Интернете

Кэширование матрицы• Проблема• Различные фильтры: мин/макс возраст

(от 16 до 70) + пол

• 3080 возможных фильтров

• (1 + 2 + … + 55) * 2 = 55 * 56

• Решение: аппроксимация фильтров

воскресенье, 16 декабря 12 г.

Page 32: Технические аспекты знакоства с девушкой в Интернете

Кэширование матрицы• Проблема• Различные фильтры: мин/макс возраст

(от 16 до 70) + пол

• 3080 возможных фильтров

• (1 + 2 + … + 55) * 2 = 55 * 56

• Решение: аппроксимация фильтров

воскресенье, 16 декабря 12 г.

Page 33: Технические аспекты знакоства с девушкой в Интернете

Кэширование с аппроксимацией• Возраст округляется до кратного X (= 4)

• Минимальный - вниз, максимальный - вверх• 210 фильтров

• (1 + 2 + … + 14) * 2 = 14 * 15

• Кэшируется порция заведомо большего размера• После извлечения из кэша выкидываются лишние записи

воскресенье, 16 декабря 12 г.

Page 34: Технические аспекты знакоства с девушкой в Интернете

Обработка фотографий

• 200–300 регистраций в минуту, половина грузит JPG на 5 мегабайт

• Первым делом уменьшайте размер входящих изображений

• CarrierWave лучше отделён от модели, чем Paperclip, обратно совместим

воскресенье, 16 декабря 12 г.

Page 35: Технические аспекты знакоства с девушкой в Интернете

Обработка фотографий

• RMagick MiniMagick не хранит в себе временного файла, использует память отдельного процесса, не поддерживает создание изображений

• GraphicsMagick — форк ImageMagick, ориентированный на стабильность и производительность

• Прирост в скорости до 2-3 раз, но это не серебрянная пуля: меньше фич, иногда производительность страдает

воскресенье, 16 декабря 12 г.

Page 36: Технические аспекты знакоства с девушкой в Интернете

Отправка СМС

• SMPP – открытый протокол, поддерживаемый большинством SMS-шлюзов

• Бинарный, за счет чего выше скорость передачи и footprint воркеров

• github.com/raykrueger/ruby-smpp – реализация для EventMachine

воскресенье, 16 декабря 12 г.

Page 37: Технические аспекты знакоства с девушкой в Интернете

Тестирование

• Модульное• Ruby — RSpec

• Erlang — EUnit

• Интеграционное?• Нагрузочное?

воскресенье, 16 декабря 12 г.

Page 38: Технические аспекты знакоства с девушкой в Интернете

RSpec для Rails и Erlang• Запуск Erlang при создании сессии

• Отдельный поток с EM, обслуживающий все соединения

• Socket.io поверх em-websocket-client

• Очередь входящих сообщенийs = open_session_with_chat

# Delegates to ActionDispatch::Integration::Sessions.post "/users/sign_in", email: '[email protected]', pass: '12345'

# Wait for a message (with timeout)s.receive(:connect).should be

# Send messages.send_event :contact_message, contact_id, text: "Hi!"

воскресенье, 16 декабря 12 г.

Page 39: Технические аспекты знакоства с девушкой в Интернете

Боты-тестеры

• Нагрузочное тестирование чата• Определение проблем с concurrency

• Помощь при ручном тестировании

• Настраиваемое поведение

воскресенье, 16 декабря 12 г.

Page 40: Технические аспекты знакоства с девушкой в Интернете

Реализация ботов

• Акторы на основе EventMachine

• Socket.io поверх em-websocket-client

• Набор "шаблонов поведения"class Caller < Wannafun::Actor behave :get_matrix behave :accept_calls behave :call_to_users behave :talk_in_callsend

EventMachine.run do Wannafun::ActorSet.new(Caller, options).start!end

воскресенье, 16 декабря 12 г.

Page 41: Технические аспекты знакоства с девушкой в Интернете

Как ловить JS ошибки на клиенте

• В сложных приложениях — сложные сценарии и граничные случаи

• Обратная связь пользователь - разработчик. Максимум информации собирается автоматически

• Echoes.js (github.com/kossnocorp/echoes). На клиенте собираем логи, фильтруем важные и прикладываем к запросу

воскресенье, 16 декабря 12 г.

Page 42: Технические аспекты знакоства с девушкой в Интернете

Echoes.jsecho.log('Test', 'logging', namespace: 'app.lol_module.45')echo.log(['trololo'])

[ { "timestamp": 1341468018606, "body": ["Test", "logging"], "namespace": "app.lol_module.45" }, { "timestamp": 1341468018606, "body": [["trololo"]], "namespace": "" } ]

echo.logs.grep 'some'#=> [{ body: ['Something'] }, { body: ['I want some LSD.']}]

воскресенье, 16 декабря 12 г.

Page 43: Технические аспекты знакоства с девушкой в Интернете

Мониторинг приложения

• Длины очередей в Resque

• Кол-во несохраненных сообщений• Кол-во знакомств в разных состояниях• Длина очереди модерации

воскресенье, 16 декабря 12 г.

Page 44: Технические аспекты знакоства с девушкой в Интернете

Head-huntung

Wannafun: [email protected]

Evil Martians: [email protected]

воскресенье, 16 декабря 12 г.

Page 45: Технические аспекты знакоства с девушкой в Интернете

Алексей Носков@alno

github.com/[email protected]

Алексей Найден@alexnayden

github.com/[email protected]

ВПРСВ НТ?

ЗБС!

Все изображения являются собственностью их автороввоскресенье, 16 декабря 12 г.