Tuesday, December 24, 2013

jsDelivr weekly news #2

Latest changelog:

  • A new load balancing algorithm was pushed to production. Its a lot smarter and makes even heavier use of RUM performance data for each provider. The whole logic was revisited and now standalone servers are no longer used by default in all cases. All sponsored CDNs from now on have higher priority and are used by default. Standalone servers are only used for individual countries. For example Finland has a rule that takes into consideration the performance for 2 additional sponsored servers on top of our CDNs. This way the speed of jsDelivr becomes even better with a lot more stability. You are encouraged to report performance issues if you experience any problems.
  • An organization account was created for jsDelivr. All jsDelivr related projects will be created under the same account
  • A CloudFlare App is under development. If anyone is interested to help please let me know. JavaScript knowledge is required.
  • It is planned to open source the jsdelivr.com website. But before that someone will have to rewrite the back-end code from scratch. At the moment most probably I will have to hire a freelancer to do that. Again if anyone is interested to help let me know
  • All .zip generation was moved to the origin. They are no longer hosted in our Github repo
  • It is now possible to load the latest version of any project by using a special URL.
  • An application to automatically fetch and upload new versions of projects is under development
  • A lot of new features are planned to be released.
  • qTip2 switched to jsDelivr as their official CDN provider!

As always you can participate and contribute to the project. Coders, designers, companies... We need everyone.
We are also interested to include even more CDNs into jsDelivr. If you know people in the CDN industry then let them know that they can help the open source community by simply sponsoring a few TBs of traffic per month.
If MaxCDN and CDN.NET could see past their differences and competition and partner up to help an open source project then anyone can.

Also in the last few months some of our providers experienced downtime. But I am pleased to say that our load balancing algorithm worked perfectly and jsDelivr uptime remained 100% without  anyone being affected.

Saturday, November 9, 2013

How jsDelivr works

I wrote a detailed article on jsDelivr and how exactly it works.

Check it out and let me know if you like it.

Load balancing multiple CDNs or how jsDelivr works

Friday, June 28, 2013

jsDelivr weekly news

Here is the new changelog:

  • Origin moved from MaxCDN push to Rackspace Cloud Files.  MaxCDN locations are now used via a Pull zone. This was done to finally allow me to enable custom HTTP headers. All CORS issues were fixed and I have now full control over HTTP headers.
  • Thanks to Cedexis a new more efficient load balancing algorithm was deployed. A bigger focus was made on uptime and failover features. If a provider goes down the switch should be almost immediate with no downtime at all.
  • A new custom location was added in Germany with 1Gbps unlimited bandwidth connection sponsored by FinnDNS.eu
  • A new project called cdnperf.com now collects uptime and performance data for jsDelivr. Make sure to check it out.
  • 2-way authentication was enabled on all jsDelivr related accounts for maximum security. (all that support this feature.)
  • alohaeditor package was removed from github because it was outdated and had more than 20000 files, most of them useless. Now the jsDelivr repo should be easier to fork and create new pull requests. No files were deleted from the CDN itself, so there will be no downtime for users that were using any of those files.


Help jsDelivr with valuable data

It doesn't matter if you are using our CDN or not, you can now help us gather valuable data and make our performance and uptime decisions even more accurate.
All you have to do is to add this script in your website just before </body>

What it does:
  • Loads in non-blocking async mode
  • After the page is done loading in the background without disturbing the user or the website in any way starts pinging jsDelivr providers.
  • It then sends back to us very useful availability and performance data.
  • Based on this data our load balancing algorithm then decides what provider is best suited for each user of jsDelivr CDN. The more users your website gets the more accurate data we will have.
  • This is very important. Currently its gets about 190k measurements per hour. Pretty good but most of those users are USA based, which means that users from other countries, like China and India could experience a slightly inaccurate decisions.
  • Please feel free to add this code in all of your blogs and websites. It helps everybody!
That's it for now, I will update this blog with more jsDelivr information as they come in.

