记一次@NonNull导致无法序列化的问题

博客讨论了使用Lombok的@NonNull注解如何生成有参构造函数,进而引发Java对象序列化失败的问题。内容指出,由于Lombok生成了用于判空的有参构造,JDK默认的无参构造函数未被添加,导致序列化时遇到错误。正确的做法应该是使用@NotNull注解,以避免此类问题的发生。

 以上这个代码在接参的时候报了一个缺少无参构造函数无法序列化的错误

将.class反编译

 可以看到编译后的源码中生成了一个有参构造 明显是 用来判空的 假设那么这个构造函数应该就是根据@NonNull生成的

 

实际上我们治理应该添加的注解是NotNull才对

 

上面因为lombook根据@NonNull生成了一个有参构造函数,导致jdk不会添加默认的无参构造函数,没有无参构造函数的话 序列化就会失败.

public interface EventCenter { default Integer getPartitions(String topic) { return 0; } default void send(@Nonnull String topic, @Nonnull Event event) { } default void send(@Nonnull String topic, @Nonnull Event event, EventFuture eventFuture) { } default void send(@Nonnull String topic, String key, @Nonnull Event event) { } default void send(@Nonnull String topic, String key, @Nonnull Event event, EventFuture eventFuture) { } default void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull Event event) { } default void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull Event event, EventFuture eventFuture) { } default void send(@Nonnull String topic, @Nonnull BaseEvent event, @Nonnull SerializeEnum serializeEnum) { } default void send(@Nonnull String topic, @Nonnull BaseEvent event, GenericEventFuture eventFuture, @Nonnull SerializeEnum serializeEnum) { } default void send(@Nonnull String topic, String key, @Nonnull BaseEvent event, @Nonnull SerializeEnum serializeEnum) { } default void send(@Nonnull String topic, String key, @Nonnull BaseEvent event, GenericEventFuture eventFuture, @Nonnull SerializeEnum serializeEnum) { } default void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull BaseEvent event, @Nonnull SerializeEnum serializeEnum) { } default void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull BaseEvent event, GenericEventFuture eventFuture, @Nonnull SerializeEnum serializeEnum) { } default void registerBroadcast(@Nonnull String topic, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService) { } default void registerBroadcast(@Nonnull String topic, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode) { } default void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService) { } default void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode) { } default void registerBroadcastWithoutThreadPool(@Nonnull String topic, @Nonnull EventHandler handler, PartitionAssignorMode partitionAssignorMode) { } default void registerUnicastWithoutThreadPool(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, PartitionAssignorMode partitionAssignorMode) { } default void unregister(@Nonnull String topic, @Nonnull EventHandler handler) { } default <T> void sendGenerically(@Nonnull String topic, @Nonnull T event) { } default <T> void sendGenerically(@Nonnull String topic, @Nonnull T event, GenericEventFuture<T> genericEventFuture) { } default <T> void sendGenerically(@Nonnull String topic, String key, @Nonnull T event) { } default <T> void sendGenerically(@Nonnull String topic, String key, @Nonnull T event, GenericEventFuture<T> genericEventFuture) { } default <T> void sendGenerically(@Nonnull String topic, @Nonnull Integer partition, @Nonnull T event) { } default <T> void sendGenerically(@Nonnull String topic, @Nonnull Integer partition, @Nonnull T event, GenericEventFuture<T> genericEventFuture) { } default <T> void registerBroadcastGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, @NonNull Class<T> clazz) { if (clazz == null) { throw new NullPointerException("clazz is marked non-null but is null"); } } default <T> void registerBroadcastGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { if (clazz == null) { throw new NullPointerException("clazz is marked non-null but is null"); } } default <T> void registerUnicastGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, @NonNull Class<T> clazz) { if (clazz == null) { throw new NullPointerException("clazz is marked non-null but is null"); } } default <T> void registerUnicastGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { if (clazz == null) { throw new NullPointerException("clazz is marked non-null but is null"); } } default <T> void registerBroadcastWithoutThreadPoolGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { if (clazz == null) { throw new NullPointerException("clazz is marked non-null but is null"); } } default <T> void registerUnicastWithoutThreadPoolGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { if (clazz == null) { throw new NullPointerException("clazz is marked non-null but is null"); } } default <T> void unregisterGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler) { } default <T> void unregisterGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, boolean isDestroyExecutorService) { } default void unregister(@Nonnull String topic, @Nonnull EventHandler eventHandler, boolean isDestroyExecutorService) { } default void registerBroadcast(@Nonnull String topic, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, @Nonnull SerializeEnum serializeEnum) { } default void registerBroadcast(@Nonnull String topic, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { } default void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, @Nonnull SerializeEnum serializeEnum) { } default void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { } default void registerBroadcastWithoutThreadPool(@Nonnull String topic, @Nonnull GenericEventHandler handler, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { } default void registerUnicastWithoutThreadPool(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { } default void unregisterAllTopics() { } @PreDestroy default void destroy() { } } EventCenter 接口如上
最新发布
10-17
/** * 注册广播事件处理器(带死信队列配置) * * @param topic 订阅的主题名称 * @param handler 事件处理器实例 * @param executor 业务处理线程池 * @param dlqConfig 死信队列配置 */ public void registerBroadcast(@Nonnull String topic, @Nonnull EventHandler handler, @Nonnull ExecutorService executor, @Nonnull DLQConfig dlqConfig) { String groupId = idGenerator.createGroupId(topic); registerUnicast(topic, groupId, handler, executor, null, dlqConfig); } /** * 注册处理广播事件的handler groupId使用UUID随机生成,确保唯一性。 * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 */ @Override public void registerBroadcast(@Nonnull String topic, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode) { String groupId = idGenerator.createGroupId(topic); registerUnicast(topic, groupId, handler, executorService, partitionAssignorMode); } /** * 注册广播事件处理器(自定义分区策略+死信队列) * * @param topic 订阅的主题名称 * @param handler 事件处理器实例 * @param executorService 业务处理线程池 * @param partitionAssignorMode 分区分配策略 * @param dlqConfig 死信队列配置 */ public void registerBroadcast(@Nonnull String topic, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService, @Nonnull PartitionAssignorMode partitionAssignorMode, @Nonnull DLQConfig dlqConfig) { String groupId = idGenerator.createGroupId(topic); registerUnicast(topic, groupId, handler, executorService, partitionAssignorMode, dlqConfig); } /** * 注册处理单播事件的handler 一个topic对应一个consumerId * * @param topic 主题 * @param groupId 消费者组Id,在同一个组里的消费者实现单播消费 * @param handler 事件处理类 * @param executor 上层传递的用于业务处理的线程池 */ @Override public void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull ExecutorService executor) { registerUnicast(topic, groupId, handler, executor, (PartitionAssignorMode) null); } /** * 注册单播事件处理器(带死信队列配置) * * @param topic 订阅的主题名称 * @param groupId 消费者组ID * @param handler 事件处理器实例 * @param executor 业务处理线程池 * @param dlqConfig 死信队列配置 */ public void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull ExecutorService executor, @Nonnull DLQConfig dlqConfig) { registerUnicast(topic, groupId, handler, executor, null,dlqConfig); } /** * 注册处理单播Topic消息的handler, * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 */ @Override public void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode) { partitionAssignorMode = getPartitionAssignorMode(topic, groupId, partitionAssignorMode); register(topic, groupId, handler, executorService, partitionAssignorMode); } /** * 注册单播事件处理器(自定义分区策略+死信队列) * * @param topic 订阅的主题名称 * @param groupId 消费者组ID * @param handler 事件处理器实例 * @param executorService 业务处理线程池 * @param partitionAssignorMode 分区分配策略 * @param dlqConfig 死信队列配置 */ public void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @Nonnull DLQConfig dlqConfig) { partitionAssignorMode = getPartitionAssignorMode(topic, groupId, partitionAssignorMode); EventHandler wrappedHandler = new DLQEventHandlerWrapper(handler, dlqConfig, topic,this); register(topic, groupId, wrappedHandler, executorService, partitionAssignorMode); } /** * 注册处理广播Topic消息的无业务线程池的Handler * * @param topic 主题 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 */ @Override public void registerBroadcastWithoutThreadPool(@Nonnull String topic, @Nonnull EventHandler handler, PartitionAssignorMode partitionAssignorMode) { String groupId = idGenerator.createGroupId(topic); registerUnicastWithoutThreadPool(topic, groupId, handler, partitionAssignorMode); } /** * 注册无线程池的广播处理器(自定义分区策略+死信队列) * * @param topic 订阅的主题名称 * @param handler 事件处理器实例 * @param partitionAssignorMode 分区分配策略 * @param dlqConfig 死信队列配置 */ public void registerBroadcastWithoutThreadPool(@Nonnull String topic, @Nonnull EventHandler handler, @Nonnull PartitionAssignorMode partitionAssignorMode, @Nonnull DLQConfig dlqConfig) { String groupId = idGenerator.createGroupId(topic); registerUnicastWithoutThreadPool(topic, groupId, handler, partitionAssignorMode, dlqConfig); } /** * 注册处理单播Topic消息的无业务线程池的Handler * * @param topic 主题 * @param groupId 消费者组 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 */ @Override public void registerUnicastWithoutThreadPool(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, PartitionAssignorMode partitionAssignorMode) { partitionAssignorMode = getPartitionAssignorMode(topic, groupId, partitionAssignorMode); register(topic, groupId, handler, null, partitionAssignorMode); } /** * 注册无线程池的单播处理器(自定义分区策略+死信队列) * * @param topic 订阅的主题名称 * @param groupId 消费者组ID * @param handler 事件处理器实例 * @param partitionAssignorMode 分区分配策略 * @param dlqConfig 死信队列配置 */ public void registerUnicastWithoutThreadPool(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull PartitionAssignorMode partitionAssignorMode, @Nonnull DLQConfig dlqConfig) { partitionAssignorMode = getPartitionAssignorMode(topic, groupId, partitionAssignorMode); // 包装Handler,添加DLQ逻辑 EventHandler wrappedHandler = new DLQEventHandlerWrapper(handler, dlqConfig, topic,this); // 调用核心注册(executorService传null,无线程池) register(topic, groupId, wrappedHandler, null, partitionAssignorMode); }以上是我已经完成带死信重载的注册方法,请仿照我的方法修改后续注册方法 @Override public <T> void registerBroadcastGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executor, @NonNull Class<T> clazz) { String groupId = idGenerator.createGroupId(topic); registerUnicastGenerically(topic, groupId, handler, executor, clazz); } /** * 注册处理广播事件的handler groupId使用UUID随机生成,确保唯一性。 * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 */ @Override public <T> void registerBroadcastGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { String groupId = idGenerator.createGroupId(topic); registerUnicastGenerically(topic, groupId, handler, executorService, partitionAssignorMode, clazz); } /** * 注册处理单播事件的handler 一个topic对应一个consumerId * * @param topic 主题 * @param groupId 消费者组Id,在同一个组里的消费者实现单播消费 * @param handler 事件处理类 * @param executor 上层传递的用于业务处理的线程池 */ @Override public <T> void registerUnicastGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executor, @NonNull Class<T> clazz) { registerUnicastGenerically(topic, groupId, handler, executor, null, clazz); } /** * 注册处理单播Topic消息的handler, * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 */ @Override public <T> void registerUnicastGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { partitionAssignorMode = getPartitionAssignorMode(topic, groupId, partitionAssignorMode); register(topic, groupId, handler, executorService, partitionAssignorMode, clazz, SerializeEnum.JSON); } /** * 注册处理广播Topic消息的无业务线程池的Handler * * @param topic 主题 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 */ @Override public <T> void registerBroadcastWithoutThreadPoolGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { String groupId = idGenerator.createGroupId(topic); registerUnicastWithoutThreadPoolGenerically(topic, groupId, handler, partitionAssignorMode, clazz); } /** * 注册处理单播Topic消息的无业务线程池的Handler * * @param topic 主题 * @param groupId 消费者组 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 */ @Override public <T> void registerUnicastWithoutThreadPoolGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { partitionAssignorMode = getPartitionAssignorMode(topic, groupId, partitionAssignorMode); register(topic, groupId, handler, null, partitionAssignorMode, clazz, SerializeEnum.JSON); }@Override public void registerBroadcast(@Nonnull String topic, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executor, @Nonnull SerializeEnum serializeEnum) { switch (serializeEnum) { case KRYO: String groupId = idGenerator.createGroupId(topic); registerUnicast(topic, groupId, handler, executor, serializeEnum); break; case JSON: default: registerBroadcastGenerically(topic, handler, executor, EventV2.class); break; } } /** * 注册处理广播事件的handler groupId使用UUID随机生成,确保唯一性。 * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 */ @Override public void registerBroadcast(@Nonnull String topic, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { switch (serializeEnum) { case KRYO: String groupId = idGenerator.createGroupId(topic); registerUnicast(topic, groupId, handler, executorService, partitionAssignorMode, serializeEnum); break; case JSON: default: registerBroadcastGenerically(topic, handler, executorService, partitionAssignorMode, EventV2.class); break; } } /** * 注册处理单播事件的handler 一个topic对应一个consumerId * * @param topic 主题 * @param groupId 消费者组Id,在同一个组里的消费者实现单播消费 * @param handler 事件处理类 * @param executor 上层传递的用于业务处理的线程池 */ @Override public void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executor, @Nonnull SerializeEnum serializeEnum) { switch (serializeEnum) { case KRYO: registerUnicast(topic, groupId, handler, executor, null, serializeEnum); break; case JSON: default: registerUnicastGenerically(topic, groupId, handler, executor, null, EventV2.class); break; } } /** * 注册处理单播Topic消息的handler, * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 */ @Override public void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { switch (serializeEnum) { case KRYO: partitionAssignorMode = getPartitionAssignorMode(topic, groupId, partitionAssignorMode); register(topic, groupId, handler, executorService, partitionAssignorMode, EventV2.class, SerializeEnum.KRYO); break; case JSON: default: registerUnicastGenerically(topic, groupId, handler, executorService, partitionAssignorMode, EventV2.class); break; } } /** * 注册处理广播Topic消息的无业务线程池的Handler * * @param topic 主题 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 */ @Override public void registerBroadcastWithoutThreadPool(@Nonnull String topic, @Nonnull GenericEventHandler handler, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { switch (serializeEnum) { case KRYO: String groupId = idGenerator.createGroupId(topic); registerUnicastWithoutThreadPool(topic, groupId, handler, partitionAssignorMode, serializeEnum); break; case JSON: default: registerBroadcastWithoutThreadPoolGenerically(topic, handler, partitionAssignorMode, EventV2.class); break; } } /** * 注册处理单播Topic消息的无业务线程池的Handler * * @param topic 主题 * @param groupId 消费者组 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 */ @Override public void registerUnicastWithoutThreadPool(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { switch (serializeEnum) { case KRYO: partitionAssignorMode = getPartitionAssignorMode(topic, groupId, partitionAssignorMode); register(topic, groupId, handler, null, partitionAssignorMode, EventV2.class, SerializeEnum.JSON); break; case JSON: default: registerUnicastWithoutThreadPoolGenerically(topic, groupId, handler, partitionAssignorMode, EventV2.class); break; } }
10-10
public interface CacheService { @Nullable <T> T get(String cacheName, @NonNull String key, @NonNull Class<T> clazz); /** @deprecated */ @Nullable @Deprecated <T> T get(String cacheName, @NonNull String key, @NonNull BiFunction<String, String, T> loadHandle, @NonNull Class<T> clazz); Stream<String> getKeysByPattern(String cacheName, @NonNull String pattern); <T> void set(String cacheName, @NonNull String key, @NonNull T value); <T> void set(String cacheName, @NonNull String key, @NonNull T value, long timeToLive, @NonNull TimeUnit timeUnit); boolean deleteKey(String cacheName, @NonNull String key); long deleteKeyByPrefix(String cacheName, @NonNull String prefix) throws UnsupportedOperationException; boolean expireKey(String cacheName, @NonNull String key, long timeToLive, @NonNull TimeUnit timeUnit); <T> boolean replace(String cacheName, @NonNull String key, @NonNull T oldValue, @NonNull T newValue); boolean cas(String cacheName, @NonNull String key, @NonNull Version value); long getRemainTimeToLive(String cacheName, @NonNull String key); IAtomicLong getAtomicLong(String cacheName, @NonNull String key); <T> Map<String, T> getHash(String cacheName, @NonNull String key, @NonNull Class<T> clazz); @Nullable <T> T getHashValue(String cacheName, @NonNull String key, @NonNull String hashKey, @NonNull Class<T> clazz); <T> T putHashValue(String cacheName, @NonNull String key, @NonNull String hashKey, @NonNull T value); @Nullable <T> T deleteHashValue(String cacheName, @NonNull String key, @NonNull String hashKey); /** @deprecated */ @Deprecated <T> Map<String, T> getTimedHash(String cacheName, @NonNull String key, @NonNull Class<T> clazz); /** @deprecated */ @Deprecated @Nullable <T> T getTimedHashValue(String cacheName, @NonNull String key, @NonNull String hashKey, @NonNull Class<T> clazz); /** @deprecated */ @Deprecated <T> T putTimedHashValue(String cacheName, @NonNull String key, @NonNull String hashKey, @NonNull T value); /** @deprecated */ @Deprecated <T> T putTimedHashValue(String cacheName, @NonNull String key, @NonNull String hashKey, @NonNull T value, long timeToLive, @NonNull TimeUnit timeUnit); /** @deprecated */ @Deprecated @Nullable <T> T deleteTimedHashValue(String cacheName, @NonNull String key, @NonNull String hashKey); <T> boolean addSortedSetValue(String cacheName, @NonNull String key, @NonNull T value, double score); <T> int addSortedSetValueReturnSize(String cacheName, @NonNull String key, @NonNull T value, double score); <T> Collection<T> rangeSortedByScore(String cacheName, @NonNull String key, double min, double max, @NonNull Class<T> clazz); <T> boolean removeSortedSetValue(String cacheName, @NonNull String key, @NonNull T value); <T> Collection<T> pollSortedByScore(String cacheName, @NonNull String key, double min, double max, @NonNull Class<T> clazz); <T> Collection<T> pollSortedByScore(String cacheName, @NonNull String key, double min, double max, int count, @NonNull Class<T> clazz); <T> Collection<T> pollFirst(String cacheName, @NonNull String key, int count, @NonNull Class<T> clazz); <T> Collection<T> pollFirst(String cacheName, @NonNull String key, int count, double min, double max, @NonNull Class<T> clazz); @Nullable <T> T peekFirst(String cacheName, @NonNull String key, @NonNull Class<T> clazz); int getSortedSetSize(String cacheName, @NonNull String key); <T> Set<T> getSet(String cacheName, @NonNull String key, @NonNull Class<T> clazz); <T> List<T> getList(String cacheName, @NonNull String key, @NonNull Class<T> clazz); <T> Queue<T> getQueue(String cacheName, @NonNull String key, @NonNull Class<T> clazz); <T> Deque<T> getDeque(String cacheName, @NonNull String key, @NonNull Class<T> clazz); <T> BlockingQueue<T> getBlockingQueue(String cacheName, @NonNull String key, @NonNull Class<T> clazz); <T> BlockingDeque<T> getBlockingDeque(String cacheName, @NonNull String key, @NonNull Class<T> clazz); } 这是项目里面的缓存接口,我实现的部分(get)有点问题,如下,怎么修改: @Slf4j @Service public class WebSocketResultCacheService { public static final String WEBSOCKET_RESULT = "websocket:result"; private static final int FILE_ID_TIME_OUT = 30; private static final TimeUnit FILE_ID_TIME_OUT_UNIT = TimeUnit.MINUTES; @Autowired private CacheService cacheService; @Autowired private ObjectMapper objectMapper; // Jackson ObjectMapper /** * @param vmsId vmsId * @param taskId taskId * @return */ public <T> getResult(String vmsId, String taskId) { String cacheKey = buildCacheKey(vmsId, taskId); return cacheService.get(WEBSOCKET_RESULT, cacheKey, ); } /** * @param vmsId vmsId * @param taskId taskId * @param dto WebSocketResultDTO */ public <T> void setValue(String vmsId, String taskId, WebSocketResultDTO<T> dto) { String cacheKey = buildCacheKey(vmsId, taskId); // todo 修改缓存名字 RedisKey.WEBSOCKET_RESULT cacheService.set(WEBSOCKET_RESULT, cacheKey, dto, FILE_ID_TIME_OUT, FILE_ID_TIME_OUT_UNIT); } /** * @param vmsId vmsId * @param taskId taskId */ public void delete(String vmsId, String taskId) { String cacheKey = buildCacheKey(vmsId, taskId); // todo 修改缓存名字 RedisKey.WEBSOCKET_RESULT cacheService.deleteKey(WEBSOCKET_RESULT, cacheKey); } private String buildCacheKey(String vmsId, String taskId) { return String.format("websocket:result:%s:%s", vmsId, taskId); } }
10-10
模块名称:eventcenter-api,作为组件对其他开发人员提供api,模块类如下:public enum CompressionType { /** * deflater */ DEFLATER }public enum DispatchMode { DEFAULT, ROUND_ROBIN, ROUND_ROBIN_WITH_KEY }@Data @NoArgsConstructor @AllArgsConstructor public class EventCenterSendResult { private String topic; private String key; private Event sendEvent; private long timestamp; private Integer partition; }@Data @NoArgsConstructor @AllArgsConstructor public class GenericEventCenterSendResult<T> { private String topic; private String key; private T sendEvent; private long timestamp; private Integer partition; }public enum KafkaClusterEnum { /** * 默认的主Kafka集群 */ PRIMARY(0, "primary"), /** * 迁移后的新Kafka集群 */ SECONDARY(1, "secondary"); @Getter private final String value; @Getter private final Integer type; private static final Map<String, KafkaClusterEnum> VALUE_MAP = new HashMap<>(2); KafkaClusterEnum(Integer type, String value) { this.value = value; this.type = type; } public static KafkaClusterEnum resolve(String value) { return VALUE_MAP.get(value); } static { for (KafkaClusterEnum type : values()) { VALUE_MAP.put(type.getValue(), type); } } }public enum KafkaMigrationOperationEnum { /** * 切换生产者 */ REPLACE(0, "replace"), /** * 关闭生产者 */ CLOSE_PRODUCER(1, "closeProducer"), /** * 关闭消费者 */ CLOSE_CONSUMER(2, "closeConsumer"); @Getter private final String value; @Getter private final Integer type; private static final Map<String, KafkaMigrationOperationEnum> VALUE_MAP = new HashMap<>(2); KafkaMigrationOperationEnum(Integer type, String value) { this.value = value; this.type = type; } public static KafkaMigrationOperationEnum resolve(String value) { return VALUE_MAP.get(value); } static { for (KafkaMigrationOperationEnum type : values()) { VALUE_MAP.put(type.getValue(), type); } } }public class LogAccess { private LogAccess() { } public final static LogAccessor LOGGER = new LogAccessor(LogFactory.getLog(Handler.class)); }public enum PartitionAssignorMode { /** * CooperativeSticky和Sticky的结果是一样的,区别在于使用的算法不一样. CooperativeSticky是将Sticky一次重平衡的过程分割成多次过程。避免重平衡过长导致系统宕机或者影响消息消费。 */ COOPERATIVE_STICKY, /** * 从字面意义上看, Sticky 是 “ 粘性的 ” ,可以理解为分配结果是带 “ 粘性的 ” : 1. 分区的分配尽量的均衡 2. 每一次重分配的结果尽量与上一次分配结果保持一致 * 当这两个目标发生冲突时,优先保证第一个目标。第一个目标是每个分配算法都尽量尝试去完成的,而第二个目标才真正体现出StickyAssignor 特性的。 */ STICKY, /** * Kafka 默认采用 RangeAssignor 的分配算法 。 RangeAssignor 对每个 Topic 进行独立的分区分配。对于每一个 Topic ,首先对分区按照分区 ID 进行数值排序,然后订阅这个Topic * 的消费组的消费者再进行字典排序,之后尽量均衡的将分区分配给消费者。 这里只能是尽量均衡,因为分区数可能无法被消费者数量整除,那么有一些消费者就会多分配到一些分区. */ RANGE, /** * RoundRobinAssignor 的分配策略是将消费组内订阅的所有 Topic 的分区及所有消费者进行排序后尽量均衡的分配(RangeAssignor 是针对单个 Topic 的分区进行排序分配的)。 如果消费组内, * 消费者订阅的Topic列表是相同的 (每个消费者都订阅了相同的 Topic ),那么分配结果是尽量均衡的(消费者之间分配到的分区数的差值不会超过1 )。 如果订阅的Topic列表是不同的 ,那么分配结果是不保证 “ 尽量均衡” * 的 */ ROUND_ROBIN }@Getter public enum SerializeEnum { /** * Kryo 序列化,使用KryoSerializeUtil */ KRYO(0, "Kryo"), /** * Json序列化,使用JsonUtils */ JSON(1, "Json"); private final Integer type; private final String name; private static final Map<Integer, SerializeEnum> TYPE_MAP = new HashMap<>(2); static { for (SerializeEnum type : values()) { TYPE_MAP.put(type.getType(), type); } } public static SerializeEnum resolve(Integer type) { SerializeEnum serializeEnum = TYPE_MAP.get(type); if (Objects.isNull(serializeEnum)) { return JSON; } return serializeEnum; } SerializeEnum(Integer type, String name) { this.type = type; this.name = name; } }public interface CircuitBreakerStatusService { /** * 获取对应主题的熔断器状态 * * @param topicName 主题名,即熔断器名 * @return 状态String */ String getCircuitBreakerStatus(String topicName); }public interface KafkaMigrationService { /** * 切换kafka集群 * @param kafkaMigrationType 切换到新的kafka集群类型 * @return true if success, false otherwise */ boolean changeKafkaTemplate(String kafkaMigrationType); /** * 关闭kafka生产者 * @param kafkaMigrationType 待关闭kafka生产者集群类型 */ void closeProducerService(String kafkaMigrationType); /** * 关闭kafka消费者 * @param kafkaMigrationType 待关闭kafka消费者集群类型 */ void closeConsumerService(String kafkaMigrationType); }/** * 聚合事件抽象类 * * @author Fang Jiahao <fangjiahao@tp-link.com.cn> * @since 2020/6/8 */ public class AbstractAggregateDomainEvent<A> extends AbstractDomainEvent implements AggregateDomainEvent { private A source; public AbstractAggregateDomainEvent(String type) { super(type); } @Override public A source() { return source; } }@SuperBuilder @ToString public abstract class AbstractDomainEvent implements DomainEvent { protected String id = StringUtils.generateUUID(); protected Date createTime = new Date(); protected String type; public AbstractDomainEvent() { } public AbstractDomainEvent(String type) { this.type = type; } @Override public String id() { return id; } @Override public Date occurredOn() { return createTime; } @Override public String type() { return type; } protected String getClassName() { return this.getClass().getName(); } }public interface AggregateDomainEvent<A> extends DomainEvent { /** * 事件发生源 只针对由聚合产生的事件 */ A source(); default A getSource() { return source(); } }public interface DomainEvent { /** * 事件唯一标识 */ String id(); /** * 发生时间 */ Date occurredOn(); String type(); }public interface DomainEventBus extends DomainEventPublisher, DomainEventHandlerRegistry { }@Getter @AllArgsConstructor public class DomainEventExecutor { private DomainEventSubscriber subscriber; private Executor executor; @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } DomainEventExecutor that = (DomainEventExecutor) o; return subscriber.equals(that.subscriber); } @Override public int hashCode() { return Objects.hash(subscriber); } public DomainEventExecutor(DomainEventSubscriber subscriber) { this.subscriber = subscriber; } }public interface DomainEventHandler<D> { void handleEvent(final D aDomainEvent); }public interface DomainEventHandlerRegistry { /** * 废弃的异步注册方法 * * @param dClass dClass * @param subscriber 注册类 * @deprecated use {@link # register(Class<D> dClass, DomainEventSubscriber<D> subscriber, ExecutorService * executorService)} instead. */ @Deprecated <D> void register(Class<D> dClass, DomainEventSubscriber<D> subscriber); /** * 同步调用注册接口 * * @param dClass dClass * @param subscriber 注册类 * @param <D> 类 */ <D> void registerSync(Class<D> dClass, DomainEventSubscriber<D> subscriber); /** * 异步调用注册接口 * * @param dClass dClass * @param subscriber 注册类 * @param <D> 类 * @param executorService 业务线程池 */ <D> void register(Class<D> dClass, DomainEventSubscriber<D> subscriber, ExecutorService executorService); <D> void unRegister(DomainEventSubscriber<D> subscriber); }public interface DomainEventPostHandler<D extends DomainEvent> { void postEventSuccess(); void postEventFailed(); }public interface DomainEventPublisher { void publish(DomainEvent domainEvent); void publishSync(DomainEvent domainEvent); default void publishAll(List<DomainEvent> domainEvents) { for (DomainEvent aDomainEvent : domainEvents) { publish(aDomainEvent); } } }public interface DomainEventSubscriber<D> { default boolean accept(D event) { return true; } void handleEvent(final D event); default void onEventFailed(D event) { } default void onEventSuccess(D event) { } }@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface HandleEvent { Class<? extends DomainEvent>[] value(); } public class DuplicateGroupIdException extends RuntimeException { public DuplicateGroupIdException() { super(); } public DuplicateGroupIdException(String message) { super(message); } public DuplicateGroupIdException(String message, Throwable cause) { super(message, cause); } public DuplicateGroupIdException(Throwable cause) { super(cause); } }@Getter @NoArgsConstructor @SuperBuilder @AllArgsConstructor public abstract class BaseEvent<T> { protected String filterKey; protected long timeStamp; protected T message; }@Getter @NoArgsConstructor @SuperBuilder public final class Event extends BaseEvent<String> { public Event(String filterKey, String message) { this.filterKey = filterKey; this.message = message; } @Override public String toString() { return JsonUtils.bean2Json(this); } public void setTimeStamp(long timeStamp) { this.timeStamp = timeStamp; } public static Event toBean(String string) { return JsonUtils.json2bean(string, Event.class); } }/** * Event Center组件对外提供的方法 * * @author ludingyang * @version 1.0 * @since 2020/7/30. */ public interface EventCenter { /** * 获取到topic的partition数量 该接口只能获取到使用EventCenter register的topic分区数量 * * @param topic topic名 * @return partition数量,如果是不存在的topic则为0 */ default Integer getPartitions(String topic) { return 0; } /** * 发送事件,会发送到任意分区上 * * @param topic 事件主题 * @param event 事件消息主体 */ default void send(@Nonnull String topic, @Nonnull Event event) { } /** * 发送事件,包含了回调方法 * * @param topic 事件主题 * @param event 事件消息主体 * @param eventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方法); onFailure(发送失败后的回调方法) */ default void send(@Nonnull String topic, @Nonnull Event event, EventFuture eventFuture) { } /** * 发送事件,相同key值的消息会发送到同一个分区上 * * @param topic 事件主题 * @param key 发送消息的key值,用于将相同key值的消息发送到同一分区中 * @param event 事件消息主体 */ default void send(@Nonnull String topic, String key, @Nonnull Event event) { } /** * 发送事件,相同key值的消息会发送到同一个分区上 * * @param topic 事件主题 * @param key 发送消息的key值,用于将相同key值的消息发送到同一分区中 * @param event 事件消息主体 * @param eventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方法); onFailure(发送失败后的回调方法) */ default void send(@Nonnull String topic, String key, @Nonnull Event event, EventFuture eventFuture) { } /** * 发送事件,消息会发送到分区partition上 * * @param topic 事件主题 * @param partition 分区 * @param event 事件消息主体 */ default void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull Event event) { } /** * 发送事件,消息会发送到分区partition上 * * @param topic 事件主题 * @param partition 分区 * @param event 事件消息主体 * @param eventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方法); onFailure(发送失败后的回调方法) */ default void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull Event event, EventFuture eventFuture) { } /** * 发送事件,会发送到任意分区上 * * @param topic 事件主题 * @param event 事件消息主体,如果serializeEnum采用Kryo序列化,event类型需要为EventV2;如果采用Json序列化,event类型为Event * @param serializeEnum 采用的序列化方式 */ default void send(@Nonnull String topic, @Nonnull BaseEvent event, @Nonnull SerializeEnum serializeEnum) { } /** * 发送事件,包含了回调方法 * * @param topic 事件主题 * @param event 事件消息主体,如果serializeEnum采用Kryo序列化,event类型需要为EventV2;如果采用Json序列化,event类型为Event * @param eventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方法); onFailure(发送失败后的回调方法) * @param serializeEnum 采用的序列化方式 */ default void send(@Nonnull String topic, @Nonnull BaseEvent event, GenericEventFuture eventFuture, @Nonnull SerializeEnum serializeEnum) { } /** * 发送事件,相同key值的消息会发送到同一个分区上 * * @param topic 事件主题 * @param key 发送消息的key值,用于将相同key值的消息发送到同一分区中 * @param event 事件消息主体,如果serializeEnum采用Kryo序列化,event类型需要为EventV2;如果采用Json序列化,event类型为Event * @param serializeEnum 采用的序列化方式 */ default void send(@Nonnull String topic, String key, @Nonnull BaseEvent event, @Nonnull SerializeEnum serializeEnum) { } /** * 发送事件,相同key值的消息会发送到同一个分区上 * * @param topic 事件主题 * @param key 发送消息的key值,用于将相同key值的消息发送到同一分区中 * @param event 事件消息主体,如果serializeEnum采用Kryo序列化,event类型需要为EventV2;如果采用Json序列化,event类型为Event * @param eventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方法); onFailure(发送失败后的回调方法) * @param serializeEnum 采用的序列化方式 */ default void send(@Nonnull String topic, String key, @Nonnull BaseEvent event, GenericEventFuture eventFuture, @Nonnull SerializeEnum serializeEnum) { } /** * 发送事件,消息会发送到分区partition上 * * @param topic 事件主题 * @param partition 分区 * @param event 事件消息主体,如果serializeEnum采用Kryo序列化,event类型需要为EventV2;如果采用Json序列化,event类型为Event * @param serializeEnum 采用的序列化方式 */ default void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull BaseEvent event, @Nonnull SerializeEnum serializeEnum) { } /** * 发送事件,消息会发送到分区partition上 * * @param topic 事件主题 * @param partition 分区 * @param event 事件消息主体,如果serializeEnum采用Kryo序列化,event类型需要为EventV2;如果采用Json序列化,event类型为Event * @param eventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方法); onFailure(发送失败后的回调方法) * @param serializeEnum 采用的序列化方式 */ default void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull BaseEvent event, GenericEventFuture eventFuture, @Nonnull SerializeEnum serializeEnum) { } /** * 注册处理广播事件的handler(默认分区分配策略为COOPERATIVE_STICKY) * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 */ default void registerBroadcast(@Nonnull String topic, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService) { } /** * 注册处理广播事件的handler * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 */ default void registerBroadcast(@Nonnull String topic, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode) { } /** * 注册处理单播事件的handler(默认分区分配策略为COOPERATIVE_STICKY) * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 */ default void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService) { } /** * 注册处理单播事件的handler * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 */ default void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode) { } /** * 注册处理广播事件的handler(不传线程池) * * @param topic 主题 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 */ default void registerBroadcastWithoutThreadPool(@Nonnull String topic, @Nonnull EventHandler handler, PartitionAssignorMode partitionAssignorMode) { } /** * 注册处理单播事件的handler(不传线程池) * * @param topic 主题 * @param groupId 消费者组 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 */ default void registerUnicastWithoutThreadPool(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, PartitionAssignorMode partitionAssignorMode) { } /** * 解注册一个主题下的handler * * @param topic 主题 * @param handler 事件处理类 */ default void unregister(@Nonnull String topic, @Nonnull EventHandler handler) { } /** * 发送事件,会发送到任意分区上 * * @param topic 事件主题 * @param event 事件消息主体 */ default <T> void sendGenerically(@Nonnull String topic, @Nonnull T event) { } /** * 发送事件,包含了回调方法 * * @param topic 事件主题 * @param event 事件消息主体 * @param genericEventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方法); onFailure(发送失败后的回调方法) */ default <T> void sendGenerically(@Nonnull String topic, @Nonnull T event, GenericEventFuture<T> genericEventFuture) { } /** * 发送事件,相同key值的消息会发送到同一个分区上 * * @param topic 事件主题 * @param key 发送消息的key值,用于将相同key值的消息发送到同一分区中 * @param event 事件消息主体 */ default <T> void sendGenerically(@Nonnull String topic, String key, @Nonnull T event) { } /** * 发送事件,相同key值的消息会发送到同一个分区上 * * @param topic 事件主题 * @param key 发送消息的key值,用于将相同key值的消息发送到同一分区中 * @param event 事件消息主体 * @param genericEventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方法); onFailure(发送失败后的回调方法) */ default <T> void sendGenerically(@Nonnull String topic, String key, @Nonnull T event, GenericEventFuture<T> genericEventFuture) { } /** * 发送事件,消息会发送到分区partition上 * * @param topic 事件主题 * @param partition 分区 * @param event 事件消息主体 */ default <T> void sendGenerically(@Nonnull String topic, @Nonnull Integer partition, @Nonnull T event) { } /** * 发送事件,消息会发送到分区partition上 * * @param topic 事件主题 * @param partition 分区 * @param event 事件消息主体 * @param genericEventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方法); onFailure(发送失败后的回调方法) */ default <T> void sendGenerically(@Nonnull String topic, @Nonnull Integer partition, @Nonnull T event, GenericEventFuture<T> genericEventFuture) { } /** * 注册处理广播事件的handler(默认分区分配策略为COOPERATIVE_STICKY) * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param clazz 定义类 */ default <T> void registerBroadcastGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, @NonNull Class<T> clazz) { } /** * 注册处理广播事件的handler * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 * @param clazz 定义类 */ default <T> void registerBroadcastGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { } /** * 注册处理单播事件的handler(默认分区分配策略为COOPERATIVE_STICKY) * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param clazz 定义类 */ default <T> void registerUnicastGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, @NonNull Class<T> clazz) { } /** * 注册处理单播事件的handler * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 * @param clazz 定义类 */ default <T> void registerUnicastGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { } /** * 注册处理广播事件的handler(不传线程池) * * @param topic 主题 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 * @param clazz 定义类 */ default <T> void registerBroadcastWithoutThreadPoolGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { } /** * 注册处理单播事件的handler(不传线程池) * * @param topic 主题 * @param groupId 消费者组 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 * @param clazz 定义类 */ default <T> void registerUnicastWithoutThreadPoolGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { } /** * 解注册一个主题下的handler * * @param topic 主题 * @param handler 事件处理类 */ default <T> void unregisterGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler) { } /** * 在不销毁executorService的场景下,解注册单个topic * @param topic 主题 * @param handler 事件处理类 * @param isDestroyExecutorService 是否需要销毁线程池 */ default <T> void unregisterGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, boolean isDestroyExecutorService) { } /** * 在不销毁executorService的场景下,解注册单个topic * @param topic 主题 * @param eventHandler 事件处理类 * @param isDestroyExecutorService 是否需要销毁线程池 */ default void unregister(@Nonnull String topic, @Nonnull EventHandler eventHandler, boolean isDestroyExecutorService) { } /** * 注册处理广播事件的handler(默认分区分配策略为COOPERATIVE_STICKY) * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param serializeEnum 采用的序列化方式 */ default void registerBroadcast(@Nonnull String topic, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, @Nonnull SerializeEnum serializeEnum) { } /** * 注册处理广播事件的handler * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 * @param serializeEnum 采用的序列化方式 */ default void registerBroadcast(@Nonnull String topic, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { } /** * 注册处理单播事件的handler(默认分区分配策略为COOPERATIVE_STICKY) * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param serializeEnum 采用的序列化方式 */ default void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, @Nonnull SerializeEnum serializeEnum) { } /** * 注册处理单播事件的handler * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 * @param serializeEnum 采用的序列化方式 */ default void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { } /** * 注册处理广播事件的handler(不传线程池) * * @param topic 主题 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 * @param serializeEnum 采用的序列化方式 */ default void registerBroadcastWithoutThreadPool(@Nonnull String topic, @Nonnull GenericEventHandler handler, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { } /** * 注册处理单播事件的handler(不传线程池) * * @param topic 主题 * @param groupId 消费者组 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 * @param serializeEnum 采用的序列化方式 */ default void registerUnicastWithoutThreadPool(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { } /** * 解注册所有的topic */ default void unregisterAllTopics() { } /** * 销毁EventCenter时释放资源 */ @PreDestroy default void destroy() { } }public interface EventFuture { /** * 发送成功后的回调函数 * * @param eventCenterSendResult 发送结果 */ void onSuccess(EventCenterSendResult eventCenterSendResult); /** * 发送失败后的回调函数 * * @param throwable 发送异常 */ void onFailure(Throwable throwable); }public interface EventHandler extends Handler { /** * 业务处理的方法 * * @param event 传递的消息封装类 */ void handleEvent(Event event); }@Getter @NoArgsConstructor @SuperBuilder @Slf4j @ToString public final class EventV2<T> extends BaseEvent<T> { public EventV2(String filterKey, T message) { this.filterKey = filterKey; this.message = message; } public void setTimeStamp(long timeStamp) { this.timeStamp = timeStamp; } public static EventV2 toBean(byte[] bytes) { return KryoSerializeUtils.byteArray2Bean(bytes, EventV2.class); } public byte[] kryoSerialize() { return KryoSerializeUtils.bean2ByteArray(this); } }public interface GenericEventFuture<T> { /** * 发送成功后的回调函数 * * @param genericEventCenterSendResult 发送结果 */ void onSuccess(GenericEventCenterSendResult<T> genericEventCenterSendResult); /** * 发送失败后的回调函数 * * @param throwable 发送异常 */ void onFailure(Throwable throwable); }public interface GenericEventHandler<T> extends Handler { /** * 业务处理的方法 * * @param event 传递的消息封装类 */ void handleEvent(T event); }public interface Handler { /** * 重平衡之前可以调用执行 可以做一些简单的操作,不建议执行耗时操作,不然会拉长重平衡时间 对于eager rebalance:STICKY,RANGE,ROUND_ROBIN;每次进行重平衡时都会触发一次。 * 对于cooperative rebalance:COOPERATIVE_STICKY;只有在consumer被分配的partitions被主动销毁或者consumer准备离开consumer group时才会触发一次 */ default void doBeforeRebalance() { LogAccess.LOGGER.info("start to process rebalance!"); } /** * 重平衡之后可以调用执行 可以做一些简单的操作,不建议执行耗时操作,不然会拉长重平衡时间 每次重平衡结束后会触发一次 */ default void doAfterRebalance() { LogAccess.LOGGER.info("ending rebalance!"); } }
09-18
public enum CompressionType { /** * deflater */ DEFLATER } /** * 分发策略,取值范围为:default、roundRobin、roundRobinWithKey roundRobin:实现负载均衡 的分发策略; default:实现随机的分发策略 * roundRobinWithKey:自定义的分发算法(实现负载均衡以及实现根据key的Hash值取余发送消息) * * @author ludingyang * @version 1.0 * @since 2021/1/26 */ public enum DispatchMode { DEFAULT, ROUND_ROBIN, ROUND_ROBIN_WITH_KEY } @Data @NoArgsConstructor @AllArgsConstructor public class EventCenterSendResult { private String topic; private String key; private Event sendEvent; private long timestamp; private Integer partition; } /** * 发送结果的封装类 * * @author ludingyang * @version 1.0 * @since 2021/3/17 */ @Data @NoArgsConstructor @AllArgsConstructor public class GenericEventCenterSendResult<T> { private String topic; private String key; private T sendEvent; private long timestamp; private Integer partition; } /** * Kafka迁移集群类型枚举 * * @author Zhou Wenpei * @version 1.0 * @since 2023/6/2 */ public enum KafkaClusterEnum { /** * 默认的主Kafka集群 */ PRIMARY(0, "primary"), /** * 迁移后的新Kafka集群 */ SECONDARY(1, "secondary"); @Getter private final String value; @Getter private final Integer type; (2); private static final Map<String, KafkaClusterEnum> VALUE_MAP = new HashMap<> KafkaClusterEnum(Integer type, String value) { this.value = value; this.type = type; } public static KafkaClusterEnum resolve(String value) { return VALUE_MAP.get(value); } static { for (KafkaClusterEnum type : values()) { VALUE_MAP.put(type.getValue(), type); } } } /** * kafka迁移操作枚举 * * @author Zhou Wenpei * @version 1.0 * @since 2023/6/13 */ public enum KafkaMigrationOperationEnum { /** * 切换生产者 */ REPLACE(0, "replace"), /** * 关闭生产者 */ CLOSE_PRODUCER(1, "closeProducer"), /** * 关闭消费者 */ CLOSE_CONSUMER(2, "closeConsumer"); @Getter private final String value; @Getter private final Integer type; private static final Map<String, KafkaMigrationOperationEnum> VALUE_MAP = new HashMap<>(2); KafkaMigrationOperationEnum(Integer type, String value) { this.value = value; this.type = type; } public static KafkaMigrationOperationEnum resolve(String value) { return VALUE_MAP.get(value); } static { for (KafkaMigrationOperationEnum type : values()) { VALUE_MAP.put(type.getValue(), type); } } } public class LogAccess { private LogAccess() { } public final static LogAccessor LOGGER = new LogAccessor(LogFactory.getLog(Handler.class)); } /** * 分区分配策略的枚举类 * * @author ludingyang * @version 1.0 * @since 2021/1/26 */ public enum PartitionAssignorMode { /** * CooperativeSticky和Sticky的结果是一样的,区别在于使用的算法不一样. CooperativeSticky是将Sticky一次重平衡的过程分割成多次过程。避免重平衡过长导致系统宕机或者影 响消息消费。 */ COOPERATIVE_STICKY, /** * 从字面意义上看, Sticky 是 “ 粘性的 ” ,可以理解为分配结果是带 “ 粘性的 ” : 1. 分区 的分配尽量的均衡 2. 每一次重分配的结果尽量与上一次分配结果保持一致 * 当这两个目标发生冲突时,优先保证第一个目标。第一个目标是每个分配算法都尽量尝试去完成的, 而第二个目标才真正体现出StickyAssignor 特性的。 */ STICKY, /** * Kafka 默认采用 RangeAssignor 的分配算法 。 RangeAssignor 对每个 Topic 进行独立的 分区分配。对于每一个 Topic ,首先对分区按照分区 ID 进行数值排序,然后订阅这个Topic * 的消费组的消费者再进行字典排序,之后尽量均衡的将分区分配给消费者。 这里只能是尽量均衡, 因为分区数可能无法被消费者数量整除,那么有一些消费者就会多分配到一些分区. */ RANGE, /** * RoundRobinAssignor 的分配策略是将消费组内订阅的所有 Topic 的分区及所有消费者进行排 序后尽量均衡的分配(RangeAssignor 是针对单个 Topic 的分区进行排序分配的)。 如果消费组内, * 消费者订阅的Topic列表是相同的 (每个消费者都订阅了相同的 Topic ),那么分配结果是尽量 均衡的(消费者之间分配到的分区数的差值不会超过1 )。 如果订阅的Topic列表是不同的 ,那么分配结果 是不保证 “ 尽量均衡” * 的 */ ROUND_ROBIN } /** * 序列化方式枚举类 * * @author Zhou Wenpei * @version 1.0 * @since 2023/9/12 */ @Getter public enum SerializeEnum { /** * Kryo 序列化,使用KryoSerializeUtil */ KRYO(0, "Kryo"), /** * Json序列化,使用JsonUtils */ JSON(1, "Json"); private final Integer type; private final String name; private static final Map<Integer, SerializeEnum> TYPE_MAP = new HashMap<> (2); static { for (SerializeEnum type : values()) { TYPE_MAP.put(type.getType(), type); } } public static SerializeEnum resolve(Integer type) { SerializeEnum serializeEnum = TYPE_MAP.get(type); if (Objects.isNull(serializeEnum)) { return JSON; } return serializeEnum; } SerializeEnum(Integer type, String name) { this.type = type; this.name = name; } } /** * 获取熔断器状态 * * @author Zhou Wenpei * @version 1.0 * @since 2023/5/17 */ public interface CircuitBreakerStatusService { /** * 获取对应主题的熔断器状态 * * @param topicName 主题名,即熔断器名 * @return 状态String */ String getCircuitBreakerStatus(String topicName); } public interface KafkaMigrationService { /** * 切换kafka集群 * @param kafkaMigrationType 切换到新的kafka集群类型 * @return true if success, false otherwise */ boolean changeKafkaTemplate(String kafkaMigrationType); /** * 关闭kafka生产者 * @param kafkaMigrationType 待关闭kafka生产者集群类型 */ void closeProducerService(String kafkaMigrationType); /** * 关闭kafka消费者 * @param kafkaMigrationType 待关闭kafka消费者集群类型 */ void closeConsumerService(String kafkaMigrationType); } public class AbstractAggregateDomainEvent<A> extends AbstractDomainEvent implements AggregateDomainEvent { private A source; public AbstractAggregateDomainEvent(String type) { super(type); } @Override public A source() { return source; } } @SuperBuilder @ToString public abstract class AbstractDomainEvent implements DomainEvent { protected String id = StringUtils.generateUUID(); protected Date createTime = new Date(); protected String type; public AbstractDomainEvent() { } public AbstractDomainEvent(String type) { this.type = type; } @Override public String id() { return id; } @Override public Date occurredOn() { return createTime; } @Override public String type() { return type; } protected String getClassName() { return this.getClass().getName(); } } public interface AggregateDomainEvent<A> extends DomainEvent { /** * 事件发生源 只针对由聚合产生的事件 */ A source(); default A getSource() { return source(); } } public interface DomainEvent { /** * 事件唯一标识 */ String id(); /** * 发生时间 */ Date occurredOn(); String type(); } /** * 扩展自 DomainEventPublisher 和 DomainEventHandlerRegistry 用于发布和管理领域事件处 理器 * * @author Fang Jiahao <fangjiahao@tp-link.com.cn> * @since 2020/6/8 */ public interface DomainEventBus extends DomainEventPublisher, DomainEventHandlerRegistry { } /** * 用于执行领域事件处理器 * * @author Fang Jiahao <fangjiahao@tp-link.com.cn> * @since 2020/6/8 */ @Getter @AllArgsConstructor public class DomainEventExecutor { private DomainEventSubscriber subscriber; private Executor executor; @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } DomainEventExecutor that = (DomainEventExecutor) o; return subscriber.equals(that.subscriber); } @Override public int hashCode() { return Objects.hash(subscriber); } public DomainEventExecutor(DomainEventSubscriber subscriber) { this.subscriber = subscriber; } } /** * 用于处理领域事件 * * @author Fang Jiahao <fangjiahao@tp-link.com.cn> * @since 2020/6/8 */ public interface DomainEventHandler<D> { } void handleEvent(final D aDomainEvent); /** * 用于注册 DomainEventHandler * * @author Fang Jiahao <fangjiahao@tp-link.com.cn> * @since 2020/6/8 */ public interface DomainEventHandlerRegistry { /** * 废弃的异步注册方法 * * @param dClass dClass * @param subscriber 注册类 * @deprecated use {@link # register(Class<D> dClass, DomainEventSubscriber<D> subscriber, ExecutorService * executorService)} instead. */ @Deprecated <D> void register(Class<D> dClass, DomainEventSubscriber<D> subscriber); /** * 同步调用注册接口 * * @param dClass dClass * @param subscriber 注册类 * @param <D> 类 */ <D> void registerSync(Class<D> dClass, DomainEventSubscriber<D> subscriber); /** * 异步调用注册接口 * * @param dClass * @param subscriber * @param <D> dClass 注册类 类 * @param executorService 业务线程池 */ <D> void register(Class<D> dClass, DomainEventSubscriber<D> subscriber, ExecutorService executorService); <D> void unRegister(DomainEventSubscriber<D> subscriber); } /** * 回调函数 * * @author Sun Xiaoyu * @version 1.0 * @since 2020-07-07 */ public interface DomainEventPostHandler<D extends DomainEvent> { void postEventSuccess(); } void postEventFailed(); /** * 用于发布领域事件 * * @author Fang Jiahao <fangjiahao@tp-link.com.cn> * @since 2020/6/8 */ public interface DomainEventPublisher { void publish(DomainEvent domainEvent); void publishSync(DomainEvent domainEvent); default void publishAll(List<DomainEvent> domainEvents) { for (DomainEvent aDomainEvent : domainEvents) { publish(aDomainEvent); } } } /** * 用于判断是否接受领域事件 处理领域事件 * * @author Fang Jiahao <fangjiahao@tp-link.com.cn> * @since 2020/6/4 */ public interface DomainEventSubscriber<D> { default boolean accept(D event) { return true; } void handleEvent(final D event); default void onEventFailed(D event) { } } } default void onEventSuccess(D event) { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface HandleEvent { } Class<? extends DomainEvent>[] value(); public class DuplicateGroupIdException extends RuntimeException { public DuplicateGroupIdException() { super(); } public DuplicateGroupIdException(String message) { super(message); } } public DuplicateGroupIdException(String message, Throwable cause) { super(message, cause); } public DuplicateGroupIdException(Throwable cause) { super(cause); } public class JsonUtils { /** * can reuse, share globally */ private static ObjectMapper mapper = new ObjectMapper(); public static ObjectMapper getMapper() { return mapper; } public static void setMapper(ObjectMapper mapper) { JsonUtils.mapper = mapper; } private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class); public static <T> T readFile(File file, Class<T> tClass) { try { return mapper.readValue(file, tClass); } catch (IOException e) { logger.warn("Parse json message exception .", e); return null; } } public static <T> T readInputStream(InputStream inputStream, Class<T> tClass) { try { return mapper.readValue(inputStream, tClass); } catch (IOException e) { logger.warn("Parse json message exception .", e); return null; } } public static String bean2Json(Object object) { try { return mapper.writeValueAsString(object); } catch (JsonProcessingException e) { logger.warn("fail to transfer bean to Json", e); return null; } } public static byte[] bean2Bytes(Object object) { try { return mapper.writeValueAsBytes(object); } catch (JsonProcessingException e) { logger.warn("fail to transfer bean to bytes", e); return null; } } public static <T> T json2bean(String json, Class<T> clazz) { try { return mapper.readValue(json, clazz); } catch (IOException e) { logger.debug("Parse json message exception. jsonString:{}, class:{}", json, clazz, e); return null; } } public static <T> T map2Bean(Map map, Class<T> tClass) { return mapper.convertValue(map, tClass); } public static <T> List<? super T> json2list(String json, Class<T> tClass) { JavaType type = getCollectionType(List.class, tClass); try { return mapper.readValue(json, type); } catch (IOException e) { logger.warn("fail to transfer json to list .", e); return null; } } public static Map<String, Object> json2Map(String json) { TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() { }; try { return mapper.readValue(json, typeRef); } catch (IOException e) { logger.warn("fail to transfer json to map .", e); return null; } } public static Map<String, Object> json2MapWithoutLog(String json) { TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() { }; try { return mapper.readValue(json, typeRef); } catch (IOException e) { return null; } } public static JavaType getCollectionType(Class<?> collectionClass, Class<?> elementClasses) { return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses); } } /** * Kryo序列化、反序列化类 * * @author Zhou Wenpei * @version 1.0 * @since 2023/8/11 */ @Slf4j public class KryoSerializeUtils { /** * 线上大都小于10K,由于粒度问题无法查看细致的大小,暂定初始大小为5K */ private static final int KRYO_BUFFER_SIZE = 5 * 1024; private KryoSerializeUtils() { } /** * 线程不安全,通过ThreadLocal实现 */ private static final ThreadLocal<Kryo> KRYOS = ThreadLocal.withInitial(() -> { // 在此处配置kryo对象 Kryo kryo = new Kryo(); kryo.setRegistrationRequired(false); return kryo; }); /** * Kryo 序列化序列化失败将返回空字节数组 */ public static byte[] bean2ByteArray(Object object) { try (Output output = new Output(KRYO_BUFFER_SIZE, -1)) { Kryo kryo = KRYOS.get(); kryo.writeObject(output, object); return output.toBytes(); } catch (Exception e) { log.warn("kryo serial object failed, exception :{}", e); return new byte[0]; } } /** * Kryo 反序列化,反序列化失败将返回空对象 */ public static <T> T byteArray2Bean(byte[] source, Class<T> destinationClass) { Kryo kryo = KRYOS.get(); try (Input input = new Input(source)) { return kryo.readObject(input, destinationClass); } catch (Exception e) { log.warn("kryo deserialize object failed, exception :{}", e); } return null; } public static void clearKryo() { KRYOS.remove(); } } public class StringUtils { private StringUtils() { } public static String generateUUID() { return UUID.randomUUID().toString().replace("-", ""); } } @Getter @NoArgsConstructor @SuperBuilder @AllArgsConstructor public abstract class BaseEvent<T> { protected String filterKey; protected long timeStamp; protected T message; } /** * 事件中心用于传递事件的类,eventStr为从消息中间件拿到的具体事件,反序列化工作由业务层完成 * * @author ludingyang * @version 1.0 * @since 2020/6/29. */ @Getter @NoArgsConstructor @SuperBuilder public final class Event extends BaseEvent<String> { public Event(String filterKey, String message) { this.filterKey = filterKey; this.message = message; } @Override public String toString() { return JsonUtils.bean2Json(this); } public void setTimeStamp(long timeStamp) { this.timeStamp = timeStamp; } public static Event toBean(String string) { return JsonUtils.json2bean(string, Event.class); } } /** * Event Center组件对外提供的方法 * * @author ludingyang * @version 1.0 * @since 2020/7/30. */ public interface EventCenter { /** * 获取到topic的partition数量 该接口只能获取到使用EventCenter register的topic分区数 量 * * @param topic topic名 * @return partition数量,如果是不存在的topic则为0 */ default Integer getPartitions(String topic) { return 0; } /** * 发送事件,会发送到任意分区上 * * @param topic 事件主题 * @param event 事件消息主体 */ default void send(@Nonnull String topic, @Nonnull Event event) { } /** * 发送事件,包含了回调方法 * * @param topic 事件主题 * @param event 事件消息主体 * @param eventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方 法); onFailure(发送失败后的回调方法) */ default void send(@Nonnull String topic, @Nonnull Event event, EventFuture eventFuture) { } /** * 发送事件,相同key值的消息会发送到同一个分区上 * * @param topic 事件主题 * @param key 发送消息的key值,用于将相同key值的消息发送到同一分区中 * @param event 事件消息主体 */ default void send(@Nonnull String topic, String key, @Nonnull Event event) { } /** * 发送事件,相同key值的消息会发送到同一个分区上 * * @param topic 事件主题 * @param key 发送消息的key值,用于将相同key值的消息发送到同一分区中 * @param event 事件消息主体 * @param eventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方 法); onFailure(发送失败后的回调方法) */ default void send(@Nonnull String topic, String key, @Nonnull Event event, EventFuture eventFuture) { } /** * 发送事件,消息会发送到分区partition上 * * @param topic 事件主题 * @param partition 分区 * @param event 事件消息主体 */ default void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull Event event) { } /** * 发送事件,消息会发送到分区partition上 * * @param topic 事件主题 * @param partition 分区 * @param event 事件消息主体 * @param eventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方 法); onFailure(发送失败后的回调方法) */ default void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull Event event, EventFuture eventFuture) { } /** * 发送事件,会发送到任意分区上 * * @param topic 事件主题 * @param event 事件消息主体,如果serializeEnum采用Kryo序列化,event类型需要为 EventV2;如果采用Json序列化,event类型为Event * @param serializeEnum 采用的序列化方式 */ default void send(@Nonnull String topic, @Nonnull BaseEvent event, @Nonnull SerializeEnum serializeEnum) { } /** * 发送事件,包含了回调方法 * * @param topic 事件主题 * @param event 事件消息主体,如果serializeEnum采用Kryo序列化,event类型需要 为EventV2;如果采用Json序列化,event类型为Event * @param eventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方 法); onFailure(发送失败后的回调方法) * @param serializeEnum 采用的序列化方式 */ default void send(@Nonnull String topic, @Nonnull BaseEvent event, GenericEventFuture eventFuture, @Nonnull SerializeEnum serializeEnum) { } /** * 发送事件,相同key值的消息会发送到同一个分区上 * * @param topic 事件主题 * @param key 发送消息的key值,用于将相同key值的消息发送到同一分区中 * @param event 事件消息主体,如果serializeEnum采用Kryo序列化,event类型需要为 EventV2;如果采用Json序列化,event类型为Event * @param serializeEnum 采用的序列化方式 */ default void send(@Nonnull String topic, String key, @Nonnull BaseEvent event, @Nonnull SerializeEnum serializeEnum) { } /** * 发送事件,相同key值的消息会发送到同一个分区上 * * @param topic 事件主题 * @param key 发送消息的key值,用于将相同key值的消息发送到同一分区中 * @param event 事件消息主体,如果serializeEnum采用Kryo序列化,event类型需要 为EventV2;如果采用Json序列化,event类型为Event * @param eventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方 法); onFailure(发送失败后的回调方法) * @param serializeEnum 采用的序列化方式 */ default void send(@Nonnull String topic, String key, @Nonnull BaseEvent event, GenericEventFuture eventFuture, @Nonnull SerializeEnum serializeEnum) { } /** * 发送事件,消息会发送到分区partition上 * * @param topic 事件主题 * @param partition 分区 * @param event 事件消息主体,如果serializeEnum采用Kryo序列化,event类型需要为 EventV2;如果采用Json序列化,event类型为Event * @param serializeEnum 采用的序列化方式 */ default void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull BaseEvent event, @Nonnull SerializeEnum serializeEnum) { } /** * 发送事件,消息会发送到分区partition上 * * @param topic 事件主题 * @param partition 分区 * @param event 事件消息主体,如果serializeEnum采用Kryo序列化,event类型需要 为EventV2;如果采用Json序列化,event类型为Event * @param eventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功后的回调方 法); onFailure(发送失败后的回调方法) * @param serializeEnum 采用的序列化方式 */ default void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull BaseEvent event, GenericEventFuture eventFuture, @Nonnull SerializeEnum serializeEnum) { } /** * 注册处理广播事件的handler(默认分区分配策略为COOPERATIVE_STICKY) * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 */ default void registerBroadcast(@Nonnull String topic, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService) { } /** * 注册处理广播事件的handler * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 */ default void registerBroadcast(@Nonnull String topic, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode) { } /** * 注册处理单播事件的handler(默认分区分配策略为COOPERATIVE_STICKY) * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 */ default void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService) { } /** * 注册处理单播事件的handler * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 */ default void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode) { } /** * 注册处理广播事件的handler(不传线程池) * * @param topic 主题 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 */ default void registerBroadcastWithoutThreadPool(@Nonnull String topic, @Nonnull EventHandler handler, PartitionAssignorMode partitionAssignorMode) { } /** * 注册处理单播事件的handler(不传线程池) * * @param topic 主题 * @param groupId 消费者组 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 */ default void registerUnicastWithoutThreadPool(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, PartitionAssignorMode partitionAssignorMode) { } /** * 解注册一个主题下的handler * * @param topic 主题 * @param handler 事件处理类 */ default void unregister(@Nonnull String topic, @Nonnull EventHandler handler) { } /** * 发送事件,会发送到任意分区上 * * @param topic 事件主题 * @param event 事件消息主体 */ default <T> void sendGenerically(@Nonnull String topic, @Nonnull T event) { } /** * 发送事件,包含了回调方法 * * @param topic 事件主题 * @param event 事件消息主体 * @param genericEventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功 后的回调方法); onFailure(发送失败后的回调方法) */ default <T> void sendGenerically(@Nonnull String topic, @Nonnull T event, GenericEventFuture<T> genericEventFuture) { } /** * 发送事件,相同key值的消息会发送到同一个分区上 * * @param topic 事件主题 * @param key 发送消息的key值,用于将相同key值的消息发送到同一分区中 * @param event 事件消息主体 */ default <T> void sendGenerically(@Nonnull String topic, String key, @Nonnull T event) { } /** * 发送事件,相同key值的消息会发送到同一个分区上 * * @param topic 事件主题 * @param key 发送消息的key值,用于将相同key值的消息发送到同一分区中 * @param event 事件消息主体 * @param genericEventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功 后的回调方法); onFailure(发送失败后的回调方法) */ default <T> void sendGenerically(@Nonnull String topic, String key, @Nonnull T event, GenericEventFuture<T> genericEventFuture) { } /** * 发送事件,消息会发送到分区partition上 * * @param topic 事件主题 * @param partition 分区 * @param event 事件消息主体 */ default <T> void sendGenerically(@Nonnull String topic, @Nonnull Integer partition, @Nonnull T event) { } /** * 发送事件,消息会发送到分区partition上 * * @param topic 事件主题 * @param partition 分区 * @param event 事件消息主体 * @param genericEventFuture 包含发送成功或失败后执行的回调方法:onSuccess(发送成功 后的回调方法); onFailure(发送失败后的回调方法) */ default <T> void sendGenerically(@Nonnull String topic, @Nonnull Integer partition, @Nonnull T event, GenericEventFuture<T> genericEventFuture) { } /** * 注册处理广播事件的handler(默认分区分配策略为COOPERATIVE_STICKY) * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param clazz 定义类 */ default <T> void registerBroadcastGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, @NonNull Class<T> clazz) { } /** * 注册处理广播事件的handler * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 * @param clazz 定义类 */ default <T> void registerBroadcastGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { } /** * 注册处理单播事件的handler(默认分区分配策略为COOPERATIVE_STICKY) * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param clazz 定义类 */ default <T> void registerUnicastGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, @NonNull Class<T> clazz) { } /** * 注册处理单播事件的handler * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 * @param clazz 定义类 */ default <T> void registerUnicastGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { } /** * 注册处理广播事件的handler(不传线程池) * * @param topic 主题 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 * @param clazz 定义类 */ default <T> void registerBroadcastWithoutThreadPoolGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { } /** * 注册处理单播事件的handler(不传线程池) * * @param topic 主题 * @param groupId 消费者组 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 * @param clazz 定义类 */ default <T> void registerUnicastWithoutThreadPoolGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) { } /** * 解注册一个主题下的handler * * @param topic 主题 * @param handler 事件处理类 */ default <T> void unregisterGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler) { } /** * 在不销毁executorService的场景下,解注册单个topic * @param topic 主题 * @param handler 事件处理类 * @param isDestroyExecutorService 是否需要销毁线程池 */ default <T> void unregisterGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, boolean isDestroyExecutorService) { } /** * 在不销毁executorService的场景下,解注册单个topic * @param topic 主题 * @param eventHandler 事件处理类 * @param isDestroyExecutorService 是否需要销毁线程池 */ default void unregister(@Nonnull String topic, @Nonnull EventHandler eventHandler, boolean isDestroyExecutorService) { } /** * 注册处理广播事件的handler(默认分区分配策略为COOPERATIVE_STICKY) * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param serializeEnum 采用的序列化方式 */ default void registerBroadcast(@Nonnull String topic, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, @Nonnull SerializeEnum serializeEnum) { } /** * 注册处理广播事件的handler * * @param topic 主题 * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 * @param serializeEnum 采用的序列化方式 */ default void registerBroadcast(@Nonnull String topic, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { } /** * 注册处理单播事件的handler(默认分区分配策略为COOPERATIVE_STICKY) * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param serializeEnum 采用的序列化方式 */ default void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, @Nonnull SerializeEnum serializeEnum) { } /** * 注册处理单播事件的handler * * @param topic 主题 * @param groupId 消费者组Id * @param handler 事件处理类 * @param executorService 上层传递的处理业务的线程池 * @param partitionAssignorMode 分区分配策略 * @param serializeEnum 采用的序列化方式 */ default void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { } /** * 注册处理广播事件的handler(不传线程池) * * @param topic 主题 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 * @param serializeEnum 采用的序列化方式 */ default void registerBroadcastWithoutThreadPool(@Nonnull String topic, @Nonnull GenericEventHandler handler, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { } /** * 注册处理单播事件的handler(不传线程池) * * @param topic 主题 * @param groupId 消费者组 * @param handler 事件处理类 * @param partitionAssignorMode 分区分配策略 * @param serializeEnum 采用的序列化方式 */ default void registerUnicastWithoutThreadPool(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) { } /** * 解注册所有的topic */ default void unregisterAllTopics() { } /** * 销毁EventCenter时释放资源 */ @PreDestroy default void destroy() { } } public interface EventFuture { /** * 发送成功后的回调函数 * * @param eventCenterSendResult 发送结果 */ void onSuccess(EventCenterSendResult eventCenterSendResult); /** * 发送失败后的回调函数 * * @param throwable 发送异常 */ void onFailure(Throwable throwable); } /** * Event Center处理监听到的Event事件,具体业务实现在各个模块进行 * * @author ludingyang * @version 1.0 * @since 2020/6/29. */ public interface EventHandler extends Handler { /** * 业务处理的方法 * * @param event 传递的消息封装类 */ void handleEvent(Event event); } @Getter @NoArgsConstructor @SuperBuilder @Slf4j @ToString public final class EventV2<T> extends BaseEvent<T> { public EventV2(String filterKey, T message) { this.filterKey = filterKey; this.message = message; } public void setTimeStamp(long timeStamp) { this.timeStamp = timeStamp; } } public static EventV2 toBean(byte[] bytes) { return KryoSerializeUtils.byteArray2Bean(bytes, EventV2.class); } public byte[] kryoSerialize() { return KryoSerializeUtils.bean2ByteArray(this); } /** * Producer可配置的回调函数(泛型接口 / EventV2接口) * * @author ludingyang * @version 1.0 * @since 2021/3/17 */ public interface GenericEventFuture<T> { /** * 发送成功后的回调函数 * * @param genericEventCenterSendResult 发送结果 */ void onSuccess(GenericEventCenterSendResult<T> genericEventCenterSendResult); /** * 发送失败后的回调函数 * * @param throwable 发送异常 */ void onFailure(Throwable throwable); } /** * Event Center处理监听到的事件,具体业务实现在各个模块进行(泛型接口) * * @author ludingyang * @version 1.0 * @since 2020/6/29. */ public interface GenericEventHandler<T> extends Handler { /** * 业务处理的方法 * * @param event 传递的消息封装类 */ void handleEvent(T event); } public interface Handler { /** * 重平衡之前可以调用执行 可以做一些简单的操作,不建议执行耗时操作,不然会拉长重平衡时间 对 于eager rebalance:STICKY,RANGE,ROUND_ROBIN;每次进行重平衡时都会触发一次。 * 对于cooperative rebalance:COOPERATIVE_STICKY;只有在consumer被分配的 partitions被主动销毁或者consumer准备离开consumer group时才会触发一次 */ default void doBeforeRebalance() { LogAccess.LOGGER.info("start to process rebalance!"); } /** * 重平衡之后可以调用执行 可以做一些简单的操作,不建议执行耗时操作,不然会拉长重平衡时间 每 次重平衡结束后会触发一次 */ default void doAfterRebalance() { LogAccess.LOGGER.info("ending rebalance!"); } 以上为eventcenter-api的全部代码,后续的开发将基于这些接口,请熟悉并了解每项功能
09-11
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值