將Spring Boot應(yīng)用連接到MySQL on Azure數(shù)據(jù)庫

最近在Azure上以應(yīng)用服務(wù)(App Service)的方式部署了一個(gè)Spring Boot應(yīng)用,數(shù)據(jù)庫選擇了MySQL on Azure,這是一個(gè)PaaS級別的服務(wù),其底層仍是虛擬機(jī),但對應(yīng)實(shí)例由Azure托管。本文記錄部署過程,以及過程中遇到的問題和解決方法。

部署過程

在開發(fā)環(huán)境中連接的是本機(jī)數(shù)據(jù)庫,工作正常。數(shù)據(jù)庫的配置寫在applicaion.properties文件里:

spring.datasource.url=jdbc:mysql://localhost:3306/wefamily?user=dbuser&password=123456
spring.jpa.hibernate.ddl-auto=update

文件的第二行表示自動(dòng)創(chuàng)建和更新數(shù)據(jù)庫表。
部署到Azure上以后,數(shù)據(jù)庫連接參數(shù)改為通過環(huán)境變量指定。Spring Boot擁有強(qiáng)大的配置管理功能,環(huán)境變量的優(yōu)先級要高于application.properties,會(huì)自動(dòng)覆蓋相關(guān)設(shè)置。
設(shè)置環(huán)境變量有兩種方法,一是使用Azure CLI,在命令行中執(zhí)行:

az webapp config appsettings set --settings SPRING_DATASOURCE_URL="jdbc:mysql://dbinstance.mysql.database.azure.com:3306/wefamilydb" --resource-group wefamily_resource_group --name wefamily-api
az webapp config appsettings set --settings SPRING_DATASOURCE_USERNAME=dbinstance%dbuser --resource-group wefamily_resource_group --name wefamily-api
az webapp config appsettings set --settings SPRING_DATASOURCE_PASSWORD=123456 --resource-group wefamily_resource_group --name wefamily-api

二是使用portal,在應(yīng)用服務(wù)的“應(yīng)用程序設(shè)置”中手動(dòng)添加和修改:

AppSettings of Azure App Service

配置好以后,應(yīng)用無法正常訪問,報(bào)500錯(cuò)誤(The request timed out.)。

問題解決

通過FTP連接到部署目錄,下載eventLog.xml查看:

Event log from Azure App Service deploy FTP

<Event>
    <System>
        <Provider Name="HttpPlatformHandler"/>
        <EventID>1000</EventID>
        <Level>1</Level>
        <Task>0</Task>
        <Keywords>Keywords</Keywords>
        <TimeCreated SystemTime="2018-07-14T10:04:05Z"/>
        <EventRecordID>35185953</EventRecordID>
        <Channel>Application</Channel>
        <Computer>RD0017FA007A37</Computer>
        <Security/>
    </System>
    <EventData>
        <Data>Process '5588' failed to start. Port = 21453, Error Code = '-2147023829'.</Data>
    </EventData>
</Event>

原因是應(yīng)用的進(jìn)程沒能正常啟動(dòng)。
嘗試在本地連接Azure數(shù)據(jù)庫,為了不修改代碼,寫了一個(gè)腳本:

#!/bin/sh
export SPRING_DATASOURCE_URL="jdbc:mysql://dbinstance.mysqldb.chinacloudapi.cn:3306/wefamilydb"
export SPRING_DATASOURCE_USERNAME=dbinstance%dbuser
export SPRING_DATASOURCE_PASSWORD=123456
mvn spring-boot:run

發(fā)現(xiàn)應(yīng)用同樣不能啟動(dòng),報(bào)錯(cuò)內(nèi)容為:

2018-07-19 11:28:14.546  WARN 1942 --- [           main] o.h.t.s.i.ExceptionHandlerLoggedImpl     : GenerationTarget encountered exception accepting command : Error executing DDL via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement
...
Caused by: java.sql.SQLException: Got error 1 from storage engine
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:965) ~[mysql-connector-java-5.1.46.jar:5.1.46]

運(yùn)行官方的TodoList示例作對比,發(fā)現(xiàn)這個(gè)工程可以正常連接Azure上的數(shù)據(jù)庫。
在網(wǎng)上搜索Error executing DDL via JDBC Statement錯(cuò)誤,發(fā)現(xiàn)此問題多與數(shù)據(jù)庫方言有關(guān);同時(shí)結(jié)合Got error 1 from storage engine,判斷問題可能與存儲(chǔ)引擎有關(guān)。
登錄開發(fā)環(huán)境的MySQL,用show table status from dbname檢查數(shù)據(jù)庫表的存儲(chǔ)引擎,發(fā)現(xiàn)自己的應(yīng)用是MyISAM,而TodoList應(yīng)用是InnoDB,再對比代碼,兩者最大的差別是Spring Boot版本不同,前者是2.0.3,后者是1.5.3。將TodoList應(yīng)用的Spring Boot升級到2.0.3,在本地創(chuàng)建出來的數(shù)據(jù)庫表果然變成了MyISAM引擎,同時(shí)也無法連接Azure上的數(shù)據(jù)庫了。
檢查文檔Azure Database for MySQL 中的限制,確認(rèn)MySQL on Azure不支持MyISAM:

MySQL on Azure Limits

在application.properties中添加配置,使用InnoDB引擎:

spring.jpa.database-platform=org.hibernate.dialect.MySQL57InnoDBDialect

問題得以解決,應(yīng)用可以在本地連接到Azure數(shù)據(jù)庫,部署到云上以后也能正常訪問了。

參考資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容