Red5总结

Red5简介
  Red5的主要功能和Macromedia公司的FMS类似,提供基于Flash的流媒体服务的一款基于Java的开源流媒体服务器。它由Java语言编写,使用RTMP作为流媒体传输协议,这与FMS完全兼容。它具有流化FLV、MP3文件,实时录制客户端流为FLV文件,共享对象,实时视频播放、Remoting等功能。用Red5替换FMS后,客户端不用更改可正常运行。

以下资料转载来源 http://www.cnblogs.com/QQingdou/archive/2010/10/19/1855766.html

前一段时间公司鉴于首页不错的流量,希望增加一些格外的收入或者做些视频推广,需要增加一个FLASH流媒体服务器播放视频,本来对于做C#.NET我来说,这个项目应该不是我来接的,最后可能是各位博友想的那样,"梦里花落知多少" 落到了我的怀里,‘杯具’还是这样发生了。

      Red5的主要功能和Macromedia公司的FMS类似,提供基于Flash的流媒体服务的一款基于Java的开源流媒体服务器。它由Java语言编写,使用RTMP作为流媒体传输协议,这与FMS完全兼容。它具有流化FLV、MP3文件,实时录制客户端流为FLV文件,共享对象,实时视频播放、Remoting等功能。用Red5替换FMS后,客户端不用更改可正常运行。 

      Red5竟然是用JAVA编写,我.NET,  无语了,那么用FMS吧,对于一个试用型项目,几千元的RMB似乎不可能,只能硬着头皮继续研究Red5。

      准备工作:

       一、JAVA环境配置:

           下载的JDK安装包,我选择的是jdk-6u10-rc2-bin-b32-windows-i586-p-12_sep_2008.exe,参考地址http://aben328.javaeye.com/blog/341499

       二、确认你的安装环境并选择RED5安装包:

            如果是Windows操作系统,可以下载对应的安装文件Red5 0.9.0 Final (27 January 2010),不是最新的(不一定是最好的),也可以下载对应的源代码自己进行研究Source,其他的操作可以参考该页面http://code.google.com/p/red5/

      准备工作完成,一切就绪。

      安装工作:

         步骤一:首先安装上面下载的JDK安装包(备注:如果你先安装RED5,会提示找不到JDK,你必须先完成步骤一在继续以下操作),安装时首先会安装JDK,必须记住安装路径,保持默认即可,默认是C:\Program Files\Java\jdk1.6.0_10,然后安装JRE,保持默认即可,默认是C:\Program Files\Java\jre6,安装完成后,必须配置环境变量,我的电脑-->属性-->高级 选项卡-->环境变量(N)-->找到 系统变量(S) 下 新建(W),然后输入 变量名(N):JAVA_HOME,变量值(V):上面JDK安装路径C:\Program Files\Java\jdk1.6.0_10,确定即可,JDK准备就绪。

         步骤二:安装RED5,安装RED5时,会要求输入外网可访问的IP,比如101.23.45.67,然后输入可访问的端口(Port),一般是5080,最后安装完成即可。

     测试工作:

          a) 一切安装就绪,现在应该体验一下RED5的真实面目了,首先启动RED5服务:重启电脑然后 我的电脑-->系统服务-->启动 RED5服务 或者 直接在安装目录下找到Red5.bat启动即可,接着在IE输入http://101.23.45.67:5080/,(你刚刚输入的IP地址和Port),没有忘吧,回车进行测试,

     会出现RED5欢迎页面,如果出现以下页面,说明RED5安装成功,如果不成功,请确认IP是否正确和可访问,Port是否正确且没有被占用。

         b)安装 DEMO

        点击 Install,进入安装页面,连接成功出现一下页面:

        

 

       选中要安装的 DEMO,然后点击 Install即可,比如说 SOSample。

       返回上个页面,点击 DEMO连接进行测试,然后点击上一步安装的DEMO,比如Shares Ball 的 View demo,进行测试,注意必须把rtmp://localhost/SOSample 改为 rtmp://101.23.45.67/SOSample,点击Connect TO Red5按钮,右边会变成绿色,否则请检查是否连接成功。在不同页面进行同样操作,如果拉动其中一个的页面的red5图标, 另外一个页面的RED5图标也按照相同轨迹移动,说明安装RED5成功。

 

       配置站点:

       打开RED5的安装目录下的webapps目录,新建自己需要的目录,如MyStream,r然后复制SOSample下的全部文件到MyStream,修改两个文件:

      一、red5-web.properties

              webapp.contextPath=/MyStream

      二、web.xml

             <param-value>/FlvStream</param-value>

      保存即可。

     下一步在MyStream目录下放置.FLV文件的即可。重启服务

      

        RTMP服务测试:

        下载 RTMP播放器测试 http://www.longtailvideo.com/players/jw-flv-player/,配置playlist.xml,将

      <location>rtmp://101.23.45.67/MyStream</location>
      <identifier>FileName</identifier>//你FLV文件名称,不需要扩展名 

      OK,IE浏览mediaplayer.html 文件,出现视频播放,恭喜你,一切成功!更多介绍,请详见参考资料。

 

  

      参考资料


