美文网首页
【Vesta发号器源码】MachineIdsIdServiceI

【Vesta发号器源码】MachineIdsIdServiceI

作者: DeanChangDM | 来源:发表于2019-05-14 09:59 被阅读0次

    Vesta发号器源码解析——MachineIdsIdServiceImpl

    这个类是一个对IdServiceImpl的扩展,继承了IdServiceImpl,实现了多个Ids的扩展

    相关字段

        //记录最后的时间戳
        protected long lastTimestamp = -1;
        //MachineId的映射关系
        protected Map<Long, Long> machineIdMap = new ConcurrentHashMap<Long, Long>();
        //存储的文件
        public static final String STORE_FILE_NAME = "machineIdInfo.store";
        //存储路径
        private String storeFilePath;
        //存储文件
        private File storeFile;
        //锁,可重入锁
        private Lock lock = new ReentrantLock();
    

    初始化方法

    重写父类中的初始化方法

        @Override
        public void init() {
            //如果当前的MachinId的provider不是MachineIdsProvider接口的实现
            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.");
            }
            //调用父类先初始化
            super.init();
            //初始化存储文件
            initStoreFile();
            //初始化MachineId
            initMachineIhid();
        }
    

    重写Id生成方法

        @Override
        protected void populateId(Id id) {
            //支持修改MachineId的方法调用
            supportChangeMachineId(id);
        }
    

    支持修改MachineId的方法

        private void supportChangeMachineId(Id id) {
            try {
                //设置machineId
                id.setMachine(this.machineId);
                //id生成器生成id
                idPopulator.populateId(timer, id, idMeta);
                //记录时间戳
                this.lastTimestamp = id.getTime();
            } catch (IllegalStateException e) {
                //发生时钟回拨,记录日志
                log.warn("Clock moved backwards, change MachineId and reset IdPopulator");
                //加锁
                lock.lock();
                try {
                    //如果当前MachineID和id中的相同,修改MachineId然后重置Id生成器
                    if (id.getMachine() == this.machineId) {
                        changeMachineId();
                        resetIdPopulator();
                    }
                } finally {
                    //解锁
                    lock.unlock();
                }
                //重新调用一次自己
                supportChangeMachineId(id);
            }
        }
    

    修改MachineId

        protected void changeMachineId() {
            //将当前的machineId和时间戳放到map里面
            this.machineIdMap.put(this.machineId, this.lastTimestamp);
            //存进文件里
            storeInFile();
            //初始化machineId
            initMachineId();
        }
    

    重置生成器

        protected void resetIdPopulator() {
            //确保id生成器是可重置的
            if (idPopulator instanceof ResetPopulator) {
                //然后充值id生成器
                ((ResetPopulator) idPopulator).reset();
            } else {
                try {
                    //否则重新初始化一个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);
                }
            }
        }
    

    初始化存储文件

    
        protected void initStoreFile() {
            //存储文件的位置没初始化
            if (storeFilePath == null || storeFilePath.length() == 0) {
                //存储文件的路径设置好
                //System.getProperty("user.dir")获取程序当前路径
                storeFilePath = System.getProperty("user.dir") + File.separator + STORE_FILE_NAME;
            }
            try {
                //记录日志
                log.info("machineId info store in <[" + storeFilePath + "]>");
                //存储文件初始化
                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) {
            }
        }
    
    

    初始化机器Id

        protected void initMachineId() {
            //起始Id记录
            long startId = this.machineId;
            //新id记录
            long newMachineId = this.machineId;
            while (true) {
                //如果新的machineId已经在map中存在了
                if (this.machineIdMap.containsKey(newMachineId)) {
                    //获取新的时间戳
                    long timestamp = timer.genTime();
                    //如果新machineId的时间戳比获取的小
                    if (this.machineIdMap.get(newMachineId) < timestamp) {
                        //使用新的machineID
                        this.machineId = newMachineId;
                        break;
                    } else {
                        //否则获取下一个MachineId作为New
                        newMachineId = ((MachineIdsProvider) this.machineIdProvider).getNextMachineId();
                    }
                    //如果新的和开始的一样,说明没有id了
                    if (newMachineId == startId) {
                        throw new RuntimeException("No machineId is available");
                    }
                    //校验id是否合法,然后重新循环
                    validateMachineId(newMachineId);
                } else {
                    //如果不包含直接设置为新的
                    //此处通常是上一轮循环到id校验合法,然后回来进入这里退出循环
                    this.machineId = newMachineId;
                    break;
                }
            }
            //记录日志
            log.warn("MachineId: {}", this.machineId);
        }
    

    存储进文件的方法

    
        protected void storeInFile() {
            //初始化Writer
            Writer writer = null;
            try {
                //初始化文件写入,append参数为false,非追加模式
                writer = new FileWriter(storeFile, false);
                //循环,将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 {
                //关闭IO
                if (writer != null) {
                    try {
                        writer.close();
                    } catch (IOException e) {
                    }
                }
            }
        }
    

    设置存储文件的路径

        //设置存储文件的位置
        public void setStoreFilePath(String storeFilePath) {
            this.storeFilePath = storeFilePath;
        }
    

    相关文章

      网友评论

          本文标题:【Vesta发号器源码】MachineIdsIdServiceI

          本文链接:https://www.haomeiwen.com/subject/fnblaqtx.html