Last active
November 10, 2022 23:44
-
-
Save nginx-gists/e99a65739b81a86dfd6b1823938c71db to your computer and use it in GitHub Desktop.
Using the NGINX JavaScript Module to Progressively Transition Clients to a New Server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
upstream old { | |
server 10.0.0.1; | |
server 10.0.0.2; | |
} | |
upstream new { | |
server 10.0.0.9; | |
server 10.0.0.10; | |
} | |
js_import /etc/nginx/progressive_transition.js; | |
js_set $upstream progressive_transition.transitionStatus; # Returns "old|new" based on window pos | |
server { | |
listen 80; | |
location / { | |
set $transition_window_start "Wed, 31 Aug 2016 17:00:00 +0100"; | |
set $transition_window_end "Wed, 31 Aug 2016 19:00:00 +0100"; | |
proxy_pass http://$upstream; | |
error_log /var/log/nginx/transition.log info; # Enable NJS logging | |
} | |
} | |
# vim: syntax=nginx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function fnv32a(str) { | |
var hval = 2166136261; | |
for (var i = 0; i < str.length; ++i ) { | |
hval ^= str.charCodeAt(i); | |
hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24); | |
} | |
return hval >>> 0; | |
} | |
function transitionStatus(req) { | |
var vars, window_start, window_end, time_now, timepos, numhash, hashpos; | |
// Get the transition window from NGINX configuration | |
vars = req.variables; | |
window_start = new Date(vars.transition_window_start); | |
window_end = new Date(vars.transition_window_end); | |
// Are we in the transition time window? | |
time_now = Date.now(); | |
if ( time_now < window_start ) { | |
return "old"; | |
} else if ( time_now > window_end ) { | |
return "new"; | |
} else { // We are in the transition window | |
// Calculate our position in the window (0-1) | |
timepos = (time_now - window_start) / (window_end - window_start); | |
// Get numeric hash for this client's IP address | |
numhash = fnv32a(req.remoteAddress); | |
// Calculate the hash's position in the output range (0-1) | |
hashpos = numhash / 4294967295; // Upper bound is 32 bits | |
req.log("timepos = " + timepos + ", hashpos = " + hashpos); //error_log [info] | |
// Should we transition this client? | |
if ( timepos > hashpos ) { | |
return "new"; | |
} else { | |
return "old"; | |
} | |
} | |
} | |
export default { transitionStatus } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For a discussion of these files, see Using the NGINX JavaScript Module to Progressively Transition Clients to a New Server