Skip to content

Commit aa81aa5

Browse files
committed
Merge branch 'up_master'
2 parents 7ea812c + d97f37d commit aa81aa5

File tree

9 files changed

+324
-67
lines changed

9 files changed

+324
-67
lines changed

.travis.yml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,52 @@ addons:
2121
- liburi-perl
2222
- libwww-perl
2323
- perl
24+
- valgrind
2425

2526
cache:
2627
directories:
2728
- download-cache
2829

2930
env:
3031
global:
31-
- JOBS=2
32-
- OPENRESTY_PREFIX=/usr/local/openresty
33-
- OPENRESTY_VER=1.11.2.3
32+
- JOBS=2
33+
- OPENRESTY_PREFIX=/usr/local/openresty
34+
- OPENRESTY_VER=1.19.9.1
35+
jobs:
36+
- TEST_NGINX_USE_VALGRIND=0
37+
- TEST_NGINX_USE_VALGRIND=1
3438

3539
install:
3640
- if [ ! -f download-cache/openresty-$OPENRESTY_VER.tar.gz ]; then
3741
wget -P download-cache https://openresty.org/download/openresty-$OPENRESTY_VER.tar.gz;
3842
fi
3943
- git clone https://github.com/openresty/test-nginx.git ../test-nginx
4044

45+
# install openresty-openssl111-dev
46+
- sudo apt-get -y install --no-install-recommends wget gnupg ca-certificates
47+
- wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -
48+
- echo "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main"
49+
| sudo tee /etc/apt/sources.list.d/openresty.list
50+
- sudo apt-get update || echo 'apt-get update failed, but ignore it'
51+
- sudo apt-get -y install --no-install-recommends openresty-openssl111 openresty-openssl111-dev
52+
4153
script:
54+
- if [ TEST_NGINX_USE_VALGRIND = 1 ]; then export luajit_xcflags='-DLUAJIT_USE_VALGRIND -DLUAJIT_USE_SYSMALLOC'; fi
4255
- tar xzf download-cache/openresty-$OPENRESTY_VER.tar.gz &&
4356
cd openresty-$OPENRESTY_VER
44-
- ./configure --prefix=$OPENRESTY_PREFIX -j$JOBS
45-
> build.log 2>&1 || (cat build.log && exit 1)
57+
- ./configure --prefix=$OPENRESTY_PREFIX
58+
--with-cc-opt="-I/usr/local/openresty/openssl111/include"
59+
--with-ld-opt="-L/usr/local/openresty/openssl111/lib -Wl,-rpath,/usr/local/openresty/openssl111/lib"
60+
--with-luajit-xcflags="$luajit_xcflags"
61+
-j$JOBS
62+
> build.log 2>&1 || (cat build.log && exit 1)
4663
- make -j$JOBS > build.log 2>&1 ||
4764
(cat build.log && exit 1)
4865
- sudo make install > build.log 2>&1 ||
4966
(cat build.log && exit 1)
5067
- cd ..
5168
- export PATH=$OPENRESTY_PREFIX/nginx/sbin:$PATH
52-
- make test jobs=$JOBS
69+
- make test jobs=$JOBS > build.log 2>&1 ||
70+
(cat build.log && exit 1)
71+
- cat build.log
72+
- if [ `grep -c '== Invalid' build.log` -gt 0 ]; then echo 'valgrind complaining' && exit 1; fi

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ LDFLAGS := -shared
1818
# on Mac OS X, one should set instead:
1919
# LDFLAGS := -bundle -undefined dynamic_lookup
2020

21+
ifeq ($(shell uname),Darwin)
22+
LDFLAGS := -bundle -undefined dynamic_lookup
23+
C_SO_NAME := librestychash.dylib
24+
endif
25+
2126
MY_CFLAGS := $(CFLAGS) -DBUILDING_SO
2227
MY_LDFLAGS := $(LDFLAGS) -fvisibility=hidden
2328

@@ -39,7 +44,9 @@ clean:; rm -f *.o *.so a.out *.d
3944

