Dubbo项目双注册中心

🤔为什么要双注册中心?

当前 Dubbo 版本注册粒度是以接口粒度来注册的,而 SpringBoot 是以服务为粒度来注册的。而且 Dubbo 有自己的注册中心(当然 Spring Cloud Alibaba Dubbo 的注册中心可以挂靠在 Spring 上)。所以当一个项目既要调用 Dubbo 服务,又要提供自己的 Web 接口给网关调用时,就要为该项目设置两个注册中心,一个 Dubbo,一个 SpringBoot的(当然可以注册到同一个注册中心上)。

🛠️创建一个 Dubbo 服务提供者

我们先创建一个 Dubbo 服务提供者,然后把它注册到 Zoookeeper 上。我这边用到是 2.7.10 版本到 Dubbo,不同 Dubbo 版本到配置有所差异化。

pom 依赖:

<dependency>
      <groupId>org.apache.dubbo</groupId>
      <artifactId>dubbo-spring-boot-starter</artifactId>
      <version>2.7.10</version>
  </dependency>
  <dependency>
      <groupId>org.apache.dubbo</groupId>
      <artifactId>dubbo-dependencies-zookeeper</artifactId>
      <version>2.7.10</version>
      <type>pom</type>
  </dependency>

然后我们定义一个接口,返回一些文字,记得加上 @DubboService 注解,让 Dubbo 应用发现这个接口并注册到注册 Zookeeper 上。同时在启动类上面还要加上 @EnableDubbo 注解。当然你也可以用配置到方式来配置这些。

@DubboService
public class DemoServiceImpl implements DemoService {
    @Override
    public String hello() {
        return "hello! This is Dubbo's demo";
    }
}

定义好接口后,我们在配置文件加上如下配置:

server:
  port: 8787
dubbo:
  application:
    id: dubbo-privode
  protocol:
    name: dubbo
    port: 28808
  registry:
    address: zookeeper://localhost:2181

在上面配置中,我们定义来项目启动到端口为 8787 ,然后配置了 Dubbo 的协议名称和端口,同时也配置了注册地址为本地的 Zookeeper 的地址。

项目启动后,我们就可以看到 Zookeeper 的节点上多了一个 dubbo 节点,节点下面有我们注册上去的 Dubbo 接口

Dubbo%20%E9%A1%B9%E7%9B%AE%E5%8F%8C%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%20a2369534007b4606b16f9819157f3c3a/Untitled.png

🛠️创建一个服务消费者

消费者基本和服务提供者配置相同,只是要额外加上 web 依赖,应为我们要对外提供 HTTP 接口。

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

然后 yml 配置稍作修改,改下端口什么的

server:
  port: 8788
dubbo:
  application:
    id: dubbo-consumer
  protocol:
    name: dubbo
    port: 28808
  registry:
    address: zookeeper://localhost:2181

配置好后,我们创建一个对外的 HTTP 接口,并且调用上面服务提供者提供的服务,我们可以直接用注解 @DubboReference 来表示我们要调用 Dubbo 服务接口。

@RestController
public class DubboConsumer {
    @DubboReference
    DemoService demoService;

    @GetMapping("/consumer")
    public String dubboDemo(){
        return demoService.hello();
    }
}

启动项目后,注册中心就会出现一个 consumers 节点,这个节点下面有我们注册上去是服务消费者。

Dubbo%20%E9%A1%B9%E7%9B%AE%E5%8F%8C%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%20a2369534007b4606b16f9819157f3c3a/Untitled%201.png

这时候我们直接访问 [http://localhost:8788/consumer](http://localhost:8788/consumer) 地址,页面就会响应 hello! This is Dubbo's demo 字符串,这是我们在服务提供者中定义返回的数据,说明我们成功调用了服务提供者提供的 Dubbo 服务。

🔑为消费者再配置一个注册中心

这时候如果我们网关要调用这个消费者提供的 HTTP 接口怎么办?

你可能会想,可以直接把http://localhost:8788/consumer 这个地址配置到网关路由到 uri 字段上。但是我们一般项目不单单是只有一个,而且有时候地址也会变化,这时候网关就要用到服务名来调用对应到服务,网关一般以 lb://service-name 来调用对应到服务。

如果网关想要以服务名来调用这个消费者,那么我们就要以服务名到方式来把这个消费者注册到 Zookeeper 上。

由于 Spring Cloud 官方已经将 Zookeeper 整合进了 Spring Cloud 体系,所以我们可以直接用 Spring Cloud 下的包。需要添加如下依赖:

<dependencies>
	<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
  </dependency>
</dependencies>

<dependencyManagement>
  <dependencies>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-dependencies</artifactId>
          <version>Hoxton.SR11</version>
          <type>pom</type>
          <scope>import</scope>
      </dependency>
  </dependencies>
</dependencyManagement>

同时配置文件需要再添加如下配置,下面的配置中我们指定了要注册到 Zookeeper 到服务名 dubbo-consumer ,配置了注册中心到地址。

spring:
  application:
    name: dubbo-consumer
  cloud:
    zookeeper:
      connect-string: localhost:2181

同时启动类也要加上 @EnableDiscoveryClient 注解,不然是不会注册到 Zookeeper 上到。

启动项目后,我们就可以在 Zookeeper 的 services 节点下面看到我们的服务了

Dubbo%20%E9%A1%B9%E7%9B%AE%E5%8F%8C%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%20a2369534007b4606b16f9819157f3c3a/Untitled%202.png

同样的我们可以看到注册上去到数据:

{
    "name": "dubbo-consumer",
    "id": "beff8ece-85a3-47ed-bd0b-34fc193eb3f1",
    "address": "169.254.238.114",
    "port": 8788,
    "sslPort": null,
    "payload": {
        "@class": "org.springframework.cloud.zookeeper.discovery.ZookeeperInstance",
        "id": "application-1",
        "name": "dubbo-consumer",
        "metadata": {
            "instance_status": "UP"
        }
    },
    "registrationTimeUTC": 1620123669588,
    "serviceType": "DYNAMIC",
    "uriSpec": {
        "parts": [
            {
                "value": "scheme",
                "variable": true
            },
            {
                "value": "://",
                "variable": false
            },
            {
                "value": "address",
                "variable": true
            },
            {
                "value": ":",
                "variable": false
            },
            {
                "value": "port",
                "variable": true
            }
        ]
    }
}

🍰网关调用

服务注册上去后,我们就可以修改下我们上节网关项目到路由配置,把它改成用服务名调用。我们可以修改 yml 配置,把 uri 改成服务调用的格式

spring:
  cloud:
    gateway:
      routes:
        - id: route-demo
          uri: lb://dubbo-consumer
          predicates:
            - Path=/**

或者如果我们是用 Java 代码方式配置的路由可以改成如下代码:

@Bean
public RouteLocator routesConfig(RouteLocatorBuilder builder){
	return builder.routes()
			.route("route-demo",r -> r.path("/**").uri("lb://dubbo-consumer"))
			.build();
}

修改完成后,启动网关,然后访问网关地址 http://localhost:8080/consumer 就可以看到页面显示 hello! This is Dubbo's demo