通信プリミティブ

 並行分散ソフトウェア/並列分散ソフトウェア

                                       電子・情報工学系
                                       新城 靖
                                       <yas@is.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.cs.tsukuba.ac.jp/~yas/sie/pdsoft-2005/2006-01-13
あるいは、次のページから手繰っていくこともできます。
http://www.cs.tsukuba.ac.jp/~yas/sie/
http://www.cs.tsukuba.ac.jp/~yas/

■捕捉

◆advisory lock と mandatory lock

mandatory lock
ロックに関する命令を実行していなくても、操作ができなくなる。
advisory lock
ロックに関する命令を実行している時だけ、ブロックされる。
講義で説明したものは、どれも、advisory lock である。いくら mutex を使っ たり、synchronized をつけたとしても、付け忘れた部分があれば、ロックは 働かない。

読み書きロックでも、読み込みだけ行うスレッドも読み込みで advisory ロックを行う必要がある。 ロックを行わないでアクセスしてはいけない。

例:銀行口座が円とドルで2種類あった時に、合計の残高を知りたい。

■今日の重要な話

通信プリミティブの分類

クライアント・サーバ型の通信。

グループ通信(マルチキャスト)の実現

資料: 谷口 秀夫 (編), 谷口 秀夫, 佐藤一朗, 佐藤 文明, 柴田 義孝, 新城 靖, 横山 和俊 (著): "情報処理学会編集 IT Text 分散処理", オーム社 (2005年9月). ISBN: 4274201333.

第2章 基盤技術 (新城)

■プロセス間通信

2つの重要なパタン プロセス間通信の構造化。send, receive は、goto 相当。

◆プロセスとメッセージ

分散システム: 離れていても心は1つ

ネットワークで接続された複数のコンピュータ上で複数のプロセスを動作させ る。プロセスは、全体として1つの仕事を成し遂げる。

ノード:プロセス、あるいは、コンピュータ

メッセージ:ノード間で交換されるデータ

分散システムでは、次のような集中システムでは普通に使える共有資源が使えない。

分散共有メモリ、分散ファイルシステムが使える場合は 使う方法も検討してもよい。

◆通信プリミティブ

メッセージを送信したり受信したりするライブラリ関数やシステム・コールを 通信プリミティブという。 最終的には、ハードウェア。 分散プログラムを記述する時には通信プリミティブを呼び出した段階まで考え ればよい。以後、プログラミング言語の実行時システムやOSが考える。

◆sendとreceive

通信の基本命令
  1. send()。メッセージを送信する。
  2. receive()。メッセージを受信する。

◆通信プリミティブの分類

◆信頼性の有無(reliable or non-reliable)

信頼性性があるかないか。専門用語では、程度問題(高い低い)ではなく、有 るか無いか。

信頼性がある通信プリミティブを利用した場合、あるプロセスが送信したメッ セージは、途中で失われることはなく、有限時間以内に通信相手のプロセスに 送り届けられる。

分散システムでは、メッセージは、失われることがある。

信頼性に対する態度

◆結合(コネクション)が作られるか結合が作られないか

結合が必要な通信プリミティブ
実際に send や receive でメッセージを送受 信する前に結合を確立させる手順を踏む。電話。
結合が作られない通信プリミティブ
送りたいデータをすぐに send することができる。郵便。

プロセスAとプロセスBの間に結合がつくられる時と作られない時

図? 同期型sendと非同期型send

◆アドレス指定

ほとんどの通信プリミティブは、間接。

直接の例:

問題:直接アドレス指定では、receiveする前にsendされると、どのプロセス にメッセージを送っていいのかわからない。

解決

◆同期型/非同期

send() したプロセスはreceive()されるのを待たずにすぐ再開する。 send() したプロセスがreceive()されるまで止まる。

図? 同期型sendと非同期型send

send,receive それぞれ2種類ある。

非同期の方が、並列性が高い。しかし、、、

  1. 転送完了までメッセージ・バッファを書き換えられない
  2. 送信側は、転送が終了したかわからない
1. は、バッファリングで解決可能。しかし、無駄なコピー、フロー制御の問 題がある。

2. は、転送完了割り込みで解決可能。プログラミングが難しい。 割り込みよりは、マルチスレッドがよい。

プログラミングの選択

時間切れ(timeout)。同期で使われる。

◆バッファリング

コピーするかしないか。

同期、非同期とは直行しているとも言えるが、普通は同期の場合にはバッファ リングを省略してコピーを減らす。

メールボックスには、しばしば有限のバッファがもうけられる。

バッファがいっぱいだった時にどうするか。 いっぱいの時にだけ送信側をブロックさせる、という方法でいいのか。

◆マルチキャスト(グループ通信)

通信の分類

