5/08/2019

Rails에서 SuckerPunch를 이용한 비동기 Thread 처리(single-process Ruby asynchronous processing library)

Rails 구동중에 쓰레드 처리 시 아래처럼 원래 루비 구문인 Thread로 처리할 수 있습니다.

Thread.new do
  Rails.application.executor.wrap do
    system('ping -c 5 127.0.0.1')
    result = Net::HTTP.get(URI.parse("http://127.0.0.1:3000/zfd"))
    puts result
  end
end

다만 이런 쓰레드에 대한 관리를 매번 해줘야한다는 것과 공통적으로 사용되는 쓰레드를 구현하기 위해선 조금 번거로운 부분들이 있습니다. 오늘 이야기드릴 라이브러리는 레일즈에서 쓰레드 사용을 위한 그런 라이브러리입니다.

suckerpunch 입니다.

I am HIT-Library? zz

What is? & How to use

SuckerPunch는 위에서 이야기드린대로 쓰레드 관련 라이브러리이고, 정확히는 단일 Ruby 프로세스에서의 비동기 처리 라이브러리입니다. 단일 어플리케이션 내부에서 Jobs을 생성하고 관리할 수 있기 때문에 Heroku같은 PaaS 환경에서 메모리나 비용적으로 효율적으로 사용할 수 있습니다.

다만 단일 프로세스 위에서 동작하기 때문에 모체가 되는 프로세스가 재시작되면 당연히 초기화됩니다.

https://github.com/brandonhilkert/sucker_punch

해당 라이브러리는 gem 패키지로 gem install 명령또는 Gemfile 이후 bundle install로 설치할 수 있습니다.

Install with gem
gem install suckerpunch

Gemfile
gem 'sucker_punch', '~> 2.0'

설치 후 앱 내부에선 SuckerPunch를 Include로 모듈을 로드하여 구현해주시면 됩니다. 제가 재미삼아 만드는 앱인데, 대략 코드를 보면 이렇습니다. (Rails에요)

controller
def action
  @log = Log.new(log_params)
  url = log_params["host"]
  hwulTest.new.scan_spider(url, @log)
  # 아래 hwulTest class에서 객체를 생성하고 멤버함수를 실행합니다.
end

# ... 생략 ...

class hwulTest
  include SuckerPunch::Job
  # SuckerPunch => Job 모듈을 가져옵니다.

  def scan_spider(url, obj)
    ActiveRecord::Base.connection_pool.with_connection do
      payload = "http://127.0.0.1:8081/JSON/~~~blahblah"
      res = HTTP.get(payload).body
      res = ActiveSupport::JSON.decode(res)

      p res["scan"]
      data = obj
      data.update(state:true) 
      data.update(data: res["scan"].to_i)
    end
  end
end

이렇게 했을 때 해당 컨트롤러에서 action 이 호출됬을 때 레일즈 메인 로직은 원하는 구문 처리 후 정상적으로 결과를 리턴해주고, hwulTest로 정의한 기능은 비동기로 백그라운드 처리됩니다.

일해라 job들아!

Built-In

찾다보니 빌트인도 가능했었네요..

Rails
rails g sucker_punch:job logger

Sinatra
# app.rb require ‘sucker_punch'
require 'sinatra'

Optional

추가적으로 볼만한 옵션은 worker, 와 jabs에 대한 정의입니다.
workers를 지정해주어 처리하는 worker를 조절할 수 있습니다. 디폴트 값으로는 2로 되어있습니다.

class LogJob
  include SuckerPunch::Job
  workers 4

  def perform(event)
    Log.new(event).track
  end
end
jobs 갯수도 제한할 수 있습니다.
class LogJob
  include SuckerPunch::Job
  max_jobs 10

  def perform(event)
    Log.new(event).track
  end
end



HAHWUL

Security engineer, Gopher and H4cker!

Share: | Coffee Me:

2 comments:

  1. 안녕하세요 하훌님 예전부터 포스트 너무 잘 보고 있습니다.
    실례지만, 버그 바운티 관련해서 궁금한 내용이 있는데 질문을 드려도 될까요?
    가능하다면 연락 방법 알려주시면 감사하겠습니다.

    ReplyDelete
    Replies
    1. 안녕하세요. 우선 잘 봐주신다니 정말 감사하네요 :)

      버바 관련해선, 넵 질문 주셔도 좋습니다. 제가 아는선에선 최대한 답변드릴게요.
      음 채널은 ... 자주보는건 트위터쪽이고 블로그 댓글이나 메일쪽로도 답변 가능합니다.

      Delete