Skip to content

Commit e07f24c

Browse files
membphisSaberMaster
authored andcommitted
optimize: Use lru to avoid resolving IP addresses repeatedly . (apache#1772)
* optimize: Use lru to avoid resolving IP addresses repeatedly . Cached the global rules to `ctx` . * optimzie: used a longer time interval for etcd and flush access log. * optimize: return upstream node directly if the count is 1 . * optimize: avoid to cache useless variable.
1 parent 6376f83 commit e07f24c

File tree

8 files changed

+117
-43
lines changed

8 files changed

+117
-43
lines changed

apisix/balancer.lua

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ local lrucache_server_picker = core.lrucache.new({
3939
local lrucache_checker = core.lrucache.new({
4040
ttl = 300, count = 256
4141
})
42+
local lrucache_addr = core.lrucache.new({
43+
ttl = 300, count = 1024 * 4
44+
})
4245

4346

4447
local _M = {
@@ -143,25 +146,47 @@ local function create_server_picker(upstream, checker)
143146
end
144147

145148

149+
local function parse_addr(addr)
150+
local host, port, err = core.utils.parse_addr(addr)
151+
return {host = host, port = port}, err
152+
end
153+
154+
146155
local function pick_server(route, ctx)
147156
core.log.info("route: ", core.json.delay_encode(route, true))
148157
core.log.info("ctx: ", core.json.delay_encode(ctx, true))
149-
local healthcheck_parent = ctx.upstream_healthcheck_parent
150158
local up_conf = ctx.upstream_conf
151-
local version = ctx.upstream_version
152-
local key = ctx.upstream_key
153-
154159
if up_conf.service_name then
155160
if not discovery then
156-
return nil, nil, "discovery is uninitialized"
161+
return nil, "discovery is uninitialized"
157162
end
158163
up_conf.nodes = discovery.nodes(up_conf.service_name)
159164
end
160165

161-
if not up_conf.nodes or #up_conf.nodes == 0 then
162-
return nil, nil, "no valid upstream node"
166+
local nodes_count = up_conf.nodes and #up_conf.nodes or 0
167+
if nodes_count == 0 then
168+
return nil, "no valid upstream node"
169+
end
170+
171+
if up_conf.timeout then
172+
local timeout = up_conf.timeout
173+
local ok, err = set_timeouts(timeout.connect, timeout.send,
174+
timeout.read)
175+
if not ok then
176+
core.log.error("could not set upstream timeouts: ", err)
177+
end
163178
end
164179

180+
if nodes_count == 1 then
181+
local node = up_conf.nodes[1]
182+
ctx.balancer_ip = node.host
183+
ctx.balancer_port = node.port
184+
return node
185+
end
186+
187+
local healthcheck_parent = ctx.upstream_healthcheck_parent
188+
local version = ctx.upstream_version
189+
local key = ctx.upstream_key
165190
local checker = fetch_healthchecker(up_conf, healthcheck_parent, version)
166191

167192
ctx.balancer_try_count = (ctx.balancer_try_count or 0) + 1
@@ -197,28 +222,25 @@ local function pick_server(route, ctx)
197222
local server_picker = lrucache_server_picker(key, version,
198223
create_server_picker, up_conf, checker)
199224
if not server_picker then
200-
return nil, nil, "failed to fetch server picker"
225+
return nil, "failed to fetch server picker"
201226
end
202227

203228
local server, err = server_picker.get(ctx)
204229
if not server then
205230
err = err or "no valid upstream node"
206-
return nil, nil, "failed to find valid upstream server, " .. err
231+
return nil, "failed to find valid upstream server, " .. err
207232
end
208233

209-
if up_conf.timeout then
210-
local timeout = up_conf.timeout
211-
local ok, err = set_timeouts(timeout.connect, timeout.send, timeout.read)
212-
if not ok then
213-
core.log.error("could not set upstream timeouts: ", err)
214-
end
234+
local res, err = lrucache_addr(server, nil, parse_addr, server)
235+
ctx.balancer_ip = res.host
236+
ctx.balancer_port = res.port
237+
-- core.log.info("proxy to ", host, ":", port)
238+
if err then
239+
core.log.error("failed to parse server addr: ", server, " err: ", err)
240+
return core.response.exit(502)
215241
end
216242

217-
local ip, port, err = core.utils.parse_addr(server)
218-
ctx.balancer_ip = ip
219-
ctx.balancer_port = port
220-
core.log.info("proxy to ", ip, ":", port)
221-
return ip, port, err
243+
return res
222244
end
223245

224246

@@ -227,16 +249,16 @@ _M.pick_server = pick_server
227249

228250

229251
function _M.run(route, ctx)
230-
local ip, port, err = pick_server(route, ctx)
231-
if err then
252+
local server, err = pick_server(route, ctx)
253+
if not server then
232254
core.log.error("failed to pick server: ", err)
233255
return core.response.exit(502)
234256
end
235257

236-
local ok, err = balancer.set_current_peer(ip, port)
258+
local ok, err = balancer.set_current_peer(server.host, server.port)
237259
if not ok then
238-
core.log.error("failed to set server peer [", ip, ":", port,
239-
"] err: ", err)
260+
core.log.error("failed to set server peer [", server.host, ":",
261+
server.port, "] err: ", err)
240262
return core.response.exit(502)
241263
end
242264

apisix/init.lua

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ local function run_plugin(phase, plugins, api_ctx)
112112
end
113113

114114
plugins = plugins or api_ctx.plugins
115-
if not plugins then
115+
if not plugins or #plugins == 0 then
116116
return api_ctx
117117
end
118118

@@ -262,6 +262,8 @@ function _M.http_access_phase()
262262
api_ctx.conf_type = nil
263263
api_ctx.conf_version = nil
264264
api_ctx.conf_id = nil
265+
266+
api_ctx.global_rules = router.global_rules
265267
end
266268

267269
router.router_http.match(api_ctx)
@@ -433,25 +435,24 @@ function _M.grpc_access_phase()
433435
end
434436

435437

436-
local function common_phase(plugin_name)
438+
local function common_phase(phase_name)
437439
local api_ctx = ngx.ctx.api_ctx
438440
if not api_ctx then
439441
return
440442
end
441443

442-
if router.global_rules and router.global_rules.values
443-
and #router.global_rules.values > 0
444-
then
444+
if api_ctx.global_rules then
445445
local plugins = core.tablepool.fetch("plugins", 32, 0)
446-
local values = router.global_rules.values
446+
local values = api_ctx.global_rules.values
447447
for _, global_rule in config_util.iterate_values(values) do
448448
core.table.clear(plugins)
449449
plugins = plugin.filter(global_rule, plugins)
450-
run_plugin(plugin_name, plugins, api_ctx)
450+
run_plugin(phase_name, plugins, api_ctx)
451451
end
452452
core.tablepool.release("plugins", plugins)
453453
end
454-
run_plugin(plugin_name, nil, api_ctx)
454+
455+
run_plugin(phase_name, nil, api_ctx)
455456
return api_ctx
456457
end
457458

apisix/plugin.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ end
235235
function _M.filter(user_route, plugins)
236236
plugins = plugins or core.table.new(#local_plugins * 2, 0)
237237
local user_plugin_conf = user_route.value.plugins
238-
if user_plugin_conf == nil then
238+
if user_plugin_conf == nil or
239+
core.table.nkeys(user_plugin_conf) == 0 then
239240
if local_conf and local_conf.apisix.enable_debug then
240241
core.response.set_header("Apisix-Plugins", "no plugin")
241242
end

benchmark/fake-apisix/conf/nginx.conf

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ pid logs/nginx.pid;
2424
worker_rlimit_nofile 20480;
2525

2626
events {
27-
accept_mutex off;
2827
worker_connections 10620;
2928
}
3029

@@ -33,6 +32,9 @@ worker_shutdown_timeout 3;
3332
http {
3433
lua_package_path "$prefix/lua/?.lua;;";
3534

35+
log_format main '$remote_addr - $remote_user [$time_local] $http_host "$request" $status $body_bytes_sent $request_time "$http_referer" "$http_user_agent" $upstream_addr $upstream_status $upstream_response_time';
36+
access_log logs/access.log main buffer=16384 flush=5;
37+
3638
init_by_lua_block {
3739
require "resty.core"
3840
apisix = require("apisix")
@@ -60,8 +62,6 @@ http {
6062

6163
listen 9080;
6264

63-
access_log off;
64-
6565
server_tokens off;
6666
more_set_headers 'Server: APISIX web server';
6767

@@ -106,6 +106,10 @@ http {
106106
apisix.http_header_filter_phase()
107107
}
108108

109+
body_filter_by_lua_block {
110+
apisix.http_body_filter_phase()
111+
}
112+
109113
log_by_lua_block {
110114
apisix.http_log_phase()
111115
}

benchmark/fake-apisix/lua/apisix.lua

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ end
2525

2626
local function fake_fetch()
2727
ngx.ctx.ip = "127.0.0.1"
28-
ngx.ctx.port = 80
28+
ngx.ctx.port = 1980
2929
end
3030

3131
function _M.http_access_phase()
@@ -42,6 +42,12 @@ function _M.http_header_filter_phase()
4242
end
4343
end
4444

45+
function _M.http_body_filter_phase()
46+
if ngx.ctx then
47+
-- do something
48+
end
49+
end
50+
4551
function _M.http_log_phase()
4652
if ngx.ctx then
4753
-- do something

bin/apisix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ http {
229229
230230
log_format main '$remote_addr - $remote_user [$time_local] $http_host "$request" $status $body_bytes_sent $request_time "$http_referer" "$http_user_agent" $upstream_addr $upstream_status $upstream_response_time';
231231
232-
access_log {* http.access_log *} main buffer=16384 flush=1;
232+
access_log {* http.access_log *} main buffer=16384 flush=3;
233233
open_file_cache max=1000 inactive=60;
234234
client_max_body_size 0;
235235
keepalive_timeout {* http.keepalive_timeout *};

conf/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ etcd:
121121
host: # it's possible to define multiple etcd hosts addresses of the same etcd cluster.
122122
- "http://127.0.0.1:2379" # multiple etcd address
123123
prefix: "/apisix" # apisix configurations prefix
124-
timeout: 3 # 3 seconds
124+
timeout: 30 # 3 seconds
125125
# user: root # root username for etcd
126126
# password: 5tHkHhYkjr6cQY # root password for etcd
127127
#eureka:

t/admin/balancer.t

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ add_block_preprocessor(sub {
3333
local balancer = require("apisix.balancer")
3434
local res = {}
3535
for i = 1, count or 12 do
36-
local host, port, err = balancer.pick_server(route, ctx)
36+
local server, err = balancer.pick_server(route, ctx)
3737
if err then
3838
ngx.say("failed: ", err)
3939
end
4040
41-
core.log.warn("host: ", host, " port: ", port)
42-
res[host] = (res[host] or 0) + 1
41+
core.log.warn("host: ", server.host, " port: ", server.port)
42+
res[server.host] = (res[server.host] or 0) + 1
4343
end
4444
4545
local keys = {}
@@ -144,6 +144,7 @@ host: 39.97.63.217 count: 6
144144
-- cached by version
145145
up_conf.nodes = {
146146
{host = "39.97.63.218", port = 80, weight = 1},
147+
{host = "39.97.63.219", port = 80, weight = 0},
147148
}
148149
test(route, ctx)
149150
@@ -192,6 +193,7 @@ host: 39.97.63.218 count: 12
192193
-- cached by version
193194
up_conf.nodes = {
194195
{host = "39.97.63.218", port = 80, weight = 1},
196+
{host = "39.97.63.219", port = 80, weight = 0},
195197
}
196198
test(route, ctx)
197199
@@ -208,3 +210,41 @@ host: 39.97.63.215 count: 12
208210
host: 39.97.63.218 count: 12
209211
--- no_error_log
210212
[error]
213+
214+
215+
216+
=== TEST 5: return item directly if only have one item in `nodes`
217+
--- config
218+
location /t {
219+
content_by_lua_block {
220+
local up_conf = {
221+
type = "roundrobin",
222+
nodes = {
223+
{host = "39.97.63.215", port = 80, weight = 1},
224+
{host = "39.97.63.216", port = 81, weight = 1},
225+
{host = "39.97.63.217", port = 82, weight = 1},
226+
}
227+
}
228+
local ctx = {}
229+
ctx.upstream_conf = up_conf
230+
ctx.upstream_version = 1
231+
ctx.upstream_key = up_conf.type .. "#route_" .. "id"
232+
233+
test(route, ctx)
234+
235+
-- one item in nodes, return it directly
236+
up_conf.nodes = {
237+
{host = "39.97.63.218", port = 80, weight = 1},
238+
}
239+
test(route, ctx)
240+
}
241+
}
242+
--- request
243+
GET /t
244+
--- response_body
245+
host: 39.97.63.215 count: 4
246+
host: 39.97.63.216 count: 4
247+
host: 39.97.63.217 count: 4
248+
host: 39.97.63.218 count: 12
249+
--- no_error_log
250+
[error]

0 commit comments

Comments
 (0)