放送(broadcast)は、特定の(物理的な)ネットワークに属するプロセス「全部」に送る。

グループ通信は、いろいろな分散アルゴリズムでよく使われる。

◆帯域保証

帯域保証とは、たとえば、64k bps のように、毎秒、どのくらいデータ を送ることができるかを保証することである。

普通の固定電話の場合、64k bps の帯域保証がなされている。電話を掛ける人 が増えてきたとしても、それが 32k bps に減らされるようなことはない。そ の代りに、電話を掛けようとすると「通話中」というエラーが返り、通信その ものが行えなくなる。

◆遅延保証

send してから receive するまで、最長どのくらいの時間がかかるかを保証す ることである。電話の場合、ある程度の遅延保証は行っているとも言える。テ レビの衛星中継のように、遅延が大きい媒体では、普通の会話はできなくなる。

◆単方向/双方向

単方向の通信しかできな い場合でも、単方向の通信を2つ逆方向で組み合わせることもできる。

◆メッセージの順序の保証

メッセージをsendした時にその通りの順序で receive できるかどうかという 意味である。結合が作られる場合は、普通は順序も保証される。

◆まとめ

TCP IP UDP イーサネット 電話 郵便
send   非同期 非同期 非同期 非同期 非同期 非同期
receive  同期 (非同期)* 同期 (非同期)* 同期 非同期
信頼性 あり なし なし なし あり なし
アドレス指定 間接 間接 間接 間接 間接 直接
結合   あり なし なし なし あり なし
方向 双方向 単方向 単方向 単方向 双方向 単方向
マルチキャスト 不可 可能 可能 可能 可能 不可
帯域保証 なし なし なし なし あり なし
* OS 内。

■TCP/IP

◆IP

IPデータグラム(datagram)転送サービス

◆TCP

ストリーム転送サービス データの区切りが保存されると、sequenced packet と呼ばれる。

TCP層の技術1:再転送付き肯定確認応答

IP層は、転送サービスとして信頼性のないデータグラムを提供する。TCP 層の仕事は、それを使って、双方向のストリーム転送サービス提供することで ある。そのために、「再転送付き肯定確認応答(positive acknowledgement with retransmission)」という、一般的によく用いられている技術が使われ ている。この技術では、データの受け手は、データを受け取る度に、送り手に 確認応答(acknowledgement, しばしば ack と省略される)を返す。データの 送り手は、確認応答を受け付けると、次のデータを送る。ある時間がたっても 確認応答が来なかった場合、データの送り手は、再転送(retransmit)する。

TCP層の技術2:スライディング・ウィンドウ

ストリームを実現する技術として、TCPは、スライディング・ウィンドウ (sliding window)と呼ばれる技術を用いている。この技術では、ウィンドウと 呼ばれる範囲を設定して、確認応答が来る前に、次々とウィンドウ内のパケッ トを送出す。確認応答を受け取ると、ウィンドウを「スライド」させ、次のパ ケットを送り出す。

フロー制御

受け手のバッファ(メモリ)は、有限である。送り手は、受け手消費する速度 に合わせてパケットを送出さなければならない。このような制御をフロー制御 という。TCPでは、スライディング・ウィンドウを用いてフロー制御を行って いる。

■marshaling/unmarshaling

プログラム中のデータ項目とネットワーク上を流れるメッセージに対応づける。
marshaling (整列化)
メモリ中からデータ項目を集めて、ネットワークでメッセージとして 転送するのに適した形式にまとめる。
unmarshaling (非整列化)
逆。
英語の綴りは、l が1つのものと2つのもの(イギリス綴り)がある。教科書によって違う。

プロセスAがメモリ中のデータを1個にまとめてネットワークに送り出す。プロセスBが受け取り元に戻す

図? marshalingとunmarshaling

4個の要素からなる構造体を整列化して送信している。 整列化する基本的な方法 ネットワークからデータを受け取ると、先頭から解釈して元のデータを再現す る。

ネットワーク上を流れている時には、整列化された データの先頭にはネットワークのヘッダが付加されている。

◆XDR

SunRPC で使われているデータ形式。バイナリ文化。

rpcgen というスタブ・コンパイラがある。 データ構造を与えると、marshaling の手続きを自動生成する。

SunRPC を使わなくて、XDR だけを使う方法もある。

xdrmem_create(XDR *, const caddr_t, const uint_t, const enum xdr_op)
メモリの指定されたの番地に保存/回復/メモリの解放。
void xdrstdio_create(XDR *, FILE *, const enum xdr_op)
FILE * を通じて、構造体の読み書き。

◆バイト・オーダー

分散プログラムでは、メッセージを送信するプロセスと受信するプロセスが 異なる CPU で実行されることがある。 整数を送るだけでも、バ イトオーダに気をつける必要がある。

C言語で扱える整数

