Dubbo实践

Posted 浪颠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo实践相关的知识,希望对你有一定的参考价值。

Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和Spring框架无缝集成。
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
--(摘自《百度百科》)

演示远程调用和服务自动注册和和发现。首先demo结构如图所示:

 

dubbo-api module提供接口服务,dubbo-consumer module是消费者,dubbo-provider module是服务提供者,dubbo-consumer和dubbo-provider同时依赖于dubbo-appi.

dubbo-api module仅仅提供接口,没有其他逻辑。

dubbo-api的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.12</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <groupId>com.mike.study</groupId>
  <artifactId>dubbo-api</artifactId>
  <version>0.0.1</version>
  <name>dubbo-api</name>
  <description>Demo project for Spring Boot</description>
  <properties>
    <java.version>8</java.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

接口类UserService,设定一个login的方法。

import com.mike.study.domain.UserInfo;

public interface UserService 
  UserInfo login(UserInfo userInfo);

同时,方便统一管理对象,设定demain.UserInfo类, 由于实体类是要在网上传输,所以实体类是需要继承Serializable接口,否则会报错。

import java.io.Serializable;

public class UserInfo implements Serializable 
  private String account;
  private String password;

  public String getAccount() 
    return account;
  

  public void setAccount(String account) 
    this.account = account;
  

  public String getPassword() 
    return password;
  

  public void setPassword(String password) 
    this.password = password;
  

至此,api module已经准备完毕。接下来创建provider,提供服务并且注册到zookeeper上。所以要事先准备好zookeeper,参考网上资料,这里不展开介绍安装教程。

dubbo-provider的pom.xml需要引入zookeeper和dubbo相关依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.12</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <groupId>com.mike.study</groupId>
  <artifactId>dubbo-provider</artifactId>
  <version>0.0.1</version>
  <name>dubbo-provider</name>
  <description>Demo project for Spring Boot</description>
  <properties>
    <java.version>8</java.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>com.mike.study</groupId>
      <artifactId>dubbo-api</artifactId>
      <version>0.0.1</version>
    </dependency>

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

    <dependency>
      <groupId>com.101tec</groupId>
      <artifactId>zkclient</artifactId>
      <version>0.10</version>
    </dependency>

    <dependency>
      <groupId>org.apache.zookeeper</groupId>
      <artifactId>zookeeper</artifactId>
      <version>3.4.10</version>
      <exclusions>
        <exclusion>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
        <exclusion>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

配置application.yml文件,设置好zookeeper的地址,dubbo框架会把服务自动注册到zookeeper上,避免同时启动会和consumer的端口有冲突,需要设定provider的端口为8081。

 spring:
   dubbo:
     application:
       name: dubbo-provider
     protocol:
       name: dubbo
       port: 20880
     registry:
       address: zookeeper://127.0.0.1:2181
 server:
   port: 8081

接下来,实现服务的逻辑,这里简单修改下user信息后直接返回出去。

 import com.alibaba.dubbo.config.annotation.Service;
 import com.mike.study.api.UserService;
 import com.mike.study.domain.UserInfo;
 import org.springframework.stereotype.Component;
 
 @Component
 @Service
 public class UserServiceImpl implements UserService 
   @Override
   public UserInfo login(UserInfo userInfo) 
     UserInfo reUser = new UserInfo();
     reUser.setAccount("账号:"+ userInfo.getAccount());
     reUser.setPassword("密码:"+ userInfo.getPassword());
 
     return reUser;
   
 

这里用到了2个注解,@Component将当前类交给springboot容器管理,@Service是dubbo的注解,将接口注册到zookeeper上供订阅者使用。

注意,上面注解外,还需要在启动类添加注解来启动dubbo自动配置。

 import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.context.ConfigurableApplicationContext;
 
 @SpringBootApplication
 @EnableDubboConfiguration // 启用dubbo自动配置
 public class DubboProviderApplication 
 
   public static void main(String[] args) 
     ConfigurableApplicationContext
             context = SpringApplication.run(DubboProviderApplication.class, args);
   
 
 

自此,provider也准备好,最后看consumer如何消费服务。

