01-02 nignx + Asp.Net WebService Restful Api做负载均衡

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 实现负载均衡示例

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值