Darts 是用于构建双数组 Double-Array [Aoe 1989] 的简单的 C++ Template Library . 双数组 (Double-Array) 是用于实现 Trie 的一种数据结构, 比其它的类 Trie 实现方式(Hash-Tree, Digital Trie, Patricia Tree, Suffix Array) 速度更快。 原始的 Double-Array 使能够支持动态添加删除 key, 但是 Darts 只支持把排好序的词典文件转换为静态的 Double-Array.

Darts 既可以像 Hash 一样作为简单的词典使用,也能非常高效的执行分词词典中必须的 Common Prefix Search 操作。

自2003年7月起, 两个开源的日语分词系统 MeCabChaSen 都使用了 Darts .

下载

  • Darts 是自由软件.遵循 LGPL(Lesser GNU General Public License) 和 BSD 协议, 可以修改后重新发布.

Source

  • darts-0.32.tar.gz: HTTP

安装

% ./configure 
% make
% make check
% make install
然后在程序中 include /usr/local/include/darts.h

使用方法

Darts 只提供了 darts.h 这个 C++ 模板文件。每次使用的时候 include 该文件即可.
使用这样的发布方式是希望通过内联函数实现高效率。

类接口

namespace Darts {

template <class NodeType, class NodeUType class ArrayType,
class ArrayUType, class LengthFunc = Length<NodeType> >

class DobuleArrayImpl
{
public:
typedef ArrayType result_type;
typedef NodeType key_type;

DoubleArrayImpl();
~DoubleArrayImpl();

int set_array(void *ptr, size_t = 0);
void *array();
void clear();
size_t size ();
size_t unit_size ();
size_t nonzero_size ();
size_t total_size ();

int build (size_t key_size,
key_type **key,
size_t *len = 0,
result_type *val = 0,
int (*pg)(size_t, size_t) = 0);

int open (const char *file,
const char *mode = "rb",
size_t offset = 0,
size_t _size = 0);

int save (const char *file,
const char *mode = "wb",
size_t offset = 0);

result_type exactMatchSearch (const key_type *key,
size_t len = 0,
size_t node_pos = 0)

size_t commonPrefixSearch (const key_type *key,
result_type *result,
size_t result_size,
size_t len = 0,
size_t node_pos = 0)

result_type traverse (const key_type *key,
size_t &node_pos,
size_t &key_pos,
size_t len = 0)
};

typedef Darts::DoubleArrayImpl<char, unsigned char,
int, unsigned int> DoubleArray;
};

模板参数说明

 

NodeTypeTrie 节点类型, 对普通的 C 字符串检索, 设置为 char 型即可.
NodeUTypeTrie 节点转为无符号整数的类型, 对普通的 C 字符串检索, 设置为 unsigned char 型即可.
ArrayTypeDouble-Array 的 Base 元素使用的类型, 通常设置为有符号 32bit 整数
ArrayUTypeDouble-Array 的 Check 元素使用的类型, 通常设置为无符号 32bit 整数
LengthFunc使用 NodeType 数组的时候,使用该函数对象获取数组的大小, 在该函数对象中对 operator() 进行重载. 
NodeType 是 char 的时候, 缺省使用 strlen 函数, 否则以 0 作为数组结束标志计算数组的大小 .

typedef 说明

模板参数类型的别名. 在外部需要使用这些类型的时候使用 .

key_type待检索的 key 的单个元素的类型. 等同于 NodeType.
result_type单个结果的类型. 等同于 ArrayType .

方法说明

int Darts::DoubleArrayImpl::build(size_t size, const key_type **str, const size_t *len = 0, const result_type *val = 0, int (*progress_func)(size_t, size_t) = 0)
构建 Double Array .

size 词典大小 (记录的词条数目),
str 指向各词条的指针 (共 size个指针)
len 用于记录各个词条的长度的数组(数组大小为 size)
val 用于保存各词条对应的 value 的数组 (数组大小为 size)
progress_func 构建进度函数.

str 的各个元素必须按照字典序排好序.
另外 val 数组中的元素不能有负值.
len, val, progress_func 可以省略,
省略的时候, len 使用 LengthFunc 计算,
val 的各元素的值为从 0 开始的计数值。 


构建成功,返回 0; 失败的时候返回值为负.
进度函数 progress_func 有两个参数.
第一个 size_t 型参数表示目前已经构建的词条数 
第二个 size_t 型参数表示所有的词条数 

result_type Darts::DoubleArrayImpl::exactMatchSearch(const key_type *key, size_t len = 0, size_t node_pos = 0)
进行精确匹配(exact match) 检索, 判断给定字符串是否为词典中的词条.

key 待检索字符串,
len 字符串长度,
node_pos 指定从 Double-Array 的哪个节点位置开始检索.

len, 和 node_pos 都可以省略, 省略的时候, len 缺省使用 LengthFunc 计算,
node_pos 缺省为 root 节点.

检索成功时, 返回 key 对应的 value 值, 失败则返回 -1. 

size_t Darts::DoubleArrayImpl::commonPrefixSearch (const key_type *key, result_type *result, size_t result_size, size_t len = 0, size_t node_pos = 0)
执行 common prefix search. 检索给定字符串的哪些的前缀是词典中的词条

key 待检索字符串,
result 用于保存多个命中结果的数组,
result_size 数组 result 大小,
len 待检索字符串长度,
node_pos 指定从 Double-Array 的哪个节点位置开始检索.

len, 和 node_pos 都可以省略, 省略的时候, len 缺省使用 LengthFunc 计算,
node_pos 缺省为 root 节点.

函 数返回命中的词条个数. 对于每个命中的词条, 词条对应的 value 值存依次放在 result 数组中. 如果命中的词条个数超过 result_size 的大小, 则 result 数组中只保存 result_size 个结果。函数的返回值为实际的命中词条个数, 可能超过 result_size 的大小。 

result_t Darts::DoubleArrayImpl::traverse (const key_type *key, size_t &node_pos, size_t &key_pos, size_t len = 0)
traverse Trie, 检索当前字符串并记录检索后到达的位置 

key 待检索字符串,
node_pos 指定从 Double-Array 的哪个节点位置开始检索.
key_pos 从待检索字符串的哪个位置开始检索
len 待检索字符串长度,

该函数和 exactMatchSearch 很相似. traverse 过程是按照检索串 key 在 TRIE 的节点中进行转移.
但是函数执行后, 可以获取到最后到达的 Trie 节点位置,最后到达的字符串位置 . 这和 exactMatchSearch 是有区别的. 

node_pos 通常指定为 root 位置 (0) . 函数调用后, node_pos 的值记录最后到达的 DoubleArray 节点位置。 
key_pos 通常指定为 0. 函数调用后, key_pos 保存最后到达的字符串 key 中的位置。 

检索失败的时候, 返回 -1 或者 -2 .
-1 表示再叶子节点失败, -2 表示在中间节点失败,.
检索成功的时候, 返回 key 对应的 value. 

int Darts::DoubleArrayImpl::save(const char *file, const char *mode = "wb", size_t offset = 0)
把 Double-Array 保存为文件.

file 保存文件名,
mode 文件打开模式 
offset 保存的文件位置偏移量, 预留将来使用, 目前没有实现 .

成功返回 0 , 失败返回 -1 

int Darts::DoubleArrayImpl::open (const char *file, const char *mode = "rb", size_t offset = 0, size_t size = 0)
读入 Double-Array 文件.

file 读取文件名,
mode 文件打开模式 
offset 读取的文件位置偏移量 

size 为 0 的时候, size 使用文件的大小 .

成功返回 0 , 失败返回 -1 

size_t Darts::DoubleArrayImpl::size()
返回 Double-Array 大小. 

size_t Darts::DoubleArrayImpl::unit_size()
Double-Array 一个元素的大小(byte).

size() * unit_size() 是, 存放 Double-Array 所需要的内存(byte) 大小. 

