解决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

修改点主要入下:

Copy
/* * 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配置文件:

Copy
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; } } }
posted @   日落西风又在吹  阅读(550)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
CONTENTS

"当前未开放哦"