ruby rails + grape + sidekiq 项目实践

这里是ruby rails + grape + sidekiq的一段实践过程,新手过程,只作为一段记录;

1、ruby + rails

(1)搭建ruby rails 环境

Getting Started with Rails

(2)新建项目文件夹

rails news grape_test

ruby rails + grape + sidekiq 项目实践

此时在/usr/local/demo/目录下出现创建了项目文件夹grap_test;

(3)替换sqlite3为mysql

本地安装好mysql之后,再用gem安装mysql2适配器:

gem install mysql2

在gemfile文件中替换掉sqlite3:

# gem 'sqlite3'
gem 'mysql2'
# 替换掉sqlite3

然后修改config/database.yml中的参数:

# config/database.yml


#
default: &default
  adapter: mysql2
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000
  username: root
  password: 'ur password'

development:
  <<: *default
  database: twi

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: twi_test

production:
  <<: *default
  database: twi_pro

安装和配置好之后运行rails s会报没有找到数据库的错误,所以需要将数据库创建和迁移:

> rake db:create

> rake db:migrate

这之后的默认数据库就变成我们的mysql 了。

(4)安装grape

gem install grape

然后在gemfile中加入

gem 'grape'

(5)在application.rb中定义API文件所在的路径,然后grape会从routes入手读API对应的module和class,去application.rb定义的路径下寻找相应的module和class并执行其中的动作;

#application.rb

require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module GrapeTest
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.

    config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
	config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]

  end
end
#config/routes.rb

Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html


  mount Twitter::API => '/'

end
#api.rb


module Twitter
  class API < Grape::API
    version 'v1', using: :header, vendor: 'twitter'
    format :json
    prefix :api

    helpers do
      def current_user
        @current_user ||= User.authorize!(env)
      end

      def authenticate!
        error!('401 Unauthorized', 401) unless current_user
      end
    end

    resource :statuses do
      desc 'Return a public timeline.'
      get :public_timeline do
        Status.limit(20)
      end

      desc 'Return a personal timeline.'
      get :home_timeline do
        authenticate!
        current_user.statuses.limit(20)
      end

      desc 'Return a status.'
      params do
        requires :id, type: Integer, desc: 'Status id.'
      end
      route_param :id do
        get do
          Status.find(params[:id])
        end
      end

      desc 'Create a status.'
      params do
        requires :status, type: String, desc: 'Your status.'
      end
      post do
        authenticate!
        Status.create!({
          user: current_user,
          text: params[:status]
        })
      end

      desc 'Update a status.'
      params do
        requires :id, type: String, desc: 'Status ID.'
        requires :status, type: String, desc: 'Your status.'
      end
      put ':id' do
        authenticate!
        current_user.statuses.find(params[:id]).update({
          user: current_user,
          text: params[:status]
        })
      end

      desc 'Delete a status.'
      params do
        requires :id, type: String, desc: 'Status ID.'
      end
      delete ':id' do
        authenticate!
        current_user.statuses.find(params[:id]).destroy
      end
    end
  end
end

(6)测试

> rails s

浏览器输入:  http://localhost:3000/

ruby rails + grape + sidekiq 项目实践

 

2、sidekiq异步处理

(1)安装redis(macOS)

brew install redis

(2)配置redis和sidekiq

config/initializers/sidekiq.rb

# 初始化sidekiq和redis的配置

redis_server = '127.0.0.1'
redis_port = 6379 
redis_db_num = 0
redis_namespace = 'sik'
 
Sidekiq.configure_server do |config|
  config.redis = { url: "redis://#{redis_server}:#{redis_port}/#{redis_db_num}", namespace: redis_namespace }
end
 
Sidekiq.configure_client do |config|
  config.redis = { url: "redis://#{redis_server}:#{redis_port}/#{redis_db_num}", namespace: redis_namespace }
end
config/sidekiq.yml

:concurrency: 5 # 并发数
:pidfile: tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:queues:
- default
- [myqueue, 2]
 
development:
:concurrency: 5
staging:
:concurrency: 10
production:
:concurrency: 20

(3)新建sidekiq异步任务

sidekiq -g sidekiq:worker Hard # will create app/workers/hard_worker.rb
# Hard_worker.rb

class HardWorker
  include Sidekiq::Worker
  def perform(name, count)
    # do something
  end
end

在API中添加异步运行的任务:

# api.rb

    ...

    version 'v1', using: :header, vendor: 'twitter'
    format :json
    prefix :api

    HardWorker.perform_async('bob', 5)

    helpers do
      def current_user
        @current_user ||= User.authorize!(env)
      end

      ...

(4)测试

rails s 打开rails ,然后新打开一个终端:

> sidekiq

ruby rails + grape + sidekiq 项目实践

(5)监控jobs的执行情况:

routes.rb

require 'sidekiq/web'
mount Sidekiq::Web => '/sidekiq'

在浏览器中输入:http://localhost:3000/sidekiq/retries

ruby rails + grape + sidekiq 项目实践

待续...