http://osflash.org/red5
http://code.google.com/p/red5/
http://labs.influxis.com/?p=47
http://developer.longtailvideo.com/trac/wiki/Player5FlashVars



完整的Red5 0.8在线录制音\视频示例代码

环境:RED5 0.8 WIN 安装版 ECLIPSE GALILEO 版 ACTIONSCRIPT 3.0

项目名称:webcam

----------------------------------------------------------------------------------------------

一、配置文件

1、red5-web.properties

配置内容:

webapp.contextPath=/webcam
webapp.virtualHosts=localhost, 127.0.0.1

2、red5-web.xml

配置内容:

默认的配置内容只需要改动一处即可:
<bean id="web.handler" 
     class="red5.Application" 
   singleton="true" />

注意:red5.Application 是我定义的应用类包路径,要与JAVA代码对应

3、web.xml

默认的配置内容只需要改动一下上下文名称即可

<context-param>
   <param-name>webAppRootKey</param-name>
   <param-value>/webcam</param-value>
</context-param>

注意:上下文名称是你的项目名也是发布路径

二、JAVA应用代码:

package red5;

import org.red5.server.adapter.MultiThreadedApplicationAdapter;
import org.red5.server.api.IConnection;
import org.red5.server.api.IScope;
import org.red5.server.api.Red5;

import org.red5.server.stream.ClientBroadcastStream;

public class Application extends MultiThreadedApplicationAdapter {
        
        //create a instance for application
        public Application app;
        public IConnection conn;
        public IScope scope;
        public ClientBroadcastStream stream;//用来接受flash上传的stream的类

        //start the recording

        //客户端call这个function要传入流的名字
        public String startRecord(String streamName){
           //start a new recording
           String fileName = String.valueOf(System.currentTimeMillis());
                app = new Application();
                conn = Red5.getConnectionLocal();//得到当前的连接
                scope = conn.getScope();//一组连入服务器的客户
                app.connect(conn,scope,null);
                System.out.println("connection Established!");
                //注意stream name,在flash端也需要匹配
                stream = (ClientBroadcastStream)app.getBroadcastStream(scope,streamName);
                System.out.println("The publisher's name is: "+stream.getPublishedName()+", created at: "+stream.getCreationTime());
                System.out.println("the stream Name is: "+fileName);
                try{
                        stream.saveAs(fileName, false);
                }catch (Exception e){
                        System.out.println(e.toString());
                }
                return fileName;
        }
        
        //stop the recording
        public String stopRecord(){
                stream.stopRecording();//停止记录

                System.out.println("byte Recieved: "+stream.getBytesReceived());
                System.out.println("Recording Stopped!");
                return "Server stop recording!";
        }

}

三、Actionscript 3.0 代码

import flash.display.MovieClip;
import flash.events.*;
import flash.media.Camera;
import flash.media.Microphone;

import flash.media.Video;
import flash.media.SoundCodec;
import flash.net.NetStream;
import flash.net.NetConnection;
import flash.display.StageAlign;
import flash.display.StageScaleMode;

var resp:Responder=new Responder(onResult);
var _video:Video;
var _cam:Camera;
var _mic:Microphone;
var _nc:NetConnection;
var _ns:NetStream;


stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
createChildren();
initConn();


function createChildren():void {
_cam=Camera.getCamera();
_cam.setQuality(144000, 85);
_cam.setMode(320, 240, 15);
_cam.setKeyFrameInterval(60);
_video=new Video();
_video.attachCamera(_cam);
addChild(_video);
_mic=Microphone.getMicrophone();
if(_mic != null){   
_mic.setSilenceLevel(0,-1);   
_mic.gain = 80;
_mic.setLoopBack(true);
}
}

function initConn():void{
_nc=new NetConnection();
_nc.objectEncoding = ObjectEncoding.AMF3;
_nc.client=this;
_nc.addEventListener(NetStatusEvent.NET_STATUS , netStatus);
_nc.connect("rtmp://localhost/webcam/",true);
}

function publish():void {
if(_nc.connected){
_ns=new NetStream(_nc);
_ns.addEventListener(NetStatusEvent.NET_STATUS , netStatus);
_ns.attachCamera(_cam);
_ns.attachAudio(_mic);
_ns.publish("mystream", "live");
}
}

function netStatus (event:NetStatusEvent):void{
if ( event.info.code == "NetConnection.Connect.Success"){
   publish();
}
}
function onResult(obj:Object):void{
   ;
}

b_start.addEventListener(MouseEvent.CLICK,btStart);
function btStart(Event:MouseEvent){
_nc.call("startRecord",new Responder(getInfor,onState),"mystream");

}
function getInfor(reobj:Object):void {
trace("Server returning Infor: "+reobj);
}
function onState(err:Object):void {
trace("Connection result error: "+err);
}
b_stop.addEventListener(MouseEvent.CLICK,btStop);
function btStop(Event:MouseEvent){
_nc.call("stopRecord",new Responder(getInfor,onState));
}

注意:FLASH只有一桢,b_start 与b_stop是我用MC做的一个按钮的实例名称。一个开始录制一个停止录制.




red5 api之IScope接口的理解

IScope 接口定义了Red5中作用域对象.该对象维护了一个由一组客户端连接组成的上下文状态.通过作用域对象我们就可以很轻松的实现一个分级访问、区域对象的共享的功能.那么,对于一个作用域对象它可以有父作用域对象,也可以有子作用域对象.如果一个客户端连接到了一个作用域对象,同时也连接到了它的父作用域对象.通过作用域对象就可以访问资源、共享对象、视音频流等.作用域对象在应用程序中定义了一些组选项.


下面是作用域所有的名称application,room,place,lobby.
下面简单介绍一下IScope接口的方法
boolean addChildScope(IBasicScope scope)
描述添加一个子作用域.如果添加成功返回True,如果添加的子作用域已经是该作用域的子作用域,那么返回False.
参数scope 一个子作用域对象.
返回值True添加成功,False添加失败,添加的子作用域已经是该作用域的子作用域.