現在のコンピュータのほとんどは、バイト単位でアドレスを付けているので、 1バイトの整数については、バイトオーダの問題はない。

2バイト、または、4バイトの整数をメモリに保存する方法 : メモリの下位番地に上位バイトを置くか下位バイトを置くか

リトルエンディアン
下位番地に下位バイトを置く。Pentium。
ビッグエンディアン。
下位番地に上位バイトを置く。PowerPC (Macintosh) や SPARC

0x12345678を2000番地に保存する。

図? バイト・オーダー

◆ビッグエンディアンとリトルエンディアンの比較

◆送り方

現在、ネットワーク・バイト・オーダとしては、ビッグエンディアンが広く 使われている。

◆バイトオーダを変換するライブラリ関数

名前 方向 ビット数
htonl() ホストからネットワークへ変換 32ビット
htons() ホストからネットワークへ変換 16ビット
ntohl() ネットワークからホストへ変換 32ビット
ntohs() ネットワークからホストへ変換 16ビット
long int hostlong, netlong;    
hostlong = 0x12345678 ;    
netlong = htonl( hostlong );    
send(conn, &netlong, sizeof(netlong), 0);

◆snprintf()/strtol()

snprintf() で文字列に直して送り、strtol() や atoi() でもどす方法もある。 文字列文化。インターネットのアプリケーションでよく使われる。

思ったほど遅くはない。

注意:sscanf() は、整数をデコードするために使う分には問題ないが、 文字列を受け取るために使うとバッファ・オーバーフローが生じる可能性があるので、 使わない方がよい。

◆文字列の送信

Unicode BOM (byte order mark) 0xffef。

◆その他

■Socket API

ソケットAPIは、TCP/IP をBSD 系 Unix に導入する時に設計された API であ る。

今後 TCP/IP 以外にも様々な通信プロトコルが開発され、Unix で利用できる ように設計されている。TCP/IP で使う時には、煩雑である。

◆ソケットAPIでのプロトコルの指定

ドメイン プロトコル
PF_INET SOCK_STREAM TCP(IPv4)
PF_INET SOCK_DGRAM UDP(IPv4)
PF_INET6 SOCK_STREAM TCP(IPv6)
PF_INET6 SOCK_DGRAM UDP(IPv6)
PF_UNIX SOCK_STREAM 同一ホスト内(UNIXドメイン)のストリーム
PF_UNIX SOCK_DGRAM 同一ホスト内(UNIXドメイン)のデータグラム
PF_NS SOCK_STREAM XNS のストリーム(SPP)
PF_NS SOCK_SEQPACKET XNS の順序付きパケット(IDP)
PF_NS SOCK_RDM XNSの信頼性のあるデータグラム(SPP)

◆ソケットAPIの主要なシステムコール、または、ライブラリ関数

名前 説明
socket() 通信プロトコルに対応したソケット・オブジェクトを作成する
connect() 結合(conection)を確立させる。サーバのアドレスを固定する。
listen() サーバ側で接続要求の待ち受けを開始する。
accept() サーバ側で接続されたソケットを得る。
bind() ソケットにアドレス(名前)を付ける。
getpeername() 通信相手のアドレス(名前)を得る。
getsockname() 自分のアドレス(名前)を得る。
send(), sendto(), sendmsg() メッセージを送信する。
recv(), recvfrom(), recvmsg() メッセージを受信する。
shutdown() 双方向の結合を部分的に切断する。
getsockopt() オプションの現在の値を取得する。
setsockopt() オプションを設定する。
select(), poll() 複数の入出力(通信を含む)を多重化する。
write() メッセージを送信する。
read() メッセージを受信する。
close() ファイル記述子を閉じる。他に参照しているファイル記述子がなければ、ソケット・オブジェクトを削除する。
write(), read(), close() はファイルと共通。

◆主要な IP アドレスを扱う関数

名前 説明
gethostbyname() ホスト名から IP アドレスを調べる。
getaddrinfo() ホスト名から IP アドレスを調べる。IPv6対応。
gethostbyaddr() IPアドレスからホスト名を調べる。
getnameinfo() IPアドレスからホスト名を調べる。IPv6対応。
freeaddrinfo() getaddrinfo(), getnameinfo() で得られた構造体を解放する。
関数名には、IP以外も考えた名前にして欲しかった。

◆JavaのAPI

Java言語は、基本的に TCP/IP と UDP/IP しかサポートしていない。したがっ て、TCP/IP や UDP/IP のプログラムを作成する場合には、分かりやすくなっ ている。

TCP/IP では、クラ イアント側とサーバ側でソケット・オブジェクトの作成するクラスが違ってい る。

