diff --git a/.flattened-pom.xml b/.flattened-pom.xml index ba71703..7a08978 100644 --- a/.flattened-pom.xml +++ b/.flattened-pom.xml @@ -16,6 +16,10 @@ han-note-gateway han-note-oss han-note-user + han-note-kv + han-note-distributed-id-generator + han-note-note + han-note-note/han-note-note-biz @@ -51,6 +55,11 @@ 2.3.3 5.6.227 3.8.0 + 3.2.2 + 2.20.0 + 0.9.16 + 5.9.0 + 3.9.4 @@ -215,12 +224,47 @@ feign-form ${feign-form.version} + + commons-io + commons-io + ${common-io.version} + + + org.perf4j + perf4j + ${perf4j.version} + + + org.apache.curator + curator-recipes + ${curator-recipes.version} + + + org.apache.zookeeper + zookeeper + ${zookeeper.version} + com.hanserwei han-note-user-api 0.0.1-SNAPSHOT - + + com.hanserwei + han-note-kv-api + 0.0.1-SNAPSHOT + + + com.hanserwei + han-note-distributed-id-generator-api + 0.0.1-SNAPSHOT + + + + com.github.ben-manes.caffeine + caffeine + ${caffeine.version} + diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/pom.xml b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/pom.xml index 35905eb..0727648 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/pom.xml +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/pom.xml @@ -14,14 +14,6 @@ han-note-distributed-id-generator-biz ${project.artifactId} 分布式 ID 生成业务层 - - 2.4 - 0.9.16 - 1.0.18 - 3.3.0 - 2.6.0 - 3.6.0 - @@ -50,39 +42,35 @@ com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery + + + com.baomidou + mybatis-plus-spring-boot3-starter + + + + com.alibaba + druid-spring-boot-3-starter + + + + com.mysql + mysql-connector-j + + commons-io commons-io - ${common-io.version} org.perf4j perf4j - ${perf4j.version} - - - mysql - mysql-connector-java - 8.0.29 - - - com.alibaba - druid - ${druid.version} - - org.mybatis - mybatis - ${mybatis.version} - - - org.apache.curator curator-recipes - ${curator-recipes.version} @@ -103,10 +91,10 @@ + org.apache.zookeeper zookeeper - ${zookeeper.version} diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/HannoteDistributedIdGeneratorBizApplication.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/HannoteDistributedIdGeneratorBizApplication.java index d9bf603..26f84a7 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/HannoteDistributedIdGeneratorBizApplication.java +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/HannoteDistributedIdGeneratorBizApplication.java @@ -1,9 +1,15 @@ package com.hanserwei.hannote.distributed.id.generator.biz; +import com.hanserwei.hannote.distributed.id.generator.biz.config.LeafProperties; +import com.hanserwei.hannote.distributed.id.generator.biz.core.segment.dao.IDAllocMapper; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; @SpringBootApplication +@EnableConfigurationProperties(LeafProperties.class) +@MapperScan(basePackageClasses = IDAllocMapper.class) public class HannoteDistributedIdGeneratorBizApplication { public static void main(String[] args) { SpringApplication.run(HannoteDistributedIdGeneratorBizApplication.class, args); diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/config/LeafDataSourceConfiguration.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/config/LeafDataSourceConfiguration.java new file mode 100644 index 0000000..0adf6c4 --- /dev/null +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/config/LeafDataSourceConfiguration.java @@ -0,0 +1,43 @@ +package com.hanserwei.hannote.distributed.id.generator.biz.config; + +import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceBuilder; +import jakarta.annotation.PostConstruct; +import javax.sql.DataSource; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.StringUtils; + +@Slf4j +@Configuration +@RequiredArgsConstructor +public class LeafDataSourceConfiguration { + + private final LeafProperties leafProperties; + + @PostConstruct + void logDataSourceSource() { + LeafProperties.Jdbc jdbc = leafProperties.getJdbc(); + if (StringUtils.hasText(jdbc.getUrl())) { + log.info("Leaf JDBC properties detected, will configure DruidDataSource via leaf.jdbc.*"); + } else { + log.info("Leaf JDBC properties not set, relying on default spring.datasource configuration"); + } + } + + @Bean + @ConditionalOnMissingBean(DataSource.class) + @ConditionalOnProperty(prefix = "leaf.jdbc", name = "url") + public DataSource leafDataSource() { + LeafProperties.Jdbc jdbc = leafProperties.getJdbc(); + var dataSource = DruidDataSourceBuilder.create().build(); + dataSource.setUrl(jdbc.getUrl()); + dataSource.setUsername(jdbc.getUsername()); + dataSource.setPassword(jdbc.getPassword()); + dataSource.setDriverClassName(jdbc.getDriverClassName()); + return dataSource; + } +} diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/config/LeafProperties.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/config/LeafProperties.java new file mode 100644 index 0000000..29f772f --- /dev/null +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/config/LeafProperties.java @@ -0,0 +1,72 @@ +package com.hanserwei.hannote.distributed.id.generator.biz.config; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Getter +@Setter +@ConfigurationProperties(prefix = "leaf") +public class LeafProperties { + + /** + * 用于区分不同集群的唯一名称,影响 Snowflake 的 zk 节点路径。 + */ + private String name = "leaf"; + + private final Segment segment = new Segment(); + private final Snowflake snowflake = new Snowflake(); + private final Jdbc jdbc = new Jdbc(); + + @Getter + @Setter + public static class Segment { + /** + * 是否启用号段模式 ID 生成。 + */ + private boolean enable = true; + } + + @Getter + @Setter + public static class Snowflake { + /** + * 是否启用 Snowflake 模式 ID 生成。 + */ + private boolean enable = true; + + /** + * Zookeeper 连接地址,示例:127.0.0.1:2181。 + */ + private String zkAddress; + + /** + * Snowflake 服务监听端口。 + */ + private int port = 0; + } + + @Getter + @Setter + public static class Jdbc { + /** + * JDBC 驱动类名。 + */ + private String driverClassName = "com.mysql.cj.jdbc.Driver"; + + /** + * 数据库连接 URL。 + */ + private String url; + + /** + * 数据库用户名。 + */ + private String username; + + /** + * 数据库密码。 + */ + private String password; + } +} diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/constant/Constants.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/constant/Constants.java deleted file mode 100644 index 811c6c1..0000000 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/constant/Constants.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.hanserwei.hannote.distributed.id.generator.biz.constant; - -public class Constants { - public static final String LEAF_SEGMENT_ENABLE = "leaf.segment.enable"; - public static final String LEAF_JDBC_URL = "leaf.jdbc.url"; - public static final String LEAF_JDBC_USERNAME = "leaf.jdbc.username"; - public static final String LEAF_JDBC_PASSWORD = "leaf.jdbc.password"; - - public static final String LEAF_SNOWFLAKE_ENABLE = "leaf.snowflake.enable"; - public static final String LEAF_SNOWFLAKE_PORT = "leaf.snowflake.port"; - public static final String LEAF_SNOWFLAKE_ZK_ADDRESS = "leaf.snowflake.zk.address"; -} diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/common/PropertyFactory.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/common/PropertyFactory.java deleted file mode 100644 index d3e5526..0000000 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/common/PropertyFactory.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.hanserwei.hannote.distributed.id.generator.biz.core.common; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.Properties; - -public class PropertyFactory { - private static final Logger logger = LoggerFactory.getLogger(PropertyFactory.class); - private static final Properties prop = new Properties(); - static { - try { - prop.load(PropertyFactory.class.getClassLoader().getResourceAsStream("leaf.properties")); - } catch (IOException e) { - logger.warn("Load Properties Ex", e); - } - } - public static Properties getProperties() { - return prop; - } -} diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/common/Result.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/common/Result.java index 9485370..d2268b3 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/common/Result.java +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/common/Result.java @@ -1,5 +1,10 @@ package com.hanserwei.hannote.distributed.id.generator.biz.core.common; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter public class Result { private long id; private Status status; @@ -12,22 +17,6 @@ public class Result { this.status = status; } - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public Status getStatus() { - return status; - } - - public void setStatus(Status status) { - this.status = status; - } - @Override public String toString() { final StringBuilder sb = new StringBuilder("Result{"); diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/common/Utils.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/common/Utils.java index 53156a5..8ffc58e 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/common/Utils.java +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/common/Utils.java @@ -19,7 +19,7 @@ public class Utils { try { List ipList = getHostAddress(null); // default the first - ip = (!ipList.isEmpty()) ? ipList.get(0) : ""; + ip = (!ipList.isEmpty()) ? ipList.getFirst() : ""; } catch (Exception ex) { ip = ""; logger.warn("Utils get IP warn", ex); @@ -32,7 +32,7 @@ public class Utils { interfaceName = interfaceName.trim(); try { List ipList = getHostAddress(interfaceName); - ip = (!ipList.isEmpty()) ? ipList.get(0) : ""; + ip = (!ipList.isEmpty()) ? ipList.getFirst() : ""; } catch (Exception ex) { ip = ""; logger.warn("Utils get IP warn", ex); diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/segment/dao/IDAllocMapper.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/segment/dao/IDAllocMapper.java index c36cbdf..f0035ff 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/segment/dao/IDAllocMapper.java +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/segment/dao/IDAllocMapper.java @@ -1,10 +1,16 @@ package com.hanserwei.hannote.distributed.id.generator.biz.core.segment.dao; import com.hanserwei.hannote.distributed.id.generator.biz.core.segment.model.LeafAlloc; -import org.apache.ibatis.annotations.*; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.Results; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; import java.util.List; +@Mapper public interface IDAllocMapper { @Select("SELECT biz_tag, max_id, step, update_time FROM leaf_alloc") @@ -27,7 +33,7 @@ public interface IDAllocMapper { @Update("UPDATE leaf_alloc SET max_id = max_id + step WHERE biz_tag = #{tag}") void updateMaxId(@Param("tag") String tag); - @Update("UPDATE leaf_alloc SET max_id = max_id + #{step} WHERE biz_tag = #{key}") + @Update("UPDATE leaf_alloc SET max_id = max_id + #{leafAlloc.step} WHERE biz_tag = #{leafAlloc.key}") void updateMaxIdByCustomStep(@Param("leafAlloc") LeafAlloc leafAlloc); @Select("SELECT biz_tag FROM leaf_alloc") diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/segment/dao/impl/IDAllocDaoImpl.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/segment/dao/impl/IDAllocDaoImpl.java index bdd36fb..4f054bd 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/segment/dao/impl/IDAllocDaoImpl.java +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/segment/dao/impl/IDAllocDaoImpl.java @@ -1,75 +1,50 @@ package com.hanserwei.hannote.distributed.id.generator.biz.core.segment.dao.impl; - import com.hanserwei.hannote.distributed.id.generator.biz.core.segment.dao.IDAllocDao; import com.hanserwei.hannote.distributed.id.generator.biz.core.segment.dao.IDAllocMapper; import com.hanserwei.hannote.distributed.id.generator.biz.core.segment.model.LeafAlloc; -import org.apache.ibatis.mapping.Environment; -import org.apache.ibatis.session.Configuration; -import org.apache.ibatis.session.SqlSession; -import org.apache.ibatis.session.SqlSessionFactory; -import org.apache.ibatis.session.SqlSessionFactoryBuilder; -import org.apache.ibatis.transaction.TransactionFactory; -import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; -import javax.sql.DataSource; import java.util.List; +@Slf4j +@Primary +@Repository +@RequiredArgsConstructor public class IDAllocDaoImpl implements IDAllocDao { - SqlSessionFactory sqlSessionFactory; - - public IDAllocDaoImpl(DataSource dataSource) { - TransactionFactory transactionFactory = new JdbcTransactionFactory(); - Environment environment = new Environment("development", transactionFactory, dataSource); - Configuration configuration = new Configuration(environment); - configuration.addMapper(IDAllocMapper.class); - sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration); + private final IDAllocMapper idAllocMapper; + @PostConstruct + void logInit() { + log.info("IDAllocDaoImpl initialized as primary IDAllocDao implementation"); } @Override public List getAllLeafAllocs() { - SqlSession sqlSession = sqlSessionFactory.openSession(false); - try { - return sqlSession.selectList("com.hanserwei.hannote.segment.dao.IDAllocMapper.getAllLeafAllocs"); - } finally { - sqlSession.close(); - } + return idAllocMapper.getAllLeafAllocs(); } @Override + @Transactional(rollbackFor = Exception.class) public LeafAlloc updateMaxIdAndGetLeafAlloc(String tag) { - SqlSession sqlSession = sqlSessionFactory.openSession(); - try { - sqlSession.update("com.hanserwei.hannote.distributed.id.generator.biz.core.segment.dao.IDAllocMapper.updateMaxId", tag); - LeafAlloc result = sqlSession.selectOne("com.hanserwei.hannote.distributed.id.generator.biz.core.segment.dao.IDAllocMapper.getLeafAlloc", tag); - sqlSession.commit(); - return result; - } finally { - sqlSession.close(); - } + idAllocMapper.updateMaxId(tag); + return idAllocMapper.getLeafAlloc(tag); } @Override + @Transactional(rollbackFor = Exception.class) public LeafAlloc updateMaxIdByCustomStepAndGetLeafAlloc(LeafAlloc leafAlloc) { - SqlSession sqlSession = sqlSessionFactory.openSession(); - try { - sqlSession.update("com.hanserwei.hannote.distributed.id.generator.biz.core.segment.dao.IDAllocMapper.updateMaxIdByCustomStep", leafAlloc); - LeafAlloc result = sqlSession.selectOne("com.hanserwei.hannote.distributed.id.generator.biz.core.segment.dao.IDAllocMapper.getLeafAlloc", leafAlloc.getKey()); - sqlSession.commit(); - return result; - } finally { - sqlSession.close(); - } + idAllocMapper.updateMaxIdByCustomStep(leafAlloc); + return idAllocMapper.getLeafAlloc(leafAlloc.getKey()); } @Override public List getAllTags() { - SqlSession sqlSession = sqlSessionFactory.openSession(false); - try { - return sqlSession.selectList("com.hanserwei.hannote.distributed.id.generator.biz.core.segment.dao.IDAllocMapper.getAllTags"); - } finally { - sqlSession.close(); - } + return idAllocMapper.getAllTags(); } } diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/snowflake/SnowflakeIDGenImpl.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/snowflake/SnowflakeIDGenImpl.java index e615cc7..08f38d5 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/snowflake/SnowflakeIDGenImpl.java +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/snowflake/SnowflakeIDGenImpl.java @@ -31,22 +31,23 @@ public class SnowflakeIDGenImpl implements IDGen { private long lastTimestamp = -1L; private static final Random RANDOM = new Random(); - public SnowflakeIDGenImpl(String zkAddress, int port) { + public SnowflakeIDGenImpl(String leafName, String zkAddress, int port) { //Thu Nov 04 2010 09:42:54 GMT+0800 (中国标准时间) - this(zkAddress, port, 1288834974657L); + this(leafName, zkAddress, port, 1288834974657L); } /** + * @param leafName 区分集群的唯一名称 * @param zkAddress zk地址 * @param port snowflake监听端口 * @param twepoch 起始的时间戳 */ - public SnowflakeIDGenImpl(String zkAddress, int port, long twepoch) { + public SnowflakeIDGenImpl(String leafName, String zkAddress, int port, long twepoch) { this.twepoch = twepoch; Preconditions.checkArgument(timeGen() > twepoch, "Snowflake not support twepoch gt currentTime"); final String ip = Utils.getIp(); - SnowflakeZookeeperHolder holder = new SnowflakeZookeeperHolder(ip, String.valueOf(port), zkAddress); - LOGGER.info("twepoch:{} ,ip:{} ,zkAddress:{} port:{}", twepoch, ip, zkAddress, port); + SnowflakeZookeeperHolder holder = new SnowflakeZookeeperHolder(leafName, ip, String.valueOf(port), zkAddress); + LOGGER.info("twepoch:{} ,leafName:{} ,ip:{} ,zkAddress:{} port:{}", twepoch, leafName, ip, zkAddress, port); boolean initFlag = holder.init(); if (initFlag) { workerId = holder.getWorkerID(); diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/snowflake/SnowflakeZookeeperHolder.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/snowflake/SnowflakeZookeeperHolder.java index b25648f..1a97c3e 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/snowflake/SnowflakeZookeeperHolder.java +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/core/snowflake/SnowflakeZookeeperHolder.java @@ -3,7 +3,6 @@ package com.hanserwei.hannote.distributed.id.generator.biz.core.snowflake; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Maps; -import com.hanserwei.hannote.distributed.id.generator.biz.core.common.PropertyFactory; import com.hanserwei.hannote.distributed.id.generator.biz.core.snowflake.exception.CheckLastTimeException; import org.apache.commons.io.FileUtils; import org.apache.curator.RetryPolicy; @@ -27,18 +26,22 @@ import java.util.concurrent.TimeUnit; public class SnowflakeZookeeperHolder { private static final Logger LOGGER = LoggerFactory.getLogger(SnowflakeZookeeperHolder.class); + private final String leafName; + private final String pathForever;//保存所有数据持久的节点 + private final String propPath; private String zk_AddressNode = null;//保存自身的key ip:port-000000001 private String listenAddress = null;//保存自身的key ip:port private int workerID; - private static final String PREFIX_ZK_PATH = "/snowflake/" + PropertyFactory.getProperties().getProperty("leaf.name"); - private static final String PROP_PATH = System.getProperty("java.io.tmpdir") + File.separator + PropertyFactory.getProperties().getProperty("leaf.name") + "/leafconf/{port}/workerID.properties"; - private static final String PATH_FOREVER = PREFIX_ZK_PATH + "/forever";//保存所有数据持久的节点 private String ip; private String port; private String connectionString; private long lastUpdateTime; - public SnowflakeZookeeperHolder(String ip, String port, String connectionString) { + public SnowflakeZookeeperHolder(String leafName, String ip, String port, String connectionString) { + this.leafName = leafName; + String prefixZkPath = "/snowflake/" + leafName; + this.pathForever = prefixZkPath + "/forever"; + this.propPath = System.getProperty("java.io.tmpdir") + File.separator + leafName + "/leafconf/{port}/workerID.properties"; this.ip = ip; this.port = port; this.listenAddress = ip + ":" + port; @@ -47,22 +50,23 @@ public class SnowflakeZookeeperHolder { public boolean init() { try { + LOGGER.info("Initializing SnowflakeZookeeperHolder for leafName={}, listenAddress={}, zkAddress={}", leafName, listenAddress, connectionString); CuratorFramework curator = createWithOptions(connectionString, new RetryUntilElapsed(1000, 4), 10000, 6000); curator.start(); - Stat stat = curator.checkExists().forPath(PATH_FOREVER); + Stat stat = curator.checkExists().forPath(pathForever); if (stat == null) { //不存在根节点,机器第一次启动,创建/snowflake/ip:port-000000000,并上传数据 zk_AddressNode = createNode(curator); //worker id 默认是0 updateLocalWorkerID(workerID); //定时上报本机时间给forever节点 - ScheduledUploadData(curator, zk_AddressNode); + scheduleUploadData(curator, zk_AddressNode); return true; } else { Map nodeMap = Maps.newHashMap();//ip:port->00001 Map realNode = Maps.newHashMap();//ip:port->(ipport-000001) //存在根节点,先检查是否有属于自己的根节点 - List keys = curator.getChildren().forPath(PATH_FOREVER); + List keys = curator.getChildren().forPath(pathForever); for (String key : keys) { String[] nodeKey = key.split("-"); realNode.put(nodeKey[0], key); @@ -71,7 +75,7 @@ public class SnowflakeZookeeperHolder { Integer workerid = nodeMap.get(listenAddress); if (workerid != null) { //有自己的节点,zk_AddressNode=ip:port - zk_AddressNode = PATH_FOREVER + "/" + realNode.get(listenAddress); + zk_AddressNode = pathForever + "/" + realNode.get(listenAddress); workerID = workerid;//启动worder时使用会使用 if (!checkInitTimeStamp(curator, zk_AddressNode)) { throw new CheckLastTimeException("init timestamp check error,forever node timestamp gt this node time"); @@ -95,7 +99,7 @@ public class SnowflakeZookeeperHolder { LOGGER.error("Start node ERROR {}", e); try { Properties properties = new Properties(); - properties.load(new FileInputStream(new File(PROP_PATH.replace("{port}", port + "")))); + properties.load(new FileInputStream(new File(propPath.replace("{port}", port + "")))); workerID = Integer.valueOf(properties.getProperty("workerID")); LOGGER.warn("START FAILED ,use local node file properties workerID-{}", workerID); } catch (Exception e1) { @@ -107,10 +111,10 @@ public class SnowflakeZookeeperHolder { } private void doService(CuratorFramework curator) { - ScheduledUploadData(curator, zk_AddressNode);// /snowflake_forever/ip:port-000000001 + scheduleUploadData(curator, zk_AddressNode);// /snowflake_forever/ip:port-000000001 } - private void ScheduledUploadData(final CuratorFramework curator, final String zk_AddressNode) { + private void scheduleUploadData(final CuratorFramework curator, final String zk_AddressNode) { Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable r) { @@ -143,7 +147,7 @@ public class SnowflakeZookeeperHolder { */ private String createNode(CuratorFramework curator) throws Exception { try { - return curator.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath(PATH_FOREVER + "/" + listenAddress + "-", buildData().getBytes()); + return curator.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath(pathForever + "/" + listenAddress + "-", buildData().getBytes()); } catch (Exception e) { LOGGER.error("create node error msg {} ", e.getMessage()); throw e; @@ -186,7 +190,7 @@ public class SnowflakeZookeeperHolder { * @param workerID */ private void updateLocalWorkerID(int workerID) { - File leafConfFile = new File(PROP_PATH.replace("{port}", port)); + File leafConfFile = new File(propPath.replace("{port}", port)); boolean exists = leafConfFile.exists(); LOGGER.info("file exists status is {}", exists); if (exists) { diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/model/SegmentBufferView.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/model/SegmentBufferView.java index a45bcb6..9028e5a 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/model/SegmentBufferView.java +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/model/SegmentBufferView.java @@ -1,5 +1,10 @@ package com.hanserwei.hannote.distributed.id.generator.biz.model; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter public class SegmentBufferView { private String key; private long value0; @@ -13,83 +18,4 @@ public class SegmentBufferView { private boolean nextReady; private boolean initOk; - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public long getValue1() { - return value1; - } - - public void setValue1(long value1) { - this.value1 = value1; - } - - public int getStep1() { - return step1; - } - - public void setStep1(int step1) { - this.step1 = step1; - } - - public long getMax1() { - return max1; - } - - public void setMax1(long max1) { - this.max1 = max1; - } - - public long getValue0() { - return value0; - } - - public void setValue0(long value0) { - this.value0 = value0; - } - - public int getStep0() { - return step0; - } - - public void setStep0(int step0) { - this.step0 = step0; - } - - public long getMax0() { - return max0; - } - - public void setMax0(long max0) { - this.max0 = max0; - } - - public int getPos() { - return pos; - } - - public void setPos(int pos) { - this.pos = pos; - } - - public boolean isNextReady() { - return nextReady; - } - - public void setNextReady(boolean nextReady) { - this.nextReady = nextReady; - } - - public boolean isInitOk() { - return initOk; - } - - public void setInitOk(boolean initOk) { - this.initOk = initOk; - } } diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/service/SegmentService.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/service/SegmentService.java index b1c7617..6390dd9 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/service/SegmentService.java +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/service/SegmentService.java @@ -1,67 +1,51 @@ package com.hanserwei.hannote.distributed.id.generator.biz.service; -import com.alibaba.druid.pool.DruidDataSource; -import com.hanserwei.hannote.distributed.id.generator.biz.constant.Constants; +import com.hanserwei.hannote.distributed.id.generator.biz.config.LeafProperties; import com.hanserwei.hannote.distributed.id.generator.biz.core.IDGen; -import com.hanserwei.hannote.distributed.id.generator.biz.core.common.PropertyFactory; import com.hanserwei.hannote.distributed.id.generator.biz.core.common.Result; import com.hanserwei.hannote.distributed.id.generator.biz.core.common.ZeroIDGen; import com.hanserwei.hannote.distributed.id.generator.biz.core.segment.SegmentIDGenImpl; import com.hanserwei.hannote.distributed.id.generator.biz.core.segment.dao.IDAllocDao; -import com.hanserwei.hannote.distributed.id.generator.biz.core.segment.dao.impl.IDAllocDaoImpl; -import com.hanserwei.hannote.distributed.id.generator.biz.exception.InitException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.sql.SQLException; -import java.util.Properties; - -@Service("SegmentService") +@Slf4j +@Service +@RequiredArgsConstructor public class SegmentService { - private Logger logger = LoggerFactory.getLogger(SegmentService.class); + + private final LeafProperties leafProperties; + private final IDAllocDao idAllocDao; private IDGen idGen; - private DruidDataSource dataSource; - public SegmentService() throws SQLException, InitException { - Properties properties = PropertyFactory.getProperties(); - boolean flag = Boolean.parseBoolean(properties.getProperty(Constants.LEAF_SEGMENT_ENABLE, "true")); - if (flag) { - // Config dataSource - dataSource = new DruidDataSource(); - dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); - dataSource.setUrl(properties.getProperty(Constants.LEAF_JDBC_URL)); - dataSource.setUsername(properties.getProperty(Constants.LEAF_JDBC_USERNAME)); - dataSource.setPassword(properties.getProperty(Constants.LEAF_JDBC_PASSWORD)); - dataSource.setValidationQuery("select 1"); - dataSource.init(); - - // Config Dao - IDAllocDao dao = new IDAllocDaoImpl(dataSource); - - // Config ID Gen - idGen = new SegmentIDGenImpl(); - ((SegmentIDGenImpl) idGen).setDao(dao); - if (idGen.init()) { - logger.info("Segment Service Init Successfully"); + @PostConstruct + public void init() { + if (leafProperties.getSegment().isEnable()) { + SegmentIDGenImpl segmentIDGen = new SegmentIDGenImpl(); + segmentIDGen.setDao(idAllocDao); + if (segmentIDGen.init()) { + this.idGen = segmentIDGen; + log.info("Segment Service Init Successfully"); } else { - throw new InitException("Segment Service Init Fail"); + throw new IllegalStateException("Segment Service Init Fail"); } } else { - idGen = new ZeroIDGen(); - logger.info("Zero ID Gen Service Init Successfully"); + this.idGen = new ZeroIDGen(); + log.info("Segment Service disabled, Zero ID Gen Service Init Successfully"); } } public Result getId(String key) { + if (idGen == null) { + throw new IllegalStateException("Segment Service not initialized"); + } return idGen.get(key); } public SegmentIDGenImpl getIdGen() { - if (idGen instanceof SegmentIDGenImpl) { - return (SegmentIDGenImpl) idGen; - } - return null; + return idGen instanceof SegmentIDGenImpl ? (SegmentIDGenImpl) idGen : null; } } diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/service/SnowflakeService.java b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/service/SnowflakeService.java index c4f395c..df16c56 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/service/SnowflakeService.java +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/java/com/hanserwei/hannote/distributed/id/generator/biz/service/SnowflakeService.java @@ -1,44 +1,53 @@ package com.hanserwei.hannote.distributed.id.generator.biz.service; - -import com.hanserwei.hannote.distributed.id.generator.biz.constant.Constants; +import com.hanserwei.hannote.distributed.id.generator.biz.config.LeafProperties; import com.hanserwei.hannote.distributed.id.generator.biz.core.IDGen; -import com.hanserwei.hannote.distributed.id.generator.biz.core.common.PropertyFactory; import com.hanserwei.hannote.distributed.id.generator.biz.core.common.Result; import com.hanserwei.hannote.distributed.id.generator.biz.core.common.ZeroIDGen; import com.hanserwei.hannote.distributed.id.generator.biz.core.snowflake.SnowflakeIDGenImpl; -import com.hanserwei.hannote.distributed.id.generator.biz.exception.InitException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; -import java.util.Properties; - -@Service("SnowflakeService") +@Slf4j +@Service +@RequiredArgsConstructor public class SnowflakeService { - private Logger logger = LoggerFactory.getLogger(SnowflakeService.class); + + private final LeafProperties leafProperties; private IDGen idGen; - public SnowflakeService() throws InitException { - Properties properties = PropertyFactory.getProperties(); - boolean flag = Boolean.parseBoolean(properties.getProperty(Constants.LEAF_SNOWFLAKE_ENABLE, "true")); - if (flag) { - String zkAddress = properties.getProperty(Constants.LEAF_SNOWFLAKE_ZK_ADDRESS); - int port = Integer.parseInt(properties.getProperty(Constants.LEAF_SNOWFLAKE_PORT)); - idGen = new SnowflakeIDGenImpl(zkAddress, port); - if(idGen.init()) { - logger.info("Snowflake Service Init Successfully"); + @PostConstruct + public void init() { + if (leafProperties.getSnowflake().isEnable()) { + String zkAddress = leafProperties.getSnowflake().getZkAddress(); + if (!StringUtils.hasText(zkAddress)) { + throw new IllegalStateException("Snowflake Service Init Fail: zk address is required"); + } + int port = leafProperties.getSnowflake().getPort(); + if (port <= 0) { + throw new IllegalStateException("Snowflake Service Init Fail: port must be positive"); + } + SnowflakeIDGenImpl snowflakeIDGen = new SnowflakeIDGenImpl(leafProperties.getName(), zkAddress, port); + if (snowflakeIDGen.init()) { + this.idGen = snowflakeIDGen; + log.info("Snowflake Service Init Successfully with zkAddress={} and port={}", zkAddress, port); } else { - throw new InitException("Snowflake Service Init Fail"); + throw new IllegalStateException("Snowflake Service Init Fail"); } } else { - idGen = new ZeroIDGen(); - logger.info("Zero ID Gen Service Init Successfully"); + this.idGen = new ZeroIDGen(); + log.info("Snowflake Service disabled, Zero ID Gen Service Init Successfully"); } } public Result getId(String key) { + if (idGen == null) { + throw new IllegalStateException("Snowflake Service not initialized"); + } return idGen.get(key); } } diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/application-dev.yml b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/application-dev.yml index 88ff417..154530a 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/application-dev.yml +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/application-dev.yml @@ -1,5 +1,6 @@ spring: - cassandra: - keyspace-name: hannote - contact-points: 127.0.0.1 - port: 9042 + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/leaf?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: mysql diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/application-prod.yml b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/application-prod.yml index e69de29..df7bd29 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/application-prod.yml +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/application-prod.yml @@ -0,0 +1,11 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: ${LEAF_DB_URL:jdbc:mysql://db-host:3306/leaf?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai} + username: ${LEAF_DB_USERNAME:leaf_user} + password: ${LEAF_DB_PASSWORD:leaf_password} + +leaf: + snowflake: + zk-address: "${LEAF_SNOWFLAKE_ZK_ADDRESS:zk.example.com:2181}" + port: ${LEAF_SNOWFLAKE_PORT:2222} diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/application.yml b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/application.yml index c828c64..6e5b49b 100644 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/application.yml +++ b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/application.yml @@ -4,3 +4,22 @@ server: spring: profiles: active: dev # 默认激活 dev 本地开发环境 + datasource: + driver-class-name: ${LEAF_JDBC_DRIVER_CLASS_NAME:com.mysql.cj.jdbc.Driver} + url: ${LEAF_JDBC_URL:jdbc:mysql://127.0.0.1:3306/leaf?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai} + username: ${LEAF_JDBC_USERNAME:root} + password: ${LEAF_JDBC_PASSWORD:mysql} + +leaf: + name: ${LEAF_NAME:han-note-leaf} + jdbc: + driver-class-name: ${LEAF_JDBC_DRIVER_CLASS_NAME:com.mysql.cj.jdbc.Driver} + url: ${LEAF_JDBC_URL:jdbc:mysql://127.0.0.1:3306/leaf?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai} + username: ${LEAF_JDBC_USERNAME:root} + password: ${LEAF_JDBC_PASSWORD:mysql} + segment: + enable: ${LEAF_SEGMENT_ENABLE:true} + snowflake: + enable: ${LEAF_SNOWFLAKE_ENABLE:true} + zk-address: "${LEAF_SNOWFLAKE_ZK_ADDRESS:127.0.0.1:2181}" + port: ${LEAF_SNOWFLAKE_PORT:2222} diff --git a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/leaf.properties b/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/leaf.properties deleted file mode 100644 index 2fd6562..0000000 --- a/han-note-distributed-id-generator/han-note-distributed-id-generator-biz/src/main/resources/leaf.properties +++ /dev/null @@ -1,12 +0,0 @@ -leaf.name=com.sankuai.leaf.opensource.test -leaf.segment.enable=true -leaf.jdbc.url=jdbc:mysql://127.0.0.1:3306/leaf?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai -leaf.jdbc.username=root -leaf.jdbc.password=mysql - -# ???? snowflake ?? -leaf.snowflake.enable=true -# snowflake ???? zk ?? -leaf.snowflake.zk.address=127.0.0.1:2181 -# snowflake ?????????? -leaf.snowflake.port=2222 diff --git a/pom.xml b/pom.xml index 075e821..010df35 100755 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,10 @@ 5.6.227 3.8.0 3.2.2 + 2.20.0 + 0.9.16 + 5.9.0 + 3.9.4 @@ -220,6 +224,26 @@ feign-form ${feign-form.version} + + commons-io + commons-io + ${common-io.version} + + + org.perf4j + perf4j + ${perf4j.version} + + + org.apache.curator + curator-recipes + ${curator-recipes.version} + + + org.apache.zookeeper + zookeeper + ${zookeeper.version} + com.hanserwei han-note-user-api