CloudFoundry 소스 분석: 라우터

4407 단어
Router의 실현은 주로 두 부분으로 구성된다. 하나는 lib/router/router이다.rb, 주요 역할과nats 서버의 상호작용,router표를 관리합니다.하나는lib/router/router_uls_server.rb, 주로 각종 외부 요청을 처리합니다.

Router


Router(lib/router/router.rb)는 주로 등록 이벤트와nats 서버의 상호작용을 통해 다른 모듈에서 발표한 정보를 처리하고 운행 정보를 통계합니다.
라우터는 setup_listeners에는 주로 두 개의 이벤트가 등록되어 있습니다. 각각'router.register'와'router.unregister'입니다.DEA 모듈은 nats 서버에 "router.register"메시지와 "router.unregister"메시지를 발표합니다. 이것은 주로 DEA의 상태와 instance의 상태 등에 근거합니다(DEA를 분석할 때 상세하게 소개합니다).
register
      NATS.subscribe('router.register') { |msg|
        msg_hash = Yajl::Parser.parse(msg, :symbolize_keys => true)
        return unless uris = msg_hash[:uris]
        uris.each { |uri| register_droplet(uri, msg_hash[:host], msg_hash[:port],
                                           msg_hash[:tags], msg_hash[:app]) }
      }

라우터가'라우터를 수신하면.register'정보를 할 때 정보 구조는 여러 개의uri가 하나의droplet instance(host,port,tags,app)에 대응하는 것과 유사하다.router는router표에 모든uri와dropletinstance의 대응 관계를 등록하고 실현 방법은 defregister_droplet (url,host,port,tags,app_id) 안에 있습니다.
루트 테이블에서 임의의 URL에 대해 앱의 여러 개droplet 실례를 비출 수 있습니다.
unregister
NATS.subscribe('router.unregister') { |msg|
        msg_hash = Yajl::Parser.parse(msg, :symbolize_keys => true)
        return unless uris = msg_hash[:uris]
        uris.each { |uri| unregister_droplet(uri, msg_hash[:host], msg_hash[:port]) }
      }
라우터가 setup_sweepers 방법에 몇 개의 타이머를 추가하여'청소'작업을 진행한다.
calc_rps는 최근 시간 간격의 요청 수(requests per second)를 계산하여 VCAP::Component에 저장합니다.varz[:requests_per_sec]에서 가장 많이 액세스하는 apps를 계산합니다.
check_registered_urls
MAX_ 초과 검출AGE_STALE 응답하지 않는 droplet 인스턴스, 등록 취소

RouterULSServer


이것은 Sinatra를 기반으로 한 http 서버입니다.
서버에서 "/"라우팅을 요청하는 GET 요청을 수락합니다.
요청한 정보는 body에 다음과 같이 저장됩니다.
{
	"host":"mytest.cloudfoundry.com",
	"stats":[
		{	"response_latency":0,
			"request_tags":"BAh7BjoOY29tcG9uZW50SSIUQ2xvdWRDb250cm9sbGVyBjoGRVQ=",
			"response_codes":{"responses_2xx":1},
			"response_samples":1
		}
		]
}

요청이 들어오면 http 서버는 state 정보를 업데이트한 다음 요청'mytest.cloudfoundry.com'을 분석하고'mytest.cloudfoundry.com'에 따라 대응하는droplet을 찾습니다
droplets = Router.lookup_droplet(url)
# Pick a droplet based on original backend addr or pick a droplet randomly
      if sticky
        _, host, port = Router.decrypt_session_cookie(sticky)
        droplet = check_original_droplet(droplets, host, port)
      end
      droplet ||= droplets[rand*droplets.size]

droplet 실례를 선택하면 실례의 tags와vaz를 업데이트하고 실례의 정보를 되돌려줍니다.
uls_response = {
        ULS_STICKY_SESSION => new_sticky,
        ULS_BACKEND_ADDR   => "#{droplet[:host]}:#{droplet[:port]}",
        ULS_REQUEST_TAGS   => uls_req_tags,
        ULS_ROUTER_IP      => Router.inet,
        ULS_APP_ID         => droplet[:app] || 0,
      }

Router의 통계


  VCAP::Component.varz[:requests] Router에서 받은 모든 요청 수
  VCAP::Component.varz[:bad_requests] Router에서 받은 모든 bad 요청 수 VCAP::Component.varz[:latency]    VCAP::Component.varz[:responses_2xx]   VCAP::Component.varz[:responses_3xx]   VCAP::Component.varz[:responses_4xx]   VCAP::Component.varz[:responses_5xx]   VCAP::Component.varz[:responses_xxx]    VCAP::Component.varz[:urls] Router에 등록된 모든 url 수이자 전체 CF 실례의 url 수인 VCAP::Component.varz[:droplets] Router에 등록된 모든 droplet의 실례 수 VCAP:::Component.varz[:tags] = {} Router에서 수집한 모든 tags
  VCAP::Component.varz[:requests_per_sec] 라우터의 최근 통계 주기 RPS

Router의 핵심 구조: @droplets


droplets는 모든 플랫폼의 모든 인스턴스 정보를 기록합니다.
URL이droplet에 대응하는 그룹입니다.여러 개의 실례가 같은 URL에 서비스됩니다.
url.downcase=>[droplet,droplet,droplet,...]
droplet 정보는 다음과 같습니다.
droplet = {
        :host => host,
        :port => port,
        :clients => Hash.new(0),
        :url => url,
        :timestamp => Time.now,
        :requests => 0,
        :tags => tags
      }
host: 실행 중인 호스트
port: 감청된 포트
clients: 통계 주기 내에 요청한 클라이언트 IP와 요청 수량의 매핑
url: 감청된 url
timestamp: 마지막 심장 박동 시간
requests: 통계 주기 내의 요청 횟수
tags: 이droplet의 tag

좋은 웹페이지 즐겨찾기