Archive for March, 2014

作者:AngryFox 分类: Uncategorized March 30th, 2014 暂无评论
#include <stdio.h>

struct str {
        int len;
        char s[0];
};

struct foo {
        struct str *a;
};

int main(int argc, char **argv) {
        struct foo f = {0};
        if(f.a->s) {
                printf(f.a->s);
        }

        return 0;
}

char s[0],if (f.a->s) 这个判断没意义!如果是char *s,这个判断有意义的
12行为f设置初始值为0,而f结构的成员是一个指针,结果f.a指向了NULL,而一个空指针结构的成员(f.a->s)会返回一个非0的值,这也是为何13行会为真,而14行试图访问这个空指针指向的结构的成员时,就会core。

Callgrind 、APD、 xdebug 、KCachegrind 等工具进行基准性能测试
“Languages’s don’t Scale, Architecture Scale”。
从 80-20 的原则看,APC 和 Memcached 是最主要的

杜绝远程 I/O

在普通的TCP/IP网络的环境下,不要进行远程数据写入操作。跨网络操作的延时看似没什么大不了的,但一旦达到临界点就回天乏术。

持续保持 URL 友好风格
URLRewrite 的重视,结构调整,或者应用程序变化的时候,URL 最好做到”用户友好”的

数据库复制延迟问题

对于 MySQL 复制的环境,如果Slave 上有读取操作,那么有些情况下可能因为 Master 和 Slave 节点数据不一致对用户造成困惑。如果从一致性的角度上考虑,其实也不复杂:,只需要对”知道数据发生了变化的用户”提供一致性就行了(基本上就是发起变更的用户),不知道数据发生变化的用户对数据的不一致有一定的”容忍程度”

大量小文件同步问题:Merkle tree

关于大量小文件的同步问题,很多上了规模的网站都会遇到,如果设计得不好或者是比较偷懒,用传统的办法(比如 rsync 之类的老模式)很容易触发问题,也浪费资源。DoubanFS 是用 Merkle tree(Hash Tree)的方式进行数据同步的。

Least Frequently Used(LFU):计算为每个缓存对象计算他们被使用的频率

作者:AngryFox 分类: Uncategorized March 29th, 2014 暂无评论

HTTP 反向代理
使用 Nginx , 这一层只进行HTTP-level 的处理。Nginx 现在是不二选择。

HTTP Cache
对于静态内容,使用 Varnish 进行缓存。如果你在 Squid 和 Varnish 之间作选择,这里已经投了一票。

路由网(Routing Mesh)
用 Erlang 实现的架构组件,路由寻址,用以提升可用性和扩展性。

动态网格(Dyno Grid)
用户部署的代码运行在这里,可以简单看成是应用服务器集群环境,只是粒度更小一点而已。

对于 Dyno Grid 的进一步信息:
服务器操作系统是 Debian ;Ruby VM 是 MRI ,开源,C 写的;App Server 用的 Thin,他们说 Thin 比 Mongrel 更精炼;Rack,应用服务器接口;Rack 中间件,可选组件;框架,任何 Rack 兼容的都成;最后是客户托管的代码。

数据库

PostgreSQL,也可以采用远程数据库。

Memory Cache
Memcached ,居家旅行架构必备。
1. 豆瓣全部的服务器都是Gentoo,除了纳斯达克,也许是全球第二大的Gentoo集群。
2. 豆瓣的Flash卡采用的都是Memblaze。
3. 豆瓣的MySQL用的都是Percona。
4. 豆瓣的非结构化数据保存在自己开发的BeansDB中。

TFS运维过程中,出过的一些问题:

机器上线后,运行环境尚未准备好,比如open files限制、打开core文件方便调查问题
版本升级不完整,部分机器或进程未升级成功
修改配置文件时,部分机器没有修改成功;某台机器配置文件被修改。
对线上机器监控时,遗漏机器、或机器上某些进程
某些磁盘没有按照正确的方式挂载

