온라인 타임 아웃 프로세스 인터페이스 문제 해결

1 입사 환원

어제 오후, 504이 분명 시간 초과 알람입니다, 경고를 받았다. 그 당시, 내가 쓴, 조금 놀랐 첫 반응이 한편으로는 다른 일이, 그냥 눈을 신경 쓰지 않았다, 그러나 경보 방법은 매우 익숙한 일으켰습니다.

놀라운 후, 우리는 손에서 일을 처리하는 것을 계속한다.

일시간 후, 그들은 확실히 문제 및 조사를 시작한 경우, 분명히 실수하지, 같은 경고를 받았다.

경보 인터페이스 컨트롤러는 마이크로 통화 서비스, 최종적으로 얻어진 데이터를 조립하는 복수 반환 getControllerAMethod ControllerA 인터페이스의 층이다. 문제는 ServiceM의 getServiceMMethod 방법 로직 ServiceM 서비스는 주로 두 개의 데이터베이스 쿼리, 매우 간단 MySQL 데이터베이스에서 데이터를 가져오고 호출자에게 리턴하는 것입니다.

에 도시 된 바와 같이 체인을 호출합니다.

2, 환경 소개

언어 : 이동

DB : MySQL의

데이터베이스 상호 작용 : 데이터베이스 / SQL (이를 바탕으로, 회사가 일부 사용자 정의 및 포장, 자연 또는 데이터베이스 / SQL을했다)

다음은 특정 문제 해결 과정이 질문을 시작 설명합니다.

 

3, 본능적 인 반응 : SQL 문에서 시작

로그 정보와보기의 해당 지점의 세부 사항에서 알람, 알람 정보를 얻을, 그것은 초과 근무 문제에 속한다.

첫 번째 반응은 SQL 문은 모양, 매우 간단합니다, SQL 문을 쿼리가 느린 경우 (이 플레이 알고에 희박하지만)을 참조하는 것입니다

TABLEA에서 A, B, C를 선택 어디에서 (A1, A2, A3)

이 히트 된 인덱스 인 것을 알 수있는 실행 계획을보고하지 마십시오.

그러나 여전히 실행 계획 및 실제 구현, 분석에서보고, 응답 시간이 상당히있다, 아무 문제가 없다.

조사 본능이 너무 재미있다, 다음 조사를 시작합니다.

 

4, 조사의 상류 : 여부를 ​​상황에 맞는 시간이 다 떨어지기

이 시간 제한 문제이기 때문에, 시간 제한의 상류가있을 수는 제한 시간의 다운 스트림 수 있으며, 조사의 첫 번째 단계는 다운 스트림의 원인의 가능성을 배제하고있다 슬로우 쿼리 시간 제한 때문이다.

그것은 상류 초과 근무 수당이되지 않을 것? 분명히 결국, 우리는 모든 서비스 호출이 설정 한 시간의 총량에 공통되는 문맥에 따라 아래로 이동을 완전히 통과 할 수 있다는 것을 알고있다.

그리고 차트에서 위의 서비스가 너무 시간이 많이 걸리는 직업, 시간 제한 ServiceM 압축 왼쪽으로 이어질 것입니다, 그래서 만약 ServiceM이, 상류 인터페이스의 마지막 단계입니다 찾을 수 있습니다.

그러나 조사가 로그에서 찾을 수 있습니다 거의 모든 SQL 쿼리가 수십 밀리 초 단위로 반환 getServiceMethod 방법 ServiceM 층은 해당 참조하십시오.

타임 아웃이 업스트림을 일으킬 수있는 충분한 시간이 없기 때문에, 이러한 관점에서.

 

예비 조사의 다운 스트림 5 : 용의자로 행

시간의 상류 적당량 때문에, 그 문제는 높은 확률 하류 서비스 인터페이스에있다.

내가 getServiceMMethod 방법 코드를 읽기 시작, 다음의 의사 코드는 기능을 구현하기위한 코드입니다

