1.cgi文件的代碼php
#include "fcgi_stdio.h" #include <stdlib.h> #include <stdio.h> int main() { /* Initialization Code */ int count = 0; /* Start of response loop */ while (FCGI_Accept() >= 0) { //* body of response loop /*/ //FCGI_printf("Content-type: text/html/r/n" // "/r/n" // "" // "FastCGI Hello/! (C, fcgi_stdio library)" // "Request number %d running on host %s " // "Process ID: %d/n",++count,getenv("SERVER_NAME"), getpid()); FCGI_printf("Content-type: text/html\r\n\r\n"); FCGI_printf("<title>FastCGI Hello HI! (C, fcgi_stdio library)</title>\n"); FCGI_printf("Request number %d running on host %s Process ID: %d\n",++count,getenv("SERVER_NAME"), getpid()); } /* End of response loop */ return 0; }
過程當中可能遇到一些問題,提示502的錯誤,緣由在代碼的cgi問題。html
使用fastcgi c api時注意的問題java
最近用fastcgi的c語言api寫服務,發現一個問題。我用nginx來接收請求,並經過fastcgi_pass傳遞到c程序。在用curl測試請求的時候,發現c程序是有被調用的,可是nginx返回的響應一直是502 "upstream closed prematurely FastCGI stdout while reading response header from upstream"。在網上找了好久,也有一樣的問題,可是通常都是說緣由是printf的時候沒有按照http協議,好比說必定要printf("Content-type: text/html \r\n\r\n")。我按照這個格式寫了,但仍是出錯。最後發現是因爲include了c和c++的一些頭文件,好比,下面的代碼就有可能出現這樣的問題(也有可能不出現問題):ios
#include "fcgi_stdio.h" #include <iostream> #include <string> #include <map> #include <stdlib.h> #include <stdio.h> int main() { while(FCGI_Accept() >= 0) { ////////////////////////////////////////////////////////////////////////// //get content type and length ////////////////////////////////////////////////////////////////////////// printf("Content-type: text/*\r\n\r\n"); printf("<title>FastCGI Hello! (C, fcgi_stdio library)</title>\n"); } }
在官方的api使用例子裏面,只有include 「fcgi_stdio.h」和「stdlib.h」這兩個頭文件。因而我看了一下fcgi_stdio.h這個文件,發現它定義了一個宏,也叫printf,而事實上是調用了FCGI_printf這個函數。 而include其餘的頭文件可能會致使連接的時候連接到原來的printf實現,因此最保險的作法是:nginx
#include "fcgi_stdio.h" #include <iostream> #include <string> #include <map> #include <stdlib.h> #include <stdio.h> int main() { while(FCGI_Accept() >= 0) { ////////////////////////////////////////////////////////////////////////// //get content type and length ////////////////////////////////////////////////////////////////////////// FCGI_printf("Content-type: text/*\r\n\r\n"); FCGI_printf("<title>FastCGI Hello! (C, fcgi_stdio library)</title>\n"); } }
2.nginx的配置文件c++
#user nobody; #daemon off; #master_process off; worker_processes 1; error_log logs/80_error.log; error_log logs/80_notice.log notice; error_log logs/80_info.log info; error_log logs/80_debug.log debug; pid logs/80.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; error_log logs/80_http_debug.log debug; access_log logs/80_http_access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on;
//部署負載均衡 #upstream resinserver{ # server 127.0.0.1:8081 weight=1; # server 127.0.0.1:8082 weight=1; # server 127.0.0.1:8083 weight=1; # keepalive 1024; #} server { listen 8080; server_name 192.168.104.101 127.0.0.1 localhost; #charset koi8-r; #access_log logs/host.access.log main; #location / { # root html; # index index.html index.htm; #proxy_pass http://resinserver/; #proxy_set_header Host $host; #proxy_set_header X-Real-IP $remote_addr; #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #} //部署cgi文件 #location ~/.cgi$ { # fastcgi_pass 127.0.0.1:9002; # fastcgi_index index.cgi; # fastcgi_param SCRIPT_FILENAME cgibin$fastcgi_script_name; # include fastcgi_params; #} #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # #error_page 500 502 503 504 /50x.html; #location = /50x.html { # root html; #} # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 #
//這是我本身添加的 location ~\.cgi$ { root /usr/local/nginx/cgibin; fastcgi_pass 127.0.0.1:9002; fastcgi_index index.cgi; fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; include fastcgi_params; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} }
3.編譯1.cgiweb
gcc -o 1.cgi 1.c -lfcgiapache
4.運行1.cgi文件api
注意這是一行命令哦。注意可能要sudo.
-p是指定fastcgi控制器綁定的TCP端口listen的.
若是你想調試單個fastcgi程序,能夠把-f換成-n.
-F指定spawn-fcgi將fork多少個child進程。以後nginx對於此cgi的請求就能夠併發了。顯然這裏的直接併發量是1000.
其餘參數能夠help看看:(看起來-C對不要php的我來講沒啥用.本文是初次使用記錄性教程,這裏就不糾結這些參數了)瀏覽器
Lenovo:/usr/local/nginx$ sbin/spawn-fcgi --help
/usr/local/nginx/sbin/spawn-fcgi -a 127.0.0.1 -p 9002 -C 25 -f /usr/local/nginx/cgibin/1.cgi
監聽的端口是9002,對應nginx的配置文件的9002
關閉spawn-fcgi打開的fastcgi程序:
$ netstat -anp | grep 9000 #查看佔用9000端口的程序ID
$ kill -9 PID #或killall 進程名
5.運行nginx
./sbin/nginx -c nginx.conf
6.在瀏覽器查看
http://192.168.104.101:8080/1.cgi
這是網上的一些測試,待有時間再作驗證,先保存起來。。。
下載:http://home.tiscali.cz:8080/~cz210552/distfiles/webbench-1.5.tar.gz
安裝:
tar zxvf webbench-1.5.tar.gz cd webbench-1.5
make && make install
使用:
webbench -c 500 -t 30 http://127.0.0.1/test.jpg
500是併發鏈接數,30是時間單位是秒
用ab測試的結果,在個人虛擬機上,看起來性能很不錯
(Apache Bench是Apache自帶的工具包)
ab -n 10000 -c 100 http://127.0.0.1/1.cgi
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: nginx/0.7.38
Server Hostname: 127.0.0.1
Server Port: 80
Document Path: /1.cgi
Document Length: 143 bytes
Concurrency Level: 100
Time taken for tests: 3.982 seconds
Complete requests: 10000
Failed requests: 8399
(Connect: 0, Receive: 0, Length: 8399, Exceptions: 0)
Write errors: 0
Total transferred: 2658399 bytes
HTML transferred: 1438399 bytes
Requests per second: 2511.06 [#/sec] (mean)
Time per request: 39.824 [ms] (mean)
Time per request: 0.398 [ms] (mean, across all concurrent requests)
Transfer rate: 651.89 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 4.6 0 51
Processing: 22 39 6.8 36 93
Waiting: 4 39 6.8 36 93
Total: 24 39 8.2 36 97
Percentage of the requests served within a certain time (ms)
50% 36
66% 39
75% 41
80% 42
90% 48
95% 54
98% 70
99% 84
100% 97 (longest request)
模塊列表
http://wiki.codemongers.com/NginxModules
FastCGI模塊源碼:nginx/src/http/modules/ngx_http_fastcgi_module.c