我正在开发服务器,因此开发了一个用于测试的客户端脚本。如果我启动多个/多个命令处理器并使用“ruby client.rb”在每个命令处理器中启动它,则此客户端脚本运行良好。为了使这个过程更有效,我正在尝试编写一个父脚本“threads.rb”,它可以使用线程激发尽可能多的客户端。它们都启动但只有最后一个在使用threads.rb时有效运行。
client.rb可以访问Redis,我在那里使用互斥锁来防止冲突。我没有锁定客户端的其他部分,也没有做任何事情来防止其中的问题。我希望能够使用threads.rb,因为client.rb可以在多个命令处理器中运行
threads.rb是:
threads = 4
the_threads = []
(1..threads).each do |thread|
puts "Creating thread #{thread}"
the_threads << Thread.new(thread) do |t|
puts "Running Client #{thread};\n"
load "./samples/client.rb"
end
end
client.rb
%w(rubygems bundler faye/websocket eventmachine json redis redis-classy redis-mutex).each { |m| require m }
Dir["./lib/*.rb", "./lib/**/*.rb"].each { |file| require file }
class ClientWs
def self.em_run
EM.run do
puts "EM is running."
uri = 'localhost'
redis_uri = URI.parse("redis://127.0.0.1:6379")
redis ||= Redis.new(host: redis_uri.host, port: redis_uri.port, password: redis_uri.password)
RedisClassy.redis = Redis.new(host: redis_uri.host, port: redis_uri.port, password: redis_uri.password)
mutex = RedisMutex.new(:device, block: 0.5, sleep: 0.5)
if mutex.lock
device = 0
channel = 100
type = 'Reader'
begin
channel += 1
type = type == 'Display' ? 'Reader' : 'Display'
device += 1 if type == 'Display'
lockbox = "Lbox_#{device}"
unit = "#{lockbox}.#{type}.Status"
status = redis.get(unit)
end until status.nil? || !status
channel = type == 'Reader' ? "RDR:#{channel}" : "DSP:#{channel}"
result = redis.set(unit, 'Offline')
puts "Connecting with:#{unit}; Using channel:#{channel};"
url = uri == 'localhost' ? "ws://#{uri}:3000/#{channel}" : "ws://#{uri}/#{channel}"
puts url
@ws = Faye::WebSocket::Client.new(url)
start = Time.now
count ||= 0
mutex.unlock
else
puts 'RedisMutex failed to obtain mutex lock.'
exit
end
timer = EventMachine.add_periodic_timer(5+rand(5)) {
count += 1
count.even? ? send({"ECHO": {"CMD": "PING"}}) : send({"CMD": "PING"})
Thread.pass
}
@ws.on :open do |event|
ClientWs.send({"OPEN": lockbox})
end
@ws.on :message do |event|
@ip_address ||= Addrinfo.ip(URI.parse(event.target.url).host).ip_address
begin
parsed = JSON.parse event.data
rescue => e
puts ">>>> [Error! Failed to parse JSON]"
puts ">>>> [#{e.message}]"
puts ">>>> #{event.data}"
end
puts ">> #{@ip_address}:#{channel}:#{event.data};"
#@ws.close
end
@ws.on :close do |event|
timer.cancel
stop = Time.now - start
result = redis.del(unit)
puts "#{stop} seconds;"
p [:close, event.code, event.reason]
ws = nil
ClientWs.em_run
end
end
end
def self.send message
payload = message.is_a?(Hash) ? message : {payload: message}
@ws.send(payload.to_json)
end
end
ClientWs.em_run
答案 0 :(得分:0)
我将它转换为使用Kernel#spawn代替线程。
the_pids = []
(1..pids).each do |pid|
puts "Running Client #{pid};\n"
Dir.chdir("D:/projects/wsserver/")
the_pids << spawn(RbConfig.ruby, "./samples/client.rb")
end