Некоторое время назад в новостях появились сообщения о том, что иностранная компания HashiCorp объявила на своем официальном сайте, что ей не разрешено использовать, развертывать и устанавливать корпоративные версии продуктов и программного обеспечения компании в Китае.
Среди них Consul — промежуточное программное обеспечение для обнаружения и настройки сервисов, с которым хорошо знакомы разработчики Java Spring Cloud.Многие люди беспокоятся о том, будет ли затронут Consul.В настоящее время HashiCorp запрещает использование только реализована версия с открытым исходным кодом.Ограничения, так что тем, кто использует Консул, не о чем беспокоиться. Однако с течением времени противостояние в разных регионах будет продолжать обостряться, и, возможно, однажды опенсорсную версию объявят отключенной, поэтому нам нужно знать, чем заменить Consul.
В 2008 году, когда zk еще не вышел, Alibaba нужно было выполнять внутреннее обнаружение сервисов, поэтому она разработала ConfigServer.Спустя десять лет, в июле 2018 года, Alibaba выпустила Nacos (реализация с открытым исходным кодом ConfigServer) версии 0.1.0, это было почти два года с версии 1.3.0, и теперь он может поддерживать множество функций:
Регистрация и обнаружение сервисов: nacos интегрирован со многими rpc-фреймворками, такими как dubbo, springcloud и т. д., что нам удобно использовать «из коробки», в то же время он также открывает нам относительно простой API для настроить наш собственный rpc.
Управление конфигурацией: центр управления конфигурацией, аналогичный apllo, позволяет нам не записывать конфигурацию в файл и выполнять унифицированное управление в фоновом режиме.
Сервер адресов: нам удобно обращаться к nacos в разных средах и разных сценариях изоляции.
Безопасность и стабильность: мониторинг производительности, зашифрованная передача, управление контролем разрешений и т. д.
Для nacos самыми большими основными функциями являются регистрация службы и управление конфигурацией.Моя статья в основном знакомит с этими двумя модулями.В этой статье в основном представлены некоторые виды использования, принципы и сравнения, связанные с обнаружением-регистрацией службы Nacos.оптимизация.
Базовые концепты
Во-первых, давайте рассмотрим некоторые основные концепции обнаружения-регистрации сервисов в Nacos:
Пространство имен: пространство имен относится к структуре верхнего уровня Nacos и используется для изоляции на уровне арендатора.Мы чаще всего используем различные среды, такие как тестовые среды и онлайн-среды, чтобы изолировать их.
Сервис: Понятие сервис один в один соответствует нашим привычным микросервисам, таким как сервис заказов, сервис логистики и так далее. Пространство имен может иметь несколько служб, а разные пространства имен могут иметь одну и ту же службу.Например, и тестовая среда, и онлайн-среда могут иметь службы заказа.
Виртуальный кластер: все машины в рамках службы образуют кластер.В Nacos кластер может быть дополнительно разделен на виртуальные кластеры по мере необходимости.
Экземпляр. Грубо говоря, машина или виртуальная машина — это экземпляр, а детальное понимание — это процесс с доступным сетевым адресом (IP:порт) для одной или нескольких служб.
Выше приведена диаграмма модели домена службы, приведенная в документе официального веб-сайта Nacos.Из диаграммы мы можем узнать, что иерархическая связь принадлежит: сервис-кластер-экземпляр.В то же время некоторые данные будут сохранены в службе, кластер и экземпляр для других нужд.
На самом деле, когда речь заходит о регистрации сервиса, многие в первую очередь думают о Zookeeper.На самом деле ZK не предоставляет напрямую функцию регистрации сервиса и подписки.Чтобы реализовать эти функции в ZK, вы должны самостоятельно разделить файловую директорию по одному. , что очень неудобно, и The Api ZK тоже очень сложно использовать.Для Nacos Api регистрации сервиса используется следующим образом:
Нам нужно только создать NamingService, а затем вызвать метод registerInstance и метод subscribe, чтобы завершить регистрацию и подписку на нашу службу.
Если вас интересует быстрый доступ к Nacos, вы можете перейти на официальный сайт, чтобы подробно ознакомиться с ним, я не буду его здесь представлять.что cos.IO/this-capable/docs/…
AP or CP
CAP
Когда речь идет о распределенных системах, она должна быть неотделима от теоремы CAP, которая называется теоремой Брюера. Для архитекторов, разрабатывающих распределенные системы (не только распределенные транзакции), CAP является отправной точкой.
C (согласованность): для данного клиента операция чтения может вернуть последнюю операцию записи. Для данных, распределенных по разным узлам, если данные обновляются на узле, если последние данные могут быть прочитаны другими узлами, это называется строгой согласованностью.Если узел не читает данные, если вы их получаете, это распределенная несогласованность .
A (доступность): исправный узел возвращает разумный ответ (не ответ об ошибке и тайм-ауте) в разумные сроки. Двумя ключами к доступности являются разумное время и разумный ответ. Разумное время означает, что запрос не может быть заблокирован на неопределенный срок и должен быть возвращен в разумные сроки. Разумный ответ означает, что система должна явно возвращать результат, и результат правильный, где правильный означает, что она должна возвращать, например, 50 вместо 40.
P (Partition Tolerance): система может продолжать работу при возникновении сетевого раздела. Например, в кластере несколько машин, и есть проблема с сетью одной машины, но кластер еще может нормально работать.
Любой, кто знаком с CAP, знает, что три нельзя разделить.Если вам интересно, вы можете поискать доказательство CAP.В распределенной системе сеть не может быть на 100% надежной, и разделение на самом деле является неизбежным явлением.Если мы выбираем CA и отказываемся от P, Тогда, когда происходит разделение, для обеспечения согласованности запрос должен быть отклонен в это время, но A не разрешает это, поэтому для распределенной системы теоретически невозможно выбрать архитектуру CA , только архитектура CP или AP.
Для CP, чтобы отказаться от доступности и добиться согласованности и отказоустойчивости разделов, наш zookeeper на самом деле является стремлением к строгой согласованности.
Для AP отказ от согласованности (согласованность, упомянутая здесь, является строгой согласованностью) и стремление к отказоустойчивости и доступности разделов является выбором многих распределенных систем при проектировании, и последний BASE также расширяется в соответствии с AP.
Кстати, теория CAP игнорирует сетевую задержку, то есть когда транзакция совершается, она копируется с узла A на узел B, но в реальности это заведомо невозможно, поэтому всегда будет какое-то несоответствие времени. В то же время, выбирая два CAP, например, вы выбираете CP, это не говорит вам отказаться от A. Поскольку вероятность появления P очень мала, большую часть времени вам все равно нужно гарантировать CA. Даже если раздел появится, вы должны подготовиться к более позднему A, например, с помощью некоторых журналов другие машины будут восстановлены в рабочем состоянии.
Выбор реестра
Как было сказано выше, все распределенные системы будут принимать решение о CAP, и тот же реестр не является исключением. Zookeeper является первым выбором для многих центров регистрации сервисов.Моя текущая компания также использует ZooKeeper в качестве центра регистрации, но с развитием компании ZK становится все более и более нестабильным, и обнаружение сервисов в нескольких компьютерных залах также очень затруднено. , В этой статье в статьеПочему Alibaba не использует ZooKeeper для обнаружения сервисов?, более подробно объясняет, почему Али не использует ZK в качестве регистрационного центра. Здесь я кратко поясняю:
Неудовлетворительная производительность, невозможность масштабирования по горизонтали: Учащиеся, знакомые с ZK, знают, что ZK записывает данные в лидера (мастер-ноду), поэтому масштабировать по горизонтали сложно.При достижении компанией определенного масштаба ZK не подходит в качестве регистрации центр.Частое чтение и запись может легко привести к нестабильности ZK. В этом случае можно разделить несколько кластеров ZK, но есть проблема: в начале каждый кластер может не иметь дело друг с другом, но если на более позднем этапе будет какой-то совместный бизнес, сервисы каждого кластера будут звонить друг другу. др. трудный момент.
ZooKeeper API сложен в использовании: использование Zookeeper действительно требует относительно опытного эксперта, вы должны быть знакомы со многими его исключениями и что делать с этими исключениями.
В реестре нет необходимости хранить какие-то исторические изменения: теоретически реестру нужно только знать, какие сервисы и экземпляры зарегистрированы в реестре в данный момент, но ZK продолжит записывать журналы транзакций для последующего исправления.
Один и тот же компьютерный зал не может быть подключен: если у нас есть структура развертывания аварийного восстановления с 5 узлами с тремя компьютерами, как показано на следующем рисунке:Если между машинным залом 3 и машинным залом 1 и 2 есть сетевая перегородка, то есть внутри машинного зала все хорошо, но машинные залы не соединены.Так как ЗК этого машинного зала разделены, то текущий ЗК также будет недоступен.Если служба не сможет использовать центр регистрации, то не будет возможности звонить друг другу.Очевидно, что это не разрешено.Если сеть между машинными залами хорошая, то должно быть разрешено звонить в одном компьютерном зале.
Исходя из вышеизложенного, ЗК не подходит для нашего регистрационного центра, другими словами, регистрационный центр не нуждается в ЦП, и мы должны предоставить больше АП.
Протоколы в Nacos
Distro
В Instance (экземпляре) Nacos предусмотрено эфемерное поле. Это поле имеет тип bool. Значение этого поля аналогично значению в ZK. Оно показывает, является ли это временным узлом. В Nacos, если это временный узел, будет использоваться протокол AP.Если это не временный узел, он перейдет к CP. Конечно, все экземпляры в реестре по умолчанию являются временными узлами.
Для реализации AP в Nacos был настроен набор протоколов Distro. Давайте проанализируем, что такое Distro:
Чистая экономия памяти
Все данные в Distro хранятся в памяти, в DistroConsistencyService:
Видно, что Distro использует ConcurrentHashMap в качестве контейнера для хранения и не требует использования дополнительных файлов для хранения. Некоторые студенты спросят, если моя машина выйдет из строя и вся информация о памяти будет потеряна, как я могу восстановить эту часть данных?
В методе загрузки DistroConsistencyService мы обходим все не собственные серверы, а затем синхронизируем данные, если один из них успешно синхронизирован, нет необходимости отправлять информацию о синхронизации на другие серверы. Это восстановит все данные.
в конечном итоге последовательный
Хоть мы и говорим о AP, на самом деле нам все равно нужно обеспечить конечную консистентность, чтобы предотвратить несогласованность данных каждой ноды в течение длительного времени.В методе Put DistroConsistencyService будет добавлена задача в TaskDispatcher, как показано ниже:
TaskDispatcher на самом деле называется DataSyncTaskDispatcher, это более уместно, в основном используется для синхронизации данных:
Основная логика - это петля выше, в основном глядя на код, который я пометил красным, здесь не нужно отправлять одно обновление, когда оно приходит, если сервис часто меняется, если кто-то отправляет его, эффективность должна быть очень низкой, поэтому здесь мы принимаем обновление.Стратегия слияния, если обновленные данные достигают определенного количества, по умолчанию здесь 1000, или последняя передача превысила определенное время. По умолчанию здесь 2 с, и будет выполнена передача. Передача здесь также создать SyncTask и поместить его в поток асинхронной отправки в пул.
В это время некоторые студенты спросят, что мне делать, если одна из моих машин только что была запущена, и я просто не получил обновленные данные? В Nacos также будет восходящая стратегия TimedSync. Эта задача будет выполняться каждые 5 с. Конкретный код задачи выполнения выглядит следующим образом:
Обратите внимание на часть обведенную красным.Это не для синхронизации всех данных, а для обхода всех данных.Синхронизироваться будет только та часть данных, которая принадлежит вашему собственному управлению (какие данные принадлежат вашему собственному управлению? Я буду обсудим это подробно в следующем разделе), а затем заставим все несобственные серверы проверять и отправлять эти данные.
С помощью этих двух методов: обновления в реальном времени и обновления по времени мы можем гарантировать, что данные на всех узлах Nacos в конечном итоге будут согласованы.
Горизонтальное расширение
Одним из недостатков ZK является то, что его нельзя масштабировать по горизонтали.Это основная проблема CP.С развитием компании и большим масштабом вам сложно поддерживать текущий бизнес. В Distro нет роли лидера, и каждый узел может обрабатывать чтение и запись Таким образом, мы можем произвольно расширять узлы Nacos по горизонтали для удовлетворения наших потребностей.
В дистрибутиве не каждый узел может обрабатывать все запросы на чтение, но и не каждый узел может обрабатывать запросы на запись.Каждый узел сам будет судить, следует ли его обрабатывать, в соответствии с хеш-значением ключа. Запрос на запись обращается к доменному имени, которое случайным образом попадает на каждый узел. Как Nacos заставляет эти запросы на запись попадать на соответствующую машину? Ответ находится в DistroFilter:
Этот ServletFilter будет выполнять некоторую фильтрацию по каждому запросу, и если он обнаружит, что запрос не является его собственным, он перенаправит запрос на соответствующий сервер для обработки, а затем вернет его пользователю после получения результата.
Здесь Nacos действительно может выполнить оптимизацию. Мы можем обнаружить, что это действие является синхронным при пересылке. Здесь мы можем использовать асинхронную отправку и включить асинхронность serlvet. Этот узел пересылки может быть похож на шлюз без синхронного ожидания, а Nacos может быть добавлена пропускная способность кластера
По сравнению с другими протоколами CP, эти преимущества Distro очень велики в реестре, и реализация всего протокола намного проще, чем они, что очень легко понять.Если вы будете заниматься протоколом реестра в будущем, вы можно сослаться на эту идею.
Raft
На самом деле в Nacos тоже есть протокол строгой согласованности.. Raft используется.. Raft используется в двух местах:
В реестре есть некоторые данные в Nacos, которые необходимо постоянно хранить. Мы будем использовать Raft для последовательного и синхронного хранения данных, таких как Service, некоторые данные в пространстве имен. Nacos считает, что экземпляр относительно быстро меняющийся, временные данные, Raft не требуется для высококонсистентного протокола, но Service и namespace — это данные, которые меняются меньше и подходят для постоянного хранения. Плотная реализация реестра. В настоящее время я использую набор Raft, написанный мной.После прочтения деталей, все еще есть некоторые отличия от стандартного Raft.Например, непрерывность журналов не гарантируется в Raft-протоколе Nacos.
После 1.3.0, чтобы постепенно использовать стандартный протокол raft для реализации дивана-jraft, Nacos пока использовался только в центре конфигурации.До центра конфигурации можно было использовать только хранилище mysql.После 1.3.0 , Nacos позаимствовал отрывок Etcd.Протокол Raft преобразует автономное хранилище KV в распределенное хранилище KV.На основе SOFA-JRaft и Apache Derby построена облегченная распределенная реляционная база данных, при этом сохранена возможность использования внешних источники данных.Пользователи могут выбрать одно из решений для хранения данных в соответствии с реальной бизнес-ситуацией.
Конкретные детали протокола Raft здесь не рассматриваются, если вам интересно, вы можете взглянуть на переведенную статью:woohoo.info Q.talent/article/RAF…
Регистрация узла и подписка
Еще одна важная вещь в реестре — это то, как наши узлы регистрируются и подписываются, как выполнять обнаружение пульса, чтобы предотвратить простои узла, и как подписанные узлы могут получать обновления в режиме реального времени.
Нам нужно просто написать приведенную выше строку кода, чтобы завершить регистрацию нашего узла. Приведенный выше код для ServiceNamemicroservice-mmp-marketing,существуетTEST1В кластере IP регистрируется как11.11.11.11, порт8888например, задача Heartbeat будет добавлена одновременно с регистрацией
Как показано в красной части рисунка выше, в пул потоков добавляется отложенная задача пульса, которая по умолчанию выполняется за 5 секунд.
существуетBeatTask, пульсация будет сначала отправлена на Nacos-Server. Если Nacos-Server определяет интервал пульсации, он изменит время следующего выполнения в соответствии с возвращенным результатом. Если наша служба не существует, это означает, что наша машина связана с некоторыми Причина в том, что нет синхронизированного пульса, из-за чего его удалили, здесь нужно заново зарегистрировать узел.
В ClientBeatCheckTask Nacos-Server мы будем регулярно сканировать Сервис на наличие экземпляров, которые не были синхронизированы в течение длительного времени в соответствии с измерением Сервиса.По умолчанию 15 с, как показано в коде в красном поле ниже:
Подписка узла
Подписка узлов имеет разные реализации в разных центрах регистрации.Общие процедуры делятся на два типа: обучение ротации и толчок.
Пуш означает что при обновлении подписанной ноды он будет активно пушить к подписчику.Наша ЗК это метод реализации пуша.Клиент и сервер установят длинное TCP соединение,клиент зарегистрирует вотчер,а потом когда нет Когда данные обновляются, сервер проталкивает их через длинное соединение. Из-за такого режима установки длительного соединения ресурсы сервера будут серьезно расходоваться, поэтому при большом количестве наблюдателей и при частых обновлениях производительность Zookeeper будет очень низкой, а то и вовсе зависать.
Обучение ротации означает, что узлы, на которые мы подписываемся, активно и регулярно получают информацию о узлах сервера, а затем выполняют локальное сравнение, и, если есть изменения, будут сделаны некоторые обновления. В Консуле тоже есть механизм вотчера, но в отличии от ZK он реализован через длинный опрос Http.Сервер Консул сразу вернет, содержит ли запрошенный url параметр ожидания, или сначала зависнет и дождется указанного Если есть изменение в услуга в течение времени ожидания, она вернется. Производительность циклического обучения может быть выше, но производительность в реальном времени может быть не очень хорошей.
В Nacos эти две идеи объединены, чтобы обеспечить как обучение вращению, так и активный толчок Давайте сначала посмотрим на часть обучения вращению, а затем на метод run в классе UpdateTask:
Обратите внимание на красную рамку выше, мы будем регулярно чередовать обучение в соответствии с параметром Service, нашей ServiceInfo, а затем обновлять его.
Давайте посмотрим, как Nacos реализует функцию push. Nacos будет записывать наших подписчиков в наш PushService. Ниже приведен основной код push в нашем PushService:
Шаг 1: Инициируйте наше продвижение через событие ServiceChangeEvent Здесь следует отметить, что, поскольку наши узлы обновляются через дистрибутив, это событие также будет запускаться, когда наш дистрибутив синхронизируется с другими машинами.
Шаг 2: Получите поддержку подписчиков на локальном компьютере, поскольку подписчики определяются в зависимости от того, был ли запрошен сервисный узел, и действие запроса сервисного узла будет случайным образом передано различным серверам Nacos, поэтому каждый из наших узлов Некоторые абоненты будут поддерживаться, и между поддерживаемыми подписчиками будет дублирование.Поскольку выполняется последующая UDP-передача, стоимость повторного обслуживания подписчиков не очень высока.
Шаг 3: Сгенерируйте ackEntry, то есть содержимое, которое мы отправляем, и кэшируем его.Кэш здесь в основном предназначен для предотвращения повторного сжатия.
Шаг 4: Наконец, отправьте udp
Push-режим Nacos сэкономит много ресурсов для длительного подключения Zookeeper через tcp.Даже большое количество обновлений узла не вызовет слишком много узких мест в производительности в Nacos.В Nacos клиент вернется, если получит сообщение udp. ACK, если Nacos-Server не получит ACK в течение определенного периода времени, он отправит его повторно. Когда время повторной отправки превышает определенное время, оно не будет повторно отправлено. Хотя это не гарантируется отправляются подписчику по udp, но у Nacos в сухом остатке также есть обучение регулярной ротации, так что можно не переживать за ситуацию, что данные не обновятся.
Благодаря этим двум методам Nacos не только обеспечивает производительность в режиме реального времени, но и гарантирует, что обновления данных не будут упущены.
Суммировать
Хотя Nacos является новым проектом с открытым исходным кодом, его архитектура и дизайн исходного кода очень сложны.Например, во внутреннем исходном коде используется много архитектуры EventBus, которая разделяет многие процессы, и его идея протокола Distro также очень достойна изучения. .
В реестре Nacos есть и другие детали, такие как селектор на основе тегов и так далее. Желающие могут спуститься и узнать в документации Nacos.
Если вы считаете, что эта статья полезна для вас, то ваше внимание и пересылка - самая большая поддержка для меня, O(∩_∩)O: