Red5のメモリー利用状況を確認してみる。オブジェクトの消失条件その2

Red5のオブジェクト消失条件を探ってみる。
ある意味動作検証でもあります。

この動作検証の結果としては、いまのところ問題はなかったです。

まず、コードから、
基本的なApplicationクラス(ApplicationAdapter継承)をつくって、様子をみます。
  1. package com.taktod.red5test;
  2.  
  3. import java.lang.ref.WeakReference;
  4. import java.util.HashMap;
  5. import java.util.Iterator;
  6. import java.util.Map;
  7.  
  8. import org.red5.server.adapter.ApplicationAdapter;
  9. import org.red5.server.api.IClient;
  10. import org.red5.server.api.IConnection;
  11. import org.red5.server.api.IScope;
  12. import org.red5.server.api.Red5;
  13. import org.red5.server.api.stream.IBroadcastStream;
  14.  
  15. /**
  16.  * Red5アプリケーション
  17.  * @author taktod
  18.  */
  19. public class Application extends ApplicationAdapter{
  20. private int connNum;
  21. private int scopeNum;
  22. private int clientNum;
  23. private Map<String, WeakReference<Object>> dataHolder;
  24. /**
  25. * アプリケーション
  26. */
  27. public Application() {
  28. dataHolder = new HashMap<String, WeakReference<Object>>();
  29. connNum = 0;
  30. scopeNum = 0;
  31. clientNum = 0;
  32. }
  33. /**
  34. * アプリケーションに接続したときの動作
  35. */
  36. @Override
  37. public boolean appConnect(IConnection conn, Object[] arg1) {
  38. if(conn.getAttribute("conn") == null) {
  39. connNum ++;
  40. Object o = new HoldData("conn" + connNum);
  41. conn.setAttribute("conn", o);
  42. dataHolder.put("conn" + connNum, new WeakReference<Object>(o));
  43. }
  44. IConnection conn2 = Red5.getConnectionLocal();
  45. if(conn2.getAttribute("conn") == null) {
  46. connNum ++;
  47. Object o = new HoldData("conn" + connNum);
  48. conn2.setAttribute("conn", o);
  49. dataHolder.put("conn" + connNum, new WeakReference<Object>(o));
  50. }
  51. System.out.println("appConnect conn:" + conn.getAttribute("conn") + " conn2:" + conn2.getAttribute("conn"));
  52. clearMap();
  53. return super.appConnect(conn, arg1);
  54. }
  55. /**
  56. * アプリケーションから切断したときの動作
  57. */
  58. @Override
  59. public void appDisconnect(IConnection conn) {
  60. if(conn.getAttribute("conn") == null) {
  61. connNum ++;
  62. Object o = new HoldData("conn" + connNum);
  63. conn.setAttribute("conn", o);
  64. dataHolder.put("conn" + connNum, new WeakReference<Object>(o));
  65. }
  66. IConnection conn2 = Red5.getConnectionLocal();
  67. if(conn2.getAttribute("conn") == null) {
  68. connNum ++;
  69. Object o = new HoldData("conn" + connNum);
  70. conn2.setAttribute("conn", o);
  71. dataHolder.put("conn" + connNum, new WeakReference<Object>(o));
  72. }
  73. System.out.println("appDisconnect conn:" + conn.getAttribute("conn") + " conn2:" + conn2.getAttribute("conn"));
  74. super.appDisconnect(conn);
  75. clearMap();
  76. }
  77. /**
  78. * アプリケーションに参加したときの動作?
  79. */
  80. @Override
  81. public boolean appJoin(IClient client, IScope scope) {
  82. if(client.getAttribute("client") == null) {
  83. clientNum ++;
  84. Object o = new HoldData("client" + clientNum);
  85. client.setAttribute("client", o);
  86. dataHolder.put("client" + clientNum, new WeakReference<Object>(o));
  87. }
  88. if(scope.getAttribute("scope") == null) {
  89. scopeNum ++;
  90. Object o = new HoldData("scope" + scopeNum);
  91. scope.setAttribute("scope", o);
  92. dataHolder.put("scope" + scopeNum, new WeakReference<Object>(o));
  93. }
  94. System.out.println("appJoin client:" + client.getAttribute("client") + " scope:" + scope.getAttribute("scope"));
  95. clearMap();
  96. return super.appJoin(client, scope);
  97. }
  98. /**
  99. * アプリケーションから離れたときの動作
  100. */
  101. @Override
  102. public void appLeave(IClient client, IScope scope) {
  103. if(client.getAttribute("client") == null) {
  104. clientNum ++;
  105. Object o = new HoldData("client" + clientNum);
  106. client.setAttribute("client", o);
  107. dataHolder.put("client" + clientNum, new WeakReference<Object>(o));
  108. }
  109. if(scope.getAttribute("scope") == null) {
  110. scopeNum ++;
  111. Object o = new HoldData("scope" + scopeNum);
  112. scope.setAttribute("scope", o);
  113. dataHolder.put("scope" + scopeNum, new WeakReference<Object>(o));
  114. }
  115. System.out.println("appLeave client:" + client.getAttribute("client") + " scope:" + scope.getAttribute("scope"));
  116. super.appLeave(client, scope);
  117. clearMap();
  118. }
  119. /**
  120. * アプリケーションがはじまったときの動作
  121. */
  122. @Override
  123. public boolean appStart(IScope scope) {
  124. if(scope.getAttribute("scope") == null) {
  125. scopeNum ++;
  126. Object o = new HoldData("scope" + scopeNum);
  127. scope.setAttribute("scope", o);
  128. dataHolder.put("scope" + scopeNum, new WeakReference<Object>(o));
  129. }
  130. System.out.println("appStart scope:" + scope.getAttribute("scope"));
  131. clearMap();
  132. return super.appStart(scope);
  133. }
  134. /**
  135. * アプリケーションが停止するときの動作
  136. */
  137. @Override
  138. public void appStop(IScope scope) {
  139. if(scope.getAttribute("scope") == null) {
  140. scopeNum ++;
  141. Object o = new HoldData("scope" + scopeNum);
  142. scope.setAttribute("scope", o);
  143. dataHolder.put("scope" + scopeNum, new WeakReference<Object>(o));
  144. }
  145. System.out.println("appStop scope:" + scope.getAttribute("scope"));
  146. super.appStop(scope);
  147. clearMap();
  148. }
  149. /**
  150. * ルームに接続するときの動作
  151. */
  152. @Override
  153. public boolean roomConnect(IConnection conn, Object[] arg1) {
  154. if(conn.getAttribute("conn") == null) {
  155. connNum ++;
  156. Object o = new HoldData("conn" + connNum);
  157. conn.setAttribute("conn", o);
  158. dataHolder.put("conn" + connNum, new WeakReference<Object>(o));
  159. }
  160. IConnection conn2 = Red5.getConnectionLocal();
  161. if(conn2.getAttribute("conn") == null) {
  162. connNum ++;
  163. Object o = new HoldData("conn" + connNum);
  164. conn2.setAttribute("conn", o);
  165. dataHolder.put("conn" + connNum, new WeakReference<Object>(o));
  166. }
  167. System.out.println("roomConnect conn:" + conn.getAttribute("conn") + " conn2:" + conn2.getAttribute("conn"));
  168. clearMap();
  169. return super.roomConnect(conn, arg1);
  170. }
  171. /**
  172. * ルームから切断するときの動作
  173. */
  174. @Override
  175. public void roomDisconnect(IConnection conn) {
  176. if(conn.getAttribute("conn") == null) {
  177. connNum ++;
  178. Object o = new HoldData("conn" + connNum);
  179. conn.setAttribute("conn", o);
  180. dataHolder.put("conn" + connNum, new WeakReference<Object>(o));
  181. }
  182. IConnection conn2 = Red5.getConnectionLocal();
  183. if(conn2.getAttribute("conn") == null) {
  184. connNum ++;
  185. Object o = new HoldData("conn" + connNum);
  186. conn2.setAttribute("conn", o);
  187. dataHolder.put("conn" + connNum, new WeakReference<Object>(o));
  188. }
  189. System.out.println("roomDisconnect conn:" + conn.getAttribute("conn") + " conn2:" + conn2.getAttribute("conn"));
  190. super.roomDisconnect(conn);
  191. clearMap();
  192. }
  193. /**
  194. * ルームに参加するときの動作?
  195. */
  196. @Override
  197. public boolean roomJoin(IClient client, IScope scope) {
  198. if(client.getAttribute("client") == null) {
  199. clientNum ++;
  200. Object o = new HoldData("client" + clientNum);
  201. client.setAttribute("client", o);
  202. dataHolder.put("client" + clientNum, new WeakReference<Object>(o));
  203. }
  204. if(scope.getAttribute("scope") == null) {
  205. scopeNum ++;
  206. Object o = new HoldData("scope" + scopeNum);
  207. scope.setAttribute("scope", o);
  208. dataHolder.put("scope" + scopeNum, new WeakReference<Object>(o));
  209. }
  210. System.out.println("roomJoin client:" + client.getAttribute("client") + " scope:" + scope.getAttribute("scope"));
  211. clearMap();
  212. return super.roomJoin(client, scope);
  213. }
  214. /**
  215. * ルームから離れるときの動作
  216. */
  217. @Override
  218. public void roomLeave(IClient client, IScope scope) {
  219. if(client.getAttribute("client") == null) {
  220. clientNum ++;
  221. Object o = new HoldData("client" + clientNum);
  222. client.setAttribute("client", o);
  223. dataHolder.put("client" + clientNum, new WeakReference<Object>(o));
  224. }
  225. if(scope.getAttribute("scope") == null) {
  226. scopeNum ++;
  227. Object o = new HoldData("scope" + scopeNum);
  228. scope.setAttribute("scope", o);
  229. dataHolder.put("scope" + scopeNum, new WeakReference<Object>(o));
  230. }
  231. System.out.println("roomLeave client:" + client.getAttribute("client") + " scope:" + scope.getAttribute("scope"));
  232. super.roomLeave(client, scope);
  233. clearMap();
  234. }
  235. /**
  236. * ルーム処理が始まったときの動作
  237. */
  238. @Override
  239. public boolean roomStart(IScope scope) {
  240. if(scope.getAttribute("scope") == null) {
  241. scopeNum ++;
  242. Object o = new HoldData("scope" + scopeNum);
  243. scope.setAttribute("scope", o);
  244. dataHolder.put("scope" + scopeNum, new WeakReference<Object>(o));
  245. }
  246. System.out.println("roomStart scope:" + scope.getAttribute("scope"));
  247. clearMap();
  248. return super.roomStart(scope);
  249. }
  250. /**
  251. * ルーム処理が終わったときの動作
  252. */
  253. @Override
  254. public void roomStop(IScope scope) {
  255. if(scope.getAttribute("scope") == null) {
  256. scopeNum ++;
  257. Object o = new HoldData("scope" + scopeNum);
  258. scope.setAttribute("scope", o);
  259. dataHolder.put("scope" + scopeNum, new WeakReference<Object>(o));
  260. }
  261. System.out.println("roomStop scope:" + scope.getAttribute("scope"));
  262. super.roomStop(scope);
  263. clearMap();
  264. }
  265. /**
  266. * 放送停止イベント
  267. */
  268. @Override
  269. public void streamBroadcastClose(IBroadcastStream stream) {
  270. System.out.println("streamBroadcastClose stream:" + stream.getName());
  271. super.streamBroadcastClose(stream);
  272. clearMap();
  273. }
  274. /**
  275. * 放送開始イベント
  276. */
  277. @Override
  278. public void streamBroadcastStart(IBroadcastStream stream) {
  279. System.out.println("streamBroadcastStart stream:" + stream.getName());
  280. super.streamBroadcastStart(stream);
  281. clearMap();
  282. }
  283. /**
  284. * ライブ放送開始イベント
  285. */
  286. @Override
  287. public void streamPublishStart(IBroadcastStream stream) {
  288. System.out.println("streamPublishStart stream:" + stream.getName());
  289. super.streamPublishStart(stream);
  290. clearMap();
  291. }
  292. /**
  293. * レコード放送開始イベント
  294. */
  295. @Override
  296. public void streamRecordStart(IBroadcastStream stream) {
  297. System.out.println("streamRecordStart stream:" + stream.getName());
  298. super.streamRecordStart(stream);
  299. clearMap();
  300. }
  301. /**
  302. * マップデータを消去し内容を確認する。
  303. * @param map
  304. */
  305. private void clearMap() {
  306. System.out.println("before:" + dataHolder.keySet());
  307. System.gc();
  308. Iterator<String> iter = dataHolder.keySet().iterator();
  309. while(iter.hasNext()) {
  310. String key = iter.next();
  311. if(dataHolder.get(key).get() == null) {
  312. iter.remove();
  313. }
  314. }
  315. System.out.println("after:" + dataHolder.keySet());
  316. }
  317. /**
  318. * 保持オブジェクトクラス
  319. */
  320. private class HoldData {
  321. private String str;
  322. public HoldData(String str) {
  323. this.str = str;
  324. }
  325. @Override
  326. public String toString() {
  327. return "HoldData:" + str;
  328. }
  329. }
  330. }
  331.  

