Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo

1

#noBackend,
или Как выжить
в эпоху толстеющих клиентов
Николай Самохвалов
nikolay@samokhvalov.com
twitter: @postgresmen

2

Часть 1
Эпоха толстеющих клиентов

3

4 очень популярных языка для интернет-проектов
Год рождения — 1995

4

«Гадкий утёнок» JavaScript
1995: 1-я версия — за 10 дней
1990-е: второстепенные роли в веб-проектах
2000-е: Web 2.0, резкое усиление важности
2010-е: доминирование в самых различных областях
- Web apps
- Node.js, npm
- React Ecosystem
…Типичная история о силе дистрибуции и монополии

5

Популярность языков программирования*
Популярность на GitHub (кол-во проектов)
___________________________
* Исследование RedMonk.com,
Q1 2016
ПопулярностьнаStackOverflow(кол-вотэгов)

6

«Мобильные» пользователи преобладают ещё с 2014
● декабрь 2014: 51% трафика в Рунете — мобильные устройства
● май 2015: поиском Google.com пользуются больше с мобильных, чем с десктоп

7

#noBackend
a.k.a. Serverless
«Толстые» клиенты в вебе
Множество фреймворков
React Ecosystem
Основной фокус разработки продукта — FRONTEND
backend — просто должен работать
(безопасный, надёжный, производительный)
iOS, Android
Mobile First

8

no, BACKEND!
Если у вас «зоопарк»
(web, mobile apps, browser extensions, desktop apps, smartTV, IoT, etc),
то единственный путь жить и развиваться —
простой/надёжный/безопасный BACKEND с API
(например, REST API или новомодный GraphQL)

9

Часть 2
Как выжить

10

“true noBackend” – используем облака
Parse.com:
2013: Facebook покупает
2016: Facebook закрывает, R.I.P.
Кладбище mBaaS (Mobile Backend as a Service)
StackMob.com:
2013: PayPal покупает
2014: PayPal закрывает, R.I.P.
…полные аналоги Parse использовать теперь как-то «стрёмно»*
— остаётся использовать AWS (с их Cognito, Lambda), Google Cloud
___________
* но если очень хочется, есть много всякой всячины:
https://github.com/anaibol/awesome-serverless

11

