Даббо! Реализуйте вызовы RPC более элегантным способом.

Dubbo

Dubbo — это инфраструктура вызовов RPC с открытым исходным кодом от Alibaba. Это может значительно упростить реализацию удаленных вызовов RPC, чтобы вы могли больше сосредоточиться на реализации бизнес-возможностей и могли использовать интерфейсы удаленных служб, такие как локальные вызовы API.

В этой статье в основном записывается некоторая ключевая информация о Dubbo и демонстрируется конкретный метод использования Dubbo в коде.

1 Описание ключевых понятий Dubbo

1.1 Основной принцип DUBBO

Базовая сетевая и принципиальная схема Dubbo выглядит следующим образом (картинка взята из сети):

Описание роли узла:

Поставщик: поставщик услуг, предоставляющий услугу.  Потребитель: потребитель службы, который вызывает удаленную службу.  Реестр: Реестр для регистрации и обнаружения служб.  Монитор: центр мониторинга, который подсчитывает время вызова и время вызова службы.

Для получения более новых и подробных инструкций см. dubboофициальная документация, подробное описание здесь повторяться не будет.

1.2 Поддержка протокола DUBBO

1. Dubbo может выбрать протокол

  1. DubboСоглашение, принятиеNIOмультиплексировать одно длинное соединение и использовать线程池Параллельная обработка запросов, сокращение рукопожатий и повышение эффективности параллелизма с повышением производительности** (рекомендуется)** [Проблема: при передаче больших файлов одно соединение становится узким местом]
  2. Rmiпротокол, который работает с роднымRMIинтероперабельность, основанная наTCPпротокол. [Проблема: иногда происходит сбой соединения, и заглушку необходимо перестроить]
  3. Hessianпротокол, который работает с роднымHessianинтероперабельность, основанная наHTTPПротокол [требуется поддержка hessian.jar, накладные расходы на короткие http-соединения высоки]

2. Dubbo может выбирать различные методы сериализации

  1. Hessian Serialization, лучшая производительность, многоязычная поддержка [Проблема: версии гессианского языка несовместимы]
  2. Dubbo Serialization, Не передавая метаинформацию класса POJO, производительность хорошая, когда передается большое количество POJO [Проблема: Когда объект параметра добавляет поля, требуется объявление внешнего файла]
  3. Json Serialization, простой текст, кросс-язычный синтаксический анализ, парсинг FastJson по умолчанию [Проблема: низкая производительность]
  4. Java SerializationJava нативная поддержка [Вопрос:] Плохое производительность

3. Протокол по умолчанию Dubbo, сериализованный как Hessian.

1.3 Разница между служебным портом и портом протокола dubbo

После запуска процесса появится соответствующий порт, например сервис SpringBoot, который будет задан в application.propertiesserver.portзначение, этот порт обычно относится кhttp协议的对外访问端口号.

dubboВ качестве самостоятельного договора при оказании внешних услуг также необходимо указатьdubbo协议对应的portИнформация. два портаразличать, не тот, который новичкам легко спутать.

dubboизportЕсть два способа указать:

    1. указано в XML
<!-- 用dubbo协议在20880端口暴露服务 -->
 <dubbo:protocol name="dubbo" port="20880" ></dubbo:protocol>
    1. Проект SpringBoot, указанный в коде
    @Bean
    public ProtocolConfig protocolConfig() {
        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setPort(8811);
        protocolConfig.setName("dubbo");
        return protocolConfig;
    }

2 Реализация кода сервиса Dubbo

В сложных и крупномасштабных распределенных системах обычно необходимо ввести реестр служб.По умолчанию Dubbo использует Zookeeper в качестве реестра, а также может подключаться к другим реестрам распределенных служб. В качестве регистрационного центра для Dubbo рекомендуется использовать Nacos с открытым исходным кодом от Али.Подробности см. в другой моей статье:"Веселье с Нако! Замена Eureka в качестве центра конфигурации и регистрации"

В следующем примере кода реестр не используется для демонстрации сценария, в котором потребители напрямую подключаются к поставщикам услуг для совершения звонков. Основное внимание уделяется интеграции и использованию Dubbo.

2.1 SpringBoot интегрирует зависимости Maven, соответствующие Dubbo