size_t Darts::DoubleArrayImpl::nonzero_size()
Double-Array 的所有元素中, 被使用的元素的数目, .
nonezero_size()/size() 用于计算压缩率. 

例子程序

从静态词典构建双数组 Double-Array.

#include <iostream>
#include <darts.h>

int main (int argc, char **argv)
{
using namespace std;

Darts::DoubleArray::key_type *str[] = { "ALGOL", "ANSI", "ARCO", "ARPA", "ARPANET", "ASCII" }; // same as char*
Darts::DobuleArray::result_type val[] = { 1, 2, 3, 4, 5, 6 }; // same as int

Darts::DoubleArray da;
da.build (6, str, 0, val);

cout << da.exactMatchSearch("ALGOL") << endl;
cout << da.exactMatchSearch("ANSI") << endl;
cout << da.exactMatchSearch("ARCO") << endl;;
cout << da.exactMatchSearch("ARPA") << endl;;
cout << da.exactMatchSearch("ARPANET") << endl;;
cout << da.exactMatchSearch("ASCII") << endl;;
cout << da.exactMatchSearch("APPARE") << endl;

da.save("some_file");
}

执行结果
1
2
3
4
5
6
-1

从标准输入读取字符串, 对 Double-Array 执行 Common Prefix Search

#include <iostream>
#include <string>
#include <algorithm>
#include <darts.h>

int main (int argc, char **argv)
{
using namespace std;

Darts::DoubleArray da;
if (da.open("some_file") == -1) return -1;

Darts::DoubleArray::result_type r [1024];
Darts::DoubleArray::key_type buf [1024];

while (cin.getline (buf, 1024)) {
size_t result = da.commonPrefixSearch(buf, r, 1024);
if (result == 0) {
cout << buf << ": not found" << endl;
} else {
cout << buf << ": found, num=" << result << " ";
copy (r, r + result, ostream_iterator<Darts::DoubleArray::result_type>(cout, " "));
cout << endl;
}
}

return 0;
}

付属程序说明

mkdarts

% ./mkdarts DictionaryFile DoubleArrayFile 
把排序好的词典 DictionaryFile 转换为 DoubleArrayFile

darts

% ./darts DoubleArrayFile 

使用 DoubleArrayFile 做 common prefix search .

使用例子

% cd tests
% head -10 linux.words
ALGOL
ANSI
ARCO
ARPA
ARPANET
ASCII
..

% ../mkdarts linux.words dar
Making Double Array: 100% |*******************************************|
Done!, Compression Ratio: 94.6903 %

% ../darts dar
Linux
Linux: found, num=2 3697 3713
Windows
Windows: not found
LaTeX
LaTeX: found, num=1 3529

参考文献, 链接

posted @ 2013-08-13 16:45 小马歌 阅读(436) | 评论 (0)编辑 收藏
 
     摘要: from: http://blog.chinaunix.net/uid-13746440-id-3152484.html0.引言基于DPDK的发包工具的性能今天已经达到双向1900Wpps了,比昨天又高了200Wpps,正是得益于oProfile检测与调优的结果,而且今天还只是很简单的用了一下(类似于下面的示例),跟踪出对几个结构体字段的访问比较缓慢,于是对结构体字段进行了仔细的顺序调整...  阅读全文
posted @ 2013-08-12 14:13 小马歌 阅读(356) | 评论 (0)编辑 收藏
 
When you running a highload website with PHP-FPM via FastCGI, the following tips may be useful to you : )
如果您高负载网站使用PHP-FPM管 理FastCGI,这些技巧也许对您有用:)

1. Compile PHP’s modules as less as possible, the simple the best (fast);
1.尽量少安装PHP模块,最简单是最好(快)的

2. Increas PHP FastCGI child number to 100 and even more. Sometime, 200 is OK! ( On 4GB memory server);
2.把您的PHP FastCGI子进程数调到100或以上,在4G内存的服务器上200就可以
注:我的1g测试机,开64个是最好的,建议使用压力测试获取最佳值

3. Using SOCKET PHP FastCGI, and put into /dev/shm on Linux;
3.使用socket连接FastCGI,linux操作系统可以放在 /dev/shm中
注: 在php-fpm.cnf 里设置<value name="listen_address">/tmp/nginx.socket</value>就可以通过socket连接 FastCGI了,/dev/shm是内存文件系统,放在内存中肯定会快了

4. Increase Linux “max open files”, using the following command (must be root):
# echo ‘ulimit -HSn 65536′ >> /etc/profile
# echo ‘ulimit -HSn 65536 >> /etc/rc.local
# source /etc/profile
4.调高linux内核打开文件数量,可以使用这些命令(必须是root帐号)
echo 'ulimit -HSn 65536' >> /etc/profile
echo 'ulimit -HSn 65536' >> /etc/rc.local
source /etc/profile
注:我是修改/etc/rc.local,加入ulimit -SHn 51200的

5. Increase PHP-FPM open file description rlimit:
# vi /path/to/php-fpm.conf
Find “<value name=”rlimit_files”>1024</value>”
Change 1024 to 4096 or higher number.
Restart PHP-FPM.
5. 增加 PHP-FPM 打开文件描述符的限制:
# vi /path/to/php-fpm.conf
找到“<value name="rlimit_files">1024</value>”
把1024 更改为 4096 或者更高.
重启 PHP-FPM.

6. Using PHP code accelerator, e.g eAccelerator, XCache. And set “cache_dir” to /dev/shm on Linux.
6.使用php代码加速器,例如 eAccelerator, XCache.在linux平台上可以把`cache_dir`指向 /dev/shm
posted @ 2013-08-05 16:19 小马歌 阅读(540) | 评论 (0)编辑 收藏
 

原文出处:http://blog.chenlb.com/2010/04/nginx-proxy-cache.html

动态网站使用缓存是很有必要的。前段时间使用了 nginx proxy_stroe 来保存静态页面,以达到缓存的目的。当然 proxy stroe 用来做缓存是不够好的方案。

缓存这一块当然还有 squid 之类的独立缓存服务器。如果使用 nginx 为 web 服务器,还要加个 squid 来缓存,是觉得多了一个 http 请求层。幸好 nginx 0.7 有了 proxy_cache 来做这个缓存的事。

之前来有个 ncache 是新浪员工开发的 nginx 模块(好像只能在 nginx 0.6 中编译无运行)。已经停止维护了,已经被加到 nginx 标准库里了。昨天还不知道 proxy_cache 就是 ncache 的功能时,还在努力匹配 ncahce,浪费了N多时间,最终没看到可以缓存。后来尝试 proxy_cache 才解决,且使用简单。

安装 Nginx 请看:安装 Nginx 配置负载均衡,如果没有 pcre 库,可以到http://sourceforge.net/projects/pcre/files/ 下载(我用的是 8.02)。

nginx 0.7.65 默认安装就可以了。

安装好后开始匹配 proxy_cache,先准备后台服务器的文件,如是 time.jsp,内容:

  1. <%=new java.util.Date() %>  

conf/nginx.conf:

  1. user  nobody;  
  2. worker_processes  1;  
  3. error_log  logs/error.log;  
  4. pid        logs/nginx.pid;  
  5.   
  6. events {  
  7.     worker_connections  1024;  
  8.     use epoll;  
  9. }  
  10.   
  11. http {  
  12.     include       mime.types;  
  13.     default_type  application/octet-stream;  
  14.   
  15.     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '  
  16.                       '$status $body_bytes_sent "$http_referer" "$request_body" '  
  17.                       '"$http_user_agent" "$http_x_forwarded_for" "$request_time"';  
  18.   
  19.     sendfile        on;  
  20.     keepalive_timeout  60;  
  21.   
  22.     proxy_cache_path /var/cache0 levels=1:2 keys_zone=pnc:100m inactive=2h max_size=10g;  
  23.     upstream backend {  
  24.         server 192.168.1.2:8080  weight=6;  
  25.         #server 192.168.1.3:8080  weight=4;  
  26.     }  
  27.   
  28.     server {  
  29.         listen       80;  
  30.         server_name  localhost;  
  31.   
  32.         access_log  logs/access.80.log  main;  
  33.   
  34.         location / {  
  35.             proxy_cache pnc;  
  36.             proxy_temp_path /var/nginx_temp;  
  37.             #proxy_cache_key "$request_uri$request_body";  
  38.             #proxy_cache_methods GET POST;  
  39.             proxy_cache_valid 200 304 1m;  
  40.             proxy_pass http://backend;  
  41.         }  
  42.   
  43.         error_page   500 502 503 504  /50x.html;  
  44.         location = /50x.html {  
  45.             root   html;  
  46.         }  
  47.     }  
  48. }  