クラス名 説明
Socket TCP/IP のクライアント側のソケット
ServerSocket TCP/IP のサーバ側のソケット
DatagramSocket UDP/IP のソケット
Java でも、実際の通信には、ファイルと同じ API を用いる。 例: Socket クラスのオブジェクトに対して getInputStream() というメソッドを実行する と、InputStream クラスのオブジェクトが返される。 InputStream は、ファイルからの入力と共通。

以後、ネットワークか ら文字列を入力するには、InputStreamReader や BufferedReader のオブジェ クトを生成して利用する。

出力側では、Socket クラスのオブジェクトに対して getOutputStream() して、 OutputStream クラスのオブジェクトを得て、 PrintStream オブジェクトを生成して利用できる。

■クライアント・サーバ・モデル

手続き呼出しの形に見えたら RPC (Remote Procedure Call)。

通信を構造化。send()/receive() を直接使うのは、goto (jump) でプログラ ムを書くようなもの。call/if/while で書きたい。

プロセスを2種類に分類する。通信は、次のパタンを繰り返す。

クライアント
先にメッセージ(要求)を send() 1回、後でメッセージ(応答)を receive() 1回
サーバ
先にメッセージ(要求)を receive() 1回、後でメッセージ(応答)を send() 1回
send() の回数と receive() の回数は同じ。相互に繰り返す。

図? send(),receive()と繰り返すクライアントと receive(),send() と繰り返すサーバ

図? 通信のパタンからみたクライアントとサーバの定義

◆クライアントとサーバに分けて考える意義

混沌とした通信を「構造化」してわかりやすくする。

図? プロセス5つ、構造化されていない通信パタン

図? 構造化されていないもの

図? プロセス5つ、構造化された通信パタン

図? 構造化されたもの

構造化プログラミング:分かりにくいgoto文をつかわないで、わかりやすい goto文だけ使う。

◆サービスの授受

元々の意味
クライアント(client)
サービスを受ける方、顧客
サーバ(server)
サービス(service)を提供する方

図? サービスの授受によるクライアントとサーバの定義

図? サービスの授受によるクライアントとサーバの定義

◆利用者数

サービスを提供する方は、1つのプログラム(コンピュータ)で複数の利用者 の面倒をみる。その結果、1台のサーバに複数のクライアントがつながる。

クライアント
一人で使うもの
サーバ
複数人で共有するもの

図? 複数のクライアントによるサーバの共有

図? 複数のクライアントによるサーバの共有

◆接続方法

TCP/IP の通信では、通信を始める前に、まず、通信路を作る作る必要がある。 これは、電話で話をする前に、まず、電話をかける操作を行うことと似ている。
クライアント
電話を掛ける方に相当する
サーバ
電話を待っている方

以上のように、クライアントとサーバは、いろいろな意味で使われる。これら の意味は、多くの場合、一致しているが、一致していないこともある。

◆能動的・受動的

通信を開始するパタンで、コンピュータ、プログラム、人間は、次の2つに分 類される。

能動的(active)
ほっといても自分でメッセージを発信し始める
受動的(passive)、受け身
何か言われると答えるが、自分ではメッセージを発信し始めることはない
クライアントとサーバから作られたシステムは、クライアントが能動的になり、 サーバは、受動的になることが多い。

図? 能動的なクライアントと受動的なサーバ

図? 能動的なクライアントと受動的なサーバ

例:WWWサーバは、WWWクライアントから何か要求が来ない限り、ずっと 黙っている。

コンピュータを使う時には、人間が能動的になり、コンピュータが受動的にな る。

テレビを見ている時には、人間が受動的になり、テレビが能動的になる。

講義形式の授業では、サービスの授受では、教官がサーバで、学生がクライア ントになる。通信の開始の方法では、教官が能動的になり、学生が受動的にな る。

大学以上では、学生は、能動的になることが求められている。

◆Peer to Peer (P2P)

P2P (Peer to Peer) という用語の意味は、怪しい。

混沌とした通信を 構造化 してわかりやすくしたものが、クライアント・サーバ・モデルである。

サーバあるシステムでは、サーバが落ちるとシステム全体が動作しなくなる。 このように複数の要素から構成されているシステムで、ある要素が故障した時 に、全体が動作しなくなるような場所を、単一障害個所(single point of failure) という。

コンピュータサイエンスでは、古くから、単一障害個所を避けるための研究が 行われてきている。もっとも成功している方法は、サーバを複数用意する方法 である。

サーバがないシステムでは、下手に作るとどの要素が故障してもシステム全体 が止まってしまうことになる。

サーバがないシステムで成功している例はある。

peer は、「対等の仲間」の意味。「通信相手」という意味もある。

検索は、サーバで索引を集めた方が速い。Web 上の検索エンジンなど。

サーバがない方法の利点(特徴)

サーバがない方法の問題点 Napster

Napster は、学問的には、特に目立った新技術はない。

