fastCGI的安装与使用

一、 CGI是什么

  • nginx服务器接收http请求并进行解析,但无法进行处理,而是交由CGI程序来处理。
  • 实际使用时,服务器会创建一个CGI进程。CGI程序会启动CGI解析器、连接其它服务器(如数据库服务器),进行逻辑处理后返回给服务器,服务器将结果发送给客户端。

二、fastCGI

  • CGI:客户端每进行一次请求,就需要创建一个CGI进程,会造成频繁的进程创建与销毁。
  • FastCGI:使用持续的进程来处理一连串的请求。这些进程由FastCGI进程管理器启动,而不是web服务器
  • 一般fastCGI和nginx安装在同一台主机上,数据库安装在另一台主机上。
    fastCGI进程不是由服务器创建的,因此它们之间通信可以应该采用本地套接字或者是网络通信。

具体流程:

请求的url:http://localhost/login?user=zhang3&passwd=123456&age=12&sex=man
命令(/login):去掉协议、域名IP、端口,尾部有文件名则去掉,去掉?及后面的字符串
当客户端点击上传时报错,报错信息在/usr/local/nginx/logs/error.log中,在其中就能看到出错时的请求行是什么

如果看到的是请求行, 如何找处理指令?
   POST /upload/UploadAction HTTP/1.1
   GET /?username=tom&phone=123&email=hello%40qq.com&date=2018-01-01&sex=male&class=3&rule=on HTTP/1.1
  • 如果是post, 处理指令就是请求行的第二部分
  • 如果是get, 处理指令就是请求行的第二部分, ? 以前的内容
- 1.浏览器解析url,向服务器发出http请求
- 2.服务器发现自己无法处理该请求,就会将请求转发给fastCGI进程处理
- 3.fastCGI读取配置文件(例如用户保存的登录信息),连接数据库服务器进行查询
- 4.fastCGI执行逻辑处理,将处理结果返回给服务器
- 5.服务器将结果返回给浏览器

流程

三、安装

fcgi-2.4.1-SNAP-0910052249.tar.gz
spawn-fcgi-1.6.5.tar.gz

四、nginx怎么把请求转发给fastcgi进程

location /login
{
    # 转发这个数据, fastCGI进程
    fastcgi_pass 地址信息:端口;
    # fastcgi.conf 和nginx.conf在同一级目录: /usr/local/nginx/conf
    # 这个文件中定义了一些http通信的时候用到环境变量, nginx赋值的
    include fastcgi.conf;
}
地址信息: 一般nginx和fastcgi部署在同一台电脑上,因此写localhost、127.0.0.1,或者实际的IP地址。
端口: 找一个空闲的没有被占用的端口即可

五、怎么启动spawn-fcgi

当fastCGI程序编写完毕后,可以按下面的方式启动(IP和端口要与上面一样)
(注意:这里不能写成localhost,而是写具体的IP,如127.0.0.1)
spawn-fcgi -a IP地址 -p 端口 -f fastcgi可执行程序

六、fastCGI程序怎么写

- 发送与接收数据
标准输入和标准输出已经被重定向到 nginx与fastCGI进程管理器的通信fd 了
因此,使用printf就是向nginx发送数据,getchar就是接收nginx转发过来的命令

- 请求体的长度
get方式肯定没有请求体,无Content-Length,无Content-Type			而post方式有
该信息被初始化到环境变量中了,在fastCGI程序中可以使用getenv("CONTENT_LENGTH")得到长度

-char * contentLength转10进制数
int len = strtol(contentLength, NULL, 10);

-读写数据块
fread/fwrite是标准C库函数,而read/write是linux系统库函数,因此这里使用通用的前者。
//由于标准输入与输出已经被重定向过了,这里的FILE *stream直接写stdin或者stdout即可
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
// http://localhost/login?user=zhang3&passwd=123456&age=12&sex=man
// 要包含的头文件
#include "fcgi_config.h" // 可选,看是否要读取配置文件
#include "fcgi_stdio.h" // 必须
// 编写代码的流程
int main()
{
    // FCGI_Accept()是一个阻塞函数, nginx给fastcgi程序发送数据的时候解除阻塞
    while (FCGI_Accept() >= 0) 
    {
        // 1. 接收数据
        // 1.1 get方式提交数据 - 数据在请求行的第二部分
        // user=zhang3&passwd=123456&age=12&sex=man
        char *text = getenv("QUERY_STRING"); 
        // 1.2 post方式提交数据
        char *contentLength = getenv("CONTENT_LENGTH");
        // 根据长度大小判断是否需要循环
        // 2. 按照业务流程进行处理
        // 3. 将处理结果发送给nginx
        // 数据回发的时候, 需要告诉nginx处理结果的格式 - 假设是html格式
        printf("Content-type: text/html;charset=utf-8\r\n\r\n");
        printf("<html>处理结果</html>");
    }
}

七、实际使用

