728x90
반응형

Go에서 정규식으로 파싱하여 사용하는데 제대로된 값이 나오지 않았다.

 

그래서 정규식으로 파싱된 모든 내용을 출력해보니 가장 마지막에 찾은 내용이 원하는 내용이었다.

 

원인은 명령을 실행하여 출력된 값에 캐리지 리턴이 있어 변경된 내용을 미처 알아차리지 못해 발생한 문제였다.

 

터미널에서 테스트를 했을 때 결과가 바로 나와 그게 출력되는 줄 알았었다.

 

하지만 실제로는 몇번 명령을 수행하고 있었던 것이었다.

 

다행히 해당 로직을 이용하는 경우가 많이 없었지만 추후에 발생할 수도 있기에 핫픽스로 버그를 수정했다.

반응형
728x90
반응형

Go로 REST API 서버를 만들어서 사용하는데 특정 API의 응답 시간이 오래 걸리는 경우가 있었다.

 

처음에 어떤 문제로 오래 걸리는지 파악이 되지 않아 캐시를 사용했지만 계속 발생했었다.

 

데이터베이스 조회에 걸리는 시간을 측정해보니 여기서 오래 걸리는 것을 확인할 수 있었다.

 

오래 걸리는 이유는 데이터베이스 커넥션 풀과 관련한 설정 문제인 것 같아 문서를 읽어보았다.

 

SetMaxIdleConns 설정값을 SetMaxOpenConns 설정값보다 크거나 같게 설정하는 것이 좋다고 써있었다.

 

SetMaxIdleConns 함수는 유휴 상태 커넥션 풀에서 최대 연결 수로 적절한 값을 설정했다.

 

SetMaxOpenConns도 기본값인 무제한으로 사용하고 있어 크게 문제가 없어 보였지만

 

SetMaxIdleConns의 설정값과 비슷하게 하는 것이 좋다고 해서 같은 값으로 설정했다.

 

며칠을 지켜보니 응답 시간이 오래 걸리는 경우가 더이상 발생하지 않았다.

 

참고 문헌

  1. golang.org/pkg/database/sql/#DB.SetMaxIdleConns

  2. golang.org/pkg/database/sql/#DB.SetMaxOpenConns

  3. github.com/go-sql-driver/mysql

반응형
728x90
반응형

서버 장애가 나서 panic이 발생했다는 알람이 많이 왔었다.

 

원인은 데이터베이스가 다운돼 쿼리를 실행할 수 없어 발생한 장애였다.

 

코드를 확인해보니 에러를 확인하고 에러가 없는 경우에 Close 함수를 실행해야 했는데 

 

항상 Close 함수를 실행을 하여 rows가 nil 값인데도 참조하여 발생한 문제였다.

rows, err := db.Query(query, args)
if err != nil {
    return
}
defer rows.Close()
...

그래서 에러를 확인하고 Close 함수를 실행하도록 코드를 수정했다.

혹시 몰라 일정 시간 이상 응답이 없으면 에러가 발생하도록 하는 코드도 추가했다.

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
rows, err := db.QueryContext(ctx, query, args)
if err != nil {
    return
}
defer rows.Close()
...

 

참고 문헌

  1. https://golang.org/pkg/database/sql/#DB.ExecContext

  2. https://golang.org/pkg/database/sql/#Conn.QueryContext

  3. https://golang.org/pkg/database/sql/#DB.PingContext

반응형
728x90
반응형

Go 프로젝트에서 http 클라이언트를 만들어서 활용하고 있었는데 어느날 서버에 응답이 없었다.

 

그래서 서버에 들어가서 확인해보니 too many open files라는 에러가 나고 있었다.

 

netstat으로 확인해보니 CLOSE_WAIT 상태로 많이 쌓여 있었다.

 

어디가 문제인가 살펴보니 defer resp.Body.Close() 를 하는데 상태값이 200인 경우에만 닫도록 돼있었다.

 

(문서에서 Body를 읽은 경우엔 항상 닫아주라고 써있다.)

resp, err := http.Get("http://example.com/")
if err != nil {
    return
} else if resp.StatusCode != 200 {
    return
}
defer resp.Body.Close()

다음과 같이 수정한 이후 경과를 살펴보니 잘 동작하는 것을 확인할 수 있었다.

resp, err := http.Get("http://example.com/")
if err != nil {
    return
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
    return
}

 

참고 문헌

  1. https://golang.org/pkg/net/http/

반응형

+ Recent posts