在脚本中添加多线程/ concurency

时间:2016-06-01 09:28:12

标签: ruby multithreading concurrency

我创建了一个脚本,用于检查填充了微服务的.json文件中的healthcheck和ports状态。 因此,对于.json文件中的每个微服务,脚本将输出HTTP状态和healthcheck主体以及其他小细节,我想在此处添加多线程以便立即返回所有输出。请参阅下面的脚本:

#!/usr/bin/env ruby
... get the environment argument part...

file = File.read('./services.json')
data_hash = JSON.parse(file)

threads = []
service = data_hash.keys
service.each do |microservice|
threads << Thread.new do
  begin
  puts "Microservice: #{microservice}"
  port = data_hash["#{microservice}"]['port']
  puts "Port: #{port}"

  nodes = "knife search 'chef_environment:#{env} AND recipe:#{microservice}' -i"
  node = %x[ #{nodes} ].split
    node.each do |n|
    puts "Node: #{n}"
    uri = URI("http://#{n}:#{port}/healthcheck?count=10")
    res = Net::HTTP.get_response(uri)
    status = Net::HTTP.get(uri)
    puts res.code
    puts status
    puts res.message
  end

rescue Net::ReadTimeout
  puts "ReadTimeout Error"
  next
end
end
end
threads.each do |thread|
  thread.join
end

无论如何,脚本首先返回puts“Microservice:#{microservice}”并输入“Port:#{port}”,之后它将返回节点并且仅在STATUS之后。 如何将每个循环的所有数据一起返回?

2 个答案:

答案 0 :(得分:1)

而不是puts将输出写入变量(哈希)。 如果您在显示输出之前等待所有线程完成其工作,请使用ThreadsWait类。

require 'thwait'
file = File.read('./services.json')
data_hash = JSON.parse(file)

h = {}
threads = []
service = data_hash.keys
service.each do |microservice|
threads << Thread.new do
  thread_id = Thread.current.object_id.to_s(36)
  begin
  h[thread_id] = "Microservice: #{microservice}"
  port = data_hash["#{microservice}"]['port']
  h[thread_id] << "Port: #{port}"

  nodes = "knife search 'chef_environment:#{env} AND recipe:#{microservice}' -i"
  node = %x[ #{nodes} ].split
    node.each do |n|
    h[thread_id]<< "Node: #{n}"
    uri = URI("http://#{n}:#{port}/healthcheck?count=10")
    res = Net::HTTP.get_response(uri)
    status = Net::HTTP.get(uri)
    h[thread_id] << res.code
    h[thread_id] << status
    h[thread_id] << res.message
  end

rescue Net::ReadTimeout
  h[thread_id] << "ReadTimeout Error"
  next
end
end
end
threads.each do |thread|
  thread.join
end

# wait untill all threads finish their job
ThreadsWait.all_waits(*threads)

p h

[编辑]

ThreadsWait.all_waits(*threads)在上面的代码中是多余的,可以省略,因为行treads.each do |thread| thread.join end确实是完全相同的。

答案 1 :(得分:1)

不是在使用puts获取数据时输出数据,而是可以在字符串中收集所有数据,然后在结尾处puts收集一次。字符串可以使用<<运算符(在Ruby中作为方法实现),因此您可以初始化字符串,添加到字符串,然后在结尾输出它,如下所示:

report = ''
report << 'first thing'
report << 'second thing'
puts report

如果你愿意,你甚至可以将它们全部保存在一起并打印完毕。