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

Виталий Глибин, HeadHunter

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

Виталий Глибин, HeadHunter

Что такое SOA?

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

Проблемы

  1. Один репозиторий, много разработчиков
  2. Рост кодовой базы
  3. Ограничения в использовании языка программирования
  4. Внешние подрядчики
  5. ... to be counted

Сервис-ориентированная архитектура (SOA)

модульный подход к разработке программного обеспечения, основанный на использовании распределённых, слабо связанных заменяемых компонентов со стандартизированными интерфейсами и протоколам взаимодействия.

Источник: Wikipedia

SOA-based сайт

Компонент системы в разработке

Контролируемая деградация

Почему это важно

Источник: Akamai

Разные требования к сервисам

Виртуализация

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

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

Проблемы

Сеть

Эксплуатация

Разработка

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

Немного про Python

Frontik

Frontik

class 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))
        )
`

Frontik

https://github.com/hhru/frontik

Что хотелось

Tortik

Preprocessors

def session(handler, callback):
    def _session_callback(session):
        handler.session = session
        callback()
    session_client.get_session(_session_callback, ...)
		

Preprocessors

class MobilePageHandler(tortik.page.RequestHandler):
    preprocessors = [
        session,
        pagedata
    ]
		

Request Handler

def get(self):
    self.add('server_time', int(time.time))
    self.add('data', {...})
    self.complete()

Postprocessors

def template(handler, data, callback):
    out = template_engine.render(handler.template_name,
                                 data=handler.get_data())
    callback(handler, out)

Postprocessors

class MobilePageHandler(tortik.page.RequestHandler):
    postprocessors = [
        template,
        translation
    ]
		

Отправка запросов на бэкенды

self.fetch_requests([
    self.make_request(
        name='vacancies',
        method='GET',
        full_url='https://api.hh.ru/vacancies/8252535'),
        ...
    ], callback=self.complete)
		

Отправка запросов на бэкенды

			self.fetch_requests([
    ('vacancies', 'https://api.hh.ru/vacancies/8252535'),
    ...
], callback=_cb)
            
		

Отправка запросов на бэкенды

def _cb():
    response = self.responses['vacancies']
    data = response.data # json или xml
    # плюс автоматический
    # self.add('vacancies', response.data)
    self.complete()
            
		

Этапы обработки запроса

Этапы обработки запроса

handler.log.stage_started('render')
# do some hard render stuff
handler.log.stage_complete('render')
        
		

Этапы обработки запроса

handler.fetch_requests(
    ...
    callback=_cb,
    stage='session'
)
        
		

Этапы обработки запроса

MONIK handler=hhmobile.pages.Page method=GET code=200 
total=93 session=13.98 page=47.14 render=21.77
translation=7.30

Этапы обработки запроса

MONIK handler=hhmobile.pages.Page method=GET code=200 
total=93 session=13.98 page=47.14 render=21.77
translation=7.30

Этапы обработки запроса

MONIK handler=hhmobile.pages.Page method=GET code=200 
total=93 session=13.98 page=47.14 render=21.77
translation=7.30

Этапы обработки запроса

MONIK handler=hhmobile.pages.Page method=GET code=200 
total=93 session=13.98 page=47.14 render=21.77
translation=7.30

Мониторинг

Мониторинг

Спасибо!

Виталий Глибин, HeadHunter
@glibin, glibin.ru

https://github.com/hhru/tortik
https://github.com/hhru/frontik

http://glibin.github.io/lections/pycon2014/