《RabbitMQ入门之Go语言教程》(3) 发布/订阅模式

本系列摘自RabbitMQ官方教程,边学习边翻译的中文的版本,水平有限,不妥之处,欢迎交流。

前一篇介绍中实现了一个工作队列,它假设队列中的每一个任务都只会被分发到一个工作者进行处理。在本篇中,我们尝试将同一个消息发送给多个消费者进行处理,这就是广为人知的发布/订阅模式。

本篇通过搭建一个日志系统来阐述发布/订阅模式,它包含两部分内容:一个用于产生日志消息的程序,另一个用于接收和打印消息。
在这个日志系统中,每一份接收者程序的拷贝都能收到消息,因此我们可以轻易地使用一个程序将日志写入磁盘,而另一个程序直接在屏幕显示。

本质上来说,当系统收到一个日志处理请求时,会把这个消息广播给所有的接收者。


- 阅读剩余部分 -

《RabbitMQ入门之Go语言教程》(2) 工作队列

本系列摘自RabbitMQ官方教程,边学习边翻译的中文的版本,水平有限,不妥之处,欢迎交流。

上一篇介绍中我们实现了从消息产生程序发送简单消息到命名队列的过程,本篇将实现一个将耗时任务分发到多个消费者程序的工作队列。

work_queue.png

工作队列的主要思想是避免对资源密集型任务处理时的等待,而是先将任务压入队列,后期再进行计划处理。我们将任务封装成消息发送给队列,由队列程序按策略分发到所有的在线工作者程序执行。当有多个工作程序同时在线时,多项任务同时被多个不同的工作者处理便成为可能。

在Web应用程序领域,如果需要在一个HTTP短连接中完成一些复杂的耗时任务时,工作队列的思想能大幅提高处理效率而带来了更好的用户体验。

- 阅读剩余部分 -

《RabbitMQ入门之Go语言教程》(1) Hello World

本系列摘自RabbitMQ官方教程,边学习边翻译的中文的版本,水平有限,不妥之处,欢迎交流。

RabbitMQ是一个开源的、使用最广的消息转发器。提供匿名消息类型,可使用多种消息协议、消息队列等,支持集群部署,
它的轻量级能够让你很轻易地在私有云或公有云环境中部署,同时提供丰富的插件工具,能够让你轻易的进行扩展,且可使用HTTP-API、命令行工具和UI界面以便于管理和监控。

RabbitMQ是一个消息转发器,它对消息进行接收并转发。你可以把它想象成邮局,当你把信件投入邮筒之后,邮递员会根据信笺上的地址进行投递。RabbitMQ这里就扮演中邮筒、邮局和邮递员的角色。RabbitMQ跟现实中的邮局所不同的是它不会对真实的信件进行投递,而是对以二进制数据-消息进行存储、转发。


- 阅读剩余部分 -

Typecho下Unique Page浏览计数插件

Typecho下Unique Page浏览计数插件

前面文章分享了网友的Page View插件,Views, 但是因为本人网站其实大部分时间都是自己在访问,因此基于PV的访问可能更多的是自己的访问量,对于后续网站检索的数据无法真实体现。故而在此基础上修改了一种基于Unique Page的浏览计数方法。

实现原理

相对于PV每一次文章内容也被浏览会增加一次计数,这里的UV则是根据客户端访问IP计数,每篇文章每一个IP在同一天的多次访问只记为1,最后相加显示之和便是文章的UV数。

代码

<?php
/**
 * Typecho 版 Unique Views
 * 
 * @package UViews 
 * @author Ray Lei
 * @version 0.0.1
 * @update: 2018.04.09
 * @link http://raylei.cn/
 */
class UViews_Plugin implements Typecho_Plugin_Interface
{
    /**
     * 激活插件方法,如果激活失败,直接抛出异常
     * 
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function activate()
    {
        Typecho_Plugin::factory('Widget_Archive')->beforeRender = array('UViews_Plugin', 'viewsCounter');

        $db = Typecho_Db::get();
        $prefix = $db->getPrefix();

        //如果已启用过该插件则不在修改数据库
        //SELECT * FROM `typecho_options` where name = 'plugins' and value like '%UViews_Plugin%'
        $result = $db->fetchRow($db->select()->from('table.options')->where('name=?', 'plugins')->where('value like ?', '%UViews_Plugin%'));

        if (empty($result)) {
          $db->query('create table typecho_content_views(
            id int primary key auto_increment,
            cid int, ip varchar(32), 
            views int,
            lastViewDate datetime
            );');
      }
  }

    /**
     * 禁用插件方法,如果禁用失败,直接抛出异常
     * 
     * @static
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function deactivate(){}
    
    /**
     * 获取插件配置面板
     * 
     * @access public
     * @param Typecho_Widget_Helper_Form $form 配置面板
     * @return void
     */
    public static function config(Typecho_Widget_Helper_Form $form){}

