From 78ed0c8ed1945881e0300fab10cb1ea446a63b43 Mon Sep 17 00:00:00 2001 From: ZhouXY108 Date: Tue, 28 May 2024 09:36:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20Seata=20=E6=9C=80=E6=96=B0?= =?UTF-8?q?=E7=9A=84=20IdWorker=20=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=B0=86?= =?UTF-8?q?=E7=94=9F=E6=88=90=20WorkerId=20=E7=9A=84=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=9B=9E=E6=9D=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NoAvailableMacFoundException.java | 19 ++++ .../zhouxy/plusone/commons/util/IdWorker.java | 90 ++++++++++++++----- 2 files changed, 87 insertions(+), 22 deletions(-) create mode 100644 src/main/java/xyz/zhouxy/plusone/commons/exception/NoAvailableMacFoundException.java diff --git a/src/main/java/xyz/zhouxy/plusone/commons/exception/NoAvailableMacFoundException.java b/src/main/java/xyz/zhouxy/plusone/commons/exception/NoAvailableMacFoundException.java new file mode 100644 index 0000000..6282c5f --- /dev/null +++ b/src/main/java/xyz/zhouxy/plusone/commons/exception/NoAvailableMacFoundException.java @@ -0,0 +1,19 @@ +package xyz.zhouxy.plusone.commons.exception; + +public class NoAvailableMacFoundException extends Exception { + public NoAvailableMacFoundException() { + super(); + } + + public NoAvailableMacFoundException(String msg) { + super(msg); + } + + public NoAvailableMacFoundException(Throwable e) { + super(e); + } + + public NoAvailableMacFoundException(String msg, Throwable e) { + super(msg, e); + } +} diff --git a/src/main/java/xyz/zhouxy/plusone/commons/util/IdWorker.java b/src/main/java/xyz/zhouxy/plusone/commons/util/IdWorker.java index 18f3144..47c5ef0 100644 --- a/src/main/java/xyz/zhouxy/plusone/commons/util/IdWorker.java +++ b/src/main/java/xyz/zhouxy/plusone/commons/util/IdWorker.java @@ -1,28 +1,30 @@ /* - * Copyright 1999-2019 Seata.io Group. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package xyz.zhouxy.plusone.commons.util; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Enumeration; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicLong; -/** - * IdWorker from Seata. - * - * @author funkye - * @author selfishlover - */ +import xyz.zhouxy.plusone.commons.exception.NoAvailableMacFoundException; + + public class IdWorker { /** @@ -74,8 +76,9 @@ public class IdWorker { /** * instantiate an IdWorker using given workerId + * @param workerId if null, then will auto assign one */ - public IdWorker(long workerId) { + public IdWorker(Long workerId) { initTimestampAndSequence(); initWorkerId(workerId); } @@ -93,7 +96,10 @@ public class IdWorker { * init workerId * @param workerId if null, then auto generate one */ - private void initWorkerId(long workerId) { + private void initWorkerId(Long workerId) { + if (workerId == null) { + workerId = generateWorkerId(); + } if (workerId > MAX_WORKER_ID || workerId < 0) { String message = String.format("worker Id can't be greater than %d or less than 0", MAX_WORKER_ID); throw new IllegalArgumentException(message); @@ -127,8 +133,7 @@ public class IdWorker { if (current >= newest) { try { Thread.sleep(5); - } catch (InterruptedException ignore) { - // don't care + } catch (InterruptedException ignore) { // NOSONAR don't care } } } @@ -139,4 +144,45 @@ public class IdWorker { private long getNewestTimestamp() { return System.currentTimeMillis() - TWEPOCH; } -} + + /** + * auto generate workerId, try using mac first, if failed, then randomly generate one + * @return workerId + */ + private static long generateWorkerId() { + try { + return generateWorkerIdBaseOnMac(); + } catch (Exception e) { + return generateRandomWorkerId(); + } + } + + /** + * use lowest 10 bit of available MAC as workerId + * @return workerId + * @throws SocketException + * @throws Exception when there is no available mac found + */ + private static long generateWorkerIdBaseOnMac() throws SocketException, NoAvailableMacFoundException { + Enumeration all = NetworkInterface.getNetworkInterfaces(); + while (all.hasMoreElements()) { + NetworkInterface networkInterface = all.nextElement(); + boolean isLoopback = networkInterface.isLoopback(); + boolean isVirtual = networkInterface.isVirtual(); + byte[] mac = networkInterface.getHardwareAddress(); + if (isLoopback || isVirtual || mac == null) { + continue; + } + return ((mac[4] & 0B11) << 8) | (mac[5] & 0xFF); + } + throw new NoAvailableMacFoundException(); + } + + /** + * randomly generate one as workerId + * @return workerId + */ + private static long generateRandomWorkerId() { + return ThreadLocalRandom.current().nextInt(MAX_WORKER_ID + 1); + } +} \ No newline at end of file