일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- ubuntu
- PYTHON
- 실행권한
- insert
- nmap
- Materials
- GoCD
- postgresql
- ssh
- SWIFT
- nohup
- nGrinder
- rethinkdb
- sshpass
- ftp
- postgres
- STF_PortForwarding
- 28015
- perfect
- centos
- openpyxl
- appium
- port forwarding
- Jupyter
- Jupyter Notebook
- STF
- create table
- appium server
- kitura
- mysql
- Today
- Total
don't stop believing
Goroutines inside a middleware 본문
Server 개발 시 비동기로 처리해야 할 때가 있습니다. 저 같은 경우 redis에 쓰기 처리를 할때는 보통 비동기로 처리하기도 합니다.
go에서 비동기 처리 할 때는 goroutine을 사용합니다.
https://github.com/gin-gonic/gin#goroutines-inside-a-middleware
goroutine을 사용할 때 중요한 부분은 gin의 원본 context를 사용하면 안되고 읽기 전용으로 복제해서 사용해야 합니다.
When starting new Goroutines inside a middleware or handler, you SHOULD NOT use the original context inside it, you have to use a read-only copy.
바로 코드를 확인하면 아래와 같습니다.
package main import ( "log" "time" "github.com/gin-gonic/gin" ) func setupRouter() *gin.Engine { // Disable Console Color // gin.DisableConsoleColor() r := gin.Default() r.GET("/long_async", longAsync) r.GET("/long_sync", longSync) return r } func longAsync(c *gin.Context) { // create copy to be used inside the goroutine cCp := c.Copy() go func() { // simulate a long task with time.Sleep(). 5 seconds time.Sleep(5 * time.Second) // note that you are using the copied context "cCp", IMPORTANT log.Println("Done! in path " + cCp.Request.URL.Path) }() } func longSync(c *gin.Context) { // simulate a long task with time.Sleep(). 5 seconds time.Sleep(5 * time.Second) // since we are NOT using a goroutine, we do not have to copy the context log.Println("Done! in path " + c.Request.URL.Path) } func main() { r := setupRouter() // Listen and Server in 0.0.0.0:8080 r.Run(":8080") }
goroutine을 사용한 async 처리와 그렇지 않은 sync 처리를 비교할 수 있습니다.
실행하고 두 route를 호출하면 아래와 같은 결과가 나옵니다.
$ go run example/server.go [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached. [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. - using env: export GIN_MODE=release - using code: gin.SetMode(gin.ReleaseMode) [GIN-debug] GET /long_async --> main.longAsync (3 handlers) [GIN-debug] GET /long_sync --> main.longSync (3 handlers) [GIN-debug] Listening and serving HTTP on :8080 [GIN] 2019/03/14 - 15:51:58 | 404 | 876ns | ::1 | GET /login-asinc [GIN] 2019/03/14 - 15:52:10 | 200 | 3.486µs | ::1 | GET /long_async 2019/03/14 15:52:15 Done! in path /long_async 2019/03/14 15:53:05 Done! in path /long_sync [GIN] 2019/03/14 - 15:53:05 | 200 | 5.00426148s | ::1 | GET /long_sync
/long_async를 호출하면 아래와 같이 15:52:10초에 response가 리턴되고 groutine은 그보다 5초 후인 15:52:15에 종료됩니다.
[GIN] 2019/03/14 - 15:52:10 | 200 | 3.486µs | ::1 | GET /long_async
2019/03/14 15:52:15 Done! in path /long_async
/long_sync의 경우 5초를 기다린 다음 response가 리턴됩니다.
2019/03/14 15:53:05 Done! in path /long_sync
[GIN] 2019/03/14 - 15:53:05 | 200 | 5.00426148s | ::1 | GET /long_sync
비동기 처리에 사용하면 좋습니다.
'Golang > Gin' 카테고리의 다른 글
Bind Uri (0) | 2019.03.14 |
---|---|
How to write log file (0) | 2019.03.14 |
Only Bind Query String (0) | 2019.03.09 |
Bind Query String or Post Data (0) | 2019.03.09 |
Model binding and validation (0) | 2019.03.06 |