您的位置:首页 > 其它

zeroMQ初体验-23.可靠性-懒惰的海盗模式

2011-10-10 15:33 399 查看
相较于通常的阻塞模式,这里只是做了一点简单的动作来加强系统的可靠性(不再是通常性质的阻塞了)。

这种模式增加/变更了以下几点:

轮询已经发出的请求直到得到响应
在一定时间内未得到相应则重新发出请求
在一定次数的重试不成功之后,停止请求

相较于传统的阻塞模式,好处显而易见:在未得到答复时可以继续发出请求而不是碰到预料之外的报错之类信息。(zeromq还默默地为你做了这么件事:当链路出现问题,它会悄悄的重新建立一个~)



client:

Ruby代码






require 'rubygems'
require 'zmq'

class LPClient
  def initialize(connect, retries = nil, timeout = nil)
    @connect = connect
    @retries = (retries || 3).to_i
    @timeout = (timeout || 3).to_i
    @ctx = ZMQ::Context.new(1)
    client_sock
    at_exit do
      @socket.close
    end
  end
  
  def client_sock
    @socket = @ctx.socket(ZMQ::REQ)
    @socket.setsockopt(ZMQ::LINGER, 0)
    @socket.connect(@connect)
  end

  def send(message)
    @retries.times do |tries|
      raise("Send: #{message} failed") unless @socket.send(message)
      if ZMQ.select( [@socket], nil, nil, @timeout)

        yield @socket.recv
        return
      else
        @socket.close
        client_sock
      end
    end
    raise 'Server down'
  end
      
end

if $0 == FILE
    server = LPClient.new(ARGV[0] || "tcp://localhost:5555", ARGV[1], ARGV[2])
    count = 0
    loop do
      request = "#{count}"
      count += 1
      server.send(request) do |reply|
        if reply == request
          puts("I: server replied OK (#{reply})")
        else
          puts("E: malformed reply from server: #{reply}")
        end
      end
    end
    puts 'success'
end

require 'rubygems'
require 'zmq'

class LPClient
  def initialize(connect, retries = nil, timeout = nil)
    @connect = connect
    @retries = (retries || 3).to_i
    @timeout = (timeout || 3).to_i
    @ctx = ZMQ::Context.new(1)
    client_sock
    at_exit do
      @socket.close
    end
  end
  
  def client_sock
    @socket = @ctx.socket(ZMQ::REQ)
    @socket.setsockopt(ZMQ::LINGER, 0)
    @socket.connect(@connect)
  end

  def send(message)
    @retries.times do |tries|
      raise("Send: #{message} failed") unless @socket.send(message)
      if ZMQ.select( [@socket], nil, nil, @timeout)
        yield @socket.recv
        return
      else
        @socket.close
        client_sock
      end
    end
    raise 'Server down'
  end
      
end

if $0 == FILE
    server = LPClient.new(ARGV[0] || "tcp://localhost:5555", ARGV[1], ARGV[2])
    count = 0
    loop do
      request = "#{count}"
      count += 1
      server.send(request) do |reply|
        if reply == request
          puts("I: server replied OK (#{reply})")
        else
          puts("E: malformed reply from server: #{reply}")
        end
      end
    end
    puts 'success'
end


server:

Ruby代码






require 'rubygems'
require 'zmq'

class LPServer
  def initialize(connect)
    @ctx = ZMQ::Context.new(1)
    @socket = @ctx.socket(ZMQ::REP)
    @socket.bind(connect)
  end

  def run
    begin
      loop do
        rsl = yield @socket.recv
        @socket.send rsl
      end
    ensure
      @socket.close
      @ctx.close
    end
  end
      
end

if $0 == FILE
  cycles = 0
  srand
  LPServer.new(ARGV[0] || "tcp://*:5555").run do |request|
    cycles += 1
    if cycles > 3
      if rand(3) == 0
        puts "I: simulating a crash"
        break
      elsif rand(3) == 0
        puts "I: simulating CPU overload"
        sleep(3)
      end
    end
    puts "I: normal request (#{request})"
    sleep(1)
    request
  end
    
end

require 'rubygems'
require 'zmq'

class LPServer
  def initialize(connect)
    @ctx = ZMQ::Context.new(1)
    @socket = @ctx.socket(ZMQ::REP)
    @socket.bind(connect)
  end

  def run
    begin
      loop do
        rsl = yield @socket.recv
        @socket.send rsl
      end
    ensure
      @socket.close
      @ctx.close
    end
  end
      
end

if $0 == FILE
  cycles = 0
  srand
  LPServer.new(ARGV[0] || "tcp://*:5555").run do |request|
    cycles += 1
    if cycles > 3
      if rand(3) == 0
        puts "I: simulating a crash"
        break
      elsif rand(3) == 0
        puts "I: simulating CPU overload"
        sleep(3)
      end
    end
    puts "I: normal request (#{request})"
    sleep(1)
    request
  end
    
end


优点:

1.容易理解和实施

2.容易并入到现有的工程项目中

3.zeromq帮助解决了一部分比较麻烦的底层实现

缺点:

没有故障转移(如果server出现了问题,只有死等了~)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: