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

Preview:

DESCRIPTION

 

Citation preview

Использование SOA дляпостроения сложных веб

проектовВиталий Глибин, HeadHunter

Что такое SOA?

Обычный сайт (монолитная архитектура)

/index

View

DB

ControllerПолучить сессию

Загрузить отклики…

Загрузить список резюме

3

Проблемы1. Один репозиторий, много разработчиков

2. Рост кодовой базы

3. Ограничения в использовании языка программирования

4. Внешние подрядчики

5. ... to be counted

4

Сервис-ориентированная архитектура(SOA)модульный подход к разработке программного обеспечения,

основанный на использовании распределённых, слабо связанных

заменяемых компонентов со стандартизированными интерфейсами и

протоколам взаимодействия.

Источник: Wikipedia

5

SOA-based сайт

/index

Controller

View

Сессия

Сервис откликов

Сервис резюме

DB1

DB2

DB3

protobuf

JSON

XML

Cloud Service

6

Компонент системы в разработке• Один сервис - один репозиторий

• Свобода выбора языка программирования

• Возможность отдать на аутсорс

7

Контролируемая деградация• Лучше показать часть информации, чем упасть с 500

• Лучше показать самое важное за 100мс—1с, чем все за 10 секунд

8

Почему это важно• 47% людей ожидают, что страница будет загружаться менее двух

секунд

• 40% закрывают страницу, если она загружается более трех секунд

• 52% считают важным скорость загрузки страницы

Источник: Akamai

11

Разные требования к сервисам• Не все сервисы должны работать под большой нагрузкой

• Некоторые могут и "полежать"

• Оптимизируем только там, где это нужно

13

Виртуализация• На одной машине один сервис

• Легче мониторить

• Легче деплоить

• Можно добавлять/удалять машины по необходимости

14

Дополнительный слой кеширования

/index

Controller

View

Сессия

Сервис откликов

Сервис резюме

DB1

DB2

DB3

protobuf

JSON

XML

memcached, redis, …varnish, nginx (proxy_cache)

Cloud Service

15

Много платформ

Основной сайт hh.ru

API api.hh.ru

Мобильный сайт m.hh.ru

Сессия Сервис откликов

Сервис резюме

Облако сервисов

16

Проблемы

Сеть• TCP / HTTP overhead

• Задержки между виртуальными машинами (используем SR-IOV)

18

Эксплуатация• Больше конфигов

• Больше деплоя

• Больше мониторинга

19

Разработка• Стало проще?

• Усложнение поддержки тестовых и development стендов

• Был один лог - стало много

20

Уникальный идентификатор запроса(request_id)

• Генерируется на nginx (ngx_http_requestid_module)

• Пробрасывается http-заголовком (X-Request-Id) на все сервисы

• Каждая запись в логе содержит request_id

• Все логи сливаем на graylog2

21

Немного про

Python

Frontik

backend1

backend2

backend3

Templating

User request

HTML/JSON

Request Handler

23

Frontikclass Page(page.PageHandler):

@page.user_page(xsl='pages/index.xsl')

def get_page(self):

self.doc.put(

self.get_url('{}/resumes'.format(resumeHost)),

self.get_url('{}/negotiations'.format(negHost))

)

24

25

26

27

28

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

• Работает на нашей патченной Tornado 2.0

(https://github.com/hhru/tornado)

• Требует libcurl, собранный с c-ares

(https://github.com/tornadoweb/tornado/pull/1017)

• Мало документации и примеров

https://github.com/hhru/frontik

29

Что хотелось• Уменьшить количество многоуровневых запросов

• Иметь бо́льшую свободу в выборе шаблонизатора

• Чтобы работало и на upstream Tornado

30

Tortik

Preprocessors

backend1

backend2

backend3

Postprocessors

User request

HTML/JSON or cool debug page

Request Handler

32

Preprocessors• Набор асинхронных обработчиков (например, получение сессии)

• Выполняются до начала выполнения обработчика запроса

def session(handler, callback):

def _session_callback(session):

handler.session = session

callback()

session_client.get_session(_session_callback, ...)

33

Preprocessorsclass MobilePageHandler(tortik.page.RequestHandler):

preprocessors = [

session,

pagedata

]

34

Request Handler• Стандартные обработчики Tornado (get, post, ...) с @asynchronous

• Выходные данные формируются через

self.add('name', data) - аналог self.doc.put() во Frontik'е

• Можно и сразу self.complete({'name': data})

def get(self):

self.add('server_time', int(time.time))

self.add('data', {...})

self.complete()

35

Postprocessors• Набор последовательных обработчиков над выходными данными

• Выполняются после выполнения обработчика запроса

(RequestHandler)

def template(handler, data, callback):

out = template_engine.render(handler.template_name,

data=handler.get_data())

callback(handler, out)

36

Postprocessorsclass MobilePageHandler(tortik.page.RequestHandler):

postprocessors = [

template,

translation

]

37

Отправка запросов на бэкендыself.fetch_requests([

self.make_request(

name='vacancies',

method='GET',

full_url='https://api.hh.ru/vacancies/8252535'),

...

], callback=self.complete)

38

Отправка запросов на бэкендыself.fetch_requests([

('vacancies', 'https://api.hh.ru/vacancies/8252535'),

...

], callback=_cb)

39

Отправка запросов на бэкендыdef _cb():

response = self.responses['vacancies']

data = response.data # json или xml

# плюс автоматический

# self.add('vacancies', response.data)

self.complete()

40

Этапы обработки запроса• получение сессии

• обработка запроса (отправка запросов на сервисы и т.п.)

• шаблонизация

41

Этапы обработки запросаhandler.log.stage_started('render')

# do some hard render stuff

handler.log.stage_complete('render')

42

Этапы обработки запросаhandler.fetch_requests(

...

callback=_cb,

stage='session'

)

43

Этапы обработки запросаMONIK handler=hhmobile.pages.Page method=GET code=200

total=93 session=13.98 page=47.14 render=21.77

translation=7.30

44

Этапы обработки запросаMONIK handler=hhmobile.pages.Page method=GET code=200

total=93 session=13.98 page=47.14 render=21.77

translation=7.30

45

Этапы обработки запросаMONIK handler=hhmobile.pages.Page method=GET code=200

total=93 session=13.98 page=47.14 render=21.77

translation=7.30

46

Этапы обработки запросаMONIK handler=hhmobile.pages.Page method=GET code=200

total=93 session=13.98 page=47.14 render=21.77

translation=7.30

47

Мониторинг

48

Мониторинг

49

Спасибо!Виталий Глибин, HeadHunter

@glibin, glibin.ru

https://github.com/hhru/tortik

https://github.com/hhru/frontik

50