テレビのアニメはどこから来る? / 第12話

第12話:イトは、お願いに書かれた「残り1席」を消した|サーバーは何を信じる?

ピコルート第12話。予約requestには残り1席、server側の記録には残り0席。上映扉が閉まるまで20秒、イトはclientの願いを写すか、現在の状態から返事を作るかを選びます。

サーバークライアントレスポンスデータの保管10分更新

お願いの中に、「残り1席」と書かれていた。

server側の記録には、「残り0席」とある。

上映室の扉が閉まるまで、あと二十秒。

第11話で最後の席が取られた直後、別の端末から新しい予約requestが届いた。

POST /reservations
{
  "seatId": 12,
  "displayedRemaining": 1
}

requestを送った端末では、古い青い1がまだ光っていた。

サーバー応答室のcurrent ledgerでは、12番席に一枚の予約札がついている。

イトの前には、成功responseを書くための青い札と、満席を伝える赤い札が一枚ずつ置かれた。

イト

お願いに1って書いてある。これを返せば、いちばん速いよ

マコト

その1は、どこで見えた数字だろう

ピコ

clientが送った値と、serverがいま持つ状態を、同じ札にしないで見よう

残り十八秒。

requestは、clientの意図を運んでくる

browserやappのように、requestを送る側をclientと呼ぶ。

requestには、何をしたいかを示すmethod、対象を示すrequest target、必要に応じてheaderやcontentが入る。

今回のrequestが伝えている中心は、短い。

12番席を予約したい

displayedRemaining: 1は、そのclientの画面に見えていた値だ。

席が現在も空いているという保証ではない。

RFC 9110のclient/serverとmessageでは、clientがrequestを送り、serverがrequestを解釈し、status codeなどを含むresponseを返すという役割が定められている。

ただし、HTTPは上映室の予約ruleを決めない。

「最後の一席を誰へ確定するか」「どの記録をcurrent stateとして扱うか」は、このフィクションの予約serviceが決めたapplicationの仕事だ。

この練習用clientがdisplayedRemainingを送る設計も、すべての予約APIに共通する形ではない。

ユイが、requestの二行へ別々の札を置いた。

seatId: 12 予約したい対象

displayedRemaining: 1 clientで見えていた値

ユイ

requestは、相手が望む成功結果そのものではないんですね

ピコ

うん。何を頼まれたかを読み、server側のruleで処理して、結果をresponseにする

残り十五秒。

serverは、箱の名前ではなく役割

サーバー応答室の中央で、予約を処理するprogramがrequestを受け取った。

このconnectionでは、そのprogramがserverだ。

serverは、requestをserviceするためにconnectionを受け、responseを送るprogramの役割を指す。

大きな黒い機械だけをserverと呼ぶわけではない。

一台のmachineで動くことも、いくつもの役割に分かれることもある。HTTPは、同じinterfaceの奥でserviceをどう実装したかまでは決めない。

さらに、clientとserverは永久に固定された名前ではない。

RFC 9110では、同じprogramが、あるconnectionではclient、別のconnectionではserverとして働く場合がある。

今回の予約programもそうだった。

  1. browserから予約requestを受けるときはserver
  2. current seatをledger serviceへ尋ねるときはclient
  3. ledgerの返事を使い、browserへfinal responseを返すときはserver

イトは、応答室の奥に一つの巨大な真実の箱があると思っていた。

実際には、役割から役割へrequestとresponseがつながっている。

「どこにある箱か」だけでは、いま何をしているかは分からない。

三つの返事札

残り十二秒。

ピコが、三枚の札を机へ並べた。

  1. 古い1を写す
  2. ledgerを全部返す
  3. 12番席だけを確かめる

一枚目なら、requestのdisplayedRemaining: 1をresponseへ写し、予約成功にできる。速い。けれど、server側のcurrent stateを一度も見ない。

二枚目なら、予約者名を含むledgerをすべてclientへ返し、client側で空席を考えてもらえる。しかし、12番席が空いているかという問いに、全員の記録は必要ない。