행 ERR = db.query (SQL1) 
ERR! = 닐 경우 { 
  ... 
} 

rows.Close () 지연 
rows.Next 대 () { 
  rows.scan (...) 
} 

행 ERR = db.query을 ( SQL2) 
잘못 경우! = nil이 { 
  ... 
} 

rows.Close () 연기 
rows.Next에 대한 () { 
  rows.scan을 (...) 
}

  

코드를 읽은 후, 나는 네, 아마이 행의 문제라고 생각합니다, 조금 흥분 시작합니다.

은 "이동 기능 당신이 옳은 일을 사용 / SQL 데이터베이스 연결 풀을 --database 알아,"나는 구덩이 행에 대해이 소개에서 제대로 가져 닫지 않았다. 레노버가 제대로 연결이 타임 아웃에서 쿼리의 결과 뒤에 얻을 수없는 연결의 누설의 결과로, 데이터베이스 연결을 닫지 않습니다 과정에서 행을 통과하기 시작했다 때문입니다 여부 그래서.

이유 나는 명확하게 분석,하지만 그것은 단지 생각할 수있는 문제뿐만 아니라 구체적인 단계는 여기에 같은 행을 사용하여 두 번 쿼리입니다 반대는하지 이전 연결로 이어지는 상황이 폐쇄 된입니다 직접 폐쇄 연결 제한 시간을 사용하여 쿼리가 원인?

이 경우 경고가 더 자주 시작 후 수신기 테스트 라인을 통해 시작 후 2 개 행이 그것을 닫고 코드를 제출받을 수있는 원래의 쿼리의 두 행.

 

6, 간단한 진정

라인의 코드 후, 효과는 즉시입니다.

알람 즉시 다시, 시간 제한 로그 정보를 중지하지 않으며, 모든 것이 제가 원인을 발견하고 지금 문제를 해결해야한다고 생각했다 과거의 진정, 돌아왔다.

귀국 후, 내 마음 11:00부터 시작, 내 컴퓨터를 꺼내 시뮬레이션, 검증 및 알람의 원인을 줄이는 다양한 시작, 다소 안심 아직도있다.

 

7 세 시간 후, 진정이 환상이 될 수 실현

두 지점까지 11 : 00 ~, 전체 3 시간, 난 단지 이유를 찾을 수 없습니다,하지만 난 해결책으로 문제를 해결하지 않을 수 있습니다 발견했다.

위와 같이 문제, 즉, 두 개의 선택 쿼리 코드가 복잡하지 않기 때문에.

그래서 같은 로컬 테스트에서 일부 코드를 작성하고, 제한 시간 후 종료 또는 연결이 나타납니다하지 않았다. 심지어, 나는 MAXCONN 및 IdleConn 1로 설정하고 시간이 초과되지 않습니다.

기사처럼하지 않는 한 "이동 기능 당신이 옳은 일을 사용 / SQL 데이터베이스 연결 풀을 --database 알아보기"레인은 초기 row.Next (에서 출구) 과정없이 rows.Close () 문처럼 낮은 발생합니다 말했다 질의, 즉 인 경우에 접속 얻을 다음 코드도.

FUNC oneConnWithRowsNextWithError () { 
	데시벨, _ = db.Open ( "MySQL은", "루트 : rootroot @ / DQM 캐릭터 세트 = UTF8 & parseTime = TRUE & LOC = 지역") 

	db.SetMaxOpenConns (1) 
	행, ERR : = db.Query ( "선택 * 테스트에서 위치를 이름 = '재키'제한 10") 
	잘못을 경우 = 전무 {! 
		fmt.Println ( "쿼리 오류") 
	} 

	내가 : = 1 
	rows.Next ()에 대한 { 
		내가 ++ 
		있다면 == 3 { 
			휴식 
		} 
		fmt.Println ( "닫기") 
	} 

	행 _ = db.Query ( "* 시험에서 선택") 
	fmt.Println (열, 행) 
}

  

