>백엔드 개발 >PHP 튜토리얼 >ngx_lua를 사용하여 동시성이 높은 애플리케이션 구축

ngx_lua를 사용하여 동시성이 높은 애플리케이션 구축

WBOY
WBOY원래의
2016-07-30 13:31:381036검색

이 글은 주로 ngx_lua를 통해 백엔드 memcached 및 redis와 비차단 방식으로 통신하는 방법에 중점을 둡니다.

1. Memcached

Nginx에서 Memcached에 액세스하려면 모듈 지원이 필요합니다. 여기서 HttpMemcModule은 백엔드 Memcached와 비차단 통신을 수행할 수 있습니다. Memcached는 공식적으로 제공되는 것으로 알고 있습니다. 이 모듈은 가져오기 작업만 지원하는 반면 Memc는 대부분의 Memcached 명령을 지원합니다.

Memc 모듈은 입력 변수를 매개 변수로 사용하여 $memc_ 접두사가 붙은 모든 변수가 Memc의 입력 변수입니다. memc_pass는 백엔드 Memcached 서버를 가리킵니다.

구성:

[일반] 보기 일반 카피프린트?

  1. #HttpMemcModule 사용
  2. location = /memc {
  3. $memc_cmd $arg_cmd;
  4. $memc_key $arg_key 설정 🎜>
  5. $memc_exptime $arg_exptime;
  6. }
  7. 출력:
  8. [일반 ] 보다 일반 카피프린트?
$ 컬 'http://localhost/memc?cmd=set&key=foo&val=Hello'

$ STORED

    $ 컬 'http://localhost/memc?cmd=get&key=foo'
  1. $ 안녕하세요
  2. 이는 memcached에 대한 액세스를 구현합니다. Lua에서 memcached에 액세스하는 방법을 살펴보겠습니다.
  3. 구성:
  4. [일반] 보기 일반 카피프린트?

#Access Memcached in Lua

