Vesta發(fā)號(hào)器源碼解析——MachineIdsIdServiceImpl
這個(gè)類是一個(gè)對(duì)IdServiceImpl的擴(kuò)展沧侥,繼承了IdServiceImpl瞎疼,實(shí)現(xiàn)了多個(gè)Ids的擴(kuò)展
相關(guān)字段
//記錄最后的時(shí)間戳
protected long lastTimestamp = -1;
//MachineId的映射關(guān)系
protected Map<Long, Long> machineIdMap = new ConcurrentHashMap<Long, Long>();
//存儲(chǔ)的文件
public static final String STORE_FILE_NAME = "machineIdInfo.store";
//存儲(chǔ)路徑
private String storeFilePath;
//存儲(chǔ)文件
private File storeFile;
//鎖,可重入鎖
private Lock lock = new ReentrantLock();
初始化方法
重寫父類中的初始化方法
@Override
public void init() {
//如果當(dāng)前的MachinId的provider不是MachineIdsProvider接口的實(shí)現(xiàn)
if (!(this.machineIdProvider instanceof MachineIdsProvider)) {
log.error("The machineIdProvider is not a MachineIdsProvider instance so that Vesta Service refuses to start.");
throw new RuntimeException(
"The machineIdProvider is not a MachineIdsProvider instance so that Vesta Service refuses to start.");
}
//調(diào)用父類先初始化
super.init();
//初始化存儲(chǔ)文件
initStoreFile();
//初始化MachineId
initMachineIhid();
}
重寫Id生成方法
@Override
protected void populateId(Id id) {
//支持修改MachineId的方法調(diào)用
supportChangeMachineId(id);
}
支持修改MachineId的方法
private void supportChangeMachineId(Id id) {
try {
//設(shè)置machineId
id.setMachine(this.machineId);
//id生成器生成id
idPopulator.populateId(timer, id, idMeta);
//記錄時(shí)間戳
this.lastTimestamp = id.getTime();
} catch (IllegalStateException e) {
//發(fā)生時(shí)鐘回?fù)芨盥簦涗浫罩? log.warn("Clock moved backwards, change MachineId and reset IdPopulator");
//加鎖
lock.lock();
try {
//如果當(dāng)前MachineID和id中的相同前酿,修改MachineId然后重置Id生成器
if (id.getMachine() == this.machineId) {
changeMachineId();
resetIdPopulator();
}
} finally {
//解鎖
lock.unlock();
}
//重新調(diào)用一次自己
supportChangeMachineId(id);
}
}
修改MachineId
protected void changeMachineId() {
//將當(dāng)前的machineId和時(shí)間戳放到map里面
this.machineIdMap.put(this.machineId, this.lastTimestamp);
//存進(jìn)文件里
storeInFile();
//初始化machineId
initMachineId();
}
重置生成器
protected void resetIdPopulator() {
//確保id生成器是可重置的
if (idPopulator instanceof ResetPopulator) {
//然后充值id生成器
((ResetPopulator) idPopulator).reset();
} else {
try {
//否則重新初始化一個(gè)Id生成器
IdPopulator newIdPopulator = this.idPopulator.getClass().newInstance();
this.idPopulator = newIdPopulator;
} catch (InstantiationException e1) {
//拋出重置失敗
throw new RuntimeException("Reset IdPopulator <[" + this.idPopulator.getClass().getCanonicalName() + "]> instance error", e1);
} catch (IllegalAccessException e1) {
//拋出重置失敗
throw new RuntimeException("Reset IdPopulator <[" + this.idPopulator.getClass().getCanonicalName() + "]> instance error", e1);
}
}
}
初始化存儲(chǔ)文件
protected void initStoreFile() {
//存儲(chǔ)文件的位置沒(méi)初始化
if (storeFilePath == null || storeFilePath.length() == 0) {
//存儲(chǔ)文件的路徑設(shè)置好
//System.getProperty("user.dir")獲取程序當(dāng)前路徑
storeFilePath = System.getProperty("user.dir") + File.separator + STORE_FILE_NAME;
}
try {
//記錄日志
log.info("machineId info store in <[" + storeFilePath + "]>");
//存儲(chǔ)文件初始化
storeFile = new File(storeFilePath);
//文件存在,寫入
if (storeFile.exists(){
//逐行讀取鹏溯,然后初始化到map中
BufferedReader reader = new BufferedReader(new FileReader(storeFile));
String line = reader.readLine();
while (line != null && line.length() > 0) {
String[] kvs = line.split(":");
if (kvs.length == 2) {
this.machineIdMap.put(Long.parseLong(kvs[0]), Long.parseLong(kvs[1]));
} else {
throw new IllegalArgumentException(storeFile.getAbsolutePath() + " has illegal value <[" + line + "]>");
}
line = reader.readLine();
}
reader.close();
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
初始化機(jī)器Id
protected void initMachineId() {
//起始Id記錄
long startId = this.machineId;
//新id記錄
long newMachineId = this.machineId;
while (true) {
//如果新的machineId已經(jīng)在map中存在了
if (this.machineIdMap.containsKey(newMachineId)) {
//獲取新的時(shí)間戳
long timestamp = timer.genTime();
//如果新machineId的時(shí)間戳比獲取的小
if (this.machineIdMap.get(newMachineId) < timestamp) {
//使用新的machineID
this.machineId = newMachineId;
break;
} else {
//否則獲取下一個(gè)MachineId作為New
newMachineId = ((MachineIdsProvider) this.machineIdProvider).getNextMachineId();
}
//如果新的和開始的一樣罢维,說(shuō)明沒(méi)有id了
if (newMachineId == startId) {
throw new RuntimeException("No machineId is available");
}
//校驗(yàn)id是否合法,然后重新循環(huán)
validateMachineId(newMachineId);
} else {
//如果不包含直接設(shè)置為新的
//此處通常是上一輪循環(huán)到id校驗(yàn)合法丙挽,然后回來(lái)進(jìn)入這里退出循環(huán)
this.machineId = newMachineId;
break;
}
}
//記錄日志
log.warn("MachineId: {}", this.machineId);
}
存儲(chǔ)進(jìn)文件的方法
protected void storeInFile() {
//初始化Writer
Writer writer = null;
try {
//初始化文件寫入肺孵,append參數(shù)為false匀借,非追加模式
writer = new FileWriter(storeFile, false);
//循環(huán),將map寫入文件中
for (Map.Entry<Long, Long> entry : this.machineIdMap.entrySet()) {
writer.write(entry.getKey() + ":" + entry.getValue() + "\n");
}
} catch (IOException e) {
//寫入異常平窘,記錄日志
log.error("Write machineId info to File<[" + storeFile.getAbsolutePath() + "]> error");
throw new RuntimeException("Write machineId info to File<[" + storeFile.getAbsolutePath() + "]> error");
} finally {
//關(guān)閉IO
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
}
}
}
}
設(shè)置存儲(chǔ)文件的路徑
//設(shè)置存儲(chǔ)文件的位置
public void setStoreFilePath(String storeFilePath) {
this.storeFilePath = storeFilePath;
}