javascript
3306端口_Spring Boot随机端口你都不会,怎么动态扩容?
一般情況下每個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
總結
原文鏈接:https://blog.csdn.net/w1014074794/article/details/106184883
總結
以上是生活随笔為你收集整理的3306端口_Spring Boot随机端口你都不会,怎么动态扩容?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springboot 获取applica
- 下一篇: 怎样知道邮箱的端口_AllenNLP源码