大家好,又見面了,我是你們的朋友全棧君。
01. CGI
1.1 什麼是CGI
通用網關接口(Common Gateway Interface、CGI)描述了用戶端和伺服器程式之間傳輸資料的一種标準,可以讓一個用戶端,從網頁浏覽器向執行在網絡伺服器上的程式請求資料。CGI獨立于任何語言的,CGI 程式可以用任何腳本語言或者是完全獨立程式設計語言實作,隻要這個語言可以在這個系統上運作。Unix shell script、Python、Ruby、PHP、 perl、Tcl、 C/C++和 Visual Basic 都可以用來編寫 CGI 程式。
1.2 CGI處理流程
- web伺服器收到用戶端(浏覽器)的請求Http Request,啟動CGI程式,并通過環境變量、标準輸入傳遞資料
- CGI程序啟動解析器、加載配置(如業務相關配置)、連接配接其它伺服器(如資料庫伺服器)、邏輯處理等
- CGI程序将處理結果通過标準輸出、标準錯誤,傳遞給web伺服器
- web伺服器收到CGI傳回的結果,建構Http Response傳回給用戶端,并殺死CGI程序
web伺服器與CGI通過環境變量、标準輸入、标準輸出、标準錯誤互相傳遞資料。在遇到使用者連接配接請求:
- 先要建立CGI子程序,然後CGI子程序處理請求,處理完事退出這個子程序:fork-and-execute
- CGI方式是用戶端有多少個請求,就開辟多少個子程序,每個子程序都需要啟動自己的解釋器、加載配置,連接配接其他伺服器等初始化工作,這是CGI程序性能低下的主要原因。當使用者請求非常多的時候,會占用大量的記憶體、cpu等資源,造成性能低下。
CGI使外部程式與Web伺服器之間互動成為可能。CGI程式運作在獨立的程序中,并對每個Web請求建立一個程序,這種方法非常容易實作,但效率很差,難以擴充。面對大量請求,程序的大量建立和消亡使作業系統性能大大下降。此外,由于位址空間無法共享,也限制了資源重用。
1.3 CGI程式結構
02. FastCGI
2.1 什麼是FastCGI
快速通用網關接口(Fast Common Gateway Interface/FastCGI)是通用網關接口(CGI)的改進,描述了用戶端和伺服器程式之間傳輸資料的一種标準。
FastCGI緻力于減少Web伺服器與CGI程式之間互動的開銷,進而使伺服器可以同時處理更多的Web請求。與為每個請求建立一個新的程序不同,FastCGI使用持續的程序來處理一連串的請求。這些程序由FastCGI程序管理器管理,而不是web伺服器
2.2 FastCGI處理流程
- Web 伺服器啟動時載入初始化FastCGI執行環境。 例如IIS、ISAPI、apache mod_fastcgi、nginx ngx_http_fastcgi_module、lighttpd mod_fastcgi。
- FastCGI程序管理器自身初始化,啟動多個CGI解釋器程序并等待來自Web伺服器的連接配接。啟動FastCGI程序時,可以配置以ip和UNIX 域socket兩種方式啟動。
- 當用戶端請求到達Web 伺服器時, Web 伺服器将請求采用socket方式轉發FastCGI主程序,FastCGI主程序選擇并連接配接到一個CGI解釋器。Web 伺服器将CGI環境變量和标準輸入發送到FastCGI子程序。
- FastCGI子程序完成處理後将标準輸出和錯誤資訊從同一socket連接配接傳回Web 伺服器。當FastCGI子程序關閉連接配接時,請求便處理完成。
- FastCGI子程序接着等待并處理來自Web 伺服器的下一個連接配接。
由于FastCGI程式并不需要不斷的産生新程序,可以大大降低伺服器的壓力并且産生較高的應用效率。它的速度效率最少要比CGI 技術提高 5 倍以上。它還支援分布式的部署,即FastCGI 程式可以在web 伺服器以外的主機上執行。
CGI 是所謂的短生存期應用程式,FastCGI 是所謂的長生存期應用程式。FastCGI像是一個常駐(long-live)型的CGI,它可以一直執行着,不會每次都要花費時間去fork一次(這是CGI最為人诟病的fork-and-execute 模式)
2.3 FastCGI程式結構
2.4 FastCGI配置
配置Nginx
location /fastcgi {
include fastcgi.conf; #包含fastCGI的參數
fastcgi_pass 192.168.199.151:8080; #配置Windows服務端的應用
}
複制
03. spawn-fcgi
3.1 什麼是spawn-fcgi
Nginx不能像Apache那樣直接執行外部可執行程式,但Nginx可以作為代理伺服器,将請求轉發給後端伺服器,這也是Nginx的主要作用之一。其中Nginx就支援FastCGI代理,接收用戶端的請求,然後将請求轉發給後端FastCGI程序。
由于FastCGI程序由FastCGI程序管理器管理,而不是Nginx。這樣就需要一個FastCGI程序管理器,管理我們編寫FastCGI程式。
spawn-fcgi是一個通用的FastCGI程序管理器,簡單小巧,原先是屬于lighttpd的一部分,後來由于使用比較廣泛,是以就遷移出來作為獨立項目。
spawn-fcgi使用pre-fork 模型,功能主要是打開監聽端口,綁定位址,然後fork-and-exec建立我們編寫的FastCGI應用程式程序,退出完成工作。FastCGI應用程式初始化,然後進入死循環偵聽socket的連接配接請求
3.2 spawn-fcgi安裝
安裝包下載下傳位址:https://github.com/lighttpd/spawn-fcgi
連結:https://pan.baidu.com/s/13lt89QTYhHwQkOxTUyJ9Yg
提取碼:7f99
第一步:解壓
:~/nginx$ unzip spawn-fcgi-master.zip
複制
第二步: 生成configure檔案
:~/nginx/spawn-fcgi-master$ ./autogen.sh
configure.ac:12: installing './compile'
configure.ac:9: installing './install-sh'
configure.ac:9: installing './missing'
src/Makefile.am: installing './depcomp'
Now type './configure ...' and 'make' to compile.
複制
第三步: 生成Makefile
:~/nginx/spawn-fcgi-master$ ./configure
複制
第四步: 編譯
:~/nginx/spawn-fcgi-master$ make
複制
第五步: 安裝
:~/nginx/spawn-fcgi-master$ sudo make install
複制
第六步: 測試
:~/nginx/spawn-fcgi-master$ spawn-fcgi
Usage: spawn-fcgi [options] [-- <fcgiapp> [fcgi app arguments]]
spawn-fcgi v1.6.5 - spawns FastCGI processes
Options:
...
複制
3.3 spawn-fcgi指令
pawn-fcgi的幫助資訊可以通過man spawn-fcgi或spawn-fcgi -h獲得,下面是部分常用
spawn-fcgi參數資訊:
參數 | 含義 |
---|---|
-f | 指定調用FastCGI的程序的執行程式位置 |
-d | 在部署前,切換到某個目錄,修改運作目錄 |
-a | 綁定到位址addr 預設0.0.0.0 |
-p | 綁定到端口port |
-s | 綁定到unix domain socket |
-C | 指定産生的FastCGI的程序數,預設為5(僅用于PHP) |
-P | 指定産生的程序的PID檔案路徑 |
-F | 指定産生的FastCGI的程序數(C的CGI用這個) |
-u和-g FastCGI | 使用什麼身份(-u使用者、-g使用者組)運作,CentOS下可以使用apache使用者,其他的根據情況配置,如nobody、www-data等 |
04. FastCGI安裝
使用C/C++編寫FastCGI應用程式,可以使用FastCGI軟體開發套件或者其它開發架構,如fcgi。
官方網站:https://fastcgi-archives.github.io/
gitHub下載下傳: https://github.com/FastCGI-Archives/fcgi2
第一步:解壓
:~/nginx$ unzip FastCGI_master.zip
複制
第二步:生成configure
:~/nginx/fcgi2-master$ ./autogen.sh
複制
第三步:生成makefile
:~/nginx/fcgi2-master$ ./configure
複制
第四步:編譯
:~/nginx/fcgi2-master$ make
複制
第五步:安裝
:~/nginx/fcgi2-master$ sudo make install
複制
05. 部署FastCGI程式
進入 fastCGI架構源代碼目錄 example/echo 是一個簡單的fastCGI程式, 可以 ./echo 來運作
将這些fastCGI部署起來,做成一個服務,給nginx使用,就要使用fastCGI程序管理器
示例:
# spawn-fcgi -f ./echo -a 0.0.0.0 -p 10000
spawn-fcgi: child spawned successfully: PID: 13837
# 啟動成功之後 顯示了這個fastCGI程式的PID
複制
部署流程
第一步:配置Nginx
#在Server中添加如下内容
location /echo {
include fastcgi.conf; #包含fastCGI的參數
fastcgi_pass 127.0.0.1:8080; #指定fastCGI的程式
}
複制
第二步:啟動cgi程式
:~/nginx/fcgi2-master/examples$ pwd
/home/deng/nginx/fcgi2-master/examples
:~/nginx/fcgi2-master/examples$ spawn-fcgi -f ./echo -a 127.0.0.1 -p 8080
spawn-fcgi: child spawned successfully: PID: 15693
複制
第三步:重新啟動Nginx,然後使用浏覽器測試
06. FastCGI程式示例
fastcgi程式完成了一個傳回用戶端IP位址的功能。
#include <stdlib.h>
#include <fcgi_stdio.h>
int main()
{
while (FCGI_Accept() >= 0)
{
printf("Content-Type:text\r\n\r\n");
printf("clint ip is %s\r\n", getenv("REMOTE_ADDR"));
}
return 0;
}
複制
編譯和測試
:~/tmp$ gcc test.c -lfcgi
:~/tmp$ REMOTE_ADDR="192.168.13.144" ./a.out
content-Type:test
client ip is 192.168.13.144
複制
使用Nginx部署測試 啟動程式
:~/tmp$ spawn-fcgi -f ./a.out -a 127.0.0.1 -p 10086
spawn-fcgi: child spawned successfully: PID: 17122
複制
配置Nginx
location /echo {
include fastcgi.conf; #包含fastCGI的參數
fastcgi_pass 127.0.0.1:10086; #指定fastCGI的程式
}
複制
使用浏覽器測試
總結:
1.使用fcgi庫時的三要素:
- while (FCGI_Accept() >= 0)循環内寫業務
- 用getenv和fread(buf, sizeof(buf), 1, stdin)擷取使用者的請求
- 用printf向使用者展示資料;
資料格式是
- 若幹行回複資料頭(最簡形式Content-Type:text\r\n)
- 一個空行
- 回複資料體
2.spawn-cgi啟動fastcgi程式時要和nginx的fastcgi_pass配置項對應好
3.良好的設計是:不同目的的請求用不同的FastCGI程式處理。
釋出者:全棧程式員棧長,轉載請注明出處:https://javaforall.cn/157437.html原文連結:https://javaforall.cn