本篇和大家分享的是一個簡易配置中心框架IConfCenter,框架是利用空餘時間寫的,主要以配置檔案+redis儲存方式作為資料同步驅動,目前支援的配置檔案格式有 .properties 和 .config,後期有時間可能增加 .xml 和 .yml檔案的識別。
框架結構簡單分為:
- confserver - 服務端
confAdmin - 配置中心後臺管理
confCenter - 配置中心
- confclient - 客戶端
每分鐘獲取配置
訂閱配置中心重新整理配置
發一張配置中心應用到專案中的手工設計圖:
confAdmin - 配置中心後臺管理
後臺管理主要就是一個簡單的操作介面,採用springboot+thymeleaf+jquery搭建,目前主要有兩個功能:展示配置檔案列表和啟用某個配置
展示配置檔案列表:其實就是讀取本地磁碟目錄中的配置檔案資訊,主要的service程式碼如下:
1 /** 2 * 配置檔案列表 3 * 4 * @return 5 */ 6 public List<File> getListConf() { 7 File baseFile = new File(confCenterConf.confserver_confs_basepath); 8 File[] files = baseFile.listFiles(); 9 List<File> list = Arrays.asList(files). 10 stream(). 11 sorted(Comparator.comparing(File::lastModified).reversed()). 12 collect(Collectors.toList()); 13 return list; 14 }
啟用某個配置:主要通過介面按鈕觸發ajax提交一個啟動post請求,後端通過解析指定配置檔案內容為Map結構,並永久儲存於Redis快取中(直到下一次配置內容更新),最後通過Redis的釋出功能通知給訂閱該配置的客戶端,讓客戶端通過api重新獲取並更新本地配置。主要的Service程式碼如下:
1 /** 2 * 啟用某個配置+通知消費端(訂閱channel規則:confs_配置檔名) 3 * 4 * @param confPath 5 * @return 6 */ 7 public MoRp qyConf(String confPath) { 8 MoRp rp = new MoRp(); 9 rp.setStatus(EnumHelper.EmRpStatus.失敗.getVal()); 10 11 try { 12 //讀取配置檔案 13 Map<String, Object> map = LoadConf.readConfToMap(confPath); 14 if (map.isEmpty()) { 15 rp.setMessage("載入配置檔案失敗,稍後重試"); 16 return rp; 17 } 18 19 //檔名稱 20 String filePathToName = LoadConf.getFilePathToName(confPath, true); 21 22 //快取key 23 String cacheKey = String.format("confs_%s", filePathToName); 24 25 //2018.09.13 臨時增加配置檔案修改時間 26 File file = new File(confPath); 27 MoGetConfRp confRp = new MoGetConfRp(); 28 confRp.setConfLastModified(file.lastModified()); 29 confRp.setConfs(map); 30 confRp.setConfVersion(filePathToName); 31 confRp.setStatus(EnumHelper.EmRpStatus.成功.getVal()); 32 33 //儲存到快取中 永久 34 if (jedisTool.set(cacheKey, confRp, 0)) { 35 36 //釋出訊息,通知客戶端更新配置 37 jedisTool.publish(cacheKey, confRp.getConfVersion()); 38 rp.setStatus(EnumHelper.EmRpStatus.成功.getVal()); 39 rp.setMessage(EnumHelper.EmRpStatus.成功.toString()); 40 } 41 } catch (IOException e) { 42 e.printStackTrace(); 43 } 44 return rp; 45 }
confCenter - 配置中心
主要提供了一個獲取指定版本的配置檔案資訊api,資訊來源由Redis快取提供,當Redis快取不存在時不會去解析配置檔案,因此主要用ConfiAdmin管理後臺觸發資料來源。其主要程式碼:
/** * 獲取配置資訊 * * @param rq * @return */ public MoGetConfRp getconf(MoGetConfRq rq) { MoGetConfRp rp = new MoGetConfRp(); try { //未指定配置版本,採用預設配置版本 if (rq.getConfVersion().isEmpty()) { rq.setConfVersion(confCenterConf.confserver_confs_currentConfVersion); } if (rq.getConfVersion().isEmpty()) { rp.setMessage("未找到配置版本"); return rp; } //快取key String cacheKey = String.format("confs_%s", rq.getConfVersion()); //獲取快取中是否存在 rp = jedisTool.get(cacheKey, MoGetConfRp.class); if (rp.getStatus() == EnumHelper.EmRpStatus.成功.getVal() && rp.getConfs().size() >= 1) { rp.setStatus(EnumHelper.EmRpStatus.成功.getVal()); rp.setMessage(EnumHelper.EmRpStatus.成功.toString()); return rp; } } catch (Exception e) { e.printStackTrace(); } return rp; }
confclient - 客戶端
主要乾了兩個事情:每分鐘獲取配置和訂閱配置中心重新整理配置。該客戶端專案各位可以打包成jar引入專案中,加上相關配置即可引入配置中心客戶端
每分鐘獲取配置
為了配置內容的一致性,這裡採用了Scheduled每隔一分鐘請求一下配置中心api,然後通過版本號對比是否有更新,如果對比有新版本那麼即可更新快取於本地的配置資訊。主要程式碼如:
1 /** 2 * 每分鐘獲取配置,版本號不一致更新本地快取 3 * 4 */ 5 @Scheduled(initialDelay = 1000 * 60,fixedDelay = 1000 * 60) 6 public void refreshConf() { 7 System.out.println(new Date() + ":當前配置版本" + 8 confCenterConf.confserver_confs_currentConfVersion); 9 if (confCenterConf.confserver_confs_currentConfVersion.isEmpty()) { 10 System.out.println("版本為空,無法自動拉取配置"); 11 return; 12 } 13 updateConf(confCenterConf.confserver_confs_currentConfVersion); 14 } 15 16 /** 17 * 更新本地配置 18 * @param strVersion 19 */ 20 private void updateConf(String strVersion) { 21 //獲取配置中心配置 22 MoGetConfRp rp = confCenterClientService.getConfCenterConf(strVersion); 23 if (rp.getStatus() != EnumHelper.EmRpStatus.成功.getVal()) { 24 return; 25 }else if(rp.getConfLastModified() == confCenterClientService.getConfLastModified()){ 26 return; 27 } 28 System.out.println(new Date() + ":更新本地配置"); 29 //版本不一致,更新本地快取 30 confCenterClientService.setConf(rp); 31 }
訂閱配置中心重新整理配置
通過實現CommandLineRunner介面的run方法,在專案啟動時通過Redis訂閱配置中心訊息,達到配置中心主動通知更新配置的目的。主要程式碼:
/** * 程式啟動執行服務 訂閱配置中心重新整理配置通道 * * @param strings * @throws Exception */ @Override public void run(String... strings) throws Exception { //訂閱配置中心重新整理配置通道 jedisTool.subscribe( "confs_" + confCenterConf.confserver_confs_currentConfVersion, b -> { System.out.println(new Date() + ":收到配置中心重新整理配置通知,版本-" + b); updateConf(b.toString()); }); }
在文章結尾時,發一張配置中心後臺管理介面圖,並希望各位能夠喜歡配置中心框架IConfCenter