一般情况下每个spring boot工程启动都有固定的端口,但是固定端口不利用服务的动态扩容,如果在一台服务器上需要对同一个服务进行多实例部署,很容易出现端口冲突,那么怎么解决这个问题呢?

random随机端口

在spring boot中,可以通过${random}来生成随机数字,我们可以在配置文件中,这么设置端口:

server.port=${random.int(2000,8000)}

通过http://random.int方法,指定生成2000~8000的随机端口。这样每次启动的端口都不一样。

多次启动,发现每次的端口都不一致说明配置成功。

注意事项:

这里需要注意spring boot项目启动属性文件的加载顺序,spring boot的属性是由里向外加载,所以最外层的最后被加载,会覆盖里层的属性。

所以如果主动在启动命令中使用–server.port配置了项目的端口号,那么属性文件中配置的随机端口属性就不会生效。

通过System.setProperty设置有效随机端口

上面的方法虽然暂时达到了想要的效果,但是有个问题:如果生成的这个随机端口已经被使用了,那么项目启动就会出现端口冲突。

那么,我们能否通过一个检测机制,让生成的随机端口一定是一个没有被占用的有效的随机端口呢?

有效端口检测原理:

通过建立socket连接,Socket socket = new Socket(Address,port);#address代表主机的IP地址,port代表端口号

如果对该主机的特定端口号能建立一个socket,则说明该主机的该端口在使用。

Socket socket = new Socket(Address,port);#address代表主机的IP地址,port代表端口号

如果对该主机的特定端口号能建立一个socket,则说明该主机的该端口在使用。

实现思路:

通过在项目启动前,获取有效的随机端口并通过System.setProperty将变量设置到系统的全局变量中,这样项目启动时就可以从全局变量中获取到server.port变量的值。

这里的system,系统指的是 JRE (runtime)system,即设置jvm运行时的全局变量。

工具类:

