1. 程式人生 > >Openresty學習(三):通過子請求完成redis的訪問

Openresty學習(三):通過子請求完成redis的訪問

在Openresty學習(二)基礎上,修改程式碼支援redis訪問(以查詢key值為例)。

官網參考:

http://openresty.org/cn/redis-nginx-module.html

https://github.com/openresty/redis2-nginx-module#redis2_query

配置:

        upstream redisbackend {
           server 127.0.0.1:6379;
           #keepalive 1024 single;
        }

        location = /redis_get {
                set_unescape_uri $key $arg_key;  
                redis2_query get $key;
                redis2_pass 127.0.0.1:6379;
        }

        location = /redis_set {
                set_unescape_uri $key $arg_key;  
                set_unescape_uri $val $arg_val;
                redis2_query set $key $val;
                redis2_pass 127.0.0.1:6379;
        }

測試結果:

1.使用子請求測試

[email protected]:~# curl -i -X POST -H "'Content-type':'application/json'" -d '{"cmd":"jquery","name":"zhangsan"}' http://47.93.228.87:80/mysql_test
HTTP/1.1 200 OK
Server: openresty/1.13.6.1
Date: Sun, 13 May 2018 03:38:56 GMT
Content-Type: text/plain; charset=GBK
Content-Length: 8
Connection: keep-alive


$2
18

2. 直接測試:

[email protected]:~# curl "http://47.93.228.87:80/redis_set?key=zhangsan&val=18"

+OK

[email protected]:~# curl "http://47.93.228.87:80/redis_get?key=zhangsan"
$2
18

其它問題:

upstream訪問redis返回資料格式為字串形式,還不清楚是否支援其它格式(如JSON格式)

原始碼:


#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>

#include "cJSON.h"

typedef struct {
    ngx_str_t output_words;
    ngx_uint_t flag;
} ngx_http_sub_request_mysql_loc_conf_t;

static char* ngx_http_sub_request_mysql(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);

static void* ngx_http_sub_request_mysql_create_loc_conf(ngx_conf_t* cf);

static char* ngx_http_sub_request_mysql_merge_loc_conf(ngx_conf_t* cf, void* parent, void* child);

static ngx_command_t ngx_http_sub_request_mysql_commands[] = {
    {
        ngx_string("sub_request_mysql"), // The command name
        NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
        ngx_http_sub_request_mysql, // The command handler
        NGX_HTTP_LOC_CONF_OFFSET,
        offsetof(ngx_http_sub_request_mysql_loc_conf_t, output_words),
        NULL
    },

    ngx_null_command
};

// Structure for the HelloWorld context
static ngx_http_module_t ngx_http_sub_request_mysql_module_ctx = {
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    ngx_http_sub_request_mysql_create_loc_conf,
    ngx_http_sub_request_mysql_merge_loc_conf
};

// Structure for the HelloWorld module, the most important thing
ngx_module_t ngx_http_sub_request_mysql_module = {
    NGX_MODULE_V1,
    &ngx_http_sub_request_mysql_module_ctx,
    ngx_http_sub_request_mysql_commands,
    NGX_HTTP_MODULE,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NGX_MODULE_V1_PADDING
};

typedef struct {
    ngx_str_t name;
    ngx_str_t db_request_data;
} ngx_http_extern_request_mysql_ctx_t;

static void extern_db_request_post_handler(ngx_http_request_t *r)
{
    ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0,
                                "%s: status[%d]",__FUNCTION__, r->headers_out.status); 

    if (r->headers_out.status != NGX_HTTP_OK)
    {
        ngx_http_finalize_request(r, r->headers_out.status);
        return;
    }

    ngx_http_extern_request_mysql_ctx_t *my_ctx = ngx_http_get_module_ctx(r,
            ngx_http_sub_request_mysql_module);

    int bodylen = my_ctx->db_request_data.len;
    r->headers_out.content_length_n = bodylen;

    ngx_buf_t *b = ngx_create_temp_buf(r->pool,bodylen);
    ngx_snprintf(b->pos, bodylen, (char *)my_ctx->db_request_data.data);
    b->last = b->pos + bodylen;
    b->last_buf = 1;

    ngx_chain_t out;
    out.buf = b;
    out.next = NULL;

    static ngx_str_t type = ngx_string("text/plain; charset=GBK");
    r->headers_out.content_type= type;
    r->headers_out.status =NGX_HTTP_OK; 

    r->connection->buffered |= NGX_HTTP_WRITE_BUFFERED;
    ngx_int_t ret = ngx_http_send_header(r);
    ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0,
            "%s: send header ret[%d]", __FUNCTION__, ret);
    ret = ngx_http_output_filter(r,&out);

    ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0,
            "%s: send body ret[%d]", __FUNCTION__, ret); 

    ngx_http_finalize_request(r,ret);
}