启动 nginx 后,打开浏览器,可以狂刷 Ctrl + F5,可以看到一样的页面。一分钟后再会一个新的页面。

是 proxy_cache_valid 200 304 1m; 告诉 nginx 后台返回的结果是 200 或 304 的响应,用 1m(分钟)的缓存。

proxy_cache_key 默认是 "$scheme$host$request_uri"。

proxy_cache_methods 默认是 GET HEAD。

当要缓存 post 请求后,要用 proxy_cache_methods POST 来打开。并且 proxy_cache_key 要对,post 的请求 query string 是在请求体内,所以加 $request_body 作为 key 的一部分。要用 post ,上面匹配去了注释就可以了。

这些匹配指令详情请看官方:http://wiki.nginx.org/NginxHttpProxyModule,中文版:http://wiki.nginx.org/NginxChsHttpProxyModule

posted @ 2013-08-02 16:14 小马歌 阅读(932) | 评论 (0)编辑 收藏
 

这里主要讲的是Nginx的优化方法,同时还需要优化php-fpm配置,方法请参考:http://blog.haohtml.com/archives/11162.

优化前:

优化后:

看得出差距还是特别的大的.

/etc/sysctl.conf

一般来说nginx配置文件中对优化比较有作用的为以下几项:

worker_processes 8;
nginx进程数,建议按照cpu数目来指定,一般为它的倍数,平时设置为2倍。

cpu个数查看方法参考:http://blog.haohtml.com/archives/11123 和 http://blog.haohtml.com/archives/9236

worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
为每个进程分配cpu,上例中将8个进程分配到8个cpu,当然可以写多个,或者将一个进程分配到多个cpu。

worker_rlimit_nofile 102400;
这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n的值保持一致。ulimit的用法参考:http://blog.haohtml.com/archives/9883

use epoll;
使用epoll的I/O模型,这个不用说了吧。

worker_connections 102400;
每个进程允许的最多连接数,理论上每台nginx服务器的最大连接数为worker_processes*worker_connections

keepalive_timeout 60;
keepalive超时时间。

client_header_buffer_size 4k;

客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。

open_file_cache max=102400 inactive=20s;
这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。

open_file_cache_valid 30s;
这个是指多长时间检查一次缓存的有效信息。

open_file_cache_min_uses 1;
open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive时间内一次没被使用,它将被移除。

关于内核参数的优化:

net.ipv4.tcp_max_tw_buckets = 6000
timewait的数量,默认是180000。

net.ipv4.ip_local_port_range = 1024    65000
允许系统打开的端口范围。

net.ipv4.tcp_tw_recycle = 1
启用timewait快速回收。

net.ipv4.tcp_tw_reuse = 1
开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接。

net.ipv4.tcp_syncookies = 1
开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies来处理。

net.core.somaxconn = 262144
web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而nginx定义的NGX_LISTEN_BACKLOG默认为511,所以有必要调整这个值。

net.core.netdev_max_backlog = 262144
每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。

net.ipv4.tcp_max_orphans = 262144
系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。这个限制仅仅是为了防止简单的DoS攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后)。

net.ipv4.tcp_max_syn_backlog = 262144
记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M内存的系统而言,缺省值是1024,小内存的系统则是128。

net.ipv4.tcp_timestamps = 0
时间戳可以避免序列号的卷绕。一个1Gbps的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉。

net.ipv4.tcp_synack_retries = 1
为了打开对端的连接,内核需要发送一个SYN并附带一个回应前面一个SYN的ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送SYN+ACK包的数量。

net.ipv4.tcp_syn_retries = 1
在内核放弃建立连接之前发送SYN包的数量。

net.ipv4.tcp_fin_timeout = 1
如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60 秒。2.2 内核的通常值是180秒,你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB服务器,也有因为大量的死套接字而内存溢出的风险,FIN- WAIT-2的危险性比FIN-WAIT-1要小,因为它最多只能吃掉1.5K内存,但是它们的生存期长些。

net.ipv4.tcp_keepalive_time = 30
当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时。

下面贴一个完整的内核优化设置:

引用

net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.tcp_max_tw_buckets = 6000
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rmem = 4096        87380   4194304
net.ipv4.tcp_wmem = 4096        16384   4194304
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 262144
net.core.somaxconn = 262144
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_keepalive_time = 30
net.ipv4.ip_local_port_range = 1024    65000

下面是一个简单的nginx配置文件:

user  www www;
worker_processes 8;
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000;
error_log  /www/log/nginx_error.log  crit;
pid        /usr/local/nginx/nginx.pid;
worker_rlimit_nofile 204800;

events
{
use epoll;
worker_connections 204800;
}

http
{
include       mime.types;
default_type  application/octet-stream;

charset  utf-8;

server_names_hash_bucket_size 128;
client_header_buffer_size 2k;
large_client_header_buffers 4 4k;
client_max_body_size 8m;

sendfile on;
tcp_nopush     on;

keepalive_timeout 60;

fastcgi_cache_path /usr/local/nginx/fastcgi_cache levels=1:2
keys_zone=TEST:10m
inactive=5m;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 8 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
fastcgi_cache TEST;
fastcgi_cache_valid 200 302 1h;
fastcgi_cache_valid 301 1d;
fastcgi_cache_valid any 1m;
fastcgi_cache_min_uses 1;
fastcgi_cache_use_stale error timeout invalid_header http_500;

open_file_cache max=204800 inactive=20s;
open_file_cache_min_uses 1;
open_file_cache_valid 30s;
tcp_nodelay on;

gzip on;
gzip_min_length  1k;
gzip_buffers     4 16k;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types       text/plain application/x-javascript text/css application/xml;
gzip_vary on;
server
{
listen       8080;
server_name  backup.aiju.com;
index index.php index.htm;
root  /www/html/;  #这里的位置很重要,不要写在其它指令里面,我曾经就调试了好久才发现这个问题的

location /status
{
stub_status on;
}

location ~ .*\.(php|php5)?$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fcgi.conf;
}

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css)$
{
expires      30d;
}

log_format  access  '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for';
access_log  /www/log/access.log  access;
}
}

