├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── imadcn
│ │ └── framework
│ │ └── idworker
│ │ ├── algorithm
│ │ ├── CompressUUID.java
│ │ └── Snowflake.java
│ │ ├── common
│ │ ├── ConfigConstants.java
│ │ ├── GeneratorStrategy.java
│ │ └── SerializeStrategy.java
│ │ ├── config
│ │ ├── ApplicationConfiguration.java
│ │ └── ZookeeperConfiguration.java
│ │ ├── exception
│ │ ├── ConfigException.java
│ │ ├── RegException.java
│ │ └── RegExceptionHandler.java
│ │ ├── generator
│ │ ├── CompressUUIDGenerator.java
│ │ ├── IdGenerator.java
│ │ └── SnowflakeGenerator.java
│ │ ├── register
│ │ ├── AbstractWorkerRegister.java
│ │ ├── GeneratorConnector.java
│ │ ├── WorkerRegister.java
│ │ └── zookeeper
│ │ │ ├── NodeInfo.java
│ │ │ ├── NodePath.java
│ │ │ └── ZookeeperWorkerRegister.java
│ │ ├── registry
│ │ ├── CoordinatorRegistryCenter.java
│ │ ├── RegistryCenter.java
│ │ └── zookeeper
│ │ │ └── ZookeeperRegistryCenter.java
│ │ ├── serialize
│ │ ├── Serializer.java
│ │ └── json
│ │ │ ├── FastJsonSerializer.java
│ │ │ ├── JacksonSerializer.java
│ │ │ └── JsonSerializer.java
│ │ ├── spring
│ │ ├── common
│ │ │ ├── BaseBeanDefinitionTag.java
│ │ │ ├── GeneratorBeanDefinitionTag.java
│ │ │ └── ZookeeperBeanDefinitionTag.java
│ │ └── schema
│ │ │ ├── handler
│ │ │ ├── GeneratorNamespaceHandler.java
│ │ │ └── IdworkerNamespaceHandler.java
│ │ │ └── parser
│ │ │ ├── BaseBeanDefinitionParser.java
│ │ │ ├── GeneratorBeanDefinitionParser.java
│ │ │ ├── GeneratorRegisteryBuilder.java
│ │ │ └── RegistryBeanDefinitionParser.java
│ │ └── util
│ │ └── HostUtils.java
└── resources
│ └── META-INF
│ ├── generator.xsd
│ ├── idworker.xsd
│ ├── spring.handlers
│ └── spring.schemas
└── test
├── java
└── com
│ └── imadcn
│ └── system
│ └── test
│ ├── AllSpringTests.java
│ ├── ProcedureTest.java
│ ├── ResultPrinter.java
│ ├── idworker
│ ├── CacheableAndtDurableTest.java
│ ├── CacheableButNotDurableTest.java
│ ├── CompressUUIDTest.java
│ ├── IdGeneratorTest.java
│ ├── IdStrategyTest.java
│ ├── JsonSerializerTest.java
│ ├── ManualCloseTest.java
│ ├── NewGeneratorDefinitionTest.java
│ ├── NotCacheableButDurableTest.java
│ ├── NotCacheableNorDurableTest.java
│ ├── RegExceptionTest.java
│ ├── RegistryFileTest.java
│ ├── SerializeFastJsonModeTest.java
│ ├── SerializeJacksonModeTest.java
│ ├── SerializeUnsupportedModeTest.java
│ ├── SpringIdWorkerTest.java
│ ├── ZKPersistModeTest.java
│ └── ZookeeperRegisterCtrTest.java
│ └── spring
│ ├── AbstractZookeeperJUnit4SpringContextTests.java
│ └── EmbedZookeeperTestExecutionListener.java
└── resources
├── META-INF
├── base.xml
├── idworker-ctx-cacheable-and-durable.xml
├── idworker-ctx-cacheable-but-not-durable.xml
├── idworker-ctx-manual.xml
├── idworker-ctx-new-xsd.xml
├── idworker-ctx-not-cacheable-but-durable.xml
├── idworker-ctx-not-cacheable-nor-durable.xml
├── idworker-ctx-persist-mode.xml
├── idworker-ctx-registry-file.xml
├── idworker-ctx-serialize-fastjson.xml
├── idworker-ctx-serialize-jackson.xml
├── idworker-ctx-strategy.xml
├── idworker-ctx.xml
└── idworker-reg-ctr.xml
├── conf
└── config.properties
└── logback.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 | *.log
11 | .settings
12 | .settings/*
13 | .classpath
14 | .project
15 | logs
16 | tmp
17 | target
18 | target/*
19 |
20 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
21 | hs_err_pid*
22 | /.idea
23 | *.cache
24 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | jdk:
3 | - openjdk8
4 | before_script:
5 | - echo "MAVEN_OPTS='-Xmx1024m -XX:MaxPermSize=256m'" > ~/.mavenrc
6 | after_success:
7 | - mvn clean cobertura:cobertura coveralls:report
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## idworker - 基于zookeeper,snowflake的分布式统一ID生成工具
2 |
3 | [](https://app.travis-ci.com/imadcn/idworker)
4 | [](https://coveralls.io/github/imadcn/idworker?branch=master)
5 | [](https://search.maven.org/artifact/com.imadcn.framework/idworker)
6 | [](https://www.apache.org/licenses/LICENSE-2.0.html)
7 |
8 | ### 是什么
9 | idworker 是一个基于zookeeper和snowflake算法的分布式统一ID生成工具,通过zookeeper自动注册机器(最多1024台),无需手动指定workerId和dataCenterId
10 |
11 | ### 怎么用
12 | #### Maven
13 |
14 | ```xml
15 |
16 | com.imadcn.framework
17 | idworker
18 | ${latest.version}
19 |
20 | ```
21 |
22 | #### XML
23 |
24 | ```xml
25 |
26 |
34 |
35 |
36 |
37 |
38 |
39 | ```
40 |
41 | #### API
42 |
43 | ```java
44 | @Autowired
45 | public IdGenerator generator;
46 |
47 | public void id() {
48 | long id = generator.nextId(); // Long型ID(64进制UUID不支持),随着时间推移,ID长度为7-19位
49 | long[] ids = generator.nextId(100_000); // 批量Long型ID(64进制UUID不支持),最多10w个
50 |
51 | String strId = generator.nextStringId(); // 字符串格式ID
52 | String fixedId = generator.nextFixedStringId(); // 固定19位长度字符串Id
53 | }
54 |
55 | ```
56 |
57 | ### 配置参考
58 | #### 注册中心配置,如zookeeper(64进制UUID策略可不配置注册中心)
59 |
60 | |属性|类型|必填|缺省值|兼容版本|描述|
61 | |:------|:------|:------|:------|:------|:------|
62 | |id|String|是| |1.0.0+|Spring容器中的ID|
63 | |server-lists|String|是| |1.0.0+|连接Zookeeper服务器的列表 包括IP地址和端口号 多个地址用逗号分隔 如: host1:2181,host2:2181|
64 | |namespace|String|否|idworker|1.0.0+|Zookeeper的命名空间|
65 | |base-sleep-time-milliseconds|int|否|1000|1.0.0+|等待重试的间隔时间的初始值 单位:毫秒|
66 | |max-sleep-time-milliseconds|int|否|3000|1.0.0+|等待重试的间隔时间的最大值 单位:毫秒|
67 | |max-retries|int|否|3|1.0.0+|最大重试次数|
68 | |session-timeout-milliseconds|int|否|60000|1.0.0+|会话超时时间 单位:毫秒|
69 | |connection-timeout-milliseconds|int|否|15000|1.0.0+|连接超时时间 单位:毫秒|
70 | |digest|String|否| |1.0.0+|连接Zookeeper的权限令牌 缺省为不需要权限验证|
71 |
72 | #### ID生成策略配置
73 |
74 | |属性|类型|必填|缺省值|兼容版本|描述|
75 | |:------|:------|:------|:------|:------|:------|
76 | |id|String|是| |1.0.0+|Spring容器中的ID|
77 | |strategy|String|是|snowflake|1.2.0+|ID生成[snowflake, compress_uuid],当策略为64进制uuid时,registry-center-ref可不用配置|
78 | |registry-center-ref|String|否| |1.0.0+|注册中心SpringBeanRef,当生成策略为snowflake时,必填|
79 | |group|String|否|default|1.0.0+|分组名,可以为不同业务分配分组,独立注册|
80 | |registry-file|String|否|./tmp/idworker/GROUPNAME.cache|1.3.0+|注册信息缓存文件地址,默认在程序所在目录 ./tmp/idworker/GROUPNAME.cache|
81 | |durable|boolean|否|false|1.4.0+|节点注册信息是否持久化存储(持久化存储会依赖于本地缓存文件,容器环境建议使用非持久化)|
82 | |serialize|String|否|fastjson|1.6.0+|序列化方式,可选值:fastjson, jackson|
83 | |cacheable|boolean|否|true|1.6.0+|是否使用本地缓存(如果不依赖本地缓存,那么每次都会申请一个新的workerId)。需要注意的是,如果不依赖本地缓存,且开启了节点持久化存储。会在一定次数以后耗尽可用节点信息。|
84 |
85 | #### 生成策略 : snowflake模式
86 |
87 | |属性|类型|必填|缺省值|兼容版本|描述|
88 | |:------|:------|:------|:------|:------|:------|
89 | |id|String|是| |1.2.0+|Spring容器中的ID|
90 | |registry-center-ref|String|是| |1.2.0+|注册中心SpringBeanRef|
91 | |group|String|否|default|1.2.0+|分组名,可以为不同业务分配分组,独立注册|
92 | |registry-file|String|否|./tmp/idworker/GROUPNAME.cache|1.3.0+|注册信息缓存文件地址,默认在程序所在目录 ./tmp/idworker/GROUPNAME.cache|
93 | |durable|String|否|false|1.4.0+|节点注册信息是否持久化存储(持久化存储会依赖于本地缓存文件,容器环境建议使用非持久化)|
94 | |serialize|String|否|fastjson|1.6.0+|序列化方式,可选值:fastjson, jackson|
95 | |cacheable|boolean|否|true|1.6.0+|是否使用本地缓存(如果不依赖本地缓存,那么每次都会申请一个新的workerId)。需要注意的是,如果不依赖本地缓存,且开启了节点持久化存储。会在一定次数以后耗尽可用节点信息。|
96 |
97 | #### 生成策略 : 64进制UUID模式
98 |
99 | |属性|类型|必填|缺省值|兼容版本|描述|
100 | |:------|:------|:------|:------|:------|:------|
101 | |id|String|是| |1.2.0+|Spring容器中的ID|
102 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.imadcn.framework
5 | idworker
6 | ${revision}
7 | jar
8 | ${project.groupId}:${project.artifactId}
9 | zookeeper/snowflake based id generator tools
10 | https://github.com/imadcn/idworker
11 |
12 |
13 |
14 | imadcn
15 | http://www.imadcn.com
16 | nevase@foxmail.com
17 | +8
18 |
19 |
20 |
21 |
22 |
23 | Apache License, Version 2.0
24 | http://www.apache.org/licenses/LICENSE-2.0
25 |
26 |
27 |
28 |
29 | https://github.com/imadcn/idworker.git
30 | scm:https://github.com/imadcn/idworker.git
31 | scm:https://github.com/imadcn/idworker.git
32 |
33 |
34 |
35 | 1.6.0
36 |
37 | 1.8
38 | 1.8
39 | UTF-8
40 |
41 | 3.8.1
42 | 3.2.0
43 | 3.2.1
44 | 3.3.0
45 | 1.6
46 | 1.6.8
47 | 2.5.3
48 | 2.7
49 | 4.3.0
50 |
51 | 4.3.30.RELEASE
52 | 4.3.0
53 | 1.2.83
54 | 2.13.4.2
55 | 4.13.2
56 | 1.7.32
57 | 1.2.7
58 | 2.11.0
59 |
60 |
61 |
62 |
63 |
64 | org.springframework
65 | spring-context
66 | ${dep.springframework.version}
67 | provided
68 |
69 |
70 | org.springframework
71 | spring-context-support
72 | ${dep.springframework.version}
73 | provided
74 |
75 |
76 | org.springframework
77 | spring-test
78 | ${dep.springframework.version}
79 | test
80 |
81 |
82 |
83 |
84 | org.apache.curator
85 | curator-framework
86 | ${dep.curator.version}
87 |
88 |
89 | org.apache.curator
90 | curator-client
91 | ${dep.curator.version}
92 |
93 |
94 | org.apache.curator
95 | curator-recipes
96 | ${dep.curator.version}
97 |
98 |
99 | org.apache.curator
100 | curator-test
101 | ${dep.curator.version}
102 | test
103 |
104 |
105 |
106 |
107 | com.alibaba
108 | fastjson
109 | ${dep.fastjson.version}
110 | provided
111 | true
112 |
113 |
114 |
115 | com.fasterxml.jackson.core
116 | jackson-databind
117 | ${dep.jackson.version}
118 | true
119 |
120 |
121 |
122 |
123 | commons-io
124 | commons-io
125 | ${dep.commons-io.version}
126 |
127 |
128 |
129 |
130 | org.slf4j
131 | slf4j-api
132 | ${dep.slf4j.version}
133 | provided
134 |
135 |
136 | org.slf4j
137 | jcl-over-slf4j
138 | ${dep.slf4j.version}
139 | provided
140 |
141 |
142 | org.slf4j
143 | log4j-over-slf4j
144 | ${dep.slf4j.version}
145 | provided
146 |
147 |
148 | ch.qos.logback
149 | logback-classic
150 | ${dep.logback.version}
151 | test
152 |
153 |
154 | org.slf4j
155 | slf4j-api
156 |
157 |
158 |
159 |
160 |
161 |
162 | junit
163 | junit
164 | ${dep.junit.version}
165 | test
166 |
167 |
168 |
169 |
170 |
171 | ossrh
172 | https://oss.sonatype.org/content/repositories/snapshots
173 |
174 |
175 | ossrh
176 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
177 |
178 |
179 |
180 |
181 |
182 |
183 | org.apache.maven.plugins
184 | maven-jar-plugin
185 | ${maven-jar-plugin.version}
186 |
187 |
188 | true
189 | true
190 |
191 | true
192 | true
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 | org.codehaus.mojo
201 | cobertura-maven-plugin
202 | ${cobertura-maven-plugin.version}
203 |
204 | true
205 | ${project.build.sourceEncoding}
206 | true
207 | xml
208 |
209 | true
210 |
211 | com/imadcn/test/**/**Test.class
212 |
213 |
214 |
215 |
216 |
217 | org.eluder.coveralls
218 | coveralls-maven-plugin
219 | ${coveralls-maven-plugin.version}
220 |
221 |
222 |
223 |
224 |
225 |
226 | release
227 |
228 |
229 |
230 |
231 | org.sonatype.plugins
232 | nexus-staging-maven-plugin
233 | ${nexus-staging-maven-plugin.version}
234 | true
235 |
236 | ossrh
237 | https://oss.sonatype.org/
238 | true
239 |
240 |
241 |
242 |
243 | org.apache.maven.plugins
244 | maven-release-plugin
245 | ${maven-release-plugin.version}
246 |
247 | true
248 | false
249 | release
250 | deploy
251 |
252 |
253 |
254 |
255 | org.apache.maven.plugins
256 | maven-compiler-plugin
257 | ${maven-compiler-plugin.version}
258 |
259 | ${maven.compiler.source}
260 | ${maven.compiler.target}
261 | ${project.build.sourceEncoding}
262 | true
263 |
264 |
265 |
266 |
267 | org.apache.maven.plugins
268 | maven-source-plugin
269 | ${maven-source-plugin.version}
270 |
271 |
272 | package
273 |
274 | jar-no-fork
275 |
276 |
277 |
278 |
279 |
280 |
281 | org.apache.maven.plugins
282 | maven-javadoc-plugin
283 | ${maven-javadoc-plugin.version}
284 |
285 |
286 | attach-javadocs
287 |
288 | jar
289 |
290 |
291 |
292 |
293 | true
294 | ${project.build.sourceEncoding}
295 | ${project.build.sourceEncoding}
296 | ${project.build.sourceEncoding}
297 |
298 |
299 |
300 |
301 | org.apache.maven.plugins
302 | maven-gpg-plugin
303 | ${maven-gpg-plugin.version}
304 |
305 |
306 | sign-artifacts
307 | verify
308 |
309 | sign
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/algorithm/CompressUUID.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2018 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.framework.idworker.algorithm;
14 |
15 | import java.util.UUID;
16 |
17 | /**
18 | * 64进制的UUID,取值范围 [a-zA-Z0-9_-]
19 | *
20 | * @author imadcn
21 | * @since 1.2.0
22 | */
23 | public class CompressUUID {
24 |
25 | private static final String[] CHARS = new String[] {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
26 | "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8",
27 | "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",
28 | "V", "W", "X", "Y", "Z", "_", "-"};
29 |
30 | /**
31 | * 不带"-"符号的UUID
32 | *
33 | * @return 不带"-"符号的UUID
34 | */
35 | public static String noneDashUuid() {
36 | return UUID.randomUUID().toString().replace("-", "");
37 | }
38 |
39 | /**
40 | * 22位长度的 UUID
41 | *
42 | * @return 22位长度的 UUID
43 | */
44 | public static String uuid22() {
45 | StringBuffer r = new StringBuffer();
46 | String uuid = new StringBuilder().append("0").append(noneDashUuid()).toString();
47 | int index = 0;
48 | int[] buff = new int[3];
49 | int l = uuid.length();
50 | for (int i = 0; i < l; i++) {
51 | index = i % 3;
52 | buff[index] = Integer.parseInt("" + uuid.charAt(i), 16);
53 | if (index == 2) {
54 | r.append(CHARS[buff[0] << 2 | buff[1] >>> 2]);
55 | r.append(CHARS[(buff[1] & 3) << 4 | buff[2]]);
56 | }
57 | }
58 | return r.toString();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/algorithm/Snowflake.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.algorithm;
2 |
3 | import java.util.Random;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 |
8 | /**
9 | * Snowflake的结构如下(每部分用-分开):
10 | * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
11 | * · 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
12 | * · 41位时间戳(毫秒级),注意,41位时间戳不是存储当前时间的时间戳,而是存储时间戳的差值(当前时间戳 -
13 | * 开始时间戳)得到的值),这里的的开始时间戳,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序epoch属性)。41位的时间戳,可以使用69年
14 | * · 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId
15 | * · 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间戳)产生4096个ID序号 加起来刚好64位,为一个Long型。
16 | *
17 | * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
18 | *
19 | * 注意这里进行了小改动:
20 | * · Snowflake是5位的datacenter加5位的机器id; 这里变成使用10位的机器id (b)
21 | * · 对系统时间的依赖性非常强,需关闭ntp的时间同步功能。当检测到ntp时间调整后,将会拒绝分配id
22 | *
23 | * @author imadcn
24 | * @since 1.0.0
25 | */
26 | public class Snowflake {
27 |
28 | private static final Logger logger = LoggerFactory.getLogger(Snowflake.class);
29 |
30 | /**
31 | * 机器ID
32 | */
33 | private final long workerId;
34 | /**
35 | * 时间起始标记点,作为基准,一般取系统的最近时间,默认2017-01-01
36 | */
37 | private final long epoch = 1483200000000L;
38 | /**
39 | * 机器id所占的位数(源设计为5位,这里取消dataCenterId,采用10位,既1024台)
40 | */
41 | private final long workerIdBits = 10L;
42 | /**
43 | * 机器ID最大值: 1023 (从0开始)
44 | */
45 | private final long maxWorkerId = -1L ^ -1L << workerIdBits;
46 | /**
47 | * 序列在id中占的位数
48 | */
49 | private final long sequenceBits = 12L;
50 | /**
51 | * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095),12位
52 | */
53 | private final long sequenceMask = -1L ^ -1L << sequenceBits;
54 | /**
55 | * 机器ID向左移12位
56 | */
57 | private final long workerIdShift = sequenceBits;
58 | /**
59 | * 时间戳向左移22位(5+5+12)
60 | */
61 | private final long timestampLeftShift = sequenceBits + workerIdBits;
62 | /**
63 | * 并发控制,毫秒内序列(0~4095)
64 | */
65 | private long sequence = 0L;
66 | /**
67 | * 上次生成ID的时间戳
68 | */
69 | private long lastTimestamp = -1L;
70 | /**
71 | * 100,000
72 | */
73 | private final int HUNDRED_K = 100_000;
74 | /**
75 | * sequence随机种子(兼容低并发下,sequence均为0的情况)
76 | */
77 | private static final Random RANDOM = new Random();
78 |
79 | /**
80 | * @param workerId 机器Id
81 | */
82 | private Snowflake(long workerId) {
83 | if (workerId > maxWorkerId || workerId < 0) {
84 | String message = String.format("worker Id can't be greater than %d or less than 0", maxWorkerId);
85 | throw new IllegalArgumentException(message);
86 | }
87 | this.workerId = workerId;
88 | }
89 |
90 | /**
91 | * Snowflake Builder
92 | *
93 | * @param workerId 机器Id
94 | * @return Snowflake Instance
95 | */
96 | public static Snowflake create(long workerId) {
97 | return new Snowflake(workerId);
98 | }
99 |
100 | /**
101 | * Snowflake Builder
102 | *
103 | * @param workerId 机器Id
104 | * @param lowConcurrency 是否低并发模式
105 | * @return Snowflake Instance
106 | */
107 | @Deprecated
108 | public static Snowflake create(long workerId, boolean lowConcurrency) {
109 | return create(workerId);
110 | }
111 |
112 | /**
113 | * 批量获取ID
114 | *
115 | * @param size 获取大小,最多10万个
116 | * @return SnowflakeId
117 | */
118 | public long[] nextId(int size) {
119 | if (size <= 0 || size > HUNDRED_K) {
120 | String message = String.format("Size can't be greater than %d or less than 0", HUNDRED_K);
121 | throw new IllegalArgumentException(message);
122 | }
123 | long[] ids = new long[size];
124 | for (int i = 0; i < size; i++) {
125 | ids[i] = nextId();
126 | }
127 | return ids;
128 | }
129 |
130 | /**
131 | * 获得ID
132 | *
133 | * @return SnowflakeId
134 | */
135 | public synchronized long nextId() {
136 | long timestamp = timeGen();
137 | // 如果上一个timestamp与新产生的相等,则sequence加一(0-4095循环);
138 | if (lastTimestamp == timestamp) {
139 | // 对新的timestamp,sequence从0开始
140 | sequence = sequence + 1 & sequenceMask;
141 | // 毫秒内序列溢出
142 | if (sequence == 0) {
143 | // 阻塞到下一个毫秒,获得新的时间戳
144 | sequence = RANDOM.nextInt(100);
145 | timestamp = tilNextMillis(lastTimestamp);
146 | }
147 | } else {
148 | // 时间戳改变,毫秒内序列重置
149 | sequence = RANDOM.nextInt(100);
150 | }
151 | // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
152 | if (timestamp < lastTimestamp) {
153 | String message = String.format("Clock moved backwards. Refusing to generate id for %d milliseconds.",
154 | (lastTimestamp - timestamp));
155 | logger.error(message);
156 | throw new RuntimeException(message);
157 | }
158 | lastTimestamp = timestamp;
159 | // 移位并通过或运算拼到一起组成64位的ID
160 | return timestamp - epoch << timestampLeftShift | workerId << workerIdShift | sequence;
161 | }
162 |
163 | /**
164 | * 等待下一个毫秒的到来, 保证返回的毫秒数在参数lastTimestamp之后
165 | *
166 | * @param lastTimestamp 上次生成ID的时间戳
167 | * @return 下一个毫秒
168 | */
169 | private long tilNextMillis(long lastTimestamp) {
170 | long timestamp = timeGen();
171 | while (timestamp <= lastTimestamp) {
172 | timestamp = timeGen();
173 | }
174 | return timestamp;
175 | }
176 |
177 | /**
178 | * 获得系统当前毫秒数
179 | *
180 | * @return 获得系统当前毫秒数
181 | */
182 | private long timeGen() {
183 | return System.currentTimeMillis();
184 | }
185 |
186 | }
187 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/common/ConfigConstants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2019 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.framework.idworker.common;
14 |
15 | /**
16 | * 配置常量
17 | *
18 | * @author imadcn
19 | * @since 1.3.0
20 | */
21 | public class ConfigConstants {
22 |
23 | public static final String SNOWFLAKE = "snowflake";
24 |
25 | public static final String COMPRESS_UUID = "compress-uuid";
26 |
27 | public static final String REGISTRY = "registry";
28 |
29 | public static final String GENERATOR = "generator";
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/common/GeneratorStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2018 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.framework.idworker.common;
14 |
15 | import com.imadcn.framework.idworker.algorithm.CompressUUID;
16 | import com.imadcn.framework.idworker.algorithm.Snowflake;
17 |
18 | /**
19 | * ID生成策略
20 | *
21 | * @author imadcn
22 | * @since 1.2.0
23 | */
24 | public enum GeneratorStrategy {
25 | /**
26 | * snowflake算法 {@link Snowflake}
27 | */
28 | SNOWFLAKE("snowflake"),
29 | /**
30 | * 64进制UUID算法 {@link CompressUUID}
31 | */
32 | COMPRESS_UUID("compress_uuid"),;
33 |
34 | /**
35 | * 策略Code
36 | */
37 | private String code;
38 |
39 | private GeneratorStrategy(String code) {
40 | this.code = code;
41 | }
42 |
43 | /**
44 | * 获取策略CODE
45 | *
46 | * @return 策略CODE
47 | */
48 | public String getCode() {
49 | return code;
50 | }
51 |
52 | /**
53 | * 根据code获取生成策略enum
54 | *
55 | * @param code 策略Code
56 | * @return 生成策略
57 | */
58 | public static GeneratorStrategy getByCode(String code) {
59 | if (code != null) {
60 | GeneratorStrategy[] strategyValues = values();
61 | if (strategyValues != null) {
62 | for (GeneratorStrategy strategy : strategyValues) {
63 | if (code.equals(strategy.getCode())) {
64 | return strategy;
65 | }
66 | }
67 | }
68 | }
69 | return null;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/common/SerializeStrategy.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.common;
2 |
3 | /**
4 | * 序列化策略常量
5 | *
6 | * @author imadcn
7 | * @since 1.6.0
8 | */
9 | public class SerializeStrategy {
10 |
11 | public static final String SERIALIZE_JSON_FASTJSON = "fastjson";
12 |
13 | public static final String SERIALIZE_JSON_JACKSON = "jackson";
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/config/ApplicationConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.config;
2 |
3 | /**
4 | * Application 配置
5 | *
6 | * @author imadcn
7 | * @since 1.0.0
8 | */
9 | public class ApplicationConfiguration {
10 |
11 | /**
12 | * 分组名字,默认default
13 | */
14 | private String group = "default";
15 | /**
16 | * 生成策略,默认snowflake
17 | *
18 | * @since 1.2.0
19 | */
20 | private String strategy = "snowflake";
21 | /**
22 | * 低并发模式(snowflake策略生效)
23 | *
24 | * @since 1.2.5
25 | */
26 | @Deprecated
27 | private boolean lowConcurrency = false;
28 | /**
29 | * zk节点信息本地缓存文件路径
30 | *
31 | * @since 1.3.0
32 | */
33 | private String registryFile;
34 | /**
35 | * zk节点是否持久化存储
36 | *
37 | * @since 1.4.0
38 | */
39 | private boolean durable;
40 |
41 | /**
42 | * 序列化工具
43 | *
44 | * @since 1.6.0
45 | */
46 | private String serialize;
47 |
48 | /**
49 | * 是否使用本地缓存(如果不依赖本地缓存,那么每次都会申请一个新的workerId)
50 | *
51 | * 需要注意的是,如果不依赖本地缓存,且开启了节点持久化存储。会在一定次数以后耗尽可用节点信息。
52 | *
53 | * @since 1.6.0
54 | */
55 | private boolean cacheable = true;
56 |
57 | public String getGroup() {
58 | return group;
59 | }
60 |
61 | public void setGroup(String group) {
62 | this.group = group;
63 | }
64 |
65 | public String getStrategy() {
66 | return strategy;
67 | }
68 |
69 | public void setStrategy(String strategy) {
70 | this.strategy = strategy;
71 | }
72 |
73 | @Deprecated
74 | public boolean isLowConcurrency() {
75 | return lowConcurrency;
76 | }
77 |
78 | @Deprecated
79 | public void setLowConcurrency(boolean lowConcurrency) {
80 | this.lowConcurrency = lowConcurrency;
81 | }
82 |
83 | public String getRegistryFile() {
84 | return registryFile;
85 | }
86 |
87 | public void setRegistryFile(String registryFile) {
88 | this.registryFile = registryFile;
89 | }
90 |
91 | public boolean isDurable() {
92 | return durable;
93 | }
94 |
95 | public void setDurable(boolean durable) {
96 | this.durable = durable;
97 | }
98 |
99 | public String getSerialize() {
100 | return serialize;
101 | }
102 |
103 | public void setSerialize(String serialize) {
104 | this.serialize = serialize;
105 | }
106 |
107 | public boolean isCacheable() {
108 | return cacheable;
109 | }
110 |
111 | public void setCacheable(boolean cacheable) {
112 | this.cacheable = cacheable;
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/config/ZookeeperConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.config;
2 |
3 | /**
4 | * Zookeeper 配置
5 | *
6 | * @author imadcn
7 | * @since 1.0.0
8 | */
9 | public class ZookeeperConfiguration {
10 |
11 | /**
12 | * 连接Zookeeper服务器的列表. 包括IP地址和端口号. 多个地址用逗号分隔. 如: host1:2181,host2:2181
13 | */
14 | private String serverLists;
15 |
16 | /**
17 | * 命名空间.
18 | */
19 | private String namespace = "idworker";
20 |
21 | /**
22 | * 等待重试的间隔时间的初始值. 单位毫秒. 默认1s
23 | */
24 | private int baseSleepTimeMilliseconds = 1000;
25 |
26 | /**
27 | * 等待重试的间隔时间的最大值. 单位毫秒. 默认3s
28 | */
29 | private int maxSleepTimeMilliseconds = 3000;
30 |
31 | /**
32 | * 最大重试次数.
33 | */
34 | private int maxRetries = 3;
35 |
36 | /**
37 | * 会话超时时间. 单位毫秒. 默认60s
38 | */
39 | private int sessionTimeoutMilliseconds;
40 |
41 | /**
42 | * 连接超时时间. 单位毫秒. 默认15s
43 | */
44 | private int connectionTimeoutMilliseconds;
45 |
46 | /**
47 | * 连接Zookeeper的权限令牌. 缺省为不需要权限验证.
48 | */
49 | private String digest;
50 |
51 | public String getServerLists() {
52 | return serverLists;
53 | }
54 |
55 | public void setServerLists(String serverLists) {
56 | this.serverLists = serverLists;
57 | }
58 |
59 | public String getNamespace() {
60 | return namespace;
61 | }
62 |
63 | public void setNamespace(String namespace) {
64 | this.namespace = namespace;
65 | }
66 |
67 | public int getBaseSleepTimeMilliseconds() {
68 | return baseSleepTimeMilliseconds;
69 | }
70 |
71 | public void setBaseSleepTimeMilliseconds(int baseSleepTimeMilliseconds) {
72 | this.baseSleepTimeMilliseconds = baseSleepTimeMilliseconds;
73 | }
74 |
75 | public int getMaxSleepTimeMilliseconds() {
76 | return maxSleepTimeMilliseconds;
77 | }
78 |
79 | public void setMaxSleepTimeMilliseconds(int maxSleepTimeMilliseconds) {
80 | this.maxSleepTimeMilliseconds = maxSleepTimeMilliseconds;
81 | }
82 |
83 | public int getMaxRetries() {
84 | return maxRetries;
85 | }
86 |
87 | public void setMaxRetries(int maxRetries) {
88 | this.maxRetries = maxRetries;
89 | }
90 |
91 | public int getSessionTimeoutMilliseconds() {
92 | return sessionTimeoutMilliseconds;
93 | }
94 |
95 | public void setSessionTimeoutMilliseconds(int sessionTimeoutMilliseconds) {
96 | this.sessionTimeoutMilliseconds = sessionTimeoutMilliseconds;
97 | }
98 |
99 | public int getConnectionTimeoutMilliseconds() {
100 | return connectionTimeoutMilliseconds;
101 | }
102 |
103 | public void setConnectionTimeoutMilliseconds(int connectionTimeoutMilliseconds) {
104 | this.connectionTimeoutMilliseconds = connectionTimeoutMilliseconds;
105 | }
106 |
107 | public String getDigest() {
108 | return digest;
109 | }
110 |
111 | public void setDigest(String digest) {
112 | this.digest = digest;
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/exception/ConfigException.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.exception;
2 |
3 | /**
4 | * configuration error exception
5 | *
6 | * @author imadcn
7 | * @since 1.6.0
8 | */
9 | public class ConfigException extends RuntimeException {
10 |
11 | private static final long serialVersionUID = 1L;
12 |
13 | public ConfigException(final String errorMessage, final Object... args) {
14 | super(String.format(errorMessage, args));
15 | }
16 |
17 | public ConfigException(final Exception cause) {
18 | super(cause);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/exception/RegException.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.exception;
2 |
3 | /**
4 | * 注册中心异常.
5 | *
6 | * @author imadcn
7 | * @since 1.0.0
8 | */
9 | public final class RegException extends RuntimeException {
10 |
11 | private static final long serialVersionUID = -6417179023552012152L;
12 |
13 | public RegException(final String errorMessage, final Object... args) {
14 | super(String.format(errorMessage, args));
15 | }
16 |
17 | public RegException(final Exception cause) {
18 | super(cause);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/exception/RegExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.exception;
2 |
3 | import org.apache.zookeeper.KeeperException.ConnectionLossException;
4 | import org.apache.zookeeper.KeeperException.NoNodeException;
5 | import org.apache.zookeeper.KeeperException.NodeExistsException;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | /**
10 | * 注册中心异常处理类.
11 | *
12 | * @author imadcn
13 | * @since 1.0.0
14 | */
15 | public final class RegExceptionHandler {
16 |
17 | private static Logger logger = LoggerFactory.getLogger(RegExceptionHandler.class);
18 |
19 | /**
20 | * 处理异常.
21 | *
22 | *
23 | * 处理掉中断和连接失效异常并继续抛注册中心.
24 | *
25 | *
26 | * @param cause 待处理异常.
27 | */
28 | public static void handleException(final Exception cause) {
29 | if (null == cause) {
30 | return;
31 | }
32 | if (isIgnoredException(cause) || null != cause.getCause() && isIgnoredException(cause.getCause())) {
33 | logger.debug("Elastic job: ignored exception for: {}", cause.getMessage());
34 | } else if (cause instanceof InterruptedException) {
35 | Thread.currentThread().interrupt();
36 | } else {
37 | throw new RegException(cause);
38 | }
39 | }
40 |
41 | private static boolean isIgnoredException(final Throwable cause) {
42 | return cause instanceof ConnectionLossException || cause instanceof NoNodeException
43 | || cause instanceof NodeExistsException;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/generator/CompressUUIDGenerator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2018 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.framework.idworker.generator;
14 |
15 | import com.imadcn.framework.idworker.algorithm.CompressUUID;
16 |
17 | /**
18 | * 64进制的UUID
19 | *
20 | * @author imadcn
21 | * @since 1.2.0
22 | */
23 | public class CompressUUIDGenerator implements IdGenerator {
24 |
25 | @Override
26 | public long[] nextId(int size) {
27 | throw new UnsupportedOperationException(
28 | "unsupported operation[public long[] nextId(int size)] in CompressUUIDGenerator");
29 | }
30 |
31 | @Override
32 | public long nextId() {
33 | throw new UnsupportedOperationException("unsupported operation[public long nextId()] in CompressUUIDGenerator");
34 | }
35 |
36 | @Override
37 | public String nextStringId() {
38 | return CompressUUID.uuid22();
39 | }
40 |
41 | @Override
42 | public String nextFixedStringId() {
43 | return nextStringId();
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/generator/IdGenerator.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.generator;
2 |
3 | /**
4 | * Id生成
5 | *
6 | * @author imadcn
7 | * @since 1.0.0
8 | */
9 | public interface IdGenerator {
10 |
11 | /**
12 | * 批量获取ID
13 | *
14 | * @param size 获取大小,最多10万个
15 | * @return ID
16 | */
17 | long[] nextId(int size);
18 |
19 | /**
20 | * 获取ID
21 | *
22 | * @return ID
23 | */
24 | long nextId();
25 |
26 | /**
27 | * 字符串格式的ID
28 | *
29 | * @since 1.2.0
30 | * @return ID
31 | */
32 | String nextStringId();
33 |
34 | /**
35 | * 固定19位长度,字符串格式的ID
36 | *
37 | * @since 1.2.0
38 | * @return ID
39 | */
40 | String nextFixedStringId();
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/generator/SnowflakeGenerator.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.generator;
2 |
3 | import java.io.IOException;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 |
8 | import com.imadcn.framework.idworker.algorithm.Snowflake;
9 | import com.imadcn.framework.idworker.exception.RegException;
10 | import com.imadcn.framework.idworker.register.GeneratorConnector;
11 | import com.imadcn.framework.idworker.register.zookeeper.ZookeeperWorkerRegister;
12 |
13 | /**
14 | * Snowflake算法生成工具
15 | *
16 | * @author imadcn
17 | * @since 1.0.0
18 | */
19 | public class SnowflakeGenerator implements IdGenerator, GeneratorConnector {
20 |
21 | static final String FIXED_STRING_FORMAT = "%019d";
22 |
23 | private Logger logger = LoggerFactory.getLogger(getClass());
24 |
25 | /**
26 | * snowflake 算法
27 | */
28 | private Snowflake snowflake;
29 | /**
30 | * snowflake 注册
31 | */
32 | private ZookeeperWorkerRegister register;
33 | /**
34 | * 是否正在工作
35 | */
36 | private volatile boolean initialized = false;
37 |
38 | private volatile boolean working = false;
39 |
40 | private volatile boolean connecting = false;
41 |
42 | public SnowflakeGenerator(ZookeeperWorkerRegister register) {
43 | this.register = register;
44 | }
45 |
46 | @Override
47 | public synchronized void init() {
48 | if (!initialized) {
49 | // 持久化节点+本地缓存,不再使用状态监听
50 | // listener = new ZookeeperConnectionStateListener(this);
51 | // // 添加监听
52 | // register.addConnectionListener(listener);
53 | // 连接与注册workerId
54 | connect();
55 | initialized = true;
56 | }
57 | }
58 |
59 | /**
60 | * 初始化
61 | */
62 | @Override
63 | public void connect() {
64 | if (!isConnecting()) {
65 | working = false;
66 | connecting = true;
67 | long workerId = register.register();
68 | if (workerId >= 0) {
69 | snowflake = Snowflake.create(workerId);
70 | working = true;
71 | connecting = false;
72 | } else {
73 | throw new RegException("failed to get worker id");
74 | }
75 | } else {
76 | logger.info("worker is connecting, skip this time of register.");
77 | }
78 | }
79 |
80 | @Override
81 | public long[] nextId(int size) {
82 | if (isWorking()) {
83 | return snowflake.nextId(size);
84 | }
85 | throw new IllegalStateException("worker isn't working, reg center may shutdown");
86 | }
87 |
88 | @Override
89 | public long nextId() {
90 | if (isWorking()) {
91 | return snowflake.nextId();
92 | }
93 | throw new IllegalStateException("worker isn't working, reg center may shutdown");
94 | }
95 |
96 | @Override
97 | public String nextStringId() {
98 | return String.valueOf(nextId());
99 | }
100 |
101 | @Override
102 | public String nextFixedStringId() {
103 | return String.format(FIXED_STRING_FORMAT, nextId());
104 | }
105 |
106 | @Override
107 | public void suspend() {
108 | this.working = false;
109 | }
110 |
111 | @Override
112 | public synchronized void close() throws IOException {
113 | // 关闭,先重置状态(避免ZK删除 workerId,其他机器抢注,会导致workerID 重新生成的BUG)
114 | reset();
115 | register.logout();
116 | }
117 |
118 | @Override
119 | public void destroy() throws IOException {
120 | close();
121 | }
122 |
123 | @Override
124 | public boolean isWorking() {
125 | return this.working;
126 | }
127 |
128 | @Override
129 | public boolean isConnecting() {
130 | return this.connecting;
131 | }
132 |
133 | /**
134 | * 重置连接状态
135 | */
136 | protected void reset() {
137 | initialized = false;
138 | working = false;
139 | connecting = false;
140 | }
141 |
142 | /**
143 | * 低并发模式
144 | *
145 | * @param lowConcurrency 低并发模式 ? true : false
146 | */
147 | @Deprecated
148 | public void setLowConcurrency(boolean lowConcurrency) {
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/register/AbstractWorkerRegister.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.register;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.net.UnknownHostException;
6 | import java.nio.charset.StandardCharsets;
7 | import java.util.Date;
8 | import java.util.UUID;
9 |
10 | import org.apache.commons.io.FileUtils;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 |
14 | import com.imadcn.framework.idworker.register.zookeeper.NodeInfo;
15 | import com.imadcn.framework.idworker.register.zookeeper.NodePath;
16 | import com.imadcn.framework.idworker.registry.CoordinatorRegistryCenter;
17 | import com.imadcn.framework.idworker.serialize.json.JsonSerializer;
18 | import com.imadcn.framework.idworker.util.HostUtils;
19 |
20 | /**
21 | * Worker注册
22 | *
23 | * @author imadcn
24 | * @since 1.6.0
25 | */
26 | public abstract class AbstractWorkerRegister implements WorkerRegister {
27 |
28 | protected Logger logger = LoggerFactory.getLogger(getClass());
29 |
30 | /**
31 | * 最大机器数
32 | */
33 | public static final long MAX_WORKER_NUM = 1024;
34 | /**
35 | * 加锁最大等待时间
36 | */
37 | public static final int MAX_LOCK_WAIT_TIME_MS = 30 * 1000;
38 | /**
39 | * 注册中心工具
40 | */
41 | private CoordinatorRegistryCenter regCenter;
42 | /**
43 | * 注册文件
44 | */
45 | private String registryFile;
46 | /**
47 | * zk节点信息
48 | */
49 | private NodePath nodePath;
50 | /**
51 | * zk节点是否持久化存储
52 | */
53 | private boolean durable;
54 | /**
55 | * Json序列化
56 | */
57 | private JsonSerializer jsonSerializer;
58 |
59 | /**
60 | * 是否使用本地缓存(如果不依赖本地缓存,那么每次都会申请一个新的workerId)
61 | */
62 | private boolean cachable;
63 |
64 | /**
65 | * 检查节点信息
66 | *
67 | * @param localNodeInfo 本地缓存节点信息
68 | * @param zkNodeInfo zookeeper节点信息
69 | * @return 节点信息相同返回true,否则返回false
70 | */
71 | protected boolean checkNodeInfo(NodeInfo localNodeInfo, NodeInfo zkNodeInfo) {
72 | try {
73 | // NodeId、HostName、GroupName 相等(本地缓存==ZK数据)
74 | if (!zkNodeInfo.getNodeId().equals(localNodeInfo.getNodeId())) {
75 | return false;
76 | }
77 | // remove ip check, temporary
78 | // if (!zkNodeInfo.getIp().equals(localNodeInfo.getIp())) {
79 | // return false;
80 | // }
81 | if (!zkNodeInfo.getHostName().equals(localNodeInfo.getHostName())) {
82 | return false;
83 | }
84 | if (!zkNodeInfo.getGroupName().equals(localNodeInfo.getGroupName())) {
85 | return false;
86 | }
87 | return true;
88 | } catch (Exception e) {
89 | logger.error("check node info error, {}", e);
90 | return false;
91 | }
92 | }
93 |
94 | /**
95 | * 缓存机器节点信息至本地
96 | *
97 | * @param nodeInfo 机器节点信息
98 | * @throws Exception 系统异常
99 | */
100 | protected void saveLocalNodeInfo(NodeInfo nodeInfo) throws Exception {
101 | try {
102 | File nodeInfoFile = new File(getRegistryFile());
103 | String nodeInfoJson = jsonizeNodeInfo(nodeInfo);
104 | FileUtils.writeStringToFile(nodeInfoFile, nodeInfoJson, StandardCharsets.UTF_8);
105 | } catch (IOException e) {
106 | logger.error("save node info cache error, {}", e);
107 | }
108 | }
109 |
110 | /**
111 | * 读取本地缓存机器节点
112 | *
113 | * @return 机器节点信息
114 | */
115 | protected NodeInfo getLocalNodeInfo() {
116 | try {
117 | File nodeInfoFile = new File(getRegistryFile());
118 | if (nodeInfoFile.exists()) {
119 | String nodeInfoJson = FileUtils.readFileToString(nodeInfoFile, StandardCharsets.UTF_8);
120 | NodeInfo nodeInfo = createNodeInfoFromJsonStr(nodeInfoJson);
121 | return nodeInfo;
122 | }
123 | } catch (Exception e) {
124 | logger.error("read node info cache error, {}", e);
125 | }
126 | return null;
127 | }
128 |
129 | /**
130 | * 初始化节点信息
131 | *
132 | * @param groupName 分组名
133 | * @param workerId 机器号
134 | * @return 节点信息
135 | * @throws UnknownHostException 未知HOST异常
136 | */
137 | protected NodeInfo createNodeInfo(String groupName, Integer workerId) throws UnknownHostException {
138 | NodeInfo nodeInfo = new NodeInfo();
139 | nodeInfo.setNodeId(genNodeId());
140 | nodeInfo.setGroupName(groupName);
141 | nodeInfo.setWorkerId(workerId);
142 | nodeInfo.setIp(HostUtils.getLocalIP());
143 | nodeInfo.setHostName(HostUtils.getLocalHostName());
144 | nodeInfo.setCreateTime(new Date());
145 | nodeInfo.setUpdateTime(new Date());
146 | return nodeInfo;
147 | }
148 |
149 | /**
150 | * 通过节点信息JSON字符串反序列化节点信息
151 | *
152 | * @param jsonStr 节点信息JSON字符串
153 | * @return 节点信息
154 | * @throws Exception 系统异常
155 | */
156 | protected NodeInfo createNodeInfoFromJsonStr(String jsonStr) throws Exception {
157 | return getJsonSerializer().parseObject(jsonStr, NodeInfo.class);
158 | }
159 |
160 | /**
161 | * 节点信息转json字符串
162 | *
163 | * @param nodeInfo 节点信息
164 | * @return json字符串
165 | * @throws Exception 系统异常
166 | */
167 | protected String jsonizeNodeInfo(NodeInfo nodeInfo) throws Exception {
168 | return getJsonSerializer().toJsonString(nodeInfo);
169 | }
170 |
171 | /**
172 | * 获取本地节点缓存文件路径
173 | *
174 | * @param groupName 分组名
175 | * @return 文件路径
176 | */
177 | protected String getDefaultFilePath(String groupName) {
178 | StringBuilder builder = new StringBuilder();
179 | builder.append(".").append(File.separator).append("tmp");
180 | builder.append(File.separator).append("idworker");
181 | builder.append(File.separator).append(groupName).append(".cache");
182 | return builder.toString();
183 | }
184 |
185 | /**
186 | * 获取节点唯一ID (基于UUID)
187 | *
188 | * @return 节点唯一ID
189 | */
190 | protected String genNodeId() {
191 | return UUID.randomUUID().toString().replace("-", "").toLowerCase();
192 | }
193 |
194 | /**
195 | * 获取节点ZK Path Key
196 | *
197 | * @param nodePath 节点路径信息
198 | * @param workerId 节点机器ID
199 | * @return 节点PATH的KEY
200 | */
201 | protected String getNodePathKey(NodePath nodePath, Integer workerId) {
202 | StringBuilder builder = new StringBuilder();
203 | builder.append(nodePath.getWorkerPath()).append("/");
204 | builder.append(workerId);
205 | return builder.toString();
206 | }
207 |
208 | public CoordinatorRegistryCenter getRegCenter() {
209 | return regCenter;
210 | }
211 |
212 | public void setRegCenter(final CoordinatorRegistryCenter regCenter) {
213 | this.regCenter = regCenter;
214 | }
215 |
216 | public String getRegistryFile() {
217 | return registryFile;
218 | }
219 |
220 | public void setRegistryFile(String registryFile) {
221 | this.registryFile = registryFile;
222 | }
223 |
224 | public boolean isDurable() {
225 | return durable;
226 | }
227 |
228 | public void setDurable(boolean durable) {
229 | this.durable = durable;
230 | }
231 |
232 | public JsonSerializer getJsonSerializer() {
233 | return jsonSerializer;
234 | }
235 |
236 | public void setJsonSerializer(JsonSerializer jsonSerializer) {
237 | this.jsonSerializer = jsonSerializer;
238 | }
239 |
240 | public boolean isCachable() {
241 | return cachable;
242 | }
243 |
244 | public void setNodePath(final NodePath nodePath) {
245 | this.nodePath = nodePath;
246 | }
247 |
248 | public void setCachable(boolean cachable) {
249 | this.cachable = cachable;
250 | }
251 |
252 | public NodePath getNodePath() {
253 | return nodePath;
254 | }
255 | }
256 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/register/GeneratorConnector.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.register;
2 |
3 | import java.io.Closeable;
4 | import java.io.IOException;
5 |
6 | /**
7 | * ID生成注册Connector
8 | *
9 | * @author imadcn
10 | * @since 1.1.0
11 | */
12 | public interface GeneratorConnector extends Closeable {
13 |
14 | /**
15 | * 初始化数据
16 | */
17 | void init();
18 |
19 | /**
20 | * 销毁数据
21 | */
22 | void destroy() throws IOException ;
23 |
24 | /**
25 | * 连接
26 | */
27 | void connect();
28 |
29 | /**
30 | * 挂起ID生产
31 | */
32 | void suspend();
33 |
34 | /**
35 | * 是否正在正常运行
36 | *
37 | * @return 是返回 true ,否则返回 false
38 | */
39 | boolean isWorking();
40 |
41 | /**
42 | * 是否正在连接
43 | *
44 | * @return 是返回 true ,否则返回 false
45 | */
46 | boolean isConnecting();
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/register/WorkerRegister.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.register;
2 |
3 | /**
4 | * Worker注册
5 | *
6 | * @author imadcn
7 | * @since 1.1.0
8 | */
9 | public interface WorkerRegister {
10 |
11 | /**
12 | * 注册workerId
13 | *
14 | * @return 注册成功的worker id
15 | */
16 | long register();
17 |
18 | /**
19 | * 退出注册
20 | */
21 | void logout();
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/register/zookeeper/NodeInfo.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.register.zookeeper;
2 |
3 | import java.io.Serializable;
4 | import java.util.Date;
5 |
6 | /**
7 | * 机器节点信息
8 | *
9 | * @author imadcn
10 | * @since 1.0.0
11 | */
12 | public class NodeInfo implements Serializable {
13 |
14 | private static final long serialVersionUID = 1L;
15 |
16 | private String nodeId;
17 | private String groupName;
18 | private Integer workerId;
19 | private String ip;
20 | private String hostName;
21 | private Date updateTime;
22 | private Date createTime;
23 | @Deprecated
24 | private String pid;
25 | @Deprecated
26 | private Long sessionId;
27 |
28 | public String getNodeId() {
29 | return nodeId;
30 | }
31 |
32 | public void setNodeId(String nodeId) {
33 | this.nodeId = nodeId;
34 | }
35 |
36 | public String getGroupName() {
37 | return groupName;
38 | }
39 |
40 | public void setGroupName(String groupName) {
41 | this.groupName = groupName;
42 | }
43 |
44 | public Integer getWorkerId() {
45 | return workerId;
46 | }
47 |
48 | public void setWorkerId(Integer workerId) {
49 | this.workerId = workerId;
50 | }
51 |
52 | public String getIp() {
53 | return ip;
54 | }
55 |
56 | public void setIp(String ip) {
57 | this.ip = ip;
58 | }
59 |
60 | public String getHostName() {
61 | return hostName;
62 | }
63 |
64 | public void setHostName(String hostName) {
65 | this.hostName = hostName;
66 | }
67 |
68 | public Date getUpdateTime() {
69 | return updateTime;
70 | }
71 |
72 | public void setUpdateTime(Date updateTime) {
73 | this.updateTime = updateTime;
74 | }
75 |
76 | public Date getCreateTime() {
77 | return createTime;
78 | }
79 |
80 | public void setCreateTime(Date createTime) {
81 | this.createTime = createTime;
82 | }
83 |
84 | @Deprecated
85 | public String getPid() {
86 | return pid;
87 | }
88 |
89 | @Deprecated
90 | public void setPid(String pid) {
91 | this.pid = pid;
92 | }
93 |
94 | @Deprecated
95 | public Long getSessionId() {
96 | return sessionId;
97 | }
98 |
99 | @Deprecated
100 | public void setSessionId(Long sessionId) {
101 | this.sessionId = sessionId;
102 | }
103 |
104 | @Override
105 | public String toString() {
106 | return "NodeInfo [nodeId=" + nodeId + ", groupName=" + groupName + ", workerId=" + workerId + ", ip=" + ip
107 | + ", hostName=" + hostName + ", updateTime=" + updateTime + ", createTime=" + createTime + "]";
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/register/zookeeper/NodePath.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.register.zookeeper;
2 |
3 | /**
4 | * 机器节点Path
5 | *
6 | * @author imadcn
7 | * @since 1.0.0
8 | */
9 | public class NodePath {
10 |
11 | private static final String WORKER_NODE = "worker";
12 |
13 | /**
14 | * workerId 分组
15 | */
16 | private String groupName;
17 |
18 | /**
19 | * 机器编号
20 | */
21 | private long workerId;
22 |
23 | private long sessionId = -1L;
24 |
25 | public NodePath(String groupName) {
26 | this.groupName = groupName;
27 | }
28 |
29 | public String getGroupPath() {
30 | return String.format("/%s", groupName);
31 | }
32 |
33 | public String getWorkerPath() {
34 | return String.format("/%s/%s", groupName, WORKER_NODE);
35 | }
36 |
37 | public String getWorkerIdPath() {
38 | return String.format("/%s/%s/%s", groupName, WORKER_NODE, workerId);
39 | }
40 |
41 | public String getGroupName() {
42 | return groupName;
43 | }
44 |
45 | public long getWorkerId() {
46 | return workerId;
47 | }
48 |
49 | public void setWorkerId(long workerId) {
50 | this.workerId = workerId;
51 | }
52 |
53 | public long getSessionId() {
54 | return sessionId;
55 | }
56 |
57 | public void setSessionId(long sessionId) {
58 | this.sessionId = sessionId;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/register/zookeeper/ZookeeperWorkerRegister.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.register.zookeeper;
2 |
3 | import java.util.Date;
4 | import java.util.List;
5 | import java.util.concurrent.Executors;
6 | import java.util.concurrent.ThreadFactory;
7 | import java.util.concurrent.TimeUnit;
8 | import java.util.concurrent.TimeoutException;
9 |
10 | import org.apache.curator.framework.CuratorFramework;
11 | import org.apache.curator.framework.imps.CuratorFrameworkState;
12 | import org.apache.curator.framework.recipes.locks.InterProcessMutex;
13 | import org.springframework.util.StringUtils;
14 |
15 | import com.imadcn.framework.idworker.common.SerializeStrategy;
16 | import com.imadcn.framework.idworker.config.ApplicationConfiguration;
17 | import com.imadcn.framework.idworker.exception.ConfigException;
18 | import com.imadcn.framework.idworker.exception.RegException;
19 | import com.imadcn.framework.idworker.register.AbstractWorkerRegister;
20 | import com.imadcn.framework.idworker.registry.CoordinatorRegistryCenter;
21 | import com.imadcn.framework.idworker.serialize.json.FastJsonSerializer;
22 | import com.imadcn.framework.idworker.serialize.json.JacksonSerializer;
23 |
24 | /**
25 | * 机器信息注册
26 | *
27 | * @author imadcn
28 | * @since 1.0.0
29 | */
30 | public class ZookeeperWorkerRegister extends AbstractWorkerRegister {
31 |
32 | public ZookeeperWorkerRegister(CoordinatorRegistryCenter regCenter,
33 | ApplicationConfiguration applicationConfiguration) {
34 | setRegCenter(regCenter);
35 | setNodePath(new NodePath(applicationConfiguration.getGroup()));
36 | setDurable(applicationConfiguration.isDurable());
37 | setCachable(applicationConfiguration.isCacheable());
38 |
39 | if (!isCachable() && isDurable()) {
40 | logger.warn("「durable」&& 「NONE cachable」 may become a waste");
41 | }
42 |
43 | if (SerializeStrategy.SERIALIZE_JSON_FASTJSON.equals(applicationConfiguration.getSerialize())) {
44 | setJsonSerializer(new FastJsonSerializer<>());
45 | } else if (SerializeStrategy.SERIALIZE_JSON_JACKSON.equals(applicationConfiguration.getSerialize())) {
46 | setJsonSerializer(new JacksonSerializer<>());
47 | } else {
48 | throw new ConfigException("unsupported serialize strategy: %s, use: [fastjson / jackson]",
49 | applicationConfiguration.getSerialize());
50 | }
51 | if (StringUtils.isEmpty(applicationConfiguration.getRegistryFile())) {
52 | setRegistryFile(getDefaultFilePath(getNodePath().getGroupName()));
53 | } else {
54 | setRegistryFile(applicationConfiguration.getRegistryFile());
55 | }
56 | }
57 |
58 | /**
59 | * 向zookeeper注册workerId
60 | *
61 | * @return workerId workerId
62 | */
63 | @Override
64 | public long register() {
65 | InterProcessMutex lock = null;
66 | try {
67 | CuratorFramework client = (CuratorFramework) getRegCenter().getRawClient();
68 | lock = new InterProcessMutex(client, getNodePath().getGroupPath());
69 | int numOfChildren = getRegCenter().getNumChildren(getNodePath().getWorkerPath());
70 | if (numOfChildren < MAX_WORKER_NUM) {
71 | if (!lock.acquire(MAX_LOCK_WAIT_TIME_MS, TimeUnit.MILLISECONDS)) {
72 | String message = String.format("acquire lock failed after %s ms.", MAX_LOCK_WAIT_TIME_MS);
73 | throw new TimeoutException(message);
74 | }
75 | NodeInfo localNodeInfo = getLocalNodeInfo();
76 | List children = getRegCenter().getChildrenKeys(getNodePath().getWorkerPath());
77 | /*
78 | * 有本地缓存的节点信息,同时ZK也有这条数据 2021.12 新增判断是否依赖本地缓存,如果不依赖本地缓存,则每次都会申请新的id
79 | */
80 | if (isCachable() && localNodeInfo != null
81 | && children.contains(String.valueOf(localNodeInfo.getWorkerId()))) {
82 | String key = getNodePathKey(getNodePath(), localNodeInfo.getWorkerId());
83 | String zkNodeInfoJson = getRegCenter().get(key);
84 | NodeInfo zkNodeInfo = createNodeInfoFromJsonStr(zkNodeInfoJson);
85 | if (checkNodeInfo(localNodeInfo, zkNodeInfo)) {
86 | // 更新ZK节点信息,保存本地缓存,开启定时上报任务
87 | getNodePath().setWorkerId(zkNodeInfo.getWorkerId());
88 | zkNodeInfo.setUpdateTime(new Date());
89 | updateZookeeperNodeInfo(key, zkNodeInfo);
90 | saveLocalNodeInfo(zkNodeInfo);
91 | executeUploadNodeInfoTask(key, zkNodeInfo);
92 | return zkNodeInfo.getWorkerId();
93 | }
94 | }
95 | // 无本地信息或者缓存数据不匹配,开始向ZK申请节点机器ID
96 | for (int workerId = 0; workerId < MAX_WORKER_NUM; workerId++) {
97 | String workerIdStr = String.valueOf(workerId);
98 | if (!children.contains(workerIdStr)) { // 申请成功
99 | NodeInfo applyNodeInfo = createNodeInfo(getNodePath().getGroupName(), workerId);
100 | getNodePath().setWorkerId(applyNodeInfo.getWorkerId());
101 | // 保存ZK节点信息,保存本地缓存,开启定时上报任务
102 | saveZookeeperNodeInfo(getNodePath().getWorkerIdPath(), applyNodeInfo);
103 | saveLocalNodeInfo(applyNodeInfo);
104 | executeUploadNodeInfoTask(getNodePath().getWorkerIdPath(), applyNodeInfo);
105 | return applyNodeInfo.getWorkerId();
106 | }
107 | }
108 | }
109 | throw new RegException("max worker num reached. register failed");
110 | } catch (RegException e) {
111 | throw e;
112 | } catch (Exception e) {
113 | logger.error("", e);
114 | throw new IllegalStateException(e.getMessage(), e);
115 | } finally {
116 | try {
117 | if (lock != null) {
118 | lock.release();
119 | }
120 | } catch (Exception ignored) {
121 | logger.error("", ignored);
122 | }
123 | }
124 | }
125 |
126 | /**
127 | * 关闭注册
128 | */
129 | @Override
130 | public synchronized void logout() {
131 | CuratorFramework client = (CuratorFramework) getRegCenter().getRawClient();
132 | if (client != null && client.getState() == CuratorFrameworkState.STARTED) {
133 | // 移除注册节点(最大程度的自动释放资源)
134 | getRegCenter().remove(getNodePath().getWorkerIdPath());
135 | // 关闭连接
136 | getRegCenter().close();
137 | }
138 | }
139 |
140 | /**
141 | * 更新节点信息Task
142 | *
143 | * @param key zk path
144 | * @param nodeInfo 节点信息
145 | */
146 | private void executeUploadNodeInfoTask(final String key, final NodeInfo nodeInfo) {
147 | Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
148 | @Override
149 | public Thread newThread(Runnable r) {
150 | Thread thread = new Thread(r, "upload node info task thread");
151 | thread.setDaemon(true);
152 | return thread;
153 | }
154 | }).scheduleWithFixedDelay(new Runnable() {
155 | @Override
156 | public void run() {
157 | updateZookeeperNodeInfo(key, nodeInfo);
158 | }
159 | }, 3L, 3L, TimeUnit.SECONDS);
160 | }
161 |
162 | /**
163 | * 保存ZK节点信息
164 | *
165 | * @param key
166 | * @param nodeInfo
167 | */
168 | private void saveZookeeperNodeInfo(String key, NodeInfo nodeInfo) throws Exception {
169 | if (isDurable()) {
170 | getRegCenter().persist(key, jsonizeNodeInfo(nodeInfo));
171 | } else {
172 | getRegCenter().persistEphemeral(key, jsonizeNodeInfo(nodeInfo));
173 | }
174 | }
175 |
176 | /**
177 | * 刷新ZK节点信息(修改updateTime)
178 | *
179 | * @param key
180 | * @param nodeInfo
181 | */
182 | private void updateZookeeperNodeInfo(String key, NodeInfo nodeInfo) {
183 | try {
184 | nodeInfo.setUpdateTime(new Date());
185 | if (isDurable()) {
186 | getRegCenter().persist(key, jsonizeNodeInfo(nodeInfo));
187 | } else {
188 | getRegCenter().persistEphemeral(key, jsonizeNodeInfo(nodeInfo));
189 | }
190 | } catch (Exception e) {
191 | logger.debug("update zookeeper node info error, {}", e);
192 | }
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/registry/CoordinatorRegistryCenter.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.registry;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * 用于协调分布式服务的注册中心.
7 | *
8 | * @author imadcn
9 | * @since 1.0.0
10 | */
11 | public interface CoordinatorRegistryCenter extends RegistryCenter {
12 |
13 | /**
14 | * 直接从注册中心而非本地缓存获取数据.
15 | *
16 | * @param key 键
17 | * @return 值
18 | */
19 | String getDirectly(String key);
20 |
21 | /**
22 | * 获取子节点名称集合.
23 | *
24 | * @param key 键
25 | * @return 子节点名称集合
26 | */
27 | List getChildrenKeys(String key);
28 |
29 | /**
30 | * 获取子节点数量.
31 | *
32 | * @param key 键
33 | * @return 子节点数量
34 | */
35 | int getNumChildren(String key);
36 |
37 | /**
38 | * 持久化临时注册数据.
39 | *
40 | * @param key 键
41 | * @param value 值
42 | */
43 | void persistEphemeral(String key, String value);
44 |
45 | /**
46 | * 持久化顺序注册数据.
47 | *
48 | * @param key 键
49 | * @param value 值
50 | * @return 包含10位顺序数字的znode名称
51 | */
52 | String persistSequential(String key, String value);
53 |
54 | /**
55 | * 持久化临时顺序注册数据.
56 | *
57 | * @param key 键
58 | */
59 | void persistEphemeralSequential(String key);
60 |
61 | /**
62 | * 添加本地缓存.
63 | *
64 | * @param cachePath 需加入缓存的路径
65 | */
66 | void addCacheData(String cachePath);
67 |
68 | /**
69 | * 释放本地缓存.
70 | *
71 | * @param cachePath 需释放缓存的路径
72 | */
73 | void evictCacheData(String cachePath);
74 |
75 | /**
76 | * 获取注册中心数据缓存对象.
77 | *
78 | * @param cachePath 缓存的节点路径
79 | * @return 注册中心数据缓存对象
80 | */
81 | Object getRawCache(String cachePath);
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/registry/RegistryCenter.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.registry;
2 |
3 | /**
4 | * 注册中心
5 | *
6 | * @author imadcn
7 | * @since 1.0.0
8 | */
9 | public interface RegistryCenter {
10 |
11 | /**
12 | * 初始化注册中心.
13 | */
14 | void init();
15 |
16 | /**
17 | * 关闭注册中心.
18 | */
19 | void close();
20 |
21 | /**
22 | * 获取注册数据.
23 | *
24 | * @param key 键
25 | * @return 值
26 | */
27 | String get(String key);
28 |
29 | /**
30 | * 获取数据是否存在.
31 | *
32 | * @param key 键
33 | * @return 数据是否存在
34 | */
35 | boolean isExisted(String key);
36 |
37 | /**
38 | * 持久化注册数据.
39 | *
40 | * @param key 键
41 | * @param value 值
42 | */
43 | void persist(String key, String value);
44 |
45 | /**
46 | * 更新注册数据.
47 | *
48 | * @param key 键
49 | * @param value 值
50 | */
51 | void update(String key, String value);
52 |
53 | /**
54 | * 删除注册数据.
55 | *
56 | * @param key 键
57 | */
58 | void remove(String key);
59 |
60 | /**
61 | * 获取注册中心当前时间.
62 | *
63 | * @param key 用于获取时间的键
64 | * @return 注册中心当前时间
65 | */
66 | long getRegistryCenterTime(String key);
67 |
68 | /**
69 | * 直接获取操作注册中心的原生客户端. 如:Zookeeper或Redis等原生客户端.
70 | *
71 | * @return 注册中心的原生客户端
72 | */
73 | Object getRawClient();
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/registry/zookeeper/ZookeeperRegistryCenter.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.registry.zookeeper;
2 |
3 | import java.nio.charset.StandardCharsets;
4 | import java.util.Collections;
5 | import java.util.Comparator;
6 | import java.util.HashMap;
7 | import java.util.List;
8 | import java.util.Map;
9 | import java.util.Map.Entry;
10 | import java.util.concurrent.TimeUnit;
11 |
12 | import org.apache.curator.framework.CuratorFramework;
13 | import org.apache.curator.framework.CuratorFrameworkFactory;
14 | import org.apache.curator.framework.api.ACLProvider;
15 | import org.apache.curator.framework.recipes.cache.ChildData;
16 | import org.apache.curator.framework.recipes.cache.TreeCache;
17 | import org.apache.curator.retry.ExponentialBackoffRetry;
18 | import org.apache.curator.utils.CloseableUtils;
19 | import org.apache.zookeeper.CreateMode;
20 | import org.apache.zookeeper.KeeperException;
21 | import org.apache.zookeeper.ZooDefs;
22 | import org.apache.zookeeper.data.ACL;
23 | import org.apache.zookeeper.data.Stat;
24 | import org.slf4j.Logger;
25 | import org.slf4j.LoggerFactory;
26 |
27 | import com.google.common.base.Preconditions;
28 | import com.imadcn.framework.idworker.config.ZookeeperConfiguration;
29 | import com.imadcn.framework.idworker.exception.RegExceptionHandler;
30 | import com.imadcn.framework.idworker.registry.CoordinatorRegistryCenter;
31 |
32 | /**
33 | * Zookeeper注册中心
34 | *
35 | * @author imadcn
36 | * @since 1.0.0
37 | */
38 | public class ZookeeperRegistryCenter implements CoordinatorRegistryCenter {
39 |
40 | private Logger logger = LoggerFactory.getLogger(getClass());
41 |
42 | private final Map caches = new HashMap<>();
43 |
44 | private ZookeeperConfiguration zkConfig;
45 |
46 | private CuratorFramework client;
47 |
48 | public ZookeeperRegistryCenter(ZookeeperConfiguration zookeeperConfigurarion) {
49 | this.zkConfig = zookeeperConfigurarion;
50 | }
51 |
52 | @Override
53 | public synchronized void init() {
54 | if (client != null) {
55 | // client已经初始化,直接重置返回
56 | return;
57 | }
58 | logger.debug("init zookeeper registry, connect to servers : {}", zkConfig.getServerLists());
59 | CuratorFrameworkFactory.Builder builder
60 | = CuratorFrameworkFactory.builder().connectString(zkConfig.getServerLists())
61 | .retryPolicy(new ExponentialBackoffRetry(zkConfig.getBaseSleepTimeMilliseconds(),
62 | zkConfig.getMaxRetries(), zkConfig.getMaxSleepTimeMilliseconds()))
63 | .namespace(zkConfig.getNamespace());
64 | if (0 != zkConfig.getSessionTimeoutMilliseconds()) {
65 | builder.sessionTimeoutMs(zkConfig.getSessionTimeoutMilliseconds());
66 | }
67 | if (0 != zkConfig.getConnectionTimeoutMilliseconds()) {
68 | builder.connectionTimeoutMs(zkConfig.getConnectionTimeoutMilliseconds());
69 | }
70 | if (zkConfig.getDigest() != null && !zkConfig.getDigest().isEmpty()) {
71 | builder.authorization("digest", zkConfig.getDigest().getBytes(StandardCharsets.UTF_8))
72 | .aclProvider(new ACLProvider() {
73 |
74 | @Override
75 | public List getDefaultAcl() {
76 | return ZooDefs.Ids.CREATOR_ALL_ACL;
77 | }
78 |
79 | @Override
80 | public List getAclForPath(final String path) {
81 | return ZooDefs.Ids.CREATOR_ALL_ACL;
82 | }
83 | });
84 | }
85 | client = builder.build();
86 | client.start();
87 | try {
88 | if (!client.blockUntilConnected(zkConfig.getMaxSleepTimeMilliseconds() * zkConfig.getMaxRetries(),
89 | TimeUnit.MILLISECONDS)) {
90 | client.close();
91 | throw new KeeperException.OperationTimeoutException();
92 | }
93 | } catch (final Exception ex) {
94 | RegExceptionHandler.handleException(ex);
95 | }
96 | }
97 |
98 | @Override
99 | public void close() {
100 | if (client == null) {
101 | return;
102 | }
103 | for (Entry each : caches.entrySet()) {
104 | each.getValue().close();
105 | }
106 | waitForCacheClose();
107 | CloseableUtils.closeQuietly(client);
108 | // 重置client状态
109 | client = null;
110 | }
111 |
112 | /**
113 | * TODO 等待500ms, cache先关闭再关闭client, 否则会抛异常 因为异步处理, 可能会导致client先关闭而cache还未关闭结束. 等待Curator新版本解决这个bug.
114 | * BUG地址:https://issues.apache.org/jira/browse/CURATOR-157
115 | */
116 | private void waitForCacheClose() {
117 | try {
118 | Thread.sleep(500L);
119 | } catch (final InterruptedException ex) {
120 | Thread.currentThread().interrupt();
121 | }
122 | }
123 |
124 | @Override
125 | public String get(final String key) {
126 | TreeCache cache = findTreeCache(key);
127 | if (null == cache) {
128 | return getDirectly(key);
129 | }
130 | ChildData resultInCache = cache.getCurrentData(key);
131 | if (null != resultInCache) {
132 | return null == resultInCache.getData() ? null : new String(resultInCache.getData(), StandardCharsets.UTF_8);
133 | }
134 | return getDirectly(key);
135 | }
136 |
137 | private TreeCache findTreeCache(final String key) {
138 | for (Entry entry : caches.entrySet()) {
139 | if (key.startsWith(entry.getKey())) {
140 | return entry.getValue();
141 | }
142 | }
143 | return null;
144 | }
145 |
146 | @Override
147 | public String getDirectly(final String key) {
148 | try {
149 | return new String(client.getData().forPath(key), StandardCharsets.UTF_8);
150 | } catch (final Exception ex) {
151 | RegExceptionHandler.handleException(ex);
152 | return null;
153 | }
154 | }
155 |
156 | @Override
157 | public List getChildrenKeys(final String key) {
158 | try {
159 | List result = client.getChildren().forPath(key);
160 | Collections.sort(result, new Comparator() {
161 | @Override
162 | public int compare(final String o1, final String o2) {
163 | return o2.compareTo(o1);
164 | }
165 | });
166 | return result;
167 | } catch (final Exception ex) {
168 | RegExceptionHandler.handleException(ex);
169 | return Collections.emptyList();
170 | }
171 | }
172 |
173 | @Override
174 | public int getNumChildren(final String key) {
175 | try {
176 | Stat stat = client.checkExists().forPath(key);
177 | if (null != stat) {
178 | return stat.getNumChildren();
179 | }
180 | } catch (final Exception ex) {
181 | RegExceptionHandler.handleException(ex);
182 | }
183 | return 0;
184 | }
185 |
186 | @Override
187 | public boolean isExisted(final String key) {
188 | try {
189 | return null != client.checkExists().forPath(key);
190 | } catch (final Exception ex) {
191 | RegExceptionHandler.handleException(ex);
192 | return false;
193 | }
194 | }
195 |
196 | @Override
197 | public void persist(final String key, final String value) {
198 | try {
199 | if (!isExisted(key)) {
200 | client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(key,
201 | value.getBytes(StandardCharsets.UTF_8));
202 | } else {
203 | update(key, value);
204 | }
205 | } catch (final Exception ex) {
206 | RegExceptionHandler.handleException(ex);
207 | }
208 | }
209 |
210 | @Override
211 | public void update(final String key, final String value) {
212 | try {
213 | client.transactionOp().setData().forPath(key, value.getBytes(StandardCharsets.UTF_8));
214 | // client.inTransaction().check().forPath(key).and().setData().forPath(key,
215 | // value.getBytes(StandardCharsets.UTF_8)).and().commit();
216 | } catch (final Exception ex) {
217 | RegExceptionHandler.handleException(ex);
218 | }
219 | }
220 |
221 | @Override
222 | public void persistEphemeral(final String key, final String value) {
223 | try {
224 | if (isExisted(key)) {
225 | client.delete().deletingChildrenIfNeeded().forPath(key);
226 | }
227 | client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(key,
228 | value.getBytes(StandardCharsets.UTF_8));
229 | } catch (final Exception ex) {
230 | RegExceptionHandler.handleException(ex);
231 | }
232 | }
233 |
234 | @Override
235 | public String persistSequential(final String key, final String value) {
236 | try {
237 | return client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath(key,
238 | value.getBytes(StandardCharsets.UTF_8));
239 | } catch (final Exception ex) {
240 | RegExceptionHandler.handleException(ex);
241 | }
242 | return null;
243 | }
244 |
245 | @Override
246 | public void persistEphemeralSequential(final String key) {
247 | try {
248 | client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(key);
249 | } catch (final Exception ex) {
250 | RegExceptionHandler.handleException(ex);
251 | }
252 | }
253 |
254 | @Override
255 | public void remove(final String key) {
256 | try {
257 | client.delete().deletingChildrenIfNeeded().forPath(key);
258 | } catch (final Exception ex) {
259 | RegExceptionHandler.handleException(ex);
260 | }
261 | }
262 |
263 | @Override
264 | public long getRegistryCenterTime(final String key) {
265 | long result = 0L;
266 | try {
267 | persist(key, "");
268 | result = client.checkExists().forPath(key).getMtime();
269 | } catch (final Exception ex) {
270 | RegExceptionHandler.handleException(ex);
271 | }
272 | Preconditions.checkState(0L != result, "Cannot get registry center time.");
273 | return result;
274 | }
275 |
276 | @Override
277 | public Object getRawClient() {
278 | if (client == null) {
279 | init();
280 | }
281 | return client;
282 | }
283 |
284 | @Override
285 | public void addCacheData(final String cachePath) {
286 | TreeCache cache = new TreeCache(client, cachePath);
287 | try {
288 | cache.start();
289 | } catch (final Exception ex) {
290 | RegExceptionHandler.handleException(ex);
291 | }
292 | caches.put(cachePath + "/", cache);
293 | }
294 |
295 | @Override
296 | public void evictCacheData(final String cachePath) {
297 | TreeCache cache = caches.remove(cachePath + "/");
298 | if (null != cache) {
299 | cache.close();
300 | }
301 | }
302 |
303 | @Override
304 | public Object getRawCache(final String cachePath) {
305 | return caches.get(cachePath + "/");
306 | }
307 | }
308 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/serialize/Serializer.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.serialize;
2 |
3 | public interface Serializer {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/serialize/json/FastJsonSerializer.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.serialize.json;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.serializer.SerializerFeature;
5 |
6 | /**
7 | * fastjson serializer
8 | *
9 | * @author imadcn
10 | * @since 1.6.0
11 | */
12 | public class FastJsonSerializer extends JsonSerializer {
13 |
14 | @Override
15 | public String toJsonString(Object object) throws Exception {
16 | return JSON.toJSONStringWithDateFormat(object, DEFAULT_DATE_FORMAT, SerializerFeature.WriteDateUseDateFormat);
17 | }
18 |
19 | @Override
20 | public T parseObject(String json, Class clazz) throws Exception {
21 | return JSON.parseObject(json, clazz);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/serialize/json/JacksonSerializer.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.serialize.json;
2 |
3 | import java.text.SimpleDateFormat;
4 |
5 | import com.fasterxml.jackson.databind.ObjectMapper;
6 |
7 | /**
8 | * jackson serializer
9 | *
10 | * @author imadcn
11 | * @since 1.6.0
12 | */
13 | public class JacksonSerializer extends JsonSerializer {
14 |
15 | private ObjectMapper objectMapper;
16 |
17 | public JacksonSerializer() {
18 | objectMapper = new ObjectMapper();
19 | objectMapper.setDateFormat(new SimpleDateFormat(DEFAULT_DATE_FORMAT));
20 | }
21 |
22 | @Override
23 | public String toJsonString(Object object) throws Exception {
24 | return objectMapper.writeValueAsString(object);
25 | }
26 |
27 | @Override
28 | public T parseObject(String json, Class clazz) throws Exception {
29 | return objectMapper.readValue(json, clazz);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/serialize/json/JsonSerializer.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.serialize.json;
2 |
3 | import com.imadcn.framework.idworker.serialize.Serializer;
4 |
5 | /**
6 | * json serializer
7 | *
8 | * @author imadcn
9 | * @since 1.6.0
10 | */
11 | public abstract class JsonSerializer implements Serializer {
12 |
13 | /**
14 | * 默认时间装换格式:yyyy-MM-dd HH:mm:ss
15 | */
16 | public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
17 |
18 | /**
19 | * to json string
20 | *
21 | * @param object 待转换对象
22 | * @return JSON 字符串
23 | * @throws Exception 系统异常
24 | */
25 | public abstract String toJsonString(Object object) throws Exception;
26 |
27 | /**
28 | * to java object
29 | *
30 | * @param json JSON 字符串
31 | * @param clazz 对象类型
32 | * @return java对象
33 | * @throws Exception 系统异常
34 | */
35 | public abstract T parseObject(String json, Class clazz) throws Exception;
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/spring/common/BaseBeanDefinitionTag.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.spring.common;
2 |
3 | /**
4 | * BaseBeanDefinitionTag
5 | *
6 | * @author imadcn
7 | * @since 1.0.5
8 | */
9 | public class BaseBeanDefinitionTag {
10 |
11 | public static final String ID = "id";
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/spring/common/GeneratorBeanDefinitionTag.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.spring.common;
2 |
3 | /**
4 | * idworker:application 配置TAF
5 | *
6 | * @author imadcn
7 | * @since 1.0.0
8 | */
9 | public final class GeneratorBeanDefinitionTag extends BaseBeanDefinitionTag {
10 |
11 | private GeneratorBeanDefinitionTag() {
12 | }
13 |
14 | public static final String GROUOP = "group";
15 |
16 | public static final String REGISTRY_CENTER_REF = "registry-center-ref";
17 |
18 | /**
19 | * 生成策略
20 | *
21 | * @since 1.2.0
22 | */
23 | public static final String STRATEGY = "strategy";
24 |
25 | /**
26 | * 低并发模式
27 | *
28 | * @since 1.2.5
29 | */
30 | @Deprecated
31 | public static final String LOW_CONCURRENCY = "low-concurrency";
32 |
33 | /**
34 | * 注册信息本地缓存文件地址
35 | *
36 | * @since 1.3.0
37 | */
38 | public static final String REGISTRY_FILE = "registry-file";
39 |
40 | /**
41 | * ZK节点是否持久化存储
42 | *
43 | * @since 1.4.0
44 | */
45 | public static final String DURABLE = "durable";
46 |
47 | /**
48 | * 序列化方式
49 | *
50 | * @since 1.6.0
51 | */
52 | public static final String SERIALIZE = "serialize";
53 |
54 | /**
55 | * 是否使用本地缓存(如果不依赖本地缓存,那么每次都会申请一个新的workerId)
56 | *
57 | * @since 1.6.0
58 | */
59 | public static final String CACHEABLE = "cacheable";
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/spring/common/ZookeeperBeanDefinitionTag.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.spring.common;
2 |
3 | /**
4 | * idworker:zookeeper 配置TAG
5 | *
6 | * @author imadcn
7 | * @since 1.0.0
8 | */
9 | public final class ZookeeperBeanDefinitionTag {
10 |
11 | private ZookeeperBeanDefinitionTag() {
12 | }
13 |
14 | public static final String SERVER_LISTS = "server-lists";
15 |
16 | public static final String NAMESPACE = "namespace";
17 |
18 | public static final String BASE_SLEEP_TIME_MS = "base-sleep-time-milliseconds";
19 |
20 | public static final String MAX_SLEEP_TIME_MS = "max-sleep-time-milliseconds";
21 |
22 | public static final String MAX_RETRIES = "max-retries";
23 |
24 | public static final String SESSION_TIMEOUT_MS = "session-timeout-milliseconds";
25 |
26 | public static final String CONNECTION_TIMEOUT_MS = "connection-timeout-milliseconds";
27 |
28 | public static final String DIGEST = "digest";
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/spring/schema/handler/GeneratorNamespaceHandler.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.spring.schema.handler;
2 |
3 | import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
4 |
5 | import com.imadcn.framework.idworker.common.ConfigConstants;
6 | import com.imadcn.framework.idworker.spring.schema.parser.GeneratorBeanDefinitionParser;
7 |
8 | /**
9 | * IdworkerNamespaceHandler
10 | *
11 | * @author imadcn
12 | * @since 1.0.0
13 | */
14 | public class GeneratorNamespaceHandler extends NamespaceHandlerSupport {
15 |
16 | @Override
17 | public void init() {
18 | registerBeanDefinitionParser(ConfigConstants.SNOWFLAKE,
19 | new GeneratorBeanDefinitionParser(ConfigConstants.SNOWFLAKE));
20 | registerBeanDefinitionParser(ConfigConstants.COMPRESS_UUID,
21 | new GeneratorBeanDefinitionParser(ConfigConstants.COMPRESS_UUID));
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/spring/schema/handler/IdworkerNamespaceHandler.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.spring.schema.handler;
2 |
3 | import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
4 |
5 | import com.imadcn.framework.idworker.common.ConfigConstants;
6 | import com.imadcn.framework.idworker.spring.schema.parser.RegistryBeanDefinitionParser;
7 |
8 | /**
9 | * IdworkerNamespaceHandler
10 | *
11 | * @author imadcn
12 | * @since 1.0.0
13 | */
14 | public class IdworkerNamespaceHandler extends NamespaceHandlerSupport {
15 |
16 | @Override
17 | public void init() {
18 | registerBeanDefinitionParser(ConfigConstants.REGISTRY,
19 | new RegistryBeanDefinitionParser(ConfigConstants.REGISTRY));
20 | registerBeanDefinitionParser(ConfigConstants.GENERATOR,
21 | new RegistryBeanDefinitionParser(ConfigConstants.GENERATOR));
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/spring/schema/parser/BaseBeanDefinitionParser.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.spring.schema.parser;
2 |
3 | import org.springframework.beans.factory.support.BeanDefinitionBuilder;
4 | import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
5 | import org.w3c.dom.Element;
6 |
7 | /**
8 | * Spring Bean Definition Parser
9 | *
10 | * @author imadcn
11 | * @since 1.0.0
12 | */
13 | public abstract class BaseBeanDefinitionParser extends AbstractBeanDefinitionParser {
14 |
15 | /**
16 | * 设置Bean Id
17 | *
18 | * @param result result
19 | * @param beanId beanId
20 | */
21 | // protected void setBeanId(BeanDefinitionBuilder result, String beanId) {
22 | // result.addPropertyValue("id", beanId);
23 | // }
24 |
25 | /**
26 | * 设置Bean Id
27 | *
28 | * @param result result
29 | * @param clazz clazz
30 | * @param parserContext parserContext
31 | * @param element element
32 | */
33 | // protected void setBeanId(BeanDefinitionBuilder result, Class> clazz,
34 | // ParserContext parserContext, Element element) {
35 | // String beanId = getBeanId(clazz, parserContext, element);
36 | // setBeanId(result, beanId);
37 | // }
38 |
39 | /**
40 | * 获取BeanId
41 | *
42 | * @param clazz clazz
43 | * @param parserContext parserContext
44 | * @param element element
45 | * @return BeanId
46 | */
47 | // protected String getBeanId(Class> clazz, ParserContext parserContext,
48 | // Element element) {
49 | // String id = element.getAttribute("id");
50 | // if (id == null || id.isEmpty()) {
51 | // String generatedBeanName = element.getAttribute("name");
52 | // if (generatedBeanName == null || generatedBeanName.isEmpty()) {
53 | // generatedBeanName = clazz.getName();
54 | // }
55 | // id = generatedBeanName;
56 | // int counter = 2;
57 | // while (parserContext.getRegistry().containsBeanDefinition(id)) {
58 | // id = generatedBeanName + (counter++);
59 | // }
60 | // }
61 | // if (id != null && !id.isEmpty()) {
62 | // if (parserContext.getRegistry().containsBeanDefinition(id)) {
63 | // throw new IllegalStateException("Duplicate spring bean id " + id);
64 | // }
65 | // }
66 | // return id;
67 | // }
68 |
69 | /**
70 | * 设置Properties
71 | *
72 | * @param attributeName attributeName
73 | * @param propertyName propertyName
74 | * @param element element
75 | * @param factory factory
76 | */
77 | protected static void addPropertyValueIfNotEmpty(final String attributeName, final String propertyName,
78 | final Element element, final BeanDefinitionBuilder factory) {
79 | String attributeValue = element.getAttribute(attributeName);
80 | if (attributeValue != null && !attributeValue.isEmpty()) {
81 | factory.addPropertyValue(propertyName, attributeValue);
82 | }
83 | }
84 |
85 | /**
86 | * 获取attribute值
87 | *
88 | * @param element element
89 | * @param attributeName attributeName
90 | * @since 1.2.0
91 | * @return attribute值
92 | */
93 | protected static String getAttributeValue(final Element element, final String attributeName) {
94 | String attributeValue = element.getAttribute(attributeName);
95 | return attributeValue;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/spring/schema/parser/GeneratorBeanDefinitionParser.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.spring.schema.parser;
2 |
3 | import org.springframework.beans.factory.support.AbstractBeanDefinition;
4 | import org.springframework.beans.factory.support.BeanDefinitionBuilder;
5 | import org.springframework.beans.factory.xml.ParserContext;
6 | import org.w3c.dom.Element;
7 |
8 | import com.imadcn.framework.idworker.common.ConfigConstants;
9 | import com.imadcn.framework.idworker.generator.CompressUUIDGenerator;
10 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
11 |
12 | /**
13 | * generator:xxx 标签解析
14 | *
15 | * @author imadcn
16 | * @since 1.2.0
17 | */
18 | public class GeneratorBeanDefinitionParser extends BaseBeanDefinitionParser {
19 |
20 | private String generatorType;
21 |
22 | /**
23 | * generator:xxx 标签解析
24 | *
25 | * @param generatorType 解析类型
26 | */
27 | public GeneratorBeanDefinitionParser(String generatorType) {
28 | this.generatorType = generatorType;
29 | }
30 |
31 | @Override
32 | protected AbstractBeanDefinition parseInternal(final Element element, final ParserContext parserContext) {
33 | Class> generatorClass = null;
34 | if (ConfigConstants.SNOWFLAKE.equals(generatorType)) {
35 | generatorClass = SnowflakeGenerator.class;
36 | } else if (ConfigConstants.COMPRESS_UUID.equals(generatorType)) {
37 | generatorClass = CompressUUIDGenerator.class;
38 | } else {
39 | throw new IllegalArgumentException("unknown registryType");
40 | }
41 | BeanDefinitionBuilder result = BeanDefinitionBuilder.rootBeanDefinition(generatorClass);
42 | // snowflake 生成策略
43 | if (generatorClass.isAssignableFrom(SnowflakeGenerator.class)) {
44 | result.addConstructorArgValue(
45 | GeneratorRegisteryBuilder.buildWorkerNodeRegisterBeanDefinition(element, parserContext));
46 | // 去掉低并发模式配置解析
47 | // result.addPropertyValue(PropertyConstants.LOW_CONCURRENCY,
48 | // getAttributeValue(element,
49 | // GeneratorBeanDefinitionTag.LOW_CONCURRENCY));
50 | result.setInitMethodName("init");
51 | result.setDestroyMethodName("destroy");
52 | }
53 | return result.getBeanDefinition();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/spring/schema/parser/GeneratorRegisteryBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2018 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.framework.idworker.spring.schema.parser;
14 |
15 | import org.springframework.beans.factory.support.AbstractBeanDefinition;
16 | import org.springframework.beans.factory.support.BeanDefinitionBuilder;
17 | import org.springframework.beans.factory.xml.ParserContext;
18 | import org.w3c.dom.Element;
19 |
20 | import com.imadcn.framework.idworker.common.GeneratorStrategy;
21 | import com.imadcn.framework.idworker.config.ApplicationConfiguration;
22 | import com.imadcn.framework.idworker.generator.CompressUUIDGenerator;
23 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
24 | import com.imadcn.framework.idworker.register.zookeeper.ZookeeperWorkerRegister;
25 | import com.imadcn.framework.idworker.spring.common.GeneratorBeanDefinitionTag;
26 |
27 | /**
28 | * Id生成策略解析
29 | *
30 | * @author imadcn
31 | * @since 1.2.0
32 | */
33 | public abstract class GeneratorRegisteryBuilder extends BaseBeanDefinitionParser {
34 |
35 | /**
36 | * snowflake策略:zookeeper配置(idworker:registry)
37 | *
38 | * @param element element
39 | * @param parserContext parserContext
40 | * @return AbstractBeanDefinition
41 | */
42 | public static AbstractBeanDefinition buildWorkerNodeRegisterBeanDefinition(final Element element,
43 | final ParserContext parserContext) {
44 | BeanDefinitionBuilder result = BeanDefinitionBuilder.rootBeanDefinition(ZookeeperWorkerRegister.class);
45 | String registryCenterRef = element.getAttribute(GeneratorBeanDefinitionTag.REGISTRY_CENTER_REF);
46 | if (registryCenterRef == null || registryCenterRef.isEmpty()) {
47 | throw new IllegalArgumentException("no attribute [registry-center-ref] found");
48 | }
49 | result.addConstructorArgReference(registryCenterRef);
50 | result.addConstructorArgValue(buildApplicationConfigurationBeanDefinition(element, parserContext));
51 | return result.getBeanDefinition();
52 | }
53 |
54 | /**
55 | * snowflake策略:参数(idworker:generator / generator:snowflake)
56 | *
57 | * @param element element
58 | * @param parserContext parserContext
59 | * @return AbstractBeanDefinition
60 | */
61 | public static AbstractBeanDefinition buildApplicationConfigurationBeanDefinition(final Element element,
62 | final ParserContext parserContext) {
63 | BeanDefinitionBuilder configuration = BeanDefinitionBuilder.rootBeanDefinition(ApplicationConfiguration.class);
64 | addPropertyValueIfNotEmpty(GeneratorBeanDefinitionTag.GROUOP, "group", element, configuration);
65 | addPropertyValueIfNotEmpty(GeneratorBeanDefinitionTag.STRATEGY, "strategy", element, configuration);
66 | addPropertyValueIfNotEmpty(GeneratorBeanDefinitionTag.REGISTRY_FILE, "registryFile", element, configuration);
67 | addPropertyValueIfNotEmpty(GeneratorBeanDefinitionTag.DURABLE, "durable", element, configuration);
68 | addPropertyValueIfNotEmpty(GeneratorBeanDefinitionTag.SERIALIZE, "serialize", element, configuration);
69 | addPropertyValueIfNotEmpty(GeneratorBeanDefinitionTag.CACHEABLE, "cacheable", element, configuration);
70 | // addPropertyValueIfNotEmpty(GeneratorBeanDefinitionTag.LOW_CONCURRENCY,
71 | // "lowConcurrency", element, configuration);
72 | return configuration.getBeanDefinition();
73 | }
74 |
75 | /**
76 | * 获取ID生成策略 Class
77 | *
78 | * @param element element
79 | * @return ID生成策略 Class
80 | */
81 | public static Class> getGeneratorClass(final Element element) {
82 | String strategyCode = getAttributeValue(element, GeneratorBeanDefinitionTag.STRATEGY);
83 | GeneratorStrategy strategy = GeneratorStrategy.getByCode(strategyCode);
84 | if (strategy == null) {
85 | throw new IllegalArgumentException("unsupported generator strategy.");
86 | }
87 | switch (strategy) {
88 | case SNOWFLAKE:
89 | return SnowflakeGenerator.class;
90 | case COMPRESS_UUID:
91 | return CompressUUIDGenerator.class;
92 | default:
93 | return SnowflakeGenerator.class;
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/spring/schema/parser/RegistryBeanDefinitionParser.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.framework.idworker.spring.schema.parser;
2 |
3 | import org.springframework.beans.factory.support.AbstractBeanDefinition;
4 | import org.springframework.beans.factory.support.BeanDefinitionBuilder;
5 | import org.springframework.beans.factory.xml.ParserContext;
6 | import org.w3c.dom.Element;
7 |
8 | import com.imadcn.framework.idworker.common.ConfigConstants;
9 | import com.imadcn.framework.idworker.config.ZookeeperConfiguration;
10 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
11 | import com.imadcn.framework.idworker.registry.zookeeper.ZookeeperRegistryCenter;
12 | import com.imadcn.framework.idworker.spring.common.ZookeeperBeanDefinitionTag;
13 |
14 | /**
15 | * idworker:registry 标签解析
16 | *
17 | * @author imadcn
18 | * @since 1.0.0
19 | */
20 | public class RegistryBeanDefinitionParser extends BaseBeanDefinitionParser {
21 |
22 | private String registryType;
23 |
24 | public RegistryBeanDefinitionParser(String registryType) {
25 | this.registryType = registryType;
26 | }
27 |
28 | @Override
29 | protected AbstractBeanDefinition parseInternal(final Element element, final ParserContext parserContext) {
30 | if (ConfigConstants.REGISTRY.equals(registryType)) {
31 | BeanDefinitionBuilder result = BeanDefinitionBuilder.rootBeanDefinition(ZookeeperRegistryCenter.class);
32 | result.addConstructorArgValue(buildZookeeperConfigurationBeanDefinition(element, parserContext));
33 | // Spring 启动初始化ZK连接
34 | result.setInitMethodName("init");
35 | return result.getBeanDefinition();
36 | } else if (ConfigConstants.GENERATOR.equals(registryType)) {
37 | Class> generatorClass = GeneratorRegisteryBuilder.getGeneratorClass(element);
38 | BeanDefinitionBuilder result = BeanDefinitionBuilder.rootBeanDefinition(generatorClass);
39 | // snowflake 生成策略
40 | if (generatorClass.isAssignableFrom(SnowflakeGenerator.class)) {
41 | result.addConstructorArgValue(
42 | GeneratorRegisteryBuilder.buildWorkerNodeRegisterBeanDefinition(element, parserContext));
43 | // result.addPropertyValue("lowConcurrency",
44 | // getAttributeValue(element,
45 | // GeneratorBeanDefinitionTag.LOW_CONCURRENCY));
46 | result.setInitMethodName("init");
47 | result.setDestroyMethodName("destroy");
48 | }
49 | return result.getBeanDefinition();
50 | }
51 | throw new IllegalArgumentException("unknown registryType");
52 | }
53 |
54 | /**
55 | * zookeeper 配置解析
56 | *
57 | * @param element element
58 | * @param parserContext parserContext
59 | * @return
60 | */
61 | private AbstractBeanDefinition buildZookeeperConfigurationBeanDefinition(final Element element,
62 | final ParserContext parserContext) {
63 | BeanDefinitionBuilder result = BeanDefinitionBuilder.rootBeanDefinition(ZookeeperConfiguration.class);
64 | addPropertyValueIfNotEmpty(ZookeeperBeanDefinitionTag.SERVER_LISTS, "serverLists", element, result);
65 | addPropertyValueIfNotEmpty(ZookeeperBeanDefinitionTag.NAMESPACE, "namespace", element, result);
66 | addPropertyValueIfNotEmpty(ZookeeperBeanDefinitionTag.BASE_SLEEP_TIME_MS, "baseSleepTimeMilliseconds", element,
67 | result);
68 | addPropertyValueIfNotEmpty(ZookeeperBeanDefinitionTag.MAX_SLEEP_TIME_MS, "maxSleepTimeMilliseconds", element,
69 | result);
70 | addPropertyValueIfNotEmpty(ZookeeperBeanDefinitionTag.MAX_RETRIES, "maxRetries", element, result);
71 | addPropertyValueIfNotEmpty(ZookeeperBeanDefinitionTag.SESSION_TIMEOUT_MS, "sessionTimeoutMilliseconds", element,
72 | result);
73 | addPropertyValueIfNotEmpty(ZookeeperBeanDefinitionTag.CONNECTION_TIMEOUT_MS, "connectionTimeoutMilliseconds",
74 | element, result);
75 | addPropertyValueIfNotEmpty(ZookeeperBeanDefinitionTag.DIGEST, "digest", element, result);
76 | return result.getBeanDefinition();
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/imadcn/framework/idworker/util/HostUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2019 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.framework.idworker.util;
14 |
15 | import java.net.InetAddress;
16 | import java.net.UnknownHostException;
17 |
18 | /**
19 | * Host Utils
20 | *
21 | * @author imadcn
22 | * @since 1.3.0
23 | */
24 | public class HostUtils {
25 |
26 | /**
27 | * 获取本地IP
28 | *
29 | * @return 本地IP
30 | * @throws UnknownHostException UnknownHostException
31 | */
32 | public static String getLocalIP() throws UnknownHostException {
33 | return InetAddress.getLocalHost().getHostAddress();
34 | }
35 |
36 | /**
37 | * 获取本地主机名
38 | *
39 | * @return 本地主机名
40 | * @throws UnknownHostException UnknownHostException
41 | */
42 | public static String getLocalHostName() throws UnknownHostException {
43 | return InetAddress.getLocalHost().getHostName();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/generator.xsd:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/idworker.xsd:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/spring.handlers:
--------------------------------------------------------------------------------
1 | http\://code.imadcn.com/schema/idworker=com.imadcn.framework.idworker.spring.schema.handler.IdworkerNamespaceHandler
2 | http\://code.imadcn.com/schema/generator=com.imadcn.framework.idworker.spring.schema.handler.GeneratorNamespaceHandler
--------------------------------------------------------------------------------
/src/main/resources/META-INF/spring.schemas:
--------------------------------------------------------------------------------
1 | http\://code.imadcn.com/schema/idworker/idworker.xsd=META-INF/idworker.xsd
2 | http\://code.imadcn.com/schema/generator/generator.xsd=META-INF/generator.xsd
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/AllSpringTests.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.system.test;
2 |
3 | import org.junit.runner.RunWith;
4 | import org.junit.runners.Suite;
5 | import org.junit.runners.Suite.SuiteClasses;
6 |
7 | import com.imadcn.system.test.idworker.SpringIdWorkerTest;
8 |
9 | @RunWith(Suite.class)
10 | @SuiteClasses({SpringIdWorkerTest.class})
11 | public final class AllSpringTests {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/ProcedureTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2017 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test;
14 |
15 | import com.imadcn.framework.idworker.config.ApplicationConfiguration;
16 | import com.imadcn.framework.idworker.config.ZookeeperConfiguration;
17 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
18 | import com.imadcn.framework.idworker.register.zookeeper.ZookeeperWorkerRegister;
19 | import com.imadcn.framework.idworker.registry.zookeeper.ZookeeperRegistryCenter;
20 |
21 | public class ProcedureTest {
22 |
23 | public static void main(String[] args) {
24 | try {
25 | ZookeeperConfiguration configuration = new ZookeeperConfiguration();
26 | configuration.setServerLists("127.0.0.1:2181");
27 | configuration.setNamespace("manual_idworker");
28 |
29 | ZookeeperRegistryCenter registryCenter = new ZookeeperRegistryCenter(configuration);
30 |
31 | ApplicationConfiguration applicationConfiguration = new ApplicationConfiguration();
32 | applicationConfiguration.setGroup("manual_group");
33 |
34 | ZookeeperWorkerRegister workerRegister
35 | = new ZookeeperWorkerRegister(registryCenter, applicationConfiguration);
36 |
37 | SnowflakeGenerator generator = new SnowflakeGenerator(workerRegister);
38 |
39 | generator.init();
40 | System.out.println(generator.nextId());
41 | generator.close();
42 |
43 | generator.init();
44 | System.out.println(generator.nextId());
45 | generator.close();
46 |
47 | } catch (Throwable e) {
48 | e.printStackTrace();
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/ResultPrinter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2018 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test;
14 |
15 | import org.slf4j.Logger;
16 | import org.slf4j.LoggerFactory;
17 |
18 | import com.alibaba.fastjson.JSON;
19 |
20 | public class ResultPrinter {
21 |
22 | protected Logger logger = LoggerFactory.getLogger(getClass());
23 |
24 | protected void print(Object object) {
25 | String json = JSON.toJSONString(object);
26 | System.out.println(json);
27 | logger.info(json);
28 | }
29 |
30 | protected void rawPrint(Object object) {
31 | System.out.println(object);
32 | logger.info("", object);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/CacheableAndtDurableTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2017 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test.idworker;
14 |
15 | import org.junit.Test;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.test.context.ContextConfiguration;
18 |
19 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
20 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
21 |
22 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx-cacheable-and-durable.xml")
23 | public final class CacheableAndtDurableTest extends AbstractZookeeperJUnit4SpringContextTests {
24 |
25 | @Autowired
26 | private SnowflakeGenerator snowflakeGenerator;
27 |
28 | @Test
29 | public void testSnowflakeId() throws InterruptedException {
30 | for (int i = 0; i < 100; i++) {
31 | print(snowflakeGenerator.nextFixedStringId());
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/CacheableButNotDurableTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2017 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test.idworker;
14 |
15 | import org.junit.Test;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.test.context.ContextConfiguration;
18 |
19 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
20 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
21 |
22 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx-cacheable-but-not-durable.xml")
23 | public final class CacheableButNotDurableTest extends AbstractZookeeperJUnit4SpringContextTests {
24 |
25 | @Autowired
26 | private SnowflakeGenerator snowflakeGenerator;
27 |
28 | @Test
29 | public void testSnowflakeId() throws InterruptedException {
30 | for (int i = 0; i < 100; i++) {
31 | print(snowflakeGenerator.nextFixedStringId());
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/CompressUUIDTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2018 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test.idworker;
14 |
15 | import org.junit.Test;
16 |
17 | import com.imadcn.framework.idworker.algorithm.CompressUUID;
18 | import com.imadcn.system.test.ResultPrinter;
19 |
20 | public class CompressUUIDTest extends ResultPrinter {
21 |
22 | @Test
23 | public void testCompressUuid() {
24 | for (int i = 0; i < 5; i++) {
25 | Object o = CompressUUID.uuid22();
26 | print(o);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/IdGeneratorTest.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.system.test.idworker;
2 |
3 | import org.junit.Test;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.test.context.ContextConfiguration;
6 |
7 | import com.imadcn.framework.idworker.generator.IdGenerator;
8 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
9 |
10 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx.xml")
11 | public final class IdGeneratorTest extends AbstractZookeeperJUnit4SpringContextTests {
12 |
13 | @Autowired
14 | private IdGenerator idGenerator;
15 |
16 | @Test
17 | public void testGetId() {
18 | Object object = idGenerator.nextId();
19 | print(object);
20 | }
21 |
22 | @Test
23 | public void testBatchGetId() {
24 | Object object = idGenerator.nextId(20);
25 | print(object);
26 | }
27 |
28 | @Test
29 | public void testWithInvalidParam() {
30 | try {
31 | Object object = idGenerator.nextId(0);
32 | print(object);
33 | } catch (Exception e) {
34 | print(e.getMessage());
35 | }
36 |
37 | try {
38 | Object object = idGenerator.nextId(-1);
39 | print(object);
40 | } catch (Exception e) {
41 | print(e.getMessage());
42 | }
43 |
44 | try {
45 | Object object = idGenerator.nextId(100_001);
46 | print(object);
47 | } catch (Exception e) {
48 | print(e.getMessage());
49 | }
50 |
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/IdStrategyTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2017 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test.idworker;
14 |
15 | import org.junit.Test;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.test.context.ContextConfiguration;
18 |
19 | import com.imadcn.framework.idworker.generator.CompressUUIDGenerator;
20 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
21 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
22 |
23 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx-strategy.xml")
24 | public final class IdStrategyTest extends AbstractZookeeperJUnit4SpringContextTests {
25 |
26 | @Autowired
27 | private CompressUUIDGenerator compressUUIDGenerator;
28 | @Autowired
29 | private SnowflakeGenerator snowflakeGenerator;
30 |
31 | @Test
32 | public void testCompressId() {
33 | print(compressUUIDGenerator.nextStringId());
34 | print(compressUUIDGenerator.nextFixedStringId());
35 | }
36 |
37 | @Test
38 | public void testSnowflakeId() {
39 | print(snowflakeGenerator.nextStringId());
40 | print(snowflakeGenerator.nextFixedStringId());
41 | }
42 |
43 | @Test
44 | public void testUnsupportedMethod1() {
45 | try {
46 | print(compressUUIDGenerator.nextId());
47 | } catch (Exception e) {
48 | print(e);
49 | }
50 | }
51 |
52 | @Test
53 | public void testUnsupportedMethod2() {
54 | try {
55 | print(compressUUIDGenerator.nextId(2));
56 | } catch (Exception e) {
57 | print(e);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/JsonSerializerTest.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.system.test.idworker;
2 |
3 | import java.util.Date;
4 |
5 | import org.junit.Before;
6 | import org.junit.Test;
7 |
8 | import com.imadcn.framework.idworker.register.zookeeper.NodeInfo;
9 | import com.imadcn.framework.idworker.serialize.json.FastJsonSerializer;
10 | import com.imadcn.framework.idworker.serialize.json.JacksonSerializer;
11 | import com.imadcn.system.test.ResultPrinter;
12 |
13 | public class JsonSerializerTest extends ResultPrinter {
14 |
15 | private FastJsonSerializer fastJsonSerializer;
16 | private JacksonSerializer jacksonSerializer;
17 | private NodeInfo nodeInfo;
18 |
19 | @Test
20 | public void testFastjsonSerializer() throws Exception {
21 | String json = fastJsonSerializer.toJsonString(nodeInfo);
22 | rawPrint(json);
23 |
24 | NodeInfo fromJson = fastJsonSerializer.parseObject(json, NodeInfo.class);
25 | print(fromJson);
26 | System.out.println(fromJson);
27 | }
28 |
29 | @Test
30 | public void testJacksonSerializer() throws Exception {
31 | String json = jacksonSerializer.toJsonString(nodeInfo);
32 | rawPrint(json);
33 |
34 | NodeInfo fromJson = jacksonSerializer.parseObject(json, NodeInfo.class);
35 | print(fromJson);
36 | System.out.println(fromJson.toString());
37 | }
38 |
39 | @Test
40 | public void testfromFastJsontoJackson() throws Exception {
41 | String json = fastJsonSerializer.toJsonString(nodeInfo);
42 | NodeInfo jsonNodeInfo = jacksonSerializer.parseObject(json, NodeInfo.class);
43 |
44 | rawPrint(equals(nodeInfo, jsonNodeInfo));
45 | System.out.println(jsonNodeInfo);
46 | }
47 |
48 | @Test
49 | public void testfromJacksontoFastJson() throws Exception {
50 | String json = jacksonSerializer.toJsonString(nodeInfo);
51 | NodeInfo jsonNodeInfo = fastJsonSerializer.parseObject(json, NodeInfo.class);
52 |
53 | rawPrint(equals(nodeInfo, jsonNodeInfo));
54 | System.out.println(jsonNodeInfo.toString());
55 | }
56 |
57 | @Before
58 | public void gensrc() {
59 | nodeInfo = new NodeInfo();
60 | nodeInfo.setCreateTime(new Date());
61 | nodeInfo.setGroupName("gn");
62 | nodeInfo.setHostName("hostname");
63 | nodeInfo.setIp("127.0.0.1");
64 | nodeInfo.setNodeId("nodeid");
65 | nodeInfo.setUpdateTime(new Date());
66 | nodeInfo.setWorkerId(102);
67 |
68 | fastJsonSerializer = new FastJsonSerializer<>();
69 | jacksonSerializer = new JacksonSerializer<>();
70 |
71 | }
72 |
73 | public boolean equals(NodeInfo n1, NodeInfo n2) {
74 | // NodeId、IP、HostName、GroupName 相等(本地缓存==ZK数据)
75 | if (!n1.getNodeId().equals(n2.getNodeId())) {
76 | return false;
77 | }
78 | if (!n1.getIp().equals(n2.getIp())) {
79 | return false;
80 | }
81 | if (!n1.getHostName().equals(n2.getHostName())) {
82 | return false;
83 | }
84 | if (!n1.getGroupName().equals(n2.getGroupName())) {
85 | return false;
86 | }
87 | return true;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/ManualCloseTest.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.system.test.idworker;
2 |
3 | import org.junit.Test;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.test.context.ContextConfiguration;
6 |
7 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
8 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
9 |
10 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx-manual.xml")
11 | public final class ManualCloseTest extends AbstractZookeeperJUnit4SpringContextTests {
12 |
13 | @Autowired
14 | private SnowflakeGenerator idGenerator;
15 |
16 | @Test
17 | public void testClose() throws Exception {
18 | Object object = idGenerator.nextId();
19 | print(object);
20 | idGenerator.close();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/NewGeneratorDefinitionTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2017 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test.idworker;
14 |
15 | import org.junit.Test;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.test.context.ContextConfiguration;
18 |
19 | import com.imadcn.framework.idworker.generator.CompressUUIDGenerator;
20 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
21 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
22 |
23 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx-new-xsd.xml")
24 | public final class NewGeneratorDefinitionTest extends AbstractZookeeperJUnit4SpringContextTests {
25 |
26 | @Autowired
27 | private CompressUUIDGenerator compressUUIDGenerator;
28 | @Autowired
29 | private SnowflakeGenerator snowflakeGenerator;
30 |
31 | @Test
32 | public void testCompressId() {
33 | print(compressUUIDGenerator.nextStringId());
34 | print(compressUUIDGenerator.nextFixedStringId());
35 | }
36 |
37 | @Test
38 | public void testSnowflakeId() {
39 | print(snowflakeGenerator.nextStringId());
40 | print(snowflakeGenerator.nextFixedStringId());
41 | }
42 |
43 | @Test
44 | public void testUnsupportedMethod1() {
45 | try {
46 | print(compressUUIDGenerator.nextId());
47 | } catch (Exception e) {
48 | print(e);
49 | }
50 | }
51 |
52 | @Test
53 | public void testUnsupportedMethod2() {
54 | try {
55 | print(compressUUIDGenerator.nextId(2));
56 | } catch (Exception e) {
57 | print(e);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/NotCacheableButDurableTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2017 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test.idworker;
14 |
15 | import org.junit.Test;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.test.context.ContextConfiguration;
18 |
19 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
20 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
21 |
22 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx-not-cacheable-but-durable.xml")
23 | public final class NotCacheableButDurableTest extends AbstractZookeeperJUnit4SpringContextTests {
24 |
25 | @Autowired
26 | private SnowflakeGenerator snowflakeGenerator;
27 |
28 | @Test
29 | public void testSnowflakeId() throws InterruptedException {
30 | for (int i = 0; i < 100; i++) {
31 | print(snowflakeGenerator.nextFixedStringId());
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/NotCacheableNorDurableTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2017 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test.idworker;
14 |
15 | import org.junit.Test;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.test.context.ContextConfiguration;
18 |
19 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
20 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
21 |
22 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx-not-cacheable-nor-durable.xml")
23 | public final class NotCacheableNorDurableTest extends AbstractZookeeperJUnit4SpringContextTests {
24 |
25 | @Autowired
26 | private SnowflakeGenerator snowflakeGenerator;
27 |
28 | @Test
29 | public void testSnowflakeId() throws InterruptedException {
30 | for (int i = 0; i < 100; i++) {
31 | print(snowflakeGenerator.nextFixedStringId());
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/RegExceptionTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2017 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test.idworker;
14 |
15 | import org.junit.Test;
16 |
17 | import com.imadcn.framework.idworker.exception.RegException;
18 |
19 | public class RegExceptionTest {
20 |
21 | @Test
22 | public void test() {
23 | try {
24 | throw new RegException(new RuntimeException("test 1"));
25 | } catch (Exception e) {
26 | System.out.println(e.getMessage());
27 | }
28 |
29 | try {
30 | throw new RegException("error message %s-%s", "s1", "s2");
31 | } catch (Exception e) {
32 | System.out.println(e.getMessage());
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/RegistryFileTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2017 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test.idworker;
14 |
15 | import org.junit.Test;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.test.context.ContextConfiguration;
18 |
19 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
20 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
21 |
22 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx-registry-file.xml")
23 | public final class RegistryFileTest extends AbstractZookeeperJUnit4SpringContextTests {
24 |
25 | @Autowired
26 | private SnowflakeGenerator snowflakeGenerator;
27 |
28 | @Test
29 | public void testSnowflakeId() throws InterruptedException {
30 | for (int i = 0; i < 100; i++) {
31 | print(snowflakeGenerator.nextFixedStringId());
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/SerializeFastJsonModeTest.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.system.test.idworker;
2 |
3 | import org.junit.Test;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.test.context.ContextConfiguration;
6 |
7 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
8 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
9 |
10 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx-serialize-fastjson.xml")
11 | public final class SerializeFastJsonModeTest extends AbstractZookeeperJUnit4SpringContextTests {
12 |
13 | @Autowired
14 | private SnowflakeGenerator idGenerator;
15 |
16 | @Test
17 | public void testGetId() {
18 | Object object = idGenerator.nextId();
19 | print(object);
20 | }
21 |
22 | @Test
23 | public void testBatchGetId() {
24 | Object object = idGenerator.nextId(20);
25 | print(object);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/SerializeJacksonModeTest.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.system.test.idworker;
2 |
3 | import org.junit.Test;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.test.context.ContextConfiguration;
6 |
7 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
8 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
9 |
10 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx-serialize-jackson.xml")
11 | public final class SerializeJacksonModeTest extends AbstractZookeeperJUnit4SpringContextTests {
12 |
13 | @Autowired
14 | private SnowflakeGenerator idGenerator;
15 |
16 | @Test
17 | public void testGetId() {
18 | Object object = idGenerator.nextId();
19 | print(object);
20 | }
21 |
22 | @Test
23 | public void testBatchGetId() {
24 | Object object = idGenerator.nextId(20);
25 | print(object);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/SerializeUnsupportedModeTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2021 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test.idworker;
14 |
15 | import org.junit.Test;
16 |
17 | import com.imadcn.framework.idworker.config.ApplicationConfiguration;
18 | import com.imadcn.framework.idworker.config.ZookeeperConfiguration;
19 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
20 | import com.imadcn.framework.idworker.register.zookeeper.ZookeeperWorkerRegister;
21 | import com.imadcn.framework.idworker.registry.zookeeper.ZookeeperRegistryCenter;
22 | import com.imadcn.system.test.ResultPrinter;
23 |
24 | public class SerializeUnsupportedModeTest extends ResultPrinter {
25 |
26 | @Test
27 | public void testUnsupported() {
28 | try {
29 | ZookeeperConfiguration configuration = new ZookeeperConfiguration();
30 | configuration.setServerLists("127.0.0.1:2181");
31 | configuration.setNamespace("manual_idworker");
32 |
33 | ZookeeperRegistryCenter registryCenter = new ZookeeperRegistryCenter(configuration);
34 |
35 | ApplicationConfiguration applicationConfiguration = new ApplicationConfiguration();
36 | applicationConfiguration.setSerialize("unsupported");
37 | applicationConfiguration.setGroup("manual_group");
38 |
39 | ZookeeperWorkerRegister workerRegister
40 | = new ZookeeperWorkerRegister(registryCenter, applicationConfiguration);
41 |
42 | SnowflakeGenerator generator = new SnowflakeGenerator(workerRegister);
43 |
44 | generator.init();
45 | System.out.println(generator.nextId());
46 | generator.close();
47 |
48 | generator.init();
49 | System.out.println(generator.nextId());
50 | generator.close();
51 |
52 | } catch (Throwable e) {
53 | logger.error("", e);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/SpringIdWorkerTest.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.system.test.idworker;
2 |
3 | import org.junit.Test;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.test.context.ContextConfiguration;
6 |
7 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
8 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
9 |
10 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx.xml")
11 | public final class SpringIdWorkerTest extends AbstractZookeeperJUnit4SpringContextTests {
12 |
13 | @Autowired
14 | private SnowflakeGenerator idGenerator;
15 |
16 | @Test
17 | public void testGetId() {
18 | Object object = idGenerator.nextId();
19 | print(object);
20 | }
21 |
22 | @Test
23 | public void testBatchGetId() {
24 | Object object = idGenerator.nextId(20);
25 | print(object);
26 | }
27 |
28 | @Test
29 | public void testWithInvalidParam() {
30 | try {
31 | Object object = idGenerator.nextId(0);
32 | print(object);
33 | } catch (Exception e) {
34 | print(e.getMessage());
35 | }
36 |
37 | try {
38 | Object object = idGenerator.nextId(-1);
39 | print(object);
40 | } catch (Exception e) {
41 | print(e.getMessage());
42 | }
43 |
44 | try {
45 | Object object = idGenerator.nextId(100_001);
46 | print(object);
47 | } catch (Exception e) {
48 | print(e.getMessage());
49 | }
50 |
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/ZKPersistModeTest.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.system.test.idworker;
2 |
3 | import org.junit.Test;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.test.context.ContextConfiguration;
6 |
7 | import com.imadcn.framework.idworker.generator.SnowflakeGenerator;
8 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
9 |
10 | @ContextConfiguration(locations = "classpath:META-INF/idworker-ctx-persist-mode.xml")
11 | public final class ZKPersistModeTest extends AbstractZookeeperJUnit4SpringContextTests {
12 |
13 | @Autowired
14 | private SnowflakeGenerator idGenerator;
15 |
16 | @Test
17 | public void testGetId() {
18 | Object object = idGenerator.nextId();
19 | print(object);
20 | }
21 |
22 | @Test
23 | public void testBatchGetId() {
24 | Object object = idGenerator.nextId(20);
25 | print(object);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/idworker/ZookeeperRegisterCtrTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2019 imadcn Group.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package com.imadcn.system.test.idworker;
14 |
15 | import org.junit.Test;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.test.context.ContextConfiguration;
18 |
19 | import com.imadcn.framework.idworker.registry.zookeeper.ZookeeperRegistryCenter;
20 | import com.imadcn.system.test.spring.AbstractZookeeperJUnit4SpringContextTests;
21 |
22 | @ContextConfiguration(locations = "classpath:META-INF/idworker-reg-ctr.xml")
23 | public final class ZookeeperRegisterCtrTest extends AbstractZookeeperJUnit4SpringContextTests {
24 |
25 | @Autowired
26 | private ZookeeperRegistryCenter regCtr;
27 |
28 | @Test
29 | public void testSequential() {
30 | String seq = regCtr.persistSequential("/idworker/sequential/t_seq_", "SEQUENCE");
31 | print(seq);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/spring/AbstractZookeeperJUnit4SpringContextTests.java:
--------------------------------------------------------------------------------
1 | package com.imadcn.system.test.spring;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.test.context.TestExecutionListeners;
6 | import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
7 |
8 | import com.alibaba.fastjson.JSON;
9 |
10 | @TestExecutionListeners(EmbedZookeeperTestExecutionListener.class)
11 | public abstract class AbstractZookeeperJUnit4SpringContextTests extends AbstractJUnit4SpringContextTests {
12 |
13 | protected Logger logger = LoggerFactory.getLogger(getClass());
14 |
15 | protected void print(Object object) {
16 | String json = JSON.toJSONString(object);
17 | System.out.println(json);
18 | logger.info(json);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/com/imadcn/system/test/spring/EmbedZookeeperTestExecutionListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 1999-2015 dangdang.com. Licensed under the Apache License, Version 2.0 (the "License"); you may not use
3 | * this file except in compliance with the License. You may obtain a copy of the License at
4 | *
5 | * http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
8 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | * specific language governing permissions and limitations under the License.
10 | */
11 |
12 | package com.imadcn.system.test.spring;
13 |
14 | import java.io.File;
15 | import java.io.IOException;
16 |
17 | import org.apache.curator.test.TestingServer;
18 | import org.springframework.test.context.TestContext;
19 | import org.springframework.test.context.support.AbstractTestExecutionListener;
20 |
21 | import com.imadcn.framework.idworker.exception.RegExceptionHandler;
22 |
23 | public final class EmbedZookeeperTestExecutionListener extends AbstractTestExecutionListener {
24 |
25 | private static volatile TestingServer testingServer;
26 |
27 | @Override
28 | public void beforeTestClass(final TestContext testContext) throws Exception {
29 | startEmbedTestingServer();
30 | }
31 |
32 | private static void startEmbedTestingServer() {
33 | if (null != testingServer) {
34 | return;
35 | }
36 | try {
37 | testingServer
38 | = new TestingServer(3181, new File(String.format("target/test_zk_data/%s/", System.nanoTime())));
39 | // CHECKSTYLE:OFF
40 | } catch (final Exception ex) {
41 | // CHECKSTYLE:ON
42 | RegExceptionHandler.handleException(ex);
43 | } finally {
44 | Runtime.getRuntime().addShutdownHook(new Thread() {
45 |
46 | @Override
47 | public void run() {
48 | try {
49 | EmbedZookeeperTestExecutionListener.sleep(2000L);
50 | testingServer.close();
51 | testingServer = null;
52 | } catch (final IOException ex) {
53 | RegExceptionHandler.handleException(ex);
54 | }
55 | }
56 | });
57 | }
58 | }
59 |
60 | public static void sleep(final long millis) {
61 | try {
62 | Thread.sleep(millis);
63 | } catch (final InterruptedException ex) {
64 | Thread.currentThread().interrupt();
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/base.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-ctx-cacheable-and-durable.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
19 |
21 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-ctx-cacheable-but-not-durable.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
19 |
21 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-ctx-manual.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-ctx-new-xsd.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-ctx-not-cacheable-but-durable.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
19 |
21 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-ctx-not-cacheable-nor-durable.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
19 |
21 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-ctx-persist-mode.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-ctx-registry-file.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-ctx-serialize-fastjson.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-ctx-serialize-jackson.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-ctx-strategy.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-ctx.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/idworker-reg-ctr.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/src/test/resources/conf/config.properties:
--------------------------------------------------------------------------------
1 | zk.servers=localhost:3181
2 | zk.namespace=test_idworker
3 | zk.baseSleepTimeMilliseconds=1000
4 | zk.maxSleepTimeMilliseconds=3000
5 | zk.maxRetries=3
6 | zk.sessionTimeoutMilliseconds=60000
7 | zk.connectionTimeoutMilliseconds=15000
8 |
9 | idworker.group=testGroup
--------------------------------------------------------------------------------
/src/test/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | ${log.context.name}
8 |
9 |
10 |
11 | ${log.pattern}
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------