2016-09-16 11 views
2

나는 섬유가 협동 스레드라는 것을 알고있다. 선점 스레드는 그렇지 않지만 파이버는 실행 컨텍스트를 제어합니다. 광섬유는 제어가 가능하므로 광섬유가 잘 정의 된 위치에서 시작하고 중지 할 수 있습니다.루비 섬유 프로그램의 제어 흐름

분명히 루비에서 섬유가 사용되는 이유는 원자로 패턴으로 인해 발생하는 중첩 된 블록을 정리하는 것입니다.

하지만 섬유를 사용하는 아래 스크립트의 제어 흐름을 파악하는 데 어려움이 있습니다.

def http_get(url) 
    f = Fiber.current 
    http = EventMachine::HttpRequest.new(url).get 

    # resume fiber once http call is done 
    http.callback { f.resume(http) } 
    http.errback { f.resume(http) } 

    return Fiber.yield 
end 

EventMachine.run do 
    Fiber.new{ 
    page = http_get('http://www.google.com/') 
    puts "Fetched page: #{page.response_header.status}" 

    if page 
     page = http_get('http://www.google.com/search?q=eventmachine') 
     puts "Fetched page 2: #{page.response_header.status}" 
    end 
    }.resume 
end 

내가 알고있는 방법은 :

1) EM은 이벤트 루프

2) 섬유가 만들어 시작 후 이력서가 호출됩니다. new에 전달 된 코드 블록이 즉시 실행되거나 이력서가 호출 된 후에 실행됩니까?

3) http_get이 처음으로 호출되었습니다. 비동기 이벤트 (리눅스에서 select, poll 또는 epoll 사용). 비동기 이벤트의 이벤트 핸들러 (콜백 메소드에 있음)를 설정합니다. 그런 다음 Fiber가 자발적으로 EventMachine 스레드 (메인 스레드)에 대한 제어권을 부여합니다. 그러나 콜백이 호출되자 마자 f.resume (http)을 사용하여 다시 제어 할 수 있습니다. 그러나이 간단한 예제에서는 f.resume (http) 뒤에 내 자신의 콜백 코드를 넣어야하겠습니까? 왜냐하면 지금은 f.resume (http)가 광섬유에 제어권을 반환하고 다른 작업을 수행하지 않기 때문입니다.

수확 후 컨트롤이 이벤트 루프로 들어가는 EventMachine으로 이동한다고 생각합니다. 따라서 두 번째 http_get은 아직 호출되지 않습니다. 일단 콜백이 호출되면, 파이버에 컨트롤이 반환됩니다 (우리는 하나의 Fiber.new 만 사용하기 때문에이 모든 경우에 파이버 인스턴스가 하나만 있다고 가정합니다). 하지만 두 번째 http_get이 언제 호출됩니까?

+0

참고 사항 : 광섬유가 생성되면 자동으로 실행되지 않습니다. 오히려 명시 적으로 Fiber # resume 메소드를 사용하여 실행하도록 요청해야합니다. – Donato

답변

0

내가 당신을 위해 대답 할 수 있는지 보겠습니다. 라인 (14 개) 검사 여부 :

01: def http_get(url) 
02: f = Fiber.current 
03: http = EventMachine::HttpRequest.new(url).get 
04: 
05: # resume fiber once http call is done 
06: http.callback { f.resume(http) } 
07: http.errback { f.resume(http) } 
08: 
09: return Fiber.yield 
10: end 
11: 
12: EventMachine.run do 
13: Fiber.new{ 
14:  page = http_get('http://www.google.com/') 
15:  puts "Fetched page: #{page.response_header.status}" 
16: 
17:  if page 
18:  page = http_get('http://www.google.com/search?q=eventmachine') 
19:  puts "Fetched page 2: #{page.response_header.status}" 
20:  end 
21: }.resume 
22: end 
  1. 라인 (21)이 코드 라인에 14 ~ 20
  2. 섬유 코드가 보인다 다음을 수행 할 섬유의 실행을 시작합니다 나는 설명을 돕기 위해 줄 번호를 추가하고 우리는 google.come에 GET 할 수 있습니다. 17 번 줄에서 http_get의 유효한 응답이 있는지 확인한 다음 18 번 줄에서 다음 요청을 수행하여 eventmachine 문자열을 검색합니다.
  3. 라인 21에서 .resume으로 인해 파이버 실행이 시작되면 라인 14가 실행되어 http_get 메소드를 호출합니다.
  4. 라인 02 - 07은 비동기 HTTP GET 요청 및 콜백을 설정합니다.
  5. Line 09는 Control을 EventMachine으로 반환합니다.
  6. 03 번 라인의 async HTTP GET 호출이 비동기 적으로 실행을 완료하고 06 번이나 07 번 라인의 콜백 중 하나가 발생하면 13 번 라인에서 20 번 라인으로 생성 된 원래 파이버가 해당 컨트롤을 다시 가져옵니다.
  7. 이제 Fiber 실행이 15 행에서 다시 시작됩니다. 06/07 행의 콜백은 http 객체에 대한 참조를 전달했으며이 객체는 이제 Line 14에서 변수 page으로 참조되고 이후 15 행에서 HTTP 요청 상태를 덤프하는 데 사용됩니다.
  8. 광섬유가 계속 실행되면 page이 true 값인지 확인한 다음 http_get을 다시 호출하지만 새 URL을 사용합니다.코드 if pagenil에 대한 확인없이 액세스 한 page이있는 곳에서 15 호선이 폭파했을 때 nil 인 경우 절대 실행될 수 없습니다.
  9. 유사한 프로세스 반복 - 02 ~ 07 행은 HTTP GET 호출을 설정하고 Line 09는 제어를 EventMachine으로 되돌립니다.
  10. 시간이 지나면 콜백 중 하나가 호출되고 Fiber 19가 다시 제어되면서 Line 19가 실행됩니다.
  11. 19 번 라인을 실행하면 파이버가 죽게됩니다.

희망을 분명히합니다.

추가 논리로 HTTP GET의 응답을 처리하는 한, puts을 일부 의미있는 처리 로직으로 바꿀 수 있다고 생각합니다. 이 샘플의 puts은 응답을 처리하는 것 같고 콜백은 주로 Fiber를 다시 시작하는 데 사용됩니다.