关于FastCGI的几个指令(http://wiki.nginx.org/NginxChsHttpFcgiModule):

fastcgi_cache_path /usr/local/nginx/fastcgi_cache levels=1:2 keys_zone=TEST:10m inactive=5m;
这个指令为FastCGI缓存指定一个路径,目录结构等级,关键字区域存储时间和非活动删除时间。

fastcgi_connect_timeout 300;
指定连接到后端FastCGI的超时时间。

fastcgi_send_timeout 300;
向FastCGI传送请求的超时时间,这个值是指已经完成两次握手后向FastCGI传送请求的超时时间。

fastcgi_read_timeout 300;
接收FastCGI应答的超时时间,这个值是指已经完成两次握手后接收FastCGI应答的超时时间。

fastcgi_buffer_size 64k;
指定读取FastCGI应答第一部分需要用多大的缓冲区,一般第一部分应答不会超过1k,由于页面大小为4k,所以这里设置为4k。

fastcgi_buffers 8 64k;
指定本地需要用多少和多大的缓冲区来缓冲FastCGI的应答。

fastcgi_busy_buffers_size 128k;
这个指令我也不知道是做什么用,只知道默认值是fastcgi_buffers的两倍。

fastcgi_temp_file_write_size 128k;
在写入fastcgi_temp_path时将用多大的数据块,默认值是fastcgi_buffers的两倍。

fastcgi_cache TEST
开启FastCGI缓存并且为其制定一个名称。个人感觉开启缓存非常有用,可以有效降低CPU负载,并且防止502错误。

fastcgi_cache_valid 200 302 1h;
fastcgi_cache_valid 301 1d;
fastcgi_cache_valid any 1m;
为指定的应答代码指定缓存时间,如上例中将200,302应答缓存一小时,301应答缓存1天,其他为1分钟。

fastcgi_cache_min_uses 1;
缓存在fastcgi_cache_path指令inactive参数值时间内的最少使用次数,如上例,如果在5分钟内某文件1次也没有被使用,那么这个文件将被移除。

fastcgi_cache_use_stale error timeout invalid_header http_500;
不知道这个参数的作用,猜想应该是让nginx知道哪些类型的缓存是没用的。

以上为nginx中FastCGI相关参数,另外,FastCGI自身也有一些配置需要进行优化,如果你使用php-fpm来管理FastCGI,可以修改配置文件中的以下值:
<value name="max_children">60</value>
同时处理的并发请求数,即它将开启最多60个子线程来处理并发连接。

<value name="rlimit_files">102400</value>
最多打开文件数。

<value name="max_requests">204800</value>
每个进程在重置之前能够执行的最多请求数。

下面贴几张测试结果图。

静态页面为我在squid配置4W并发那篇文章中提到的测试文件,下图为同时在6台机器运行webbench -c 30000 -t 600 http://backup.aiju.com:8080/index.html命令后的测试结果:
使用netstat过滤后的连接数:
php页面在status中的结果(php页面为调用phpinfo):
php页面在netstat过滤后的连接数:
未使用FastCGI缓存之前的服务器负载:
此时打开php页面已经有些困难,需要进行多次刷新才能打开。上图中cpu0负载偏低是因为测试时将网卡中断请求全部分配到cpu0上,并且在nginx中开启7个进程分别制定到cpu1-7。
使用FastCGI缓存之后:
此时可以很轻松的打开php页面。

这个测试并没有连接到任何数据库,所以并没有什么参考价值,不过不知道上述测试是否已经到达极限,根据内存和cpu的使用情况来看似乎没有,但是已经没有多余的机子来让我运行webbench了。

参考资料:

http://hi.baidu.com/myus/blog/item/f37d05d1b1d1ad399a5027ff.html

http://kenwublog.com/docs/linux-kernel-2-6-36-optimization.htm

http://blog.sina.com.cn/s/blog_50a736440100j023.html

2 THOUGHTS ON “NGINX优化配置(转)

posted @ 2013-08-01 22:18 小马歌 阅读(240) | 评论 (0)编辑 收藏
 
都知道 http加速器 现在 varnish 比 squid 名声大,所以 先整了一把varnish,但是研究之后,发现不支持SSL,只得作罢,开始换上squid.

到网上下了一个最新版 3.3.8,开始搜索配置资料,发现都是以前的旧的,不适用,后来发现了一个 针对3.0的配置: http://linux008.blog.51cto.com/2837805/618731
 
  按照提示安装完成了,启用了 --enable-ssl选项。

后来又参考官方文档 加上了https支持,参考:http://wiki.squid-cache.org/ConfigExamples/Reverse/SslWithWildcardCertifiate

 
 但是很不辛,居然报错:“FATAL: http(s)_port: defaultsite option requires Acceleration mode flag.”

然后根据提示 去 查找https_port用法,参考资料:http://www.squid-cache.org/Doc/config/https_port/

原来 是 缺少[mode]选项,根据我的需要,加了“accel”,问题解决.

具体业务的完整配置参考附件。
https_port 443 cert=/usr/local/squid/cert.pem key=/usr/local/squid/cert.key accel defaultsite=img0-yoursite.yourdomain.com vhost
cache_peer 1.2.3.4 parent 80 0 no-query originserver ssl sslflags=DONT_VERIFY_PEER name=img0
acl sites_server_img0 dstdomain img0-yoursite.yourdomain.com
cache_peer_access img0 allow sites_server_img0
http_access allow sites_server_img0

https_port 443 cert=/usr/local/squid/cert.pem key=/usr/local/squid/cert.key accel defaultsite=img1-yoursite.yourdomain.com vhost
cache_peer 1.2.3.4 parent 80 0 no-query originserver ssl sslflags=DONT_VERIFY_PEER name=img1
acl sites_server_img1 dstdomain img1-yoursite.yourdomain.com
cache_peer_access img1 allow sites_server_img1
http_access allow sites_server_img1

####base######
visible_hostname localhost
cache_mgr xiaomage234@163.com
cache_effective_user nobody
cache_effective_group nobody
####cache#####
cache_mem 600 MB
cache_swap_low 90
cache_swap_high 95
maximum_object_size 12000 KB
maximum_object_size_in_memory 1024 KB
cache_dir ufs /usr/local/squid/var/cache 10000 16 256
cache_access_log /usr/local/squid/var/logs/access.log
cache_log /usr/local/squid/var/logs/cache.log
cache_store_log /usr/local/squid/var/logs/store.log
#####no-cache##########
hierarchy_stoplist cgi-bin ?/.php
acl QUERY urlpath_regex cgi-bin /?/.php
#acl DIRECT url_regex -i ^http://192.168.0.201
cache deny QUERY
#cache deny DIRECT
#####refresh_pattern####
refresh_pattern ^ftp: 60 20% 10080
refresh_pattern ^gopher: 60 0% 1440

refresh_pattern ^gopher: 60 0% 1440
refresh_pattern . 0 20% 1440
refresh_pattern -i /.css$       360     50%     2880     reload-into-ims
refresh_pattern -i /.js$        1440    50%     2880     reload-into-ims
refresh_pattern -i /.html$      720     50%     1440     reload-into-ims
refresh_pattern -i /.jpg$       1440    90%     2880     ignore-reload
refresh_pattern -i /.gif$       1440    90%     2880     ignore-reload
refresh_pattern -i /.swf$       1440    90%     2880     ignore-reload
refresh_pattern -i /.jpg$       1440    50%     2880     ignore-reload
refresh_pattern -i /.png$       1440    50%     2880     ignore-reload
refresh_pattern -i /.bmp$       1440    50%     2880     ignore-reload
refresh_pattern -i /.doc$       1440    50%     2880     ignore-reload
refresh_pattern -i /.ppt$       1440    50%     2880     ignore-reload
refresh_pattern -i /.xls$       1440    50%     2880     ignore-reload
refresh_pattern -i /.pdf$       1440    50%     2880     ignore-reload
refresh_pattern -i /.rar$       1440    50%     2880     ignore-reload
refresh_pattern -i /.zip$       1440    50%     2880     ignore-reload
refresh_pattern -i /.txt$       1440    50%     2880     ignore-reload
######proxy agent###        
http_port 80 accel vhost vport
cache_peer 1.2.3.4 parent 80 0 no-query originserver name=img00
cache_peer_domain img00 img0-yoursite.yourdomain.com

cache_peer 1.2.3.4 parent 80 0 no-query originserver name=img01
cache_peer_domain img01 img1-yoursite.yourdomain.com
######alc#####
acl manager2 proto cache_object
acl localhost src 127.0.0.1/32
acl to_localhost dst 127.0.0.0/8
acl localnet src 10.0.0.0/8     # RFC1918 possible internal network
acl localnet src 172.16.0.0/12  # RFC1918 possible internal network
acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
acl LanSrc src all
acl LanDst dst all
acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 21          # ftp
acl Safe_ports port 443         # https
acl Safe_ports port 70          # gopher
acl Safe_ports port 210         # wais
acl Safe_ports port 1025-65535  # unregistered ports
acl Safe_ports port 280         # http-mgmt
acl Safe_ports port 488         # gss-http
acl Safe_ports port 591         # filemaker
acl Safe_ports port 777         # multiling http
acl CONNECT method CONNECT
acl LanDstDM dstdomain .kanbox.com

http_access allow manager2 localhost
http_access deny manager2
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow LanDstDM
http_access allow LanSrc
http_access allow LanDst
http_access allow localnet
http_access deny all

下载附件:
/Files/xiaomage234/squid.conf.txt

v
arnish的配置,不支持https:
/Files/xiaomage234/default.vcl.txt
posted @ 2013-07-31 13:58 小马歌 阅读(4266) | 评论 (1)编辑 收藏
 
from:http://blog.csdn.net/langeldep/article/details/6641682
分类: Linux操作与使用2011-07-28 17:49 4999人阅读 评论(4) 收藏 举报

要使用分布式文件系统来降低成本,于是搜寻了开源的分布式文件系统。


经过安装部署和测试,把我使用中碰到的一些问题总结一下, 希望对大家有所帮助, 我也有一些问题没有搞懂,希望和大家一起交流,共同进步。


第一:CEPH

网上搜索了一些资料, 说 ceph 性能最高,C++编写的代码,支持Fuse,并且没有单点故障依赖, 于是下载安装, 由于 ceph 使用 btrfs 文件系统, 而btrfs 文件系统需要 Linux 2.6.34 以上的内核才支持, 显然我使用的 RHEL5 的内核还不支持 btrfs文件系统, 于是下载最新的内核进行升级, 搞了2天没有升级成功, 编译一次都要耗费1个多小时才能完成,最后发现最新版的 ubuntu 系统支持btrfs文件系统, 于是安装 ubuntu 的虚拟机,btrfs 文件系统搞定了, 但是启动ceph的相关进程出错, 无法启动成功。所以谈不上对其进行过测试。


CEPH中使用了一个比较先进的算法 crush算法, 据翻译出来,为分布式基于对象的存储系统设计了一个可升级的伪随机的数据分布函数,它能够有效地管理数据对象和存储设备,而不需要通过一个中心目录。由于大系统都是动态的,CRUSH被设计成为一个当把不需要的数据迁移最小化时,能方便的增加或移除存储设备。这个算法提供了一个大范围的不同种类的数据复制和可靠性机制,以及根据用户自定义的策略来分配数据,这种策略迫使数据复制从故障领域分离出来。


另外CEPH使用的文件系统为btrfs, 这个文件系统具有很多先进的特性, 为下一代Linux使用的文件系统。

BTRFS最终可能会给ZFS等带来更多威胁,它具有在线碎片整理功能(只有固态盘有这项功能)、Copy-On-Write技术、数据压缩、镜像、数据条带和快照等等。

  另外,BTRFS在数据存储方面比ext更完善。它包括一些逻辑卷管理和RAID硬件功能,可以对内部元数据和用户数据进行检验和,同时内嵌了快照功能。ext4也可以实现以上一些功能,但是需要与文件系统和逻辑卷管理器进行通信。


这么多先进的功能, 可惜现在还无法消受啊。。。。。。


第二:glusterfs

网上说glusterfs比较不错, 稳定,适合大型应用, 关键是没有单点故障依赖,C语言的代码, 支持FUSE,于是下载安装研究。 安装配置还算简单,启动后进行测试。

开始感觉确实不错,很爽。 后来用压力测试工具对其吞吐量进行测试 , 发现性能不能满足我们的生产需求,不知道是哪里的配置问题,

我们测试的都是大文件的读操作和大文件的写操作, 吞吐量在 5MB/秒左右, 显然不能满足要求。但是没有找到具体的瓶颈,毕竟程序是别人写的,要查瓶颈也不容易。


关于 glusterfs的详细的资料, 可以看这位弟兄的文章, 他做的比较深入  。

http://zhoubo.sinaapp.com/?cat=22


第三:moosefs

这个网上说性能不错,有单点故障依赖, C代码编写,支持FUSE, 下载试试吧。

安装配置还算简单。很快就搭建好环境了, 于是进行测试。测试性能还不错。吞吐量在15MB/秒以上。


第四:mogilefs 

网上说这个是性能最高的, 不过是perl编写的代码, 对外提供API来进行使用, 搭建相对比较复杂一点, 因为需要安装很多依赖的第三方perl包,另外还要安装Mysql数据库来支持。

安装完毕后, 服务器端起来了, 客户端有JAVA, PHP,  PERL, RUBY 等开发的, 我需要的是要支持 FUSE 的, 但是这个分布式的文件系统,对FUSE的支持需要安装一个PERL与C通信的模块, 这个模块死活编译不过去, 最后无法测试成功,无奈只能有时间了继续研究。


第五:fastDFS

网上说是“国人在mogileFS的基础上进行改进的key-value型文件系统,同样不支持FUSE,提供比mogileFS更好的性能”, 这不是扯蛋吗 ? Mogilefs 是perl写的, 如果 fastDFS是在 mogilefs 的基础上改进的话, 应该也是perl写的, 但是下载了fastDFS的代码后, 人家都是C的代码, 怎么可能是在mogilefs的基础上改进呢 ?看了一下fastDFS具体的结构,准确的说应该是“借鉴了MogileFS的思路”,而不能说“在MogileFS的基础上改进”。


我安装了一下, 安装还算简单, 不支持fuse, 上传文件后会生成一个http的下载地址, 通过http的方式进行下载。这种方式显然不适合我想要的生产环境。



下面是一个网友写的 FastFDS和MogileFS的对比文章, 感觉比较客观真实, 所以在这里给大家转帖一下。



FastDFS设计时借鉴了MogileFS的一些思路。FastDFS是一个完善的分布式文件存储系统,通过客户端API对文件进行读写。可以说,MogileFS的所有功能特性FastDFS都具备,MogileFS网址:http://www.danga.com/mogilefs/。

另外,相对于MogileFS,FastDFS具有如下特点和优势:
1. FastDFS完善程度较高,不需要二次开发即可直接使用;
2. 和MogileFS相比,FastDFS裁减了跟踪用的数据库,只有两个角色:tracker和storage。FastDFS的架构既简化了系统,同时也消除了性能瓶颈;
3. 在系统中增加任何角色的服务器都很容易:增加tracker服务器时,只需要修改storage和client的配置文件(增加一行tracker配置);增加storage服务器时,通常不需要修改任何配置文件,系统会自动将该卷中已有文件复制到该服务器;
4. FastDFS比MogileFS更高效。表现在如下几个方面:
  1)参见上面的第2点,FastDFS和MogileFS相比,没有文件索引数据库,FastDFS整体性能更高;
  2)从采用的开发语言上看,FastDFS比MogileFS更底层、更高效。FastDFS用C语言编写,代码量不到2万行,没有依赖其他开源软件或程序包,安装和部署特别简洁;而MogileFS用perl编写;
  3)FastDFS直接使用socket通信方式,相对于MogileFS的HTTP方式,效率更高。并且FastDFS使用sendfile传输文件,采用了内存零拷贝,系统开销更小,文件传输效率更高。
