SpringCloudAlibaba学习-加入Dubbo

  • Post author:
  • Post category:其他




前言

上次学习了SpringCloudAlibaba的注册中心+配置中心Nacos,写了一个小Demo,对SpringCloudAlibaba有了一个基本的认知。这次将引入Dubbo,实现服务间的调用。

在接触SpringCloudAlibaba之前,微服务之间的调用,我们最常用的可能是Feign。在上次的Demo中,用的则是LoadBalance的方式。这一次,将试着用Dubbo来实现微服务之间的调用。Dubbo采用RPC的方式来调用,不需要去了解它的底层细节,调用其他服务的方法,就像调用自己的服务本地的方法一样,非常简单自然。比起Feign来说,要更加的直观。而且Dubbo也要求采用接口的方式进行调用,这也是面向接口编程的一种体现。话不多说,我们开始着手改造,将上次的小Demo引入Dubbo吧。



先抽取接口吧

我们上次的Demo,写了一个服务提供者和一个服务消费者,通过LoadBalance的方式进行调用。既然要使用Dubbo,就需要将服务提供者的服务,抽象成一个公共的接口,再由服务提供者和消费者分别进行引用。

首先,我们要新建一个Module作为公共的接口,两个服务都需要引用这个Module。命名为nacos-public-interface。这个Module的pom文件不需要引入什么额外的依赖,我这里只引入了一个lombok的依赖。

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

我们之前的服务,是将返回结果包装成一个实体类进行返回的。那么既然要抽取接口,这个实体类也应该被抽取出来,放在公共的接口中。

还有一点需要注意,实体类需要实现Serializable接口,以供序列化

package com.akitsuki.entity;

import lombok.Data;

import java.io.Serializable;

/**
 * @author ziling.wang@hand-china.com
 * @date 2022/9/27 15:22
 */
@Data
public class EntityInfo implements Serializable {

    private String entityId;
    private String info;
    private String sendTime;
}

然后,将之前的查询方法,包装成接口,我们的这个公共接口Module就算完成了

package com.akitsuki;

import com.akitsuki.entity.EntityInfo;

/**
 * @author ziling.wang@hand-china.com
 * @date 2022/10/13 16:43
 */
public interface IEntityService {
    /**
     * 查询entity 信息
     * @return
     */
    EntityInfo queryEntityInfo(String entityId);
}

接口抽取完了,我们还需要让生产者和消费者分别引用这个接口的依赖,并且移除掉生产者项目中本来的实体类

        <dependency>
            <groupId>com.akitsuki</groupId>
            <artifactId>nacos-public-interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>



开始引入Dubbo依赖

我在操作过程中,发现Dubbo的依赖不是很好拉,所以我加上了阿里云的仓库

    <repositories>
        <repository>
            <id>aliyun</id>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

然后是在父项目的dependencyManagement中,加入dubbo-bom的管理,这里我们用3.0.7版本的dubbo,比较新

            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-bom</artifactId>
                <version>3.0.7</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

关于Dubbo的依赖,这里主要有以下三个:

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-nacos</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>2.0.4</version>
        </dependency>

首先肯定是spring-boot的starter,然后由于我们的注册中心使用的是nacos,所以这里也需要引入dubbo注册到nacos的依赖。最后则是nacos-client的依赖,这个依赖

非常关键

,在我做这个demo的时候,有很多bug都是这个依赖所引起的。首先,必须要引入这个依赖。然后,依赖的版本号也很关键。和3.0.7的Dubbo相匹配的nacos-client,经过我多次实验,就是2.0.4。如果采用其他的版本或者不引入,一般会出现一些class not found之类的报错,或者其他的奇怪错误。



配置文件

dubbo其实提供了很多配置项,但这里我们要实现小demo,只需要不多的几个即可。

dubbo:
  application:
    name: dubbo-provider
  protocol:
    name: dubbo
    port: -1
  registry:
    address: nacos://localhost:8858

可以看到,这里设置了应用名、协议、端口、注册中心地址。这里给出的是生产者的配置,消费者只需要修改一下name即可。这里的端口设置成-1,代表自动选择端口,会从20880开始,由系统自动进行管理。



生产者的改造

生产者的改造主要是将之前的Service实现我们抽取出的公共接口,并且在类上加一个注解@DubboService,来指明当前的类是用于提供给Dubbo服务的,别的服务可以通过Dubbo来调用到这个类。

package com.akitsuki.service;

import com.akitsuki.IEntityService;
import com.akitsuki.entity.EntityInfo;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;

/**
 * @author ziling.wang@hand-china.com
 * @date 2022/9/27 15:23
 */

@DubboService
@Service
public class EntityInfoService implements IEntityService {

    @Override
    public EntityInfo queryEntityInfo(String entityId) {
        EntityInfo entityInfo = new EntityInfo();
        entityInfo.setEntityId(entityId);
        entityInfo.setInfo("Hello Nacos");
        entityInfo.setSendTime(String.valueOf(System.currentTimeMillis()));
        return entityInfo;
    }
}



消费者的改造

消费者的改造要更加简单,就像我们使用依赖注入,注入一个Bean一样。我们可以使用@DubboReference注解来注入这个公共接口。然后,就可以像普通的Bean一样进行使用了,非常方便。

package com.akitsuki.controller;

import com.akitsuki.IEntityService;
import com.alibaba.fastjson.JSON;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * @author ziling.wang@hand-china.com
 * @date 2022/9/27 16:43
 */
@RestController
public class EntityInfoController {

    @Autowired
    private RestTemplate restTemplate;

    @DubboReference
    private IEntityService entityService;

    @GetMapping(value = "/entityInfo/{entityId}")
    public String getEntityInfo(@PathVariable("entityId") String entityId) {
        String url = "http://nacos-provider/entityInfo/" + entityId;
        return restTemplate.getForEntity(url, String.class).getBody();
    }

    @GetMapping(value = "/entityInfo/dubbo/{entityId}")
    public String getEntityInfoByDubbo(@PathVariable("entityId") String entityId) {
        return JSON.toJSONString(entityService.queryEntityInfo(entityId));
    }
}



测试!

我们先启动nacos,然后分别启动生产者和消费者,可以从nacos的服务管理中看到生产者和消费者,以及Dubbo的一些注册。

试着调用一下我们新加的通过Dubbo进行调用的接口

很好,完美运行。这样我们就实现了Dubbo与Nacos的整合,在SpringCloudAlibaba的道路上又前进了一步。



版权声明:本文为Forget_Re原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。