…или …а давайте всё же сами!
…например, PostgreSQL
…например, PostgREST (http://postgrest.com)

12

— путь настоящего джедая: сможем не только выжить,
но и использовать силу!
+

13

PostgREST — API для вашей БД
http://postgrest.com
Написан на Haskell
MIT license
Активно развивается
чат: https://gitter.im/begriffs/postgrest
CREATE VIEW v1.person
AS SELECT * FROM public.person; → /person
CREATE FUNCTION v1.myfunc(...) … → /rpc/myfunc
LANGUAGE ...;
(функции на языках: SQL, plpgsql, plpython, plr, plv8 и т.д.!)
GET → SELECT
POST → INSERT
PATCH → UPDATE
DELETE → DELETE
Только POST

14

Урок 1: качество
Обязательно, обязательно автоматизируем тестирование API
- дома (Jenkins, TeamCity, etc)
- или в облаках (Circle CI, Travis CI, etc)
Тестируем:
- не только «хорошее», но и «плохое»
- быстродействие

15

Не надо так

16

Проверка работы REST API
Как работать с REST API:
- Старый добрый Firefox умеет «Edit and Resend» (разовые проверки)
- cURL
- HTTPie (http://httpie.org)
- Postman (пачка тестов, environments — отгружаем в файлы)
- newman — для консольного запуска пачки Postman-тестов

17

Урок 2: безопасность. Обязательно тестируем!
DB level: используем has_***_privilegeв тестах sqitch, pg_tap или аналогах
SELECT 1 / (not has_table_privilege)::int4
FROM has_table_privilege('anonymous', 'v1.post', 'select');
API level: пишем тесты для «плохих»
случаев и проверяем:
- 401 Unauthorized
- 403 Forbidden
- 400 Bad Request
и т.п.
Деление на 0, если есть привилегия!

18

Урок 2-а: анонимные запросы и безопасность
«а» — анонимы
Изучаем и работаем с JWT (см., например, http://jwt.io)
Урезанная DB role для анонимных доступов
(--anonymous у PostgREST)
Этой роли — никаких прав, кроме 2-3 методов в схеме v1
(можно с SECURITY DEFINER),
например: register, login, password_reset
На другие методы прав у аноним-роли быть не должно!
(тестируем API-вызовы)

19

Урок 2-b: права на столбцы
1) Совсем не светим секретноe — не включаем в выборку представления:
CREATE VIEW v1.post AS
SELECT id, title, body, moderated -- Никаких email, password и т.п.
FROM public.post;
2) Управляем доступом с помощью прав на столбцы:
GRANT SELECT,DELETE ON v1.post TO apiuser;
GRANT INSERT,UPDATE (title, body) ON v1.post TO apiuser; -- moderated -
R/O

20

Урок 2-с: запрет доступа к «чужим» строкам
Нельзя позволять юзеру менять чужие данные => нужно проверять `user_id`
PostgreSQL до 9.4 включительно:
используем триггеры и current_setting('postgrest.claims.XXXXX')
PostgreSQL 9.5+: используем Row-Level Security
…и опять не забываем тестировать

21

Урок 3-a: производительность. CPU vs network
Типичный пример из social media: выбор самых свежих материалов из
коллекций, на которые подписан юзер. Главное — round-trip time (RTT)!
Таблицы: person, post, collection, person2collection
Вариант 1:
select …
from post p … join person2collection p2c ..
where p2c.collection_id in (...list…)
And p.id < :prev_id
order by p.id desc limit :per_page;
select … from collection where id in (...);
select … from person … where id in (...);
– 3 API-вызова, RTT*3
Вариант 2:
select
p.*
row_to_json(c.*),
row_to_json(p.*)
from post p
join person2collection p2c ..
join collection c ..
join person p ..
where p.id < :prev_id
order by p.id desc limit :per_page;
- 1 API-вызов, RTT*1, ура!

22

Урок 3-b: «продвинутый» SQL
10 млн юзеров, 100 млн постов, 1 млн коллекций => оба варианта ~1-10 sec
Можно ли быстре?!
Да. Изучаем джедайские техники:
Максим Богук, pgDay’14 «Неклассические приёмы оптимизации запросов»
http://pgday.ru/files/pgmaster14/max.boguk.query.optimization.pdf
Придётся освоить и применить в комлексе:
● Recursive CTE (WITH RECURSIVE …)
● работа с массивами
● свёртка строк
● Window functions
● generate_series, generate_subscripts
● Loose indexscan https://wiki.postgresql.org/wiki/Loose_indexscan

23

~ 1-10ms !!!

24

Урок 3-c: масштабируемость. Три уровня
Уровень 1: много экземпляров PostgREST
Уровень 2: часть GET-запросов → readonly PostgREST, подключённые к Postgres-реплике(ам)
(направляем с помощью nginx). Принудительный мастер — с помощью custom http header.
Уровень 3: как масштабировать мастер? Сходу — пока никак.
Варианты:
3.1) микросервисная архитектура
(например, spilo и patroni от Zalando
– см. Highload++2015 http://www.highload.ru/2015/abstracts/1846.html)
3.2) CitusDB?
Пока нет, мешают WITH в PostgREST (возможно, уберут)
3.3) Можно просто подождать (см. планы Postgres по кластеру)
3.4) А надо ли вам? Миллион TPS на 1 мастере — может быть выгоднее «webscale» с
неэффективными узлами, как 1 трактор может быть выгоднее 100 людей с лопатами!

25

Урок 4: что не стоит делать внутри
Не стоит делать внутри:
если непредсказумое время работы,
если есть работа с внешними ресурсами (http-запросы, API)
Примеры:
● Отправка почты, СМС
● Сохранение картинок в хранилище
● Вызовы внешних API

26