◆クライアント・サーバ・モデルを実現する3つの基本命令

  1. get_request(port_t serviceport,message_t request/*in*/): サーバ・プロセスにより使われる。クライアント・プロ セスから送られてくる要求メッセージを待つ。
  2. send_reply(port_t client,message_t reply): サーバ・プロセスにより使われる。クライアント・プロ セスに対して応答メッセージを送る。
  3. do_operation(port_t server,message_t request/*out*/, message_t reply/*in*/): クライアント・プロセスにより使われる。サーバへ要 求を送り、サーバからの応答が返ってくるまで待つ。
サーバは、普通、get_request() で、クライアントから何か要求メッセージが 届くのを待っている。

クライアントが何かサーバにして欲しい時には、do_operation() で、サーバ に要求メッセージを送る。そして、サーバからの応答メッセージを待つ。

サーバは、要求メッセージを受けとると、何か仕事をして、send_reply() で、 クライアントに応答メッセージを返す。そして、再び次の要求メッセージ を待つ。

1つのサーバに複数のクライアントがアクセスすることがある。1つのクライ アントも、複数のサーバに同時にアクセスすることもできる。

図? クライアント・サーバ・モデルに基づく通信で使う3つの命令

図? クライアント・サーバ・モデルに基づく通信で使う3つの命令

◆実現例

例1:7種類のメッセージを使う方法

例2:3種類(回数)

例3:2種類(回数)

◆RPC

RPC (Remote Procedure Call) ( 遠隔手続き呼び出し ) は、分散システムを構築する時に広く使われている「プロセス間通信」の方法。 NFS (Network File System) を始めとする分散ファイル・システムの構築や、 や NIS (Network Information Service) (パスワード・ファイルなどの共有) で使われている。

(<−>文化的には、TCP/IP上のテキストベースのプロトコルとは対照。)

◆RPCの特徴

TCP/IP で提供されているストリームや UDP/IP で提供されているデー タグラムと比較して、RPC には次のような特徴がある。 RPCで「遠隔(remote)」というのは、もともとはネットワークに接続された別 のコンピュータという意味であったが、最近では、同じコンピュータの内部で もRPCが使われる。「遠隔(remote)」とは、「別のコンピュータ」という意味 ではなく、「別のアドレス空間」という意味もある。

RPCでは、別のアドレス空間の間でデータがやり取りされるので、基本的に 「ポインタ」を受け渡しすることはできない。しかし、SunRPC では、ポイン タの先を再帰的に「コピー」する機能がある。

◆RPCを実現する基本命令

下位層では、上であげた3つの基本命令が使われている。

このRPCの3つの命令は、システムコール、または、ライブラリで実現される。 SunRPCには、get_request() に相当する命令が定義されていない。

◆スタブとスタブ生成器

RPCでプログラムを作成するときには、3つの基本命令を利用することは、ほ とんどない。 スタブ生成器(stub generator) を使えば、インタフェースの定義から3つの基本命令を呼び出すようなプログ ラムが自動生成される(lex、yacc )。

スタブ(stub) は、プロセス間通信を普通の手続き呼出しと全く同じ形式で行なうことができ るようにするためのプログラム。 もともとは木の切株の意味。

図? クライアント側スタブ、サーバ側スタブ

図? スタブによる遠隔手続き呼出しの実現

スタブの分類

クライアント側スタブ
手続き呼出しの形で呼び出される。do_operation() 命令を実行する。
サーバ側スタブ
無限ループを持つプログラム。 get_request() でクライアントからのメッ セージを受け取り、対応する手続きを呼び出し、結果をsend_reply() により 返す。
スタブでは、パラメタ(引数と結果)の 整列化(marshalling) ( パック ) と 非整列化(unmarshalling) ( アンパック ) も行なわれる。SunRPC では、 XDR (eXternal Data Representation) と呼ばれている方法を使っている。

◆SunRPC のrpcgenコマンドとファイル

SunRPC には、rpcgen というスタブ・コンパイラがある。 rpcgen コマンドを使うには、次のようなファイルを作成する。

rpcgenによるRPCプログラム開発で利用するファイル

図? rpcgenによるRPCプログラム開発で利用するファイル

name.x
インタフェースを記述。
name_client.c
クライアント側の main プログラム。
name_server.c
サーバ側で、RPC で呼び出されるプログラム。 (main は、rpcgen により自動生成される。)

◆rpcgenコマンドの使い方

% rpcgen name.x [←]
次の4つのファイルが生成される。
name.h
そのRPCのプログラムで使う定数、データ構造、スタブ手続きのインタフェー ス。
name_clnt.c
クライアント側のスタブ。
name_xdr.c
name.x で定義したデータ構造について、 XDR のための手続き(整列化と非整列化を行なう手続き) 。 クライアント側とサーバ側の両方で使われる。
name_svc.c
サーバ側の main 関数とディスパッチ手続き。受け付けた RPC の要求を解析 して、開発者が定義した手続きを呼び出す。
これらのファイルの内容は、人間が十分読めるも。

