Я склонен использовать этот подход во всех вызовах функции от HTML attributes:-
onclick="SomeMethod.call(this)"
Тогда в javascript do:-
function SomeMethod()
{
this.setAttribute('name', this.id);
}
, Это имеет явное преимущество, когда можно также присвоиться непосредственно к свойствам обработчика событий в Javascript code:-
document.getElementById("someID").onclick = SomeMethod
, Если бы SomeMethod взял элемент контекста в качестве параметра, это было бы очень неудобный установить up:-
function(id) {
var elem = document.getElementById(id)
elem.onclick = function() { SomeMethod(elem); }
}("someID");
, Хуже все же, это было бы закрытием утечки памяти.
Некоторые мысли ...
Просто потому, что вам нужно прочитать 50 сайтов и, естественно, вы хотите параллельная работа не означает, что вам нужно 50 процессов или потоков. Вам нужно сбалансировать замедление и накладные расходы. Как насчет того, чтобы 10 или 20 процессов читали несколько сайтов каждый?
В зависимости от того, какой Ruby вы используете, будьте осторожны с зелеными потоками, вы можете не получить желаемый параллельный результат.
Возможно, вы захотите структурировать его как обратный, клиентский inetd, и используйте connect_nonblock
и IO.select
, чтобы получить нужные параллельные соединения, заставив все серверы отвечать параллельно. Вам действительно не нужна параллельная обработка результатов, вам просто нужно встать в очередь на всех серверах параллельно, потому что именно там задержка действительно есть.
Итак, что-то вроде этого из библиотеки сокетов ... расширите его для нескольких незавершенных соединений ...
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(80, 'www.google.com')
begin
socket.connect_nonblock(sockaddr)
rescue Errno::EINPROGRESS
IO.select(nil, [socket])
begin
socket.connect_nonblock(sockaddr)
rescue Errno::EISCONN
end
end
socket.write("GET / HTTP/1.0\r\n\r\n")
# here perhaps insert IO.select. You may not need multiple threads OR multiple
# processes with this technique, but if you do insert them here
results = socket.read
На самом деле можно запустить несколько рабочих процессов delayed_job.
Из http://github.com/collectiveidea/delayed_job :
# Runs two workers in separate processes.
$ RAILS_ENV=production script/delayed_job -n 2 start
$ RAILS_ENV=production script/delayed_job stop
Итак, теоретически, вы можете просто выполнить:
$ RAILS_ENV=production script/delayed_job -n 50 start
Это вызовет 50 процессов, однако я не уверен, будет ли это рекомендовано в зависимости от ресурсов системы, в которой вы это используете.
Альтернативным вариантом было бы использование потоков . Просто создайте новый поток для каждого из ваших заданий.
При использовании этого метода следует помнить, что ActiveRecord
не является потокобезопасным. Вы можете сделать его поточно-ориентированным, используя следующие параметры:
ActiveRecord::Base.allow_concurrency = true
Поскольку вы работаете с рельсами, я бы посоветовал вам использовать для этого delayed_job вместо разделения на потоки или вилки. Причина в том, что обработка тайм-аутов и прочего, когда браузер ожидает, может быть настоящей болью. Есть два подхода, которые вы можете использовать с DJ
. Первый - создать 50+ рабочих. В зависимости от вашей среды это может быть довольно тяжелое решение для памяти, но оно отлично работает. Затем, когда вам нужно выполнить задание, просто создайте 50 уникальных заданий. Если слишком много памяти и вы хотите делать что-то таким образом, создайте отдельную среду, урезанную специально для ваших рабочих.
Второй способ - создать отдельное задание, которое использует Curl :: Multi для запуска ваши 50 одновременных TCP-запросов. Подробнее об этом можно узнать здесь: http: //curl-multi.rubyforge.