dubbo-consumer由于是要冲zookeeper上拿到接口,所以也要引入zookeeper等相关依赖。

 <?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>2.7.12</version>
     <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>com.mike.study</groupId>
   <artifactId>dubbo-consumer</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>dubbo-consumer</name>
   <description>Demo project for Spring Boot</description>
   <properties>
     <java.version>8</java.version>
   </properties>
   <dependencies>
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
 
     <dependency>
       <groupId>com.mike.study</groupId>
       <artifactId>dubbo-api</artifactId>
       <version>0.0.1</version>
     </dependency>
 
     <dependency>
       <groupId>com.alibaba.spring.boot</groupId>
       <artifactId>dubbo-spring-boot-starter</artifactId>
       <version>2.0.0</version>
     </dependency>
 
     <dependency>
       <groupId>com.101tec</groupId>
       <artifactId>zkclient</artifactId>
       <version>0.10</version>
     </dependency>
 
     <dependency>
       <groupId>org.apache.zookeeper</groupId>
       <artifactId>zookeeper</artifactId>
       <version>3.4.10</version>
       <exclusions>
         <exclusion>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-log4j12</artifactId>
         </exclusion>
         <exclusion>
           <groupId>log4j</groupId>
           <artifactId>log4j</artifactId>
         </exclusion>
       </exclusions>
     </dependency>
 
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-test</artifactId>
       <scope>test</scope>
     </dependency>
   </dependencies>
 
   <build>
     <plugins>
       <plugin>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-maven-plugin</artifactId>
       </plugin>
     </plugins>
   </build>
 
 </project>

同样配置application.yml,指定zookeeper和服务端口。

 spring:
   dubbo:
     application:
       name: dubbo-consumer
     protocol:
       name: dubbo
       port: 20880
     registry:
       address: zookeeper://127.0.0.1:2181
 server:
   port: 8082

添加一个controller层用来调用UserService服务,添加  @Reference注解拿到provider的远程接口。

 import com.alibaba.dubbo.config.annotation.Reference;
 import com.mike.study.api.UserService;
 import com.mike.study.domain.UserInfo;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 
 @RestController
 public class UserController 
   @Reference
   UserService userService;
 
   @GetMapping("/login")
   public UserInfo login(UserInfo userInfo)
     UserInfo result = userService.login(userInfo);
     return  result;
   
 

同样,consumer也要启动dubbo的自动配置。

 import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 
 @SpringBootApplication
 @EnableDubboConfiguration
 public class DubboConsumerApplication 
 
   public static void main(String[] args) 
     SpringApplication.run(DubboConsumerApplication.class, args);
   
 
 

依次跑起zookeeper,provider服务,consumer服务。查看zookeeper的节点,可以看到,consumer和provider节点。

 在浏览器上访问consumer:http://localhost:8082/login?account=test&password=123,效果如下

 

Dubbo 专题(基础篇):Dubbo 介绍环境搭建与实践

前几天复习了 Dubbo 相关的技术点,趁热打铁记录一下,本篇博客属于 Dubbo 的入门基础篇,内容主要包括 Dubbo 概念Dubbo 特点Dubbo 基本工作原理Dubbo 环境搭建Dubbo Demo 实践,一起来学习下吧。


Dubbo 概念

Dubbo 是一款高性能、轻量级的开源 Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用智能容错和负载均衡,以及服务自动注册和发现

Dubbo 同时也是一个分布式服务框架,用于多个系统间的相互调用的。基于这个功能,然后又衍生出服务的注册、发现,监控、路由、治理,多协议支持等。

要理解概念,首先就要知道概念中涉及的技术点,先来介绍下什么是 RPC。

RPC

RPC,全称:Remote Procedure Call,即:“远程过程调用”,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络通信的规范或协议,可以理解为一台计算机程序远程调用另外一台计算机的子程序,而不用关心底层网络通信。通俗来说,就是客户端在不知道调用细节的情况下,调用存在于远程计算机上的某个对象,就像调用本地应用程序中的对象一样。

介绍了 RPC,还需要了解下什么是分布式。

分布式

分布式是一种模型结构,区别于核心式,可以从字面理解为 “分布在各处”。

之前自己在学习的时候经常会混淆分布式和集群的概念,在这里我们就把他们放在一起进行比较分析,便于大家加深理解。

集群是个物理形态,分布式是个工作方式

也就是说,集群是指同一种组件的多个实例形成的逻辑上的整体。

而分布式是指通过网络连接的多个组件,通过交换信息协作而形成的系统,它更强调信息的交换与协作。这两个概念并不完全冲突,有时分布式系统也可以是一个集群。