    /**
     * 个人用户的配置面板
     * 
     * @access public
     * @param Typecho_Widget_Helper_Form $form
     * @return void
     */
    public static function personalConfig(Typecho_Widget_Helper_Form $form){}

    // Function to get the client ip address
    public static function get_client_ip_env() {
        $ipaddress = '';
        if (getenv('HTTP_CLIENT_IP'))
            $ipaddress = getenv('HTTP_CLIENT_IP');
        else if(getenv('HTTP_X_FORWARDED_FOR'))
            $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
        else if(getenv('HTTP_X_FORWARDED'))
            $ipaddress = getenv('HTTP_X_FORWARDED');
        else if(getenv('HTTP_FORWARDED_FOR'))
            $ipaddress = getenv('HTTP_FORWARDED_FOR');
        else if(getenv('HTTP_FORWARDED'))
            $ipaddress = getenv('HTTP_FORWARDED');
        else if(getenv('REMOTE_ADDR'))
            $ipaddress = getenv('REMOTE_ADDR');
        else
            $ipaddress = 'UNKNOWN';

        return $ipaddress;
    }

    /**
     * 加入 beforeRender
     * 
     * @access public
     * @return void
     */
    public static function viewsCounter()
    {
        // 访问计数
        if (Typecho_Widget::widget('Widget_Archive')->is('single')) {
            $db = Typecho_Db::get();
            $cid = Typecho_Widget::widget('Widget_Archive')->cid;
            $row = $db->fetchRow($db->select('ip, views, lastViewDate')->from('table.content_views')->where('cid = ?', $cid)->where('ip= ?', UViews_Plugin::get_client_ip_env()));

            //如果不存在,则新增,否则根据访问时间来更新计数和上次访问时间
            if (empty($row)) {
                $insert  = $db->insert('table.content_views')->rows(array('ip' =>UViews_Plugin::get_client_ip_env() , 'cid'=>$cid,'views'=>1, 'lastViewDate'=> date("Y-m-d H:i:s")));
                $insertret = $db->query($insert);
            }else{
                $date = new DateTime($row["lastViewDate"]);
                if(date("Y-m-d") != $date->format('Y-m-d'))
                 $db->query($db->update('table.content_views')->rows(array('views'=>(int)$row['views']+1, 'lastViewDate'=>date('Y-m-d H:i:s')))->where('cid=?', $cid));
             else
                 $db->query($db->update('table.content_views')->rows(array('lastViewDate'=>date('Y-m-d H:i:s')))->where('cid=?', $cid));
         }

     }
 }

    /**
     * 输出访问次数
     *
     * 语法: UViews_Plugin::theViews();
     * 输出: '访问: xx,xxx 次'
     *
     * 语法: UViews_Plugin::theViews('有 ', ' 次点击');
     * 输出: '有 xx,xxx 次点击'
     *
     * @access public
     * @param string  $before 前字串
     * @param string  $after  后字串
     * @param bool    $echo   是否显示 (0 用于运算,不显示)
     * @return string
     */
    public static function theViews($before = '(UV)访问: ', $after = ' 次', $echo = 1)
    {
        $db = Typecho_Db::get();
        $cid = Typecho_Widget::widget('Widget_Archive')->cid;
        $row = $db->fetchRow($db->select(array('sum(views)' => 'ViewCount'))->from('table.content_views')->where('cid = ?', $cid));
        if ($echo)
            echo $before, number_format($row['ViewCount']), $after;
        else
            return $row['ViewCount'];
    }    
}

插件的使用方法:将上述代码命名为Plugin.php, 在usr/Plugins/下新建UViews文件夹,然后上传该文件;

后续操作见之前Views插件介绍文章: Typecho文章浏览次数统计插件设置.

最后,在需要使用访问计数的地方添加如下代码即可:

<?php UViews_Plugin::theViews(); ?>

Typecho文章浏览次数统计插件设置

文章阅读数是一个衡量传播价值的重要指标,有PV(Page View), UV(Unique View)等,本篇介绍下简单PV统计插件的使用方法。

Page View是指页面被访问的次数,单一用户多次访问页面或刷新页面均会被计算次数。

Unique View,独立访客数,指一天内访问该页面的人数,一般使用IP来区分,统一IP的多次访问不会被重复计数。

本篇介绍简单PV指标的插件使用方法,因本站访客寥寥无几,大部分都是自己的访问次数,所以PV并不能真实体现被浏览的情况,后续笔者会在此插件的基础上实现UV的统计方式。

- 阅读剩余部分 -