|
1 | 1 | package com.example.snow;
|
2 | 2 |
|
| 3 | +import cn.hutool.core.util.RandomUtil; |
3 | 4 | import org.slf4j.Logger;
|
4 | 5 | import org.slf4j.LoggerFactory;
|
5 | 6 |
|
@@ -59,58 +60,20 @@ public class IdWorkerPatch2 {
|
59 | 60 | */
|
60 | 61 | private long sequence;
|
61 | 62 |
|
62 |
| - private static volatile InetAddress LOCAL_ADDRESS = null; |
63 |
| - private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); |
64 |
| - |
65 | 63 | /**
|
66 | 64 | * 构造函数
|
67 | 65 | */
|
68 | 66 | public IdWorkerPatch2() {
|
69 | 67 | this.datacenterId = getDatacenterId();
|
70 |
| - this.workerId = getMaxWorkerId(datacenterId); |
71 |
| - } |
72 |
| - |
73 |
| - /** |
74 |
| - * 基于网卡MAC地址计算余数作为数据中心 |
75 |
| - * <p> |
76 |
| - * 可自定扩展 |
77 |
| - */ |
78 |
| - protected long getDatacenterId() { |
79 |
| - long id = 0L; |
80 |
| - try { |
81 |
| - NetworkInterface network = NetworkInterface.getByInetAddress(getLocalAddress()); |
82 |
| - if (null == network) { |
83 |
| - id = 1L; |
84 |
| - } else { |
85 |
| - byte[] mac = network.getHardwareAddress(); |
86 |
| - if (null != mac) { |
87 |
| - id = ((0x000000FF & (long) mac[mac.length - 2]) | (0x0000FF00 & (((long) mac[mac.length - 1]) << 8))) >> 6; |
88 |
| - id = id % (maxDatacenterId + 1); |
89 |
| - } |
90 |
| - } |
91 |
| - } catch (Exception e) { |
92 |
| - logger.warn(" getDatacenterId: " + e.getMessage()); |
| 68 | + this.workerId = getMaxWorkerId(this.datacenterId); |
| 69 | + // sanity check for workerId |
| 70 | + if (this.workerId > maxWorkerId || this.workerId < 0L) { |
| 71 | + this.workerId = RandomUtil.randomLong(0, 31); |
93 | 72 | }
|
94 |
| - |
95 |
| - return id; |
96 |
| - } |
97 |
| - |
98 |
| - /** |
99 |
| - * 基于 MAC + PID 的 hashcode 获取16个低位 |
100 |
| - * <p> |
101 |
| - * 可自定扩展 |
102 |
| - */ |
103 |
| - protected long getMaxWorkerId(long datacenterId) { |
104 |
| - StringBuilder mpId = new StringBuilder(); |
105 |
| - mpId.append(datacenterId); |
106 |
| - String name = ManagementFactory.getRuntimeMXBean().getName(); |
107 |
| - if (name != null && name.length() > 0) { |
108 |
| - // GET jvmPid |
109 |
| - mpId.append(name.split("@")[0]); |
| 73 | + if (this.datacenterId > maxDatacenterId || this.datacenterId < 0L) { |
| 74 | + this.datacenterId = RandomUtil.randomLong(0, 31); |
110 | 75 | }
|
111 |
| - |
112 |
| - // MAC + PID 的 hashcode 获取16个低位 |
113 |
| - return (mpId.toString().hashCode() & 0xffff) % (maxWorkerId + 1); |
| 76 | + logger.info("SnowFlake Starting. workerId {}, datacenterId {}, sequence {}", workerId, datacenterId, sequence); |
114 | 77 | }
|
115 | 78 |
|
116 | 79 | /**
|
@@ -173,6 +136,16 @@ protected long getMaxWorkerId(long datacenterId) {
|
173 | 136 | */
|
174 | 137 | private long lastSequence = 0L;
|
175 | 138 |
|
| 139 | + /** |
| 140 | + * IP正则表达式 |
| 141 | + */ |
| 142 | + private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); |
| 143 | + |
| 144 | + /** |
| 145 | + * 本机地址 |
| 146 | + */ |
| 147 | + private static volatile InetAddress LOCAL_ADDRESS = null; |
| 148 | + |
176 | 149 | /**
|
177 | 150 | * 获得下一个ID (该方法是线程安全的)
|
178 | 151 | *
|
@@ -251,20 +224,57 @@ private long tilNextMillis(long lastTimestamp) {
|
251 | 224 | }
|
252 | 225 |
|
253 | 226 | /**
|
254 |
| - * Find first valid IP from local network card |
255 |
| - * |
256 |
| - * @return first valid local IP |
| 227 | + * 基于网卡MAC地址计算余数作为数据中心 |
| 228 | + * <p> |
| 229 | + * 可自定扩展 |
257 | 230 | */
|
258 |
| - public static InetAddress getLocalAddress() { |
259 |
| - if (LOCAL_ADDRESS != null) { |
260 |
| - return LOCAL_ADDRESS; |
| 231 | + protected long getDatacenterId() { |
| 232 | + try { |
| 233 | + long id = 0L; |
| 234 | + if (LOCAL_ADDRESS == null) { |
| 235 | + LOCAL_ADDRESS = getLocalAddress(); |
| 236 | + } |
| 237 | + NetworkInterface network = NetworkInterface.getByInetAddress(LOCAL_ADDRESS); |
| 238 | + byte[] mac = network.getHardwareAddress(); |
| 239 | + if (null != mac) { |
| 240 | + id = ((0x000000FF & (long) mac[mac.length - 2]) | (0x0000FF00 & (((long) mac[mac.length - 1]) << 8))) >> 6; |
| 241 | + id = id % (maxDatacenterId + 1); |
| 242 | + } |
| 243 | + return id; |
| 244 | + } catch (Exception e) { |
| 245 | + logger.warn("getDatacenterId: " + e.getMessage()); |
| 246 | + return -1L; |
261 | 247 | }
|
| 248 | + } |
262 | 249 |
|
263 |
| - LOCAL_ADDRESS = getLocalAddress0(); |
264 |
| - return LOCAL_ADDRESS; |
| 250 | + /** |
| 251 | + * 基于 MAC + PID 的 hashcode 获取16个低位 |
| 252 | + * <p> |
| 253 | + * 可自定扩展 |
| 254 | + */ |
| 255 | + protected long getMaxWorkerId(long datacenterId) { |
| 256 | + try { |
| 257 | + StringBuilder mpId = new StringBuilder(); |
| 258 | + mpId.append(datacenterId); |
| 259 | + String name = ManagementFactory.getRuntimeMXBean().getName(); |
| 260 | + if (name != null && name.length() > 0) { |
| 261 | + // GET jvmPid |
| 262 | + mpId.append(name.split("@")[0]); |
| 263 | + } |
| 264 | + // MAC + PID 的 hashcode 获取16个低位 |
| 265 | + return (mpId.toString().hashCode() & 0xffff) % (maxWorkerId + 1); |
| 266 | + } catch (Exception e) { |
| 267 | + logger.warn("getMaxWorkerId: " + e.getMessage()); |
| 268 | + return -1L; |
| 269 | + } |
265 | 270 | }
|
266 | 271 |
|
267 |
| - private static InetAddress getLocalAddress0() { |
| 272 | + /** |
| 273 | + * Find first valid IP from local network card |
| 274 | + * |
| 275 | + * @return first valid local IP |
| 276 | + */ |
| 277 | + private static InetAddress getLocalAddress() { |
268 | 278 | InetAddress localAddress = null;
|
269 | 279 | try {
|
270 | 280 | localAddress = InetAddress.getLocalHost();
|
@@ -305,11 +315,13 @@ private static InetAddress getLocalAddress0() {
|
305 | 315 | return localAddress;
|
306 | 316 | }
|
307 | 317 |
|
| 318 | + /** |
| 319 | + * local IP Valid |
| 320 | + */ |
308 | 321 | private static boolean isValidAddress(InetAddress address) {
|
309 | 322 | if (address == null || address.isLoopbackAddress()) {
|
310 | 323 | return false;
|
311 | 324 | }
|
312 |
| - |
313 | 325 | String name = address.getHostAddress();
|
314 | 326 | return (name != null && !"0.0.0.0".equals(name) && !"127.0.0.1".equals(name) && IP_PATTERN.matcher(name).matches());
|
315 | 327 | }
|
|
0 commit comments