18 Jan 2011

Writing a PHP daemon application

There is a special group of applications that require a different PHP script execution model. For example:

  • A chat server (or any other kind of socket server therefore)
  • A HTML5 WebSocket server
  • A web crawler, data harvester or any other real-time service

All of the mentioned applications need to be run in the background as daemons – something that PHP was never designed/supposed to be good at. The plain C language is a weapon of choice when it comes to writing a daemon implementation, but then again, if the application in question does not depend on high performance and concurrency – PHP can do the job quite well.

This article contains some of my past experiences with daemon-like PHP scripts. Hopefully it will be useful to the rest of PHP community.

Using PHP command line interface

CLI executable should be used for running daemon scripts. A simple invocation would look like this:

php /path/to/run.php

Further command line arguments can be used to fine-tune your daemon process:

php \
-f /path/to/run.php \
-c /path/to/custom/php.ini \
-d error_log=/var/log/chatserver

In the example above a custom php.ini configuration file will be used and all daemon related error messages will be logged to a separate /var/log/chatserver file.

PHP command line process has slightly different configuration from other SAPIs. The most important change is that script execution time limit is disabled by default and so you do not need to concern yourself with set_time_limit() calls or max_execution_time INI setting. Other configuration options should be tweaked depending on your requirements. You may want to disable memory limit for example:

# From command line
php ... -d memory_limit=-1

The run loop of a daemon

A daemon should not terminate as is the case with a regular PHP-HTTP request (or crontab job therefore). To achieve this one can write a run loop like this:

while (true) {

    ... // Process tasks
}

And a socket server might have the following loop implementation:

// Initialize and bind non-blocking listening server socket
$server_socket = ...;

while (true) {

    // Accept new client connections
    if(($client_socket = socket_accept($server_socket)) !== false) {
        ...
    }

    ... // Process all connected client sockets
}

Provided loops do not block on anything and would quickly consume 100% CPU. It depends on your implementation but you may want to hang for a while at certain point with a sleep() or usleep() function to avoid that.

Using upstart to control daemon process

A daemon has to run in the background and needs to be controlled from command line. It also should start/stop on server reboots. To achieve this on a Unix-like system one can write a System-V init script or an upstart job. I am a huge fan of upstart and prefer it for its features and simplicity. Note that upstart is the default init daemon in Ubuntu and if you are running that you are more than likely have everything ready and in place.

Imagine you want to write a control script for a PHP chat server. With upstart you need to create a new job at /etc/init/chatserver.conf:

# The default run-level for Ubuntu/Debian is 2
start on runlevel 2
stop on runlevel [!2]

# Upstart can respawn your daemon process on segfault/crashes/etc
respawn
respawn limit 2 10

# A daemon should not run as a root user
# We are using "www" user here
exec sudo -u www php -f /path/to/run.php ...

Controlling your daemon from command line is now trivial:

start chatserver
restart chatserver
stop chatserver

A System-V control script would be a bit more complicated and actual implementation would depend on target distribution. However, one could use Debian start-stop-daemon or similar utility to simplify things significantly.

Custom process title with proctitle extension

While at this point you should have a fully working daemon setup there are still some extras you may want to consider adding. One of them is a custom process title functionality that is provided in Linux/BSD systems using setproctitle() call (and then visible in ps command output). PHP has a tiny wrapper/binding around this feature in PECL proctitle extension.

To install it – run the following from command line (and then enable this extension in your php.ini configuration):

pecl install proctitle-alpha

Building on that chat server idea you can provide a number of active client connections in the process title. It should be updated periodically when the number changes with the following function call:

setproctitle('chatserver ('.count($client_sockets).' clients)');

Running a ps axf command would result in:

PID TTY      STAT   TIME COMMAND
442 ?        Ss     0:00 nginx: master process nginx
443 ?        S      2:07  \_ nginx: worker process
...                      ...
472 ?        Ss    58:00 chatserver (3 clients)

Handling daemon log files

As already pointed out previously – you can easily override default php.ini configuration from CLI to fit your daemon implementation. One thing worth considering is setting up file-level error logging and redirecting daemon log entries to a separate file with error_log directive.