Урок 5: асинхронная работа
Обрабатываем асинхронно (демоны на python/ruby/nodejs/etc),
отправляя сообщения с помощью:
● LISTEN/NOTIFY (пример есть в документации по PostgREST http://postgrest.
com/examples/users/#password-reset)
● mbus (Р. Друзягин, И. Фролков, доклад PgDay’15 http://pgday.
ru/files/papers/23/pgday.2015.messaging.frolkov.druzyagin.pdf)
● Сообщения в AMPQ (например, PostgreSQL LISTEN Exchange: https://github.
com/aweber/pgsql-listen-exchange)

27

Памятка #noBackend-разработчика
1. Ни шагу без CI (прежде всего, негативные проверки API)
2. Проверить (и проверять тестами!) все двери:
a. что может аноним?
b. защищены (чтение, модификация) ли важные поля?
c. можно ли поменять «чужие» записи? а заставить хозяина поменять свои
собственные?
3. Проверить эффективность и быстродействие:
a. можно ли сделать ещё меньше HTTP-запросов?
b. насколько они эффективны сложные запросы и есть ли пути оптимизации?
c. легко ли «положить» backend неожиданными фильтрами, сортировками,
соединениями?
d. легко ли «положить» его большим количеством запросов?
e. какие пути смасштабироваться есть в арсенале?
4. Дополнительно:
a. как делаются асинхронные задачи (скорость, надёжность, блокировки)?
b. есть ли зависимость от внешних ресурсов? Если да, сможем ли сделать
асинхронную работу?

28

The End
Спасибо!
https://twitter.com/postgresmen
http://PostgreSQLRussia.org
http://Postgres.CHAT

More Related Content

#noBackend, или Как выжить в эпоху толстеющих клиентов

  • 1. #noBackend, или Как выжить в эпоху толстеющих клиентов Николай Самохвалов nikolay@samokhvalov.com twitter: @postgresmen
  • 3. 4 очень популярных языка для интернет-проектов Год рождения — 1995
  • 4. «Гадкий утёнок» JavaScript 1995: 1-я версия — за 10 дней 1990-е: второстепенные роли в веб-проектах 2000-е: Web 2.0, резкое усиление важности 2010-е: доминирование в самых различных областях - Web apps - Node.js, npm - React Ecosystem …Типичная история о силе дистрибуции и монополии
  • 5. Популярность языков программирования* Популярность на GitHub (кол-во проектов) ___________________________ * Исследование RedMonk.com, Q1 2016 ПопулярностьнаStackOverflow(кол-вотэгов)
  • 6. «Мобильные» пользователи преобладают ещё с 2014 ● декабрь 2014: 51% трафика в Рунете — мобильные устройства ● май 2015: поиском Google.com пользуются больше с мобильных, чем с десктоп
  • 7. #noBackend a.k.a. Serverless «Толстые» клиенты в вебе Множество фреймворков React Ecosystem Основной фокус разработки продукта — FRONTEND backend — просто должен работать (безопасный, надёжный, производительный) iOS, Android Mobile First
  • 8. no, BACKEND! Если у вас «зоопарк» (web, mobile apps, browser extensions, desktop apps, smartTV, IoT, etc), то единственный путь жить и развиваться — простой/надёжный/безопасный BACKEND с API (например, REST API или новомодный GraphQL)
  • 10. “true noBackend” – используем облака Parse.com: 2013: Facebook покупает 2016: Facebook закрывает, R.I.P. Кладбище mBaaS (Mobile Backend as a Service) StackMob.com: 2013: PayPal покупает 2014: PayPal закрывает, R.I.P. …полные аналоги Parse использовать теперь как-то «стрёмно»* — остаётся использовать AWS (с их Cognito, Lambda), Google Cloud ___________ * но если очень хочется, есть много всякой всячины: https://github.com/anaibol/awesome-serverless
  • 11. …или …а давайте всё же сами! …например, PostgreSQL …например, PostgREST (http://postgrest.com)
  • 12. — путь настоящего джедая: сможем не только выжить, но и использовать силу! +
  • 13. PostgREST — API для вашей БД http://postgrest.com Написан на Haskell MIT license Активно развивается чат: https://gitter.im/begriffs/postgrest CREATE VIEW v1.person AS SELECT * FROM public.person; → /person CREATE FUNCTION v1.myfunc(...) … → /rpc/myfunc LANGUAGE ...; (функции на языках: SQL, plpgsql, plpython, plr, plv8 и т.д.!) GET → SELECT POST → INSERT PATCH → UPDATE DELETE → DELETE Только POST
  • 14. Урок 1: качество Обязательно, обязательно автоматизируем тестирование API - дома (Jenkins, TeamCity, etc) - или в облаках (Circle CI, Travis CI, etc) Тестируем: - не только «хорошее», но и «плохое» - быстродействие
  • 16. Проверка работы REST API Как работать с REST API: - Старый добрый Firefox умеет «Edit and Resend» (разовые проверки) - cURL - HTTPie (http://httpie.org) - Postman (пачка тестов, environments — отгружаем в файлы) - newman — для консольного запуска пачки Postman-тестов
  • 17. Урок 2: безопасность. Обязательно тестируем! DB level: используем has_***_privilegeв тестах sqitch, pg_tap или аналогах SELECT 1 / (not has_table_privilege)::int4 FROM has_table_privilege('anonymous', 'v1.post', 'select'); API level: пишем тесты для «плохих» случаев и проверяем: - 401 Unauthorized - 403 Forbidden - 400 Bad Request и т.п. Деление на 0, если есть привилегия!
  • 18. Урок 2-а: анонимные запросы и безопасность «а» — анонимы Изучаем и работаем с JWT (см., например, http://jwt.io) Урезанная DB role для анонимных доступов (--anonymous у PostgREST) Этой роли — никаких прав, кроме 2-3 методов в схеме v1 (можно с SECURITY DEFINER), например: register, login, password_reset На другие методы прав у аноним-роли быть не должно! (тестируем API-вызовы)
  • 19. Урок 2-b: права на столбцы 1) Совсем не светим секретноe — не включаем в выборку представления: CREATE VIEW v1.post AS SELECT id, title, body, moderated -- Никаких email, password и т.п. FROM public.post; 2) Управляем доступом с помощью прав на столбцы: GRANT SELECT,DELETE ON v1.post TO apiuser; GRANT INSERT,UPDATE (title, body) ON v1.post TO apiuser; -- moderated - R/O
  • 20. Урок 2-с: запрет доступа к «чужим» строкам Нельзя позволять юзеру менять чужие данные => нужно проверять `user_id` PostgreSQL до 9.4 включительно: используем триггеры и current_setting('postgrest.claims.XXXXX') PostgreSQL 9.5+: используем Row-Level Security …и опять не забываем тестировать
  • 21. Урок 3-a: производительность. CPU vs network Типичный пример из social media: выбор самых свежих материалов из коллекций, на которые подписан юзер. Главное — round-trip time (RTT)! Таблицы: person, post, collection, person2collection Вариант 1: select … from post p … join person2collection p2c .. where p2c.collection_id in (...list…) And p.id < :prev_id order by p.id desc limit :per_page; select … from collection where id in (...); select … from person … where id in (...); – 3 API-вызова, RTT*3 Вариант 2: select p.* row_to_json(c.*), row_to_json(p.*) from post p join person2collection p2c .. join collection c .. join person p .. where p.id < :prev_id order by p.id desc limit :per_page; - 1 API-вызов, RTT*1, ура!
  • 22. Урок 3-b: «продвинутый» SQL 10 млн юзеров, 100 млн постов, 1 млн коллекций => оба варианта ~1-10 sec Можно ли быстре?! Да. Изучаем джедайские техники: Максим Богук, pgDay’14 «Неклассические приёмы оптимизации запросов» http://pgday.ru/files/pgmaster14/max.boguk.query.optimization.pdf Придётся освоить и применить в комлексе: ● Recursive CTE (WITH RECURSIVE …) ● работа с массивами ● свёртка строк ● Window functions ● generate_series, generate_subscripts ● Loose indexscan https://wiki.postgresql.org/wiki/Loose_indexscan
  • 24. Урок 3-c: масштабируемость. Три уровня Уровень 1: много экземпляров PostgREST Уровень 2: часть GET-запросов → readonly PostgREST, подключённые к Postgres-реплике(ам) (направляем с помощью nginx). Принудительный мастер — с помощью custom http header. Уровень 3: как масштабировать мастер? Сходу — пока никак. Варианты: 3.1) микросервисная архитектура (например, spilo и patroni от Zalando – см. Highload++2015 http://www.highload.ru/2015/abstracts/1846.html) 3.2) CitusDB? Пока нет, мешают WITH в PostgREST (возможно, уберут) 3.3) Можно просто подождать (см. планы Postgres по кластеру) 3.4) А надо ли вам? Миллион TPS на 1 мастере — может быть выгоднее «webscale» с неэффективными узлами, как 1 трактор может быть выгоднее 100 людей с лопатами!
  • 25. Урок 4: что не стоит делать внутри Не стоит делать внутри: если непредсказумое время работы, если есть работа с внешними ресурсами (http-запросы, API) Примеры: ● Отправка почты, СМС ● Сохранение картинок в хранилище ● Вызовы внешних API
  • 26. Урок 5: асинхронная работа Обрабатываем асинхронно (демоны на python/ruby/nodejs/etc), отправляя сообщения с помощью: ● LISTEN/NOTIFY (пример есть в документации по PostgREST http://postgrest. com/examples/users/#password-reset) ● mbus (Р. Друзягин, И. Фролков, доклад PgDay’15 http://pgday. ru/files/papers/23/pgday.2015.messaging.frolkov.druzyagin.pdf) ● Сообщения в AMPQ (например, PostgreSQL LISTEN Exchange: https://github. com/aweber/pgsql-listen-exchange)
  • 27. Памятка #noBackend-разработчика 1. Ни шагу без CI (прежде всего, негативные проверки API) 2. Проверить (и проверять тестами!) все двери: a. что может аноним? b. защищены (чтение, модификация) ли важные поля? c. можно ли поменять «чужие» записи? а заставить хозяина поменять свои собственные? 3. Проверить эффективность и быстродействие: a. можно ли сделать ещё меньше HTTP-запросов? b. насколько они эффективны сложные запросы и есть ли пути оптимизации? c. легко ли «положить» backend неожиданными фильтрами, сортировками, соединениями? d. легко ли «положить» его большим количеством запросов? e. какие пути смасштабироваться есть в арсенале? 4. Дополнительно: a. как делаются асинхронные задачи (скорость, надёжность, блокировки)? b. есть ли зависимость от внешних ресурсов? Если да, сможем ли сделать асинхронную работу?