dubbo小技巧之随机port

背景

目前端口问题确实多且恶心

一个应用上线需要关注如下几个问题:

  1. 多环境配置
  2. jenkins构建
  3. 数据库创建和用户权限
  4. 数据库备份增加新库
  5. 端口申请

其中端口申请也是比较麻烦和没有管理的 目前约定俗成用

应用名称+端口号来建立文件夹

但是这个只能涉及到http端口 我们至少还涉及到服务发布【dubbo端口】

分析

本节我们关注一下dubbo的端口

为何我们需要知道端口号呢???

网络通信究竟是如何建立的了???

按照以前的知识使用ip地址不就可以找到目的主机了么【暂时不考虑nat】

上述描述是没错的。但是由于根据ip可以找到主机 但是对应主机却没办法找到哪个进程【此时端口发挥了标志进程的作用===》也就是同一个ip和端口只对应一个进程】

基于上述的描述其实我们就需要知道端口号了。

但是事实上我们真的要知道端口号么???

我们知道dubbo的注册中心【我们约定好将自己的ip和端口放到一个大家都认可的位置】===》不考虑直连

那么从这边可以看出来其实我们是不需要知道端口号的 因为其他调用dubbo的应用会去注册中心获取

那么我们如何配置端口号呢???

可以配置

1
dubbo.port=-1

源码分析

由于我们统一是没有设置端口的 端口设置是从protocol 中继承下来的。

那么关于端口号比如默认从dubbo协议会是20880

我们构建对应socket的时候会如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Integer port = protocolConfig.getPort();
if (provider != null && (port == null || port == 0)) {
port = provider.getPort();
}
final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();
if (port == null || port == 0) {
port = defaultPort;
}
if (port == null || port <= 0) {
port = getRandomPort(name);
if (port == null || port < 0) {
port = NetUtils.getAvailablePort(defaultPort);
putRandomPort(name, port);
}
logger.warn("Use random available port(" + port + ") for protocol " + name);
}

这段代码涉及到了ExtensionLoader去获取对应协议默认端口【对于dubbo就是20880】

8f9824711408c71985574a8512af550d332.jpg

上述代码中很明显当配置的端口号

当配置port为0那么将执行默认端口号 但是port小于0的时候将执行如下代码获取随机端口号【注意同一协议将会复用端口号】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static int getAvailablePort(int port) {
if (port <= 0) {
return getAvailablePort();
}
for(int i = port; i < MAX_PORT; i ++) {
ServerSocket ss = null;
try {
ss = new ServerSocket(i);
return i;
} catch (IOException e) {
// continue
} finally {
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
}
}
}
}
return port;
}

基本上来说上述的port就是协议的默认端口号也就是20880

而dubbo将会建立对应的socket来校验端口号是否能够被使用

因此将可以很方便的产生新的端口号【且不会冲突~】

问题

那我们springboot的暴露端口是否可以随机呢???

如果可以随机要怎么处理,如果不能随机原因是啥???