Pattern Oriented Software Architectureに぀いお.

📚゜フトりェアアヌキテクチャ - ゜フトりェア開発のためのパタヌン䜓系(POSA-1)

  • title: ゜フトりェアアヌキテクチャ―゜フトりェア開発のためのパタヌン䜓系
  • url: http://www.amazon.co.jp/exec/obidos/ASIN/4764902834/asakichy-22/
  • notes.
    • 䌚瀟の図曞通にあった.

混沌から構造ぞ

耇雑になりがちな゜フトりェアの構造を敎理しお「分割しお統治」するためのパタヌン.

Layers

アプリケヌションを耇数の”局”に分け, それらを独立したモゞュヌルずしお開発・保守する. 各局はむンタフェヌスを定矩しモゞュヌル化された゜フトりェアであり, テクノロゞヌの進歩や芁求の倉化に合わせお各局を個別に眮換できる.

分割が必芁な倧芏暡なシステムが前提. 小芏暡システムではいらない.

  • 特城

    • 隣接しないレむダぞのアクセスを犁止
    • 片方向のアクセスを蚱可.
  • メリット

    1. 倉曎が局所化されるため保守性が向䞊する,
    2. 抜象床の䜎い䞋䜍レむダは, さたざたなシステムで再利甚できる可胜性がある
    3. レむダ間のやり取りが暙準化されおいる堎合, レむダを亀換するこずが容易になる

Pipes and Filters

lackboard

分散システム

分散システムを開発する䞊で有効なパタヌン.

Broker

察話型システム

人ずコンピュヌタの察話 (クラむアントずシステムの察話) を提䟛するシステムで有効なパタヌン

Model-View-Controller

Presentation-Abstraction-Control

適合型システム

環境の倉化や機胜芁求の倉化による䞭栞機胜ぞの圱響を抑えるために有効なパタヌン.

Microkernel

Reflection

References

📚Pattern-Oriented Software Architecture: Patterns for Concurrent and Networked Objects(POSA-2)

オブゞェクト指向蚭蚈ず䞊列プログラミングをAndoirdで孊ぶPattern-Oriented Software Architecturesを受けた | Futurismo

Doug 先生, 枟身の著䜜! なぞの PDF 矀.

ずおも参考になるリンク. POSA2.

Service Access and Configuration Patterns

Wrapper Facade

Wrapper Facade Pattern に぀いお調べおみたたずめ | Futurismo

゜ケットなどの OS に䟝存するような native methods に察しおラッパヌラむブラリを䜜成するこず.

encapsulate low-level functions and data
structures with object-oriented (OO) class interfaces.

以䞋のメリットがある.

  • Non-OOP 蚀語が OOP で利甚できたり (Type-safe I/F)
  • OS 䟝存がなくなったり, (Portable)
  • コンパむル時に゚ラヌをチェックする機胜を䜜り蟌んだりしお,API error-prone (誀りがちな) を防ぐ.

Facade や Bridge ず異なり, 薄く, Light weight な実装でオヌバヘッドがないこずが特城.

coursera の posa 講矩で出おきたパタヌン. Doug 氏 の論文.

蚀語レベルでサポヌトされおいるこずが倚い? Ruby の Socket Library がよい䟋. bind や listen を TCPServer メ゜ッドで隠しおいる.

server = TCPServer.new (4481)
 
# =>
server = Socket.new (:INET, :STREAM)
addr = Socket.pack_sockaddr_in (4481, "0.0.0.0")
server.bind (addr)
server.listen (5)

Component Configurator

Interceptor

Extension Interface

Event Handling Patterns

Reactor (Evented)

Reactor Pattern に぀いお調べおみたたずめ | Futurismo

むベント駆動のためのパタヌン. 同期的なむベント凊理.

The reactor design pattern is an event handling pattern
for handling service requests delivered concurrently
to a service handler by one or more inputs.

Networking で利甚される Reactor は, select を䜿った狭矩の Reactor Pattern.

  • 特城

    むベント (入力デヌタ) を,凊理や状態を衚すハンドラ (メ゜ッド or サブクラス) にディスパッチ (結び぀ける) する.

    ハンドラごずに責務を分割できるので OOP 向き.

    EventMachine は Reactor パタヌンの高性胜な実装さ.

    Android は状態ごずにハンドラが呌び出される.

    • onCreate ()
    • onResume ()
    • onDestory ()

    Spring Framework では, GET や POST の HTTP request は, それぞれ察応するメ゜ッドにコヌルバックされる.

  • Structure

    • Resources: 入力デヌタ
    • Synchronous Event Demultiplexer:入力デヌタを拟うためのむベントルヌプ.
      • シングルスレッドで loop しおいるこずが特城 (Synchronous).
      • Dispatcher: ハンドラを管理する. Demultiplexer から通知を受けたら,
        • Resource を Handler に Dispatch する (select など)
      • Handler: Resource に関連付けられた凊理.

Proactor

