使用nginx建立反向代理服务器

nginx 简介

nginx 是一个高性能的 http 服务器,代码完全用C语言编写,能够支持高达50,000个并发连接数的响应。与其它 http 服务器相比,nginx 具有以下几个特性:

  • nginx 可以在大部分 Linux OS 上编译运行,并且可以比较简单地在 Windows 上移植。
  • nginx 可以提供很方便的反向代理功能。
  • nginx 可以轻松完成负载均衡服务

由于业务需求,我学习 nginx 主要是希望将 nginx 作为反向代理服务器进行使用, 并希望它能提供负载均衡功能

nginx 在 Windows 中运行

为了方便尝试,目前准备简单地在 Windows 上配置使用即可,下载地址为 http://nginx.org/en/docs/windows.html 下载后解压,运行 nginx.exe 或者运行命令行,在解压目录中输入 start nginx 即可运行。
检查 nginx 进程可以使用 tasklist 指令:

tasklist /fi "imagename eq nginx.exe"

映像名称                       PID 会话名              会话#       内存使用
========================= ======== ================ =========== ============
nginx.exe                     6516 Console                    1        444 K
nginx.exe                    33104 Console                    1        820 K

其中一个进程是 master 进程,另外一个是 worker 进程。
另外一些简单命令有:

nginx -s stop   快速停止nginx
nginx -s quit   优雅退出
nginx -s reload 如果改变配置文件,开启新的worker进程以运行新的配置
nginx -s reopen 重新打开log文件

nginx 使用

nginx 常用功能

  • 代理服务器
  • 负载均衡
  • web 缓存

nginx 配置文件结构

./conf/nginx.conf

worker_processes  1;           #全局块
events{                        #events块 
    worker_connections  1024;
}
http                           #http块
{
    include       mime.types;  #http全局块
    default_type  application/octet-stream;
    keepalive_timeout  65;
    server {
        listen       80;       #server全局块
        server_name  localhost;
        location / {           #location块
            root   html;
            index  index.html index.htm;
        }
        location [PATTERN] 
        {
            ...
        }
    }
    server
    {
      ...
    }
}

配置文件参数的详解可以查看 http://tengine.taobao.org/book/chapter_02.html#id6

http://www.nginx.cn/doc/ 中也列出了几个配置文件的例子可以参考:

  • 两个虚拟主机(纯静态-html 支持) - Two Virtual Hosts, Serving Static Files
http {
 server {
   listen          80;
   server_name     www.domain1.com;
   access_log      logs/domain1.access.log main;
   location / {
   index index.html;
   root  /var/www/domain1.com/htdocs;
   }
 }
 server {
   listen          80;
   server_name     www.domain2.com;
   access_log      logs/domain2.access.log main;
   location / {
   index index.html;
   root  /var/www/domain2.com/htdocs;
   }
 }
}

反向代理

原理+实践

反向代理概念

反向代理(Reverse Proxy)方式是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器;并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
通常的代理服务器,只用于代理内部网络对Internet的连接请求,客户机必须指定代理服务器,并将本来要直接发送到Web服务器上的http请求发送到代理服务器中。当一个代理服务器能够代理外部网络上的主机,访问内部网络时,这种代理服务的方式称为反向代理服务。

可以看出,使用反向代理服务器的好处有:

  • 代理服务器可以在安全数据库和可能共计的恶意节点中提供一道屏障,提高系统安全性
  • 可以将用户请求的 http 服务重定向为 https , 提高用户安全性
  • 使得负载均衡功能可以方便应用

反向代理服务器配置

较为基本的反向代理服务器配置相对简单,主要是运用 HttpProxy 模块,下面给出一份基础模板可以参考:

#设定负载均衡的服务器列表
#weigth参数表示权值,权值越高被分配到的几率越大
upstream test{
    server ip0:8080 weight=1;
    server ip1:8080 weight=1;            
}
server {
    #侦听的80端口
    listen       80;
    server_name  localhost;
    location / {
        index index.html;
        proxy_pass   http://test;    #设置代理
        #以下是一些反向代理的配置可删除
        proxy_redirect             off; 
        #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
        proxy_set_header           Host $host; 
        proxy_set_header           X-Real-IP $remote_addr; 
        proxy_set_header           X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_connect_timeout      90; 
        proxy_send_timeout        150; 
        proxy_read_timeout         150; 
        proxy_buffer_size          4k; 
        proxy_buffers              4 32k; 
        proxy_busy_buffers_size    64k; 
        proxy_temp_file_write_size 64k; 
    }
}

反向代理动态服务发现:

了解了反向代理配置后,仍然是无法成功运用在目标系统中,因为目标系统要求服务具有伸缩性,即可以动态增加服务内容,或者增加服务器。因此需要代理服务器也能动态发现服务。
使用etcd+confd管理nginx配置 则是一个可行的尝试, 利用etcd动态发现服务,然后用confd监听etcd的变化,从而改变配置文件。
生成配置的方式为:

通过API将配置写入etcd,confd注册监控etcd的key为/nginx/,只要发生变化就通知 confd 根据模板生成配置。confd 默认的配置路径为 /etc/confd/,创建 conf.d 和 template 两个目录,分别存放配置资源和配置模板。

confd 的安装地址为 https://github.com/kelseyhightower/confd, 看了一下也包含了对 Windows 系统的支持, 但是做的比较粗糙,在 Windows系统中查找配置文件仍然是从 /etc/confd 中寻找:WARNING Cannot load template resources: confdir '/etc/confd' does not exist, 因此还是建议在 Linux 系统下运行。
nginx 的配置模板需要动态写入,因此需要修改(这里只讨论增减服务器):

upstream www_{{getv "/nginx/https/www/server/server_name"}} {
    {{range getvs "/nginx/https/www/upstream/*"}}server {{.}};{{end}}
}

server {
    server_name         {{getv "/nginx/https/www/server/server_name"}}:443;
    location / { 
        proxy_pass        http://www_{{getv "/nginx/https/www/server/server_name"}};
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_redirect    off;
    }   
}

但是目前仍然有问题,就是配置文件生成之后,如何能够动态加载,加载方式有如下几种:

  • dns动态解析:改变dns配置
  • 动态模板解析: 使用jinja2、mako的模板引擎,动态的根据你提供变量渲染配置
  • 服务发现模式:
  1. 前面2个都有比较大的限制,并且需要reload的话,nginx新老配置交替的时候会掉15%左右的qps, 因此频繁reload方式并不建议,服务发现模式有些时候可以不按照reload方式进行:

在github中的不少nginx服务发现的实现,他们不会新开进程,而是在在master进程中注册一个定时器,该事件会触发watch,当发现version的版本号发生变更时,就知道主机列表发生了变化,进而重载配置. 那么如何让worker进程也使用新的配置? 这时候可能不会使用共享变量,因为读写都要加锁,及其影响速度. 所以每个worker都会缓存一份location upstream的配置,每个worker也会有个定时器,他的事件共享内存的upstream有无变化…

  1. 可以基于 Redis 动态路由: 第一次请求时,从 Redis 获取路由地址,放入本地缓存中,并设置有效时间,后续请求直接从本地缓存中获取,如果本地缓存失效,则从 Redis 中请求。
    但没有考虑 redis 数据与本地缓存数据不一致问题。

而且不管如何动态更新,一个关键问题是,nginx 的最小单位是 IP 地址 + 端口, 而目标系统的最小单位是服务。因此相对难以应用。但本次探索不失为一个有价值的尝试。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容