ruby 真是内存大户啊~
我的小破站运行在阿里云 1g 内存上,mysql+sidekiq+puma 这三个内存大户吃了大部分的内存。
时不时从 swap 交换数据的时候,整个系统的负载就飙升,top NO.1 只看到个 kswap[xxx] 的进程。
所以我决定将 MEM NO.1 的 sidekiq 去掉。
于是就用写了这个程序 https://github.com/molisoft/rkejob/
除了是一个队列(感觉这样改进后,更像是将请求异步化了),还是一个定时任务工具(因为我之前用 Sidetiq 作为定时任务工具)
之前的 rails 的队列流程如下:
rails -> redis -> sidekiq(Runing)
现在的流程:
rails -> redis -> rkejob ---(POST)---> rails
什么?!最后请求又请求回来了?没错啊,最后又是 rails web 端来执行队列任务了。所以相当于将“请求异步化”了~~~
这样的设计,其实就注定不适合做那种分分钟耗时数分钟,数十分钟的任务了~~~ 请酌情使用~~~ 保平安
在 rkejob 程序的同目录下新建配置 config.yml
redis:
host: localhost
port: 6379
queue:
pool: 30
concurrency: 3
namespace: "namespace_sidekiq"
database: 0
queues:
- default
job:
url: "https://www.xxx.com/myjobs"
crons:
-
name: "CheckServerStatus"
url: "https://www.xxx.com/mycrons"
spec: "0 0 3 * * *" # 每天凌晨3点运行
-
name: "CheckXXXXXStatus"
url: "https://www.xxx.com/mycrons"
spec: "@every 10m"
这样每一个队列任务都会被请求到 job.url 这个配置中,顺便会 sidekiq 请求过去的参数也一并请求到 rails-web 中了,下面会介绍 rails-web 端怎么处理这些数据。
crons 就是配置定时任务了~
rails 这边需要做呢?几乎不需要做任何任务改动,只需要加 2 个 action,分别处理 job 和 cron。
require 'yaml'
# 这个比较重要哦~ 因为写入到redis中的数据是可以直接被yaml解析成ruby代码的,会出问题,所以这个加个猴子补丁~~
Psych::Visitors::ToRuby.prepend Module.new {
def resolve_class(klass_name)
klass_name && klass_name.safe_constantize || super
end
}
class MyJobsController < ApplicationController
skip_before_action :verify_authenticity_token, :only => [:myjobs, :mycron]
before_action :only_local
# 队列
#
def myjobs
request_body = request.raw_post
(target, method_name, args) = YAML.load(request_body)
if target.to_s == 'Mailer'
eval("#{target}.#{method_name}(*args)").deliver_now()
else
eval("#{target}.new.#{method_name}(*args)")
end
render :text => 'success'
end
# 定时任务
#
def mycron
target = request.raw_post
eval("#{target}.new.perform()")
render :text => 'success'
end
private
# 这里最好加验证,禁止外网请求 :)你懂的
def only_local
# if request.remote_ip != '127.0.0.1'
# redirect_to root_path
# end
end
end
已在我的小破站上跑了几天了~~ 看日志来看~~~ 还可以~~~
golang 真是不错啊~~~