Nginx + fastCGI 实现动态网页部署

简介

  • 本文章主要介绍下,如何通过Nginx + fastCGI来部署动态网页。

CGI介绍

  • 在介绍fastCGI之前先介绍下CGI是什么。
  • CGI : Common Gateway Interface,公共网关接口。在物理层面上是一段程序,运行在服务器上,提供同客户端HTML页面的接口。
  • Nginx+CGI处理步骤
  • 用户发送HTTP请求到Web服务器
  • Web服务器fork一个CGI子进程,将用户请求交给CGI程序
  • CGI程序把处理结果传送给Web服务器,CGI子进程被销毁
  • Web服务器把结果返回到用户
    请添加图片描述
  • CGI缺点
    • CGI每处理一个请求,就要fork一个子进程,处理完请求,再销毁子进程。频繁的创建和销毁进程,就会大大降低Web服务器的效率。
  • fastCGI
    • fastCGI是对CGI的优化,fastCGI并不会每处理一个请求就创建一个进程, 这样就避免了频繁创建和销毁CGI进程,可以大大提高服务器的效率。
    • 下面就重点介绍下fastCGI

fastCGI

  • FastCGI是一个可伸缩的、高速的在HTTP服务器和动态脚本语言间通信的接口,主要优点是把动态语言和HTTP服务器分离开来。
  • 主要是将CGI进程保持在内存中进行管理调度,以获得较高的性能。
  • fastCGI的工作原理
    • Web服务器启动时载入fastCGI进程管理器
    • fastCGI进程管理器自身初始化,启动多个CGI子进程并等待来自Web服务器的连接
    • 当客户端请求到达Web服务器时,fastCGI进程管理器选择并连接到一个CGI进程来处理请求
    • fastCGI子进程完成处理后将结果返回给Web服务器
  • 问题
    • Nginx下fastCGI与服务器是分离的,就是Nginx无法直接调用fastCGI,需要用spawn-fcgi来管理

spawn-fcgi

  • spawn-fcgi是Nginx和fastCGI之间的桥梁,负责Nginx和fastCGI之间的数据通信
    请添加图片描述

安装

  • fastCGI
    • ./configure
    • make
    • make install
  • 如果make时报错,在libfcgi/fcgio.cpp中添加头文件 #include <stdio.h>
  • spawn-fcgi
    • ./configure
    • make
    • make install
  • 关于Nginx的安装另一篇文章中有介绍 : Nginx部署静态网页

环境配置

  • Nginx配置
    • 主要是将Nginx处理不了的指令交给fastCGI操作
    • 打开Nginx配置文件 /usr/local/nginx/conf/nginx.conf,在server字段里加一个location字段
      •   # 处理指令
          location /fastCgiTest{
          	# 配置fastcgi模块,这里的端口是fastCGI进程的端口
          	fastcgi_pass 192.168.206.128:10010
          	# 包含配置文件
          	include fastcgi.conf
          }
        
  • Nginx默认展示登录网页(用该程序替换Nginx默认index.html)
    •   <!DOCTYPE html>
        <html lang="en">
        <head>
        	<meta charset="UTF-8">
        	<title>FastCGI测试网站</title>
        </head>
        <body>
        	<h1 align="center">FastCGI测试网站</h1>
        	<div class="container">
        		<form method="post" action="http://192.168.206.128/fastCgiTest">
        		<p align="center"><label>姓名:<input type="text" name="username" placeholder="admin" autofocus="autofocus"></label></p>
        		<p align="center"><label>密码:<input type="tel" name="phone" placeholder="000" required="required"></label></p>
        		<p align="center">
        	 		<button class="mybtn">登录</button>
        	 	</p>
        		</form>
        	</div>
        </body>
        </html>
      

spawn-fcgi的使用

  • 命令 : spawn-fcgi -a IP -p PORT -f fastcgi程序
    • IP : Nginx服务器ip地址,就是上面配置的127.0.0.1
    • PORT : 服务器将数据发送到的端口,就是上面我们配置的10010端口
    • fastcgi程序 : spawn-fcgi fork fastcgi进程,fastcgi程序需要我们自己实现并编译。