static ngx_int_t extern_db_sub_req_post_handler(ngx_http_request_t *r,
        void *data, ngx_int_t rc)
{
    ngx_str_t response_data;
    ngx_http_request_t *pr = r->parent;

    ngx_http_extern_request_mysql_ctx_t *my_ctx = ngx_http_get_module_ctx(pr,
            ngx_http_sub_request_mysql_module);
    pr->headers_out.status = r->headers_out.status;

    ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0,
                                "%s: %d",__FUNCTION__, r->headers_out.status);

    if (r->headers_out.status == NGX_HTTP_OK)
    {
        ngx_buf_t *sub_recv_buf = &r->upstream->buffer;

        response_data.data = sub_recv_buf->pos;
        response_data.len = ngx_buf_size(sub_recv_buf);

        ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0,
                "data: %d, %V", response_data.len,
                &response_data);
        my_ctx->db_request_data.len = response_data.len;
        my_ctx->db_request_data.data = response_data.data;
    }

    pr->write_event_handler = extern_db_request_post_handler;

    return NGX_OK;
}

static void ngx_http_sub_request_mysql_client_body_handler_pt(ngx_http_request_t *r)
{
    ngx_int_t rc = NGX_OK;
    char log_buf[32] = {0};
    u_char body_buf[256] = {0};
    ngx_buf_t *p_body_buf = NULL;
    cJSON *root = NULL;
    cJSON *name = NULL;
    cJSON *command = NULL;
    cJSON *age = NULL;

    ngx_http_sub_request_mysql_loc_conf_t* hlcf = NULL;
    hlcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_request_mysql_module);
    if (NULL == hlcf)
    {
    }

    ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0,
                          "%s", log_buf);

    p_body_buf = r->request_body->bufs->buf;
    ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0,
                          "length:%d", ngx_buf_size(p_body_buf));
    
    ngx_snprintf(body_buf, sizeof(body_buf), "%*s",
            ngx_buf_size(p_body_buf), p_body_buf->pos);

    ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0,
            "main: receive body:%s", body_buf);

    root = cJSON_Parse((char *)body_buf);
    if (NULL == root)
    {
        return;
    }

    command = cJSON_GetObjectItemCaseSensitive(root, "cmd");
    if (NULL == command)
    {
        return;
    }
    
    name = cJSON_GetObjectItemCaseSensitive(root, "name");
    if (NULL == name)
    {
        return;
    }

    ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0,
                          "parse cmd: %s, name: %s",
                          command->valuestring,
                          name->valuestring);    

    ngx_http_extern_request_mysql_ctx_t *my_ctx = ngx_http_get_module_ctx(r,
            ngx_http_sub_request_mysql_module);
    if (NULL == my_ctx)
    {
        my_ctx = ngx_palloc(r->pool, sizeof(ngx_http_extern_request_mysql_ctx_t));
        if (NULL == my_ctx)
        {
            return;
        }

        ngx_http_set_ctx(r, my_ctx, ngx_http_sub_request_mysql_module);
    }

    ngx_http_post_subrequest_t *my_sub_req = ngx_palloc(r->pool,
            sizeof(ngx_http_post_subrequest_t));
    if (NULL == my_sub_req)
    {
        return;
    }

    my_sub_req->handler = extern_db_sub_req_post_handler;

    my_sub_req->data = my_ctx;

    ngx_str_t sub_uri;
    ngx_str_t sub_args;

    if (0 == ngx_strncmp(command->valuestring, "query", strlen("query")))
    {
        sub_uri.len = ngx_strlen("/mysql_query");
        sub_uri.data = ngx_palloc(r->pool,sub_uri.len);
        ngx_snprintf(sub_uri.data, sub_uri.len, "%s",
               "/mysql_query");

        sub_args.len = ngx_strlen("name=") + ngx_strlen(name->valuestring);
        sub_args.data = ngx_palloc(r->pool,sub_args.len);
        ngx_snprintf(sub_args.data, sub_args.len, "%s%s",
               "name=", name->valuestring);
    }
    else if (0 == ngx_strncmp(command->valuestring, "add", strlen("add")))
    {
        age = cJSON_GetObjectItemCaseSensitive(root, "age");
        if (NULL == age)
        {
            return;
        }
        sub_uri.len = ngx_strlen("/mysql_add");
        sub_uri.data = ngx_palloc(r->pool,sub_uri.len);
        ngx_snprintf(sub_uri.data, sub_uri.len, "%s",
               "/mysql_add");

        sub_args.len = ngx_strlen("name=") + ngx_strlen(name->valuestring)
                + ngx_strlen("age=") + ngx_strlen(age->valuestring) + 1;
        sub_args.data = ngx_palloc(r->pool,sub_args.len);
        ngx_snprintf(sub_args.data, sub_args.len, "%s%s&%s%s",
               "name=", name->valuestring, "age=", age->valuestring);
    }
    else if (0 == ngx_strncmp(command->valuestring, "delete", strlen("delete")))
    {
        sub_uri.len = ngx_strlen("/mysql_delete");
        sub_uri.data = ngx_palloc(r->pool,sub_uri.len);
        ngx_snprintf(sub_uri.data, sub_uri.len, "%s",
               "/mysql_delete");

        sub_args.len = ngx_strlen("name=") + ngx_strlen(name->valuestring);
        sub_args.data = ngx_palloc(r->pool,sub_args.len);
        ngx_snprintf(sub_args.data, sub_args.len, "%s%s",
               "name=", name->valuestring);
    }
    else if (0 == ngx_strncmp(command->valuestring, "update", strlen("update")))
    {
        age = cJSON_GetObjectItemCaseSensitive(root, "age");
        if (NULL == age)
        {
            return;
        }
        sub_uri.len = ngx_strlen("/mysql_update");
        sub_uri.data = ngx_palloc(r->pool,sub_uri.len);
        ngx_snprintf(sub_uri.data, sub_uri.len, "%s",
               "/mysql_update");

        sub_args.len = ngx_strlen("name=") + ngx_strlen(name->valuestring)
                + ngx_strlen("age=") + ngx_strlen(age->valuestring) + 1;
        sub_args.data = ngx_palloc(r->pool,sub_args.len);
        ngx_snprintf(sub_args.data, sub_args.len, "%s%s&%s%s",
               "name=", name->valuestring, "age=", age->valuestring);
    }
    else if (0 == ngx_strncmp(command->valuestring, "jquery", strlen("jquery")))  //-->新增加處理分支
    {
        sub_uri.len = ngx_strlen("/redis_get");
        sub_uri.data = ngx_palloc(r->pool,sub_uri.len);
        ngx_snprintf(sub_uri.data, sub_uri.len, "%s",
                "/redis_get");

        sub_args.len = ngx_strlen("key=") + ngx_strlen(name->valuestring);
        sub_args.data = ngx_palloc(r->pool,sub_args.len);
        ngx_snprintf(sub_args.data, sub_args.len, "%s%s",
               "key=", name->valuestring);
    }
else { } ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "sub request uri: %V, args: %V", &sub_uri, &sub_args); ngx_http_request_t *sr = NULL; rc = ngx_http_subrequest(r, &sub_uri, &sub_args, &sr, my_sub_req, NGX_HTTP_SUBREQUEST_IN_MEMORY); if (rc != NGX_OK) { return; } return; } static int ngx_response_info(ngx_http_request_t* r) { ngx_int_t rc = NGX_OK; ngx_buf_t* b = NULL; ngx_chain_t out[2]; cJSON *root = NULL; char json_buf[256] = {0}; root = cJSON_CreateObject(); cJSON_AddItemToObject(root, "res-info", cJSON_CreateString("no account info in body")); r->headers_out.content_type.len = sizeof("application/json; charset=utf-8") - 1; r->headers_out.content_type.data = (u_char*)"application/json; charset=utf-8"; b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); out[0].buf = b; out[0].next = NULL; snprintf(json_buf, sizeof(json_buf), "%s", cJSON_Print(root)); ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "%s,length:%d", json_buf, strlen(json_buf)); b->pos = (u_char*)cJSON_Print(root); b->last = b->pos + strlen(json_buf); b->memory = 1; b->last_buf = 1; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = strlen(json_buf); rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } rc = ngx_http_output_filter(r, &out[0]); ngx_http_finalize_request(r,rc); cJSON_Delete(root); return rc; } static ngx_int_t ngx_http_sub_request_mysql_handler(ngx_http_request_t* r) { ngx_int_t rc = NGX_OK; int no_content_flag = 0; if (r->headers_in.content_length) { ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "%s: content length is %d", __FUNCTION__, ngx_atoi(r->headers_in.content_length->value.data, r->headers_in.content_length->value.len)); } else { no_content_flag = 1; ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "no content"); } if (0 == no_content_flag && ngx_atoi(r->headers_in.content_length->value.data, r->headers_in.content_length->value.len) <= 0) { ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "in: content length is %d", ngx_atoi(r->headers_in.content_length->value.data, r->headers_in.content_length->value.len)); no_content_flag = 1; ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "no content"); } ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "no content flag:%d", no_content_flag); if (no_content_flag) { return ngx_response_info(r); } rc = ngx_http_read_client_request_body(r, ngx_http_sub_request_mysql_client_body_handler_pt); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "%s", "unknown respone"); return rc; } return NGX_DONE; } static void* ngx_http_sub_request_mysql_create_loc_conf(ngx_conf_t* cf) { ngx_http_sub_request_mysql_loc_conf_t* conf; conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_sub_request_mysql_loc_conf_t)); if (conf == NULL) { return NGX_CONF_ERROR; } conf->output_words.len = 0; conf->output_words.data = NULL; conf->flag = NGX_CONF_UNSET; return conf; } static char* ngx_http_sub_request_mysql_merge_loc_conf(ngx_conf_t* cf, void* parent, void* child) { ngx_http_sub_request_mysql_loc_conf_t* prev = parent; ngx_http_sub_request_mysql_loc_conf_t* conf = child; ngx_conf_merge_str_value(conf->output_words, prev->output_words, "Nginx"); ngx_conf_merge_uint_value(conf->flag, prev->flag, 1); return NGX_CONF_OK; } static char* ngx_http_sub_request_mysql(ngx_conf_t* cf, ngx_command_t* cmd, void* conf) { ngx_http_core_loc_conf_t* clcf; clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf->handler = ngx_http_sub_request_mysql_handler; ngx_conf_set_str_slot(cf, cmd, conf); return NGX_CONF_OK; }