実行結果は以下のとおり。
かなり長いですが...

起動
appStart scope:HoldData:scope1
before:[scope1]
after:[scope1]
接続1
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Connecting to: [WebScope@32e62121 Depth = 1, Path = '/default', Name = 'test']
appConnect conn:HoldData:conn1 conn2:HoldData:conn1
before:[scope1, conn1]
after:[scope1, conn1]
appJoin client:HoldData:client1 scope:HoldData:scope1
before:[client1, scope1, conn1]
after:[client1, scope1, conn1]
切断1
appDisconnect conn:HoldData:conn1 conn2:HoldData:conn1
before:[client1, scope1, conn1]
after:[client1, scope1, conn1]
appLeave client:HoldData:client1 scope:HoldData:scope1
before:[client1, scope1, conn1]
after:[client1, scope1, conn1]
接続2
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Connecting to: [WebScope@32e62121 Depth = 1, Path = '/default', Name = 'test']
appConnect conn:HoldData:conn2 conn2:HoldData:conn2
before:[client1, conn2, scope1, conn1]
after:[conn2, scope1]
appJoin client:HoldData:client2 scope:HoldData:scope1
before:[client2, conn2, scope1]
after:[client2, conn2, scope1]
接続3
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Connecting to: [WebScope@32e62121 Depth = 1, Path = '/default', Name = 'test']
appConnect conn:HoldData:conn3 conn2:HoldData:conn3
before:[client2, conn2, conn3, scope1]
after:[client2, conn2, conn3, scope1]
appJoin client:HoldData:client3 scope:HoldData:scope1
before:[client3, client2, conn2, conn3, scope1]
after:[client3, client2, conn2, conn3, scope1]
切断3
appDisconnect conn:HoldData:conn3 conn2:HoldData:conn3
before:[client3, client2, conn2, conn3, scope1]
after:[client3, client2, conn2, conn3, scope1]
appLeave client:HoldData:client3 scope:HoldData:scope1
before:[client3, client2, conn2, conn3, scope1]
after:[client3, client2, conn2, conn3, scope1]
切断2
appDisconnect conn:HoldData:conn2 conn2:HoldData:conn2
before:[client3, client2, conn2, conn3, scope1]
after:[client2, conn2, scope1]
appLeave client:HoldData:client2 scope:HoldData:scope1
before:[client2, conn2, scope1]
after:[client2, conn2, scope1]
 
