├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── async-event-core ├── pom.xml ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── cubbery │ │ │ └── event │ │ │ ├── Channel.java │ │ │ ├── Dispatcher.java │ │ │ ├── EventBus.java │ │ │ ├── EventBusRegistry.java │ │ │ ├── EventBusSpring.java │ │ │ ├── EventCreator.java │ │ │ ├── EventStorage.java │ │ │ ├── HandlerFinder.java │ │ │ ├── ISubscribe.java │ │ │ ├── Statistics.java │ │ │ ├── Subscriber.java │ │ │ ├── channel │ │ │ ├── AbstractChannel.java │ │ │ ├── ChannelData.java │ │ │ ├── MemoryChannel.java │ │ │ ├── MonitoredChannel.java │ │ │ └── PersistentChannel.java │ │ │ ├── conf │ │ │ ├── Configurable.java │ │ │ ├── ConfigureKeys.java │ │ │ └── Context.java │ │ │ ├── event │ │ │ ├── DeadEvent.java │ │ │ ├── EventState.java │ │ │ ├── Offline.java │ │ │ ├── RetryEvent.java │ │ │ ├── SimpleEvent.java │ │ │ └── impl │ │ │ │ ├── DefaultEventCreator.java │ │ │ │ └── EncryptEventCreator.java │ │ │ ├── exception │ │ │ ├── EventBusException.java │ │ │ ├── EventHandlerException.java │ │ │ └── EventStorageException.java │ │ │ ├── finder │ │ │ ├── AbstractHandlerFinder.java │ │ │ ├── AnnotatedHandlerFinder.java │ │ │ ├── BothHandlerFinder.java │ │ │ └── ListenerHandlerFinder.java │ │ │ ├── handler │ │ │ ├── EventHandler.java │ │ │ └── PersistenceEventHandler.java │ │ │ ├── monitor │ │ │ └── ChannelStatistics.java │ │ │ ├── retry │ │ │ ├── Lease.java │ │ │ ├── LeaseTask.java │ │ │ ├── RetryMarker.java │ │ │ └── RetryService.java │ │ │ ├── utils │ │ │ ├── Formatter.java │ │ │ ├── HostUtils.java │ │ │ ├── JsonUtils.java │ │ │ ├── MapUtils.java │ │ │ ├── RefactorUtils.java │ │ │ ├── ThreadFactories.java │ │ │ ├── Threads.java │ │ │ ├── Validation.java │ │ │ └── security │ │ │ │ ├── Base32.java │ │ │ │ ├── Des.java │ │ │ │ └── DesCrypter.java │ │ │ └── worker │ │ │ ├── AbstractWorker.java │ │ │ ├── ConsumeWorker.java │ │ │ └── RetryWorker.java │ └── test │ │ └── java │ │ └── com │ │ └── cubbery │ │ └── event │ │ ├── Demo.java │ │ ├── Demo2.java │ │ ├── EventBusSpringTest.java │ │ ├── SemaphoreTest.java │ │ ├── event │ │ ├── Person.java │ │ ├── SimpleEventTest.java │ │ └── Sub.java │ │ ├── finder │ │ ├── AnnotatedHandlerFinderTest.java │ │ ├── BothHandlerFinderTest.java │ │ └── ListenerHandlerFinderTest.java │ │ └── utils │ │ ├── HostUtilsTest.java │ │ └── security │ │ └── DesCrypterTest.java └── testng-qa.xml ├── async-event-example ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── cubbery │ │ │ └── event │ │ │ └── sample │ │ │ ├── SampleWithAnnotaionSub.java │ │ │ ├── SampleWithListenerSub.java │ │ │ ├── SampleWithMonitoredChannel.java │ │ │ ├── black │ │ │ └── HttpMonitorUsage.java │ │ │ ├── channel │ │ │ └── MonitoredPersistenceChannel.java │ │ │ ├── conf │ │ │ └── ConfDemo.java │ │ │ ├── event │ │ │ ├── AnnotationSub.java │ │ │ ├── BothSub.java │ │ │ ├── EventA.java │ │ │ ├── EventAny.java │ │ │ └── ListenerSub.java │ │ │ ├── jdbc │ │ │ ├── MysqlSpringDemo.java │ │ │ └── OjdbcSpringDemo.java │ │ │ ├── mon │ │ │ ├── HttpMonitorUsage.java │ │ │ ├── LogMonitorUsage.java │ │ │ └── ZkMonitorUsage.java │ │ │ ├── monitor │ │ │ ├── HttpMonitorUsage.java │ │ │ └── ZkMonitorUsage.java │ │ │ └── spring │ │ │ └── MutipDemo.java │ └── resources │ │ ├── conf │ │ └── conf.properties │ │ ├── log4j.properties │ │ ├── mon │ │ ├── spring-http.xml │ │ ├── spring-log.xml │ │ └── spring-zk.xml │ │ ├── ojdbc │ │ └── db.properties │ │ ├── spring-orac.xml │ │ └── spring.xml │ └── test │ └── java │ └── freamwork │ ├── core │ ├── AbstractStatisticalStressStrategy.java │ ├── BaseStressConfig.java │ ├── ConfigurableStressStrategy.java │ ├── Context.java │ ├── CountLimitedStressStrategy.java │ ├── StressStrategy.java │ ├── StressStrategySupport.java │ ├── StressTask.java │ ├── TimeLimitedStressStrategy.java │ ├── Workbench.java │ ├── read.md │ └── stat │ │ ├── DefaultStatisticImpl.java │ │ ├── NumberUtil.java │ │ └── Statistical.java │ ├── simple │ ├── common │ │ └── UniqNumUtil.java │ ├── core │ │ ├── ConcurrentTask.java │ │ └── ConcurrentTest.java │ └── task │ │ └── Task.java │ └── test │ ├── EncryptRunner.java │ ├── Event.java │ ├── EventBusStressTest.java │ ├── EventPool.java │ ├── EventSub.java │ └── Runner.java ├── async-event-jdbc ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cubbery │ │ └── event │ │ └── storage │ │ ├── DbUtils.java │ │ └── JdbcEventStorage.java │ └── resources │ ├── async-event-mysql-20160229.sql │ └── async_event_oracle-20160307.sql ├── async-event-monitor ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cubbery │ │ └── event │ │ └── monitor │ │ ├── MonitorServer.java │ │ ├── http │ │ └── SimpleHttpMonitor.java │ │ ├── log │ │ └── LogMonitor.java │ │ └── zk │ │ ├── SimpleZkMonitor.java │ │ ├── ZKManager.java │ │ └── ZkTools.java │ └── resources │ └── html │ ├── channel.html │ └── retry.html ├── async-event-server └── pom.xml ├── doc └── frame.png └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | .idea/* 11 | */target/* 12 | */*.iml 13 | *.iml 14 | 15 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 16 | hs_err_pid* 17 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Change Log of Async-Event 2 | ==== 3 | The current stable version : **[1.0.0]()** 4 | 5 | ###Async-Event-1.0.0 (2016-4-20) 6 | - 原始版本。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # async-event 2 | 进程内部异步事件调用组件 3 | 4 | ## 解决什么问题: 5 | 6 | + 加速服务处理效率。提供进程级别的事件发布和异步处理能力。 7 | + 服务解耦。观察者和发布者之间互不干涉,解耦关系。 8 | + 事件驱动。提供一对多的对象关系。 9 | + 最终一致性。低延时,最终一致。 10 | 11 | 12 | ## 生产数据: 13 | 14 | + 使用异步事件组件优化服务[前]: 15 | + tps->2000,tp90->100ms,tp99->120ms 16 | + 使用异步事件组件优化服务[后]: 17 | + tps->2000,tp90->20ms,tp99->30ms 18 | 19 | ## 总体设计 20 | 21 | ![总体设计](/doc/frame.png) 22 | 23 | 24 | ## Usage: 25 | 26 | //实例化事件总线,使用内存队列 27 | final EventBus eventBus = new EventBus(new MemoryChannel(1024)); 28 | //注册消费者 29 | eventBus.register(new ListenerSub()); 30 | eventBus.register(new BothSub()); 31 | //启动事件总线 32 | eventBus.start(); 33 | 34 | //发送事件消息(需要启动后才能发送) 35 | eventBus.publish(new SimpleEvent()); 36 | eventBus.publish(new EventAny()); 37 | eventBus.publish(new EventA()); 38 | //停止事件总线 39 | eventBus.stop(); 40 | 41 | ## 开发计划 42 | 43 | 44 | 1、持久化增加mybatis. 45 | 2、远程storage服务,统一管理。统一组件化。 46 | -------------------------------------------------------------------------------- /async-event-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | async-event 7 | com.cubbery.event 8 | 1.0.1 9 | 10 | 4.0.0 11 | 12 | async-event-core 13 | com.cubbery.event 14 | async-event-core 15 | jar 16 | 17 | 18 | 19 | com.google.code.gson 20 | gson 21 | 22 | 23 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/Channel.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | import com.cubbery.event.channel.ChannelData; 7 | import com.cubbery.event.handler.EventHandler; 8 | 9 | import java.util.Set; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | /** 13 | * 事件通道接口 14 | */ 15 | public interface Channel { 16 | 17 | /** 18 | * put in to 19 | * 20 | * @param event 21 | * @return 22 | */ 23 | boolean offer(Object event,Set handlers); 24 | 25 | /** 26 | * remove and get one from the q 27 | * 28 | * @param timeout 29 | * @param unit 30 | * @return 31 | */ 32 | ChannelData poll(long timeout, TimeUnit unit); 33 | 34 | /** 35 | * is empty when queue.size() == 0 36 | * 37 | * @return 38 | */ 39 | boolean isEmpty(); 40 | 41 | /** 42 | * get storage if this is persistence 43 | * 44 | * @return 45 | */ 46 | EventStorage getStorage(); 47 | 48 | /** 49 | * put a storage if necessary 50 | * 51 | * @param storage 52 | */ 53 | void setStorage(EventStorage storage); 54 | 55 | /** 56 | * check init is ok 57 | */ 58 | boolean checkInit(); 59 | 60 | /** 61 | * get a creator for event 62 | * 63 | * @return 64 | */ 65 | EventCreator getCreator(); 66 | 67 | /** 68 | * set a creator for event 69 | * 70 | * @param creator 71 | */ 72 | void setCreator(EventCreator creator); 73 | } 74 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/Dispatcher.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | import com.cubbery.event.channel.ChannelData; 7 | import com.cubbery.event.worker.ConsumeWorker; 8 | import com.cubbery.event.utils.ThreadFactories; 9 | import com.cubbery.event.utils.Validation; 10 | 11 | import java.util.concurrent.TimeUnit; 12 | 13 | /** 14 | * 事件派发者,程序逻辑处理器,使用守护线程。 15 | */ 16 | final class Dispatcher { 17 | private final EventBus eventBus; 18 | private volatile boolean running; 19 | 20 | protected Dispatcher(EventBus eventBus) { 21 | this.eventBus = eventBus; 22 | this.running = false; 23 | } 24 | 25 | public synchronized Dispatcher start() { 26 | if(!this.running) { 27 | this.running = true; 28 | //使用守护线程是由于:(对于持久化消息,有重试进程定时mark事件成重试状态) 29 | new ThreadFactories(true,"Dispatcher").newThread(new DispatcherTask()).start(); 30 | } 31 | return this; 32 | } 33 | 34 | public synchronized void stop() { 35 | this.running = false; 36 | } 37 | 38 | class DispatcherTask implements Runnable { 39 | private final ThreadLocal counter = new ThreadLocal(){ 40 | @Override 41 | protected Integer initialValue() { 42 | return 0;//Integer cache 127 ~ -127 43 | } 44 | }; 45 | 46 | @Override 47 | public void run() { 48 | Channel channel = eventBus.getChannel(); 49 | while (running) { 50 | //避免线程无法shutDown,所以给定一个超时时间,而不是一直阻塞 51 | ChannelData event = selfRegulation(channel,channel.poll(10, TimeUnit.MILLISECONDS)); 52 | if(event != null) { 53 | eventBus.getConsumeExecutor().submit(new ConsumeWorker(event.getHandler(), event)); 54 | } 55 | } 56 | } 57 | 58 | private ChannelData selfRegulation(Channel channel,ChannelData event) { 59 | //常驻线程,避免线程无法shutDown,阻塞进程关闭。所以给定一个超时时间,而不是一直阻塞 60 | try { 61 | Validation.checkNotNull(event, "Event cannot be null."); 62 | Validation.checkNotNull(event.getData(), "Event cannot be null."); 63 | return event; 64 | } catch (Exception e) { 65 | if(counter.get() > 2) { 66 | //当2个周期没有拿到数据,那么wait 1min 67 | counter.set(0); 68 | return channel.poll(60,TimeUnit.SECONDS); 69 | } else { 70 | ChannelData eventData = channel.poll(10, TimeUnit.MILLISECONDS); 71 | counter.set(counter.get() + 1); 72 | return selfRegulation(channel,eventData); 73 | } 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/EventBusRegistry.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016,www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * 类描述
14 | * 创建人百墨
15 | * 创建时间: 2016/5/12 - 16:16
16 | * 17 | * @version 1.0.0
18 | */ 19 | class EventBusRegistry { 20 | private final static Logger LOG = LoggerFactory.getLogger("Event-Bus-All"); 21 | private final static List allBus = new ArrayList(); 22 | 23 | static { 24 | Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 25 | @Override 26 | public void run() { 27 | try { 28 | destroyAll(); 29 | } catch (Throwable e) { 30 | } 31 | } 32 | },"EventBusShutDownHook")); 33 | } 34 | 35 | public static void report(EventBus eventBus) { 36 | allBus.add(eventBus); 37 | } 38 | 39 | public static void destroyAll() { 40 | for(EventBus bus : allBus) { 41 | if(bus != null) { 42 | bus.stop(); 43 | LOG.info("Event Bus Stopped!"); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/EventBusSpring.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | import com.cubbery.event.utils.HostUtils; 7 | import com.cubbery.event.event.impl.EncryptEventCreator; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * Spring辅助配置类:辅助处理:
14 | *
    15 | *
      黑名单字符串处理
    16 | *
      订阅者处理
    17 | *
      指定加解密
    18 | *
19 | * 创建人百墨
20 | * 创建时间: 2016/3/4 - 10:24
21 | * @version 1.0.0
22 | */ 23 | public class EventBusSpring { 24 | private EventBus eventBus; 25 | private List subscribers; 26 | private List blackIps; 27 | 28 | public EventBusSpring(EventBus eventBus) { 29 | this(eventBus,new ArrayList(0)); 30 | } 31 | 32 | public EventBusSpring(EventBus eventBus, List subscribers) { 33 | this(eventBus, subscribers,new ArrayList(0)); 34 | } 35 | 36 | public EventBusSpring(EventBus eventBus, List subscribers, String blackIpStr) { 37 | this.eventBus = eventBus; 38 | this.subscribers = subscribers; 39 | this.blackIps = ipStrToList(blackIpStr); 40 | } 41 | 42 | public EventBusSpring(EventBus eventBus, List subscribers, String blackIpStr,boolean needEncryptEvent) { 43 | this.eventBus = eventBus; 44 | this.subscribers = subscribers; 45 | this.blackIps = ipStrToList(blackIpStr); 46 | if (needEncryptEvent) { 47 | this.eventBus.getChannel().setCreator(new EncryptEventCreator()); 48 | } 49 | } 50 | 51 | public EventBusSpring(EventBus eventBus, List subscribers,List blackIps) { 52 | this.eventBus = eventBus; 53 | this.subscribers = subscribers; 54 | this.blackIps = blackIps; 55 | } 56 | 57 | public synchronized void start() { 58 | for(Object obj : subscribers) { 59 | this.eventBus.register(obj); 60 | } 61 | this.eventBus.setBlackIps(blackIps); 62 | this.eventBus.start(); 63 | } 64 | 65 | public synchronized void stop() { 66 | this.eventBus.stop(); 67 | } 68 | 69 | public synchronized void setSubscribers(List subscribers) { 70 | this.subscribers = subscribers; 71 | } 72 | 73 | public static List ipStrToList(String blackIpStr) { 74 | List ips = new ArrayList(); 75 | if(blackIpStr != null && !blackIpStr.equals("")) { 76 | String[] arr = blackIpStr.split("\\|"); 77 | for(String ip : arr) { 78 | if(HostUtils.isValidIpAddress(ip)) { 79 | ips.add(ip); 80 | } 81 | } 82 | } 83 | return ips; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/EventCreator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016,www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | import com.cubbery.event.event.SimpleEvent; 7 | import com.cubbery.event.handler.EventHandler; 8 | 9 | /** 10 | * 类描述
11 | * 创建人百墨
12 | * 创建时间: 2016/4/18 - 15:34
13 | * 14 | * @version 1.0.0
15 | */ 16 | public interface EventCreator { 17 | 18 | /** 19 | * 将从队列中取出的数据格式化成统一的数据结构,便于保存和后续统一使用 20 | * 21 | * @param e 任意obj或者包装结构 22 | * @return 23 | */ 24 | SimpleEvent create(Object e,EventHandler handler); 25 | 26 | /** 27 | * 由统一格式,反解成event的格式 28 | * 29 | * @param event 统一格式 30 | * @param clazz 目标对象类型 31 | * @return 反解失败返回null 32 | */ 33 | Object reCreate(SimpleEvent event,Class clazz); 34 | } 35 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/EventStorage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | import com.cubbery.event.event.SimpleEvent; 7 | import com.cubbery.event.event.Offline; 8 | import com.cubbery.event.event.RetryEvent; 9 | import com.cubbery.event.retry.Lease; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * 事件持久化标准协议 15 | */ 16 | public interface EventStorage { 17 | 18 | /** 19 | * 插入一条事件消息 20 | * 21 | * @param event 插入成功后,返回主键ID 22 | */ 23 | void insertEvent(List event) ; 24 | 25 | /** 26 | * 单条更新成死信状态 27 | * 28 | * @param id 29 | * @return 30 | */ 31 | int markAsDead(long id); 32 | 33 | /** 34 | * 单条更新成成功状态 35 | * 36 | * @param id 37 | * @return 38 | */ 39 | int markAsSuccess(long id); 40 | 41 | /** 42 | * 单条更新成重试状态 43 | * 44 | * @param id 45 | * @return 46 | */ 47 | int markAsRetry(long id); 48 | 49 | /** 50 | * 批量跟新为待重试状态 51 | * 52 | * @return 53 | */ 54 | int batchMarkAsRetry(); 55 | 56 | /** 57 | * 批量标记超过最大重试上限的事件为死信 58 | * 59 | * @param maxRetryCount 最大重试上限 60 | * @return 61 | */ 62 | int batchMarkAsDead(int maxRetryCount); 63 | 64 | /** 65 | * 查询一个单位(100-1000左右)的待重试事件 66 | * 67 | * @return 68 | */ 69 | List selectRetryEvents(int maxRetryCount); 70 | 71 | /** 72 | * 查询租约信息 73 | * 74 | * @return 75 | */ 76 | Lease selectLease(); 77 | 78 | /** 79 | * 续租约 80 | * 81 | * @param masterInfo 82 | * @param oldVersion 83 | * @return 84 | */ 85 | int updateLease(String masterInfo, long oldVersion,long period); 86 | 87 | /** 88 | * 尝试插入一则数据,如果插入失败(主键异常,那么忽略) 89 | */ 90 | void initLease(long period); 91 | 92 | /** 93 | * 插入一则下线消息到下线表 94 | * 95 | * @param masterInfo 96 | * @return 97 | */ 98 | int confirmOffline(Offline masterInfo); 99 | 100 | /** 101 | * 查询最近下线记录 102 | * 103 | * @return 104 | */ 105 | Offline getLastOffline(); 106 | 107 | public enum DataSourceType { 108 | MYSQL,ORACLE; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/HandlerFinder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | import com.cubbery.event.handler.EventHandler; 7 | 8 | import java.util.Map; 9 | import java.util.Set; 10 | 11 | /** 12 | * 事件处理器发现者 13 | * 用于发现通过实现监听器或者注解方式的事件处理者接口 14 | * @version 1.0.0
15 | * 16 | */ 17 | public interface HandlerFinder { 18 | /** 19 | * 查询(发现)订阅方法 20 | * 21 | * @param listener 监听者(订阅者) 22 | * @return 23 | */ 24 | Map, Set> findAllHandlers(Object listener); 25 | 26 | /** 27 | * 配置存储 28 | * 29 | * @param storage 30 | * @return 31 | */ 32 | HandlerFinder setStorage(EventStorage storage); 33 | } 34 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/ISubscribe.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | /** 7 | * 接口方式的订阅者 8 | * @param 9 | */ 10 | public interface ISubscribe { 11 | /**订阅者方法名**/ 12 | String methodName = "handler"; 13 | 14 | /** 15 | * 订阅者逻辑处理 16 | * 17 | * @param event 18 | */ 19 | void handler(T event); 20 | } 21 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/Statistics.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.util.*; 10 | import java.util.concurrent.atomic.AtomicLong; 11 | 12 | /** 13 | * 创建人百墨
14 | * @version 1.0.0
15 | * 统计信息采集样本。统计信息汇聚在此处,上报到其他需求方 16 | */ 17 | public abstract class Statistics { 18 | private static final Logger logger = LoggerFactory.getLogger(Statistics.class); 19 | private static final String COUNTER_GROUP_START_TIME = "start.time"; 20 | private static final String COUNTER_GROUP_STOP_TIME = "stop.time"; 21 | 22 | private final Type type; 23 | private final String name; 24 | private final Map counterMap; 25 | 26 | private AtomicLong startTime; 27 | private AtomicLong stopTime; 28 | 29 | public Statistics(Type type, String name, String... attrs) { 30 | this.type = type; 31 | this.name = name; 32 | Map counterInitMap = new HashMap(); 33 | // Initialize the counters 34 | for (String attribute : attrs) { 35 | counterInitMap.put(attribute, new AtomicLong(0L)); 36 | } 37 | this.counterMap = Collections.unmodifiableMap(counterInitMap); 38 | startTime = new AtomicLong(0L); 39 | stopTime = new AtomicLong(0L); 40 | start(); 41 | } 42 | 43 | public void start() { 44 | stopTime.set(0L); 45 | for (String counter : counterMap.keySet()) { 46 | counterMap.get(counter).set(0L); 47 | } 48 | startTime.set(System.currentTimeMillis()); 49 | logger.info("Component type: " + type + ", name: " + name + " started"); 50 | } 51 | 52 | public void stop() { 53 | stopTime.set(System.currentTimeMillis()); 54 | logger.info("Component type: " + type + ", name: " + name + " stopped !"); 55 | final String typePrefix = type.name().toLowerCase(Locale.ENGLISH); 56 | 57 | logger.info("Shutdown Metric for type: " + type + ", " + "name: " + name + ". " 58 | + typePrefix + "." + COUNTER_GROUP_START_TIME + " == " + startTime); 59 | 60 | logger.info("Shutdown Metric for type: " + type + ", " + "name: " + name + ". " 61 | + typePrefix + "." + COUNTER_GROUP_STOP_TIME + " == " + stopTime); 62 | 63 | final List mapKeys = new ArrayList(counterMap.keySet()); 64 | Collections.sort(mapKeys); 65 | for (final String counterMapKey : mapKeys) { 66 | final long counterMapValue = get(counterMapKey); 67 | logger.info("Shutdown Metric for type: " + type + ", " + "name: " + name + ". " + counterMapKey + " == " + counterMapValue); 68 | } 69 | } 70 | 71 | protected long get(String counter) { 72 | return counterMap.get(counter).get(); 73 | } 74 | 75 | protected void set(String counter, long value) { 76 | counterMap.get(counter).set(value); 77 | } 78 | 79 | protected long addAndGet(String counter, long delta) { 80 | return counterMap.get(counter).addAndGet(delta); 81 | } 82 | 83 | protected long increment(String counter) { 84 | return counterMap.get(counter).incrementAndGet(); 85 | } 86 | 87 | public String getTypeDesc() { 88 | return type.name(); 89 | } 90 | 91 | public Type getType() { 92 | return type; 93 | } 94 | 95 | public long getStartTime() { 96 | return startTime.get(); 97 | } 98 | 99 | public long getStopTime() { 100 | return stopTime.get(); 101 | } 102 | 103 | @Override 104 | public final String toString() { 105 | StringBuilder sb = new StringBuilder("{\"name\":\"").append(type.name()) 106 | .append("\",\"startTime\":\"").append(getStartTime()) 107 | .append("\",\"stopTime\":\"").append(getStopTime()).append("\",\"data\":{"); 108 | boolean first = true; 109 | Iterator counterIterator = counterMap.keySet().iterator(); 110 | while (counterIterator.hasNext()) { 111 | if (first) { 112 | first = false; 113 | } else { 114 | sb.append(", "); 115 | } 116 | String counterName = counterIterator.next(); 117 | sb.append("\"" + counterName.replace(".","")).append("\":\"").append(get(counterName)).append("\""); 118 | } 119 | sb.append("}}"); 120 | 121 | return sb.toString(); 122 | } 123 | 124 | public static enum Type { 125 | CHANNEL; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/Subscriber.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target(ElementType.METHOD) 14 | public @interface Subscriber { 15 | /**注解方式的订阅者**/ 16 | } 17 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/channel/AbstractChannel.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.channel; 5 | 6 | import com.cubbery.event.Channel; 7 | import com.cubbery.event.EventStorage; 8 | import com.cubbery.event.conf.Configurable; 9 | import com.cubbery.event.conf.ConfigureKeys; 10 | import com.cubbery.event.conf.Context; 11 | import com.cubbery.event.EventCreator; 12 | import com.cubbery.event.event.impl.DefaultEventCreator; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | abstract class AbstractChannel implements Channel,Configurable { 17 | protected TimeUnit timeUnit ; 18 | protected long expire ; 19 | protected EventCreator eventCreator; 20 | 21 | protected AbstractChannel() { 22 | timeUnit = TimeUnit.MILLISECONDS; 23 | expire = 10; 24 | eventCreator = new DefaultEventCreator(); 25 | } 26 | 27 | @Override 28 | public EventStorage getStorage() { 29 | return null; 30 | } 31 | 32 | @Override 33 | public void setStorage(EventStorage storage) { 34 | } 35 | 36 | @Override 37 | public EventCreator getCreator() { 38 | return this.eventCreator; 39 | } 40 | 41 | @Override 42 | public void setCreator(EventCreator creator) { 43 | this.eventCreator = creator; 44 | } 45 | 46 | @Override 47 | public void configure(Context context) { 48 | expire = context.getLong(ConfigureKeys.CHANNEL_OFFER_EXPIRE,expire); 49 | timeUnit = context.getTimeUnit(ConfigureKeys.BUS_TIME_UNIT,timeUnit); 50 | } 51 | } -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/channel/ChannelData.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.channel; 5 | 6 | import com.cubbery.event.handler.EventHandler; 7 | 8 | /** 9 | * 10 | *事件处理单元 11 | *用于封装一个事件和该事件对应的处理者,作为一个事件处理单元 12 | * 13 | */ 14 | public class ChannelData { 15 | /** event **/ 16 | private Object data; 17 | /** persistent primary key **/ 18 | private long id; 19 | /** handler for event **/ 20 | private EventHandler handler; 21 | 22 | 23 | public ChannelData(Object data) { 24 | this.data = data; 25 | } 26 | 27 | public ChannelData(Object data, EventHandler handler) { 28 | this.data = data; 29 | this.handler = handler; 30 | } 31 | 32 | public ChannelData(Object data, long id, EventHandler handler) { 33 | this.data = data; 34 | this.id = id; 35 | this.handler = handler; 36 | } 37 | 38 | public Object getData() { 39 | return data; 40 | } 41 | 42 | public void setData(Object data) { 43 | this.data = data; 44 | } 45 | 46 | public long getId() { 47 | return id; 48 | } 49 | 50 | public void setId(long id) { 51 | this.id = id; 52 | } 53 | 54 | public EventHandler getHandler() { 55 | return handler; 56 | } 57 | 58 | public void setHandler(EventHandler handler) { 59 | this.handler = handler; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/channel/MemoryChannel.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.channel; 5 | 6 | import com.cubbery.event.handler.EventHandler; 7 | 8 | import java.util.Set; 9 | import java.util.concurrent.LinkedBlockingQueue; 10 | import java.util.concurrent.Semaphore; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | public class MemoryChannel extends AbstractChannel { 14 | 15 | private LinkedBlockingQueue queue; 16 | private Semaphore queueRemaining; 17 | 18 | public MemoryChannel(int capacity) { 19 | super(); 20 | queueRemaining = new Semaphore(capacity); 21 | this.queue = new LinkedBlockingQueue(capacity); 22 | } 23 | 24 | @Override 25 | public boolean offer(Object event,Set handlers) { 26 | try { 27 | if(queueRemaining.tryAcquire(handlers.size(),expire,timeUnit)) { 28 | for(EventHandler handler : handlers) { 29 | if(!queue.offer(new ChannelData(event,0,handler))) { 30 | throw new RuntimeException("Queue add failed, this shouldn't be able to happen"); 31 | } 32 | } 33 | return true; 34 | } 35 | } catch (InterruptedException e) { 36 | Thread.currentThread().interrupt(); 37 | } 38 | return false; 39 | } 40 | 41 | protected boolean offer(Set data) { 42 | try { 43 | if(queueRemaining.tryAcquire(data.size(),expire,timeUnit)) { 44 | for(ChannelData ds : data) { 45 | if(!queue.offer(ds)) { 46 | throw new RuntimeException("Queue add failed, this shouldn't be able to happen"); 47 | } 48 | } 49 | return true; 50 | } 51 | } catch (InterruptedException e) { 52 | Thread.currentThread().interrupt(); 53 | } 54 | return false; 55 | } 56 | 57 | @Override 58 | public ChannelData poll(long timeout, TimeUnit unit) { 59 | try { 60 | ChannelData data = queue.poll(timeout, unit); 61 | if(null != data) { 62 | queueRemaining.release(); 63 | } 64 | return data; 65 | } catch (InterruptedException e) { 66 | Thread.interrupted(); 67 | return null; 68 | } 69 | } 70 | 71 | @Override 72 | public boolean isEmpty() { 73 | return queue.isEmpty(); 74 | } 75 | 76 | @Override 77 | public boolean checkInit() { 78 | return queue != null && queue.isEmpty(); 79 | } 80 | 81 | protected int getSize() { 82 | return queue.size() ; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/channel/MonitoredChannel.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.channel; 5 | 6 | import com.cubbery.event.handler.EventHandler; 7 | import com.cubbery.event.monitor.ChannelStatistics; 8 | 9 | import java.util.Set; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | public class MonitoredChannel extends MemoryChannel { 13 | 14 | private ChannelStatistics statistics; 15 | 16 | public MonitoredChannel(int capacity,ChannelStatistics statistics) { 17 | super(capacity); 18 | this.statistics = statistics; 19 | this.statistics.setChannelCapacity(capacity); 20 | this.statistics.setChannelSize(capacity); 21 | } 22 | 23 | @Override 24 | public boolean offer(Object event,Set handlers) { 25 | boolean isOk = false; 26 | try { 27 | this.statistics.incrementEventPutAttemptCount(handlers.size()); 28 | isOk = super.offer(event,handlers); 29 | } finally { 30 | if(isOk) { 31 | this.statistics.addToEventPutSuccessCount(handlers.size()); 32 | this.statistics.setChannelSize(getSize()); 33 | } 34 | } 35 | return isOk; 36 | } 37 | 38 | @Override 39 | public ChannelData poll(long timeout, TimeUnit unit) { 40 | boolean isOk = false; 41 | this.statistics.incrementEventTakeAttemptCount(); 42 | try { 43 | ChannelData obj = super.poll(timeout, unit); 44 | isOk = (obj != null); 45 | return obj; 46 | } finally { 47 | if(isOk) { 48 | this.statistics.addToEventTakeSuccessCount(1); 49 | } 50 | this.statistics.setChannelSize(getSize()); 51 | } 52 | } 53 | 54 | @Override 55 | public boolean isEmpty() { 56 | return super.isEmpty(); 57 | } 58 | 59 | @Override 60 | public boolean checkInit() { 61 | return super.checkInit(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/channel/PersistentChannel.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.channel; 5 | 6 | import com.cubbery.event.EventStorage; 7 | import com.cubbery.event.event.SimpleEvent; 8 | import com.cubbery.event.handler.EventHandler; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import java.util.ArrayList; 13 | import java.util.HashSet; 14 | import java.util.List; 15 | import java.util.Set; 16 | import java.util.concurrent.TimeUnit; 17 | 18 | public class PersistentChannel extends MemoryChannel { 19 | private final Logger LOGGER = LoggerFactory.getLogger("Persistent-Channel"); 20 | 21 | private EventStorage storage; 22 | 23 | public PersistentChannel(int capacity, final EventStorage storage) { 24 | super(capacity); 25 | this.storage = storage; 26 | } 27 | 28 | @Override 29 | public boolean offer(Object event,Set handlers) { 30 | try { 31 | List eventList = new ArrayList(handlers.size()); 32 | for(EventHandler handler : handlers) { 33 | SimpleEvent simpleEvent = getCreator().create(event, handler); 34 | eventList.add(simpleEvent); 35 | } 36 | storage.insertEvent(eventList); 37 | 38 | Set dataList = new HashSet(eventList.size()); 39 | for (SimpleEvent e : eventList) { 40 | dataList.add(new ChannelData(event,e.getId(),e.getEventHandler())); 41 | } 42 | super.offer(dataList); 43 | return true; 44 | } catch (Exception e) { 45 | //1、数据库记录成功,但是队列入失败。重试服务处理此类问题。 46 | //2、数据库和队列对入失败,没有影响。 47 | LOGGER.warn("Offer operator wrong! event = {} " + event,e); 48 | } 49 | return false; 50 | } 51 | 52 | @Override 53 | public ChannelData poll(long timeout, TimeUnit unit) { 54 | //对于这种不需要持久化了,直接使用mem实现 55 | return super.poll(timeout, unit); 56 | } 57 | 58 | @Override 59 | public boolean checkInit() { 60 | return super.checkInit() && storage != null ; 61 | } 62 | 63 | @Override 64 | public EventStorage getStorage() { 65 | return this.storage; 66 | } 67 | 68 | 69 | @Override 70 | public void setStorage(EventStorage storage) { 71 | this.storage = storage; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/conf/Configurable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.conf; 5 | 6 | /** 7 | * 对于实现了该接口的所有组件,都可配置,在所有组件注册到bus后,bus读取配置文件,下发到所有组件。配置生效。 8 | */ 9 | public interface Configurable { 10 | /** 11 | * 可配置组件,配置下发 12 | * 13 | * @param context 14 | */ 15 | void configure(Context context); 16 | } 17 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/conf/ConfigureKeys.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.conf; 5 | 6 | public interface ConfigureKeys { 7 | 8 | /**总线消费者数量**/ 9 | String BUS_CONSUME_COUNT = "bus.consume.count"; 10 | 11 | /**总线分发者数量**/ 12 | String BUS_DISPATCH_COUNT = "bus.dispatch.count"; 13 | 14 | /**总线时间单位**/ 15 | String BUS_TIME_UNIT = "bus.time.unit"; 16 | 17 | /**渠道默认超时时间**/ 18 | String CHANNEL_OFFER_EXPIRE = "channel.offer.expire"; 19 | 20 | /**通道类型**/ 21 | String CHANNEL_TYPE = "channel.type"; 22 | 23 | /**通道大小**/ 24 | String CHANNEL_SIZE = "channel.size"; 25 | 26 | /**重试服务master优先权,单位为秒(s)**/ 27 | String RETRY_MASTER_PRIORITY = "retry.master.priority"; 28 | 29 | /**重试并发处理数**/ 30 | String RETRY_PARALLEL_COUNT = "retry.parallel.count"; 31 | 32 | /**事件最大重试次数**/ 33 | String EVENT_MAX_RETRY_COUNT = "event.maxRetry.count"; 34 | 35 | /**新master上线等待时间**/ 36 | String RETRY_MASTER_WAIT = "retry.master.wait"; 37 | 38 | /**是否开启确认下线功能**/ 39 | String RETRY_MAKESURE_OFFLINE = "retry.makeSure.offline"; 40 | 41 | /**租约周期**/ 42 | String RETRY_LEASE_PERIOD = "retry.lease.period"; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/conf/Context.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.conf; 5 | 6 | import java.lang.reflect.Field; 7 | import java.util.Collections; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.Properties; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | /** 14 | * 配置信息,相当于properties 15 | */ 16 | public class Context { 17 | private Map parameters; 18 | 19 | public Context() { 20 | parameters = Collections.synchronizedMap(new HashMap()); 21 | } 22 | 23 | public Context(Map parameters) { 24 | this(); 25 | this.putAll(parameters); 26 | } 27 | 28 | public Context(Properties properties) { 29 | this(); 30 | Class clazz = ConfigureKeys.class; 31 | Field[] fs = clazz.getFields(); 32 | for(Field f : fs) { 33 | try { 34 | String fValue = (String) f.get(clazz); 35 | this.put(fValue, (String) properties.get(fValue)); 36 | } catch (IllegalAccessException e) { 37 | // 38 | } 39 | } 40 | } 41 | 42 | public void putAll(Map map) { 43 | parameters.putAll(map); 44 | } 45 | 46 | public void put(String key, String value) { 47 | parameters.put(key, value); 48 | } 49 | 50 | public boolean containsKey(String key) { 51 | return parameters.containsKey(key); 52 | } 53 | 54 | public Integer getInt(String key, Integer defaultValue) { 55 | String value = get(key); 56 | if(value != null) { 57 | return Integer.parseInt(value.trim()); 58 | } 59 | return defaultValue; 60 | } 61 | 62 | public Integer getInt(String key) { 63 | return getInt(key, null); 64 | } 65 | 66 | public Long getLong(String key, Long defaultValue) { 67 | String value = get(key); 68 | if(value != null) { 69 | return Long.parseLong(value.trim()); 70 | } 71 | return defaultValue; 72 | } 73 | 74 | public TimeUnit getTimeUnit(String key,TimeUnit defaultValue) { 75 | String result = parameters.get(key); 76 | if(result != null) { 77 | TimeUnit unit = TimeUnit.valueOf(result); 78 | if(unit != null) { 79 | return unit; 80 | } 81 | } 82 | return defaultValue; 83 | } 84 | 85 | public boolean getBoolean(String key, boolean defaultValue) { 86 | String value = get(key); 87 | return Boolean.getBoolean(value); 88 | } 89 | 90 | public TimeUnit getTimeUnit(String key) { 91 | return getTimeUnit(key,null); 92 | } 93 | 94 | public Long getLong(String key) { 95 | return getLong(key,null); 96 | } 97 | 98 | public String getString(String key, String defaultValue) { 99 | return get(key, defaultValue); 100 | } 101 | 102 | public String getString(String key) { 103 | return get(key); 104 | } 105 | 106 | private String get(String key) { 107 | return get(key, null); 108 | } 109 | 110 | private String get(String key, String defaultValue) { 111 | String result = parameters.get(key); 112 | if(result != null) { 113 | return result; 114 | } 115 | return defaultValue; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/event/DeadEvent.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.event; 5 | 6 | public class DeadEvent extends SimpleEvent { 7 | public DeadEvent() { 8 | setStatus(EventState.DEAD); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/event/EventState.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.event; 5 | 6 | public interface EventState { 7 | 8 | int SUCCESS = 0;//受理成功 9 | int CONSUME = 1;//待消费 10 | int RETRY = 2;//重试消息 11 | int DEAD = 3;//死信消息 12 | 13 | } 14 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/event/Offline.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.event; 5 | 6 | import java.io.Serializable; 7 | import java.util.Date; 8 | 9 | public class Offline implements Serializable { 10 | private long id; 11 | private String master; 12 | private Date modifiedTime; 13 | private Date createdTime; 14 | private Date now; 15 | 16 | public Offline() { 17 | } 18 | 19 | public Offline(String master) { 20 | this.master = master; 21 | } 22 | 23 | public long getId() { 24 | return id; 25 | } 26 | 27 | public void setId(long id) { 28 | this.id = id; 29 | } 30 | 31 | public String getMaster() { 32 | return master; 33 | } 34 | 35 | public void setMaster(String master) { 36 | this.master = master; 37 | } 38 | 39 | public Date getModifiedTime() { 40 | return modifiedTime; 41 | } 42 | 43 | public void setModifiedTime(Date modifiedTime) { 44 | this.modifiedTime = modifiedTime; 45 | } 46 | 47 | public Date getCreatedTime() { 48 | return createdTime; 49 | } 50 | 51 | public void setCreatedTime(Date createdTime) { 52 | this.createdTime = createdTime; 53 | } 54 | 55 | public Date getNow() { 56 | return now; 57 | } 58 | 59 | public void setNow(Date now) { 60 | this.now = now; 61 | } 62 | 63 | public long getInterval() { 64 | return this.getCreatedTime().getTime() - this.getNow().getTime(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/event/RetryEvent.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.event; 5 | 6 | public class RetryEvent extends SimpleEvent { 7 | public RetryEvent() { 8 | setStatus(EventState.RETRY); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/event/SimpleEvent.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.event; 5 | 6 | import com.cubbery.event.handler.EventHandler; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * event 基础实现,mapping到数据库逻辑结构。 12 | */ 13 | public class SimpleEvent { 14 | private long id; 15 | private int status; 16 | private String mark; 17 | private Date createdTime; 18 | private Date modifiedTime; 19 | /**event type:event class CanonicalName**/ 20 | private String type; 21 | /**handler type:subscribe class CanonicalName # subscribe method name**/ 22 | private String expression; 23 | /**event body:decEncrypt(Json(obk))**/ 24 | private String data; 25 | 26 | private EventHandler eventHandler; 27 | 28 | public void setId(long id) { 29 | this.id = id; 30 | } 31 | 32 | public String getMark() { 33 | return mark; 34 | } 35 | 36 | public void setMark(String mark) { 37 | this.mark = mark; 38 | } 39 | 40 | public Date getCreatedTime() { 41 | return createdTime; 42 | } 43 | 44 | public void setCreatedTime(Date createdTime) { 45 | this.createdTime = createdTime; 46 | } 47 | 48 | public Date getModifiedTime() { 49 | return modifiedTime; 50 | } 51 | 52 | public void setModifiedTime(Date modifiedTime) { 53 | this.modifiedTime = modifiedTime; 54 | } 55 | 56 | public String getData() { 57 | return data; 58 | } 59 | 60 | public void setData(String data) { 61 | this.data = data; 62 | } 63 | 64 | public int getStatus() { 65 | return status; 66 | } 67 | 68 | public void setStatus(int status) { 69 | this.status = status; 70 | } 71 | 72 | public String getExpression() { 73 | return expression; 74 | } 75 | 76 | public void setExpression(String expression) { 77 | this.expression = expression; 78 | } 79 | 80 | public long getId() { 81 | return this.id; 82 | } 83 | 84 | public String getType() { 85 | return this.type; 86 | } 87 | 88 | public void setType(String type) { 89 | this.type = type; 90 | } 91 | 92 | public EventHandler getEventHandler() { 93 | return eventHandler; 94 | } 95 | 96 | public void setEventHandler(EventHandler eventHandler) { 97 | this.eventHandler = eventHandler; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/event/impl/DefaultEventCreator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016,www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.event.impl; 5 | 6 | import com.cubbery.event.EventCreator; 7 | import com.cubbery.event.channel.ChannelData; 8 | import com.cubbery.event.event.SimpleEvent; 9 | import com.cubbery.event.handler.EventHandler; 10 | import com.cubbery.event.utils.JsonUtils; 11 | 12 | /** 13 | * 类描述: 默认事件构造器
14 | * 创建人百墨
15 | * 创建时间: 2016/4/18 - 15:38
16 | * 17 | * @version 1.0.0
18 | */ 19 | public class DefaultEventCreator implements EventCreator { 20 | @Override 21 | public SimpleEvent create(Object e, EventHandler handler) { 22 | if(e != null ) { 23 | SimpleEvent simpleEvent = new SimpleEvent(); 24 | if(e instanceof ChannelData) { 25 | simpleEvent.setId(((ChannelData)e).getId()); 26 | } 27 | simpleEvent.setData(JsonUtils.serialize(e)); 28 | simpleEvent.setType(e.getClass().getCanonicalName()); 29 | if(handler != null) { 30 | simpleEvent.setExpression(handler.expression()); 31 | simpleEvent.setEventHandler(handler); 32 | } 33 | return simpleEvent; 34 | } 35 | return null; 36 | } 37 | 38 | @Override 39 | public Object reCreate(SimpleEvent event, Class clazz) { 40 | if(clazz == null) return null; 41 | if(!SimpleEvent.class.equals(clazz)) { 42 | //还原事件类型 43 | if(event.getData() == null) { 44 | try { 45 | return clazz.newInstance(); 46 | } catch (InstantiationException e) { 47 | // 48 | } catch (IllegalAccessException e) { 49 | // 50 | } 51 | return null; 52 | } 53 | return JsonUtils.deSerialize(event.getData(), clazz); 54 | } 55 | return event; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/event/impl/EncryptEventCreator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016,www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.event.impl; 5 | 6 | import com.cubbery.event.EventCreator; 7 | import com.cubbery.event.channel.ChannelData; 8 | import com.cubbery.event.event.SimpleEvent; 9 | import com.cubbery.event.handler.EventHandler; 10 | import com.cubbery.event.utils.JsonUtils; 11 | import com.cubbery.event.utils.security.DesCrypter; 12 | 13 | /** 14 | * 类描述: 加密事件构造器
15 | * 创建人百墨
16 | * 创建时间: 2016/4/18 - 15:39
17 | * 18 | * @version 1.0.0
19 | */ 20 | public class EncryptEventCreator implements EventCreator { 21 | 22 | @Override 23 | public SimpleEvent create(Object e, EventHandler handler) { 24 | if(e != null ) { 25 | SimpleEvent simpleEvent = new SimpleEvent(); 26 | if(e instanceof ChannelData) { 27 | simpleEvent.setId(((ChannelData)e).getId()); 28 | } 29 | simpleEvent.setData(DesCrypter.encrypt(JsonUtils.serialize(e))); 30 | simpleEvent.setType(e.getClass().getCanonicalName()); 31 | if(handler != null) { 32 | simpleEvent.setExpression(handler.expression()); 33 | simpleEvent.setEventHandler(handler); 34 | } 35 | return simpleEvent; 36 | } 37 | return null; 38 | } 39 | 40 | @Override 41 | public Object reCreate(SimpleEvent event, Class clazz) { 42 | if(clazz == null) return null; 43 | if(!SimpleEvent.class.equals(clazz)) { 44 | //还原事件类型 45 | if(event.getData() == null) { 46 | try { 47 | return clazz.newInstance(); 48 | } catch (InstantiationException e) { 49 | // 50 | e.printStackTrace(); 51 | } catch (IllegalAccessException e) { 52 | // 53 | e.printStackTrace(); 54 | } 55 | return null; 56 | } 57 | return JsonUtils.deSerialize(DesCrypter.decrypt(event.getData()), clazz); 58 | } 59 | return event; 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/exception/EventBusException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.exception; 5 | 6 | /**总线异常**/ 7 | public class EventBusException extends RuntimeException { 8 | public EventBusException(String message) { 9 | super(message); 10 | } 11 | 12 | public EventBusException(Throwable cause) { 13 | super(cause); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/exception/EventHandlerException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.exception; 5 | 6 | /**时间消费异常**/ 7 | public class EventHandlerException extends RuntimeException { 8 | public EventHandlerException(String message) { 9 | super(message); 10 | } 11 | 12 | public EventHandlerException(Throwable cause) { 13 | super(cause); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/exception/EventStorageException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.exception; 5 | 6 | /**事件存储异常**/ 7 | public class EventStorageException extends EventBusException { 8 | public EventStorageException(String message) { 9 | super(message); 10 | } 11 | 12 | public EventStorageException(Throwable cause) { 13 | super(cause); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/finder/AbstractHandlerFinder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.finder; 5 | 6 | import com.cubbery.event.EventStorage; 7 | import com.cubbery.event.HandlerFinder; 8 | import com.cubbery.event.handler.EventHandler; 9 | import com.cubbery.event.handler.PersistenceEventHandler; 10 | 11 | import java.lang.reflect.Method; 12 | 13 | abstract class AbstractHandlerFinder implements HandlerFinder { 14 | private EventStorage storage; 15 | 16 | protected EventHandler makeHandler(Object listener, Method method) { 17 | if(getStorage() != null) { 18 | return new PersistenceEventHandler(listener, method,getStorage()); 19 | } 20 | return new EventHandler(listener, method); 21 | } 22 | 23 | public EventStorage getStorage() { 24 | return storage; 25 | } 26 | 27 | public AbstractHandlerFinder setStorage(EventStorage storage) { 28 | this.storage = storage; 29 | return this; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/finder/AnnotatedHandlerFinder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.finder; 5 | 6 | import com.cubbery.event.Subscriber; 7 | import com.cubbery.event.handler.EventHandler; 8 | 9 | import java.lang.reflect.Method; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.Set; 13 | 14 | import static com.cubbery.event.utils.MapUtils.put; 15 | 16 | /**注解方式订阅者查找服务**/ 17 | public class AnnotatedHandlerFinder extends AbstractHandlerFinder { 18 | 19 | @Override 20 | public Map, Set> findAllHandlers(Object listener) { 21 | Map, Set> methodsInAnno = new HashMap, Set>(); 22 | Class clazz = listener.getClass(); 23 | while (clazz != null) { 24 | for (Method method : clazz.getMethods()) { 25 | Subscriber annotation = method.getAnnotation(Subscriber.class); 26 | if (annotation != null) { 27 | Class[] parameterTypes = method.getParameterTypes(); 28 | if (parameterTypes.length != 1) { 29 | throw new IllegalArgumentException( "Method " + method + " has @Subscribe annotation, but requires " + parameterTypes.length + " arguments. Event handler methods " + "must require a single argument."); 30 | } 31 | Class eventType = parameterTypes[0]; 32 | EventHandler handler = makeHandler(listener, method); 33 | put(methodsInAnno,eventType, handler); 34 | } 35 | } 36 | clazz = clazz.getSuperclass(); 37 | } 38 | return methodsInAnno; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/finder/BothHandlerFinder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.finder; 5 | 6 | import com.cubbery.event.EventStorage; 7 | import com.cubbery.event.HandlerFinder; 8 | import com.cubbery.event.handler.EventHandler; 9 | 10 | import java.util.Map; 11 | import java.util.Set; 12 | 13 | import static com.cubbery.event.utils.MapUtils.putAll; 14 | 15 | /**订阅者查找服务**/ 16 | public class BothHandlerFinder extends AbstractHandlerFinder { 17 | private final HandlerFinder annotatedFinder; 18 | private final HandlerFinder listenersFinder; 19 | 20 | public BothHandlerFinder() { 21 | this.annotatedFinder = new AnnotatedHandlerFinder(); 22 | this.listenersFinder = new ListenerHandlerFinder(); 23 | } 24 | 25 | @Override 26 | public Map, Set> findAllHandlers(Object listener) { 27 | Map, Set> multimap = this.annotatedFinder.findAllHandlers(listener); 28 | putAll(multimap,this.listenersFinder.findAllHandlers(listener)); 29 | return multimap; 30 | } 31 | 32 | @Override 33 | public AbstractHandlerFinder setStorage(EventStorage storage) { 34 | super.setStorage(storage); 35 | annotatedFinder.setStorage(getStorage()); 36 | listenersFinder.setStorage(getStorage()); 37 | return this; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/finder/ListenerHandlerFinder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.finder; 5 | 6 | import com.cubbery.event.ISubscribe; 7 | import com.cubbery.event.handler.EventHandler; 8 | 9 | import java.lang.reflect.Method; 10 | import java.lang.reflect.ParameterizedType; 11 | import java.lang.reflect.Type; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | import java.util.Set; 15 | 16 | import static com.cubbery.event.utils.MapUtils.put; 17 | 18 | /**接口方式订阅者查找服务**/ 19 | public class ListenerHandlerFinder extends AbstractHandlerFinder { 20 | 21 | @Override 22 | public Map, Set> findAllHandlers(Object listener) { 23 | Map, Set> methodsInListener = new HashMap, Set>(); 24 | Class clazz = listener.getClass(); 25 | Type[] types = clazz.getGenericInterfaces(); 26 | for(Type type : types) { 27 | if(type instanceof ParameterizedType) { 28 | ParameterizedType parameterizedType = (ParameterizedType) type; 29 | if(!parameterizedType.getRawType().equals(ISubscribe.class)) { 30 | continue; 31 | } 32 | Type[] typeArguments = parameterizedType.getActualTypeArguments(); 33 | if(typeArguments.length == 1) { 34 | try { 35 | Class eventType = ((Class)typeArguments[0]); 36 | Method method = clazz.getMethod(ISubscribe.methodName,eventType); 37 | EventHandler handler = makeHandler(listener, method); 38 | put(methodsInListener,eventType, handler); 39 | } catch (Exception e) { 40 | throw new IllegalArgumentException( "Method has not implements ISubscribe "); 41 | } 42 | } 43 | } 44 | } 45 | return methodsInListener; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/handler/EventHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.handler; 5 | 6 | import com.cubbery.event.channel.ChannelData; 7 | import com.cubbery.event.exception.EventHandlerException; 8 | import com.cubbery.event.utils.Validation; 9 | 10 | import java.lang.reflect.Method; 11 | 12 | /** 13 | * 相当于订阅者的代理 14 | */ 15 | public class EventHandler { 16 | private final Object target; 17 | private final Method method; 18 | 19 | public EventHandler(Object target, Method method) { 20 | Validation.checkNotNull(target, "EventHandler target cannot be null."); 21 | Validation.checkNotNull(method, "EventHandler method cannot be null."); 22 | this.target = target; 23 | this.method = method; 24 | method.setAccessible(true); 25 | } 26 | 27 | public void handleEvent(Object event) throws EventHandlerException { 28 | preHandle(event); 29 | try { 30 | if(event instanceof ChannelData) { 31 | method.invoke(target, new Object[] { ((ChannelData) event).getData() }); 32 | } else { 33 | method.invoke(target, new Object[]{event}); 34 | } 35 | } catch (IllegalArgumentException e) { 36 | throw new Error("Method rejected target/argument: " + event, e); 37 | } catch (IllegalAccessException e) { 38 | throw new Error("Method became inaccessible: " + event, e); 39 | } catch (Throwable e) { 40 | throw new EventHandlerException(e); 41 | } finally { 42 | afterHandle(event); 43 | } 44 | } 45 | 46 | protected void afterHandle(Object event) { 47 | //后置 48 | } 49 | 50 | protected void preHandle(Object event) { 51 | //前置 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | final int PRIME = 31; 57 | return (PRIME + method.hashCode()) * PRIME + target.hashCode(); 58 | } 59 | 60 | @Override 61 | public boolean equals(Object obj) { 62 | if(this == obj) { 63 | return true; 64 | } 65 | if(obj == null) { 66 | return false; 67 | } 68 | if(getClass() != obj.getClass()) { 69 | return false; 70 | } 71 | 72 | final EventHandler other = (EventHandler) obj; 73 | return method.equals(other.method) && target == other.target; 74 | } 75 | 76 | public String expression() { 77 | return target.getClass().getCanonicalName() + "#" + method.getName(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/handler/PersistenceEventHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.handler; 5 | 6 | import com.cubbery.event.EventStorage; 7 | import com.cubbery.event.channel.ChannelData; 8 | import com.cubbery.event.exception.EventHandlerException; 9 | import com.cubbery.event.exception.EventStorageException; 10 | 11 | import java.lang.reflect.Method; 12 | 13 | /** 14 | * 持久化类型的事件订阅者代理 15 | */ 16 | public class PersistenceEventHandler extends EventHandler { 17 | private final EventStorage storage; 18 | 19 | public PersistenceEventHandler(Object target, Method method, EventStorage storage) { 20 | super(target, method); 21 | this.storage = storage; 22 | } 23 | 24 | @Override 25 | public void handleEvent(Object event) { 26 | long id = 0; 27 | if(event instanceof ChannelData) { 28 | id = ((ChannelData)event).getId(); 29 | } 30 | if(id < 0) { 31 | throw new EventStorageException("Persistence Data Should Be Have A PrimerKey!"); 32 | } 33 | try { 34 | super.handleEvent(event); 35 | markAsSuccess(id); 36 | } catch (EventHandlerException e) { 37 | markAsRetry(id); 38 | } catch (Throwable throwable) { 39 | markAsDead(id); 40 | } 41 | } 42 | 43 | private void markAsDead(long id) { 44 | if(id > 0) { 45 | storage.markAsDead(id); 46 | } 47 | } 48 | 49 | private void markAsRetry(long id) { 50 | if(id > 0) { 51 | storage.markAsRetry(id); 52 | } 53 | } 54 | 55 | private void markAsSuccess(long id) { 56 | if(id > 0) { 57 | storage.markAsSuccess(id); 58 | } 59 | } 60 | 61 | public EventStorage getStorage() { 62 | return storage; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/monitor/ChannelStatistics.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.monitor; 5 | 6 | import com.cubbery.event.Statistics; 7 | 8 | /** 9 | * 队列监控指标,接入方可以使用自行定义的队列以及监控。比如监控数据实时汇报到zk。后台对zk的节点做监控数据读取 10 | */ 11 | public class ChannelStatistics extends Statistics { 12 | private static final String COUNTER_CHANNEL_SIZE = "channel.current.size"; 13 | 14 | private static final String COUNTER_EVENT_PUT_ATTEMPT = "channel.event.put.attempt"; 15 | 16 | private static final String COUNTER_EVENT_TAKE_ATTEMPT = "channel.event.take.attempt"; 17 | 18 | private static final String COUNTER_EVENT_PUT_SUCCESS = "channel.event.put.success"; 19 | 20 | private static final String COUNTER_EVENT_TAKE_SUCCESS = "channel.event.take.success"; 21 | 22 | private static final String COUNTER_CHANNEL_CAPACITY = "channel.capacity"; 23 | 24 | private static final String[] ATTRIBUTES = { 25 | COUNTER_CHANNEL_SIZE, COUNTER_EVENT_PUT_ATTEMPT, 26 | COUNTER_EVENT_TAKE_ATTEMPT, COUNTER_EVENT_PUT_SUCCESS, 27 | COUNTER_EVENT_TAKE_SUCCESS, COUNTER_CHANNEL_CAPACITY 28 | }; 29 | 30 | public ChannelStatistics(String name) { 31 | super(Type.CHANNEL, name, ATTRIBUTES); 32 | } 33 | 34 | public ChannelStatistics(String name, String[] attrs) { 35 | super(Type.CHANNEL, name, attrs); 36 | } 37 | 38 | public long getChannelSize() { 39 | return get(COUNTER_CHANNEL_SIZE); 40 | } 41 | 42 | public void setChannelSize(long newSize) { 43 | set(COUNTER_CHANNEL_SIZE, newSize); 44 | } 45 | 46 | public long getEventPutAttemptCount() { 47 | return get(COUNTER_EVENT_PUT_ATTEMPT); 48 | } 49 | 50 | public long incrementEventPutAttemptCount() { 51 | return increment(COUNTER_EVENT_PUT_ATTEMPT); 52 | } 53 | 54 | public long incrementEventPutAttemptCount(int step) { 55 | return addAndGet(COUNTER_EVENT_PUT_ATTEMPT,step); 56 | } 57 | 58 | public long getEventTakeAttemptCount() { 59 | return get(COUNTER_EVENT_TAKE_ATTEMPT); 60 | } 61 | 62 | public long incrementEventTakeAttemptCount(int step) { 63 | return addAndGet(COUNTER_EVENT_TAKE_ATTEMPT,step); 64 | } 65 | public long incrementEventTakeAttemptCount() { 66 | return increment(COUNTER_EVENT_TAKE_ATTEMPT); 67 | } 68 | 69 | public long getEventPutSuccessCount() { 70 | return get(COUNTER_EVENT_PUT_SUCCESS); 71 | } 72 | 73 | public long addToEventPutSuccessCount(long delta) { 74 | return addAndGet(COUNTER_EVENT_PUT_SUCCESS, delta); 75 | } 76 | 77 | public long getEventTakeSuccessCount() { 78 | return get(COUNTER_EVENT_TAKE_SUCCESS); 79 | } 80 | 81 | public long addToEventTakeSuccessCount(long delta) { 82 | return addAndGet(COUNTER_EVENT_TAKE_SUCCESS, delta); 83 | } 84 | 85 | public void setChannelCapacity(long capacity){ 86 | set(COUNTER_CHANNEL_CAPACITY, capacity); 87 | } 88 | 89 | public long getChannelCapacity(){ 90 | return get(COUNTER_CHANNEL_CAPACITY); 91 | } 92 | 93 | public double getChannelFillPercentage(){ 94 | long capacity = getChannelCapacity(); 95 | if(capacity != 0L) { 96 | return ((getChannelSize()/(double)capacity) * 100); 97 | } 98 | return Double.MAX_VALUE; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/retry/Lease.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.retry; 5 | 6 | import java.io.Serializable; 7 | import java.util.Date; 8 | 9 | public class Lease implements Serializable { 10 | //主键 11 | private long id; 12 | //修改时间(master最后续租期时间) 13 | private Date modifiedTime; 14 | //创建时间 15 | private Date createdTime; 16 | //数据库当前时间(用作查询,不做存储) 17 | private Date now; 18 | //lease 周期 19 | private long period; 20 | //master 信息 21 | private String master; 22 | //version 用于加乐观锁 23 | private long version; 24 | 25 | public long getId() { 26 | return id; 27 | } 28 | 29 | public void setId(long id) { 30 | this.id = id; 31 | } 32 | 33 | public Date getModifiedTime() { 34 | return modifiedTime; 35 | } 36 | 37 | public void setModifiedTime(Date modifiedTime) { 38 | this.modifiedTime = modifiedTime; 39 | } 40 | 41 | public Date getCreatedTime() { 42 | return createdTime; 43 | } 44 | 45 | public void setCreatedTime(Date createdTime) { 46 | this.createdTime = createdTime; 47 | } 48 | 49 | public Date getNow() { 50 | return now; 51 | } 52 | 53 | public void setNow(Date now) { 54 | this.now = now; 55 | } 56 | 57 | public long getPeriod() { 58 | return period; 59 | } 60 | 61 | public void setPeriod(long period) { 62 | this.period = period; 63 | } 64 | 65 | public String getMaster() { 66 | return master; 67 | } 68 | 69 | public Lease setMaster(String master) { 70 | this.master = master; 71 | return this; 72 | } 73 | 74 | public long getVersion() { 75 | return version; 76 | } 77 | 78 | public void setVersion(long version) { 79 | this.version = version; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/retry/LeaseTask.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.retry; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | /** 10 | * Leader Node Selection With Lease.(time unit:milliseconds) 11 | */ 12 | final class LeaseTask implements Runnable { 13 | private final static Logger LOG = LoggerFactory.getLogger("Lease-Task"); 14 | 15 | private RetryService retryService; 16 | private boolean leaseStop; 17 | 18 | public LeaseTask(RetryService retryService,boolean leaseStop) { 19 | this.retryService = retryService; 20 | this.leaseStop = leaseStop; 21 | } 22 | 23 | @Override 24 | public void run() { 25 | do { 26 | try { 27 | //1、查询Lease表,获取Lease信息 28 | Lease leaseEntity = retryService.getLeaseDao().selectLease(); 29 | LOG.info("Read Lease Master Info ..." + leaseEntity.getMaster()); 30 | long interval = leaseEntity.getNow().getTime() - leaseEntity.getModifiedTime().getTime(); 31 | long milliseconds = leaseEntity.getPeriod() * 1000; 32 | long wait = waitTime(interval,milliseconds); 33 | if(wait > 0) { 34 | LOG.info("Lease Wait for ..." + wait); 35 | Thread.sleep(wait); 36 | continue; 37 | } 38 | //试着去抢占,拿到锁 39 | int row = retryService.getLeaseDao().updateLease(retryService.getName(),leaseEntity.getVersion(),retryService.getLeasePeriod()); 40 | LOG.info("Compete Lease Master ..." + row); 41 | retryService.setMaster(row == 1);//不关心前一次的状态,不用cas。按照最后最新的数据去覆盖。 42 | } catch (Throwable e) { 43 | LOG.error("Lease is terminal !",e); 44 | retryService.setMaster(false);//处理异常无条件设置为普通节点。 45 | sleep();//此时被打断,不再care,进入下一个循环。 46 | } 47 | } while (!leaseStop); 48 | } 49 | 50 | private long waitTime(long interval,long period) { 51 | if(retryService.isMaster()) { 52 | return period - interval - retryService.getPriority() * 1000; 53 | } 54 | return period - interval; 55 | } 56 | 57 | private void sleep() { 58 | try { 59 | Thread.sleep(100); 60 | } catch (InterruptedException e) { 61 | Thread.interrupted(); 62 | LOG.error("Lease is Interrupted !", e); 63 | } 64 | } 65 | 66 | public synchronized void stop() { 67 | LOG.info("Try To Lease Service !"); 68 | leaseStop = true; 69 | retryService.setMaster(false); 70 | LOG.info("Stop Retry Service Success !"); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/retry/RetryMarker.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.retry; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.util.Timer; 10 | import java.util.TimerTask; 11 | 12 | /** 13 | * A Daemon Thread For :Batch Mark Consume State To Retry State & Batch Mark Retry State To Dead State. 14 | */ 15 | class RetryMarker extends TimerTask { 16 | private final static Logger LOG = LoggerFactory.getLogger("Retry_Marker"); 17 | private final static long period = 10 * 60 * 1000;// 10 min 18 | private Timer timer; 19 | private RetryService retryService; 20 | 21 | public RetryMarker(RetryService retryService) { 22 | this.retryService = retryService; 23 | timer = new Timer(true); 24 | } 25 | 26 | @Override 27 | public void run() { 28 | try { 29 | int rows = retryService.getLeaseDao().batchMarkAsRetry(); 30 | LOG.info("Execute Batch Mark to Retry Success ! Row = " + rows); 31 | int num = retryService.getLeaseDao().batchMarkAsDead(retryService.getMaxRetryCount()); 32 | LOG.info("Execute Batch Mark to Dead Success ! MaxRetry = " + retryService.getMaxRetryCount() + " Row = " + num); 33 | } catch (Exception e) { 34 | LOG.info("Retry Batch Mark Error!"); 35 | } 36 | } 37 | 38 | public synchronized void start() { 39 | timer.purge(); 40 | timer.scheduleAtFixedRate(this,0,period); 41 | } 42 | 43 | public synchronized void stop() { 44 | timer.cancel(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/utils/Formatter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016,www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.utils; 5 | 6 | /** 7 | * 类描述
8 | * 创建人百墨
9 | * 创建时间: 2016/4/15 - 9:53
10 | * 11 | * @version 1.0.0
12 | */ 13 | public final class Formatter { 14 | 15 | /** 16 | * 把纳秒的输出增加千分位,方便人工读数.例如:1234567 => 1,234,567 17 | * 18 | * @param ns 1234567 19 | * @return 1,234,567 20 | */ 21 | public static String formatNS(long ns) { 22 | String src = String.valueOf(ns); 23 | int len = src.length(); 24 | int count = len / 3; 25 | int first = len % 3; 26 | if (count < 1 || (count == 1 && first == 0)) { 27 | return src; 28 | } 29 | if (first == 0) { 30 | first = 3; 31 | count--; 32 | } 33 | StringBuilder sb = new StringBuilder(len + count); 34 | for (int i = 0; i < len; i++) { 35 | sb.append(src.charAt(i)); 36 | if ((i+1) == first) { 37 | sb.append(','); 38 | } else if (i > first && ((i+1-first)%3) == 0 && (i+1) < len) { 39 | sb.append(','); 40 | } 41 | } 42 | String fmt = sb.toString(); 43 | //assert fmt.length() == (len+count); 44 | return fmt; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/utils/HostUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.utils; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.lang.management.ManagementFactory; 10 | import java.net.InetAddress; 11 | import java.net.NetworkInterface; 12 | import java.util.Enumeration; 13 | import java.util.Random; 14 | import java.util.regex.Pattern; 15 | 16 | /** 17 | * 创建人百墨
18 | * 修改人
19 | * 创建时间: 2016/3/29 - 10:05
20 | * 21 | * @version 1.0.0
22 | */ 23 | public class HostUtils { 24 | private static final Logger logger = LoggerFactory.getLogger(HostUtils.class); 25 | 26 | public static final String LOCALHOST = "127.0.0.1"; 27 | 28 | public static final String ANYHOST = "0.0.0.0"; 29 | 30 | private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); 31 | 32 | private static volatile InetAddress LOCAL_ADDRESS = null; 33 | 34 | /** 35 | * 获取当前机器的标识: ip_pid_random 36 | * 37 | * @return 38 | */ 39 | public static String aboutThisJvm() { 40 | StringBuffer sb = new StringBuffer(); 41 | sb.append(getLocalHost()); 42 | // get name representing the running Java virtual machine. 43 | String name = ManagementFactory.getRuntimeMXBean().getName(); 44 | // get pid 45 | sb.append("_").append(name.split("@")[0]); 46 | sb.append("_").append(new Random().nextInt(100)); 47 | return sb.toString(); 48 | } 49 | 50 | /** 51 | * 如果获取网络地址失败,返回本地回环地址:127.0.0.1 52 | * 53 | * @return 本地地址 54 | */ 55 | public static String getLocalHost() { 56 | InetAddress address = getLocalAddress(); 57 | return address == null ? LOCALHOST : address.getHostAddress(); 58 | } 59 | 60 | public static boolean isValidNetAddress(String ipAddress) { 61 | return (ipAddress != null 62 | && ! ANYHOST.equals(ipAddress) 63 | && ! LOCALHOST.equals(ipAddress) 64 | && IP_PATTERN.matcher(ipAddress).matches()); 65 | } 66 | 67 | public static boolean isValidIpAddress(String ipAddress) { 68 | return (ipAddress != null && IP_PATTERN.matcher(ipAddress).matches()); 69 | } 70 | 71 | /** 72 | * 遍历本地网卡,返回第一个合理的IP。 73 | * 74 | * @return 本地网卡IP 75 | */ 76 | private static InetAddress getLocalAddress() { 77 | if (LOCAL_ADDRESS != null) 78 | return LOCAL_ADDRESS; 79 | InetAddress localAddress = getLocalAddress0(); 80 | LOCAL_ADDRESS = localAddress; 81 | return localAddress; 82 | } 83 | 84 | private static InetAddress getLocalAddress0() { 85 | InetAddress localAddress = null; 86 | try { 87 | localAddress = InetAddress.getLocalHost(); 88 | if (isValidAddress(localAddress)) { 89 | return localAddress; 90 | } 91 | } catch (Throwable e) { 92 | logger.warn("Failed to retrieving ip address, " + e.getMessage(), e); 93 | } 94 | try { 95 | Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); 96 | if (interfaces != null) { 97 | while (interfaces.hasMoreElements()) { 98 | try { 99 | NetworkInterface network = interfaces.nextElement(); 100 | Enumeration addresses = network.getInetAddresses(); 101 | if (addresses != null) { 102 | while (addresses.hasMoreElements()) { 103 | try { 104 | InetAddress address = addresses.nextElement(); 105 | if (isValidAddress(address)) { 106 | return address; 107 | } 108 | } catch (Throwable e) { 109 | logger.warn("Failed to retrieving ip address, " + e.getMessage(), e); 110 | } 111 | } 112 | } 113 | } catch (Throwable e) { 114 | logger.warn("Failed to retrieving ip address, " + e.getMessage(), e); 115 | } 116 | } 117 | } 118 | } catch (Throwable e) { 119 | logger.warn("Failed to retrieving ip address, " + e.getMessage(), e); 120 | } 121 | logger.error("Could not get local host ip address, will use 127.0.0.1 instead."); 122 | return localAddress; 123 | } 124 | 125 | private static boolean isValidAddress(InetAddress address) { 126 | if (address == null || address.isLoopbackAddress()) { 127 | return false; 128 | } 129 | String name = address.getHostAddress(); 130 | return isValidNetAddress(name); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/utils/JsonUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.utils; 5 | 6 | import com.google.gson.Gson; 7 | import com.google.gson.GsonBuilder; 8 | 9 | public class JsonUtils { 10 | private static Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create(); 11 | 12 | private JsonUtils() { 13 | } 14 | 15 | public static String serialize(T obj) { 16 | try { 17 | return gson.toJson(obj); 18 | } catch (Exception e) { 19 | return null; 20 | } 21 | } 22 | 23 | public static T deSerialize(String json, Class classOfT) { 24 | try { 25 | return gson.fromJson(json, classOfT); 26 | } catch (Exception e) { 27 | return null; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/utils/MapUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.utils; 5 | 6 | import com.cubbery.event.handler.EventHandler; 7 | 8 | import java.util.HashSet; 9 | import java.util.Map; 10 | import java.util.Set; 11 | 12 | public class MapUtils { 13 | 14 | public static void put(final Map, Set> map,final Class clazz,final EventHandler handler) { 15 | if(!map.containsKey(clazz)) { 16 | map.put(clazz,new HashSet());//初始化 17 | } 18 | map.get(clazz).add(handler); 19 | } 20 | 21 | public static void put(final Map, Set> map,final Class clazz,final Set handler) { 22 | if(!map.containsKey(clazz)) { 23 | map.put(clazz,new HashSet());//初始化 24 | } 25 | map.get(clazz).addAll(handler); 26 | } 27 | 28 | public static void putAll(final Map, Set> map,final Map, Set> map0) { 29 | Set> keys = map0.keySet(); 30 | for(Class clazz : keys) { 31 | put(map,clazz,map0.get(clazz)); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/utils/RefactorUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.utils; 5 | 6 | import java.lang.reflect.Constructor; 7 | import java.lang.reflect.InvocationTargetException; 8 | 9 | /** 10 | * 创建人百墨
11 | * 创建时间: 2016/3/9 - 9:28
12 | * @version 1.0.0
13 | */ 14 | public class RefactorUtils { 15 | public static Object newInstance(Class target,Object...parameters){ 16 | try { 17 | if(parameters == null || parameters.length == 0) { 18 | return target.newInstance(); 19 | } 20 | Class[] parameterTypes = new Class[parameters.length]; 21 | for(int i = 0 ; i < parameters.length ; i++) { 22 | parameterTypes[i] = convertPrimitive(parameters[i].getClass()); 23 | } 24 | Constructor constructor = target.getConstructor(parameterTypes); 25 | return constructor.newInstance(parameters); 26 | } catch (NoSuchMethodException e) { 27 | //TODO 需要特殊处理 28 | e.printStackTrace(); 29 | } catch (InvocationTargetException e) { 30 | e.printStackTrace(); 31 | } catch (InstantiationException e) { 32 | e.printStackTrace(); 33 | } catch (IllegalAccessException e) { 34 | e.printStackTrace(); 35 | } 36 | return null; 37 | } 38 | 39 | private static Class convertPrimitive(Class clazz) { 40 | if(clazz == Boolean.class) return boolean.class; 41 | if(clazz == Character.class) return char.class; 42 | if(clazz == Byte.class) return byte.class; 43 | if(clazz == Short.class) return short.class; 44 | if(clazz == Integer.class) return int.class; 45 | if(clazz == Long.class) return long.class; 46 | if(clazz == Float.class) return float.class; 47 | if(clazz == Double.class) return double.class; 48 | return clazz; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/utils/ThreadFactories.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.utils; 5 | 6 | import java.util.concurrent.ThreadFactory; 7 | import java.util.concurrent.atomic.AtomicInteger; 8 | 9 | public class ThreadFactories implements ThreadFactory { 10 | private final AtomicInteger threadId ; 11 | private final StringBuilder prefix ; 12 | private final boolean isDaemon; 13 | 14 | public ThreadFactories(String name) { 15 | this(false,name); 16 | } 17 | 18 | public ThreadFactories(boolean isDaemon, String name) { 19 | this.prefix = new StringBuilder("Async_Event_").append(name).append("_"); 20 | this.threadId = new AtomicInteger(0); 21 | this.isDaemon = isDaemon; 22 | } 23 | 24 | @Override 25 | public Thread newThread(Runnable r) { 26 | Thread thread = new Thread(r); 27 | //mark as user thread ,the jvm exit on all of the thread are demon! 28 | thread.setDaemon(isDaemon); 29 | thread.setName(prefix.toString() + threadId.incrementAndGet()); 30 | return thread; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/utils/Threads.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.utils; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.util.concurrent.ExecutorService; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | public class Threads { 13 | private final static Logger LOG = LoggerFactory.getLogger(Threads.class); 14 | /** 15 | * sleep等待,单位为毫秒,忽略InterruptedException 16 | * 17 | * @param millis 18 | */ 19 | public static void sleep(long millis) { 20 | try { 21 | Thread.sleep(millis); 22 | } catch (InterruptedException e) { 23 | Thread.interrupted(); 24 | return; 25 | } 26 | } 27 | 28 | /** 29 | * sleep等待,忽略InterruptedException 30 | * 31 | * @param duration 32 | * @param unit 33 | */ 34 | public static void sleep(long duration, TimeUnit unit) { 35 | try { 36 | Thread.sleep(unit.toMillis(duration)); 37 | } catch (InterruptedException e) { 38 | Thread.interrupted(); 39 | return; 40 | } 41 | } 42 | 43 | /** 44 | * 两阶段关闭: 45 | * 第一阶段调用 shutdown 拒绝传入任务。 46 | * 第二阶段调用 shutdownNow(如有必要)取消所有遗留的任务。 47 | * 48 | * @param pool 49 | */ 50 | public static void shutDownAndAwaitTerminal(ExecutorService pool) { 51 | if(pool == null) { 52 | return; 53 | } 54 | //Disable new tasks from being submitted 55 | pool.shutdown(); 56 | try { 57 | //Wait a while(10s) for existing tasks to terminate 58 | if(!pool.awaitTermination(10,TimeUnit.SECONDS)) { 59 | // Cancel currently executing tasks 60 | pool.shutdownNow(); 61 | // Wait a while for tasks to respond to being cancelled 62 | if(!pool.awaitTermination(10,TimeUnit.SECONDS)) { 63 | LOG.error("Pool did not terminate! "); 64 | } 65 | } 66 | } catch (InterruptedException e) { 67 | // (Re-)Cancel if current thread also interrupted 68 | pool.shutdownNow(); 69 | // Preserve interrupt status 70 | Thread.currentThread().interrupt(); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/utils/Validation.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.utils; 5 | 6 | /** 7 | * 创建人百墨
8 | * @version 1.0.0
9 | */ 10 | public class Validation { 11 | public static T checkNotNull(T reference) { 12 | if (reference == null) { 13 | throw new NullPointerException(); 14 | } 15 | return reference; 16 | } 17 | 18 | public static T checkNotNull(T reference, Object errorMessage) { 19 | if (reference == null) { 20 | throw new NullPointerException(String.valueOf(errorMessage)); 21 | } 22 | return reference; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/utils/security/Des.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.utils.security; 5 | 6 | import javax.crypto.Cipher; 7 | 8 | class Des { 9 | protected final String FACTORY_KEY = "PBEWithMD5AndDES"; 10 | protected Cipher cipher; 11 | 12 | // 8-byte Salt 13 | static byte[] salt = { 14 | (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, 15 | (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03 16 | }; 17 | 18 | // Iteration count 19 | static int iterationCount = 3; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/utils/security/DesCrypter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.utils.security; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import javax.crypto.*; 10 | import javax.crypto.spec.PBEKeySpec; 11 | import javax.crypto.spec.PBEParameterSpec; 12 | import java.security.spec.AlgorithmParameterSpec; 13 | import java.security.spec.KeySpec; 14 | 15 | public class DesCrypter { 16 | private final static String DES_KEY = "zX/95tXv+4PTBD4xkm3992jpnqcynZ#@"; 17 | private final static Logger LOG = LoggerFactory.getLogger(DesCrypter.class); 18 | //cipher 非线程安全 19 | private static ThreadLocal desEncrypter = new ThreadLocal(){ 20 | @Override 21 | protected Encrypter initialValue() { 22 | try { 23 | return new Encrypter(DES_KEY); 24 | } catch (Exception e) { 25 | LOG.info("Encrypter Init Error!",e); 26 | return null; 27 | } 28 | } 29 | }; 30 | private static ThreadLocal desDecrypter = new ThreadLocal(){ 31 | @Override 32 | protected Decrypter initialValue() { 33 | try { 34 | return new Decrypter(DES_KEY); 35 | } catch (Exception e) { 36 | LOG.info("Decrypt Init Error!",e); 37 | return null; 38 | } 39 | } 40 | }; 41 | 42 | public static String encrypt(String txt) { 43 | try { 44 | return desEncrypter.get().encrypt(txt); 45 | } catch (Exception e) { 46 | LOG.info("Encrypt Error "); 47 | throw new RuntimeException(e); 48 | } 49 | } 50 | 51 | public static String decrypt(String txt) { 52 | try { 53 | return desDecrypter.get().decrypt(txt); 54 | } catch (Exception e) { 55 | LOG.info("Decrypt Error "); 56 | throw new RuntimeException(e); 57 | } 58 | } 59 | 60 | static class Encrypter extends Des { 61 | 62 | public Encrypter(String passPhrase) throws Exception { 63 | // Create the key 64 | KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount); 65 | SecretKey key = SecretKeyFactory.getInstance(FACTORY_KEY).generateSecret(keySpec); 66 | cipher = Cipher.getInstance(key.getAlgorithm()); 67 | // Prepare the parameter to the ciphers 68 | AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount); 69 | // Create the ciphers 70 | cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); 71 | } 72 | 73 | public String encrypt(String str) throws Exception { 74 | // Encode the string into bytes using utf-8 75 | byte[] utf8 = str.getBytes("UTF-8"); 76 | // Encrypt 77 | byte[] enc = encrypt(utf8); 78 | return Base32.encode(enc); 79 | } 80 | 81 | public byte[] encrypt(byte[] utf8) throws IllegalBlockSizeException, BadPaddingException { 82 | return cipher.doFinal(utf8); 83 | } 84 | } 85 | 86 | static class Decrypter extends Des { 87 | public Decrypter(String passPhrase) throws Exception { 88 | // Create the key 89 | KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount); 90 | SecretKey key = SecretKeyFactory.getInstance(FACTORY_KEY).generateSecret(keySpec); 91 | cipher = Cipher.getInstance(key.getAlgorithm()); 92 | // Prepare the parameter to the ciphers 93 | AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount); 94 | // Create the ciphers 95 | cipher.init(Cipher.DECRYPT_MODE, key, paramSpec); 96 | } 97 | 98 | public String decrypt(String str) throws Exception { 99 | byte[] dec = Base32.decode(str); 100 | // Decrypt 101 | byte[] utf8 = decrypt(dec); 102 | // Decode using utf-8 103 | return new String(utf8,"UTF-8"); 104 | 105 | } 106 | 107 | public byte[] decrypt(byte[] dec) throws IllegalBlockSizeException, BadPaddingException { 108 | return cipher.doFinal(dec); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/worker/AbstractWorker.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.worker; 5 | 6 | import com.cubbery.event.handler.EventHandler; 7 | import com.cubbery.event.handler.PersistenceEventHandler; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | abstract class AbstractWorker { 12 | protected final Logger LOG = LoggerFactory.getLogger("Consume_Worker"); 13 | 14 | protected void markAsDead(EventHandler handler,long id) { 15 | if(handler instanceof PersistenceEventHandler && id > 0) { 16 | PersistenceEventHandler pHandler = (PersistenceEventHandler) handler; 17 | pHandler.getStorage().markAsDead(id); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/worker/ConsumeWorker.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.worker; 5 | 6 | import com.cubbery.event.channel.ChannelData; 7 | import com.cubbery.event.handler.EventHandler; 8 | 9 | /** 10 | * 从queue中取出的event可以使用该worker来消费,否则不能 11 | */ 12 | public class ConsumeWorker extends AbstractWorker implements Runnable { 13 | private EventHandler handler; 14 | private ChannelData event;//从queue中取出的event 15 | 16 | public ConsumeWorker(EventHandler handler, ChannelData event) { 17 | this.handler = handler; 18 | this.event = event; 19 | } 20 | 21 | @Override 22 | public void run() { 23 | try { 24 | handler.handleEvent(event); 25 | } catch (Throwable throwable) { 26 | //对于非持久化的消息,异常会从handler穿透到这里,所以catch处理之 27 | LOG.error("Error Consume Event {} ",event.getData()); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /async-event-core/src/main/java/com/cubbery/event/worker/RetryWorker.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.worker; 5 | 6 | import com.cubbery.event.EventBus; 7 | import com.cubbery.event.channel.ChannelData; 8 | import com.cubbery.event.event.SimpleEvent; 9 | import com.cubbery.event.handler.EventHandler; 10 | 11 | /** 12 | * 此时由于从数据库中加载的event都泛化成了simpleEvent,所以需要先做一次还原。 13 | */ 14 | public class RetryWorker extends AbstractWorker implements Runnable { 15 | private final EventBus eventBus; 16 | private final EventHandler handler; 17 | private final SimpleEvent simpleEvent;//从queue中取出的event 18 | 19 | public RetryWorker(EventBus eventBus, EventHandler handler, SimpleEvent event) { 20 | this.eventBus = eventBus; 21 | this.handler = handler; 22 | this.simpleEvent = event; 23 | } 24 | 25 | 26 | @Override 27 | public void run() { 28 | Class clazz = eventBus.getEventClassByType(simpleEvent.getType()); 29 | Object obj = eventBus.getChannel().getCreator().reCreate(simpleEvent,clazz); 30 | if(obj != null) { 31 | handler.handleEvent(new ChannelData(obj,simpleEvent.getId(),handler)); 32 | } else { 33 | markAsDead(this.handler,this.simpleEvent.getId()); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /async-event-core/src/test/java/com/cubbery/event/Demo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | import com.cubbery.event.channel.MemoryChannel; 7 | import com.cubbery.event.event.SimpleEvent; 8 | import com.cubbery.event.utils.Threads; 9 | 10 | import java.util.concurrent.CountDownLatch; 11 | import java.util.concurrent.atomic.AtomicInteger; 12 | 13 | public class Demo { 14 | private static volatile boolean end = false; 15 | 16 | public static void main(String[] args) throws InterruptedException { 17 | final EventBus eventBus = new EventBus(new MemoryChannel(1024)); 18 | eventBus.register(new AnnotationSub()); 19 | eventBus.register(new AnnotationSub2()); 20 | eventBus.start(); 21 | 22 | final CountDownLatch countDownLatch = new CountDownLatch(1); 23 | for (int i = 0; i < 10 && !end; i++) { 24 | new Thread(new Runnable() { 25 | @Override 26 | public void run() { 27 | try { 28 | countDownLatch.await(); 29 | } catch (InterruptedException e) { 30 | e.printStackTrace(); 31 | } 32 | for (int a = 0; a < 100; a++) { 33 | eventBus.publish(new SimpleEvent()); 34 | } 35 | } 36 | }).start(); 37 | } 38 | countDownLatch.countDown(); 39 | Threads.sleep(1000); 40 | end = true; 41 | eventBus.stop(); 42 | } 43 | } 44 | 45 | class AnnotationSub { 46 | AtomicInteger counter = new AtomicInteger(0); 47 | 48 | @Subscriber 49 | public void handler(SimpleEvent event) { 50 | System.out.println(System.currentTimeMillis() + " ---1---> " + counter.incrementAndGet()); 51 | } 52 | } 53 | 54 | class AnnotationSub2 { 55 | AtomicInteger counter = new AtomicInteger(0); 56 | 57 | @Subscriber 58 | public void handler(SimpleEvent event) { 59 | System.out.println(System.currentTimeMillis() + " ----2--> " + counter.incrementAndGet()); 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /async-event-core/src/test/java/com/cubbery/event/Demo2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | import com.cubbery.event.finder.ListenerHandlerFinder; 7 | import com.cubbery.event.utils.Threads; 8 | import com.cubbery.event.channel.MemoryChannel; 9 | import com.cubbery.event.event.SimpleEvent; 10 | 11 | import java.util.concurrent.CountDownLatch; 12 | import java.util.concurrent.atomic.AtomicInteger; 13 | 14 | public class Demo2 { 15 | private static volatile boolean end = false; 16 | 17 | public static void main(String[] args) { 18 | final EventBus eventBus = new EventBus(new MemoryChannel(1024),new ListenerHandlerFinder()); 19 | eventBus.register(new InterSub()); 20 | eventBus.register(new InterSub2()); 21 | eventBus.start(); 22 | 23 | final CountDownLatch countDownLatch = new CountDownLatch(1); 24 | for (int i = 0; i < 10 && !end; i++) { 25 | new Thread(new Runnable() { 26 | @Override 27 | public void run() { 28 | try { 29 | countDownLatch.await(); 30 | } catch (InterruptedException e) { 31 | e.printStackTrace(); 32 | } 33 | for (int a = 0; a < 100; a++) { 34 | eventBus.publish(new SimpleEvent()); 35 | } 36 | } 37 | }).start(); 38 | } 39 | countDownLatch.countDown(); 40 | Threads.sleep(1000); 41 | end = true; 42 | eventBus.stop(); 43 | } 44 | } 45 | 46 | class InterSub implements ISubscribe { 47 | AtomicInteger counter = new AtomicInteger(0); 48 | 49 | @Override 50 | public void handler(SimpleEvent event) { 51 | System.out.println(System.currentTimeMillis() + " ---1---> " + counter.incrementAndGet()); 52 | } 53 | } 54 | 55 | class InterSub2 implements ISubscribe { 56 | AtomicInteger counter = new AtomicInteger(0); 57 | 58 | @Override 59 | public void handler(SimpleEvent event) { 60 | System.out.println(System.currentTimeMillis() + " ---2---> " + counter.incrementAndGet()); 61 | } 62 | } -------------------------------------------------------------------------------- /async-event-core/src/test/java/com/cubbery/event/EventBusSpringTest.java: -------------------------------------------------------------------------------- 1 | package com.cubbery.event; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | import java.util.List; 6 | 7 | import static org.testng.Assert.*; 8 | 9 | public class EventBusSpringTest { 10 | @Test 11 | public void ipStrToListTest_single() { 12 | String ipStr = "127.0.0.1"; 13 | List ipList = EventBusSpring.ipStrToList(ipStr); 14 | assertEquals(ipList.get(0),ipStr); 15 | } 16 | 17 | @Test 18 | public void ipStrToListTest_mutip() { 19 | String ipStr = "127.0.0.1|127.0.0.2|127.0.0.4|10.9.45.12"; 20 | List ipList = EventBusSpring.ipStrToList(ipStr); 21 | assertEquals(ipList.get(0),"127.0.0.1"); 22 | assertEquals(ipList.get(1),"127.0.0.2"); 23 | assertEquals(ipList.get(2),"127.0.0.4"); 24 | assertEquals(ipList.get(3),"10.9.45.12"); 25 | } 26 | 27 | @Test 28 | public void ipStrToListTest_unvali() { 29 | String ipStr = "127.0.0|0.0.0.2|127.0.0.4"; 30 | List ipList = EventBusSpring.ipStrToList(ipStr); 31 | //assertEquals(ipList.get(0),"127.0.0"); 32 | assertEquals(ipList.get(0),"0.0.0.2"); 33 | assertEquals(ipList.get(1),"127.0.0.4"); 34 | } 35 | } -------------------------------------------------------------------------------- /async-event-core/src/test/java/com/cubbery/event/SemaphoreTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event; 5 | 6 | import org.testng.annotations.Test; 7 | 8 | import java.util.concurrent.Semaphore; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | import static org.testng.Assert.assertTrue; 12 | import static org.testng.Assert.fail; 13 | 14 | public class SemaphoreTest { 15 | 16 | @Test 17 | public void testSem() { 18 | int size = 3; 19 | Semaphore semaphore = new Semaphore(size); 20 | assertTrue(semaphore.tryAcquire(3)); 21 | //1 22 | semaphore.release(); 23 | try { 24 | assertTrue(!semaphore.tryAcquire(2,1, TimeUnit.SECONDS)); 25 | } catch (InterruptedException e) { 26 | fail(); 27 | } 28 | semaphore.release(); 29 | try { 30 | assertTrue(semaphore.tryAcquire(2,1, TimeUnit.SECONDS)); 31 | } catch (InterruptedException e) { 32 | fail(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /async-event-core/src/test/java/com/cubbery/event/event/Person.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016,www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.event; 5 | 6 | /** 7 | * 类描述
8 | * 创建人百墨
9 | * 创建时间: 2016/4/18 - 16:18
10 | * 11 | * @version 1.0.0
12 | */ 13 | public class Person { 14 | private int age; 15 | private String name; 16 | 17 | public int getAge() { 18 | return age; 19 | } 20 | 21 | public void setAge(int age) { 22 | this.age = age; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /async-event-core/src/test/java/com/cubbery/event/event/SimpleEventTest.java: -------------------------------------------------------------------------------- 1 | package com.cubbery.event.event; 2 | 3 | import com.cubbery.event.handler.EventHandler; 4 | import com.google.gson.Gson; 5 | import com.cubbery.event.event.impl.EncryptEventCreator; 6 | import com.cubbery.event.utils.security.DesCrypter; 7 | import org.testng.annotations.BeforeClass; 8 | import org.testng.annotations.Test; 9 | 10 | import java.lang.reflect.Method; 11 | 12 | import static org.testng.Assert.*; 13 | 14 | public class SimpleEventTest { 15 | 16 | Sub sub; 17 | Method method; 18 | Person person; 19 | 20 | @BeforeClass 21 | public void before() { 22 | person = new Person();person.setAge(111);person.setName("cubbery"); 23 | sub = new Sub(); 24 | try { 25 | method = Sub.class.getMethod("handler",Person.class); 26 | } catch (NoSuchMethodException e) { 27 | fail(); 28 | } 29 | } 30 | 31 | @Test 32 | public void testCreate() throws Exception { 33 | SimpleEvent simple = new EncryptEventCreator().create(person,new EventHandler(sub,method)); 34 | 35 | assertEquals(simple.getData(), DesCrypter.encrypt(new Gson().toJson(person))); 36 | assertEquals(simple.getExpression(),sub.getClass().getCanonicalName() + "#" + method.getName()); 37 | assertEquals(simple.getType(),Person.class.getCanonicalName()); 38 | 39 | } 40 | 41 | @Test 42 | public void testReCreate() throws Exception { 43 | SimpleEvent simple = new SimpleEvent(); 44 | simple.setData(DesCrypter.encrypt(new Gson().toJson(person))); 45 | Object obj = new EncryptEventCreator().reCreate(simple, Person.class); 46 | assertTrue(obj instanceof Person); 47 | Person p = (Person) obj; 48 | assertEquals(p.getAge(),person.getAge()); 49 | assertEquals(p.getName(),person.getName()); 50 | } 51 | 52 | @Test 53 | public void testReCreate_Empty(){ 54 | SimpleEvent simple = new SimpleEvent(); 55 | simple.setData(DesCrypter.encrypt(new Gson().toJson(new Person()))); 56 | Object obj = new EncryptEventCreator().reCreate(simple, Person.class); 57 | assertTrue(obj != null); 58 | assertTrue(obj instanceof Person); 59 | } 60 | 61 | @Test 62 | public void testReCreate_NULL() throws Exception { 63 | SimpleEvent simple = new SimpleEvent(); 64 | simple.setData(null); 65 | Object obj = new EncryptEventCreator().reCreate(simple,Person.class); 66 | assertTrue(obj != null); 67 | assertTrue(obj instanceof Person); 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /async-event-core/src/test/java/com/cubbery/event/event/Sub.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016,www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.event; 5 | 6 | import com.cubbery.event.ISubscribe; 7 | 8 | /** 9 | * 类描述
10 | * 创建人百墨
11 | * 创建时间: 2016/4/18 - 16:18
12 | * 13 | * @version 1.0.0
14 | */ 15 | public class Sub implements ISubscribe { 16 | 17 | @Override 18 | public void handler(Person event) { 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /async-event-core/src/test/java/com/cubbery/event/finder/AnnotatedHandlerFinderTest.java: -------------------------------------------------------------------------------- 1 | package com.cubbery.event.finder; 2 | 3 | import com.cubbery.event.ISubscribe; 4 | import com.cubbery.event.Subscriber; 5 | import com.cubbery.event.event.SimpleEvent; 6 | import com.cubbery.event.handler.EventHandler; 7 | import org.testng.annotations.Test; 8 | 9 | import java.util.Collection; 10 | import java.util.Iterator; 11 | import java.util.Map; 12 | import java.util.Set; 13 | 14 | import static org.testng.Assert.assertTrue; 15 | import static org.testng.Assert.fail; 16 | 17 | public class AnnotatedHandlerFinderTest { 18 | 19 | @Test 20 | public void testFindAllHandlers() throws Exception { 21 | AnnoSub listener = new AnnoSub(); 22 | Map, Set> map = new AnnotatedHandlerFinder().findAllHandlers(listener); 23 | assertTrue(map.containsKey(SimpleEvent.class)); 24 | 25 | Collection handlers = map.get(SimpleEvent.class); 26 | assertTrue(handlers.size() == 1); 27 | Iterator iterator = handlers.iterator(); 28 | assertTrue(iterator.hasNext()); 29 | EventHandler handler = iterator.next(); 30 | try { 31 | assertTrue(handler.equals(new EventHandler(listener,listener.getClass().getMethod(ISubscribe.methodName,SimpleEvent.class)))); 32 | } catch (NoSuchMethodException e) { 33 | fail(); 34 | } 35 | } 36 | } 37 | 38 | class AnnoSub { 39 | 40 | @Subscriber 41 | public void handler(SimpleEvent event) { 42 | 43 | } 44 | } -------------------------------------------------------------------------------- /async-event-core/src/test/java/com/cubbery/event/finder/BothHandlerFinderTest.java: -------------------------------------------------------------------------------- 1 | package com.cubbery.event.finder; 2 | 3 | import com.cubbery.event.ISubscribe; 4 | import com.cubbery.event.Subscriber; 5 | import com.cubbery.event.handler.EventHandler; 6 | import com.cubbery.event.event.SimpleEvent; 7 | import org.testng.annotations.Test; 8 | 9 | import java.lang.reflect.Method; 10 | import java.util.Collection; 11 | import java.util.Iterator; 12 | import java.util.Map; 13 | import java.util.Set; 14 | 15 | import static org.testng.Assert.*; 16 | 17 | public class BothHandlerFinderTest { 18 | 19 | @Test 20 | public void testFindAllHandlers_listener() throws Exception { 21 | Sub listener = new Sub(); 22 | Map, Set> map = new BothHandlerFinder().findAllHandlers(listener); 23 | assertTrue(map.containsKey(SimpleEvent.class)); 24 | 25 | Collection handlers = map.get(SimpleEvent.class); 26 | assertTrue(handlers.size() == 1); 27 | Iterator iterator = handlers.iterator(); 28 | assertTrue(iterator.hasNext()); 29 | EventHandler handler = iterator.next(); 30 | try { 31 | assertTrue(handler.equals(new EventHandler(listener,listener.getClass().getMethod(ISubscribe.methodName,SimpleEvent.class)))); 32 | } catch (NoSuchMethodException e) { 33 | fail(); 34 | } 35 | } 36 | 37 | @Test 38 | public void testFindAllHandlers_anno() throws Exception { 39 | AnnoSub annoSub = new AnnoSub(); 40 | Map, Set> map = new BothHandlerFinder().findAllHandlers(annoSub); 41 | assertTrue(map.containsKey(SimpleEvent.class)); 42 | 43 | Collection handlers = map.get(SimpleEvent.class); 44 | assertTrue(handlers.size() == 1); 45 | Iterator iterator = handlers.iterator(); 46 | assertTrue(iterator.hasNext()); 47 | EventHandler handler = iterator.next(); 48 | try { 49 | assertTrue(handler.equals(new EventHandler(annoSub,annoSub.getClass().getMethod(ISubscribe.methodName,SimpleEvent.class)))); 50 | } catch (NoSuchMethodException e) { 51 | fail(); 52 | } 53 | } 54 | 55 | @Test 56 | public void testFindAllHandlers_both() throws Exception { 57 | BothSub bothSub = new BothSub(); 58 | Map, Set> map = new BothHandlerFinder().findAllHandlers(bothSub); 59 | assertTrue(map.containsKey(SimpleEvent.class)); 60 | 61 | Collection handlers = map.get(SimpleEvent.class); 62 | assertTrue(handlers.size() == 2); 63 | assertTrue(map.get(SimpleEvent.class).contains(new EventHandler(bothSub,bothSub.getClass().getMethod(ISubscribe.methodName,SimpleEvent.class)))); 64 | 65 | Method method = null; 66 | for(Method m : BothSub.class.getMethods()) { 67 | if(m.isAnnotationPresent(Subscriber.class)) { 68 | method = m; 69 | break; 70 | } 71 | } 72 | if(method != null) { 73 | assertTrue(map.get(SimpleEvent.class).contains(new EventHandler(bothSub, method))); 74 | } else { 75 | fail(); 76 | } 77 | } 78 | 79 | @Test 80 | public void testFindAllHandlers_both2() throws NoSuchMethodException { 81 | BothSub2 bothSub = new BothSub2(); 82 | Map, Set> map = new BothHandlerFinder().findAllHandlers(bothSub); 83 | assertTrue(map.containsKey(SimpleEvent.class)); 84 | 85 | Collection handlers = map.get(SimpleEvent.class); 86 | assertTrue(handlers.size() == 1); 87 | assertTrue(map.get(SimpleEvent.class).contains(new EventHandler(bothSub,bothSub.getClass().getMethod(ISubscribe.methodName,SimpleEvent.class)))); 88 | } 89 | } 90 | 91 | class BothSub implements ISubscribe { 92 | 93 | @Override 94 | public void handler(SimpleEvent event) { 95 | 96 | } 97 | 98 | @Subscriber 99 | public void handler0(SimpleEvent event) { 100 | 101 | } 102 | } 103 | 104 | class BothSub2 implements ISubscribe { 105 | 106 | @Subscriber 107 | @Override 108 | public void handler(SimpleEvent event) { 109 | 110 | } 111 | } -------------------------------------------------------------------------------- /async-event-core/src/test/java/com/cubbery/event/finder/ListenerHandlerFinderTest.java: -------------------------------------------------------------------------------- 1 | package com.cubbery.event.finder; 2 | 3 | import com.cubbery.event.ISubscribe; 4 | import com.cubbery.event.event.SimpleEvent; 5 | import com.cubbery.event.handler.EventHandler; 6 | import org.testng.annotations.Test; 7 | 8 | import java.util.Collection; 9 | import java.util.Iterator; 10 | import java.util.Map; 11 | import java.util.Set; 12 | 13 | import static org.testng.Assert.assertTrue; 14 | import static org.testng.Assert.fail; 15 | 16 | public class ListenerHandlerFinderTest { 17 | 18 | @Test 19 | public void testFindAllHandlers() { 20 | Sub listener = new Sub(); 21 | Map, Set> map = new ListenerHandlerFinder().findAllHandlers(listener); 22 | assertTrue(map.containsKey(SimpleEvent.class)); 23 | 24 | Collection handlers = map.get(SimpleEvent.class); 25 | assertTrue(handlers.size() == 1); 26 | Iterator iterator = handlers.iterator(); 27 | assertTrue(iterator.hasNext()); 28 | EventHandler handler = iterator.next(); 29 | try { 30 | assertTrue(handler.equals(new EventHandler(listener,listener.getClass().getMethod(ISubscribe.methodName,SimpleEvent.class)))); 31 | } catch (NoSuchMethodException e) { 32 | fail(); 33 | } 34 | } 35 | } 36 | 37 | class Sub implements ISubscribe { 38 | 39 | @Override 40 | public void handler(SimpleEvent event) { 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /async-event-core/src/test/java/com/cubbery/event/utils/HostUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.cubbery.event.utils; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | import static org.testng.Assert.*; 6 | 7 | public class HostUtilsTest { 8 | 9 | @Test 10 | public void testAboutThisJvm() throws Exception { 11 | 12 | } 13 | 14 | // @Test 15 | public void testIpAddress() throws Exception { 16 | assertEquals(HostUtils.getLocalHost(),"10.9.45.12"); 17 | } 18 | } -------------------------------------------------------------------------------- /async-event-core/testng-qa.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /async-event-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | async-event 7 | com.cubbery.event 8 | 1.0.1 9 | 10 | 4.0.0 11 | async-event-example 12 | 13 | 14 | UTF-8 15 | 11.2.0.2.0 16 | 3.2.4.RELEASE 17 | 18 | 19 | 20 | 21 | 22 | com.cubbery.event 23 | async-event-monitor 24 | 25 | 26 | com.cubbery.event 27 | async-event-core 28 | 29 | 30 | com.cubbery.event 31 | async-event-jdbc 32 | 33 | 34 | mysql 35 | mysql-connector-java 36 | 37 | 38 | com.oracle 39 | ojdbc14 40 | 41 | 42 | 43 | 44 | 45 | org.springframework 46 | spring-core 47 | ${spring_version} 48 | 49 | 50 | org.springframework 51 | spring-beans 52 | ${spring_version} 53 | 54 | 55 | org.springframework 56 | spring-context 57 | ${spring_version} 58 | 59 | 60 | org.springframework 61 | spring-context-support 62 | ${spring_version} 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/SampleWithAnnotaionSub.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample; 5 | 6 | import com.cubbery.event.EventBus; 7 | import com.cubbery.event.channel.MemoryChannel; 8 | import com.cubbery.event.event.SimpleEvent; 9 | import com.cubbery.event.sample.event.AnnotationSub; 10 | import com.cubbery.event.sample.event.BothSub; 11 | import com.cubbery.event.sample.event.EventA; 12 | import com.cubbery.event.sample.event.EventAny; 13 | 14 | public class SampleWithAnnotaionSub { 15 | public static void main(String[] args) { 16 | final EventBus eventBus = new EventBus(new MemoryChannel(1024)); 17 | eventBus.register(new AnnotationSub()); 18 | eventBus.register(new BothSub()); 19 | eventBus.start(); 20 | 21 | try { 22 | eventBus.publish(new SimpleEvent()); 23 | } catch (Exception e) { 24 | 25 | } 26 | eventBus.publish(new EventAny()); 27 | eventBus.publish(new EventA()); 28 | eventBus.stop(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/SampleWithListenerSub.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample; 5 | 6 | import com.cubbery.event.sample.event.BothSub; 7 | import com.cubbery.event.sample.event.EventA; 8 | import com.cubbery.event.sample.event.EventAny; 9 | import com.cubbery.event.sample.event.ListenerSub; 10 | import com.cubbery.event.EventBus; 11 | import com.cubbery.event.channel.MemoryChannel; 12 | import com.cubbery.event.event.SimpleEvent; 13 | 14 | public class SampleWithListenerSub { 15 | public static void main(String[] args) { 16 | //实例化事件总线,使用内存队列 17 | final EventBus eventBus = new EventBus(new MemoryChannel(1024)); 18 | //注册消费者 19 | eventBus.register(new ListenerSub()); 20 | eventBus.register(new BothSub()); 21 | //启动事件总线 22 | eventBus.start(); 23 | 24 | //发送事件消息(需要启动后才能发送) 25 | try { 26 | eventBus.publish(new SimpleEvent()); 27 | } catch (Exception e) { 28 | 29 | } 30 | eventBus.publish(new EventAny()); 31 | eventBus.publish(new EventA()); 32 | //停止事件总线 33 | eventBus.stop(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/SampleWithMonitoredChannel.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample; 5 | 6 | import com.cubbery.event.EventBus; 7 | import com.cubbery.event.channel.MonitoredChannel; 8 | import com.cubbery.event.monitor.ChannelStatistics; 9 | import com.cubbery.event.sample.event.EventA; 10 | import com.cubbery.event.sample.event.ListenerSub; 11 | import com.cubbery.event.utils.Threads; 12 | 13 | import java.util.concurrent.atomic.AtomicBoolean; 14 | 15 | public class SampleWithMonitoredChannel { 16 | public static void main(String[] args) { 17 | final ChannelStatistics cs = new ChannelStatistics("channel_monitor"); 18 | final EventBus eventBus = new EventBus(new MonitoredChannel(1024,cs)); 19 | eventBus.register(new ListenerSub()); 20 | eventBus.start(); 21 | 22 | final AtomicBoolean isEnd = new AtomicBoolean(false); 23 | 24 | new Thread(new Runnable() { 25 | @Override 26 | public void run() { 27 | while (!isEnd.get()) { 28 | eventBus.publish(new EventA("lee",10)); 29 | } 30 | } 31 | }).start(); 32 | 33 | Threads.sleep(1000); 34 | isEnd.set(true); 35 | eventBus.stop(); 36 | System.out.println("===End====" + cs); 37 | 38 | //===End====CHANNEL:channel_monitor{channel.event.put.success=239598, channel.current.size=0, channel.capacity=1024, channel.event.take.attempt=239625, channel.event.take.success=239625, channel.event.put.attempt=541960} 39 | //对于并发较高时,管道太小会导致发布事件大量失败! 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/black/HttpMonitorUsage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.black; 5 | 6 | import com.cubbery.event.sample.event.BothSub; 7 | import com.cubbery.event.sample.event.EventA; 8 | import com.cubbery.event.EventBus; 9 | import com.cubbery.event.utils.HostUtils; 10 | import com.cubbery.event.utils.Threads; 11 | import org.springframework.context.support.ClassPathXmlApplicationContext; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.concurrent.CountDownLatch; 16 | 17 | /** 18 | * 创建人百墨
19 | * 修改人
20 | * 创建时间: 2016/3/28 - 18:06
21 | * 22 | * @version 1.0.0
23 | */ 24 | public class HttpMonitorUsage { 25 | 26 | public static void main(String[] args) { 27 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/mon/spring-http.xml","spring-orac.xml"); 28 | final EventBus eventBus = applicationContext.getBean("eventBus",EventBus.class); 29 | eventBus.register(new BothSub()); 30 | List ips = new ArrayList(1); 31 | ips.add(HostUtils.getLocalHost()); 32 | eventBus.setBlackIps(ips); 33 | 34 | eventBus.start(); 35 | 36 | final CountDownLatch countDownLatch = new CountDownLatch(1); 37 | for (int i = 0; i < 10 ; i++) { 38 | new Thread(new Runnable() { 39 | @Override 40 | public void run() { 41 | try { 42 | countDownLatch.await(); 43 | } catch (InterruptedException e) { 44 | e.printStackTrace(); 45 | } 46 | for (int a = 0; a < 10 ; a++) { 47 | int v = a % 3; 48 | if(a % 3 != 0 ) { 49 | Threads.sleep(1000 * v); 50 | } 51 | eventBus.publish(new EventA("Lee",a));//发送事件消息 52 | } 53 | } 54 | }).start(); 55 | } 56 | countDownLatch.countDown(); 57 | 58 | /*Threads.sleep(1000 * 60 * 5); 59 | eventBus.stop(); 60 | applicationContext.close();*/ 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/channel/MonitoredPersistenceChannel.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.channel; 5 | 6 | import com.cubbery.event.EventStorage; 7 | import com.cubbery.event.channel.ChannelData; 8 | import com.cubbery.event.channel.PersistentChannel; 9 | import com.cubbery.event.handler.EventHandler; 10 | import com.cubbery.event.monitor.ChannelStatistics; 11 | 12 | import java.util.Set; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | /** 16 | * 创建人百墨
17 | * 该类在基本管道的基础上,实现了复合的管道类型。 18 | * @version 1.0.0
19 | */ 20 | public class MonitoredPersistenceChannel extends PersistentChannel { 21 | private final ChannelStatistics channelStatistics; 22 | 23 | public MonitoredPersistenceChannel(int capacity, EventStorage storage, ChannelStatistics channelStatistics) { 24 | super(capacity, storage); 25 | this.channelStatistics = channelStatistics; 26 | this.channelStatistics.setChannelCapacity(capacity); 27 | this.channelStatistics.setChannelSize(capacity); 28 | } 29 | 30 | 31 | @Override 32 | public boolean offer(Object event,Set handlers) { 33 | boolean isOk = false; 34 | try { 35 | this.channelStatistics.incrementEventPutAttemptCount(handlers.size()); 36 | isOk = super.offer(event,handlers); 37 | } finally { 38 | if(isOk) { 39 | this.channelStatistics.addToEventPutSuccessCount(handlers.size()); 40 | } 41 | this.channelStatistics.setChannelSize(getSize()); 42 | } 43 | return isOk; 44 | } 45 | 46 | protected boolean offer(Set data) { 47 | boolean isOk = false; 48 | try { 49 | this.channelStatistics.incrementEventPutAttemptCount(data.size()); 50 | isOk = super.offer(data); 51 | } finally { 52 | if(isOk) { 53 | this.channelStatistics.addToEventPutSuccessCount(data.size()); 54 | } 55 | this.channelStatistics.setChannelSize(getSize()); 56 | } 57 | return isOk; 58 | } 59 | 60 | @Override 61 | public ChannelData poll(long timeout, TimeUnit unit) { 62 | this.channelStatistics.incrementEventTakeAttemptCount(); 63 | ChannelData obj = null; 64 | try { 65 | obj = super.poll(timeout, unit); 66 | return obj; 67 | } finally { 68 | if(obj != null) { 69 | this.channelStatistics.addToEventTakeSuccessCount(1); 70 | } 71 | this.channelStatistics.setChannelSize(getSize()); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/conf/ConfDemo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.conf; 5 | 6 | import com.cubbery.event.sample.event.BothSub; 7 | import com.cubbery.event.sample.event.EventA; 8 | import com.cubbery.event.sample.event.EventAny; 9 | import com.cubbery.event.EventBus; 10 | import com.cubbery.event.sample.event.ListenerSub; 11 | 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | import java.util.Properties; 15 | 16 | public class ConfDemo { 17 | public static void main(String[] args) throws IOException { 18 | Properties properties = new Properties(); 19 | InputStream is = ConfDemo.class.getResourceAsStream("/conf/conf.properties"); 20 | properties.load(is); 21 | final EventBus eventBus = new EventBus(properties); 22 | 23 | //注册消费者 24 | eventBus.register(new ListenerSub()); 25 | eventBus.register(new BothSub()); 26 | //启动事件总线 27 | eventBus.start(); 28 | 29 | //发送事件消息(需要启动后才能发送) 30 | eventBus.publish(new EventAny()); 31 | eventBus.publish(new EventA()); 32 | //停止事件总线 33 | eventBus.stop(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/event/AnnotationSub.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.event; 5 | 6 | import com.cubbery.event.Subscriber; 7 | 8 | import static com.cubbery.event.sample.event.ListenerSub.counter; 9 | 10 | public class AnnotationSub { 11 | 12 | @Subscriber 13 | public void sub(EventA eventA) { 14 | System.out.println(getClass() + "=====sub=====" + counter.incrementAndGet()); 15 | } 16 | 17 | @Subscriber 18 | public void sub0(EventAny eventAny) { 19 | System.out.println(getClass() + "=====sub0=====" + counter.incrementAndGet()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/event/BothSub.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.event; 5 | 6 | import com.cubbery.event.ISubscribe; 7 | import com.cubbery.event.Subscriber; 8 | 9 | import static com.cubbery.event.sample.event.ListenerSub.counter; 10 | 11 | public class BothSub implements ISubscribe { 12 | 13 | @Override 14 | public void handler(EventA event) { 15 | System.out.println(getClass() + "=====handler=====" + counter.incrementAndGet()); 16 | //throw new RuntimeException("Not Suc......"); 17 | } 18 | 19 | 20 | @Subscriber 21 | public void sub(EventA eventA) { 22 | System.out.println(getClass() + "=====sub=====" + counter.incrementAndGet()); 23 | } 24 | 25 | @Subscriber 26 | public void sub0(EventAny eventAny) { 27 | System.out.println(getClass() + "=====sub0=====" + counter.incrementAndGet()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/event/EventA.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.event; 5 | 6 | public class EventA { 7 | private String name; 8 | private int age; 9 | 10 | public EventA() { 11 | } 12 | 13 | public EventA(String name, int age) { 14 | this.name = name; 15 | this.age = age; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | public void setName(String name) { 23 | this.name = name; 24 | } 25 | 26 | public int getAge() { 27 | return age; 28 | } 29 | 30 | public void setAge(int age) { 31 | this.age = age; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/event/EventAny.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.event; 5 | 6 | public class EventAny { 7 | } 8 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/event/ListenerSub.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.event; 5 | 6 | import com.cubbery.event.ISubscribe; 7 | 8 | import java.util.concurrent.atomic.AtomicInteger; 9 | 10 | public class ListenerSub implements ISubscribe { 11 | 12 | @Override 13 | public void handler(EventA event) { 14 | System.out.println(event.getName() + "=====handler=====" + counter.incrementAndGet()); 15 | } 16 | 17 | public static final AtomicInteger counter = new AtomicInteger(0); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/jdbc/MysqlSpringDemo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.jdbc; 5 | 6 | import com.cubbery.event.EventBus; 7 | import com.cubbery.event.EventStorage; 8 | import com.cubbery.event.channel.PersistentChannel; 9 | import com.cubbery.event.retry.RetryService; 10 | import com.cubbery.event.storage.JdbcEventStorage; 11 | import com.cubbery.event.utils.Threads; 12 | import org.springframework.context.support.ClassPathXmlApplicationContext; 13 | 14 | public class MysqlSpringDemo { 15 | private static volatile boolean end = false; 16 | 17 | public static void main(String[] args) throws Exception { 18 | /*ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-orac.xml","spring.xml"); 19 | 20 | //使用持久化的通道,保证数据不丢 21 | final EventBus eventBus = applicationContext.getBean("eventBus",EventBus.class); 22 | 23 | eventBus.register(new BothSub());//注册消费者 24 | eventBus.register(new ListenerSub());//注册消费者 25 | eventBus.start(); 26 | 27 | final CountDownLatch countDownLatch = new CountDownLatch(1); 28 | for (int i = 0; i < 10 && !end; i++) { 29 | new Thread(new Runnable() { 30 | @Override 31 | public void run() { 32 | try { 33 | countDownLatch.await(); 34 | } catch (InterruptedException e) { 35 | e.printStackTrace(); 36 | } 37 | for (int a = 0; a < 100 && !end; a++) { 38 | eventBus.publish(new EventA());//发送事件消息 39 | } 40 | } 41 | }).start(); 42 | } 43 | countDownLatch.countDown(); 44 | Threads.sleep(1000 * 60); 45 | end = true; 46 | eventBus.stop();*/ 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/jdbc/OjdbcSpringDemo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.jdbc; 5 | 6 | import com.cubbery.event.EventBus; 7 | import com.cubbery.event.sample.event.EventA; 8 | import com.cubbery.event.sample.event.ListenerSub; 9 | import com.cubbery.event.utils.Threads; 10 | import org.springframework.context.support.ClassPathXmlApplicationContext; 11 | 12 | import java.util.concurrent.CountDownLatch; 13 | 14 | public class OjdbcSpringDemo { 15 | private static volatile boolean end = false; 16 | public static void main(String[] args) { 17 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-orac.xml","spring.xml"); 18 | final EventBus eventBus = applicationContext.getBean("eventBus",EventBus.class); 19 | eventBus.register(new ListenerSub());//注册消费者 20 | eventBus.start(); 21 | 22 | final CountDownLatch countDownLatch = new CountDownLatch(1); 23 | for (int i = 0; i < 10 && !end; i++) { 24 | new Thread(new Runnable() { 25 | @Override 26 | public void run() { 27 | try { 28 | countDownLatch.await(); 29 | } catch (InterruptedException e) { 30 | e.printStackTrace(); 31 | } 32 | for (int a = 0; a < 100 && !end; a++) { 33 | eventBus.publish(new EventA());//发送事件消息 34 | } 35 | } 36 | }).start(); 37 | } 38 | countDownLatch.countDown(); 39 | Threads.sleep(1000 * 60); 40 | // end = true; 41 | // eventBus.stop(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/mon/HttpMonitorUsage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.mon; 5 | 6 | import com.cubbery.event.sample.event.BothSub; 7 | import com.cubbery.event.EventBus; 8 | import org.springframework.context.support.ClassPathXmlApplicationContext; 9 | 10 | /** 11 | * 创建人百墨
12 | * 修改人
13 | * 创建时间: 2016/3/28 - 18:06
14 | * 15 | * @version 1.0.0
16 | */ 17 | public class HttpMonitorUsage { 18 | 19 | public static void main(String[] args) { 20 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/mon/spring-http.xml","spring-orac.xml"); 21 | final EventBus eventBus = applicationContext.getBean("eventBus",EventBus.class); 22 | eventBus.register(new BothSub()); 23 | 24 | eventBus.start(); 25 | 26 | /* final CountDownLatch countDownLatch = new CountDownLatch(1); 27 | for (int i = 0; i < 10 ; i++) { 28 | new Thread(new Runnable() { 29 | @Override 30 | public void run() { 31 | try { 32 | countDownLatch.await(); 33 | } catch (InterruptedException e) { 34 | e.printStackTrace(); 35 | } 36 | for (int a = 0; a < 10 ; a++) { 37 | int v = a % 3; 38 | if(a % 3 != 0 ) { 39 | Threads.sleep(1000 * v); 40 | } 41 | eventBus.publish(new EventA());//发送事件消息 42 | } 43 | } 44 | }).start(); 45 | } 46 | countDownLatch.countDown();*/ 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/mon/LogMonitorUsage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.mon; 5 | 6 | import com.cubbery.event.sample.event.BothSub; 7 | import com.cubbery.event.EventBus; 8 | import com.cubbery.event.sample.event.EventA; 9 | import com.cubbery.event.utils.Threads; 10 | import org.springframework.context.support.ClassPathXmlApplicationContext; 11 | 12 | import java.util.concurrent.CountDownLatch; 13 | 14 | public class LogMonitorUsage { 15 | public static void main(String[] args) { 16 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/mon/spring-log.xml", "spring-orac.xml"); 17 | final EventBus eventBus = applicationContext.getBean("eventBus", EventBus.class); 18 | eventBus.register(new BothSub()); 19 | 20 | eventBus.start(); 21 | final CountDownLatch countDownLatch = new CountDownLatch(1); 22 | for (int i = 0; i < 10; i++) { 23 | new Thread(new Runnable() { 24 | @Override 25 | public void run() { 26 | try { 27 | countDownLatch.await(); 28 | } catch (InterruptedException e) { 29 | e.printStackTrace(); 30 | } 31 | for (int a = 0; a < 10; a++) { 32 | int v = a % 3; 33 | if (a % 3 != 0) { 34 | Threads.sleep(1000 * v); 35 | } 36 | eventBus.publish(new EventA());//发送事件消息 37 | } 38 | } 39 | }).start(); 40 | } 41 | countDownLatch.countDown(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/mon/ZkMonitorUsage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.mon; 5 | 6 | import com.cubbery.event.sample.event.BothSub; 7 | import com.cubbery.event.sample.event.EventA; 8 | import com.cubbery.event.EventBus; 9 | import com.cubbery.event.utils.Threads; 10 | import org.springframework.context.support.ClassPathXmlApplicationContext; 11 | 12 | import java.util.concurrent.CountDownLatch; 13 | 14 | public class ZkMonitorUsage { 15 | public static void main(String[] args) { 16 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/mon/spring-zk.xml","spring-orac.xml"); 17 | final EventBus eventBus = applicationContext.getBean("eventBus",EventBus.class); 18 | eventBus.register(new BothSub()); 19 | eventBus.start(); 20 | 21 | final CountDownLatch countDownLatch = new CountDownLatch(1); 22 | for (int i = 0; i < 10 ; i++) { 23 | new Thread(new Runnable() { 24 | @Override 25 | public void run() { 26 | try { 27 | countDownLatch.await(); 28 | } catch (InterruptedException e) { 29 | e.printStackTrace(); 30 | } 31 | for (int a = 0; a < 100 ; a++) { 32 | int v = a % 3; 33 | if(a % 3 != 0 ) { 34 | Threads.sleep(1000 * v); 35 | } 36 | eventBus.publish(new EventA());//发送事件消息 37 | } 38 | } 39 | }).start(); 40 | } 41 | countDownLatch.countDown(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/monitor/HttpMonitorUsage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.monitor; 5 | 6 | import com.cubbery.event.EventBus; 7 | import com.cubbery.event.sample.event.BothSub; 8 | import com.cubbery.event.sample.event.EventA; 9 | import com.cubbery.event.utils.Threads; 10 | import org.springframework.context.support.ClassPathXmlApplicationContext; 11 | 12 | import java.util.concurrent.CountDownLatch; 13 | 14 | /** 15 | * 创建人百墨
16 | * 修改人
17 | * 创建时间: 2016/3/28 - 18:06
18 | * 19 | * @version 1.0.0
20 | */ 21 | public class HttpMonitorUsage { 22 | 23 | public static void main(String[] args) { 24 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/mon/spring-http.xml","spring-orac.xml"); 25 | final EventBus eventBus = applicationContext.getBean("eventBus",EventBus.class); 26 | eventBus.register(new BothSub()); 27 | 28 | eventBus.start(); 29 | 30 | final CountDownLatch countDownLatch = new CountDownLatch(1); 31 | for (int i = 0; i < 10 ; i++) { 32 | new Thread(new Runnable() { 33 | @Override 34 | public void run() { 35 | try { 36 | countDownLatch.await(); 37 | } catch (InterruptedException e) { 38 | e.printStackTrace(); 39 | } 40 | for (int a = 0; a < 10 ; a++) { 41 | int v = a % 3; 42 | if(a % 3 != 0 ) { 43 | Threads.sleep(1000 * v); 44 | } 45 | eventBus.publish(new EventA("Lee",a));//发送事件消息 46 | } 47 | } 48 | }).start(); 49 | } 50 | countDownLatch.countDown(); 51 | 52 | /*Threads.sleep(1000 * 60 * 5); 53 | eventBus.stop(); 54 | applicationContext.close();*/ 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/monitor/ZkMonitorUsage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.monitor; 5 | 6 | import com.cubbery.event.sample.event.BothSub; 7 | import com.cubbery.event.sample.event.EventA; 8 | import com.cubbery.event.EventBus; 9 | import com.cubbery.event.utils.Threads; 10 | import org.springframework.context.support.ClassPathXmlApplicationContext; 11 | 12 | import java.util.concurrent.CountDownLatch; 13 | 14 | public class ZkMonitorUsage { 15 | public static void main(String[] args) { 16 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/mon/spring-zk.xml"); 17 | final EventBus eventBus = applicationContext.getBean("eventBus",EventBus.class); 18 | eventBus.register(new BothSub()); 19 | eventBus.start(); 20 | 21 | final CountDownLatch countDownLatch = new CountDownLatch(1); 22 | for (int i = 0; i < 10 ; i++) { 23 | new Thread(new Runnable() { 24 | @Override 25 | public void run() { 26 | try { 27 | countDownLatch.await(); 28 | } catch (InterruptedException e) { 29 | e.printStackTrace(); 30 | } 31 | for (int a = 0; a < 100 ; a++) { 32 | int v = a % 3; 33 | if(a % 3 != 0 ) { 34 | Threads.sleep(1000 * v); 35 | } 36 | eventBus.publish(new EventA());//发送事件消息 37 | } 38 | } 39 | }).start(); 40 | } 41 | countDownLatch.countDown(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /async-event-example/src/main/java/com/cubbery/event/sample/spring/MutipDemo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.sample.spring; 5 | 6 | import com.cubbery.event.sample.event.AnnotationSub; 7 | import com.cubbery.event.sample.event.BothSub; 8 | import com.cubbery.event.EventBus; 9 | import com.cubbery.event.channel.PersistentChannel; 10 | import com.cubbery.event.finder.BothHandlerFinder; 11 | import com.cubbery.event.retry.RetryService; 12 | import com.cubbery.event.sample.event.EventA; 13 | import com.cubbery.event.utils.Threads; 14 | import org.springframework.context.support.ClassPathXmlApplicationContext; 15 | 16 | import java.util.concurrent.CountDownLatch; 17 | 18 | public class MutipDemo { 19 | private static volatile boolean end = false; 20 | 21 | public static void main(String[] args) throws Exception { 22 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-orac.xml"); 23 | 24 | //使用持久化的通道,保证数据不丢 25 | final EventBus eventBus = new EventBus( 26 | //使用spring配置的持久化队列 27 | new PersistentChannel(1024, (com.cubbery.event.EventStorage) applicationContext.getBean("storage")), 28 | new BothHandlerFinder()//指定只能使用接口方式定义消费者 29 | ); 30 | //启用重试服务 31 | RetryService retryService = new RetryService(eventBus); 32 | eventBus.setRetryService(retryService); 33 | 34 | //注册消费者 35 | eventBus.register(new AnnotationSub());//注册消费者 36 | eventBus.register(new BothSub());//注册消费者 37 | //启动事件总线 38 | eventBus.start(); 39 | 40 | final CountDownLatch countDownLatch = new CountDownLatch(1); 41 | for (int i = 0; i < 10 && !end; i++) { 42 | new Thread(new Runnable() { 43 | @Override 44 | public void run() { 45 | try { 46 | countDownLatch.await(); 47 | } catch (InterruptedException e) { 48 | e.printStackTrace(); 49 | } 50 | for (int a = 0; a < 100 && !end; a++) { 51 | try { 52 | eventBus.publish(new EventA());//发送事件消息 53 | }catch (Exception e) { 54 | 55 | } 56 | } 57 | } 58 | }).start(); 59 | } 60 | countDownLatch.countDown(); 61 | Threads.sleep(10 * 1000); 62 | end = true; 63 | //停止事件总线 64 | eventBus.stop(); 65 | } 66 | } -------------------------------------------------------------------------------- /async-event-example/src/main/resources/conf/conf.properties: -------------------------------------------------------------------------------- 1 | #通道默认超时时间 2 | channel.offer.expire=1 3 | #通道类型 4 | #[注意:该配置只对于提供了默认构造参数或者有一个通道大小的构造函数的类型适用。对于复杂类型的通道该配置不生效] 5 | channel.type=com.jdpay.event.channel.MemoryChannel 6 | #通道大小 7 | channel.size=1024 8 | 9 | #总线消费者数量 10 | bus.consume.count=5 11 | #总线分发者数量 12 | bus.dispatch.count=2 13 | #总线时间单位 14 | bus.time.unit=MILLISECONDS 15 | 16 | #重试服务master优先权,单位为秒(s) 17 | retry.master.priority=10 18 | #重试并发处理数 19 | retry.parallel.count=2 20 | #新master上线等待次数 21 | retry.master.wait=2 22 | #租约周期 23 | retry.lease.period=60 -------------------------------------------------------------------------------- /async-event-example/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger = INFO, out 2 | log4j.logger.org.hibernate.SQL = DEBUG 3 | log4j.appender.out = org.apache.log4j.ConsoleAppender 4 | log4j.appender.out.layout = org.apache.log4j.PatternLayout 5 | log4j.appender.out.layout.ConversionPattern = %d %p [%c.%M] - %m%n 6 | log4j.appender.log = org.apache.log4j.DailyRollingFileAppender 7 | log4j.appender.log.File = certifycenter.log 8 | log4j.appender.log.DatePattern = .yyyy-MM-dd 9 | log4j.appender.log.layout = org.apache.log4j.PatternLayout 10 | log4j.appender.log.layout.ConversionPattern = %d %p [%c.%M] - %m%n -------------------------------------------------------------------------------- /async-event-example/src/main/resources/mon/spring-http.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /async-event-example/src/main/resources/mon/spring-log.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /async-event-example/src/main/resources/mon/spring-zk.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /async-event-example/src/main/resources/ojdbc/db.properties: -------------------------------------------------------------------------------- 1 | jdbc.drive=oracle.jdbc.OracleDriver 2 | jdbc.url=jdbc:oracle:thin:@10.9.45.242:1521:test 3 | jdbc.username=test 4 | jdbc.password=test 5 | jdbc.min_connections=5 6 | jdbc.max_connections=20 7 | jdbc.checkout_timeout=5000 8 | jdbc.idle_timeout=60 -------------------------------------------------------------------------------- /async-event-example/src/main/resources/spring-orac.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /async-event-example/src/main/resources/spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/AbstractStatisticalStressStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)AbstractStatisticalStressStrategy.java Created on 2013-7-9 3 | * 4 | * Copyright 2003-2012 UMPay, Inc. All rights reserved. 5 | * Use is subject to license terms. 6 | */ 7 | package freamwork.core; 8 | 9 | import freamwork.core.stat.DefaultStatisticImpl; 10 | import freamwork.core.stat.Statistical; 11 | 12 | public abstract class AbstractStatisticalStressStrategy implements StressStrategy { 13 | protected Statistical stat = new DefaultStatisticImpl(this);// 默认 14 | 15 | public Statistical getStatistical() { 16 | return stat; 17 | } 18 | 19 | public void setStatistical(Statistical stat) { 20 | this.stat = stat; 21 | } 22 | 23 | protected abstract int getTaskPeriod(); 24 | 25 | protected void doTask(final StressTask task) { 26 | try { 27 | long start = System.currentTimeMillis(); 28 | boolean result = task.doTask(); 29 | long end = System.currentTimeMillis(); 30 | stat.addTimeUsed((int) (end - start)); 31 | stat.addCount(result); 32 | if (getTaskPeriod() > 0) { 33 | Thread.sleep(getTaskPeriod()); 34 | } 35 | } catch (Throwable e) { 36 | e.printStackTrace(); 37 | stat.addFail(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/BaseStressConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)BaseStressConfig.java Created on Apr 25, 2012 3 | * 4 | * Copyright 2003-2012 UMPay, Inc. All rights reserved. 5 | * Use is subject to license terms. 6 | */ 7 | package freamwork.core; 8 | 9 | import java.util.Properties; 10 | 11 | public class BaseStressConfig { 12 | protected Properties config; 13 | 14 | public BaseStressConfig(Properties config) { 15 | this.config = config; 16 | } 17 | 18 | public int getThreadNum() { 19 | return Integer.parseInt(config.getProperty(StressStrategy.KEY_THREAD_NUM, "10")); 20 | } 21 | 22 | public int getTaskPeriod() { 23 | return Integer.parseInt(config.getProperty(StressStrategy.KEY_TASK_PERIOD, "0")); 24 | } 25 | 26 | public int getStatPeriod() { 27 | return Integer.parseInt(config.getProperty(StressStrategy.KEY_STAT_PERIOD, "1000")); 28 | } 29 | 30 | public StressTask getTaskClass() { 31 | String taskClass = config.getProperty(StressStrategy.KEY_TASK_CLASS, null); 32 | if (taskClass == null) 33 | throw new IllegalArgumentException("未配置任务实现类!"); 34 | try { 35 | return (StressTask) Class.forName(taskClass.trim()).newInstance(); 36 | } catch (Exception e) { 37 | throw new IllegalArgumentException("加载任务实现类错误:" + taskClass, e); 38 | } 39 | } 40 | 41 | public String getOutputFileName() { 42 | return config.getProperty("RESULT_PATH", "").trim(); 43 | } 44 | 45 | public final String getResultPath() { 46 | return config.getProperty(StressStrategy.KEY_RESULT_PATH, null); 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return String.format("配置信息[线程数:%d, 任务间隔:%dms, 任务实现类:%s]%n", getThreadNum(), getTaskPeriod(), getTaskClass().getClass().getName()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/ConfigurableStressStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)ConfigurableStressStrategy.java Created on 2013-7-9 3 | * 4 | * Copyright 2003-2012 UMPay, Inc. All rights reserved. 5 | * Use is subject to license terms. 6 | */ 7 | package freamwork.core; 8 | 9 | import java.util.Properties; 10 | 11 | public abstract class ConfigurableStressStrategy extends AbstractStatisticalStressStrategy { 12 | protected Properties config; 13 | 14 | public ConfigurableStressStrategy(Properties config) { 15 | this.config = config; 16 | } 17 | 18 | public abstract BaseStressConfig getStressConfig(); 19 | 20 | @Override 21 | protected int getTaskPeriod() { 22 | return getStressConfig().getTaskPeriod(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/Context.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, cubbery.com. All rights reserved. 3 | */ 4 | package freamwork.core; 5 | 6 | import org.springframework.beans.BeansException; 7 | import org.springframework.context.ApplicationContext; 8 | import org.springframework.context.ApplicationContextAware; 9 | 10 | public class Context implements ApplicationContextAware { 11 | public static ApplicationContext applicationContext; 12 | 13 | public static T getBean(Class clazz) { 14 | return applicationContext.getBean(clazz); 15 | } 16 | 17 | @Override 18 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 19 | this.applicationContext = applicationContext; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/CountLimitedStressStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)CountLimitedStressStrategy.java Created on 2013-7-8 3 | * 4 | * Copyright 2003-2012 UMPay, Inc. All rights reserved. 5 | * Use is subject to license terms. 6 | */ 7 | package freamwork.core; 8 | 9 | 10 | import freamwork.core.stat.NumberUtil; 11 | 12 | import java.util.Properties; 13 | 14 | public class CountLimitedStressStrategy extends ConfigurableStressStrategy { 15 | public CountLimitedStressStrategy(Properties config) { 16 | super(config); 17 | } 18 | 19 | private CountLimitedStressConfig clsConfig; 20 | public void runStress() { 21 | clsConfig = getStressConfig(); 22 | int runCounts = clsConfig.getTasksPerThread(); 23 | final StressTask task = clsConfig.getTaskClass(); 24 | for (int i = 0; i < runCounts; i++) { 25 | doTask(task); 26 | } 27 | } 28 | 29 | @Override 30 | public CountLimitedStressConfig getStressConfig() { 31 | return new CountLimitedStressConfig(this.config); 32 | } 33 | 34 | public double percentageOfCompletion() { 35 | long processed = getStatistical().getProcessed(); 36 | int all = clsConfig.getThreadNum() * clsConfig.getTasksPerThread(); 37 | double percent = processed * 100 / 1.0 / all; 38 | return NumberUtil.roundTo(percent, 2); 39 | } 40 | 41 | static class CountLimitedStressConfig extends BaseStressConfig{ 42 | public CountLimitedStressConfig(Properties config) { 43 | super(config); 44 | } 45 | 46 | // 첼몸窟넋돨훨蛟鑒 47 | private static final String TASK_PER_THREAD_KEY = "TASK_PER_THREAD"; 48 | 49 | public int getTasksPerThread() { 50 | return Integer.parseInt(config.getProperty(TASK_PER_THREAD_KEY, "1000")); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/StressStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)StressStrategy.java Created on 2013-7-8 3 | * 4 | * Copyright 2003-2012 UMPay, Inc. All rights reserved. 5 | * Use is subject to license terms. 6 | */ 7 | package freamwork.core; 8 | 9 | public interface StressStrategy { 10 | // 线程数 11 | String KEY_THREAD_NUM = "THREAD_NUM"; 12 | // 交易间隔 13 | String KEY_TASK_PERIOD = "TASK_PERIOD"; 14 | // 统计时间间隔 15 | String KEY_STAT_PERIOD = "STAT_PERIOD"; 16 | // 任务类 17 | String KEY_TASK_CLASS = "TASK_CLASS"; 18 | // 日志路径 19 | String KEY_RESULT_PATH = "RESULT_PATH"; 20 | // 压力策略实现类 21 | String KEY_STRATEGY_CLASS = "STRATEGY_CLASS"; 22 | 23 | void runStress(); 24 | double percentageOfCompletion(); 25 | } 26 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/StressStrategySupport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)StressStrategySupport.java Created on 2013-7-9 3 | * 4 | * Copyright 2003-2012 UMPay, Inc. All rights reserved. 5 | * Use is subject to license terms. 6 | */ 7 | package freamwork.core; 8 | 9 | import java.io.IOException; 10 | import java.lang.reflect.Constructor; 11 | import java.util.Properties; 12 | 13 | import static freamwork.core.StressStrategy.KEY_STRATEGY_CLASS; 14 | 15 | public class StressStrategySupport { 16 | public static StressStrategy getStressStrategy(String configFile) { 17 | if (configFile == null || configFile.equals("")) { 18 | throw new IllegalArgumentException("压力配置文件不能为空!"); 19 | } 20 | final Properties props = new Properties(); 21 | try { 22 | props.load(ClassLoader.getSystemResourceAsStream(configFile)); 23 | } catch (IOException e) { 24 | throw new IllegalStateException("找不到配置文件: " + configFile, e); 25 | } 26 | String strategyClazz = props.getProperty(KEY_STRATEGY_CLASS); 27 | if (strategyClazz == null || strategyClazz.trim().equals("")) { 28 | throw new IllegalStateException("没有配置压力策略类,KEY=" + KEY_STRATEGY_CLASS); 29 | } 30 | try { 31 | Constructor con = Class.forName(strategyClazz).getConstructor(Properties.class); 32 | return (StressStrategy) con.newInstance(props); 33 | } catch (Exception e) { 34 | throw new IllegalStateException("无法实例化压力策略类:" + strategyClazz); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/StressTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)StressTask.java Created on Apr 25, 2012 3 | * 4 | * Copyright 2003-2012 UMPay, Inc. All rights reserved. 5 | * Use is subject to license terms. 6 | */ 7 | package freamwork.core; 8 | 9 | public interface StressTask { 10 | 11 | /** 12 | * 压力测试需要执行的任务 13 | * 14 | * @return 任务成功执行返回true,否则返回false 15 | */ 16 | boolean doTask() throws Exception; 17 | } 18 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/TimeLimitedStressStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)TimeLimitedStressStrategy.java Created on 2013-7-8 3 | * 4 | * Copyright 2003-2012 UMPay, Inc. All rights reserved. 5 | * Use is subject to license terms. 6 | */ 7 | package freamwork.core; 8 | 9 | 10 | import freamwork.core.stat.NumberUtil; 11 | 12 | import java.util.Properties; 13 | 14 | public class TimeLimitedStressStrategy extends ConfigurableStressStrategy { 15 | private volatile long startTime; 16 | public TimeLimitedStressStrategy(Properties config) { 17 | super(config); 18 | } 19 | 20 | private TimeLimitedStressConfig tlsConfig; 21 | public void runStress() { 22 | tlsConfig = getStressConfig(); 23 | int runMSec = tlsConfig.getTimeTestLimit() * 1000; 24 | final StressTask task = tlsConfig.getTaskClass(); 25 | startTime = System.currentTimeMillis(); 26 | while(System.currentTimeMillis() < startTime + runMSec){ 27 | doTask(task); 28 | } 29 | 30 | } 31 | 32 | @Override 33 | public TimeLimitedStressConfig getStressConfig() { 34 | return new TimeLimitedStressConfig(config); 35 | } 36 | 37 | public double percentageOfCompletion() { 38 | long now = System.currentTimeMillis(); 39 | double percent = (now - startTime) * 100 / 1000.0 / tlsConfig.getTimeTestLimit(); 40 | return NumberUtil.roundTo(percent, 2); 41 | } 42 | 43 | static class TimeLimitedStressConfig extends BaseStressConfig { 44 | public TimeLimitedStressConfig(Properties config) { 45 | super(config); 46 | } 47 | 48 | // 每个线程的时间(秒) 49 | public static final String TIME_TEST_LIMIT = "TIME_TEST_LIMIT"; 50 | 51 | public int getTimeTestLimit() { 52 | return Integer.parseInt(config.getProperty(TIME_TEST_LIMIT, "10")); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/Workbench.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)Workbench.java Created on 2012-11-15 3 | * 4 | * Copyright 2003-2012 UMPay, Inc. All rights reserved. 5 | * Use is subject to license terms. 6 | */ 7 | package freamwork.core; 8 | 9 | import java.io.FileWriter; 10 | import java.io.IOException; 11 | import java.util.concurrent.*; 12 | import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy; 13 | 14 | public class Workbench { 15 | 16 | private ExecutorService servicePool; 17 | private ScheduledExecutorService scheduledThreadPool; 18 | private CountDownLatch finish; 19 | 20 | private BaseStressConfig config; 21 | 22 | private FileWriter resultWriter;; 23 | 24 | private volatile boolean initialized; 25 | 26 | private ConfigurableStressStrategy stressStrategy; 27 | 28 | public Workbench(String configFile) throws IOException { 29 | initWorkbench(configFile); 30 | } 31 | 32 | /** 33 | * @throws java.io.IOException 34 | */ 35 | private void initWorkbench(String configFile) throws IOException { 36 | if (initialized) { 37 | return; 38 | } 39 | this.stressStrategy = getStressStrategy(configFile); 40 | this.config = stressStrategy.getStressConfig(); 41 | if (this.config == null) { 42 | throw new NullPointerException("未配置压力测试参数!"); 43 | } 44 | servicePool = new ThreadPoolExecutor(config.getThreadNum(), config.getThreadNum(), 60, TimeUnit.SECONDS, new LinkedBlockingQueue(2000), new CallerRunsPolicy()); 45 | finish = new CountDownLatch(config.getThreadNum()); 46 | 47 | scheduledThreadPool = Executors.newScheduledThreadPool(1); 48 | scheduledThreadPool.scheduleAtFixedRate(new Runnable() { 49 | public void run() { 50 | statistic(); 51 | } 52 | }, config.getStatPeriod(), config.getStatPeriod(), TimeUnit.MILLISECONDS); 53 | 54 | if (!"".equals(config.getOutputFileName())) { 55 | resultWriter = new FileWriter(config.getOutputFileName()); 56 | } 57 | this.initialized = true;// 初始化完成 58 | } 59 | 60 | public ConfigurableStressStrategy getStressStrategy(String configFile) { 61 | return (ConfigurableStressStrategy) StressStrategySupport.getStressStrategy(configFile); 62 | } 63 | 64 | public void startPerf() throws Exception { 65 | if (!initialized) { 66 | throw new IllegalStateException("未初始化!"); 67 | } 68 | 69 | final int threadNum = config.getThreadNum(); 70 | for (int i = 0; i < threadNum; i++) { 71 | servicePool.execute(new Runnable() { 72 | public void run() { 73 | stressStrategy.runStress(); 74 | finish.countDown(); 75 | } 76 | }); 77 | } 78 | finish.await(); 79 | scheduledThreadPool.shutdownNow(); 80 | statistic(); 81 | servicePool.shutdown(); 82 | } 83 | 84 | void statistic() { 85 | String info = stressStrategy.getStatistical().getStatInfo(); 86 | if (resultWriter != null) { 87 | try { 88 | resultWriter.write(info); 89 | resultWriter.flush(); 90 | } catch (IOException e) { 91 | } 92 | } else { 93 | System.out.print(info); 94 | } 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/read.md: -------------------------------------------------------------------------------- 1 | # 这个是架构组使用的stress框架, 2 | 3 | ### 使用:见配置文件!运行StressMain的main函数 -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/stat/DefaultStatisticImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)DefaultStatisticImpl.java Created on 2013-7-9 3 | * 4 | * Copyright 2003-2012 UMPay, Inc. All rights reserved. 5 | * Use is subject to license terms. 6 | */ 7 | package freamwork.core.stat; 8 | 9 | import freamwork.core.StressStrategy; 10 | 11 | import java.util.concurrent.atomic.AtomicLong; 12 | 13 | public class DefaultStatisticImpl implements Statistical { 14 | private long startTime; 15 | private StressStrategy stressStrategy; 16 | private AtomicLong fail = new AtomicLong(0); 17 | private AtomicLong success = new AtomicLong(0); 18 | private AtomicLong timeUsed = new AtomicLong(0); 19 | 20 | public DefaultStatisticImpl(StressStrategy stressStrategy) { 21 | this.startTime = System.currentTimeMillis(); 22 | this.stressStrategy = stressStrategy; 23 | } 24 | 25 | public long addCount(boolean success) { 26 | return success ? addSucess() : addFail(); 27 | } 28 | 29 | public long getFail() { 30 | return fail.get(); 31 | } 32 | 33 | public long addSucess() { 34 | return success.incrementAndGet(); 35 | } 36 | 37 | public long addFail() { 38 | return fail.incrementAndGet(); 39 | } 40 | 41 | public long addTimeUsed(int msec) { 42 | return timeUsed.addAndGet(msec); 43 | } 44 | 45 | public long getTimeUsed() { 46 | return timeUsed.get(); 47 | } 48 | 49 | public long getProcessed() { 50 | return success.get() + fail.get(); 51 | } 52 | 53 | public double tps() { 54 | long timeSpent = System.currentTimeMillis() - startTime; 55 | return NumberUtil.roundTo(getProcessed() * 1000 * 1.0 / timeSpent, 2); 56 | } 57 | 58 | public double trt() { 59 | return NumberUtil.roundTo(getTimeUsed() / 1.0 / getProcessed(), 2); 60 | } 61 | 62 | public String getStatInfo() { 63 | long processed = getProcessed(); 64 | long fail = getFail(); 65 | double trt = trt(); 66 | double failPercent = NumberUtil.roundTo(fail / 1.0 / processed * 100, 2); 67 | double percentageOfCompletion = stressStrategy.percentageOfCompletion(); 68 | double tps = tps(); 69 | String info = String.format("Progress[%s%%(%d Processed)],TRT[%s ms],TPS[%s],Fail[%d],FP[%s%%]\r\n", percentageOfCompletion, processed, trt, tps, fail, failPercent); 70 | return info; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/stat/NumberUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.jd.com. All rights reserved. 3 | */ 4 | package freamwork.core.stat; 5 | 6 | /** 7 | * 类描述
8 | * 创建人百墨
9 | * 创建时间: 2016/4/15 - 10:42
10 | * 11 | * @version 1.0.0
12 | */ 13 | public class NumberUtil { 14 | public static double roundTo(double val, int places) { 15 | double factor = Math.pow(10, places); 16 | return ((int) ((val * factor) + 0.5)) / factor; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/core/stat/Statistical.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)Statistical.java Created on 2013-7-9 3 | * 4 | * Copyright 2003-2012 UMPay, Inc. All rights reserved. 5 | * Use is subject to license terms. 6 | */ 7 | package freamwork.core.stat; 8 | 9 | public interface Statistical { 10 | long addCount(boolean success); 11 | 12 | long getFail(); 13 | 14 | long addSucess(); 15 | 16 | long addFail(); 17 | 18 | long addTimeUsed(int msec); 19 | 20 | long getProcessed(); 21 | 22 | double tps(); 23 | 24 | double trt(); 25 | 26 | String getStatInfo(); 27 | } -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/simple/common/UniqNumUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.jd.com. All rights reserved. 3 | */ 4 | package freamwork.simple.common; 5 | 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | /** 9 | * 类描述
10 | * 创建人百墨
11 | * 创建时间: 2016/4/15 - 10:00
12 | * 13 | * @version 1.0.0
14 | */ 15 | public class UniqNumUtil { 16 | private static AtomicInteger num = new AtomicInteger(0); 17 | 18 | public static String getUniqNum(int length) { 19 | String cur = String.valueOf(System.nanoTime()); 20 | return cur.substring(cur.length() - length) + num.getAndIncrement(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/simple/core/ConcurrentTask.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, cubbery.com. All rights reserved. 3 | */ 4 | package freamwork.simple.core; 5 | 6 | public interface ConcurrentTask { 7 | void run(); 8 | } 9 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/simple/core/ConcurrentTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, cubbery.com. All rights reserved. 3 | */ 4 | package freamwork.simple.core; 5 | 6 | import com.cubbery.event.utils.Formatter; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Collections; 10 | import java.util.List; 11 | import java.util.concurrent.CopyOnWriteArrayList; 12 | import java.util.concurrent.CountDownLatch; 13 | import java.util.concurrent.atomic.AtomicInteger; 14 | 15 | public class ConcurrentTest { 16 | private CountDownLatch startSignal = new CountDownLatch(1);//开始阀门 17 | private CountDownLatch doneSignal = null;//结束阀门 18 | 19 | //响应时间 20 | private CopyOnWriteArrayList list = new CopyOnWriteArrayList(); 21 | 22 | private AtomicInteger err = new AtomicInteger();//原子递增 23 | private ConcurrentTask task = null; 24 | private int numPerThread = 1;//每个线程执行次数 25 | 26 | public ConcurrentTest(int concurrent,int numPerThread,ConcurrentTask task){ 27 | this.task = task; 28 | this.numPerThread = numPerThread; 29 | 30 | if(task == null){ 31 | System.out.println("task can not null"); 32 | System.exit(1); 33 | } 34 | 35 | doneSignal = new CountDownLatch(concurrent);//并发数(线程数) 36 | } 37 | 38 | /** 39 | * @throws ClassNotFoundException 40 | */ 41 | public void start(){ 42 | //创建线程,并将所有线程等待在阀门处 43 | runThread(); 44 | //打开阀门 45 | startSignal.countDown();//递减锁存器的计数,如果计数到达零,则释放所有等待的线程 46 | try { 47 | doneSignal.await();//等待所有线程都执行完毕 48 | } catch (InterruptedException e) { 49 | e.printStackTrace(); 50 | } 51 | //计算执行时间 52 | getExeTime(); 53 | } 54 | 55 | /** 56 | * 初始化所有线程,并在阀门处等待 57 | */ 58 | private void runThread() { 59 | long len = doneSignal.getCount();//线程数 60 | //每个任务的线程数 61 | for (int i = 0; i < len; i++) { 62 | new Thread(new MyThreadRun(numPerThread,task) { 63 | @Override 64 | void before() { 65 | try { 66 | startSignal.await();//使当前线程在锁存器倒计数至零之前一直等待 67 | } catch (InterruptedException e) { 68 | err.getAndIncrement();//相当于err++ 69 | } 70 | } 71 | 72 | @Override 73 | void after() { 74 | long end = (System.nanoTime() - startTime); 75 | list.add(end); 76 | } 77 | 78 | @Override 79 | long getStartTime() { 80 | return System.nanoTime(); 81 | } 82 | 83 | @Override 84 | void finish() { 85 | doneSignal.countDown(); 86 | } 87 | },"ConcurrentTest_" + i).start(); 88 | } 89 | 90 | } 91 | 92 | /** 93 | * 计算平均响应时间 94 | */ 95 | private void getExeTime() { 96 | int size = list.size(); 97 | List _list = new ArrayList(size); 98 | _list.addAll(list); 99 | Collections.sort(_list); 100 | long min = _list.get(0); 101 | long max = _list.get(size-1); 102 | long sum = 0L; 103 | for (Long t : _list) { 104 | sum += t; 105 | } 106 | long avg = sum/size; 107 | 108 | System.out.println("===: ======="); 109 | System.out.println("sum: " + Formatter.formatNS(sum)); 110 | System.out.println("min: " + Formatter.formatNS(min)); 111 | System.out.println("max: " + Formatter.formatNS(max)); 112 | System.out.println("avg: " + Formatter.formatNS(avg)); 113 | System.out.println("err: " + err.get()); 114 | System.out.println("===: ======="); 115 | } 116 | 117 | abstract class MyThreadRun implements Runnable{ 118 | int replay; 119 | ConcurrentTask task; 120 | public Long startTime; 121 | 122 | MyThreadRun(int replay,ConcurrentTask task){ 123 | this.replay = replay; 124 | this.task = task; 125 | } 126 | 127 | @Override 128 | public void run() { 129 | do{ 130 | try{ 131 | before(); 132 | startTime = getStartTime(); 133 | task.run(); 134 | after(); 135 | }catch (Throwable t){ 136 | t.printStackTrace(); 137 | } 138 | }while (--replay > 0); 139 | 140 | finish(); 141 | } 142 | 143 | abstract void before(); 144 | abstract void after(); 145 | abstract long getStartTime(); 146 | abstract void finish(); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/simple/task/Task.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, cubbery.com. All rights reserved. 3 | */ 4 | package freamwork.simple.task; 5 | 6 | public abstract class Task { 7 | protected T target; 8 | public Task(T t) { 9 | this.target = t; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/test/EncryptRunner.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.jd.com. All rights reserved. 3 | */ 4 | package freamwork.test; 5 | 6 | import freamwork.simple.core.ConcurrentTask; 7 | import freamwork.simple.core.ConcurrentTest; 8 | import freamwork.simple.task.Task; 9 | 10 | import static com.cubbery.event.utils.security.DesCrypter.encrypt; 11 | import static freamwork.simple.common.UniqNumUtil.getUniqNum; 12 | 13 | /** 14 | * 类描述
15 | * 创建人百墨
16 | * 创建时间: 2016/4/18 - 15:25
17 | * 18 | * @version 1.0.0
19 | */ 20 | public class EncryptRunner { 21 | public static void main(String[] args) { 22 | /* 23 | ===: ======= 24 | sum: 4,274,342,478 25 | min: 23,399 26 | max: 420,821,638 27 | avg: 4,274,342 28 | err: 0 29 | ===: ======= 30 | */ 31 | new ConcurrentTest(10,100,new EncryptTest(null)).start();//10个并发,100次重复 32 | /* 33 | ===: ======= 34 | sum: 4,270,944,970 35 | min: 10,263 36 | max: 399,123,212 37 | avg: 427,094 38 | err: 0 39 | ===: ======= 40 | */ 41 | new ConcurrentTest(10,1000,new EncryptTest(null)).start();//10个并发,1000次重复 42 | //结论:单线程数一定的时候,随着重复次数的增加,平均耗时显著提升 43 | } 44 | } 45 | 46 | class EncryptTest extends Task implements ConcurrentTask { 47 | 48 | public EncryptTest(Object o) { 49 | super(o); 50 | } 51 | 52 | @Override 53 | public void run() { 54 | encrypt(getUniqNum(10)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/test/Event.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.jd.com. All rights reserved. 3 | */ 4 | package freamwork.test; 5 | 6 | /** 7 | * 类描述
8 | * 创建人百墨
9 | * 创建时间: 2016/4/15 - 10:01
10 | * 11 | * @version 1.0.0
12 | */ 13 | public class Event { 14 | String e1; 15 | String e8; 16 | String e7; 17 | String e6; 18 | String e5; 19 | String e4; 20 | String e3; 21 | String e2; 22 | SubEvent subEvent; 23 | 24 | public String getE1() { 25 | return e1; 26 | } 27 | 28 | public void setE1(String e1) { 29 | this.e1 = e1; 30 | } 31 | 32 | public String getE8() { 33 | return e8; 34 | } 35 | 36 | public void setE8(String e8) { 37 | this.e8 = e8; 38 | } 39 | 40 | public String getE7() { 41 | return e7; 42 | } 43 | 44 | public void setE7(String e7) { 45 | this.e7 = e7; 46 | } 47 | 48 | public String getE6() { 49 | return e6; 50 | } 51 | 52 | public void setE6(String e6) { 53 | this.e6 = e6; 54 | } 55 | 56 | public String getE5() { 57 | return e5; 58 | } 59 | 60 | public void setE5(String e5) { 61 | this.e5 = e5; 62 | } 63 | 64 | public String getE4() { 65 | return e4; 66 | } 67 | 68 | public void setE4(String e4) { 69 | this.e4 = e4; 70 | } 71 | 72 | public String getE3() { 73 | return e3; 74 | } 75 | 76 | public void setE3(String e3) { 77 | this.e3 = e3; 78 | } 79 | 80 | public String getE2() { 81 | return e2; 82 | } 83 | 84 | public void setE2(String e2) { 85 | this.e2 = e2; 86 | } 87 | 88 | public SubEvent getSubEvent() { 89 | return subEvent; 90 | } 91 | 92 | public void setSubEvent(SubEvent subEvent) { 93 | this.subEvent = subEvent; 94 | } 95 | } 96 | 97 | class SubEvent { 98 | String f1; 99 | String f9; 100 | String f8; 101 | String f7; 102 | String f6; 103 | String f5; 104 | String f4; 105 | String f3; 106 | String f2; 107 | 108 | public String getF1() { 109 | return f1; 110 | } 111 | 112 | public void setF1(String f1) { 113 | this.f1 = f1; 114 | } 115 | 116 | public String getF9() { 117 | return f9; 118 | } 119 | 120 | public void setF9(String f9) { 121 | this.f9 = f9; 122 | } 123 | 124 | public String getF8() { 125 | return f8; 126 | } 127 | 128 | public void setF8(String f8) { 129 | this.f8 = f8; 130 | } 131 | 132 | public String getF7() { 133 | return f7; 134 | } 135 | 136 | public void setF7(String f7) { 137 | this.f7 = f7; 138 | } 139 | 140 | public String getF6() { 141 | return f6; 142 | } 143 | 144 | public void setF6(String f6) { 145 | this.f6 = f6; 146 | } 147 | 148 | public String getF5() { 149 | return f5; 150 | } 151 | 152 | public void setF5(String f5) { 153 | this.f5 = f5; 154 | } 155 | 156 | public String getF4() { 157 | return f4; 158 | } 159 | 160 | public void setF4(String f4) { 161 | this.f4 = f4; 162 | } 163 | 164 | public String getF3() { 165 | return f3; 166 | } 167 | 168 | public void setF3(String f3) { 169 | this.f3 = f3; 170 | } 171 | 172 | public String getF2() { 173 | return f2; 174 | } 175 | 176 | public void setF2(String f2) { 177 | this.f2 = f2; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/test/EventBusStressTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.jd.com. All rights reserved. 3 | */ 4 | package freamwork.test; 5 | 6 | import com.cubbery.event.EventBus; 7 | import freamwork.simple.core.ConcurrentTask; 8 | import freamwork.simple.task.Task; 9 | 10 | import static freamwork.test.EventPool.get; 11 | 12 | /** 13 | * 类描述
14 | * 创建人百墨
15 | * 创建时间: 2016/4/15 - 9:57
16 | * 17 | * @version 1.0.0
18 | */ 19 | public class EventBusStressTest extends Task implements ConcurrentTask { 20 | 21 | public EventBusStressTest(EventBus eventBus) { 22 | super(eventBus); 23 | } 24 | 25 | @Override 26 | public void run() { 27 | this.target.publish(get()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/test/EventPool.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.jd.com. All rights reserved. 3 | */ 4 | package freamwork.test; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.Random; 9 | 10 | import static freamwork.simple.common.UniqNumUtil.getUniqNum; 11 | 12 | /** 13 | * 类描述
14 | * 创建人百墨
15 | * 创建时间: 2016/4/15 - 10:05
16 | * 17 | * @version 1.0.0
18 | */ 19 | public class EventPool { 20 | private static List eventPool; 21 | private static int size; 22 | 23 | public static void init(int size) { 24 | EventPool.size = size; 25 | eventPool = new ArrayList(size); 26 | 27 | for (int a = 0; a < size; a++) { 28 | Event event = new Event(); 29 | event.setE1(getUniqNum(10)); 30 | event.setE2(getUniqNum(10)); 31 | event.setE3(getUniqNum(10)); 32 | event.setE4(getUniqNum(10)); 33 | event.setE5(getUniqNum(10)); 34 | event.setE6(getUniqNum(10)); 35 | event.setE7(getUniqNum(10)); 36 | event.setE8(getUniqNum(10)); 37 | 38 | SubEvent subEvent = new SubEvent(); 39 | subEvent.setF1(getUniqNum(11)); 40 | subEvent.setF2(getUniqNum(11)); 41 | subEvent.setF4(getUniqNum(11)); 42 | subEvent.setF3(getUniqNum(11)); 43 | subEvent.setF5(getUniqNum(11)); 44 | subEvent.setF6(getUniqNum(11)); 45 | subEvent.setF7(getUniqNum(11)); 46 | subEvent.setF8(getUniqNum(11)); 47 | subEvent.setF9(getUniqNum(11)); 48 | 49 | event.setSubEvent(subEvent); 50 | eventPool.add(event); 51 | } 52 | } 53 | 54 | public static Event get() { 55 | return eventPool.get(new Random().nextInt(size)); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/test/EventSub.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.jd.com. All rights reserved. 3 | */ 4 | package freamwork.test; 5 | 6 | import com.cubbery.event.ISubscribe; 7 | 8 | /** 9 | * 类描述
10 | * 创建人百墨
11 | * 创建时间: 2016/4/15 - 10:20
12 | * 13 | * @version 1.0.0
14 | */ 15 | public class EventSub implements ISubscribe { 16 | @Override 17 | public void handler(Event event) { 18 | try { 19 | Thread.sleep(0,100);//100 ns 20 | } catch (InterruptedException e) { 21 | e.printStackTrace(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /async-event-example/src/test/java/freamwork/test/Runner.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.jd.com. All rights reserved. 3 | */ 4 | package freamwork.test; 5 | 6 | import com.cubbery.event.EventBus; 7 | import freamwork.simple.core.ConcurrentTest; 8 | import org.springframework.context.support.ClassPathXmlApplicationContext; 9 | 10 | /** 11 | * 类描述
12 | * 创建人百墨
13 | * 创建时间: 2016/4/15 - 10:17
14 | * 15 | * @version 1.0.0
16 | */ 17 | public class Runner { 18 | public static void main(String[] args) throws InterruptedException { 19 | ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml","spring-orac.xml"); 20 | final EventBus eventBus = applicationContext.getBean("eventBus",EventBus.class); 21 | eventBus.register(new EventSub()); 22 | 23 | eventBus.start(); 24 | 25 | EventPool.init(100); 26 | /* 27 | ===: ======= 28 | sum: 40,676,685,409 29 | min: 14,026,225 30 | max: 755,596,717 31 | avg: 40,676,685 32 | err: 0 33 | ===: ======= 34 | */ 35 | //new ConcurrentTest(10,100,new EventBusStressTest(eventBus)).start();//10个并发,100次重复 36 | 37 | //Thread.sleep(10000); 38 | 39 | /* 40 | ===: ======= 41 | sum: 39,964,314,762 42 | min: 13,577,526 43 | max: 947,670,239 44 | avg: 39,964,314 45 | err: 0 46 | ===: ======= 47 | */ 48 | new ConcurrentTest(10,100,new EventBusStressTest(eventBus)).start();//10个并发,100次重复 49 | 50 | eventBus.stop(); 51 | applicationContext.stop(); 52 | applicationContext.close(); 53 | System.exit(1); 54 | //性能瓶颈主要在数据库 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /async-event-jdbc/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | async-event 7 | com.cubbery.event 8 | 1.0.1 9 | 10 | 4.0.0 11 | 12 | async-event-jdbc 13 | com.cubbery.event 14 | async-event-jdbc 15 | jar 16 | 17 | 18 | 19 | com.cubbery.event 20 | async-event-core 21 | provided 22 | 23 | 24 | com.oracle 25 | ojdbc14 26 | provided 27 | 28 | 29 | -------------------------------------------------------------------------------- /async-event-jdbc/src/main/resources/async-event-mysql-20160229.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- 主机: 127.0.0.1 3 | -- 服务器版本: 5.6.19 - MySQL Community Server (GPL) 4 | -- 服务器操作系统: Win64 5 | -- HeidiSQL 版本: 8.3.0.4796 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8 */; 10 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 11 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 12 | 13 | -- 导出 event 的数据库结构 14 | CREATE DATABASE IF NOT EXISTS `event` /*!40100 DEFAULT CHARACTER SET utf8 */; 15 | USE `event`; 16 | 17 | 18 | -- 导出 表 event.async_event 结构 19 | CREATE TABLE IF NOT EXISTS `async_event` ( 20 | `id` int(11) NOT NULL AUTO_INCREMENT, 21 | `status` int(4) NOT NULL, 22 | `data` varchar(512) DEFAULT NULL, 23 | `type` varchar(50) NOT NULL, 24 | `expression` varchar(100) , 25 | `mark` int(11) DEFAULT NULL, 26 | `retry_count` int(4) , 27 | `createdTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 28 | `modifiedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 29 | PRIMARY KEY (`id`) 30 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 31 | 32 | -- 数据导出被取消选择。 33 | 34 | 35 | -- 导出 表 event.async_lease 结构 36 | CREATE TABLE IF NOT EXISTS `async_lease` ( 37 | `id` int(11) NOT NULL, 38 | `period` int(11) NOT NULL, 39 | `version` int(11) NOT NULL, 40 | `master` varchar(512) DEFAULT NULL, 41 | `createdTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 42 | `modifiedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 43 | PRIMARY KEY (`id`) 44 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 45 | 46 | -- 数据导出被取消选择。 47 | 48 | 49 | -- 导出 表 event.async_lease_offline 结构 50 | CREATE TABLE IF NOT EXISTS `async_lease_offline` ( 51 | `id` int(11) NOT NULL, 52 | `master` int(11) DEFAULT NULL, 53 | `createdTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 54 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 55 | 56 | -- 数据导出被取消选择。 57 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 58 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 59 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 60 | -------------------------------------------------------------------------------- /async-event-jdbc/src/main/resources/async_event_oracle-20160307.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE TABLE customer.ASYNC_EVENT 3 | ( 4 | ID NUMBER(11) NOT NULL, 5 | STATUS VARCHAR2(2 ) NOT NULL, 6 | TYPE VARCHAR2(128) NOT NULL, 7 | EXPRESSION VARCHAR2(128 ) , 8 | DATA VARCHAR2(2000 ) , 9 | MARK VARCHAR2(32) , 10 | RETRY_COUNT NUMBER(4) , 11 | CREATED_DATE TIMESTAMP (6) NOT NULL, 12 | MODIFIED_DATE TIMESTAMP (6) NOT NULL 13 | ); 14 | 15 | COMMENT ON TABLE customer.ASYNC_EVENT IS '异步事件表'; 16 | COMMENT ON COLUMN customer.ASYNC_EVENT.ID IS '主键ID'; 17 | COMMENT ON COLUMN customer.ASYNC_EVENT.STATUS IS '状态(0,成功,1,待消费,2,待重试,3,私信)'; 18 | COMMENT ON COLUMN customer.ASYNC_EVENT.TYPE IS '事件类型(class名称)'; 19 | COMMENT ON COLUMN customer.ASYNC_EVENT.EXPRESSION IS '订阅者表达式。结构:(className#methodName)'; 20 | COMMENT ON COLUMN customer.ASYNC_EVENT.DATA IS '事件对象(json串)'; 21 | COMMENT ON COLUMN customer.ASYNC_EVENT.MARK IS '备注'; 22 | COMMENT ON COLUMN customer.ASYNC_EVENT.RETRY_COUNT IS '重试次数'; 23 | COMMENT ON COLUMN customer.ASYNC_EVENT.CREATED_DATE IS '创建时间'; 24 | COMMENT ON COLUMN customer.ASYNC_EVENT.MODIFIED_DATE IS '修改时间'; 25 | 26 | 27 | ALTER TABLE customer.ASYNC_EVENT add constraint PK_ASYNC_EVENT primary key (ID); 28 | 29 | create sequence customer.SEQ_ASYNC_EVENT_ID 30 | minvalue 1 31 | maxvalue 99999999999 32 | start with 1 33 | increment by 1 34 | cache 100; 35 | 36 | CREATE TABLE customer.ASYNC_LEASE 37 | ( 38 | ID NUMBER(11) NOT NULL, 39 | PERIOD NUMBER(11) NOT NULL, 40 | VERSION NUMBER(11) NOT NULL, 41 | MASTER VARCHAR2(32 ) , 42 | CREATED_DATE TIMESTAMP (6) NOT NULL, 43 | MODIFIED_DATE TIMESTAMP (6) NOT NULL 44 | ); 45 | COMMENT ON TABLE customer.ASYNC_LEASE IS '异步事件租期表'; 46 | COMMENT ON COLUMN customer.ASYNC_LEASE.ID IS '主键ID'; 47 | COMMENT ON COLUMN customer.ASYNC_LEASE.PERIOD IS '租期(单位s)'; 48 | COMMENT ON COLUMN customer.ASYNC_LEASE.VERSION IS '版本(用于并发控制)'; 49 | COMMENT ON COLUMN customer.ASYNC_LEASE.MASTER IS '租期持有者信息(主节点ip_pid_romdam)'; 50 | COMMENT ON COLUMN customer.ASYNC_LEASE.CREATED_DATE IS '创建时间'; 51 | COMMENT ON COLUMN customer.ASYNC_LEASE.MODIFIED_DATE IS '修改时间'; 52 | 53 | ALTER TABLE customer.ASYNC_LEASE add constraint PK_ASYNC_LEASE primary key (ID); 54 | 55 | CREATE TABLE customer.ASYNC_LEASE_OFFLINE 56 | ( 57 | ID NUMBER(11) NOT NULL, 58 | MASTER VARCHAR2(32 ) , 59 | CREATED_DATE TIMESTAMP (6) NOT NULL, 60 | MODIFIED_DATE TIMESTAMP (6) NOT NULL 61 | ); 62 | COMMENT ON TABLE customer.ASYNC_LEASE_OFFLINE IS '异步事件租期持有者下线表'; 63 | COMMENT ON COLUMN customer.ASYNC_LEASE_OFFLINE.ID IS '主键ID'; 64 | COMMENT ON COLUMN customer.ASYNC_LEASE_OFFLINE.MASTER IS '租期持有者信息(主节点ip_pid_romdam)'; 65 | COMMENT ON COLUMN customer.ASYNC_LEASE_OFFLINE.CREATED_DATE IS '创建时间'; 66 | COMMENT ON COLUMN customer.ASYNC_LEASE_OFFLINE.MODIFIED_DATE IS '修改时间'; 67 | 68 | ALTER TABLE customer.ASYNC_LEASE_OFFLINE add constraint PK_ASYNC_LEASE_OFFLINE primary key (ID); 69 | 70 | create sequence customer.SEQ_ASYNC_LEASE_OFFLINE 71 | minvalue 1 72 | maxvalue 99999999999 73 | start with 1 74 | increment by 1 75 | cache 100; -------------------------------------------------------------------------------- /async-event-monitor/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | async-event 7 | com.cubbery.event 8 | 1.0.1 9 | 10 | 4.0.0 11 | 12 | async-event-monitor 13 | com.cubbery.event 14 | async-event-monitor 15 | jar 16 | 17 | 18 | 19 | io.netty 20 | netty-all 21 | 22 | 23 | com.cubbery.event 24 | async-event-core 25 | 26 | 27 | org.apache.zookeeper 28 | zookeeper 29 | 30 | 31 | -------------------------------------------------------------------------------- /async-event-monitor/src/main/java/com/cubbery/event/monitor/MonitorServer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.monitor; 5 | 6 | import com.cubbery.event.Statistics; 7 | 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | public abstract class MonitorServer { 13 | /**样本集合**/ 14 | protected final Map samples = new HashMap(); 15 | 16 | protected MonitorServer() { 17 | } 18 | 19 | protected MonitorServer(List samples) { 20 | if(null == samples || samples.size() < 1) return; 21 | for(Statistics statistics : samples) { 22 | this.samples.put(statistics.getType(),statistics); 23 | } 24 | } 25 | 26 | /** 27 | * close 28 | */ 29 | public abstract void close(); 30 | 31 | /** 32 | * startUp 33 | */ 34 | public abstract void startUp(); 35 | 36 | public Map getSamples() { 37 | return samples; 38 | } 39 | 40 | public void setSamples(Map samples) { 41 | this.samples.putAll(samples); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /async-event-monitor/src/main/java/com/cubbery/event/monitor/log/LogMonitor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.monitor.log; 5 | 6 | import com.cubbery.event.Statistics; 7 | import com.cubbery.event.monitor.MonitorServer; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.Timer; 14 | 15 | public final class LogMonitor extends MonitorServer { 16 | private final static Logger LOG = LoggerFactory.getLogger("Log_Monitor"); 17 | private final static long period = 10 * 60 * 1000;// 10 min 18 | private Timer timer; 19 | 20 | public LogMonitor(List samples) { 21 | super(samples); 22 | this.timer = new Timer(true); 23 | } 24 | 25 | public synchronized void startUp() { 26 | timer.purge(); 27 | timer.scheduleAtFixedRate(new Task(),0,period); 28 | } 29 | 30 | public synchronized void close() { 31 | timer.cancel(); 32 | } 33 | 34 | class Task extends java.util.TimerTask { 35 | 36 | @Override 37 | public void run() { 38 | //遍历所有样本,依次上报 39 | for(Map.Entry entry : samples.entrySet()) { 40 | switch (entry.getKey()) { 41 | case CHANNEL: 42 | LOG.info("==Channel==" + entry.getValue().toString()); 43 | break; 44 | default: 45 | break; 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /async-event-monitor/src/main/java/com/cubbery/event/monitor/zk/SimpleZkMonitor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.monitor.zk; 5 | 6 | import com.cubbery.event.Statistics; 7 | import com.cubbery.event.monitor.MonitorServer; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.util.*; 12 | 13 | import static com.cubbery.event.utils.HostUtils.aboutThisJvm; 14 | 15 | /** 16 | * 创建人百墨
17 | * 修改人
18 | * 创建时间: 2016/3/28 - 15:27
19 | * @version 1.0.0
20 | * 21 | * 路径示例: async_event_[app]_[statisticType]_[node(ip+pid)] 22 | * 23 | */ 24 | public class SimpleZkMonitor extends MonitorServer { 25 | private final static Logger _LOG = LoggerFactory.getLogger(SimpleZkMonitor.class); 26 | 27 | private final Map _ZK_PATH = new HashMap(); 28 | private final String appName ; 29 | private final int internal; 30 | private final ZKManager zkManager; 31 | private final Timer timer; 32 | private volatile boolean isRunning = false; 33 | 34 | public SimpleZkMonitor(String appName,String zkConnectString) { 35 | this(appName,zkConnectString,null); 36 | } 37 | 38 | public SimpleZkMonitor(String appName,String zkConnectString,List samples) { 39 | this(appName,zkConnectString,5,samples); 40 | } 41 | 42 | public SimpleZkMonitor(String appName,String zkConnectString,int internal,List samples) { 43 | super(samples); 44 | this.internal = internal; 45 | this.appName = appName; 46 | this.timer = new Timer(true);//Daemon 47 | this.zkManager = new ZKManager(zkConnectString); 48 | } 49 | 50 | @Override 51 | public void close() { 52 | isRunning = false; 53 | try { 54 | zkManager.close(); 55 | timer.cancel(); 56 | } catch (Exception e) { 57 | _LOG.info("Try to close zk monitor Error!",e); 58 | } 59 | } 60 | 61 | @Override 62 | public synchronized void startUp() { 63 | if(isRunning == true) { 64 | return; 65 | } 66 | timer.schedule(new TimerTask() { 67 | @Override 68 | public void run() { 69 | report2Zk(); 70 | } 71 | },0,internal); 72 | } 73 | 74 | private void report2Zk() { 75 | //遍历所有样本,依次上报 76 | for(Map.Entry entry : samples.entrySet()) { 77 | switch (entry.getKey()) { 78 | case CHANNEL: 79 | reportChannel(entry.getValue()); 80 | break; 81 | default: 82 | break; 83 | } 84 | } 85 | } 86 | 87 | private void reportChannel(Statistics value) { 88 | String zkPath = zkPath(Statistics.Type.CHANNEL); 89 | String content = value.toString(); 90 | //write to zk 91 | try { 92 | zkManager.updateConf(zkPath,content); 93 | } catch (Exception e) { 94 | _LOG.info("Report to zk Error!",e); 95 | } 96 | } 97 | 98 | private String zkPath(Statistics.Type type) { 99 | if(!_ZK_PATH.containsKey(type)) { 100 | StringBuilder sb = new StringBuilder(); 101 | sb.append("/async_event/").append(appName); 102 | sb.append("/").append(type.name()); 103 | sb.append("/").append(aboutThisJvm()); 104 | _ZK_PATH.put(type,sb.toString()); 105 | } 106 | return _ZK_PATH.get(type); 107 | } 108 | } 109 | 110 | 111 | -------------------------------------------------------------------------------- /async-event-monitor/src/main/java/com/cubbery/event/monitor/zk/ZKManager.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.monitor.zk; 5 | 6 | import org.apache.zookeeper.*; 7 | import org.apache.zookeeper.data.ACL; 8 | import org.apache.zookeeper.data.Id; 9 | import org.apache.zookeeper.server.auth.DigestAuthenticationProvider; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.concurrent.CountDownLatch; 16 | 17 | public class ZKManager { 18 | private final static Logger _LOG = LoggerFactory.getLogger(ZKManager.class); 19 | 20 | private ZooKeeper zk; 21 | private List acl = new ArrayList(); 22 | private final String zkConnectString; 23 | private String userName = "async_event"; 24 | private String password = "async_event"; 25 | private final int zkSessionTimeout;//5s 26 | 27 | public ZKManager(String zkConnectString) { 28 | this(zkConnectString,5 * 1000); 29 | } 30 | 31 | public ZKManager(String zkConnectString,int zkSessionTimeout) { 32 | this.zkConnectString = zkConnectString; 33 | this.zkSessionTimeout = zkSessionTimeout; 34 | try { 35 | CountDownLatch countDownLatch = new CountDownLatch(1); 36 | if (this.checkZookeeperState() == false) { 37 | createZookeeper(countDownLatch); 38 | } 39 | countDownLatch.countDown(); 40 | } catch (Exception e) { 41 | _LOG.error("Create Zk Manager Err!",e); 42 | throw new RuntimeException(e); 43 | } 44 | } 45 | 46 | /** 47 | * 重连zookeeper 48 | * 49 | * @throws Exception 50 | */ 51 | public synchronized void reConnection() throws Exception { 52 | if (this.zk != null) { 53 | this.zk.close(); 54 | this.zk = null; 55 | this.connect(); 56 | } 57 | } 58 | 59 | public boolean checkZookeeperState() throws Exception { 60 | return zk != null && zk.getState() == ZooKeeper.States.CONNECTED; 61 | } 62 | 63 | public void close() throws InterruptedException { 64 | _LOG.info("关闭zookeeper连接"); 65 | this.zk.close(); 66 | } 67 | 68 | public void updateConf(String zkPath,String content) throws Exception { 69 | if(zk.exists(zkPath, false) == null){ 70 | ZkTools.createPath(zk, zkPath, CreateMode.PERSISTENT, acl); 71 | } 72 | zk.setData(zkPath,content.getBytes(),-1); 73 | } 74 | 75 | private void connect() throws Exception { 76 | CountDownLatch connectionLatch = new CountDownLatch(1); 77 | createZookeeper(connectionLatch); 78 | connectionLatch.await(); 79 | } 80 | 81 | private void createZookeeper(final CountDownLatch connectionLatch) throws Exception { 82 | zk = new ZooKeeper(zkConnectString, zkSessionTimeout, 83 | new Watcher() { 84 | public void process(WatchedEvent event) { 85 | sessionEvent(connectionLatch, event); 86 | } 87 | }); 88 | String authString = userName + ":" + password; 89 | zk.addAuthInfo("digest", authString.getBytes()); 90 | acl.clear(); 91 | acl.add(new ACL(ZooDefs.Perms.ALL, new Id("digest", DigestAuthenticationProvider.generateDigest(authString)))); 92 | acl.add(new ACL(ZooDefs.Perms.READ, ZooDefs.Ids.ANYONE_ID_UNSAFE)); 93 | } 94 | 95 | private void sessionEvent(CountDownLatch connectionLatch, WatchedEvent event) { 96 | if (event.getState() == Watcher.Event.KeeperState.SyncConnected) { 97 | _LOG.info("收到ZK连接成功事件!"); 98 | connectionLatch.countDown(); 99 | } else if (event.getState() == Watcher.Event.KeeperState.Expired) { 100 | _LOG.error("会话超时,等待重新建立ZK连接..."); 101 | try { 102 | reConnection(); 103 | } catch (Exception e) { 104 | _LOG.error(e.getMessage(), e); 105 | } 106 | } 107 | // Disconnected:Zookeeper会自动处理Disconnected状态重连 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /async-event-monitor/src/main/java/com/cubbery/event/monitor/zk/ZkTools.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015, www.cubbery.com. All rights reserved. 3 | */ 4 | package com.cubbery.event.monitor.zk; 5 | 6 | import org.apache.zookeeper.CreateMode; 7 | import org.apache.zookeeper.ZooKeeper; 8 | import org.apache.zookeeper.data.ACL; 9 | import org.apache.zookeeper.data.Stat; 10 | 11 | import java.io.Writer; 12 | import java.util.ArrayList; 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | public class ZkTools { 17 | 18 | public static void createPath(ZooKeeper zk, String path,CreateMode createMode, List acl) throws Exception { 19 | String[] list = path.split("/"); 20 | String zkPath = ""; 21 | for (String str : list) { 22 | if (str.equals("") == false) { 23 | zkPath = zkPath + "/" + str; 24 | if (zk.exists(zkPath, false) == null) { 25 | zk.create(zkPath, null, acl, createMode); 26 | } 27 | } 28 | } 29 | } 30 | 31 | public static void printTree(ZooKeeper zk,String path,Writer writer,String lineSplitChar) throws Exception{ 32 | String[] list = getTree(zk,path); 33 | Stat stat = new Stat(); 34 | for(String name:list){ 35 | byte[] value = zk.getData(name, false, stat); 36 | if(value == null){ 37 | writer.write(name + lineSplitChar); 38 | }else{ 39 | writer.write(name+"[v."+ stat.getVersion() +"]"+"["+ new String(value) +"]" + lineSplitChar); 40 | } 41 | } 42 | } 43 | public static void deleteTree(ZooKeeper zk,String path) throws Exception{ 44 | String[] list = getTree(zk,path); 45 | for(int i= list.length -1;i>=0; i--){ 46 | zk.delete(list[i],-1); 47 | } 48 | } 49 | 50 | public static String[] getTree(ZooKeeper zk,String path) throws Exception{ 51 | if(zk.exists(path, false) == null){ 52 | return new String[0]; 53 | } 54 | List dealList = new ArrayList(); 55 | dealList.add(path); 56 | int index =0; 57 | while(index < dealList.size()){ 58 | String tempPath = dealList.get(index); 59 | List children = zk.getChildren(tempPath, false); 60 | if(tempPath.equalsIgnoreCase("/") == false){ 61 | tempPath = tempPath +"/"; 62 | } 63 | Collections.sort(children); 64 | for(int i = children.size() -1;i>=0;i--){ 65 | dealList.add(index+1, tempPath + children.get(i)); 66 | } 67 | index++; 68 | } 69 | return (String[])dealList.toArray(new String[0]); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /async-event-monitor/src/main/resources/html/retry.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lipengming/async-event/5f23b84d78377e3f748ea3de7a5f39d0b4faab8d/async-event-monitor/src/main/resources/html/retry.html -------------------------------------------------------------------------------- /async-event-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | async-event 7 | com.cubbery.event 8 | 1.0.1 9 | 10 | 4.0.0 11 | 12 | async-event-server 13 | 服务器事件存储服务 14 | 15 | -------------------------------------------------------------------------------- /doc/frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lipengming/async-event/5f23b84d78377e3f748ea3de7a5f39d0b4faab8d/doc/frame.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.cubbery.event 8 | async-event 9 | pom 10 | 1.0.1 11 | 进程内异步事件组件 12 | 13 | 14 | async-event-core 15 | async-event-jdbc 16 | async-event-monitor 17 | async-event-server 18 | async-event-example 19 | 20 | 21 | 22 | UTF-8 23 | 3.1.0 24 | 1.1.0 25 | 5.1.34 26 | 10.2.0.3.0 27 | 3.2.4.RELEASE 28 | 2.3.1 29 | 4.0.9.Final 30 | 3.4.5 31 | 32 | 33 | 34 | 35 | 36 | 37 | com.google.code.gson 38 | gson 39 | ${json_version} 40 | 41 | 42 | 43 | mysql 44 | mysql-connector-java 45 | ${mysql_version} 46 | 47 | 48 | 49 | com.oracle 50 | ojdbc14 51 | ${oracle_version} 52 | 53 | 54 | 55 | 56 | io.netty 57 | netty-all 58 | ${netty_version} 59 | 60 | 61 | 62 | 63 | org.apache.zookeeper 64 | zookeeper 65 | ${zk_client_version} 66 | 67 | 68 | org.slf4j 69 | slf4j-api 70 | 71 | 72 | org.slf4j 73 | slf4j-log4j12 74 | 75 | 76 | log4j 77 | log4j 78 | 79 | 80 | 81 | 82 | 83 | 84 | com.cubbery.event 85 | async-event-core 86 | ${project.version} 87 | 88 | 89 | com.cubbery.event 90 | async-event-jdbc 91 | ${project.version} 92 | 93 | 94 | com.cubbery.event 95 | async-event-monitor 96 | ${project.version} 97 | 98 | 99 | com.cubbery.event 100 | async-event-sample 101 | ${project.version} 102 | 103 | 104 | 105 | 106 | 107 | 108 | org.slf4j 109 | slf4j-api 110 | 1.7.10 111 | 112 | 113 | org.testng 114 | testng 115 | 6.8.8 116 | test 117 | 118 | 119 | 120 | 121 | 122 | 123 | org.apache.maven.plugins 124 | maven-compiler-plugin 125 | 126 | 1.6 127 | 1.6 128 | UTF-8 129 | 130 | 131 | 132 | 133 | org.apache.maven.plugins 134 | maven-source-plugin 135 | 136 | 137 | attach-sources 138 | 139 | jar 140 | 141 | 142 | 143 | 144 | 145 | 146 | --------------------------------------------------------------------------------