相關推薦

Openresty學習通過請求完成redis訪問

在Openresty學習(二)基礎上,修改程式碼支援redis訪問(以查詢key值為例)。官網參考:http://openresty.org/cn/redis-nginx-module.htmlhttps://github.com/openresty/redis2-nginx

vue學習父元件向元件傳參

既然是元件化開發,當然少不了資料傳遞,我們先看看官網上寫的。 使用props傳遞引數,試一下,還是用我們之前的專案結構 一、靜態傳遞 1.main_header.vue <template> <div>{{msg}}</div> &

vue移動音樂app開發學習輪播圖組件的開發

hub out webapp width eth reat slot utc -1 本系列文章是為了記錄學習中的知識點,便於後期自己觀看。如果有需要的同學請登錄慕課網,找到Vue 2.0 高級實戰-開發移動端音樂WebApp進行觀看,傳送門。 完成後的頁面狀態以及項目結構如

PE檔案格式學習匯出表

1.回顧 上篇文章中介紹過,可選頭中的資料目錄表是一個大小為0x10的陣列,匯出表就是這個陣列中的第一個元素。 我們再回顧下資料目錄表的結構體: struct _IMAGE_DATA_DIRECTORY {     DWORD VirtualAddress;    

TensorFlow學習tf.reduce_sum()

壓縮求和 tf.reduce_sum( input_tensor, axis=None, keepdims=None, name=None, reduction_indices=None, keep_dims=None ) Args:

網頁開發學習表單

表單是網頁中提供的一種互動式操作手段,無論是提交搜尋的資訊,還是網上註冊等都需要使用表單。使用者可以通過提交表單資訊與伺服器進行動態交流。表單主要可以分為兩部分:一是HTML原始碼描述的表單;二是提交後的表單處理,需要使用伺服器端編寫好 JSP等程式碼對客戶端提交的資訊作出迴應。

ionic學習建立pages頁面

1.建立命令:ionic g page 名稱 2. app.module.ts 引入宣告元件 3.如果跳轉,在跳轉的ts中引入元件 步驟: 1.新建頁面news元件 2.app.module.ts 中引入宣告 3.在home頁面中

rabbitmq學習rabbitmq之扇形交換機、主題交換機

 前言 上篇我們學習了rabbitmq的作用以及直連交換機的程式碼實現,這篇我們繼續看如何用程式碼實現扇形交換機和主題交換機 一、扇形交換機   1.生產者    /** * 生產者 */ public class LogProducer { //交換機名稱 pu

MFC學習專案學習

使用PROJECT->Class Wizard...按步驟設計生成MFC介面 點選"Add Class..."按鈕,在彈窗中輸入想要建立的視窗名字(也就是Class name,.h和.cpp檔案會自動同步) 可在Resource View看到所有的介面

Java類集框架Set介面

Set子介面只是簡單地繼承了Collection介面,並沒有擴充其他的方法。Set集合中不允許儲存重複的資料。在Set介面下有兩個常用的子類:HashSet、TreeSet。HashSet是雜湊存放資料,而TreeSet是有序存放的子類,預設按照字母的升序排列。在實際開發中如果沒有排序要求,

webpack學習配置HtmlWebpackPlugin

demo地址: https://github.com/Lkkkkkkg/webpack-demo webpack初步配置參照 https://blog.csdn.net/qq593249106/article/details/84892069 當前目錄結構: |- /dist //用

日系插畫學習光影與結構

透視應用:可以先把房間裡的東西,用立方體概括出來       透視應用:可以先把消失點畫出來,再確定人物和房子的位置   複製圖層:拖動圖層到新建圖層按鈕上   魚眼

Vue學習數據綁定語法

ESS com tle pre ext 分享圖片 info sage 文本 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8">

WebSocket協議探究MQTT協議

一 複習和目標 1 複習 Nodejs實現WebSocket伺服器 Netty實現WebSocket伺服器(附帶了原始碼分析) Js api實現WebSocket客戶端 注:Nodejs使用的Socket.io模組實現,Netty本身對WebSocket有一定的支援,所以這兩種實現都相

執行緒學習執行緒的互斥

生產者與消費者模型 在講同步和互斥之前,首先了解一下消費者模型 什麼是消費者模型? 消費者模型是一個描述消費者和生產者之間的關係的一個模型,生產者和消費者模型指的是在一個場所中,兩個角色,三種關係 消費者和消費者之間——互斥 消費者之間是競爭關係,比如有一個

zookeeper學習配置zookeeper叢集

安裝zookeeper的條件: scp命令可以正常使用,jdk,mysql。 CentOS6.7 zookeeper-3.4.5 (1) 機器部署 安裝到3臺虛擬機器上 安裝好JDK (2) 上傳 上傳用工具。 (3) 解壓 tar -zxvf zookee

pandas系列學習DataFrame

作者:chen_h 微訊號 & QQ:862251340 微信公眾號:coderpai 如果你正在進行資料科學,從基於 Excel 的分析轉向 Python 指令碼和自動分析領域,你將會遇到非常流行的資料處理方式 Pandas。Pandas 的

TensorFlow學習CNN-Relation-Extraction

cnn_relation_extraction部分記錄 import tensorflow as tf import numpy as np import os import datetime import time from cnn_relation_extraction

MongoDB學習MongoDB Shell的使用

MongoDB shell   MongoDB自帶簡潔但功能強大的JavaScript shell。JavaScript shell鍵入一個變數會將變數的值轉換為字串列印到控制檯上。   開啟命令提示(cmd.exe)。進入到MongoDB解壓的目錄的bin目錄下,即D:\NoSQL\mongodb-w

Maven學習生命週期與maven外掛

一、maven 生命週期 (一)簡介 Maven強大的一個重要的原因是它有一個十分完善的生命週期模型(lifecycle),這個生命週期可以從兩方面來理解:      1、顧名思義,執行Maven的每個步驟都由它來定義的,這種預定義的預設行為使得我們使用Ma