@Slf4j
public class NetUtils {/*** 测试本机端口是否被使用* @param port* @return*/public static boolean isLocalPortUsing(int port){boolean flag = true;try {//如果该端口还在使用则返回true,否则返回false,127.0.0.1代表本机flag = isPortUsing("127.0.0.1", port);} catch (Exception e) {}return flag;}/**** 测试主机Host的port端口是否被使用* @param host* @param port* @throws UnknownHostException*/public static boolean isPortUsing(String host,int port)  {boolean flag = false;try {InetAddress Address = InetAddress.getByName(host);Socket socket = new Socket(Address,port);  //建立一个Socket连接flag = true;} catch (IOException e) {//log.info(e.getMessage(),e);}return flag;}//start--end是所要检测的端口范围static int start=0;static int end=1024;/*** 由于本机上安装了mysql,采用3306端口去验证* @param args*/public static void main(String args[]){int testPost =3306;if(isLocalPortUsing(testPost)){System.out.println("端口 "+testPost+" 已被使用");}else{System.out.println("端口 "+testPost+"未使用");}}
}
public class ServerPortUtils {/*** 获取可用端口* @return*/public static int getAvailablePort(){int max = 65535;int min = 2000;Random random = new Random();int port = random.nextInt(max)%(max-min +1) + min;boolean using = NetUtils.isLocalPortUsing(port);if(using){return  getAvailablePort();}else{return  port;}}}

项目启动前设置server.port环境变量

/*** 开始命令*/
@Slf4j
public class StartCommand {public StartCommand(String[] args){Boolean isServerPort = false;String serverPort = "";if(args != null){for (String arg:args){if(StringUtils.hasText(arg) &&arg.startsWith("--server.port")){isServerPort = true;serverPort = arg;break;}}}//没有指定端口,则随机生成一个可用的端口if(!isServerPort){int port = ServerPortUtils.getAvailablePort();log.info("current server.port=" + port);System.setProperty("server.port",String.valueOf(port));}else{//指定了端口,则以指定的端口为准log.info("current server.port=" + serverPort.split("=")[1]);System.setProperty("server.port",serverPort.split("=")[1]);}}}

启动类调用方法:

@SpringBootApplication
@EnableUserClient
@RestController
public class DemoApplication {@AutowiredEnvironment environment;public static void main(String[] args) {new StartCommand(args);SpringApplication.run(DemoApplication.class, args);}
}

通过自定义PropertiesPropertySource属性源实现

public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {@Overridepublic void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {//MapPropertySourceProperties properties = new Properties();properties.put("server.port", ServerPortUtils.getAvailablePort());System.out.println(properties.get("server.port"));PropertiesPropertySource source = new PropertiesPropertySource("myCustom", properties);environment.getPropertySources().addLast(source);//environment.getPropertySources().addAfter();}
}

通过配置在resources/META-INF/spring.factories文件中使用全名注册

org.springframework.boot.env.EnvironmentPostProcessor=com.laowan.demo.command.MyEnvironmentPostProcessor

这样在项目启动后,就会将该属性源加载到Environment中。

server.port=0随机端口 (推荐)

通过设置server.port=0,在spring boot项目启动时,会自动去寻找一个空闲的端口,避免端口冲突。

扩展:server.port=-1

设置为-1是为了完全关闭HTTP端点,但仍创建一个WebApplicationContext, 主要是在单元测试时使用。

验证: 执行单元测试,获取server.port属性

@SpringBootTest
@Slf4j
class DemoApplicationTests {@AutowiredEnvironment environment;@Testvoid getProperties() {System.out.println(environment.getProperty("server.port"));}
}

执行结果为:-1

总结

  1. 为什么要设置随机端?主要是为了解决动态扩容时出现端口冲突的问题。
  2. 怎么获取一个有效的随机端口号
  3. spring boot下实现随机端口的三种方式。关于方式三的自定义属性源的实现方式可以多多品味,实践一下,更好的体会属性文件的加载顺序。
  4. 补充通过server.port=0,设置一个有效的随机端口,推荐做法

作者:斗者_2013
原文链接:https://blog.csdn.net/w1014074794/article/details/106184883

3306端口_Spring Boot随机端口你都不会,怎么动态扩容?相关推荐

  1. linux ftp随机端口,linuxFTP生产环境配置

    1.ftp采用两个端口控制: A 20端口用于数据传输. B 21端口用于控制,或指建立TCP连接. 2.主动方式连接过程: [注意]:C表示客户端 S表示服务器端 A. S端要开启20.21端口: ...

  2. ssh 端口_【科普】SSH都不懂,还搞什么网络

    今天小编为大家分享一篇关于SSH 的介绍和使用方法的文章.本文从SSH是什么出发,讲述了SSH的基本用法,之后在远程登录.端口转发等多种场景下进行独立的讲述,希望能对大家有所帮助. 1. 什么是SSH ...

  3. Spring Cloud实战小贴士:随机端口

    太久没有更新,一时不知道该从哪儿开始,索性就从一个小技巧开始吧. 在之前的<Spring Cloud构建微服务架构>系列博文中,我们经常会需要启动多个实例的情况来测试注册中心.配置中心等基 ...

  4. (10)Spring Boot修改端口号【从零开始学Spring Boot】

    Spring boot 默认端口是8080,如果想要进行更改的话,只需要修改applicatoin.properties文件,在配置文件中加入: server.port=9090 常用配置: #### ...

  5. hbase java 端口_HBase远程Java客户端尝试通过随机端口进行身份验证

    我想将本地java/scala进程连接到远程HBase服务器(v 1.1.2)(在docker中).我有以下代码:HBase远程Java客户端尝试通过随机端口进行身份验证 val config = H ...

  6. jmx为啥开了额外两个随机端口?

    2019独角兽企业重金招聘Python工程师标准>>> jmx为啥开了额外两个随机端口? 博客分类: java 通常配置的是registry port: -Dcom.sun.mana ...

  7. linux怎么开放3306端口,Linux开启3306端口(开放mysql访问端口)

    1.本地测试3306是否开启 首先要ping一下看是否联通 ping 192.168.43.47 之后使用telnet命令查看是否可用 telnet 192.168.43.47 3306 2.linu ...

  8. Linux调整随机端口范围(服务器启动失败 端口被占用)

    问题描述 博主最近在工作中遇到了问题,服务器启动不起来,bug显示端口被占用. 端口是被connect端给占用了,非listen端. 原因分析: 经过调查发现,由于同一台主机上开启的服务器太多,导致生 ...

  9. zabbix的日常监控-自动发现端口并监测(服务器开启的所有端口或监控指定端口)(十三)...

    动批量检查agent开放的端口 注:此方法给监控磁盘IO(即十二)篇过程一样: 注释:如果服务器上的应用都是固定的,不会随机产生的都可以使用自动发现端口来监控:  如果服务器会随机出现端口且每次启动程 ...

最新文章

  1. ubuntu下安装wine
  2. swoole 定时器
  3. Qt for Android Splash启动页最简单延时关闭
  4. mysql5.0源码安装_linux小白 mysql5.0源码安装配置
  5. 计算机网络——差错控制
  6. mysql实体监听器_GitHub - langjiangit/spring-boot-starter-mysql-binlog: mysql的binlog监听器
  7. 电大计算机一级b考试试题,电大计算机考试本科试题
  8. iOS音频的后台播放总结(后台网络请求歌曲,Remote控制,锁屏封面,各种打断)...
  9. python 生成pdf页面大小_使用具有自定义大小页面和最佳图像分辨率的Reportlab生成PDF...
  10. 计算机管理是什么控件,Win7旗舰版系统WMI控件的功能作用是什么?
  11. 中国女子高尔夫球场市场趋势报告、技术动态创新及市场预测
  12. SpringBoot读取配置文件
  13. 区块链xuperchain ubuntu多机多节点 single共识 部署教程
  14. 洛谷P2057 [SHOI2007]善意的投票 题解
  15. 接口工具POSTMAN怎么设置中文
  16. 视频教程-Windows Server 2016 IPAM 服务管理-Windows
  17. FineReport报表工具激活码
  18. SpringBoot Zxing _ Java 生成二维码(可内嵌图片)
  19. 老spring3.2版本 redistemplate 报错_卡普空“令人惊讶”的老系列新作,会是《恐龙危机》吗?...
  20. 2022. 12 青少年软件编程(C 语言) 等级考试试卷(一级)

热门文章

  1. Javascript 笔记与总结(2-11)暴力操作节点
  2. 关于[UITableView setEditing:YES animated:YES] 没有animation
  3. 【Linux】——常见的rc的含义
  4. Flex与后台交互的4种方法
  5. 神不知鬼不觉地置换 XP用户密码
  6. 3.产品成本在完工和在制产品间分配
  7. 如何简单地利用Bitmap为中介储存图片到数据库中
  8. 判断一个变量是不是数组
  9. 数据结构(算法)-线性表2(单链表)
  10. 《AutoCAD全套园林图纸绘制自学手册》一第1章 园林设计基本概念1.1 概述