Update: Access MyTubio stations without an account!
I understand some people are hesitant to fill out the 5 text fields and give their email address to some unknown website, this is why I allowed access to certain stations without needing an account.
As a “guest” you have read-only access to the stations. You can listen/watch the various songs, skip ahead, modify the slider values allowing you to control often “Liked” songs are played and how often duplicate songs are played. What you don’t have is the ability to like or dislike a song, and of course create your own private station with your own favorite songs. Essentially you are stuck listening to songs that the creator of the station likes. I includes some of the popular genres to try to please as many people as I can:
Rock – Seeded with awesomeness such as Slipknot, Disturbed, Metallica.
Electronica – Party with such artists as deadmau5, Paul Van Dyk, Armin Van Buuren, and more.
Dubstep – Have to have Dubstep. This one is seeded with skrillex and the keyword dubstep , so you get the newest “hits”
Chill – Relax and enjoy artists such as A.I.R., DJ Shadow, Rob Dougan, RJ2D, and Royksopp
Hip Hop – Seeded with top artists such as Lil Wayne, Drake, LMFAO, Eminem, and many more.
There you go, Enjoy!
Goodnight Sweet Apache (Increase performance with Nginx + PHP-FPM)
When running a VPS box with no swap and only 512M of RAM we cannot afford to run unnecessary memory hogs. Apache2 proved to be one of the biggest memory hogs on my little VPS. Running over 20 wordpress blogs, and several PHP+mySQL webapps had this box crawling and sometimes coming to a halt spewing “Cannot allocate memory” “fork: Resource unavailable” errors, basically bringing down my whole operation. The culprit was Apache2!
The solution: Nginx + PHP-FPM
Nginx is a light weight and extremely quick http server. It has all the features the big ol clunky Apache has, yet it uses barely any resources and serves content extremely fast. The main difference is asynchronous handling of requests instead of using threads as Apache does. Basically a small number of Nginx “worker” processes can plow through enormous stacks of requests without waiting on each other and without synchronizing; they just “close their eyes” and eat the proverbial elephant as fast as they can, one bite at a time. Nginx also uses a memory pool which avoids memory leaks, makes allocs and dealloc very quick, and avoids memory fragmentation. Not only is it highly modular, but it also has has cool configuration features such as allowing you to do code blocks with “if” statements and events.
Apache, by contrast, approaches large numbers of requests by spinning off more processes to handle them, typically consuming a lot of RAM as it does so. Apache looks at the elephant and thinks about how big it is as it tucks into its meal, and sometimes Apache gets a little anxious about the size of its meal. Nginx, on the other hand, just starts chomping.
A great quote by Chris Lea on the Why Use Nginx? page: “Apache is like Microsoft Word, it has a million options but you only need six. Nginx does those six things, and it does five of them 50 times faster than Apache.”
However, while being awesome at serving static files and pages, Nginx is a bit slow when it comes to serving dynamic pages. No problem! This is where PHP-FPM comes in!
PHP FastCGI Process Manager, PHP-FPM can turn on or turn off new PHP processes as dictated by the server’s load. This makes it a much smarter and more powerful package; it can consume fewer resources and at the same time scale transparently under load and maintain speed. With FastCGI, PHP acts more akin to an application server. PHP-FPM, as well as spawn-fcgi, manage this; loading and killing PHP instances as needed. This has a lot of benefits, not the least of which is reduced memory overhead.
Excited and ready to install? Let’s do this!
yum install nginx
For php-fpm I had to use http://rpms.famillecollet.com/ Enterprise Linux 5 repo.
yum install php php-fpm php-mysql (and any other modules you need)
In /etc/php-fpm.d/www.conf I changed the following to optimize performance on my little box:
Improving performance with Memcached
MyTubio runs on a VPS box for now. It has 512M Ram and no swap. When running apache2+mysql memory was very sparse and would easily get consumed 100% if there were many simultaneous connections, leading to unable to allocate memory errors, ”cannot fork: Resource temporarily unavailable” errors in the shell and so on. Not to mention the slow downs from MySQL having to process every query and Apache having to render every php page.
Problem: MySQL is using up a ton of CPU, sites load slow, many slow queries found.
Solution: Memcached. Web apps which deal with massive amounts of data in the DB such as MyTubio frequently use high CPU intensive queries with counts and joins and so on. The more users using MyTubio the more impact this has on the DB. Enter Memcached…
What is Memcached? Its basically an in-memory Key-Value store. The advantage is that we can store anything such as SQL query results in the memory, and retrieve it with lightning speed because there is no FS I/O needed. This is particularly useful if your web app does many “selects”. MyTubio does tons of selects, for example, it has to get songs for each station, history of songs played, and these selects are from large DB’s and sometimes take long. So implemented Memcached as a middle man between the web app and MySQL. It was surprisingly easy.
Install memcached (yum install memcached)
Install php-pecl-memcache module (not memcached)
Run memcached (/etc/init.d/memcached start)
In your PHP code initialize the memcache object:
global $memcache;$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");
Create a wrapper class for mysql_query such as this:
function mysql_query_mcd($sql) {
global $memcache;
$key="SQL:".md5($sql);
$data = $memcache->get($key);
if($data === false){
$data = array();
dbconn();
$res= mysql_query($sql);
while($rec = mysql_fetch_assoc($res)){
$data[] = $rec;
}
// cache for 10 mins
$memcache->set($key, $data, 0, 60*10);
}
return $data;
}
The key is created from the SQL queries MD5 checksum, which means every query gets its own unique key for which it stores a result as an associative array. This is great because we don’t need to create arbitrary keys for each query and remember them. So anytime a query is called, it creates a key based on the md5 sum, and then it checks Memcache to see if the key exists with a memcache->get, if it doesn’t, then we must execute the query in MySQL and store the result in memcache so it will exist next time we do a get. If it does exist, then we just return the result from the memcache, MySQL is left alone.
Edit the way your web app queries and iterates rows:
Before:
$res=mysql_query($query);
while(list($col1,$col2,$col2)=mysql_fetch_row($res)) {
// do stuff with each column
}
After:
$resm=mysql_query_mcd($query);
foreach($resm as $key=>$res) {
list($col1,$col2,$col2)=array_values(res);
// do stuff with each column
}
The change is very simple and quick. First we assign $resm to catch the associative array that our mysql_query_mcd function returns, then we create a foreach loop which iterates each row of the result, then we the list function sets the variables for all of the array values of row $res. And the rest of the code stays untouched! And of course if you rely on counts then you would replace mysql_num_rows($res) to count($resm);. Now this select query’s results will be cached for 10 mins, so MySQL is only touched once in 10 minutes!
CAUTION: Because we have a 10 minute cache expiration for all queries, this means that data may be 10 minutes old, so if your data is updated before 10 mins is up, you must invalidate the key for the query that selects the data in memcache with a “delete” so that the data is updated. This method is best used for selects which do not get updated very often, or does not need to be current.
In MyTubio’s case, I use this method to cache all songs for a particular station id when a user starts listening. And to select a song i just randomly pick one out of the cached array. The array will get updated 10 minutes later with a new song list and the user will never notice this.
Hello world!
First post!
MyTubio is now in Beta stage. The core features work great. (On Chrome and Firefox only).
Still to come:
- Add/Edit/Remove Individual Songs per station.
- Android phone app
Please send any feedback, bugs, comments, praises, flames… The more the better!
