本文讲述了 Dubbo 直连的几种实现方式以及我在进行直连调试的时候遇到的几个问题。
1. Dubbo 直连的几种方式
在 Dubbo 官网的直连提供者这篇文章中向开发者介绍了绕过注册中心,直接通过ip+端口指定服务提供者的直连方式。
需要注意的是:官方建议直连方式仅开发测试时使用!
Dubbo 直连有4种实现方式:
1.1 通过 XML 配置
<dubbo:reference id="xxxService" interface="com.alibaba.XxxService" url="dubbo://localhost:20890" />
1.2 通过注解方式配置
@Reference(check = false, timeout = 60000, url = "localhost:20890")
private XxxService xxxService;
1.3 通过 -D 参数指定接口
java -Dcom.alibaba.XxxService=dubbo://localhost:20890 -jar Demo.jar
1.4 通过 -D 参数指定映射文件
java -Ddubbo.resolve.file=xxx.properties -jar Demo.jar
然后在 xxx.properties
文件中加入如下配置
com.alibaba.xxx.XxxService=dubbo://localhost:20890
2. 直连调试
在项目中有很多个 Dubbo 接口,而且在线上的某种环境中是没有 zk 注册中心的,出于切换 Dubbo 接口调用方式以及方便管理所有 Dubbo 接口的考虑,我选用的是第四种——通过映射文件实现直连。
注意:本项目使用的 Dubbo 版本是2.6.0。
2.1 @Reference注入为null
刚开始调试的时候,我发现在有注册中心的环境下发现在消费者中无法通过 @Reference
注解注入 Dubbo 接口,开始我以为是 Dubbo 版本的问题,后来将生产者与消费者的 Dubbo 版本号改为一致才发现不是这个原因。自己研究了好久,实在找不到原因了于是寻求身为 Dubbo committer
的同事的帮助才知道原来是在启动类中没有配置 @EnableDubboConfiguration
注解启用 Dubbo 导致的,惭愧惭愧。
2.2 映射文件路径问题排查
在解决了上面的问题之后,首先我在消费者的配置文件中将 Spring.dubbo.registry.address
改为 N/A
,表明不使用注册中心,然后在 resource
目录下新增映射文件dubbo.properties
,同时在映射文件中指定直连接口:
com.alibaba.xxx.XxxService=dubbo://localhost:20891
最后在编译器的 Run/Debug Configuration
中添加如下的启动参数配置:
然后在启动之后却出现了让我差异的报错:
dubbo.properties
文件不存在,开始我以为是 target 目录中没有把这个文件编译进去,因为之前也发生过 idea 编译后某些类和资源文件没有更新的情况,但事实却不是如此,target目录中 dubbo.properties
好端端的在那里。
然后我把编译器 Run/Debug Configuration
配置中的文件名改成了它的绝对路径
-Ddubbo.resolve.file=/Users/fan/workspace/Windfall/src/main/resources/dubbo.properties
发现程序可以正常启动,这样问题就很明显了,绝对是文件路径的锅!
我循着报错的异常栈,在报错的地方打了一个断点进行调试,在新建 FileInputStream
对象打开文件的地方执行了获取 File
对象绝对路径的方法。
dubbo.properties
的绝对路径竟然是这么个玩意,本项目的项目名是 Windfall
,相当于程序会从当前工程目录下寻找映射文件,而我创建文件的路径是 Windfall->src->main->resource
,这当然会找不到。
于是我把启动参数改成了:
-Ddubbo.resolve.file=src/main/resources/dubbo.properties
果然,在编译器中程序正常启动了。
问题就这样解决了,但是让我疑惑的是,为什么我指定了映射文件名之后,它的路径却变成了从当前工程目录下进行寻找。然后我翻了翻 File#getAbsolutePath()
方法,发现这个方法中执行的逻辑其实是这样的:
public String resolve(File f) {
if (isAbsolute(f)) return f.getPath();
return resolve(System.getProperty("user.dir"), f.getPath());
}
如果文件本来就是以绝对路径创建的,直接返回它的 path,否则在 path 前加上 user.dir
作为该文件的绝对路径,而 user.dir
环境变量就是指用户当前工作目录。
2.3 关于 user.dir
还有需要注意的是,在命令行中启动 jar 包,user.dir
的路径就是执行启动命令的目录。
为此,我写了一个测试程序。
public class demo{
public static void main(String[] args) {
System.out.println(System.getProperties("user.dir"));
}
}
先用 javac demo.java
命令编译程序,然后执行java demo
命令启动程序,打印 user.dir
的信息,我在多个目录中都尝试了这个程序,发现输出的结果都不相同。
从程序执行的结果来看,user.dir
的结果就是执行启动命令的路径。所以,在服务器上使用 Dubbo 进行直连的时候,需要注意 dubbo.properties
文件需要放在执行启动脚本的目录。
3. 小结
本文讲述了 Dubbo 直连的几种实现方式以及我在进行直连调试的时候遇到的几个问题:
@EnableDubboConfiguration
注解启用 Dubbonew File()
路径问题user.dir
值问题
4. 参考资料
最后,本文收录于个人语雀知识库: 我所理解的后端技术,欢迎来访。
文档信息
- 本文作者:Planeswalker23
- 本文链接:https://planeswalker23.github.io/2020/09/09/%E6%88%91%E6%89%80%E7%90%86%E8%A7%A3%E7%9A%84%E5%85%B6%E4%BB%96%E9%97%AE%E9%A2%98-%E7%AC%AC9%E7%AF%87-%E7%94%B1Dubbo%E7%9B%B4%E8%BF%9E%E5%BC%95%E5%87%BA%E7%9A%84File%E8%B7%AF%E5%BE%84%E9%97%AE%E9%A2%98/
- 版权声明:本作品系原创,作者保留所有权利,未经作者允许,禁止转载和演绎。