本项目使用当前(2018年7月)最新的官方正式版本实践,SpringBoot 2.0.3+dubbo-spring-boot-starter 0.2.0(即dubbo2.6.2)+zookeeper集群
文章主要参考了Dubbo在Apache的项目主页的文档,还有Dubbo Spring Boot 工程在github的说明和例子
文章写得较繁琐,重点在后半部分
项目GitHub地址:https://github.com/linshenkx/dubbo-springboot
项目名为dubbo,其下分3个模块base-interface,provider和consumer
新建dubbo项目,在dubbo项目下添加base-interface,provider和consumer 3个模块
修改各个模块pom文件,组成项目结构,具体如下
注意,这里的packing是pom,子模块为jar
而且,子模块不定义groupId和version,即跟随主项目的groupId和version
另外,这里的插件是maven-deploy-plugin,并没有spring-boot-maven-plugin,因为一些子模块不需要(如base-interface)
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.linshen.dubbogroupId>
<artifactId>dubboartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>pompackaging>
<name>dubboname>
<description>Demo project for Spring Bootdescription>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.0.1.RELEASEversion>
parent>
<modules>
<module>base-interfacemodule>
<module>providermodule>
<module>consumermodule>
modules>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
<dubbo-springboot.version>0.2.0dubbo-springboot.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.bootgroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
<version>${dubbo-springboot.version}version>
dependency>
<dependency>
<groupId>com.alibaba.bootgroupId>
<artifactId>dubbo-spring-boot-actuatorartifactId>
<version>${dubbo-springboot.version}version>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-deploy-pluginartifactId>
<configuration>
<skip>trueskip>
configuration>
plugin>
plugins>
build>
project>
注意,这里没有引入spring-boot-maven-plugin插件,因为base-interface并不是一个真正的SpringBoot项目,也没有启动类
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<artifactId>base-interfaceartifactId>
<name>base-interfacename>
<parent>
<groupId>com.linshen.dubbogroupId>
<artifactId>dubboartifactId>
<version>0.0.1-SNAPSHOTversion>
parent>
project>
注意这里引入了actuator,非必须,也可以去掉的
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<artifactId>providerartifactId>
<packaging>jarpackaging>
<name>providername>
<description>Demo project for Spring Bootdescription>
<parent>
<groupId>com.linshen.dubbogroupId>
<artifactId>dubboartifactId>
<version>0.0.1-SNAPSHOTversion>
<relativePath>../pom.xmlrelativePath>
parent>
<dependencies>
<dependency>
<groupId>com.linshen.dubbogroupId>
<artifactId>base-interfaceartifactId>
<version>${project.version}version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.alibaba.bootgroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>com.alibaba.bootgroupId>
<artifactId>dubbo-spring-boot-actuatorartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<executions>
<execution>
<goals>
<goal>repackagegoal>
goals>
execution>
executions>
plugin>
plugins>
build>
project>
consumer比provider多了web依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(ProviderApplication.class)
.web(WebApplicationType.NONE)
.run(args);
}
}
至此,项目搭建完毕
按照前文讲的,我们来实现最基础的问候功能(hello和goodbye)
如下,是一个很单纯的接口
public interface HelloService {
String sayHello(String name);
String sayGoodbye(String name);
}
如下,重点在于@Service
注解
@Service(
version = "${hello.service.version}",
application = "${dubbo.application.id}",
protocol = "${dubbo.protocol.id}",
registry = "${dubbo.registry.id}"
)
public class DefaultHelloService implements HelloService {
@Override
public String sayHello(String name) {
return "Hello "+name+" !";
}
@Override
public String sayGoodbye(String name) {
return "Goodbye "+name+" !";
}
application.yml文件如下:
注意,dubbo.registry.address请设置为真实zookeeper地址,我这里用的是zookeeper集群,具体可参考上一篇文章:SpringBoot2+Dubbo 学习系列1:使用Docker部署zookeeper
如果要简单的话可以像官方教程一样直接用广播,这样就不需要使用注册中心了(相应的,就不能指定dubbo.registry.protocol)
dubbo.registry.id = my-registry
dubbo.registry.address = N/A
另外注意这里给了dubbo.protocol的参数,因为provider是要通过dubbo协议来提供服务的(当然也可以用其他协议,这里不展开)
spring:
application:
name: linshen-dubbo-provider1
server:
port: 9090
dubbo:
registry:
protocol: zookeeper
address: ip:2181,ip:2182,ip:2183
id: lin-registry-1
protocol:
port: 12345
name: dubbo
id: dubbo
status: server
application:
name: linshen-dubbo-provider-name1
id: linshen-dubbo-provider-id1
qos-enable: true
qos-port: 22222
scan:
basePackages: com.linshen.dubbo.provider.service
hello:
service:
version: 1.0.0
如下,重点在于@Reference
注意,下面的注解中在官方给的例子中是把registry换成url,如**url = “dubbo://localhost:12345”**来指定dubbo服务地址,这样下面yml文件就可以不用写dubbo.registry板块了(毕竟官方给的例子没有真正的注册中心),但我还是觉得使用一开始就使用zookeeper会更加自然,更容易理解
@RestController
public class HelloController {
@Reference(
version = "${hello.service.version}",
application = "${dubbo.application.id}",
registry = "${dubbo.registry.id}"
)
private HelloService helloService;
@GetMapping("hello/{name}")
public String sayHello(@PathVariable String name){
return helloService.sayHello(name);
}
@GetMapping("goodbye/{name}")
public String sayGoodbye(@PathVariable String name){
return helloService.sayGoodbye(name);
}
}
application.yml文件如下:
注意,这里我开启了actuator
spring:
application:
name: linshen-dubbo-consumer1
server:
port: 9091
hello:
service:
version: 1.0.0
dubbo:
application:
id: linshen-dubbo-consumer-id1
name: linshen-dubbo-consumer-name1
registry:
protocol: zookeeper
address: ip:2181,ip:2182,ip:2183
id: lin-registry-1
management:
endpoint:
dubbo-configs:
enabled: true
dubbo:
enabled: true
dubbo-services:
enabled: true
dubbo-properties:
enabled: true
dubbo-shutdown:
enabled: true
dubbo-references:
enabled: true
health:
dubbo:
status:
defaults: memory
extras: load,threadpool
endpoints:
web:
exposure:
include: '*'
需要注意的是,如果想要执行插件的jar打包,run启动等命令,需要先在根项目下运行mvn install
,注意不是mvn install-install
,否则会出现Failed to collect dependencies
问题
如图是只是日志的一部分,其中红线为本机ip,蓝线为zookeeper所在主机ip,绿框为连接建立状态,从日志中也可以看出来,大概流程是先初始化客户端连接到zookeeper集群,在开通一个socket连接到一台zookeeper主机,接着就注册当前客户端信息(包含dubbo协议地址,服务信息等等,如截图),然后与注册中心建立连接完成,会话建立,状态更改为CONNECTED,然后注册中心会订阅此provider信息并通知所有订阅此provider信息的url.(这个流程只是从日志上粗略地看的,并不一定准确)
前面和provider差不多,也是要把自身注册到zookeeper上的,注册完后还会多一些步骤,如下图
可以很直观地看到,注册完之后红线比蓝线要多得多,因为注册完之后就和zookeeper没什么事了,consumer从注册中心获得provider的信息后,便直接和provider建立连接,如图中所示,是通过NettyClient建立的连接,然后从注册中心查阅特定的dubbo service服务,然后建立引用关系
以简单地查看dubbo信息为例:
dubbo还开放了很多其他的endpoint来监控
如dubbo/configs查看配置信息,dubbo/references查看引用实体等.
需要注意的是,由于使用的是SpringBoot2,所以Actuator的基础路径是ip:port/actuator,以前只是ip:port而已,这一点在dubbo的官方说明里还没有更改,详情请看Spring Boot 2.0官方文档之 Actuator
到目前来看监控还是很不方便的,特别是当服务较多的时候,我们都值得Spring Cloud的服务治理中心是有终端网页的,图形化界面,关系看起来非常直观,舒服,当然Dubbo也有,而且还原生支持中文,那就是Dubbo Admin,只不过它得另外部署,界面如下,部署放在下一篇文章说:Spring Boot 2+Dubbo 学习系列3:dubbo-ops 之 Dubbo Admin
dubbo官网:http://dubbo.apache.org
dubbo指南:http://start.dubbo.io/
dubboGitHub中文指南:https://github.com/apache/incubator-dubbo-spring-boot-project/blob/master/README_CN.md
Spring Boot 2+gRPC 学习系列1:搭建Spring Boot 2+gRPC本地项目:https://blog.csdn.net/alinyua/article/details/83030149
Spring Boot 2+gRPC 学习系列2:搭建Spring Cloud +gRPC集群项目:https://blog.csdn.net/alinyua/article/details/83043823
Spring Boot 2+Dubbo 学习系列1:使用Docker部署zookeeper:https://blog.csdn.net/alinyua/article/details/81016734
Spring Boot 2+Dubbo 学习系列2:搭建Spring Boot 2+Dubbo+Zookeeper集群:https://blog.csdn.net/alinyua/article/details/81019925
Spring Boot 2+Dubbo 学习系列3:dubbo-ops 之 Dubbo Admin:https://blog.csdn.net/alinyua/article/details/81034023
linshenkx/grpc-springboot-cloud(Spring Cloud +gRPC集群项目):https://github.com/linshenkx/grpc-springboot-cloud
linshenkx/grpc-springboot-lin(Spring Boot 2+gRPC本地项目):https://github.com/linshenkx/grpc-springboot-lin
linshenkx/spring-cloud-lin(Spring Boot 2整合Spring Cloud):https://github.com/linshenkx/spring-cloud-lin