Overview

最近在阅读博客中的文章时发现一个奇怪的现象,就是有评论的文章加载速度特别慢,代码块的颜色渲染也要等很久才能显示出来。这让我很困惑,因为我将代码块高亮渲染的代码也放在了本地。最初我以为是代码块中的代码太多,导致渲染时间久。后来发现只有有评论的文章才会出现这种情况,使用了Chrome发现,有评论的页面会出现http://www.gravatar.com/avatar/#####链接请求失败。#####是我省略的一串不可读字符串,后面会说这些字符串是什么。
因为http://www.gravatar.com/avatar这个服务不可用,所以导致页面一直在等待这个网址的回复,直到超出响应时间,才会运行接下来的动作,比如渲染代码块高亮颜色

评论者头像提供服务

其实blog在显示评论者图片时,并不是显示本地的图片或者评论者自己设定的图像,而是用用头像提供网站服务给评论者一个特定的头像,想知道具体细节,就需要查看下面的文件。
打开blog/var/Typecho/文件夹中的Common.php文件,找到下面的代码:

$url = $isSecure ? 'https://secure.gravatar.com' : 'http://www.gravatar.com';
$url .= '/avatar/';

这里定义了取头像的地址,即https://secure.gravatar.com/avatar或者https://gravatar.com/avatar

总不能所有的评论者都用一样的图片吧,继续查看紧接着下面的代码:

if (!empty($mail)) {
        $url .= md5(strtolower(trim($mail)));
}

原来Typecho根据评论者提供的邮箱,进行md5转化,形成一串字符串,就可以形成一个新的请求链接:http://www.gravatar.com/avatar/#####,这里的#####就是这个md5编码之后的字符串。但是这个请求不只有邮箱md5之后这一个字符串,还有下面几个参数:

$url .= '?s=' . $size;
$url .= '&r=' . $rating;
$url .= '&d=' . $default;

这三个参数从在后台设置->评论中的选项中读取数据,比如$rating取的数据就是 启用Gravatar头像服务, 最高显示评级为## 的头像,这里的##有一下选项:

G - 普通
PG - 十三岁以上
R - 十七岁以上成人
X - 限制级    

知道了这些以后,我们要做的就很简单了,只需要修改头像服务提供站点就可以了。将Common.php中的

$url = $isSecure ? 'https://secure.gravatar.com' : 'http://www.gravatar.com';
$url .= '/avatar/';

替换为

$url = 'http://cdn.v2ex.com/gravatar/';

我们这里使用的是国内很好的一个程序员社区V2EX提供的CDN服务,速度很快。
如果你想在评论时显示一个自定义头像,去 www.gravatar.com 注册一个账号,并上传一张自己喜欢的头像,就可以了。如果你没设置过,这个网站也会给你返回一个默认头像。
现在评论之后,就可以出现评论者的头像了,而且速度非常快。

怎么找到Common.php

可能有人会好奇,我怎么恰好知道在Common.php里面修改呢。这其实是个通用的方法:

  1. 在我用Chrome查看完页面之后,就知道http://www.gravatar.com的网站服务提供方出现了问题,既然后台没办法设置这个,那一定是在代码中哪个地方设置的。

  2. blog的根目录,使用下面的linux命令查找所有包含gravatar.com的文件:

    grep -nr gravatar.com .
    

    输出下面的结果:

    ./admin/profile.php:14:                <p><a href="http://gravatar.com/emails/" title="<?php _e('在 Gravatar 上修改头像'); ?>"><?php echo '<img class="profile-avatar" src="' . Typecho_Common::gravatarUrl($user->mail, 220, 'X', 'mm', $request->isSecure()) . '" alt="' . $user->screenName . '" />'; ?></a></p>
    ./var/Typecho/Common.php:939:        $url = $isSecure ? 'https://secure.gravatar.com' : 'http://www.gravatar.com';
    ./var/Widget/Options/Discussion.php:54:            'commentsAvatar'        =>  _t('启用 <a href="http://gravatar.com">Gravatar</a> 头像服务, 最高显示评级为 %s 的头像'
    

    可以看到,有三个文件包含了gravatar.com,分别是./admin/profile.php的第14行,./var/Typecho/Common.php的第939行,./var/Widget/Options/Discussion.php的第54行,./表示当前搜索的位置。
    查看这三个文件,会发现profile.phpDiscussion.php对应后台管理界面的两个页面,Common.php就是定义头像服务网址的地方。

小结

这个问题本身非常小,但是给网站本身带来的性能影响是非常大的,而且当管理员登陆后台,进入管理菜单下的评论页面时,居然会直接导致站点宕机,需要重启Apache服务器才可以。因此小的细节对整体的影响还是很大的,自己写代码的时候也要多多注意。