• 2017-05-17

    轻量级 COMET 服务器 icomet 支持 EventSource(SSE)

    Views: 1041 | No Comments

    最初的 COMET 技术,指的是 HTTP 长轮询,不过,随着时间的推进,许多能实现浏览器即时推送的技术都可被称为 COMET 技术。由我开发的基于 libevent 库的轻量级 COMET 服务器开源项目 icomet,支持主流的浏览器推送技术,并且支持移动端。

    最近,在网友的贡献下,icomet 支持了 HTML 5 的 Server-Sent Events(SSE, EventSource) 技术。这项技术也是 W3C 标准之一,详情可见:http://www.w3.org/TR/eventsource/

    在支持 HTML 5 的浏览器中使用 SSE,代码会非常简洁,示例如下:

    var source = new EventSource("http://127.0.0.1:8100/sse?cname=12&seq=1");
    source.onmessage = function(e) {
        document.body.innerHTML += e.data;
    };
    

    e.data 就是服务器推送的数据。icomet 项目源码中带有 demo/web/sse.html 脚本,你直接拖到浏览器里即可看运行效果。

    源码和示例下载:https://github.com/ideawu/icomet

    Posted by ideawu at 2017-05-17 14:21:01 Tags:
  • 2016-08-19

    集成于 iphp 框架的 PHP 并发模型和工具

    Views: 5374 | 2 Comments

    由于 PHP 具有"所思即所写"的强大优势, 使其在 Web 之外, 也被广泛用于后台脚本编写. 而且, 当你已经用 PHP 来开发 Web 应用时, 你显然不愿意再引入 Java 或者 Python 等语言, 再说, 这些语言相对 PHP 的强大优势, 显示太弱了.

    不过, 用 PHP 来编写后台脚本, 也有一些劣势, 那便是 PHP 缺少并发模型. 例如, 当你用 HTTP 请求第三方服务, 而第三方每一个请求要处理 10 秒时, 这就需要你并发地发起请求. curl_multi 当然能处理, 但不通用, 而且对代码逻辑的改变太大, 需要从串行化改为批量化, 对思维干扰太大.

    为此, PHP 提供了一套 Master-Workers 并发模型, 帮助你实现 PHP 的并发处理.

    Continue reading »

    Posted by ideawu at 2016-08-19 14:29:36
  • 2016-06-23

    单启动多个mysql实例mysqld_multi配置

    Views: 3662 | No Comments

    1. 创建 mysqld_multi.conf 配置

    [mysqld_multi]
    mysqld=/usr/bin/mysqld_safe  
    mysqladmin=/usr/bin/mysqladmin 
    user=AAA
    password=BBB
    
    
    [mysqld3306]
    port=3306
    datadir=/var/lib/mysql3306
    socket=/var/lib/mysql3306/mysql.sock
    pid-file=/var/lib/mysql3306/mysqld.pid
    log-error=/var/log/mysqld_3306.log
    user=mysql
    symbolic-links=0
    character-set-server = utf8
    skip-name-resolve
    
    server-id=123
    log-bin=mysql-bin
    log-slave-updates
    binlog-ignore-db=mysql
    binlog-ignore-db=test
    binlog-ignore-db=information_schema
    binlog-ignore-db=performance_schema
    replicate-ignore-db=mysql
    replicate-ignore-db=test
    replicate-ignore-db=information_schema
    replicate-ignore-db=performance_schema
    master-connect-retry=10
    max_connections=1000
    
    sort_buffer_size = 300M
    join_buffer_size = 300M
    key_buffer_size  = 300M
    innodb_buffer_pool_size = 4000M
    query_cache_size=200M
    

    注意, 要配置 user 和 password, 一会将要创建一个帐号用于 mysqld_multi.
    Continue reading »

    Posted by ideawu at 2016-06-23 16:27:32
  • 2016-06-23

    PHP过滤掉Emoji表情字符

    Views: 5588 | 1 Comment

    这段代码在 stackoverflow 上搜到, 据说是 Smarty 用的.

    function smarty_modifier_emojistrip($string)
    {       
        return preg_replace('/\xEE[\x80-\xBF][\x80-\xBF]|\xEF[\x81-\x83][\x80-\xBF]/', '', $string);
    }
    
    Posted by ideawu at 15:53:56
  • 2016-06-17

    一个简单的聊天或者私信系统设计

    Views: 4678 | 1 Comment

    不少网站都会内置聊天或者私信系统, 为了方便更多人, 现将一个最简单的聊天系统的接口设计放在这里, 这是一个基于 HTTP 的聊天系统设计.

    首先是视图设计:

    # view:
    
    msg/unread
    	(全局)未读消息列表
    chat
    	一对一聊天窗口
    chat/history
    	我的聊天记录(按人组织)列表
    

    接着是数据接口设计:

    # ajax:
    
    msg/unread/get
    	获取(全局)未读消息列表
    	@last_msg_id: 获取比此消息更晚的未读消息, 不包含该条消息.
    chat/get
    	获取一对一聊天记录
    	@user_id: (msg_id, user_id 必须传一个)聊天者
    	@msg_id: (msg_id, user_id 必须传一个)根据此消息, 可得到聊天者, 并可在显示聊天记录时定位到对应的消息
    chat/get_new
    	@user_id: 聊天者
    	@last_msg_id: 获取比此消息更晚的消息, 不包含该条消息.
    chat/send
    	发送消息
    chat/history/get
    	我的聊天记录(按人组织)列表
    

    其中, 带有 last_msg_id 参数的接口, 可用于轮询获取新消息, 以便在缺少推送机制(PUSH)时提供一种替代方案. 大多数情况下, 10秒一次的刷新频率能达到"实时聊天"的效果.

    当有推送机制时, 如采用 iComet, 推送机制只推送通知(notify), 实际的消息内容仍然通过带 last_msg_id 的接口获取. 也就是说, 把固定刷新频率, 改为受通知时刷新(PUSH + PULL 结合).

    另外, 消息的持久化可以使用 MySQL 数据库, 但更推荐 SSDB NoSQL 数据库, 可以 SSDB 能存储超过十亿条的聊天历史记录并能快速查询.

    基于 SSDB + iComet 的聊天系统 demo: https://github.com/ideawu/icomet-demos

    Posted by ideawu at 2016-06-17 17:51:27
  • 2016-02-25

    PHP 用 curl 读取 HTTP chunked 数据

    Views: 6128 | No Comments

    对于 Web 服务器返回的 HTTP chunked 数据, 我们可能希望在每一个 chunk 返回时得到回调, 而不是所有的响应返回后再回调. 例如, 当服务器是 icomet 的时候.

    在 PHP 中使用 curl 代码如下:

    <?php  
    $url = "http://127.0.0.1:8100/stream";
    
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'myfunc');
    $result = curl_exec($ch);
    curl_close($ch);
    
    function myfunc($ch, $data){
        $bytes = strlen($data);
        // 处理 data
        return $bytes;
    }
    

    但是, 这里有一个问题. 对于一个 chunk, 回调函数可能会被调用多次, 每一次大概是 16k 的数据. 这显然不是我们希望得到的. 因为 icomet 的一个 chunk 是以 "\n" 结尾, 所以回调函数可以做一下缓冲.

    function myfunc($ch, $data){
        $bytes = strlen($data);
        static $buf = '';
        $buf .= $data;
        while(1){
            $pos = strpos($buf, "\n");
            if($pos === false){
                break;
            }
            $data = substr($buf, 0, $pos+1);
            $buf = substr($buf, $pos+1);
    
            // 处理 data
        }
    }
    
    Posted by ideawu at 2016-02-25 16:44:11
|<<<123456789>>>| 1/27 Pages, 162 Results.