编写fastcgi程序

  • 这是参考fastcgi中的一个demo写的一个,主要实现登录功能,如果输入正确的用户名和密码,展示登录成功界面,如果输入错误的用户名和密码,继续展示登录界面,并提示重新登录。
  •  #include "fcgi_config.h"
     #include <stdlib.h>
    
     #ifdef HAVE_UNISTD_H
     #include <unistd.h>
     #endif
    
     #ifdef _WIN32
     #include <process.h>
     #else
     extern char **environ;
     #endif
    
     #include <string.h>
     #include "fcgi_stdio.h"
    
     //检查登录账号和密码
     int checkLogin(char* recvBuf, const char* userName, const char* password);
    
     int main ()
     {
     	char **initialEnv = environ;
    	 	int count = 0;
    
     	while (FCGI_Accept() >= 0) {
     		//请求数据长度
         	char *contentLength = getenv("CONTENT_LENGTH");
     		//请求方法(GET/POST)
     		char *requestmechod = getenv("REQUEST_METHOD");
    
     		//响应头(printf相当于发送数据)
     		printf("MyFlag: IsFastCGI\r\n");  //可以加自定义响应头
     		printf("Content-type: text/html\r\n");
     		printf("\r\n");
    
     		int length = 0;
     		//POST请求
     		if(strcmp(requestmechod, "POST") == 0){
     			length = strtol(contentLength, NULL, 10);
     			//post请求没有数据,不处理
     			if(length == 0){
     				continue;
     			}
     		
     			//读取post请求数据
     			char ch;
     			char recvBuf[1024 * 10] = {0};
     			for (int i = 0; i < length; i++) {
                	 	if ((ch = getchar()) < 0) {
                     	printf("read post data failed\n");
                     	continue;
     				}
     				recvBuf[i] = ch;
             	}
     		
     			if(checkLogin(recvBuf, "admin", "000")){
     				printf("<h1>Login success!</h1>\r\n");
     			}else{
     				printf("<!DOCTYPE html>\r\n");
     				printf("<html lang=\"en\">\r\n");
     				printf("<head>\r\n");
     				printf("<meta charset=\"UTF-8\">\r\n");
     				printf("<title>FastCGI测试网站</title>\r\n");
     				printf("</head>\r\n");
     				printf("<body>\r\n");
     				printf("<h1 align=\"center\">FastCGI测试网站</h1>\r\n");
     				printf("<div class=\"container\">\r\n");
     				printf("<form method=\"post\" action=\"http://192.168.206.128/fastCgiTest\">\r\n");
     				printf("<p align=\"center\"><label>姓名:<input type=\"text\" name=\"username\" placeholder=\"admin\" autofocus=\"autofocus\"></label></p>\r\n");
     				printf("<p align=\"center\"><label>密码:<input type=\"password\" name=\"password\" placeholder=\"000\" required=\"required\"></label></p>\r\n");
     				printf("<p align=\"center\">\r\n");
     				printf("<button class=\"mybtn\">登录</button>\r\n");
     				printf("</p>\r\n");
     				printf("</form>\r\n");
     				printf("</div>\r\n");
     				printf("<dialog open>\r\n");
     				printf("<p>用户名或密码错误,请重新登录</p>\r\n");
     				printf("<form method=\"dialog\">\r\n");
     				printf("<button align=\"center\">确定</button>\r\n");
     				printf("</form>\r\n");
     				printf("</dialog>\r\n");
     				printf("</html>\r\n");
     			}
     		}
    
     	} /* while */
    
     	return 0;
     }
    
     int checkLogin(char* recvBuf, const char* userName, const char* password){	
     	char* p = recvBuf;
     	char* pUserName = strtok(p, "&");
     	char* pPassWord = strtok(NULL, "&");
    
     	char* pUserNameKey = strtok(pUserName, "=");
     	char* pUserNameValue = strtok(NULL, "=");
    
    
     	char* pPassWordKey = strtok(pPassWord, "=");
     	char* pPassWordValue = strtok(NULL, "=");
    
    
     	if(strcmp(pUserNameValue, userName) == 0 && strcmp(pPassWordValue, password) == 0){
     		return 1;
     	}
     	return 0;
     }
    
  • 编译
    • gcc echo.c -lfcgi
  • 启动fastcgi
    • spawn-fcgi -a 192.168.206.128 -p 10010 -f ./a.out
    • 如果有以下报错,说明启动失败了。先直接启动下a.out看是什么报错
    • spawn-fcgi: child exited with: 127
    • 直接启动a.out,可以看到以下报错
    • ./a.out: error while loading shared libraries: libfcgi.so.0: cannot open shared object file: No such file or directory
    • 说明找不到库文件libfcgi.so,这个文件在这个目录下 /usr/local/lib
    • 可以把这个目录加到 /etc/ld.so.conf文件中,执行sudo ldconfig
    • 再重新启动fastcgi程序。注意a.out前面一定要加路径。
    • 有以下打印说明启动成功了
    • spawn-fcgi: child spawned successfully: PID: 26378

