Mercurial > hg > Papers > 2014 > nobuyasu-master
diff paper/chapter4.tex @ 69:4f31182c8244
fixed
author | Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 01 Feb 2014 22:41:24 +0900 |
parents | d770a2b534b3 |
children | 4e8bfd65768f |
line wrap: on
line diff
--- a/paper/chapter4.tex Sat Feb 01 21:06:49 2014 +0900 +++ b/paper/chapter4.tex Sat Feb 01 22:41:24 2014 +0900 @@ -17,8 +17,7 @@ \subsection{トポロジーマネージャーの起動} Alice を用いてサーバノードでトポロジーの形成を行う方法を述べる. -Alice のトポロジーマネージャーの起動は\ref{src:alice_dot}の様に行う. -(\ref{src:alice_ntm_run}). +Alice のトポロジーマネージャーの起動は\ref{src:alice_ntm_run}の様に行う. \begin{lstlisting}[frame=lrbt,label=src:alice_ntm_run,caption=Alice によるネットワークトポロジーマネージャーの起動,numbers=left] % java -cp Alice.jar alice.topology.manager.TopologyManager -p 10000 -conf ./topology/tree5.dot \end{lstlisting} @@ -45,7 +44,7 @@ node0 や node1 はサーバノードの名前を示す. サーバノードの間にはラベルがあり, Alice 上ではこのラベル に指定される文字列(キー)を使うことで他のサーバノードのデータへアクセスすることができる. -node0 -> node1 はサーバノード同士の繋がりを示している. +node0 \verb|->| node1 はサーバノード同士の繋がりを示している. 次に続く label="child1" は, node0 が node1 のデータに"child1"という文字列を使うことでアクセス できることを示す. @@ -106,8 +105,9 @@ CodeSegmentには計算に必要なDataSegmentが登録される. そしてDataSegmentが準備され次第CodeSegmentによる計算が実行される. DataSegmentの取得は文字列のキーを使うことで行える. -以下のコードにCodeSegmentの例を示す. -\begin{lstlisting}[frame=lrbt,label=src:syslog_nfconntrack,caption=CodeSegmentの実行,numbers=left] +コード\ref{src:cs_sample}にCodeSegmentの例を示す. +\newpage +\begin{lstlisting}[frame=lrbt,label=src:cs_sample,caption=CodeSegmentの実行,numbers=left] public class TestCodeSegment extends CodeSegment { public Receiver arg1 = ids.create(CommandType.TAKE); @@ -130,8 +130,8 @@ } } \end{lstlisting} -これは, 数字を1から10まで出力を行い終了するプログラムである. コードの説明を行う. +このプログラムは, 数字を1から10まで出力を行い終了するプログラムである. 17行目から19行目の処理が最初に行われる. まずTestCodeSegmentというCodeSegmentのインスタンスcsを生成する. csはarg1というReceiverクラスのフィールドを保持しており, Receiverクラスは @@ -253,7 +253,7 @@ TreeOperationLogをシリアライズ可能な形にするにあたって気をつけなければならないのが, フィールドを シリアライズ可能にする部分である. TreeOperationLogはTreeOperationをいくつも保持し, TreeOperationはNodePathとNodeOperationを保持するものであった. -そのため, これら全てシリアライズ可能な形にしなければならない. +そのため, これら全てをシリアライズ可能な形にしなければならない. 基本的にこれらの実装は, フィールドを全てプリミティブなものだけにすればよい. MessagePackはListを扱うこともできるため, TreeOperationLogで継承されていたIterableの挙動もListを使うことで @@ -261,7 +261,7 @@ \subsection{ログに対する情報の追加} TreeOperationLogをシリアライズ可能な形にした後, 問題が発生した. -それは, TreeOperationLog事態は木の名前を保持していないというものである. +それは, TreeOperationLog自体は木の名前を保持していないというものである. そのため, TreeOperationLogだけを受け取っても, そのログがどの木に対して行われるのか わからなかった. そこで, TreeOperationLogの情報だけでなく, 木の名前とUUID, それとtimestampの情報も付与 @@ -296,7 +296,7 @@ それは, \verb|ods.put|の処理をレスポンスを返すスレッドの中で行うと, レスポンスが悪くなる可能性が あることだ. そのため, \verb|ods.put|を行うのは別のThreadにしたほうがよい. -以下のコードはcommitに成功した後に, NetworkTreeOperationへと変換したログを別スレッド渡し +以下のコードはcommitに成功した後に, NetworkTreeOperationへと変換したログを別スレッドに渡し て処理させるコードである. \begin{lstlisting}[frame=lrbt,label=src:logconvert_and_execute,caption=NetworkTreeOperationをputするために別スレッドを立ち上げる,numbers=left] NetworkTreeOperationLog netLog = new NetworkTreeOperationLog(_uuid, _treeName,newLog); @@ -306,20 +306,20 @@ LogPutCodeSegmentの実装は次のようになっている. \begin{lstlisting}[frame=lrbt,label=src:,caption=putを行うためだけのCodeSegmentの用意,numbers=left] -// LogPutCodeSegment Class -NetworkTreeOperationLog log; -public LogPutCodeSegment(NetworkTreeOperationLog _log) { - log = _log; -} - -@Override -public void run() { - ods.put("log", log); +public class LogPutCodeSegment extends CodeSegment{ + NetworkTreeOperationLog log; + public LogPutCodeSegment(NetworkTreeOperationLog _log) { + log = _log; + } + @Override + public void run() { + ods.put("log", log); + } } \end{lstlisting} 上で述べた問題は, ベンチマークテストなど, 大量の負荷をかけたさいに発生する. -負荷とはJungleのデータに変更を加わることである. -データの変更により大量のログが生成される. +負荷とはJungleのデータに変更が加わることである. +多数のデータの変更により大量のログが生成される. そのため, \verb|ods.put|によりDataSegmentの"log"にアクセスが集中してしまい, レスポンスが 悪くなっていた. \verb|ods.put|を行うタイミングには気をつけなければず, 上記のコードにしても改良の余地はある. @@ -333,6 +333,7 @@ Aliceでは接続を行っている相手のDataSegmentのキーのリストは"\_CLIST"キーを使うことで取得することができる. "\_CLIST"キーで得られるリストを使って他サーバノードへとデータをputするコードを次に示す. +\newpage \begin{lstlisting}[frame=lrbt,label=src:log_put,caption=他サーバノードへのログの送信部分,numbers=left] public class LogUpdateCodeSegment extends CodeSegment { Receiver log = ids.create(CommandType.TAKE); @@ -345,18 +346,19 @@ List<String> list = clist.asClass(List.class); for (String node : list) { - ods.put(node, log.key, log.getVal()); + ods.put(node, log.key, log.getVal()); // Send datasegment to other node } : \end{lstlisting} -変数logはNetworTreeOperationLogが入っている. +12行目の\verb|ods.put(node, log.key, log.getVal())|が他サーバノードへデータを送る部分になる. +変数logにはNetworTreeOperationLogが入っている. 変数listには"\_CLIST"により得られたデータが入っている. それは文字列のListとなっている. listの中身を1つずつ受け取り, \verb|ods.put|する際に引数として渡してやることで, 他サーバノードの DataSegmentにアクセスが行える. listの具体的な内容は, 図\ref{fig:tree_topology}で組まれたトポロジーでいうところの, "parent", "child1", "child2" -の文字列となっている. +の文字列のListとなっている. もし子どもとなるサーバノードがないときは"parent"だけがListには入れられる. @@ -366,9 +368,9 @@ このTreeEditorを使用し, ログに入っているTreeOperationを1つ1つ取り出し同じ編集を行わせる. 例えば次のようになる. \begin{lstlisting}[frame=lrbt,label=src:data_edit,caption=ログを受け取ってのデータの反映,numbers=left] -// Receiver log <- "log"キーから取得できるデータが張っている +// Receiver log <- "log"キーから取得できるデータが入っている // Jungle jugnle -NetworkTreeOperationLog netLog = log.asClass(NetworkTreeOperationLog.class); // NetworkTreeOperationLogへのコンバート +NetworkTreeOperationLog netLog = log.asClass(NetworkTreeOperationLog.class); String treeName = netLog.getTreeName(); JungleTree tree = jungle.getTreeByName(treeName); TreeEditor editor = tree.getLocalTreeEditor(); // Editor の取得 @@ -385,10 +387,10 @@ 7行目で取り出されたTreeOperationからさらにNodePathとNodeOperationを取り出しているのが8行目と9行目になる. 最後にedit関数にTreeEditorとNodePath, それとNodeOpeartionを引き渡している. edit関数は次のようになる. -\begin{lstlisting}[frame=lrbt,label=src:data_edito2,caption=edit関数の実装,numbers=left] +\begin{lstlisting}[frame=lrbt,label=src:data_edit2,caption=edit関数の実装,numbers=left] Either<Error, JungleTreeEditor> edit(JungleTreeEditor editor, NodePath path, NodeOperation nodeOp, int pos) { - String key = "; + String key = ""; Command c = nodeOp.getCommand(); switch (c) { case PUT_ATTRIBUTE: @@ -411,6 +413,7 @@ %\subsection{ローカルのデータ編集専用のTreeEditorの用意} %データ編集が行われ, +\newpage \section{永続性の実装} 次は, ログの書き出しによる永続性の実装について述べる. 第3章でJungleはWriterいう永続性実装のための機能が元々用意されていることを述べた. @@ -421,7 +424,7 @@ つまり, WriterでNetworkTreeOperationLogを書き出すようにすればよい. 以下にログをディスクへ書き出すためのクラスPersistentChangeListWriterの実装を示す. -\begin{lstlisting}[frame=lrbt,label=src:,caption=NetworkTreeOperationをディスクへ書き出す,numbers=left] +\begin{lstlisting}[frame=lrbt,label=src:writer,caption=NetworkTreeOperationをディスクへ書き出す,numbers=left] public class PersistentChangeListWriter implements ChangeListWriter { MessagePack msgpack; @@ -457,14 +460,17 @@ ことができる(Listing\ref{src:data_edit}, \ref{src:data_edit2}). -\section{掲示板プログラムにおけるマージの実装} +\newpage +\section{Mergeの実装} Jungle に分散実装を行った後の問題としてデータ衝突がある. 他のサーバノードから送られてくるデータが既に手元で変更を加えた木構造を対象とした 場合に発生する問題である. -Jungle ではこれをアプリケーション毎にマージを実装することで解決させる. +Jungle ではこれをアプリケーション毎にMergeを実装することで解決させる. + +\section{掲示板プログラムにおけるデータ衝突} 今回分散実装を行い, 例題として掲示板プログラムを用意した. -掲示板プログラムに実装を行ったマージについて述べる. +掲示板プログラムに実装を行ったMergeについて述べる. まず Jungle を用いた掲示板プログラムのデータ保持方法を図\ref{fig:merge2}に示す. \begin{figure}[htpb] \begin{center} @@ -499,12 +505,14 @@ \newpage +\subsection{掲示板プログラムにおけるMerge} + 図\ref{fig:merge_imp2}の server node0 の木の状態にするのが理想である. 掲示板のへの書き込みの表示は, 書き込みされた時間が早い順に表示されるようにしたい. これを timestamp を利用することで行う. 他サーバノードから来たデータに関しては, timestamp を参照し, 次に自分の保持している 木の子ノードの timestamp と比べていくことでデータの追加する場所を決める. -これが今回実装を行った掲示板システムにおけるマージになる. +これが今回実装を行った掲示板システムにおけるMergeになる. %単一サーバで動いている時の Jungle はただ子ノードとして後ろに追加するだけだが, 分散 %環境下においては timestamp に従い子ノードを追加する位置を決めるようにする.