Once you have this configured – any general PHP warnings/errors will be logged automatically based on your error_reporting directive. You can also log other daemon-related log entries using the following function call:

error_log('Rejecting client - maximum number of clients reached');

Further, you may want to configure logrotate to rotate your old daemon log files. A simple logrotate configuration entry would look like this:

(Located at /etc/logrotate.d/chatserver on Ubuntu)

/var/log/chatserver {
    weekly;
    rotate 4;
}

This would rotate chat server log file every week (keeping up to 4 old rotated log files).

A word on parallel processing, forking and the like

You may have already heard that PHP lacks any kind of kernel-level threading support. And I would go as far as to say PHP is the wrong tool if you need this kind of behavior in your daemon application. Still, it’s worth mentioning that there are some hacks/methods floating around that may be worth considering if you truly need this functionality.

One relatively safe option is to use process forking with pcntl_fork() function call (part of Process Control extension). Keep in mind that PHP processes are fat and multiple forked childs will use a lot of memory. You may want to custom-compile your PHP CLI binary to disable any extensions/features that are not used in your daemon application. Another issue you may run across is inter-process communication and data sharing between your daemon processes. You may want to look at Semaphore extension that has some IPC facilities.

There is also this brave attempt worth checking that has an implementation of user-land PHP threading. The functional interface looks really great and tempting but it does require a custom PHP re-compile with some patching. I haven’t had the chance to try this threading support myself so If you did had a look at it – be sure to leave a comment or two.

12 Dec 2010

PHP data caching techniques

Caching intermediate data is the most primitive and yet the most rewarding optimization technique where you don’t need to fiddle with any complex algorithms or premature optimizations. If you are into PHP you should be aware of all the best practices and the right tools for this job to make your websites fly.

Static scope variables

This is a quick and effective way to cache function/method results using language-supported static scope variables. Consider an example that wraps some complex computation:

function getValue() {

    static $value;

    if (is_null($value)) {
        $value = ...; // Compute
    }

    return $value;
}

Now whenever you use this function in a code and whatever number of calls you make to it – the value will be computed only once.

This caching technique does not depend on any external extensions and is supported within language level. Since statically scoped variables are only accessible within local functions that they are defined in – it might be difficult to invalidate the cache. Usually, this requires passing some sort of boolean $use_cache variable or resolving to using static class variables instead.

Static variables are not shared between PHP processes and only can be cached for a short time – spanning script execution lifetime. O good candidate is a method that is called from multiple places many times – like holding on some sort of user state or a result of mathematically intensive operation.

The same functionality can be implemented using global variables, but that would result in global namespace pollution and is discouraged.

APC shared memory functions

PHP is a semi-compiled language and that means that every script is compiled not directly to machine code but to an intermediate level known as opcode instruction-set (bytecodes). This compilation step is CPU intensive operation and has to be done every time the script is executed. APC (Alternative PHP Cache) is an extension that skips this compilation step by caching opcodes in memory.

While APC is usually advertised just for this opcode cache functionality – it comes with some extras like set of shared memory access functions:

function getCurrencyRates() {

    $rates = apc_fetch('rates');

    if (empty($rates)) {

        // Query from database or external API
        $rates = ...;

        // Exchange rates will be cached for 1 hour
        apc_store('rates', $rates, 3600);
    }

    return $rates;
}

Now the advantage of this approach is obvious – it’s the use of shared memory. This type of memory is shared between different processes/threads and, unlike static variables, data cached this way will persist between multiple requests.

To invalidate the cache one can use time-to-live (TTL) values as with the example above or a set of functions:

apc_delete('rates');        // Remove $rates cache
apc_clear_cache('user');    // Remove all user cache variables

Some other notes on APC shared memory support:

  • There is an INI configuration directive for limiting cache to exact memory size. With proper TTL values this gives you the ability to prioritize cached data, where in the case of hitting a memory-limit expired/oldest values will be expunged from the cache.
  • From a performance point of view – static variables will always going to be faster than apc_fetch/apc_store functions as shared memory access needs to be locked and synchronized to prevent race conditions.
  • APC is quite popular, is maintained by core PHP developers and (very likely) will be bundled with PHP 5.4.

