Несколько дней назад я прочитал статью, написанную доктором Тургаем Челиком, старшим инженером OpsGenie (компания, занимающаяся Dev & Ops) (ссылка в конце статьи), в которой сообщалось, что изначально они использовали Nginx в качестве шлюза. для монолитных приложений, а позже После знакомства с микросервисной архитектурой постепенно стали внедряться и другие компоненты.
Мне нравится докапываться до сути работы, которую я делаю, или технологий, которые меня интересуют, поэтому, когда я читаю статью и обнаруживаю, что не вижу дизайнерских идей, которые хочу увидеть, я иду собирать информацию. Я борюсь со Spring Cloud, поэтому решил написать статью, чтобы попытаться объяснить, почему существует такая разница в производительности с точки зрения дизайна.
Введение в технологию
В статье сравниваются Nginx, ZUUL, Spring Cloud, Linkerd и другие технологии (на самом деле Envoy и UnderTow также являются необязательными API-шлюзами, которые в этой статье не рассматриваются), далее я представлю их отдельно. API-шлюз.
Шлюз API
Причиной появления шлюза API является появление микросервисной архитектуры.Разные микросервисы обычно имеют разные сетевые адреса, и внешним клиентам может потребоваться вызывать интерфейсы нескольких сервисов для выполнения бизнес-требования.Если клиент напрямую общается с каждым микросервисом Сервисная связь, будут следующие проблемы:
- Клиент будет запрашивать разные микросервисы несколько раз, что увеличивает сложность клиента.
- Существуют междоменные запросы, которые относительно сложно обрабатывать в определенных сценариях.
- Аутентификация сложна, и каждая служба требует независимой аутентификации.
- Сложность рефакторинга, может потребоваться повторное разбиение микросервисов по мере итерации проекта. Например, несколько услуг могут быть объединены в одну или одна услуга может быть разделена на несколько. Если клиент напрямую общается с микросервисом, рефакторинг будет сложно реализовать.
- Некоторые микросервисы могут использовать протоколы, несовместимые с брандмауэром/браузером, и прямой доступ будет затруднен.
Эти проблемы можно решить с помощью API Gateway. Шлюз API — это промежуточный уровень между клиентом и сервером, и все внешние запросы сначала проходят через уровень шлюза API. То есть реализация API учитывает больше бизнес-логики, в то время как безопасность, производительность и мониторинг могут выполняться шлюзом API, что не только повышает гибкость бизнеса, но и обеспечивает безопасность.Типичная схема архитектуры показана на фигура:
Преимущества использования API Gateway заключаются в следующем:
- Легко контролировать. Данные мониторинга можно собирать на шлюзе и передавать во внешние системы для анализа.
- Легко пройти аутентификацию. Аутентификацию можно выполнить на шлюзе перед пересылкой запроса во внутренние микросервисы без необходимости аутентификации в каждом микросервисе.
- Сокращается количество взаимодействий между клиентами и отдельными микросервисами.
Службы Nginx
Nginx состоит из ядра и модулей.Дизайн ядра очень маленький и лаконичный, а выполняемая работа тоже очень простая.Он только сопоставляется с URL-адресом клиентского запроса, ища конфигурационный файл, который используется для запуска различных модулей для выполнения соответствующей работы.
На следующем рисунке показан общий поток обработки HTTP-запросов:
Модули Nginx компилируются непосредственно в Nginx, поэтому они являются статическими методами компиляции. После запуска Nginx модули Nginx загружаются автоматически, в отличие от Apache, который сначала компилирует модуль в so-файл, а затем указывает, загружать или нет в файле конфигурации. При разборе конфигурационного файла каждый модуль Nginx может обрабатывать определенный запрос, но один и тот же запрос на обработку может быть выполнен только одним модулем.
После запуска Nginx будет главный процесс и несколько рабочих процессов.Главный процесс и рабочий процесс взаимодействуют посредством межпроцессного взаимодействия, как показано на рисунке. Точка блокировки рабочего процесса Worker находится в вызовах функций мультиплексирования ввода-вывода, таких как select(), epoll_wait() и т. д., ожидающих возникновения событий чтения/записи данных. Nginx использует асинхронный и неблокирующий способ обработки запросов, то есть Nginx может обрабатывать тысячи запросов одновременно. Количество запросов, которые рабочий процесс может обрабатывать одновременно, ограничено только объемом памяти, а с точки зрения архитектурного дизайна, различные рабочие процессы Блокировок синхронизации при обработке одновременных запросов между процессами практически нет, рабочие процессы обычно не засыпают, поэтому при количестве процессов на Nginx, равном количеству ядер ЦП (желательно, чтобы каждый рабочий процесс был привязан к конкретное процессорное ядро), затраты на переключение между процессами минимальны.
Зуул из Netflix
Zuul — это компонент шлюза микросервисов с открытым исходным кодом для Netflix, который можно использовать с Eureka, Ribbon, Hystrix и другими компонентами. Ядром Zuul является серия фильтров, которые могут выполнять следующие функции:
- Аутентификация и безопасность: определите требования аутентификации для каждого ресурса и отклоните те, которые не соответствуют требованиям.
- Обзор и мониторинг: отслеживайте значимые данные и статистику с периферийными местоположениями для точного представления о производстве.
- Динамическая маршрутизация. Динамическая маршрутизация запросов к различным серверным кластерам.
- Стресс-тест: постепенно увеличивайте трафик к кластеру, чтобы увидеть производительность.
- Распределение нагрузки. Выделите соответствующую емкость для каждого типа нагрузки и отклоните запросы, превышающие лимит.
- Статическая обработка ответов. Частичные ответы создаются непосредственно на периферии, что позволяет избежать их пересылки во внутренние кластеры.
- Эластичность для нескольких регионов: маршрутизация запросов между регионами AWS с целью разнообразить использование ELB (Elastic Load Balancing, Elastic Load Balancing) и приблизить границы системы к пользователям системы.
Эти упомянутые выше функции недоступны в Nigix, потому что Netflix создал Zuul для решения многих проблем в облаке (особенно для того, чтобы помочь AWS решить эти функции в межрегиональных ситуациях), а не просто для того, чтобы сделать что-то вроде обратного прокси-сервера Nigix, конечно, мы можно использовать только функцию обратного прокси, которая здесь не описана.
Zuul1 построен на основе Servlet Framework. Как показано на рисунке, он использует метод блокировки и многопоточности, то есть один поток обрабатывает запрос на соединение. Этот метод приведет к увеличению числа выживших соединений и потоку. происходит увеличение.
Огромное отличие Zuul2 заключается в том, что он работает на асинхронном и неблокирующем фреймворке, один поток на ядро ЦП, обрабатывает все запросы и ответы, а жизненный цикл запросов и ответов обрабатывается посредством событий и обратных вызовов, что сокращает количество потоков и поэтому меньше накладных расходов. А поскольку данные хранятся в том же ЦП, кеш на уровне ЦП можно использовать повторно, а упомянутые выше проблемы с задержкой и повторным штормом также значительно сокращаются за счет сохранения количества соединений и событий в очереди (меньше, чем переключение потоков). .Уровней много, а натуральный расход небольшой). Это изменение определенно значительно улучшит производительность, и мы увидим результаты в более позднем сеансе тестирования.
Сегодня мы говорим о производительности шлюза API, что также включает в себя высокую доступность.Мы кратко представим функции высокой доступности Zuul.Высокая доступность очень важна, потому что трафик от внешних запросов к внутренним микросервисам будет проходить через Zuul, поэтому в производственная среда В целом, высокодоступный Zuul должен быть развернут, чтобы избежать единой точки отказа. Как правило, у нас есть два сценария развертывания:
1. Клиент Zuul регистрируется на сервере Eureka.
Эта ситуация относительно проста: вам нужно всего лишь зарегистрировать несколько узлов Zuul на сервере Eureka, чтобы добиться высокой доступности Zuul. По сути, высокая доступность в данном случае ничем не отличается от высокой доступности других сервисов. Давайте посмотрим на картинку ниже: когда клиент Zuul зарегистрирован на сервере Eureka, ему нужно всего лишь развернуть несколько узлов Zuul для достижения высокой доступности. Клиент Zuul будет автоматически запрашивать список серверов Zuul с сервера Eureka, а затем использовать компоненты балансировки нагрузки (например, ленту) для запроса кластера Zuul.
2. Клиент Zuul не может зарегистрироваться на сервере Eureka.
Если наш клиент — мобильное приложение, то зарегистрироваться на Eureka Server по схеме 1 невозможно. В этом случае мы можем добиться высокой доступности Zuul за счет дополнительных балансировщиков нагрузки, таких как Nginx, HAProxy, F5 и т.д.
Как показано на рисунке, клиент Zuul отправляет запрос балансировщику нагрузки, а балансировщик нагрузки перенаправляет запрос на один из своих прокси-узлов Zuul, чтобы обеспечить высокую доступность Zuul.
Spring Cloud
Хотя в Spring Cloud есть «Облако», это не решение для облачных вычислений, а построенный на базе Spring Boot набор инструментов для быстрого построения общей схемы распределенных систем.
Приложения, разработанные с помощью Spring Cloud, очень подходят для развертывания в Docker или PaaS, поэтому их также называют облачными приложениями. Облако Native можно просто понимать как программную архитектуру для облачной среды.
Поскольку это набор инструментов, он должен содержать много инструментов.Давайте посмотрим на следующую картинку:
Поскольку речь идет только о сравнении шлюзов API, я не буду представлять другие инструменты один за другим.
Spring Cloud интегрировал Zuul, но, с точки зрения Zuul, серьезных изменений нет, но вся структура Spring Cloud была интегрирована с компонентами, предоставляя гораздо больше функций, чем Netflix Zuul, и могут быть различия в сравнении.
Сервисная сетка Linkerd
Я думаю, что Dr. Turgay Celik использовал LinkerD в качестве одного из объектов сравнения, вероятно, потому что LinkerD предоставляет сетку упругости обслуживания для облачных приложений, а сетка обслуживания может предоставлять легкий высокопроизводительный сетевой прокси, а также предоставляет поддержку Microsevice Framework.
Из введения, linkerd — это наш RPC-прокси с открытым исходным кодом для микросервисов, который напрямую основан на Finagle (внутренней базовой библиотеке Twitter, которая отвечает за управление процессом связи между различными сервисами. Фактически, каждый онлайн-сервис компании Twitter основан на Он построен на Finagle и поддерживает сотни миллионов вызовов RPC, которые происходят в секунду. Цель разработки — помочь пользователям упростить эксплуатацию и обслуживание в рамках микросервисной архитектуры. Он предназначен для обработки срочных служб. Уровень коммуникационной инфраструктуры службы.
Подобно Spring Cloud, Linkerd также обеспечивает балансировку нагрузки, Fuse Machine, обнаружение сервисов, динамическую маршрутизацию запросов, повторные попытки и автономный режим, TLS, интеграцию шлюза HTTP, прозрачный прокси-сервер, gRPC, распределенную трассировку, эксплуатацию и обслуживание и многие другие функции. Он достаточно полный, добавив еще один для технического выбора микросервисного фреймворка. Так как с Linkerd не контактировал, анализировать с архитектурного уровня пока не могу, буду дополнять этот контент в будущем и делать техническую подборку сам.
Результаты теста производительности
В статье доктора Тургая Челика в качестве тестового инструмента используется инструмент оценки производительности HTTP-сервера Apache AB. Обратите внимание, что, поскольку он основан на тесте общедоступного облака Amazon (AWS), он может отличаться от результатов теста на вашей реальной физической машине.
В ходе эксперимента запускаются две машины, клиентская и серверная, и соответственно устанавливаются несколько тестируемых служб, к которым клиент обращается несколькими способами, чтобы попытаться получить ресурсы. План тестирования показан на следующем рисунке:
Доктор Тургай Челик выбрал для этого теста три среды, а именно:
- Одно ядро ЦП, 1 ГБ памяти: используется для сравнения обратного прокси Nginx и Zuul (средние результаты после удаления первого запуска);
- Два ядра ЦП, 8 ГБ ОЗУ: используется для сравнения обратного прокси Nginx и Zuul (средние результаты после удаления первого запуска);
- 8-ядерные ЦП, 32 ГБ ОЗУ: Для сравнения обратный прокси-сервер Nginx, Zuul (средние результаты после удаления первого запуска), Spring Cloud Zuul, Linkerd.
В процессе тестирования используется 200 параллельных потоков для отправки в общей сложности запросов 10 000. Шаблон команды выглядит следующим образом:
ab -n 10000 -c 200 HTTP://
<server-address>
/<path to resource>
Примечание: поскольку тест доктора Тургая Челика основан на Zuul 1, производительность низкая и не может точно отражать производительность текущей версии Zuul.Я проведу свои собственные эксперименты и опубликую результаты в следующих статьях.
Из приведенных выше результатов видно, что в одноядерной среде Zuul имеет наихудшую производительность (950,57 раз/с), метод прямого доступа имеет лучшую производительность (6519,68 раз/с), а метод обратного прокси-сервера Nginx проигрывает 26% по сравнению с производительность метода прямого доступа (4888,24 раза/с). В двухъядерной среде производительность Nginx почти в 3 раза выше, чем у Zuul (6187,14 раза/с и 2099,93 раза/с соответственно). В мощной тестовой среде (8 ядер) нет большой разницы между прямым доступом, Nginx и Zuul, но у Spring Cloud Zuul может быть внутреннее общее потребление, что приводит к нескольким запросам в секунду. 873.14.
окончательный вывод
С точки зрения продукта шлюз API отвечает за маршрутизацию запросов на обслуживание, композицию и преобразование протоколов. Все запросы от клиента сначала проходят через шлюз API, который затем направляет запрос в соответствующий микросервис. Шлюзы API часто обрабатывают запрос, вызывая несколько микросервисов и объединяя результаты.Он может конвертировать между веб-протоколами (такими как HTTP и WebSocket) и недружественными для Интернета протоколами, используемыми внутри, поэтому он по-прежнему очень полезен, поэтому выбор технических решений также важен для всей системы.
Из того, что я понимаю о принципах проектирования этих четырех компонентов, шаблон проектирования Zuul1 аналогичен шаблону Nigix.Каждая операция ввода-вывода выбирает один из рабочих потоков для выполнения, а поток запроса блокируется до тех пор, пока рабочий поток не будет завершено, но разница в том, что Nginx реализован на C++, Zuul реализован на Java, а сама JVM имеет медленную первую загрузку. Производительность Zuul 2 определенно будет значительно улучшена по сравнению с Zuul 1. Кроме того, производительность Zuul в первом тесте плохая, но со второго раза она намного лучше, вероятно, из-за оптимизации JIT (Just In Time). Что касается Linkerd, то его конструкция шлюза чувствительна к ресурсам, поэтому сравнение его с другими реализациями шлюза в общей среде может привести к неточным результатам.
об авторе
Чжоу Минъяо, Окончил Чжэцзянский университет, магистр технических наук. 13 лет опыта работы в разработке программного обеспечения, 10 лет опыта технического управления, 4 года опыта разработки распределенного программного обеспечения и 17 патентов на изобретения. Автор книг «Оптимизация производительности Java в Dahua», «Глубокое понимание JVM и G1 GC», «Техническое лидерство: как программисты могут руководить командой». Учетная запись WeChat michael_tec, общедоступная учетная запись WeChat «Дядя Майк говорит в 10 часов каждую ночь».
Оригинальная английская ссылка выглядит следующим образом:Engineering.op находится на IE.com/comparing- ах...
благодарныйГо ЛэйПланирование и рецензирование этой статьи.
Если Google не может решить вашу проблему, если вы хотите получить частную практику ведущих архитекторов, если вы хотите изучить более 100 частных архитектурных проектов дома и за рубежом,кликните сюда, зарегистрируйтесь сейчас со скидкой 20%Глобальный саммит архитекторов ArchSummit[станция Шэньчжэнь]