固定在这个时间段,一般来说,是后台定时任务引起(主机服务提供商或者本身的各种定时任务)。

Berkeley DB
Tokyo Cabinet Memcachedb

作者:AngryFox 分类: Uncategorized March 20th, 2014 暂无评论

层次化向竖井式演进、服务分成逻辑(指令)+存储/状态(数据)

动态可扩展性和服务容灾性
1. 服务(子系统)无状态化,
2. 所以服务可以采用 Web 模式来开发, 也即 Web Server + 脚本语言 + 存储
在网络繁忙的时候能够让一些数据的中转,就是路由器的转发表

2. 获取你需要的数据;编写工具;为工具添加补丁;添加调控旋钮。
3. 度量;消除瓶颈;测试;不断重复这样的过程。
1. 编写系统活动报告工具(wsar):
记录整个系统状态,包括OS状态、硬件状态、BEAM状态。这是为了便于从其他系统获取状态信息,如虚拟内存。跟踪记录CPU利用率、系统整体利用率、用户时间、系统时间、中断时间、上下文切换、系统调用、traps、数据包发送和接收、所有进程队列中总消息数、繁忙的端口事件、通信速率、字节输入/输出、调度状态,垃圾回收状态等。
最初一分钟运行一次,当系统运行变得困难时,时间段将降为1秒钟一次,因为一分钟无法运行的情况很少发生。了解所有系统运行情况需要非常细粒度的统计数据。
2. CPU(pmcstat)中的硬件性能计数器:
通过查看CPU时间占用百分比,可以了解正在执行的模拟器(emulator)周期时间。假如是16%,说明只有16%的时间执行模拟代码,所以即使你能消除所有Erlang代码的执行时间,也只能节省总运行时间16%,这意味着你应该将重点放在其他方面以提高系统的效率。
3. dtrace、 内核锁计数、fprof
Dtrace是主要用于调试,而不是提高性能。
在FreeBSD上给BEAM打补丁加入CPU时间戳。
写脚本创建所有进程的聚合视图,查看哪些程序一直在占用系统资源。
最大的胜利是给模拟器启用锁计数。
4. 一些问题:
早期发现很多时间花在了垃圾回收程序上,这个问题已经被解决了。
发现一些网络堆栈的问题,后来堆栈被调走了。
大多数问题是关于模拟器的锁冲突,主要体现在锁计数的输出上。
5. 度量
综合的工作负载,这意味着从你自己的测试脚本中生成流量,这对极限规模下面向用户系统调优没有价值。
对于用户表这样简单的接口效果不错,生成接入然后尽可能快地读取。
假如在一台服务器只支持100万连接,那么整个系统将需要30台这样的主机去打开足够的IP端口,生成足够多的连接;然而,这么多的开销仅仅可以测试一台服务器。对于测试200万个连接的服务器需要用到60个主机,生成这样的规模真的很难。
很难生成生产环境下的那种流量。在正常的工作量下还可以估算,但在现实中看到的那些网络事件、世界事件,这主要因为多平台上客户端的不同用户行为,而且不同国家之间也有差异。
Tee’d 工作负载
采用正常生产环境流量,然后把它放到一个单独的系统中。
这对系统非常有用,因为产生的副作用会受到限制。不想看到网络拥堵,或者对用户造成影响。
Erlang支持热加载,所以可以在完整生产负荷下产生想法、编译,在程序运行时加载变化,而且能即时看到变化的好坏。
添加旋钮动态调节生产加载,观察它对性能的影响。观察特征输出,比如CPU使用率、VM 使用率、监听队列溢出并调节旋钮,看看系统会有怎样的反应。
真正的生产负载
最终测试。输入工作和输出工作都要测试。
多次将服务器放入DNS中,使其得到正常情况两倍或三倍的流量。TTL事务会产生问题,因为客户端不会遵守DNS TTL,而且这里还会有延迟,因此无法快速做出反应以获得更多可以被处理的流量。
IPFW. 将一台服务器的流量转移给另一台,这样可以使主机的连接数达到理想的水平。内核如果因为有个Bug就奔溃是不行的。