◆rpcgenのインタフェース定義の例

ハッシュ表 typedef char *key_t; typedef key_t *keyarray_t;
typedef string key_t<256>;
struct keyvalue_t { 
   key_t key; 
   int   value ;
};
typedef key_t  keyarray_t<>;

program HASHTABLE_PROG { 
   version HASHTABLE_VERSION {
       int        PUT(keyvalue_t)  = 11 ; 
       int        GETVALUE(key_t)  = 12 ; 
       keyarray_t GETKEYS(void)    = 13 ; 
   } = 1 ;
} = 0x20051001 ;
遠隔手続き呼出しでは、送受信できるデータは基本的には値だけであり、 ポインタを送ることはできない。

SunRPC では、ポインタの先の1要素だけコピーして送る機能がある。SunRPC では、ポインタによる単純なリストや木構造を送ることができる。

双方向リストなど、内部にループを含むものは SunRPC では送ることができな い。また、ポインタで実現された有向非循環グラフを送ると木構造に展開され てしまう。

◆Binding

クライアントとサーバを結び付ける。 RPC では、動的(dynamic)になる。

ローカルの手続き呼出しでは、リンク時に固定される。

クライアントとサーバは1対1ではない。

binding のための命令

◆SunRPC での Binding

SunRPCでは、多くの場合、TCP/IPやUDP/IPを使ってメッセージを送る。この場 合、手続きをを次の5つの番号で区別する。 広く使われるプログラム番号は、 /etc/rpc というファイルに含まれている。

TCP/IPまたはUDP/IPでデータを送るにはポート番号が必要になる。 サーバが動作しているホストには、 portmapper とよばれる特殊な RPC のサーバが動作している。 サーバは起動時に自分の<プログラム番号, バージョン, プロトコル, ポート番号>をPortmapper に登録する (pmap_set())。

クライアントは、実際にサーバに接続する前に、Portmapper に<プ ログラム番号, バージョン, プロトコル>を送り、 TCP/IPまたはUDP/IPのポート番号を得る(pmap_getport())。最終的には, この ポート番号を使ってメッセージを送る。

Portmapper 自身のポート番号は、111 に固定されている。

portmapper が binding

図? SunRPC での binding (portmapper)

◆クライアント・サーバ型通信を実現する上での解決すべき問題

(RPCを実現する上での問題)

◆障害

◆クライアントがサーバを見つけられない

◆要求メッセージが紛失

時間切れ再要求。簡単。

◆応答メッセージが紛失

難しい。単純な時間切れだとまずい。

例: 銀行預金転送。

対策:

◆要求受信後、サーバがクラッシュ

番号では対応できない。要求実行前と実行後を区別できない。

RPCのセマンティクス

集中だと、クライアントもサーバもいっしょに死ぬので、問題はない。

◆要求送信後、クライアントがクラッシュ

孤児問題(orphan problem)。

親(クライアント)がいない計算を孤児という。

対応方法

根絶(extermination)。
RPC 前にログに書く。クラッシュしたらログを見て根絶する。重たい。 孫の孤児(grandorphan)問題がある。
再生(reincarnation)
リブートすると、タイムスタンプをサーバに投げる。サーバは、 全孤児を消去する。
穏和な再生(gentle reincarnation)
タイムスタンプを受信すると、サーバは親を探し、見つからない時だけ孤児を消去する。
期限切れ(expiration)
RPC に標準時間Tを与え、その時間内に終了しないものを消去する。 それ以上かかる時には、明示的に要求する。クラッシュ後、サーバがTだけ待てば 孤児は消える。

孤児が、ロックを持っていたら、孤児を消しただけでは話を終わらない。

◆idempotent冪等

冪等(idempotent)な操作とは、 その操作を何回繰り返しても、1回だけ実行した時と同じ結果になるもの。

例:

idempotentではない操作

◆stateless server

無状態サーバ(stateless server) とは、サーバ内部に状態を保持しないようなサーバ。

状態の例

RPCで冪等な操作や無状態サーバを実現すると、クラッシュに強いシステムを 作れる。クライアントは、サーバから応答がない場合、何度要求を再送信して もよい。

例:NFS Version 2

サーバは、ファイルに対する書き込み要求を受け付けると、ディスクへ の書き込みを完了してから応答を返す。 応答が返ってきた要求は、 ディスクへの書き込みが完了したことが保証されている。 この段階でサーバがクラッシュしたとしても、なにも失われない。

しかし、、、重たい。NFS Version 3 では、状態付きのサーバになった。

