Spring Boot随机端口怎么动态扩容?
Spring Boot随机端口怎么动态扩容?
在spring boot中,可以通过${random}来生成随机数字,我们可以在配置文件中,这么设置端口:
代码语言:javascript代码运行次数:0运行复制 代码解读复制代码server.port=${random.int(2000,8000)}
通过random.int方法,指定生成2000~8000的随机端口。这样每次启动的端口都不一样。
多次启动,发现每次的端口都不一致说明配置成功。
注意事项:
这里需要注意spring boot项目启动属性文件的加载顺序,spring boot的属性是由里向外加载,所以最外层的最后被加载,会覆盖里层的属性。
所以如果主动在启动命令中使用–server.port配置了项目的端口号,那么属性文件中配置的随机端口属性就不会生效。
上面的方法虽然暂时达到了想要的效果,但是有个问题:如果生成的这个随机端口已经被使用了,那么项目启动就会出现端口冲突。
那么,我们能否通过一个检测机制,让生成的随机端口一定是一个没有被占用的有效的随机端口呢?
有效端口检测原理:
通过建立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运行时的全局变量。
工具类:
代码语言:javascript代码运行次数:0运行复制 代码解读复制代码@Slf4j
public class etUtils {
/**
* 测试本机端口是否被使用
* @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.getByame(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,采用06端口去验证
* @param args
*/
public static void main(String args[]){
int testPost =06;
if(isLocalPortUsing(testPost)){
println("端口 "+testPost+" 已被使用");
}else{
println("端口 "+testPost+"未使用");
}
}
}
public class ServerPortUtils {
/**
* 获取可用端口
* @return
*/
public static int getAvailablePort(){
int max = 6555;
int min = 2000;
Random random = new Random();
int port = (max)%(max-min +1) + min;
boolean using = etUtils.isLocalPortUsing(port);
if(using){
return getAvailablePort();
}else{
return port;
}
}
}
项目启动前设置server.port环境变量
代码语言:javascript代码运行次数:0运行复制 代码解读复制代码/**
* 开始命令
*/
@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]);
}
}
}
启动类调用方法:
代码语言:javascript代码运行次数:0运行复制 代码解读复制代码@SpringBootApplication
@EnableUserClient
@RestController
public class DemoApplication {
@Autowired
Environment environment;
public static void main(String[] args) {
new StartCommand(args);
SpringApplication.run(, args);
}
}
代码解读复制代码public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
//MapPropertySource
Properties properties = new Properties();
properties.put("server.port", ServerPortUtils.getAvailablePort());
println(properties.get("server.port"));
PropertiesPropertySource source = new PropertiesPropertySource("myCustom", properties);
environment.getPropertySources().addLast(source);
//environment.getPropertySources().addAfter();
}
}
通过配置在resources/META-IF/spring.factories文件中使用全名注册
代码语言:javascript代码运行次数:0运行复制 代码解读复制代码org.springframework.EnvironmentPostProcessor=com.laowan.demomand.MyEnvironmentPostProcessor
这样在项目启动后,就会将该属性源加载到Environment中。
server.port=0随机端口 (推荐)
通过设置server.port=0,在spring boot项目启动时,会自动去寻一个空闲的端口,避免端口冲突。
设置为-1是为了完全关闭HTTP端点,但仍创建一个WebApplicationContext, 主要是在单元测试时使用。
验证: 执行单元测试,获取server.port属性
代码语言:javascript代码运行次数:0运行复制 代码解读复制代码@SpringBootTest
@Slf4j
class DemoApplicationTests {
@Autowired
Environment environment;
@Test
void getProperties() {
println(environment.getProperty("server.port"));
}
}
执行结果为:-1
- 为什么要设置随机端?主要是为了解决动态扩容时出现端口冲突的问题。
- 怎么获取一个有效的随机端口号
- spring boot下实现随机端口的三种方式。关于方式三的自定义属性源的实现方式可以多多品味,实践一下,更好的体会属性文件的加载顺序。
- 补充通过server.port=0,设置一个有效的随机端口,推荐做法
#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
推荐阅读
留言与评论(共有 13 条评论) |
本站网友 试着忘记 | 12分钟前 发表 |
怎么获取一个有效的随机端口号spring boot下实现随机端口的三种方式 | |
本站网友 美容护肤小常识 | 3分钟前 发表 |
注意事项:这里需要注意spring boot项目启动属性文件的加载顺序 | |
本站网友 看女人的b | 1分钟前 发表 |
port);#address代表主机的IP地址 | |
本站网友 夏天是谁的儿子 | 28分钟前 发表 |
ServerPortUtils.getAvailablePort()); println(properties.get("server.port")); PropertiesPropertySource source = new PropertiesPropertySource("myCustom" | |
本站网友 泰迪熊博物馆 | 21分钟前 发表 |
就会将该属性源加载到Environment中 | |
本站网友 银川房子 | 19分钟前 发表 |
String.valueOf(port)); }else{//指定了端口 | |
本站网友 可爱儿童房间 | 12分钟前 发表 |
系统指的是 JRE (runtime)system | |
本站网友 网上交易软件 | 25分钟前 发表 |
serverPort.split("=")[1]); } } }启动类调用方法:代码语言:javascript代码运行次数:0运行复制 代码解读复制代码@SpringBootApplication @EnableUserClient @RestController public class DemoApplication { @Autowired Environment environment; public static void main(String[] args) { new StartCommand(args); SpringApplication.run( | |
本站网友 果酸换肤精华 | 28分钟前 发表 |
SpringApplication application) { //MapPropertySource Properties properties = new Properties(); properties.put("server.port" | |
本站网友 陇南论坛 | 16分钟前 发表 |
工具类:代码语言:javascript代码运行次数:0运行复制 代码解读复制代码@Slf4j public class etUtils { /** * 测试本机端口是否被使用 * @param port * @return */ public static boolean isLocalPortUsing(int port){ boolean flag = true; try { //如果该端口还在使用则返回true | |
本站网友 大集体改制 | 0秒前 发表 |
args){ if(StringUtils.hasText(arg) && arg.startsWith("--server.port") ){ isServerPort = true; serverPort = arg; break; } } } //没有指定端口 | |
本站网友 新疆房产网 | 14分钟前 发表 |
我们可以在配置文件中 |