Memcached for large distributed caches

Once the website starts getting a lot of hits you are eventually tasked to distribute the load among different machines. As a result this usually involves moving PHP into multiple application servers. If you happen to use APC for caching before – every application server has now it’s own separate and duplicate cache.

Memcached on the other hand is a distributed key-value storage daemon. It can be deployed on a separate dedicated server or on the same PHP application stack. It’s important to understand that there is no synchronization/replication between multiple Memcached servers and that they are completely unaware of each other. The actual server that will be used for storage is chosen on the client side by hash algorithm based on supplied data “key” value. This is why, unlike APC, cached data is not duplicated between different machines and the memory is better utilized for large distributed applications.

The API is very similar to APC shared memory functionality. The same currency exchange rate example implemented using Memcache PHP extension:

// Assuming there is only a single memcached daemon
$memcache = new Memcache();
$memcache->pconnect('...');

function getCurrencyRates() {

    global $memcache;

    $rates = $memcache->get('rates');

    if ($rates === false) {

        // Query from database or external API
        $rates = ...;

        // Exchange rates will be cached for 1 hour
        $memcache->set('rates', $rates, 0, 3600);
    }

    return $rates;
}

Invalidating the cache is similar to APC – using TTL functionality or a set of functions:

$memcache->delete('rates'); // Remove $rates cache
$memcache->flush();         // Remove all cached data

Local APC caches are always going to be a faster technique compared to Memcached solution. There are some network latency involved as the client needs to communicate with the server daemon over a dedicated text-based protocol.

In-memory database tables

While not directly related to PHP – most of the database management systems have in-memory table implementations. Data stored in that kind of table does not persist between restarts and is guaranteed to be kept in memory and never flushed back to disk. This usually means really fast access to rows making these tables suitable for data caching.

MySQL provides in-memory tables using MEMORY storage engine. While data will be purged between server restarts – table schema will persist:

CREATE TABLE test (...) ENGINE = MEMORY

PostgreSQL has temporary tables that persist only for a session – to cache data in a temporary table one would have to use persistent database connections:

CREATE TEMPORARY TABLE test (...)

SQLite can create entire database in-memory but is subject to the same restrictions as PostgreSQL – data will persist only for a session and one would need to use persistent connections to keep it alive between multiple requests:

$pdo = new PDO(
    'sqlite::memory:',
    null,
    null,
    array(PDO::ATTR_PERSISTENT => true)
);

So what can you do with in-memory table? While this will never going to be as fast as APC/Memcached key-value access – you get the power of SQL. Cached data can be filtered, ordered, grouped or even joined with other table data.

Simple file-level caches

Flat file caches should be an alternative to the mentioned methods above and only used when the system does not have required extensions or the data in question is not suitable to be kept in-memory (due to size for example).

Since caching is usually done for performance, and performance optimizations are a result of high concurrency – you should always utilize file locking to prevent read/write race conditions:

// Acquire exclusive lock when writing
file_put_contents('...', $data, LOCK_EX);

// Use shared locks for reading
$fp = fopen('...', 'r');
flock($fp, LOCK_SH);
$data = stream_get_contents($fp);
flock($fp, LOCK_UN); // Release the lock
fclose($fp);
20 Nov 2010

New to PHP 5.4: Traits

As a long-time internals.php mailing list reader I am going to tell you a small secret – the first alpha release for PHP 5.4 should be just around the corner. This release is packed with some welcome new language features, usual bug fixes followed by some performance and memory management improvements. One of the noteworthy language additions are Traits – a brand new horizontal code reuse mechanism.

The domain of Traits

When a class is extending another class it is said that the child class is now a kind-of parent class – it has common properties, methods and functionality. Thus, inheritance provides access to all non-private code of a parent class following a pattern of vertical code reuse.

However, while inheritance is a great way to reuse code – it does not solve all duplication issues. There are times when two objects might require common functionality but are not supposed to be derived from the same parent class. Consider an example of two classes:

