Anycast

This week we started testing our global anycast network. We have a real-time map which shows which people are served by each location. Today we have three locations online, we hope to have 10-12 by the end of the year.

anycast

The Internet is definitely not a big truck

3 responses to “Anycast”

  1. Congratulations on the accomplishment.

    May I ask how the data was charted in real time?

    1. Pyry Hakulinen Avatar
      With bash, Perl, PHP and JavaScript 🙂 It is just a prototype, but works well enough for me. I put all the codebits in github, in case you are interested: .gist table { margin-bottom: 0; } 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 Show hidden characters "Instructions" 1) Install index.php to some webserver, and run "latlongudp.pl" on the same server. 2) Then feed IPs to the latlongudp.pl server with something like this: tail -F /var/log/nginx/access_log|perl -e '$|=1;while(<>){print "someidentifier,$1n" if/(d+.d+.d+.d+)/}'|nc -u somenode.example.com 5001 Modify someidentifier to to fit your needs. 3) Enjoy the map… view raw README hosted with ❤ by GitHub 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 Show hidden characters <?php $dbh = new SQLite3( '/dev/shm/hits.db' ); if ( isset( $_GET['g'] ) ) { $dbh->busyTimeout(1000); $stmt = $dbh->prepare( 'SELECT host,lat,lng FROM hit WHERE service = ? GROUP BY lat,lng ORDER BY RANDOM() LIMIT 10000;'); $stmt->bindValue(1, preg_replace( '/[^a-z]/', '', $_GET['g'] ), SQLITE3_TEXT); $stmt->execute(); $result = $stmt->execute(); $stats = array(); while( $row = $result->fetchArray( SQLITE3_ASSOC ) ) { $stats[] = $row; } header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Pragma: no-cache"); if ( isset( $_GET['callback'] ) ) { header("Content-type: text/javascript"); $callback = preg_replace( '/[^a-zA-Z0-9_]/', '', $_GET['callback'] ); echo "$callback(" . json_encode( $stats ) . ");"; } else { echo json_encode( $stats ); } } else { ?><!DOCTYPE html> <html> <head> <title>anycast map</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <meta charset="UTF-8"> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <style> #map canvas { /* padding:0;margin:0;*/ /*border:1px solid #111;*/ position:absolute; } * {margin:0;padding:0; } body, html { background:black; } /* height:100%;margin:0; padding:0px; /*padding:10px; background:black; }*/ </style> <script> // ctx.fillStyle = "rgb(200,0,0)"; // ctx.fillRect (10, 10, 55, 50); var map, heatmap; var hitdata=new Array(); var running = 0; var data = new Array(); var dcs = new Array(); var dcss = new Array(); dcss["lax"] = new Array(0,0,255); //"blue"//["rgba(0, 0, 255, 0.0)","rgba(0, 0, 255, 1.0)"]; dcss["lhr"] = new Array(255,0,0);//"red"//["rgba(255,0,0,0.0)","rgba(255,0,0,1.0)"]; dcss["iad"] = new Array(0,255,0); //"green"//["rgba(0,255,0,0.0)","rgba(0,255,0,1.0)"]; dcss["sat"] = new Array(255,127,0);//"orange"//["rgba(151,0,151,0.0)","rgba(151,0,151,1.0)"]; dcss["yyz"] = new Array(255,0,255);//"purple"//["rgba(151,0,151,0.0)","rgba(151,0,151,1.0)"]; dcss["mia"] = new Array(255,255,0); //"yellow" // dcss["dfw"] = new Array(255,255,255); // "white" // dcss["fra"] = new Array(0,255,255); // "light blue" // dcss["sin"] = new Array(46,139,87); // "dark green" // dcss["sjc"] = new Array(102,0,12); // "dark purple" // var canvas var image var w=1000; var h=500; var ww=w/360; var hh=h/180; var getint $(document).ready(function() { get_size(); highlight(); getdata(); getint=setInterval( function(){getdata();}, 1000 ); create_canvas(); setInterval( function(){addstuff();}, 100 ); setInterval( function(){fadecanvas();}, 200 ); setInterval( function(){rotate_canvas();}, 30000 ); }); function highlight() { if( matches = window.location.search.match(/dc=(w+)/) ){ for( i in dcss ) { if(i == matches[1]){ dcss[i] = new Array(255,0,0); }else{ dcss[i] = new Array(0,0,255); } } } } function get_size(){ var matches; if ( matches = window.location.search.match(/w=(d+)/) ){ w=matches[1]; ww=w/360; } if ( matches = window.location.search.match(/h=(d+)/) ){ h=matches[1]; hh=h/180; } } var fade=null function rotate_canvas() { if (document.getElementById('map').children.length > 4 && fade==null ) { fade=document.getElementById('map').firstElementChild } create_canvas(); } function fadecanvas() { if(fade){ if(fade.style.opacity<=0.3){ document.getElementById('map').removeChild(fade); fade=null; }else{ fade.style.opacity-=0.1; fade.style.filter = 'alpha(opacity=' + Math.ceil(fade.style.opacity*10) + ')'; } } } function create_canvas() { element=document.createElement('canvas'); canvas=element.getContext('2d'); canvas.canvas.width=w; canvas.canvas.height=h; element.style.opacity=1; image = canvas.createImageData(w,h) for( i in dcss ) { dcs[i] = canvas.createImageData(1,1) dcs[i].data[0] = dcss[i][0]; dcs[i].data[1] = dcss[i][1]; dcs[i].data[2] = dcss[i][2]; dcs[i].data[3] = 255; } document.getElementById('map').appendChild(element); } var jqxhr; var service="wpcom"; if( matches = window.location.search.match(/s=(w+)/) ){ service=matches[1]; } function getdata(){ if (!running){ $.ajax( "?g="+service, { cache:true, crossDomain:true, dataType:"jsonp", jsonpCallback:"jsonpcallback", timeout:4000, } ).done( function(data) { if( data.length ) { hitdata=data; hitdata.sort(function() {return 0.5 – Math.random()}); } running=0; }).fail(function( jqXHR, textStatus,errorThrown ) { // alert( "Request failed: " + textStatus + " : " + errorThrown); }).always(function() { running=0; // alert("foo"); }); running=1; } } var max=1000; var per_iter = 1000; data=new Array(); function addstuff() { for (k=0;k<per_iter;k++){ var point = hitdata.pop(); if (point){ x=Math.ceil((180+point['lng'])*ww); y=Math.ceil((90–point['lat'])*hh); canvas.putImageData(dcs[point['host']], x,y); } } per_iter=130; } </script> </head> <body> <div id="map"></div> </body> </html><? } view raw index.php hosted with ❤ by GitHub 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 Show hidden characters #!/usr/bin/perl # feeder on LBs # tail -F /var/log/nginx/access_log|perl -e '$|=1;while(<>){($f,$f,$ip)=split/s+/;$ip=~s/"//g;print "lax,$ipn"}'|nc -u somenode.example.com 5001 use strict; use warnings; use IO::Socket; use IO::Socket::INET; use Math::Round qw( nhimult nearest ); use Geo::IP; use DBI; my $gi = Geo::IP->open("geocity.dat", GEOIP_MEMORY_CACHE); my $sock = new IO::Socket::INET ( LocalPort => '5001', Proto => 'udp', ) or die "ERROR in Socket Creation : $!n"; # hits.db created with #CREATE TABLE hit (time INTEGER, lat REAL,lng REAL, host TEXT); #CREATE INDEX time ON hit (time); my $dbh = DBI->connect("dbi:SQLite:dbname=/dev/shm/hits.db","","",{AutoCommit=>0}); $dbh->do("CREATE TABLE hit (time INTEGER, lat REAL,lng REAL, host TEXT, service TEXT);"); $dbh->do("CREATE INDEX time ON hit (time);"); $dbh->do("CREATE INDEX service ON hit (service);"); my $sth = $dbh->prepare("INSERT OR REPLACE INTO hit (lat,lng,host,time,service) VALUES(?,?,?,?,?)"); my $old_time; my $data; my $c=0; $|++; my $round=0.001;#.5; while ($sock->recv($data, 30)) { print "."; print "n" if ++$c %80==0; chomp($data); # print "$datan"; my ($dc,$ip,$service) = split /,/,$data; $service||="wpcom"; my $r=$gi->record_by_addr($ip); next if !$r || $r->longitude==0; my ($lat,$lng) = ($r->latitude, $r->longitude); # gunzip($recieved_data => $output); my $curtime = time(); my $time = nhimult(2, $curtime); if( $old_time != $time ){ $dbh->do("DELETE FROM hit WHERE time < " . ($curtime – 11) ); $dbh->commit; $old_time=$time; print "commitn"; } $sth->execute(nearest($round,$lat), nearest($round, $lng), $dc, time(),$service); } view raw latlongudp.pl hosted with ❤ by GitHub

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: