diff --git a/.gitignore b/.gitignore index c5b3f1dc581f3166ff1ef661aec59ec1bb14f31d..c70c359b279541a908087123a49115bbe7433a71 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ target /.idea /limitart.iml +.tmp diff --git a/config/pom.xml b/config/pom.xml index 7921366058ee8bf385f2d0c774265d7c0fc441de..509adf2bc79c9480dd77f6f7c4600a56235c1b90 100644 --- a/config/pom.xml +++ b/config/pom.xml @@ -5,7 +5,7 @@ limitart top.limitart - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 diff --git a/core/pom.xml b/core/pom.xml index 1213408ed116de5ec91f5ae320b0d8ac720a8b67..de313a31c4564c2320a2edee37ed714961ce7a17 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -5,7 +5,7 @@ top.limitart limitart - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 diff --git a/core/src/main/java/top/limitart/base/BinaryMeta.java b/core/src/main/java/top/limitart/base/BinaryMeta.java index eaf18e01fbfcd1c845fa337dcf93d3b61f7c0fe6..8caa0a00705cc5531f401210f1b8a0685cb7f943 100644 --- a/core/src/main/java/top/limitart/base/BinaryMeta.java +++ b/core/src/main/java/top/limitart/base/BinaryMeta.java @@ -42,6 +42,7 @@ import java.util.concurrent.ConcurrentHashMap; */ @SuppressWarnings({"rawtypes", "unchecked"}) public class BinaryMeta implements Closeable { + private static boolean COMPRESS_INT32_64 = true; private static final Map, ConstructorAccess> messageMetaCache = new ConcurrentHashMap<>(); @@ -62,7 +63,8 @@ public class BinaryMeta implements Closeable { replaceBuffer(buffer); } - public BinaryMeta() {} + public BinaryMeta() { + } /** * 替换buffer @@ -80,7 +82,9 @@ public class BinaryMeta implements Closeable { return buffer; } - /** 仅仅置空,不减少引用计数 */ + /** + * 仅仅置空,不减少引用计数 + */ public void softClose() { Conditions.notNull(this.buffer, "already release"); this.buffer = null; @@ -268,6 +272,8 @@ public class BinaryMeta implements Closeable { putMessageMetaList((List) object); } else if (component == String.class) { putStringList((List) object); + } else if (component == byte[].class) { + putByteArrayList((List) object); } } else { if (type == Byte.class) { @@ -487,6 +493,8 @@ public class BinaryMeta implements Closeable { field.set(this, getMessageMetaList((Class) component)); } else if (component == String.class) { field.set(this, getStringList()); + } else if (component == byte[].class) { + field.set(this, getByteArrayList()); } } else { if (type == Byte.class) { @@ -1055,7 +1063,9 @@ public class BinaryMeta implements Closeable { return new ArrayList<>(); default: List list = new ArrayList<>(); - list.add(getByteArray()); + for (int i = 0; i < len; i++) { + list.add(getByteArray()); + } return list; } } diff --git a/core/src/main/java/top/limitart/base/IntCounter.java b/core/src/main/java/top/limitart/base/IntCounter.java index c903488499d7a5ad9827b57224f53432ae860266..b042d68806a70d96ce03216534448580f605799b 100644 --- a/core/src/main/java/top/limitart/base/IntCounter.java +++ b/core/src/main/java/top/limitart/base/IntCounter.java @@ -16,7 +16,7 @@ package top.limitart.base; import top.limitart.base.label.ThreadUnsafe; -import top.limitart.util.GameMathUtil; +import top.limitart.util.MathUtil; /** * int计数器 @@ -90,7 +90,7 @@ public class IntCounter { * @return */ protected int setCount(int value) { - return this.count = GameMathUtil.fixedBetween(value, low(), high()); + return this.count = MathUtil.fixedBetween(value, low(), high()); } /** @@ -147,7 +147,7 @@ public class IntCounter { */ public int getAndAdd(int delta) { int old = getCount(); - setCount(GameMathUtil.safeAdd(old, delta)); + setCount(MathUtil.safeAdd(old, delta)); return old; } diff --git a/core/src/main/java/top/limitart/base/LongCounter.java b/core/src/main/java/top/limitart/base/LongCounter.java index 8bb27a19cbde6d48c03c19b9f8d9752ca9d22ebc..8effee088fead41b294b5beb9efa2e52c8cb56e0 100644 --- a/core/src/main/java/top/limitart/base/LongCounter.java +++ b/core/src/main/java/top/limitart/base/LongCounter.java @@ -16,7 +16,7 @@ package top.limitart.base; import top.limitart.base.label.ThreadUnsafe; -import top.limitart.util.GameMathUtil; +import top.limitart.util.MathUtil; /** * 计数器 @@ -87,7 +87,7 @@ public class LongCounter { * @return */ public long setCount(long value) { - return this.count = GameMathUtil.fixedBetween(value, low(), high()); + return this.count = MathUtil.fixedBetween(value, low(), high()); } /** @@ -115,7 +115,7 @@ public class LongCounter { * @return */ public long addAndGet(long delta) { - return setCount(GameMathUtil.safeAdd(getCount(), delta)); + return setCount(MathUtil.safeAdd(getCount(), delta)); } /** @@ -144,7 +144,7 @@ public class LongCounter { */ public long getAndAdd(long delta) { long old = getCount(); - setCount(GameMathUtil.safeAdd(old, delta)); + setCount(MathUtil.safeAdd(old, delta)); return old; } diff --git a/core/src/main/java/top/limitart/base/SmoothRandomWeight.java b/core/src/main/java/top/limitart/base/SmoothRandomWeight.java index 05e9c920840b2decb3efbac3b78cb6cf1ca40cd2..ad7818b8ccc3991c9d077f06f3d63600f1852e8d 100644 --- a/core/src/main/java/top/limitart/base/SmoothRandomWeight.java +++ b/core/src/main/java/top/limitart/base/SmoothRandomWeight.java @@ -19,7 +19,7 @@ package top.limitart.base; import top.limitart.base.label.ThreadSafe; -import top.limitart.util.GameMathUtil; +import top.limitart.util.MathUtil; import top.limitart.util.RandomUtil; /** 平滑加权随机Created by Hank on 2019/4/26 */ @@ -47,7 +47,7 @@ public class SmoothRandomWeight { int sum = 0; boolean allSame = true; // 降低数据量级 - int gcd = GameMathUtil.gcd(weights); + int gcd = MathUtil.gcd(weights); for (int i = 0; i < weights.length; i++) { this.weights[i] = weights[i] / gcd; sum += this.weights[i]; @@ -57,7 +57,7 @@ public class SmoothRandomWeight { } this.allSame = allSame; this.sum = sum; - this.deviationFactor = GameMathUtil.fixedBetween(deviationFactor, 0, 1); + this.deviationFactor = MathUtil.fixedBetween(deviationFactor, 0, 1); this.curFactor = deviationFactor; } @@ -66,7 +66,7 @@ public class SmoothRandomWeight { // 如果长度都不一样,直接全部重置 reset(weights, this.deviationFactor); } else { - int gcd = GameMathUtil.gcd(weights); + int gcd = MathUtil.gcd(weights); int sum = 0; boolean allSame = true; for (int i = 0; i < weights.length; i++) { diff --git a/core/src/main/java/top/limitart/collections/AbstractIntMap.java b/core/src/main/java/top/limitart/collections/AbstractIntMap.java index ec99d2abd57f565544171a47b0b5fa24db96ee52..cc9a9a6b97359531060f2ceef29bdc5067f2ab66 100644 --- a/core/src/main/java/top/limitart/collections/AbstractIntMap.java +++ b/core/src/main/java/top/limitart/collections/AbstractIntMap.java @@ -16,7 +16,7 @@ package top.limitart.collections; import top.limitart.base.NotImplementedException; -import top.limitart.util.GameMathUtil; +import top.limitart.util.MathUtil; import java.util.Collection; import java.util.Map; @@ -102,7 +102,7 @@ public abstract class AbstractIntMap implements IntMap { */ @Override public int addAndGet(K key, int delta) { - return accumulateAndGet(key, delta, GameMathUtil::safeAdd); + return accumulateAndGet(key, delta, MathUtil::safeAdd); } /** @@ -136,7 +136,7 @@ public abstract class AbstractIntMap implements IntMap { */ @Override public int getAndAdd(K key, int delta) { - return getAndAccumulate(key, delta, GameMathUtil::safeAdd); + return getAndAccumulate(key, delta, MathUtil::safeAdd); } /** diff --git a/core/src/main/java/top/limitart/collections/AbstractLongMap.java b/core/src/main/java/top/limitart/collections/AbstractLongMap.java index 621dbcb93c7969607b797a939557beb98a0b0ab2..7b8777156da6460bf4ba43e5ed214a56866d1978 100644 --- a/core/src/main/java/top/limitart/collections/AbstractLongMap.java +++ b/core/src/main/java/top/limitart/collections/AbstractLongMap.java @@ -16,7 +16,7 @@ package top.limitart.collections; import top.limitart.base.NotImplementedException; -import top.limitart.util.GameMathUtil; +import top.limitart.util.MathUtil; import java.util.Collection; import java.util.Map; @@ -102,7 +102,7 @@ public abstract class AbstractLongMap implements LongMap { */ @Override public long addAndGet(K key, long delta) { - return accumulateAndGet(key, delta, GameMathUtil::safeAdd); + return accumulateAndGet(key, delta, MathUtil::safeAdd); } /** @@ -136,7 +136,7 @@ public abstract class AbstractLongMap implements LongMap { */ @Override public long getAndAdd(K key, long delta) { - return getAndAccumulate(key, delta, GameMathUtil::safeAdd); + return getAndAccumulate(key, delta, MathUtil::safeAdd); } /** diff --git a/core/src/main/java/top/limitart/collections/ConcurrentHashSet.java b/core/src/main/java/top/limitart/collections/ConcurrentHashSet.java index 14b402f37419451d9dd95a65da2b4ffdf5a3b2b5..1fe11e10aed95d340027cfdedeb05a281204a972 100644 --- a/core/src/main/java/top/limitart/collections/ConcurrentHashSet.java +++ b/core/src/main/java/top/limitart/collections/ConcurrentHashSet.java @@ -15,6 +15,7 @@ */ package top.limitart.collections; +import java.util.Collection; import top.limitart.base.label.ThreadSafe; import java.util.AbstractSet; @@ -43,6 +44,10 @@ public class ConcurrentHashSet extends AbstractSet { map = new ConcurrentHashMap<>(initialCapacity); } + public ConcurrentHashSet(Collection collection) { + map = new ConcurrentHashMap<>(); + addAll(collection); + } @Override public Iterator iterator() { return map.keySet().iterator(); diff --git a/core/src/main/java/top/limitart/collections/ConcurrentTable.java b/core/src/main/java/top/limitart/collections/ConcurrentTable.java index fc48314a257b98e641cceb1a2cd3a99f5c78c449..9a4b4eaea1b7d03fcd0c81713671d9c22757f1c4 100644 --- a/core/src/main/java/top/limitart/collections/ConcurrentTable.java +++ b/core/src/main/java/top/limitart/collections/ConcurrentTable.java @@ -26,6 +26,7 @@ import java.util.concurrent.ConcurrentHashMap; * @author hank */ @ThreadSafe +@Deprecated public class ConcurrentTable implements Table { private final Map> maps = new ConcurrentHashMap<>(); diff --git a/core/src/main/java/top/limitart/collections/EnumIntCounter.java b/core/src/main/java/top/limitart/collections/EnumIntCounter.java index 2fd3b31efeb80b0726a8aeb0a044538d9cb7980a..e14125116ea0a9b831e710d8f6abbd5b42e5f721 100644 --- a/core/src/main/java/top/limitart/collections/EnumIntCounter.java +++ b/core/src/main/java/top/limitart/collections/EnumIntCounter.java @@ -17,7 +17,7 @@ package top.limitart.collections; import top.limitart.base.label.ThreadUnsafe; import top.limitart.util.EnumUtil; -import top.limitart.util.GameMathUtil; +import top.limitart.util.MathUtil; import java.util.Arrays; import java.util.Iterator; @@ -148,7 +148,7 @@ public class EnumIntCounter> implements Iterable { * @return */ public int addAndGet(E key, int delta) { - int result = GameMathUtil.safeAdd(getCount(key), delta); + int result = MathUtil.safeAdd(getCount(key), delta); putCount(key, result); return result; } @@ -182,7 +182,7 @@ public class EnumIntCounter> implements Iterable { */ public int getAndAdd(E key, int delta) { int old = getCount(key); - putCount(key, GameMathUtil.safeAdd(old, delta)); + putCount(key, MathUtil.safeAdd(old, delta)); return old; } diff --git a/core/src/main/java/top/limitart/collections/HashedTable.java b/core/src/main/java/top/limitart/collections/HashedTable.java index f3dbfb06a26c1f5984f894fdac39a885383a02a1..898167a6a34f402eb08776ee94f183375ddfeec4 100644 --- a/core/src/main/java/top/limitart/collections/HashedTable.java +++ b/core/src/main/java/top/limitart/collections/HashedTable.java @@ -25,6 +25,7 @@ import java.util.*; * @author hank */ @ThreadUnsafe +@Deprecated public class HashedTable implements Table { private final Map> maps = new HashMap<>(); diff --git a/core/src/main/java/top/limitart/collections/Table.java b/core/src/main/java/top/limitart/collections/Table.java index 1f540295d3ccd59663d59d4d6ae3926cfa72e7db..fe4df445e4183f224e1be2f67355f4568748401f 100644 --- a/core/src/main/java/top/limitart/collections/Table.java +++ b/core/src/main/java/top/limitart/collections/Table.java @@ -10,6 +10,7 @@ import java.util.Set; * @author hank * @version 2017/12/18 0018 19:34 */ +@Deprecated public interface Table { static Table empty() { return new HashedTable<>(); diff --git a/core/src/main/java/top/limitart/concurrent/DisruptorTaskQueue.java b/core/src/main/java/top/limitart/concurrent/DisruptorTaskQueue.java index 9f954dd6621bed5c6f13fde8cb5c1a991b876064..0d88dedd3f2e6404115f2cf776dd7faffe9e1576 100644 --- a/core/src/main/java/top/limitart/concurrent/DisruptorTaskQueue.java +++ b/core/src/main/java/top/limitart/concurrent/DisruptorTaskQueue.java @@ -17,11 +17,14 @@ package top.limitart.concurrent; import com.lmax.disruptor.BlockingWaitStrategy; import com.lmax.disruptor.ExceptionHandler; +import com.lmax.disruptor.InsufficientCapacityException; import com.lmax.disruptor.dsl.Disruptor; import com.lmax.disruptor.dsl.ProducerType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import top.limitart.base.Alone; +import top.limitart.base.Conditions; +import top.limitart.base.UncatchableException; import top.limitart.base.function.Process3; import top.limitart.base.function.Processes; @@ -31,10 +34,12 @@ import top.limitart.base.function.Processes; * @author Hank */ public class DisruptorTaskQueue extends AbstractTaskQueue { + private static final Logger LOGGER = LoggerFactory.getLogger(DisruptorTaskQueue.class); private final Disruptor> disruptor; private final SingletonThreadFactory threadFactory; private Process3 exception; + private ExecuteStrategy strategy = ExecuteStrategy.BLOCK_BUT_NOTICE; public static DisruptorTaskQueue create(SingletonThreadFactory threadFactory) { return new DisruptorTaskQueue(threadFactory); @@ -59,6 +64,7 @@ public class DisruptorTaskQueue extends AbstractTaskQueue { private DisruptorTaskQueue(String threadName) { this(threadName, 2 << 12); // 4096 } + /** * 构造函数 * @@ -76,11 +82,12 @@ public class DisruptorTaskQueue extends AbstractTaskQueue { }, bufferSize); } + /** * 构造函数 * * @param threadFactory - * @param bufferSize 指定RingBuffer的大小 + * @param bufferSize 指定RingBuffer的大小 */ @SuppressWarnings("unchecked") private DisruptorTaskQueue(SingletonThreadFactory threadFactory, int bufferSize) { @@ -133,9 +140,50 @@ public class DisruptorTaskQueue extends AbstractTaskQueue { return this; } + /** + * 设置执行队列满时的策略 + * + * @param strategy + * @return + */ + public DisruptorTaskQueue executeStrategy(ExecuteStrategy strategy) { + this.strategy = strategy; + return this; + } + @Override public void execute0(Runnable runnable) { - disruptor.getRingBuffer().publishEvent((event, sequence) -> event.set(runnable)); + Conditions.notNull(runnable); + try { + long next = disruptor.getRingBuffer().tryNext(); + publish(runnable, next); + } catch (InsufficientCapacityException e) { + //这里用不用tryPublishEvent,他内部会默认阻塞当前线程,知道能插入为止。用try让他快速失败,我们好调试我们的程序到底是消费过慢还是生产过快,因为此队列假设的是消费必须比生产快 + if (this.strategy == ExecuteStrategy.FAST_FAIL + || this.strategy == ExecuteStrategy.BLOCK_BUT_NOTICE) { + UncatchableException uncatchableException = new UncatchableException( + "task queue " + this.thread().getName() + + " is not enough to execute task, maybe customer is too slowly or provider is too fast! "); + LOGGER.error("no capacity", uncatchableException); + Processes.invoke(exception, runnable, + uncatchableException, + disruptor.getCursor() + 1); + } + if (this.strategy == ExecuteStrategy.BLOCK_BUT_NOTICE + || this.strategy == ExecuteStrategy.BLOCK) { + //阻塞 + long next = disruptor.getRingBuffer().next(); + publish(runnable, next); + } + } + } + + private void publish(Runnable runnable, long seq) { + try { + disruptor.getRingBuffer().get(seq).set(runnable); + } finally { + disruptor.getRingBuffer().publish(seq); + } } @Override @@ -150,4 +198,19 @@ public class DisruptorTaskQueue extends AbstractTaskQueue { LOGGER.info("thread " + threadFactory.get().getName() + " stop!"); } } + + public enum ExecuteStrategy { + /** + * 如果无法入队,则直接失败 + */ + FAST_FAIL, + /** + * 如果无法入队,则阻塞等待,但会警告 + */ + BLOCK_BUT_NOTICE, + /** + * 如果无法入队,则阻塞等待 + */ + BLOCK + } } diff --git a/core/src/main/java/top/limitart/util/CodecUtil.java b/core/src/main/java/top/limitart/util/CodecUtil.java index 6bd22d0779bdbc3c72811c7ff25433f02b92c049..59fc91115f7b23bdf674ded33208887ad8e08e77 100644 --- a/core/src/main/java/top/limitart/util/CodecUtil.java +++ b/core/src/main/java/top/limitart/util/CodecUtil.java @@ -37,9 +37,13 @@ import java.util.zip.GZIPOutputStream; * @author hank * @version 2018/4/20 0020 11:06 */ -public class CodecUtil { +public final class CodecUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(CodecUtil.class); + private CodecUtil() { + } + public static String urlEncode(String str) throws UnsupportedEncodingException { return URLEncoder.encode(str, StandardCharsets.UTF_8.name()); } diff --git a/core/src/main/java/top/limitart/util/EnumUtil.java b/core/src/main/java/top/limitart/util/EnumUtil.java index fa99fd3550e119bf6286ce750ed3d2fba7b60fb0..4522fc92230b1d00a9a244d3d07a8eb07d48321c 100644 --- a/core/src/main/java/top/limitart/util/EnumUtil.java +++ b/core/src/main/java/top/limitart/util/EnumUtil.java @@ -24,6 +24,10 @@ import top.limitart.base.label.Nullable; * @version 2018/2/12 0012 20:22 */ public final class EnumUtil { + + private EnumUtil() { + } + /** * 获取序号对应的枚举类型 * diff --git a/core/src/main/java/top/limitart/util/HTTPClient.java b/core/src/main/java/top/limitart/util/HTTPClient.java index 5c44b7f8a4d92d41ab44b1f4c40cf23b398c6041..6289be670ba042e262d7a5ffd675db0625d1cd98 100644 --- a/core/src/main/java/top/limitart/util/HTTPClient.java +++ b/core/src/main/java/top/limitart/util/HTTPClient.java @@ -33,10 +33,16 @@ import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.Future; -/** HTTP客户端 Created by Hank on 2019/3/17 */ -public class HTTPClient { +/** + * HTTP客户端 Created by Hank on 2019/3/17 + */ +public final class HTTPClient { + private static final Logger LOGGER = LoggerFactory.getLogger(HTTPClient.class); + private HTTPClient() { + } + public static byte[] download(String uri) { return download(uri); } diff --git a/core/src/main/java/top/limitart/util/GameMathUtil.java b/core/src/main/java/top/limitart/util/MathUtil.java similarity index 99% rename from core/src/main/java/top/limitart/util/GameMathUtil.java rename to core/src/main/java/top/limitart/util/MathUtil.java index b2de41296828e1e5572bc0d28d46787fd919dba1..8b27d344547a33b9132d65deac5b677febc711ce 100644 --- a/core/src/main/java/top/limitart/util/GameMathUtil.java +++ b/core/src/main/java/top/limitart/util/MathUtil.java @@ -27,8 +27,8 @@ import java.util.List; * * @author hank */ -public final class GameMathUtil { - private GameMathUtil() {} +public final class MathUtil { + private MathUtil() {} /** * 安全相加,如果越界返回int最大值 diff --git a/core/src/main/java/top/limitart/util/ObjectUtil.java b/core/src/main/java/top/limitart/util/ObjectUtil.java index dd8bd98155a288682b2c7d2c8fe6456e24c0152c..3e02ecd9c56bf51e282d0a621c640d8be9a4c409 100644 --- a/core/src/main/java/top/limitart/util/ObjectUtil.java +++ b/core/src/main/java/top/limitart/util/ObjectUtil.java @@ -8,7 +8,11 @@ import java.lang.reflect.Field; * @author hank * @version 2018/12/28 0028 20:27 */ -public class ObjectUtil { +public final class ObjectUtil { + + private ObjectUtil() { + } + /** * 通过反射字段拷贝 * diff --git a/core/src/test/java/top/limitart/util/GameMathUtilTest.java b/core/src/test/java/top/limitart/util/GameMathUtilTest.java index 5c80219ac5afaf51c2dcc97cc2f0642cde5f7a85..76a9c9e43d1fa1634e846ee6cec160f37e5985d1 100644 --- a/core/src/test/java/top/limitart/util/GameMathUtilTest.java +++ b/core/src/test/java/top/limitart/util/GameMathUtilTest.java @@ -30,11 +30,11 @@ public class GameMathUtilTest { @Test public void safeTest() { - Assert.assertTrue(GameMathUtil.safeAdd(10, 11) == 21); - Assert.assertTrue(GameMathUtil.safeAdd(Integer.MAX_VALUE, 1) == Integer.MAX_VALUE); - Assert.assertTrue(GameMathUtil.safeSub(10, 11) == -1); - Assert.assertTrue(GameMathUtil.safeSub(Integer.MIN_VALUE, 1) == Integer.MIN_VALUE); - Assert.assertTrue(GameMathUtil.safeMulti(10, 11) == 110); - Assert.assertTrue(GameMathUtil.safeMulti(Integer.MAX_VALUE, 10) == Integer.MAX_VALUE); + Assert.assertTrue(MathUtil.safeAdd(10, 11) == 21); + Assert.assertTrue(MathUtil.safeAdd(Integer.MAX_VALUE, 1) == Integer.MAX_VALUE); + Assert.assertTrue(MathUtil.safeSub(10, 11) == -1); + Assert.assertTrue(MathUtil.safeSub(Integer.MIN_VALUE, 1) == Integer.MIN_VALUE); + Assert.assertTrue(MathUtil.safeMulti(10, 11) == 110); + Assert.assertTrue(MathUtil.safeMulti(Integer.MAX_VALUE, 10) == Integer.MAX_VALUE); } } diff --git a/db/pom.xml b/db/pom.xml index 04650b8b647ed43ccb8b6bb89b89b3891cc61fe4..4773a36cab0d09da4c5e651ea45bb58fa7c0eea9 100644 --- a/db/pom.xml +++ b/db/pom.xml @@ -5,7 +5,7 @@ limitart top.limitart - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 diff --git a/db/src/main/java/top/limitart/db/DBHandler.java b/db/src/main/java/top/limitart/db/DBHelper.java similarity index 84% rename from db/src/main/java/top/limitart/db/DBHandler.java rename to db/src/main/java/top/limitart/db/DBHelper.java index c22101212f6849a296e82698b75a51198722e2a2..e17658b1bbf3de9671cae97ca0405d6c497013d5 100644 --- a/db/src/main/java/top/limitart/db/DBHandler.java +++ b/db/src/main/java/top/limitart/db/DBHelper.java @@ -29,15 +29,15 @@ import java.util.List; * @author hank * @version 2018/4/14 0014 16:47 */ -public interface DBHandler extends AutoCloseable { +public interface DBHelper extends AutoCloseable { /** * 创建一个实际的数据库 * * @param dataSource * @return */ - static DBHandler createReal(DBDataSource dataSource) { - return new SimpleDBHandler(dataSource); + static DBHelper createSimple(DBDataSource dataSource) { + return new SimpleDBHelper(dataSource); } /** @@ -45,8 +45,9 @@ public interface DBHandler extends AutoCloseable { * * @return */ - static DBHandler createFake() { - return new FakeDBHandler(); + @Deprecated + static DBHelper createFake() { + return new FakeDBHelper(); } /** @@ -74,7 +75,7 @@ public interface DBHandler extends AutoCloseable { * @return * @throws SQLException */ - List selectList(Select select, ResultHandler handler) throws SQLException; + List selectList(Select select, QueryResult handler) throws SQLException; /** * 查找单个实例 @@ -85,7 +86,7 @@ public interface DBHandler extends AutoCloseable { * @return * @throws SQLException */ - T selectOne(Select select, ResultHandler handler) throws SQLException; + T selectOne(Select select, QueryResult handler) throws SQLException; /** * 更新(插入、更新、删除) diff --git a/db/src/main/java/top/limitart/db/FakeDBHandler.java b/db/src/main/java/top/limitart/db/FakeDBHelper.java similarity index 86% rename from db/src/main/java/top/limitart/db/FakeDBHandler.java rename to db/src/main/java/top/limitart/db/FakeDBHelper.java index 00f61c3ffe50356e73ddd7ba42ccf2de4a732046..31cf85dffc9361c47d712e8823cc64f2eba84d29 100644 --- a/db/src/main/java/top/limitart/db/FakeDBHandler.java +++ b/db/src/main/java/top/limitart/db/FakeDBHelper.java @@ -29,19 +29,20 @@ import java.util.List; * @author hank * @version 2018/4/14 0014 16:47 */ -public class FakeDBHandler implements DBHandler { +@Deprecated +public class FakeDBHelper implements DBHelper { @Override public DataSource dataSource() { throw new UnsupportedOperationException(); } @Override - public List selectList(Select select, ResultHandler handler) throws SQLException { + public List selectList(Select select, QueryResult handler) throws SQLException { return Collections.EMPTY_LIST; } @Override - public T selectOne(Select select, ResultHandler handler) throws SQLException { + public T selectOne(Select select, QueryResult handler) throws SQLException { return null; } diff --git a/db/src/main/java/top/limitart/db/ResultHandler.java b/db/src/main/java/top/limitart/db/QueryResult.java similarity index 95% rename from db/src/main/java/top/limitart/db/ResultHandler.java rename to db/src/main/java/top/limitart/db/QueryResult.java index b7fc8c2e34f7013b5bd539f6ce3e0df699e7c349..54a1f684e7224355218299d6f9df8e2dc5e95607 100644 --- a/db/src/main/java/top/limitart/db/ResultHandler.java +++ b/db/src/main/java/top/limitart/db/QueryResult.java @@ -18,6 +18,6 @@ package top.limitart.db; import java.sql.ResultSet; import java.sql.SQLException; -public interface ResultHandler { +public interface QueryResult { T parse(ResultSet resultSet) throws SQLException; } diff --git a/db/src/main/java/top/limitart/db/SimpleDBHandler.java b/db/src/main/java/top/limitart/db/SimpleDBHelper.java similarity index 93% rename from db/src/main/java/top/limitart/db/SimpleDBHandler.java rename to db/src/main/java/top/limitart/db/SimpleDBHelper.java index c5dfe5c215fe7950140753d514d7e2ce75f32a57..d045446d5777467f9d3354d9cf0c34853f72c993 100644 --- a/db/src/main/java/top/limitart/db/SimpleDBHandler.java +++ b/db/src/main/java/top/limitart/db/SimpleDBHelper.java @@ -33,13 +33,13 @@ import java.util.List; * @author hank * @version 2018/4/14 0014 16:47 */ -public class SimpleDBHandler implements DBHandler { - private static Logger LOGGER = LoggerFactory.getLogger(SimpleDBHandler.class); +public class SimpleDBHelper implements DBHelper { + private static Logger LOGGER = LoggerFactory.getLogger(SimpleDBHelper.class); private static long SLOW_SQL = 100; private final DataSource dataSource; /** @param dataSource */ - public SimpleDBHandler(DBDataSource dataSource) { + public SimpleDBHelper(DBDataSource dataSource) { this.dataSource = dataSource; } @@ -49,7 +49,7 @@ public class SimpleDBHandler implements DBHandler { } @Override - public List selectList(Select select, ResultHandler handler) throws SQLException { + public List selectList(Select select, QueryResult handler) throws SQLException { try (Connection con = connection(); PreparedStatement preparedStatement = select.withParams(con); ResultSet resultSet = preparedStatement.executeQuery()) { @@ -62,7 +62,7 @@ public class SimpleDBHandler implements DBHandler { } @Override - public T selectOne(Select select, ResultHandler handler) throws SQLException { + public T selectOne(Select select, QueryResult handler) throws SQLException { try (Connection con = connection(); PreparedStatement preparedStatement = select.withParams(con); ResultSet resultSet = preparedStatement.executeQuery()) { diff --git a/db/src/main/java/top/limitart/db/sql/Prepare.java b/db/src/main/java/top/limitart/db/sql/Prepare.java index c0ff306297f948fac48c6b8cbb23d56cbeff7bf9..53fb2778a3af341ffa9cdcf2941fa7ed45291359 100644 --- a/db/src/main/java/top/limitart/db/sql/Prepare.java +++ b/db/src/main/java/top/limitart/db/sql/Prepare.java @@ -21,23 +21,8 @@ package top.limitart.db.sql; * @author hank * @version 2018/4/14 0014 16:47 */ +@Deprecated public interface Prepare { - static void main(String[] args) { - SQL insert = Prepare.insert().into("account").values("id", 1, "name", "hank"); - System.out.println(insert.sql()); - SQL delete = Prepare.delete().from("account").where(Where.create().whereEquals("id", 1)); - System.out.println(delete.sql()); - Update update = - Prepare.update("account") - .set("id", 1, "age", 10) - .where(Where.create().whereEquals("name", "hank")); - System.out.println(update.sql()); - Select select = - Prepare.select("id", "age") - .from("account") - .where(Where.create().whereEquals("name", "hank")); - System.out.println(select.sql()); - } /** * 开始编写插入语句 diff --git a/demo/pom.xml b/demo/pom.xml index b46569b106f6327fc4e45f25edd61924dbc74693..78dd4f532c83efd5b1b843eee37523c4ddd76b35 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -5,7 +5,7 @@ top.limitart limitart - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 @@ -38,6 +38,36 @@ limitart-hotdep ${project.version} + + ${project.groupId} + limitart-fastmq-pipeline + ${project.version} + + + ${project.groupId} + limitart-fastmq-consumer + ${project.version} + + + ${project.groupId} + limitart-fastmq-provider + ${project.version} + + + ${project.groupId} + limitart-rpc-service-center + ${project.version} + + + ${project.groupId} + limitart-rpc-service-provider + ${project.version} + + + ${project.groupId} + limitart-rpc-service-consumer + ${project.version} + org.apache.logging.log4j diff --git a/demo/script/top/limitart/script/HelloScriptImpl.java b/demo/script/top/limitart/demo/script/HelloScriptImpl.java similarity index 87% rename from demo/script/top/limitart/script/HelloScriptImpl.java rename to demo/script/top/limitart/demo/script/HelloScriptImpl.java index 3a50352dfe2fe6fc0bf9f206fa35ad99bc2fae0d..d2804e7a41c2122ef084f644c0ab28d3e1ce59af 100644 --- a/demo/script/top/limitart/script/HelloScriptImpl.java +++ b/demo/script/top/limitart/demo/script/HelloScriptImpl.java @@ -1,4 +1,4 @@ -package top.limitart.script; +package top.limitart.demo.script; public class HelloScriptImpl implements HelloScript { @Override diff --git a/demo/src/main/java/top/limitart/base/EnumBehaviorDemo.java b/demo/src/main/java/top/limitart/demo/base/EnumBehaviorDemo.java similarity index 64% rename from demo/src/main/java/top/limitart/base/EnumBehaviorDemo.java rename to demo/src/main/java/top/limitart/demo/base/EnumBehaviorDemo.java index f42b921779805124f630f86195f93c0aa9218ee9..7f66ca340d40ed7f426f0474064a0dbb7989cb2b 100644 --- a/demo/src/main/java/top/limitart/base/EnumBehaviorDemo.java +++ b/demo/src/main/java/top/limitart/demo/base/EnumBehaviorDemo.java @@ -1,4 +1,6 @@ -package top.limitart.base; +package top.limitart.demo.base; + +import top.limitart.base.EnumBehavior; /** * @author hank diff --git a/demo/src/main/java/top/limitart/collections/ConcurrentLRUCacheDemo.java b/demo/src/main/java/top/limitart/demo/collections/ConcurrentLRUCacheDemo.java similarity index 93% rename from demo/src/main/java/top/limitart/collections/ConcurrentLRUCacheDemo.java rename to demo/src/main/java/top/limitart/demo/collections/ConcurrentLRUCacheDemo.java index b313af62b1f5de3d8626849160910ff902f93478..6fe1922227768f9c8c15259195bf08226f3b9872 100644 --- a/demo/src/main/java/top/limitart/collections/ConcurrentLRUCacheDemo.java +++ b/demo/src/main/java/top/limitart/demo/collections/ConcurrentLRUCacheDemo.java @@ -1,8 +1,9 @@ -package top.limitart.collections; +package top.limitart.demo.collections; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; +import top.limitart.collections.ConcurrentLRUCache; /** * @author hank diff --git a/demo/src/main/java/top/limitart/collections/RankMapDemo.java b/demo/src/main/java/top/limitart/demo/collections/RankMapDemo.java similarity index 95% rename from demo/src/main/java/top/limitart/collections/RankMapDemo.java rename to demo/src/main/java/top/limitart/demo/collections/RankMapDemo.java index 4db5211e6aa8584479e2f740d557cd009dc51c94..9b210cb205f7daa20c07e99fb08e3d8f21d8bd89 100644 --- a/demo/src/main/java/top/limitart/collections/RankMapDemo.java +++ b/demo/src/main/java/top/limitart/demo/collections/RankMapDemo.java @@ -1,8 +1,9 @@ -package top.limitart.collections; +package top.limitart.demo.collections; import top.limitart.base.CompareChain; import java.util.Comparator; +import top.limitart.collections.RankMap; public class RankMapDemo { private static final Comparator COMPARATOR = diff --git a/demo/src/main/java/top/limitart/concurrent/TaskQueueCronDemo.java b/demo/src/main/java/top/limitart/demo/concurrent/TaskQueueCronDemo.java similarity index 91% rename from demo/src/main/java/top/limitart/concurrent/TaskQueueCronDemo.java rename to demo/src/main/java/top/limitart/demo/concurrent/TaskQueueCronDemo.java index 6dd71844e6771af76e9252c99ef4f8893548dbc4..0040b5afd27018e74f2df8f33f81bab459e1418a 100644 --- a/demo/src/main/java/top/limitart/concurrent/TaskQueueCronDemo.java +++ b/demo/src/main/java/top/limitart/demo/concurrent/TaskQueueCronDemo.java @@ -1,4 +1,4 @@ -package top.limitart.concurrent; +package top.limitart.demo.concurrent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,6 +6,8 @@ import org.slf4j.LoggerFactory; import java.text.ParseException; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import top.limitart.concurrent.TaskQueue; +import top.limitart.concurrent.TaskQueueGroup; /** * @author hank diff --git a/demo/src/main/java/top/limitart/config/ConfigMetaDemo.java b/demo/src/main/java/top/limitart/demo/config/ConfigMetaDemo.java similarity index 71% rename from demo/src/main/java/top/limitart/config/ConfigMetaDemo.java rename to demo/src/main/java/top/limitart/demo/config/ConfigMetaDemo.java index cf0519efc227bd4a67310d069864ac98f07b291f..9a23cc1ecf644e5c3ebddfb6f7529d88196302a9 100644 --- a/demo/src/main/java/top/limitart/config/ConfigMetaDemo.java +++ b/demo/src/main/java/top/limitart/demo/config/ConfigMetaDemo.java @@ -1,4 +1,6 @@ -package top.limitart.config; +package top.limitart.demo.config; + +import top.limitart.config.ConfigMeta; /** * @author hank diff --git a/demo/src/main/java/top/limitart/config/D_ChipRank.java b/demo/src/main/java/top/limitart/demo/config/D_ChipRank.java similarity index 93% rename from demo/src/main/java/top/limitart/config/D_ChipRank.java rename to demo/src/main/java/top/limitart/demo/config/D_ChipRank.java index 0bdf3ed70f24c8c992e4c1f0998a3caf2aafe406..7ce7855cc4ef5947d3811ee145a05f75d772457c 100644 --- a/demo/src/main/java/top/limitart/config/D_ChipRank.java +++ b/demo/src/main/java/top/limitart/demo/config/D_ChipRank.java @@ -14,7 +14,9 @@ * limitations under the License. */ -package top.limitart.config; +package top.limitart.demo.config; + +import top.limitart.config.ConfigMeta; /** * 最高奖金排行奖励 from dat_proto at 2018-12-24T14:33:18.841 diff --git a/demo/src/main/java/top/limitart/config/D_WinRank.java b/demo/src/main/java/top/limitart/demo/config/D_WinRank.java similarity index 94% rename from demo/src/main/java/top/limitart/config/D_WinRank.java rename to demo/src/main/java/top/limitart/demo/config/D_WinRank.java index 4bdbe133a680e48fe737fc38a559924f0f1f896d..3e051366d01a1b95799e2cbecf986796a032cc65 100644 --- a/demo/src/main/java/top/limitart/config/D_WinRank.java +++ b/demo/src/main/java/top/limitart/demo/config/D_WinRank.java @@ -14,7 +14,9 @@ * limitations under the License. */ -package top.limitart.config; +package top.limitart.demo.config; + +import top.limitart.config.ConfigMeta; /** * 胜利场数排行奖励 from dat_proto at 2018-12-24T14:33:18.841 diff --git a/demo/src/main/java/top/limitart/config/DataTypeDemo.java b/demo/src/main/java/top/limitart/demo/config/DataTypeDemo.java similarity index 92% rename from demo/src/main/java/top/limitart/config/DataTypeDemo.java rename to demo/src/main/java/top/limitart/demo/config/DataTypeDemo.java index 6def3a20681449b17218aa7119150ac23905980c..5de8c6bd4fd0ff0fa037679cc05bb8450fdad41a 100644 --- a/demo/src/main/java/top/limitart/config/DataTypeDemo.java +++ b/demo/src/main/java/top/limitart/demo/config/DataTypeDemo.java @@ -16,8 +16,10 @@ * */ -package top.limitart.config; +package top.limitart.demo.config; +import top.limitart.config.IntArray2DType; +import top.limitart.config.IntArrayType; import top.limitart.json.JSON; import top.limitart.util.CollectionUtil; diff --git a/demo/src/main/java/top/limitart/config/ExcelModelDemo.java b/demo/src/main/java/top/limitart/demo/config/ExcelModelDemo.java similarity index 83% rename from demo/src/main/java/top/limitart/config/ExcelModelDemo.java rename to demo/src/main/java/top/limitart/demo/config/ExcelModelDemo.java index 7c5a9e5e5b0f53ac2a0471affdc111321393d260..07575cdf65f24147ae7eb60b013f5b332b7a975b 100644 --- a/demo/src/main/java/top/limitart/config/ExcelModelDemo.java +++ b/demo/src/main/java/top/limitart/demo/config/ExcelModelDemo.java @@ -1,7 +1,11 @@ -package top.limitart.config; +package top.limitart.demo.config; import java.util.Collections; import java.util.Map; +import top.limitart.config.ConfigContainers; +import top.limitart.config.DataParser; +import top.limitart.config.ExcelModel; +import top.limitart.config.SheetHead; /** * @author hank diff --git a/demo/src/main/java/top/limitart/config/Person.java b/demo/src/main/java/top/limitart/demo/config/Person.java similarity index 97% rename from demo/src/main/java/top/limitart/config/Person.java rename to demo/src/main/java/top/limitart/demo/config/Person.java index b9948afb0d8f53e801d4e223827889fa413cdd37..805b050a6a02d6b2e7c0b79a83448c7deae2f51b 100644 --- a/demo/src/main/java/top/limitart/config/Person.java +++ b/demo/src/main/java/top/limitart/demo/config/Person.java @@ -16,7 +16,7 @@ * */ -package top.limitart.config; +package top.limitart.demo.config; import top.limitart.base.BinaryMeta; diff --git a/demo/src/main/java/top/limitart/config/PersonDataType.java b/demo/src/main/java/top/limitart/demo/config/PersonDataType.java similarity index 94% rename from demo/src/main/java/top/limitart/config/PersonDataType.java rename to demo/src/main/java/top/limitart/demo/config/PersonDataType.java index 6c9ea3721809965c9ed073decf3ee45743c72c4f..241b442262373004c79460bf03d93923a2e45159 100644 --- a/demo/src/main/java/top/limitart/config/PersonDataType.java +++ b/demo/src/main/java/top/limitart/demo/config/PersonDataType.java @@ -16,9 +16,10 @@ * */ -package top.limitart.config; +package top.limitart.demo.config; import top.limitart.base.BinaryMeta; +import top.limitart.config.JSONParsingType; /** Created by Hank on 2018/12/23 */ public class PersonDataType extends JSONParsingType { diff --git a/demo/src/main/java/top/limitart/event/EventDemo.java b/demo/src/main/java/top/limitart/demo/event/EventDemo.java similarity index 77% rename from demo/src/main/java/top/limitart/event/EventDemo.java rename to demo/src/main/java/top/limitart/demo/event/EventDemo.java index 31090cb67cb02c3cdcf965391f6e810588aff144..34a0da1ae6affb06c3ced9adc1c06a83b01900f0 100644 --- a/demo/src/main/java/top/limitart/event/EventDemo.java +++ b/demo/src/main/java/top/limitart/demo/event/EventDemo.java @@ -1,4 +1,6 @@ -package top.limitart.event; +package top.limitart.demo.event; + +import top.limitart.event.Event; /** * @author hank diff --git a/demo/src/main/java/top/limitart/event/EventProviderDemo.java b/demo/src/main/java/top/limitart/demo/event/EventProviderDemo.java similarity index 84% rename from demo/src/main/java/top/limitart/event/EventProviderDemo.java rename to demo/src/main/java/top/limitart/demo/event/EventProviderDemo.java index 3f1d4e7456b695b269495c8e54ea7cf6078a43e1..48b2293e99623b5e198815939dde113880763e4c 100644 --- a/demo/src/main/java/top/limitart/event/EventProviderDemo.java +++ b/demo/src/main/java/top/limitart/demo/event/EventProviderDemo.java @@ -1,6 +1,9 @@ -package top.limitart.event; +package top.limitart.demo.event; import top.limitart.concurrent.TaskQueue; +import top.limitart.event.AbstractEventProvider; +import top.limitart.event.Event; +import top.limitart.event.EventProvider; /** * @author hank diff --git a/demo/src/main/java/top/limitart/demo/fastmq/PipelineConsumerDemo.java b/demo/src/main/java/top/limitart/demo/fastmq/PipelineConsumerDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..68dc040b8db221c36883718e9f038dc3313a29c5 --- /dev/null +++ b/demo/src/main/java/top/limitart/demo/fastmq/PipelineConsumerDemo.java @@ -0,0 +1,39 @@ +package top.limitart.demo.fastmq; + +import java.nio.charset.StandardCharsets; +import java.util.LinkedList; +import java.util.List; +import top.limitart.fastmq.consumer.MQConsumerBinaryClient; + +public class PipelineConsumerDemo { + + private static MQConsumerBinaryClient consumerClient; + + static { + try { + List tags = new LinkedList<>(); + tags.add("fuck"); + tags.add("shit"); + consumerClient = + new MQConsumerBinaryClient( + "127.0.0.1", + 9000, + "test_zone", + tags, + msg -> {System.out.println(new String(msg, StandardCharsets.UTF_8)) + ; + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) throws Exception { + consumerClient.run(args); + } +} diff --git a/demo/src/main/java/top/limitart/demo/fastmq/PipelineProviderDemo.java b/demo/src/main/java/top/limitart/demo/fastmq/PipelineProviderDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..a56a811caf7a29818676c27418f637282ce2316f --- /dev/null +++ b/demo/src/main/java/top/limitart/demo/fastmq/PipelineProviderDemo.java @@ -0,0 +1,35 @@ +package top.limitart.demo.fastmq; + +import java.nio.charset.StandardCharsets; +import java.util.LinkedList; +import java.util.List; +import top.limitart.fastmq.provider.MQProviderBinaryClient; + +public class PipelineProviderDemo { + + private static MQProviderBinaryClient providerClient; + + static { + try { + List tags = new LinkedList<>(); + tags.add("fuck"); + tags.add("shit"); + providerClient = + new MQProviderBinaryClient( + "127.0.0.1", + 9000); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) throws Exception { + providerClient.run(args); + int count = 0; + while (true) { + providerClient.sendMsg("test_zone", ("hello fastmq !" + count++) + .getBytes(StandardCharsets.UTF_8)); + Thread.sleep(30); + } + } +} diff --git a/demo/src/main/java/top/limitart/demo/fastmq/PipelineServerDemo.java b/demo/src/main/java/top/limitart/demo/fastmq/PipelineServerDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..6e057d3e46709463046dabcc18684d0f47be832a --- /dev/null +++ b/demo/src/main/java/top/limitart/demo/fastmq/PipelineServerDemo.java @@ -0,0 +1,22 @@ +package top.limitart.demo.fastmq; + +import top.limitart.fastmq.pipeline.MQPipelineBinaryServer; +import top.limitart.fastmq.pipeline.core.Pipeline; + +public class PipelineServerDemo { + + private static Pipeline pipeline = new Pipeline(); + private static MQPipelineBinaryServer binaryServer; + + static { + try { + binaryServer = new MQPipelineBinaryServer(pipeline, 9000); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) throws Exception { + binaryServer.run(args); + } +} diff --git a/demo/src/main/java/top/limitart/logging/LoggerDemo.java b/demo/src/main/java/top/limitart/demo/logging/LoggerDemo.java similarity index 87% rename from demo/src/main/java/top/limitart/logging/LoggerDemo.java rename to demo/src/main/java/top/limitart/demo/logging/LoggerDemo.java index 84da38bed28975b525cd7e934e50aa30a2b60a1f..d265c6809d25d2ab7f6b699326fb15a36fa5112e 100644 --- a/demo/src/main/java/top/limitart/logging/LoggerDemo.java +++ b/demo/src/main/java/top/limitart/demo/logging/LoggerDemo.java @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package top.limitart.logging; +package top.limitart.demo.logging; + +import top.limitart.logging.Logger; +import top.limitart.logging.Loggers; public class LoggerDemo { private static final Logger LOGGER = Loggers.create(); diff --git a/demo/src/main/java/top/limitart/mapping/RouterDemo.java b/demo/src/main/java/top/limitart/demo/mapping/RouterDemo.java similarity index 88% rename from demo/src/main/java/top/limitart/mapping/RouterDemo.java rename to demo/src/main/java/top/limitart/demo/mapping/RouterDemo.java index 46bb1ddca8581c76139214883f0019e929466b47..c771eb9d0be23263845271fdb5b4603dca4f7880 100644 --- a/demo/src/main/java/top/limitart/mapping/RouterDemo.java +++ b/demo/src/main/java/top/limitart/demo/mapping/RouterDemo.java @@ -1,4 +1,6 @@ -package top.limitart.mapping; +package top.limitart.demo.mapping; + +import top.limitart.mapping.Router; /** * @author hank diff --git a/demo/src/main/java/top/limitart/mapping/StringMapperClass.java b/demo/src/main/java/top/limitart/demo/mapping/StringMapperClass.java similarity index 66% rename from demo/src/main/java/top/limitart/mapping/StringMapperClass.java rename to demo/src/main/java/top/limitart/demo/mapping/StringMapperClass.java index 85845cc5c590ed89289bb223f67de62afc7dba8f..ff8fd7f4cd7bed2c9bd966331b6fbaa01d7ded96 100644 --- a/demo/src/main/java/top/limitart/mapping/StringMapperClass.java +++ b/demo/src/main/java/top/limitart/demo/mapping/StringMapperClass.java @@ -1,4 +1,7 @@ -package top.limitart.mapping; +package top.limitart.demo.mapping; + +import top.limitart.mapping.Mapper; +import top.limitart.mapping.Request; /** * @author hank diff --git a/demo/src/main/java/top/limitart/mapping/StringPoster.java b/demo/src/main/java/top/limitart/demo/mapping/StringPoster.java similarity index 71% rename from demo/src/main/java/top/limitart/mapping/StringPoster.java rename to demo/src/main/java/top/limitart/demo/mapping/StringPoster.java index 068705faaed5980c990e64e5108c6e5576dbbf63..b7985fcef804480fea627b0c8b05dd9db18e9070 100644 --- a/demo/src/main/java/top/limitart/mapping/StringPoster.java +++ b/demo/src/main/java/top/limitart/demo/mapping/StringPoster.java @@ -1,4 +1,4 @@ -package top.limitart.mapping; +package top.limitart.demo.mapping; /** * @author hank diff --git a/demo/src/main/java/top/limitart/mapping/StringQuestParam.java b/demo/src/main/java/top/limitart/demo/mapping/StringQuestParam.java similarity index 59% rename from demo/src/main/java/top/limitart/mapping/StringQuestParam.java rename to demo/src/main/java/top/limitart/demo/mapping/StringQuestParam.java index 52cc8f3ef9c83e413e3199226b045c40230d2a50..85408cff3148b6faf0094e70954487aa035cfe1f 100644 --- a/demo/src/main/java/top/limitart/mapping/StringQuestParam.java +++ b/demo/src/main/java/top/limitart/demo/mapping/StringQuestParam.java @@ -1,4 +1,6 @@ -package top.limitart.mapping; +package top.limitart.demo.mapping; + +import top.limitart.mapping.RequestContext; /** * @author hank diff --git a/demo/src/main/java/top/limitart/mapping/StringRequest.java b/demo/src/main/java/top/limitart/demo/mapping/StringRequest.java similarity index 86% rename from demo/src/main/java/top/limitart/mapping/StringRequest.java rename to demo/src/main/java/top/limitart/demo/mapping/StringRequest.java index a6183e42987dd896d4850a630842002592e3ba71..33e662d248f2f2666299eee52fd32f76abb324d3 100644 --- a/demo/src/main/java/top/limitart/mapping/StringRequest.java +++ b/demo/src/main/java/top/limitart/demo/mapping/StringRequest.java @@ -1,4 +1,4 @@ -package top.limitart.mapping; +package top.limitart.demo.mapping; /** * @author hank diff --git a/demo/src/main/java/top/limitart/net/BinaryClientDemo.java b/demo/src/main/java/top/limitart/demo/net/BinaryClientDemo.java similarity index 89% rename from demo/src/main/java/top/limitart/net/BinaryClientDemo.java rename to demo/src/main/java/top/limitart/demo/net/BinaryClientDemo.java index 858ba6173c1e4f0fbb3ac8976072c896054dcdb6..14ff192ad72523455fe869fde03d69fd71cc4feb 100644 --- a/demo/src/main/java/top/limitart/net/BinaryClientDemo.java +++ b/demo/src/main/java/top/limitart/demo/net/BinaryClientDemo.java @@ -13,9 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package top.limitart.net; +package top.limitart.demo.net; +import top.limitart.mapping.Mapper; import top.limitart.mapping.Router; +import top.limitart.net.AddressPair; import top.limitart.net.binary.BinaryEndPoint; import top.limitart.net.binary.BinaryMessage; import top.limitart.net.binary.BinaryRequestParam; @@ -26,7 +28,7 @@ public class BinaryClientDemo { BinaryEndPoint.builder(false) .router( Router.empty(BinaryMessage.class, BinaryRequestParam.class) - .registerMapperClass(MessageMapper.class)) + .registerMapperClass(Mapper.class)) .onConnected( (s, state) -> { if (state) { diff --git a/demo/src/main/java/top/limitart/net/BinaryMessageDemo.java b/demo/src/main/java/top/limitart/demo/net/BinaryMessageDemo.java similarity index 96% rename from demo/src/main/java/top/limitart/net/BinaryMessageDemo.java rename to demo/src/main/java/top/limitart/demo/net/BinaryMessageDemo.java index 698bec759884b8ae4971b7925ebf774b7c4b4791..3c022b236af0b2728d38a259b5b74f18dd4224ad 100644 --- a/demo/src/main/java/top/limitart/net/BinaryMessageDemo.java +++ b/demo/src/main/java/top/limitart/demo/net/BinaryMessageDemo.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package top.limitart.net; +package top.limitart.demo.net; import top.limitart.net.binary.BinaryMessage; import top.limitart.net.binary.BinaryMessages; diff --git a/demo/src/main/java/top/limitart/net/BinaryMessageDemo2.java b/demo/src/main/java/top/limitart/demo/net/BinaryMessageDemo2.java similarity index 96% rename from demo/src/main/java/top/limitart/net/BinaryMessageDemo2.java rename to demo/src/main/java/top/limitart/demo/net/BinaryMessageDemo2.java index 729b93d37d5b0f456d311881d5a294668eaf2c8a..cd74b4ed05daad243d040feb5f5d0772724fae20 100644 --- a/demo/src/main/java/top/limitart/net/BinaryMessageDemo2.java +++ b/demo/src/main/java/top/limitart/demo/net/BinaryMessageDemo2.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package top.limitart.net; +package top.limitart.demo.net; import top.limitart.net.binary.BinaryMessage; import top.limitart.net.binary.BinaryMessages; diff --git a/demo/src/main/java/top/limitart/net/BinaryScriptManager.java b/demo/src/main/java/top/limitart/demo/net/BinaryScriptManager.java similarity index 96% rename from demo/src/main/java/top/limitart/net/BinaryScriptManager.java rename to demo/src/main/java/top/limitart/demo/net/BinaryScriptManager.java index e265802d111dfb9017a1b5a33a2e3bbe0669c874..2d0273705e92e61e14953fe50e09c8066d5af63f 100644 --- a/demo/src/main/java/top/limitart/net/BinaryScriptManager.java +++ b/demo/src/main/java/top/limitart/demo/net/BinaryScriptManager.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package top.limitart.net; +package top.limitart.demo.net; import top.limitart.mapping.Mapper; import top.limitart.mapping.Request; diff --git a/demo/src/main/java/top/limitart/net/BinaryScriptManagerImpl.java b/demo/src/main/java/top/limitart/demo/net/BinaryScriptManagerImpl.java similarity index 96% rename from demo/src/main/java/top/limitart/net/BinaryScriptManagerImpl.java rename to demo/src/main/java/top/limitart/demo/net/BinaryScriptManagerImpl.java index e2914f0755b7a6a7716ce54ec9cc1e16e47231d6..545e3e2fdd0ed59824593d8fdc143d2556e2874b 100644 --- a/demo/src/main/java/top/limitart/net/BinaryScriptManagerImpl.java +++ b/demo/src/main/java/top/limitart/demo/net/BinaryScriptManagerImpl.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package top.limitart.net; +package top.limitart.demo.net; import top.limitart.net.binary.BinaryRequestParam; diff --git a/demo/src/main/java/top/limitart/net/BinaryServerDemo.java b/demo/src/main/java/top/limitart/demo/net/BinaryServerDemo.java similarity index 94% rename from demo/src/main/java/top/limitart/net/BinaryServerDemo.java rename to demo/src/main/java/top/limitart/demo/net/BinaryServerDemo.java index 8731c00766e7158270fe67a03516081093f9d9fc..a8971814e9b445bad53d10b0d56328238e3f8dd6 100644 --- a/demo/src/main/java/top/limitart/net/BinaryServerDemo.java +++ b/demo/src/main/java/top/limitart/demo/net/BinaryServerDemo.java @@ -13,9 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package top.limitart.net; +package top.limitart.demo.net; import top.limitart.mapping.Router; +import top.limitart.net.AddressPair; +import top.limitart.net.NettySession; import top.limitart.net.binary.BinaryEndPoint; import top.limitart.net.binary.BinaryMessage; import top.limitart.net.binary.BinaryRequestParam; diff --git a/demo/src/main/java/top/limitart/net/BinarySessionRole.java b/demo/src/main/java/top/limitart/demo/net/BinarySessionRole.java similarity index 62% rename from demo/src/main/java/top/limitart/net/BinarySessionRole.java rename to demo/src/main/java/top/limitart/demo/net/BinarySessionRole.java index 357d9fa2acaabec315cdf2916aa4b80fd8d57ec7..bea8b72c348505593544bfa6241dc5ed226e197d 100644 --- a/demo/src/main/java/top/limitart/net/BinarySessionRole.java +++ b/demo/src/main/java/top/limitart/demo/net/BinarySessionRole.java @@ -1,6 +1,7 @@ -package top.limitart.net; +package top.limitart.demo.net; +import top.limitart.net.NettySessionActor; import top.limitart.net.binary.BinaryMessage; public class BinarySessionRole extends NettySessionActor {} diff --git a/demo/src/main/java/top/limitart/net/FlashSSLServerDemo.java b/demo/src/main/java/top/limitart/demo/net/FlashSSLServerDemo.java similarity index 80% rename from demo/src/main/java/top/limitart/net/FlashSSLServerDemo.java rename to demo/src/main/java/top/limitart/demo/net/FlashSSLServerDemo.java index 8e46688b0859df06d90340c98042ed2c25bc08e8..ac3c5cca76ea240c85231f222da5bfc77fbb0144 100644 --- a/demo/src/main/java/top/limitart/net/FlashSSLServerDemo.java +++ b/demo/src/main/java/top/limitart/demo/net/FlashSSLServerDemo.java @@ -1,5 +1,6 @@ -package top.limitart.net; +package top.limitart.demo.net; +import top.limitart.net.AddressPair; import top.limitart.net.flashssl.FlashSSLEndPoint; /** diff --git a/demo/src/main/java/top/limitart/net/HTTPSServerDemo.java b/demo/src/main/java/top/limitart/demo/net/HTTPSServerDemo.java similarity index 95% rename from demo/src/main/java/top/limitart/net/HTTPSServerDemo.java rename to demo/src/main/java/top/limitart/demo/net/HTTPSServerDemo.java index a29cbc23925ebb3f40983cbfa4b977f3536c6b32..725de75caabd86259625557aa8f173cf567d2e09 100644 --- a/demo/src/main/java/top/limitart/net/HTTPSServerDemo.java +++ b/demo/src/main/java/top/limitart/demo/net/HTTPSServerDemo.java @@ -16,7 +16,7 @@ * */ -package top.limitart.net; +package top.limitart.demo.net; /** Created by Hank on 2018/10/14 */ public class HTTPSServerDemo { diff --git a/demo/src/main/java/top/limitart/net/HTTPServerDemo.java b/demo/src/main/java/top/limitart/demo/net/HTTPServerDemo.java similarity index 95% rename from demo/src/main/java/top/limitart/net/HTTPServerDemo.java rename to demo/src/main/java/top/limitart/demo/net/HTTPServerDemo.java index 3703e8a18d763a96f763c268e94531430b30a788..793ec6dda37263b9cbe2f488215519087aeecf05 100644 --- a/demo/src/main/java/top/limitart/net/HTTPServerDemo.java +++ b/demo/src/main/java/top/limitart/demo/net/HTTPServerDemo.java @@ -16,8 +16,9 @@ * */ -package top.limitart.net; +package top.limitart.demo.net; +import top.limitart.net.AddressPair; import top.limitart.net.http.HTTPEndPoint; import java.nio.charset.StandardCharsets; diff --git a/demo/src/main/java/top/limitart/net/LocalEndPointDemo.java b/demo/src/main/java/top/limitart/demo/net/LocalEndPointDemo.java similarity index 87% rename from demo/src/main/java/top/limitart/net/LocalEndPointDemo.java rename to demo/src/main/java/top/limitart/demo/net/LocalEndPointDemo.java index bb0e61b8806d66dd8894d39fd12cefc76bb4dcc9..4eeb21e21fc50f9ce3f3e1fed31aba3189ceb455 100644 --- a/demo/src/main/java/top/limitart/net/LocalEndPointDemo.java +++ b/demo/src/main/java/top/limitart/demo/net/LocalEndPointDemo.java @@ -1,6 +1,9 @@ -package top.limitart.net; +package top.limitart.demo.net; +import top.limitart.demo.net.BinaryMessageDemo; import top.limitart.mapping.Router; +import top.limitart.net.AddressPair; +import top.limitart.net.NettyEndPointType; import top.limitart.net.binary.BinaryEndPoint; import top.limitart.net.binary.BinaryMessage; import top.limitart.net.binary.BinaryRequestParam; diff --git a/demo/src/main/java/top/limitart/net/MessageMapper.java b/demo/src/main/java/top/limitart/demo/net/MessageMapper.java similarity index 93% rename from demo/src/main/java/top/limitart/net/MessageMapper.java rename to demo/src/main/java/top/limitart/demo/net/MessageMapper.java index d1ebce6bccb464e60d9f025b368399c5b7ad5844..0629c610d69a65ff76c14fe9146269157699c03c 100644 --- a/demo/src/main/java/top/limitart/net/MessageMapper.java +++ b/demo/src/main/java/top/limitart/demo/net/MessageMapper.java @@ -16,12 +16,14 @@ * */ -package top.limitart.net; +package top.limitart.demo.net; import com.google.protobuf.Message; import io.netty.channel.EventLoop; +import top.limitart.demo.net.BinaryMessageDemo; import top.limitart.mapping.Mapper; import top.limitart.mapping.Request; +import top.limitart.net.Session; import top.limitart.net.binary.BinaryMessage; import top.limitart.net.binary.BinaryRequestParam; import top.limitart.net.protobuf.ProtobufRequestParam; diff --git a/demo/src/main/java/top/limitart/net/MessagePackageTest.java b/demo/src/main/java/top/limitart/demo/net/MessagePackageTest.java similarity index 98% rename from demo/src/main/java/top/limitart/net/MessagePackageTest.java rename to demo/src/main/java/top/limitart/demo/net/MessagePackageTest.java index 80b3cf24da49ac655cc43b12a6997fa9e8cdd99a..a0c9e182547f22824cbfc316040a37e148d9e6e8 100644 --- a/demo/src/main/java/top/limitart/net/MessagePackageTest.java +++ b/demo/src/main/java/top/limitart/demo/net/MessagePackageTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package top.limitart.net; +package top.limitart.demo.net; import top.limitart.base.BinaryMeta; import top.limitart.net.binary.BinaryMessage; diff --git a/demo/src/main/java/top/limitart/net/ProtobufClientDemo.java b/demo/src/main/java/top/limitart/demo/net/ProtobufClientDemo.java similarity index 88% rename from demo/src/main/java/top/limitart/net/ProtobufClientDemo.java rename to demo/src/main/java/top/limitart/demo/net/ProtobufClientDemo.java index 6c4f0b72acd168056a519a7747e2865593231d3a..4e149e1223733211f6fefcca2bd3bb805387c6fb 100644 --- a/demo/src/main/java/top/limitart/net/ProtobufClientDemo.java +++ b/demo/src/main/java/top/limitart/demo/net/ProtobufClientDemo.java @@ -1,7 +1,9 @@ -package top.limitart.net; +package top.limitart.demo.net; import com.google.protobuf.Message; +import top.limitart.demo.net.MessageMapper; import top.limitart.mapping.Router; +import top.limitart.net.AddressPair; import top.limitart.net.protobuf.ProtobufEndPoint; import top.limitart.net.protobuf.ProtobufRequestParam; diff --git a/demo/src/main/java/top/limitart/net/ProtobufMessageDemo.java b/demo/src/main/java/top/limitart/demo/net/ProtobufMessageDemo.java similarity index 99% rename from demo/src/main/java/top/limitart/net/ProtobufMessageDemo.java rename to demo/src/main/java/top/limitart/demo/net/ProtobufMessageDemo.java index 24a0a675d55ffe06268c74ecdaf363ea34d4dc94..7a08964a977e1d31ef513ce9c44e3ea6f4750642 100644 --- a/demo/src/main/java/top/limitart/net/ProtobufMessageDemo.java +++ b/demo/src/main/java/top/limitart/demo/net/ProtobufMessageDemo.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: protobuf3.proto -package top.limitart.net; +package top.limitart.demo.net; public final class ProtobufMessageDemo { private ProtobufMessageDemo() {} diff --git a/demo/src/main/java/top/limitart/net/ProtobufServerDemo.java b/demo/src/main/java/top/limitart/demo/net/ProtobufServerDemo.java similarity index 93% rename from demo/src/main/java/top/limitart/net/ProtobufServerDemo.java rename to demo/src/main/java/top/limitart/demo/net/ProtobufServerDemo.java index b188f4ade444029609725a7a9885c1e0b064b4c6..4718c901b64261469744a9490a5f53656b4a5c92 100644 --- a/demo/src/main/java/top/limitart/net/ProtobufServerDemo.java +++ b/demo/src/main/java/top/limitart/demo/net/ProtobufServerDemo.java @@ -13,10 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package top.limitart.net; +package top.limitart.demo.net; import com.google.protobuf.Message; +import top.limitart.demo.net.MessageMapper; import top.limitart.mapping.Router; +import top.limitart.net.AddressPair; import top.limitart.net.protobuf.ProtobufEndPoint; import top.limitart.net.protobuf.ProtobufRequestParam; diff --git a/demo/src/main/java/top/limitart/net/ProtobufSessionRole.java b/demo/src/main/java/top/limitart/demo/net/ProtobufSessionRole.java similarity index 59% rename from demo/src/main/java/top/limitart/net/ProtobufSessionRole.java rename to demo/src/main/java/top/limitart/demo/net/ProtobufSessionRole.java index 5735461d5df2ed05297a106cd3c7e8271f8f6ad0..9112703f9849eaf3578c4f67d469d3257f6edef9 100644 --- a/demo/src/main/java/top/limitart/net/ProtobufSessionRole.java +++ b/demo/src/main/java/top/limitart/demo/net/ProtobufSessionRole.java @@ -1,6 +1,7 @@ -package top.limitart.net; +package top.limitart.demo.net; import com.google.protobuf.Message; +import top.limitart.net.NettySessionActor; public class ProtobufSessionRole extends NettySessionActor {} diff --git a/demo/src/main/java/top/limitart/net/WebSocketServerDemo.java b/demo/src/main/java/top/limitart/demo/net/WebSocketServerDemo.java similarity index 85% rename from demo/src/main/java/top/limitart/net/WebSocketServerDemo.java rename to demo/src/main/java/top/limitart/demo/net/WebSocketServerDemo.java index 72fc86fa210d77ea1a40525a7d56b76e4d974cc9..7d3a5aafc9e807411a10203a1f78832c80d985d0 100644 --- a/demo/src/main/java/top/limitart/net/WebSocketServerDemo.java +++ b/demo/src/main/java/top/limitart/demo/net/WebSocketServerDemo.java @@ -16,10 +16,14 @@ * */ -package top.limitart.net; +package top.limitart.demo.net; import io.netty.channel.EventLoop; import io.netty.handler.codec.http.websocketx.WebSocketFrame; +import top.limitart.net.AddressPair; +import top.limitart.net.NettyEndPointType; +import top.limitart.net.NettySession; +import top.limitart.net.Session; import top.limitart.net.binary.BinaryMessage; import top.limitart.net.http.HTTPRequest; import top.limitart.net.http.HTTPSession; @@ -28,7 +32,7 @@ import top.limitart.net.websocket.WebSocketEndPoint; /** Created by Hank on 2019/2/24 */ public class WebSocketServerDemo { public static void main(String[] args) throws Exception { - new WebSocketEndPoint("web-socket-server", "/",NettyEndPointType.SERVER_REMOTE, 0, 0) { + new WebSocketEndPoint("web-socket-server", "/", NettyEndPointType.SERVER_REMOTE, 0, 0) { @Override protected void exceptionThrown(NettySession session, Throwable cause) throws Exception {} diff --git a/demo/src/main/java/top/limitart/redefinable/HelloRedefine.java b/demo/src/main/java/top/limitart/demo/redefinable/HelloRedefine.java similarity index 71% rename from demo/src/main/java/top/limitart/redefinable/HelloRedefine.java rename to demo/src/main/java/top/limitart/demo/redefinable/HelloRedefine.java index cb437bb00cedcf6b4dfd69320d7f8f210025283f..c4677b4814836239f90eef3097fa5960296ddd25 100644 --- a/demo/src/main/java/top/limitart/redefinable/HelloRedefine.java +++ b/demo/src/main/java/top/limitart/demo/redefinable/HelloRedefine.java @@ -1,4 +1,4 @@ -package top.limitart.redefinable; +package top.limitart.demo.redefinable; public class HelloRedefine { public void hello(){ diff --git a/demo/src/main/java/top/limitart/redefinable/RedefinableDemo.java b/demo/src/main/java/top/limitart/demo/redefinable/RedefinableDemo.java similarity index 75% rename from demo/src/main/java/top/limitart/redefinable/RedefinableDemo.java rename to demo/src/main/java/top/limitart/demo/redefinable/RedefinableDemo.java index 378b2d9fe0b925a78cf02c149a9a17be76c4dffc..a20c01ddd8db6c7957fb2507661658a20d2c404e 100644 --- a/demo/src/main/java/top/limitart/redefinable/RedefinableDemo.java +++ b/demo/src/main/java/top/limitart/demo/redefinable/RedefinableDemo.java @@ -1,6 +1,7 @@ -package top.limitart.redefinable; +package top.limitart.demo.redefinable; import java.io.File; +import top.limitart.redefinable.RedefinableApplication; public class RedefinableDemo { public static void main(String[] args) throws Exception { diff --git a/demo/src/main/java/top/limitart/redefinable/ScriptEntrance.java b/demo/src/main/java/top/limitart/demo/redefinable/ScriptEntrance.java similarity index 78% rename from demo/src/main/java/top/limitart/redefinable/ScriptEntrance.java rename to demo/src/main/java/top/limitart/demo/redefinable/ScriptEntrance.java index b976e91f1ce6b5afe8e2908e7d2b070a861e3ce2..f6187c6d6c7030bd49e8f8a81d16d66536b2171c 100644 --- a/demo/src/main/java/top/limitart/redefinable/ScriptEntrance.java +++ b/demo/src/main/java/top/limitart/demo/redefinable/ScriptEntrance.java @@ -1,4 +1,7 @@ -package top.limitart.redefinable; +package top.limitart.demo.redefinable; + +import top.limitart.redefinable.RedefinableApplicationContext; +import top.limitart.redefinable.RedefinableModule; public class ScriptEntrance extends RedefinableModule { private HelloRedefine helloRedefine = new HelloRedefine(); diff --git a/demo/src/main/java/top/limitart/demo/rpc/HelloRpc.java b/demo/src/main/java/top/limitart/demo/rpc/HelloRpc.java new file mode 100644 index 0000000000000000000000000000000000000000..bcc21195870a8455de0710467d3c527f259b9027 --- /dev/null +++ b/demo/src/main/java/top/limitart/demo/rpc/HelloRpc.java @@ -0,0 +1,9 @@ +package top.limitart.demo.rpc; + +import top.limitart.rpc.srvcommon.RPCService; + +@RPCService(provider = "limitart") +public interface HelloRpc { + + int plus(int a, int b) throws Exception; +} diff --git a/demo/src/main/java/top/limitart/demo/rpc/HelloRpcImpl.java b/demo/src/main/java/top/limitart/demo/rpc/HelloRpcImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..8596d2dbe6749185fbd5d4262cb9b4666fdde4ba --- /dev/null +++ b/demo/src/main/java/top/limitart/demo/rpc/HelloRpcImpl.java @@ -0,0 +1,9 @@ +package top.limitart.demo.rpc; + +public class HelloRpcImpl implements HelloRpc { + + @Override + public int plus(int a, int b) { + return a + b; + } +} diff --git a/demo/src/main/java/top/limitart/demo/rpc/RPCServiceCenterDemo.java b/demo/src/main/java/top/limitart/demo/rpc/RPCServiceCenterDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..babb37f99272f2c708439b01aab14052c192f58d --- /dev/null +++ b/demo/src/main/java/top/limitart/demo/rpc/RPCServiceCenterDemo.java @@ -0,0 +1,11 @@ +package top.limitart.demo.rpc; + +import top.limitart.rpc.RPCServiceCenter; + +public class RPCServiceCenterDemo { + + public static void main(String[] args) throws Exception { + RPCServiceCenter center = new RPCServiceCenter(9999); + center.run(args); + } +} diff --git a/demo/src/main/java/top/limitart/demo/rpc/RPCServiceConsumerDemo.java b/demo/src/main/java/top/limitart/demo/rpc/RPCServiceConsumerDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..d82e677959856fc4ccdfa860fa408fb11e3a5c24 --- /dev/null +++ b/demo/src/main/java/top/limitart/demo/rpc/RPCServiceConsumerDemo.java @@ -0,0 +1,22 @@ +package top.limitart.demo.rpc; + +import top.limitart.rpc.srvconsumer.RPCServiceConsumer; + +public class RPCServiceConsumerDemo { + + public static void main(String[] args) throws Exception { + RPCServiceConsumer consumer = new RPCServiceConsumer("test_consumer", "127.0.0.1", 9999, + "top.limitart.demo.rpc"); + consumer.run(args); + HelloRpc proxy = consumer.createProxy(HelloRpc.class); + int count = 0; + while (true) { + try{ + int plus = proxy.plus(++count, 1); + System.out.println("rpc result:" + plus); + }catch (Exception e){ + e.printStackTrace(); + } + } + } +} diff --git a/demo/src/main/java/top/limitart/demo/rpc/RPCServiceProviderDemo.java b/demo/src/main/java/top/limitart/demo/rpc/RPCServiceProviderDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..9e75ae0fbdd12e89d8b167b1a33100d3e16900b8 --- /dev/null +++ b/demo/src/main/java/top/limitart/demo/rpc/RPCServiceProviderDemo.java @@ -0,0 +1,12 @@ +package top.limitart.demo.rpc; + +import top.limitart.rpc.srvprovider.RPCServiceProvider; + +public class RPCServiceProviderDemo { + + public static void main(String[] args) throws Exception { + RPCServiceProvider provider = new RPCServiceProvider("test_provider", "127.0.0.1", 9999, + new String[]{"top.limitart.demo.rpc"}, new String[]{"top.limitart.demo.rpc"}); + provider.run(args); + } +} diff --git a/demo/src/main/java/top/limitart/script/AutoReloadScriptDemo.java b/demo/src/main/java/top/limitart/demo/script/AutoReloadScriptDemo.java similarity index 71% rename from demo/src/main/java/top/limitart/script/AutoReloadScriptDemo.java rename to demo/src/main/java/top/limitart/demo/script/AutoReloadScriptDemo.java index ec7400ccc89667974d428df8157d48c74986d3cd..2db1dfb88c3e1e7169e3c8492dbb20618c924e92 100644 --- a/demo/src/main/java/top/limitart/script/AutoReloadScriptDemo.java +++ b/demo/src/main/java/top/limitart/demo/script/AutoReloadScriptDemo.java @@ -13,19 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package top.limitart.script; +package top.limitart.demo.script; import java.io.IOException; +import top.limitart.script.FileScriptLoader; +import top.limitart.script.ScriptConstructException; +import top.limitart.script.ScriptKeyDuplicatedException; +import top.limitart.script.ScriptNotExistException; /** @author hank */ public class AutoReloadScriptDemo { public static void main(String[] args) throws InstantiationException, IllegalAccessException, IOException, ScriptConstructException, - ScriptNotExistException, ScriptKeyDuplicatedException, InterruptedException { + ScriptNotExistException, ScriptKeyDuplicatedException, InterruptedException { FileScriptLoader loader = new FileScriptLoader<>("./demo/script", 5); while (true) { Thread.sleep(1000); - HelloScript script = loader.getScript(1); + top.limitart.demo.script.HelloScript script = loader.getScript(1); script.sayHello(); } } diff --git a/demo/src/main/java/top/limitart/script/HelloScript.java b/demo/src/main/java/top/limitart/demo/script/HelloScript.java similarity index 91% rename from demo/src/main/java/top/limitart/script/HelloScript.java rename to demo/src/main/java/top/limitart/demo/script/HelloScript.java index f0882f014ef65e5a7805e3ce046a2269a60288a3..1dc448de3337d4cb4939c9072e20fe21bae67e27 100644 --- a/demo/src/main/java/top/limitart/script/HelloScript.java +++ b/demo/src/main/java/top/limitart/demo/script/HelloScript.java @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package top.limitart.script; +package top.limitart.demo.script; + +import top.limitart.script.Script; /** * 脚本引用测试 diff --git a/demo/src/main/java/top/limitart/script/ScriptSourceDemo.java b/demo/src/main/java/top/limitart/demo/script/ScriptSourceDemo.java similarity index 97% rename from demo/src/main/java/top/limitart/script/ScriptSourceDemo.java rename to demo/src/main/java/top/limitart/demo/script/ScriptSourceDemo.java index 737d9cddfb4361d9c3f776750144bb50eba23ab8..fdc07b02b7177689b613ddd750568275a8f68484 100644 --- a/demo/src/main/java/top/limitart/script/ScriptSourceDemo.java +++ b/demo/src/main/java/top/limitart/demo/script/ScriptSourceDemo.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package top.limitart.script; +package top.limitart.demo.script; /** * 脚本编译测试 diff --git a/demo/src/main/java/top/limitart/singleton/SingletonA.java b/demo/src/main/java/top/limitart/demo/singleton/SingletonA.java similarity index 41% rename from demo/src/main/java/top/limitart/singleton/SingletonA.java rename to demo/src/main/java/top/limitart/demo/singleton/SingletonA.java index ddb8b96ad554275916fc0ff046e1655d7d8c69a1..4b3935beb6056a8b53b9c24e4bc84ec90d91c14f 100644 --- a/demo/src/main/java/top/limitart/singleton/SingletonA.java +++ b/demo/src/main/java/top/limitart/demo/singleton/SingletonA.java @@ -1,8 +1,12 @@ -package top.limitart.singleton; +package top.limitart.demo.singleton; + +import top.limitart.singleton.Ref; +import top.limitart.singleton.Singleton; @Singleton public class SingletonA { - @Ref SingletonB singletonB; + @Ref + SingletonB singletonB; public void say() { System.out.println(singletonB); diff --git a/demo/src/main/java/top/limitart/singleton/SingletonB.java b/demo/src/main/java/top/limitart/demo/singleton/SingletonB.java similarity index 45% rename from demo/src/main/java/top/limitart/singleton/SingletonB.java rename to demo/src/main/java/top/limitart/demo/singleton/SingletonB.java index 287d7a9af4b4a69c25886f738d62b90ace0baa17..989597ae57351ec7303a93a78a92eb4c3d5ea590 100644 --- a/demo/src/main/java/top/limitart/singleton/SingletonB.java +++ b/demo/src/main/java/top/limitart/demo/singleton/SingletonB.java @@ -1,10 +1,16 @@ -package top.limitart.singleton; +package top.limitart.demo.singleton; + +import top.limitart.singleton.Ref; +import top.limitart.singleton.Singleton; @Singleton public class SingletonB { - @Ref SingletonA singletonA; - @Ref SingletonC singletonC; - @Ref SingletonD singletonD; + @Ref + SingletonA singletonA; + @Ref + SingletonC singletonC; + @Ref + SingletonD singletonD; public void say() { System.out.println(singletonA); diff --git a/demo/src/main/java/top/limitart/singleton/SingletonC.java b/demo/src/main/java/top/limitart/demo/singleton/SingletonC.java similarity index 85% rename from demo/src/main/java/top/limitart/singleton/SingletonC.java rename to demo/src/main/java/top/limitart/demo/singleton/SingletonC.java index b0eec7636a19dc3a8e3c98a55c8f7f8e2dce54ee..a3a106c1132cc1ea952d506a784d1e44fe63e88e 100644 --- a/demo/src/main/java/top/limitart/singleton/SingletonC.java +++ b/demo/src/main/java/top/limitart/demo/singleton/SingletonC.java @@ -16,12 +16,16 @@ * */ -package top.limitart.singleton; +package top.limitart.demo.singleton; + +import top.limitart.singleton.Ref; +import top.limitart.singleton.Singleton; /** Created by Hank on 2018/12/11 */ @Singleton public class SingletonC { - @Ref SingletonC singletonC; + @Ref + SingletonC singletonC; @Ref public SingletonC(SingletonA singletonA, SingletonB singletonB) { diff --git a/demo/src/main/java/top/limitart/singleton/SingletonD.java b/demo/src/main/java/top/limitart/demo/singleton/SingletonD.java similarity index 89% rename from demo/src/main/java/top/limitart/singleton/SingletonD.java rename to demo/src/main/java/top/limitart/demo/singleton/SingletonD.java index 0dd180eb707b4f5f96e977e8a3608abbee498613..a84dd773c99e0b0016e1f8a0fbc0ce69f6277f50 100644 --- a/demo/src/main/java/top/limitart/singleton/SingletonD.java +++ b/demo/src/main/java/top/limitart/demo/singleton/SingletonD.java @@ -16,7 +16,10 @@ * */ -package top.limitart.singleton; +package top.limitart.demo.singleton; + +import top.limitart.singleton.Ref; +import top.limitart.singleton.Singleton; /** Created by Hank on 2018/12/11 */ @Singleton diff --git a/demo/src/main/java/top/limitart/singleton/SingletonDemo.java b/demo/src/main/java/top/limitart/demo/singleton/SingletonDemo.java similarity index 50% rename from demo/src/main/java/top/limitart/singleton/SingletonDemo.java rename to demo/src/main/java/top/limitart/demo/singleton/SingletonDemo.java index 47b091b6267704dc4c68c8c33d080f8f413d6c0f..8a99eb1a518d2c5414ee07809a08a2e345d2dd48 100644 --- a/demo/src/main/java/top/limitart/singleton/SingletonDemo.java +++ b/demo/src/main/java/top/limitart/demo/singleton/SingletonDemo.java @@ -1,9 +1,18 @@ -package top.limitart.singleton; +package top.limitart.demo.singleton; + +import top.limitart.demo.singleton.SingletonA; +import top.limitart.demo.singleton.SingletonB; +import top.limitart.demo.singleton.SingletonC; +import top.limitart.singleton.Ref; +import top.limitart.singleton.Singletons; public class SingletonDemo { - @Ref SingletonB singletonB; - @Ref SingletonA singletonA; - @Ref SingletonC singletonC; + @Ref + SingletonB singletonB; + @Ref + SingletonA singletonA; + @Ref + SingletonC singletonC; public void say() { singletonB.say(); diff --git a/demo/src/main/java/top/limitart/game/htb/HTBDemo.java b/demo/src/main/java/top/limitart/game/htb/HTBDemo.java deleted file mode 100644 index fc20cbdb6c7806c11811a96fa527f692ef556d5d..0000000000000000000000000000000000000000 --- a/demo/src/main/java/top/limitart/game/htb/HTBDemo.java +++ /dev/null @@ -1,63 +0,0 @@ -package top.limitart.game.htb; - -import top.limitart.game.FPSBootstrap; -import top.limitart.game.FPSLimiter; -import top.limitart.game.FPSRunner; -import top.limitart.game.SimpleFPSRunner; -import top.limitart.game.htb.event.RRoleStartHandleEvent; -import top.limitart.game.htb.event.TBattleTurnEndEvent; - -/** - * @author hank - * @version 2019/6/15 0015 16:42 - */ -public class HTBDemo { - public static void main(String[] args) { - FPSBootstrap bootstrap = new FPSBootstrap("htb-room", 4); - HTBTable table = createTable(); - bootstrap.add(table, () -> {}); - FPSLimiter limiter = new FPSLimiter(1000); - bootstrap.add( - new SimpleFPSRunner() { - @Override - public void onUpdate() throws Exception { - limiter.tick( - () -> { - for (FPSRunner fpsRunner : bootstrap) { - if (fpsRunner instanceof HTBTable) { - HTBTable t = (HTBTable) fpsRunner; - if (t.isEnd()) { - t.where().execute(() -> bootstrap.remove(t.uniqueID())); - } - } - } - }); - } - - @Override - public long uniqueID() { - return -1; - } - }, - () -> {}); - } - - private static HTBTable createTable() { - HTBRoleDemo role1 = new HTBRoleDemo(1, 20); - HTBRoleDemo role2 = new HTBRoleDemo(2, 30); - HTBTableDemo table = new HTBTableDemo(1, role1, role2); - table.listen( - RRoleStartHandleEvent.class, - e -> { - System.out.println(e.getRole().uniqueID() + " " + "start!!"); - }); - table.listen( - TBattleTurnEndEvent.class, - e -> { - if (e.currentTurn() >= 4) { - e.table().end(); - } - }); - return table; - } -} diff --git a/demo/src/main/java/top/limitart/game/htb/HTBRoleDemo.java b/demo/src/main/java/top/limitart/game/htb/HTBRoleDemo.java deleted file mode 100644 index b7ea00a512c061969a55436e66a5439c3a0ed20d..0000000000000000000000000000000000000000 --- a/demo/src/main/java/top/limitart/game/htb/HTBRoleDemo.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * * Copyright (c) 2016-present The Limitart Project - * * - * * 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 - * * - * * 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 top.limitart.game.htb; - -/** Created by Hank on 2019/6/30 */ -public class HTBRoleDemo extends HTBRole { - private long id; - private int speed; - - public HTBRoleDemo(long id, int speed) { - this.id = id; - this.speed = speed; - } - - @Override - public int speed() { - return this.speed; - } - - @Override - public boolean ready() { - return true; - } - - @Override - public long uniqueID() { - return this.id; - } -} diff --git a/demo/src/main/java/top/limitart/game/htb/HTBTableDemo.java b/demo/src/main/java/top/limitart/game/htb/HTBTableDemo.java deleted file mode 100644 index bc5dde0c12956e1f9bc3328ed4b6d0637cf64365..0000000000000000000000000000000000000000 --- a/demo/src/main/java/top/limitart/game/htb/HTBTableDemo.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * - * * Copyright (c) 2016-present The Limitart Project - * * - * * 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 - * * - * * 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 top.limitart.game.htb; - -/** Created by Hank on 2019/6/30 */ -public class HTBTableDemo extends HTBTable { - public HTBTableDemo(long uniqueID, HTBRoleDemo... roles) { - super(uniqueID); - for (HTBRoleDemo role : roles) { - addRole(role); - } - } -} diff --git a/demo/src/main/java/top/limitart/game/scene8/SceneDemo.java b/demo/src/main/java/top/limitart/game/scene8/SceneDemo.java deleted file mode 100644 index 0b289cd78bf3ef7d64f1d34ac5813c82166706c0..0000000000000000000000000000000000000000 --- a/demo/src/main/java/top/limitart/game/scene8/SceneDemo.java +++ /dev/null @@ -1,81 +0,0 @@ -package top.limitart.game.scene8; - -import top.limitart.game.FPSBootstrap; - -/** - * @author hank - * @version 2019/6/1 0001 17:15 - */ -public class SceneDemo { - private static SceneCore core; - - public static void main(String[] args) throws InterruptedException { - core = - new WalkableScene(120, 80, 4, 4, 6, 6) { - @Override - protected void beforeObjAdd(WalkableSceneObj obj) { - super.beforeObjAdd(obj); - System.out.println("beforeObjAdd:" + obj); - } - - @Override - protected void onObjAdd(WalkableSceneObj obj) { - super.onObjAdd(obj); - System.out.println("onObjAdd:" + obj); - for (int i = 0; i < 100; i++) { - obj.changePos(obj.x() + 1, obj.y() + 1); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - @Override - protected void onObjUpdate(WalkableSceneObj obj) { - // System.out.println("onObjUpdate:" + obj); - } - - @Override - protected void beforeObjRemove(WalkableSceneObj obj) { - System.out.println("beforeObjRemove:" + obj); - } - - @Override - protected void onObjRemove(WalkableSceneObj obj) { - super.onObjRemove(obj); - System.out.println("onObjRemove:" + obj); - } - - @Override - protected void onAddToArea(WalkableScene.Area area, WalkableSceneObj obj) { - System.out.println(String.format("onAddToArea area:%s,obj:%s", area, obj)); - } - - @Override - protected void onRemoveFromArea(WalkableScene.Area area, WalkableSceneObj obj) { - System.out.println(String.format("onRemoveFromArea area:%s,obj:%s", area, obj)); - } - - @Override - public long uniqueID() { - return 1; - } - }; - FPSBootstrap bootstrap = new FPSBootstrap("scene-demo", 4); - bootstrap.add( - core, - () -> { - SceneItem a = new SceneItem(); - a.changePos(20, 40); - core.add(a); - // a.destroy(); - }); - } - - public static class SceneItem extends WalkableSceneObj { - @Override - public void onUpdate() {} - } -} diff --git a/eclipse-java-google-style.xml b/eclipse-java-google-style.xml new file mode 100644 index 0000000000000000000000000000000000000000..096e983b2e20c76c6953851300cb89eeb67d23a9 --- /dev/null +++ b/eclipse-java-google-style.xml @@ -0,0 +1,337 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fastmq/common/pom.xml b/fastmq/common/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..5c084c77eade38a63cb8146cc1796f4fd5060868 --- /dev/null +++ b/fastmq/common/pom.xml @@ -0,0 +1,21 @@ + + + + limitart-fastmq + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-fastmq-common + + + + ${project.groupId} + limitart-net + ${project.version} + + + \ No newline at end of file diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/SessionParamConst.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/SessionParamConst.java new file mode 100644 index 0000000000000000000000000000000000000000..9938e60c291480b62f31439a5e7976320f40fce4 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/SessionParamConst.java @@ -0,0 +1,6 @@ +package top.limitart.fastmq.common; + +public class SessionParamConst { + public static int ZONE = 1; + public static int HEART_BEAT = 2; +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/BinaryRequest.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/BinaryRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..f4e0343e406d472b70162ef6bd00a99285a58d41 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/BinaryRequest.java @@ -0,0 +1,7 @@ +package top.limitart.fastmq.common.binary; + +import top.limitart.net.binary.BinaryRequestParam; + +public class BinaryRequest extends BinaryRequestParam { + +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/Consts.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/Consts.java new file mode 100644 index 0000000000000000000000000000000000000000..a1ce336142665f26548d9a3c0fbb2b6d5f8f6493 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/Consts.java @@ -0,0 +1,19 @@ +package top.limitart.fastmq.common.binary; + +public class Consts { + + public static final short REQ_REGISTER_ZONE_MSG = 1; + public static final short RES_REGISTER_ZONE_MSG = REQ_REGISTER_ZONE_MSG + 1; + public static final short RES_CUSTOMER_READY_MSG = RES_REGISTER_ZONE_MSG + 1; + public static final short RES_ZONE_CLAIM_MSG = RES_CUSTOMER_READY_MSG + 1; + public static final short REQ_HEART_BEAT = RES_ZONE_CLAIM_MSG + 1; + public static final short RES_HEART_BEAT = REQ_HEART_BEAT + 1; + public static final short RES_PIPELINE_ESTABLISHED = RES_HEART_BEAT + 1; + public static final short REQ_PULL = RES_PIPELINE_ESTABLISHED + 1; + public static final short RES_PULL = REQ_PULL + 1; + public static final short REQ_PUSH_MSG_TO_PIPELINE = RES_PULL + 1; + public static final short REQ_BROADCAST_MSG_TO_PIPELINE = REQ_PUSH_MSG_TO_PIPELINE + 1; + public static final short REQ_PUSH_MSG_TO_PIPELINE_WITH_TAGS = REQ_BROADCAST_MSG_TO_PIPELINE + 1; + public static final short REQ_BROADCAST_MSG_TO_PIPELINE_WITH_TAGS = REQ_PUSH_MSG_TO_PIPELINE_WITH_TAGS + 1; + public static final short RES_PUSH_MSG_RESULT = REQ_BROADCAST_MSG_TO_PIPELINE_WITH_TAGS + 1; +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqBroadcastMsgToPipelineMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqBroadcastMsgToPipelineMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..770fa273a462d73970cbd839133d66bfe0372687 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqBroadcastMsgToPipelineMsg.java @@ -0,0 +1,13 @@ +package top.limitart.fastmq.common.binary; + +import top.limitart.net.binary.BinaryMessage; + +public class ReqBroadcastMsgToPipelineMsg extends BinaryMessage { + + public byte[] bytes; + + @Override + public short id() { + return Consts.REQ_BROADCAST_MSG_TO_PIPELINE; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqBroadcastMsgToPipelineWithTagsMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqBroadcastMsgToPipelineWithTagsMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..9f55fe77d666848c7ced51200ed187be4cb9c211 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqBroadcastMsgToPipelineWithTagsMsg.java @@ -0,0 +1,15 @@ +package top.limitart.fastmq.common.binary; + +import java.util.List; +import top.limitart.net.binary.BinaryMessage; + +public class ReqBroadcastMsgToPipelineWithTagsMsg extends BinaryMessage { + + public List tags; + public byte[] bytes; + + @Override + public short id() { + return Consts.REQ_BROADCAST_MSG_TO_PIPELINE_WITH_TAGS; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqCustomerReadyMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqCustomerReadyMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..3a281e841e38f38763ea185aa4213fa3d3b7ba9a --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqCustomerReadyMsg.java @@ -0,0 +1,16 @@ +package top.limitart.fastmq.common.binary; + +import top.limitart.net.binary.BinaryMessage; + +public class ReqCustomerReadyMsg extends BinaryMessage { + + //集群编号 + public String zone; + //TOKEN + public String token; + + @Override + public short id() { + return Consts.RES_CUSTOMER_READY_MSG; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqHeartBeatMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqHeartBeatMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..578a9d674c37c4d7465ba5ee4e88e50109792bd9 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqHeartBeatMsg.java @@ -0,0 +1,11 @@ +package top.limitart.fastmq.common.binary; + +import top.limitart.net.binary.BinaryMessage; + +public class ReqHeartBeatMsg extends BinaryMessage { + public static final ReqHeartBeatMsg INSTANCE = new ReqHeartBeatMsg(); + @Override + public short id() { + return Consts.REQ_HEART_BEAT; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqPullMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqPullMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..e2828a007960f74b6d9cdb909a0fc2f233fe1038 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqPullMsg.java @@ -0,0 +1,12 @@ +package top.limitart.fastmq.common.binary; + +import top.limitart.net.binary.BinaryMessage; + +public class ReqPullMsg extends BinaryMessage { + public int pullNum; + + @Override + public short id() { + return Consts.REQ_PULL; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqPushMsgToPipelineMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqPushMsgToPipelineMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..2f65f005c3f9d27c42241ce0744967b38fe6dda6 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqPushMsgToPipelineMsg.java @@ -0,0 +1,14 @@ +package top.limitart.fastmq.common.binary; + +import top.limitart.net.binary.BinaryMessage; + +public class ReqPushMsgToPipelineMsg extends BinaryMessage { + + public String zone; + public byte[] bytes; + + @Override + public short id() { + return Consts.REQ_PUSH_MSG_TO_PIPELINE; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqPushMsgToPipelineWithTagsMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqPushMsgToPipelineWithTagsMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..2dabbdabf24bfed42e29d99f5e2df92d782c1853 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqPushMsgToPipelineWithTagsMsg.java @@ -0,0 +1,15 @@ +package top.limitart.fastmq.common.binary; + +import java.util.List; +import top.limitart.net.binary.BinaryMessage; + +public class ReqPushMsgToPipelineWithTagsMsg extends BinaryMessage { + + public List tags; + public byte[] bytes; + + @Override + public short id() { + return Consts.REQ_PUSH_MSG_TO_PIPELINE_WITH_TAGS; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqRegisterZoneMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqRegisterZoneMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..9f81bc9d19f9eaec8d4eb43697260d024817920f --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqRegisterZoneMsg.java @@ -0,0 +1,17 @@ +package top.limitart.fastmq.common.binary; + +import java.util.List; +import top.limitart.net.binary.BinaryMessage; + +public class ReqRegisterZoneMsg extends BinaryMessage { + + //集群编号 + public String zone; + //标签 + public List tags; + + @Override + public short id() { + return Consts.REQ_REGISTER_ZONE_MSG; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqZoneClaimMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqZoneClaimMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..3bd3ef8150c96a19f74314fc972b06dd41d510d8 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ReqZoneClaimMsg.java @@ -0,0 +1,14 @@ +package top.limitart.fastmq.common.binary; + + +import top.limitart.net.binary.BinaryMessage; + +public class ReqZoneClaimMsg extends BinaryMessage { + + public static final ReqZoneClaimMsg INSTANCE = new ReqZoneClaimMsg(); + + @Override + public short id() { + return Consts.RES_ZONE_CLAIM_MSG; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResHeartBeatMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResHeartBeatMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..65d72bd63a90c0163c7ba511ac019d8217976929 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResHeartBeatMsg.java @@ -0,0 +1,11 @@ +package top.limitart.fastmq.common.binary; + +import top.limitart.net.binary.BinaryMessage; + +public class ResHeartBeatMsg extends BinaryMessage { + public static final ResHeartBeatMsg INSTANCE = new ResHeartBeatMsg(); + @Override + public short id() { + return Consts.RES_HEART_BEAT; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResPipelineEstablishedMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResPipelineEstablishedMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..0c5632f7bbcd91ca010b5710db9b27fd5145b47b --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResPipelineEstablishedMsg.java @@ -0,0 +1,12 @@ +package top.limitart.fastmq.common.binary; + +import top.limitart.net.binary.BinaryMessage; + +public class ResPipelineEstablishedMsg extends BinaryMessage { + public static final ResPipelineEstablishedMsg INSTANCE = new ResPipelineEstablishedMsg(); + + @Override + public short id() { + return Consts.RES_PIPELINE_ESTABLISHED; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResPullMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResPullMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..63e7f4bbc750cf46477f658a1162b31201f78a0c --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResPullMsg.java @@ -0,0 +1,14 @@ +package top.limitart.fastmq.common.binary; + +import java.util.LinkedList; +import java.util.List; +import top.limitart.net.binary.BinaryMessage; + +public class ResPullMsg extends BinaryMessage { + public List msgs = new LinkedList<>(); + + @Override + public short id() { + return Consts.RES_PULL; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResPushMsgResultMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResPushMsgResultMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..452a2d7dc590345f1a403bc7b527df969b46c722 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResPushMsgResultMsg.java @@ -0,0 +1,28 @@ +package top.limitart.fastmq.common.binary; + +import top.limitart.net.binary.BinaryByteMessage; + +public class ResPushMsgResultMsg extends BinaryByteMessage { + + public static final ResPushMsgResultMsg SUCCESS = new ResPushMsgResultMsg(); + public static final ResPushMsgResultMsg NO_ZONE = new ResPushMsgResultMsg(1); + public static final ResPushMsgResultMsg ZONE_EMPTY = new ResPushMsgResultMsg(2); + public static final ResPushMsgResultMsg ZONE_NOT_ACTIVE = new ResPushMsgResultMsg(3); + public static final ResPushMsgResultMsg ZONE_HAS_NO_BUFFER = new ResPushMsgResultMsg(4); + public static final ResPushMsgResultMsg ZONE_BUFFER_HAS_NO_CAPACITY = new ResPushMsgResultMsg(5); + public static final ResPushMsgResultMsg TAG_EMPTY = new ResPushMsgResultMsg(6); + public static final ResPushMsgResultMsg CAN_NOT_FIND_ZONE_BY_TAGS = new ResPushMsgResultMsg(7); + public static final ResPushMsgResultMsg NO_MSG_CONTENT = new ResPushMsgResultMsg(8); + public ResPushMsgResultMsg(int i) { + super((byte) i); + } + + public ResPushMsgResultMsg() { + super(); + } + + @Override + public short id() { + return Consts.RES_PUSH_MSG_RESULT; + } +} diff --git a/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResRegisterZoneMsg.java b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResRegisterZoneMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..a08d4c2375bd7576e4d015042ff4aba670668d22 --- /dev/null +++ b/fastmq/common/src/main/java/top/limitart/fastmq/common/binary/ResRegisterZoneMsg.java @@ -0,0 +1,17 @@ +package top.limitart.fastmq.common.binary; + +import top.limitart.net.binary.BinaryMessage; + +public class ResRegisterZoneMsg extends BinaryMessage { + + /** + * 0 成功 1失败 + */ + public byte code; + public String token; + + @Override + public short id() { + return Consts.RES_REGISTER_ZONE_MSG; + } +} diff --git a/fastmq/consumer/pom.xml b/fastmq/consumer/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..dc76891debf94a6c13f176c567bbcc105ec5a61e --- /dev/null +++ b/fastmq/consumer/pom.xml @@ -0,0 +1,26 @@ + + + + limitart-fastmq + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-fastmq-consumer + + + + ${project.groupId} + limitart-net + ${project.version} + + + ${project.groupId} + limitart-fastmq-common + ${project.version} + + + \ No newline at end of file diff --git a/fastmq/consumer/src/main/java/top/limitart/fastmq/consumer/ConsumerMsgHandler.java b/fastmq/consumer/src/main/java/top/limitart/fastmq/consumer/ConsumerMsgHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..a66eae5e198d0d28f35d808c0c06fee456c98947 --- /dev/null +++ b/fastmq/consumer/src/main/java/top/limitart/fastmq/consumer/ConsumerMsgHandler.java @@ -0,0 +1,5 @@ +package top.limitart.fastmq.consumer; + +public interface ConsumerMsgHandler { + void onMsg(byte[] msg); +} diff --git a/fastmq/consumer/src/main/java/top/limitart/fastmq/consumer/MQConsumerBinaryClient.java b/fastmq/consumer/src/main/java/top/limitart/fastmq/consumer/MQConsumerBinaryClient.java new file mode 100644 index 0000000000000000000000000000000000000000..4b5fe8181e80c85980ccf4693f44e273eab1c000 --- /dev/null +++ b/fastmq/consumer/src/main/java/top/limitart/fastmq/consumer/MQConsumerBinaryClient.java @@ -0,0 +1,252 @@ +package top.limitart.fastmq.consumer; + +import io.netty.channel.EventLoop; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import top.limitart.base.ApplicationBootstrap; +import top.limitart.base.Conditions; +import top.limitart.collections.ImmutableList; +import top.limitart.concurrent.TaskQueue; +import top.limitart.fastmq.common.binary.BinaryRequest; +import top.limitart.fastmq.common.binary.ReqCustomerReadyMsg; +import top.limitart.fastmq.common.binary.ReqHeartBeatMsg; +import top.limitart.fastmq.common.binary.ReqPullMsg; +import top.limitart.fastmq.common.binary.ReqRegisterZoneMsg; +import top.limitart.fastmq.common.binary.ResHeartBeatMsg; +import top.limitart.fastmq.common.binary.ResPipelineEstablishedMsg; +import top.limitart.fastmq.common.binary.ResPullMsg; +import top.limitart.fastmq.common.binary.ResRegisterZoneMsg; +import top.limitart.fastmq.common.binary.ReqZoneClaimMsg; +import top.limitart.mapping.Mapper; +import top.limitart.mapping.Request; +import top.limitart.mapping.Router; +import top.limitart.net.AddressPair; +import top.limitart.net.NettySession; +import top.limitart.net.Session; +import top.limitart.net.binary.BinaryEndPoint; +import top.limitart.net.binary.BinaryMessage; +import top.limitart.net.binary.BinaryRequestParam; +import top.limitart.util.FileUtil; +import top.limitart.util.StringUtil; +import top.limitart.util.TimeUtil; + +public class MQConsumerBinaryClient extends ApplicationBootstrap { + + private static final Logger LOGGER = LoggerFactory.getLogger(MQConsumerBinaryClient.class); + private static final String TOKEN_FILE = "pipeline-token.tmp"; + private static final long PULL_REQUEST_INTERVAL = TimeUnit.SECONDS.toMillis(5); + private BinaryEndPoint client; + private ConsumerBinaryHandler clientHandler; + private AddressPair remoteAddress; + private String token; + private String zone; + private List tags; + private volatile long lastReceiveMsgTime; + private TaskQueue msgThread = TaskQueue.create("msg-consume"); + private ConsumerMsgHandler msgHandler; + private Session session; + private boolean handling = false; + + public MQConsumerBinaryClient( + String remoteIp, int port, String zone, List tags, ConsumerMsgHandler msgHandler) + throws Exception { + this.remoteAddress = AddressPair.withIP(remoteIp, port); + this.zone = zone; + if (tags != null) { + this.tags = ImmutableList.of(tags); + } else { + this.tags = Collections.emptyList(); + } + this.msgHandler = Conditions.notNull(msgHandler); + this.clientHandler = new ConsumerBinaryHandler(); + Router router = + Router.empty(BinaryMessage.class, BinaryRequest.class) + .registerMapperClass(ConsumerBinaryHandler.class, (c) -> this.clientHandler); + this.client = + BinaryEndPoint.client() + .router(router) + .onMessageIn((m, s, r) -> onMessageIn(m, s, r)) + // .timeoutSeconds(5) + .autoReconnect(10) + .onConnected((s, b) -> onConnected(s, b)) + .build(); + File file = new File("." + File.separator + TOKEN_FILE); + if (file.exists()) { + byte[] content = FileUtil.readFile(file); + this.token = new String(content, StandardCharsets.UTF_8); + LOGGER.info("read token on disk {}", this.token); + } else { + LOGGER.info("can not find token on disk , ignore it!"); + } + msgThread.scheduleAtFixedRate(() -> secondTick(), 0, 1, TimeUnit.SECONDS); + } + + private void secondTick() { + if (TimeUtil.now() - lastReceiveMsgTime > PULL_REQUEST_INTERVAL && !handling) { + requestPullMsg(); + } + } + + private void requestPullMsg() { + if (session != null) { + ReqPullMsg msg = new ReqPullMsg(); + msg.pullNum = 20; // TODO + session.writeNow( + msg, + (b, t) -> { + if (b) { + this.lastReceiveMsgTime = TimeUtil.now(); + LOGGER.debug("send msg pull request to pipeline {}", session); + } + }); + } + } + + private void onMessageIn( + BinaryMessage msg, + NettySession session, + Router router) { + BinaryRequest binaryRequestParam = (BinaryRequest) router.contextInstance(); + // TODO 可能有一些参数加入上下文 + binaryRequestParam.session(session); + router.request(msg, binaryRequestParam, Router.MethodInvoker::invoke); + } + + private void onConnected(NettySession session, Boolean connectedOrNot) { + if (connectedOrNot) { + this.clientHandler.signOnPipeline(session); + } else { + this.session = null; + } + } + + @Override + protected void onStart(String[] args) throws Exception { + this.client.start(this.remoteAddress); + } + + @Override + protected void onDestroy(String[] args) { + msgThread.shutdown(); + } + + @Mapper + private class ConsumerBinaryHandler { + + /** + * 向Pipeline注册一个通道 + * + * @param session + */ + private void signOnPipeline(NettySession session) { + ReqRegisterZoneMsg msg = new ReqRegisterZoneMsg(); + msg.zone = MQConsumerBinaryClient.this.zone; + msg.tags = MQConsumerBinaryClient.this.tags; + session.writeNow( + msg, + (b, t) -> { + if (!b) { + LOGGER.error("sign on pipeline error", t); + } else { + LOGGER.info("sign on pipeline {} ...", remoteAddress); + } + }); + } + + /** + * pipeline回复注册结果 + * + * @param msg + * @param request + */ + public void onRegisterZoneResponse(@Request ResRegisterZoneMsg msg, BinaryRequest request) { + if (msg.code != 0) { + LOGGER.error("sign on pipeline {} fail!", remoteAddress); + return; + } + if (StringUtil.empty(msg.token)) { + LOGGER.error("pipeline {} response a empty token???", request.session()); + return; + } + MQConsumerBinaryClient.this.token = msg.token; + try { + FileUtil.writeNewFile( + "." + File.separator, + TOKEN_FILE, + MQConsumerBinaryClient.this.token.getBytes(StandardCharsets.UTF_8)); + LOGGER.info("write token {} on {}", msg.token, TOKEN_FILE); + } catch (IOException e) { + LOGGER.error("write token on disk error", e); + return; + } + LOGGER.info("sign on pipeline {} success!", remoteAddress); + ready(request.session()); + } + + private void ready(Session session) { + ReqCustomerReadyMsg msg = new ReqCustomerReadyMsg(); + msg.zone = MQConsumerBinaryClient.this.zone; + msg.token = MQConsumerBinaryClient.this.token; + session.writeNow( + msg, + (b, t) -> { + if (b) { + LOGGER.info("send ready to pipeline {}", session); + } else { + LOGGER.error("send ready to pipeline {} error", session); + } + }); + } + + /** + * pipeline通知消费者认领 + * + * @param msg + * @param request + */ + public void onNeedClaim(@Request ReqZoneClaimMsg msg, BinaryRequest request) { + if (StringUtil.empty(MQConsumerBinaryClient.this.token)) { + LOGGER.error("no old token to claim pipeline {}", remoteAddress); + return; + } + ready(request.session()); + } + + /** + * 与pipeline建立通道 + * + * @param msg + */ + public void onPipelineEstablished( + @Request ResPipelineEstablishedMsg msg, BinaryRequest request) { + MQConsumerBinaryClient.this.session = request.session(); + LOGGER.info("pipeline {} established!", remoteAddress); + } + + public void onHeartBeat(@Request ReqHeartBeatMsg msg, BinaryRequest request) { + request.session().writeNow(ResHeartBeatMsg.INSTANCE); + } + + public void onMsgPull(@Request ResPullMsg msg) { + msgThread.execute( + () -> { + handling = true; + for (byte[] bytes : msg.msgs) { + try { + MQConsumerBinaryClient.this.msgHandler.onMsg(bytes); + } catch (Exception e) { + LOGGER.error("msg handle error", e); + } + } + handling = false; + requestPullMsg(); + }); + } + } +} diff --git a/fastmq/pipeline/pom.xml b/fastmq/pipeline/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..e6740cd2a6da51fb63f382575bfdd6fdea3fd3e2 --- /dev/null +++ b/fastmq/pipeline/pom.xml @@ -0,0 +1,26 @@ + + + + limitart-fastmq + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-fastmq-pipeline + + + + ${project.groupId} + limitart-net + ${project.version} + + + ${project.groupId} + limitart-fastmq-common + ${project.version} + + + \ No newline at end of file diff --git a/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/MQPipelineBinaryServer.java b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/MQPipelineBinaryServer.java new file mode 100644 index 0000000000000000000000000000000000000000..a404566de0de3d99c3881534a4dccec326d739e9 --- /dev/null +++ b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/MQPipelineBinaryServer.java @@ -0,0 +1,386 @@ +package top.limitart.fastmq.pipeline; + +import io.netty.channel.EventLoop; +import io.netty.util.concurrent.ScheduledFuture; +import java.io.IOException; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import top.limitart.base.ApplicationBootstrap; +import top.limitart.fastmq.common.SessionParamConst; +import top.limitart.fastmq.common.binary.BinaryRequest; +import top.limitart.fastmq.common.binary.ReqBroadcastMsgToPipelineMsg; +import top.limitart.fastmq.common.binary.ReqBroadcastMsgToPipelineWithTagsMsg; +import top.limitart.fastmq.common.binary.ReqCustomerReadyMsg; +import top.limitart.fastmq.common.binary.ReqHeartBeatMsg; +import top.limitart.fastmq.common.binary.ReqPullMsg; +import top.limitart.fastmq.common.binary.ReqPushMsgToPipelineMsg; +import top.limitart.fastmq.common.binary.ReqPushMsgToPipelineWithTagsMsg; +import top.limitart.fastmq.common.binary.ReqRegisterZoneMsg; +import top.limitart.fastmq.common.binary.ResHeartBeatMsg; +import top.limitart.fastmq.common.binary.ResPipelineEstablishedMsg; +import top.limitart.fastmq.common.binary.ResPullMsg; +import top.limitart.fastmq.common.binary.ResPushMsgResultMsg; +import top.limitart.fastmq.common.binary.ResRegisterZoneMsg; +import top.limitart.fastmq.common.binary.ReqZoneClaimMsg; +import top.limitart.fastmq.pipeline.binary.PipelineBinarySession; +import top.limitart.fastmq.pipeline.core.Pipeline; +import top.limitart.fastmq.pipeline.core.Pipeline.States; +import top.limitart.fastmq.pipeline.core.PipelineRingBuffer; +import top.limitart.mapping.Mapper; +import top.limitart.mapping.Request; +import top.limitart.mapping.Router; +import top.limitart.net.AddressPair; +import top.limitart.net.NettySession; +import top.limitart.net.Session; +import top.limitart.net.binary.BinaryEndPoint; +import top.limitart.net.binary.BinaryMessage; +import top.limitart.net.binary.BinaryRequestParam; +import top.limitart.util.MathUtil; +import top.limitart.util.RandomUtil; +import top.limitart.util.StringUtil; + +public class MQPipelineBinaryServer extends ApplicationBootstrap { + + private static Logger LOGGER = LoggerFactory.getLogger(MQPipelineBinaryServer.class); + private Pipeline pipeline; + private BinaryEndPoint endPoint; + private PipelineBinaryHandler handler; + private int port; + private Map prs = new ConcurrentHashMap<>(); + + public MQPipelineBinaryServer(Pipeline pipeline, int port) throws Exception { + this.pipeline = pipeline; + this.port = port; + this.handler = new PipelineBinaryHandler(); + endPoint = + BinaryEndPoint.server() + .router( + Router.empty(BinaryMessage.class, BinaryRequest.class) + .registerMapperClass(PipelineBinaryHandler.class, c -> this.handler)) + .onConnected((s, b) -> onConnected(s, b)) + .onMessageIn((m, s, r) -> onMessageIn(m, s, r)) + .name("binary-pipeline-server") + // .onExceptionThrown((s, t) -> LOGGER.error("session " + s, t)) + .build(); + } + + private void onMessageIn( + BinaryMessage msg, + NettySession session, + Router router) { + BinaryRequest binaryRequestParam = (BinaryRequest) router.contextInstance(); + // TODO 可能有一些参数加入上下文 + binaryRequestParam.session(session); + router.request(msg, binaryRequestParam, Router.MethodInvoker::invoke); + } + + private void onConnected(NettySession session, Boolean connectedOrDisconnected) { + if (!connectedOrDisconnected) { + String zone = session.params().getString(SessionParamConst.ZONE); + if (zone != null) { + pipeline.inactiveZone(zone); + LOGGER.error("session {} disconnected, inactive zone {}", session, zone); + } + ScheduledFuture scheduledFuture = session.params().getObj(SessionParamConst.HEART_BEAT); + if (scheduledFuture != null) { + scheduledFuture.cancel(true); + LOGGER.info("{} cancel heartbeat echo", session); + } + } else { + ScheduledFuture scheduledFuture = + session + .thread() + .scheduleAtFixedRate( + () -> session.writeNow(ReqHeartBeatMsg.INSTANCE), 5, 5, TimeUnit.SECONDS); + session.params().putObj(SessionParamConst.HEART_BEAT, scheduledFuture); + LOGGER.info("{} start heartbeat echo", session); + } + } + + @Override + protected void onStart(String[] args) throws Exception { + endPoint.start( + AddressPair.withPort(port), + (s, b, t) -> { + if (b) { + LOGGER.info("pipeline binary start success!"); + } else { + LOGGER.error("bind error", t); + System.exit(1); + } + }); + } + + @Override + protected void onDestroy(String[] args) { + endPoint.stop(); + try { + pipeline.close(); + } catch (IOException e) { + LOGGER.error("close pipeline error", e); + } + } + + @Mapper + private class PipelineBinaryHandler { + + /** + * 消费者注册 + * + * @param msg + */ + public void consumerRegister(@Request ReqRegisterZoneMsg msg, BinaryRequest context) { + ResRegisterZoneMsg res = new ResRegisterZoneMsg(); + if (StringUtil.empty(msg.zone)) { + res.code = 1; + context.session().writeNow(res); + LOGGER.error("session {} send a null zone", context.session()); + return; + } + if (!pipeline.registerBuffer(msg.zone, msg.tags)) { + // 如果这个队列本来存在且并未处于激活状态就需要该客户端来认领 + States zoneState = pipeline.getZoneState(msg.zone); + if (zoneState != null && zoneState != States.ACTIVE) { + context.session().writeNow(ReqZoneClaimMsg.INSTANCE); + LOGGER.info("session {} need claim", context.session()); + } else { + res.code = 1; + context.session().writeNow(res); + LOGGER.info("zone {} does not belong to session {}", msg.zone, context.session()); + } + return; + } + res.code = 0; + res.token = pipeline.getZoneToken(msg.zone); + context.session().writeNow(res); + LOGGER.info( + "session {} , zone {} register success,then tell me ready!", context.session(), msg.zone); + } + + /** + * 消费者准备好 + * + * @param msg + * @param context + */ + public void consumerReady(@Request ReqCustomerReadyMsg msg, BinaryRequest context) { + // 先看参数 + if (StringUtil.empty(msg.zone)) { + LOGGER.error("session {} send a null zone for ready", context.session()); + context.session().close(); + return; + } + if (StringUtil.empty(msg.token)) { + LOGGER.error("session {} send a null token for ready", context.session()); + context.session().close(); + return; + } + States zoneState = pipeline.getZoneState(msg.zone); + if (zoneState == null) { + LOGGER.error("session {} does not register for zone {}", context.session(), msg.zone); + context.session().close(); + return; + } + if (zoneState == States.ACTIVE) { + LOGGER.error("can not active zone {} twice for session {}", msg.zone, context.session()); + context.session().close(); + return; + } + String zoneToken = pipeline.getZoneToken(msg.zone); + if (!zoneToken.equals(msg.token)) { + LOGGER.error( + "can not active zone {} with a wrong token for session {}", + msg.zone, + context.session()); + context.session().close(); + return; + } + pipeline.activeZone(msg.zone); + context.session().params().putString(SessionParamConst.ZONE, msg.zone); + context.session().writeNow(ResPipelineEstablishedMsg.INSTANCE); + } + + private String pullerZone(Session session) { + return session.params().getString(SessionParamConst.ZONE); + } + + public void onHeartBeatResponse(@Request ResHeartBeatMsg msg) { + // DO NOTHING + } + + public void onPullRequest(@Request ReqPullMsg msg, BinaryRequest request) { + Session session = request.session(); + String zone = pullerZone(session); + if (StringUtil.empty(zone)) { + LOGGER.error("session {} is not validated", session); + return; + } + PipelineRingBuffer buffer = MQPipelineBinaryServer.this.pipeline + .getBufferByZone(zone, true); + if (buffer == null) { + LOGGER.error("session {} , zone {} has no buffer", session, zone); + return; + } + int pullNum = MathUtil.fixedBetween(msg.pullNum, 1, 100); + List bytes = buffer.peekAtMost(pullNum); + if (bytes.isEmpty()) { + if (prs.containsKey(zone)) { + LOGGER.debug("session {} , zone {} has no msg , hangout but already", session, zone); + return; + } + prs.put(zone, new PipelineBinarySession(session, pullNum)); + LOGGER.info("session {} , zone {} has no msg , hangout success", session, zone); + return; + } + prs.remove(zone); // TODO 不删除 复用 + pushMsgsToConsumer(zone, session, bytes); + } + + private void pushMsgsToConsumer( + String zone, Session session, List bytes) { + ResPullMsg msg = new ResPullMsg(); + msg.msgs = bytes; + session.writeNow( + msg, + (b, t) -> { + if (b) { + LOGGER + .debug("send msgs to session {} , zone {}, num {}", session, zone, bytes.size()); + } else { + LOGGER.error("send msgs to session " + session + " , zone " + zone + " fail", t); + } + }); + } + + public void receiveProviderMsg(@Request ReqPushMsgToPipelineMsg msg, BinaryRequest request) { + if (StringUtil.empty(msg.zone)) { + request.session().writeNow(ResPushMsgResultMsg.ZONE_EMPTY); + return; + } + if (msg.bytes == null || msg.bytes.length == 0) { + request.session().writeNow(ResPushMsgResultMsg.NO_MSG_CONTENT); + return; + } + States zoneState = MQPipelineBinaryServer.this.pipeline.getZoneState(msg.zone); + if (zoneState == null) { + request.session().writeNow(ResPushMsgResultMsg.NO_ZONE); + return; + } + if (zoneState != States.ACTIVE) { + request.session().writeNow(ResPushMsgResultMsg.ZONE_NOT_ACTIVE); + return; + } + PipelineRingBuffer buffer = MQPipelineBinaryServer.this.pipeline + .getBufferByZone(msg.zone, true); + if (buffer == null) { + request.session().writeNow(ResPushMsgResultMsg.ZONE_HAS_NO_BUFFER); + return; + } + if (!buffer.enqueue(msg.bytes)) { + request.session().writeNow(ResPushMsgResultMsg.ZONE_BUFFER_HAS_NO_CAPACITY); + return; + } + request.session().writeNow(ResPushMsgResultMsg.SUCCESS); + noticeConsumers(msg.zone); + } + + public void receiveProviderMsg(@Request ReqPushMsgToPipelineWithTagsMsg msg, + BinaryRequest request) { + if (msg.tags == null || msg.tags.isEmpty()) { + request.session().writeNow(ResPushMsgResultMsg.TAG_EMPTY); + return; + } + if (msg.bytes == null || msg.bytes.length == 0) { + request.session().writeNow(ResPushMsgResultMsg.NO_MSG_CONTENT); + return; + } + List> buffers = MQPipelineBinaryServer.this.pipeline + .getBuffersByTags(new HashSet<>(msg.tags), true); + if (buffers.isEmpty()) { + request.session().writeNow(ResPushMsgResultMsg.CAN_NOT_FIND_ZONE_BY_TAGS); + return; + } + PipelineRingBuffer buffer = buffers + .get(RandomUtil.nextInt(0, buffers.size() - 1)); + if (!buffer.enqueue(msg.bytes)) { + request.session().writeNow(ResPushMsgResultMsg.ZONE_BUFFER_HAS_NO_CAPACITY); + return; + } + request.session().writeNow(ResPushMsgResultMsg.SUCCESS); + noticeConsumers(buffer.getZone()); + } + + public void receiveProviderMsg(@Request ReqBroadcastMsgToPipelineMsg msg, + BinaryRequest request) { + if (msg.bytes == null || msg.bytes.length == 0) { + request.session().writeNow(ResPushMsgResultMsg.NO_MSG_CONTENT); + return; + } + List> allBuffers = MQPipelineBinaryServer.this.pipeline + .getAllBuffers(true); + boolean allFail = true; + for (PipelineRingBuffer buffer : allBuffers) { + if (!buffer.enqueue(msg.bytes)) { + request.session().writeNow(ResPushMsgResultMsg.ZONE_BUFFER_HAS_NO_CAPACITY); + continue; + } + allFail = false; + noticeConsumers(buffer.getZone()); + } + if (!allFail) { + request.session().writeNow(ResPushMsgResultMsg.SUCCESS); + } + + } + + public void receiveProviderMsg(@Request ReqBroadcastMsgToPipelineWithTagsMsg msg, + BinaryRequest request) { + if (msg.tags == null || msg.tags.isEmpty()) { + request.session().writeNow(ResPushMsgResultMsg.TAG_EMPTY); + return; + } + if (msg.bytes == null || msg.bytes.length == 0) { + request.session().writeNow(ResPushMsgResultMsg.NO_MSG_CONTENT); + return; + } + List> buffers = MQPipelineBinaryServer.this.pipeline + .getBuffersByTags(new HashSet<>(msg.tags), true); + if (buffers.isEmpty()) { + request.session().writeNow(ResPushMsgResultMsg.CAN_NOT_FIND_ZONE_BY_TAGS); + return; + } + boolean allFail = true; + for (PipelineRingBuffer buffer : buffers) { + if (!buffer.enqueue(msg.bytes)) { + request.session().writeNow(ResPushMsgResultMsg.ZONE_BUFFER_HAS_NO_CAPACITY); + continue; + } + allFail = false; + noticeConsumers(buffer.getZone()); + } + if (!allFail) { + request.session().writeNow(ResPushMsgResultMsg.SUCCESS); + } + } + + private void noticeConsumers(String zone) { + PipelineBinarySession pipelineBinarySession = prs.get(zone); + if (pipelineBinarySession == null) { + return; + } + PipelineRingBuffer buffer = MQPipelineBinaryServer.this.pipeline + .getBufferByZone(zone, true); + List bytes = buffer.peekAtMost(pipelineBinarySession.requestNum()); + if (bytes.isEmpty()) { + return; + } + prs.remove(zone); + pushMsgsToConsumer(zone, pipelineBinarySession.session(), bytes); + } + } +} diff --git a/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/MQPipelineRestServer.java b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/MQPipelineRestServer.java new file mode 100644 index 0000000000000000000000000000000000000000..589e5a9afe49cef3e458929a1b1a961ded7c244b --- /dev/null +++ b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/MQPipelineRestServer.java @@ -0,0 +1,5 @@ +package top.limitart.fastmq.pipeline; + +public class MQPipelineRestServer { + +} diff --git a/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/binary/PipelineBinarySession.java b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/binary/PipelineBinarySession.java new file mode 100644 index 0000000000000000000000000000000000000000..7a14c0b0e681a5f2d5e753fae869ef6a78abf231 --- /dev/null +++ b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/binary/PipelineBinarySession.java @@ -0,0 +1,32 @@ +package top.limitart.fastmq.pipeline.binary; + +import io.netty.channel.EventLoop; +import top.limitart.base.Conditions; +import top.limitart.net.Session; +import top.limitart.net.binary.BinaryMessage; + +public class PipelineBinarySession { + private Session session; + private int alreadyRequest; + + public PipelineBinarySession(Session session, int num) { + this.session = Conditions.notNull(session); + this.alreadyRequest = num; + } + + public Session session() { + return this.session; + } + + public void cancelRequest() { + this.alreadyRequest = 0; + } + + public void setupRequest(int num) { + this.alreadyRequest = num; + } + + public int requestNum() { + return this.alreadyRequest; + } +} diff --git a/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/core/MessageSlot.java b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/core/MessageSlot.java new file mode 100644 index 0000000000000000000000000000000000000000..c0750d06d5800d4b07715a8578def4e6ee840de4 --- /dev/null +++ b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/core/MessageSlot.java @@ -0,0 +1,26 @@ +package top.limitart.fastmq.pipeline.core; + +public class MessageSlot implements PipelineRingBufferSlot { + + private byte[] value; + + @Override + public void setValue(byte[] bytes) { + this.value = bytes; + } + + @Override + public byte[] getValue() { + return this.value; + } + + @Override + public void active() { + + } + + @Override + public void inactive() { + + } +} diff --git a/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/core/Pipeline.java b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/core/Pipeline.java new file mode 100644 index 0000000000000000000000000000000000000000..bcdf3675b78b91dc62130c8506f4f74a78ff2a1d --- /dev/null +++ b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/core/Pipeline.java @@ -0,0 +1,347 @@ +package top.limitart.fastmq.pipeline.core; + +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; +import java.util.regex.Pattern; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import top.limitart.base.Conditions; +import top.limitart.base.UniqueID; +import top.limitart.collections.ConcurrentHashSet; +import top.limitart.collections.ImmutableSet; +import top.limitart.concurrent.TaskQueue; +import top.limitart.util.StringUtil; +import top.limitart.util.TimeUtil; + +/** + * 消息总线 + */ +public class Pipeline implements Closeable { + + private static Logger LOGGER = LoggerFactory.getLogger(Pipeline.class); + private static final long HANG_TO_SHUTDOWN_INTERVAL = TimeUnit.SECONDS.toMillis(10); + // TAG + private Map> tagAndZone = new HashMap<>(); + // 所有队列 + private Map zoneAndQueue = new HashMap<>(); + // 轮询线程 + private final TaskQueue queue = TaskQueue.create("buffer-robin"); + + private Lock lock = new ReentrantLock(); + + public Pipeline() { + queue.scheduleAtFixedRate(this::dealShutdownAndHang, 5, 5, TimeUnit.MINUTES); + } + + + private void dealShutdownAndHang() { + lock.lock(); + try { + List waitToDelete = new LinkedList<>(); + for (Puller value : zoneAndQueue.values()) { + if (value.stateData.state == States.SHUTDOWN) { + waitToDelete.add(value.zone); + } else if (value.stateData.state == States.HANG + || value.stateData.state == States.REGISTER) { + if (TimeUtil.now() - value.stateData.changeTime > HANG_TO_SHUTDOWN_INTERVAL) { + value.changeState(States.SHUTDOWN); + LOGGER.warn( + "zone {}'s state turn to {} from {},please check!", + value.zone, + States.SHUTDOWN, + States.HANG); + } + } + } + for (String zone : waitToDelete) { + if (!removeBufferByZone(zone)) { + LOGGER.error("remove zone {} failed???", zone); + continue; + } + LOGGER.info("remove zone {} from Pipeline", zone); + } + } finally { + lock.unlock(); + } + } + + /** + * 通过集群编号删除队列 + * + * @param zone 整个集群唯一编号 + * @return + */ + private boolean removeBufferByZone(String zone) { + if (StringUtil.empty(zone)) { + LOGGER.error("can not remove buffer because zone null or empty"); + return false; + } + // TAG + for (Set value : tagAndZone.values()) { + value.removeIf(v -> v.equals(zone)); + } + return zoneAndQueue.remove(zone) != null; + } + + public List> getAllBuffers(boolean onlyActive) { + List> list = new ArrayList<>(); + try { + lock.lock(); + zoneAndQueue.values().forEach((v) -> { + if (!onlyActive || v.stateData.state == States.ACTIVE) { + list.add(v.buffer); + } + }); + return list; + } finally { + lock.unlock(); + } + } + + public List> getBuffersByTags(Set tags, boolean onlyActive) { + Conditions.notNull(tags); + List> list = new ArrayList<>(); + try { + lock.lock(); + for (Entry> entry : tagAndZone.entrySet()) { + String key = entry.getKey(); + if (tags.contains(key)) { + Set value = entry.getValue(); + for (String zone : value) { + PipelineRingBuffer bufferByZone = getBufferByZone(zone, onlyActive); + if (bufferByZone != null) { + list.add(bufferByZone); + } + } + } + } + } finally { + lock.unlock(); + } + return list; + } + + public List> getBuffersByMatchedTags(Pattern tagPattern, + boolean onlyActive) { + List> list = new ArrayList<>(); + try { + lock.lock(); + for (Entry> entry : tagAndZone.entrySet()) { + String key = entry.getKey(); + if (StringUtil.matchReg(tagPattern, key)) { + Set value = entry.getValue(); + for (String zone : value) { + PipelineRingBuffer bufferByZone = getBufferByZone(zone, onlyActive); + if (bufferByZone != null) { + list.add(bufferByZone); + } + } + } + } + } finally { + lock.unlock(); + } + return list; + } + + public PipelineRingBuffer getBufferByZone(String zone, boolean onlyActive) { + if (StringUtil.empty(zone)) { + LOGGER.error("can not get buffer because zone null or empty"); + return null; + } + try { + lock.lock(); + Puller puller = getPullerByZone(zone); + if (puller == null) { + return null; + } + if (onlyActive && puller.stateData.state != States.ACTIVE) { + return null; + } + return puller.buffer; + } finally { + lock.unlock(); + } + } + + public States getZoneState(String zone) { + Puller pullerByZone = getPullerByZone(zone); + if (pullerByZone == null) { + return null; + } + return pullerByZone.stateData.state; + } + + public void activeZone(String zone) { + Puller pullerByZone = getPullerByZone(zone); + if (pullerByZone != null) { + pullerByZone.changeState(States.ACTIVE); + LOGGER.info("zone {} active", zone); + } + } + + public void inactiveZone(String zone) { + Puller pullerByZone = getPullerByZone(zone); + if (pullerByZone != null) { + pullerByZone.changeState(States.HANG); + LOGGER.info("zone {} inactive", zone); + } + } + + public void shutdownZone(String zone) { + Puller pullerByZone = getPullerByZone(zone); + if (pullerByZone != null) { + pullerByZone.changeState(States.SHUTDOWN); + LOGGER.info("zone {} ready to shutdown", zone); + } + } + + public String getZoneToken(String zone) { + Puller pullerByZone = getPullerByZone(zone); + if (pullerByZone == null) { + return null; + } + return pullerByZone.token; + } + + private Puller getPullerByZone(String zone) { + Conditions.notNull(zone); + return zoneAndQueue.get(zone); + } + + /** + * 注册一个队列
生产者和消费者会根据唯一编号zone和个性化tag来发送和消费 + * + * @param zone 整个集群唯一编号 + * @param tags 该单位的自定义标签 + */ + public boolean registerBuffer(String zone, List tags) { + if (StringUtil.empty(zone)) { + LOGGER.error("zone null or empty"); + return false; + } + try { + lock.lock(); + if (zoneAndQueue.containsKey(zone)) { + LOGGER.error("zone duplicated {}", zone); + return false; + } + Set tagSet = new HashSet<>(); + if (tags != null) { + tagSet.addAll(tags); + tagSet.forEach(tag -> tagAndZone.computeIfAbsent(tag, (k) -> new HashSet<>()).add(zone)); + } + zoneAndQueue.put(zone, new Puller(zone, tagSet)); + LOGGER.info("zone {} register in pipeline", zone); + return true; + } finally { + lock.unlock(); + } + } + + @Override + public void close() throws IOException { + queue.shutdown(); + } + + private static class Puller { + + private String zone; + private Set tags; + private State stateData = new State(); + private PipelineRingBuffer buffer; + private String token = UniqueID.UUID(); + + public Puller(String zone, Set tags) { + this.zone = zone; + if (tags != null) { + this.tags = new ConcurrentHashSet<>(tags); + } else { + this.tags = new ConcurrentHashSet<>(); + } + buffer = new PipelineRingBuffer<>(zone, () -> new MessageSlot()); + } + + public Set getTags() { + return ImmutableSet.of(this.tags); + } + + public void changeState(States state) { + this.stateData.changeState(state); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Puller puller = (Puller) o; + return zone.equals(puller.zone); + } + + @Override + public int hashCode() { + return Objects.hash(zone); + } + } + + private static class State { + + private volatile States state = States.REGISTER; + private volatile long changeTime = TimeUtil.now(); + private Lock lock = new ReentrantLock(); + + public States getState() { + return this.state; + } + + public long getChangeTime() { + return changeTime; + } + + public void changeState(States newState) { + try { + lock.lock(); + this.state = newState; + changeTime = TimeUtil.now(); + } finally { + lock.unlock(); + } + } + } + + public enum States { + /** + * 注册中(正在校验合法性,无法消费消息) + */ + REGISTER, + /** + * 激活模式(可以正常消费消息) + */ + ACTIVE, + /** + * 挂起模式(异常,不能消费消息,需要重新激活,队列不会被清除) + */ + HANG, + /** + * 关闭(关闭模式的消息队列会被轮询清除) + */ + SHUTDOWN, + } +} diff --git a/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/core/PipelineRingBuffer.java b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/core/PipelineRingBuffer.java new file mode 100644 index 0000000000000000000000000000000000000000..02496204b129bdf0989c0cf274247b75dbb75baa --- /dev/null +++ b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/core/PipelineRingBuffer.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.fastmq.pipeline.core; + +import com.lmax.disruptor.InsufficientCapacityException; +import com.lmax.disruptor.RingBuffer; +import com.lmax.disruptor.Sequence; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import top.limitart.base.Conditions; +import top.limitart.base.UncatchableException; +import top.limitart.fastmq.pipeline.core.PipelineRingBufferSlot.PipelineRingBufferSlotFactory; + +/** + * 快速失败环形队列 + */ +public class PipelineRingBuffer { + + private static final Logger LOGGER = LoggerFactory.getLogger(PipelineRingBuffer.class); + private final String zone; + private final RingBuffer> buffer; + private final Sequence readCursor; + private EnqueueStrategy strategy = EnqueueStrategy.FAST_FAIL; + + public PipelineRingBuffer(String zone, PipelineRingBufferSlotFactory factory) { + this(zone, 2 << 12, factory); + } + + public PipelineRingBuffer(String zone, int size, PipelineRingBufferSlotFactory factory) { + this.zone = zone; + buffer = RingBuffer.createMultiProducer(() -> factory.newSlot(), size); + readCursor = new Sequence(); + buffer.addGatingSequences(readCursor); + } + + public String getZone() { + return zone; + } + + /** + * 设置执行队列满时的策略 + * + * @param strategy + * @return + */ + public PipelineRingBuffer enqueueStrategy(EnqueueStrategy strategy) { + this.strategy = strategy; + return this; + } + + public boolean enqueue(V task) { + Conditions.notNull(task); + try { + long seq = buffer.tryNext(); + publish(task, seq); + return true; + } catch (InsufficientCapacityException e) { + if (this.strategy == EnqueueStrategy.FAST_FAIL + || this.strategy == EnqueueStrategy.BLOCK_BUT_NOTICE) { + LOGGER.error("no capacity", new UncatchableException( + "buffer " + this + + " is not enough to enqueue task, maybe customer is too slowly or provider is too fast! ")); + } + if (this.strategy == EnqueueStrategy.BLOCK_BUT_NOTICE + || this.strategy == EnqueueStrategy.BLOCK) { + //阻塞 + long seq = buffer.next(); + publish(task, seq); + return true; + } + } + return false; + } + + public boolean enqueue(List tasks) { + Conditions.args(tasks != null && !tasks.isEmpty(), "task list is null or empty"); + long start = buffer.getCursor() + 1; + try { + long end = buffer.tryNext(tasks.size()); + publish(tasks, start, end); + return true; + } catch (InsufficientCapacityException e) { + if (this.strategy == EnqueueStrategy.FAST_FAIL + || this.strategy == EnqueueStrategy.BLOCK_BUT_NOTICE) { + LOGGER.error("no capacity", new UncatchableException( + "buffer " + this + + " is not enough to enqueue task, maybe customer is too slowly or provider is too fast! ")); + } + if (this.strategy == EnqueueStrategy.BLOCK_BUT_NOTICE + || this.strategy == EnqueueStrategy.BLOCK) { + //阻塞 + long end = buffer.next(tasks.size()); + publish(tasks, start, end); + return true; + } + } + return false; + } + + /** + * 消费一条数据 + * + * @return + */ + public V peek() { + List ringBufferTasks = peekAtMost(1); + if (ringBufferTasks.isEmpty()) { + return null; + } + return ringBufferTasks.get(0); + } + + /** + * 指定消费最多num条数据 + * + * @param num + * @return + */ + public List peekAtMost(int num) { + Conditions.positive(num); + List list = null; + if (num > 1) { + list = new LinkedList<>(); + } + int count = 0; + while (count < num) { + long now = readCursor.get(); + if (now >= buffer.getCursor()) { + break; + } + long next = now + 1; + if (!readCursor.compareAndSet(now, next)) { + continue; + } + PipelineRingBufferSlot slot = buffer.get(next); + if (list != null) { + list.add(slot.getValue()); + } else { + list = Collections.singletonList(slot.getValue()); + } + try { + slot.inactive(); + } catch (Exception e) { + LOGGER.error("inactive callback error", e); + } + ++count; + } + return list; + } + + private void publish(List tasks, long low, long high) { + try { + for (int i = 0; i < tasks.size(); i++) { + PipelineRingBufferSlot slot = buffer.get(low + i); + slot.setValue(tasks.get(i)); + try { + slot.active(); + } catch (Exception e) { + LOGGER.error("active callback error", e); + } + } + } finally { + buffer.publish(low, high); + } + } + + private void publish(V tasks, long seq) { + try { + PipelineRingBufferSlot slot = buffer.get(seq); + slot.setValue(tasks); + try { + slot.active(); + } catch (Exception e) { + LOGGER.error("active callback error", e); + } + } finally { + buffer.publish(seq); + } + } + + public enum EnqueueStrategy { + /** + * 如果无法入队,则直接失败 + */ + FAST_FAIL, + /** + * 如果无法入队,则阻塞等待,但会警告 + */ + BLOCK_BUT_NOTICE, + /** + * 如果无法入队,则阻塞等待 + */ + BLOCK + } +} diff --git a/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/core/PipelineRingBufferSlot.java b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/core/PipelineRingBufferSlot.java new file mode 100644 index 0000000000000000000000000000000000000000..7f9a463f02e2f6b98bd8e5174089d5379b05e550 --- /dev/null +++ b/fastmq/pipeline/src/main/java/top/limitart/fastmq/pipeline/core/PipelineRingBufferSlot.java @@ -0,0 +1,22 @@ +package top.limitart.fastmq.pipeline.core; + +public interface PipelineRingBufferSlot { + + void setValue(V v); + + V getValue(); + + void active(); + + void inactive(); + + /** + * 环形队列的可复用插槽 + * + * @param + */ + interface PipelineRingBufferSlotFactory { + + PipelineRingBufferSlot newSlot(); + } +} diff --git a/fastmq/pom.xml b/fastmq/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..3cb5ac95046ac3469aec6b1389ef96eb961f653f --- /dev/null +++ b/fastmq/pom.xml @@ -0,0 +1,20 @@ + + + + limitart + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-fastmq + pom + + pipeline + consumer + provider + common + + \ No newline at end of file diff --git a/fastmq/provider/pom.xml b/fastmq/provider/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..dea339428ba03f1668500dbcdb6ec5273259a6b9 --- /dev/null +++ b/fastmq/provider/pom.xml @@ -0,0 +1,26 @@ + + + + limitart-fastmq + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-fastmq-provider + + + + ${project.groupId} + limitart-net + ${project.version} + + + ${project.groupId} + limitart-fastmq-common + ${project.version} + + + \ No newline at end of file diff --git a/fastmq/provider/src/main/java/top/limitart/fastmq/provider/MQProviderBinaryClient.java b/fastmq/provider/src/main/java/top/limitart/fastmq/provider/MQProviderBinaryClient.java new file mode 100644 index 0000000000000000000000000000000000000000..a6bc224a580483c0da721919812e98a09e264745 --- /dev/null +++ b/fastmq/provider/src/main/java/top/limitart/fastmq/provider/MQProviderBinaryClient.java @@ -0,0 +1,123 @@ +package top.limitart.fastmq.provider; + +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import top.limitart.base.ApplicationBootstrap; +import top.limitart.base.BinaryMeta; +import top.limitart.base.Conditions; +import top.limitart.fastmq.common.binary.BinaryRequest; +import top.limitart.fastmq.common.binary.ReqBroadcastMsgToPipelineMsg; +import top.limitart.fastmq.common.binary.ReqBroadcastMsgToPipelineWithTagsMsg; +import top.limitart.fastmq.common.binary.ReqHeartBeatMsg; +import top.limitart.fastmq.common.binary.ReqPushMsgToPipelineMsg; +import top.limitart.fastmq.common.binary.ReqPushMsgToPipelineWithTagsMsg; +import top.limitart.fastmq.common.binary.ResHeartBeatMsg; +import top.limitart.fastmq.common.binary.ResPushMsgResultMsg; +import top.limitart.mapping.Mapper; +import top.limitart.mapping.Request; +import top.limitart.mapping.Router; +import top.limitart.net.AddressPair; +import top.limitart.net.NettySession; +import top.limitart.net.binary.BinaryEndPoint; +import top.limitart.net.binary.BinaryMessage; + + +public class MQProviderBinaryClient extends ApplicationBootstrap { + + private static final Logger LOGGER = LoggerFactory.getLogger(MQProviderBinaryClient.class); + private BinaryEndPoint client; + private AddressPair remoteAddress; + private ProviderBinaryHandler providerBinaryHandler; + private NettySession session; + + public MQProviderBinaryClient(String remoteIp, int port) throws Exception { + this.remoteAddress = AddressPair.withIP(remoteIp, port); + providerBinaryHandler = new ProviderBinaryHandler(); + Router router = + Router.empty(BinaryMessage.class, BinaryRequest.class) + .registerMapperClass(ProviderBinaryHandler.class, (c) -> providerBinaryHandler); + this.client = + BinaryEndPoint.client() + .router(router) + .autoReconnect(10) + .onConnected((s, b) -> onConnected(s, b)) + .build(); + } + + public void sendMsgWithTags(List tags, byte[] bytes) { + if (this.session == null || !this.session.writable()) { + //todo + return; + } + ReqPushMsgToPipelineWithTagsMsg msg = new ReqPushMsgToPipelineWithTagsMsg(); + msg.bytes = bytes; + msg.tags = tags; + session.writeNow(msg); + } + + public void sendMsg(String zone, byte[] bytes) { + if (this.session == null || !this.session.writable()) { + //todo + return; + } + ReqPushMsgToPipelineMsg msg = new ReqPushMsgToPipelineMsg(); + msg.zone = zone; + msg.bytes = bytes; + session.writeNow(msg); + } + + public void broadcastMsgWithTags(List tags, byte[] bytes) { + if (this.session == null || !this.session.writable()) { + //todo + return; + } + ReqBroadcastMsgToPipelineWithTagsMsg msg = new ReqBroadcastMsgToPipelineWithTagsMsg(); + msg.bytes = bytes; + msg.tags = tags; + session.writeNow(msg); + } + + public void broadcastMsg(byte[] bytes) { + if (this.session == null || !this.session.writable()) { + //todo + return; + } + Conditions.notNull(bytes); + ReqBroadcastMsgToPipelineMsg msg = new ReqBroadcastMsgToPipelineMsg(); + msg.bytes = bytes; + session.writeNow(msg); + } + + private void onConnected(NettySession session, Boolean connectedOrNot) { + if (connectedOrNot) { + this.session = session; + } else { + this.session = null; + } + } + + @Override + protected void onStart(String[] args) throws Exception { + this.client.start(this.remoteAddress); + } + + @Override + protected void onDestroy(String[] args) { + this.client.stop(); + } + + @Mapper + private class ProviderBinaryHandler { + + public void onHeartBeat(@Request ReqHeartBeatMsg msg, BinaryRequest request) { + request.session().writeNow(ResHeartBeatMsg.INSTANCE); + } + + public void onPushMsgResult(@Request ResPushMsgResultMsg msg, BinaryRequest request) { + if (msg.getCode() != ResPushMsgResultMsg.SUCCESS.getCode()) { + MQProviderBinaryClient.LOGGER.error("push msg error {}", msg.getCode()); + } + } + } +} diff --git a/game/limitart-game.iml b/game/limitart-game.iml new file mode 100644 index 0000000000000000000000000000000000000000..64bd157846a0965f6c76dbef6473e5f793c5d927 --- /dev/null +++ b/game/limitart-game.iml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/game/pom.xml b/game/pom.xml index f1a2ee27f021406fa20e493c2578149c42bebe4a..7e495becf03c35e2a71df6f5b8f17b7e68e443c8 100644 --- a/game/pom.xml +++ b/game/pom.xml @@ -5,7 +5,7 @@ limitart top.limitart - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 diff --git a/game/src/main/java/top/limitart/game/poker/TexasPokerCalculator.java b/game/src/main/java/top/limitart/game/poker/TexasPokerCalculator.java index b597826f201ee4010130562bf92087403b6b3d29..53b8585dec5689825cac0378b497a668f15d558e 100644 --- a/game/src/main/java/top/limitart/game/poker/TexasPokerCalculator.java +++ b/game/src/main/java/top/limitart/game/poker/TexasPokerCalculator.java @@ -17,7 +17,7 @@ package top.limitart.game.poker; import top.limitart.util.CollectionUtil; import top.limitart.util.EnumUtil; -import top.limitart.util.GameMathUtil; +import top.limitart.util.MathUtil; import java.util.ArrayList; import java.util.List; @@ -86,7 +86,7 @@ public class TexasPokerCalculator { sum.add(tableCard); } // 从所有牌中任意选取五张的集合 - List> cnm = GameMathUtil.CNM(sum, 5); + List> cnm = MathUtil.CNM(sum, 5); // 所有组合中牌型最大的一种 long maxValue = 0; TexasPokerCalculator maxEval = null; diff --git a/game/src/test/java/top/limitart/game/poker/PokersTest.java b/game/src/test/java/top/limitart/game/poker/PokersTest.java index 3ec73cebce850d74efdbeabc37646cc36fee61e0..858a04cc6c2da088cdf4de8fe8901f060eefac25 100644 --- a/game/src/test/java/top/limitart/game/poker/PokersTest.java +++ b/game/src/test/java/top/limitart/game/poker/PokersTest.java @@ -5,7 +5,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import top.limitart.util.CollectionUtil; -import top.limitart.util.GameMathUtil; +import top.limitart.util.MathUtil; import top.limitart.util.StringUtil; import java.util.ArrayList; @@ -28,7 +28,7 @@ public class PokersTest { break; } } - fiveCards = GameMathUtil.CNM(bytes, 5); + fiveCards = MathUtil.CNM(bytes, 5); } @After diff --git a/hotdep/pom.xml b/hotdep/pom.xml index 9f253afe7cb6ac7a7d70ee735bc52bed02b1b464..0944d4922dff5c52b7f07d02f2dae4ed71080efe 100644 --- a/hotdep/pom.xml +++ b/hotdep/pom.xml @@ -5,7 +5,7 @@ limitart top.limitart - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 diff --git a/intellij-java-google-style.xml b/intellij-java-google-style.xml new file mode 100644 index 0000000000000000000000000000000000000000..45bf14cca6855c83be1fe5cea6c4aeaed09e1b85 --- /dev/null +++ b/intellij-java-google-style.xml @@ -0,0 +1,598 @@ + + + + + + \ No newline at end of file diff --git a/net/pom.xml b/net/pom.xml index e6482d50729b273482565092000f07c01aad87e9..c5080c645ff59fb334f86843ea4f5fa49d25fd7f 100644 --- a/net/pom.xml +++ b/net/pom.xml @@ -5,7 +5,7 @@ limitart top.limitart - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 diff --git a/net/src/main/java/top/limitart/mapping/RouterImpl.java b/net/src/main/java/top/limitart/mapping/RouterImpl.java index b0b4014cbacf24316a082a71e33dc34ba6a449ef..8b468c76611d5f1221db8f92ae8708880d4afff4 100644 --- a/net/src/main/java/top/limitart/mapping/RouterImpl.java +++ b/net/src/main/java/top/limitart/mapping/RouterImpl.java @@ -40,275 +40,305 @@ import java.util.function.Consumer; * @author hank * @version 2018/10/8 0008 20:48 */ -public class RouterImpl implements Router { - private static final Logger LOGGER = LoggerFactory.getLogger(RouterImpl.class); - // !!这里的asm应用经测试在JAVA8下最优 - private final Map, Context> msgs = new ConcurrentHashMap<>(); - private final Map, Object> managerInstances = new ConcurrentHashMap<>(); - private Class mClass; - private Class cClass; - private final ConstructorAccess contextMethod; +public class RouterImpl + implements Router { + private static final Logger LOGGER = LoggerFactory.getLogger(RouterImpl.class); + // !!这里的asm应用经测试在JAVA8下最优 + private final Map, Context> msgs = new ConcurrentHashMap<>(); + private final Map, Object> managerInstances = new ConcurrentHashMap<>(); + private Class mClass; + private Class cClass; + private final ConstructorAccess contextMethod; - /** - * 创造一个空的消息工厂 - * - * @return - */ - public static Router empty(Class mClass, Class cClass) { - return new RouterImpl(mClass, cClass); - } + /** + * 创造一个空的消息工厂 + * + * @return + */ + public static Router empty( + Class mClass, Class cClass) { + return new RouterImpl(mClass, cClass); + } - /** - * 通过扫描包创建消息工厂 - * - * @param scanPackage - * @param confirmInstance 指定manager的 实例 - * @return - * @throws IOException - * @throws ReflectiveOperationException - */ - public static Router create( - Class mClass, - Class cClass, - String scanPackage, - Function1, Object> confirmInstance) - throws Exception { - Conditions.notNull(scanPackage, "scanPackage"); - RouterImpl factory = new RouterImpl(mClass, cClass); - List> classesByPackage = - ReflectionUtil.getClassesBySuperClass(scanPackage, Object.class); - for (Class clazz : classesByPackage) { - factory.registerMapperClass(clazz, confirmInstance); - } - return factory; + /** + * 通过扫描包创建消息工厂 + * + * @param scanPackage + * @param confirmInstance 指定manager的 实例 + * @return + * @throws IOException + * @throws ReflectiveOperationException + */ + public static Router create( + Class mClass, + Class cClass, + String scanPackage, + Function1, Object> confirmInstance) + throws Exception { + Conditions.notNull(scanPackage, "scanPackage"); + RouterImpl factory = new RouterImpl(mClass, cClass); + List> classesByPackage = + ReflectionUtil.getClassesBySuperClass(scanPackage, Object.class); + for (Class clazz : classesByPackage) { + factory.registerMapperClass(clazz, confirmInstance); } + return factory; + } - /** - * 通过包扫描创建消息工厂 - * - * @param scanPackage 包名 - * @return - * @throws ReflectiveOperationException - * @throws IOException - */ - public static Router create( - Class mClass, Class cClass, String scanPackage) - throws IOException, ReflectiveOperationException, RequestDuplicatedException { - Conditions.notNull(scanPackage, "scanPackage"); - RouterImpl factory = new RouterImpl(mClass, cClass); - List> classesByPackage = - ReflectionUtil.getClassesBySuperClass(scanPackage, Object.class); - for (Class clazz : classesByPackage) { - factory.registerMapperClass(clazz, null); + /** + * 通过包扫描创建消息工厂 + * + * @param scanPackage 包名 + * @return + * @throws ReflectiveOperationException + * @throws IOException + */ + public static Router create( + Class mClass, Class cClass, String scanPackage) + throws IOException, ReflectiveOperationException, RequestDuplicatedException { + Conditions.notNull(scanPackage, "scanPackage"); + RouterImpl factory = new RouterImpl(mClass, cClass); + List> classesByPackage = + ReflectionUtil.getClassesBySuperClass(scanPackage, Object.class); + for (Class clazz : classesByPackage) { + if (clazz.getAnnotation(Mapper.class) == null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("{} has no @Mapper annotation", clazz.getName()); } - return factory; + continue; + } + factory.registerMapperClass(clazz, null); } + return factory; + } - public RouterImpl(Class mClass, Class cClass) { - this.mClass = mClass; - this.cClass = cClass; - this.contextMethod = ConstructorAccess.get(this.cClass); - } + public RouterImpl(Class mClass, Class cClass) { + this.mClass = mClass; + this.cClass = cClass; + this.contextMethod = ConstructorAccess.get(this.cClass); + } - /** - * 注册一个manager - * - * @param mapperClass - * @throws InstantiationException - * @throws IllegalAccessException - */ - @Override - public Router registerMapperClass(Class mapperClass) - throws IllegalAccessException, InstantiationException, RequestDuplicatedException { - return registerMapperClass(mapperClass, null); - } + /** + * 注册一个manager + * + * @param mapperClass + * @throws InstantiationException + * @throws IllegalAccessException + */ + @Override + public Router registerMapperClass(Class mapperClass) + throws IllegalAccessException, InstantiationException, RequestDuplicatedException { + return registerMapperClass(mapperClass, null); + } - /** - * 注册一个manager - * - * @param mapperClass 类 - * @param confirmInstance 指定manager的 实例 - */ - public Router registerMapperClass( - Class mapperClass, Function1, Object> confirmInstance) - throws IllegalAccessException, InstantiationException, RequestDuplicatedException { - Mapper manager = mapperClass.getAnnotation(Mapper.class); - if (manager == null) { - return this; - } - // 扫描方法 - MethodAccess methodAccess = MethodAccess.get(mapperClass); - for (int i = 0; i < methodAccess.getMethods().size(); ++i) { - Method method = methodAccess.getMethods().get(i); - //扫描该方法的参数 - Class[] parameterTypes = method.getParameterTypes(); - Annotation[][] parameterAnnotations = method.getParameterAnnotations(); - //找到标记为@Request的参数和RequestContext的位置,Request必须,因为要判定是什么消息,Conext非必须 - List> paramList = new ArrayList<>(2); - Class msgType = null; - Class contextType = null; - for (int j = 0; j < parameterTypes.length; j++) { - Class parameterType = parameterTypes[j]; + /** + * 注册一个manager + * + * @param mapperClass 类 + * @param confirmInstance 指定manager的 实例 + */ + public Router registerMapperClass( + Class mapperClass, Function1, Object> confirmInstance) + throws IllegalAccessException, InstantiationException, RequestDuplicatedException { + Mapper manager = mapperClass.getAnnotation(Mapper.class); + if (manager == null) { + throw new InstantiationException(mapperClass.getName() + " has no @Mapper annotation"); + } + // 扫描方法 + MethodAccess methodAccess = MethodAccess.get(mapperClass); + for (int i = 0; i < methodAccess.getMethods().size(); ++i) { + Method method = methodAccess.getMethods().get(i); + // 扫描该方法的参数 + Class[] parameterTypes = method.getParameterTypes(); + Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + // 找到标记为@Request的参数和RequestContext的位置,Request必须,因为要判定是什么消息,Conext非必须 + List> paramList = new ArrayList<>(2); + Class msgType = null; + Class contextType = null; + for (int j = 0; j < parameterTypes.length; j++) { + Class parameterType = parameterTypes[j]; - for (Annotation annotation : parameterAnnotations[j]) { - if (annotation.annotationType() == Request.class) { - if (msgType != null) { - throw new RequestDuplicatedException("one method more than one Request(@Request)???"); - } - msgType = parameterType; - paramList.add(msgType); - break; - } - } - if (ReflectionUtil.isInheritFrom(parameterType, RequestContext.class)) { - contextType = parameterType; - paramList.add(contextType); - } - } - if (msgType == null) { - continue; + for (Annotation annotation : parameterAnnotations[j]) { + if (annotation.annotationType() == Request.class) { + if (msgType != null) { + throw new RequestDuplicatedException("one method more than one Request(@Request)???"); } - //没有找到必要的消息类型就返回 - if (!Modifier.isPublic(method.getModifiers())) { - throw new IllegalAccessError( - "method must be PUBLIC:" - + mapperClass.getName() - + "." - + ReflectionUtil.getMethodOverloadName(method)); - } - if (!mClass.isAssignableFrom(msgType)) { - LOGGER.info("{} IS NOT a {},IGNORE.", msgType.getName(), mClass.getName()); - continue; - } - if (contextType != null && !cClass.isAssignableFrom(contextType)) { - throw new IllegalAccessException( - mapperClass.getName() - + "." - + ReflectionUtil.getMethodOverloadName(method) - + " param can only be ASSIGNABLE from " - + cClass.getName()); - } - ConstructorAccess constructorAccess = - (ConstructorAccess) ConstructorAccess.get(msgType); - if (msgs.containsKey(msgType)) { - throw new RequestDuplicatedException(msgType.getName()); - } - Context messageContext = new Context(); - messageContext.conAccess = constructorAccess; - messageContext.managerClazz = mapperClass; - messageContext.methodName = method.getName(); - messageContext.paramTypes = paramList.toArray(new Class[0]); - messageContext.methodAccess = methodAccess; - msgs.put((Class) msgType, messageContext); - if (!managerInstances.containsKey(mapperClass)) { - managerInstances.put(mapperClass, confirmInstance != null ? confirmInstance.apply(mapperClass) : mapperClass.newInstance()); - } - LOGGER.info("register request " + msgType.getName() + " at " + mapperClass.getName()); + msgType = parameterType; + paramList.add(msgType); + break; + } } - return this; - } - - /** - * 替换掉manager的实例 - * - * @param request - * @param newInstance - */ - public void replaceInstance(Class mapperClass, MESSAGE request, Object newInstance) { - Conditions.notNull(mapperClass, "mapperClass"); - Conditions.notNull(request, "request"); - Conditions.notNull(newInstance, "newInstance"); - if (managerInstances.containsKey(mapperClass)) { - managerInstances.put(mapperClass, newInstance); + if (ReflectionUtil.isInheritFrom(parameterType, RequestContext.class)) { + contextType = parameterType; + paramList.add(contextType); } + } + if (msgType == null) { + continue; + } + // 没有找到必要的消息类型就返回 + if (!Modifier.isPublic(method.getModifiers())) { + throw new IllegalAccessError( + "method must be PUBLIC:" + + mapperClass.getName() + + "." + + ReflectionUtil.getMethodOverloadName(method)); + } + if (!mClass.isAssignableFrom(msgType)) { + LOGGER.info("{} IS NOT a {},IGNORE.", msgType.getName(), mClass.getName()); + continue; + } + if (contextType != null && !cClass.isAssignableFrom(contextType)) { + throw new IllegalAccessException( + mapperClass.getName() + + "." + + ReflectionUtil.getMethodOverloadName(method) + + " param can only be ASSIGNABLE from " + + cClass.getName()); + } + ConstructorAccess constructorAccess = + (ConstructorAccess) ConstructorAccess.get(msgType); + if (msgs.containsKey(msgType)) { + throw new RequestDuplicatedException(msgType.getName()); + } + Context messageContext = new Context(); + messageContext.conAccess = constructorAccess; + messageContext.managerClazz = mapperClass; + messageContext.methodName = method.getName(); + messageContext.paramTypes = paramList.toArray(new Class[0]); + messageContext.methodAccess = methodAccess; + msgs.put((Class) msgType, messageContext); + if (!managerInstances.containsKey(mapperClass)) { + managerInstances.put( + mapperClass, + confirmInstance != null + ? confirmInstance.apply(mapperClass) + : mapperClass.newInstance()); + } + LOGGER.info("register request " + msgType.getName() + " at " + mapperClass.getName()); } + return this; + } - @Override - public void foreachRequestClass(Consumer> consumer) { - msgs.keySet().forEach(consumer); + /** + * 替换掉manager的实例 + * + * @param request + * @param newInstance + */ + public void replaceInstance(Class mapperClass, MESSAGE request, Object newInstance) { + Conditions.notNull(mapperClass, "mapperClass"); + Conditions.notNull(request, "request"); + Conditions.notNull(newInstance, "newInstance"); + if (managerInstances.containsKey(mapperClass)) { + managerInstances.put(mapperClass, newInstance); } + } - /** - * 根据ID获取一个消息实例 - * - * @param requestClass - * @return - */ - @Override - public MESSAGE requestInstance(Class requestClass) { - if (!msgs.containsKey(requestClass)) { - return null; - } - Context messageContext = msgs.get(requestClass); - return messageContext.conAccess.newInstance(); - } + @Override + public void foreachRequestClass(Consumer> consumer) { + msgs.keySet().forEach(consumer); + } - /** - * 根据ID获取一个消息实例 - * - * @return - */ - @Override - public CONTEXT contextInstance() { - return (CONTEXT) contextMethod.newInstance(); + /** + * 根据ID获取一个消息实例 + * + * @param requestClass + * @return + */ + @Override + public MESSAGE requestInstance(Class requestClass) { + if (!msgs.containsKey(requestClass)) { + return null; } + Context messageContext = msgs.get(requestClass); + return messageContext.conAccess.newInstance(); + } - @Override - public void request(MESSAGE msg, CONTEXT context, Process1 proc) { - Conditions.notNull(msg, "request"); - Context messageContext = msgs.get(msg.getClass()); - if (messageContext == null) { - LOGGER.error("request empty,id:" + msg.getClass().getName()); - // 消息上下文不存在 - return; - } - Object object = managerInstances.get(messageContext.managerClazz); - proc.accept(new Invoker(messageContext.methodAccess, object, messageContext.methodName, messageContext.paramTypes, msg, context)); - } + /** + * 根据ID获取一个消息实例 + * + * @return + */ + @Override + public CONTEXT contextInstance() { + return (CONTEXT) contextMethod.newInstance(); + } - private class Context { - private ConstructorAccess conAccess; - private MethodAccess methodAccess; - private String methodName; - private Class[] paramTypes; - private Class managerClazz; + @Override + public void request(MESSAGE msg, CONTEXT context, Process1 proc) { + Conditions.notNull(msg, "request"); + Context messageContext = msgs.get(msg.getClass()); + if (messageContext == null) { + LOGGER.error("request empty,id:" + msg.getClass().getName()); + // 消息上下文不存在 + return; } + Object object = managerInstances.get(messageContext.managerClazz); + proc.accept( + new Invoker( + messageContext.methodAccess, + object, + messageContext.methodName, + messageContext.paramTypes, + msg, + context)); + } - public class Invoker implements MethodInvoker { - private MethodAccess methodAccess; - private Object object; - private Class[] paramTypes; - private MESSAGE msg; - private String methodName; - private CONTEXT param; + private class Context { + private ConstructorAccess conAccess; + private MethodAccess methodAccess; + private String methodName; + private Class[] paramTypes; + private Class managerClazz; + } - public Invoker(MethodAccess methodAccess, Object object, String methodName,Class[] paramTypes, MESSAGE msg) { - this(methodAccess, object, methodName, paramTypes, msg, null); - } + public class Invoker implements MethodInvoker { + private MethodAccess methodAccess; + private Object object; + private Class[] paramTypes; + private MESSAGE msg; + private String methodName; + private CONTEXT param; - public Invoker(MethodAccess methodAccess, Object object, String methodName, Class[] paramTypes,MESSAGE msg, CONTEXT param) { - this.methodAccess = methodAccess; - this.object = object; - this.methodName = methodName; - this.msg = msg; - this.param = param; - this.paramTypes = paramTypes; - } + public Invoker( + MethodAccess methodAccess, + Object object, + String methodName, + Class[] paramTypes, + MESSAGE msg) { + this(methodAccess, object, methodName, paramTypes, msg, null); + } - @Override - public Object invoke() { - //这里就是通过paramtype的位置确定参数位置,后面如果参数继续灵活增多,这里方法需要修改 - Object[] paramInstance = new Object[paramTypes.length]; - for (int i = 0; i < paramTypes.length; i++) { - if(paramTypes[i]!=null){ - if(paramTypes[i] == msg.getClass()){ - paramInstance[i] = msg; - }else if(param!=null && paramTypes[i] == param.getClass()){ - paramInstance[i] = param; - } - } - } - return methodAccess.invoke(object, methodName, paramTypes, paramInstance); + public Invoker( + MethodAccess methodAccess, + Object object, + String methodName, + Class[] paramTypes, + MESSAGE msg, + CONTEXT param) { + this.methodAccess = methodAccess; + this.object = object; + this.methodName = methodName; + this.msg = msg; + this.param = param; + this.paramTypes = paramTypes; + } + + @Override + public Object invoke() { + // 这里就是通过paramtype的位置确定参数位置,后面如果参数继续灵活增多,这里方法需要修改 + Object[] paramInstance = new Object[paramTypes.length]; + for (int i = 0; i < paramTypes.length; i++) { + if (paramTypes[i] != null) { + if (paramTypes[i] == msg.getClass()) { + paramInstance[i] = msg; + } else if (param != null && paramTypes[i] == param.getClass()) { + paramInstance[i] = param; + } } + } + return methodAccess.invoke(object, methodName, paramTypes, paramInstance); } + } } diff --git a/net/src/main/java/top/limitart/net/NettyEndPoint.java b/net/src/main/java/top/limitart/net/NettyEndPoint.java index b794a66621b98bcad6f7e580f52bf2ac582f5170..01c679b0f25b1aad163f60357b8992a09a4d509a 100644 --- a/net/src/main/java/top/limitart/net/NettyEndPoint.java +++ b/net/src/main/java/top/limitart/net/NettyEndPoint.java @@ -144,9 +144,9 @@ public abstract class NettyEndPoint AddressPair addressPair, int waitSeconds, Process3, Boolean, Throwable> listener) { stop(); LOGGER.info( - "{} try connect {} server: {} after {} seconds...", + "{} try connect {} server:{} after {} seconds...", name(), - type.local() ? "local" : "", + type.local() ? "local" : "remote", addressPair, waitSeconds); if (waitSeconds > 0) { diff --git a/pipeline-token.tmp b/pipeline-token.tmp new file mode 100644 index 0000000000000000000000000000000000000000..b98b9ea918efa86bdf9a701fea3a8bdf316bf74b --- /dev/null +++ b/pipeline-token.tmp @@ -0,0 +1 @@ +E8FC3DBBBED24D6EB5675DBA3E1C0F48 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 7013d726ae33a572e7f0d95a598f7a42161419bd..fdca3662333fec8e4d615fe7e7490327fd8ea807 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 top.limitart limitart - 3.1.0 + 3.2.0-SNAPSHOT pom limitart @@ -26,11 +26,13 @@ demo net hotdep - game + config db project-starter project-logic + fastmq + rpc http://maven.limitart.top @@ -53,6 +55,7 @@ http://www.limitart.top https://git.oschina.net/HankXV/Limitart.git + limitart-releases @@ -67,6 +70,14 @@ + + org.codehaus.mojo + versions-maven-plugin + 2.7 + + false + + org.apache.maven.plugins maven-dependency-plugin @@ -170,18 +181,44 @@ + + + default-profile + + true + + ${java.home}/../lib/tools.jar + + + + ${java.home}/../lib/tools.jar + + + + + + + + + + + + + + + org.ow2.asm asm - 6.0 + 7.0 org.javassist javassist - 3.25.0-GA + 3.26.0-GA @@ -189,94 +226,93 @@ tools 1.8 system - ${env.JAVA_HOME}/lib/tools.jar + ${tools-jar} com.lmax disruptor - 3.4.0 + 3.4.2 org.slf4j slf4j-api - 1.7.25 + 1.7.30 org.slf4j slf4j-jdk14 - 1.7.25 + 1.7.30 test io.netty netty-all - 4.1.22.Final + 4.1.44.Final org.apache.httpcomponents httpclient - 4.5.7 + 4.5.11 org.apache.httpcomponents fluent-hc - 4.5.7 + 4.5.11 com.google.protobuf protobuf-java - 3.6.1 + 3.11.1 com.fasterxml.jackson.datatype jackson-datatype-jdk8 - 2.9.4 + 2.10.1 com.fasterxml.jackson.datatype jackson-datatype-jsr310 - 2.9.4 + 2.10.1 com.zaxxer HikariCP - 3.0.0 + 3.4.2 com.alibaba druid - 1.1.9 + 1.1.21 org.freemarker freemarker - 2.3.28 + 2.3.29 org.apache.poi poi - 4.0.0 + 4.1.1 org.apache.poi poi-ooxml - 4.0.0 + 4.1.1 - junit junit - 4.12 + 4.13 test diff --git a/project-logic/pom.xml b/project-logic/pom.xml index 48537dfe4c6f1f06ae3f47c9b0fb12c771d3c30a..c183d8304891409fcab23d02a9fdb5bd56405e03 100644 --- a/project-logic/pom.xml +++ b/project-logic/pom.xml @@ -5,7 +5,7 @@ limitart top.limitart - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 diff --git a/project-starter/pom.xml b/project-starter/pom.xml index b2d046b2a8448dd790f54f6ff0e4bbc0d19dd5fb..779df2df051e6e17117d24ab299edde66f554786 100644 --- a/project-starter/pom.xml +++ b/project-starter/pom.xml @@ -5,7 +5,7 @@ limitart top.limitart - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 diff --git a/rpc/pom.xml b/rpc/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..b23b72227bef41b768fd9eedca736854f194e425 --- /dev/null +++ b/rpc/pom.xml @@ -0,0 +1,20 @@ + + + + limitart + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-rpc + pom + + service-center + service-provider + service-consumer + service-common + + \ No newline at end of file diff --git a/rpc/service-center/pom.xml b/rpc/service-center/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..cb55f622ddc42e89e0a964d87b95f8045d76d5fe --- /dev/null +++ b/rpc/service-center/pom.xml @@ -0,0 +1,35 @@ + + + + limitart-rpc + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-rpc-service-center + + + + ${project.groupId} + limitart-fastmq-pipeline + ${project.version} + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-jdk14 + test + + + ${project.groupId} + limitart-rpc-common + ${project.version} + + + \ No newline at end of file diff --git a/rpc/service-center/src/main/java/top/limitart/rpc/RPCServiceCenter.java b/rpc/service-center/src/main/java/top/limitart/rpc/RPCServiceCenter.java new file mode 100644 index 0000000000000000000000000000000000000000..646ee7f7263c6c2177d306b29c05df319b4a757e --- /dev/null +++ b/rpc/service-center/src/main/java/top/limitart/rpc/RPCServiceCenter.java @@ -0,0 +1,28 @@ +package top.limitart.rpc; + +import top.limitart.base.ApplicationBootstrap; +import top.limitart.fastmq.pipeline.MQPipelineBinaryServer; +import top.limitart.fastmq.pipeline.core.Pipeline; + +public class RPCServiceCenter extends ApplicationBootstrap { + + private MQPipelineBinaryServer pipelineServer; + + public RPCServiceCenter(int port) throws Exception { + this.pipelineServer = new MQPipelineBinaryServer(new Pipeline(), port); + } + + public RPCServiceCenter(Pipeline pipeline, int port) throws Exception { + this.pipelineServer = new MQPipelineBinaryServer(pipeline, port); + } + + @Override + protected void onStart(String[] args) throws Exception { + this.pipelineServer.run(args); + } + + @Override + protected void onDestroy(String[] args) { + + } +} diff --git a/rpc/service-common/pom.xml b/rpc/service-common/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..f66ff5d7a285b293948bd3edd381a45180ebfa54 --- /dev/null +++ b/rpc/service-common/pom.xml @@ -0,0 +1,21 @@ + + + + limitart-rpc + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-rpc-common + + + + ${project.groupId} + limitart-core + ${project.version} + + + \ No newline at end of file diff --git a/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCMeta.java b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCMeta.java new file mode 100644 index 0000000000000000000000000000000000000000..95c9979f902c6705fa2c0786e9fcddbcf3983c12 --- /dev/null +++ b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCMeta.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.rpc.srvcommon; + +import io.netty.buffer.ByteBuf; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import top.limitart.base.BinaryMeta; +import top.limitart.base.UncatchableException; + +public abstract class RPCMeta extends BinaryMeta { + + public RPCMeta(ByteBuf buffer) { + super(buffer); + } + + public RPCMeta() { + } + + protected final Object decodeObj(Class type) + throws IllegalAccessException { + return decodeObj(type.getName()); + } + + @SuppressWarnings("unchecked") + protected final Object decodeObj(String type) + throws IllegalAccessException { + if (type == null || type.equals("null")) { + return null; + } else if (type.equals(Integer.class.getName()) || type.equals(int.class.getName())) { + return getInt(); + } else if (type.equals(int[].class.getName())) { + return getIntArray(); + } else if (type.equals(Byte.class.getName()) || type.equals(byte.class.getName())) { + return getByte(); + } else if (type.equals(byte[].class.getName())) { + return getByteArray(); + } else if (type.equals(Short.class.getName()) || type.equals(short.class.getName())) { + return getShort(); + } else if (type.equals(short[].class.getName())) { + return getShortArray(); + } else if (type.equals(Long.class.getName()) || type.equals(long.class.getName())) { + return getLong(); + } else if (type.equals(long[].class.getName())) { + return getLongArray(); + } else if (type.equals(Boolean.class.getName()) || type.equals(boolean.class.getName())) { + return getBoolean(); + } else if (type.equals(boolean[].class.getName())) { + return getBooleanArray(); + } else if (type.equals(String.class.getName())) { + return getString(); + } else if (type.equals(String[].class.getName())) { + return getStringArray(); + } else if (type.equals(Float.class.getName()) || type.equals(float.class.getName())) { + return getFloat(); + } else if (type.equals(float[].class.getName())) { + return getFloatArray(); + } else if (type.equals(Double.class.getName()) || type.equals(double.class.getName())) { + return getDouble(); + } else if (type.equals(double[].class.getName())) { + return getDoubleArray(); + } else if (type.equals(Character.class.getName()) || type.equals(char.class.getName())) { + return getChar(); + } else if (type.equals(char[].class.getName())) { + return getCharArray(); + } else if (type.equals(ArrayList.class.getName()) || type.equals(List.class.getName())) { + List objList = new ArrayList<>(); + short length = getShort(); + if (length > 0) { + String listType = getString(); + for (int i = 0; i < length; ++i) { + objList.add(decodeObj(listType)); + } + } + return objList; + } else if (type.equals(HashMap.class.getName()) || type.equals(Map.class.getName())) { + short length = getShort(); + if (length == 0) { + return null; + } + String keyType = getString(); + String valueType = getString(); + Map map = new HashMap<>(); + for (int i = 0; i < length; ++i) { + map.put(decodeObj(keyType), decodeObj(valueType)); + } + return map; + } else if (type.equals(HashSet.class.getName()) || type.equals(Set.class.getName())) { + short length = getShort(); + if (length == 0) { + return null; + } + String setType = getString(); + Set set = new HashSet<>(); + for (int i = 0; i < length; ++i) { + set.add(decodeObj(setType)); + } + return set; + } else if (type.startsWith("[L")) { + @SuppressWarnings("rawtypes") + Class forName = null; + try { + forName = Class.forName(type); + } catch (ClassNotFoundException e) { + throw new UncatchableException(e); + } + return getMessageMetaArray(forName.getComponentType()); + } else { + @SuppressWarnings("rawtypes") + Class forName = null; + try { + forName = Class.forName(type); + } catch (ClassNotFoundException e) { + throw new UncatchableException(e); + } + return getMessageMeta(forName); + } + } + + @SuppressWarnings("unchecked") + protected final void encodeObj(Object object) throws IllegalAccessException { + if (object == null) { + return; + } + Class type = object.getClass(); + if (type.equals(Integer.class) || type.equals(int.class)) { + putInt((int) object); + } else if (type.equals(int[].class)) { + putIntArray((int[]) object); + } else if (type.equals(Byte.class) || type.equals(byte.class)) { + putByte((int) object); + } else if (type.equals(byte[].class)) { + putByteArray((byte[]) object); + } else if (type.equals(Short.class) || type.equals(short.class)) { + putShort((short) object); + } else if (type.equals(short[].class)) { + putShortArray((short[]) object); + } else if (type.equals(Long.class) || type.equals(long.class)) { + putLong((long) object); + } else if (type.equals(long[].class)) { + putLongArray((long[]) object); + } else if (type.equals(Boolean.class) || type.equals(boolean.class)) { + putBoolean((boolean) object); + } else if (type.equals(boolean[].class)) { + putBooleanArray((boolean[]) object); + } else if (type.equals(String.class)) { + putString((String) object); + } else if (type.equals(String[].class)) { + putStringArray((String[]) object); + } else if (type.equals(Float.class) || type.equals(float.class)) { + putFloat((float) object); + } else if (type.equals(float[].class)) { + putFloatArray((float[]) object); + } else if (type.equals(Double.class) || type.equals(double.class)) { + putDouble((double) object); + } else if (type.equals(double[].class)) { + putDoubleArray((double[]) object); + } else if (type.equals(Character.class) || type.equals(char.class)) { + putChar((char) object); + } else if (type.equals(char[].class)) { + putCharArray((char[]) object); + } else if (type.equals(ArrayList.class) || type.equals(List.class)) { + List objs = (List) object; + if (objs.isEmpty()) { + putShort((short) 0); + } else { + putShort((short) objs.size()); + String name = objs.get(0).getClass().getName(); + putString(name); + for (Object obj : objs) { + encodeObj(obj); + } + } + } else if (type.equals(HashMap.class) || type.equals(Map.class)) { + Map map = (Map) object; + if (map.isEmpty()) { + putShort((short) 0); + } else { + putShort((short) map.size()); + boolean f = false; + for (Entry next : map.entrySet()) { + if (!f) { + f = true; + putString(next.getKey().getClass().getName()); + putString(next.getValue().getClass().getName()); + } + encodeObj(next.getKey()); + encodeObj(next.getValue()); + } + } + } else if (type.equals(HashSet.class) || type.equals(Set.class)) { + Set set = (Set) object; + if (set.isEmpty()) { + putShort((short) 0); + } else { + putShort((short) set.size()); + boolean f = false; + for (Object value : set) { + if (!f) { + f = true; + putString(value.getClass().getName()); + } + encodeObj(value); + } + } + } else if (object instanceof BinaryMeta) { + putMessageMeta((BinaryMeta) object); + } else if (object.getClass().isArray() + && object.getClass().getComponentType().getSuperclass() == BinaryMeta.class) { + putMessageMetaArray((BinaryMeta[]) object); + } else { + throw new UncatchableException(object.getClass().getName() + " does not supported yet!"); + } + } +} diff --git a/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCService.java b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCService.java new file mode 100644 index 0000000000000000000000000000000000000000..2416f8e55fc9a8fa7e8771f26174c2a6cf76bb94 --- /dev/null +++ b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCService.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.rpc.srvcommon; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * RPC服务 + * + * @author Hank + * + */ +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface RPCService { + String provider(); + + String module() default ""; +} diff --git a/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCServiceExecuteException.java b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCServiceExecuteException.java new file mode 100644 index 0000000000000000000000000000000000000000..a485b4bd4022214bcaba75401008d1ab968fe0a5 --- /dev/null +++ b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCServiceExecuteException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.rpc.srvcommon; + + +import top.limitart.base.UncatchableException; + +/** + * 服务执行错误 + * + * @author Hank + * + */ +public class RPCServiceExecuteException extends UncatchableException { + private static final long serialVersionUID = 1L; + + public RPCServiceExecuteException(String info) { + super(info); + } +} diff --git a/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCServiceIOException.java b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCServiceIOException.java new file mode 100644 index 0000000000000000000000000000000000000000..5d823aa2d49f2897eeb2d28ee371517468285094 --- /dev/null +++ b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCServiceIOException.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.rpc.srvcommon; + +import java.io.IOException; + +/** + * 服务IO错误 + * + * @author Hank + * + */ +public class RPCServiceIOException extends IOException { + private static final long serialVersionUID = 1L; + + public RPCServiceIOException(String info) { + super(info); + } + + public RPCServiceIOException(Exception e) { + super(e); + } +} diff --git a/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCServiceProxyException.java b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCServiceProxyException.java new file mode 100644 index 0000000000000000000000000000000000000000..7d37c3e6c0f437dafd786360c24b366c7cb892c8 --- /dev/null +++ b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RPCServiceProxyException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.rpc.srvcommon; + + +import top.limitart.base.CatchableException; + +/** + * 服务代理错误 + * + * @author Hank + * + */ +public class RPCServiceProxyException extends CatchableException { + private static final long serialVersionUID = 1L; + + public RPCServiceProxyException(String info) { + super(info); + } +} diff --git a/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RpcExecuteClientMsg.java b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RpcExecuteClientMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..b91f3f928be67b6de3d2062ea4c3edcf9a8d6189 --- /dev/null +++ b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RpcExecuteClientMsg.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.rpc.srvcommon; + +import io.netty.buffer.ByteBuf; +import java.util.ArrayList; +import java.util.List; + +public class RpcExecuteClientMsg extends RPCMeta { + public String consumerName; + public int requestId; + public String moduleName; + public String methodName; + public List paramTypes = new ArrayList<>(); + public List params = new ArrayList<>(); + + public RpcExecuteClientMsg(ByteBuf buffer) { + super(buffer); + } + + public RpcExecuteClientMsg() { + } + + @Override + public String toString() { + return moduleName + "@" + methodName; + } + + @Override + public void serialize() throws IllegalArgumentException, IllegalAccessException { + putString(this.consumerName); + putInt(this.requestId); + putString(this.moduleName); + putString(this.methodName); + putStringList(this.paramTypes); + if (this.paramTypes != null) { + for (Object object : params) { + encodeObj(object); + } + } + } + + @Override + public void deserialize() throws IllegalArgumentException, IllegalAccessException { + this.consumerName = getString(); + this.requestId = getInt(); + this.moduleName = getString(); + this.methodName = getString(); + this.paramTypes = getStringList(); + // 这里特殊处理,因为服务器要知道参数类型去寻找具体的类 + for (String type : this.paramTypes) { + this.params.add(decodeObj(type)); + } + } +} diff --git a/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RpcResultServerMsg.java b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RpcResultServerMsg.java new file mode 100644 index 0000000000000000000000000000000000000000..a01951a136867b04bd4f334ae4bc00d33e629aaf --- /dev/null +++ b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RpcResultServerMsg.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.rpc.srvcommon; + + +import io.netty.buffer.ByteBuf; + +public class RpcResultServerMsg extends RPCMeta { + + /** + * 成功 + */ + public final static int SUCCESS = 0; + /** + * 没有模块 + */ + public final static int SERVER_HAS_NO_MODULE = 1; + /** + * 没有方法 + */ + public final static int SERVER_HAS_NO_METHOD = 2; + + private int requestId; + private int errorCode; + private String returnType; + private Object returnVal; + + public RpcResultServerMsg(ByteBuf buffer) { + super(buffer); + } + + public RpcResultServerMsg() { + } + + public int getRequestId() { + return requestId; + } + + public void setRequestId(int requestId) { + this.requestId = requestId; + } + + public int getErrorCode() { + return errorCode; + } + + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + public String getReturnType() { + return returnType; + } + + public void setReturnType(String returnType) { + this.returnType = returnType; + } + + public Object getReturnVal() { + return returnVal; + } + + public void setReturnVal(Object returnVal) { + this.returnVal = returnVal; + } + + @Override + public void serialize() throws IllegalArgumentException, IllegalAccessException { + putInt(this.requestId); + putInt(this.errorCode); + putString(this.returnType); + encodeObj(this.returnVal); + } + + @Override + public void deserialize() throws IllegalArgumentException, IllegalAccessException { + this.requestId = getInt(); + this.errorCode = getInt(); + this.returnType = getString(); + this.returnVal = decodeObj(this.returnType); + } +} diff --git a/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RpcUtil.java b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RpcUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..b35952d16e6b251a641805539aa9ebc0d6d1c2c6 --- /dev/null +++ b/rpc/service-common/src/main/java/top/limitart/rpc/srvcommon/RpcUtil.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.rpc.srvcommon; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import top.limitart.base.BinaryMeta; +import top.limitart.util.StringUtil; + +public final class RpcUtil { + private RpcUtil() { + } + + /** + * 获取服务名称 + * + * @param providerName + * @param serviceClass + * @return + * @throws RPCServiceProxyException + */ + public static String getServiceName(String providerName, Class serviceClass) + throws RPCServiceProxyException { + RPCService annotation = serviceClass.getAnnotation(RPCService.class); + if (annotation == null) { + throw new RPCServiceProxyException("not a RPCService class(annotation)"); + } + String modole = annotation.module(); + if (StringUtil.empty(modole)) { + modole = serviceClass.getSimpleName(); + } + return providerName + "@" + modole; + } + + /** + * 检查RPC参数类型是否符合标准 + * + * @param type + * @return + * @throws RPCServiceProxyException + */ + public static void checkParamType(Class type) throws RPCServiceProxyException { + if (!type.isPrimitive()) { + if (type.isArray()) { + checkParamType(type.getComponentType()); + } else { + if (!BinaryMeta.class.isAssignableFrom(type) && type != String.class && type != List.class + && type != ArrayList.class && type != HashMap.class && type != Map.class + && type != HashSet.class && type != Set.class) { + throw new RPCServiceProxyException(type.getName() + "必须是基础类型(包括其数组)或" + BinaryMeta.class.getName() + + "的子类,或者为上述类型的java.util.List或java.util.ArrayList"); + } + } + } + } +} diff --git a/rpc/service-consumer/pom.xml b/rpc/service-consumer/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..1865a17aa4f070a6f27add9a389664d6cf908928 --- /dev/null +++ b/rpc/service-consumer/pom.xml @@ -0,0 +1,40 @@ + + + + limitart-rpc + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-rpc-service-consumer + + + ${project.groupId} + limitart-fastmq-provider + ${project.version} + + + ${project.groupId} + limitart-fastmq-consumer + ${project.version} + + + ${project.groupId} + limitart-rpc-common + ${project.version} + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-jdk14 + test + + + + \ No newline at end of file diff --git a/rpc/service-consumer/src/main/java/top/limitart/rpc/srvconsumer/RPCServiceConsumer.java b/rpc/service-consumer/src/main/java/top/limitart/rpc/srvconsumer/RPCServiceConsumer.java new file mode 100644 index 0000000000000000000000000000000000000000..1ef8c6a756f6f9afb3922f2e48294ee918a308ef --- /dev/null +++ b/rpc/service-consumer/src/main/java/top/limitart/rpc/srvconsumer/RPCServiceConsumer.java @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.rpc.srvconsumer; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import java.io.IOException; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.LongAdder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import top.limitart.base.ApplicationBootstrap; +import top.limitart.fastmq.consumer.ConsumerMsgHandler; +import top.limitart.fastmq.consumer.MQConsumerBinaryClient; +import top.limitart.fastmq.provider.MQProviderBinaryClient; +import top.limitart.rpc.srvcommon.RPCService; +import top.limitart.rpc.srvcommon.RPCServiceExecuteException; +import top.limitart.rpc.srvcommon.RPCServiceIOException; +import top.limitart.rpc.srvcommon.RPCServiceProxyException; +import top.limitart.rpc.srvcommon.RpcExecuteClientMsg; +import top.limitart.rpc.srvcommon.RpcResultServerMsg; +import top.limitart.rpc.srvcommon.RpcUtil; +import top.limitart.util.ReflectionUtil; +import top.limitart.util.StringUtil; + +/** + * RPC客户端 + * + * @author hank + */ +public class RPCServiceConsumer extends ApplicationBootstrap implements ConsumerMsgHandler { + + private static Logger LOGGER = LoggerFactory.getLogger( + RPCServiceConsumer.class); + public static final int MAX_CALL_BACK_LENGTH = 2000; + public static final long EXECUTE_TIMEOUT = 5; + private MQConsumerBinaryClient consumerClient; + private MQProviderBinaryClient providerClient; + // 动态代理集合 + private Map, Object> clientProxys = new HashMap<>(); + // 服务对应的本地代理接口集合 + private Map> serviceProxyClasses = new HashMap<>(); + // RequestId生成器 + private AtomicInteger requestIdCreater = new AtomicInteger(0); + // RPC调用回调集合 + private Map futures = new ConcurrentHashMap<>(); + private LongAdder dropNum = new LongAdder(); + private String customerName; + + public RPCServiceConsumer(String customerName, String serviceCenterIp, int serviceCenterPort, + String... servicePackages) + throws Exception { + this.customerName = customerName; + initRpcProxys(servicePackages); + //初始化请求发送客户端 + providerClient = new MQProviderBinaryClient(serviceCenterIp, serviceCenterPort); + consumerClient = new MQConsumerBinaryClient(serviceCenterIp, serviceCenterPort, customerName, + null, this); + } + + @Override + protected void onStart(String[] args) throws Exception { + providerClient.run(args); + consumerClient.run(args); + } + + @Override + protected void onDestroy(String[] args) { + } + + /** + * 创建RPC同步调用代理 + * + * @param interfaceClss + * @return + * @throws RPCServiceProxyException + */ + @SuppressWarnings("unchecked") + public T createProxy(Class interfaceClss) throws RPCServiceProxyException { + Object proxyObject = this.clientProxys.get(interfaceClss); + if (proxyObject == null) { + throw new RPCServiceProxyException(interfaceClss.getName() + "不是一个RPC服务!"); + } + return (T) proxyObject; + } + + /** + * 初始化本地服务代理 + * + * @throws IOException + * @throws ReflectiveOperationException + * @throws Exception + */ + private void initRpcProxys(String[] interfacePackages) + throws RPCServiceProxyException, IOException, ReflectiveOperationException { + clientProxys.clear(); + List> classesByPackage = new ArrayList<>(); + for (String temp : interfacePackages) { + classesByPackage.addAll(ReflectionUtil.getClassesBySuperClass(temp, Object.class)); + } + for (Class clazz : classesByPackage) { + RPCService annotation = clazz.getAnnotation(RPCService.class); + if (annotation == null) { + continue; + } + if (!clazz.isInterface()) { + throw new RPCServiceProxyException(clazz.getName() + "RPC服务器必须是一个接口!"); + } + // 检查参数是否符合标准 + String provider = annotation.provider(); + if (StringUtil.empty(provider)) { + throw new RPCServiceProxyException("服务:" + clazz.getName() + "的提供商为空!"); + } + String serviceName = RpcUtil.getServiceName(provider, clazz); + // 检查方法 + Method[] methods = clazz.getMethods(); + for (Method method : methods) { + String methodOverloadName = ReflectionUtil.getMethodOverloadName(method); + // 检查参数 + Class[] parameterTypes = method.getParameterTypes(); + for (Class paramsType : parameterTypes) { + RpcUtil.checkParamType(paramsType); + } + // 检查返回参数是否合法 + RpcUtil.checkParamType(method.getReturnType()); + // 异常抛出检查 + Class[] exceptionTypes = method.getExceptionTypes(); + if (exceptionTypes == null || exceptionTypes.length < 1) { + throw new RPCServiceProxyException( + "类" + clazz.getName() + "的方法" + methodOverloadName + "必须要抛出异常:" + + Exception.class.getName()); + } + boolean exOk = false; + for (Class ex : exceptionTypes) { + if (ex == Exception.class) { + exOk = true; + } + } + if (!exOk) { + throw new RPCServiceProxyException( + "类" + clazz.getName() + "的方法" + methodOverloadName + "的异常抛出必须有:" + + Exception.class.getName()); + } + } + // 创建动态代理类 + Object newProxyInstance = ReflectionUtil.newProxy(clazz, + (InvocationHandler) (proxy, method, args) -> proxyExecute(serviceName, proxy, + method.getName(), + ReflectionUtil.getMethodOverloadName(method), args)); + if (serviceProxyClasses.containsKey(serviceName)) { + throw new RPCServiceProxyException("服务名重复:" + serviceName); + } + serviceProxyClasses.put(serviceName, clazz); + clientProxys.put(clazz, newProxyInstance); + LOGGER.info("创建服务动态代理:" + serviceName + ",服务提供商:" + provider + ",代理实例:" + newProxyInstance); + } + } + + /** + * rpc动态代理方法 + * + * @param serviceName + * @param proxy + * @param methodName + * @param methodOverloadName + * @throws InterruptedException + * @throws RPCServiceIOException + */ + private Object proxyExecute(String serviceName, Object proxy, String methodName, + String methodOverloadName, + Object[] args) + throws RPCServiceExecuteException, InterruptedException, RPCServiceIOException { + if (proxy != null) { + if ("equals".equals(methodName)) { + return proxy == args[0]; + } else if ("hashCode".equals(methodName)) { + return System.identityHashCode(proxy); + } else if ("toString".equals(methodName)) { + return proxy.getClass().getName() + "@" + Integer + .toHexString(System.identityHashCode(proxy)); + } + } + if (futures.size() > MAX_CALL_BACK_LENGTH) { + dropNum.increment(); + throw new RPCServiceExecuteException( + "回调列表超过限制:" + MAX_CALL_BACK_LENGTH + + ",不进行任何处理!,已抛弃数量:" + dropNum.longValue()); + } + RemoteFuture future = rpcSend(serviceName, methodOverloadName, args); + if (future.getResponseResult() == null) { + // 无条件线程等待 + boolean await = future.getCountDownLatch() + .await(EXECUTE_TIMEOUT, TimeUnit.SECONDS); + futures.remove(future.getRequestId()); + if (!await) { + throw new RPCServiceExecuteException( + "动态代理方法:" + methodOverloadName + "超时,回调ID:" + future + .getRequestId()); + } + } + // 等待完成设置回调完成,服务器处理完毕后就不用唤醒此线程 + RpcResultServerMsg response = future.getResponseResult(); + int errorCode = response.getErrorCode(); + if (errorCode == RpcResultServerMsg.SUCCESS) { + return response.getReturnVal(); + } else if (errorCode == RpcResultServerMsg.SERVER_HAS_NO_MODULE) { + throw new RPCServiceExecuteException("没有服务名为:" + serviceName); + } else if (errorCode == RpcResultServerMsg.SERVER_HAS_NO_METHOD) { + throw new RPCServiceExecuteException( + "没有服务名为:" + serviceName + "的" + methodOverloadName + "方法!"); + } else { + throw new RPCServiceExecuteException("服务名:" + serviceName + "返回未知错误码!"); + } + } + + /** + * 发送到RPC请求到服务器 + * + * @param serviceName + * @param methodOverloadName + * @param args + * @return + * @throws Exception + */ + private RemoteFuture rpcSend(String serviceName, String methodOverloadName, Object[] args) + throws RPCServiceIOException { + // 开始构造消息 + RpcExecuteClientMsg msg = new RpcExecuteClientMsg(); + msg.consumerName = this.customerName; + msg.requestId = requestIdCreater.incrementAndGet(); + msg.moduleName = serviceName; + msg.methodName = methodOverloadName; + if (args != null && args.length > 0) { + for (Object obj : args) { + if (obj == null) { + msg.paramTypes.add(null); + msg.params.add(null); + } else { + msg.paramTypes.add(obj.getClass().getName()); + msg.params.add(obj); + } + } + } + RemoteFuture future = new RemoteFuture(); + future.setRequestId(msg.requestId); + futures.put(msg.requestId, future); + if (futures.size() > 100) { + LOGGER.error( + "警告!开始动态代理方法:" + methodOverloadName + ",回调列表长度:" + futures.size() + + "(并发量),id:" + msg.requestId); + } + // 发送消息 + ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(); + try { + msg.replaceBuffer(buf); + msg.serialize(); + byte[] c = new byte[buf.readableBytes()]; + buf.readBytes(c); + providerClient.sendMsgWithTags(Collections.singletonList(msg.moduleName), c); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } finally { + buf.release(); + } + return future; + } + + /** + * 当RPC服务器回应RPC服务结果 + */ + private void onRPCResonse(RpcResultServerMsg msg) { + int requestId = msg.getRequestId(); + RemoteFuture rpcFuture = futures.get(requestId); + if (rpcFuture == null) { + LOGGER.error("requestId:" + requestId + "找不到回调!"); + return; + } + rpcFuture.setResponseResult(msg); + // 唤醒线程 + rpcFuture.getCountDownLatch().countDown(); + } + + @Override + public void onMsg(byte[] msg) { + ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(); + buffer.writeBytes(msg); + RpcResultServerMsg t = new RpcResultServerMsg(buffer); + try { + t.deserialize(); + } catch (IllegalAccessException e) { + LOGGER.error("decode response error", e); + return; + } finally { + buffer.release(); + } + onRPCResonse(t); + } +} diff --git a/rpc/service-consumer/src/main/java/top/limitart/rpc/srvconsumer/RemoteFuture.java b/rpc/service-consumer/src/main/java/top/limitart/rpc/srvconsumer/RemoteFuture.java new file mode 100644 index 0000000000000000000000000000000000000000..91d805d8a1f6a76c8a010405125d7da95a11d282 --- /dev/null +++ b/rpc/service-consumer/src/main/java/top/limitart/rpc/srvconsumer/RemoteFuture.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.rpc.srvconsumer; + +import java.util.concurrent.CountDownLatch; +import top.limitart.rpc.srvcommon.RpcResultServerMsg; + +/** + * 远程调用回调 + * + * @author hank + */ +public class RemoteFuture { + + private int requestId; + private volatile RpcResultServerMsg responseResult; + private CountDownLatch countDownLatch = new CountDownLatch(1); + + public int getRequestId() { + return requestId; + } + + public void setRequestId(int requestId) { + this.requestId = requestId; + } + + public RpcResultServerMsg getResponseResult() { + return responseResult; + } + + public void setResponseResult(RpcResultServerMsg responseResult) { + this.responseResult = responseResult; + } + + public CountDownLatch getCountDownLatch() { + return countDownLatch; + } +} diff --git a/rpc/service-provider/pom.xml b/rpc/service-provider/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..f4b69af3b59ff4c4687a21d4e65fd386a4166e53 --- /dev/null +++ b/rpc/service-provider/pom.xml @@ -0,0 +1,45 @@ + + + + limitart-rpc + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-rpc-service-provider + + + + ${project.groupId} + limitart-fastmq-provider + ${project.version} + + + ${project.groupId} + limitart-fastmq-consumer + ${project.version} + + + ${project.groupId} + limitart-rpc-common + ${project.version} + + + ${project.groupId} + limitart-core + ${project.version} + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-jdk14 + test + + + \ No newline at end of file diff --git a/rpc/service-provider/src/main/java/top/limitart/rpc/srvprovider/RPCServiceProvider.java b/rpc/service-provider/src/main/java/top/limitart/rpc/srvprovider/RPCServiceProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..c6dbfe27a83c39156f874a3966884ddb7d7f9507 --- /dev/null +++ b/rpc/service-provider/src/main/java/top/limitart/rpc/srvprovider/RPCServiceProvider.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.rpc.srvprovider; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import top.limitart.base.ApplicationBootstrap; +import top.limitart.fastmq.consumer.ConsumerMsgHandler; +import top.limitart.fastmq.consumer.MQConsumerBinaryClient; +import top.limitart.fastmq.provider.MQProviderBinaryClient; +import top.limitart.rpc.srvcommon.RPCService; +import top.limitart.rpc.srvcommon.RPCServiceProxyException; +import top.limitart.rpc.srvcommon.RpcExecuteClientMsg; +import top.limitart.rpc.srvcommon.RpcResultServerMsg; +import top.limitart.rpc.srvcommon.RpcUtil; +import top.limitart.util.ReflectionUtil; +import top.limitart.util.StringUtil; + +/** + * RPC服务提供者 + * + * @author hank + */ +public class RPCServiceProvider extends ApplicationBootstrap implements ConsumerMsgHandler { + + private static Logger LOGGER = LoggerFactory.getLogger( + RPCServiceProvider.class); + //发送RPC调用结果 + private MQProviderBinaryClient providerClient; + //接收RPC调用请求 + private MQConsumerBinaryClient consumerClient; + private Map services = new HashMap<>(); + + public RPCServiceProvider(String providerName, String serviceCenterIp, int serviceCenterPort, + String[] interfacePackages, String[] implPackages) + throws Exception { + initAllServices(interfacePackages, implPackages); + this.providerClient = new MQProviderBinaryClient(serviceCenterIp, serviceCenterPort); + this.consumerClient = new MQConsumerBinaryClient(serviceCenterIp, serviceCenterPort, + providerName, new LinkedList<>(services.keySet()), this); + } + + @Override + protected void onStart(String[] args) throws Exception { + this.providerClient.run(args); + this.consumerClient.run(args); + } + + @Override + protected void onDestroy(String[] args) { + + } + + /** + * 扫描本地服务 + * + * @throws RPCServiceProxyException + * @throws IOException + * @throws ReflectiveOperationException + * @throws Exception + */ + private void initAllServices(String[] interfacePackages, String[] implPackages) + throws RPCServiceProxyException, IOException, ReflectiveOperationException { + services.clear(); + List> interfacesByPackage = new ArrayList<>(); + for (String temp : interfacePackages) { + LOGGER.info("开始在包:" + temp + "下查找接口..."); + interfacesByPackage.addAll(ReflectionUtil.getClassesBySuperClass(temp, Object.class)); + } + // RPC接口集合 + Map, Map> rpcInterfaces = new HashMap<>(); + // 查找所有RPC接口 + for (Class clazz : interfacesByPackage) { + // 必须是一个接口 + RPCService annotation = clazz.getAnnotation(RPCService.class); + if (annotation == null) { + continue; + } + if (!clazz.isInterface()) { + throw new RPCServiceProxyException(clazz.getName() + "RPC服务器必须是一个接口!"); + } + // 检查参数是否符合标准 + String provider = annotation.provider(); + if (StringUtil.empty(provider)) { + throw new RPCServiceProxyException("RPC接口提供商不能为空!"); + } + String serviceName = RpcUtil.getServiceName(provider, clazz); + if (services.containsKey(serviceName)) { + throw new RPCServiceProxyException("服务名:" + serviceName + "重复!"); + } + // 检查方法 + Method[] methods = clazz.getMethods(); + Map methodSet = new HashMap<>(); + // 检查方法参数是否合法 + for (Method method : methods) { + String methodOverloadName = ReflectionUtil.getMethodOverloadName(method); + // 检查参数 + Class[] parameterTypes = method.getParameterTypes(); + for (Class paramsType : parameterTypes) { + RpcUtil.checkParamType(paramsType); + + } + // 检查返回参数是否合法 + RpcUtil.checkParamType(method.getReturnType()); + // 异常抛出检查 + Class[] exceptionTypes = method.getExceptionTypes(); + if (exceptionTypes == null || exceptionTypes.length < 1) { + throw new RPCServiceProxyException( + "类" + clazz.getName() + "的方法" + methodOverloadName + "必须要抛出异常:" + + Exception.class.getName()); + } + boolean exOk = false; + for (Class ex : exceptionTypes) { + if (ex == Exception.class) { + exOk = true; + } + } + if (!exOk) { + throw new RPCServiceProxyException( + "类" + clazz.getName() + "的方法" + methodOverloadName + "的异常抛出必须有:" + + Exception.class.getName()); + } + methodSet.put(ReflectionUtil.getMethodOverloadName(method), method); + } + rpcInterfaces.put(clazz, methodSet); + } + // 查找RPC接口的实现类 + List> implsByPackage = new ArrayList<>(); + for (String temp : implPackages) { + LOGGER.info("开始在包:" + temp + "下查找接口实现..."); + implsByPackage.addAll(ReflectionUtil.getClassesBySuperClass(temp, Object.class)); + } + for (Class clazz : implsByPackage) { + Class[] interfaces = clazz.getInterfaces(); + if (interfaces == null || interfaces.length < 1) { + continue; + } + // 检查实现的接口实例的所有RPC服务 + Map> serviceNames = new HashMap<>(); + Object instance = null; + // 遍历接口(主要处理一个实例,实现了多个RPC接口的情况) + for (Class temp : interfaces) { + Map hashMap = rpcInterfaces.get(temp); + // 没有RPC服务 + if (hashMap == null) { + continue; + } + RPCService annotation = temp.getAnnotation(RPCService.class); + // 此类有实现此RPC接口 + serviceNames.put(RpcUtil.getServiceName(annotation.provider(), temp), temp); + if (instance == null) { + instance = clazz.newInstance(); + } + } + // 如果查找到了实例 + if (instance != null && !serviceNames.isEmpty()) { + for (Entry> entry : serviceNames.entrySet()) { + String serviceName = entry.getKey(); + if (services.containsKey(serviceName)) { + throw new RPCServiceProxyException("服务:" + serviceName + "发现了多个实现类:" + instance); + } + RpcServiceInstance data = new RpcServiceInstance(); + data.setInstance(instance); + Class value = entry.getValue(); + data.getMethods().putAll(rpcInterfaces.get(value)); + services.put(serviceName, data); + LOGGER.info("发现服务:" + serviceName + ",实例名称:" + + (clazz.getName() + "@" + Integer.toHexString(instance.hashCode()))); + } + } + } + } + + /** + * 执行RPC消费者请求的方法 + * + * @param requestId + * @param moduleName + * @param methodName + * @param params + */ + private void executeRPC(String customerName, int requestId, String moduleName, String methodName, + List params) + throws Exception { + RpcResultServerMsg msg = new RpcResultServerMsg(); + msg.setRequestId(requestId); + msg.setErrorCode(RpcResultServerMsg.SUCCESS); + try { + RpcServiceInstance serviceInstanceData = services.get(moduleName); + if (serviceInstanceData == null) { + LOGGER.error("RPC消费者:" + customerName + "发送了未知的服务名:" + moduleName); + msg.setErrorCode(RpcResultServerMsg.SERVER_HAS_NO_MODULE); + return; + } + Method method = serviceInstanceData.getMethods().get(methodName); + if (method == null) { + LOGGER.error("RPC消费者:" + customerName + "发送了未知的方法名:" + methodName + ",服务名为:" + + moduleName); + msg.setErrorCode(RpcResultServerMsg.SERVER_HAS_NO_METHOD); + return; + } + if (msg.getErrorCode() == 0) { + try { + Object result = method.invoke(serviceInstanceData.self(), params.toArray()); + if (result != null) { + msg.setReturnType(result.getClass().getName()); + msg.setReturnVal(result); + } + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } + } finally { + // 发送消息 + ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(); + try { + msg.replaceBuffer(buf); + msg.serialize(); + byte[] c = new byte[buf.readableBytes()]; + buf.readBytes(c); + providerClient.sendMsg(customerName, c); + } catch (Exception e) { + LOGGER.error("send result error", e); + } finally { + buf.release(); + } + } + } + + /** + * 获取服务实体 + * + * @param providerName + * @param clazz + * @return + * @throws + */ + @SuppressWarnings("unchecked") + public T getServiceInstance(String providerName, Class clazz) + throws RPCServiceProxyException { + RPCService annotation = clazz.getAnnotation(RPCService.class); + if (annotation == null) { + throw new RPCServiceProxyException(clazz.getName() + "is not a RPCService!"); + } + RpcServiceInstance serviceInstanceData = services + .get(RpcUtil.getServiceName(providerName, clazz)); + if (serviceInstanceData == null) { + return null; + } + return (T) serviceInstanceData.self(); + } + + + @Override + public void onMsg(byte[] msg) { + ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(); + buffer.writeBytes(msg); + RpcExecuteClientMsg t = new RpcExecuteClientMsg(buffer); + try { + t.deserialize(); + } catch (IllegalAccessException e) { + LOGGER.error("decode response error", e); + return; + } finally { + buffer.release(); + } + try { + executeRPC(t.consumerName, t.requestId, t.moduleName, t.methodName, t.params); + } catch (Exception e) { + LOGGER.error("execute error", e); + } + } +} diff --git a/rpc/service-provider/src/main/java/top/limitart/rpc/srvprovider/RpcServiceInstance.java b/rpc/service-provider/src/main/java/top/limitart/rpc/srvprovider/RpcServiceInstance.java new file mode 100644 index 0000000000000000000000000000000000000000..e6ac8d4c61ff08e33801a079065c1208c3886273 --- /dev/null +++ b/rpc/service-provider/src/main/java/top/limitart/rpc/srvprovider/RpcServiceInstance.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016-present The Limitart Project + * + * 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 + * + * 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 top.limitart.rpc.srvprovider; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * RPC服务实现类 + * + * @author ank + * + */ +public class RpcServiceInstance { + private Object instance; + private Map methods = new HashMap<>(); + + public Object self() { + return instance; + } + + public void setInstance(Object instance) { + this.instance = instance; + } + + public Map getMethods() { + return methods; + } + + public void setMethods(HashMap methods) { + this.methods = methods; + } +} diff --git a/service-center/pom.xml b/service-center/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..d36b49564d609b43d65bb0eeed6b8ec09ba66246 --- /dev/null +++ b/service-center/pom.xml @@ -0,0 +1,15 @@ + + + + limitart + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-rpc-service-center + + + \ No newline at end of file diff --git a/service-consumer/pom.xml b/service-consumer/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..4e350cbe94ae8a16501695af2c0a41ff634be90e --- /dev/null +++ b/service-consumer/pom.xml @@ -0,0 +1,15 @@ + + + + limitart + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-rpc-service-consumer + + + \ No newline at end of file diff --git a/service-provider/pom.xml b/service-provider/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..c7ef87b06781f72cca1402b2f3e17c6aa1ba7299 --- /dev/null +++ b/service-provider/pom.xml @@ -0,0 +1,15 @@ + + + + limitart + top.limitart + 3.2.0-SNAPSHOT + + 4.0.0 + + limitart-rpc-service-provider + + + \ No newline at end of file diff --git a/update-version.sh b/update-version.sh new file mode 100644 index 0000000000000000000000000000000000000000..5bd9102daaa6e867096535536b16eb796f780d6b --- /dev/null +++ b/update-version.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +mvn -N versions:update-child-modules \ No newline at end of file