comparison upstream_random.t @ 1350:fda743e92b31

Tests: upstream random tests.
author Sergey Kandaurov <pluknet@nginx.com>
date Fri, 15 Jun 2018 13:59:08 +0300
parents
children a37d8526e691
comparison
equal deleted inserted replaced
1349:99a83f7e7755 1350:fda743e92b31
1 #!/usr/bin/perl
2
3 # (C) Sergey Kandaurov
4 # (C) Nginx, Inc.
5
6 # Tests for upstream random balancer module.
7
8 ###############################################################################
9
10 use warnings;
11 use strict;
12
13 use Test::More;
14
15 BEGIN { use FindBin; chdir($FindBin::Bin); }
16
17 use lib 'lib';
18 use Test::Nginx qw/ :DEFAULT http_end /;
19
20 ###############################################################################
21
22 select STDERR; $| = 1;
23 select STDOUT; $| = 1;
24
25 my $t = Test::Nginx->new()->has(qw/http proxy upstream_zone upstream_random/)
26 ->write_file_expand('nginx.conf', <<'EOF');
27
28 %%TEST_GLOBALS%%
29
30 daemon off;
31 worker_processes 2;
32
33 events {
34 }
35
36 http {
37 %%TEST_GLOBALS_HTTP%%
38
39 upstream u {
40 zone z 1m;
41 random;
42 server 127.0.0.1:8081;
43 server 127.0.0.1:8082;
44 server 127.0.0.1:8083 down;
45 }
46
47 upstream lc {
48 zone lc 1m;
49 random two;
50 server 127.0.0.1:8081;
51 server 127.0.0.1:8082;
52 server 127.0.0.1:8083 down;
53 }
54
55 upstream w {
56 zone w 1m;
57 random two least_conn;
58 server 127.0.0.1:8081;
59 server 127.0.0.1:8082 weight=2;
60 }
61
62 upstream mc {
63 zone mc 1m;
64 random;
65 server 127.0.0.1:8081 max_conns=2;
66 server 127.0.0.1:8082 max_conns=1;
67 }
68
69 upstream mc2 {
70 zone mc 1m;
71 random two;
72 server 127.0.0.1:8081 max_conns=2;
73 server 127.0.0.1:8082 max_conns=1;
74 }
75
76 upstream one {
77 random;
78 server 127.0.0.1:8081;
79 }
80
81 upstream two {
82 random two;
83 server 127.0.0.1:8081;
84 }
85
86 upstream zone {
87 zone z 1m;
88 random;
89 server 127.0.0.1:8081;
90 }
91
92 upstream ztwo {
93 zone z 1m;
94 random two;
95 server 127.0.0.1:8081;
96 }
97
98 server {
99 listen 127.0.0.1:8080;
100 server_name localhost;
101
102 location / {
103 proxy_pass http://u;
104 }
105
106 location /lc/ {
107 proxy_pass http://lc/;
108 }
109
110 location /w {
111 proxy_pass http://w;
112 }
113
114 location /mc/ {
115 proxy_pass http://mc/;
116 }
117
118 location /mc2/ {
119 proxy_pass http://mc2/;
120 }
121
122 location /one {
123 proxy_pass http://one;
124 }
125
126 location /two {
127 proxy_pass http://two;
128 }
129
130 location /zone {
131 proxy_pass http://zone;
132 }
133
134 location /ztwo {
135 proxy_pass http://ztwo;
136 }
137 }
138 }
139
140 EOF
141
142 $t->run_daemon(\&http_daemon, port(8081));
143 $t->run_daemon(\&http_daemon, port(8082));
144 $t->try_run('no upstream random')->plan(12);
145
146 $t->waitforsocket('127.0.0.1:' . port(8081));
147 $t->waitforsocket('127.0.0.1:' . port(8082));
148
149 ###############################################################################
150
151 my @ports = my ($port1, $port2) = (port(8081), port(8082));
152
153 like(http_get('/'), qr/X-Port: ($port1|$port2)/, 'random');
154 like(http_get('/lc/'), qr/X-Port: ($port1|$port2)/, 'random two');
155
156 my $s = http_get('/lc/w', start => 1, sleep => 0.2);
157 my $r = http_get('/lc/');
158 my ($p) = http_end($s) =~ /X-Port: (\d+)/;
159 like($r, qr/X-Port: (?!$p)/, 'random wait');
160
161 SKIP: {
162 skip 'long test', 3 unless $ENV{TEST_NGINX_UNSAFE};
163
164 is(parallel('/w', 3), "$port1: 1, $port2: 2", 'random weight');
165
166 is(parallel('/mc/w', 4), "$port1: 2, $port2: 1", 'max_conns');
167 is(parallel('/mc2/w', 4), "$port1: 2, $port2: 1", 'max_conns two');
168
169 }
170
171 # single variants
172
173 like(http_get('/one'), qr/X-Port: $port1/, 'single one');
174 like(http_get('/two'), qr/X-Port: $port1/, 'single two');
175 like(http_get('/zone'), qr/X-Port: $port1/, 'zone one');
176 like(http_get('/ztwo'), qr/X-Port: $port1/, 'zone two');
177
178 like(many('/close', 10), qr/$port2: 10/, 'failures');
179 like(many('/lc/close', 10), qr/$port2: 10/, 'failures two');
180
181 ###############################################################################
182
183 sub many {
184 my ($uri, $count, %opts) = @_;
185 my %ports;
186
187 for (1 .. $count) {
188 if (http_get($uri) =~ /X-Port: (\d+)/) {
189 $ports{$1} = 0 unless defined $ports{$1};
190 $ports{$1}++;
191 }
192
193 select undef, undef, undef, $opts{delay} if $opts{delay};
194 }
195
196 my @keys = map { my $p = $_; grep { $p == $_ } keys %ports } @ports;
197 return join ', ', map { $_ . ": " . $ports{$_} } @keys;
198 }
199
200 sub parallel {
201 my ($uri, $n) = @_;
202 my %ports;
203
204 my @s = map { http_get($uri, start => 1, sleep => 0.1) } (1 .. $n);
205
206 for (@s) {
207 if (http_end($_) =~ /X-Port: (\d+)/) {
208 $ports{$1} = 0 unless defined $ports{$1};
209 $ports{$1}++;
210 }
211 }
212
213 my @keys = map { my $p = $_; grep { $p == $_ } keys %ports } @ports;
214 return join ', ', map { $_ . ": " . $ports{$_} } @keys;
215 }
216
217 ###############################################################################
218
219 sub http_daemon {
220 my ($port) = @_;
221
222 my $server = IO::Socket::INET->new(
223 Proto => 'tcp',
224 LocalHost => '127.0.0.1',
225 LocalPort => $port,
226 Listen => 5,
227 Reuse => 1
228 )
229 or die "Can't create listening socket: $!\n";
230
231 local $SIG{PIPE} = 'IGNORE';
232
233 while (my $client = $server->accept()) {
234 $client->autoflush(1);
235
236 my $headers = '';
237 my $uri = '';
238
239 while (<$client>) {
240 $headers .= $_;
241 last if (/^\x0d?\x0a?$/);
242 }
243
244 $uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i;
245
246 if ($uri eq '/w') {
247 Test::Nginx::log_core('||', "$port: sleep(2.5)");
248 select undef, undef, undef, 2.5;
249 }
250
251 if ($uri eq '/close' && $port == port(8081)) {
252 next;
253 }
254
255 Test::Nginx::log_core('||', "$port: response, 200");
256 print $client <<EOF;
257 HTTP/1.1 200 OK
258 Connection: close
259 X-Port: $port
260
261 OK
262 EOF
263
264 close $client;
265 }
266 }
267
268 ###############################################################################