Go buger / jsonparser 를 사용 하여 반 직렬 화 성능 최적화

머리말
최근 에는 로그 시스템 ES 클 러 스 터 에서 데 이 터 를 내 보 내 고 압축 하여 텐 센트 클 라 우 드 에 업로드 하여 오프라인 콜 드 백업 데이터 로 사용 하 는 도 구 를 만 들 고 있 습 니 다.이 과정 에서 몇 가지 개성 에너지 문제 에 부 딪 혔 다.
그 중에서 도 Elasticsearch SDK 의 역 직렬 화 성능 이 병목 이 되 었 기 때문에 여기에 처리 방안 을 기록 합 니 다.
역 직렬 화 성능olivere/elastic 는 자주 사용 하 는 기능 이 매우 강 한 Go Elasticsearch 클 라 이언 트 SDK 로 대부분의 Elasticsearch 의 요청 매개 변 수 를 구조 체 와 방법 으로 밀봉 하여 사용 하기 쉬 운 정도 가 매우 높다.요청 반환 값 을 처리 할 때 olivere/elastic Go 내 에 만들어 진 json 라 이브 러 리 를 사용 하여 요청 결 과 를 대응 하 는 구조 체 로 역 정렬 하여 후속 작업 에 매우 편리 합 니 다.
그러나 대량의 데 이 터 를 내 보 낼 때 예 를 들 어 Search / Scroll 로 매번 수만 개의 문 서 를 내 보 내 고 색인 내 보 낼 때 pprof 분석 을 통 해 반 직렬 화 는 대량의 CPU 순환 을 차지한다.
따라서 특정 수 요 를 위해 극한 성능 을 추구 하기 위해 서 는 이에 대한 특별 처리 가 필요 하 다.
buger / jsonparser 사용 하기
다행히 olivere/elasticPerformRequest 방법 을 제공 하여 누 드 바이트 로 돌아 갑 니 다. 우 리 는 기 존의 도구 구축 요 구 를 재 활용 한 다음 에 원래 바이트 로 돌아 가 스스로 처리 할 수 있 습 니 다.buger/jsonparser 라 이브 러 리 를 선택 하 였 습 니 다. 이 라 이브 러 리 는 원본 JSON 바이트 에서 특정한 내장 필드 를 검색 하고 배열 을 옮 겨 다 닐 수 있 습 니 다.
반 직렬 화 된 구조 체 에 비해 필드 를 처리 하 는 방법 은 성능 을 크게 향상 시 키 고 메모 리 를 절약 할 수 있 습 니 다. 정확히 말 하면 추가 메모 리 를 소모 하지 않 습 니 다.경험 증, 반 직렬 화 에 사용 되 는 CPU 순환 은 기 존의 80% 에서 20% 로 줄 어 들 었 습 니 다.buger/jsonparser 의 사용 방법 은 매우 간단 하 다. 공식 문 서 를 참고 할 수도 있 고 다음 과 같은 예 도 참고 할 수 있다.
이 예 는 Elasticsearch 의 Search / Scroll 결과 에서 hits.hits 배열 의 _source 필드 를 가 져 오고 외부 리 셋 을 호출 하여 _source 필드 의 원본 JSON 바이트 를 전달 하 는 것 이다.
// find hits.hits
	var hitsBuf []byte
	var hitsType jsonparser.ValueType
	if hitsBuf, hitsType, _, err = jsonparser.Get(buf, "hits", "hits"); err != nil {
     
		return
	}
	if hitsType != jsonparser.Array {
     
		err = errors.New("hits.hits is not array")
		return
	}

	// iterate hits.hits
	var itErr error
	var itCount int64
	_, _ = jsonparser.ArrayEach(hitsBuf, func(value []byte, dataType jsonparser.ValueType, offset int, err error) {
     
		itCount++
		if itErr != nil {
     
			return
		}
		srcBuf, srcType, _, srcErr := jsonparser.Get(value, "_source")
		if srcErr != nil {
     
			itErr = srcErr
			return
		}
		if srcType != jsonparser.Object {
     
			itErr = errors.New("missing _source in hits.hits")
			return
		}
		if itErr = e.handler(srcBuf, e.count, e.total); err != nil {
     
			return
		}
		atomic.AddInt64(&e.count, 1)
	})

이 를 바탕 으로 포 장 된 라 이브 러 리 를 참고 하 세 요.https://github.com/guoyk93/esexporter
물론 []byte 을 바탕 으로 검색 을 하 는 것 은 완전한 흐름 식 해석 이 아니 지만 반 직렬 화 된 다음 에 처리 하 는 것 보다 훨씬 좋다.
기 존 *elastic.Client 대상 을 재 활용 하 는 것 을 고려 하지 않 는 다 면 다른 io.Reader 기반 JSON 스 트림 분석 라 이브 러 리 를 사용 하여 메모리 의 실시 간 추출 을 전혀 차지 하지 않 을 수 있 습 니 다.
핵심 적 인 관점 은 특정한 수요 에 직면 하여 흐름 식 해석 은 성능 과 메모리 점용 을 크게 향상 시 킬 수 있다 는 것 이다.

좋은 웹페이지 즐겨찾기