表? NFSで使われているRPCの手続き

手続き名 意味 関連するコマンド、 システムコール
null() 何もしない rpcinfo -u hostname nfs コマンド
getattr() 属性の読み出し ls -l コマンド, stat システムコール , open システムコール
setattr() 属性の設定 chmod , chown コマンド
lookup() ファイルの検索 open システムコール
readlink() シンボリックリンクの読み出し ls -l コマンド, readlink システムコール
read() ファイルの読み出し read システムコール
write() ファイルの書き込み write システムコール
create() ファイルの作成 creat システムコール, open システムコール
remove() ハードリンクの削除 rm コマンド, unlink システムコール
rename() ファイル名前の変更 mv コマンド, rename システムコール
link() ハードリンクの作成 ln コマンド, link システムコール
symlink() シンボリックリンクの作成 ln -s コマンド, symlink システムコール
mkdir() ディレクトリの作成 mkdir コマンド
rmdir() ディレクトリの削除 rmdir コマンド
readdir() ディレクトリの読み出し ls コマンド
statfs() ファイルシステムの利用状況 df コマンド, statfs システムコール
commit()* ディスクへの書き込み fsync システムコール
access()* アクセス権のチェック access システムコール
* は、NFS Version 3 の新しい手続き。

◆cookie

RPC のようにコネクションが作られない 通信サービスを使う時に 冪等や無状態といった性質を実現する時に必要になる技術。

例:NFSでのディレクトリの読み込み手続き nfsproc_readdir() で、1回の RPC で全部のデータを返せないことが起きる。 ディレクトリのどの位置まで読み込んだかを 示す中間状態を クッキー(cookie) という形でクライアントに返す。

クライアントは、次の RPC の呼び出しで、 前回受けとった応答の中のクッキーを、サーバへの要求に含めて送す。

/usr/include/rpcsvc/nfs_prot.x:

const NFS_COOKIESIZE	= 4;
typedef opaque nfscookie[NFS_COOKIESIZE];

/*
 * Arguments to readdir
 */
struct readdirargs {
	nfs_fh dir;		/* directory handle */
	nfscookie cookie;
	unsigned count;		/* number of directory bytes to read */
};

struct entry {
	unsigned fileid;
	filename name;
	nfscookie cookie;
	entry *nextentry;
};

struct dirlist {
	entry *entries;
	bool eof;
};

union readdirres switch (nfsstat status) {
case NFS_OK:
	dirlist reply;
default:
	void;
};

nfsproc_readdir() で、1回目と2回目の RPC の間にディレクトリの内容が 更新された場合、どのような結果になるのか不明。

◆WWWでのcookie

HTTP では、 TCP/IP というコネクションが作られる通信サービスが使われいるが、 1ページ1ページを転送する度にコネクションを切っているので、 複数ページ のアクセスの時にはコネクションが作られない通信サービスを使っているのと 論理的に同じ。

途中経過を保存したい時:

サーバは、その情報を利用して、適切なページ(たとえば前回最後に訪れたペー ジ)を表示させるようにすることができる。

◆WWW cookieの例(RFC2965より)

User Agent は、WWW ブラウザと思ってよい。
4.  EXAMPLES

4.1  Example 1

   Most detail of request and response headers has been omitted.  Assume
   the user agent has no stored cookies.

      1. User Agent -> Server

        POST /acme/login HTTP/1.1
        [form data]

        User identifies self via a form.

      2. Server -> User Agent

        HTTP/1.1 200 OK
        Set-Cookie2: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"

        Cookie reflects user's identity.

      3. User Agent -> Server

        POST /acme/pickitem HTTP/1.1
        Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"
        [form data]

        User selects an item for "shopping basket".

      4. Server -> User Agent

        HTTP/1.1 200 OK
        Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";
                Path="/acme"

        Shopping basket contains an item.

      5. User Agent -> Server

        POST /acme/shipping HTTP/1.1
        Cookie: $Version="1";
                Customer="WILE_E_COYOTE"; $Path="/acme";
                Part_Number="Rocket_Launcher_0001"; $Path="/acme"
        [form data]

        User selects shipping method from form.

      6. Server -> User Agent

        HTTP/1.1 200 OK
        Set-Cookie2: Shipping="FedEx"; Version="1"; Path="/acme"

        New cookie reflects shipping method.

      7. User Agent -> Server

        POST /acme/process HTTP/1.1
        Cookie: $Version="1";
                Customer="WILE_E_COYOTE"; $Path="/acme";
                Part_Number="Rocket_Launcher_0001"; $Path="/acme";
                Shipping="FedEx"; $Path="/acme"
        [form data]

        User chooses to process order.

      8. Server -> User Agent

        HTTP/1.1 200 OK

        Transaction is complete.

   The user agent makes a series of requests on the origin server, after
   each of which it receives a new cookie.  All the cookies have the
   same Path attribute and (default) domain.  Because the request-URIs
   all path-match /acme, the Path attribute of each cookie, each request
   contains all the cookies received so far.