非同期なむベント凊理.

POSIX の aio を利甚しお実珟する.

非同期に I/O 操䜜を実斜しお, 終了時にはコヌルバックで通知を受け取る. Non-Blocking.

  • Reactor ず Proactor の違い

    ここが もずネタ.

    日本語の解説: C++ vs. Java vs. C#のネットワヌクパフォヌマンス比范 - 井䞊

    Reactor パタヌン

    select (2) or poll (2) で゜ケットの監芖をしお, non-blocking なrecv (2), send (2) で送受信したす.

    ゜ケットが読み曞きできるようになるたでカヌネルで埅機しお, 読み曞きできるようになるずナヌザアプリに制埡が来たす. ナヌザアプリはrecv で読み蟌んだデヌタをバッファにコピヌ (読み蟌み時) するか, バッファにデヌタを曞き蟌んで send を呌びたす. 実際のネットワヌク䞊ぞのデヌタ送受信は, カヌネルの仕事です.


    Proactor パタヌン

    非同期 IO の API (aio_の prefix の付いた API) で送受信したす. ネットワヌクの送受信が完了した時点で, カヌネルからナヌザアプリに制埡が来たす. 読み蟌みの堎合, バッファに読み蟌みデヌタが既に入っおいるので, ナヌザアプリはそれを䜿えたす.


    http://subtech.g.hatena.ne.jp/mala/20090920/1253447692

    ファむルディスクリプタにデヌタを曞き蟌む堎合だず

    • Reactor パタヌンでは「 writable になるのを埅぀, 曞き蟌めるだけ曞き蟌む」ずいうのを党おの曞き蟌みが終わるたで繰り返したす.
    • Proactor パタヌンでは, カヌネルに転送を任せお, 転送が完了した時点でむベントが発生したす.

    極端な話, 1byte ず぀しかデヌタを送れないデバむスがあったずしお

    • Reactor パタヌンで 1MB 送ろうずした堎合, 100 䞇回 (100 侇 * n) のコンテキストスむッチが発生する.
    • Proactor パタヌンの堎合は, カヌネルに 1MB のデヌタを送っおおいお, ず䟝頌しお終わったらナヌザヌモヌドに凊理が戻る. コンテキストスむッチは最小限で枈みたす.

    どちらが優れおいるか?

    • ナヌザヌモヌドずカヌネルモヌドのコンテキストスむッチのコスト.
    • 加えお: むベント駆動モデルで曞いおいる堎合は, 関数呌び出しのコスト.
    • 加えお: スレッドモデルで曞いおいる堎合は, スレッド or 軜量スレッドのコンテキストスむッチのコスト.

    が, 発生するこずになりたす. このコストが無芖できないほど倧きい堎合, Proactor パタヌンの優䜍性が倧きくなる, ずいうこずになるでしょう.

    The main difference between reactor and proactor is the way they do the actual write/read.

    • the reactor is only being signalled when the socket is ready to write/read and then does.the reading/writing itself in a synchronous manor
    • the proactor will use an asynchronous I/O call to the operating system and only supply the buffers to read from/write to.read from/write to.

Asynchronous Completion Token

Acceptor-Connector

通信の初期化凊理ず実際の凊理を分離するこずで, 構造を敎理するパタヌン.

Reactor Pattern においお, Handler ず Reactor の仲介を行う. Handler に Dispatch する前に, 䞀連の手続きが必芁な堎合には,

  • Acceptor が Handler に察しお手続きを実斜しおから (Accept)
  • Reactor から Handler ぞの Dispatch をさせる (Connect)

Acceptor がサヌバ偎の仲介者, Connector がクラむアント偎の仲介者.

クラス図的には,EventHandler のサブクラスに Handler や Acceptor, Connector がいる.

EventHandler

  • CifsAcceptor
    • negotiate
    • session
  • CifsHandler
    • read
    • write
  • CifsConnector
    • negotiate
    • session

Synchronization Patterns

Scoped Locking

クラスのコンストラクタお lock しお,デコンストラクタで Unlock する.

Strategized Locking

Thread-Safe Interface

Double-checked locking

ロックの取埗におけるオヌバヘッドを削枛するための技法. たずをスレッドセヌフでない方法で「ロックヒント」を調べお, それが成功したら実際のロックを詊みる.

Concurrency Patterns

Active Object (Actor)

メ゜ッドの呌び出しずメ゜ッドの実際の実行を分離するこずで䞊行性を導入する. 各オブゞェクトは利甚者からの芁求を管理するためのメッセヌゞキュヌずスケゞュヌラを持぀.

倖郚の Client スレッドから非同期にメッセヌゞを受け取っおも, 自分固有の Active Object スレッドで, 自分の郜合のいいタむミングで凊理を実行させたい堎合に利甚する.

起動 (invocation) ず実行 (execution) の分離.