测试

  • 首先我们在浏览器中访问Nginx,默认端口为80。然后会展示我们写的登录网页,在登录网页中输入用户名和密码后,点击提交,会发送POST请求到Nginx配置文件中配置的/fastCgiTest指令上。Nginx就会根据ip和端口将指令转发到fastCGI程序,fastCGI程序处理POST请求数据,如果用户名和密码正确,显示登录成功,如果用户名和密码错误,继续展示登录界面,并提示用户重新登录。
  • 先访问Nginx,展示默认网页
    在这里插入图片描述
  • 输入正确的用户名和密码,fastCGI程序处理后展示登录成功界面
    在这里插入图片描述
  • 输入错误的用户名和密码,fastCGI程序处理后,重新展示登录界面,并提示重新登录
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/21575.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

了解这3大特性,再也不担心传输线问题了!

电阻是一个实实在在的物理元器件&#xff0c;通过欧姆定律我们可以知道&#xff0c;电压、电流和电阻三者之间的关系&#xff0c;UI*R。 我们通过一个具体的电路来分析这三者之间的具体关系&#xff0c;请看下面的一张最简单的电路图。这个电路图只有一个电源一个电阻和一些导…

MySQL---多表联合查询(下)(内连接查询、外连接查询、子查询(ALL/ANY/SOME/IN/EXISTS关键字)、自关联查询)

1. 内连接查询 数据准备&#xff1a; use mydb3;-- 创建部门表 create table if not exists dept3(deptno varchar(20) primary key , -- 部门号name varchar(20) -- 部门名字 );-- 创建员工表 create table if not exists emp3(eid varchar(20) primary key , -- 员工编号e…

尝试探索水下目标检测,基于yolov5轻量级系列模型n/s/m开发构建海底生物检测系统

其实&#xff0c;水下目标检测相关的项目早在之前就已经做了几个了&#xff0c;但是没有系统性地对比过&#xff0c;感兴趣的话可以先看下之前的文章&#xff0c;如下&#xff1a; 《基于自建数据集【海底生物检测】使用YOLOv5-v6.1/2版本构建目标检测模型超详细教程》 《基于…

AVL树(平衡二叉搜索树)

如果BST树插入的顺序是有序的&#xff0c;那么BST树就会退化成一个双链表结构&#xff0c;查询的速率就会很慢&#xff0c; 所以有了AVL树的意义。 AVL树的定义&#xff1a; 是具有下列性质的二叉搜索树 1、它的左子树和右子树都是AVL树 2、左子树和右子树的高度之差的绝对值…

办公智慧化风起云涌,华为MateBook X Pro 2023是最短距离

今年以来&#xff0c;我们几乎每个月&#xff0c;甚至每星期都可以看到大模型应用&#xff0c;在办公场景下推陈出新。 办公智慧化已成必然&#xff0c;大量智力工作正在被自动化。一个普遍共识是&#xff1a;AI能力范围之内的职业岌岌可危&#xff0c;AI 能力范围之外的职业欣…

瑞吉外卖 - 分页查询分类功能(12)

某马瑞吉外卖单体架构项目完整开发文档&#xff0c;基于 Spring Boot 2.7.11 JDK 11。预计 5 月 20 日前更新完成&#xff0c;有需要的胖友记得一键三连&#xff0c;关注主页 “瑞吉外卖” 专栏获取最新文章。 相关资料&#xff1a;https://pan.baidu.com/s/1rO1Vytcp67mcw-PD…

《Netty》从零开始学netty源码(五十八)之NioEventLoop.execute()