Необходимо ввести пакет dubbo (например, реестр не используется, поэтому нет необходимости вводить пакеты, связанные с zookeeper).

    <dependency>
        <groupId>com.alibaba.spring.boot</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>2.0.0</version>
    </dependency>

2.2 Поставщик услуг Поставщик услуг

2.2.1 Реализовать определенный интерфейс RPC, который необходимо открыть для внешнего мира, и внедрить конкретную логику реализации.

Обратите внимание на две аннотации: 1,@ComponentЭто по логике SpringBoot, служба автоматически управляется Spring, и первоначальная загрузка завершена; 2,@com.alibaba.dubbo.config.annotation.ServiceЭто предоставляется Dubbo, что указывает на то, что этот тип услуг должен предоставляться извне через dubbo.

Следующим образом:

@Component
@com.alibaba.dubbo.config.annotation.Service(timeout = 5000)
public class RpcDemoServiceImpl implements RpcDemoService {

    @Override
    public String queryCurrentTime(String queryId) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        String formattedDate = simpleDateFormat.format(new Date());
        System.out.println(queryId + " called, current time is: " + formattedDate);
        return queryId + "|" + formattedDate;
    }
}

2.2.2 Определите каталог dubbo для сканирования в классе запуска

Обратите внимание на смысл 2-х аннотаций: 1,@SpringBootApplicationУкажите для запуска в соответствии с обычным приложением SpringBoot; 2,@EnableDubboВключите поддержку Dubbo и укажите соответствующий каталог, он будет сканировать классы в указанном каталоге, чтобы найти все@com.alibaba.dubbo.config.annotation.ServiceИдентифицированный класс интерфейса службы dubbo, который необходимо опубликовать извне.

Следующим образом:

@SpringBootApplication
@EnableDubbo(scanBasePackages = {"com.vzn.local.dubbo.provider.service"})
public class ProviderApp {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApp.class);
    }
}

2.2.3 Укажите настройки, связанные с dubbo

Есть два способа, которые можно прописать прямо в коде или указать в конфигурационном файле.

2.2.3.1 Задается Bean-инъекцией в коде

пройти через@Beanспособ ввести ключевое определение Dubbo. Содержание конфигурации совпадает с конфигурацией XML, а конкретное значение устанавливается здесь с помощью соответствующего объекта JAVA.

Основные классы конфигурации: 1. Конфигурация приложения соответствующий XML<dubbo:application />Информация о конфигурации узла.

2. Конфигурация протокола соответствующий XML<dubbo:protocol />Информация о конфигурации узла.

3. Конфигурация реестра соответствующий XML<dubbo:registry />Информация о конфигурации узла.

Пример кода выглядит следующим образом:

@Configuration
public class DubboConfig {

    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-provider");
        return applicationConfig;
    }

    @Bean
    public ProtocolConfig protocolConfig() {
        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setPort(8811);
        protocolConfig.setName("dubbo");
        return protocolConfig;
    }

    @Bean
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("N/A");
        registryConfig.setRegister(false);

//        registryConfig.setAddress("zookeeper://127.0.0.1:2181");
        return registryConfig;
    }
}
2.2.3.2 Пройтиapplication.propertiesСредняя конфигурация
spring.application.name=dubbo-provider
server.port=28811

# dubbo config
dubbo.application.id=dubbo-provider
dubbo.application.name=dubbo-provider
dubbo.protocol.name=dubbo
dubbo.protocol.port=8811
dubbo.registry.address=N/A

На этом логика интеграции dubbo в простой SpringBoot через код и аннотации завершена, и его можно запускать напрямую.

Уведомление:

  1. Локальный тестовый DEMO, реестр не установлен, и для вызова используется прямое соединение, поэтому адрес, настроенный в RegistryConfig,N/A;
  2. В реальном использовании, если вы используетеzookeeperВ качестве реестра он настроен здесь какzookeeperсоответствующийIPа такжеportстоимость. (Конечно,Вы также можете выбратьNacosИспользовать как центр конфигурации + регистрации, рекомендуется)

2.3 Потребитель услуг

2.3.1 Локально ссылаться на сервисный интерфейс RPC и реализовать соответствующий класс услуг