◆WWW cookieとプライバシ

現在の Cookie の実現では、利用者のプライバシーを犯す危険性が高いという 問題が指摘されている。

普通のWWWサーバでは、要求を送ってきたコンピュータのIPアドレスを記 録しているので、コンピュータ単位でのアクセス状況を記録することはできる が、個人を特定することはできない。

クッキーを利用することにより、コンピュータではなくどの個人がアクセスし てきたかを記録することができる。

クッキーから電子メールのアドレスや氏名まで調べることはできない。 しかし、インターネットをサーフしている間にどこかでそれを打ち込んだが最 後、クッキーと電子メール・アドレスや氏名との対応が記録されてしまう危険 性がある。

参考

RFC2965 HTTP State Management Mechanism
Netscape社によるWWWにおけるクッキー実現の案
http://wp.netscape.com/newsref/std/cookie_spec.html

◆HTTP での cookie

HTTP では、 TCP/IP というコネクションが作られる通信サービスが使われいるが、 1ページ1ページを転送する度にコネクションを切っているので、 複数ページ のアクセスの時にはコネクションが作られない通信サービスを使っているのと 論理的に同じ。

HTTP でも、クライアントの状態をサーバ側で保存するためにクッキーが使わ れることがある。

◆SunRPC

■グループ通信

グループ通信で何が難しいか

◆設計の論点

並列処理では、クローズが多い。 IP MBone のように、オープンでないとどうしようもないものもある。

対等だと、クラッシュに強い(single point of failure がない)が、何をす るにもすぐ投票が必要になる。

◆メンバシップの管理

グループサーバを持つか持たないか。

難しいのは、メンバのプロセスがクラッシュした時。 何も言わずにグループから抜ける。

◆アドレス指定

◆通信プリミティブ

one-to-oneの通信と同じにしたい。しかし、 障害がなければ、簡単。

◆atomic broadcastの簡単なアルゴリズム

◆メッセージの到着順

one-to-one でも問題があるのに、group 通信だとさらに複雑。

total ordering は、グループ通信では実現が難しすぎる。弱いものが実現さ れる。

プロセスが複数のグループに属していると、1つのメッセージについての順序 だけ考えていてはすまなくなる。

◆スケーラビリテイ

数が増えた時に動くか。

◆冗長性

ネットワークのダウンに対応するには、ネットワークを冗長に しないといけない。冗長性があると、メッセージの重複を うまく扱う必要がでてくる。

下手をすると、メッセージが増幅しながいつまでもぐるぐる回る。

◆例 ISIS システム

分散アプリケーションのためのツールキット。 コーネル大学。

◆ISISの同期性(synchrony)

同期システム(synchronous system)
イベント(マルチキャスト)の順序が厳密に逐次的に発生する。オーバーラップしない。 イベント(マルチキャストを含む)は、完了までの時間は、0。 実現不可能。
緩やかな同期システム(loosly synchronous system)
イベントは有限時間で届く。
仮想的な同期システム(virtually synchronous system)
因果関係が成り立つようにがんばる。(並行なものは、手抜き。)

◆ISISの通信プリミティブ

ABCAST
緩やかな同期
CBCAST
仮想的な同期
GBCAST
仮想的な同期(グループのメンバシップ用)

最初の実現:2相コミットによる ABCAST 。重すぎる。

  1. 送信者は、タイムスタンプを含むメッセージを全てのメンバに送る。
  2. 各メンバは、送信、または、受信したメッセージで最大のものを最初の送信者に送る。
  3. 送信者は、全ての返事を受け取ると、最大のものを選び、メンバにコミット・メッセージを送る。コミット・メッセージは、タイムスタンプの順に届けられる。
CBCASTの実現

メンバの数:n

各プロセスは、グループごとに、長さnのベクトルVを持つ。 i番目の要素は、プロセスiから正しい順序で受信したメッセージの最後の番号。 0に初期化される。

  1. プロセスは、送信すべきメッセージがあると、 ベクトルの自分のスロットを増加させ、メッセージの一部として送信する。
  2. メッセージのベクトルをV、メモリ中のベクトルをLとする。 メッセージがjから送られてきたものとすると、次の条件の時に受け取る。 そうでないものは、この条件が満たされるまでバッファリングされる。

M1が届くまでM2の配送を遅延。

図? ISISでのCBCASTの実現。

◆ニュースシステム

マルチキャストの実装。
↑[もどる] ←[12月22日] ・[1月13日] →[1月20日]
Last updated: 2006/01/18 19:08:03
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>