如今不少軟件都支持集羣部署,可是測試環境一般資源有限,因此通常經過單臺機器模擬集羣部署(使用不一樣端口,運行相同jar包),本文的目的就是經過多種方式實現此需求。html
一、jar程序java
① springboot程序spring
② 只包含一個main方法,用於啓動程序,輸出進程IDapache
③ 路徑:C:/demo.jar(windows) /demo.jar(Linux)windows
二、啓動程序springboot
① 包含main方法的程序bash
一、經過URLClassLoader加載jar程序(windows平臺)測試
二、經過java -jar命令啓動jar程序(windows平臺)spa
三、經過複製原始jar文件,啓動不一樣的jar程序(windows平臺).net
四、經過Linux Shell腳本啓動(Linux平臺)
一、經過URLClassLoader加載jar程序(windows平臺)
① 說明
1) 啓動程序屢次加載jar程序
2) jar程序和啓動程序使用相同進程,非獨立進程,無實際意義,僅介紹
② 啓動jar程序:運行啓動程序main方法
③ 終止jar程序:中止啓動程序(由於共用同一個進程,終止主程序,jar程序會同時終止)
二、代碼
① jar程序
@SpringBootApplication public class DemoStarter { public static void main(String[] args) { // 獲取進程Id String name = ManagementFactory.getRuntimeMXBean().getName(); String processId = name.split("@")[0]; System.out.println(processId); SpringApplication.run(DemoStarter.class, args); } }
② 啓動程序
import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; public class Starter1 { public static void main(String[] args) throws Exception { start("7001"); start("7002"); start("7003"); } private static void start(String port) throws Exception { String path = "file:" + "C:/demo.jar"; URLClassLoader classLoader = new URLClassLoader(new URL[]{new URL(path)}); // jar程序的啓動類完整路徑 Class demo = classLoader.loadClass("DemoStarter"); Method method = demo.getMethod("main", String[].class); method.invoke(null, (Object) new String[]{port}); } }
一、經過java -jar命令啓動jar包(windows平臺)
① 說明
1) 啓動程序使用命令屢次啓動jar包
2) 動態構建cmd命令(不一樣參數),啓動相同jar程序,各個jar程序使用不一樣進程
② 啓動jar程序
1) 運行啓動程序main方法
2) 保存各個進程ID到文件
③ 終止jar程序
1) 根據保存的進程ID中止各個jar程序
二、代碼
① jar程序(同方式一)
② 啓動程序
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; public class Starter2 { public static void main(String[] args) throws Exception { cmd("7001"); cmd("7002"); cmd("7003"); // 根據文件中的進程Id終止程序 killByProcessId("PID1"); killByProcessId("PID2"); killByProcessId("PID3"); } private static void cmd(String port) throws Exception { String cmd = "java -jar -Dserver.port=" + port + " " + "C:/demo.jar"; Process p = Runtime.getRuntime().exec(cmd); InputStream is = p.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); // 獲取進程Id(DemoStarter-->main方法 // reader.readLine()第一行爲System.out.println(processId)輸出內容 String processId; while ((processId = reader.readLine()) != null) { break; } is.close(); reader.close(); // 這裏能夠將進程ID保存到文件中 System.out.println("processId:" + processId); } private static void killByProcessId(String processId) throws Exception { String cmd = "taskkill /F /PID \"" + processId + "\""; Runtime.getRuntime().exec(cmd); } }
一、經過複製原始jar文件,啓動不一樣的jar程序(windows平臺)
① 說明
1) 複製原始jar包,生成新的jar包
2) 動態構建cmd命令(不一樣參數、不一樣jar包名稱),啓動不一樣jar包,各個jar包使用不一樣進程
② 啓動jar程序
1) 運行啓動程序的main方法
2) 保存各個進程ID到文件
③ 終止程序
1) 根據保存的進程ID中止各個jar程序
④ 複製jar文件須要時間,但能夠解決啓動相同jar包可能存在的問題
二、代碼
③ jar程序(同方式一)
④ 啓動程序
import org.apache.commons.io.FileUtils; import java.io.BufferedReader; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; public class Starter3 { public static void main(String[] args) throws Exception { copyCmd(); // 根據文件中的進程Id終止程序 killByProcessId("PID1"); killByProcessId("PID2"); killByProcessId("PID3"); } private static void copyCmd() throws Exception { File srcFile = new File("C:/demo.jar"); File destiFile2 = new File("C:/demo2.jar"); File destiFile3 = new File("C:/demo3.jar"); // 刪除以前複製的jar包 FileUtils.forceDelete(destiFile2); FileUtils.forceDelete(destiFile3); FileUtils.copyFile(srcFile, destiFile2); FileUtils.copyFile(srcFile, destiFile3); copy("java -jar -Dserver.port=7001 C:/demo.jar"); copy("java -jar -Dserver.port=7002 C:/demo2.jar"); copy("java -jar -Dserver.port=7003 C:/demo3.jar"); } private static void copy(String cmd) throws Exception { Process p; p = Runtime.getRuntime().exec(cmd); InputStream is = p.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); // 獲取進程Id(DemoStarter-->main方法 // reader.readLine()第一行爲System.out.println(processId)輸出內容 String processId; while ((processId = reader.readLine()) != null) { break; } is.close(); reader.close(); // 這裏能夠將進程ID保存到文件中 System.out.println("ProcessId:" + processId); } private static void killByProcessId(String processId) throws Exception { String cmd = "taskkill /F /PID \"" + processId + "\""; Runtime.getRuntime().exec(cmd); } }
一、經過Linux Shell腳本啓動(Linux平臺)
① 執行java -jar命令
② 根據端口獲取進程ID
③ 根據進程ID終止程序
二、代碼
① jar程序(同方式一)
② Shell命令
1) 啓動程序
#!/bin/bash java -jar -Dserver.port=7001 /demo.jar java -jar -Dserver.port=7002 /demo.jar java -jar -Dserver.port=7003 /demo.jar
2) 終止程序
#!/bin/bash pid1=`netstat -anp | grep 7001 | awk '{printf $7}' | cut -d/ -f1` pid2=`netstat -anp | grep 7002 | awk '{printf $7}' | cut -d/ -f1` pid3=`netstat -anp | grep 7003 | awk '{printf $7}' | cut -d/ -f1` kill ${pid1} kill ${pid2} kill ${pid3}
一、方式一能夠經過調用method.invoke傳遞參數
二、其它方式可經過jar命令傳遞參數
三、啓動程序經過Process啓動jar程序並獲取jar程序進程ID
四、屢次啓動jar程序時報錯:」unable to register MBean」
設置參數spring.jmx.enabled=false
五、根據端口號獲取進程ID(windows)
netstat -ano|findstr "7001 7002 7003"
六、根據進程ID中止進程(windows)
taskkill /F /PID "1"
一、http://www.javashuo.com/article/p-wzvcygmo-kt.html