Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Использование сервис-ориентированной архитектуры (SOA) для построения сложных веб проектов

Использование сервис-ориентированной архитектуры (SOA) для построения сложных веб проектов

Виталий Глибин (Headhunter)

Расскажу о том, что такое SOA, какие проблемы решает, а какие добавляет. Как мы готовим SOA в самом высоконагруженном job-портале рунета. Frontik и tortik — настоящее и будущее наших frontend-фреймворков на базе Python Tornado. Подробный рассказ о tortik — архитектура, возможности, тонкости. Покажу примеры использования, удобство отладки и профилирования как в development окружении, так и в production.

Moscow Python Meetup

July 31, 2014
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. Обычный сайт (монолитная архитектура) /index View DB Controller Получить сессию

    Загрузить отклики … Загрузить список резюме 3
  2. Проблемы 1. Один репозиторий, много разработчиков 2. Рост кодовой базы

    3. Ограничения в использовании языка программирования 4. Внешние подрядчики 5. ... to be counted 4
  3. Сервис-ориентированная архитектура (SOA) модульный подход к разработке программного обеспечения, основанный

    на использовании распределённых, слабо связанных заменяемых компонентов со стандартизированными интерфейсами и протоколам взаимодействия. Источник: Wikipedia 5
  4. Компонент системы в разработке • Один сервис - один репозиторий

    • Свобода выбора языка программирования • Возможность отдать на аутсорс 7
  5. Контролируемая деградация • Лучше показать часть информации, чем упасть с

    500 • Лучше показать самое важное за 100мс—1с, чем все за 10 секунд 8
  6. Почему это важно • 47% людей ожидают, что страница будет

    загружаться менее двух секунд • 40% закрывают страницу, если она загружается более трех секунд • 52% считают важным скорость загрузки страницы Источник: Akamai 11
  7. Разные требования к сервисам • Не все сервисы должны работать

    под большой нагрузкой • Некоторые могут и "полежать" • Оптимизируем только там, где это нужно 13
  8. Виртуализация • На одной машине один сервис • Легче мониторить

    • Легче деплоить • Можно добавлять/удалять машины по необходимости 14
  9. Дополнительный слой кеширования /index Controller View Сессия Сервис откликов Сервис

    резюме DB1 DB2 DB3 protobuf JSON XML memcached, redis, … varnish, nginx (proxy_cache) Cloud Service 15
  10. Много платформ Основной сайт hh.ru API api.hh.ru Мобильный сайт m.hh.ru

    Сессия Сервис откликов Сервис резюме Облако сервисов 16
  11. Уникальный идентификатор запроса (request_id) • Генерируется на nginx (ngx_http_requestid_module) •

    Пробрасывается http-заголовком (X-Request-Id) на все сервисы • Каждая запись в логе содержит request_id • Все логи сливаем на graylog2 21
  12. Frontik c l a s s P a g e

    ( p a g e . P a g e H a n d l e r ) : @ p a g e . u s e r _ p a g e ( x s l = ' p a g e s / i n d e x . x s l ' ) d e f g e t _ p a g e ( s e l f ) : s e l f . d o c . p u t ( s e l f . g e t _ u r l ( ' { } / r e s u m e s ' . f o r m a t ( r e s u m e H o s t ) ) , s e l f . g e t _ u r l ( ' { } / n e g o t i a t i o n s ' . f o r m a t ( n e g H o s t ) ) ) 24
  13. 25

  14. 26

  15. 27

  16. 28

  17. ` Frontik • Изначально был заточен под XML/XSLT (сейчас умеет

    и JSON) • Работает на нашей патченной Tornado 2.0 (https://github.com/hhru/tornado) • Требует libcurl, собранный с c-ares (https://github.com/tornadoweb/tornado/pull/1017) • Мало документации и примеров 29
  18. https://github.com/hhru/frontik Что хотелось • Уменьшить количество многоуровневых запросов • Иметь

    бо́льшую свободу в выборе шаблонизатора • Чтобы работало и на upstream Tornado 30
  19. 32

  20. Preprocessors backend1 backend2 backend3 Postprocessors User request HTML/JSON or cool

    debug page Request Handler Preprocessors • Набор асинхронных обработчиков (например, получение сессии) • Выполняются до начала выполнения обработчика запроса d e f s e s s i o n ( h a n d l e r , c a l l b a c k ) : d e f _ s e s s i o n _ c a l l b a c k ( s e s s i o n ) : h a n d l e r . s e s s i o n = s e s s i o n c a l l b a c k ( ) s e s s i o n _ c l i e n t . g e t _ s e s s i o n ( _ s e s s i o n _ c a l l b a c k , . . . ) 33
  21. Preprocessors c l a s s M o b i

    l e P a g e H a n d l e r ( t o r t i k . p a g e . R e q u e s t H a n d l e r ) : p r e p r o c e s s o r s = [ s e s s i o n , p a g e d a t a ] 34
  22. Request Handler • Стандартные обработчики Tornado (get, post, ...) с

    @asynchronous • Выходные данные формируются через s e l f . a d d ( ' n a m e ' , d a t a ) - аналог self.doc.put() во Frontik'е • Можно и сразу s e l f . c o m p l e t e ( { ' n a m e ' : d a t a } ) d e f g e t ( s e l f ) : s e l f . a d d ( ' s e r v e r _ t i m e ' , i n t ( t i m e . t i m e ) ) s e l f . a d d ( ' d a t a ' , { . . . } ) s e l f . c o m p l e t e ( ) 35
  23. Postprocessors • Набор последовательных обработчиков над выходными данными • Выполняются

    после выполнения обработчика запроса (RequestHandler) d e f t e m p l a t e ( h a n d l e r , d a t a , c a l l b a c k ) : o u t = t e m p l a t e _ e n g i n e . r e n d e r ( h a n d l e r . t e m p l a t e _ n a m e , d a t a =h a n d l e r . g e t _ d a t a ( )) c a l l b a c k ( h a n d l e r , o u t ) 36
  24. Postprocessors c l a s s M o b i

    l e P a g e H a n d l e r ( t o r t i k . p a g e . R e q u e s t H a n d l e r ) : p o s t p r o c e s s o r s = [ t e m p l a t e , t r a n s l a t i o n ] 37
  25. Отправка запросов на бэкенды s e l f . f

    e t c h _ r e q u e s t s ( [ s e l f . m a k e _ r e q u e s t ( n a m e = ' v a c a n c i e s ' , m e t h o d = ' G E T ' , f u l l _ u r l = ' h t t p s : / / a p i . h h . r u / v a c a n c i e s / 8 2 5 2 5 3 5 ' ) , . . . ] , c a l l b a c k = s e l f . c o m p l e t e ) 38
  26. Отправка запросов на бэкенды s e l f . f

    e t c h _ r e q u e s t s ( [ ( ' v a c a n c i e s ' , ' h t t p s : / / a p i . h h . r u / v a c a n c i e s / 8 2 5 2 5 3 5 ' ) , . . . ] , c a l l b a c k = _ c b ) 39
  27. Отправка запросов на бэкенды d e f _ c b

    ( ) : r e s p o n s e = s e l f . r e s p o n s e s [ ' v a c a n c i e s ' ] d a t a = r e s p o n s e . d a t a # j s o n и л и x m l # п л ю с а в т о м а т и ч е с к и й # s e l f . a d d ( ' v a c a n c i e s ' , r e s p o n s e . d a t a ) s e l f . c o m p l e t e ( ) 40
  28. Этапы обработки запроса h a n d l e r

    . l o g . s t a g e _ s t a r t e d ( ' r e n d e r ' ) # d o s o m e h a r d r e n d e r s t u f f h a n d l e r . l o g . s t a g e _ c o m p l e t e ( ' r e n d e r ' ) 42
  29. Этапы обработки запроса h a n d l e r

    . f e t c h _ r e q u e s t s ( . . . c a l l b a c k = _ c b , s t a g e = ' s e s s i o n ' ) 43
  30. Этапы обработки запроса M O N I K h a

    n d l e r = h h m o b i l e . p a g e s . P a g e m e t h o d = G E T c o d e = 2 0 0 t o t a l = 9 3 s e s s i o n = 1 3 . 9 8 p a g e = 4 7 . 1 4 r e n d e r = 2 1 . 7 7 t r a n s l a t i o n = 7 . 3 0 44
  31. Этапы обработки запроса M O N I K h a

    n d l e r = h h m o b i l e . p a g e s . P a g e m e t h o d = G E T c o d e = 2 0 0 t o t a l = 9 3 s e s s i o n = 1 3 . 9 8 p a g e = 4 7 . 1 4 r e n d e r = 2 1 . 7 7 t r a n s l a t i o n = 7 . 3 0 45
  32. Этапы обработки запроса M O N I K h a

    n d l e r = h h m o b i l e . p a g e s . P a g e m e t h o d = G E T c o d e = 2 0 0 t o t a l = 9 3 s e s s i o n = 1 3 . 9 8 p a g e = 4 7 . 1 4 r e n d e r = 2 1 . 7 7 t r a n s l a t i o n = 7 . 3 0 46
  33. Этапы обработки запроса M O N I K h a

    n d l e r = h h m o b i l e . p a g e s . P a g e m e t h o d = G E T c o d e = 2 0 0 t o t a l = 9 3 s e s s i o n = 1 3 . 9 8 p a g e = 4 7 . 1 4 r e n d e r = 2 1 . 7 7 t r a n s l a t i o n = 7 . 3 0 47