>  기사  >  백엔드 개발  >  nginx+루아+레디스

nginx+루아+레디스

WBOY
WBOY원래의
2016-08-08 09:19:061099검색
최근에는 nginx+lua+redis를 사용하여 높은 동시성 및 트래픽이 많은 애플리케이션을 지원하는 시스템을 구축하고 있습니다. 개발 중에 문득 golang도 같은 효과를 낼 수 있지 않을까 하는 생각이 들었습니다. 그래서 비교를 위해 간단한 코드를 작성했습니다. 자세히 설명하지는 않겠습니다. nginx+lua+redis를 사용하여 동시성 높은 애플리케이션을 구축하는 방법에 대한 소개는 인터넷에 많이 있습니다. 저는 openresty+lua+redis를 사용하고 있습니다. 테스트 결과를 먼저 게시하세요. 기기는 2013년에 출시된 새로운 로우 프로파일 air입니다. - (1.3 GHz Intel Core i5, 4 GB 1600 MHz DDR3), 명령: ab -n 1000 -c 100 http://localhost:8880/openresty+lua+redis: Concurrency Level: 100 Time taken for tests: 0.458 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 689000 bytes HTML transferred: 533000 bytes Requests per second: 2183.67 [#/sec] (mean) Time per request: 45.794 [ms] (mean) Time per request: 0.458 [ms] (mean, across all concurrent requests) Transfer rate: 1469.29 [Kbytes/sec] received golang+redis: Concurrency Level: 100 Time taken for tests: 0.503 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 650000 bytes HTML transferred: 532000 bytes Requests per second: 1988.22 [#/sec] (mean) Time per request: 50.296 [ms] (mean) Time per request: 0.503 [ms] (mean, across all concurrent requests) Transfer rate: 1262.05 [Kbytes/sec] received lua 코드: -- redis 配置localparams={host='127.0.0.1',port=6379,}localred=redis:new()localok,err=red:connect(params.host,params.port)ifnotokthenngx.say("failed to connect: ",err)returnendlocalposition_key=ngx.var.position_keylocalcontent=red:get(position_key)ngx.print(content)golang 코드: packagemainimport("fmt""github.com/garyburd/redigo/redis""log""net/http""time")funcgetConn()(redis.Conn,error){conn,err:=redis.DialTimeout("tcp",":6379",0,1*time.Second,1*time.Second)iferr!=nil{fmt.Println(err)}returnconn,err}funcindexHandler(whttp.ResponseWriter,r*http.Request){conn,err:=getConn()iferr!=nil{http.Error(w,err.Error(),http.StatusInternalServerError)return}result,err:=conn.Do("get","content_1")iferr!=nil{http.Error(w,err.Error(),http.StatusInternalServerError)return}fmt.Fprintf(w,"Hello, %q",result)}funcmain(){http.HandleFunc("/",indexHandler)err:=http.ListenAndServe(":8880",nil)iferr!=nil{log.Fatal("ListenAndServe: ",err.Error())}} 이후 다수 번 스트레스 테스트를 거친 후 우리는 nginx + lua + redis의 조합이 실제로 효율적이며 golang + redis의 솔루션도 크게 다르지 않다는 것을 발견했습니다. 전체 시스템을 개발하여 배포하는 방식과 비교하면 golang이 개발 습관에 더 적합하고 더 적합할 수 있습니다. 결국 nginx + lua의 개발 및 테스트는 약간 어색합니다. Connection Pool 보충 사용법 및 테스트 결과

마지막 테스트를 마치고 이 코드에 개선의 여지가 있다고 느껴서 golang에서 Redis Connection Pool을 어떻게 사용하는지 확인해 봤습니다. (실제로는 redigo를 사용하는 방법입니다.) Lua에서 redis 연결 풀을 사용하는 방법은 (실제로는 Rest.redis를 사용하는 방법입니다.)

먼저 결과로 이동:

openresty + lua + redis Concurrency Level: 100 Time taken for tests: 0.284 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 687000 bytes HTML transferred: 531000 bytes Requests per second: 3522.03 [#/sec] (mean) Time per request: 28.393 [ms] (mean) Time per request: 0.284 [ms] (mean, across all concurrent requests) Transfer rate: 2362.93 [Kbytes/sec] received

그런 다음 golang을 살펴보세요.

golang + redis Concurrency Level: 100 Time taken for tests: 0.327 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 650000 bytes HTML transferred: 532000 bytes Requests per second: 3058.52 [#/sec] (mean) Time per request: 32.696 [ms] (mean) Time per request: 0.327 [ms] (mean, across all concurrent requests) Transfer rate: 1941.44 [Kbytes/sec] received

lua 코드:

-- redis 配置localparams={host='127.0.0.1',port=6379,}localred=redis:new()localok,err=red:connect(params.host,params.port)ifnotokthenngx.say("failed to connect: ",err)returnendlocalposition_key=ngx.var.position_keylocalcontent=red:get(position_key)ngx.print(content)localok,err=red:set_keepalive(10000,100)ifnotokthenngx.say("failed to set keepalive: ",err)returnend

golang 코드:

packagemainimport("flag""fmt""github.com/garyburd/redigo/redis""log""net/http""runtime""time")var(pool*redis.PoolredisServer=flag.String("redisServer",":6379",""))funcindexHandler(whttp.ResponseWriter,r*http.Request){t0:=time.Now()conn:=pool.Get()t1:=time.Now()fmt.Printf("The call took %v to run.\n",t1.Sub(t0))deferconn.Close()result,err:=conn.Do("get","content_1")iferr!=nil{http.Error(w,err.Error(),http.StatusInternalServerError)return}fmt.Fprintf(w,"Hello, %q",result)}funcnewPool(serverstring)*redis.Pool{return&redis.Pool{MaxIdle:3,IdleTimeout:240*time.Second,Dial:func()(redis.Conn,error){c,err:=redis.Dial("tcp",server)iferr!=nil{returnnil,err}returnc,err},TestOnBorrow:func(credis.Conn,ttime.Time)error{_,err:=c.Do("PING")returnerr},}}funcmain(){runtime.GOMAXPROCS(runtime.NumCPU())flag.Parse()pool=newPool(*redisServer)http.HandleFunc("/",indexHandler)err:=http.ListenAndServe(":8880",nil)iferr!=nil{log.Fatal("ListenAndServe: ",err.Error())}}

golang은 스레드 풀을 추가하는 것 외에도 CPU 코어 수도 설정합니다.

그러나 이 테스트는 그다지 엄격하지 않습니다. Redis, nginx, golang http 서버 및 ab 스트레스 테스트는 모두 동일한 시스템에 있으며 서로 영향을 미칩니다. 관심이 있는 경우 별도로 배포하고 테스트할 수 있습니다.

위에서는 nginx+lua+redis에 대한 내용을 소개했으며, PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.