暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

负载均衡--Nginx

进击的大杂烩 2017-12-29
241


微信公众号:进击的大杂烩
欢迎关注我,一起学习,一起进步!

什么是负载均衡

负载平衡(Load balancing)是一种计算机网络技术,用来在多个计算机(计算机集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到最优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。 使用带有负载平衡的多个服务器组件,取代单一的组件,可以通过冗余提高可靠性。负载平衡服务通常是由专用软体和硬件来完成。负载均衡往往配合健康检查使用。

C/S模型的演变
1.单一 server 模型

  • 优点:
    简单

  • 缺点:
    服务端单点
    单机吞吐量有限

  • 适用场景
    非重要业务
    测试环境
    产品初期

2.多 server 模型

  • 优点:
    最基础的负载均衡

  • 缺点:
    轮询算法由客户端决定
    客户端无法实时掌控服务端状态

  • 适用场景:
    大量外部客户端(如浏览器)接入
    客户端可控

3.多 server 进阶模型

  • 优点:
    可用性变高

  • 缺点
    客户端复杂度高更高
    轮询算法由客户端决定
    多客户端时,心跳会造成额外负担

  • 适用场景
    高时效性
    客户端可控

4.代理模型

  • 优点
    客户端开发简单
    扩展/收缩对客户端透明

  • 缺点
    代理维护成本
    可能带来长连接问题
    代理自身局限性

  • 适用场景
    适用于大多数场景
    逻辑解耦

  • 代理基本模型种类

    1.四层负载均衡


    基于ip + port的负载均衡 如:
    LVS,f5/haproxy/nginx的四层模式
    优点:
    理论上可应用于任何应用层协议
    某些场景下可突破端口数限制
    缺点:
    无法理解应用层协议
    仅能通过4层信息分流
    2.七层负载均衡


    基于应用层信息的负载均衡 如:
    f5/haproxy/nginx的7层模式,mysql-proxy
    优点:
    可理解应用层信息
    可根据应用层信息进行分流
    可作为网关使用
    缺点:
    仅支持特定的应用层协议

负载均衡-Nginx

Nginx简介:

nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev.

  • 概述:
    七层协议支持http, mail(imap | pop3 | smtp)
    新版本支持四层负载均衡(since 1.9.0)

  • 为什么要用nginx:
    高性能

    静态文件 负载均衡
    协议支持完善(gzip, keepalived等)
    功能强大(缓存,安全等)
    稳定
    模块 扩展丰富
    其它(平滑重启)


  • Nginx 为什么性能好?
    Nginx采用的是IO多路复用的IO模型(根据操作系统选择使用epoll或select模型)
    下面一节会简单的讲解一下什么是IO模型

  • Nginx的缺点


缺点如何突破
自身无法支持动态语言Fastcgi, uswgi等中间件
配置语法有局限性(如不支持if else)Nginx_lua扩展
做代理时受端口数限制多机部署
自身高可用问题keepalived
做代理时候无主动健康检查nginx_upstream_check_module扩展


Nginx的常用场景(接入 分流 缓存 动静分离 CDN)

1.常规架构

2.产品应用实例

3.使用注意事项
  • Nginx的配置文件是声明型(declarative),而非过程型的(procedural)
    Nginx指令执行顺序的13个阶段 http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html#02-NginxDirectiveExecOrder01

location test {
  set  $a 32;
  echo $a;
  set $a 56;
  echo $a;
}
curl 'http://localhost:8080/test
56
56
实际的执行顺序
  set $a 32;
  set $a 56;
  echo $a;
  echo $a;

  • proxy_next_upstream双刃剑,可能会造成系统雪崩,可能会导致多次写库。


    检索系统应关闭 Error,Timeout,4xx,5xx
    http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream

  • 注入问题

location  {
    rewrite ^ https://$host/$uri;
}
GET test%0d%0aSet-Cookie:%20malicious%3d1 HTTP/1.0
Host: yourserver.com
HTTP/1.1 302 Moved Temporarily
Server:
Location: https://yourserver.com/test
Set-Cookie: malicious=1
原因:
  $uri在使用时会url_decode
解决方案:
  跳转时候使用$request_uri

IO模型

CPU告诉我们,它自己很快,而上下文切换慢、内存读数据慢、磁盘寻址与取数据慢、网络传输慢……总之,离开CPU 后的一切,除了一级高速缓存,都很慢。我们观察计算机的组成可以知道,主要由运算器、控制器、存储器、输入设备、输出设备五部分组成。运算器和控制器主要集成在CPU中,除此之外全是I/O,包括读写内存、读写磁盘、读写网卡全都是I/O。I/O成了最大的瓶颈。

操作真实延迟cpu的感觉
执行指令0.38纳秒1秒
读L1缓存0.5纳秒1.3秒
分支纠错5纳秒13秒
读L2缓存7纳秒18.2秒
加/解锁25纳秒1分5秒
内存寻址100纳秒4分20秒
上下文切换/系统调用1.5微秒1小时5分钟
1Gbps网络上传输2KB数据20微秒14.4小时
从内存读1M连续数据250微秒7.5天
ping同idc两台主机0.5毫秒15天
从ssd读取1M连续数据1毫秒1个月
从硬盘读取1M连续数据20毫秒20个月
ping不同城市主机150毫秒12.5年
虚拟机重启4秒300年
服务器重启5分钟2万5千年

1.阻塞IO模型IO模型种类

  • 阻塞IO模型:


    在linux中,默认情况下所有的socket都是blocking。
    当内核未准备好数据时,进程只能block,傻傻等待。
    食堂打饭:
    管食堂大妈要一份饭,之后傻等,待大妈准备好饭后,拿饭走人。

rv = ''
while True:
   #  block io
   data = sock.recv(1024)
   if not data:
       sock.close()
       break
   rv += data
return rv

2.非阻塞IO模型
  • 非阻塞IO模型


    用户进程需要不断的主动询问kernel数据好了没有
    效率可能更低下
    食堂打饭:
    管食堂大妈要一份饭,到座位玩手机,之后每过一段时间来问一下饭准备好没,直到饭好了,拿饭走人。


rv = ''
while True:
   sock.setblocking(False)
   try:
       data = sock.recv(1024)
       if not data:
           sock.close()
           break
       rv += data
   except OSError:
       do_something_else
return rv

3.IO多路复用
  • IO多路复用

    用户进程通过某些系统调用(select, epoll)监听在多个fd上
    当fd可读/写时,内核将通知用户进程,用户进程再读取
    避免了无意义的block
    食堂打饭:
    管食堂大妈要一份饭(系统调用),到座位玩手机,直到大妈喊你,再去拿饭走人。

while sockets:
   # this select call blocks until one or more of the
   # sockets is ready for read I/O
   rlist, _, _ = select(sockets, [], [])
   # rlist is the list of sockets with data ready to read
   for sock in rlist:
       data = ''
       while True:
           new_data = sock.recv(1024)
           else:
               if not new_data:
                   break
               else:
                   data += new_data

IO 模型的应用


1.进程模型:
  • 单线程

  • 多线程

  • 单线程IO多路复用

2.高并发模型:
  • 多线程:
    并发达到一定量时内存首先将耗尽 因为在 linux 系统中,线程数是有限的,每个线程必须预分配8m大小的栈,不论是否使用!所以,线程增加时,内存首先成为瓶颈即使挺过内存问题,当并发请求足够多时,cpu 争用线程的调度问题又成为系統瓶颈

  • 单线程IO多路复用:
    只有相关事件发生时,才处理具体数据 如果当前接口没有数据时,就会立即切换出去,处理其它请求,所以,虽然只有一个线程,但是,可以同时处理很多很多的請求处理 那么,这种形式的 web 系統,可以很轻易的将 cpu 跑满,即使带宽没有跑满的情况下; 而 apache 这类多进程多线程模型的服务器,则很难将 cpu 跑满。

参考&阅读补充

  • 章亦春的nginx教程 http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html

  • Nginx_lua手册 https://github.com/openresty/lua-nginx-module

  • Taobao nginx手册 http://tengine.taobao.org/book/

  • Nginx wiki http://nginx.org/


文章转载自进击的大杂烩,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论