企业里需要几种人:
管理者,能全局把握事情,并不找借口将事情做完成的人
干活的人,能服从老板不找借口将事情做完的人
有关系的人,不能做事,但老爸比李刚还狠的人。
有钱人,项目向前推进,钱当然是最重要的。

作者:AngryFox 分类: Uncategorized March 10th, 2014 暂无评论

http://www.cnblogs.com/cenalulu/p/3310034.html

Memcache的存储涉及到slab,page,chunk三个概念
1.Chunk为固定大小的内存空间,默认为96Byte。
2.page对应实际的物理空间,1个page为1M。
3.同样大小的chunk又称为slab。

1. memcache已经分配的内存不会再主动清理。
2. memcache分配给某个slab的内存页不能再分配给其他slab。
3. flush_all不能重置memcache分配内存页的格局,只是给所有的item置为过期。
4. memcache最大存储的item(key+value)大小限制为1M,这由page大小1M限制
5.由于memcache的分布式是客户端程序通过hash算法得到的key取模来实现,不同的语言可能会采用不同的hash算法,同样的客户端程序也有可能使用相异的方法,因此在多语言、多模块共用同一组memcached服务时,一定要注意在客户端选择相同的hash算法
6.启动memcached时可以通过-M参数禁止LRU替换,在内存用尽时add和set会返回失败
7.memcached启动时指定的是数据存储量,没有包括本身占用的内存、以及为了保存数据而设置的管理空间。因此它占用的内存量会多于启动时指定的内存分配量,这点需要注意。
8.memcache存储的时候对key的长度有限制,php和C的最大长度都是250

item_flush_expired()函数就是扫描表中的item,对过期的item执行unlink操作
重新计算一下数据的预期平均长度,调整growth factor,以获得最恰当的设置
调优Slab和内存分配
memcached在启动时指定Growth Factor因子(通过-f选项),就可以在某种程度上控制slab之间的差异。
默认值为1.25。但是,在该选项出现之前,这个因子曾经固定为2,称为“powers of 2”策略。
最大30天的数据过期时间,设置为永久的也会在这个时间过期,常量REALTIME_MAXDELTA
60*60*24*30控制

-S, –stat_freq=:定期清理静态数据的间隔时间, e.g.: –resp_freq=10s.

memcached压力测试工具memslap使用说明:
item还有一个特性就是它有过期时间,这是memcached的一个很有用的特性,很多应用都是依赖于memcached的item过期,比如session存储、操作锁等。item_flush_expired()函数就是扫描表中的item,对过期的item执行unlink操作,当然这只是一个回收动作,实际上在get的时候还要进行时间判断:
Memcached的内存管理方式是非常精巧和高效的,它很大程度上减少了直接alloc系统内存的次数,降低函数开销和内存碎片产生几率

创业的产品的设计思想

首先,能集中存储的,就不要分布存储,数据集中存储有单点的危险,但是比之分布式存储带来的复杂度不可同日而语。况且集中式的存储也可以利用各种机制做备份,所谓单点风险远没有想象中那么大。

其次,能利用开源框架的,就不要重复造轮子。程序员都喜欢造轮子,但是造轮子的周期长,并且不一定造的更好。在强调开发效率的互联网时代,如果能直接利用现有框架组装出你想要的东西,迅速占领市场,比你造的高性能、高可用、高科技的轮子更实用。这个跟做新产品开发有点类似,迅速组装,高效开发,然后再想办法改进。

第三,要文本,不要二进制。协议要文本化,配置要文本化。不要担心性能,在可见的时间里,你基本不会因为文本化的问题遇到性能瓶颈。

第四,要透明,不要黑盒。基础产品尤其需要对用户透明,你的用户不是小白用户,他们也是程序员,而程序员天生对黑盒性质的东西充满厌恶,他们总想知道你的东西背后在做什么,这对于查找问题分析问题也很重要。怎么做到透明呢?设计,统计,监控,日志等等。

