red5流媒体服务器研究(1)——启动的秘密
如有转载,请注明出处,谢谢。
由于工作上面的需要,开始了对流媒体的研究。对于一个做了许久J2EE应用的人来说,关于流媒体的印象仅仅停留在边播边下载上(其实是点播),至于说到实时直播什么的一头雾水。。然后,找到了red5,看了licence,好吧,开源,java写的,果断开始研究。
下载RC版本,打开文件目录,跟tomcat的文件结构比较像,然后点开conf,大概超过20个配置文件,果断放一边,然后下载源代码,开始导入IDE。。。
打开red5.bat,第七行
if NOT DEFINED RED5_MAINCLASS set ED5_MAINCLASS=org.red5.server.Bootstrap
启动的入口应该就在org.red5.server.Bootstrap这里了。OK,开始读源码去。
打开源码文件的第一印象,注释写得很全,看起来应该没有太大的问题了,松了口气。
//retrieve path elements from system properties String root = getRed5Root(); getConfigurationRoot(root);
看到这个地方,以后编写java的可执行程序的时候,相关的jar包什么的看来不用去用shell脚本或者其他的脚本来管理了,可以在启动前开始加载。。
// create a new instance of this class using new classloader Object boot = Class.forName("org.red5.server.Launcher", true, loader).newInstance(); Method m1 = boot.getClass().getMethod("launch", (Class[]) null); m1.invoke(boot, (Object[]) null);
设置各种环境后真正的启动,从org.red5.server.Launcher开始
打开到org.red5.server.Launcher文件
//create red5 app context FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext(new String[] { "classpath:/red5.xml" }, false); //set the current threads classloader as the loader for the factory/appctx ctx.setClassLoader(Thread.currentThread().getContextClassLoader()); //refresh must be called before accessing the bean factory ctx.refresh();
直接采用spring进行加载, create red5 app context。
打开red5.xml配置文件
<!-- This file just wires together the context tree. Its accessed by ContextSingletonBeanFactoryLocator --> <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:/red5.properties" /> </bean> <!-- First we load the common context, its shared between all the other contexts --> <!-- Global context serves as the parent to all child contexts. --> <bean id="red5.common" class="org.springframework.context.support.FileSystemXmlApplicationContext"> <constructor-arg><list><value>classpath:/red5-common.xml</value></list></constructor-arg> </bean> <!-- Then we load the core context, with the common as parent --> <!-- Context holding all the networking, users should need to edit. --> <bean id="red5.core" class="org.springframework.context.support.FileSystemXmlApplicationContext"> <constructor-arg><list><value>classpath:/red5-core.xml</value></list></constructor-arg> <constructor-arg><ref bean="red5.common" /></constructor-arg> </bean> <!-- Then we load the global contexts, note its important this happens before app container loads --> <bean id="context.loader" class="org.red5.server.ContextLoader"> <property name="parentContext" ref="red5.common" /> <property name="contextsConfig" value="classpath:/red5.globals" /> <property name="useShutdownHook" value="false" /> </bean> <bean id="pluginLauncher" class="org.red5.server.plugin.PluginLauncher" /> <!-- Now we can load the JEE container / servlet engine --> <import resource="classpath:/jee-container.xml"/>
注释上写着:This file just wires together the context tree.按照个人习惯,打开red5-core.xml文件,看到第一行注释:<!-- This context holds all the networking: mina -->,里面应该包括了所有的关于mina,socket通信方面的内容。
<!-- RTMP Mina Transport --> <bean id="rtmpTransport" class="org.red5.server.net.rtmp.RTMPMinaTransport" init-method="start" destroy-method="stop"> <property name="ioHandler" ref="rtmpMinaIoHandler" /> <property name="connectors"> <list> <bean class="java.net.InetSocketAddress"> <constructor-arg index="0" type="java.lang.String" value="${rtmp.host}" /> <constructor-arg index="1" type="int" value="${rtmp.port}" /> </bean> <!-- You can now add additional ports and ip addresses <bean class="java.net.InetSocketAddress"> <constructor-arg index="0" type="java.lang.String" value="${rtmp.host}" /> <constructor-arg index="1" type="int" value="1936" /> </bean> --> </list> </property> <property name="ioThreads" value="${rtmp.io_threads}" /> <property name="tcpNoDelay" value="${rtmp.tcp_nodelay}" /> <!-- This is the interval at which the sessions are polled for stats. If mina monitoring is not enabled, polling will not occur. --> <property name="minaPollInterval" value="${jmx.mina.poll.interval}" /> <property name="enableMinaMonitor" value="${jmx.mina.monitor.enable}" /> </bean>
从配置上看,org.red5.server.net.rtmp.RTMPMinaTransport就是启动mina的地方了。
<!-- RTMP Mina IO Handler --> <bean id="rtmpMinaIoHandler" class="org.red5.server.net.rtmp.RTMPMinaIoHandler"> <property name="handler" ref="rtmpHandler" /> <property name="rtmpConnManager" ref="rtmpMinaConnManager" /> </bean>
启动mina后,关于数据上的处理,就在org.red5.server.net.rtmp.RTMPMinaIoHandler里面了。
mina的启动先放一放,根据red5的相关文档,其中有集成tomcat容器,从red5.xml文件中可看到
<!-- Now we can load the JEE container / servlet engine --> <import resource="classpath:/jee-container.xml"/>
所以,关于集成tomcat的地方,就在配置文件jee-container.xml文件中。
<bean id="tomcat.server" class="org.red5.server.tomcat.TomcatLoader" init-method="init" destroy-method="shutdown" depends-on="context.loader"> <property name="webappFolder" value="${red5.root}/webapps" /> <property name="connector"> <bean class="org.apache.catalina.connector.Connector"> <!-- Blocking I/O --> <constructor-arg type="java.lang.String" value="org.apache.coyote.http11.Http11Protocol" /> <!-- Non-blocking I/O --> <!-- <constructor-arg type="java.lang.String" value="org.apache.coyote.http11.Http11NioProtocol" /> --> <property name="port"><value>${http.port}</value></property> <property name="redirectPort"><value>${https.port}</value></property> <property name="enableLookups"><value>false</value></property> <property name="useIPVHosts"><value>true</value></property> <property name="URIEncoding"><value>${http.URIEncoding}</value></property> </bean> </property> <property name="address"> <bean class="java.net.InetSocketAddress"> <constructor-arg index="0" type="java.lang.String" value="${http.host}" /> <constructor-arg index="1" type="int" value="${http.port}" /> </bean> </property> <property name="baseHost"> <bean class="org.apache.catalina.core.StandardHost"> <property name="name" value="${http.host}" /> <property name="unpackWARs" value="true" /> <property name="autoDeploy" value="true" /> <property name="xmlValidation" value="false" /> <property name="xmlNamespaceAware" value="false" /> </bean> </property> <property name="valves"> <list> <bean id="valve.access" class="org.apache.catalina.valves.AccessLogValve"> <property name="directory" value="log" /> <property name="prefix" value="${http.host}_access." /> <property name="suffix" value=".log" /> <property name="pattern" value="common" /> <property name="resolveHosts" value="false" /> <property name="rotatable" value="true" /> </bean> </list> </property> </bean>
从上面的配置看,red5加载集成tomcat的主要入口就在org.red5.server.tomcat.TomcatLoader里面了,可惜源码包中没有这部分内容,在其他地方也没有找到,应该是不开源的一部分。
从配置的内容看,其主要包括 webappFolder 为发布应用的目录,相当于 tomcat中的webapp,其余部分都是http,https,baseHost等相关配置,相关内容在red5.properties文件中,可对应查找。
回到mina启动部分,根据配置的内容socket数据的处理入口在org.red5.server.net.rtmp.RTMPMinaIoHandler中
/** * Handles all RTMP protocol events fired by the MINA framework. */ public class RTMPMinaIoHandler extends IoHandlerAdapter implements ApplicationContextAware
。
下一章 red5流媒体服务器研究(二)——RTMP协议和数据解析