boolean connect(IConnection conn)
描述添加一个连接对象.
参数conn一个连接对象.
返回值True表示成功,如果该连接对象已经属于该作用域对象则返回False.
boolean connect(IConnection conn,Object[] params)
描述添加一个连接对象,并传入相应的参数对象.
参数conn连接对象.
params参数对象.
返回值True表示成功.如果该连接对象已经属于该作用域对象则返回False.
boolean createChildScope(String name)
描述通过一个字符串名称创建一个子作用域对象.成功返回True,如果该子对象已经存在本作用域中,则返回False.
参数name 子作用域的名称.
返回值True表示创建成功.如果该子对象已经存在本作用域中,则返回False.
void disconnect(IConnection conn)
描述从该作用域对象的连接对象列表中删除一个指定的连接对象.这样就会把所有提供该连接对象的客户端和本作用域断开连接.
参数提供的连接对象..
IBasicScope getBasicScope(String type,String name)
描述获得一个子作用域对象.
参数type子作用域的类型.
name子作用域的名称.
返回值如果指定子作用域对象存在返回该对象,否则返回Null.
IteratorString getBasicScopeNames(String type)
描述获得所有指定类型的子作用域.
参数类型名称.
返回值返回一个范型的迭代器,通过该迭代器可以获得所有子作用域对象.
SetIClient getClients()
描述返回当前作用域对象中所有子作用域对象的范型集合.
返回值所有子作用域对象的范型集合.
IteratorIConnection getConnections()
描述获得本作用域所有连接对象的范型迭代器.
返回值连接对象迭代器.
IContext getContext()
描述返回本作用域上下文环境.
返回值返回本作用域上文对象.
String getContextPath()
描述返回上下文路径.
返回值上下文路径.
IScopeHandler getHandler()
描述获得该作用域对象的控制器对象.
返回值作用域的控制器对象.
IScope getScope(String name)
描述通过名称获得作用域对象.
参数name 作用域对象名称.
返回值指定名称的作用域对象.
IteratorString getScopeNames()
描述获得所有子作用域的名称迭代器.
返回值子作用域名称迭代器.
boolean hasChildScope(String name)
描述判断当前作用域是否有指定名称的子作用域.
参数name 子作用域的名称.
返回值如果存在返回True,反之返回False.
boolean hasChildScope(String type, String name)
描述通过指定类型和名称判断当前作用域是否有指定名称的子作用域.
参数type 子作用域的类型.
name 子作用域的名称.
返回值如果存在返回True,反之返回False.
boolean hasHandler()
描述判断该作用域是否存在控制器.
返回值存在返回True,反之返回False.
SetIConnection lookupConnections(IClient client)
描述通过客户端对象,查找连接对象.
返回值返回只读的连接对象集合的迭代器.
void removeChildScope(IBasicScope scope)
描述删除指定的子作用域.
参数子作用域对象.

red5的常用方法