ルーム接続実験
接続4
roomStart scope:HoldData:scope2
before:[client2, conn2, scope2, scope1]
after:[scope2, scope1]
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Connecting to: [Scope@519549e Depth = 2, Path = '/default/test', Name = '135']
appConnect conn:HoldData:conn4 conn2:HoldData:conn4
before:[conn4, scope2, scope1]
after:[conn4, scope2, scope1]
appJoin client:HoldData:client4 scope:HoldData:scope1
before:[conn4, client4, scope2, scope1]
after:[conn4, client4, scope2, scope1]
roomConnect conn:HoldData:conn4 conn2:HoldData:conn4
before:[conn4, client4, scope2, scope1]
after:[conn4, client4, scope2, scope1]
roomJoin client:HoldData:client4 scope:HoldData:scope2
before:[conn4, client4, scope2, scope1]
after:[conn4, client4, scope2, scope1]
切断4
roomDisconnect conn:HoldData:conn4 conn2:HoldData:conn4
before:[conn4, client4, scope2, scope1]
after:[conn4, client4, scope2, scope1]
roomLeave client:HoldData:client4 scope:HoldData:scope2
before:[conn4, client4, scope2, scope1]
after:[conn4, client4, scope2, scope1]
roomStop scope:HoldData:scope2
before:[conn4, client4, scope2, scope1]
after:[conn4, client4, scope2, scope1]
appDisconnect conn:HoldData:conn4 conn2:HoldData:conn4
before:[conn4, client4, scope2, scope1]
after:[conn4, client4, scope2, scope1]
appLeave client:HoldData:client4 scope:HoldData:scope1
before:[conn4, client4, scope2, scope1]
after:[conn4, client4, scope2, scope1]
[ERROR] [NioProcessor-1] org.red5.io.amf.Input - Error loading class: com.taktod.red5test.Application$HoldData
接続5
roomStart scope:HoldData:scope3
before:[conn4, client4, scope3, scope2, scope1]
after:[scope3, scope1]
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Connecting to: [Scope@61b00766 Depth = 2, Path = '/default/test', Name = '135']
appConnect conn:HoldData:conn5 conn2:HoldData:conn5
before:[conn5, scope3, scope1]
after:[conn5, scope3, scope1]
appJoin client:HoldData:client5 scope:HoldData:scope1
before:[conn5, client5, scope3, scope1]
after:[conn5, client5, scope3, scope1]
roomConnect conn:HoldData:conn5 conn2:HoldData:conn5
before:[conn5, client5, scope3, scope1]
after:[conn5, client5, scope3, scope1]
roomJoin client:HoldData:client5 scope:HoldData:scope3
before:[conn5, client5, scope3, scope1]
after:[conn5, client5, scope3, scope1]
接続6
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Connecting to: [Scope@61b00766 Depth = 2, Path = '/default/test', Name = '135']
appConnect conn:HoldData:conn6 conn2:HoldData:conn6
before:[conn6, conn5, client5, scope3, scope1]
after:[conn6, conn5, client5, scope3, scope1]
appJoin client:HoldData:client6 scope:HoldData:scope1
before:[conn6, conn5, client5, client6, scope3, scope1]
after:[conn6, conn5, client5, client6, scope3, scope1]
roomConnect conn:HoldData:conn6 conn2:HoldData:conn6
before:[conn6, conn5, client5, client6, scope3, scope1]
after:[conn6, conn5, client5, client6, scope3, scope1]
roomJoin client:HoldData:client6 scope:HoldData:scope3
before:[conn6, conn5, client5, client6, scope3, scope1]
after:[conn6, conn5, client5, client6, scope3, scope1]
切断6
roomDisconnect conn:HoldData:conn6 conn2:HoldData:conn6
before:[conn6, conn5, client5, client6, scope3, scope1]
after:[conn6, conn5, client5, client6, scope3, scope1]
roomLeave client:HoldData:client6 scope:HoldData:scope3
before:[conn6, conn5, client5, client6, scope3, scope1]
after:[conn6, conn5, client5, client6, scope3, scope1]
appDisconnect conn:HoldData:conn6 conn2:HoldData:conn6
before:[conn6, conn5, client5, client6, scope3, scope1]
after:[conn6, conn5, client5, client6, scope3, scope1]
appLeave client:HoldData:client6 scope:HoldData:scope1
before:[conn6, conn5, client5, client6, scope3, scope1]
after:[conn6, conn5, client5, client6, scope3, scope1]
切断5
roomDisconnect conn:HoldData:conn5 conn2:HoldData:conn5
before:[conn6, conn5, client5, client6, scope3, scope1]
after:[conn5, client5, scope3, scope1]
roomLeave client:HoldData:client5 scope:HoldData:scope3
before:[conn5, client5, scope3, scope1]
after:[conn5, client5, scope3, scope1]
roomStop scope:HoldData:scope3
before:[conn5, client5, scope3, scope1]
after:[conn5, client5, scope3, scope1]
appDisconnect conn:HoldData:conn5 conn2:HoldData:conn5
before:[conn5, client5, scope3, scope1]
after:[conn5, client5, scope3, scope1]
appLeave client:HoldData:client5 scope:HoldData:scope1
before:[conn5, client5, scope3, scope1]
after:[conn5, client5, scope3, scope1]
接続7
[ERROR] [NioProcessor-1] org.red5.io.amf.Input - Error loading class: com.taktod.red5test.Application$HoldData
roomStart scope:HoldData:scope4
before:[scope4, conn5, client5, scope3, scope1]
after:[scope4, scope1]
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Connecting to: [Scope@541b55f2 Depth = 2, Path = '/default/test', Name = '135']
appConnect conn:HoldData:conn7 conn2:HoldData:conn7
before:[scope4, conn7, scope1]
after:[scope4, conn7, scope1]
appJoin client:HoldData:client7 scope:HoldData:scope1
before:[client7, scope4, conn7, scope1]
after:[client7, scope4, conn7, scope1]
roomConnect conn:HoldData:conn7 conn2:HoldData:conn7
before:[client7, scope4, conn7, scope1]
after:[client7, scope4, conn7, scope1]
roomJoin client:HoldData:client7 scope:HoldData:scope4
before:[client7, scope4, conn7, scope1]
after:[client7, scope4, conn7, scope1]
切断7
roomDisconnect conn:HoldData:conn7 conn2:HoldData:conn7
before:[client7, scope4, conn7, scope1]
after:[client7, scope4, conn7, scope1]
roomLeave client:HoldData:client7 scope:HoldData:scope4
before:[client7, scope4, conn7, scope1]
after:[client7, scope4, conn7, scope1]
roomStop scope:HoldData:scope4
before:[client7, scope4, conn7, scope1]
after:[client7, scope4, conn7, scope1]
appDisconnect conn:HoldData:conn7 conn2:HoldData:conn7
before:[client7, scope4, conn7, scope1]
after:[client7, scope4, conn7, scope1]
appLeave client:HoldData:client7 scope:HoldData:scope1
before:[client7, scope4, conn7, scope1]
after:[client7, scope4, conn7, scope1]
 
