Examining the Glastonbury Ticket Sales Website
By Chris Gilbert
Note: Also see my updated 2016 post about this topic.
Tomorrow is that time of year again, when hundreds of thousands of people spend hours pressing their F5 key, in an often futile attempt to try to book Glastonbury Festival tickets. Although I have been successful the last couple of years anyway, this year I had the opportunity to do a bit of investigation beforehand, as they had a smaller ticket sale on Thursday evening. Since we have baby in tow this year, will be caravanning, and couldn’t buy a coach ticket, but I could use the opportunity to check out the SeeTickets servers, and get an idea how their pages and queuing system work. This is also more important, since 15,000 of the tickets have already sold, there will be less available tomorrow than on previous years. When I first hit the site, right on the dot of 6pm, I refreshed a few times, and immediately got to the coach ticket selection page. Here, you got to choose between Wednesday, and Thursday departures. I clicked Wednesday, and immediately got a registration numbers form. I was impressed - in the past I’d been stuck in a queue for a long time before being able to type my reg numbers in! So, I saved the page, so I could have a look at it later. I clicked through, and had a look at all the pages, including the payment page. Over the next half an hour I refreshed the page a few times, until I got added to the normal queuing system. This is a javascript based refresh which refreshes every 20 seconds, and polls the server for a booking slot. I assume they use a session based queuing system, because although last year there were problems after typing in the registration numbers (because of a DNS configuration issue), the previous festival, once I got through to this screen, I had no further issues. Looking at this then, it’s fairly simple on how to get your booking slot - you keep refreshing the page until instead of showing you a queuing message, you get a page where you type in the registration numbers. What you are actually hoping the see, is this form:
<span data-valmsg-for="RegistrationErrors" data-valmsg-replace="true"></span><form novalidate="novalidate" action="/event/addregistrations" id="mainRegForm" method="post"><input id="showCode" name="showCode" value="800004" type="hidden"> <h3>YOUR DETAILS</h3> <div> <label>Registration Number: </label><input id="registrations\_0\_\_RegistrationId" maxlength="30" name="registrations\[0\].RegistrationId" type="text"><span data-valmsg-for="registrations\[0\].RegistrationId" data-valmsg-replace="true"></span> <label>Postcode: </label><input id="registrations\_0\_\_PostCode" maxlength="30" name="registrations\[0\].PostCode" type="text"><span data-valmsg-for="registrations\[0\].PostCode" data-valmsg-replace="true"></span> </div> <h3>ADD UP TO 5 ADDITIONAL TICKETS</h3> <div> <span>#1</span> <label>Registration Number: </label><input id="registrations\_1\_\_RegistrationId" maxlength="30" name="registrations\[1\].RegistrationId" type="text"><span data-valmsg-for="registrations\[1\].RegistrationId" data-valmsg-replace="true"></span> <label>Postcode: </label><input id="registrations\_1\_\_PostCode" maxlength="30" name="registrations\[1\].PostCode" type="text"><span data-valmsg-for="registrations\[1\].PostCode" data-valmsg-replace="true"></span> <div> </div> <span>#2</span> <label>Registration Number: </label><input id="registrations\_2\_\_RegistrationId" maxlength="30" name="registrations\[2\].RegistrationId" type="text"><span data-valmsg-for="registrations\[2\].RegistrationId" data-valmsg-replace="true"></span> <label>Postcode: </label><input id="registrations\_2\_\_PostCode" maxlength="30" name="registrations\[2\].PostCode" type="text"><span data-valmsg-for="registrations\[2\].PostCode" data-valmsg-replace="true"></span> <div> </div> <span>#3</span> <label>Registration Number: </label><input id="registrations\_3\_\_RegistrationId" maxlength="30" name="registrations\[3\].RegistrationId" type="text"><span data-valmsg-for="registrations\[3\].RegistrationId" data-valmsg-replace="true"></span> <label>Postcode: </label><input id="registrations\_3\_\_PostCode" maxlength="30" name="registrations\[3\].PostCode" type="text"><span data-valmsg-for="registrations\[3\].PostCode" data-valmsg-replace="true"></span> <div> </div> <span>#4</span> <label>Registration Number: </label><input id="registrations\_4\_\_RegistrationId" maxlength="30" name="registrations\[4\].RegistrationId" type="text"><span data-valmsg-for="registrations\[4\].RegistrationId" data-valmsg-replace="true"></span> <label>Postcode: </label><input id="registrations\_4\_\_PostCode" maxlength="30" name="registrations\[4\].PostCode" type="text"><span data-valmsg-for="registrations\[4\].PostCode" data-valmsg-replace="true"></span> <div> </div> <span>#5</span> <label>Registration Number: </label><input id="registrations\_5\_\_RegistrationId" maxlength="30" name="registrations\[5\].RegistrationId" type="text"><span data-valmsg-for="registrations\[5\].RegistrationId" data-valmsg-replace="true"></span> <label>Postcode: </label><input id="registrations\_5\_\_PostCode" maxlength="30" name="registrations\[5\].PostCode" type="text"><span data-valmsg-for="registrations\[5\].PostCode" data-valmsg-replace="true"></span> </div> <input value="Proceed" id="add\_registrations" type="submit"> <p><a href="javascript:void(0)">Clear registration form</a></p> </form> <script type="text/javascript"> window.onload = function () { registrationValidator.init($('form#mainRegForm'), 6, '#registrations\_{0}\_\_RegistrationId', '#registrations\_{0}\_\_PostCode '); $('.clear-form').click(function() { if (confirm('Are you sure you want to clear the registration details form?')) { $('.add-registration input\[type="text"\]').val(''); $('.add-registration .field-validation-error').empty(); } }); }; </script>
Pretty straightforward - it’s a basic HTML form which submits to /event/addregistrations with the POST data you provide. So, is there a way to avoid hitting F5 over and over? Well, perhaps - but I suspect trying to submit directly to this URL with the POST data would be a mistake. I neglected to check, but I expect by this point, I already had a session ID on the server, and this would be included with the HTTP post in the headers. I imagine, without this, the request would just be rejected. This is at best - if they have any paranoid security software, you might end up getting your IP banned, which we really don’t want, at least, before we’ve got tickets. So, what if we hit the queuing system? Will the refresh every 20 seconds be enough? I think not. The issue with this is that you only get one chance to get a booking session every 20 seconds - and you just have to be lucky with that. Since there are likely half a million other people or more trying to get one too, your chances are very limited, if you just refresh once every 20 seconds. To get a better idea how they keep sessions, I had a look through the cookies created by the glastonbury.seetickets.com site. One is an ‘NRAGENT’ cookie, which looks to be related to the newrelic monitoring agent they are using - good bit of software actually. One is more interesting - it’s called X-Mapping-xxrandomdata. A quick google reveals that this one is set by the Stingray Traffic Manager software, which is used for load balancing. Interesting. So that tells us, that it is most likely that in front of backend web/application servers are a couple of load balancers. Other cookies are _utma, _utmb, _utmc, _utmz, these are all for Google Analytics, so we can ignore them. Finally, there is a cookie called SeeAffiliate, with content id1umg. I’m not sure what this is, but it expired back in September, so I think it must have been an old cookie from a previous visit. The X-Mapping cookie looks like the only one of significance here. However, I am checking several days later, so my session cookie may well have disappeared now. Looking at the DNS records, there were two IPs for the ticket booking servers. So, if they are using load balancers, there are likely two, one for each IP address. Seeing as there are two IPs, this provides a simple round-robin load balancing, where clients only resolve one address at a time, and therefore get sent to one frontend load balancer or another. Looking at the dig record more closely, they have the TTL value set to 60 seconds. At least - I thought they did. Looking at the BT nameserver, things are slightly different now - the TTL is ticking down, each time I hit it: [email protected] (British Telecom (UK)):```
glastonbury.seetickets.com. 25 IN [CNAME](http://www.ietf.org/rfc/rfc1035.txt) seetickets.com.
seetickets.com. 13 IN [A](http://www.ietf.org/rfc/rfc1035.txt) 194.168.202.201
seetickets.com. 13 IN [A](http://www.ietf.org/rfc/rfc1035.txt) 194.168.202.218
seetickets.com. 13 IN [A](http://www.ietf.org/rfc/rfc1035.txt) 194.168.202.202
The TTL here is 13 seconds, and each time I hit it, it decreases and then goes back to 60. This only happens on the BT server though, not Google or any of the others I tried. Perhaps something specific about the BT DNS server? Or perhaps a special DNS setup for Glastonbury? I’m not sure. The only advantage I can see to this short time-to-live setting is that client requests are distributed evenly across the IPs. This is probably useful to them, but perhaps not always to us. It does mean that if one server goes down though, you won’t have to wait too long before you hit the next one. They’ve also added a new server since several days ago, .218. In addition, glastonbury.seetickets.com is just a CNAME to seetickets.com, so you are probably hitting the same IPs as the rest of their ticket booking too. Hmm. I did a reverse DNS lookup on the IP records to find out a bit more. It looks like they are being hosted by Virgin media, or at least are on their network. Great! I am on Virgin Media too. See Tickets are a Nottingham company, and I am also in Nottingham. This bodes well for latency issues. I tried pinging servers, but they are not responding to ICMP at the moment. This is probably a fair precaution - they are going to be busy enough as it is, without having to send back thousands of pings a second to geeky IT people like me. Unfortunately, this makes it difficult to check our latency. We can instead use netcat to check how long it takes to establish a TCP connection to each of the IPs: Right, so now we want to reduce lag as much as possible, and get latency as close to zero as is possible. First port of call, plugin to our ethernet switch. WiFi adds quite a bit of latency - testing to our own router, it averages 3-5ms on Wifi, going as high as 56ms at some points. On cabled LAN it’s <1ms. Ok, so we have bought ourselves a few milliseconds per requests with little effort. Now, the basics, lets speed up the computer(s) as much as possible:
- Close all other programs except the browser
- Close the other tabs and windows on the browser
- Disconnect phones and other devices from your network to avoid things leeching bandwidth
- Disable all browser plugins, except perhaps Check4Change (as below)
Now the setup - we have three IPs, so perhaps three computers hitting all of them would work best. Unfortunately there are only two of us, and neither of us want RSI from hitting F5 over and over. So, bring in the Check4Change firefox extension, which seems ideal for this situation. It reloads the page on a configurable time period, and checks for a change to an area of the HTML. This means it isn’t just a ‘blind’ reloader plugin - some of them refresh over and over, but don’t know when to stop. I had no luck with these last year, and I think they just made things harder. The great thing about Check4Change is that you can check to see when a bit of text in the page has changed - it will then alert you, and flash the tab to let you know. Excellent! So, after installing the plugin, we’ll test it out. At present, the site says ‘check back on Sunday’. So, I highlight ‘check back’ and right click, turn on Check 4Change. You can configure timeout periods - perhaps 1 or 2 seconds is what we want. Great, it seems to be very quickly refreshing the page - I can’t see what it’s doing at all, it’s so quick. This is not reassuring, so I think perhaps I will test it on another page which I know to be changing. Time for that later - firstly, we need to assemble the information we need.
- Get all registration numbers and associated postcodes you are booking beforehand. Put them in a text file for cutting and pasting.
- Have your DEBIT card (or credit card if you are booking internationally) to hand. Tickets are not confirmed until payment is taken, so you need to be able to do this very quickly.
- Make sure there’s enough available in your account for all the tickets - you don’t want your payment to be refused and lose your tickets at the last moment.
- Have computers setup, fully charged.
- Have drinks and snacks to hand - you may not be moving for 3 or 4 hours.
- Start bright and early, give yourself time to setup. Visit the site earlier than 9am. Firstly this will cache all the other objects on the site, so you won’t have to load them all when the site is particularly busy. Secondly, you will be in line in case they open the booking early (which has been known to happen).
- Give your reg numbers to other friends who are trying to book tickets. Your chances are better, and in the past it warned you if a ticket had already been booked for a number, so you couldn’t buy them twice.
- Stay calm, and keep trying. Quite often you can get lucky, hit a lull in traffic and get your booking in quick and easily.
- A few more tabs when refreshing is fine, but bear in mind your session may be shared amongst them, so you may have issues if trying to fill out the forms in multiple tabs at the same time. It’s best to try to follow the forms through on one tab before you try the same on another (where you are trying to book more than 6 tickets).
Finally, for redundancy and to increase your chances, have several computers available. An OS crash could kill your chances of getting tickets, you can also refresh quicker and hit the servers faster with two endpoints rather than one. A neat trick that worked well last year, because of a dodgy DNS record, was to add the server address to your OS hosts file. This saves the browser needing to do a DNS lookup to find the address, which could save time every minute or so, as the time-to-live record is set so low. I’d not recommend doing this when using one computer, unless on the day it becomes clear that one of the IP addresses is down. You stand the best chance if you can hit any of the servers. With several computers though, perhaps it’s worth setting a DNS record in each hosts file. In windows, this file is located in c:\windows\system32\drivers\etc usually. You need to open it as administrator, and add a line, something like the following to it: 194.168.202.202 glastonbury.seetickets.com You have to open notepad as administrator to edit this file. I decided to take a mixed approach - use one computer with a fixed host record, and the other doing normal DNS lookups. This would allow flexibility - I can use one to change the IP manually if necessary, and hit all possible servers on the other. Ok, so we are just about ready. Now, just time to check the Firefox extension is working ok, and we are ready to go!
[View Comments]({{ < ref examining-the-glastonbury-ticket-sales-website-comments > }})