Gas optimization in Solidity, Ethereum
I’m sorry but my English is terrible. I hope you understand that generously.Recently, I was developing a toy project named Blind Market. It’s a simple P2P trading application using smart contract. I was making a contract using Solidity, and the trade stage proceeded in the order of pending, shipping, and done. The problem was appeared in done phase. The problem was that when I tried to close the transaction by paying the price raised by the seller in msg.value, the following error occurred.Pe...
Uvicorn & Gunicorn
Uvicorn and GunicornUvicorn and Gunicorn are important concepts when developing applications in Python. However, there are many concepts to be aware of in order to fully understand Uvicorn and Gunicorn. The following is a brief summary of the necessary concepts, and the details will be dealt with separately later.Necessary ConceptsStarletteStarlette is a Web application server that can run asynchronously. Starlette runs on top of Uvicorn.FastAPIFastAPI provides many features on top of Starlet...
P2WPKH
P2WPKHP2WPKH란 비트코인 내에서 가장 일반적인 스크립트 형식으로 비트코인 프로토콜에 대한 지불 거래 유형이다. 주소는 1로 시작하는데, 세그윗을 지원하는 새로운 주소 3 또는 bc1로 시작하는 주소보다 훨씬 비싸다. https://mirror.xyz/0xA1d9f681B25C14C1eE7B87f1CF102E73cA3ad4d9/egjhNVklgy_LgZmcTXXAOTBa6ePBqO3Ja9ZSoDIad-8 즉, 비트코인 주소가 1로 시작하면 P2PKH 주소를 사용하고 있는 것이다. 공개키의 간단한 해시이며, 이 해시를 주소로 사용하는 것이다. 이것은 원래 비트코인 주소 형식이었으며 오늘까지도 충실히 작동한다. 레거시 주소는 세그윗과 호환되지 않지만, 여전히 문제없이 P2PKH 주소에서 세그윗 주소로 BTC를 보낼 수 있다. 그러나 레거시 주소 트랜잭션이 더 크기 때문에 P2PKH 주소에서 전송하는 평균 속도는 세그윗 주소에서 전송할 때보다 더 높은 요금이 발생할 수 있다....
Smart Contract Developer, Web3 Backend Developer
Gas optimization in Solidity, Ethereum
I’m sorry but my English is terrible. I hope you understand that generously.Recently, I was developing a toy project named Blind Market. It’s a simple P2P trading application using smart contract. I was making a contract using Solidity, and the trade stage proceeded in the order of pending, shipping, and done. The problem was appeared in done phase. The problem was that when I tried to close the transaction by paying the price raised by the seller in msg.value, the following error occurred.Pe...
Uvicorn & Gunicorn
Uvicorn and GunicornUvicorn and Gunicorn are important concepts when developing applications in Python. However, there are many concepts to be aware of in order to fully understand Uvicorn and Gunicorn. The following is a brief summary of the necessary concepts, and the details will be dealt with separately later.Necessary ConceptsStarletteStarlette is a Web application server that can run asynchronously. Starlette runs on top of Uvicorn.FastAPIFastAPI provides many features on top of Starlet...
P2WPKH
P2WPKHP2WPKH란 비트코인 내에서 가장 일반적인 스크립트 형식으로 비트코인 프로토콜에 대한 지불 거래 유형이다. 주소는 1로 시작하는데, 세그윗을 지원하는 새로운 주소 3 또는 bc1로 시작하는 주소보다 훨씬 비싸다. https://mirror.xyz/0xA1d9f681B25C14C1eE7B87f1CF102E73cA3ad4d9/egjhNVklgy_LgZmcTXXAOTBa6ePBqO3Ja9ZSoDIad-8 즉, 비트코인 주소가 1로 시작하면 P2PKH 주소를 사용하고 있는 것이다. 공개키의 간단한 해시이며, 이 해시를 주소로 사용하는 것이다. 이것은 원래 비트코인 주소 형식이었으며 오늘까지도 충실히 작동한다. 레거시 주소는 세그윗과 호환되지 않지만, 여전히 문제없이 P2PKH 주소에서 세그윗 주소로 BTC를 보낼 수 있다. 그러나 레거시 주소 트랜잭션이 더 크기 때문에 P2PKH 주소에서 전송하는 평균 속도는 세그윗 주소에서 전송할 때보다 더 높은 요금이 발생할 수 있다....
Smart Contract Developer, Web3 Backend Developer

Subscribe to Primrose

