lua 개발 -- my sql 과 http 모듈

20370 단어 lua
Mysql 클 라 이언 트
lua - resty - mysql 은 cosocket API 기반 의 ngxlua 가 제공 하 는 Lua Mysql 클 라 이언 트 는 이 를 통 해 Mysql 작업 을 완성 할 수 있 습 니 다.기본적으로 OpenResty 를 설치 할 때 이 모듈 을 가 져 왔 습 니 다. 문 서 를 참고 할 수 있 습 니 다.https://github.com/openresty/lua-resty-mysql。
편집 testmysql.lua
local function close_db(db)
    if not db then
        return
    end
    db:close()
end

local mysql = require("resty.mysql")
--    
local db, err = mysql:new()
if not db then
    ngx.say("new mysql error : ", err)
    return
end
--      (  )
db:set_timeout(1000)

local props = {
    host = "127.0.0.1",
    port = 3306,
    database = "mysql",
    user = "root",
    password = "123456"
}

local res, err, errno, sqlstate = db:connect(props)

if not res then
   ngx.say("connect to mysql error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)
   return close_db(db)
end

--   
local drop_table_sql = "drop table if exists test"
res, err, errno, sqlstate = db:query(drop_table_sql)
if not res then
   ngx.say("drop table error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)
   return close_db(db)
end

--   
local create_table_sql = "create table test(id int primary key auto_increment, ch varchar(100))"
res, err, errno, sqlstate = db:query(create_table_sql)
if not res then
   ngx.say("create table error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)
   return close_db(db)
end

--  
local insert_sql = "insert into test (ch) values('hello')"
res, err, errno, sqlstate = db:query(insert_sql)
if not res then
   ngx.say("insert error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)
   return close_db(db)
end

res, err, errno, sqlstate = db:query(insert_sql)

ngx.say("insert rows : ", res.affected_rows, " , id : ", res.insert_id, "
"
) -- local update_sql = "update test set ch = 'hello2' where id =" .. res.insert_id res, err, errno, sqlstate = db:query(update_sql) if not res then ngx.say("update error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate) return close_db(db) end ngx.say("update rows : ", res.affected_rows, "
"
) -- local select_sql = "select id, ch from test" res, err, errno, sqlstate = db:query(select_sql) if not res then ngx.say("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate) return close_db(db) end for i, row in ipairs(res) do for name, value in pairs(row) do ngx.say("select row ", i, " : ", name, " = ", value, "
"
) end end ngx.say("
"
) -- sql local ch_param = ngx.req.get_uri_args()["ch"] or '' -- ngx.quote_sql_str sql local query_sql = "select id, ch from test where ch = " .. ngx.quote_sql_str(ch_param) res, err, errno, sqlstate = db:query(query_sql) if not res then ngx.say("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate) return close_db(db) end for i, row in ipairs(res) do for name, value in pairs(row) do ngx.say("select row ", i, " : ", name, " = ", value, "
"
) end end -- local delete_sql = "delete from test" res, err, errno, sqlstate = db:query(delete_sql) if not res then ngx.say("delete error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate) return close_db(db) end ngx.say("delete rows : ", res.affected_rows, "
"
) close_db(db)

추가 / 수정 / 삭제 에 대해 다음 형식의 응답 을 되 돌려 줍 니 다.
{
    insert_id = 0,
    server_status = 2,
    warning_count = 1,
    affected_rows = 32,
    message = nil
}

affected_rows 는 조작 에 영향 을 주 는 줄 수 를 표시 합 니 다. insertid 는 자체 증가 시퀀스 를 사용 할 때 발생 하 는 id 입 니 다.
검색 에 대해 서 는 다음 형식의 응답 을 되 돌려 줍 니 다.
{  
        { id= 1, ch= "hello"},  
        { id= 2, ch= "hello2"}  
    }  

null 은 ngx. null 로 돌아 갑 니 다.
example. conf 프로필
     location /lua_mysql {
        default_type 'text/html';
        lua_code_cache on;
        content_by_lua_file /usr/example/lua/test_mysql.lua;
     }

3. 방문http://192.168.1.2/lua_my sql? ch = hello 테스트 를 통 해 다음 과 같은 결 과 를 얻 었 습 니 다.
    insert rows : 1 , id : 2  
    update rows : 1  
    select row 1 : ch = hello  
    select row 1 : id = 1  
    select row 2 : ch = hello2  
    select row 2 : id = 2  
    select row 1 : ch = hello  
    select row 1 : id = 1  
    delete rows : 2  

클 라 이언 트 는 아직 사전 컴 파일 SQL 지원 (즉, 자리 표시 자 교체 위치 변수) 을 제공 하지 않 았 습 니 다. 이렇게 하면 인삼 에 들 어 갈 때 ngx. quote 를 사용 하 는 것 을 기억 합 니 다.sql_str 문자열 의 의 미 를 바 꾸 어 sql 주입 을 방지 합 니 다.연결 풀 은 이전 레 디 스 클 라 이언 트 와 똑 같 아서 소개 하지 않 습 니 다.
Mysql 클 라 이언 트 에 대한 소 개 는 기본적으로 충분 합 니 다. 더 많은 참고 바 랍 니 다.https://github.com/openresty/lua-resty-mysql。
MongoDB 와 같은 다른 데이터베이스 클 라 이언 트 는 github 에서 찾 아 사용 할 수 있 습 니 다.
Http 클 라 이언 트
OpenResty 는 기본적으로 Http 클 라 이언 트 를 제공 하지 않 았 기 때문에 제3자 가 제공 해 야 합 니 다.물론 우 리 는 ngx. location. capture 를 통 해 실현 할 수 있 지만 제한 이 있 습 니 다. 나중에 다시 소개 하 겠 습 니 다.
우 리 는 github 에서 해당 하 는 클 라 이언 트 를 검색 할 수 있 습 니 다. 예 를 들 어https://github.com/pintsized/lua-resty-http。
lua-resty-http
1. lua - resty - http 클 라 이언 트 를 lualib 에 다운로드 합 니 다.
cd /usr/example/lualib/resty/  
wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http_headers.lua  
wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http.lua 

2、test_http_1.lua
local http = require("resty.http")
--  http     
local httpc = http.new()

local resp, err = httpc:request_uri("http://s.taobao.com", {
    method = "GET",
    path = "/search?q=hello",
    headers = {
        ["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36"
    }
})

if not resp then
    ngx.say("request error :", err)
    return
end

--     
ngx.status = resp.status

--     
for k, v in pairs(resp.headers) do
    if k ~= "Transfer-Encoding" and k ~= "Connection" then
        ngx.header[k] = v
    end
end
--   
ngx.say(resp.body)

httpc:close()

응답 헤더 에 있 는 Transfer - Encoding 과 Connection 은 무시 할 수 있 습 니 다. 이 데 이 터 는 현재 server 에서 출력 되 었 기 때 문 입 니 다.
3. example. conf 프로필
  location /lua_http_1 {
        default_type 'text/html';
        lua_code_cache on;
        content_by_lua_file /usr/example/lua/test_http_1.lua;
     }

4. nginx. conf 의 http 부분 에 다음 명령 을 추가 하여 DNS 분석 을 합 니 다.
    resolver 8.8.8.8;  

DNS 해상도 기 resolver 8.8.8.8 을 설정 해 야 합 니 다. 그렇지 않 으 면 도 메 인 이름 을 분석 할 수 없습니다.5. 방문http://192.168.1.2/lua_http_1 타 오 바 오의 검색 창 을 볼 수 있 습 니 다.
사용 방식 이 비교적 간단 합 니 다. 예 를 들 어 시간 초과 와 연결 풀 설정 은 이전 Redis 클 라 이언 트 와 마찬가지 로 설명 하지 않 습 니 다.더 많은 클 라 이언 트 사용 규칙 참고https://github.com/pintsized/lua-resty-http。
ngx.location.capture
ngx. location. capture 도 http 요청 을 완성 할 수 있 지만 현재 nginx 서버 에 비해 경로 만 요청 할 수 있 습 니 다. 이전의 절대 경 로 를 사용 하여 접근 할 수 없 지만 nginx upstream 에 맞 춰 우리 가 원 하 는 기능 을 실현 할 수 있 습 니 다.
1. ngix. cong 의 http 부분 에 다음 upstream 설정 을 추가 합 니 다.
  upstream backend {  
        server s.taobao.com;  
        keepalive 100;  
    }  

즉, upstream 에 backend 로 요청 합 니 다.또한 이전의 DNS 해상도 기 를 반드시 추가 해 야 한 다 는 것 을 기억 하 세 요.
2. example. conf 에서 다음 location 설정
    location ~ /proxy/(.*) {  
       internal;  
       proxy_pass http://backend/$1$is_args$args;  
    }  

내부 접근 만 가능 하 다 는 뜻 입 니 다. 즉, 외부 에서 url 을 통 해 접근 할 수 없습니다.그리고 proxypass 는 upstream 에 전송 을 요청 합 니 다.
3、test_http_2.lua
    local resp = ngx.location.capture("/proxy/search", {  
        method = ngx.HTTP_GET,  
        args = {q = "hello"}  

    })  
    if not resp then  
        ngx.say("request error :", err)  
        return  
    end  
    ngx.log(ngx.ERR, tostring(resp.status))  

    --       
    ngx.status = resp.status  

    --       
    for k, v in pairs(resp.header) do  
        if k ~= "Transfer-Encoding" and k ~= "Connection" then  
            ngx.header[k] = v  
        end  
    end  
    --     
    if resp.body then  
        ngx.say(resp.body)  
    end  

ngx. location. capture 를 통 해 하위 요청 을 보 냅 니 다. 이 곳 은 하위 요청 이기 때문에 모든 요청 헤더 가 현재 요청 에서 계승 되 었 습 니 다. 예 를 들 어 ngx. ctx 와 ngx. var 의 계승 여 부 는 공식 문 서 를 참고 할 수 있 습 니 다.http://wiki.nginx.org/HttpLuaModule#ngx.location.capture。 또한 ngx. location. capture 도 제공 합 니 다.multi 는 여러 개의 요청 을 동시에 보 내 는 데 사 용 됩 니 다. 이러한 총 응답 시간 은 가장 느 린 것 입 니 다. 대량으로 호출 할 때 유용 합 니 다.4. example. conf 프로필 location / luhttp_2 {default type 'text / html'; lua code cache on; content by lua file / usr / example / lua / test http 2. lua;} 5.http://192.168.1.2/lua_http_2 테스트 를 진행 하면 타 오 바 오 검색 창 을 볼 수 있 습 니 다.
우 리 는 upstream + ngx. location. capture 방식 을 통 해 번 거 롭 지만 더 좋 은 성능 과 upstream 의 연결 탱크, 부하 균형, 고장 전이, proxy cache 등 특성 을 얻 을 수 있 습 니 다.
그러나 현재 요청 한 요청 헤더 에 계승 하기 때문에 문제 가 있 을 수 있 습 니 다. 흔히 볼 수 있 는 것 은 gzip 압축 문제 입 니 다. ngx. location. capture 는 백 엔 드 서버 의 GZIP 내용 을 압축 하지 않 습 니 다. 해결 방법 은 참고 할 수 있 습 니 다.https://github.com/openresty/lua-nginx-module/issues/12;대부분의 http 호출 은 내부 서비스 이기 때문에 proxy location 에 proxy 를 추가 할 수 있 습 니 다.pass_request_headers off;요청 헤더

좋은 웹페이지 즐겨찾기