class A { ... }
class B extends ArrayObject {
    // Uses SPL ArrayObject functionality
}

Now imagine one is required to make both classes act as singletons. With current PHP 5.3 feature-set this is a problem. Extending from a common Singleton class is not possible for class B as PHP OOP model is heavily influenced by Java and is limited to only a single parent class in the inheritance tree. In a language like C++ one could solve this issue with templates or multiple inheritance (mixins in other languages) – none of which are available in PHP.

While traits are technically different from mixins – they are both designed to fill the same gap left by a single-parent inheritance model:

trait Singleton {
    public static function getInstance() { ... }
}

class A {
    use Singleton;
    // ...
}

class B extends ArrayObject {
    use Singleton;
    // ...
}

// Singleton method is now available for both classes
A::getInstance();
B::getInstance();

As the original author of the patch Stefan Marr pointed out – traits are nothing more but a compiler assisted copy and paste. Common functionality can be grouped inside a trait definition and then included within a class with use statement.

Conflicts and Aliases

When two traits have a method defined with the same name and then both are used within the same class – a name conflict will occur. While this is probably not going to be a common case it’s worth mentioning that there is a syntax just to solve that kind of conflict state:

// Assuming that trait A and B both have a method hello() defined
class Test {
    use A, B {
        B::hello insteadof A;
    }
}

// Test class will now have "hello" method implementation of trait B

This is achieved using a new insteadof operator that excludes one method in favor of another. And if there is a need to use both hello method implementations in the same class – one can use further aliasing options:

class Test {
    use A, B {
        B::hello insteadof A;
        A::hello as helloA;
    }
}

// Test class will now have "hello" and "helloA" methods

As an extra – aliasing operator as can also be used to change method visibility and other modifiers (the only exception is static which is not supported):

use A {
    testA as protected;
    testB as final;
}

Expressing trait requirements

Trait method definitions support all modifiers just like regular class methods do – that includes visibility modifiers, final, static and abstract. The latter can be used to define abstract methods expressing requirements for this particular trait:

trait Printer {

    public function print() {
        print $this->getData();
    }

    // Should be defined in a class that uses Printer trait
    abstract protected function getData();
}

Traits are stateless and limited to only method definitions and abstract requirements – however, due to the very dynamic PHP nature it is possible to use object instance variables or informal methods as well. For example, consider this trait implementation:

trait A {

    public function hello() {

        // Code that depends on instance variable "test"
        if (isset($this->test)) { ... }
    }
}

The code inside if statement will be executed when the class has an instance variable “test” defined. While this will work as intended creating an informal protocol between trait and a class – a better approach would be to define setters and getters for required data as abstract trait method definitions mentioned earlier.

Other notes

  • Traits only take part in the process of building a class and do not add any new run-time semantics. That means that usual PHP object-oriented functionality (like late static bindings) work as expected when combined with traits.
  • Traits integrate into the precedence order of method overriding where methods from the current class override trait methods, which in return override methods from the base class.
  • Traits can be composed from other traits (the same way classes use traits).
  • Traits are not a new concept to PHP – other similar implementations are available for Self, Perl 6, Fortress, Scala and other programming languages.

Further reading

There is no official documentation for traits yet just a single RFC document that is quite up-to-date with current implementation. Some further examples can be found by looking at official test cases.

21 Oct 2010

Chrome text-shadow blur bug

More than a year ago I have reported a Chrome text-shadow bug. This bug is related to “blur” rendering part of text-shadow CSS rule. Chrome has just hit version 7 and this issue has not even been assigned a milestone yet. Please help us push it forward by voting for it (hit the star button).

If you are wondering what the bug looks like – see Twitter documentation page with Firefox and then Chrome respectively.

17 Oct 2010

X-UA-Compatible: pushing Internet Explorer to the edge

Internet Explorer 8 is shipped with two rendering engines – the old IE7 and a completely new and rewritten engine for IE8. That relatively new engine has finally dropped support for crazy hasLayout stuff and despite being slow in today’s standards – it actually brings a very complete CSS 2.1 implementation. I have yet to come across any CSS issues when comparing Firefox-to-IE8 layouts.

