Your SlideShare is downloading. ×
大江戸Ruby会議01 "mission critical"なシステムでも使えるThreadの作り方
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

大江戸Ruby会議01 "mission critical"なシステムでも使えるThreadの作り方

3,653

Published on

2011/04/10 (日) @深川江戸資料館レクホール

2011/04/10 (日) @深川江戸資料館レクホール

3 Comments
6 Likes
Statistics
Notes
  • ・識別子で思い出しましたが、Thread[;name]に’logger’とか’worker-1’とか固有名を入れて、Threadモニタでその名前を出すようにしたことがあります。似たようなのがあれば標準に提案しませんか。

    ・’aborting’で時間がかかることがあるんですね。。。やってみないとわからない情報なんでしょうねえ。ありがとうございます。

    ・ThreadとSocketの両資源が残っているときにThread#killで回収しようとすると、Socket資源がリークしたりするので、Thread#raiseなどで先にSocketを別の方法で回収、というのが「お行儀のよい」方法だと思います。でも、bindだと資源はリークしないかもだし、きれいごと言ってるだけかもしれません。次の機会があればbindに気をつけてみます。
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • nahiさん、コメントありがとうございます。

    ・th_infosは、サンプルコードではHashのkeyにカウンタ-を使っているのですが、
     複数プロセス × 複数スレッドの中で、固有の識別IDになる値をkeyにすることを想定しています。  →サンプルコードは分かりやすくするために、配列にした方がよかったですね。

    ・Thread#alive? だと、’aborting’ もtrueを返すので、異常なThreadを早く検知し、
     再起動するために、statusを使っています。
     statusの適切な更新が難しいというのは、知らなかったので、今後検討したいと思います…。

    ・Thread#kill については、Thread#alive? がfalse を返す場合ならよいのですが、
     Thread#alive?がtrue(または、status が’run’ ) を返して、
     Threadのループ内で更新させる情報(Slide内のThreadWatch#valid? )で
     異常と判断された場合には、Thread#killは必要だと思うのですが、いかがでしょうか?
     →各Thread で、socket をbind() しているような場合、
      Threadを停止(kill)してからでないと、bind()エラーが出ていた記憶があります。
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • ・th_infosがArrayでなくてHashなのはなぜなんでしたっけ。

    ・Thread#statusを’run’もしくは’sleep’で比較するのでなく、Thread#alive?を呼んでほしいです。JRubyのようなGILなし環境だと、statusを適切に更新するのが難しいので。。。

    ・今の構成だと、Thread#kill -> Thread#joinが絶対に刺さらないようにする必要があります。ensureでIO#closeとかやったり、ログ書き出し→その先のMutex取れず、などのパターンで刺さると、メインスレッドが止まるので。Thread#kill!だとリークする可能性もあるので、daemon系ではThread#kill系列は基本避けたほうがよいと思います。

    ・と、ここまで書いておいてなんですが、!th.alive?であれば、killとか意味ないかも?
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
3,653
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
3
Likes
6
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. 江森 真由美
    “mission critical”なシステムでも使える Thread の作り方
  • 2. プロフィール
    江森 真由美 (@emorima)
    (株)ケーシーエスキャロット
           ユニットマネージャ
    2004年からRubyを使用
  • 3. “mission critical”なシステムとは?
  • 4. “mission “critical”
    24時間365日、止まらないことを要求される基幹業務、あるいは、そのような業務遂行のために使用されるコンピュータシステムのこと。(中略)
    このような業務に使用されるシステムには、極めて高い信頼性や耐障害性、障害発生時に被害を最小に食い止める様々な機能、万全のサポート体制などが必要となる。
             (IT用語辞典 e-Wordsより)
  • 5. Threadを作る上でのポイント
    メインスレッドでは、
    起動したスレッドの状態を監視する。
    起動したスレッドの状態が異常の場合、スレッドを再起動する。
  • 6. defself.thread_main(idx)
    loop do
    #スレッド処理
    end
    end
    defself.main(argv)
    th_infos = Hash.new
    foriin0…100
    th_infos[i] =Thread.new(i){|idx| thread_main(idx)}
    end
    check_threads(th_infos)
    end
  • 7. defself.check_threads(th_infos)
    loop do
    th_infos.eachdo |i, th|
    f_restart = false
    caseth.status
    when“run”, “sleep”
    else
    f_restart = true
    end
    iff_restart
    th.kill
    th.join
    th_infos[i] =
    Thread.new(i) {|idx| thread_main(idx)}
    end
    end
    sleep1
    end
    end
  • 8. でも、これでは不十分
    「万が一」

    考える必要がある
  • 9. 「万が一」
    Threadが
    刺さっても
    何とか
    しないといけない
  • 10. どうするか?
    少し状況を変えて
    考えてみましょう
  • 11. 順調です
    順調です
    (嘘だけど)
    Aさん
    日報・週報
    提出
    Bさん
    遅れて
    ます
    ???
    Dさん
    Cさん
    管理者
  • 12. Threadのループ内で
    情報更新(報告)
    その内容で判断する
  • 13. classThreadWatch
    definitialize(timer)
    @update_time = nil
    @alive_timer = timer
    @mutex = Mutex.new
    end
    defupdate
    @mutex.synchronizedo
    @update_time = Time.now
    end
    end
    def valid?
    @mutex.synchronizedo
    returnfalseif!@update_time.nil? &&
    (Time.now - @update_time) > @alive_timer)
    end
    true
    end
    end
  • 14. defself.thread_main(idx, watch)
    loop do
    watch.update
    #スレッド処理
    end
    end
    defself.main(argv)
    th_infos = Hash.new
    foriin0…100
    w = ThreadWatch.new(600)
    th = Thread.new(i, w) do |idx, watch|
    thread_main(idx, watch)
    end
    th_infos[i] =[th, w]
    end
    check_threads(th_infos)
    end
  • 15. defself.check_threads(th_infos)
    loop do
    th_infos.eachdo |i, info|
    th, w = info
    f_restart = false
    caseth.status
    when“run”, “sleep”
    f_restart = true unless w.valid?
    else
    f_restart = true
    end
    iff_restart
    th.kill
    th.join
    th = Thread.new(i, w) do |idx, watch|
    thread_main(idx, watch)
    end
    th_infos[i] = [th, w]
    end
    end
    end
    end
  • 16. テスト
    テストの話も
    しないと…
    Rubyだし。
  • 17. テスト
    無限ループの
    テストって
    どうすれば???
  • 18. 無限ループのテスト
    loop do がある限り、処理が返ってこないため、テスト確認ができない。
    • ループ処理は、変数やメソッドでループの実行判定をするようにする。
  • defself.thread_main(idx, watch)
    while run?
    watch.update
    #スレッド処理
    end
    end
    defself.run?
    true
    end
  • 19. describe OedoThread, “thread_main”do
    class OedoThread
    @@counter = 0
    def self.run?
    @@counter += 1
    return false if @@counter > 3
    true
    end
    end
    it “call 3 times” do
    m_watch = mock(“thread watch”)
    m_watch.should_receive(:update).exactly(3)
    OedoThread.thread_main(1, m_watch)
    end
    end
  • 20. まとめ
    “mission critical”なシステムでThreadを使う場合
    Threadのチェックは、Thread.statusの状態チェックだけではなく、Thread側での更新チェックも実装する。
    チェック結果が異常な場合には、Threadは再起動する。
    loop do を使うとテストが書けないため、ループを実行するかどうかを判定するメソッド(または変数)を作成する。
  • 21. ご静聴
    ありがとう
    ございました

×