nginx: 是一个Web服务器,如果不是需要apache的特殊功能的话,nginx是服务器的首选。
是一个轻量级的反向代理。(两个应用是web和mail)
模块化设计
反向代理: 反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源。同时,用户不需要知道目标服务器的地址,也无须在用户端作任何设定。反向代理服务器通常可用来作为Web加速,即使用反向代理作为Web服务器的前置机来降低网络和服务器的负载,提高访问效率。
通常的代理服务器,只用于代理内部网络对Internet的连接请求,客户机必须指定代理服务器,并将本来要直接发送到Web服务器上的http请求发送到代理服务器中。由于外部网络上的主机并不会配置并使用这个代理服务器,普通代理服务器也被设计为在Internet上搜寻多个不确定的服务器,而不是针对Internet上多个客户机的请求访问某一个固定的服务器,因此普通的Web代理服务器不支持外部对内部网络的访问请求。
当一个代理服务器能够代理外部网络上的主机,访问内部网络时,这种代理服务的方式称为反向代理服务。此时代理服务器对外就表现为一个Web服务器,外部网络就可以简单把它当作一个标准的Web服务器而不需要特定的配置。不同之处在于,这个服务器没有保存任何网页的真实数据,所有的静态网页或者CGI程序,都保存在内部的Web服务器上。因此对反向代理服务器的攻击并不会使得网页信息遭到破坏,这样就增强了Web服务器的安全性。
keepalived+nginx:
keepalived非常轻量级的高可用实现方案,nginx是非常轻量级的反向代理。天造地设的一对。
nginx基于异步IO来实现的,基于事件驱动的加上边缘触发来完成一个线程(单线程进程)处理多个请求,面对C10K问题是一个行之有效的方案。
C10K:最初的服务器是基于进程/线程模型。新到来一个TCP连接,就需要分配一个进程。假如有C10K,就需要创建1W个进程 。
-------------------------
IO模型:
阻塞:一个进程所发出的IO请求不能得到满足的时候,必须要一直等待至内核把这个数据从IO设备复制到内核缓冲区,再从内核缓冲区复制给这个进程的地址空间以后,在这个期间,进程必须处于等待状态。
非阻塞:当进程向内核发出系统调用的之后,不等待,而是一遍一遍轮询检查内核有没有把数据准备好。
同步:发送一个数据,对方收下来并且完整存储下来之后才返回,这叫同步。(双方必须要同步时钟信号)
异步(Mysql复制):把数据发送出去,对方什么时候收下来,什么时候存储下来都不管。(双方不需要同步时钟信号)
同步阻塞:
同步非阻塞:基于事件驱动的IO(event-driven)
异步阻塞:IO复用
异步非阻塞:aio
0、HTTP和HTTPS的区别:
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
以下是具体一些分析
一、HTTP和HTTPS的基本概念
HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。
二 **、**HTTP和HTTPS的主要特点和工作流程
HTTP特点:
1.支持客户/服务器模式。(C/S模式)
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快
HTTP工作流程:
第一步:建立TCP/IP连接,客户端与服务器通过Socket三次握手进行连接
第二步:客户端向服务端发起HTTP请求(例如:POST/login.html http/1.1)
第三步:客户端发送请求头信息,请求内容,最后会发送一空白行,标示客户端请求完毕
第四步:服务器做出应答,表示对于客户端请求的应答,例如:HTTP/1.1 200 OK
第五步:服务器向客户端发送应答头信息
第六步:服务器向客户端发送请求头信息后,也会发送一空白行,标示应答头信息发送完毕,接着就以Content-type要求的数据格式发送数据给客户端
第七步:服务端关闭TCP连接,如果服务器或者客户端增Connection:keep-alive就表示客户端与服务器端继续保存连接,在下次请求时可以继续使用这次的连接
HTTPS特点:
HTTPS是HTTP协议的修改,它加密数据并确保其机密性。其配置可保护用户在与网站交互时免于窃取个人信息和计费数据。
1、优点
相比于http,https可以提供更加优质保密的信息,保证了用户数据的安全性,此外https同时也一定程度上保护了服务端,使用恶意攻击和伪装数据的成本大大提高。
2、缺点
缺点也同样很明显,第一https的技术门槛较高,多数个人或者私人网站难以支撑,CA机构颁发的证书都是需要年费的,此外对接Https协议也需要额外的技术支持;其二,目前来说大多数网站并不关心数据的安全性和保密性,其https最大的优点对它来说并不适用;
其三,https加重了服务端的负担,相比于http其需要更多的资源来支撑,同时也降低了用户的访问速度;
第四,目前来说Http网站仍然大规模使用,在浏览器侧也没有特别大的差别,很多用户不关心的话根本不感知。
HTTPS工作流程:
第一步:客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
第二步:Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
第三步:客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
第四步:客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
第五步:Web服务器利用自己的私钥解密出会话密钥。
第六步:Web服务器利用会话密钥加密与客户端之间的通信。
最后说一句 ,ssl证书阿里云上可以免费申请一年
-------------------------
基本的HTTP服务器特性:
- 处理静态文件、索引文件,打开文件描述符缓存(一个页面通常具有元数据和数据,nginx可以缓存数据的元数据和文件描述符,下一次找的时候通过缓存就能找到)
- 使用缓存加速反向代理,简单负载均衡以及容错(反向代理时候能够实现后端服务器的健康检查,一旦发现不健康了,可以自动剔除,类似与keepalived。这个第三方模块只支持1.0,不支持1.2于是就有了Tenginx)
- Tenginx:淘宝官方弄得,有更多的第三方模块。(开源)
- 远程Fast CGI(结合这个方式支持PHP,apache是直接将php做成模块)、uwsgi(基于这个来支持python,不是PHP)、SCGI、和memcached服务的缓存加速支持。(nginx做反向代理的时候已经可以提供缓存功能,默认缓存在磁盘上的,但是可以实现在内存中缓存打开的文件描述符,httpd做反向代理既可以支持磁盘缓存,也可以支持内存缓存,现在的nginx已经附带了memcached模块)
- SSI:可以实行将一个页面当中某些内容做成静态的,某些内容做成动态的,缓存静态的内容,动态加载动态的内容。
其他的HTTP服务器特性:
基于域名和IP和端口的虚拟主机;
keep—alived(长连接)和pipelined连接支持;
重新加载配置以及在线升级时,不需要终端正在处理的请求(有一个主进程生成很多的子进程,子进程有worker等,新连接使用新配置,老旧的连接先使用旧连接,当老连接慢慢退出以后,在建立新连接);(热部署/平滑升级)
带缓存的日志写操作;
3xx~5xx错误代码重定向;
重写模块,使用正则表达式改变URI;
根据客户端地址执行不同功能(不光时地址,也可以是浏览器类型)
支持FLV流和MP4流;(边下载边播放)
架构和扩展性:
一个主进程和多个工作进程,工作进程以非特权用户进行(一个master进程产生多个worker进程,master以管理员身份启动(master负责分析配置文件是否有错误,有错误也不会影响worker进程,只是master会告诉你有错误,需要重新装载,然后就是新用新的,旧用旧的)(监控80端口,只有管理员才能启用小于1024的端口),worker进程由master进程以普通用户身份生成,master主要是监控worker进程是不是够数目以及运行是否正常)(每个worker进程内部还有许多模块,用到那个模块,调用哪个模块)(除了最核心的功能之外,其他的都以模块的方式运行,这些模块以流水线的方式在工作)
如果负载以CPU密集型应用为主,如SSL或者压缩应用,则worker数应和cpu数相同,若负载以IO密集型为主,如相应大量内容给客户端,则worker进程应为cpu个数的1.5~2倍。
支持事件驱动机制:kqueue(freeBSD 4.1+)、epoll(Linux2.6+)、/dev/poll(这三种是支持事件驱动的IO框架,nginx都支持)如果不支持epoll,则选择select或者poll。
支持sendfile和sendfile 64:内核不需要将从磁盘中调用的文件复制给用户空间进行封装,用户空间封装完成之后在复制给内核,而是直接代替用户空间进行封装,然后直接转发给网卡。
10000个非活跃的HTTP keep-alive连接仅占用2.5M内存
尽可能避免数据拷贝操作(sendfile)
主进程主要完成的工作:
- 读取并验证配置信息
- 创建、绑定以及关闭套接字
- 启动、终止以及维护worker进程的个数
- 无须终止服务而重新配置工作的特性**(热部署/平滑升级)**
- 控制非中断式程序升级,启用新的二进制程序并在需要时回滚至老版本
- 重新打开日志文件(实现日志滚动)
worker进程主要完成的任务:
- 接受、传入并处理来自客户端的连接
- 提供反向代理以及过滤功能
- nginx任何能完成的其他任务
cache loader进程主要的工作:
- 检查缓存存储中的缓存对象
- 使用缓存元数据建立内存数据库
cache manager进程主要任务:
- 缓存的失效以及过期检验
nginx配置:
main:核心配置
http:只对web服务器有效
server:
location:定义虚拟主机
upstream:只有在定义反向代理的时候才能用到
mail:只对mail服务器有效
server{}:虚拟主机(两个虚拟主机监听同一个地址,同一个端口,但是server_name不同,这就是基于名称的虚拟主机)
location{}:nginx结合以下两种功能。
httpd:
<DocumentRoot " ">
:基于本地文件系统路径来定义访问属性
<Location “/bbs”>
:基于URI路径来定义访问属性
URI:www.baidu.com**/URI**
----------------------------
URL的一般格式为(带方括号[]的为可选项):
protocol : // hostname [:port ] / path /
URL的格式由三部分组成:
①第一部分是协议(或称为服务方式)。
②第二部分是存有该资源的主机IP地址(有时也包括端口号)。
③第三部分是主机资源的具体地址,如目录和文件名等。
第一部分和第二部分用“😕/”符号隔开,
第二部分和第三部分用“/”符号隔开。
第一部分和第二部分是不可缺少的,第三部分有时可以省略。
三、URI和URL之间的区别
从上面的例子来看,你可能觉得URI和URL可能是相同的概念,其实并不是,URI和URL都定义了资源是什么,但URL还定义了该如何访问资源。URL是一种具体的URI,它是URI的一个子集,它不仅唯一标识资源,而且还提供了定位该资源的信息。URI 是一种语义上的抽象概念,可以是绝对的,也可以是相对的,而URL则必须提供足够的信息来定位,是绝对的。
----------------------------
location:
location [ = | ~ | ~* | ^~ ] URI {}
location URI {}:花括号中的内容对于URI当前路径包括子路径下的所有内容都生效
location = URI {}:只对于当前URI文件生效,如果是目录,对目录下的文件无效(精确匹配指定路径)
location ~ URI {}:模式匹配,区分字符大小写,可以使用正则表达式
location ~* URI {}:模式匹配,不区分字符大小写,可以使用正则表达式
location ^~ URI {}:取反,不使用正则表达式。
如果匹配到多个location,由优先级决定:【 = | ~ /~*(谁在上边先匹配谁) | ^~ | other】
location = / {
A
}
location / {
B
}
location /documents {
C
}
location ^~ /images/ {
D
}
location ~* \.(gif|jpg|jpeg)$ {
E
}
访问结果:
/~A
/index.html~B
/documents/index.html~C:优先级判断
/images/1.gif~D:优先级判断
/documents/1.jpg~E:使用优先级判断
location规则中的“防火墙”:
默认接受所有人访问,黑名单:deny +地址 ;白名单:allow +地址,然后 deny all。
location中的模块:
auth_basic:实现HTTP认证
location / {
auth_basic: “提示信息”
auth_basic_user_file htpasswd——指明那个配置文件,里边保存的有用户名和密码
#借助于apache的htpsswd模块来验证
#htpasswd -c(创建一个新文件) -m(md5加密) passwordfile username
#htpasswd -c -m /etc/nginx/filename(路径随意) username
注意:第二次不能使用-c选项了
authindex on;开启自动索引(列出所有索引)
stub_status模块:
活动连接数:1
已经接受的连接个数:1 已经处理的连接个数:1 已经处理的请求个数:1
正在读首部的请求个数: 正在读取主题的请求个数或正在处理请求内容的个数或者正在向其客户端发送响应的个数: 处于长连接模式中的保持的连接个数
第一个请求进来先检查缓存中有没有内容,如果没有,然后对请求报文重新进行封装,发送至Fast CGI(PHP)服务器,PHP服务器发送回来的数据先缓存至本地,然后封装一个响应报文给客户端,当第二个请求报文来的时候,先检查缓存,若有,且没有失效,直接返回。就是这种异步模型加本地缓存机制,前端发现有1000个连接,到了后端却只有50个。
memcached是一个公共缓存,可以供每一个app server缓存和查询。
①:App server觉得这个结果可以缓存,然后要程序自己将数据放到memcached服务器上,当下一次找的时候,直接到memecached中找
②:所以以后每个app server找数据时,先到memcached中找没有了,在连接至数据库,读过来之后,有程序本身缓存至memcached服务器,再向外响应。
当某一个用户请求发送到第一个php服务器上,PHP服务器所执行的任何一个代码,都是先编译成opcode,编译以后才能执行。
一个appserver以fast CGI工作的时候,为每一个连接生成一个fast CGI进程,第一个进程编译的opcode只能为第一个进程使用(用户多次请求同一个内容,缓存这个opcode才有意义),但是第二个连接使用第二个fast CGI进程,但是第二个fast CGI进程不能使用第一个进程Fast CGI所编译的opcode。xcache就是在同一个appserver上为多个进程使用同一个opcode缓存。
如果使用持久连接,每次来自同一个客户端的会话被分配至同一个appserver,appserver将会话信息保存至本地运行内存,如果这个appserver挂了,那个这个会话就没有,可以使用appserver集群,将会话信息共享至其他appserver内存,但是这样的话,每一个会话都需要通过组播的方式发送给其他的appserver,如果appserver多的话,这样数据量就太大了,只适应于小规模的appserver集群。
我们可以建立一个会话共享内存区(memcached正是这种服务器),所以,当第一个用户的第一个请求发送到appserver时,appserver发现需要给这个请求建立一个会话,这个会话不在保存至本地了(原来为了持久,保存至本地内存中),直接保存至memcached中,每次用户请求来,都会发送一个cookie,根据这个cookie去找相应的session,根据这个session和用户建立相应的会话。
但是memcached挂了,所有的会话信息全没了,所以我们应该给memcached高可用,但是memcached认为我们这都是缓存信息,并不是关键数据,如果我挂了,缓存数据丢失,最多也就是重建而已,所以我这不会使用高可以用的,memcached本身不支持高可用的。但是memcached可以很好的支持分布式,
memcached使用键值对存储,但是对于非键值对数据,memcached无法进行存储,例如(一个人姓名,性别,年龄,浏览网页:张三,男,30,30)等,客户端并无法理解两个30为什么东西,所以我们可以使用一张表,将里边的每个值做一个键值对,再将整个信息作为一个键值对,这就是redis。
所以,当需求只是简单的键值对数据的时候,依然使用memcached,但是如果用到复杂数据结构的话,就是用redis,redis只是其中一种解决方案。redis实质上是一个databases,而这种数据库叫做Nosql,因为这种数据库不能基于sql语句来查找。
所以,memcached用来存储session,redis用来存储计数器,比如微博转发次数。
但是我们的结构越来越复杂,导致处理逻辑过于复杂,可能会产生bug,那应该怎么办?
我们可以将网站分区,这个服务器是论坛,那个服务器是个人信息等。所有访问每个大型网站的时候,主页总是访问量最大的,所以我们要将主页静态化,只是里边有些板块是动态生成的,但是这些板块都是缓存好的,不能说打开个主页,服务器垮了。
转发服务器的三种:
LVS:工作在四层,工作在内核
nginx:工作在七层,工作在用户空间
haproxy:工作在七层,工作在用户空间
注意:工作在四层好,并且工作在内核好,因为工作在内核可以直接转发,经过优化之后,lvs可以抗住数百万个请求,但是nginx和haproxy能抗住数万个都挺好了。同等条件下,nginx不如haproxy的转发能力好,但是nginx对内存的要求量非常小。
但是nginx可以缓存结果,首先,memcached用来缓存会话,xcache用来缓存编译结果,而nginx用来缓存整个程序生成的结果的(opcode加上数据库的数据会生成一个结果)。但是我们的服务器本来就要进行转发,就很忙,还要进行缓存,所有我们可以将缓存独立出来。
但是如果第一次的请求,转发至了第一个缓存服务器,第二次请求,转发至了第二个服务器,那第一个缓存还能命中吗?为了提高缓存命中率,我们就做持久连接或者做缓存同步,但是持久连接好一点,但是持久连接会破环负载均衡效果。
那怎么转发对于不同内容的请求呢?lvs没有这个功能。
如果负载以CPU密集型应用为主,如SSL或者压缩应用,则worker数应和cpu数相同,若负载以IO密集型为主,如相应大量内容给客户端,则worker进程应为cpu个数的1.5~2倍。
nginx如何安装第三方模块:
–with-http_:安装nginx内置模块
–add-module=:安装第三方模块
nginx -V:查看第三方模块
进入编译目录:./configure --prefix=安装路径 --with --add:原来的模块也要进行预编译,除非不要了,add后边跟第三方模块放置的位置。
然后拷贝(带权限复制) ./objs/nginx sbin/nginx
然后重启服务
----------------
负载均衡:
静态算法:轮询和加权轮询