[ruby-on-rails] Rails에서 Thread.current [] 사용의 안전성
Thread.current
해시 (예 : current_user, 현재 하위 도메인 등)에 정보를 저장하는 관행에 대해 상충되는 의견을 계속 받고 있습니다. 이 기술은 모델 계층 (쿼리 범위 지정, 감사 등) 내에서 이후의 처리를 단순화하는 방법으로 제안되었습니다.
- Rails에서 스레드 변수가 간헐적으로 발생하는 이유는 무엇입니까?
- Rails 용 API 래퍼에서 Thread.current를 사용하는 대안
- Thread.current [] 값과 클래스 레벨 속성은 레일에서 사용하기에 안전합니까?
많은 사람들은 MVC 패턴을 깨뜨리기 때문에 이러한 관행을 받아 들일 수 없다고 생각합니다. 다른 사람들은 접근 방식의 신뢰성 / 안전성에 대해 우려를 표명하고 2 부로 구성된 질문은 후자 측면에 중점을 둡니다.
-
는 IS
Thread.current
해시는 전체주기 동안, 오직 하나의 응답 가능하고 개인이 보장? -
응답이 끝날 때 스레드가 다른 수신 요청으로 전달되어에 저장된 정보가 유출 될 수 있음을 이해합니다
Thread.current
. 대응이 끝나기 전에 그러한 정보를 지우는 것만으로도 (예 :Thread.current[:user] = nil
컨트롤러에서 실행 하여after_filter
) 보안 위반을 방지 할 수 있습니까?
감사! 주세페
답변
스레드 로컬 변수에서 벗어나야하는 특별한 이유는 없습니다. 주요 문제는 다음과 같습니다.
- 이를 사용하는 코드를 테스트 할 때 스레드 로컬 변수를 설정해야하므로 테스트하기가 더 어렵습니다.
- 스레드 로컬을 사용하는 클래스는 이러한 개체를 사용할 수 없지만 스레드 로컬 변수 내부에 있다는 지식이 필요 하며 이러한 종류의 간접 지정은 일반적 으로 데 미터 의 법칙을 위반합니다.
- 프레임 워크가 스레드를 재사용하는 경우 스레드 로컬을 정리하지 않는 것이 문제가 될 수 있습니다 (스레드 로컬 변수가 이미 시작되고 변수 초기화를 위해 || = 호출 에 의존하는 코드 가 실패 할 수 있음)
따라서 사용하는 것이 완전히 의문의 여지 가 없지만 가장 좋은 방법은 사용하지 않는 것이지만 때때로 스레드 로컬이 상당히 많은 코드를 변경하지 않고도 가능한 가장 간단한 솔루션이 될 벽에 부딪 히게됩니다. 당신은 타협해야 할 것이고, 스레드 로컬로 완벽하지 않은 객체 지향 모델을 가지고 있거나 똑같이하기 위해 꽤 많은 코드를 변경해야합니다.
따라서 그것은 대부분 귀하의 경우에 가장 적합한 솔루션이 될 것이라고 생각하는 문제이며 실제로 스레드 로컬 경로를 따라 내려가는 경우 다음 정리를 기억하는 블록으로 수행하도록 조언합니다. 다음과 같이 완료됩니다.
around_filter :do_with_current_user
def do_with_current_user
Thread.current[:current_user] = self.current_user
begin
yield
ensure
Thread.current[:current_user] = nil
end
end
이렇게하면이 스레드가 재활용되는 경우 사용하기 전에 스레드 로컬 변수가 정리됩니다.
답변
이 작은 gem은 스레드 / 요청 로컬 변수가 요청 사이에 고정되지 않도록합니다 : https://github.com/steveklabnik/request_store
답변
받아 들여진 대답은 질문을 다루지 만 Rails 5는 이제 Thread.current를 사용 하는 “Abstract super class” ActiveSupport :: CurrentAttributes 를 제공합니다.
가능한 ( 인기없는 ) 솔루션 으로 링크를 제공 할 것이라고 생각했습니다 .
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/current_attributes.rb
답변
허용되는 답변은 기술적으로 정확하지만 답변에서 부드럽게 지적하고 http://m.onkey.org/thread-safety-for-your-rails 에서 그렇게 부드럽게 지적 하지 않습니다.
Thread.current
꼭 필요하지 않은 경우 스레드 로컬 저장소를 사용하지 마십시오.
에 대한 gem request_store
은 또 다른 솔루션 (더 나은)이지만 스레드 로컬 저장소에서 멀리 떨어져 있어야하는 더 많은 이유 때문에 readme를 읽으십시오.
거의 항상 더 나은 방법이 있습니다.