Since this was a major rewrite and some outstanding IE7 bugs could not be fixed in a backwards-compatible way – a new compatibility button was introduced. This button is visible on the right side of address bar just before the reload/stop buttons. As an end-user you can click it if the website is not rendering properly and as a web developer you can quickly test your CSS styles between IE 7/8 rendering modes.

Now with that new compatibility behavior IE8 has also introduced X-UA-Compatible <meta> tag that can be used by web developers to target specific browser versions. Like for example, if you had a website that was working fine in IE7 and then is broken all around in the new IE8 you can set “IE=7” and it will use old rendering engine silently. This is an easy way to fix things, but then again is also holding back the web (and IE) from moving forward.

A good practice would be to:

  • use standards mode doctype declaration (like HTML5 <!DOCTYPE html>)
  • fix IE 7/6 rendering issues with CSS hacks or conditional comments

and then use a little neat trick to maximize Internet Explorer user experience by means of the following <meta> tag:

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

This will trigger two things:

  • Will always use the latest Internet Explorer rendering engine available AND will completely remove compatibility button – thus slightly simplifying already bloated IE8 user interface. Note that “edge” is a valid value as per MSDN documentation.
  • If Google Chrome Frame is installed it will use WebKit for rendering and V8 as JavaScript engine.

This meta tag can be wrapped around in a pseudo server-side if (PRODUCTION) { ... } condition so you can still toggle between different modes in development.

The advantage of using edge instead of not using it at all is that you remove compatibility button from Internet Explorer user interface and you effectively disable X-UA-Compatible behavior! It’s like saying to the end-users: yes, I have tested it both on IE7 and IE8 and it’s compatible everywhere.

26 Sep 2010

Add gzip/deflate compression to PHP HTTP streams

As already pointed out in my previous blog entry – PHP streams are a great feature (yet overlooked) that among other things can be used to POST data without cURL extension. But most of the time you write code that is just GET'ing some web content, like for example:

file_get_contents('http://example.com');

Now PHP has a couple of methods for viewing response headers, but basically none that could show actual request ones. So I used Microsoft Network Monitor for this purpose, and here is what’s really happening behind the scenes:

GET / HTTP/1.0
Host: example.com

Seems good enough if not for the fact that it is using now legacy HTTP protocol version (1.0). That means it is missing some newer features – like persistent connections, chunked transfer encoding and proper compression support that was introduced with HTTP 1.1.

Making it HTTP 1.1 compatible

Starting with PHP 5.3 – a new HTTP context option (protocol_version) was added that can be used to switch to 1.1 version. And we can use it (combined with other extra headers and features) to add gzip/deflate compression support like this:

// Our new and improved HTTP context
$context = stream_context_create(array(
    'http' => array(
        'protocol_version' => 1.1, // HTTP 1.1 compatible
        'header' => array(
            'Connection: close', // No Keep-Alive
            'Accept-Encoding: gzip, deflate'
        )
    )
));

// Make HTTP GET request
$result = file_get_contents('http://example.com', false, $context);

// Decompress content
$result = 'data://text/plain;base64,'.base64_encode($result);
$result = file_get_contents('compress.zlib://'.$result);

You will probably want to wrap this block in a function (like getHTTP) as this is just a pseudo-code. We use two extra headers here – by Connection: close we tell servers that persistent connection feature will not be used (PHP does not seem to support it internally and if not specified will actually hang for a while at this method as per Keep-Alive). And by Accept-Encoding: gzip, deflate we are saying that we support gzip and deflate compression methods and the server should send us back compressed content.

The next step is to decompress this content – and this is where zlib extension comes to the rescue. It is enabled by default on Windows and can be compiled-in with —with-zlib configure option on Unix/Linux systems. This extension defines it’s own compress.zlib stream wrapper that we use in the code above. Internally this zlib wrapper is using gzopen() method and is smart enough to not decompress content that is not compressed (that’s why there is no code to check for Content-Encoding response header).

