предисловие
Глядя на что-то, написанное год или два назад, я всегда задаюсь вопросом, действительно ли это было сделано моими собственными руками? В некоторых местах я не выдержал и начал долгий путь реконструкции.
До и после сравнения
Краткое введение, прежде чем мы начнемcim
Этот проект, следующая его архитектурная схема:
Проще говоря, это система обмена мгновенными сообщениями, которая в основном состоит из следующих частей:
-
IM-server
Естественно, это сервер, который используется для поддержания длительного соединения с клиентом. -
IM-client
Клиент можно просто рассматривать как клиентский инструмент, аналогичный QQ; конечно, функции, конечно, не так богаты, и предоставляют только некоторые простые функции отправки и получения сообщений. -
Route
Служба маршрутизации в основном используется для аутентификации клиентов, пересылки сообщений и т. д. Она предоставляет некоторые http-интерфейсы, которые можно использовать для просмотра состояния системы, онлайн-номера и других функций.
Конечно, сервер и маршрутизацию можно масштабировать по горизонтали.
Это блок-схема отправки сообщений в предположении, что два сервера A, B и служба маршрутизации теперь развернуты; гдеClientA
иClientB
Поддерживайте долгосрочные соединения с серверами A и B соответственно.
когдаClientA
В направленииClientB
Отправитьhello world
, весь поток сообщений показан на рисунке:
- пройти первым
http
отправить сообщениеRoute
Служить. - Служба маршрутизации узнает
ClientB
подключен кServerB
на; потом черезhttp
отправить сообщениеServerB
. - наконец-то
ServerB
передать сообщение сClientB
длинный канал связиpush
Продолжайте, пока сообщение успешно отправлено.
Вот я перехватилClientA
В направленииRoute
Код для инициации запроса:
okhttp
инициировалhttp
Запрос, хотя это может выполнить функцию, но это не элегантно.
Например: Предположим, нам нужно подключиться к интерфейсу Alipay, естественно, нет проблем с отправкой http-запроса сюда, но когда различные отделы внутри Alipay напрямую обращаются к интерфейсу друг друга, исходный http-запрос использовать не следует.
должно быть предоставлено поставщиком услугapi
Пакет, потребители услуг должны полагаться только на этот пакет для реализации интерфейсных вызовов.
Конечно, в конце концов вы можете использовать http или собственный частный протокол.
Также похоже на то, что мы используемDubbo
илиSpringCloud
, обычно опираясь непосредственно наapi
package, удаленный сервис может вызываться как локальный метод, а основные детали полностью экранированы.Неважно, использует ли он http или другие частные протоколы, и вызывающему абоненту все равно.
Если вы так говорите, то есть ли какой-то внутренний вкус? Разве это не официальное объяснение RPC.
То же самое и здесь,Client
,Route
,Server
По сути, все они представляют собой систему, и их интерфейсные вызовы друг к другу тоже должны бытьRPC
только разумно.
Итак, то, что я реорганизовал, стало таким:
Код намного проще, как вызов нативного метода, и есть несколько преимуществ:
- Основные детали полностью защищены, а бизнес-код и код обслуживания могут быть реализованы лучше.
- Даже если сервис-провайдер модифицирует параметры, это можно быстро обнаружить при компиляции, а вызов по-прежнему совершенно незнающий, так что это тоже повышает риск.
Динамический прокси, который невозможно обойти
Поговорим о том, как это реализовано.
На самом деле, выше«Практическое применение динамических агентов»Также упоминается, что принцип аналогичен.
Для того, чтобы быть невидимым для вызывающего, необходимо создать прокси-объект интерфейса, в котором реализован процесс кодирования, вызова и декодирования.
Соответствующее здесь на самом деле создатьrouteApi
Прокси-объект, ключом является этот код:
RouteApi routeApi = new ProxyManager<>(RouteApi.class, routeUrl, okHttpClient).getInstance();
Полный исходный код выглядит следующим образом:
один из нихgetInstance()
Функция возвращает объект интерфейса, который необходимо проксировать;ProxyInvocation
это реализацияInvocationHandler
Класс интерфейса, этот набор кода должен использоватьJDK
Три оси для реализации динамического прокси.
ПроверятьProxyInvocation
Исходный код обнаружит, что когда мы вызываем любой метод прокси-интерфейса, он выполняетinvoke()
метод.
иinvoke()
Этот метод естественным образом реализует процесс кодирования, удаленного вызова и декодирования, упомянутый на рисунке выше; я думаю, что его легко понять каждому, поскольку он не является предметом данного обсуждения, я не буду вводить его слишком подробно.
Суммировать
На самом деле понять их несложноDubbo
этот видRPC
Основной исходный код фреймворка доступен, и общая идея аналогична, за исключением того, что он использует частный протокол, поэтому кодирование и декодирование будут отличаться.
Так что если вы хотите сделать это самиRPC
Framework, вы могли бы также попробовать эту идею, когда вы запускаете код, который вы написали сами.RPC
изhelloworld
Я чувствую, что я интегрировался с самим собойDubbo
,SpringCloud
Ощущения от таких сторонних фреймворков совершенно другие.
Весь исходный код для этой статьи:
Ваши лайки и репост - лучшая поддержка для меня