5. FastDFS有着详细的设计和使用文档,而MogileFS的文档相对比较缺乏。
6. FastDFS的日志记录非常详细,系统运行时发生的任何错误信息都会记录到日志文件中,当出现问题时方便管理员定位错误所在。
7. FastDFS还对文件附加属性(即meta data,如文件大小、图片宽度、高度等)进行存取,应用不需要使用数据库来存储这些信息。
8. FastDFS从V1.14开始支持相同文件内容只保存一份,这样可以节省存储空间,提高文件访问性能。


第六:Lustre

本来还对这个分布式文件系统抱有无限的希望, 被Oracle公司收购后, 这个东西连下载地址都没有了。。。。。。, 狂晕一吧!!!

如果那个弟兄找到下载地址, 麻烦给通知一下, 谢谢。

posted @ 2013-07-18 14:38 小马歌 阅读(425) | 评论 (0)编辑 收藏
 

1.     ccmalloc-Linux和Solaris下对C和C++程序的简单的使用内存泄漏和malloc调试库。

2.     Dmalloc-Debug Malloc Library.

3.     Electric Fence-Linux分发版中由Bruce Perens编写的malloc()调试库。

4.     Leaky-Linux下检测内存泄漏的程序。

5.     LeakTracer-Linux、Solaris和HP-UX下跟踪和分析C++程序中的内存泄漏。