第五,要拥抱标准,不要另搞一套。已经有了久经考验的HTTP协议,你就不要再搞个STTP,有了AMQP协议,你就不要再搞个BMQP。被广泛认可的标准是一些业界的顶尖专家制定出来的,他们早就将你没有考虑到的问题都考虑进去了。你自己搞的那一套,随着时间推移你会发现跟业界标准越来越像,因为面对的问题是一样的。使用标准的额外好处是,你有一大堆可用的代码或者类库可以直接使用,特别是在面对跨语言的时候。

第六,能Share nothing,就不要搞状态复制。无状态的东西是最可爱的,天然的无副作用。水平扩展不要太容易。

第七,要将你的系统做的越不“重要”越好,如果太多的产品依赖你的系统,那么当你的系统故障的时候,整个应用就完蛋了。我们不要担这个责任,我们要将系统做的越来越“不重要”,别人万一没了你也能重启,也能一定时间内支撑正常的工作。

第八,要专注眼前,适当关注未来。有远见是好事,但是太多远见就容易好高骛远。为很小可能性设计的东西,没有机会经历实际检验,当故障真的发生的时候,你也不可能完全信赖它。更好的办法是将系统设计得可介入,可在紧急情况下人工去介入处理,可介入是不够的,还要容易介入。

第九,不要对用户有假设,假设你的用户都是smart programmer,假设你的用户不需要位运算,假设你的用户要同步不要异步。除非你对这个领域非常熟悉并实际使用过类似的东西,否则还是不要假设。

作者:AngryFox 分类: Uncategorized March 2nd, 2014 暂无评论

Comet 架构非常适合事件驱动的 Web 应用,以及对交互性和实时性要求很强的应用,如股票交易行情分析、聊天室和 Web

版在线游戏等。
1. 传统轮询:
此方法是利用 HTML 里面 meta 标签的刷新功能,在一定时间间隔后进行页面的转载,以此循环往复。它的最大

缺点就是页面刷性给人带来的体验很差,而且服务器的压力也会比较大。
2. Ajax 轮询:
异步响应机制,即通过不间断的客户端 Ajax 请求,去发现服务端的变化。这种方式由于是客户端主动连接的,

所以会有一定程度的延时,并且服务器的压力也不小。
3. 长连接:
这也是我们之前所介绍的一种方式。由于它是利用客户端的现有连接实现服务器主动向客户端推送信息,所以延

时的情况很少,并且由于服务端的可操控性使得服务器的压力也迅速减小。其实这种技术还有其他的实现方式,通过

Iframe,在页面上嵌入一个隐藏帧(Iframe),将其“src”属性指向一个长连接的请求,这样一来,服务端就能够源源不

断的向客户端发送数据。这种方式的不足就在于:它会造成浏览器的进度栏一直显示没有加载完成。
4. 套接字:
可以利用 Flash 的 XMLSocket 类或者 Java 的 Applet 来建立 Socket 连接,实现全双工的服务器推送,然后

通过 Flash 或者 Applet 与 JavaScript 通信的接口来实现最终的数据推送。但是这种方式需要 Flash 或者 JVM 的支持

,同样不太合适于终端用户。
5. HTML5 的 WebSocket:
这种方式其实与套接字一样,但是这里需要单独强调一下:它是不需要用户而外安装任何插件的。HTML5 提供了
一个 WebSocket 的 JavaScript 接口,可以直接与服务端建立 Socket 连接,实现全双工通信,这种方式的服务器推送就
是完全意义上的服务器推送了,没有半点模拟的成分,只是现阶段支持 HTML5 的浏览器并不多,而且一般老版本的各种浏
览器基本都不支持。

具体在web中应用思路即:
浏览器发送请求[Client] —> 监听数据 —> 收到数据 —> 分析状态 —> 页面显示 —> 重新发送链接(若未接

收到数据相应,达到设定时长后中断当前连接,重新发起新连接)