1 启动nginx     2 启动spawn-fcgi    3 打开http://192.168.232.132/demo.html
先编译一份fastcgi程序,这里将就使用example提供的代码。
book@100ask:~/Downloads/fcgi-2.4.1-SNAP-0910052249/examples$ gcc echo.c -o app -lfcgi
运行程序前,先使用ldd检查一下它的动态库是不是都能找到

book@100ask:~/Downloads/fcgi-2.4.1-SNAP-0910052249/examples$ ldd app
        linux-vdso.so.1 (0x00007ffeb4be2000)
        libfcgi.so.0 => not found
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f36a622a000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f36a681e000)
由上可知,libfcgi.so动态库找不到(注意,后面的.0是版本号,不要管),因此先find找一下:
book@100ask:~/Downloads/fcgi-2.4.1-SNAP-0910052249/examples$ sudo find / -name libfcgi.so
find: ‘/run/user/1001/gvfs’: Permission denied
/home/book/Downloads/fcgi-2.4.1-SNAP-0910052249/libfcgi/.libs/libfcgi.so
/usr/local/lib/libfcgi.so
可以看到,/usr/local/lib目录下有该动态库文件,需要把这个路径加入到 /etc/ld.so.conf ,然后执行sudo ldconfig。
/etc/ld.so.conf记录了编译时使用的动态库的路径,也就是加载so库的路径。安装源码包时,如果没有指定--prefix为/usr/lib,就会默认安装在usr/local下,也就是动态库在/usr/local/lib下,导致系统找不到该动态库。因此,最好将/usr/local/lib这个目录添加到该文件中
启动fcgi进程
spawn-fcgi -a 127.0.0.1 -p 10000 -f ./app

八、fastcgi.conf里是fastCGI的环境变量

文件位置:/usr/local/nginx/conf/fastcgi.conf
环境变量说明
SCRIPT_FILENAME脚本文件请求的路径
QUERY_STRING请求的参数;如?app=123
REQUEST_METHOD请求的动作(GET,POST)
CONTENT_TYPE请求头中的Content-Type字段
CONTENT_LENGTH请求头中的Content-length字段
SCRIPT_NAME脚本名称(就是指令)
REQUEST_URI请求的地址不带参数
DOCUMENT_URI与$uri相同
DOCUMENT_ROOT网站的根目录。在server配置中root指令中指定的值
SERVER_PROTOCOL请求使用的协议,通常是HTTP/1.0或HTTP/1.1
GATEWAY_INTERFACEcgi 版本
SERVER_SOFTWAREnginx 版本号,可修改、隐藏
REMOTE_ADDR客户端IP
REMOTE_PORT客户端端口
SERVER_ADDR服务器IP地址
SERVER_PORT服务器端口
SERVER_NAME服务器名,域名在server配置中指定的server_name

九、

Post提交数据常用的四种编码方式
  • application/x-www-form-urlencoded

    # 请求行
    POST http://www.example.com HTTP/1.1
    # 请求头
    Content-Type: application/x-www-form-urlencoded;charset=utf-8
    # 空行
    # 请求数据(向服务器提交的数据)
    title=test&user=kevin&passwd=32222
    
  • application/json

    POST / HTTP/1.1
    Content-Type: application/json;charset=utf-8
    {"title":"test","sub":[1,2,3]}
    
  • text/xml

    POST / HTTP/1.1
    Content-Type: text/xml
    <?xml version="1.0" encoding="utf8"?>
    <methodcall>
        <methodname color="red">examples.getStateName</methodname>
        <params>
        	<value><i4>41</i4></value>
        </params>
    </methodcall>
    
  • multipart/form-data 传输大文件,多个数据块

    • 在请求体中,首先是随机生成的一对字符串作为分割符,其中才是要传输的数据
    • 传输的数据中,首先是一些键值对用来描述文件属性,然后才是文件内容。
    • Content-Disposition可以自己随便加,但是Content-Type是有固定格式的Content-Type的对应写法
    POST / HTTP/1.1
    Content-Type: multipart/form-data
    # 发送的数据
    ------WebKitFormBoundaryPpL3BfPQ4cHShsBz \r\n
    Content-Disposition: form-data; name="file"; filename="qw.png"
    Content-Type: image/png\r\n; md5="xxxxxxxxxx"
    \r\n
    .............文件内容................
    .............文件内容................
    ------WebKitFormBoundaryPpL3BfPQ4cHShsBz--
    Content-Disposition: form-data; name="file"; filename="qw.png"
    Content-Type: image/png\r\n; md5="xxxxxxxxxx"
    \r\n
    .............文件内容................
    .............文件内容................
    ------WebKitFormBoundaryPpL3BfPQ4cHShsBz--
    

一些问题:
访问时,仍然是访问nginx监听的端口,而不是fcgi的端口。
出现spawn-fcgi: child exited with: 126时,表示程序不是可执行的, chmod 777 xxx就好
注意响应空行的问题

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值