4045
install:
4146
$(INSTALL) -d $(DESTDIR)$(LUA_LIB_DIR)/resty
47+
$(INSTALL) -d $(DESTDIR)$(LUA_LIB_DIR)/resty/balancer
4248
$(INSTALL) lib/resty/*.lua $(DESTDIR)$(LUA_LIB_DIR)/resty
49+
$(INSTALL) lib/resty/balancer/*.lua $(DESTDIR)$(LUA_LIB_DIR)/resty/balancer
4350
$(INSTALL) $(C_SO_NAME) $(DESTDIR)$(LUA_LIB_DIR)/
4451

4552
test : all

README.markdown

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ Synopsis
101101

102102
local rr_up = package.loaded.my_rr_up
103103

104+
-- Note that Round Robin picks the first server randomly
104105
local server = rr_up:find()
105106

106107
assert(b.set_current_peer(server))
@@ -137,6 +138,7 @@ The `id` should be `table.concat({host, string.char(0), port})` like the nginx c
137138
when we need to keep consistency with nginx chash.
138139

139140
The `id` can be any string value when we do not need to keep consistency with nginx chash.
141+
The `weight` should be a non negative integer.
140142

141143
```lua
142144
local nodes = {

chash.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include <stdio.h>
22
#include <stdlib.h>
33
#include <math.h>
4+
#include <assert.h>
5+
46
#include "chash.h"
57

68

@@ -164,7 +166,9 @@ chash_point_sort(chash_point_t arr[], uint32_t n)
164166

165167
for (i = 0; i < n; i++) {
166168
node = &arr[i];
167-
index = node->hash / step; // can not bigger than m
169+
index = node->hash / step;
170+
171+
assert(index < m); // index must less than m
168172

169173
for (end = index; end >= 0; end--) {
170174
if (points[end].id == 0) {
@@ -188,7 +192,10 @@ chash_point_sort(chash_point_t arr[], uint32_t n)
188192

189193
/* left shift after end when node->hash is bigger than them */
190194
/* only end == index can match this */
191-
while (points[end + 1].id != 0 && points[end + 1].hash < node->hash) {
195+
while (end + 1 < m
196+
&& points[end + 1].id != 0
197+
&& points[end + 1].hash < node->hash)
198+
{
192199
points[end].hash = points[end + 1].hash;
193200
points[end].id = points[end + 1].id;
194201
end += 1;
@@ -223,6 +230,8 @@ chash_point_sort(chash_point_t arr[], uint32_t n)
223230
}
224231

225232
insert:
233+
assert(end < m && end >= 0);
234+
226235
points[end].id = node->id;
227236
points[end].hash = node->hash;
228237
}

lib/resty/balancer/utils.lua

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
local _M = {}
2+
3+
_M.name = "balancer-utils"
4+
_M.version = "0.03"
5+
6+
local new_tab
7+
do
8+
local ok
9+
ok, new_tab = pcall(require, "table.new")
10+
if not ok or type(new_tab) ~= "function" then
11+
new_tab = function (narr, nrec) return {} end
12+
end
13+
end
14+
_M.new_tab = new_tab
15+
16+
17+
local nkeys, tab_nkeys
18+
do
19+
local ok
20+
ok, nkeys = pcall(require, "table.nkeys")
21+
if not ok or type(nkeys) ~= "function" then
22+
nkeys = function(tab)
23+
local count = 0
24+
for _, _ in pairs(tab) do
25+
count = count + 1
26+
end
27+
return count
28+
end
29+
30+
else
31+
tab_nkeys = nkeys
32+
end
33+
end
34+
_M.nkeys = nkeys
35+
36+
37+
function _M.copy(nodes)
38+
local newnodes = new_tab(0, tab_nkeys and tab_nkeys(nodes) or 4)
39+
for id, weight in pairs(nodes) do
40+
newnodes[id] = tonumber(weight)
41+
end
42+
43+
return newnodes
44+
end
45+
46+
47+
return _M

lib/resty/chash.lua

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
local bit = require "bit"
66
local ffi = require 'ffi'
77

8+
local utils = require "resty.balancer.utils"
9+
10+
local new_tab = utils.new_tab
11+
local copy = utils.copy
812

