--- 阅读时间约 15 分钟 ---
众所周知,互联网已经离不开 WEB服务器 ,技术领域中 WEB服务器 不止 Nginx 一个,其他还有很多如 Apache 、 Tomcat 、 Lighthttpd 等,相信能看到这篇文章的友友们对这几个单词都不陌生。而 Nginx 因其高性能、轻量性、健壮性让技术大厂们无法忽视它的存在。
Nginx 是一个免费、开源、高性能的 HTTP服务器 和 反向代理 ,以及 IMAP / POP3 代理服务器。以高性能、稳定性和丰富的功能、简单的配置、低资源消耗而闻名。
这是 Nginx 官网首页贴出的 Partners 名单,看看啥概念吧:
包括 由淘宝发起的项目 Tengine 、由章亦春发起 连锤子科技把T2发布会门票收入都捐赠的开源项目 OpenResty ,都是基于 Nginx 进行的定向开发。国内几乎所有大厂都使用到了 Nginx 技术。
Nginx 服务器,正常运行过程中:
Request:Nginx中 HTTP 请求。
基本的 HTTP Web Server 工作模式:
根据其功能基本上分为以下几种类型:
“ WEB服务 ”,这个概念其实很简单,个人理解大致分为以下几个部分:
大部分程序员的工作就是进行服务编写和项目搭构,再由 Nginx 这样的工具,对外持续提供服务,当然不仅是WEB服务,我们平时通过网络访问的绝大部分资源,其内部都有 Nginx 的身影。
Nginx 是一个高性能处理 HTTP协议 的服务软件,而互联网在我们日常生活中,凡是用于给用户展示的,绝大多数都是 HTTP协议 ,因此像 Nginx 这种以高性能稳定运行的解析HTTP协议软体理所当然会无处不在。当然如果仅仅是这样我们大可以用其他软体来代替, Nginx 真正的强大还不止于这些。
Nginx 本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用它来做服务器,同时现在也很流行动静分离,亦可通过它来实现。
server {
listen 80;
server_name localhost;
location / {
root e:/www/data;
index index.html;
}
}
通过以上配置,我们在访问 http://localhost 时就会默认访问到 E://www/data 目录下的 index.html 。
项目只有静态资源
更改Nginx配置并启动,即可完成部署。
反向代理是大部分用户通过 Nginx 完成最多的一件工作, 反向代理(Reverse Proxy) 方式是指以代理服务器来接受 Internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 Internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
简单来说就是真实的服务器不能直接被外部网络访问,所以需要一台代理服务器,而代理服务器能被外部网络访问的同时又跟真实服务器处于同一个网络环境,当然也可能是同一台服务器的不同端口,这就是国内市场上大部分中小型企业的服务器中存在 Nginx 服务的原因,甚至隔壁 SegmentFault 也经常会全站访问 502 Bad Gateway —— Nginx xx.xx.xx(版本号)。
server {
listen 80;
server_name localhost;
location / {
proxy\_pass http://localhost:8080;
proxy\_set\_header Host $host:$server\_port;
}
}
业务服务器不能直接被外部网络访问,即不能直接映射外网ip,需要一台代理服务器,而代理服务器能被外部网络访问同时又和业务服务器的网络相通。
使用反向代理功能。将 Nginx 服务器映射外网ip,业务服务器无需映射,外网用户访问时首先访问 Nginx 服务器,然后再由 Nginx 服务器访问业务服务器资源后转发给用户,这是目前互联网服务器的主流方案,既满足了业务外网访问的需求,又保证了业务服务器的安全。
动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好拆分后,我们就可以根据静态资源(如html、css、js、图片文件)的特点对其做缓存操作,这样就完成了网站静态化处理的核心思路。并且 Nginx 安装在服务器上的 http 和 反向代理服务组件,除了WEB服务意外还提供了 负载均衡 服务,这对用户访问服务器尤其在高并发的时候尤其关键,可以将用户访问静态资源和动态请求区分开,分配给不同的执行单元,提高响应速度,具体会在下文中提出。
upstream test{
server localhost:8080;
server localhost:8081;
}
server {
listen 80;
server_name localhost;
location / {
root e:/wwwroot;
index index.html;
}
# 所有静态请求都由nginx处理,存放目录为html
location ~ .(gif|jpg|jpeg|png|bmp|swf|css|js)$ {
root e:/wwwroot;
}
# 所有动态请求都转发给tomcat处理
location ~ .(do)$ {
proxy\_pass http://test;
}
error\_page 500 502 503 504 /50x.html;
location = /50x.html {
root e:/wwwroot;
}
}
项目对性能有要求,需要写出对并发和健壮性有要求的WEB服务。
上述需求我们就可以使用静态服务器及反向代理模块,将静态资源由 Nginx 本地提供,动态资源反向代理到后端的 Tomcat 提供,其中 Tomcat 和 Nginx 可以在同一台服务器也可以在不同服务器中。
最近开发公司一个项目就是,不同地级市分别对应不同的业务首页,就是用 Nginx 实现的。多套业务系统使用同一个ip或者域名进行访问,以不同后缀进行区分,需要一台 Nginx 服务器做统一的访问入口。
使用 Nginx 对入口项目进行部署,再使用反向代理模块将所有 Nginx 服务器作为外网或内网用户统一的访问入口,然后根据设置的 localtion 规则匹配不同的后缀转发至不同的业务服务器。通常和前文提到的反向代理场景结合使用实现一个域名来访问多个业务系统,同时甚至还可以实现统一的 https 访问,通过在 Nginx 服务器上配置证书,后端所有业务服务器无需每台额外配置证书即可实现 https 访问。
这一场景其实就是使用了 反向代理 模块,由于服务器不存在 同源策略 ,因此通过 Nginx 代理服务器将请求中转即可解决开发时临时请求跨域问题,这应该是前端开发用 Nginx 做的最多的事。
阅读我的另一篇文章:Nginx:多项目开发配置跨域代理
将前后端项目都部署在服务器之后,因为请求和服务放在一起所以不存在跨域问题。但在非维护的开发时,如果后端没有为自己的服务提供跨域,我们必须自己来完成以请求数据来完成开发。
不过我们在工作中并不是每个项目都使用了 webpack 或者引入了类似 http-proxy-middleware 的中间件,甚至还有可能维护 JSP 项目,所以我们有必要了解一个轻量级即开即用的跨域工具。
正向代理,意思是一个位于客户端和原始服务器 (origin server) 之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标 (原始服务器) ,然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。
Nginx 不支持 CONNECT ,所以无法正向代理 HTTPS 网站(网上银行、Gmail)。如果访问 HTTPS 网站,比如:https://www.google.com ,
Nginx access.log 日志:" CONNECT www.google.com:443 HTTP/1.1 " 400 。
1 server {
2 resolver 8.8.8.8;
3 resolver_timeout 5s;
4
5 listen 80;
6
7 access_log /home/reistlin/logs/proxy.access.log;
8 error_log /home/reistlin/logs/proxy.error.log;
9
10 location / {
11 proxy_pass scheme://scheme://host$request_uri;
12 proxy_set_header Host $http_host;
13
14 proxy_buffers 256 4k;
15 proxy_max_temp_file_size 0;
16
17 proxy_connect_timeout 30;
18
19 proxy_cache_valid 200 302 10m;
20 proxy_cache_valid 301 1h;
21 proxy_cache_valid any 1m;
22 }
23 }
行2 - resolver 是配置正向代理的 DNS服务器 ,比如 Google Public DNS .
行3 - 超时时间 5s .
行5 - listen 是正向代理的端口 .
行11 - 配置正向代理参数,与 行12 均是由 Nginx 变量组成 .
行12 - 解决当 URL 中带 " . " 后 Nginx 503 错误 .
行14 - 配置缓存大小 .
行15 - 关闭磁盘缓存读写,减少 I / O .
行17 - 代理连接超时时间 .
当我们需要把我们的服务器作为代理服务器时。
可以用 Nginx 来实现正向代理,但是目前 Nginx 有一个需要注意的问题:不支持 HTTPS *,如果想实现 HTTPS 的需求需要借助第三方模块 ngx_http_proxy_connect_module ,配置 HTTPS 请阅读fs_Dong的文章:搭建Nginx正向代理服务。
统计整个系统访问的浏览器信息、IP、地理位置、操作系统等信息作为项目上大数据展示的初始数据来源。
通常搭配 反向代理 、 访问入口统一 的场景,使用 Nginx 的日志 及 地理位置库插件 来采集信息,然后由 eCloud平台 进行初步分析后供大俗韩剧平台采集和展示。主流发布的一键部署包已包含 地理位置库插件。
重头戏来了,大厂都无法拒绝的硬菜。
负载均衡 也是 Nginx 的一个常用功能,简而言之就是当存在 2台或2台以上的服务器时,根据规则随机将请求分发到指定的服务器上处理,负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。而 Nginx 目前支持自带 3种负载均衡策略,还有 2种常用的第三方策略:
-- RR(默认)
每个请求按时间顺序注意分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。简易配置:
1 upstream test {
2 server localhost:8080;
3 server localhost:8081;
4 }
5 server {
6 listen 80;
7 server_name localhost;
8 client_max_body_size 1024M;
9
10 location / {
11 proxy_pass http://test;
12 proxy_set_header Host $host:$server_port;
13 }
14 }
行2、3 - 负载均衡的核心代码,配置两台服务器,这里实际上是一台服务器的不同端口,而8081的服务器是不存在的,也就是说访问不到,但是我们访问 http://localhost 的时候也不会有问题,会默认跳转到 http://localhost:8080 ,具体是因为 Nginx 会自动判断服务器的状态,如果服务器不能访问(服务挂了)就不会跳转到这台服务器,所以避免了一台服务器挂了影响使用的情况。由于 Nginx 默认是 RR 策略,所以我们不需要其他更多的设置。
-- 权重 weight
必须实现 session 共享,否则导致用户 session 不同步,致使用户重新登陆。指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。例如
1 upstream test {
2 server localhost:8080 weight=9; #请求的 90% 进入到8080服务器
3 server localhost:8081 weight=1; #请求的 10% 进入到8081服务器
4 }
行2、3 - 访问10次种一般只会有 1此访问到8081,而其他 9次回访问到8080
-- ip_hash:
上面的 2种方式都存在一个缺陷,当下一个请求到达的时候请求可能分发到另外一个服务器,当我们的程序不是无状态(采用了 session 保存数据),这时候就会产出BUG,比如把登录信息保存在 session 种,那么跳转到另外一台服务器的时候就需要重新登录,所以很多时候我们需要一个用户之访问一个服务器,此时就需要用 ip_hash 替代了。
ip_hash 的每个请求按 访问ip的 hash结果进行分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题。
1 upstream test {
2 ip_hash;
3 server localhost:8080;
4 server localhost:8081;
5 }
-- fair (第三方)
按后端服务器的响应时间来分配请求,优先分配响应时间最短的服务器。
1 upstream backend {
2 fair;
3 server localhost:8080;
4 server localhost:8081;
5 }
-- url_hash (第三方)
按 访问url的 hash结果来分配请求,使每个 url 定向到同一个后端服务器,后端服务器为缓存时比较有效。在 upstream 中加入 hash语句,server语句中不能写入 weight 等其他参数,hash_method 是使用的 hash 算法。
1 upstream backend {
2 hash $request_uri;
3 hash_method crc32;
4 server localhost:8080;
5 server localhost:8081;
6 }
-- 总结
以上 5种负载均衡 各自适用不同情况下使用,所以可以根据实际情况选择哪种策略模式,但 fair 与 url_hash 需要安装第三方模块才能使用。
主流分布式架构方案中,实现将请求按一定的策略分发至后端多台业务服务器,实现业务服务的高可用及高并发。
使用 Nginx 的 反向代理 、 负载均衡 模块,根据配置的 url后缀规则 转发至 upstream 中个服务器列表,默认按 轮询策略 ,同时还支持 权重 和 ip_hash ,有 redis 缓存登录 session 的方案中推荐使用 轮询策略 ,否则使用 ip_hash 策略实现同一ip 的用户请求固定至后端同一台服务器。
负载均衡(LB, Load Balance)是一种技术解决方案,用来在多个资源(一般是服务器)中分配负载,达到最优化资源使用,避免过载。
资源,相当于每个服务实例的执行操作单元,负载均衡就是将大量的数据处理操作分摊到多个操作单元去执行,用来解决互联网分布式系统的大流量、高并发和高可用的问题。
高可用是 CAP 定理 ,也是分布式系统的基础,0分布式系统的3个指标:
高可用 简称 HA,是系统一种特征或者指标,通常是指提供一定性能上的服务运行时间,高于平均正常时间段。反之消除系统服务不可用的时间。
衡量系统是否满足 高可用 ,就是当一台或多台服务器宕机的时候,系统整体和服务依然正常可用。举个例子,一些知名的网站保证 4 个 9 以上的可用性,也就是可用性超过 99.99%。那 0.01% 就是所谓故障时间的百分比。比如电商网站有赞,服务不可用会造成商家损失金钱和用户。那么在提高可用性基础上同时,对系统宕机和服务不可用会有补偿。
比如下单服务,可以使用带有负载均衡的多个下单服务实例,代替单一的下单服务实例,即使用冗余的方式来提高可靠性。
总而言之,负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一。一般通过负载均衡,冗余同一个服务实例的方式,解决分布式系统的大流量、高并发和高可用的问题。负载均衡核心关键:在于是否分配均匀。
微服务架构中,网关路由到具体的服务实例 hello:
两个相同的服务实例 hello service ,一个接口 8000, 另一个接口 8082 ,通过 Kong 的负载均衡 LB 功能,让请求均匀的分发到两个 hello 服务实例。
Kong 的负载均衡策略算法很多:默认 weighted-round-robin 孙发,还有 consumer: consumer id 作为 hash 算法输入值等。
微服务架构中, A 服务调用 B 服务的集群。通过了 Ribbon 客户端负载均衡组件:
常见的互联网分布式系统架构分为几层,一般如下:
一般请求从客户端层到业务服务层,层层访问都需要负载均衡。即每个上游调用下游多个业务方的时候,需要均匀调用。这样整体系统来看,就比较负载均衡。
通过 DNS 轮询 实现, DNS 可以通过 A(Address,返回域名指向 IP 地址)设置多个 IP 地址。比如图例访问 bysocket.com 的 DNS 配置了 ip1 和 ip2 。为了反向代理层的高可用,至少回有两条 A 记录。这样冗余的两个 ip 对应的 nginx 服务实例,防止单点故障。
每次请求 bysocket.com 域名的时候,通过 DNS 轮询 ,返回对应的 ip 地址,每个 ip 对应的反向代理层的服务实例,也就是 nginx 的外网 ip。这样可以做到每一个反向代理层实例得到的请求分配是均衡的。
通过反向代理层的 负载均衡 模块 处理。比如 Nginx 有多种均衡方法:
1. 请求轮询。以 RR 默认策略 请求按时间顺序,逐一分配到 Web 层服务,然后周而复始。如果 Web 层服务 down掉,自动剔除。
1 upstream web-server {
2 server ip3;
3 server ip4;
4 }
2. ip_hash。按照 ip 的哈希值,确定路由到对应的 Web 层。只要用户的 ip 是均匀的,那么轻巧到 Web 层也是均匀的。
还有个好处就是同一个 ip 的请求回分发到相同的 Web 层服务。这样每个用户固定访问一个 Web层服务,可以解决 session 问题。
1 upstream web-server {
2 ip_hash;
3 server ip3;
4 server ip4;
5 }
3. weight 权重。
4. fair。
5. url_hash 等。
比如 Dubbo 是一个服务治理安敢,包括服务注册、服务降级、访问控制、动态配置路由规则、权重调节、负载均衡。其中一个特性就是智能负载均衡:内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。
为了避免单点故障和支持服务的横向扩容,一个服务通常回部署多个实例,即 Dubbo 集群部署。回将多个服务实例成为一个服务提供方,然后根据配置的随机负载均衡策略,在20个 Provider 中随机选择一个来调用,假设随机到了第 7 个 Provider 。 LoadBalance 组件从提供者地址列表中,使用均衡策略,选择一个提供者进行调用,如果调用失败,再选另一台调用。
Dubbo 内置了4种负载均衡策略:
同样,因为业务的需要也可以实现自己的负载均衡策略。
数据存储层的负载均衡,一般通过 DBProxy 实现。比如 MySQL 分库分表。
当单库或者单表访问太大,数据量太大的情况下,需要进行垂直拆分和水平拆分两个维度。比如水平切分规则:
但伴随着这块的负载会出现下面的问题需要解决:
现状分库分表的产品方案很多: 当当 sharding-jdbc 、阿里的 Cobar 等。
对外来看,负载均衡是一个系统或软件的整体。对内看来,层层上下游调用。只要存在调用,就需要考虑负载均衡这个因素。所以负载均衡(Load Balance)使分布式系统架构设计种必须考虑的因素之一。考虑主要是如何让下游接收到的请求使均匀分布的:
参考文献:
手机扫一扫
移动阅读更方便
你可能感兴趣的文章