在使用red5+flash做rpg游戏开发的时候有些功能是需要服务器来提供的,如最简单的多人用户上线,当一个用户上线后后要通知所有其他的用户,这个时候就需要red5去获取所用链接的客户端,然后通知客户端用户上线。当用户下线的时候,也是同样的需要red5的支持。 我在开发的时候是使用red5 0.8的版本。 下面详细介绍一下具体的实现。 ApplicationAdapter是客户端与red5连接的基础 ...
在使用red5+flash做rpg游戏开发的时候有些功能是需要服务器来提供的,如最简单的多人用户上线,当一个用户上线后后要通知所有其他的用户,这个时候就需要red5去获取所用链接的客户端,然后通知客户端用户上线。当用户下线的时候,也是同样的需要red5的支持。 
我在开发的时候是使用red5 0.8的版本。 
下面详细介绍一下具体的实现。 
ApplicationAdapter是客户端与red5连接的基础类: 
下面来介绍一下调用的顺序,和建立so的方法。 
第一步: 
RED5服务器启动后,开始加载,此时只能获取应用的SCOPE 
public boolean appStart(IScope arg0) { 
       this.createSharedObject(arg0, "point", true); 
ISharedObject so = this.getSharedObject(arg0, "point");//建立一个so 
if (so != null) 
so.addSharedObjectListener(new ShareObjectListener()); 
       return true; 

改方法中的ShareObjectListener监听器是一个需要实现ISharedObjectListener接口的类。这样就建立一个so了。 
第二步:

响应连接处理,可获取当前connection的信息,并且可以接收客户端提供的参数

public boolean appConnect(IConnection conn, Object[] params){ 
       return true; 
}

第三步:连接成功,此时可获取client信息和SCOPE信息 
public boolean appJoin(IClient client, IScope app){ 
       return true; 

@Override 
public boolean roomStart(IScope arg0) { 
System.out.println(" 启动roomStart"); 
return true; 

如果需要获取每一个room中的客户端连接。 
@Override 
public boolean roomConnect(IConnection arg2, Object[] arg1) { 
         IScope arg0 = arg2.getScope(); 
         Set<IClient> i = arg0.getClients(); 
for (IClient c : i) { 
callClient(c.getConnections().iterator().next()); 

return true; 

public void callClient(IConnection conn) { 
        if (conn instanceof IServiceCapableConnection) { 
IServiceCapableConnection sc = (IServiceCapableConnection) conn; 
sc.invoke("resultFun",new Object[]{peopleArray},this); 
         } 

最后一步:

客户端浏览器关闭即退出应用。

public void appDisconnect(IConnection conn) { 
        return; 

 



转几篇Red5的日志配置

按这几篇文章配置,基本上就能搞定了。

一、第一篇中文的,开始。。。。

首先不能完全 按照log4j的配置去搞log4j.properties,因为他们是用 log4j+slf4j 搞在一起的

在 classes下面要有个logback-myapp.xml的文件,里面配置

<?xml version=”1.0″ encoding=”UTF-8″?>
<configuration>
    <appender name=”RED5DEMO” class=”ch.qos.logback.core.FileAppender”>
        <File>log/red5demo.log</File>
        <Append>false</Append>
        <Encoding>UTF-8</Encoding>
        <BufferedIO>false</BufferedIO>
        <ImmediateFlush>true</ImmediateFlush>
        <layout class=”ch.qos.logback.classic.PatternLayout”>
            <Pattern>
                %date [%thread] %-5level %logger{35} - %msg%n
            </Pattern>
        </layout>
    </appender>
    <root>
        <level value=”DEBUG” />
        <appender-ref ref=”RED5DEMO” />
    </root>       
    <logger name=”org.red5.demos.red5demo”>
        <level value=”DEBUG” />
    </logger>

</configuration>

重启red5 在 red5/log 下看到一个red5demo.log文件了。

二.再看另外一篇文章:

1、概述:
Red5起初使用的log4j日志系统,现在使用的是logback日志系统。
Ceki在Java日志领域世界知名。他创造了Log4J,这个最早的Java日志框架即便在JRE内置日志功能的竞争下
仍然非常流行。随后他又着手实现SLF4J这个“简单的日志前端接口(simple logging facade for java)”来替代JCL(Jakarta Commons-Logging)。这几年Ceki在从事他的新项目,LOGBack,一个“可靠、通用、快速而又灵活的Java日志框架”。
主要函数有:
package org.slf4j;
public interface Logger {
  // Printing methods:
  public void trace(String message);
  public void debug(String message);
  public void info(String message);
  public void warn(String message);
  public void error(String message);
}
主要日志级别有:TRACE DEBUG INFO WARN ERROR OFF 

2、Red5LoggerFactory类:
red5-svn\java\server\trunk\src\org\red5\logging\Red5LoggerFactory文件中定义了”Red5LoggerFactory”类。
它简化了获取日志实例的请求操作,在Red5应用程序中推荐使用。
public class Red5LoggerFactory {
  public static Logger getLogger(Class clazz) {
    String contextName = null;
    return getLogger(clazz, contextName);
  }
  public static Logger getLogger(Class clazz, String contextName) {
    …
  }
}
getLogger()是个重载函数。
*)如果只传递一个参数,则返回默认context的日志系统,即”red5.log”。
   Red5源码中一般都是调用第一个函数,如下所示:
   private static Logger log = Red5LoggerFactory.getLogger(TomcatLoader.class);
*)如果传递两个参数,则返回指定webapp context的日志系统,即”xxx.log”。
   Red5的应用程序一般都是调用第二个函数,如下所示:
   private static Logger log = Red5LoggerFactory.getLogger(Application.class, “oflaDemo”);

  (这里有一点要注意,xuggle的例子貌似调用的不对:
    final private Logger log = Red5LoggerFactory.getLogger(this.getClass());)

3、注意事项:
*)只要修改了web.xml文件,添加了日志侦听,就可生成指定的日志文件xxx.log。
*)logback-webapp.xml这个配置文件必要要放对位置,即jar打包文件的根目录或者class目录下。
   (否则即使生成了xxx.log文件,后续日志也无法写进去。)
*)java源程序里要正确返回指定的日志系统,即使用Red5LoggerFactory类的两个参数的getLogger函数。
   (否则返回的是Red5默认的日志系统,即写到red5.log文件里)

三、具体怎么用写日志,再看:

Logging Setup

The logging system uses Simple Logging Facade for Java ( SLF4J). This framework supports many of the logging systems available for Java and also provides simple implementations. The logging used by our dependencies are mainly Log4j and Apache commons logging and SLF4J allows us to combine them into one system. SLF4J gives you the ability to select a logging implementation and provides proxies for you dependencies if their maintainers did not select the same framework.

We prefer the  logback log implementation, but you may use whatever you like. There are some hoops you will have to jump through to get  Log4j or  Commons logging to work. Blog post about using other loggers here.

After you chose an implementation framework, some of the SLF4J jars must NOT be in your applications classpath or they will cause conflicts. The default case it to use Logback, so the following jars must be included:

slf4j-api - The core APIlogback-core - Current Logback core librarylogback-classic - Logback support librarylog4j-over-slf4j - Log4j proxy/bridgejcl-over-slf4j - Apache commons logging proxy/bridgejul-to-slf4j - java.util.logging proxy/bridge

The items denoted as “proxy/bridge” listen for the logging calls to those implementations and pass them through to SLF4J.

The following two strategies are to be consider untested.

If you prefer to use Log4j instead, the following jars are required:

slf4j-api - The core APIlog4j - Current Log4j library (1.2+)slf4j-log4j12 - Log4j adapterjcl-over-slf4j - Apache commons logging proxy/bridgejul-to-slf4j - java.util.logging proxy/bridge

If you prefer to use Commons logging the following jars are required:

slf4j-api - The core APIcommons-logging - Apache commons logging libraryslf4j-jcl - Commons logging adapterlog4j-over-slf4j - Log4j proxy/bridgejul-to-slf4j - java.util.logging proxy/bridge

If you want to use another implementation not shown here, simply check out the faq  SLF4J FAQ

Logback is the successor of Log4j and was created by the creator of Log4j and SLF4J. A conversion tool has been created for your log4j properties files  configuration converter There is also an eclipse console plugin eclipse console plugin.

Web applications

In your web applications remove the following entry from your web.xml

<context-param><param-name>log4jConfigLocation</param-name><param-value>/WEB-INF/log4j.properties</param-value></context-param>

Add the following to the web.xml

<listener><listener-class>org.red5.logging.ContextLoggingListener</listener-class></listener><filter><filter-name>LoggerContextFilter</filter-name><filter-class>org.red5.logging.LoggerContextFilter</filter-class></filter><filter-mapping><filter-name>LoggerContextFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

You should also:

Remove any “log4j” listeners from the web.xmlRemove any log4j.properties or log4j.xml filesCreate a logback-myApp.xml where myApp is the name for your webapp and place it on your webapp classpath (WEB-INF/classes or in your application jar within WEB-INF/lib)Set your display-name in the web application to match the context name you will be using (Use the example oflaDemo as a guide).Ensure that the contextName and jmxConfigurator have the correct context name, this is the name of your web application

Sample webapp logback config file (logback-myApp.xml), not to be confused with the red5 log config file located in /conf

<?xml version=”1.0″ encoding=”UTF-8″?><configuration><contextName>myApp</contextName><jmxConfiguratorcontextName=“myApp”/><appendername=“FILE”class=“ch.qos.logback.core.FileAppender”><File>example.log</File><Append>false</Append><BufferedIO>false</BufferedIO><ImmediateFlush>true</ImmediateFlush><layoutclass=“ch.qos.logback.classic.PatternLayout”><Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern></layout></appender><root><levelvalue=“DEBUG“/><appender-refref=“FILE”/></root><loggername=“com.example”><levelvalue=“DEBUG“/></logger></configuration>

Reminder replace everything that says “myApp” with your application name.

Imports

When using logback and slf4j, your imports should consist only of the following for a non webapp class:

importorg.slf4j.LoggerFactory;importorg.slf4j.Logger;

It is suggested that you use Red5LoggerFactory in-place of LoggerFactory to ensure that your application gets the correct logger.

For loggers inside your webapp imports should be:

importorg.slf4j.Logger;importorg.red5.logging.Red5LoggerFactory;

Logger Instantiation

For non webapp classes:

To log to a “root” logger, change all your logger instantiation statements to:

privatestaticLogger log=Red5LoggerFactory.getLogger(MyClassName.class);

Reminder replace “MyClassName” with the name of the class itself.

To log to a “context” logger, change all your logger instantiation statements to:

privatestaticLogger log=Red5LoggerFactory.getLogger(MyClassName.class,“myApp”);

Reminder replace “myApp” with the name of the context; “myApp” would become “oflaDemo” for the oflaDemo application.

Your old instantiations probably resemble this:

privatestaticLogger log=Logger.getLogger(MyClassName.class.getName());

Your applications logging configuration file must contain the name of your application context in its file name; For instance the “oflaDemo” uses the configuration logback-oflaDemo.xml.

Lastly, as an optimation change your log statements to:

log.debug(“Here is a log message for an object {}”, myobject);

You no longer need to concatenate strings when logging, if you need more than one variable do the following:

log.debug(“Here is a log message with a couple vars {} or {} or {}”,new Object[]{object1, myobject, object3});



red5 cluster 集群

red5的开发者真是太伟大了,把集群搞的这么平民化。

1. 下载red50.8

2. 修改一下build.xml ant dist-cluster

3. 把red5/home/cluster 的edge和origin 部署到你的edge和origin Server上。

比如2(2个edge)-2(2个origin),就需要4台机器

edge1

edge2

origin1(ip:origin1)

origin2(ip:origin2)

4. 修改edge Server上的

red5-edge-core.xml

把下面

<bean id="mrtmpClient"
   class="org.red5.server.net.mrtmp.MRTMPClient" init-method="start" >
   <property name="ioHandler" ref="mrtmpHandler" />
   <property name="server" value="${mrtmp.server}" />
   <property name="port" value="${mrtmp.port}" />
</bean>

修改为

<bean id="mrtmpClient"
   class="org.red5.server.net.mrtmp.MRTMPClient" init-method="start" >
   <property name="ioHandler" ref="mrtmpHandler" />
   <property name="server" value="${origin1}" />
   <property name="port" value="${mrtmp.port}" />
</bean>

<!-- 如果你只有3台机器 或只需要部署一个origin 请把下面这段注释掉就ok了 -->

<bean id="mrtmpClient2"
   class="org.red5.server.net.mrtmp.MRTMPClient" init-method="start" >
   <property name="ioHandler" ref="mrtmpHandler" />
   <property name="server" value="${origin2}" />
   <property name="port" value="${mrtmp.port}" />
</bean>

5. 启动你的2个origin和2个edge

6.测试你的集群是否成功

在origin机器上

开2个browser(浏览器)

http://localhost:5080/demos/BallControl.html

http://localhost:5080/demos/BallControl.html

把rtmp的ip分别改为 edge1的 和 edge2 的

移动那个球试试看。你一定会部署成功的。



收藏red5文章

Red相关

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值