6.     MEMWATCH-由Johan Lindh编写,是一个开放源代码C语言内存错误检测工具,主要是通过gcc的precessor来进行。

7.     Valgrind-Debugging and profiling Linux programs, aiming at programs written in C and C++.

8.     KCachegrind-A visualization tool for the profiling data generated by Cachegrind and Calltree.

9.     Leak Monitor-一个Firefox扩展,能找出跟Firefox相关的泄漏类型。

10. IE Leak Detector (Drip/IE Sieve)-Drip和IE Sieve leak detectors帮助网页开发员提升动态网页性能通过报告可避免的因为IE局限的内存泄漏。

11. Windows Leaks Detector-探测任何Win32应用程序中的任何资源泄漏(内存,句柄等),基于Win API调用钩子。

12. SAP Memory Analyzer-是一款开源的JAVA内存分析软件,可用于辅助查找JAVA程序的内存泄漏,能容易找到大块内存并验证谁在一直占用它,它是基于Eclipse RCP(Rich Client Platform),可以下载RCP的独立版本或者Eclipse的插件。

13. DTrace-即动态跟踪Dynamic Tracing,是一款开源软件,能在Unix类似平台运行,用户能够动态检测操作系统内核和用户进程,以更精确地掌握系统的资源使用状况,提高系统性能,减少支持成本,并进行有效的调节。

14. IBM Rational PurifyPlus-帮助开发人员查明C/C++、托管.NET、Java和VB6代码中的性能和可靠性错误。PurifyPlus 将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单一、完整的工具包中。

15. Parasoft Insure++-针对C/C++应用的运行时错误自动检测工具,它能够自动监测C/C++程序,发现其中存在着的内存破坏、内存泄漏、指针错误和I/O等错误。并通过使用一系列独特的技术(SCI技术和变异测试等),彻底的检查和测试我们的代码,精确定位错误的准确位置并给出详细的诊断信息。能作为Microsoft Visual C++的一个插件运行。

16. Compuware DevPartner for Visual C++ BoundsChecker Suite-为C++开发者设计的运行错误检测和调试工具软件。作为Microsoft Visual Studio和C++ 6.0的一个插件运行。

17. Electric Software GlowCode-包括内存泄漏检查,code profiler,函数调用跟踪等功能。给C++和.Net开发者提供完整的错误诊断,和运行时性能分析工具包。

18. Compuware DevPartner Java Edition-包含Java内存检测,代码覆盖率测试,代码性能测试,线程死锁,分布式应用等几大功能模块。

19. Quest JProbe-分析Java的内存泄漏。

20. ej-technologies JProfiler-一个全功能的Java剖析工具,专用于分析J2SE和J2EE应用程序。它把CPU、执行绪和内存的剖析组合在一个强大的应用中。JProfiler可提供许多IDE整合和应用服务器整合用途。JProfiler直觉式的GUI让你可以找到效能瓶颈、抓出内存泄漏、并解决执行绪的问题。4.3.2注册码:A-G666#76114F-1olm9mv1i5uuly#0126

21. BEA JRockit-用来诊断Java内存泄漏并指出根本原因,专门针对Intel平台并得到优化,能在Intel硬件上获得最高的性能。

22. SciTech Software AB .NET Memory Profiler-找到内存泄漏并优化内存使用针对C#,VB.Net,或其它.Net程序。

23. YourKit .NET & Java Profiler-业界领先的Java和.NET程序性能分析工具。

24. AutomatedQA AQTime-AutomatedQA的获奖产品performance profiling和memory debugging工具集的下一代替换产品,支持Microsoft, Borland, Intel, Compaq 和 GNU编译器。可以为.NET和Windows程序生成全面细致的报告,从而帮助您轻松隔离并排除代码中含有的性能问题和内存/资源泄露问题。支持.Net 1.0,1.1,2.0,3.0和Windows 32/64位应用程序。

25. JavaScript Memory Leak Detector-微软全球产品开发欧洲团队(Global Product Development- Europe team, GPDE) 发布的一款调试工具,用来探测JavaScript代码中的内存泄漏,运行为IE系列的一个插件。

附录:内存泄漏的发生方式

1.     常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。

2.     偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。

3.     一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块且仅有一块内存发生泄漏。

4.     隐 式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是 对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。

什么是系统资源?

当应用程序在Windows中运行时,Windows必须实时"跟踪"该应用程序的运行,并保留与之相关的许多信息,如按钮、光标、菜单的位置和位图、窗口的状况等,这些信息由Windows保留在一种叫堆的内存块中,堆的英文为Heap。简单地说,堆是采用特殊机制管理的内存块。由Windows的一个系统内核User.exe管理的堆叫做User资源堆(User Resource Heap),由另一个系统内核Gdi.exe管理的堆叫做GDI资源堆(Graphical Device Interface Resource Heap,简称GDI Resource Heap),User资源堆和GDI资源堆合称为系统资源堆(System Resource Heap),习惯上就把它们叫做系统资源(System Resource)。

  微软将Windows的系统资源(堆)分为五个堆,其中User资源堆为三个,而GDI资源堆为两个。

  三个User资源堆分别是:16位的用户堆(User Heap,64KB);32位的窗口堆(Windows Heap,2MB);32位的用户菜单堆(User Menu Heap,2MB)。

  两个GDI资源堆分别是:16位的GDI堆(GDI Heap,64KB);32位的GDI堆(GDI,2MB)。

  从这里的系统资源分类和大小我们应该明白,不管CPU是P4还是486,内存是8M还是1G,所有Windows的用户都拥有同样大小的系统资源(堆),用户不能自已增加或减少系统资源的大小,这是由操作系统决定的,与硬件档次没有任何关系。

  Windows的User资源堆和GDI资源堆的可用(Free)空间称为可用 User资源和可用GDI资源,Windows中以百分数表示它们,用户可以选择 "开始/附件/系统工具/系统信息",来实时查看它们的大小。 
为了您的安全,请只打开来源可靠的网址


来自: http://hi.baidu.com/jrckkyy/blog/item/6947f42332ec80589922ed6d.html 

posted @ 2013-06-26 15:12 小马歌 阅读(1580) | 评论 (0)编辑 收藏
 

1. Tair总述

1.1 系统架构

一个Tair集群主要包括3个必选模块:configserver、dataserver和client,一个可选模块:invalidserver。通常情况下,一个集群中包含2台configserver及多台dataServer。两台configserver互为主备并通过维护和dataserver之间的心跳获知集群中存活可用的dataserver,构建数据在集群中的分布信息(对照表)。dataserver负责数据的存储,并按照configserver的指示完成数据的复制和迁移工作。client在启动的时候,从configserver获取数据分布信息,根据数据分布信息和相应的dataserver交互完成用户的请求。invalidserver主要负责对等集群的删除和隐藏操作,保证对等集群的数据一致。

从架构上看,configserver的角色类似于传统应用系统的中心节点,整个集群服务依赖于configserver的正常工作。但实际上相对来说,tair的configserver是非常轻量级的,当正在工作的服务器宕机的时候另外一台会在秒级别时间内自动接管。而且,如果出现两台服务器同时宕机的最恶劣情况,只要应用服务器没有新的变化, tair依然服务正常。而有了configserver这个中心节点,带来的好处就是应用在使用的时候只需要配置configserver的地址(现在可以直接配置Diamond key),而不需要知道内部节点的情况。

