最近把客戶端的內測分發平臺使用Spring Boot+Kotlin重構了,以前是用Tomcat部署的,現在改用Jar包部署。由於是比較簡單的單體應用,所以沒有使用持續整合框架Jenkins
,都是通過FTP上傳到Tomcat目錄,然後重啟Tomcat。
同時支援HTTP與HTTPS
獲取SSL的簽名這裡就不說了,Google搜尋也有很多生成免費的簽名方案,我是把簽名檔案放在resources
目錄
├── build.gradle
├── gradlew
├── settings.gradle
├── src
│ ├── main
│ │ ├── java
│ │ ├── kotlin
│ │ ├── resources
│ │ │ ├── application.properties
│ │ │ ├── keystore.p12
複製程式碼
方案一(不推薦,不無法相容HTTPS和HTTP)
直接修改application.properties
# 埠
server.port=8443
# 簽名路徑
server.ssl.key-store=/Users/Wiki/BetaServer/src/main/resources/keystore.p12
server.ssl.key-store-password=123123
server.ssl.keyStoreType=PKCS12
server.ssl.keyAlias:tomcat
複製程式碼
Spring本身就提供非常方便支援HTTPS的方式,直接修改application.properties
即可實現HTTPS,但是使用這種方式就不能直接使用HTTP了。
方案二(相容HTTPS和HTTP)
我們在application.properties
自定義了幾個引數
#HTTP埠
server.port=8080
#配置模SSL
tomcat.ssl.enable=true
tomcat.ssl.key-store=keystore.p12
tomcat.ssl.key-store-password=123123
tomcat.ssl.keyStoreType=PKCS12
tomcat.ssl.port=8443
複製程式碼
由於我是打包成Jar格式檔案然後放在伺服器執行,意味著resources目錄下的檔案無法獲取到絕對路徑或者相對路徑,我們換一個做法,我們在啟動HTTPS的時候把resources的檔案讀取出來,寫入到一個臨時的路徑,那麼就可以解決這個問題。
@ConditionalOnExpression(value = "${tomcat.ssl.enable:false}")
@Configuration
open class CustomTomcatSSLConfiguration {
@Value("${tomcat.ssl.port:8443}")
private val tomcatSSLPort: Int = 0
@Value("${tomcat.ssl.key-store:}")
private val tomcatSSLKeyStore: String? = null
@Value("${tomcat.ssl.key-store-password:}")
private val keystorePassword: String? = null
@Value("${tomcat.ssl.keyStoreType:PKCS12}")
private val keystoreType: String? = null
@Bean
open fun servletContainer(): ServletWebServerFactory {
val tomcat = TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(createSSLConnector())
return tomcat;
}
open fun createSSLConnector(): Connector {
// 由於下面需要填寫簽名的地址,如果我們打包成Jar,這個地址就失效了,從 resources 讀取 簽名檔案
val stream = javaClass.classLoader.getResourceAsStream(tomcatSSLKeyStore)
// 然後寫入當前應用執行的路徑
val file = File(tomcatSSLKeyStore)
file.writeBytes(stream.readBytes())
val connector = Connector("org.apache.coyote.http11.Http11NioProtocol")
connector.port = tomcatSSLPort;
connector.secure = true
connector.scheme = "https"
connector.setAttribute("SSLEnabled", true)
connector.setAttribute("sslProtocol", "TLS")
connector.setAttribute("protocol", "org.apache.coyote.http11.Http11Protocol")
connector.setAttribute("clientAuth", false)
// 使用臨時的前面檔案路徑
connector.setAttribute("keystoreFile", file.absolutePath)
connector.setAttribute("keystoreType", keystoreType)
connector.setAttribute("keystorePass", keystorePassword)
connector.setAttribute("keyPass", keystorePassword)
return connector
}
}
複製程式碼
打包Jar
我的使用Gradle來代替Maven,打包非常的方便,直接執行命令打包即可
./gradlew bootJar
複製程式碼
上傳Jar到Linux伺服器
由於不是經常更新,所以沒有引入Jenkins
,後續會考慮引入。以前我都是通過FTP上傳war到伺服器,然後重啟Tomcat來實現部署。最近我發現一個更加方便的做法,使用scp
命令,可以實現把當前電腦的檔案上傳到伺服器。
scp -P 22222 build/libs/BetaServer.jar apps@100.100.100.100:/home/apps/webapp/
複製程式碼
啟動Jar
我們都知道Jar的啟動是可以通過 java -jar BetaServer.jar
即可啟動,但是當我們關閉命令視窗,這個程式就會被關閉導致服務也被關閉了,所以我們需要讓這個服務後臺執行,關閉視窗也不受影響。
nohup java -jar BetaServer.jar > log.txt &
複製程式碼
記得不要把後面&
忽略了,整行都是需要的,log.txt
是原來命令列輸出的日誌,我們把它寫到檔案中,也方便我們後續檢視錯誤。
訪問伺服器
由於上面我們配置的HTTP是8080埠,HTTPS是8443埠,那麼我們就可以通過以下命令訪問
http://100.100.100.100:8080/index
https://100.100.100.100:8443/index
複製程式碼
修改埠對映
上面的訪問是帶有埠,但是我們釋出出去的網頁,肯定不能讓使用者也需要輸入埠,體驗太差了,我們要把HTTP的埠改成80、HTTPS改成443,那麼理論上就可以實現這樣訪問
http://100.100.100.100/index
https://100.100.100.100/index
複製程式碼
在Linux的下面部署了應用,為了安全我們使用非root使用者進行啟動,非root使用者不能監聽1024以下的埠號,如果直接改成80和443,會報安全性異常。
java.net.SocketException: Permission denied
複製程式碼
所以這裡需要使用linux的埠轉發機制,把到80埠的服務請求都轉到8080埠上,443埠轉發到8443。
在root下面執行一下命令:
$ iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
$ iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8443
$ service iptables save
複製程式碼
到這裡就大功告成啦。