三枚目なら、serverが12番席とcurrent remainingだけをledger serviceへ尋ね、予約ruleを適用できる。結果を待つ時間がかかり、clientが望む「成功」にならない可能性もある。

待っているclientの輪が、黄色から橙へ変わった。

「早く返して」と光っている。

青い成功札を入れれば、一瞬で輪は消える。

でも、その先には一つしかない12番席がある。

ピコ

どの返事にする?

マコト

clientを喜ばせる答えと、処理した結果は、同じとは限らない

イトはrequestの古い1へ、小さな札を重ねた。

clientで見えた値

「これは、席の計算から外す」

青い成功札を棚へ戻し、12番席だけをledger serviceへ送った。

current stateからresponseを組み立てる

残り八秒。

ledger serviceから、短い返事が戻った。

{
  "seatId": 12,
  "reserved": true,
  "remaining": 0
}

予約programは、browserから見るとserverだった。

ledgerへ尋ねる瞬間にはclientになり、返ってきたcurrent stateを読んだ。

イトは、予約ruleを確認する。

すでにreservedの席へ、二枚目の予約札をつけない

そしてfinal responseを組み立てた。

409 Conflict
{
  "reserved": false,
  "remaining": 0,
  "reason": "already_taken"
}

responseにはstatus codeがあり、必要に応じてheaderやcontentが入る。status codeは、requestを処理した結果をclientが解釈する手がかりになる。

RFC 9110のstatus codeはresponse resultの意味を定める。今回の409とbodyは、この予約serviceが「current stateとの衝突」を伝える一つの設計例であり、すべてのserviceが同じ形を返すとは限らない。

残り四秒。

イトが、赤い0のresponseをclientへ返した。

望まれなかったnoが、席を一つに保った

待っていたclientの青い1が消えた。

残り0席

予約buttonは「満席」へ変わる。

clientが望んだ予約は、成立しなかった。

けれど、12番席にある予約札は一枚のままだ。

二人を同じ椅子へ案内する二枚目の札は作られなかった。

イトがrequest封筒の古い1の札を計算路から外し、current ledgerの一枚だけ予約済みの座席を確認して、0のresponse札を待つclientへ返している
clientの願いをそのまま成功にせず、対象のcurrent stateを確かめて、期待に反する0を返す。

イトは、古い1の札を捨てなかった。

request封筒の内側へ戻し、「clientで見えていた値」として残した。

間違った数字ではない。

ただ、serverが予約結果を決めるための現在値ではなかった。

serverは、clientの言うことを何でも否定する係でも、いつも正しい答えが眠る箱でもない。

requestの意図とtargetを読み、applicationのruleに沿って必要な処理をし、その結果をstatusとcontentにして返す役割だ。

今回イトが信じたのは、「serverと呼ばれるものなら正しい」という名前ではなかった。

12番席というtarget、current ledger、二重予約を作らないruleの三つだった。

pageそのものを求めるrequest

上映室の扉が閉まった。

最後のresponseは、その前にclientへ届いた。

応答室が静かになった瞬間、別の入口で新しい封筒が光った。

GET /screenings/finale

新しく来た端末は、残席dataだけではなく、上映案内のpageそのものを求めている。

HTML。

CSS。

JavaScript。

画像。

browserが組み立てる材料を、どの受付が返すのか。

イトは、応答室の隣にある明るい窓口を見た。

そこには、Web serverの札がかかっている。

次回:Webサーバーはどんな係?

予約serverは、current seatを確かめて、残席0のresponseを返した。

けれど、serverという役割は広い。

pageを求めるrequestには、どの材料を、どんな順番で返すのか。

次回、ピコルート第13話。

Webページの材料を返す受付へ進む。

画面のむこう側をもっと知る

物語で見たclient、server、request、responseの役割を図で整理するなら、サーバーとはで確かめられます。

この物語を、解説で深める

第12話で生まれた疑問を、解説記事で少し深く見ていきます。物語で感じた不思議さを残したまま、言葉と仕組みを順番に整理しましょう。

サーバーとは?初心者向けに役割とクライアントとの違いを解説を読む