Bug描述:
線上發版一段時間後,接口查詢RDS中含有特殊表情字符的字段內容出現亂碼問題
Bug現象:
如下特殊表情字符會返回爲“跟我??走吧”
開始解決:
因爲數據庫都是已經存進去了特殊表情字符的,在可視化的工具都可以直接看到,沒有問題的。使用命令查看數據庫的編碼格式以及存儲特殊表情字符的字段編碼都是utf8mb4,所以開始從最外層代碼開始排查定位問題。
--- 查看數據庫編碼
SHOW VARIABLES LIKE '%character%';
-
首先覺得是接口返回的字符亂碼問題,便對接口返回編碼進行如下控制
@GetMapping(value = "/xxx", produces = "application/json;charset=UTF-8")
-
發佈上去後,暫時沒有問題,發現不止暱稱接口如此,只要是任意字符帶有特殊表情都會如此,比如房間名、簡介、標題等。初步覺得應該是全局返回編碼問題,便進行如下代碼進行全局編碼配置
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Bean
public HttpMessageConverter<String> responseBodyConverter() {
return new StringHttpMessageConverter(StandardCharsets.UTF_8);
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(responseBodyConverter());
addDefaultHttpMessageConverters(converters);
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}
-
發佈完成後,短時間沒有問題。過了大概十分鐘後會出現偶發性的亂碼,考慮到公司架構爲分佈式高可用的微服務,開始懷疑是某臺服務器編碼的問題,便使用postman對每個服務器使用IP+端口的方式進行直接的調用。
-
調用後發現,亂碼並不是固定出現在某臺服務某個端口,具有一定的隨機性,排除服務器編碼問題。開始往更內一層懷疑,覺得是阿里雲RDS雲數據庫的問題。
-
一方面開始提工單,一方面開始排查阿里雲的數據庫問題。因爲有使用阿里雲數據庫代理來進行讀寫分離,便開始懷疑是這個問題,使用了數據庫直連的內外網地址進行連接,測試發現近10多個小時沒有出現亂碼問題,已經定位到了問題就是阿里雲數據庫代理的問題。
阿里初步解決:
在控制檯的讀寫分離代理配置那裏,關閉事務級連接池之後重連數據庫。
推測阿里數據庫代理的事務級連接池配置使用的編碼格式可能是默認的utf8
使用如上方式後,果然沒有什麼問題,然後又打開了事務連接池,問題果然馬上覆現,實錘了有問題。
阿里給出的最終解決方案:
當然我並沒有嘗試,原因是阿里工程師告知:升級期間會有30S的閃斷 建議您在低峯期進行 保證程序有自動重連機制
因爲當時安裝的時候就是最新的,現在出了升級內核,推測應該是對我的這種情況進行了處理,先獲取數據庫的編碼格式,然後連接池進行了一個同步設置的操作來保證不亂碼。不過我已經不想用連接池了,沒有必要更新,還會讓數據庫30S閃斷,相對於這時間造成的影響不值得。至此bug已經解決,踩坑耗時兩天多。。。
期間也有些阿里工程師其它的指引,有些根本沒用還操作有風險,建議以後踩坑的朋友還是先找個臨時庫多試驗下,以免造成不可挽救的損失。比如:
- 您可以參考:https://help.aliyun.com/knowledge_detail/41702.html?spm=5176.11065259.1996646101.searchclickresult.21bf7a20dRbUtT
控制檯設置參數character_set_server爲utf8mb4這個操作一定不要隨便設置,因爲他要重啓數據庫才能生效,而且這並不是問題的根本,我的開發環境數據庫並沒有設置爲也可以存儲特殊表情字符的。
以上都是本人的拙見,還煩請大佬們批評指正。