從上一個upload試用 后,現在我們需要上傳圖片到redis,由於upload模塊會緩存到文件夾,后續處理時再從文件夾讀取。這樣多出來的io操作希望盡量避免的情況下,我們舍棄upload模塊,只使用redis模塊來完成上傳,因為我們暫時不需要處理這些上傳數據,就算要處理從redis中拿出來應該會更快。
安裝並運行redis-server,默認的redis-server沒有設置密碼,且默認127.0.0.1:6379(nginx.conf中redis2_pass的設置對應),我們測試使用默認的就行了。
$ sudo apt install redis-server $ redis-server
使用redis,我們需要一些模塊:redis2-nginx-module, redis2需要用到set-misc-nginx-module,而這個set-misc-nginx模塊需要ngx-devel-kit模塊。
下載上述3個模塊並提取(我的模塊存放目錄:/home/dyan/OpenSource/workspace/nginx-modules)
nginx源碼重新編譯一下 (nginx源碼目錄/home/dyan/OpenSource/nginx-1.4.2),在該目錄下編譯
$ ./configure --add-module=/home/dyan/OpenSource/workspace/nginx-modules/redis2-nginx-module-master\
--add-module=/home/dyan/OpenSource/workspace/nginx-modules/ngx_devel_kit-master\
--add-module=/home/dyan/OpenSource/workspace/nginx-modules/set-misc-nginx-module-master
nginx已經安裝到/usr/local/nginx下
然后修改/usr/local/nginx/conf/nginx.conf(修改前記得先備份),
但是,這個nginx默認的上傳大小限制太小了我們需要對http字段修改client_header_buffer_size和client_body_buffer_size的限制。
client_body_buffer_size 1024k;
client_header_buffer_size 1024k; #這個是為了方便我們測試,redis2模塊上傳功能時直接把數據放到header中,這樣似乎不合理
在http字段server字段中添加如下配置
#$curl "localhost/get?key=ask" location = /get { set_unescape_uri $key $arg_key; redis2_query get $key; redis2_pass 127.0.0.1:6379; } #$curl "localhost/set?key=ask&val=answer" location = /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; }
這時確認新的配置沒有問題后重載nginx配置
$ sudo /usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful $ ps -ef|grep nginx root 9111 3070 0 8月01 ? 00:00:00 nginx: master process sbin/nginx dyan 28862 9111 0 22:57 ? 00:00:00 nginx: worker process dyan 30167 6058 0 23:50 pts/19 00:00:00 grep --color=auto nginx
$ sudo kill -HUP 9111
查看效果,
$ curl "localhost/set?key=hello&val=world"
+OK
$ curl "localhost/get?key=hello"
$5 #這里的$不是shell,是redis的返回值部分
world
附上一個demo_redis_set.cpp檢驗redis的set功能
//demo_redis_set.cpp
#include <curl/curl.h> #include <iostream> #include <sstream> #include <string.h> #include <hiredis/hiredis.h> using namespace std; size_t write_data(void* ptr, size_t size, size_t nmemb, void* stream) { string data((const char*) ptr, (size_t) size * nmemb); *((stringstream*) stream) << data << endl; return size * nmemb; } int main() { FILE *fp = fopen("test8.png","rb"); if(NULL == fp) { cout<<"open file failed"<<endl; return -1; } fseek(fp,0,SEEK_END); size_t file_len = ftell(fp); fseek(fp,0,SEEK_SET); char *data = new char[file_len]; fread(data,1,file_len,fp); fclose(fp); CURL *m_curl = curl_easy_init(); cout<<"file_len:"<<file_len<<endl; char *encode_data = curl_easy_escape(m_curl,data,file_len); // cout<<"encode len:"<<encode_data<<endl; string url="localhost/set"; url += "?key=inquire&val="; url += encode_data;
//釋放curl_easy_escape分配的內存
curl_free(encode_data); cout<<url.length()<<endl; stringstream ssanswer; curl_easy_setopt(m_curl,CURLOPT_SSL_VERIFYPEER,false); curl_easy_setopt(m_curl,CURLOPT_URL,url.c_str()); curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &ssanswer); CURLcode res = curl_easy_perform(m_curl); string ans = ssanswer.str(); cout<<ans<<endl; //redis 連接 struct timeval timeout = {2, 0}; //2s的超時時間 //redisContext是Redis操作對象 redisContext *pRedisContext = (redisContext*)redisConnectWithTimeout("127.0.0.1", 6379, timeout); if ( (NULL == pRedisContext) || (pRedisContext->err) ) { if (pRedisContext) { std::cout << "connect error:" << pRedisContext->errstr << std::endl; } else { std::cout << "connect error: can't allocate redis context." << std::endl; } return -1; } //redisReply是Redis命令回復對象 redis返回的信息保存在redisReply對象中 redisReply *pRedisReply = (redisReply*)redisCommand(pRedisContext, "get inquire"); //執行INFO命令 int decode_len=0; cout<<"pRedisReply->len:"<<pRedisReply->len<<endl; FILE *fw = fopen("output3.png","wb"); if(NULL == fw) { cout<<"open file failed"<<endl; return -1; } cout<<"redis data len:"<<pRedisReply->len<<endl; int ret = fwrite(pRedisReply->str,1,pRedisReply->len,fw); cout<<"write len:"<<ret<<endl; fclose(fw); //當多條Redis命令使用同一個redisReply對象時 //每一次執行完Redis命令后需要清空redisReply 以免對下一次的Redis操作造成影響 freeReplyObject(pRedisReply); delete[] data; delete[] encode_data; return 0; }
編譯並執行,
$ g++ -g demo_redis_set.cpp -o test -lcurl -lhiredis -std=c++11 $ ./test file_len:41558 104068 +OK pRedisReply->len:41558 redis data len:41558 write len:41558
看上去一切正常,最后比較一下輸入文件與輸出文件
$ diff test8.png output3.png
#結果返回是一個空行,說明這2個文件是相同的。如果不同就會返回:二進制文件 test8.png 和 output3.png 不同