Sunday, June 2, 2013

jsDelivr News: New infrastructure and more



It's been a while since I posted news regarding jsDelivr.
Let's see what happened since then:

  • jsDelivr moved to a new infrastructure!
    • It now utilizes a Multi-CDN system using Cedexis load balancing.
    • NetDNA and CDN.NET are the main CDN providers. All traffic is load balanced between them.
    • The system checks both Uptime and Performance before deciding which CDN should serve the user. This algorithm guarantees a super reliable and fast network.
    • Tested in the wild. One of the CDN providers had Uptime issues (10'), jsDelivr to this day has 100% Uptime.  
  • Custom POPs are planned to be added in the next few days.  
    • A few hosting providers have sponsored jsDelivr with VPS nodes in locations where there is no CDN presence. (If you are a provider and want to sponsor a free VPS please mail me contact@jsdelivr.com)
    • Traffic will be load balanced based on the same algorithm, Uptime+Performance.
    • Nginx+SSL will be installed to serve the content. A Caching Proxy configuration is going to be used to make sure the system is 100% malware free.
  • During the next month its planned to switch to Akamai hosted DNS from AWS Route 53.
  • Pingdom published a small interview with me and a friend of mine. jsDelivr-jster interview
  • More than 600 projects are currently hosted!

Uptime and performance are very important to me and this is why I do anything I can to improve jsDelivr even further. It is constantly under development and brainstorm for new ideas. I want to make it one of the most popular public CDNs out there.
I think it's safe to say that currently jsDelivr is the most advanced free public CDN out there. The only thing it lacks is some serious promotion. I hope people eventually will see that it deserves their trust and will start using it.

Thanks

Don't forget to follow me @jimaek and stay updated.

Wednesday, April 10, 2013

How to handle time consuming PHP scripts

Some times you might have to write PHP scripts that can take a long time to finish.
For example create/recover backups, install CMS demos, parse large amounts of data etc...
To make sure your scripts will work as expected you will need to know and remember a few things.

Timeouts 

The first thing you have to do is to set the max_execution_time parameter in your PHP configuration.
If the script is executed by the web server (i.e in response of a HTTP request from a user) then you will also have to set the correct timeout parameters in the web server config.
For Apache its TimeOut and FastCgiServer… -idle-timeout (if you are using fastcgi)
For Nginx its send_timeout and fastcgi_read_timeout (if you are using fastcgi)

The web server can also proxy requests to an other web server that will in his turn execute the PHP script (e.g nginx - frontend, apache - backend). In this case you will have to set the correct timeout parameters for the proxy.
For Apache its ProxyTimeout and for Nginx proxy_read_timeout.


User Interruption 

If the script is executed in response to a HTTP request, then the user can easily interrupt the script by canceling the request in his browser.
If you want for the PHP script to continue running even after the user canceled/interrupted his request then set TRUE in ignore_user_abort parameter of PHP.


Loss of Open Connection

If the script opens a connection with any other service (DB, mail, ftp..) and the connection happens to close/timeout then the script will fail to execute correctly.
For example if during the execution of the script we open a connection to MySQL and for some time don't use it, then MySQL will close the connection based on the wait_timeout parameter.
In this case the first thing should be to try and increase the connection timeout. For example for MySQL we can run the following query:
SET SESSION wait_timeout = 9999

But if we don't have this opportunity then we can check if the connection is open in parts of code where the connection could timeout and re-connect if needed.
For example in the mysqli module there is a useful function called mysqli::ping to check the status of our connection. Plus there is the configuration parameter mysqli.reconnect for automatic re-connection if the connection closes.
If you are trying to do the same thing for an other kind of service and there is no similar configuration or function available then you could try to write it yourself.
The function should try to connect to your service and in case of error (you can use try and catch) re-connect. For example:


class FtpConnection
{
    private $ftp;

    public function connect()
    {
        $this->ftp = ftp_connect('ftp.server');
        ...
    }

    public function reconnect()
    {
        try
        {
            if (!ftp_pwd($this->ftp))
                $this->connect();
        }
        catch($e)
        {
            $this->connect();
        }
    }

    ...
}

or
class MssqlConnection
{
    private $db;

    public function connect()
    {
        $this->db = mssql_connect('mssql.server');
        ...
    }
    
    public function reconnect()
    {
        try
        {
            if (!mssql_query('SELECT 1 FROM dual', $this->db))
                $this->connect();
        }
        catch($e)
        {
            $this->connect();
        }
    }

    ...
}

Parallel Execution

Its not rare when long scripts are executed on schedule (cron) and its expected that at any moment only one copy of the script will be running.
But it can happen that the script will be executed on schedule while the old one is still running. This will lead to unpredictable problems and errors.
In this case you should use a locking technique of the resourses being used, but this task is always solved individually. You can check if there is an other copy running and either wait for it to finish or cancel the current script execution. To achieve this you can check the list of running processes or lock the execution of the script itself, something like:

if (lockStart('script.php'))
{
    // main php code
    ...
    lockStop('script.php');
}


Web Server Load

In cases when the long scripts are executed by the web server, the client connection with the web server stays open until the script finishes. This is not a good thing since the web server's task is to execute the request as fast as possible and give the result. But if the connection stays open then one of the web server workers(process) will be busy for a long time. And if a high amount of these scripts will be executed at the same time then all the workers (apache MaxClients) will be busy executing them thus the server will simply stop responding to any new requests, resulting in downtime.

That's why when processing a user's request you should execute the script in background using php-cli to keep the server load as low as possible. If needed you can use AJAX to check the status of the script exection.


Feel free to comment and share the article. Also don't forget to check out and use jsDelivr.

Tuesday, April 9, 2013

Where are JavaScript and the web going?

by Simon St. Laurent

This post originally appeared on the O'Reilly Programming Blog (http://programming.oreilly.com/2013/04/where-are-javascript-and-the-web-going.html). It’s republished with permission.

JavaScript and HTML5 just keep moving. One day it’s form validation, the next animation.
Then it becomes full-on model view controller stacks getting data from sensors on devices and communicating with back-end servers that are themselves largely JavaScript.
Peter Cooper and I (Simon St. Laurent) have tried to capture some of this power in the upcoming Fluent conference, so that attendees can find their ways to the tools that work for them. We also have an online preview coming this Thursday, April 4th.
Peter and I paused for a moment to talk about what we’re doing and where we see JavaScript and the Web heading. Though we work together on the conference, our perspectives aren’t quite the same, something I think works out for the better.
Highlights include:
  • Different tiers of technology adoption (discussed at the 2:41 mark)
  • “3-D demos don’t really interest the main market, whereas doing medical visualization, stuff like that, is more mass market” (5:42)
  • “The experimental end with robots … Nodecopter” (9:30)
  • JavaScript crossing over to the server with Node, or a polyglot world? (11:27)
  • Can frameworks or other languages that compile to JavaScript address modularization and code management questions? (14:50; and more on enterprise development at 17:43)
  • Learning from Ruby and Rails’ RJS experience (22:40)
  • Learning JavaScript “to get the job done” (26:08)
You’ll find our full discussion in the following video:



And dont forget that the early registration for Fluent Conference 2013 is ending April 10. Use our promotion code to get a 20% discount: "JSDEL"

Tuesday, February 26, 2013

JPEG optimization tools benchmark

Intro

I have a web project that hosts more than 15.000 images of various sizes from 300kb up to 10MB.
In total these images take about 8GB of space. These images are served from a small VPS with 365MB of RAM and optimized LAMP stack with  Nginx as reverse proxy.
Since I am a performance freak, I want to speed up the image serving as much as possible.
But before tweaking any server settings I have to optimize the images themselves.
For this I started looking for linux JPEG optimization tools and found a few, no idea which one is the best so I decided to run a few benchmarks and share the results with the rest of you.

List of tools


jpegrescan- A lossless jpeg optimization script written in Perl. Created in 2008 and hosted for a long time on a pastebin page it doesn't inspire a lot of confidence, but why not.

jpegtran - A popular tool for lossless jpeg optimization.

JPGCrush - Found only as a comment on hacker news without any documentation or info. Lets do this!

jpegoptim - Maybe the most popular tool for lossless and lossy image optimization


imgopt - A rather simple bash script that uses multiple tools at the same time to achieve maximum optimization.



Benchmarks

For the benchmark I am going to use the following:
4 random images from /r/serverporn.
My own image collection of 872808kb.


First I am going to test the 4 random images
Name Type Parameters Total size before (KB) Total size after (KB) Difference
jpegrescan lossless none 3772 3556 -5.726%
jpegtran lossless -copy none -optimize 3772 3724 -1.273%
jpegtran lossless -copy none -optimize -progressive 3772 3560 -5.62%
JPGCrush lossless none 3772 3772 0% *
jpegoptim lossless --strip-all 3772 3724 -1.273%
jpegoptim lossly --strip-all --max=90 3772 3236 -14.21%
imgopt lossless none 3772 3724 -1.273%
*Not sure where is the problem. It run just fine with no results. I will be excluding it from the next benchmark.

And now some heavy testing. I have a directory with 2400 images and a total size of 853MB.
Lets see how the tools are doing on a larger scale.

Name Type Parameters Total size before (KB) Total size after (KB) Difference
jpegrescan lossless none 872808 756976 -13.271%
jpegtran lossless -copy none -optimize 872808 797764 -8.598
jpegtran lossless -copy none -optimize -progressive 872808 770764 -11.691%
jpegoptim lossless --strip-all 872808 819896 -6.062%
jpegoptim lossy --strip-all --max=90 872808 606260 -30.539%
imgopt lossless none 872808 832072 -4.667%


Summary

I didn't expect this, jpegrescan has the best lossless compression compared to all other tools including the most popular ones. Of course it took about 4-5 times longer to finish, but still, who knew.
And of course the winner is jpegoptim with lossy compression and quality of 90.
I think this the best option, since the users can not tell the difference between 100 and a 90 quality but the size reduction is significant.

P.S Do not forget to check out the new redesigned jsdelivr.com

Friday, February 15, 2013

jsDelivr 2.0 changelog and some thoughts

I am happy to announce jsDelivr's first redesign.
Its now based on Twitter's Bootstrap and features a number of improvements. 
Here is a changelog:
  • The origin server was moved to Github. It means that all changes made to the Github repo are synced to the CDN. I hope this will help to create a community that will help jsDelivr grow even bigger.
  • The homepage is not static any more. It shows the first 5 projects in the DB.
  • All results now only show 2 CDN links by default. A "Show more" button will allow you to see the rest of the links. The result is a much cleaner and browsable website.
  • Before, to view the links of an older version of a project you had to be on the project's page because the project name was taken from the URL hashbang. You could not use it directly in the search results. This was fixed and you can now use it anywhere you want.
  • When you request the update of a project you can now enter your email. This will resolve an issue I had. Half of the update requests were not processed because I could simply not find the new version. Now I will be able to contact the user to get more information. 
  • Github links were added along with the homepage. If a project doesn't have a homepage then the github link will be used in both cases.
  • Better UI and typography. Everything is bigger and cleaner.
  • Search improvements:
    • A small delay was added before an Ajax request will run.
    • Unique pages and permalinks. Before a "bootstrap" search request or permalink would match at least 3 projects containing the word "bootstrap". Now its considered a unique permalink and will only match the project named "Bootstrap". If you want to see the others you will have to type for example "bootstra" or "bootstrap."
  • Experimental use of tags next to each project. Currently the system can recognize some jquery plugins,wordpress, bootstrap plugins and fonts.
  • An "Integration" button was added. Each time its pressed, it will run an ajax request to get the file list of the project and version selected. After that it will output only the javascript and css files of the project, ready to be copy pasted into your website.
  • The back-end was partially rewritten, making the code more readable and easier to extend and use.
  • A proper FAQ page was created. Send me emails if you want me to add anything else.
  • A Network page was added showing the location of jsDelivr's CDN. Once it goes live more information will be listed with details of the setup.
  • packages.php was moved to http://api.jsdelivr.com/packages.php. Its now hosted by AppFog,Memcachier and Xeround. 
  

TODO:

  • Fill in the "About" page.
  • More information regarding jsDelivr's infrastructure and back-end.
  • Donation page.
  • Finally create a favicon.
  • Fix "Show more" when loading a different version. (no idea how)  
  • Get project info from Github via API. (worth it?)
  • A real API. (Any suggestions?)

Just stuff:

  • Lots of webmasters are skeptic about using jsDelivr because they don't know anything about what happens behind the curtains. So from now on I am trying to make it as transparent as possible. If you are one of those users please email me with the information you would like to know that would make you comfortable with using jsDelivr. I would appreciate that and it would help many people.
  • I am always looking for possible ways to promote jsDelivr. Let me know if you think of something. Plus if you want to guest post/be an author/interview/benchmark or something else, do the same thing, contact me.
  • I cant wait for the new infrastructure to be ready. Right now I just wait for the sponsor companies to release some new features that will allow me to use them with jsDelivr. HTTPS is my eternal problem, if it wasn't for it, right now the jsDelivr network would be huge.
  • Any developers out there that want to host something on jsDelivr? The rules are really flexible, just let me know. It would be great for jsDelivr to become your official CDN.
  • Same goes for WordPress developers. wp-slimstats already has integrated jsDelivr as a feature. Anybody else interested?
I think thats it. You can mail me at contact@jsdelivr.com or leave a comment here.
Sorry for any grammar mistakes.

Monday, January 14, 2013

Nginx Load Balancing Basics

Nginx is a powerful high performance web server with a lot of features that can help high load projects to overcome their problems.
Here you can see a particular feature of Nginx that allows you to load balance the traffic across multiple external and internal(on same hardware) servers.

Load Balancing can come in handy when your only server can no longer handle all the incoming requests and you need to offload some of the load to an other server.
The load balancing is implemented by the HttpUpstreamModule that most of the times is included in Nginx by default.

Basic Config

Lets say you have deployed your website/webapp on multiple servers in the same network with the IPs 10.0.1.1,10.0.1.2,10.0.1.3 (of course it doesn't matter where the servers are. They can all be on the same physical machine, in the same network or even somewhere else in the internet).
All of the servers/backends will be combined into one upstream link by Nginx and then used as a single server in the rest of the configuration. 
This is an oversimplified principal of a personal "cloud" so lets call our upstream myCloud:

upstream myCloud{
  server 10.0.1.1;
  server 10.0.1.2;
  server 10.0.1.3;
} 

You can add as many servers as you want in there, including localhost,LAN and Online servers.
upstream myCloud{
  server s1.domain.com;
  server 10.0.1.2;
  server unix:/tmp/backend;
  server 127.0.0.1:8080;
} 

"myCloud" is now a registered upstream server that can be used as a parameter with the proxy_pass option. Now, wherever we use the myCloud upstream, Nginx, with the help of Round-Robin algorithm, will select the server to be used and proxy the received request to it.

Now you can use the new upstream link in your vhost config:

 
server {
  listen domain.com:80;
  access_log /var/log/nginx/proxy.log;
 
  location / {
    proxy_pass http://myCloud;
  }
}


Bind clients to servers

Often, it will be necessary for a single client to be served by a single server, not having different servers answering each request. For this, Nginx has the option ip_hash.
When ip_hash is turned on, the proxy server will remember the client's IP address hash and will use the same server every time.

upstream myCloud{
  ip_hash;
  server 10.0.1.1;
  server 10.0.1.2;
  server 10.0.1.3;
} 

Exclude Servers

If for some reason you need to temporary exclude one or more servers from being proxied by Nginx, you can use the "down" parameter:

upstream myCloud{
  server 10.0.1.1;
  server 10.0.1.2 down;
  server 10.0.1.3;
} 

Define priorities

You can define priorities by using a "weight" option for each server. The weight of a server roughly describes how often he will be used.
For example let's say the weight of the 10.0.1.1 server is 3, of the 10.0.1.2 is 1 and the weight of 10.0.1.3 is 2. 
In this case the first 3 requests will be proxied to server 10.0.1.1, the 4th to server 10.0.1.2 and the 5th and 6th requests will be proxied to server 10.0.1.3, after which the cycle will start again from the beginning.
The weight for all servers by default is equal to 1, but you change it as you wish.

upstream myCloud{
  server 10.0.1.1 weight=3;
  server 10.0.1.2;
  server 10.0.1.3 weight=2;
} 

Automatic Failover

If any of the upstream servers stops responding, then Nginx won't be able to connect to it and will serve the next available server from the "cloud".
The client won't actually experience any downtime but rather a long response from the server, which is not good. 
The next problem is that Nginx will try to connect to the non responsive server over and over again on each cycle, losing valuable time.
But with the parameter max_fails you can set a maximum amount of connection failures before Nginx marks the server as down and stops trying to connect there.
By default this option equals to 1, which means that after a connection failure Nginx will stop trying to connect for a certain amount of time. This is defined by the option fail_timeout and by default is 10 seconds.

upstream myCloud{
  server 10.0.1.1 max_fails=3 fail_timeout=120;
  server 10.0.1.2;
  server 10.0.1.3;
} 

Backup Servers

Backup Servers are used only when all of the normal upstream servers stop responding to requests. They are marked with the backup parameter.

upstream myCloud{
  server 10.0.1.1;
  server 10.0.1.2;
  server 10.0.1.3;
  server 10.0.1.8 backup;
  server 10.0.1.9 backup;
} 


That's it, please comment,like and share if you liked the post. 

Thursday, January 10, 2013

Hello World!



Here we go, my first post on the official blog of jsDelivr

I never actually had the time to properly present jsDelivr so this is my chance.

jsDelivr is a free public CDN that hosts javascript libraries and jQuery plugins, including all of the files they need to work (css/png).
It even hosts javascript files used by popular WordPress plugins, like WP SlimStat.
Other than that, fonts and CSS frameworks/files are also allowed.
Basically if a lot of websites use it then we probably can host it. The rules are very flexible.
Just send me an email if you are not sure if we allow whatever you want to host.

These are some of the key things that jsDelivr offers:
  • Speeds up the websites
  • Cuts the bandwidth bill
  • Offloads the server from extra requests
  • Allows developers to host their files on a fast CDN for free
  • Which allows them to offer direct links to their users for easier and faster integration.
  • HTTPS support
  • A free WordPress plugin for easier integration. 


The service is free and will stay this way. I do not plan adding any premium features or anything like that. It is a non-profit service that will live with the help of its sponsors, my funds and hopefully of future donations.
All of the traffic is sponsored by companies that agreed to help, like NetDNA. And the other stuff, like SSL certs, hosting, freelancers are all paid by me. So if you would like to help just send me an email, I will really appreciate that.


Tips:
Did you know that you can type "all" in the search box to view all hosted packages?

Plus you can get the list of all of our packages in JSON over here http://www.jsdelivr.com/packages.php and here including hashes http://www.jsdelivr.com/hash.php
In case you want to do something awesome with jsDelivr :)

Also did you know that all developers can request FTP access to the folder of their project to upload the new versions by themselves?


Thats it for now, I will try to keep the blog updated with jsDelivr news, plus to post interesting content in the area of high performance and website speed optimizations.

Thank you all!