Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

«Тотальный контроль производительности» Михаил Юматов, ЦИАН

286 views

Published on

Выступление на PYCON RUSSIA 2017

Published in: Internet
  • Be the first to comment

«Тотальный контроль производительности» Михаил Юматов, ЦИАН

  1. 1. 1 Т О Т А Л Ь Н Ы Й К О Н Т Р О Л Ь П Р О И З В О Д И Т Е Л Ь Н О С Т И М И Х А И Л Ю М А Т О В
  2. 2. О себе - Руководитель разработки в ЦИАН - В ЦИАНе с 2015 - 10 лет разработки на Python 2
  3. 3. Про ЦИАН - 6,8 млн покупателей и арендаторов в месяц - 72% москвичей знают о нас - 8x разработка за 2014-2017 3
  4. 4. Хочу знать - Насколько быстро выполняется запрос? - Почему работает медленно? - Что делать,чтобы стало быстрее? 4
  5. 5. В двух словах про Graphite + StatsD + Grafana 5
  6. 6. Graphite: темпоральная БД (TSDB) 6 import socket sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(b'search-offers 300n', ('graphite', 2013)) t0 t1 t2 ... 300 347 323 ... timestamp value
  7. 7. StatsD: агрегатор метрик 7 from statsd import StatsClient statsd = StatsClient() statsd.timing('search-offers', 200) stat StatsD stat.upper stat.upper_99 stat.upper_90 ...
  8. 8. Grafana: дешборд для визуализации метрик 8 from statsd import StatsClient statsd = StatsClient() statsd.timing('search-offers', 200)
  9. 9. Что получили полезного: - Есть время работы функции - Есть количество запросов в секунду 9
  10. 10. Что не очень нравится: - Нет контекста - Хаос метрик 10
  11. 11. .request .get-user .search-offers .get-urls .render t0 t1 t2 t3 t4 11
  12. 12. {app}.{method}.{handler}.{status_code}.{stat} Наводим порядок Приложение HTTP-метод (GET, POST, ...) Обработчик запроса Код состояния HTTP Метрика 12
  13. 13. with statsd.timer('search-offers'): result = es.search(index, query) with prof.timer('search-offers'): result = es.search(index, query) Наводим порядок Было Стало 13
  14. 14. 14
  15. 15. Что получили полезного: - Знаем время работы всех типов запросов - Знаем,какие типы запросов работают медленно - Знаем,как ведут себя ключевые операции в рамках запроса 15
  16. 16. Чего не хватает: - Почему запрос затупил в конкретный момент времени? 16
  17. 17. 17 ? !
  18. 18. .request .get-user .search-offers .get-urls .render t0 t1 t2 t3 t4 18
  19. 19. 19 Собираем - длительность,время начала,аргументы каждой операции - длительность,время начала,параметры каждого запроса И - логируем все плохие запросы в ELK
  20. 20. Slowlog 20 with slowlog.operation_elastic( name='ElasticSearch.search', args=(index, query)): result = es.search(index, query)
  21. 21. Slowlog 21
  22. 22. Что получили полезного: - Можно разобраться,почему затупил запрос 22
  23. 23. Чего не хватает: - Почему запрос затупил в конкретный момент времени? 23
  24. 24. .request .get-urls t0 t3 24 .get-urls ? ? ? ......
  25. 25. .request .get-urls t0 t3 25 .get-urls ? ? ? ...... X-RequestId X-RequestId
  26. 26. Что получили полезного: - Можно трассировать запросы по ID - Можно глубже разобраться в проблеме затупов 26
  27. 27. Чего не хватает: - Как быть,есть стабильно работает медленно,а причины неизвестны 27
  28. 28. .request .get-user .search-offers .get-urls .render t0 t1 t2 t3 t4 28
  29. 29. StatProf 29 import signal signal.signal(signal.SIGALRM, sample) signal.setitimer(signal.ITIMER_REAL, 0.05) t1 t2 t3 t4 семплы
  30. 30. StatProf 30 import signal signal.signal(signal.SIGALRM, sample) signal.setitimer(signal.ITIMER_REAL, 0.05) t1 t2 t3 t4 семплы
  31. 31. StatProf 31 def sample(signum, frame): stack = [] while frame is not None: stack.append(format_frame(frame)) frame = frame.f_back stack = ';'.join(reversed(stack)) stacks.append(stack) signal.setitimer(signal.ITIMER_REAL, INTERVAL)
  32. 32. StatProf 32 __call__(django.core.handlers.wsgi:wsgi.py::160); get_response(django.core.handlers.base:base.py::73); view(django.views.generic.base:base.py::62); dispatch(django.views.generic.base:base.py::79); get(offer.views:views.py::130); search_offers(offer.views:views.py::231); ... 10 stack1 73 stack2 32 stack3 ...
  33. 33. 33 Собираем - семплы и их количество - длительность каждого запроса И - логируем все запросы в ELK
  34. 34. FlameGraph 34
  35. 35. FlameGraph 35 !
  36. 36. Как все это используем: 1. Смотрим графики,следим за алертами 2. Ищем медленные запросы в slowlog'е 3. Смотрим flamegraph'ы,когда ничего не понятно 36
  37. 37. Ссылки 37 Graphite: https://graphiteapp.org/ StatsD: https://github.com/etsy/statsd Grafana: https://grafana.com/ FlameGraph: https://github.com/brendangregg/FlameGraph cian-prof: https://gist.github.com/yumike/7b69afb5a1206b0b8db6458cc88fd038 cian-slowlog: https://gist.github.com/yumike/7ed521eccfde363f300d6c6b52159d5b cian-statprof: https://gist.github.com/yumike/d2c833e3289d08cae514af73a6a2cb37
  38. 38. Спасибо за внимание! Вопросы? 38 my@cian.ru http://t.me/yumike

×