放送開始実験
接続8
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Connecting to: [WebScope@32e62121 Depth = 1, Path = '/default', Name = 'test']
appConnect conn:HoldData:conn8 conn2:HoldData:conn8
before:[client7, scope4, conn7, conn8, scope1]
after:[conn8, scope1]
appJoin client:HoldData:client8 scope:HoldData:scope1
before:[client8, conn8, scope1]
after:[client8, conn8, scope1]
接続8視聴開始
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Remembering client buffer on stream: 2000
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Remembering client buffer on stream: 2000
接続9
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Connecting to: [WebScope@32e62121 Depth = 1, Path = '/default', Name = 'test']
appConnect conn:HoldData:conn9 conn2:HoldData:conn9
before:[client8, conn8, conn9, scope1]
after:[client8, conn8, conn9, scope1]
appJoin client:HoldData:client9 scope:HoldData:scope1
before:[client8, client9, conn8, conn9, scope1]
after:[client8, client9, conn8, conn9, scope1]
放送開始
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Remembering client buffer on stream: 0
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider connect
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Stream start
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider connect
streamPublishStart stream:87bc6e26-40b4-4ea3-8735-cce386d6c9de
before:[client8, client9, conn8, conn9, scope1]
after:[client8, client9, conn8, conn9, scope1]
streamBroadcastStart stream:87bc6e26-40b4-4ea3-8735-cce386d6c9de
before:[client8, client9, conn8, conn9, scope1]
after:[client8, client9, conn8, conn9, scope1]
放送停止
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Close
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider disconnect
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider disconnect
streamBroadcastClose stream:87bc6e26-40b4-4ea3-8735-cce386d6c9de
before:[client8, client9, conn8, conn9, scope1]
after:[client8, client9, conn8, conn9, scope1]
録画放送開始
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Remembering client buffer on stream: 0
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider connect
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Stream start
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider connect
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider connect
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Consumer connect
streamRecordStart stream:f8451502-48e6-45f2-84f1-3ccb5b7b8029
before:[client8, client9, conn8, conn9, scope1]
after:[client8, client9, conn8, conn9, scope1]
streamBroadcastStart stream:f8451502-48e6-45f2-84f1-3ccb5b7b8029
before:[client8, client9, conn8, conn9, scope1]
after:[client8, client9, conn8, conn9, scope1]
録画放送停止
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Close
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider disconnect
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider disconnect
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider disconnect
streamBroadcastClose stream:f8451502-48e6-45f2-84f1-3ccb5b7b8029
before:[client8, client9, conn8, conn9, scope1]
after:[client8, client9, conn8, conn9, scope1]
録画放送開始
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Remembering client buffer on stream: 0
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider connect
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Stream start
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider connect
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider connect
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Consumer connect
streamRecordStart stream:5a4ebd67-e3f3-4729-806a-6c0540bf6438
before:[client8, client9, conn8, conn9, scope1]
after:[client8, client9, conn8, conn9, scope1]
streamBroadcastStart stream:5a4ebd67-e3f3-4729-806a-6c0540bf6438
before:[client8, client9, conn8, conn9, scope1]
after:[client8, client9, conn8, conn9, scope1]
録画放送停止
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Close
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider disconnect
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider disconnect
[INFO] [NioProcessor-1] org.red5.server.stream.ClientBroadcastStream - Provider disconnect
streamBroadcastClose stream:5a4ebd67-e3f3-4729-806a-6c0540bf6438
before:[client8, client9, conn8, conn9, scope1]
after:[client8, client9, conn8, conn9, scope1]
切断9
appDisconnect conn:HoldData:conn9 conn2:HoldData:conn9
before:[client8, client9, conn8, conn9, scope1]
after:[client8, client9, conn8, conn9, scope1]
appLeave client:HoldData:client9 scope:HoldData:scope1
before:[client8, client9, conn8, conn9, scope1]
after:[client8, client9, conn8, conn9, scope1]
切断8
appDisconnect conn:HoldData:conn8 conn2:HoldData:conn8
before:[client8, client9, conn8, conn9, scope1]
after:[client8, conn8, scope1]
appLeave client:HoldData:client8 scope:HoldData:scope1
before:[client8, conn8, scope1]
after:[client8, conn8, scope1]
接続10
[INFO] [NioProcessor-1] org.red5.server.net.rtmp.RTMPHandler - Connecting to: [WebScope@32e62121 Depth = 1, Path = '/default', Name = 'test']
appConnect conn:HoldData:conn10 conn2:HoldData:conn10
before:[client8, conn10, conn8, scope1]
after:[conn10, scope1]
appJoin client:HoldData:client10 scope:HoldData:scope1
before:[conn10, client10, scope1]
after:[conn10, client10, scope1]
 