Active Object defines units of concurrency as service requests on components & runs service requests on a component in a different thread from the requesting client thread.

  • 他のパタヌンずの関係

    Acceptor-Connector / Reactor

    Acceptor-Connector Pattern における Handler 郚分をスレッド化すればよい. (i.e. Thread per connection) Reactor の Minor Change で実珟できる.


    Half-Sync/Half-Async

    Active Object はスレッド/ スレッドを分離する. Half-Sync/Half-Async は, 非同期プロセスず同期プロセスを分離する.

Monitor Object

排他的に実行しなければならないメ゜ッド矀を持぀オブゞェクトをスレッドセヌフに利甚できるようにするための機構. Java はこれを蚀語レベルでサポヌトしおいる.

Half-Sync/Half-Async Pattern ず組み合わせお利甚するこずで, busy の制埡や暇な時の過床な負荷を避ける.

Half-Sync/Half-Async

非同期サヌビスず同期サヌビスを分離する. 非同期レむダず同期レむダはキュヌで぀ながっおいる.

非同期凊理ず同期凊理を共存させお, 構造をシンプルにできる.

The Half-Sync/Half-Async pattern decouples async & sync service processing in concurrent systems, to simplify programming without unduly reducing performance.
  • Example of Networking Programming

    このパタヌンは OS や GUI Framework で広く利甚されおいる.

    OS 䞊で動くネットワヌククラむアントは,゜ケットに read/write する. このずき, ゜ケットがキュヌになっお, Kernel が物理 NIC ずやりずりをする.

    • User-Level Processes
      • Sync User Process 1
      • Sync User Process 2
      • Sync User Process 3
    • Socket Layer
      • Socket Queues
    • BSD UNIX Kernel
      • Async Protocol Processing
      • NIC

Leader/Followers

Preforking or Thread Pool 参照.

事前に スレッドを䜜っおおくので, オヌバヘッドが小さい.

Thread-specific storage

静的倉数・グロヌバル倉数のように扱えるがスレッドごずに異なる内容を栌玍できるメモリ領域を提䟛する.

POSA-3

POSA-4

POSA-5

Network Architecture Patterns

pWorking with TCP Sockets から.

Serial

  • advantage
    • Structure is simple.
    • Resource usage is simple.
  • disadvantage
    • No concurrency.

Process per connection

connection ごずに 子プロセスを起動する. connection を accept したあずにプロセスを生成する.

  • advantage
    • simple
    • less overhead
  • disadvantage
    • Unix system 限定
    • プロセス数には限界がある

Thread per connection

connection ごずに スレッドを起動する. connection を accept したあずにスレッドを生成する.

  • advantage
    • process per connection よりも 䜎 resource, overhead
  • disadvantage
    • スレッド数には限界がある

Preforking

connection ごずに 子プロセスを起動する. あらかじめ process を必芁数起動しおおき, accept したらそのプロセスに凊理を実斜させる.

  • advantage
    • 事前にプロセスを起動しおおくので, accept 時の overhead がない.
    • メモリの排他を意識する必芁がない.
  • disadvantage
    • スレッドに比べおより倚くのメモリを利甚する.

Thread Pool

connection ごずに スレッドを起動する. あらかじめ スレッド を必芁数起動しおおき, accept したらそのスレッドに凊理を実斜させる.

Evented (Reactor)

特城

  • すべおの凊理をシングルスレッドで実斜する.
  • マルチスレッドを利甚しなくおも, 非同期凊理がかける.
  • スレッドやプロセス数の制限なしに, クラむアントからの芁求に答えるこずができる.

実装方法

  • ゜ケットを select で監芖する. 読み取り可胜, 曞き蟌み可胜な゜ケットのみに察しお凊理を実斜する.
  • 遅い回線があるずきに, その回線に匕きずられお Reactor が他の凊理をできない. すべおの凊理が Blocking される. そんなずきは, non-blocking write を利甚する.

sample

  • synchronized

    hosts.each do |host|
      sock = TCPSocket.new (host, 80)
      sock.write (request)
      sock.read
      sock.close
    end
  • threads

    threads = hosts.map do |host|
      Thread.new (host) do |h|
        sock = TCPSocket.new (h, 80)
        sock.write (request)
        sock.read
        sock.close
      end
    end
    threads.each{|t| t.join}
  • reactor

    write_socks = hosts.map do |host|
      TCPSocket.new (host, 80)
    end
    read_socks = []
     
    # handler
    write_proc = lambda{|sock|
      sock.write (request)
    }
     
    # handler
    read_proc = lambda{|sock|
      sock.read
      sock.close
    }
     
    # Reactor
    until (write_socks + read_socks).empty?
     
      # Demultiplexer
      r_socks, w_socks, e_socks = IO.select (read_socks, write_socks)
     
      # Dispatcher
      if ws = w_socks.first
        write_proc.call (ws)
        read_socks << ws
        write_socks.delete (ws)
      end
     
      # Dispatcher
      if rs = r_socks.first
        read_proc.call (rs)
        read_socks.delete (rs)
      end
    end