🤔为什么要双注册中心?
当前 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 接口
🛠️创建一个服务消费者
消费者基本和服务提供者配置相同,只是要额外加上 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
节点,这个节点下面有我们注册上去是服务消费者。
这时候我们直接访问 [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
节点下面看到我们的服务了
同样的我们可以看到注册上去到数据:
{ "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