session外存储,比如使用redis,这样多节点间可以共享
负载均衡使用nginx,转发请求到各个node chat节点
redis存储用户基本信息,如状态信息、好友关系
node chat节点间通信使用redis的pub/sub
前端使用socket.io或者自己封装长连接
做好客户端断开重练和服务端node chat节点的动态增删

通过web界面查看时Nginx需要开启status模块,也就是安装Nginx时加上 –with-http_stub_status_module 然后配置
Nginx.conf

Pushlet – 开源 Comet 框架
Pushlet 是一个开源的 Comet 框架,在设计上有很多值得借鉴的地方,对于开发轻量级的 Comet 应用很有参考价值。

观察者模型
Pushlet 使用了观察者模型:客户端发送请求,订阅感兴趣的事件;服务器端为每个客户端分配一个会话 ID 作为标记,

事件源会把新产生的事件以多播的方式发送到订阅者的事件队列里。

客户端 JavaScript 库
pushlet 提供了基于 AJAX 的 JavaScript 库文件用于实现长轮询方式的“服务器推”;还提供了基于 iframe 的

JavaScript 库文件用于实现流方式的“服务器推”。

JavaScript 库做了很多封装工作:
定义客户端的通信状态:STATE_ERROR、STATE_ABORT、STATE_NULL、STATE_READY、STATE_JOINED、STATE_LISTENING;
保存服务器分配的会话 ID,在建立连接之后的每次请求中会附上会话 ID 表明身份;
提供了 join()、leave()、subscribe()、 unsubsribe()、listen() 等 API 供页面调用;
提供了处理响应的 JavaScript 函数接口 onData()、onEvent()…
网页可以很方便地使用这两个 JavaScript 库文件封装的 API 与服务器进行通信。

客户端与服务器端通信信息格式
pushlet 定义了一套客户与服务器通信的信息格式,使用 XML 格式。定义了客户端发送请求的类型:join、leave、
subscribe、unsubscribe、listen、refresh;以及响应的事件类型:data、join_ack、listen_ack、refresh、heartbeat
、error、abort、subscribe_ack、unsubscribe_ack。

服务器端事件队列管理
pushlet 在服务器端使用 Java Servlet 实现,其数据结构的设计框架仍可适用于 PHP、C 编写的后台客户端。
Pushlet 支持客户端自己选择使用流、拉(长轮询)、轮询方式。服务器端根据客户选择的方式在读取事件队列
(fetchEvents)时进行不同的处理。“轮询”模式下 fetchEvents() 会马上返回。”流“和”拉“模式使用阻塞的方式
读事件,如果超时,会发给客户端发送一个没有新信息收到的“heartbeat“事件,如果是“拉”模式,会把“heartbeat
”与“refresh”事件一起传给客户端,通知客户端重新发出请求、建立连接。

客户服务器之间的会话管理
服务端在客户端发送 join 请求时,会为客户端分配一个会话 ID, 并传给客户端,然后客户端就通过此会话 ID 标明身
份发出 subscribe 和 listen 请求。服务器端会为每个会话维护一个订阅的主题集合、事件队列。
服务器端的事件源会把新产生的事件以多播的方式发送到每个会话(即订阅者)的事件队列里。
RTMP协议就像一个用来装数据包的容器,这些数据可以是AMF格式的数据,也可以是FLV中的视/音频数据。一个单一的连接
可以通过不同的通道传输多路网络流。这些通道中的包都是按照固定大小的包传输的。
nginx http push stream

–with-debug
netstat -anp | awk ‘/^tcp/{a[$6]++}END{for(i in a){printf(“%s\t%d\n”,i,a[i])}}’
curl -X GET http://localhost:8082/activity?id=0 -verbose

https://pushmodule.slact.net/

https://github.com/wandenberg/nginx-push-stream-module

http://www.nginxpushstream.com/