KostyaEsmukov

29 января 2018, Казань, Россия

# Понедельник 74 твита

Всем привет! На этой неделе с вами @KostyaEsmukov из Казани. Поговорим об Ansible, Django и немного о фронтенде.

8:20

Работаю в небольшой организации "Наше Дело" над несколькими проектами, в том числе над добровольцыроссии.рф

8:20

Примерный план на неделю:

8:20

Также в этом году я заканчиваю КФУ. В универе занимаюсь всяким IoT-ом на линуксах, в основном вокруг VPN.

Задавайте вопросы :)

8:20

В качестве git remote и CI используем self-hosted gitlab-ce (не gitlab.com, который периодически падае… twitter.com/i/web/status/9…

8:34

В обслуживании неприхотлив, обновляется тупо пуллом образа и пересозданием контейнера.
docs.gitlab.com/omnibus/docker…

8:34

При желании docker registry и CI раннеры можно без проблем вынести отдельно на другие машины. Интеграция с Jira аде… twitter.com/i/web/status/9…

8:34

Во-первых, CE версия урезана. Нету даже такой простой штуки, как Rebase вместо Merge commit при принятии Merge рекв… twitter.com/i/web/status/9…

8:34

Но можно запретить Merge коммиты кроме fast-forward, если нужна линейная история. Тогда rebase надо делать локально… twitter.com/i/web/status/9…

8:34

Во-вторых, мультиреповых пайплайнов в CE нет. Но есть в EE: docs.gitlab.com/ee/ci/multi_pr…

8:34

В одном проекте было так: Django апп в одном репе, а деплоящий его ansible в другом. В Django репе последним шагом… twitter.com/i/web/status/9…

8:34

Сейчас мы делаем иначе. Ансибл отдельным репом по-прежнему есть, но он не деплоит апп, а просто готовит сервер и пи… twitter.com/i/web/status/9…

8:34

Сначала это был простейший docker-compose, который выкинули из-за того, что он не способен без диких костылей в zero downtime deployment.

8:35

Поигрались с docker swarm, пострессили его и поняли, что такое в прод мы не готовы брать. Это было в октябре 2017,… twitter.com/i/web/status/9…

8:35

Вместо docker-compose засунули маленький ансибл, который деплоит только докер контейнеры с аппом. Как композ, тольк… twitter.com/i/web/status/9…

8:35

Из нюансов такого решения могу отметить то, что приходится дублировать inventory (хосты, куда деплоить) между основ… twitter.com/i/web/status/9…

8:35

В-третьих, CI все-таки довольно простенький. Для наших нужд (прогнать тесты, собрать докер образ, запушить в приват… twitter.com/i/web/status/9…

8:35

На практике ничего от этого у нас еще не падало, но для страховки, и чтобы раннеры не забивались, отменяем руками п… twitter.com/i/web/status/9…

8:35

Раннеры CI могут запускать jobs прямо в докере, а не локально. Для этого используют docker executor, а в репе в .gi… twitter.com/i/web/status/9…

8:35

1. Docker-in-docker (DinD)
Он плох тем, что нельзя использовать docker caching (реюз существующих слоев при сборке… twitter.com/i/web/status/9…

8:35

Да и контейнеры с jobs надо запускать с privileged флагом, что не делает DinD более безопасным. И вообще этот вариа… twitter.com/i/web/status/9…

8:35

2. Проброс /var/run/docker.sock в контейнеры раннеров, что позволяет собирать на хостовом docker daemon.
Этот вариа… twitter.com/i/web/status/9…

8:35

Но проблема решается просто: выносите раннер на отдельную виртуалку, где больше ничего нет, и живете спокойно.

8:35

Про докер добавлю, что если использовать ровно одну машину для раннеров, то кеширование слоев докера работает надеж… twitter.com/i/web/status/9…

8:35

На машине с раннером раз в неделю чистятся все образы и контейнеры в докере, иначе он быстро забивается.

8:35

В-четвертых, docker registry не чистится от старых образов прям совсем. Из вариантов – либо руками тыкать "удалить"… twitter.com/i/web/status/9…

8:35
@backendsecret Пробовал в BARS Group устраиваться? Debian или CentOS? Vim, Emacs, Sublime или PyCharm?

1. нет, мне и тут хорошо :)

8:41

Однажды, прямо в разгар рабочего дня, наш гитлаб начал сыпать ошибками. Вроде без всякой видимой причины.

8:48

По логам обнаружили, что, оказывается, там есть врубленный по дефолту гем rack-attack, который заблочил наш nginx п… twitter.com/i/web/status/9…

8:48
@backendsecret А что скажешь по kubernetes?

Поглядываем, но пока страшно. Экспертизы у нас по нему нет. На наших масштабах <10 машин на проект с ансиблом, каже… twitter.com/i/web/status/9…

9:58
@backendsecret У вас не блюгрин деплой ?

Нет. Накат прошлой версии из гитлаба занимает ~1-2 минуты нажатием на одну кнопку. Пригодилось всего один раз.

Так… twitter.com/i/web/status/9…

10:26

На одной машине за nginx работает по два апстрима веб аппа. Сначала ансибл gracefully прибивает один, обновляет его… twitter.com/i/web/status/9…

10:26

По сравнению с гитхабом, гитлабу, на мой взгляд, очень не хватает reviews, когда все комменты отправляются автору о… twitter.com/i/web/status/9…

14:30

Но зато у гитлаба есть клевая, на мой взгляд, фича: можно смотреть дифф между форс пушами (они называют это version… twitter.com/i/web/status/9…

14:30

Как ускорить сборку докер образов:

14:39

1. Как работает кеширование слоев можно почитать тут:
docs.docker.com/engine/usergui…

14:39

Не очень очевидный трюк здесь заключается в том, чтобы сначала добавить в образ файл с зависимостями вашего приложе… twitter.com/i/web/status/9…

14:39

Если файл с зависимостями меняется редко, то эти слои будут реюзаться, т.о. не вызывая установку зависимостей при каждом билде.

14:39

2. Зависимости могут компилироваться из исходников при установке. Например, psycopg2 (PG клиент) в python. Но вмест… twitter.com/i/web/status/9…

14:39

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

Однако, здесь есть нюанс. Ес… twitter.com/i/web/status/9…

14:39

А вам приходится использовать докер образы от левых людей в проде? Не страшно?

14:40
@backendsecret если докерфайлы перечитывать, то нет

А если завтра этот ноунейм автор туда фигню запушит? Можно пулить по неизменяемому digest образа, но нетегированные… twitter.com/i/web/status/9…

14:53
@backendsecret Что в swarm для вас было критично?

1. так и не получилось сделать 0dtd на нескольких нодах: все равно валились ошибки github.com/moby/moby/issu…

15:03

Из проблем с докером я сталкивался с такими:

15:30

1. Периодические сообщения в wall "unregister_netdevice: waiting for lo to become free". Что-то течёт в ядре и до с… twitter.com/i/web/status/9…

15:30

CentOS вообще из-за этой проблемы под небольшой нагрузкой начинал флудить (раз в 10 сек) этими сообщениями и перест… twitter.com/i/web/status/9…

15:30

На дебианах-убунтах такого не было у нас – наблюдаются просто одиночные сообщения без видимых последствий.

15:30

2. Если в системе есть роут 0.0.0.0/0 (от OpenVPN, например), то при старте докер демон не может найти свободную по… twitter.com/i/web/status/9…

15:30

3. Иногда докер не может удалить контейнер с ошибкой "device or resource busy". Чаще всего это проявляется на CentO… twitter.com/i/web/status/9…

15:30

В доках для RHEL рекомендуют devicemapper с LVM, но для ядра 4+ можно юзать нынче дефолтный overlay2.… twitter.com/i/web/status/9…

15:30

4. Если один контейнер высовывает с хоста UDP порт (53 для DNS, например), а из другого попытаться отправить на хос… twitter.com/i/web/status/9…

15:30

5. После появления multi-platform images ( blog.docker.com/2017/09/docker… ) иногда при пуле официальных образов вылезает о… twitter.com/i/web/status/9…

15:30

Полчаса приходится ждать, пока оно там у них соберется и запушится: github.com/docker-library…

15:30

6. Если собирать в образ какую-нибудь фигню с дикими флагами оптимизации (раньше phalcon так делал), то при запуске… twitter.com/i/web/status/9…

15:30

2, 4, 6 выявляются на этапе внедрения, это не критично.
1 даунтаймы только на CentOS вызывало, и то полтора года на… twitter.com/i/web/status/9…

15:30
@backendsecret docker tag noname/image:tag myname/image:tag
docker push myname/image:tag

Это после обязательного… twitter.com/i/web/status/9…

15:32
Wow that was fast, here’s the video from my keynote this morning youtu.be/7mzbIOtcIaQ

BTW If you haven’t seen yet this keynote by @jessfraz with some insights on containers history and security – I’d r… twitter.com/i/web/status/9…

15:34

Python/Django локально разрабатываем в докере с композом. PyCharm нормально подцепляет все зависимости, подсказки р… twitter.com/i/web/status/9…

19:50

А вот фронт делаем без докера. npm i + npm start – и так проще некуда. Зато проблемы докер тут доставляет: прокинут… twitter.com/i/web/status/9…

19:50

Ansible. Начну с хорошего: он работает :)
Разобраться в нем довольно легко за день-два. Поведение предсказуемо.
Пос… twitter.com/i/web/status/9…

20:01

Но вот поддержка гораздо сложнее: не могу сказать, что за 1.5 года у меня появилась хоть какая-либо уверенность в т… twitter.com/i/web/status/9…

20:01

Итак, по порядку:

  1. Очень легко наговнокодить. Прям слишком.

Можно кучу плейбуков плодить 🤢 вместо одного с тэгам…twitter.com/i/web/status/9…w

20:01

Тщательное изучение Best Practices (и доков в целом) просто обязательно, иначе с граблей не сойдёте: docs.ansible.com/ansible/latest…

20:01

Особое внимание хочу обратить на паттерн "Variables and Vaults" из дока выше. Он позволяет сделать все переменные,… twitter.com/i/web/status/9…

20:01

Есть, конечно, Single Encrypted Variables, но выглядит это не очень приятно (имхо): docs.ansible.com/ansible/latest…

20:01

Также не все знают, что есть такие штуки как:

20:01

И самое наболевшее: это когда кладешь сертификаты файлами в роли. Приходится писать жуткую логику, которая разрулив… twitter.com/i/web/status/9…

20:01

2. Логика в set_fact в ямле выглядит ужасно. Плохо форматируется, мало возможностей (ограничены jinja2 фильтрами +… twitter.com/i/web/status/9…

20:01

3. Python 2 vs 3. Оно влияет на плейбуки. Например, в Pyhton2 jinja2 фильтры возвращают листы. А в Python3 – генера… twitter.com/i/web/status/9…

20:01

4. Роли в Galaxy довольно сомнительного качества. Хороших мало. То они на конкретный дистрибутив (не твой), то тест… twitter.com/i/web/status/9…

20:01

5. С тестами довольно тяжело. У нас их на ансибле совсем нет. Вместо этого отлаживаем на стейджинге, и лишь потом н… twitter.com/i/web/status/9…

20:01

Пробовали молекулу, но она [была в сентябре 2017] довольно сырая: то свежий ансибл не поддерживается, то линтер пад… twitter.com/i/web/status/9…

20:01

Еще у них очень клёвый роадмап. Приз ребятам за находчивость! Жаль, что на работе такое не прокатит.… twitter.com/i/web/status/9…

20:01

Также, судя по всему, они нашли "фатальный недостаток" в galaxy и запилили свой пакетный менеджер: gilt.readthedocs.io/en/latest/

20:01

# Вторник 39 твитов

@backendsecret Очень полезно посмотреть ещё и сюда: github.com/jdauphant/awes…
7:04
@backendsecret Если использовать conda, можно в одном yaml файле и питон, и пакеджи, и библиотеки описать и ставить… twitter.com/i/web/status/9…
7:11

Nginx. Если вы используете его с докером, то nginx-proxy упрощает жизнь.
В него прокидывается сокет докер демона, ч… twitter.com/i/web/status/9…

7:25

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

7:25

... т.к. живых апстримов нет. Приходится его релоудить после деплоя аппа, чтобы он заново отрезолвил домены из апст… twitter.com/i/web/status/9…

7:25

Также к этой связке легко добавить поддержку LetsEncrypt с помощью github.com/JrCs/docker-le…

7:25

Только скейлить сетап nginx+LetsEncrypt сложнее: нужен общий стор между нодами (челленджи, сертификаты). Да и вообщ… twitter.com/i/web/status/9…

7:25

Также LetsEncrypt предлагает 3 вида челленджей: HTTP, DNS, TLS-SNI. Можно использовать DNS челлендж с одной машины… twitter.com/i/web/status/9…

7:25

Кстати, TLS-SNI челлендж планируют совсем убрать, т.к. легко получить сертификат для домена, который не контролируе… twitter.com/i/web/status/9…

7:25

Альтернатива – traefik.io . У него есть поддержка распределенного LE через K-V store. github.com/containous/tra…

7:25

Если еще не читали статью о том, как в StackOverflow год назад внедряли https – очень рекомендую. Про один wildcard… twitter.com/i/web/status/9…

7:25
Спринт на три недели я ласково зову «водопадик». twitter.com/backendsecret/…
7:34
@backendsecret Если сервис только на одной машине, то для прода это вполне весомое условие, согласен. А падение стейджа чем так критично?

Падение стейджа не критично. Но чем ближе среда прода к среде стейджа, тем меньше риск положить прод. Особенно с ан… twitter.com/i/web/status/9…

9:02
@jyraff @backendsecret У нас в рельсе другая проблема с Docker'ом: чтобы все это дело отдавалось nginx'ом, приходит… twitter.com/i/web/status/9…

В Django тоже такая особенность есть. Если uwsgi еще умеет статику раздавать из контейнера, то Django Channels – ни… twitter.com/i/web/status/9…

9:06

Почему nginx, а не traefik или даже голый веб апп:

9:14

1. Nginx очень качественный и быстрый. Даже я, такой “везучий”, не сталкивался с багами ни разу.

9:14

А вот issue трекер traefik сразу отпугивает: github.com/containous/tra…
Поищите даже по таким базовым вещам как gzip,… twitter.com/i/web/status/9…

9:14

2. Все-таки иногда нужно переопределять локейшоны. Редиректы расставить, заголовки кеширования на статику, robots.t… twitter.com/i/web/status/9…

9:14

3. Nginx может в microcaching: во время наплыва можно врубить кеширование ответов аппа для гостей. У нас снижало на… twitter.com/i/web/status/9…

9:14

Только осторожно с геоипом, куками и заголовками. Надо знать, от чего зависят ответы аппа. И апп не должен слать se… twitter.com/i/web/status/9…

9:14

Если в Django это практически не нужно (проще кеширование из Django через redis заюзать), то для ноды с Server Side… twitter.com/i/web/status/9…

9:14

4. Nginx (и -proxy + LEcompanion) умеет OCSP stapling из коробки. keycdn.com/support/ocsp-s…

Traefik не умеет… twitter.com/i/web/status/9…

9:14

5. Nginx замечательно работает с http/2. Не хватает только server push. Но, честно, пользы от него мало: чтобы брау… twitter.com/i/web/status/9…

9:14

CloudFlare умеет h/2 push. По моим экспериментам, если пушить бандлы вебпака (которые иначе прекрасно кешируются),… twitter.com/i/web/status/9…

9:14

А может кто-то все-таки успешно использует h/2 push? Расскажите!

9:14

CORS исторически у нас всегда был в nginx. Как-то так: enable-cors.org/server_nginx.h…
На первый взгляд вроде всё мило: эко… twitter.com/i/web/status/9…

9:21

На второй не очень:

9:21

3. OPTIONS запросы не доходят до аппа. Django Rest Framework там возвращает инфу по эндпоинту, например, которая мо… twitter.com/i/web/status/9…

9:21

Мониторинг. Минимальный набор у нас это: nginx access logs + Sentry + Zabbix + uptimerobot.com . Настраивае… twitter.com/i/web/status/9…

17:21

Zabbix с версии 3 стал очень хорошим. Появилось TLS шифрование между агентом и коллектором (теперь VPN/LAN для них… twitter.com/i/web/status/9…

17:21

Из коробки легко настраиваются алерты в почту. Можно настроить хоть в телеграм: gist.github.com/KostyaEsmukov/…

Агенты раз… twitter.com/i/web/status/9…

17:21

Но добавлять кастомные метрики в заббикс неудобно. Нужно и в агент конфиг дописать, и в вебморду template сделать (… twitter.com/i/web/status/9…

17:21

Sentry мы очень любим. С Python/Django интеграция вообще прекрасная. По любому непойманному исключению есть куча ин… twitter.com/i/web/status/9…

17:21

Есть Cloud версия. Но надо иметь в виду, что несмотря на наличие встроенного data scrubber на клиенте, часть секрет… twitter.com/i/web/status/9…

17:21

Клиент Sentry для JS чуть похуже питоновского. Инфы отсылается меньше. Также у них их две версии: "raven-js" для бр… twitter.com/i/web/status/9…

17:21

Prometheus хорош. Прожорливый по памяти только, да и разворачивается тяжеловато: куча отдельных компонентов (сам pr… twitter.com/i/web/status/9…

17:21

Из аппа метрики можно экспортить так:

17:21

Если между прометеусом и экспортерами нет защищенной сети (у нас разные проекты мониторятся), то в доках рекомендуе… twitter.com/i/web/status/9…

17:21

Мы спрятали за nginx с клиентскими сертификатами. Работает замечательно, но ансибла вокруг этого всего многовато.

17:21

# Среда 53 твита

@backendsecret Мы как раз выбрали DNS челендж вместо того чтобы шарить папку или заруливать выписывание только на о… twitter.com/i/web/status/9…
7:29
@backendsecret 1. Как масштабировать прометей и бороться с дырками в таймлане метрик?

1. Насчет масштабирования – federation. Насчет дырок – зависит от их причины. Если это от ребута сервера – то они т… twitter.com/i/web/status/9…

7:40

2. Можно прикрыть его nginx с basic auth. По аксес логам видно, какой юзер слал запросы.

7:40

Python. На двойке после тройки прям противно писать. Но тройка лично мне, несмотря на проблемы (о них ниже – всё имхо), нравится.

7:52

1. Основная проблема 3 это Py2. Где-то ещё приходится писать 2+3 код (это когда пишешь на 2, но так, чтобы оно еще… twitter.com/i/web/status/9…

7:52

Многим еще приходится писать на Python 2, потому что миграция большой кодовой базы на тройку это реально дорого, а… twitter.com/i/web/status/9…

7:52

Интервью с инженерами из инстаграм о том, почему (typings, community, performance) и как (10 месяцев в 3 стадии) он… twitter.com/i/web/status/9…

7:52

Вот интересные сайтики, где показано, сколько из топовых пакетов поддерживают тройку. Спойлер: почти все.… twitter.com/i/web/status/9…

7:52

Из моей практики сейчас осталось всего два пакета, которые еще не поддерживают 3: evernote-sdk-python (есть бета дл… twitter.com/i/web/status/9…

7:52

Очень больно смотреть на новые (мелкие!) проекты, которые начинают на Python2. Просто потому, что так привыкли. Пож… twitter.com/i/web/status/9…

7:52

2. Стандартная библиотека хоть и большая, но местами тухловатая. Например, http клиент (urllib) даже ответ в юникод… twitter.com/i/web/status/9…

7:52

Есть поддержка IDNA encoding, но она реализует устаревшую (на 7 лет) версию спеки. Поэтому приходится юзать сторонн… twitter.com/i/web/status/9…

7:52

Вместо модуля регулярок re иногда юзают сторонний regex, в котором есть поддержка Unicode codepoint properties (нап… twitter.com/i/web/status/9…

7:52

А в Татарстане у нас вообще свой мир: pic.twitter.com/Cimq1YPq1J

7:52

3. Performance – это не про пайтон. Говорят, что pypy вместо cpython снижает нагрузку. Но, имхо, от пайтона ждать п… twitter.com/i/web/status/9…

7:52

Кстати, в cpython 3.7 будет небольшая оптимизация потребления памяти при использовании GC для shared memory (из-за… twitter.com/i/web/status/9…

7:52

4. Куча мяса вокруг доставки зависимостей: easy_install, pip, conda, apt/yum/etc. setup.py, pbr, PEP… twitter.com/i/web/status/9…

7:54

В общем, проблем хватает. Но community, на мой взгляд, отличное.

7:54

Про синхронизацию состояния между фронтом и бэком поговорим в четверг pic.twitter.com/I3RrdTyXuV

7:55
@backendsecret Как организовывать структуру проекта с Django или аналогичного рода фреймворком, когда для фронта An… twitter.com/i/web/status/9…

Если бэк отдает только API, то однозначно отдельными репами. Мобильные приложения не храните в репе с бэкендом же,… twitter.com/i/web/status/9…

8:20
Ещё причина - необходимость работы в энтерпрайзе с RHEL6, где из коробки py2.6 twitter.com/backendsecret/…

А еще внутренние зависимости энтерпрайза на py2. Это да.

Мой твит был о мелких проектах, не обремененных энтерпра… twitter.com/i/web/status/9…

8:25
Я конечно о своем буду ныть. Вот сколько сил/времени в каждой команде на все это уходит. А это потеря фокуса, несде… twitter.com/i/web/status/9…

Да, Вы абсолютно правы. Именно поэтому я и затронул Prometheus. На одном Zabbix с современным веб аппом действитель… twitter.com/i/web/status/9…

10:04

Помимо community пайтона мне очень близки его принципы из The Zen of Python. Самый известный, наверное, это:

Expli… twitter.com/i/web/status/9…

10:10

А если вы *реально* его прочитали и помедитировали, то вот это может вызвать у вас недоумение:
There should be one-… twitter.com/i/web/status/9…

10:10

Если вы читали код на Python 2+3, то наверняка могли видеть необычные импорты такого вида:

from __future__ import… twitter.com/i/web/status/9…

10:20

Большинство из них касаются Python2, но и для тройки есть парочка:
generator_stop (с 3.5) python.org/dev/peps/pep-0…twitter.com/i/web/status/9…

10:20

Я жду 3.7 ради __future__ annotations, который откладывает evaluation of type annotations, что решит проблему с обя… twitter.com/i/web/status/9…

10:20

Еще есть __future__ пасхалка, заменяющая оператор != на <>:

>>> from __future__ import barry_as_FLUFL
>>> 1 <> 2… twitter.com/i/web/status/9…

10:20

Django. Позиционирует себя как "Web framework that encourages ... pragmatic design", но URLValidator не принимает у… twitter.com/i/web/status/9…

19:11

Но в целом принципы, перечисленные на этой странице, вполне соблюдаются и в Django, и в аппах для нее (по моим набл… twitter.com/i/web/status/9…

19:11

REST API на голой Django писать неудобно, поэтому для апи практически всегда тащат Django Rest Framework (DRF). Бол… twitter.com/i/web/status/9…

19:11

Пермишки проверять надо в BasePermission классах. Отображением и валидацией управлять в Serializer. Фильтрацией в F… twitter.com/i/web/status/9…

19:11

Причем креативить то можно. Только потом сплошные страдания от этого. Лишний код (бойлерплейт!), который надо подде… twitter.com/i/web/status/9…

19:11

Строгий RESTful никто не навязывает (но из коробки DRF пытается быть похожим). Добавляйте свои нетривиальные экшоны… twitter.com/i/web/status/9…

19:11

Изучив все эти абстракции, рапидно разворачивать проекты довольно несложно.
Разумеется, это утверждение верно для л… twitter.com/i/web/status/9…

19:11

Естественно, все эти ништяки аукаются ценой запросов ORM (хотя в среднем они довольно адекватные) и вездесущими cou… twitter.com/i/web/status/9…

19:11

Из коробки клёвые админка и гуи для API, которые реюзают часть (если не всю) написанной логики для API. Не надо ник… twitter.com/i/web/status/9…

19:11

Накидал модельку-вьюсет-сериалайзер-тесты для новостей, выдал админскую учетку стаффам с пермишками только к этим н… twitter.com/i/web/status/9…

19:11

Очень клёвая поддержка geospatial через postgis из коробки. Прям очень. Полигоны, точки, расстояния – всё спокойно… twitter.com/i/web/status/9…

19:11

Некоторые вещи приходится кастомайзить. Тот же URLValidator, например. Или пагинатор свой. Но проблем с этим у нас… twitter.com/i/web/status/9…

19:11

Очень рекомендую апп django-waffle. Позволяет делать фича-флаги. Мы их используем очень по-разному: для тестировани… twitter.com/i/web/status/9…

19:11

И хотя автор DRF не рекомендует отключать DRF Browsable API, оно течёт значениями FK. Например, если у юзера есть F… twitter.com/i/web/status/9…

19:11

Мы закрыли DRF Browsable API через django-waffle, показываем только стаффу.

19:11

Также значения FK по дефолту рендерятся в html шаблоне админки на странице редактирования сущности. Тут вопрос перф… twitter.com/i/web/status/9…

19:11

Django большая. Есть также протухшие куски. Например, поле для картинок не умеет генерить вариации – юзают django-s… twitter.com/i/web/status/9…

19:11

Иногда добавляют новые куски. Например, нативный JSONField для PG (в 1.9) или db migrations (1.7) – то, что раньше… twitter.com/i/web/status/9…

19:11

План миграции c south великолепный: удалите все миграции и создайте новые. What could possibly go wrong?… twitter.com/i/web/status/9…

19:11

Опять про инстаграм: как они апгрейдились с Django 1.3 до 1.8: youtu.be/lx5WQjXLlq8?t=… (ссылка с таймтегом)

19:11

До версии 2.0 каждый *.* релиз считался мажорным (как у postgres). С 2.0 маркировка версий немного поменялась: docs.djangoproject.com/en/dev/interna…

19:11

Кстати, если вы мейнтейните Django проект и до сих пор не подписались на django-announce mailing list, очень рекоме… twitter.com/i/web/status/9…

19:11

Для вебсокетов есть Django Channels: запросы принимает daphne ("HTTP and WS termination server") и через redis/amqp… twitter.com/i/web/status/9…

19:11

Выглядит сложно, но на деле проблем не вызывает. У нас на нескольких проектах оно в проде, не жалуемся.

19:11

Как-то так. Django хейтить у меня получается хуже, чем всё остальное :)

Про ORM и тестирование напишу отдельно (завтра).

19:11

# Четверг 49 твитов

@backendsecret Миниатюры проще генерить на лету с кешированием через nginx + image_filter или гошными тулзами. Зара… twitter.com/i/web/status/9…

Это когда media хранится у тебя (или гоняется через тебя). Но взять S3-alike сторадж проще в обслуживании, имхо. Пр… twitter.com/i/web/status/9…

6:47
@backendsecret Мы тут совместно уютным чатиком написали FAQ для заинтересованных github.com/amureki/django…
6:49
@salikhov @backendsecret И после этого какой-то умник натравит скрипт в цикле запрашивающий размеры с изменением в… twitter.com/i/web/status/9…

А другой умник при тех же затратах пойдёт плодить сущности через ваше REST API. Абузить можно много чего.

Также ко… twitter.com/i/web/status/9…

7:05

Django ORM. Действительно очень прагматичная штука. Селекты с джойнами ей даются очень легко. Immutable и lazy quer… twitter.com/i/web/status/9…

7:22

Надо ко всем запросам приджойнить FK? Не вопрос, в модельку пихаешь менеджер, который модифицирует дефолтный QS (se… twitter.com/i/web/status/9…

7:22

Надо отпагинировать ответ? BasePagination принимает QS и нарезает его лимитами-оффсетами как угодно (постранично, к… twitter.com/i/web/status/9…

7:22

Тут следствие: Django без её ORM юзать в принципе можно, но вы не сможете использовать практически ничего из неё: а… twitter.com/i/web/status/9…

7:22

В любой момент можно скатиться до сырого SQL. Причём в двух вариантах: "низкоуровневый" для записи и обернутый в Ra… twitter.com/i/web/status/9…

7:22

Модельки можно наследовать. Например, один раз мы закодили модерацию, и теперь просто подмешиваем её модельку/сериа… twitter.com/i/web/status/9…

7:22

Неадекватные запросы (лично у меня) бывают только для монстров с GROUP BY. И то по тестам сразу становится понятно,… twitter.com/i/web/status/9…

7:22

DELETE/INSERT испортить сложно :).
Есть bulk_create для одного INSERT с кучей VALUES.
Но нет постгресовского ON CO… twitter.com/i/web/status/9…

7:22

Есть сигналы: чтобы после сохранения сущности можно было что-то сделать: счётчики пересчитать, имейл отправить и т.… twitter.com/i/web/status/9…

7:22

Проблема с сигналами в том, что для запросов по нескольким строкам они не вызываются. Например, для bulk_create и д… twitter.com/i/web/status/9…

7:22

Есть и ряд других нюансов в угоду прагматичности, расстраивающих DBA и перфекционистов:

7:22

2. Те самые choices (как SQL enum), о которых я вчера писал, на самом деле хранятся как varchar, а не как enum. Воз… twitter.com/i/web/status/9…

7:22

3. Валидаторы не переносятся в constraints бд. Даже такие простые как choices и min/max. И при ретриве из бд объект… twitter.com/i/web/status/9…

7:22

4. Перед сохранением при валидации проще сделать несколько селектов и сформировать ошибки, чем сразу пытаться сохра… twitter.com/i/web/status/9…

7:22
@backendsecret привет! А можешь заретвитить вакансию плз, возможно кто-то из читателей мечтает писать на Elixir в большом проекте.

Aviasales twitter.com/fliptheweb/sta…

8:18

Django + DRF tests. Тестраннер из коробки адекватный (но докинуть pytest + линтер стоит).
Кто-то может удивиться, н… twitter.com/i/web/status/9…

9:10

Теоретически, нормальные unit тесты (работающие <1 сек) можно получить, если заморочиться с моками кучи джанговской… twitter.com/i/web/status/9…

9:10

Но на практике [нам] это не сильно мешает. Приложение разбито на мелкие аппы. Тесты аппа, в свою очередь, на отдель… twitter.com/i/web/status/9…

9:10

С другой стороны, писать такие пухлые тесты кажется прагматично: при апгрейдах помогает.

9:10

С HTTP запросами в тестах проблема решается с помощью vcrpy (аналог рубишного vcr): при первом запуске HTTP запросы… twitter.com/i/web/status/9…

9:10

К вопросу о необходимости тестов и о покрытии, скажу так: непокрытое кусает за задницу в самый неподходящий момент.… twitter.com/i/web/status/9…

9:10

Переходим к фронту. Хочу обсудить с вами хипстерский тренд: пихание SPA во все щели вместо обычных HTML шаблонов на… twitter.com/i/web/status/9…

14:08

Если коротко: на SPA проще и быстрее делать модный фронт, меньше дублирования кода на бэке (API всё равно надо). Но… twitter.com/i/web/status/9…

14:08

(+) Удобнее сборка. Не надо думать, как втащить в ваш бэкенд coffeescript/uglifier/sass/yui, а потом – oh SHI💩 – вы… twitter.com/i/web/status/9…

14:08

Во фронте всё меняется быстрее, чем на бэке. У нас уже давно evergreen браузеры. Место IE уже успел занять Safari.… twitter.com/i/web/status/9…

14:08

(+) Компоненты дают удобную структуру: вёрстка и стили рядом с логикой, реюзаются хорошо, BEM не нужен (простите).

14:08

(+) Управление состоянием в шаблоне это сложно. Сделать интерактивную загрузку аватарки так, чтобы она сразу везде… twitter.com/i/web/status/9…

14:08

С реакт-редуксом такой проблемы в принципе нет, т.к. источник правды один, и он всегда актуально выведен в отображение.

14:08

Для ангуляра это *частично* тоже корректно, но не совсем: типично данные из HTTP запросов один раз стекаются в шабл… twitter.com/i/web/status/9…

14:08

(+) Навигация быстрее, интеракция быстрее => UX лучше (при прочих равных).

14:08

(-) Нужна куча инфраструктуры вокруг. SPA без SSR грузится заметно дольше, чем шаблоны. А SSR это сразу nodejs в прод тащить надо.

14:08

Нельзя просто так взять вебпаковый фронт, собрать dist и задеплоить его в 2 разных окружения: CDN/API урлы и прочие… twitter.com/i/web/status/9…

14:08

(-) Типичный SSR из коробки возвращает на любой запрос http status 200. Редиректов нет. Еретики!
(справедливости ра… twitter.com/i/web/status/9…

14:08

(-) Поддерживать древние браузеры сложнее. С SSR прочитать сайт смогут все (пренебрежём поехавшей вёрсткой на IE8),… twitter.com/i/web/status/9…

14:08

(-) При перегрузах API сервера SPA фронт практически ни на один запрос не выдаст адекватный ответ: для рендеринга н… twitter.com/i/web/status/9…

14:08

(-) Требуется решать проблему с пробросом загруженных в SSR данных до аппа в браузере. В реакт-редуксе замечал 2 гл… twitter.com/i/web/status/9…

14:08

(-) Иногда очень сложно сделать выбор. react/preact? redux/mobx? cssmodules/CSSinJS? (в Ангуляре с этим сильно прощ… twitter.com/i/web/status/9…

14:08

(-) i18n на бэке и на фронте разный. Тексты лежат в разных местах и иногда дублируются. Правила плюрализации могут отличаться.

14:08

(-) Появляется проблема показа-сокрытия доступных кнопочек-формочек. Из REST апи просто так эту информацию не всегд… twitter.com/i/web/status/9…

14:08

Да ещё и кнопочки эти надо для каждого объекта из длинного списка рисовать. Без замусоривания сущности флагами дост… twitter.com/i/web/status/9…

14:08

(-) Есть клиенты, у которых одна версия SPA во вкладке живёт больше суток. Даже если этот SPA – единственный консью… twitter.com/i/web/status/9…

14:08

(*) Ни один вариант не решает проблему дублирования логики (валидации, подсчёта символов в твите).
Ну, тут всё зави… twitter.com/i/web/status/9…

14:08

*нет, не предлагайте мне писать API на nodejs в монорепе, оно того не стоит*

14:08

В общем: шо то говно, шо это говно, и обе эти … ну вы поняли.

14:08
@backendsecret Trello просто периодически просит перезагрузить страницу

Jira великолепно проблему устаревания кода фронта решает (правда, там не SPA): хочешь видеть свежий бэклог во время… twitter.com/i/web/status/9…

15:17

А todoist (реакт) вытаскивает такую кнопочку в контекстное меню: pic.twitter.com/2VgxM4lPag

15:17

# Пятница 26 твитов

Доброе утро и с пятницей!

Придумайте подпись к картинке :)
(и помогите мне развидеть здесь 2 зуба с зубной пастой… twitter.com/i/web/status/9…

6:29

Node.js. Интернет просто переполнен примерами простых веб серверов, а когда дело доходит до прода, выясняется ряд особенностей:

10:02

1. Как получить IP клиента, имея объект http request? Обычно это деталь окружения: задается в апп сервере или в нас… twitter.com/i/web/status/9…

10:02

– Why not? Разве бывают сэтапы иные чем traefik/nginx с realip перед нодой? Разве бывают другие заголовки для перед… twitter.com/i/web/status/9…

10:02

2. Graceful Shutdown. Дёрнуть httpServer.close() при SIGTERM это полдела. По-видимому, кто-то решил, что для закрыт… twitter.com/i/web/status/9…

10:02

И да, вы не столкнётесь с этой проблемой, пока ваша нода работает за nginx с дефолтным proxy_pass, который не юзает… twitter.com/i/web/status/9…

10:02

Npm не был бы npm, если бы там не было второго пакета с таким же функционалом (причём от автора самого npm): github.com/isaacs/server-…

10:02

3. Нет никаких интерфейсов (в смысле ООП). Хотите нормальный логгер? Манки-патчьте console.log/error/*. И учтите, ч… twitter.com/i/web/status/9…

10:02

4. Нельзя просто так взять и запустить ноду в несколько процессов. Есть Process Managers: pm2/strongloop, но помимо… twitter.com/i/web/status/9…

10:02

Ну окей, есть ведь встроенный cluster module? И кода вроде не много: nodejs.org/api/cluster.ht…
Да, только когда к эт… twitter.com/i/web/status/9…

10:02

5. Надо следить за падениями из-за недостатка heap (1.7G по дефолту). Они могут происходить как по причине утечек в… twitter.com/i/web/status/9…

10:02

В принципе, ничего здесь криминального нет. Но кажется, что с абстракциями в ноде что-то пошло не так.

10:02

Angular. Очень легко наговнякать, если в команде нет экспертизы по нему. Но если есть, то скорость разработки (имхо… twitter.com/i/web/status/9…

16:25

ng-cli сейчас очень хороший. "ng new" генерит вам адекватно настроенный SPA с тест раннерами (и юнит, и e2e). Внутр… twitter.com/i/web/status/9…

16:25

С SSR ещё в начале 2017 всё было очень плохо. С Angular 4 стало сильно лучше. Из проблем SSR остались (имхо):

16:25

1. HTTP redirects. Поведение из коробки: вернуть отрендеренный ответ после редиректов, а в браузере, после инициали… twitter.com/i/web/status/9…

16:25

2. HTTP status. Для страницы 404, например. По дефолту всегда и на всё будет 200. Решается похожим образом как в гисте выше.

16:25

3. State transfer. В ng5 появился сервис TransferState, пихающий данные из сервера в браузер через html. Можно пове… twitter.com/i/web/status/9…

16:25

HTTP клиент, кстати, очень клёвый. Есть интерсепторы (как middleware), ютилы для тестов, легко подписаться на прогр… twitter.com/i/web/status/9…

16:25

Опять же, как и в Django/DRF, в ng куча чётких абстракций. Code scaffolding для новых компонентов/сервисов/пайпов з… twitter.com/i/web/status/9…

16:25
Для ангуляра это *частично* тоже корректно, но не совсем: типично данные из HTTP запросов один раз стекаются в шабл… twitter.com/i/web/status/9…

Бойлерплейта немало, но, кажется, сильно меньше, чем в RRS.

Документация средненькая. Многие вещи не покрыты (zon… twitter.com/i/web/status/9…

16:25

С появлением AOT тормоза JIT и жирнющие бандлы давно ушли в прошлое. На добровольцыроссии.рф сейчас это 550 кб г… twitter.com/i/web/status/9…

16:25

Новички, по моим наблюдениям, сталкиваются со следующими проблемами:

16:25

2. Работа с DOM браузера. Почти всегда можно (и нужно) обойтись манипуляциями с shadow DOM. А когда нельзя (jquery)… twitter.com/i/web/status/9…

16:25

3. Zone.js. Всякие setTimeout там, где не надо. В панике делают импорт ChangeDetectorRef, который вообще трогать не… twitter.com/i/web/status/9…

16:25

В целом – на ангуляре хорошо, что бы там ни говорили злые языки, не осилившие его. Хотя управление состоянием в rea… twitter.com/i/web/status/9…

16:25

# Суббота 12 твитов

Юникод в ссылках. Если вы ещё ни разу не выводили в прод IDN домены или юникод пути/слаги, то вот, что вас ожидает… twitter.com/i/web/status/9…

14:44

URI (RFC3986) vs IRI (RFC3987).
URI не могут содержать юникод и ограничены символами типа a-z0-9:@% и т.п.
IRI рас… twitter.com/i/web/status/9…

14:44

То, что вы видите в адресной строке хрома (читабельное и на русском) – это IRI.
То, что попадает в буфер обмена, к… twitter.com/i/web/status/9…

14:44

По спеке HTTP 1.1 (RFC7230) везде юзаются только URI (для h/2 аналогично).

IDN host преобразовывается в ascii по п… twitter.com/i/web/status/9…

14:44

1. Некоторые клиенты (как минимум whatsapp и vk при подгрузке сниппетов) отправляют не percent-encoded segments, а… twitter.com/i/web/status/9…

14:44

Nodejs интерпретирует этот UTF8 как latin1 и в таком виде отдаёт аппу. Роутер ангуляра у нас от такого сходил с ума… twitter.com/i/web/status/9…

14:44

2. IE/Edge в CORS шлют IDN домен в корявом представлении юникода вместо punycode. В ответ они не принимают ничего к… twitter.com/i/web/status/9…

14:44

У себя вы это ещё можете подпереть *, но если ваш фронт ходит на другие сайты (oauth через JS SDK), то там 99% что… twitter.com/i/web/status/9…

14:44

3. Даже в 2018 ещё не все внешние сервисы способны работать с IDN. Например, mailgun: stackoverflow.com/q/46877391

14:44

4. Очень желательно добавить в интерфейс кнопку/поле для копирования в буфер обмена IRI, иначе юзеры будут шарить э… twitter.com/i/web/status/9…

14:44

5. В HTML в <a href= надо указывать URI. Почтовые клиенты к этому особенно чувствительны: IRI в href вообще за ссылку не считают.

14:44

Ко всему этому безобразию добавлю, что если вы принимаете от юзеров ссылки (website юзера, например) и показываете… twitter.com/i/web/status/9…

14:44

# Воскресенье 13 твитов

Напоследок немного нетехнического.

К сожалению, нередко мне приходится видеть новые проекты, написанные совсем без… twitter.com/i/web/status/9…

12:21

Практически любой *новый* проект должен быть максимально простым (MVP), чтобы быстрее реагировать на изменения.

П… twitter.com/i/web/status/9…

12:21

А меняется всё вокруг: требования, окружение, тренды, настроение людей. Свои ошибки надо исправлять быстро.

Тут пр… twitter.com/i/web/status/9…

12:21

Это также касается и тестов: селективное покрытие повышает качество продукта (а иногда даже ускоряет разработку). Н… twitter.com/i/web/status/9…

12:21

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

Новые проекты, казалось бы, это хороший… twitter.com/i/web/status/9…

12:21

Бизнес не любит лишние риски, но склонен доверять нам, айтишникам, в принятии технических решений (особенно не-IT б… twitter.com/i/web/status/9…

12:21

Как тогда знакомиться с технологиями, благодаря которым вы сможете делать свою работу лучше (быстрее/качественнее/с… twitter.com/i/web/status/9…

12:21

2. Общайтесь! Есть уютные локальные чатики, митапы, конференции, твиттер, менторинг. Люди, как правило, с удовольст… twitter.com/i/web/status/9…

12:21

3. *хотел написать про pet-проджекты, но почему-то передумал*

Ну а кроме шуток: если есть желание и возможность де… twitter.com/i/web/status/9…

12:21

А если в команде нет опыта запуска похожих (технически) проектов – то постарайтесь найти человека, у которого он ес… twitter.com/i/web/status/9…

12:21

Прекрасно понимаю, что маленьким командам найти себе такого человека бывает крайне сложно (из-за денег или недостат… twitter.com/i/web/status/9…

12:21

Пора прощаться. С вами был @KostyaEsmukov
Надеюсь, что хоть кому-то мой скромный опыт оказался полезен.
Спасибо, с вами круто!

14:58

А если вам это всё показалось интересным и вы бы хотели работать с нами над добровольцыроссии.рф – напишите мне в DM: @KostyaEsmukov

14:58

github.com

other