這幾天工作需要使用Apollo配置中心。Apollo唯一的依賴是MySQL數據庫,然而公司只有Oracle數據庫資源。這里有一個Oracle適配改動的分支,但是它是基於0.8.0版本的Apollo。看着Apollo官方文檔上各種特性都只有1.0.0以上版本才有,我決定基於當前最新版本(1.2.0)自己改一波。
基礎
在開始改動前我們需要了解Apollo工程的整體結構,以及調試啟動的方法。建議本地先搭建個MySQL庫,然后把Apollo跑起來看看。官方對此有詳細的文檔。
另外,從MySQL到Oracle,一個比較大的問題是Apollo中很多表名、字段名和Oracle的關鍵字有沖突,導致無法在Oracle建表。這個問題可以使用雙引號來解決。我們知道,Oracle的SQL語句在解釋時會把所有的字符都轉為大寫(字符串常量除外),所以我們一般認為Oracle的SQL語法不區分大小寫。比如說我可以用如下SQL建表:
create TaBle aPplicAtiOn(...);
最終我們會得到一張名為APPLICATION
的表。在一些情況下,我們會需要區分大小寫的表名,這時候我們可以在建表時用雙引號將表名括起來:
create TaBle "aPplicAtiOn"(...);
這樣,我們就真正得到了名為aPplicAtiOn
的表了。同理,字段名、同名等Oracle對象也都可以用雙引號來區分大小寫。關於Oracle雙引號,這里有更多的講解。
Oracle適配改動
下面的改動大部分是參考已有的vanpersl/apollo
基於0.8.0的Oracle版本的代碼。這里是他的修改內容。
總體來說改動量不大。我大約花了一天的時間完成了整個改動。下面是改動步驟。
准備數據庫用戶
- 准備兩個Oracle用戶(Oracle用戶相當於MySQL的庫),分別用於存放配置數據(假設這個用戶叫ApolloConfig)和管理數據(假設這個用戶叫ApolloPortal)。配置數據和管理數據有很多表名是相同的,所以必須使用兩個用戶。你也可以使用兩個現有的用戶,但是要注意不要和現有的表沖突了。
- 使用Oracle的SQL腳本建表。這里是我整理后的兩個SQL腳本,ApolloConfig用戶執行apolloconfigdb.sql腳本,ApolloPortal用戶執行apolloportaldb.sql腳本。
Apollo工程加入ojdbc的依賴
- 我測試了ojdbc6和ojdbc7是可以使用的,而ojdbc12則會報版本太低的錯誤。我最后使用的ojdbc6,因為我最后測試的是ojdbc6就懶得再換了。
- 另外,我在做這一步的時候發現使用Maven源的ojdbc包是無法啟動項目的。只能到Oracle官網下載jar包,然后本地引用。ojdbc的依賴添加到parent項目和apollo-common項目。
修改數據庫連接配置
- 新建好Oracle的庫后,將Apollo配置中原本MySQL的連接配置改為Oracle的連接配置——注意,根據你的部署方式,可能需要修改兩處或者三處的連接配置。
spring.datasource.url=jdbc:oracle:thin:@{ip}:{port}:{db}
spring.datasource.username={ApolloConfig|ApolloPortal}
spring.datasource.password={password}
添加Oracle配置。
這些配置改動在apollo-common
的application.properties
配置文件。
- 添加配置
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
指定使用Oracle驅動 - 如果你的Oracle版本在11c以下(比如10g或者11g),那么還需要添加
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
。否則Hibernate會生成fetch first ? rows only
之類的11c才支持的語句導致SQL執行錯誤。 - 其他的連接池之類的配置。
Sequence
- Apollo的表使用的自增ID作為主鍵。Oracle沒有直接支持自增ID的功能,必須通過Sequence實現。在建表的SQL里已為兩個庫分別建了名為
ID_SEQ
的Sequence。代碼中所有的Entity類的id
屬性都要加上GeneratedValue
和SequenceGenerator
的配置。Apollo的代碼中大部分的Entity類是繼承自一個BaseEntity
基類的,所以要修改的地方並不多。- 這幾個類需要修改:
BaseEntity
、ReleaseMessage
、InstanceConfig
、Instance
、UserPO
、ConsumerAudit
- 如下添加
GeneratedValue
和SequenceGenerator
兩行:
- 這幾個類需要修改:
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
@SequenceGenerator(name = "sequence", sequenceName = "ID_SEQ", allocationSize = 1)
@Column(name = "Id")
private long id;
...
}
Oracle關鍵字的問題
這部分的改動最多,也最枯燥。合理利用IDE的replace功能可以極大的提高修改效率。
- 由於原本MySQL的表名列名用了很多Oracle的關鍵字,所以轉到Oracle時所有的表名列名都用雙引號括起來。可在
apollo-commom
的application-properties
配置中加上:
spring.jpa.hibernate.globally_quoted_identifiers=true
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
這樣Hibernate的ORM生成SQL語句時就會自動給表名列名都加上雙引號。
- 另外,一些在注解里的類SQL語句用到的字段要手工加上雙引號。大概有以下這些地方:
- @SQLDelete和@Where的地方
- AuthConfiguration.java中有一堆直接寫SQL的
- 所有的isDeleted和id都要改首字母大寫
- Namespace有個appId,Item有個key、value、comment,GreyReleaseRule有appId和releaseId
- 其他我還沒發現的犄角旮旯
成果
我最后修改的結果上傳在這里:https://github.com/sKabYY/apollo。
目前已經平穩運行。后面如果有bug修改或者升級也會更新上去。
和原代碼的對比可以看這里。