913
local ffi_new = ffi.new
1014
local C = ffi.C
@@ -38,13 +42,6 @@ void chash_point_delete(chash_point_t *old_points, uint32_t old_length,
3842
uint32_t id);
3943
]]
4044

41-
42-
local ok, new_tab = pcall(require, "table.new")
43-
if not ok or type(new_tab) ~= "function" then
44-
new_tab = function (narr, nrec) return {} end
45-
end
46-
47-
4845
--
4946
-- Find shared object file package.cpath, obviating the need of setting
5047
-- LD_LIBRARY_PATH
@@ -58,6 +55,12 @@ local function load_shared_lib(so_name)
5855

5956
local cpath = package.cpath
6057

58+
local postfix = ".so"
59+
if ffi.os == "OSX" then
60+
postfix = ".dylib"
61+
end
62+
so_name = so_name .. postfix
63+
6164
for k, _ in string_gmatch(cpath, "[^;]+") do
6265
local fpath = string_match(k, "(.*/)")
6366
fpath = fpath .. so_name
@@ -77,9 +80,9 @@ local _M = {}
7780
local mt = { __index = _M }
7881

7982

80-
local clib = load_shared_lib("librestychash.so")
83+
local clib = load_shared_lib("librestychash")
8184
if not clib then
82-
error("can not load librestychash.so")
85+
error("can not load librestychash")
8386
end
8487

8588
local CONSISTENT_POINTS = 160 -- points per server
@@ -95,10 +98,7 @@ local function _precompute(nodes)
9598
total_weight = total_weight + weight
9699
end
97100

98-
local newnodes = new_tab(0, n)
99-
for id, weight in pairs(nodes) do
100-
newnodes[id] = weight
101-
end
101+
local newnodes = copy(nodes)
102102

103103
local ids = new_tab(n, 0)
104104
local npoints = total_weight * CONSISTENT_POINTS

lib/resty/roundrobin.lua

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,17 @@ local pairs = pairs
33
local next = next
44
local tonumber = tonumber
55
local setmetatable = setmetatable
6+
local math_random = math.random
67

8+
local utils = require "resty.balancer.utils"
9+
10+
local copy = utils.copy
11+
local nkeys = utils.nkeys
12+
local new_tab = utils.new_tab
713

814
local _M = {}
915
local mt = { __index = _M }
1016

11-
12-
local function copy(nodes)
13-
local newnodes = {}
14-
for id, weight in pairs(nodes) do
15-
newnodes[id] = weight
16-
end
17-
18-
return newnodes
19-
end
20-
21-
2217
local _gcd
2318
_gcd = function (a, b)
2419
if b == 0 then
@@ -46,18 +41,32 @@ local function get_gcd(nodes)
4641
return only_key, gcd, max_weight
4742
end
4843

44+
local function get_random_node_id(nodes)
45+
local count = nkeys(nodes)
46+
47+
local id = nil
48+
local random_index = math_random(count)
49+
50+
for _ = 1, random_index do
51+
id = next(nodes, id)
52+
end
53+
54+
return id
55+
end
56+
4957

5058
function _M.new(_, nodes)
5159
local newnodes = copy(nodes)
5260
local only_key, gcd, max_weight = get_gcd(newnodes)
61+
local last_id = get_random_node_id(nodes)
5362

5463
local self = {
5564
nodes = newnodes, -- it's safer to copy one
5665
only_key = only_key,
5766
max_weight = max_weight,
5867
gcd = gcd,
5968
cw = max_weight,
60-
last_id = nil,
69+
last_id = last_id,
6170
}
6271
return setmetatable(self, mt)
6372
end
@@ -68,7 +77,7 @@ function _M.reinit(self, nodes)
6877
self.only_key, self.gcd, self.max_weight = get_gcd(newnodes)
6978

7079
self.nodes = newnodes
71-
self.last_id = nil
80+
self.last_id = get_random_node_id(nodes)
7281
self.cw = self.max_weight
7382
end
7483

0 commit comments

Comments
 (0)