Note: technically we could chain compress.zlib on top of a regular http wrapper ("compress.zlib://http://example.com" in this case), but there is a bug in current PHP stream implementation and we cannot set context options for chained wrappers. So the code above is using intermediate code/hack with data URL wrapper.

And if you are wondering how our HTTP request headers look like now – here they are:

GET / HTTP/1.1
Host: example.com
Connection: close
Accept-Encoding: gzip, deflate

Much better! This functionality requires PHP 5.3+ however.

Impact on a real-world application

I have a side-project running on a dedicated VPS host and it’s handling a lot of remote HTTP background requests. You can see my bandwidth savings with enabled compression support in the following chart (blue is inbound traffic, green – outbound):

Bandwidth savings with PHP gzip/deflate compression

I have also included CPU usage graph since CPU is used for decompression. Don’t mind these spikes as I was probably compiling something. The point is that CPU impact here is somewhat non-existent.

Update

That mentioned bug has now been fixed in 5.3.4 version and so it is possible to simplify code like this:

$result = file_get_contents(
    'compress.zlib://http://example.com',
    false,
    stream_context_create(array(
    'http' => array(
        'protocol_version' => 1.1,
        'header' => array(
            'Connection: close',
            'Accept-Encoding: gzip, deflate'
        )
    )
));
23 Sep 2010

Idea for a PHP Validator

How about creating a PHP code validator? Got this idea by looking at tokenizer and reflection extensions. I doubt I will find the time to work on this myself but then someone else might be interested to pick it up.

From user’s point of view there could be a form made of a large textarea box and a single file upload input. One could paste code snippet on that textarea or upload a ZIP'ed source code archive (or a single .php file) for validation.

What’s the result?

Validation page could show an output like:

PHP version required: 5.1.4+

Required extensions:
    - gd
    - pdo
    - pdo_pgsql
    - etc..

E_STRICT compatible: No

Lines of code: 11,453 (36% comments)

(and anything else I can't think of right now)

Optional/additional information could be provided – like, for example, what’s the cause (think function name and line number) of that 5.1.4+ requirement.

What about implementation, what’s the cache?

As already suggested – implementation should rely on tokenizer/reflection extensions and not use preg_match() or any kind of custom parser. As for determining required PHP version I can think of two things:

  • Use php.net documentation to get function/method/feature requirements (can be automated to some extent)
  • use tokenizer extension to analyze uploaded code and apply version requirements (for example – a T_ABSTRACT token implies a 5.0.0+ version)

Getting required extensions should be quite simple, if not for code like:

if (extension_loaded('apc')) { /* stuff */ }
if (function_exists('apc_store')) { /* stuff */ }
if (method_exists('ZipArchive', 'open')) { /* stuff */ }

// or the worst case possible
$func = 'apc_store';
$func(...);

// or use of get_defined_functions(), get_loaded_extensions()

This of course does not mean it’s not possible to implement – it’s just that you will have to track these things in your validator code.

Who could make use of this tool?

  • Someone writing a library/module
  • Administrator deploying a PHP application/website
  • Forum/StackOverflow/etc user pasting code snippet in that textarea to quickly check requirement
  • And anyone else not too sure about their code

So what do you think? Is it worth the time? Are there any other technical issues I am not aware right now that could hinder implementation?

21 Sep 2010

POSTing data without cURL extension

When it comes to making HTTP POST requests the Web seems to be full of code samples that use cURL extension. Don’t follow them, don’t copy them – it’s flawed. PHP has support for this natively starting with 4.3 version (released 8 years ago).

// Your POST data
$data = http_build_query(array(
    'param1' => 'data1',
    'param2' => 'data2'
));

// Create HTTP stream context
$context = stream_context_create(array(
    'http' => array(
        'method' => 'POST',
        'header' => 'Content-Type: application/x-www-form-urlencoded',
        'content' => $data
    )
));

// Make POST request
$response = file_get_contents('http://example.com', false, $context);

Be sure to read more on PHP streams.

20 Sep 2010

Create your own feeds with Feed43

I use Google Reader to save time and stay in touch with all that is happening on web development land, this includes all kinds of news websites, blogs and libraries/tools. Like for example, I am interested when a new release of Smarty is available, but then again, some websites like smarty.net do not provide their own RSS or Atom feeds. This is where services like Feed43 (pronounced “Feed For Free”) shine.

With Feed43 you can manually create a feed for a website that is missing this crucial functionality. What you actually do is define a custom content extraction rule using search patterns (think simplified regular expressions). And in the end you have a link that you can drop into your favorite feed aggregator. A simple, useful and interesting web service. It’s worth mentioning that it is free. There are paid plans that basically update your feed more often (on a free plan feeds are updated every 6 hours) and remove a footer note from each item indicating that this was actually delivered using Feed43. So in short, give it a try if you need anything like that.

I wish they added another feature tho – ability to define a set of search patterns for inner item pages (from already extracted item links). Like some websites have news pages but they only publish item titles or short descriptions and actual content is on an inner page. One could write a search pattern that will be used for every inner page to get full item description. That would allow to create full-description feeds and IMHO should not be that complicated to implement. This could be a paid plan feature and is purely a suggestion to the author.

Another interesting way to use this service would be to create feeds for your own website and then publish and promote them to your users. Think of the benefits – you don’t need to invest time in your own implementation and you save bandwidth by means of Feed43 caching. Note, this is not the same as FeedBurner where you still need your own feed implementation – you could, however, proxy your feeds using FeedBurner for even more features (like statistics).

And about that smarty.net issue – here are links to some of the public feeds that I have created for some of the websites that are too lazy to implement RSS feeds natively:

19 Sep 2010

Gmail with your custom @domain.com

I use Gmail as my main email client for both work and personal use and I love it. However, what I always thought would be great to have is an interface and functionality of Google email client under your custom company domain (like @yourcompany.com). Lo and behold, it seems there is a way to do just that – using Google Apps.

Essentially, Apps is more than email as it also provides a connection to other Google services like Docs or Calendar. But in this case I was more interested in Gmail setup only and here is a step-by-step guide on how to start rolling your own @domain.com emails.

First, you need to sign up for Google Apps. Did I mention it is completely free? Free in a way as Standard Edition is limited to 50 accounts, but then there is also an option to add nicknames so a single account can handle both contact@ and info@ emails.

Once you have completed that sign up process you will be asked to verify your domain ownership. At this point you need access to DNS settings for your domain. This is usually located somewhere on your domain name registrar or hosting provider website. Once you have found DNS settings – create a new CNAME or TXT record entry. Google says it can take anything between 24 hours to 2 days for your domain to be activated, but in my case it was more like a hour or so.

I am not going to provide instructions here on how to add DNS records as it is provider specific. You will be guided with that further after sign-up. It’s also worth mentioning that there are other methods for verification – like meta tag or HTML file, however, you will be required to modify other DNS MX entries shortly so a DNS verification method seems logical and straightforward.

At this point you have to tell email clients (MTAs) what SMTP servers to use when they send email targeted to your @domain.com. Here are the steps used by MTAs for email delivery:

  1. When email needs to be sent – MTA client will look-up DNS records for domain in email address
  2. It then grabs first mail exchange (MX) record by priority and connects to a given address
  3. If that server does not respond or fails for any other reason – it goes to the next MX record by priority

So all you need to do now is route your domain email traffic to Google email servers by creating the following MX records:

ASPMX.L.GOOGLE.COM        Priority 1
ALT1.ASPMX.L.GOOGLE.COM   Priority 5
ALT2.ASPMX.L.GOOGLE.COM   Priority 5
ASPMX2.GOOGLEMAIL.COM     Priority 10
ASPMX3.GOOGLEMAIL.COM     Priority 10

Some DNS providers label priority as “Level” or use another term, but essentially it is the same thing/number. And this is it – you can now activate Gmail application under Google Apps and start using your domain for email.

This is a great and cheap way to handle email. Did you know you don’t even need any hosting to get this running? All you need is a domain, and .com domains cost around $10 per year. It is also worth mentioning some extras you get with this Gmail setup – 7+ GB email storage, cache-all address and you can even upload your custom logo.