Subscribe to Primrose
Share Dialog
Share Dialog
<100 subscribers
<100 subscribers
회사에서 마주친 에러
$ [mysql] 2024/03/11 18:37:09 packets.go:122: closing bad idle connection: unexpected read from socket
$ [mysql] 2024/03/11 18:37:09 packets.go:122: closing bad idle connection: unexpected read from socket
Batch 처리를 요하는 작업들이 모여있는 인스턴스에서 발생했다.
비즈니스 로직 자체에는 문제가 없었고, 커넥션 관련 설정도 디폴트로 되어있는 상황이었다.
사실 서비스 전체적으로 보면 MySQL 자체를 많이 쓰는 상황은 아니었고, 동시에 실행되는 job 이 MySQL 기반이었어서 커넥션 관련 문제로 좁혀놓고 디버깅을 시작했다.
이 과정에서 새롭게 알게된 사실에 대한 기록.
gorm 은 sql 패키지의 DB 객체를 wrapping 하고 있다.
sql.DB 구조체에는 Stats 라는 메소드가 있다.
var db := &sql.DB{}
stats := db.Stats() // stats ?
Stats 구조체는 아래와 같이 생겼다.
// DBStats contains database statistics.
type DBStats struct {
MaxOpenConnections int // Maximum number of open connections to the database.
// Pool Status
OpenConnections int // The number of established connections both in use and idle.
InUse int // The number of connections currently in use.
Idle int // The number of idle connections.
// Counters
WaitCount int64 // The total number of connections waited for.
WaitDuration time.Duration // The total time blocked waiting for a new connection.
MaxIdleClosed int64 // The total number of connections closed due to SetMaxIdleConns.
MaxIdleTimeClosed int64 // The total number of connections closed due to SetConnMaxIdleTime.
MaxLifetimeClosed int64 // The total number of connections closed due to SetConnMaxLifetime.
}
위에서 부터 읽어보자.
최대 커넥션 개수
현재 열려있는 커넥션 개수
사용중인 커넥션 개수
유휴 커넥션 개수
커넥션을 대기하는 개수
총 대기 시간
SetMaxIdleConns 로 인해 닫힌 유휴 커넥션 개수
SetConnMaxIdleTime 로 인해 닫힌 유휴 커넥션 개수
SetConnMaxLifetime 로 인해 닫힌 커넥션 개수
go 의 *sql.DB 구조체에서는 아래와 같이 설정들을 커스터마이징 할 수 있다.
// 값은 예시
db.SetConnMaxLifetime(time.Hour)
db.SetMaxIdleConns(100)
db.SetConnMaxIdleTime(time.Hour)
db.SetMaxOpenConns(100)
참고로 기본값은 0으로 들어가는데, 이 경우 제한이 없다는 말이다.
물론 제한이 없다고해서 커넥션을 무한대로 만들어낼수는 없다. 또한 어지간한 경우에는 비즈니스 로직을 먼저 검토해보는 것이 좋다.
GORM 에서는 아래와 같이 커스터마이징 할 것을 권고하고 있다.
// Get generic database object sql.DB to use its functions
sqlDB, err := db.DB()
// SetMaxIdleConns sets the maximum number of connections in the idle connection
pool.sqlDB.SetMaxIdleConns(10)
// SetMaxOpenConns sets the maximum number of open connections to the
database.sqlDB.SetMaxOpenConns(100)
// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
sqlDB.SetConnMaxLifetime(time.Hour)
위에서 언급했듯이, 커넥션 관련 문제로 보고 모니터링을 시작했다.
주기적으로 Stats 를 찍어봤을때 MaxConn 이 많아도 20을 넘어가지 않았고, 특이사항으로 보기에는 어려웠다.
다만 특정 작업이 실행될때마다 OpenConn 이 늘어나고 줄어들지 않는 문제가 발견되었다.
이유는 다음과 같았다.
var db := &gorm.DB{}
db.Transaction(func(tx *gorm.DB) error {
db.Where("~~~").Find(&Something{})
})
트랜잭션 안에서 트랜잭션 대신 다른 커넥션을 계속해서 집어오는 레거시가 있었다.
이러한 Job 이 실행되고 나면 커넥션 개수가 하나 늘어나는데, 이런 작업이 몇 개가 있다보니 일종의 커넥션 누수가 발생한 것으로 추정했다.
특이한 것은 강제로 재실행을 했을때 SavePoint 로그가 찍히는 것도 아니고, 에러가 찍힌 뒤에 실행이 되지 않는 경우와 실행이 되는 경우 등 불규칙적인 행태를 보인다는 것이다.
우선 해당 레거시를 모두 수정하고, MaxConnLifetime 을 한 시간으로 설정해서 계속해서 좀비 커넥션이 계속해서 살아남는 것을 방지했다.
아직 작업은 못했지만 추후 커넥션 풀에서 하나씩 폴링해서 받아오는 구조로 변경을 고려중이다.
https://github.com/go-sql-driver/mysql/issues/1120 https://gorm.io/docs/generic_interface.html
회사에서 마주친 에러
$ [mysql] 2024/03/11 18:37:09 packets.go:122: closing bad idle connection: unexpected read from socket
$ [mysql] 2024/03/11 18:37:09 packets.go:122: closing bad idle connection: unexpected read from socket
Batch 처리를 요하는 작업들이 모여있는 인스턴스에서 발생했다.
비즈니스 로직 자체에는 문제가 없었고, 커넥션 관련 설정도 디폴트로 되어있는 상황이었다.
사실 서비스 전체적으로 보면 MySQL 자체를 많이 쓰는 상황은 아니었고, 동시에 실행되는 job 이 MySQL 기반이었어서 커넥션 관련 문제로 좁혀놓고 디버깅을 시작했다.
이 과정에서 새롭게 알게된 사실에 대한 기록.
gorm 은 sql 패키지의 DB 객체를 wrapping 하고 있다.
sql.DB 구조체에는 Stats 라는 메소드가 있다.
var db := &sql.DB{}
stats := db.Stats() // stats ?
Stats 구조체는 아래와 같이 생겼다.
// DBStats contains database statistics.
type DBStats struct {
MaxOpenConnections int // Maximum number of open connections to the database.
// Pool Status
OpenConnections int // The number of established connections both in use and idle.
InUse int // The number of connections currently in use.
Idle int // The number of idle connections.
// Counters
WaitCount int64 // The total number of connections waited for.
WaitDuration time.Duration // The total time blocked waiting for a new connection.
MaxIdleClosed int64 // The total number of connections closed due to SetMaxIdleConns.
MaxIdleTimeClosed int64 // The total number of connections closed due to SetConnMaxIdleTime.
MaxLifetimeClosed int64 // The total number of connections closed due to SetConnMaxLifetime.
}
위에서 부터 읽어보자.
최대 커넥션 개수
현재 열려있는 커넥션 개수
사용중인 커넥션 개수
유휴 커넥션 개수
커넥션을 대기하는 개수
총 대기 시간
SetMaxIdleConns 로 인해 닫힌 유휴 커넥션 개수
SetConnMaxIdleTime 로 인해 닫힌 유휴 커넥션 개수
SetConnMaxLifetime 로 인해 닫힌 커넥션 개수
go 의 *sql.DB 구조체에서는 아래와 같이 설정들을 커스터마이징 할 수 있다.
// 값은 예시
db.SetConnMaxLifetime(time.Hour)
db.SetMaxIdleConns(100)
db.SetConnMaxIdleTime(time.Hour)
db.SetMaxOpenConns(100)
참고로 기본값은 0으로 들어가는데, 이 경우 제한이 없다는 말이다.
물론 제한이 없다고해서 커넥션을 무한대로 만들어낼수는 없다. 또한 어지간한 경우에는 비즈니스 로직을 먼저 검토해보는 것이 좋다.
GORM 에서는 아래와 같이 커스터마이징 할 것을 권고하고 있다.
// Get generic database object sql.DB to use its functions
sqlDB, err := db.DB()
// SetMaxIdleConns sets the maximum number of connections in the idle connection
pool.sqlDB.SetMaxIdleConns(10)
// SetMaxOpenConns sets the maximum number of open connections to the
database.sqlDB.SetMaxOpenConns(100)
// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
sqlDB.SetConnMaxLifetime(time.Hour)
위에서 언급했듯이, 커넥션 관련 문제로 보고 모니터링을 시작했다.
주기적으로 Stats 를 찍어봤을때 MaxConn 이 많아도 20을 넘어가지 않았고, 특이사항으로 보기에는 어려웠다.
다만 특정 작업이 실행될때마다 OpenConn 이 늘어나고 줄어들지 않는 문제가 발견되었다.
이유는 다음과 같았다.
var db := &gorm.DB{}
db.Transaction(func(tx *gorm.DB) error {
db.Where("~~~").Find(&Something{})
})
트랜잭션 안에서 트랜잭션 대신 다른 커넥션을 계속해서 집어오는 레거시가 있었다.
이러한 Job 이 실행되고 나면 커넥션 개수가 하나 늘어나는데, 이런 작업이 몇 개가 있다보니 일종의 커넥션 누수가 발생한 것으로 추정했다.
특이한 것은 강제로 재실행을 했을때 SavePoint 로그가 찍히는 것도 아니고, 에러가 찍힌 뒤에 실행이 되지 않는 경우와 실행이 되는 경우 등 불규칙적인 행태를 보인다는 것이다.
우선 해당 레거시를 모두 수정하고, MaxConnLifetime 을 한 시간으로 설정해서 계속해서 좀비 커넥션이 계속해서 살아남는 것을 방지했다.
아직 작업은 못했지만 추후 커넥션 풀에서 하나씩 폴링해서 받아오는 구조로 변경을 고려중이다.
https://github.com/go-sql-driver/mysql/issues/1120 https://gorm.io/docs/generic_interface.html
No activity yet