1.1.1 ConfigServer的功能

1) 通过维护和dataserver心跳来获知集群中存活节点的信息
2) 根据存活节点的信息来构建数据在集群中的分布表。
3) 提供数据分布表的查询服务。
4) 调度dataserver之间的数据迁移、复制。

1.1.2 DataServer的功能

1) 提供存储引擎
2) 接受client的put/get/remove等操作
3) 执行数据迁移,复制等
4) 插件:在接受请求的时候处理一些自定义功能
5) 访问统计

1.1.3 InvalidServer的功能

1) 接收来自client的invalid/hide等请求后,对属于同一组的集群(双机房独立集群部署方式)做delete/hide操作,保证同一组集群的一致。
2) 集群断网之后的,脏数据清理。
3) 访问统计。

1.1.4 client的功能

1) 在应用端提供访问Tair集群的接口。
2) 更新并缓存数据分布表和invalidserver地址等。
3) LocalCache,避免过热数据访问影响tair集群服务。
4) 流控

1.2 存储引擎与应用场景

Tair经过这两年的发展演进,除了应用于cache缓存外,在存储(持久化)上支持的应用需求也越来越广泛。现在主要有mdb,rdb,ldb三种存储引擎。

1.2.1 mdb

定位于cache缓存,类似于memcache。
支持k/v存取和prefix操作

1.2.1.1 mdb的应用场景
在实际业务中,大部分当缓存用(后端有DB之类的数据源)。
也可用做大访问少量临时数据的存储(例如session登录,防攻击统计等)。
集团内绝对多数cache服务都是采用的tair mdb。

1.2.2 rdb

定位于cache缓存,采用了redis的内存存储结构。
支持k/v,list,hash,set,sortedset等数据结构。

1.2.2.1 rdb的应用场景
适用于需要高速访问某些数据结构的应用,例如SNS中常见的的粉丝存储就可以采用set等结构;或者存储一个商品的多个属性(hashmap);高效的消息队列(list)等。现在有30个左右的应用在使用rdb服务。

1.2.3 ldb

定位于高性能存储,并可选择内嵌mdb cache加速,这种情况下cache与持久化存储的数据一致性由tair进行维护。 支持k/v,prefix等数据结构。今后将支持list,hash,set,sortedset等redis支持的数据结构。

1.2.3.1 ldb的应用场景
存储,里面可以细分如下场景:
1) 持续大数据量的存入读取,类似淘宝交易快照。
2) 高频度的更新读取,例如计数器,库存等。
3) 离线大批量数据导入后做查询。参见fastdump
也可以用作cache:
数据量大,响应时间敏感度不高的cache需求可以采用。例如天猫实时推荐。

1.3 基本概念

1.3.1 configID

唯一标识一个tair集群,每个集群都有一个对应的configID,在当前的大部分应用情况下configID是存放在diamond中的,对应了该集群的configserver地址和groupname。业务在初始化tairclient的时候需要配置此ConfigID。

1.3.2 namespace

又称area, 是tair中分配给应用的一个内存或者持久化存储区域, 可以认为应用的数据存在自己的namespace中。 
同一集群(同一个configID)中namespace是唯一的。
通过引入namespace,我们可以支持不同的应用在同集群中使用相同的key来存放数据,也就是key相同,但内容不会冲突。一个namespace下是如果存放相同的key,那么内容会受到影响,在简单K/V形式下会被覆盖,rdb等带有数据结构的存储引擎内容会根据不同的接口发生不同的变化。

1.3.3 quota配额

对应了每个namespace储存区的大小限制,超过配额后数据将面临最近最少使用(LRU)的淘汰。
持久化引擎(ldb)本身没有配额,ldb由于自带了mdb cache,所以也可以设置cache的配额。超过配额后,在内置的mdb内部进行淘汰。

1.3.3.1 配额是怎样计算的
配额大小直接影响数据的命中率和资源利用效率,业务方需要给出一个合适的值,通常的计算方法是评估在保证一定命中率情况下所需要的记录条数,这样配额大小即为: 记录条数 * 平均单条记录大小。

1.3.3.2 管理员如何配置配额
单份数据情况下,业务提供的配额就是需要配置在Tair系统中的配额。但对于多备份,在系统中实际计算的配额为: 业务配额 * 备份数

1.3.4 expireTime:过期时间

expiredTime 是指数据的过期时间,当超过过期时间之后,数据将对应用不可见,这个设置同样影响到应用的命中率和资源利用率。不同的存储引擎有不同的策略清理掉过期的数据。调用接口时,expiredTime单位是秒,可以是相对时间(比如:30s),也可以是绝对时间(比如:当天23时,转换成距1970-1-1 00:00:00的秒数)。 小于0,不更改之前的过期时间
如果不传或者传入0,则表示数据永不过期;
大于0小于当前时间戳是相对时间过期;
大于当前时间戳是绝对时间过期;

1.3.5 version

Tair中存储的每个数据都有版本号,版本号在每次更新后都会递增,相应的,在Tair put接口中也有此version参数,这个参数是为了解决并发更新同一个数据而设置的,类似于乐观锁。
很多情况下,更新数据是先get,修改get回来的数据,然后put回系统。如果有多个客户端get到同一份数据,都对其修改并保存,那么先保存的修改就会被后到达的修改覆盖,从而导致数据一致性问题,在大部分情况下应用能够接受,但在少量特殊情况下,这个是我们不希望发生的。
比如系统中有一个值”1”, 现在A和B客户端同时都取到了这个值。之后A和B客户端都想改动这个值,假设A要改成12,B要改成13,如果不加控制的话,无论A和B谁先更新成功,它的更新都会被后到的更新覆盖。Tair引入的version机制避免了这样的问题。刚刚的例子中,假设A和B同时取到数据,当时版本号是10,A先更新,更新成功后,值为12,版本为11。当B更新的时候,由于其基于的版本号是10,此时服务器会拒绝更新,返回version error,从而避免A的更新被覆盖。B可以选择get新版本的value,然后在其基础上修改,也可以选择强行更新。

1.3.5.1 如何获取到当前key的version
get接口返回的是DataEntry对象,该对象中包含get到的数据的版本号,可以通过getVersion()接口获得该版本号。在put时,将该版本号作为put的参数即可。 如果不考虑版本问题,则可设置version参数为0,系统将强行覆盖数据,即使版本不一致。

1.3.5.2 version是如何改变的
Version改变的逻辑如下:
1) 如果put新数据且没有设置版本号,会自动将版本设置成1。
2) 如果put是更新老数据且没有版本号,或者put传来的参数版本与当前版本一致,版本号自增1。
3) 如果put是更新老数据且传来的参数版本与当前版本不一致,更新失败,返回VersionError。
4) put时传入的version参数为0,则强制更新成功,版本号自增1。

1.3.5.3 version返回不一致的时候,该如何处理
如果更新所基于的version和系统中当前的版本不一致,则服务器会返回ResultCode.VERERROR。 这时你可以重新get数据,然后在新版本的数据上修改;或者设置version为0重新请求,以达到强制更新的效果,应用可以根据自身对数据一致性的要求在这两种策略间进行选择。

1.3.5.4 version具体使用案例
如果应用有10个client会对key进行并发put,那么操作过程如下: 
1) get key。如果get key成功,则进入步骤2;如果数据不存在,则进入步骤3. 
2) 在调用put的时候将get key返回的verison重新传入put接口。服务端根据version是否匹配来返回client是否put成功。 
3) get key数据不存在,则新put数据。此时传入的version必须不是0和1,其他的值都可以(例如1000,要保证所有client是一套逻辑)。因为传入0,tair会认为强制覆盖;而传入1,第一个client写入会成功,但是新写入时服务端的version以0开始计数啊,所以此时version也是1,所以下一个到来的client写入也会成功,这样造成了冲突