举个例子,比如一堆人在干一样的工作,那么他们本身就构成了一个集群。

而一旦这堆人工作的时候进行了交流与协作,不管干的活是否一样,他们之间就是分布式的工作方式。刚刚说到的 ”分布式系统也可以是一个集群“ 是指,如果这堆人采用了交流协作的工作方式,同时干的工作一样,那也是一个集群。

从分布式的概念出发,我们就可以更好的理解 Dubbo,说白了它的主要意义就在于简化服务提供方和服务消费方之间的调用流程,能够让双方进行更方便的沟通与协作


Dubbo 特点

面向接口代理的高性能RPC调用
提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用底层细节。

智能负载均衡
内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。

服务自动注册与发现
支持多种注册中心服务,服务实例上下线实时感知。

高度可扩展能力
遵循微内核+插件的设计原则,所有核心能力如Protocol、Transport、Serialization被设计为扩展点,平等对待内置实现和第三方实现。

运行期流量调度
内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。

可视化的服务治理与运维
提供丰富服务治理、运维工具:随时查询服务元数据、服务健康状态及调用统计,实时下发路由策略、调整配置参数。


Dubbo 基本工作原理

从上图中我们可以看到,Dubbo 中的节点主要分为 5 种角色,具体说明如下:

节点名称说明
Provider暴露服务的服务提供方。
Consumer调用远程服务的服务消费方。
Registry服务注册与发现的注册中心(默认选择 Zookeeper 作为注册中心)。
Monitor统计服务的调用次数和调用时间的监控中心。
Container服务运行容器。

Dubbo 的组成看似简单,但是内部包含了丰富的实现细节,可以说是 “麻雀虽小,五脏俱全”,它的工作流程如下:

  • 启动容器,加载和运行服务提供者;
  • 服务提供者在启动时,在注册中心发布注册自己提供的服务;
  • 服务消费者在启动时,在注册中心订阅自己所需的服务;
  • 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者;
  • 服务消费者从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用;
  • 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

到现在,Dubbo 的概念、特点、基本工作原理都清晰了,最后来上手实践,一起搭建下 Dubbo 的环境吧!


Dubbo 环境搭建

搭建注册中心

1.下载 ZooKeeper
我们选择 zookeeper-3.4.11.tar.gz 进行下载,下载路径如下:
https://archive.apache.org/dist/zookeeper/

2.安装 ZooKeeper
我们选择直接本地安装的方式,将压缩包解压后,找到配置文件 conf 中的 zoo_sample.cfg,将其重命名为 zoo.cfg:

打开 zoo.cfg 文件,修改 dataDir 为指定的相对路径,我是在 conf 同级目录下创建了 data 目录并进行指定:

修改完成后,在 bin 目录下打开 cmd 运行 Server.cmd,输出最下面的绑定信息即代表安装完成:

搭建管理控制台

1.进入 GitHub 上管理控制台地址,并下载代码
https://github.com/apache/dubbo-admin

2.打包生成 jar 文件
在 dubbo-admin-master 根目录执行 mvn clean package​​​​​ 命令

看到如上图所示的 BUILD SUCCESS 表示打包成功。

3.运行 jar 文件
通过 cmd 进入如下图所示的路径,执行 java -jar dubbo-admin-server-0.3.0.jar

输出以下内容表示成功启动,我们可以在浏览器访问验证:

4.访问控制台
启动浏览器,输入:http://127.0.0.1:8080/,默认的用户名和密码都是 root,此时就可以进入控制台了。


Dubbo Demo 实践

1.创建工程
创建一个名为 DubboDemo 的 maven 工程;

2.创建服务接口,服务提供者和服务消费者模块
在工程下分别创建三个名为 dubbo-api,dubbo-provider,dubbo-consumer 的 maven module,模块名称和作用如以下表格所示:

模块名称模块作用
dubbo-api存放公共接口;
dubbo-consumer调用远程服务;
dubbo-provider提供远程服务;

创建完成的目录如图:

3.构建 maven 项目,导入所需要的 jar 包依赖
(详情参看后面提供的项目代码)

4.编写代码实现功能
在模块 dubbo-api 中创建一个名为 com.alibaba.dubbo.demo 的包,在包下创建一个名为DemoService 的接口,接口代码如下:

package com.alibaba.dubbo.demo;
import java.util.List;

public interface DemoService 
   List<String> getPermissions(Long id);