Реализуйте простой проект SpringBoot в обычном@ServiceВ указанном классе вводится локальный интерфейс API, соответствующий удаленной службе RPC, и@com.alibaba.dubbo.config.annotation.ReferenceАннотация используется для идентификации, эта аннотация означает, что этот bean-компонент будет вызывать метод в удаленном реальном классе реализации через RPC и возвращать результат выполнения.

Это преимущество фреймворка Dubbo,Вся базовая логика инкапсулирована и защищена, поэтому, когда интерфейс RPC используется в бизнес-коде, его можно вызывать непосредственно через локальный API, что значительно снижает сложность кодирования и позволяет разработчикам больше сосредоточиться на своем бизнесе. .Не нужно обращать внимание на то, как должен вызываться RPC на удаленный сервер.

Пример кода выглядит следующим образом:

@org.springframework.stereotype.Service
public class RpcConsumerService {

//    @Reference
//    private RpcDemoService rpcDemoService;

    // 下面两种方式指定的参数,都可以调用成功
    @Reference(protocol = "dubbo", url = "172.31.236.79:8811", interfaceClass = RpcDemoService.class)
    // @Reference(url = "dubbo://172.31.236.79:8811")
    private RpcDemoService rpcDemoService;

    public String getTime(String requestId) {
        return rpcDemoService.queryCurrentTime(requestId);
    }
}

проиллюстрировать:

Местный код DEMO, без регистрационного центра, метод прямого подключения, так что выше@ReferenceСоответствующая информация об URL-адресе (конкретный IP-адрес и порт протокола dubbo службы прямого подключения) указана в файлах .

2.3.2 Включить поддержку dubbo в классе запуска

следующим образом:

@SpringBootApplication
@EnableDubbo(scanBasePackages = {"com.vzn.local.dubbo.consumer.service"})
public class ConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApp.class);
    }
}

2.3.3 Вручную введите информацию о конфигурации, связанной с DUBBO в код

Как и в случае с Provider, он немного отличается:

@Configuration
public class DubboConfig {

    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-consumer");
        return applicationConfig;
    }

    @Bean
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("N/A");
//        registryConfig.setAddress("zookeeper://127.0.0.1:2181");
        registryConfig.setClient("curator");
        return registryConfig;
    }

    @Bean
    public ConsumerConfig consumerConfig() {
        ConsumerConfig consumerConfig = new ConsumerConfig();
        consumerConfig.setTimeout(3000);
        return consumerConfig;
    }
}

или непосредственно вapplication.propertiesСредняя конфигурация:

spring.application.name=dubbo-consumer
server.port=28812

# dubbo config
dubbo.application.id=dubbo-consumer
dubbo.application.name=dubbo-consumer
dubbo.protocol.name=dubbo
dubbo.registry.address=N/A
dubbo.registry.client=curator

dubbo.server=false
dubbo.consumer.timeout=3000

В сфере бытового обслуживания дополнительноConsumerConfigконфигурации этот пример просто определяет значение тайм-аута вызывающего объекта.

2.3.4 Предоставление услуги контроллера для тестовых вызовов

В соответствии с общей практикой SpringBoot для запуска тестового использования предоставляется служба контроллера.

@RestController
@RequestMapping("/demo/dubbo")
public class RpcController {

    @Resource(name = "rpcConsumerService")
    private RpcConsumerService service;

    @GetMapping("/get/time/{requestId}")
    public String getTime(@PathVariable("requestId") String requestId) {
        String time = service.getTime(requestId);
        System.out.println("RPC call the getTime result:" + time);
        return time;
    }
}

Пока реализован простой клиентский сервис Dubbo, реализованный SpringBoot.После запуска вызовите сервис контроллера, чтобы проверить эффект.

2.4 Проверка тестового звонка

Последовательно запустите службы Provider и Consumer, а затем отправьте уведомление в браузере, чтобы активировать метод службы Consumer:

http://127.0.0.1:28812/demo/dubbo/get/time/1

Результаты теста:

1|2019-12-23 14:21:11.463

Можно обнаружить, что когда метод в потребителе выполняется, соответствующий метод в процессе-поставщике вызывается RPC из процесса-потребителя, и возвращается конкретный результат выполнения метода, и проверка теста завершена.


Добро пожаловать, чтобы обратить внимание на мой общедоступный номер"Примечания по архитектуре», оригинальные технические статьи будут опубликованы как можно скорее, и вы также сможете общаться и обсуждать коммуникационные технологии вместе.