nginx简介:
nginx (“engine x”) 是一个高性能的 http 和 反向代理 服务器,也是一个 imap/pop3/smtp 代理服务器 。 nginx 是由 igor sysoev 为俄罗斯访问量第二的rambler.ru 站点开发的,它已经在该站点运行超过四年多了。igor 将源代码以类bsd许可证的形式发布。自nginx 发布四年来,nginx 已经因为它的稳定性、丰富的功能集、 示例配置文件和低系统资源的消耗而闻名了。目前国内各大门户网站已经部署了nginx,如新浪、网易、腾讯等;国内几个重要的视频分享网站也部署了nginx,如六房间、酷6等。 新近发现nginx 技术在国内日趋火热,越来越多的网站开始部署nginx。这边都是网上说的。
nginx安装
nginx是一款轻量级的web 服务器/反向代理服务器及电子邮件(imap/pop3)代理服务器,并在一个bsd-like 协议下发行。由俄罗斯的程序设计师igor sysoev所开发,供俄国大型的入口网站及搜索引擎rambler(俄文:рамблер)使用。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、新浪、网易、腾讯等。
最新版本的nginx版本为1.9.3,我这下载的是window版本的,一般实际场景都是安装在linux系统下的,由于linux系统目前正在摸索中这里就不介绍。官方下载地址:。下载完成之后解压运行nginx.exe就启动了nginx了,启动后会在进程里面看到nginx。
要实现负载均衡需要修改conf/nginx.conf的配置信息,修改配置信息之后重新启动nginx服务,可以通过nginx -s reload指令实现。这里我们使用ants提供的一个批处理来操作。
将nginx.bat文件放到nginx.exe相同文件夹下,直接运行就行了。文章结尾会提供本文用到的所有文件。
站点搭建及配置
1.搭建两个iis站点
站点下只有一个简单的index页面,用来输出当前服务器信息。由于我没有两台机器,所以将两个站点都部署到本机了,分别绑定了8082和9000两个端口。
protected void page_load(object sender, eventargs e) { label0.text = "请求开始时间:"+datetime.now.tostring("yyyy-mm-dd hh:mm:ss"); label1.text = "服务器名称:" + server.machinename;//服务器名称 label2.text = "服务器ip地址:" + request.servervariables["local_addr"];//服务器ip地址 label3.text = "http访问端口:" + request.servervariables["server_port"];//http访问端口" label4.text = ".net解释引擎版本:" + ".net clr" + environment.version.major + "." + environment.version.minor + "." + environment.version.build + "." + environment.version.revision;//.net解释引擎版本 label5.text = "服务器操作系统版本:" + environment.osversion.tostring();//服务器操作系统版本 label6.text = "服务器iis版本:" + request.servervariables["server_software"];//服务器iis版本 label7.text = "服务器域名:" + request.servervariables["server_name"];//服务器域名 label8.text = "虚拟目录的绝对路径:" + request.servervariables["appl_rhysical_path"];//虚拟目录的绝对路径 label9.text = "执行文件的绝对路径:" + request.servervariables["path_translated"];//执行文件的绝对路径 label10.text = "虚拟目录session总数:" + session.contents.count.tostring();//虚拟目录session总数 label11.text = "虚拟目录application总数:" + application.contents.count.tostring();//虚拟目录application总数 label12.text = "域名主机:" + request.servervariables["http_host"];//域名主机 label13.text = "服务器区域语言:" + request.servervariables["http_accept_language"];//服务器区域语言 label14.text = "用户信息:" + request.servervariables["http_user_agent"]; label14.text = "cpu个数:" + environment.getenvironmentvariable("number_of_processors");//cpu个数 label15.text = "cpu类型:" + environment.getenvironmentvariable("processor_identifier");//cpu类型 label16.text = "请求来源地址:" + request.headers["x-real-ip"]; }
2.修改nginx配置信息
修改nginx监听端口,修改http server下的listen节点值,由于本机80端口已经被占用,我改为监听8083端口。
listen 8083;
在http节点下添加upstream(服务器集群),server设置的是集群服务器的信息,我这里搭建了两个站点,配置了两条信息。
#服务器集群名称为jq_one upstream jq_one { server 127.0.0.1:9000; server 127.0.0.1:8082; }
在http节点下找到location节点修改
location / { root html; index index.aspx index.html index.htm; #修改主页为index.aspx #其中jq_one对应着upstream设置的集群名称 proxy_pass http://jq_one; #设置主机头和客户端真实地址,以便服务器获取客户端真实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; }
修改完成配置文件以后记得重启nginx服务,最终完整配置文件信息如下
3.运行结果
访问http://127.0.0.1:8083/index.aspx ,多访问几次,着重关注标红部分。
可以看到,我们的请求被分发到了8082站点和9000站点,并且第一次是8082站点第二次9000。出现这样的结果证明我们负载均衡搭建成功了。尝试关闭其中的9000站点,然后刷新页面发现输出的http端口一直是8082,也就是说其中一个站点挂了,只要还有一个站点是好的,我们的还是可以服务。
问题分析
虽然我们搭建好了负载均衡站点,但是还存在以下问题。
1.如果站点使用了session,请求平均分配到两个站点,那么必然存在session共享问题,该如何解决?
使用数据库保存session信息使用nginx将同一ip的请求分配到固定服务器,修改如下。ip_hash会计算ip对应hash值,然后分配到固定服务器
upstream jq_one{
server 127.0.0.1:8082 ;
server 127.0.0.1:9000 ;
ip_hash;
}
搭建一台redis服务器,对session的读取都从该redis服务器上读取。后面的文章将介绍分布式缓存redis的使用
2.管理员更新站点文件,该怎么操作,现在还只有两台服务器,可以手工将文件更新到两台服务器,如果是10台呢,那么手工操作必然是不可行的
多服务器站点更新可以使用goodsync 文件同步程序,会自动检测文件的修改新增,然后同步到其它服务器上。在linux下可以使用rsync
3.站点中的文件上传功能会将文件分配到不同的服务器,文件共享问题如何解决。
使用文件服务器将所有文件存储到该服务器上,文件操作读取写入都在该服务器上。这里同样会存在一个问题,文件服务器存在读写上限。
4.负载的服务器配置不一样,有的高有的低可不可以让配置高的服务器处理请求多一些
这里讲一下,负载均衡有好几种算法 轮转法,散列法,最少连接法,最低缺失法,最快响应法,加权法。我们这里可以使用加权法来分配请求。
upstream jq_one{
server 127.0.0.1:8082 weight=4;
server 127.0.0.1:9000 weight=1;
}
通过weight设置每台服务器分配请求站的权重,值越高分配的越多。
5.由于请求是经过nginx转发过来的,可以在代码里面获取到用户请求的实际ip地址吗?
答案是肯定的,在localtion节点设置如下请求头信息
#设置主机头和客户端真实地址,以便服务器获取客户端真实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;
代码里面通过request.headers["x-real-ip"],就能获取到真实ip