Роль реестра
В первую очередь хочу подумать над вопросом, может ли Dubbo продолжать играть без регистрационного центра?
Конечно, пока известна информация об адресе поставщика услуг, потребитель может позвонить ему после настройки. Если сервисов всего несколько, играть так, конечно, нормально. Но существуют сотни производственных сервисов, и если для каждого сервиса требуется написанная от руки информация о конфигурации, представьте, насколько это хлопотно.
Хорошо, если ни одна из вышеперечисленных проблем не имеет значения, просто представьте, что произойдет с потребителями, если поставщик услуг выйдет из строя в середине работы? Потребитель не знает, поэтому он продолжает отправлять запросы поставщику услуг, а затем продолжает сбой. В настоящее время единственный способ — изменить информацию об адресе службы и перезапустить службу.
Видно, что если реестра нет, поиск и обнаружение сервисов в распределенной среде будет очень хлопотным, и все нужно настраивать вручную и нельзя автоматизировать. Поэтому здесь необходима третья сторона для координации отношений между поставщиками услуг и потребителями, которой является реестр.
Основные функции регистрационного центра:
- При динамическом присоединении поставщик услуг динамически раскрывает себя потребителям через реестр, при этом потребителям не нужно обновлять файлы конфигурации один за другим.
- Динамическое обнаружение сервисов, потребители могут динамически обнаруживать новые сервисы без перезапуска.
- Унифицированная конфигурация, чтобы избежать несогласованной конфигурации каждой службы, вызванной локальной конфигурацией.
- Динамическая настройка, центр регистрации поддерживает динамическую настройку параметров, а новые параметры автоматически обновляются на всех соответствующих сервисных узлах.
- Унифицированное управление, основанное на данных реестра, позволяет управлять узлами обслуживания и настраивать их унифицированным образом.
Рабочий процесс реестра
Общий рабочий процесс регистрационного центра относительно прост, и его блок-схема примерно выглядит следующим образом:
Основной рабочий процесс можно разделить на следующие этапы:
- После запуска поставщика услуг он регистрирует службу в реестре.
- После запуска потребитель активно подписывается на службу провайдера в реестре, чтобы получить все доступные в настоящее время службы, оставив при этом функцию обратного вызова.
- Если поставщик услуг добавлен или отключен, реестр уведомит потребителя с помощью функции обратного вызова, зарегистрированной на втором этапе.
- dubbo-admin (центр управления услугами) подпишется на поставщиков и потребителей услуг, чтобы всеми поставщиками и потребителями услуг можно было управлять в консоли.
Предыдущая версия Dubbo в основном может использовать ZooKeeper и Redis в качестве реестра.Постоянное обновление версии Dubbo также поддерживает nacos, consul и т. д. в качестве реестра.
Исходный код ядра реестра Dubbo
ps: следующий исходный код основан на версии dubbo 2.7.3.
Реестр реализует шаблонный режим, исходный код находится в модуле dubbo-registry, а отношение классов следующее:
самый верхнийRegistryService
Интерфейс определяет основные методы, а именно регистрацию, отмену регистрации, подписку, отмену подписки и запрос.
Абстрактный класс среднего уровня в основном реализует общую логику, например:AbstractRegistry
реализовать механизм кэширования,FailbackRegistry
Реализовать функцию повторной попытки отказа.
Нижний слойZookeeperRegistry
Etc. — это конкретный класс реализации, реализующий логику взаимодействия с центрами регистрации, такими как ZooKeeper.
Далее подробно разбираемAbstractRegistry
иFailbackRegistry
логика.
AbstractRegistry
Принцип реализации кэша
Если каждый вызов службы должен обращаться к реестру для запроса списка доступных служб в режиме реального времени, это не только создаст огромную нагрузку на реестр, но и создаст дополнительные сетевые запросы, что приведет к снижению производительности системы.
Во-вторых, реестру нужны несильные зависимости, и его простои не могут повлиять на обычные вызовы службы.
Исходя из вышеперечисленных пунктов, модуль реестраAbstractRegistry
В классе реализован общий механизм кэширования. Кэш здесь можно разделить на две категории: кеш службы памяти и кеш дисковых файлов.
Кэш службы в памяти
Кэш службы памяти хорошо изучен и его проще всего реализовать.AbstractRegistry
использоватьConcurrentMap
Сохраните соответствующую информацию.
private final ConcurrentMap<URL, Map<String, List<URL>>> notified = new ConcurrentHashMap<>();
Ключом в этой коллекции является URL-адрес потребителя, а значением является коллекция Map. Эта внутренняя коллекция карт использует каталог службы в качестве ключа, который является поставщиками, маршрутизаторами, конфигураторами и потребителями, а значением является соответствующая коллекция списка услуг.
кеш файлов на диске
Поскольку кеш памяти исчезает при перезапуске службы, добавляется дополнительный кеш дисковых файлов.
Расположение кэша файлов по умолчанию находится в${user.home}/.dubbo/
папка с именем файлаdubbo-registry-${application.name}-${register_address}.cache
. можно установитьdubbo.registry.file
Информация о конфигурации для изменения конфигурации по умолчанию, исходный код реализации выглядит следующим образом:
String filename = url.getParameter(Constants.FILE_KEY, System.getProperty("user.home") + "/.dubbo/dubbo-registry-" + url.getParameter(Constants.APPLICATION_KEY) + "-" + url.getAddress() + ".cache");
ps:
{register_address} принимает информацию об адресе регистрационного центра. Полное имя файла кэша:
C:\Users\xxx/.dubbo/dubbo-registry-dubbo-auto-configure-consumer-sample-127.0.0.1:2181.cache
Использование содержимого файла кэшаproperties
формат файла конфигурации, т.е.key=value
Формат. Ключ — это имя интерфейса службы, а значение — список служб, так как служб может быть несколько, они будут разделены пробелами.
Загрузка кэшированных файлов
Когда программа dubbo инициализируется,AbstractRegistry
Конструктор будет считывать данные из файла локального диска вProperties
В экземпляре объекта последующие будут записаны первымиProperties
, и, наконец, запишите информацию внутри файла.
Исходный код инициализации кеша выглядит следующим образом.
Сохранение и обновление файлов кеша
Кэшированные файлы будут проходить черезAbstractRegistry#notify
способ сохранения или обновления. Когда клиент подписывается на полный объем данных, полученных службой в первый раз, или получает новые данные в последующих обратных вызовах, он вызываетAbstractRegistry#notify
способ обновления кеша памяти и файлового кеша.
notify
Исходный код метода выглядит следующим образом:
В методе кэширования файла сохранения сначала объединяются данные, полученные из URL-адреса, в строку, а затем записывается вышеупомянутыйproperties
объект и, наконец, вывод в файл.
Здесь вы можете выбрать один из двух методов сохранения: синхронный или асинхронный. так какnotify
Может вызываться несколько раз. Для повышения производительности системы система по умолчанию использует асинхронный режим для сохранения.
saveProperties
Исходный код метода выглядит следующим образом:
doSaveProperties
Метод в конечном итоге запишет информацию в кеш. Учитывая, что метод сохранения может быть вызван несколькими потоками одновременно, здесь используется метод CAS.Во-первых, сравните размер версии.Если он меньше, то это означает, что новый поток записывает информацию, и это обновление напрямую отброшен.
Во-вторых, учитывая, что несколько приложений dubbo могут совместно использовать файл кеша, монопольная блокировка файла используется здесь как распределенная блокировка, чтобы предотвратить одновременную работу нескольких приложений с одним и тем же файлом.
Как только файл будет записан неправильно или блокировка не будет получена, операция сохранения будет повторяться непрерывно, пока не будет превышено максимальное количество раз.
ps: До dubbo 2.7.2 максимальное количество повторов не устанавливалось.Если у файла нет разрешения на сохранение, сохранение всегда будет неудачным, а асинхронный поток попадет в бесконечный цикл.
doSaveProperties
Исходный код метода выглядит следующим образом:
FailbackRegistry
механизм повторной попытки
FailbackRegistry
наследоватьAbstractRegistry
, выполненоregister
,subscribe
и других норм общего права, и добавитьdoRegister
,doSubscribe
и другие шаблонные методы, которые реализуются подклассами.
еслиdoRegister
Когда в методе шаблона возникает исключение, неудавшаяся задача будет помещена в коллекцию, а затем метод шаблона будет периодически вызываться снова.
FailbackRegistry
Неудачные наборы повторных попыток:
кsubscribe
метод в качестве примера, здесь будут вызывать этиdoSubscribe
шаблонный метод. Если возникает исключение, содержимое кэш-файла будет считано, а затем будет загружена служба. Наконец, в набор повторов добавляются новые асинхронные задачи синхронизации, а затем таймеры используются для повторения этих задач.
FailbackRegistry#subscribe
Исходный код метода:
существуетaddFailedSubscribed
Будет создана новая запланированная задача, которая затем будет передана таймеру для выполнения. Максимальное количество попыток по умолчанию для запланированных задач — 3, а интервал вызова по умолчанию — 5 с.
addFailedSubscribed
Исходный код выглядит следующим образом:
Другие неудачные повторные попытки аналогичны, все они унаследованы отAbstractRetryTask
Родительский класс, отношения классов показаны ниже.
Суммировать
В этой статье в основном описывается роль реестра, рабочий процесс, общий механизм кэширования и механизм повторных попыток при сбое. Из него вы можете изучить шаблон шаблона, а также навыки многопоточного параллелизма.
Здесь нет конкретной реализации центра регистрации, так как ZooKeeper в настоящее время является самым важным центром регистрации, в следующей части будет рассказано о принципе центра регистрации ZooKeeper, так что следите за обновлениями.
справочные книги
«Глубокое понимание Apache Dubbo и реальных боевых действий»