1、nginx负载均衡的几种配置方式
(1)轮询(默认方式)
nginx将所有请求按照时序分发到下游服务器,如果下游服务器挂了,自会自动剔除,每台下游服务器访问的记录是一样的
worker_processes 2; //工作进程的个数
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream webservice { #配置集群,语法为: upstream [集群名称]
server 127.0.0.1:5004; # 配置下游服务器,语法: 下游服务器ip:port
server 127.0.0.1:5005; # 配置下游服务器,语法: 下游服务器ip:port
}
server {
listen 8096; # 监听端口,可以理解为nginx端口,一旦启动nginx就不要轻易动这配置
server_name localhost; # nginx服务器名
location / {
proxy_pass http://webservice; #请求转向backend定义的服务器列表,即反向代理,对应upstream负载均衡器,语法: http://[(上面配置的)集群名称] 或者 http://ip:port
proxy_redirect default;
}
}
}
(2)权重
指定轮询几率,weight和访问比率成正比,通常用于下游服务器性能不同的场景,这里只修改集群定义部分,其他部分配置不变。
# 像下面配置指定 5004 访问的几率更大
upstream webservice {
server 127.0.0.1:5004 weight=2; #访问机率为20%
server 127.0.0.1:5005 weight=8; #访问机率为80%
}
(3)ip_hash
上述方式存在一个问题就是说,在负载均衡系统中,假如用户在某台服务器上登录了,那么该用户第二次请求的时候,因为我们是负载均衡系统,每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,因此将
每个请求都根据访问ip的hash结果分配,经过这样的处理,每个访客固定访问一个后端服务,如下配置
upstream webservice {
ip_hash;
server 127.0.0.1:5004;
server 127.0.0.1:5005;
}
ip_hash还可以与权重(weight)搭配使用
upstream webservice {
ip_hash;
server 127.0.0.1:5004 weight=2;
server 127.0.0.1:5005 weight=8;
}
(4)最少连接(least_conn)
将请求分配当前最空闲的服务器上,即分配到当前连接数最少的服务器上。
upstream webservice {
least_conn;
server 127.0.0.1:5004;
server 127.0.0.1:5005;
}
也可以搭配权重使用
upstream webservice {
least_conn;
server 127.0.0.1:5004 weight=2;
server 127.0.0.1:5005 weight=8;
}
(5)fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream webservice {
fair;
server 127.0.0.1:5004;
server 127.0.0.1:5005;
}
也可以搭配权重使用
upstream webservice {
fair;
server 127.0.0.1:5004 weight=2;
server 127.0.0.1:5005 weight=8;
}
(6)url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
即同一个url(也就是同一个资源请求)会到达同一台机器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取,这样可以节省资源。
upstream webservice {
hash $request_uri;
server 127.0.0.1:5004;
server 127.0.0.1:5005;
}
也可以搭配权重使用
upstream webservice {
hash $request_uri;
server 127.0.0.1:5004 weight=2;
server 127.0.0.1:5005 weight=8;
}
每个设备的状态设置为:
down
表示单前的server暂时不参与负载;weight
默认为1,weight
越大,负载的权重就越大;max_fails
:允许请求失败的次数默认为1,当超过最大次数时,返回proxy_next_upstream
模块定义的错误fail_timeout:max_fails
次失败后,暂停的时间;backup
: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
2、搭建asp.net Web项目
(1)先创建两个asp.net Web应用程序 WebSite1和WebSite2,代码结构如图(两个结构一样)
(2)然后分别编写一个WebService Restful Api,代码如下
Website1:
<1>新建一个REST文件夹,添加一个GetUserInfoService 类,代码如下
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
namespace WebSite1.REST
{
#region 实现
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single, IncludeExceptionDetailInFaults = true)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class GetUserInfoService : IGetUserInfoService
{
public string GetName()
{
return "张三";
}
}
#endregion
#region rest api 接口
[ServiceContract(Name = "GetUserInfoService")]
public interface IGetUserInfoService
{
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "/GetName", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
string GetName();
}
#endregion
}
<2>Global.asax.cs 文件中的Application_Start方法中注册刚才定义的api(路由),代码如下:
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add(new ServiceRoute("REST/GetUserInfoService", new WebServiceHostFactory(), typeof(GetUserInfoService)));
RegisterRoutes();
}
<3>为了防止出现路由不兼容,在web.config中的根节点下添加以下配置
<!--
在 Internet 信息服务 7.0 下运行 ASP.NET AJAX 需要 system.webServer
节。对早期版本的 IIS 来说则不需要此节。
-->
<system.serviceModel>
<bindings />
<client />
<!--路由集成功能兼容-->
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
WebSite2:
<1>新建一个REST文件夹,添加一个GetDataService 类,代码如下
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
namespace WebSite2.REST
{
#region 实现
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single, IncludeExceptionDetailInFaults = true)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class GetDataService : IGetDataService
{
public string GetData()
{
return "Succcess! Data from database";
}
}
#endregion
#region rest api 接口
[ServiceContract(Name = "GetDataService")]
public interface IGetDataService
{
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "/GetData", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
string GetData();
}
#endregion
}
<2>Global.asax.cs 文件中的Application_Start方法中注册刚才定义的api(路由),代码如下:
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add(new ServiceRoute("REST/GetDataService", new WebServiceHostFactory(), typeof(GetDataService)));
RegisterRoutes();
}
<3>为了防止出现路由不兼容,在web.config中的根节点下添加以下配置
<!--
在 Internet 信息服务 7.0 下运行 ASP.NET AJAX 需要 system.webServer
节。对早期版本的 IIS 来说则不需要此节。
-->
<system.serviceModel>
<bindings />
<client />
<!--路由集成功能兼容-->
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
最后两个项目的default.aspx页面分别写点东西区分一下,这里就不贴代码了。
(4)将代码部署到IIS或者发布到IIS,我习惯直接将源码部署到IIS,具体步骤不再赘述
访问两个站点,确认这可以正常访问
3、配置nginx负载均衡,我选择轮询方式
(1)下载安装nginx,修改conf文件夹中的nginx.conf文件(修改前先备份),我这里贴出完整配置
#user nobody;
worker_processes 2;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
upstream ytest {
server 127.0.0.1:5004;
server 127.0.0.1:5005;
}
server {
listen 8096;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
#location / {
#root D:/workspace/publish/webSite2;
#index index.html;
#}
location / {
proxy_pass http://ytest;
proxy_redirect default;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
#error_page 500 502 503 504 /50x.html;
#location = /50x.html {
# root html;
#}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
(3)启动nginx,在ngin.exe目录下按住shit并点击鼠标右键,打开poershell,输入start nginx
命令启动,启动成功后可以在任务管理器中看到任务进程。
PS:为了防止报以下错误,请先启动一个powershell输入nginx -c conf/nginx.conf,回车,然后再新打开一个powershell输入start nginx
命令
(4)访问localhost:8096,即下图配置的(nginx)服务
效果:默认访问的是default.aspx页面
我们测试以下webservice 的 rest api,看效果
访问api的时候就很明显能感到轮询的效果,同一个api在两台服务器之间轮询,在website1上能找到,在website2上就是404,另一个api也是如此。
参考文章
【Nginx】实现负载均衡的几种方式
Nginx实现负载均衡
Nginx+IIS+asp.net mvc 实现负载均衡示例