그러나 원래의 코드는 연결이 결국 종료됩니다 것 rows.Close () 메소드를 연기, 상황 메모리 누수가 발생하지 않습니다이다.

(이 문제에 대한 진정한 해결책은 문제가 다시 없기 때문에) 지금이 순간, 나는 머피의 법칙 생각했다.

그래서 나는 로그를 결합, 구이 소스를 시작하는 중요한 단서가 많은 쿼리가 활발하게되는 작업을 취소하는 것입니다 발견했다. 예,이 context.Timeout (이 코드는 우리의 데이터베이스 / SQL 기저 함수에 풍부) 취소 반환 취소합니다.

트리거 조건을 취소하는 데이터베이스 / SQL을 수행하기위한 QueryContext의 방법은 ERR를 돌려줍니다

// QueryContext는 일반적으로 SELECT를 행을 반환하는 쿼리를 실행합니다. 
// 인수는 쿼리의 모든 자리 표시 자 매개 변수입니다. 
FUNC (dB에서의 DB *) QueryContext (CTX context.Context 쿼리 스트링 인수 ... 인터페이스 {}) (* 행 오류) { 
	VAR 행 * 로우 
	VAR의 ERR 오류 
	의 I = 0; 난 maxBadConnRetries를 <; 나는 {++ 
		행, ERR = db.query (CTX, 쿼리, 인수, cachedOrNewConn) 
		ERR 경우를! = driver.ErrBadConn { 
			휴식 
		} 
	} 
	경우 ERR == driver.ErrBadConn { 
		반환 db.query (CTX, 쿼리, 인수, alwaysNewConn) 
	} 
	ERR, 행을 반환 
}

  

첫 번째 반응은 직접 취소 상황의 결과로, 시간의 부족의 상류이지만, 이런 이유로 우리는 이미 배제했다.

그래서이 코드는 (이 나중에 말할 것입니다, 매우 중요하다)도 한 번 QueryTimeout 구성이 너무 작습니다 여부를 매개 변수라는 우리의 자체 개발 한 코드로 의심되는 여러 레이어를 거절하지만, 구성에 갔다되었습니다 발견 분명히 충분히 800ms이다.

점점 더 많은 문제를, 나는 마지 못해 침대에 갔다.

 

8, 머피의 법칙은 여전히 ​​유령

오늘 오후, 나는 그들이오고있어이 익숙한 경고를 받았다 (만 경고를 받았다).

말했다 이전,이 문제가 사라되지 않도록 중요한 메시지가 확실히 있기 때문에 시간 초과, 취소 할 수 있습니다, 시간 제한이 연결되지 때문일 수 있습니다.

getServiceMMethod 자신에게 패스를 요청했으며, 누출 사건을 연결하지 않았지만, 다른 장소가 누출되지 않습니다 때문에? 그래서 일반적으로 코드 개체의 사용에 대한 행을 확인이 닫혀 있는지 여부, 코드 ServiceM 모든 서비스를 사라.

조사가 희망 후.

지금까지, 나는 내 마음은 연결 누수의 문제가있다 배제되었습니다했다.

나는 8시 오늘의 주위에, 로그를 거절하기 때문에 기간, 나는 또한 우리의 DBA를 요청, 비정상적인 상태 DB에 의한 것으로 의심되는 수백 밀리 초 단위로 여러 쿼리가 있습니다. 내 대답에 대한 DBA 데이터베이스는 아주 정상입니다.

또한 DB의 과거 상태와없는 트래픽 이상, 기복없이 연결 풀의 수에 비해 모니터를 보았다.

동료는 이전의 큰 이상의 새로운 기능을 몇 일 전에했다, 그래서 나는이 문제를 찾을 수 없습니다, 함수에 대응하는 새로운 코드에서 보았다.

 

도 9에 준비된 "Quxianjiuguo"

나는 아직 알 수없는 다른 방법으로이 문제를 방지 할 수 있는지 궁금해하기 시작, 근본 원인이 발견되지 않았다합니다. 결국, 문제를 해결하는 가장 좋은 방법은 (다른 방법을 넣어) 해결되지 않습니다.