location = /memc {

    내부; #내부 액세스만
  1. set $memc_cmd get
  2. set $memc_key $arg_key; 🎜>
  3. memc_pass '127.0.0.1:11211';
  4. }
  5. 위치 = /lua_memc { 🎜>
  6. content_by_lua '
  7. local res = ngx.location.capture("/memc", {
  8. args = { key = ngx.var.arg_key }
  9. })
  10. if res.status == 20 0 then
  11. ngx.say(res.body)
  12. end
  13. '; 🎜>
  14. 출력:
  15. [일반] 보기 일반 카피프린트?
  16. $ 컬 'http://localhost/lua_memc?key=foo'
  17. $ 안녕하세요
Lua를 통해 memcached에 액세스하는 것은 주로 함수 호출과 유사한 방식으로 하위 요청을 통해 구현됩니다. 먼저, memcached 저장소와 동일한 백엔드 memcached를 통한 통신을 위해 memc 위치가 정의됩니다. 전체 Memc 모듈이 비차단이므로 ngx.location.capture도 비차단이므로 전체 작업이 비차단입니다.

2. Redis

Redis에 액세스하려면 비차단 방식으로 Redis와 통신할 수도 있는 HttpRedis2Module의 지원이 필요합니다. 그러나 redis2의 응답은 redis의 기본 응답이므로 Lua에서 사용할 경우 이 응답을 구문 분석해야 합니다. LuaRedisModule을 사용할 수 있습니다. 이 모듈은 redis의 기본 요청을 구성하고 redis의 기본 응답을 구문 분석할 수 있습니다.

구성:

[일반] 보기 일반 카피프린트?

  1. #Lua의 Redis 액세스
  2. location = /redis {
  3. 내부; #내부 액세스만
  4. redis2_query get $arg_key;
  5. redis2_pass '127.0.0.1:6379' 🎜>
  6. }
  7. location = /lua_redis { #LuaRedisParser 필요
  8. content_by_lua '
  9. local 파서 = require("redis.parser")
  10. local res = ngx.location.capture("/redis", {
  11. args = { key = ngx.var.arg_key }
  12. })
  13. if res. = 200 then >
  14. end
  15.  ' 출력:
  16. [일반] 보기 일반 카피프린트?
  17. $ 컬 'http://localhost/lua_redis?key=foo'
  18. $ 안녕하세요
Memcached에 액세스하는 것과 마찬가지로 Redis 쿼리를 위해 특별히 Redis 저장소를 제공한 다음 하위 요청을 통해 Redis를 호출해야 합니다. 3. Redis Pipeline

실제로 Redis에 접속할 때 여러 키를 동시에 쿼리해야 할 수도 있습니다. ngx.location.capture_multi를 사용하여 여러 하위 요청을 Redis 저장소로 보낸 다음 응답 내용을 구문 분석할 수 있습니다. 그러나 Nginx 커널에서는 한 번에 시작할 수 있는 하위 요청 수가 50개를 초과할 수 없다고 규정하고 있으므로 키 수가 50개를 초과하면 이 솔루션은 더 이상 적용되지 않습니다.

다행스럽게도 redis는 하나의 연결에서 여러 명령을 실행할 수 있는 파이프라인 메커니즘을 제공하므로 명령을 여러 번 실행하는 데 따른 왕복 지연을 줄일 수 있습니다. 클라이언트가 파이프라인을 통해 여러 명령을 보낸 후 redis는 이러한 명령을 순차적으로 수신하고 실행한 다음 명령의 결과를 순차적으로 출력합니다. Lua에서 파이프라인을 사용할 때 redis2 모듈의 redis2_raw_queries를 사용하여 redis의 기본 요청 쿼리를 수행해야 합니다.
  1. 구성: [일반] 보기 일반 카피프린트?
    1. #Lua의 Redis 액세스
    2. location = /redis {
    3. 내부 ; '127.0.0.1:6379';
    4. content_by_lua 'conf/pipeline.lua'
    5. }
    6. 파이프라인 .lua
    7. [일반] 보기 일반 카피프린트?
    8. -- conf/pipeline.lua 파일
    9. local 파서 = require('redis.parser ')
    10. local reqs = {
    {'get', 'one'}, {'get', 'two'} }

    --네이티브 Redis 쿼리를 구성하고 onernget twon
    1. local raw_reqs = { }
    2. i의 경우 req in ipairs(reqs) do
    3. table.insert(raw_reqs,parser.build_query(req))
    4. local res = ngx.location.capture('/redis?'..#reqs, { body = table.concat( raw_reqs , '') }) 
    5.                                                                            ~ | plies) do
    6. ngx.say(reply[1])
    7. end end
    8. 출력:
    9. [일반] 보기 일반 카피프린트?
    10. $ 컬 'http://localhost/pipeline'
    11. $ 먼저
    12. 4. Connection Pool
    13. 이전 Redis 및 Memcached에 액세스하는 예에서는 요청이 처리될 때마다 , 백엔드 서버와의 연결이 설정되고 요청이 처리된 후 연결이 해제됩니다. 이 프로세스에서는 세 번의 핸드셰이크 및 대기 시간과 같은 약간의 오버헤드가 발생하며 이는 동시성이 높은 애플리케이션에서는 허용되지 않습니다. 이러한 오버헤드를 제거하기 위해 연결 풀이 여기에 도입되었습니다. 연결 풀에는 HttpUpstreamKeepaliveModule 모듈의 지원이 필요합니다.
    14. 구성:
    15. [일반] 보기 일반 카피프린트?
      1. http {
      2. # HttpUpstreamKeepaliveModule 필요 🎜>
      3. 서버 127.0.0.1:6379;
      4. # 1024개의 연결을 수용할 수 있는 연결 풀
      5. keepalive 1024 Single 🎜 > location = /redis {
      6. redis2_pass redis_pool;
      7. } 이 모듈은 keepalive 지시문과 해당 컨텍스트를 제공합니다. 업스트림입니다. Nginx를 역방향 프록시로 사용할 때 업스트림이 사용된다는 것을 알고 있습니다. 실제로 업스트림은 "업스트림"을 의미하며 redis, memcached 또는 mysql과 같은 일부 서버일 수 있습니다. 업스트림은 가상 서버 클러스터를 정의할 수 있으며 이러한 백엔드 서버는 로드 밸런싱을 누릴 수 있습니다. Keepalive 1024는 연결 풀의 크기를 정의합니다. 연결 수가 이 크기를 초과하면 후속 연결이 자동으로 짧은 연결로 변질됩니다. 연결 풀의 사용은 매우 간단합니다. 원래 IP와 포트 번호를 바꾸면 됩니다.
      8. 누군가가 연결 풀을 사용하지 않고(이전 Memc 모듈을 사용하여) memcached에 액세스했을 때 rps가 20,000이었다고 측정한 적이 있습니다. Connection Pool을 사용한 후 rps는 140,000까지 치솟았습니다. 실제 상황에서는 이렇게 큰 개선이 이루어지지 않을 수도 있지만 기본적으로 100~200% 개선은 여전히 ​​가능합니다.
      9. 5. 요약
      10. memcached 및 redis에 대한 액세스 요약은 다음과 같습니다. 1. Nginx는 강력한 프로그래밍 모델을 제공합니다. 위치는 함수와 동일하고, 하위 요청은 함수 호출과 동일하며, 위치도 하위 요청을 자신에게 보낼 수 있으므로 재귀 모델을 형성합니다. 모델이 채택되었습니다. 복잡한 비즈니스 로직을 구현합니다.
      11. 2. Nginx의 IO 작업은 비차단이어야 합니다. Nginx가 이를 차단하면 Nginx의 성능이 크게 저하됩니다. 따라서 Lua에서는 이러한 IO 작업을 Nginx의 이벤트 모델에 위임하기 위해 ngx.location.capture를 통해 하위 요청을 발행해야 합니다. 3. TCP 연결을 사용해야 할 경우 연결 풀을 사용해 보세요. 이렇게 하면 연결 설정 및 해제 시 많은 오버헤드가 제거됩니다.
      12. 위 내용은 내용의 측면을 포함하여 동시성이 높은 애플리케이션을 구축하기 위한 ngx_lua의 사용을 소개합니다. PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.