解决Nginx同网段ip_hash负载均衡无效果

问题

Nginx ip_hash在局域网中所有机器访问的都是同一台机器没有Hash。造成原因如被Hash的Ip为192.168.1.100;实则上Nginx进行Hash算法时取的是192.168.1所以在局域网同网段所有机器得到的结果服务器都是同一台

解决

修改Nginx目录源码:nginx-1.18.0\src\http\modules\ngx_http_upstream_ip_hash_module.c;

将源码修改为通过全IP进行hash

修改点主要入下:

/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */


#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>


typedef struct {
    /* the round robin data must be first */
    ngx_http_upstream_rr_peer_data_t   rrp;

    ngx_uint_t                         hash;

    u_char                             addrlen;
    u_char                            *addr;

    u_char                             tries;

    ngx_event_get_peer_pt              get_rr_peer;
} ngx_http_upstream_ip_hash_peer_data_t;


static ngx_int_t ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r,
    ngx_http_upstream_srv_conf_t *us);
static ngx_int_t ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc,
    void *data);
static char *ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd,
    void *conf);


static ngx_command_t  ngx_http_upstream_ip_hash_commands[] = {

    { ngx_string("ip_hash"),
      NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
      ngx_http_upstream_ip_hash,
      0,
      0,
      NULL },

      ngx_null_command
};


static ngx_http_module_t  ngx_http_upstream_ip_hash_module_ctx = {
    NULL,                                  /* preconfiguration */
    NULL,                                  /* postconfiguration */

    NULL,                                  /* create main configuration */
    NULL,                                  /* init main configuration */

    NULL,                                  /* create server configuration */
    NULL,                                  /* merge server configuration */

    NULL,                                  /* create location configuration */
    NULL                                   /* merge location configuration */
};


ngx_module_t  ngx_http_upstream_ip_hash_module = {
    NGX_MODULE_V1,
    &ngx_http_upstream_ip_hash_module_ctx, /* module context */
    ngx_http_upstream_ip_hash_commands,    /* module directives */
    NGX_HTTP_MODULE,                       /* module type */
    NULL,                                  /* init master */
    NULL,                                  /* init module */
    NULL,                                  /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    NULL,                                  /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};

/* 修改点1,次数由3修改为4 */
static u_char ngx_http_upstream_ip_hash_pseudo_addr[4];


static ngx_int_t
ngx_http_upstream_init_ip_hash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us)
{
    if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) {
        return NGX_ERROR;
    }

    us->peer.init = ngx_http_upstream_init_ip_hash_peer;

    return NGX_OK;
}


static ngx_int_t
ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r,
    ngx_http_upstream_srv_conf_t *us)
{
    struct sockaddr_in                     *sin;
#if (NGX_HAVE_INET6)
    struct sockaddr_in6                    *sin6;
#endif
    ngx_http_upstream_ip_hash_peer_data_t  *iphp;

    iphp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_ip_hash_peer_data_t));
    if (iphp == NULL) {
        return NGX_ERROR;
    }

    r->upstream->peer.data = &iphp->rrp;

    if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) {
        return NGX_ERROR;
    }

    r->upstream->peer.get = ngx_http_upstream_get_ip_hash_peer;

    switch (r->connection->sockaddr->sa_family) {

    case AF_INET:
        sin = (struct sockaddr_in *) r->connection->sockaddr;
        iphp->addr = (u_char *) &sin->sin_addr.s_addr;
        iphp->addrlen = 4; /* 修改点2,次数由3修改为4 */
        break;

#if (NGX_HAVE_INET6)
    case AF_INET6:
        sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
        iphp->addr = (u_char *) &sin6->sin6_addr.s6_addr;
        iphp->addrlen = 16;
        break;
#endif

    default:
        iphp->addr = ngx_http_upstream_ip_hash_pseudo_addr;
        iphp->addrlen = 4;  /* 修改点2,次数由3修改为4 */
    }

    iphp->hash = 89;
    iphp->tries = 0;
    iphp->get_rr_peer = ngx_http_upstream_get_round_robin_peer;

    return NGX_OK;
}

Nignx配置文件:

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    #gzip  on;
    upstream  testcluster { 
	  ip_hash; 
	  server   127.0.0.1:11001;
	  server   127.0.0.1:11002;
	  server   127.0.0.1:11003;
	}
	
    server {
        listen       80;
        server_name  localhost;
        location / {
	  	  # 代理请求头
	  	  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_buffering off;
	  	  proxy_pass http://testcluster;
	   }
    }

}
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
`ip_hash`是Nginx的一种负载均衡算法,它基于客户端的IP地址来确定将请求转发给哪个后端服务器。使用`ip_hash`算法,相同IP地址的客户端将始终被分配到同一个后端服务器,这有助于保持会话的一致性。 要配置Nginx使用`ip_hash`算法进行负载均衡,可以按照以下步骤进行: 1. 打开Nginx的配置文件。通常在Linux系统中,配置文件位于`/etc/nginx/nginx.conf`或`/etc/nginx/conf.d/default.conf`。 2. 在`http`块内添加一个`upstream`块,定义要进行负载均衡的服务器列表。示例代码如下: ```nginx http { upstream backend { ip_hash; server backend1.example.com; server backend2.example.com; server backend3.example.com; } ... } ``` 在上面的示例中,我们使用`ip_hash`指令在`upstream`块中启用了IP哈希负载均衡算法,并列出了要进行负载均衡的服务器。 3. 在Nginx的配置文件中,找到你要使用负载均衡的位置(如`location`块),并将其代理到上面定义的`backend`服务器组。示例代码如下: ```nginx http { upstream backend { ip_hash; server backend1.example.com; server backend2.example.com; server backend3.example.com; } server { ... location / { proxy_pass http://backend; } ... } } ``` 在上面的示例中,我们使用`proxy_pass`将请求代理到名为`backend`的服务器组。 4. 保存配置文件并重新加载Nginx配置。在终端中执行以下命令: ```shell sudo nginx -t # 检查配置文件语法是否正确 sudo systemctl reload nginx # 重新加载Nginx配置 ``` 这样配置后,Nginx将使用`ip_hash`算法将请求分发给后端服务器。相同IP地址的客户端将被分配到同一个后端服务器上,从而保持会话的一致性。 请注意,`ip_hash`算法适用于基于客户端IP地址的负载均衡,并且要求Nginx编译时启用了`--with-http_upstream_ip_hash_module`模块。确保你的Nginx版本支持此功能。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值