springboot集成dubbo踩坑文档
zookeeper
下载zookeeper,解压到路径
/Users/chen/MyWorkProgram/apache-zookeeper-3.6.2-bin
然后到下级目录config中copy文件zoo_sample.cfg,改名为zoo.cfg
zoo.cfg文件内容如下:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper/data
clientPort=2181
dataLogDir=/tmp/zookeeper/log
启用zookeeper:
zkserver.sh start
2. 总结:springboot引入dubbo依赖及版本
<!-- dubbo start -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.0.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.0.2.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery</artifactId>
<version>4.2.0</version>
</dependency>
<!-- dubbo end -->
dubbo配置文件如下:
dubbo:
application:
name: dubbo-micro
registry:
address: zookeeper://127.0.0.1:2181 #注册zookeeper的地址
timeout: 2000000
protocol:
name: dubbo
port: 20878
consumer:
check: false #不检查消费者对应的生产者是否存在
编写项目代码及踩坑
micro模块:dubbo的consumer方
项目主启动类添加注解:@EnableDubbo
使用@DubboReference注解,调用dubbo生产者
@DubboReference
private TestApi testApi;
- 启动项目报错如下:
Caused by: java.lang.ClassNotFoundException: org.apache.curator.framework.CuratorFrameworkFactory
main模块缺少依赖:
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
- 添加后,再次启动项目报错如下:
ClassNotFoundException: org.apache.curator.framework.recipes.cache.NodeCacheListener
main模块缺少依赖:
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.8.0</version>
</dependency>
- 添加后,再次启动项目报错如下:
ClassNotFoundException: org.apache.curator.x.discovery.ServiceDiscoveryBuilder
main模块缺少依赖:
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-x-discovery -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery</artifactId>
<version>5.1.0</version>
</dependency>
添加后成consumer功启动(注意,这里把dubbo.consumer.check关闭了,启动成功):
order模块:dubbo的provider方
父模块添加如下依赖,用于管理依赖版本
<!-- dubbo start -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.0.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.0.2.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery</artifactId>
<version>5.1.0</version>
</dependency>
<!-- dubbo end -->
main模块添加依赖:
<!-- dubbo start -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery</artifactId>
</dependency>
<!-- dubbo end -->
service添加依赖:
<!-- dubbo start -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!-- dubbo end -->
主启动类添加注解:
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
@EnableDubbo
在api创建接口用于外部调用:
public interface TestApi {
void testDubbo();
}
在service接口继承TestApi:
#DubboService注解将接口注册到dubbo
@DubboService(interfaceClass = TestApi.class,version = "1.0.0")
@Component
public class TestService implements TestApi{
@Override
public void testDubbo() {
System.out.println("testApi调用到了");
}
}
启动order项目报错:
Action:
Correct the classpath of your application so that it contains compatible versions of the classes org.apache.curator.x.discovery.details.ServiceDiscoveryImpl and org.apache.curator.framework.api.CreateBuilder
2022-02-23 16:37:31.902 WARN 48028 --- [ main] ConfigServletWebServerApplicationContext : Exception thrown from ApplicationListener handling ContextClosedEvent
java.lang.RuntimeException: java.lang.RuntimeException: org.apache.curator.framework.api.DeleteBuilder.guaranteed()Ljava/lang/Object;
版本冲突:
将父模块的pom.xml文件中的依赖版本
- curator-framework
- curator-recipes
- curator-x-discovery
全部改成4.2.0版本,然后启动order,启动成功
zookeeper查看dubbo
#启动客户端
chen@localhost bin % ./zkCli.sh
#查看日志
[zk: localhost:2181(CONNECTED) 0] ls /dubbo
[com.example.TestApi, config, mapping, metadata]
#查看指定服务的消费者如下:消费者注册成功
[zk: localhost:2181(CONNECTED) 119] ls /dubbo/com.example.TestApi/consumers
[dubbo%3A%2F%2F192.168.1.165%2Fcom.example.TestApi%3Fapplication%3Ddubbo-micro%26category%3Dconsumers%26check%3Dfalse%26dubbo%3D2.0.2%26interface%3Dcom.example.TestApi%26metadata-type%3Dremote%26methods%3DtestDubbo%26pid%3D47447%26qos.enable%3Dfalse%26release%3D3.0.2.1%26side%3Dconsumer%26sticky%3Dfalse%26timestamp%3D1645602972378]
#查看指定服务的生产者如下:生产者注册成功
[zk: localhost:2181(CONNECTED) 2] ls /dubbo/com.example.TestApi/providers
[dubbo%3A%2F%2F192.168.1.165%3A20879%2Fcom.example.TestApi%3Fanyhost%3Dtrue%26application%3Ddubbo-order%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dcom.example.TestApi%26metadata-type%3Dremote%26methods%3DtestDubbo%26pid%3D47966%26release%3D3.0.2.1%26revision%3D1.0.0%26service-name-mapping%3Dtrue%26side%3Dprovider%26timestamp%3D1645605185700%26version%3D1.0.0]
测试
将micro模块的yml中的dubbo.consumer.check=false注释,重新启动,报错如下:
java.lang.IllegalStateException: Failed to check the status of the service com.example.TestApi. No provider available for the service com.example.TestApi from the url dubbo://192.168.1.165/com.example.TestApi?application=dubbo-micro&dubbo=2.0.2&interface=com.example.TestApi&metadata-type=remote&methods=testDubbo&pid=48277&qos.enable=false®ister.ip=192.168.1.165&release=3.0.2.1&side=consumer&sticky=false×tamp=1645606944192 to the consumer 192.168.1.165 use dubbo version 3.0.2.1
经查:provider
//provider的版本指定为1.0.0
@DubboService(interfaceClass = TestApi.class,version = "1.0.0")
zookeeper中provider的信息,尾部标注version:version=1.0.0
[dubbo%3A%2F%2F192.168.1.165%3A20879%2Fcom.example.TestApi%3Fanyhost%3Dtrue%26application%3Ddubbo-order%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dcom.example.TestApi%26metadata-type%3Dremote%26methods%3DtestDubbo%26pid%3D48223%26release%3D3.0.2.1%26revision%3D1.0.0%26service-name-mapping%3Dtrue%26side%3Dprovider%26timestamp%3D1645606764608%26version%3D1.0.0]
而micro在消费的时候没有指定provider的版本,更正为:
@DubboReference(version = "1.0.0")
private TestApi testApi;
至此:micro通过dubbo调用order接口调试成功
注意事项:
- dubbo-spring-boot-starter,dubbo,curator-framework,curator-recipes,curator-x-discovery的版本问题
- provider指定版本后,consumer也要指定相同版本
- 如果调用的时候传输的参数是对象,记得实现序列化(在远程调用过程中函数不在同一个内存里,无法直接传递函数的参数,因此需要客户端把参数转换成字节流,传给服务端,然后服务端将字节流转换成自身能读取的格式,是一个序列化和反序列化的过程。)
- dubbo采用的是RPC调用,micro服务调用order服务中的方法时,先把参数序列化打包传输给order,order接收包之后解析,得到对应的调用函数的函数指针,调用函数,把返回的参数序列化,打包返回给micro,micro解析处理,至此调用链路完成(寻找调用的函数指针:order端在本地维护一个Call ID到函数指针的映射call_id_map,可以用Map<String, Method> callIdMap,order根据请求包解析出key值:Call ID,得到value值:函数指针)