Your SlideShare is downloading. ×
0
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Технические аспекты знакоства с девушкой в Интернете
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

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

2,506

Published on

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

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

Published in: Technology
0 Comments
12 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,506
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
31
Comments
0
Likes
12
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Технические аспекты знакомства с девушкой в интернете Алексей Найден, Алексей Носков Evil Martiansвоскресенье, 16 декабря 12 г.
  • 2. воскресенье, 16 декабря 12 г.
  • 3. воскресенье, 16 декабря 12 г.
  • 4. Wannafun.ru • Онлайн speed dating • Знакомство только с теми, кто в сети • Поток лиц aka «матрица» • 3 минуты чата для принятия решения • 48% / 52%воскресенье, 16 декабря 12 г.
  • 5. Проект в цифрах • 500 000 пользователей • 2000 онлайн • 2-3 события в секунду на юзера • Более 100 http-запросов в минуту на юзера • Более 5 000 000 чатов • Более 45 000 000 сообщенийвоскресенье, 16 декабря 12 г.
  • 6. На чем всё работает Erlang Postgres Redis EventMachine Rails Resqueвоскресенье, 16 декабря 12 г.
  • 7. воскресенье, 16 декабря 12 г.
  • 8. Онлайн-взаимодействия • Знакомства: входящие/исходящие, сообщения • Контакт-лист: личные сообщения, онлайн/ оффлайн • Уведомлениявоскресенье, 16 декабря 12 г.
  • 9. Взаимодействие с браузером Pusher (http://pusher.com/) Faye (http://faye.jcoglan.com/) Push-канал к клиенту Pub/sub Нет серверной логики Нет серверной логики Socket.io (http://socket.io/) Абстракция над WebSocket, Flash и Polling Произвольная серверная логикавоскресенье, 16 декабря 12 г.
  • 10. Серверная реализация socket.io • NodeJS • На тестах падала VM — epic fail • EventMachine • Не было актуальной версии • Erlang • Не было актуальной версиивоскресенье, 16 декабря 12 г.
  • 11. Что хорошего в Erlang • Нет коллбеков - простой последовательный код • Нет разделяемого состояния, структуры данных неизменяемы - concurrency проще • Иерархия супервизоров - высокая устойчивость • Прозрачная распределенность • Бесшовный деплойвоскресенье, 16 декабря 12 г.
  • 12. Архитектура чат-сервера • Соединения обслуживаются Cowboy • Каждая сессия - отдельный процесс • Вспомогательные процессы для работы с БД, Redisвоскресенье, 16 декабря 12 г.
  • 13. Начало знакомствавоскресенье, 16 декабря 12 г.
  • 14. Одновременный ответвоскресенье, 16 декабря 12 г.
  • 15. Синхронная реализациявоскресенье, 16 декабря 12 г.
  • 16. воскресенье, 16 декабря 12 г.
  • 17. Очереди задач • Resque • Быстро работает, использует Redis • Удобный Web UI • Redis полезен и для других задач: • Хранение счетчиков • Синхронизация состояния • Кэшированиевоскресенье, 16 декабря 12 г.
  • 18. Уникальные задачи • Сохранение сообщений • Прогрев кэша • Расчет статистики Можно использовать Redis для блокировкивоскресенье, 16 декабря 12 г.
  • 19. Обычный код def perform return unless redis.setnx("lock", true) # do task actions ensure redis.del "lock" end Реализация: resque-lock (<= 1.0.0)воскресенье, 16 декабря 12 г.
  • 20. воскресенье, 16 декабря 12 г.
  • 21. Правильный код 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 Реализация: resque-lock (>= 1.1.0)воскресенье, 16 декабря 12 г.
  • 22. воскресенье, 16 декабря 12 г.
  • 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 user SELECT * FROM messages WHERE destination_id = ? AND source_id = ? ORDER BY created_at DESC LIMIT 10 # Unread messages of user SELECT * FROM messages WHERE destination_id = ? AND read_at IS NULL ORDER BY created_at DESC LIMIT 10воскресенье, 16 декабря 12 г.
  • 24. Плохие индексы # History of messages received from given user add_index messages, [source_id, destination_id] # Unread messages of user add_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 г.
  • 25. Отличные индексы! # History of messages received from given user add_index messages, [source_id, destination_id, created_at], :order => { created_at => desc } # Unread messages of user add_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 г.
  • 26. Массивы и hstore • Как сериализация, только лучше • Могут индексироватьсявоскресенье, 16 декабря 12 г.
  • 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.01 Usual table size: 249 MB Hstore table size: 219 MB Array table size: 257 MBвоскресенье, 16 декабря 12 г.
  • 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 г.
  • 29. Кэширование последовательностей • Выбираем последовательность на несколько шагов вперед • Кэшируем идентификаторы в Redis id = 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 end endвоскресенье, 16 декабря 12 г.
  • 30. воскресенье, 16 декабря 12 г.
  • 31. Кэширование матрицы • Проблема • Различные фильтры: мин/макс возраст (от 16 до 70) + пол • 3080 возможных фильтров • (1 + 2 + … + 55) * 2 = 55 * 56 • Решение: аппроксимация фильтроввоскресенье, 16 декабря 12 г.
  • 32. Кэширование матрицы • Проблема • Различные фильтры: мин/макс возраст (от 16 до 70) + пол • 3080 возможных фильтров • (1 + 2 + … + 55) * 2 = 55 * 56 • Решение: аппроксимация фильтроввоскресенье, 16 декабря 12 г.
  • 33. Кэширование с аппроксимацией • Возраст округляется до кратного X (= 4) • Минимальный - вниз, максимальный - вверх • 210 фильтров • (1 + 2 + … + 14) * 2 = 14 * 15 • Кэшируется порция заведомо большего размера • После извлечения из кэша выкидываются лишние записивоскресенье, 16 декабря 12 г.
  • 34. Обработка фотографий • 200–300 регистраций в минуту, половина грузит JPG на 5 мегабайт • Первым делом уменьшайте размер входящих изображений • CarrierWave лучше отделён от модели, чем Paperclip, обратно совместимвоскресенье, 16 декабря 12 г.
  • 35. Обработка фотографий • RMagick MiniMagick не хранит в себе временного файла, использует память отдельного процесса, не поддерживает создание изображений • GraphicsMagick — форк ImageMagick, ориентированный на стабильность и производительность • Прирост в скорости до 2-3 раз, но это не серебрянная пуля: меньше фич, иногда производительность страдаетвоскресенье, 16 декабря 12 г.
  • 36. Отправка СМС • SMPP – открытый протокол, поддерживаемый большинством SMS-шлюзов • Бинарный, за счет чего выше скорость передачи и footprint воркеров • github.com/raykrueger/ruby-smpp – реализация для EventMachineвоскресенье, 16 декабря 12 г.
  • 37. Тестирование • Модульное • Ruby — RSpec • Erlang — EUnit • Интеграционное? • Нагрузочное?воскресенье, 16 декабря 12 г.
  • 38. RSpec для Rails и Erlang • Запуск Erlang при создании сессии • Отдельный поток с EM, обслуживающий все соединения • Socket.io поверх em-websocket-client • Очередь входящих сообщений s = open_session_with_chat # Delegates to ActionDispatch::Integration::Session s.post "/users/sign_in", email: 123@example.com, pass: 12345 # Wait for a message (with timeout) s.receive(:connect).should be # Send message s.send_event :contact_message, contact_id, text: "Hi!"воскресенье, 16 декабря 12 г.
  • 39. Боты-тестеры • Нагрузочное тестирование чата • Определение проблем с concurrency • Помощь при ручном тестировании • Настраиваемое поведениевоскресенье, 16 декабря 12 г.
  • 40. Реализация ботов • Акторы на основе EventMachine • Socket.io поверх em-websocket-client • Набор "шаблонов поведения" class Caller < Wannafun::Actor behave :get_matrix behave :accept_calls behave :call_to_users behave :talk_in_calls end EventMachine.run do Wannafun::ActorSet.new(Caller, options).start! endвоскресенье, 16 декабря 12 г.
  • 41. Как ловить JS ошибки на клиенте • В сложных приложениях — сложные сценарии и граничные случаи • Обратная связь пользователь - разработчик. Максимум информации собирается автоматически • Echoes.js (github.com/kossnocorp/echoes). На клиенте собираем логи, фильтруем важные и прикладываем к запросувоскресенье, 16 декабря 12 г.
  • 42. Echoes.js echo.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 г.
  • 43. Мониторинг приложения • Длины очередей в Resque • Кол-во несохраненных сообщений • Кол-во знакомств в разных состояниях • Длина очереди модерациивоскресенье, 16 декабря 12 г.
  • 44. Head-huntung Wannafun: red.scorpix@gmail.com Evil Martians: surrender@evl.msвоскресенье, 16 декабря 12 г.
  • 45. ВПРСВ НТ? ЗБС! Алексей Носков Алексей Найден @alno @alexnayden github.com/alno github.com/anayden alexey.noskov@evl.ms alexey.nayden@evl.ms Все изображения являются собственностью их автороввоскресенье, 16 декабря 12 г.

×