1.3.5.5 version分布式锁
Tair中存在该key,则认为该key所代表的锁已被lock;不存在该key,在未加锁。操作过程和上面相似。业务方可以在put的时候增加expire,已避免该锁被长期锁住。
当然业务方在选择这种策略的情况下需要考虑并处理Tair宕机带来的锁丢失的情况。

1.3.5.6 什么情况下需要使用version
业务对数据一致性有较高的要求,并且访问并发高,那么通过version可以避免数据的意外结果。
如果不关心并发,那么建议不传入version或者直接传0。

1.4 集群部署方式

Tair通过多种集群部署方式,来满足各类应用的容灾需求。
下面所述的双机房可以扩展到多机房,现阶段基本还是采用的双机房。
现总共有4种方式:
mdb存储引擎适用于双机房单集群单份,双机房独立集群,双机房单集群双份。
rdb存储引擎适用于双机房单集群单份。
ldb存储引擎适用于双机房主备集群,双机房单集群单份。

1.4.1 双机房单集群单份

双机房单集群单备份数是指,该Tair集群部署在两个机房中(也就是该Tair集群的机器分别在两个机房), 数据存储份数为1, 该类型集群部署示意图如下所示。数据服务器(Dataserver)分布在两个机房中,他们都属于同一集群。

使用场景:
1) 后端有无数据源都可。
2) 后端有数据源,且更新比例很高的场景。
优点:
1) 服务器存在于双机房,任一机房宕机保持可用。
2) 单份数据,无论应用在哪个机房,看到的都是同一个数据。
缺点:
1) 应用服务器会跨机房访问。如上图,并假设应用服务器在cm3和cm4,那么cm3的应用服务器也可能调用到cm4的tair机器,cm4的亦然。
2) 当一边机房出现故障时,tair中的数据会失效一半(一半这个数值是按两边机房tair机器数相同估计的,如果不相同,则按对应比例估算)
该部署方式,应用在删除数据时,只需要调用delete即可,无需调用invalid。当然,调用invalid也可,这种方式下会直接退化到delete。

1.4.2 双机房独立集群

双机房独立集群是指,在两个机房中同时部署2个独立的Tair集群,这两个集群没有直接关系。下图是一个典型的双机房独立集部署示意图,可以看到,cm3和cm4各有一个完整的tair集群(2个configserver+多个dataserver)。图中还多了一个invalidserver的角色, invalidserver接收客户端的invalid或者hide请求后,会对各机房内的集群进行delete或者hide操作,以此保障Tair中的数据和后端数据源保持一致的。

适用场景:
1) 后端必须要有数据源,否则则退化成单机房集群,Tair集群本身不做同步。
2) 读写比不能过小,不然可能会带来Tair命中率降低。例如某个key,在数据库中被频繁更新,那么此时应用必须调用invalid来确保Tair和DB的一致性。此时应用读Tair一直会不命中,导致整体命中率低,可能造成DB压力比较大。 如果依然有疑问的话,请联系 tair答疑。
优点:
1) 每个机房拥有独立Tair集群,应用在哪个机房就访问相同机房的Tair集群,不会出现跨机房调用和流量。
2) 单边机房故障,不会影响业务访问tair命中率。
缺点:
1) 后端必须要有数据源,也就是这种部署方式下,Tair必然是当作传统意义上的cache存在的。因为Tair mdb集群之间本身不会做数据同步,多集群间一致性保证依赖于后端数据源,如DB。
2) 当后端数据源数据发生更新后,业务不能直接把数据put到Tair,而是先需要调用invalid接口来失效这些对等集群中的数据(来保持各Tair集群的数据和后端数据源的一致性)。之后业务可以把数据put到当前Tair集群(注意:只会put到本机房的Tair集群,不会put到对端集群)或者在读Tair时发生not exist的时候从后端数据源取来放入Tair。

1.4.3 双机房单集群双份

双机房单集群双份,是指一个Tair集群部署在2个机房中,数据保存2份,并且同一数据的2个备份不会放在同一个数据服务器上。根据数据分布策略的不同,还可以将同一份数据的不同备份分布到不同的机房上。该类型的集群部署方式与双机房单集群单份数据的部署方式一样。其不同之处,数据保存份数不一样。该类型集群部署方式示意图如下图所示,数据服务器分别部署在两个不同的机房里,所有的数据服务器都被相同的配置服务器管理,在逻辑上,他们构成一个独立的集群。

现只有tbsession集群使用了这种部署方式。
适用场景:
后端无数据源,临时数据的存放,非cache。
cache类应用推荐使用双机房独立集群和双机房单集群单份部署方式。
优点:
1) 数据存放两份,数据安全性有一定保障。但由于存储引擎是mdb,数据存放在内存中,无法绝对保证数据不丢失。
2) 当一边机房故障时,另外一边机房依然可以服务,并且数据不丢失。
缺点:
1) 如果机房间网络出现异常情况,依然有较小几率丢失数据。

1.4.4 双机房主备集群

这种部署方式中,存在一个主集群和一个备份集群,分别在两个机房中。如下图所示,不妨假设CM3中部署的是主集群,CM4中部署的是备份集群。那么,在正常情况下,用户只使用主集群,读写数据都与主集群交互。主备集群会自动同步数据(不需要业务去更新两边),保证两个机房数据的最终一致性。当一个机房发生故障后,备集群会自动切换成主集群,提供服务,保证系统可用性。

适用场景:
该方式只在ldb存储引擎中存在,也就是业务将Tair当作最终存储使用。我们会在当前主集群存两份数据,并由Tair异步将数据更新到备集群,确保数据安全和服务可用。
优点:
1) 数据安全和服务可用性高。
2) 用户调用方便,无需考虑多集群间数据一致性的问题。

posted @ 2013-06-25 11:58 小马歌 阅读(393) | 评论 (0)编辑 收藏
 
 相对于SOCKET开发者,TCP创建过程和链接折除过程是由TCP/IP协议栈自动创建的.因此开发者并不需要控制这个过程.但是对于理解TCP底层运作机制,相当有帮助.
 
   而且对于有网络协议工程师之类笔试,几乎是必考的内容.企业对这个问题热情之高,出乎我的意料:-)。有时上午面试前强调这个问题,并重复讲一次,下午几乎每一个人都被问到这个问题。
 
因此在这里详细解释一下这两个过程。
 
TCP三次握手
 
所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。
 
三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.在socket编程中,客户端执行connect()时。将触发三次握手。
 
 
 
 
  • 第一次握手:
    客户端发送一个TCP的SYN标志位置1的包指明客户打算连接的服务器的端口,以及初始序号X,保存在包头的序列号(Sequence Number)字段里。
  • 第二次握手:
    服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均为1同时,将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即X+1。

 

  • 第三次握手.
    客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1

SYN攻击

   在三次握手过程中,服务器发送SYN-ACK之后,收到客户端的ACK之前的TCP连接称为半连接(half-open connect).此时服务器处于Syn_RECV状态.当收到ACK后,服务器转入ESTABLISHED状态.

  Syn攻击就是 攻击客户端 在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直 至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。

 Syn攻击是一个典型的DDOS攻击。检测SYN攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击.在Linux下可以如下命令检测是否被Syn攻击

netstat -n -p TCP | grep SYN_RECV

一般较新的TCP/IP协议栈都对这一过程进行修正来防范Syn攻击,修改tcp协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半连接和缩短超时时间等.

但是不能完全防范syn攻击。

TCP 四次挥手

TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。

 

 

 

参见wireshark抓包,实测的抓包结果并没有严格按挥手时序。我估计是时间间隔太短造成。

source url:http://bluedrum.cublog.cn


TCP状态变迁图及状态说明

状态:描述
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉
posted @ 2013-06-24 16:33 小马歌 阅读(364) | 评论 (0)编辑 收藏
仅列出标题
共95页: First 上一页 25 26 27 28 29 30 31 32 33 下一页 Last