4.1 dubbo-provider 功能实现
加入公共接口所在的依赖

<dependency>
    <groupId>org.example</groupId>
    <artifactId>dubbo-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

在 resources 下添加配置文件:provider.xml,用 Spring 配置声明暴露服务:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://code.alibabatech.com/schema/dubbo
       http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <!--定义了提供方应用信息,用于计算依赖关系;在 dubbo-admin 或 dubbo-monitor 会显示这个名字,方便辨识-->
    <dubbo:application name="demo-provider" owner="programmer" organization="dubbox"/>
    <!--使用 zookeeper 注册中心暴露服务,注意要先开启 zookeeper-->
    <dubbo:registry address="zookeeper://localhost:2181"/>
    <!-- 用dubbo协议在20881端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20881"/>
    <!--使用 dubbo 协议实现定义好的 api.PermissionService 接口-->
    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" protocol="dubbo" />
    <!--具体实现该接口的 bean-->
    <bean id="demoService" class="com.alibaba.dubbo.demo.impl.DemoServiceImpl"/>
</beans>

创建一个名为 com.alibaba.dubbo.demo.impl 的包,在该包下新建一个名为 DemoServiceImpl 并实现 DemoService 接口,代码如下:

package com.alibaba.dubbo.demo.impl;
import com.alibaba.dubbo.demo.DemoService;
import java.util.ArrayList;
import java.util.List;
public class DemoServiceImpl implements DemoService 

   public List<String> getPermissions(Long id) 
       List<String> demo = new ArrayList<String>();
       demo.add(String.format("Permission_%d", id - 1));
       demo.add(String.format("Permission_%d", id));
       demo.add(String.format("Permission_%d", id + 1));
       return demo;
   

编写服务提供方启动类,具体代码如下:

package com.alibaba.dubbo.demo.impl;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;

public class Provider 

    public static void main(String[] args) throws IOException 
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
        System.out.println(context.getDisplayName() + ": here");
        context.start();
        System.out.println("服务已经启动...");
        System.in.read();
    

启动服务:
4.2 dubbo-consumer 功能实现
加入公共接口所在的依赖

<dependency>
    <groupId>org.example</groupId>
    <artifactId>dubbo-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

在 resources 下添加配置文件:consumer.xml,通过 Spring 配置引用远程服务:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <dubbo:application name="demo-consumer" owner="programmer" organization="dubbox"/>
    <!--向 zookeeper 订阅 provider 的地址,由 zookeeper 定时推送-->
    <dubbo:registry address="zookeeper://localhost:2181"/>
    <!--使用 dubbo 协议调用定义好的 api.PermissionService 接口-->
    <dubbo:reference id="permissionService" interface="com.alibaba.dubbo.demo.DemoService"/>
</beans>

在 demo-consumer 模块中创建名为 com.alibaba.dubbo.demo 的包,并在该包下创建Consumer 类,具体代码如下:

package com.alibaba.dubbo.demo;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Consumer 
    public static void main(String[] args) 
        //测试常规服务
        ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("consumer.xml");
        context.start();
        System.out.println("consumer start");
        DemoService demoService = context.getBean(DemoService.class);
        System.out.println("consumer");
        System.out.println(demoService.getPermissions(1L));
    

5.运行项目,先确保 provider 已被运行后再启动 consumer 模块

可以看到,这里已经接受到了来自 provider 提供者发送的数据。

项目代码参考了如下链接:
https://github.com/GenshenWang/DubboDemo

本篇博客介绍了 Dubbo 入门概念,工作原理和环境搭建,下一篇我们将针对 Dubbo 与 SpringBoot 的整合与配置进行介绍。


本篇博客参考了以下资料,在此表示特别感谢:

https://www.zhihu.com/question/20004877
https://segmentfault.com/a/1190000019896723
https://blog.csdn.net/Future_LL/article/details/104156396
https://segmentfault.com/a/1190000011913838
https://cloud.tencent.com/developer/article/1345955

以上是关于Dubbo实践的主要内容,如果未能解决你的问题,请参考以下文章

Dubbo 专题(基础篇):Dubbo 介绍环境搭建与实践

Dubbo 专题(基础篇):Dubbo 介绍环境搭建与实践

dubbo源码实践-总结

dubbo源码实践-总结

dubbo实践

Dubbo——Dubbo中的常用标签服务化最佳实践