|
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