目录 NioEventLoop.execute()addTask()startThread()NioEventLoop.run()select()处理keys与执行任务processSelectedKeys()处理AbstractNioChannelselectAgain() runAllTasks()fetchFromScheduledTaskQueue()runAllTasksFrom()afterRunningAllTasks() 带截止时间的runAllTasks(…

由浅入深Netty入门案例

目录 1 概述1.1 Netty 是什么&#xff1f;1.2 Netty 的作者1.3 Netty 的地位1.4 Netty 的优势 2 Hello World2.1 目标2.2 服务器端2.3 客户端2.4 流程梳理2.5 提示 1 概述 1.1 Netty 是什么&#xff1f; Netty is an asynchronous event-driven network application framework…

免费可用 ChatGPT 网页版

前言 ChatGPT&#xff08;全名&#xff1a;Chat Generative Pre-trained Transformer&#xff09;&#xff0c;美国OpenAI 研发的聊天机器人程序 &#xff0c;于2022年11月30日发布 。ChatGPT是人工智能技术驱动的自然语言处理工具&#xff0c;它能够通过理解和学习人类的语言来…

在 Python 中执行逐元素加法

文章目录 Python 中的逐元素加法在 Python 中使用 zip() 函数执行逐元素加法在 Python 中使用 map() 函数执行逐元素加法在 Python 中使用 NumPy 执行逐元素加法 我们将通过示例介绍在 Python 中按元素添加两个列表的不同方法。 Python 中的逐元素加法 在 Python 中使用列表时…

最简单配置jenkins容器使用宿主机的docker方法

构建镜像和发布镜像到harbor都需要使用到docker命令。而在Jenkins容器内部安装Docker官方推荐直接采用宿主机带的Docker即可 设置Jenkins容器使用宿主机Docker 设置宿主机docker.sock权限 chown root:root /var/run/docker.sock chmod orw /var/run/docker.sock 添加数据卷 v…

Nacos之服务配置中心

1.基础配置 1.1.新建模块cloudalibaba-config-nacos-client3377 1.1.1.POM <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance…

网络:网络分层与协议/OSI七层模型/(TCP/IP模型)

一、简单理解 OSI模型(Open System Interconnection)&#xff1a; 七层模型&#xff0c;亦称OSI&#xff08;Open System Interconnection&#xff09;。参考模型是国际标准化组织&#xff08;ISO&#xff09;制定的一个用于计算机或通信系统间互联的标准体系&#xff0c;一般…

chatgpt赋能Python-pythondic

Python Dict - Python中最有用的数据结构之一 当谈到Python的数据结构时&#xff0c;Python字典&#xff08;Python Dict&#xff09;是最常用和最有用的数据结构之一。Python字典是一个非常强大且多才多艺的数据结构&#xff0c;它不仅易于学习和使用&#xff0c;而且可以大大…

【嵌入式Linux】设备树基本语法

设备树基本语法 1_总领-本期设备树视频要怎么讲&#xff1f;讲什么&#xff1f;_哔哩哔哩_bilibili 基本的 特殊的 中断控制 描述GIC控制器 时钟 CPU GPIO 个数&#xff0c;保留范围&#xff08;起始、长度&#xff09;&#xff0c;个数对应的名字 GPIO映射-这个脚被用了换一…

CBFS Vault 2022 for .NET Crack

将多个文件打包到一个 Vault - 一个“文件中的文件系统”&#xff0c;完成每个文件的压缩、透明加密和随机读/写访问。 亮点包括新的日记选项、用于更好地控制和跟踪的新事件&#xff0c;以及一系列核心性能和可用性改进 [了解更多]。 CBFS保险库 在任何地方存储一个完整的文件…

javascript-基础知识点总结

目录 &#xff08;一&#xff09;基础语法 1、javaScript引入方式 2、变量与常量 3、数据类型 typeof操作符 4、运算符 5、输出函数 6、类型转化 7、转移字符 8、注释 &#xff08;二&#xff09;流程控制 1、选择结构 switch 2、循环结构 for &#xff08;三&…

neovim下window的快捷切换

neovim下window的快捷切换 在使用emacs的时候&#xff0c;喜欢加插件window-numbering。 这样在分屏之后的emacs里&#xff0c;通过配置快捷键leaderwnumber 跳转到对应的windows, 而且该软件会在对应底部显示数字提示&#xff0c;非常方便。 另外:为什么不用快捷键leadernumb…

【Linux系统】Linux进程信号详解

Linux进程信号 0 引言1 认识信号1.1 什么是信号1.2 发送信号的本质1.3 信号的处理 2 信号的产生2.1 键盘产生2.2 调用系统函数向进程发送信号2.3 由软件条件产生信号2.4 硬件异常产生信号 3 信号的保存4 信号的处理5 总结 0 引言 本篇文章会从Linux信号的产生到信号的保存&…

Linux上开启coredump

Linux上开启core dump Core dump&#xff08;核心转储&#xff09;是在程序崩溃时生成的一种文件&#xff0c;其中包含了程序在崩溃时的内存状态信息。它可以帮助程序员在调试程序时快速定位问题&#xff0c;并且是一种非常有用的调试工具。core dump的作用如下&#xff1a; 帮…