次期MultiThread UltraMonkey-L7プログラムモデル検討


スレッドモデル UltraMonkey-L7(以下、l7vsd)が取り得るべきthread方式を以下に示す。

スレッド方式名メリットデメリット
woker方式既存の構造の延長でのマルチスレッドになるMQの構造などに対応できない
updown方式upstream側とdownstream側でthreadを分けることによりブロックせず動けるMQの構造に半分対応出来ない、工数が多い
side方式ClientSideとRealServerSideでthreadを分けることによりMQの構造に対応出来る工数が多い

これらの方式が存在するが、現状のLinuxKernelの方針からSide方式を検討する。 Side方式によるThreadの種類は以下の物がある。

スレッド種類概要
LisingスレッドVirtualService一つにつき一つ作られる。acceptしたらClientThreadに処理を引き渡す。
ClientSideスレッドClientからのデータ受信、データ送信を行うthread
RealServerSideスレッドRealServerからのデータ受信、データ送信を行うthread


上記スレッドが主要な種類になり、以下のような配置になる(他にもメインスレッドとバーチャルサービススレッドが考えられるがこれらはグルーピングの単位のため、ここでは考察しない。) l7vsd構造.png
この図ではまず、Client側NICにClintからの接続要求(赤い破線)がくるところから始まる。
MultiQueueを使っていたとしても全てのCPUでLisningSocketをbindしているわけにはいかないので、この部分は他のCPUからの割り込みがLisingScoketをbindしているCPUに入ってくることになる。
その後、acceptした時に、l7vsdはconnectionがどのCPUを使っているのかを判断し、図ではCPU1に割当たっているClientSideThreadに処理を引き継ぐ。
このClientSideThreadはCPUごとにpoolingする必要があり(threaqdのcreateは非常に重いため)、LisingThreadはconnectした通信がどのCPUを使っているのかを判断し、該当のCPUに結びついているThreadPoolからThreadを引き出す。 threadpool構造.png
図にあるようにLisningしているThreadは一つでかつ、シリアライズされる部分。
acceptしたときに接続が使用しているCPUにくくりつけられたThreadPool(ThreadPoolの中にあるThreadは全てcpu affinityでCPUに結びついています)よりThreadを引き出して処理を引き出したThreadに委任する。
LisningThreadの仕事はここまでで、再びLisningThreadは次のaccept処理のloopに入る。
ClientSideSocketはRealServerSideThreadを該当のThreadPoolより引き出してActiveにする。
ちなみにThreadがPoolに戻るタイミングは、自分と対向側のコネクションが切断された場合であり、それぞれのthreadがばらばらに(どのタイミングになるかは予測できない)に戻る。
タイミングによってはThreadPoolへ集中して戻される事象の発生が予測されるため、ThreadPoolのプログラミングは非常に考慮する必要がある。