Всем привет!
Современная разработка - это микросервисы, микросервисы - это много внешних взаимодействий, а внешние взаимодействия - это API.
Каким должно быть хорошее API?
1) API должно быть версионировано. Все течет, все меняется: бизнес-требования, новые типы потребителей. О версионировании нужно подумать заранее.
2) Сервер и клиенты поддерживают работу с несколькими версиями API. Это позволит избежать синхронных внедрений двух и более микросервисов. Синхронное внедрение - это сложно и повышает вероятность нарушить все наши "девятки" (SLA)
3) API описано схемой. Король горы для REST запросов - OpenAPI. Отмечу, что в отличие от JSON Schema или XSD OpenAPI описывает не модель данных, а web сервис целиком: поддерживаемые HTTP методы - GET, POST,..., коды ответов HTTP, параметры запроса, заголовки.
4) CDC тестирование - https://martinfowler.com/articles/consumerDrivenContracts.html#Consumer-drivenContracts
В чем суть: создается контракт - человеко и машиночитаемое описание тест-кейсов для API, на основании которых генерируются API тесты для поставщика и потребителя. Примеры реализаций:
Spring Cloud Contract https://docs.spring.io/spring-cloud-contract/docs/current/reference/html/getting-started.html#getting-started-three-second-tour
Pact https://docs.pact.io/5-minute-getting-started-guide
Надо отметить, что OpenAPI и CDS в ряде моментов дублируют информацию, об этой проблеме и возможном решении для Spring можно почитать тут: https://springframework.guru/defining-spring-cloud-contracts-in-open-api/
5) API должно предусматривать уникальный идентификатор запроса, обеспечивающий идемпотентность - возможность повторного вызова метода API, не приводящего к дублированию данных на сервере. В сети и на сервере случаются сбои, повтор вызова в этом случае - естественный выход из ситуации. При получении второго и последующего запросов сервер, определив по уникальному идентификатору, что он уже получал этот запрос, должен вернуть текущий статус операции
6) API должно содержать trace_id - уникальный идентификатор операции. trace_id генерируется на клиенте и копируется в каждый последующий запрос по всем микросервисам. Потом с помощью таких инструментов, как Jaeger дерево запросов визуализируется, что упрощает отлавливание ошибок
7) в API не должно быть ничего лишнего. Добавляем то, что нужно клиенту, если появляется новые требования - версионируем API. Иначе получим аналог "божественного объекта" - https://ru.wikipedia.org/wiki/Божественный_объект
#API #arch #tracing
Современная разработка - это микросервисы, микросервисы - это много внешних взаимодействий, а внешние взаимодействия - это API.
Каким должно быть хорошее API?
1) API должно быть версионировано. Все течет, все меняется: бизнес-требования, новые типы потребителей. О версионировании нужно подумать заранее.
2) Сервер и клиенты поддерживают работу с несколькими версиями API. Это позволит избежать синхронных внедрений двух и более микросервисов. Синхронное внедрение - это сложно и повышает вероятность нарушить все наши "девятки" (SLA)
3) API описано схемой. Король горы для REST запросов - OpenAPI. Отмечу, что в отличие от JSON Schema или XSD OpenAPI описывает не модель данных, а web сервис целиком: поддерживаемые HTTP методы - GET, POST,..., коды ответов HTTP, параметры запроса, заголовки.
4) CDC тестирование - https://martinfowler.com/articles/consumerDrivenContracts.html#Consumer-drivenContracts
В чем суть: создается контракт - человеко и машиночитаемое описание тест-кейсов для API, на основании которых генерируются API тесты для поставщика и потребителя. Примеры реализаций:
Spring Cloud Contract https://docs.spring.io/spring-cloud-contract/docs/current/reference/html/getting-started.html#getting-started-three-second-tour
Pact https://docs.pact.io/5-minute-getting-started-guide
Надо отметить, что OpenAPI и CDS в ряде моментов дублируют информацию, об этой проблеме и возможном решении для Spring можно почитать тут: https://springframework.guru/defining-spring-cloud-contracts-in-open-api/
5) API должно предусматривать уникальный идентификатор запроса, обеспечивающий идемпотентность - возможность повторного вызова метода API, не приводящего к дублированию данных на сервере. В сети и на сервере случаются сбои, повтор вызова в этом случае - естественный выход из ситуации. При получении второго и последующего запросов сервер, определив по уникальному идентификатору, что он уже получал этот запрос, должен вернуть текущий статус операции
6) API должно содержать trace_id - уникальный идентификатор операции. trace_id генерируется на клиенте и копируется в каждый последующий запрос по всем микросервисам. Потом с помощью таких инструментов, как Jaeger дерево запросов визуализируется, что упрощает отлавливание ошибок
7) в API не должно быть ничего лишнего. Добавляем то, что нужно клиенту, если появляется новые требования - версионируем API. Иначе получим аналог "божественного объекта" - https://ru.wikipedia.org/wiki/Божественный_объект
#API #arch #tracing
martinfowler.com
Consumer-Driven Contracts: A Service Evolution
Pattern
Pattern
Consumers should drive the definition of service contracts, while limiting to their individual needs. Suppliers should then validate against the union of their consumers' contracts.
Всем привет!
В разработке сейчас много хайповых понятий, те же микросервисы, Service Mesh, GitOps, Serverless. Обо всем этом как-нибудь напишу, а сегодня пару мыслей про Cloud Native.
Если подумать, то для того, чтобы сделать native приложение для облака, нужно не так уж много.
1) k8s должен как-то понимать, что приложение поднялось и может принимать траффик. Для этого облачный сервис должен реализовать probes, они же healthchecks.
https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
Вообще их три, но в случае простейшего приложения хватит одной - liveness. Остальные две нужны если приложение долго стартует - startup или может быть недоступно в процессе работы - readyness.
2) облачное приложение не должно долго стартовать. Причина: k8s при добавлении новых нод или подов, или изменения их настроек Anti-affinity (возможности совместной работы на одной ноде) в любой момент может погасить под и поднять его на другом сервере. Да, можно указать startup probe чтобы траффик не шел на долго стартующее приложение. Можно указать maxUnavailable https://kubernetes.io/docs/tasks/run-application/configure-pdb/ для того, чтобы k8s оставлял запас подов при изменении их численности. Но все это обходные пути. Если вспомнить про Spring Boot, то я бы сказал что ему есть куда расти в плане оптимизации, не зря сейчас растет популярность его альтернатив, стартующих существенно быстрее: Quarkus, Micronaut, Helidon и использования native images.
3) cloud native приложение не должно зависеть от локального состояния - кэширования данных локально. Все критичные для работы данные должны хранится или в storage, или на клиенте. Причина все та же - k8s в любой момент может поднять под на другом сервере, локальный кэш при этом теряется.
4) для cloud native приложения крайне рекомендуется отбрасывать метрики и поддерживать distributed tracing - https://opentelemetry.io/docs/concepts/what-is-opentelemetry/. Причина: перенос в облако упрощает разработку, как правило идет рука об руку с микросервисами, следовательно, сервисов становится существенно больше, следовательно, должны быть инструменты для отслеживания их состояния и более точного понимания, где проблема.
Что на мой взгляд не относится к критичным требованиям для Cloud native приложений.
1) поддержка Docker. В Docker можно засунуть практически любое приложение, есть куча официальных образов. Даже IBM Websphere и WildFly, хотя использование их в облаке выглядит странным) Вижу проблему только с Windows native приложениями, но их остается не так уже много
2) поддержка внутри приложения cloud \ fault tolerance функций: circuit breakers, retries, timeouts, service discovery. Например, этот функционал реализуется в Spring Cloud библиотеке. Почему так? Потому что в связке k8s + service mesh все эти функции можно реализовать на уровне облака. Не хочу сказать, что Spring Cloud и его аналоги не нужны, но точно не обязательны для облака.
3) использование REST API. С одной стороны для HTTP траффика k8s + service mesh дает больше возможностей по маршрутизации, но с другой стороны tcp трафик тоже маршрутизируется.
#cloud_native #microservices #spring_boot #tracing
В разработке сейчас много хайповых понятий, те же микросервисы, Service Mesh, GitOps, Serverless. Обо всем этом как-нибудь напишу, а сегодня пару мыслей про Cloud Native.
Если подумать, то для того, чтобы сделать native приложение для облака, нужно не так уж много.
1) k8s должен как-то понимать, что приложение поднялось и может принимать траффик. Для этого облачный сервис должен реализовать probes, они же healthchecks.
https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
Вообще их три, но в случае простейшего приложения хватит одной - liveness. Остальные две нужны если приложение долго стартует - startup или может быть недоступно в процессе работы - readyness.
2) облачное приложение не должно долго стартовать. Причина: k8s при добавлении новых нод или подов, или изменения их настроек Anti-affinity (возможности совместной работы на одной ноде) в любой момент может погасить под и поднять его на другом сервере. Да, можно указать startup probe чтобы траффик не шел на долго стартующее приложение. Можно указать maxUnavailable https://kubernetes.io/docs/tasks/run-application/configure-pdb/ для того, чтобы k8s оставлял запас подов при изменении их численности. Но все это обходные пути. Если вспомнить про Spring Boot, то я бы сказал что ему есть куда расти в плане оптимизации, не зря сейчас растет популярность его альтернатив, стартующих существенно быстрее: Quarkus, Micronaut, Helidon и использования native images.
3) cloud native приложение не должно зависеть от локального состояния - кэширования данных локально. Все критичные для работы данные должны хранится или в storage, или на клиенте. Причина все та же - k8s в любой момент может поднять под на другом сервере, локальный кэш при этом теряется.
4) для cloud native приложения крайне рекомендуется отбрасывать метрики и поддерживать distributed tracing - https://opentelemetry.io/docs/concepts/what-is-opentelemetry/. Причина: перенос в облако упрощает разработку, как правило идет рука об руку с микросервисами, следовательно, сервисов становится существенно больше, следовательно, должны быть инструменты для отслеживания их состояния и более точного понимания, где проблема.
Что на мой взгляд не относится к критичным требованиям для Cloud native приложений.
1) поддержка Docker. В Docker можно засунуть практически любое приложение, есть куча официальных образов. Даже IBM Websphere и WildFly, хотя использование их в облаке выглядит странным) Вижу проблему только с Windows native приложениями, но их остается не так уже много
2) поддержка внутри приложения cloud \ fault tolerance функций: circuit breakers, retries, timeouts, service discovery. Например, этот функционал реализуется в Spring Cloud библиотеке. Почему так? Потому что в связке k8s + service mesh все эти функции можно реализовать на уровне облака. Не хочу сказать, что Spring Cloud и его аналоги не нужны, но точно не обязательны для облака.
3) использование REST API. С одной стороны для HTTP траффика k8s + service mesh дает больше возможностей по маршрутизации, но с другой стороны tcp трафик тоже маршрутизируется.
#cloud_native #microservices #spring_boot #tracing
Kubernetes
Configure Liveness, Readiness and Startup Probes
This page shows how to configure liveness, readiness and startup probes for containers.
For more information about probes, see Liveness, Readiness and Startup Probes
The kubelet uses liveness probes to know when to restart a container. For example, liveness…
For more information about probes, see Liveness, Readiness and Startup Probes
The kubelet uses liveness probes to know when to restart a container. For example, liveness…
Всем привет!
Небольшая заметка, пример как рождаются унифицирующие стандарты в разработке.
Этапы развития распределенной трассировки - очень полезной технологии для отслеживания пути запроса между микросервисами, о которой я уже несколько раз писал:
1) появляются разные реализации трассировки, самые известные - Jaeger и Zipkin
2) в 2016 году создается независимый от вендора стандарт для клиентских библиотек создания трейсов и отправки данных трейсинга во внешнее хранилище - OpenTracing. В качестве хранилищ поддерживаются те же Jaeger и Zipkin. Под эгидой Google в 2017 году параллельно создается еще один, менее известный - OpenCensus
3) OpenTracing и OpenCensus объединяются в 2019 году в OpenTelemetry. https://opentelemetry.io/docs/concepts/what-is-opentelemetry/#hello-opentelemetry
Появляется также промежуточный слой collectors для маршрутизации и балансировки данных трассировки https://opentelemetry.io/docs/concepts/data-collection/
Причем под телеметрией понимаются не только трассировка, но и сбор метрик.
Естественно есть библиотека для Java.
Вроде бы конец истории...
4) Ребята из Micrometer, создавшие ранее фасад для отправки метрик в JVM приложениях, также решили "прибрать к рукам" :) и tracing, в 2022 году появляется Micrometer Tracing. Spring Boot 3, недавно вышедший, оперативно объявляет о его поддержке https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes. Судя по декларированной цели https://micrometer.io/docs/tracing#_purpose - не все еще используют OpenTelemetry, поэтому нужен новый фасад.
Что смущает. С одной стороны Micrometer Tracing вводит новый уровень абстракции: разделяет процессы создания трейса (tracer) и отправки его в хранилища (reporter) и, соответственно, поддерживает разные tracers и reporters. Это стандартный путь развития любой технологии.
С другой стороны он дублирует функционал OpenTelemetry, и новый уровень абстракции выглядит излишним.
Как говорится, будем посмотреть, что в итоге приживется. Spring Boot - конечно весомый козырь
P.S. Рекомендую ознакомится с терминологией распределенной трассировки - https://micrometer.io/docs/tracing#_glossary
И пара примеров внедрения:
https://habr.com/ru/company/ru_mts/blog/537892/
https://habr.com/ru/company/hh/blog/686414/
#tracing
Небольшая заметка, пример как рождаются унифицирующие стандарты в разработке.
Этапы развития распределенной трассировки - очень полезной технологии для отслеживания пути запроса между микросервисами, о которой я уже несколько раз писал:
1) появляются разные реализации трассировки, самые известные - Jaeger и Zipkin
2) в 2016 году создается независимый от вендора стандарт для клиентских библиотек создания трейсов и отправки данных трейсинга во внешнее хранилище - OpenTracing. В качестве хранилищ поддерживаются те же Jaeger и Zipkin. Под эгидой Google в 2017 году параллельно создается еще один, менее известный - OpenCensus
3) OpenTracing и OpenCensus объединяются в 2019 году в OpenTelemetry. https://opentelemetry.io/docs/concepts/what-is-opentelemetry/#hello-opentelemetry
Появляется также промежуточный слой collectors для маршрутизации и балансировки данных трассировки https://opentelemetry.io/docs/concepts/data-collection/
Причем под телеметрией понимаются не только трассировка, но и сбор метрик.
Естественно есть библиотека для Java.
Вроде бы конец истории...
4) Ребята из Micrometer, создавшие ранее фасад для отправки метрик в JVM приложениях, также решили "прибрать к рукам" :) и tracing, в 2022 году появляется Micrometer Tracing. Spring Boot 3, недавно вышедший, оперативно объявляет о его поддержке https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes. Судя по декларированной цели https://micrometer.io/docs/tracing#_purpose - не все еще используют OpenTelemetry, поэтому нужен новый фасад.
Что смущает. С одной стороны Micrometer Tracing вводит новый уровень абстракции: разделяет процессы создания трейса (tracer) и отправки его в хранилища (reporter) и, соответственно, поддерживает разные tracers и reporters. Это стандартный путь развития любой технологии.
С другой стороны он дублирует функционал OpenTelemetry, и новый уровень абстракции выглядит излишним.
Как говорится, будем посмотреть, что в итоге приживется. Spring Boot - конечно весомый козырь
P.S. Рекомендую ознакомится с терминологией распределенной трассировки - https://micrometer.io/docs/tracing#_glossary
И пара примеров внедрения:
https://habr.com/ru/company/ru_mts/blog/537892/
https://habr.com/ru/company/hh/blog/686414/
#tracing
OpenTelemetry
What is OpenTelemetry?
A short explanation of what OpenTelemetry is, and is not.
Ещё интересный доклад - про нетривиальное использование трейсинга (tracing).
Начнём с того, что далеко не у всех он настроен. Окей, настроили. Теперь нам проще разбирать проблемы на ПРОМ в микросервисной архитектуре.
Все?
Нет) А если взять трейсы за некий период, отсемплировать их уменьшив объём и сложить их в графовую БД? Получим реверс-инжиниринг архитектуры. Причём это будет не «мертвая» архитектура, по кем-то когда-то написанной аналитике, а настоящая. Да, не 100% точная, из-за мертвых интеграций и поломанного трейсинга, но все же. Что с ней можно сделать? Контролировать... архитектуру. Например:
- Общая схема вызовов
- Циклические ссылки
- Длина цепочек вызовов
- Лишние с точки зрения разделения на бизнес-домены связи
- Критичность сервисов - сервисы, которые чаще всего используются другими сервисами
- Однотипные вызовы, которые можно объединить в batch запрос
- Вызовы в цикле
- Анализ использования практики Graceful degradation
Сама идея - практически бесплатный для бизнес-команд инструмент анализа архитектуры - отлично IMHO.
P.S. для этих же целей в теории можно использовать данные из Service Mesh, только добавляется ещё один снижающий точность фактор - не все компоненты находятся в облаке (и не все компоненты в облаке используют Service Mesh)
P.P.S. Конечно идея идеально подходит для компаний а-ля Яндекс и Авито (собственно в Авито ее и внедрили) - там, где нет жёсткого контроля интеграций на уровне согласования аналитики. Но IMHO в любом случае можно использовать как контрольный механизм, ещё одну «сеть»
#arch #tracing
Начнём с того, что далеко не у всех он настроен. Окей, настроили. Теперь нам проще разбирать проблемы на ПРОМ в микросервисной архитектуре.
Все?
Нет) А если взять трейсы за некий период, отсемплировать их уменьшив объём и сложить их в графовую БД? Получим реверс-инжиниринг архитектуры. Причём это будет не «мертвая» архитектура, по кем-то когда-то написанной аналитике, а настоящая. Да, не 100% точная, из-за мертвых интеграций и поломанного трейсинга, но все же. Что с ней можно сделать? Контролировать... архитектуру. Например:
- Общая схема вызовов
- Циклические ссылки
- Длина цепочек вызовов
- Лишние с точки зрения разделения на бизнес-домены связи
- Критичность сервисов - сервисы, которые чаще всего используются другими сервисами
- Однотипные вызовы, которые можно объединить в batch запрос
- Вызовы в цикле
- Анализ использования практики Graceful degradation
Сама идея - практически бесплатный для бизнес-команд инструмент анализа архитектуры - отлично IMHO.
P.S. для этих же целей в теории можно использовать данные из Service Mesh, только добавляется ещё один снижающий точность фактор - не все компоненты находятся в облаке (и не все компоненты в облаке используют Service Mesh)
P.P.S. Конечно идея идеально подходит для компаний а-ля Яндекс и Авито (собственно в Авито ее и внедрили) - там, где нет жёсткого контроля интеграций на уровне согласования аналитики. Но IMHO в любом случае можно использовать как контрольный механизм, ещё одну «сеть»
#arch #tracing