- 浏览: 984888 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
JMS(ActiveMQ) PTP和PUB/SUB模式实例:http://donald-draper.iteye.com/blog/2347445
ActiveMQ连接工厂、连接详解:http://donald-draper.iteye.com/blog/2348070
ActiveMQ会话初始化:http://donald-draper.iteye.com/blog/2348341
ActiveMQ生产者:http://donald-draper.iteye.com/blog/2348381
ActiveMQ消费者:http://donald-draper.iteye.com/blog/2348389
ActiveMQ启动过程详解:http://donald-draper.iteye.com/blog/2348399
ActiveMQ Broker发送消息给消费者过程详解:http://donald-draper.iteye.com/blog/2348440
Spring与ActiveMQ的集成:http://donald-draper.iteye.com/blog/2347638
Spring与ActiveMQ的集成详解一:http://donald-draper.iteye.com/blog/2348449
Spring与ActiveMQ的集成详解二:http://donald-draper.iteye.com/blog/2348461
执行以下命令,
可以看到,activemq jar包中有一个类为Main,这就是active的启动入口
1.解析扩展
从上可以看出,解析拓展目录配置项,并将扩展目录添加到拓展集合中
2.获取配置
3.将配置文件添加到ClassPath
将配置文件添加到ClassPath集合中
4.
将lib扩展目录添加到扩展目录集合中
5.
从系统获取activemq.classpath,添加到ClassPath集合中
6.
启动broker
我们来看ShellCommand类,及其main方法
再看main方法:
来看执行启动broker命令
//AbstractCommand
回到启动broker中
//打印帮助命令
//ShellCommand
CommandContext通过CommandShellOutputFormatter打印帮助文档
//CommandShellOutputFormatter
从上面可以看当activemq的参数为帮助信息或版本信息,则打印相关信息,否则启动broker
回到启动命令
//启动broker
//ShellCommand
我们来看start命令
//StartCommand
来看BrokerFactory工厂根据配置文件创建Broker服务
a.创建broker工厂处理handler
BrokerFactoryHandler handler = createBrokerFactoryHandler(brokerURI.getScheme());
有上面configURI = new URI("xbean:activemq.xml"),activeMQ将配置文件,放在JMX中管理,
协议为Xbean
xbean文件
b.由Handler创建BrokerService
//XBeanBrokerFactory
//XBeanBrokerFactory
贴上activemq.xml broker配置片段,以便理解
//从上下文中获取broker属性
从上可以看出XBeanBrokerFactory首先根据activemq.xml在JMX中xbean信息,通过Spring加载
应用上下文的方式解析xbean信息,然后从应用上下文中获取broker服务XBeanBrokerService
再看启动Broker
启动在BrokerService中
从上面可以看出BrokerService的构造,主要是初始化关闭broker是否有Hook,任务线程优先级,是否允许重启,是否支出调度器,消费者生产者允许使用的内存占比。
来看启动
我们最关心的是启动broker
启动broker
开启所有连接
来看启动连接监听
启动连接监听
从上面看初始化TransportConnector,就是初始化broker服务,允许连接的最大消费者与生产者等信息。
//启动连接
//TcpTransportFactory
再看TcpTransportServer
再看启动server
看到ServiceSupport,实际调用的为doStart
//TransportServerThreadSupport
同时启动TcpTransportServer线程
//TcpTransportServer
在brokerService启动过程中有设置了连接监听器
//TransportConnector
总结:
从activemq脚本,可以看出启动ActiveMQ实际是启动,bin文件夹下的其实activemq.jar包中有一个类为Main,这就是active的启动入口,Main主要是加载lib目录和ClassPath,初始化类加载器,委托给ShellCommand,由ShellCommand根据命令描述去执行,如果是Version和HELP,则打印信息,若是启动命令,则通过XBeanBrokerFactory创建BrokerService,这个过程主要利用的Spring的bean容器机制,然后启动BrokerService,主要启动持久化适配器,JMX连接,上下文关系器,最后启动所有网络连接,及TcpTransport连接,默认使用的是openwire:tcp,所以我们就看一下
TcpTransportServer,TcpTransportServer有TcpTransportFactory创建并配置OpenWire协议转换器,启动TcpTransportServer,就是从ServerSocketFactory获取ServerSocket,并绑定ip和port,监听连接,并设置ServerSocket的监听器org.apache.activemq.transport.nio.SelectorManager.Listener,这个用的
是java nio。
//SelectorManager
ActiveMQ连接工厂、连接详解:http://donald-draper.iteye.com/blog/2348070
ActiveMQ会话初始化:http://donald-draper.iteye.com/blog/2348341
ActiveMQ生产者:http://donald-draper.iteye.com/blog/2348381
ActiveMQ消费者:http://donald-draper.iteye.com/blog/2348389
ActiveMQ启动过程详解:http://donald-draper.iteye.com/blog/2348399
ActiveMQ Broker发送消息给消费者过程详解:http://donald-draper.iteye.com/blog/2348440
Spring与ActiveMQ的集成:http://donald-draper.iteye.com/blog/2347638
Spring与ActiveMQ的集成详解一:http://donald-draper.iteye.com/blog/2348449
Spring与ActiveMQ的集成详解二:http://donald-draper.iteye.com/blog/2348461
[activemq@zabbix bin]$ more activemq ... 配置Active HOME,BASE,OPTS,CONF,JAVA_HOME&JAVA_CMD路径, ... //执行jar包 invokeJar(){ PIDFILE="$1" TASK_TODO="$2" RET="1" if [ ! -f "${ACTIVEMQ_HOME}/bin/activemq.jar" ];then echo "ERROR: '${ACTIVEMQ_HOME}/bin/activemq.jar' does not exist, define ACTIVEMQ_HOME in the config" exit 1 fi #执行active jar包 # Execute java binary if [ -n "$TASK_TODO" ] && [ "$TASK_TODO" != "stop" ];then $EXEC_OPTION $DOIT_PREFIX "\"$JAVACMD\" $ACTIVEMQ_OPTS $ACTIVEMQ_DEBUG_OPTS \ -Dactivemq.classpath=\"${ACTIVEMQ_CLASSPATH}\" \ -Dactivemq.home=\"${ACTIVEMQ_HOME}\" \ -Dactivemq.base=\"${ACTIVEMQ_BASE}\" \ -Dactivemq.conf=\"${ACTIVEMQ_CONF}\" \ -Dactivemq.data=\"${ACTIVEMQ_DATA}\" \ $ACTIVEMQ_CYGWIN \ -jar \"${ACTIVEMQ_HOME}/bin/activemq.jar\" $COMMANDLINE_ARGS >/dev/null 2>&1 & RET=\"\$?\"; APID=\"\$!\"; echo \$APID > "${PIDFILE}"; echo \"INFO: pidfile created : '${PIDFILE}' (pid '\$APID')\";exit \$RET" $DOIT_POSTFIX RET="$?" #./activemq start 启动Broker invoke_start(){ if ( checkRunning );then PID="`cat $ACTIVEMQ_PIDFILE`" echo "INFO: Process with pid '$PID' is already running" exit 0 fi ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_SUNJMX_START $ACTIVEMQ_SSL_OPTS -Djava.awt.headless=true -Djava.io.tmpdir=\"${ACTIVEMQ_TMP}\"" echo "INFO: Starting - inspect logfiles specified in logging.properties and log4j.properties to get details" invokeJar "$ACTIVEMQ_PIDFILE" start exit "$?" } .... [activemq@zabbix bin]$ ls activemq activemq-diag activemq.jar env linux-x86-32 linux-x86-64 macosx wrapper.jar [activemq@zabbix bin]$
执行以下命令,
jar -xvf activemq.jar
可以看到,activemq jar包中有一个类为Main,这就是active的启动入口
package org.apache.activemq.console; public class Main { //shell命令任务class public static final String TASK_DEFAULT_CLASS = "org.apache.activemq.console.command.ShellCommand"; private static boolean useDefExt = true; private File activeMQHome;//MQ家目录 private File activeMQBase; private ClassLoader classLoader;//类加载器 //activeMQ 扩展目录 private final Set extensions = new LinkedHashSet(); //activeMQ 类加载路径 private final Set activeMQClassPath = new LinkedHashSet(); } public Main() { } public static void main(String args[]){ //从洗通获取java io临时目录,没有则创建 File tmpdir = new File(System.getProperty("java.io.tmpdir")); if(!tmpdir.exists()) tmpdir.mkdirs(); Main app = new Main(); List tokens = new LinkedList(Arrays.asList(args)); //解析扩展 app.parseExtensions(tokens); //获取配置 File confDir = app.getActiveMQConfig(); //将配置文件添加到ClassPath app.addClassPath(confDir); if(useDefExt && app.canUseExtdir()) { boolean baseIsHome = app.getActiveMQBase().equals(app.getActiveMQHome()); //创建lib目录 File baseLibDir = new File(app.getActiveMQBase(), "lib"); File homeLibDir = new File(app.getActiveMQHome(), "lib"); if(!baseIsHome) app.addExtensionDirectory(baseLibDir); app.addExtensionDirectory(homeLibDir); //创建lib下的camel,optional,web,extra目录 if(!baseIsHome) { app.addExtensionDirectory(new File(baseLibDir, "camel")); app.addExtensionDirectory(new File(baseLibDir, "optional")); app.addExtensionDirectory(new File(baseLibDir, "web")); app.addExtensionDirectory(new File(baseLibDir, "extra")); } app.addExtensionDirectory(new File(homeLibDir, "camel")); app.addExtensionDirectory(new File(homeLibDir, "optional")); app.addExtensionDirectory(new File(homeLibDir, "web")); app.addExtensionDirectory(new File(homeLibDir, "extra")); } //从系统获取activemq.classpath,添加到 app.addClassPathList(System.getProperty("activemq.classpath")); try { //启动broker int ret = app.runTaskClass(tokens); System.exit(ret); } catch(ClassNotFoundException e) { System.out.println((new StringBuilder()).append("Could not load class: ").append(e.getMessage()).toString()); try { ClassLoader cl = app.getClassLoader(); if(cl != null) { System.out.println("Class loader setup: "); printClassLoaderTree(cl); } } catch(MalformedURLException malformedurlexception) { } System.exit(1); } catch(Throwable e) { System.out.println((new StringBuilder()).append("Failed to execute main task. Reason: ").append(e).toString()); System.exit(1); } }
1.解析扩展
app.parseExtensions(tokens);
public void parseExtensions(List tokens) { if(tokens.isEmpty()) return; int count = tokens.size(); for(int i = 0; i < count;) { String token = (String)tokens.get(i); if(token.equals("--extdir")) { count--; tokens.remove(i); if(!extDir.isDirectory()) { System.out.println((new StringBuilder()).append("Extension directory specified is not valid directory: ").append(extDir).toString()); System.out.println("Ignoring extension directory option."); } else { //添加拓展目录 addExtensionDirectory(extDir); } } //添加拓展目录 public void addExtensionDirectory(File directory) { extensions.add(directory); }
从上可以看出,解析拓展目录配置项,并将扩展目录添加到拓展集合中
2.获取配置
File confDir = app.getActiveMQConfig(); public File getActiveMQConfig() { File activeMQConfig = null; if(System.getProperty("activemq.conf") != null) { //从系统获取activemq.conf,如果不为空,则创建配置文件 activeMQConfig = new File(System.getProperty("activemq.conf")); } else { activeMQConfig = new File((new StringBuilder()).append(getActiveMQBase()).append("/conf").toString()); System.setProperty("activemq.conf", activeMQConfig.getAbsolutePath()); } return activeMQConfig; }
3.将配置文件添加到ClassPath
app.addClassPath(confDir); public void addClassPath(File classpath) { activeMQClassPath.add(classpath); }
将配置文件添加到ClassPath集合中
4.
boolean baseIsHome = app.getActiveMQBase().equals(app.getActiveMQHome()); //创建lib目录 File baseLibDir = new File(app.getActiveMQBase(), "lib"); File homeLibDir = new File(app.getActiveMQHome(), "lib"); if(!baseIsHome) app.addExtensionDirectory(baseLibDir); app.addExtensionDirectory(homeLibDir); //创建lib下的camel,optional,web,extra目录 app.addExtensionDirectory(new File(homeLibDir, "camel")); app.addExtensionDirectory(new File(homeLibDir, "optional")); app.addExtensionDirectory(new File(homeLibDir, "web")); app.addExtensionDirectory(new File(homeLibDir, "extra"));
将lib扩展目录添加到扩展目录集合中
5.
从系统获取activemq.classpath,添加到ClassPath集合中
app.addClassPathList(System.getProperty("activemq.classpath"));
6.
启动broker
int ret = app.runTaskClass(tokens);
public int runTaskClass(List tokens) throws Throwable { ClassLoader cl; //获取java版本及home目录 StringBuilder buffer = new StringBuilder(); buffer.append(System.getProperty("java.vendor")); buffer.append(" "); buffer.append(System.getProperty("java.version")); buffer.append(" "); buffer.append(System.getProperty("java.home")); System.out.println((new StringBuilder()).append("Java Runtime: ").append(buffer.toString()).toString()); buffer = new StringBuilder(); //获取java运行时环境的内存状况 buffer.append("current="); buffer.append(Runtime.getRuntime().totalMemory() / 1024L); buffer.append("k free="); buffer.append(Runtime.getRuntime().freeMemory() / 1024L); buffer.append("k max="); buffer.append(Runtime.getRuntime().maxMemory() / 1024L); buffer.append("k"); System.out.println((new StringBuilder()).append(" Heap sizes: ").append(buffer.toString()).toString()); List jvmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments(); buffer = new StringBuilder(); Object arg; for(Iterator i$ = jvmArgs.iterator(); i$.hasNext(); buffer.append(" ").append(arg)) arg = i$.next(); //配置MQ扩展目录,家目录,配置文件以及数据目录 System.out.println((new StringBuilder()).append(" JVM args:").append(buffer.toString()).toString()); System.out.println((new StringBuilder()).append("Extensions classpath:\n ").append(getExtensionDirForLogging()).toString()); System.out.println((new StringBuilder()).append("ACTIVEMQ_HOME: ").append(getActiveMQHome()).toString()); System.out.println((new StringBuilder()).append("ACTIVEMQ_BASE: ").append(getActiveMQBase()).toString()); System.out.println((new StringBuilder()).append("ACTIVEMQ_CONF: ").append(getActiveMQConfig()).toString()); System.out.println((new StringBuilder()).append("ACTIVEMQ_DATA: ").append(getActiveMQDataDir()).toString()); //获取类加载器 cl = getClassLoader(); Thread.currentThread().setContextClassLoader(cl); String args[]; Class task; Method runTask; args = (String[])tokens.toArray(new String[tokens.size()]); //加载ShellCommand类 task = cl.loadClass("org.apache.activemq.console.command.ShellCommand"); //获取ShellCommand的main方法 runTask = task.getMethod("main", new Class[] { [Ljava/lang/String;, java/io/InputStream, java/io/PrintStream }); //调用ShellCommand的 return ((Integer)runTask.invoke(task.newInstance(), new Object[] { args, System.in, System.out })).intValue(); InvocationTargetException e; e; throw e.getCause(); } //获取加载类 public ClassLoader getClassLoader() throws MalformedURLException { if(classLoader == null) { classLoader = org/apache/activemq/console/Main.getClassLoader(); if(!extensions.isEmpty() || !activeMQClassPath.isEmpty()) { ArrayList urls = new ArrayList(); Iterator iter; File dir; for(iter = activeMQClassPath.iterator(); iter.hasNext(); urls.add(dir.toURI().toURL())) dir = (File)iter.next(); iter = extensions.iterator(); do { if(!iter.hasNext()) break; File dir = (File)iter.next(); if(dir.isDirectory()) { File files[] = dir.listFiles(); if(files != null) { Arrays.sort(files, new Comparator() { public int compare(File f1, File f2) { return f1.getName().compareTo(f2.getName()); } public volatile int compare(Object obj, Object obj1) { return compare((File)obj, (File)obj1); } final Main this$0; { this$0 = Main.this; super(); } }); int j = 0; while(j < files.length) { if(files[j].getName().endsWith(".zip") || files[j].getName().endsWith(".jar")) urls.add(files[j].toURI().toURL()); j++; } } } } while(true); URL u[] = new URL[urls.size()]; urls.toArray(u); classLoader = new URLClassLoader(u, classLoader); } //设置当前线程类加载器 Thread.currentThread().setContextClassLoader(classLoader); } return classLoader; }
我们来看ShellCommand类,及其main方法
public class ShellCommand extends AbstractCommand { private boolean interactive; private String helpFile[]; public ShellCommand() { this(false); } public ShellCommand(boolean interactive) { this.interactive = interactive; ArrayList help = new ArrayList(); help.addAll(Arrays.asList(new String[] { interactive ? "Usage: [task] [task-options] [task data]" : "Usage: Main [--extdir <dir>] [task] [task-options] [task data]", "", "Tasks:" })); ArrayList commands = getCommands(); Collections.sort(commands, new Comparator() { public int compare(Command command, Command command1) { return command.getName().compareTo(command1.getName()); } public volatile int compare(Object obj, Object obj1) { return compare((Command)obj, (Command)obj1); } final ShellCommand this$0; { this$0 = ShellCommand.this; super(); } }); Command command; for(Iterator i$ = commands.iterator(); i$.hasNext(); help.add(String.format(" %-24s - %s", new Object[] { command.getName(), command.getOneLineDescription() }))) command = (Command)i$.next(); help.addAll(Arrays.asList(new String[] { "", "Task Options (Options specific to each task):", " --extdir <dir> - Add the jar files in the directory to the classpath.", " --version - Display the version information.", (new StringBuilder()).append(" -h,-?,--help - Display this help information. To display task specific help, use ").append(interactive ? "" : "Main ").append("[task] -h,-?,--help").toString(), "", "Task Data:", " - Information needed by each specific task.", "", "JMX system property options:", " -Dactivemq.jmx.url=<jmx service uri> (default is: 'service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi')", " -Dactivemq.jmx.user=<user name>", " -Dactivemq.jmx.password=<password>", "" })); //将扩展目录,lib目录添加到辅助文件集合 helpFile = (String[])help.toArray(new String[help.size()]); } }
再看main方法:
public static int main(String args[], InputStream in, PrintStream out) { CommandContext context; List tokens; ShellCommand main; //创建命令上下文 context = new CommandContext(); context.setFormatter(new CommandShellOutputFormatter(out)); tokens = new ArrayList(Arrays.asList(args)); main = new ShellCommand(); main.setCommandContext(context); //执行启动broker命令 main.execute(tokens); return 0; Exception e; e; context.printException(e); return 1; }
来看执行启动broker命令
main.execute(tokens);
//AbstractCommand
public void execute(List tokens) throws Exception { //解析activemq 命令参数 parseOptions(tokens); //打印帮助命令 if(isPrintHelp) printHelp(); else //打印版本 if(isPrintVersion) context.printVersion(ActiveMQConnectionMetaData.PROVIDER_VERSION); else //启动broker runTask(tokens); } //解析参数 protected void parseOptions(List tokens) throws Exception { while(!tokens.isEmpty()) { String token = (String)tokens.remove(0); if(token.startsWith("-")) { //以“-”开头,则为配置项,处理参数配置项 handleOption(token, tokens); } else { //否则为命令 tokens.add(0, token); return; } } } protected void handleOption(String token, List tokens) throws Exception { isPrintHelp = false; isPrintVersion = false; if(token.equals("-h") || token.equals("-?") || token.equals("--help")) { //帮助信息,清除tokens isPrintHelp = true; tokens.clear(); } else if(token.equals("--version")) { //打印版本 isPrintVersion = true; tokens.clear(); } else if(token.startsWith("-D")) { //系统参数 String key = token.substring(2); String value = ""; int pos = key.indexOf("="); if(pos >= 0) { value = key.substring(pos + 1); key = key.substring(0, pos); } System.setProperty(key, value); } else { //扩展配置型 if(token.startsWith("--")) { String prop = token.substring(2); if(tokens.isEmpty() || ((String)tokens.get(0)).startsWith("-")) context.print((new StringBuilder()).append("Property '").append(prop).append("' is not specified!").toString()); else if(IntrospectionSupport.setProperty(this, prop, tokens.remove(0))) return; } context.printInfo((new StringBuilder()).append("Unrecognized option: ").append(token).toString()); isPrintHelp = true; } }
回到启动broker中
//打印帮助命令
if(isPrintHelp) printHelp();
//ShellCommand
protected void printHelp() { context.printHelp(helpFile); }
CommandContext通过CommandShellOutputFormatter打印帮助文档
//CommandShellOutputFormatter
public class CommandShellOutputFormatter implements OutputFormatter { private OutputStream outputStream; private PrintStream out; public void printHelp(String helpMsgs[]) { for(int i = 0; i < helpMsgs.length; i++) out.println(helpMsgs[i]); out.println(); } }
从上面可以看当activemq的参数为帮助信息或版本信息,则打印相关信息,否则启动broker
回到启动命令
//启动broker
runTask(tokens);
//ShellCommand
protected void runTask(List tokens) throws Exception { if(tokens.size() > 0) { Command command = null; String taskToken = (String)tokens.remove(0); Iterator i$ = getCommands().iterator(); do { if(!i$.hasNext()) break; Command c = (Command)i$.next(); if(!taskToken.equals(c.getName())) continue; command = c; break; } while(true); if(command == null) if(taskToken.equals("help")) printHelp(); else printHelp(); if(command != null) { command.setCommandContext(context); //执行命令 command.execute(tokens); } } else { printHelp(); } }
我们来看start命令
public class StartCommand extends AbstractCommand { //配置文件 public static final String DEFAULT_CONFIG_URI = "xbean:activemq.xml"; //帮助文档 protected String helpFile[] = { "Task Usage: Main start [start-options] [uri]", "Description: Creates and starts a broker using a configuration file, or a broker URI.", "", "Start Options:", " -D<name>=<value> Define a system property.", " --version Display the version information.", " -h,-?,--help Display the start broker help information.", "", "URI:", "", " XBean based broker configuration:", "", " Example: Main xbean:file:activemq.xml", " Loads the xbean configuration file from the current working directory", " Example: Main xbean:activemq.xml", " Loads the xbean configuration file from the classpath", "", " URI Parameter based broker configuration:", "", " Example: Main broker:(tcp://localhost:61616, tcp://localhost:5000)?useJmx=true", " Configures the broker with 2 transport connectors and jmx enabled", " Example: Main broker:(tcp://localhost:61616, network:tcp://localhost:5000)?persistent=false", " Configures the broker with 1 transport connector, and 1 network connector and persistence disabled", "" }; }
//StartCommand
protected void runTask(List brokerURIs) throws Exception { do { final BrokerService broker; try { URI configURI; if(brokerURIs.isEmpty()) configURI = new URI("xbean:activemq.xml"); else configURI = new URI((String)brokerURIs.get(0)); System.out.println((new StringBuilder()).append("Loading message broker from: ").append(configURI).toString()); //BrokerFactory工厂根据配置文件创建Broker服务 broker = BrokerFactory.createBroker(configURI); //启动Broker broker.start(); } catch(Exception e) { context.printException(new RuntimeException((new StringBuilder()).append("Failed to execute start task. Reason: ").append(e).toString(), e)); throw e; } if(!broker.waitUntilStarted()) throw new Exception(broker.getStartException()); final CountDownLatch shutdownLatch = new CountDownLatch(1); //添加停止broker的JVM回调挂钩 Thread jvmShutdownHook = new Thread() { public void run() { try { broker.stop(); } catch(Exception exception) { } } final BrokerService val$broker; final StartCommand this$0; { this$0 = StartCommand.this; broker = brokerservice; super(); } }; //将停止broker的JVM回调挂钩添加到运行时环境 Runtime.getRuntime().addShutdownHook(jvmShutdownHook); broker.addShutdownHook(new Runnable() { public void run() { shutdownLatch.countDown(); } final CountDownLatch val$shutdownLatch; final StartCommand this$0; { this$0 = StartCommand.this; shutdownLatch = countdownlatch; super(); } }); //等待停止broker信号shutdownLatch shutdownLatch.await(); try { Runtime.getRuntime().removeShutdownHook(jvmShutdownHook); } catch(Throwable throwable) { } if(broker.isRestartRequested()) System.out.println("Restarting broker"); else return; } while(true); }
来看BrokerFactory工厂根据配置文件创建Broker服务
broker = BrokerFactory.createBroker(configURI);
public static BrokerService createBroker(URI brokerURI) throws Exception { return createBroker(brokerURI, false); } public static BrokerService createBroker(URI brokerURI, boolean startBroker) throws Exception { if(brokerURI.getScheme() == null) throw new IllegalArgumentException((new StringBuilder()).append("Invalid broker URI, no scheme specified: ").append(brokerURI).toString()); //a.创建broker工厂处理handler BrokerFactoryHandler handler = createBrokerFactoryHandler(brokerURI.getScheme()); //b.由Handler创建BrokerService BrokerService broker = handler.createBroker(brokerURI); if(startBroker) broker.start(); return broker; }
a.创建broker工厂处理handler
BrokerFactoryHandler handler = createBrokerFactoryHandler(brokerURI.getScheme());
有上面configURI = new URI("xbean:activemq.xml"),activeMQ将配置文件,放在JMX中管理,
协议为Xbean
public final class BrokerFactory { //看到这个是不是很熟悉,根据协议机制,加载BROKER_FACTORY private static final FactoryFinder BROKER_FACTORY_HANDLER_FINDER = new FactoryFinder("META-INF/services/org/apache/activemq/broker/"); private static final ThreadLocal START_DEFAULT = new ThreadLocal(); //创建broker工厂handler, public static BrokerFactoryHandler createBrokerFactoryHandler(String type) throws IOException { //这种模式,前面已经说过,加载META-INF/services/org/apache/activemq/broker/ //文件夹下xbean文件中class属性对应的broker工厂类 return (BrokerFactoryHandler)BROKER_FACTORY_HANDLER_FINDER.newInstance(type); } }
xbean文件
class=org.apache.activemq.xbean.XBeanBrokerFactory
b.由Handler创建BrokerService
BrokerService broker = handler.createBroker(brokerURI);
//XBeanBrokerFactory
public class XBeanBrokerFactory implements BrokerFactoryHandler { private boolean validate; static { PropertyEditorManager.registerEditor(java/net/URI, org/apache/xbean/spring/context/impl/URIEditor); } }
//XBeanBrokerFactory
public BrokerService createBroker(URI config) throws Exception { String uri = config.getSchemeSpecificPart(); if(uri.lastIndexOf('?') != -1) { IntrospectionSupport.setProperties(this, URISupport.parseQuery(uri)); uri = uri.substring(0, uri.lastIndexOf('?')); } //创建上下文 ApplicationContext context = createApplicationContext(uri); BrokerService broker = null; try { //从上下文中获取broker属性 broker = (BrokerService)context.getBean("broker"); } catch(BeansException beansexception) { } if(broker == null) { String names[] = context.getBeanNamesForType(org/apache/activemq/broker/BrokerService); int i = 0; do { if(i >= names.length) break; String name = names[i]; broker = (BrokerService)context.getBean(name); if(broker != null) break; i++; } while(true); } if(broker == null) { throw new IllegalArgumentException((new StringBuilder()).append("The configuration has no BrokerService instance for resource: ").append(config).toString()); } else { SpringBrokerContext springBrokerContext = new SpringBrokerContext(); springBrokerContext.setApplicationContext(context); springBrokerContext.setConfigurationUrl(uri); broker.setBrokerContext(springBrokerContext); return broker; } }
//创建应用上下文,通Spring的机制 protected ApplicationContext createApplicationContext(String uri) throws MalformedURLException { Resource resource; resource = Utils.resourceFromString(uri); LOG.debug((new StringBuilder()).append("Using ").append(resource).append(" from ").append(uri).toString()); return new ResourceXmlApplicationContext(resource) { protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) { reader.setValidating(isValidate()); } //XML Broker工厂 final XBeanBrokerFactory this$0; { this$0 = XBeanBrokerFactory.this; super(x0); } }; FatalBeanException errorToLog; errorToLog; LOG.error((new StringBuilder()).append("Failed to load: ").append(resource).append(", reason: ").append(errorToLog.getLocalizedMessage()).toString(), errorToLog); throw errorToLog; }
贴上activemq.xml broker配置片段,以便理解
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}"> <destinationPolicy> <policyMap> <policyEntries> <policyEntry topic=">" > <!-- The constantPendingMessageLimitStrategy is used to prevent slow topic consumers to block producers and affect other consumers by limiting the number of messages that are retained For more information, see: http://activemq.apache.org/slow-consumer-handling.html --> <pendingMessageLimitStrategy> <constantPendingMessageLimitStrategy limit="1000"/> </pendingMessageLimitStrategy> </policyEntry> </policyEntries> </policyMap> </destinationPolicy> <!-- The managementContext is used to configure how ActiveMQ is exposed in JMX. By default, ActiveMQ uses the MBean server that is started by the JVM. For more information, see: http://activemq.apache.org/jmx.html --> <managementContext> <managementContext createConnector="false"/> </managementContext> <!-- Configure message persistence for the broker. The default persistence mechanism is the KahaDB store (identified by the kahaDB tag). For more information, see: http://activemq.apache.org/persistence.html --> <persistenceAdapter> <kahaDB directory="${activemq.data}/kahadb"/> </persistenceAdapter> <!-- The systemUsage controls the maximum amount of space the broker will use before disabling caching and/or slowing down producers. For more information, see: http://activemq.apache.org/producer-flow-control.html --> <systemUsage> <systemUsage> <memoryUsage> <memoryUsage percentOfJvmHeap="70" /> </memoryUsage> <storeUsage> <storeUsage limit="100 gb"/> </storeUsage> <tempUsage> <tempUsage limit="50 gb"/> </tempUsage> </systemUsage> </systemUsage> <!-- The transport connectors expose ActiveMQ over a given protocol to clients and other brokers. For more information, see: http://activemq.apache.org/configuring-transports.html --> <transportConnectors> <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB --> <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> </transportConnectors> <!-- destroy the spring context on shutdown to stop jetty --> <shutdownHooks> <bean xmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.hooks.SpringContextHook" /> </shutdownHooks> </broker>
//从上下文中获取broker属性
broker = (BrokerService)context.getBean("broker");
public class XBeanBrokerService extends BrokerService { private boolean start; public XBeanBrokerService() { start = BrokerFactory.getStartDefault(); } //在构造完之后,调用afterPropertiesSet private void postConstruct() { try { afterPropertiesSet(); } catch(Exception ex) { throw new RuntimeException(ex); } } public void afterPropertiesSet() throws Exception { //初始化内存使用情况 ensureSystemUsageHasStore(); if(shouldAutostart()) start(); } //保证内存还有空间可用 private void ensureSystemUsageHasStore() throws IOException { SystemUsage usage = getSystemUsage(); if(usage.getStoreUsage().getStore() == null) usage.getStoreUsage().setStore(getPersistenceAdapter()); if(usage.getTempUsage().getStore() == null) usage.getTempUsage().setStore(getTempDataStore()); if(usage.getJobSchedulerUsage().getStore() == null) usage.getJobSchedulerUsage().setStore(getJobSchedulerStore()); } }
从上可以看出XBeanBrokerFactory首先根据activemq.xml在JMX中xbean信息,通过Spring加载
应用上下文的方式解析xbean信息,然后从应用上下文中获取broker服务XBeanBrokerService
再看启动Broker
broker.start();
启动在BrokerService中
public class BrokerService implements Service { public static final String DEFAULT_PORT = "61616";//默认端口 public static final String LOCAL_HOST_NAME; public static final String BROKER_VERSION; public static final String DEFAULT_BROKER_NAME = "localhost"; public static final int DEFAULT_MAX_FILE_LENGTH = 33554432; public static final long DEFAULT_START_TIMEOUT = 600000L; private static final Logger LOG; private static final long serialVersionUID = 7353129142305630237L; private boolean useJmx;//是否用JMX private boolean enableStatistics;//是否开启统计 private boolean persistent;//是否持久化 private boolean populateJMSXUserID; private boolean useAuthenticatedPrincipalForJMSXUserID;//JMX用户验证id private boolean populateUserNameInMBeans; private long mbeanInvocationTimeout; private boolean useShutdownHook;//java运行时,关闭broker,是否有Hook private boolean useLoggingForShutdownErrors; private boolean shutdownOnMasterFailure;//是否在Master宕机时,关闭broker private boolean shutdownOnSlaveFailure; private boolean waitForSlave; private long waitForSlaveTimeout; private boolean passiveSlave; private String brokerName;//broker名称 private File dataDirectoryFile;//数据目录 private File tmpDataDirectory; private Broker broker; private BrokerView adminView; private ManagementContext managementContext;//管理器上下文 private ObjectName brokerObjectName; private TaskRunnerFactory taskRunnerFactory;//任务工厂 private TaskRunnerFactory persistenceTaskRunnerFactory; private SystemUsage systemUsage;//系统内存使用情况 private SystemUsage producerSystemUsage;//生产者内存使用情况 private SystemUsage consumerSystemUsaage;//消费者内存使用情况 private PersistenceAdapter persistenceAdapter;//持久化适配器 private PersistenceAdapterFactory persistenceFactory;//持久化工厂 protected DestinationFactory destinationFactory;//目的地工厂 private MessageAuthorizationPolicy messageAuthorizationPolicy;//消息验证策略 private final List transportConnectors = new CopyOnWriteArrayList();//transportConnectors private final List networkConnectors = new CopyOnWriteArrayList();//networkConnectors private final List proxyConnectors = new CopyOnWriteArrayList(); private final List jmsConnectors = new CopyOnWriteArrayList();//jmsConnectors private final List services = new ArrayList(); private transient Thread shutdownHook;//关闭broke,运行hook线程 private String transportConnectorURIs[];//transportConnector urI private String networkConnectorURIs[]; private JmsConnector jmsBridgeConnectors[]; private boolean deleteAllMessagesOnStartup;//是否在启时,删除所有消息 private boolean advisorySupport; private URI vmConnectorURI;//虚拟机URI private String defaultSocketURIString; private PolicyMap destinationPolicy; //Broker运行状态 private final AtomicBoolean started = new AtomicBoolean(false); private final AtomicBoolean stopped = new AtomicBoolean(false); private final AtomicBoolean stopping = new AtomicBoolean(false); private BrokerPlugin plugins[]; private boolean keepDurableSubsActive; private boolean useVirtualTopics; private boolean useMirroredQueues; private boolean useTempMirroredQueues; //brokerid private BrokerId brokerId; private volatile DestinationInterceptor destinationInterceptors[]; private ActiveMQDestination destinations[];//消息目的地 private PListStore tempDataStore; private int persistenceThreadPriority;//持久化线程优先级 private boolean useLocalHostBrokerName; private final CountDownLatch stoppedLatch = new CountDownLatch(1);//关闭信号量 private final CountDownLatch startedLatch = new CountDownLatch(1);//启动信号量 private Broker regionBroker; private int producerSystemUsagePortion; private int consumerSystemUsagePortion; private boolean splitSystemUsageForProducersConsumers; private boolean monitorConnectionSplits; private int taskRunnerPriority;//任务线程优先级 private boolean dedicatedTaskRunner; private boolean cacheTempDestinations; private int timeBeforePurgeTempDestinations; private final List shutdownHooks = new ArrayList(); private boolean systemExitOnShutdown; private int systemExitOnShutdownExitCode; private SslContext sslContext;//SSL上下文 private boolean forceStart; private IOExceptionHandler ioExceptionHandler; private boolean schedulerSupport; private File schedulerDirectoryFile; private Scheduler scheduler;//调度器 private ThreadPoolExecutor executor;//线程执行器 private int schedulePeriodForDestinationPurge; private int maxPurgedDestinationsPerSweep; private int schedulePeriodForDiskUsageCheck; private BrokerContext brokerContext;//broker上下文 private boolean networkConnectorStartAsync; private boolean allowTempAutoCreationOnSend; private JobSchedulerStore jobSchedulerStore;//job调度存储器 private final AtomicLong totalConnections = new AtomicLong();//连接数 private final AtomicInteger currentConnections = new AtomicInteger(); private long offlineDurableSubscriberTimeout; private long offlineDurableSubscriberTaskSchedule; private DestinationFilter virtualConsumerDestinationFilter; private final AtomicBoolean persistenceAdapterStarted = new AtomicBoolean(false); private Throwable startException; private boolean startAsync; private Date startDate; private boolean slave; private boolean restartAllowed; private boolean restartRequested; private boolean rejectDurableConsumers; private int storeOpenWireVersion; static { //加载版本信息 String version; LOG = LoggerFactory.getLogger(org/apache/activemq/broker/BrokerService); try { ClassLoader loader = org/apache/activemq/broker/BrokerService.getClassLoader(); Class clazz = loader.loadClass("org.bouncycastle.jce.provider.BouncyCastleProvider"); Provider bouncycastle = (Provider)clazz.newInstance(); Security.insertProviderAt(bouncycastle, 2); LOG.info("Loaded the Bouncy Castle security provider."); } String localHostName = "localhost"; try { localHostName = InetAddressUtil.getLocalHostName(); } LOCAL_HOST_NAME = localHostName; version = null; InputStream in; in = org/apache/activemq/broker/BrokerService.getResourceAsStream("/org/apache/activemq/version.txt"); InputStreamReader isr; isr = new InputStreamReader(in); BufferedReader reader; reader = new BufferedReader(isr); try { version = reader.readLine(); } IOException ie; ie; LOG.warn("Error reading broker version ", ie); BROKER_VERSION = version; } public BrokerService() { useJmx = true; enableStatistics = true; persistent = true; mbeanInvocationTimeout = 0L; useShutdownHook = true; waitForSlaveTimeout = 600000L; brokerName = "localhost"; advisorySupport = true; keepDurableSubsActive = true; useVirtualTopics = true; useMirroredQueues = false; useTempMirroredQueues = true; persistenceThreadPriority = 10; producerSystemUsagePortion = 60; consumerSystemUsagePortion = 40; monitorConnectionSplits = false; taskRunnerPriority = 5; cacheTempDestinations = false; timeBeforePurgeTempDestinations = 5000; forceStart = false; schedulerSupport = false; schedulePeriodForDestinationPurge = 0; maxPurgedDestinationsPerSweep = 0; schedulePeriodForDiskUsageCheck = 0; networkConnectorStartAsync = false; offlineDurableSubscriberTimeout = -1L; offlineDurableSubscriberTaskSchedule = 300000L; startException = null; startAsync = false; slave = true; restartAllowed = true; restartRequested = false; rejectDurableConsumers = false; storeOpenWireVersion = 11; } }
从上面可以看出BrokerService的构造,主要是初始化关闭broker是否有Hook,任务线程优先级,是否允许重启,是否支出调度器,消费者生产者允许使用的内存占比。
来看启动
public void start() throws Exception { if(stopped.get() || !started.compareAndSet(false, true)) return; stopping.set(false); startDate = new Date(); MDC.put("activemq.broker", brokerName); if(systemExitOnShutdown && useShutdownHook) throw new ConfigurationException("'useShutdownHook' property cannot be be used with 'systemExitOnShutdown', please turn it off (useShutdownHook=false)"); processHelperProperties(); if(!isUseJmx()) break MISSING_BLOCK_LABEL_156; MDC.remove("activemq.broker"); //启动管理器上下文 startManagementContext(); NetworkConnector connector; //注册网络连接 for(Iterator i$ = getNetworkConnectors().iterator(); i$.hasNext(); registerNetworkConnectorMBean(connector)) connector = (NetworkConnector)i$.next(); MDC.put("activemq.broker", brokerName); BrokerRegistry brokerRegistry = BrokerRegistry.getInstance(); if(brokerRegistry.lookup(getBrokerName()) == null) brokerRegistry.bind(getBrokerName(), this); //启动适配器 startPersistenceAdapter(startAsync); //启动broker startBroker(startAsync); brokerRegistry.bind(getBrokerName(), this); }
我们最关心的是启动broker
启动broker
startBroker(startAsync);
private void startBroker(boolean async) throws Exception { if(async) (new Thread("Broker Starting Thread") { public void run() { try { synchronized(persistenceAdapterStarted) { if(!persistenceAdapterStarted.get()) persistenceAdapterStarted.wait(); } doStartBroker(); } catch(Throwable t) { startException = t; } } final BrokerService this$0; { this$0 = BrokerService.this; super(x0); } }).start(); else //关键点 doStartBroker(); } //启动broker private void doStartBroker() throws Exception { if(startException != null) return; //启动目的地 startDestinations(); //添加关闭hook addShutdownHook(); broker = getBroker(); brokerId = broker.getBrokerId(); broker.start(); if(isUseJmx()) { if(getManagementContext().isCreateConnector() && !getManagementContext().isConnectorStarted()) { managementContext.stop(); //启动管理器上下文 startManagementContext(); } ManagedRegionBroker managedBroker = (ManagedRegionBroker)regionBroker; managedBroker.setContextBroker(broker); adminView.setBroker(managedBroker); } if(ioExceptionHandler == null) setIoExceptionHandler(new DefaultIOExceptionHandler()); if(isUseJmx() && Log4JConfigView.isLog4JAvailable()) { ObjectName objectName = BrokerMBeanSupport.createLog4JConfigViewName(getBrokerObjectName().toString()); Log4JConfigView log4jConfigView = new Log4JConfigView(); AnnotatedMBean.registerMBean(getManagementContext(), log4jConfigView, objectName); } //开启所有连接 startAllConnectors(); getBroker().brokerServiceStarted(); checkSystemUsageLimits(); //启动信号 startedLatch.countDown(); getBroker().nowMasterBroker(); }
开启所有连接
startAllConnectors();
public void startAllConnectors() throws Exception { Set durableDestinations = getBroker().getDurableDestinations(); List al = new ArrayList(); TransportConnector connector; //启动连接监听startTransportConnector(connector) for(Iterator iter = getTransportConnectors().iterator(); iter.hasNext(); al.add(startTransportConnector(connector))) connector = (TransportConnector)iter.next(); if(al.size() > 0) { transportConnectors.clear(); setTransportConnectors(al); } slave = false; URI uri = getVmConnectorURI(); Map map = new HashMap(URISupport.parseParameters(uri)); map.put("async", "false"); uri = URISupport.createURIWithQuery(uri, URISupport.createQueryString(map)); if(!stopped.get()) { //初始化线程执行器 ThreadPoolExecutor networkConnectorStartExecutor = null; if(isNetworkConnectorStartAsync()) networkConnectorStartExecutor = new ThreadPoolExecutor(0, 2147483647, 10L, TimeUnit.SECONDS, new SynchronousQueue(), new ThreadFactory() { public Thread newThread(Runnable runnable) { Thread thread = new Thread(runnable, (new StringBuilder()).append("NetworkConnector Start Thread-").append(count++).toString()); thread.setDaemon(true); return thread; } int count; final BrokerService this$0; { this$0 = BrokerService.this; super(); count = 0; } }); //启动NetworkConnector for(Iterator iter = getNetworkConnectors().iterator(); iter.hasNext();) { final NetworkConnector connector = (NetworkConnector)iter.next(); connector.setLocalUri(uri); connector.setBrokerName(getBrokerName()); connector.setDurableDestinations(durableDestinations); if(getDefaultSocketURIString() != null) connector.setBrokerURL(getDefaultSocketURIString()); if(networkConnectorStartExecutor != null) networkConnectorStartExecutor.execute(new Runnable() { public void run() { try { BrokerService.LOG.info("Async start of {}", connector); connector.start(); } catch(Exception e) { BrokerService.LOG.error("Async start of network connector: {} failed", connector, e); } } final NetworkConnector val$connector; final BrokerService this$0; { this$0 = BrokerService.this; connector = networkconnector; super(); } }); else connector.start(); } if(networkConnectorStartExecutor != null) ThreadPoolUtils.shutdown(networkConnectorStartExecutor); ProxyConnector connector; for(Iterator iter = getProxyConnectors().iterator(); iter.hasNext(); connector.start()) connector = (ProxyConnector)iter.next(); JmsConnector connector; for(Iterator iter = jmsConnectors.iterator(); iter.hasNext(); connector.start()) connector = (JmsConnector)iter.next(); Service service; for(Iterator i$ = services.iterator(); i$.hasNext(); service.start()) { service = (Service)i$.next(); configureService(service); } } }
来看启动连接监听
启动连接监听
startTransportConnector(connector)
public TransportConnector startTransportConnector(TransportConnector connector) throws Exception { //设置连接broker connector.setBrokerService(this); //设置任务工厂 connector.setTaskRunnerFactory(getTaskRunnerFactory()); MessageAuthorizationPolicy policy = getMessageAuthorizationPolicy(); if(policy != null) connector.setMessageAuthorizationPolicy(policy); if(isUseJmx()) connector = registerConnectorMBean(connector); connector.getStatistics().setEnabled(enableStatistics); //启动连接 connector.start(); return connector; }
public class TransportConnector implements Connector, BrokerServiceAware { protected final CopyOnWriteArrayList connections;//连接信息 protected TransportStatusDetector statusDector; private BrokerService brokerService;//broker服务 private TransportServer server;//监听Server private URI uri; private BrokerInfo brokerInfo; private TaskRunnerFactory taskRunnerFactory;//任务工厂 private MessageAuthorizationPolicy messageAuthorizationPolicy; private DiscoveryAgent discoveryAgent; private final ConnectorStatistics statistics; private URI discoveryUri; private String name; private boolean disableAsyncDispatch; private boolean enableStatusMonitor; private Broker broker; private boolean updateClusterClients; private boolean rebalanceClusterClients; private boolean updateClusterClientsOnRemove; private String updateClusterFilter; private boolean auditNetworkProducers; //允许连接的最大消费者与生产者 private int maximumProducersAllowedPerConnection; private int maximumConsumersAllowedPerConnection; private PublishedAddressPolicy publishedAddressPolicy; private boolean allowLinkStealing; LinkedList peerBrokers;//peer public TransportConnector() { LOG = LoggerFactory.getLogger(org/apache/activemq/broker/TransportConnector); connections = new CopyOnWriteArrayList(); brokerInfo = new BrokerInfo(); statistics = new ConnectorStatistics(); enableStatusMonitor = false; updateClusterClients = false; updateClusterClientsOnRemove = false; auditNetworkProducers = false; maximumProducersAllowedPerConnection = 2147483647; maximumConsumersAllowedPerConnection = 2147483647; publishedAddressPolicy = new PublishedAddressPolicy(); peerBrokers = new LinkedList(); } }
从上面看初始化TransportConnector,就是初始化broker服务,允许连接的最大消费者与生产者等信息。
//启动连接
connector.start();
public void start() throws Exception { broker = brokerService.getBroker(); brokerInfo.setBrokerName(broker.getBrokerName()); brokerInfo.setBrokerId(broker.getBrokerId()); brokerInfo.setPeerBrokerInfos(broker.getPeerBrokerInfos()); brokerInfo.setFaultTolerantConfiguration(broker.isFaultTolerantConfiguration()); brokerInfo.setBrokerURL(broker.getBrokerService().getDefaultSocketURIString()); //设置Server接受连接监听器 getServer().setAcceptListener(new TransportAcceptListener() { public void onAccept(final Transport transport) { try { brokerService.getTaskRunnerFactory().execute(new Runnable() { public void run() { try { if(!brokerService.isStopping()) { //接受连接后,创建连接,启动连接,这个时候是不是 //与前面联系上了,当启动连接时,启动会话,启动 //会话执行器,通知消费者消费消息 Connection connection = createConnection(transport); connection.start(); } else { throw new BrokerStoppedException((new StringBuilder()).append("Broker ").append(brokerService).append(" is being stopped").toString()); } } } final Transport val$transport; final _cls1 this$1; { this$1 = _cls1.this; transport = transport1; super(); } }); } } final TransportConnector this$0; { this$0 = TransportConnector.this; super(); } }); getServer().setBrokerInfo(brokerInfo); //启动server getServer().start(); //slave发现代理 DiscoveryAgent da = getDiscoveryAgent(); if(da != null) { da.registerService(getPublishableConnectString()); da.start(); } if(enableStatusMonitor) { statusDector = new TransportStatusDetector(this); statusDector.start(); } } public TransportServer getServer() throws IOException, URISyntaxException { if(server == null) //设置Server setServer(createTransportServer()); return server; } 创建TransportServer protected TransportServer createTransportServer() throws IOException, URISyntaxException { if(brokerService == null) throw new IllegalArgumentException("You must specify the brokerService property. Maybe this connector should be added to a broker?"); else return TransportFactorySupport.bind(brokerService, uri); } //TransportFactorySupport //绑定broker服务于URI public static TransportServer bind(BrokerService brokerService, URI location) throws IOException { TransportFactory tf; //根据以前的文章这个应该很熟悉,TransportFactory获取工厂,实际为TcpTransportFactory tf = TransportFactory.findTransportFactory(location); if(brokerService != null && (tf instanceof BrokerServiceAware)) ((BrokerServiceAware)tf).setBrokerService(brokerService); TransportServer transportserver; if(brokerService != null) SslContext.setCurrentSslContext(brokerService.getSslContext()); //绑定地址 transportserver = tf.doBind(location); SslContext.setCurrentSslContext(null); return transportserver; Exception exception; exception; SslContext.setCurrentSslContext(null); throw exception; }
//TcpTransportFactory
public class TcpTransportFactory extends TransportFactory { ublic TransportServer doBind(URI location) throws IOException { TcpTransportServer server; Map options = new HashMap(URISupport.parseParameters(location)); //创建SOCKET工厂 ServerSocketFactory serverSocketFactory = createServerSocketFactory(); server = createTcpTransportServer(location, serverSocketFactory); //设置Server协议 server.setWireFormatFactory(createWireFormatFactory(options)); IntrospectionSupport.setProperties(server, options); Map transportOptions = IntrospectionSupport.extractProperties(options, "transport."); server.setTransportOption(transportOptions); //绑定Server server.bind(); return server; URISyntaxException e; e; throw IOExceptionSupport.create(e); }
再看TcpTransportServer
public class TcpTransportServer extends TransportServerThreadSupport implements ServiceListener { protected ServerSocket serverSocket;//ServerSocket protected SelectorSelection selector; protected int backlog; protected WireFormatFactory wireFormatFactory; protected final TcpTransportFactory transportFactory;//transportFactory protected long maxInactivityDuration; protected long maxInactivityDurationInitalDelay; protected int minmumWireFormatVersion; protected boolean useQueueForAccept; protected boolean allowLinkStealing; protected boolean trace; protected int soTimeout; protected int socketBufferSize;//缓存大小 protected int connectionTimeout;//连接超时时间 protected String logWriterName; protected boolean dynamicManagement; protected boolean startLogging; protected final ServerSocketFactory serverSocketFactory; protected BlockingQueue socketQueue;//socket的队列 protected Thread socketHandlerThread; protected int maximumConnections; protected AtomicInteger currentTransportCount;//连接数 public TcpTransportServer(TcpTransportFactory transportFactory, URI location, ServerSocketFactory serverSocketFactory) throws IOException, URISyntaxException { super(location); backlog = 5000; wireFormatFactory = new OpenWireFormatFactory(); maxInactivityDuration = 30000L; maxInactivityDurationInitalDelay = 10000L; useQueueForAccept = true; trace = false; soTimeout = 0; socketBufferSize = 65536; connectionTimeout = 30000; logWriterName = TransportLoggerSupport.defaultLogWriterName; dynamicManagement = false; startLogging = true; socketQueue = new LinkedBlockingQueue(); maximumConnections = 2147483647; currentTransportCount = new AtomicInteger(); this.transportFactory = transportFactory; this.serverSocketFactory = serverSocketFactory; } } 初始化TcpTransportServer就是,连接缓存大小,连接延时,协议格式化工厂,socketServer工厂等; 先看TcpTransportServer绑定 public void bind() throws IOException { URI bind = getBindLocation(); String host = bind.getHost(); host = host != null && host.length() != 0 ? host : "localhost"; InetAddress addr = InetAddress.getByName(host); try { //根据ip和port创建serverSocket serverSocket = serverSocketFactory.createServerSocket(bind.getPort(), backlog, addr); configureServerSocket(serverSocket); } }
再看启动server
getServer().start();
public class TcpTransportServer extends TransportServerThreadSupport implements ServiceListener
public abstract class TransportServerThreadSupport extends TransportServerSupport implements Runnable
public abstract class TransportServerSupport extends ServiceSupport implements TransportServer
看到ServiceSupport,实际调用的为doStart
//TransportServerThreadSupport
protected void doStart() throws Exception { LOG.info((new StringBuilder()).append("Listening for connections at: ").append(getConnectURI()).toString()); runner = new Thread(null, this, (new StringBuilder()).append("ActiveMQ Transport Server: ").append(toString()).toString(), stackSize); runner.setDaemon(daemon); runner.setPriority(9); runner.start(); }
同时启动TcpTransportServer线程
//TcpTransportServer
public void run() { //从serverSocket获取通道,java nio final ServerSocketChannel chan = serverSocket.getChannel(); if(chan != null) try { chan.configureBlocking(false); selector = SelectorManager.getInstance().register(chan, new org.apache.activemq.transport.nio.SelectorManager.Listener() { //通道选择器 public void onSelect(SelectorSelection sel) { try { SocketChannel sc = chan.accept(); if(sc != null) if(isStopped() || getAcceptListener() == null) sc.close(); else if(useQueueForAccept) socketQueue.put(sc.socket()); else handleSocket(sc.socket()); } catch(Exception e) { onError(sel, e); } } public void onError(SelectorSelection sel, Throwable error) { Exception e = null; if(error instanceof Exception) e = (Exception)error; else e = new Exception(error); if(!isStopping()) onAcceptError(e); else if(!isStopped()) { TcpTransportServer.LOG.warn("run()", e); onAcceptError(e); } } final ServerSocketChannel val$chan; final TcpTransportServer this$0; { this$0 = TcpTransportServer.this; chan = serversocketchannel; super(); } }); selector.setInterestOps(16); selector.enable(); } catch(IOException ex) { selector = null; } else do { if(isStopped()) break; Socket socket = null; try { //第一次,没有socket,则创建serverSocket socket = serverSocket.accept(); if(socket != null) if(isStopped() || getAcceptListener() == null) socket.close(); else if(useQueueForAccept) //将serverSocket添加socketQueue socketQueue.put(socket); else handleSocket(socket); } } while(true); } protected final void handleSocket(Socket socket) { boolean closeSocket = true; try { if(currentTransportCount.get() >= maximumConnections) throw new ExceededMaximumConnectionsException("Exceeded the maximum number of allowed client connections. See the 'maximumConnections' property on the TCP transport configuration URI in the ActiveMQ configuration file (e.g., activemq.xml)"); HashMap options = new HashMap(); options.put("maxInactivityDuration", Long.valueOf(maxInactivityDuration)); options.put("maxInactivityDurationInitalDelay", Long.valueOf(maxInactivityDurationInitalDelay)); options.put("minmumWireFormatVersion", Integer.valueOf(minmumWireFormatVersion)); options.put("trace", Boolean.valueOf(trace)); options.put("soTimeout", Integer.valueOf(soTimeout)); options.put("socketBufferSize", Integer.valueOf(socketBufferSize)); options.put("connectionTimeout", Integer.valueOf(connectionTimeout)); options.put("logWriterName", logWriterName); options.put("dynamicManagement", Boolean.valueOf(dynamicManagement)); options.put("startLogging", Boolean.valueOf(startLogging)); options.putAll(transportOptions); WireFormat format = wireFormatFactory.createWireFormat(); Transport transport = createTransport(socket, format); closeSocket = false; if(transport instanceof ServiceSupport) ((ServiceSupport)transport).addServiceListener(this); Transport configuredTransport = transportFactory.serverConfigure(transport, format, options); //连接监听器接受连接,创建连接,开启连接 getAcceptListener().onAccept(configuredTransport); currentTransportCount.incrementAndGet(); } }
在brokerService启动过程中有设置了连接监听器
public void start() throws Exception { broker = brokerService.getBroker(); brokerInfo.setBrokerName(broker.getBrokerName()); brokerInfo.setBrokerId(broker.getBrokerId()); brokerInfo.setPeerBrokerInfos(broker.getPeerBrokerInfos()); brokerInfo.setFaultTolerantConfiguration(broker.isFaultTolerantConfiguration()); brokerInfo.setBrokerURL(broker.getBrokerService().getDefaultSocketURIString()); //设置Server接受连接监听器 getServer().setAcceptListener(new TransportAcceptListener() { public void onAccept(final Transport transport) { try { brokerService.getTaskRunnerFactory().execute(new Runnable() { public void run() { try { if(!brokerService.isStopping()) { //接受连接后,创建连接,启动连接,这个时候是不是 //与前面联系上了,当启动连接时,启动会话,启动 //会话执行器,通知消费者消费消息 Connection connection = createConnection(transport); connection.start(); } } } }
//TransportConnector
protected Connection createConnection(Transport transport) throws IOException { TransportConnection answer = new TransportConnection(this, transport, broker, disableAsyncDispatch ? null : taskRunnerFactory, brokerService.getTaskRunnerFactory()); boolean statEnabled = getStatistics().isEnabled(); answer.getStatistics().setEnabled(statEnabled); answer.setMessageAuthorizationPolicy(messageAuthorizationPolicy); return answer; }
总结:
从activemq脚本,可以看出启动ActiveMQ实际是启动,bin文件夹下的其实activemq.jar包中有一个类为Main,这就是active的启动入口,Main主要是加载lib目录和ClassPath,初始化类加载器,委托给ShellCommand,由ShellCommand根据命令描述去执行,如果是Version和HELP,则打印信息,若是启动命令,则通过XBeanBrokerFactory创建BrokerService,这个过程主要利用的Spring的bean容器机制,然后启动BrokerService,主要启动持久化适配器,JMX连接,上下文关系器,最后启动所有网络连接,及TcpTransport连接,默认使用的是openwire:tcp,所以我们就看一下
TcpTransportServer,TcpTransportServer有TcpTransportFactory创建并配置OpenWire协议转换器,启动TcpTransportServer,就是从ServerSocketFactory获取ServerSocket,并绑定ip和port,监听连接,并设置ServerSocket的监听器org.apache.activemq.transport.nio.SelectorManager.Listener,这个用的
是java nio。
public final class CommandContext { //activemq 命令输出格式工具 private OutputFormatter formatter; }
public interface OutputFormatter { public abstract OutputStream getOutputStream(); public abstract void printMBean(ObjectInstance objectinstance); public abstract void printMBean(ObjectName objectname); public abstract void printMBean(AttributeList attributelist); public abstract void printMBean(Map map); public abstract void printMBean(Collection collection); public abstract void printMessage(Map map); //打印消息 public abstract void printMessage(Message message); public abstract void printMessage(Collection collection); //打印帮助信息 public abstract void printHelp(String as[]); public abstract void printInfo(String s); public abstract void printException(Exception exception); public abstract void printVersion(String s); public abstract void print(Map map); public abstract void print(String as[]); public abstract void print(Collection collection); public abstract void print(String s); }
//SelectorManager
public final class SelectorManager { public static final SelectorManager SINGLETON = new SelectorManager(); private Executor selectorExecutor; private Executor channelExecutor; private final LinkedList freeWorkers = new LinkedList(); private int maxChannelsPerWorker; public static interface Listener { public abstract void onSelect(SelectorSelection selectorselection); public abstract void onError(SelectorSelection selectorselection, Throwable throwable); } public SelectorManager() { selectorExecutor = createDefaultExecutor(); channelExecutor = selectorExecutor; maxChannelsPerWorker = 1024; } protected ExecutorService createDefaultExecutor() { ThreadPoolExecutor rc = new ThreadPoolExecutor(getDefaultCorePoolSize(), getDefaultMaximumPoolSize(), getDefaultKeepAliveTime(), TimeUnit.SECONDS, new SynchronousQueue(), new ThreadFactory() { public Thread newThread(Runnable runnable) { i++; Thread t = new Thread(runnable, (new StringBuilder()).append("ActiveMQ NIO Worker ").append(i).toString()); return t; } private long i; final SelectorManager this$0; { this$0 = SelectorManager.this; super(); i = 0L; } }); return rc; } private static int getDefaultCorePoolSize() { return Integer.getInteger("org.apache.activemq.transport.nio.SelectorManager.corePoolSize", 0).intValue(); } private static int getDefaultMaximumPoolSize() { return Integer.getInteger("org.apache.activemq.transport.nio.SelectorManager.maximumPoolSize", 2147483647).intValue(); } private static int getDefaultKeepAliveTime() { return Integer.getInteger("org.apache.activemq.transport.nio.SelectorManager.keepAliveTime", 30).intValue(); } public static SelectorManager getInstance() { return SINGLETON; } public synchronized SelectorSelection register(AbstractSelectableChannel selectableChannel, Listener listener) throws IOException { SelectorSelection selection; for(selection = null; selection == null;) if(freeWorkers.size() > 0) { SelectorWorker worker = (SelectorWorker)freeWorkers.getFirst(); if(worker.isReleased()) { freeWorkers.remove(worker); } else { worker.retain(); selection = new SelectorSelection(worker, selectableChannel, listener); } } else { SelectorWorker worker = new SelectorWorker(this); freeWorkers.addFirst(worker); selection = new SelectorSelection(worker, selectableChannel, listener); } return selection; } synchronized void onWorkerFullEvent(SelectorWorker worker) { freeWorkers.remove(worker); } public synchronized void onWorkerEmptyEvent(SelectorWorker worker) { freeWorkers.remove(worker); } public synchronized void onWorkerNotFullEvent(SelectorWorker worker) { freeWorkers.addFirst(worker); } public Executor getChannelExecutor() { return channelExecutor; } public void setChannelExecutor(Executor channelExecutor) { this.channelExecutor = channelExecutor; } public int getMaxChannelsPerWorker() { return maxChannelsPerWorker; } public void setMaxChannelsPerWorker(int maxChannelsPerWorker) { this.maxChannelsPerWorker = maxChannelsPerWorker; } public Executor getSelectorExecutor() { return selectorExecutor; } public void setSelectorExecutor(Executor selectorExecutor) { this.selectorExecutor = selectorExecutor; } }
发表评论
-
Spring与ActiveMQ的集成详解二
2017-01-03 10:07 2084JMS(ActiveMQ) PTP和PUB/SUB模 ... -
Spring与ActiveMQ的集成详解一
2017-01-02 17:19 4592JMS(ActiveMQ) PTP和PUB/SUB模式实例:h ... -
ActiveMQ Broker发送消息给消费者过程详解
2017-01-02 15:30 6283JMS(ActiveMQ) PTP和PUB/SUB模 ... -
ActiveMQ消费者详解
2017-01-01 14:38 8667JMS(ActiveMQ) PTP和PUB/SUB模式实例:h ... -
ActiveMQ生产者详解
2017-01-01 12:29 6867JMS(ActiveMQ) PTP和PUB/SUB模式实例:h ... -
ActiveMQ会话初始化详解
2016-12-31 20:26 4784JMS(ActiveMQ) PTP和PUB/SUB模 ... -
ActiveMQ连接工厂、连接详解
2016-12-29 16:09 12044JMS(ActiveMQ) PTP和PUB/SUB模式实例:h ... -
基于LevelDB的高可用ActiveMQ集群
2016-12-28 18:34 4284ActiveMQ实现负载均衡+高可用部署方案:http://w ... -
ActiveMQ 目录配置文件
2016-12-28 12:47 7795下载apache-activemq-5.12.1.tar.gz ... -
Spring与ActiveMQ的集成
2016-12-27 18:09 1727JMS与MQ详解:http://www.fx114.net/q ... -
ActiveMQ PTP模式实例二
2016-12-27 14:45 698这篇主要是测试PTP模式下的回复消息,具体测试代码如下: 队列 ... -
JMS(ActiveMQ) PTP和PUB/SUB模式实例
2016-12-27 09:02 3125深入浅出JMS(一)——JMS简介 :http://blog. ...
相关推荐
### ActiveMQ消息服务配置详解 #### 一、ActiveMQ配置概览 ActiveMQ是一款非常流行的开源消息中间件,它基于Java开发,支持多种消息传递模式,如点对点(P2P)、发布/订阅(Pub/Sub)等。本文将详细介绍ActiveMQ的配置...
### ActiveMQ 快速上手知识点详解 #### 一、ActiveMQ简介 - **定义**:ActiveMQ 是 Apache 软件基金会所研发的一款开源消息中间件,它完全支持 JMS 1.1 和 J2EE 1.4 规范,能够作为 JMS Provider 实现消息传递功能...
### ActiveMQ集群安装与部署详解 #### 一、概述 ActiveMQ是一款开源的消息中间件,支持多种消息协议,包括AMQP、STOMP等,并且具备丰富的特性如持久化消息存储、事务支持等。在分布式系统中,为了提高系统的可用性...
### Zookeeper与ActiveMQ整合详解 #### 一、概述 在分布式系统中,为了提高系统的稳定性和可用性,通常会采用多种技术手段来确保服务的持续运行。Zookeeper与ActiveMQ的整合是一种常见且有效的方法,它通过...
**Spring整合ActiveMQ详解** Spring框架是Java领域中极为重要的应用开发框架,它提供了一整套的工具和服务,使得开发者可以轻松地构建可维护、可扩展的应用程序。而ActiveMQ则是Apache软件基金会的一个开源项目,它...
1. **部署**:将activemq-ra-3.1-M3.jar放入应用服务器的lib目录,如`$APP_SERVER_HOME/lib`,确保服务器启动时能加载到这个库。 2. **配置**:在应用服务器的资源适配器配置文件(如WebLogic的`weblogic-ejb-jar....
### 组件搭建与调试知识点详解 #### 一、Zookeeper 集群搭建与调试 **1.1 Zookeeper 概述** Zookeeper 是一个分布式协调服务,它为分布式应用提供一致性服务,包括命名服务、配置管理、集群管理等功能。在大数据...
### ActiveMQ教程与配置详解 #### 一、ActiveMQ简介 **ActiveMQ**是目前最受欢迎且功能强大的开源消息中间件之一。它完全遵循了JMS 1.1和J2EE 1.4规范,这使得它能够在各种企业级应用程序中发挥重要作用。尽管JMS...
### Linux部署分布式微服务架构详解 #### 一、概述 随着云计算和大数据技术的发展,分布式系统已成为企业级应用开发的标准模式。在Linux环境下部署分布式微服务架构不仅可以利用Linux系统的稳定性和安全性,还能...
### CentOS环境下AMQ集群与Zookeeper集群安装配置详解 #### 一、概述 本文将详细介绍如何在CentOS环境中安装配置ActiveMQ (AMQ) 集群和Zookeeper集群。这两种集群技术对于分布式系统的消息传递和服务协调至关重要...
2. **启动Zookeeper**:运行`zookeeper-3.4.6\bin`目录下的`zkServer.cmd`或`zkServer.sh`脚本启动服务。 3. **配置Dubbox**:Dubbox可以通过配置文件指定Zookeeper的地址,如上文所示。 #### 五、标准的JMS实现...
### Linux发版流程详解 #### 一、概述 在Linux环境下进行软件版本发布时,通常会涉及一系列标准化的操作步骤来确保发布的稳定性和高效性。本文将详细介绍一个具体的Linux发版流程,包括部署前的准备工作、应用程序...
- **安装ActiveMQ**:下载并安装ActiveMQ,通过运行`activeMQ.bat`启动服务。如果一切正常,不应该遇到任何错误。 - **安装Tomcat**:根据实际情况选择合适的版本进行安装。对于BigBlueButton的部署来说,Tomcat是...
4. 网络协议和服务框架:需要掌握HTTPServer、Gateway、SEDA原理,以及Netty的启动和执行过程、服务端和客户端的使用方式、事件驱动线程模型、Netty技术原理、NIO技术常见的API等。 5. 性能优化:包括内存管理、...
- **启动服务**:`./rabbitmq-server –detached` - **查看服务状态**:`./rabbitmqctl status` - **关闭服务**:`./rabbitmqctl stop` - **命令帮助**:`./rabbitmqctl –help` ##### RabbitMQ配置文件路径 - **...
### Puppet资源service详解 Puppet是一种强大的自动化工具,主要用于配置管理和部署。在Puppet中,`service`资源类型被用来管理各种系统服务的状态。本文将详细介绍`service`资源的使用方法,并通过具体案例来加深...
- 此外,还需要确保环境中已经安装了其他必要的组件,如Tomcat、ZooKeeper、ActiveMQ等。 - **启动与停止** - 启动Mycat:进入Mycat的bin目录,执行`./mycat start`命令。 - 停止Mycat:同样在bin目录下,执行`....
Spring Boot是Spring框架的一个子项目,旨在简化Spring应用的初始搭建以及开发过程。它通过提供默认配置来帮助开发者快速创建一个可运行的独立应用。下面将详细阐述Spring Boot的核心概念、优势、常用特性以及实际...