큰 전송 시간 제한 ServiceM 방법을 준비합니다.

캐시가 요구 한 금액의 일부를 방어하기 위해 캐시 getServiceMMethod 방법 ServiceM 서비스를 추가 할 수도 준비.

좋아, Zheliang 조를 사용하려고 내일, 여기 중지합니다.

그래서, 나는 내 마음의 방법으로, 재고의 경고 기능과 아웃을 몇 가지 활동을받을 준비가되어 있습니다.

 

(10), 생각했다, 나는 진실을 발견

알람 업스트림, 다운 스트림 시간 제한 ->

시간의 상류 부족 제외 ->

음의 다운 스트림 행은 닫혀 있지 ->

불안정한 상태의 데이터베이스를 제외 ->

다운 스트림 타임 아웃을 결정 ->

용의자가 연결되지 수 ->

연결하기, 연결 수, 연결 얻을

그래서 우리는 위의 그냥 막연하게 연결 풀 설정이 여기에없는 기억, QueryTimeout 매개 변수를 설정하는 것입니다, 데이터베이스 구성 매개 변수를 통해 찾습니다. 다음 읽기 구성을 켜기, idleConn는 = X, MAXCONN는 = Y.

모니터링을 다시 보았다 getServiceMMethod QPS 방법은, 내가 진리를 발견 한 것 같아요.

아침에 여덟 이른 아침부터 QPS는 Y를 깨고 8 시경까지 증가하고, 그리고 MAXCONN = Y.있다

그래서 그것은 단지 기다릴 수 연결을하지 쿼리 작업의 뒤쪽으로 이어지는, MAXCONN 이상이어야한다, 타임 아웃을 기다리거나 연결을하지 않았다, 그래서 위 말했다 트리거는 ServiceM이다 또한 상류 보는 시간 제한 알람을 주도 취소 기다리고있다으로 타임 아웃의 getServiceMMethod 실행.

알람이 아직 이해하지 않은 경우 그림이 Y보다 더 많은 이유 그래서 직접 사용할 수있는 요청에 의해 다음이 기간 동안 풀에 다시 넣어하여 연결을 완료 한 쿼리 작업을 수행하기 위해 다른 작업이 있어야한다, 모든 후가 될 것입니다 창 제한 시간을 기다립니다.

이 경고가 출석하지 않는 이유 그래서, 나의 이해는 이전보다 작은 새로운 라인은 문제를 강조, 최근 동료 기능 인터페이스가 호출 수를 증가시키는 것이다됩니다.

 

11 요약

사실, 마지막 이유는 간단 할 수있다, 양 구성 연결 수는 나중에 연결 시간 제한을하지 작업을 쿼리 주도, 작은 것, 업입니다.

조사가 상대적으로 어렵도록하지만 서비스 컨트롤러 층과 DB 층의 맨 아래에이 타임 아웃은, 각 층은 제한 될 수 있습니다.

다음은 몇 가지 핵심 포인트는 군더더기입니다

  • 특별한주의를 필요로하는 코드에 대한 최근 변경. 당신은 경고없이 긴 시간을 한 경우, 새로운 코드 경보의 최근 완료, 높은 확률과 온라인 관계 (이 시간 초과 사실과 새로운 코드도 관련되어 온라인, 코드 자체는 아무런 문제가 없지만, 새로운 온라인 트래픽 더 큰하지만)
  • 도구를 잘 사용합니다. 좋은 모니터링 및 로깅 시스템 및 기타 도구를 단서 및 유용한 링크를 찾을 수 있습니다.
  • 하향식 조사 및 추적합니다. 좋은 위치 버그의 경우, 원인까지 같은 특정 순서, 검증, 배제에 체크로 순서를 호출 할 수 있습니다.

 

추천

출처www.cnblogs.com/bigdataZJ/p/timeout-troubleshooting.html