終わり
 

基本的な動作としては、
Red5を起動し、アプリケーションが読み込まれたら
→appStart

ユーザーが接続した場合
appConnect→appJoin
ユーザーが切断した場合
appDisconnect→appLeave

ルームに接続した場合
roomStart→appConnect→appJoin→roomConnect→roomJoin
他ユーザーがさらにルームに接続した場合
appConnect→appJoin→roomConnect→roomJoin
ルームから切断した場合
roomDisconnect→roomLeave→roomStop→appDisconnect→appLeave
多数ユーザーがいる状態で切断したとき
roomLeave→roomStop→appDisconnect→appLeave

放送に関して
このログをみる限りは、play状態になって待機状態になると、バッファデータの取得待ちになる(特にApplicationAdapterで取得できるイベントなし)
live publish状態になると
streamPublishStart→streamBroadcastStart
record publish状態になると
streamRecordStart→streamBroadcastStart
publishを停止すると
streamBroadcastClose
が呼ばれる。

Mapに持たせたデータによると、この検証結果によると、Client、Connection、Scopeともに、必要あれば、存在し必要なければ、きちんと消えていました。
scopeデータだけは、別でおこなった回線を無理矢理引っこ抜くや、処理上で別のユーザーにちょっかいをかける。(client.disconnectを走らせる。)重い処理を実施する。
等をおこなったときに、のこったことがありました。(詳細は気が向いたら検証します。)

以下は個人的な感想

アプリケーションを組むときの方針としては、
Joinで接続完了なので、そのあとでアプリベースのログイン処理を入れる等する。
Leaveでログアウト開始なので、はじめの時点でログアウト処理を入れる等する。
処理がおもくなったりした場合には、Red5.getConnectionLocalのデータが上書きされる可能性があるので、なるべくRed5.setConnectionLocalでただしい値に戻してから
処理を継承元に渡した方がいいかなと思います。
最終更新:2010年12月30日 11:17
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。