Quantcast
Channel: IT社区推荐资讯 - ITIndex.net
Viewing all 15843 articles
Browse latest View live

软件的升级、更新是个怎样的过程?

$
0
0
感谢 @ 胡 锦 涛邀请,这个不敢不答啊,说不定已经有数十个快递员在我家门外蓄势待发呢。

在互联网不太普及的时代,很多软件公司还是会发布离线更新包,这种更新包其实就是个安装程序,只是安装的内容是更新的部分,没有变化的文件直接用已经安装的版本的。此外这些安装程序还会修改一些系统配置以适应新版本的功能,比如注册COM组件,修改注册表等。

现在互联网已经十分普及,几乎所有软件都采用在线升级,具体实现上,有下列几种做法。

1. 比较简单的,通过http协议,检测是否有更新,就是把本地版本号发给服务器,服务器会返回一个配置文件,里面表明是否有新版本,并且带有新版本的下载地址,更新程序按照URL下载新版本的安装程序,然后执行这个安装程序,用户根据安装程序提示进行更新。

2. 再进化一步,每次都重新安装太麻烦,更新程序下载一个新版本的压缩包(zip/7z),然后帮用户解压缩到安装目录。现在客户端都追求简单设计尽量降低和系统的耦合,基本都是复制文件就算安装的那种绿色软件,所以把新版本的文件一更新就能用。

3. 如果某个软件体积已经比较大了,比如大于10MB,每次都下载一个完整的新版本的话,下载就太慢,安装也慢。既然本地已经有个安装版本了,每次更新其实变化的东西也不是很多,那么有个软件就下载一个更新文件的压缩包,然后解压缩到安装目录覆盖旧文件。

4. 有的软件更大,更新也频繁,每次更新的exe dll模块大多都有更新,所以还是要下载很大的更新包,于是有人用 bsdiff算法求新版本和旧版本的二进制差异,如果新版本就是修了bug改了几行代码,那么bsdiff生产的补丁也就几KB,下载的二进制补丁用bspatch来更新本地版本。bsdiff的算法库很小,大约才30+KB很容易集成到更新程序里。

5. 有的软件更更大,即使用bsdiff产生的补丁还是很大,有人搞出了更给力的补丁算法,Chrome的方法, http://dev.chromium.org/developers/design-documents/software-updates-courgette
从介绍看,它比bsdiff生成的补丁还要小一个数量级,这个想法相当巧妙,对于那种代码模块为主的程序尤其有效。很多时候我们只改了几行代码,但是DLL模块却改变了很多,主要是因为代码优化链接时重排造成的,如果比较汇编代码差异就会很小,Courgette就把DLL反编译成汇编码,然后和旧版本的汇编码比较得到差异,更新的时候把旧版本也反编译打补丁然后再编译成DLL。这样的话如果只改了几行代码,那么生成的补丁可能就几十个字节。

6. 随着更新包越来越大,更新下载和安装的时间也越来越长,造成用户长时间等待,有的软件采用了后台下载后台更新的方式。所谓后台下载就是无论用户是否点了立刻更新,只要有新版本就在后台偷偷给用户下载下来,有点流氓,但这也是为了用户体验呢。那么后台更新呢,正在运行的程序,每个文件都是被占用的,是不能更新的。还是Chrome想出来的,双目录更新,把就版本先复制到另一个目录,然后更新这份新复制的,下次用户启动的时候就直接启动新版本。
比如 Chrome有如下的目录结构
Chrome
    +Application
        +35.0.1916.153
        +35.0.1916.114
         chrome.exe 

它用版本号做目录名,每次升级的时候更新新版本,旧版本在另一个目录运行不受影响。下次启动的时候 Chrome.exe永远加载最新版本的dll运行就好了。chrome.exe是个很小的程序,里面的逻辑就是检测下版本号加载最新版本的dll,这样简单的程序本身几乎不需要更新。


在需求的推动下,现代客户端的升级程序已经相当复杂了,包括了支持灰度放量的新版本检测,http断点续传下载,MD5完整性校验,bsdiff/courgette 二进制补丁更新,双目录迭代升级等技术。到了移动app时代,以上这些技术都用不到了,操作系统垄断了升级机制,只能通过操作系统检测下载安装更新,iOS做得相当彻底,Android还给app留了条自己下载apk安装的路,但是二进制补丁完整性校验等就彻底不需要app开发者自己操心了。

— 完 —
本文作者: 姚冬

【知乎日报】 你都看到这啦,快来点我嘛 Σ(▼□▼メ)

此问题还有 1 个回答,查看全部。
延伸阅读:
有哪些工具或者软件堪称神器?
国内软件盗版流行的原因是什么?

99%的人都不知道的iPhone功能

$
0
0

一:晃手机可以撤销输入的文字

f49a53af-5d2f-429a-8876-6705eded52cf_medium

 

二:充电时开启飞行模式,会快1倍。

6ac3421c-2601-48b4-9e0e-55492227c13b_medium

三:时钟里的计时器可以定时关闭音乐

9e52ab7a-153f-46f0-a122-ee6d600b8e07_medium

 

四:按25%、50%、75%拖动进度条

abb721b3-a555-40fb-a7bf-d259e3017bbe_medium

按住进度圆点然后把手指移动到进度条下边一些,再左右移动时就可以了。

 

五:按住音量键可以照相

f5de2f99-11d0-4f9a-920f-20e5e69603be_medium

不方便触屏时很好用。

 

六:长按拍照键可以连续拍照

d56c31c7-d810-4e3a-a553-ab2132c96c66_medium

七:拖拽短信内容可以查看详细时间

cbcc8c25-250e-4388-8d0e-decb8b80f2a5_medium

八:双击空格可以输入句号

3b08ea8f-6f62-4058-9109-d7c21e029bc2_medium

九:长按英文句号会出现常用网址后缀

511cacfa-4e5b-44bd-9d17-1f16a3e8b052_medium

 

选译自 http://aplus.com/a/iphone-tricks-you-didnt-know

Oracle索引

$
0
0

在关系数据库中,索引是一种与表有关的数据库结构,它可以使对应于表的SQL语句执行得更快。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。

对于数据库来说,索引是一个必选项,但对于现在的各种大型数据库来说,索引可以大大提高数据库的性能,以至于它变成了数据库不可缺少的一部分。

 

索引分类:

逻辑分类

singlecolumnorconcatenated  对一列或多列建所引

uniqueornonunique   唯一的和非唯一的所引,也就是对某一列或几列的键值(key)是否是唯一的。

Function-based  基于某些函数索引,当执行某些函数时需要对其进行计算,可以将某些函数的计算结果事先保存并加以索引,提高效率。

Doman  索引数据库以外的数据,使用相对较少

 

物理分类

B-Tree:normalorreversekeyB-Tree索引也是我们传统上常见所理解的索引,它又可以分为正常所引和倒序索引。

Bitmap:位图所引,后面会细讲

B-Tree 索引

 

B-Treeindex也是我们传统上常见所理解的索引。B-tree(balancetree)即平衡树,左右两个分支相对平衡。

B-Treeindex

 

Root为根节点,branch为分支节点,leaf到最下面一层称为叶子节点。每个节点表示一层,当查找某一数据时先读根节点,再读支节点,最后找到叶子节点。叶子节点会存放indexentry(索引入口),每个索引入口对应一条记录。

Indexentry的组成部分:

Indexentryentryheader  存放一些控制信息。

Keycolumnlength  某一key的长度

Keycolumnvalue  某一个key的值

ROWID  指针,具体指向于某一个数据

创建索引:

 

用户登录:
SQL> conn as1/as1
Connected.

创建表:
SQL> create table dex (id int,sex char(1),name char(10));
Table created.

向表中插入1000条数据
SQL> begin
 for i in 1..1000
 loop
 insert into dex values(i,'M','chongshi');
 end loop;
 commit;
 end;
 /

PL/SQL procedure successfully completed.

查看表记录
SQL> select * from dex;
        ID SE NAME
---------- -- --------------------
       ... . .....
M  chongshi
M  chongshi
M  chongshi
M  chongshi
M  chongshi
M  chongshi
M  chongshi
M  chongshi
M  chongshi
M  chongshi
rows selected.

创建索引:
SQL> create index dex_idx1 on dex(id);
Index created.
注:对表的第一列(id)创建索引。

查看创建的表与索引
SQL> select object_name,object_type from user_objects;

OBJECT_NAME                  OBJECT_TYPE
--------------------------------------------------------------------------------
DEX                           TABLE
DEX_IDX1                      INDEX

索引分离于表,作为一个单独的个体存在,除了可以根据单个字段创建索引,也可以根据多列创建索引。Oracle要求创建索引最多不可超过32列。

 

 

SQL> create index dex_index2 on dex(sex,name);
Index created.

SQL>  select object_name,object_type from user_objects;

OBJECT_NAME                           OBJECT_TYPE
--------------------------------------------------------------------------------
DEX                                       TABLE
DEX_IDX1                                 INDEX
DEX_INDEX2                               INDEX

 

这里需要理解:

  编写一本书,只有章节页面定好之后再设置目录;数据库索引也是一样,只有先插入好数据,再建立索引。那么我们后续对数据库的内容进行插入、删除,索引也需要随之变化。但索引的修改是由oracle自动完成的。

上面这张图能更加清晰的描述索引的结构。

跟节点记录0至50条数据的位置,分支节点进行拆分记录0至10.......42至50,叶子节点记录每第数据的长度和值,并由指针指向具体的数据。

最后一层的叶子节是双向链接,它们是被有序的链接起来,这样才能快速锁定一个数据范围。

如:

SQL> select * from dex where id>23 and id<32;

        ID SE NAME
---------- -- --------------------
M  chongshi
M  chongshi
M  chongshi
M  chongshi
M  chongshi
M  chongshi
M  chongshi
M  chongshi
rows selected.


如上面查找的列子,通过索引的方式先找到第23条数据,再找到第32条数据,这样就能快速的锁定一个查找的范围,如果每条数据都要从根节点开始查找的话,那么效率就会非常低下。

 

位图索引

 

  位图索引主要针对大量相同值的列而创建。拿全国居民登录一第表来说,假设有四个字段:姓名、性别、年龄、和身份证号,年龄和性别两个字段会产生许多相同的值,性别只有男女两种值,年龄,1到120(假设最大年龄120岁)个值。那么不管一张表有几亿条记录,但根据性别字段来区分的话,只有两种取值(男、女)。那么位图索引就是根据字段的这个特性所建立的一种索引。

BitmapIndex

  从上图,我们可以看出,一个叶子节点(用不同颜色标识)代表一个key,startrowid和endrowid规定这种类型的检索范围,一个叶子节点标记一个唯一的bitmap值。因为一个数值类型对应一个节点,当时行查询时,位图索引通过不同位图取值直接的位运算(与或),来获取到结果集合向量(计算出的结果)。

 

举例讲解:

假设存在数据表T,有两个数据列A和B,取值如下,我们看到A和B列中存在相同的数据。

对两个数据列A、B分别建立位图索引:idx_t_bita和idx_t_bitb。两个索引对应的存储逻辑结构如下:

Idx_t_bita索引结构,对应的是叶子节点:

Idx_t_bitb索引结构,对应的是叶子节点:

 

对查询“select*fromtwhereb=1and(a=’L’ora=’M’)”

分析:位图索引使用方面,和B*索引有很大的不同。B*索引的使用,通常是从根节点开始,经过不断的分支节点比较到最近的符合条件叶子节点。通过叶子节点上的不断Scan操作,“扫描”出结果集合rowid。

而位图索引的工作方式截然不同。通过不同位图取值直接的位运算(与或),来获取到结果集合向量(计算出的结果)。

针对实例SQL,可以拆分成如下的操作:

1、a=’L’ora=’M’

a=L:向量:1010

a=M:向量:0001

or操作的结果,就是两个向量的或操作:结果为1011。

 

2、结合b=1的向量

中间结果向量:1011

B=1:向量:1001

and操作的结果,1001。翻译过来就是第一和第四行是查询结果。

 

3、获取到结果rowid

目前知道了起始rowid和终止rowid,以及第一行和第四行为操作结果。可以通过试算的方法获取到结果集合rowid。

 

位图索引的特点

1.Bitmap索引的存储空间节省

2.Bitmap索引创建的速度快

3.Bitmap索引允许键值为空

4.Bitmap索引对表记录的高效访问

 

创建位图索引:

查看表记录
SQL> select * from dex;
...................
        ID SEX NAME
---------- -- --------------------
M  chongshi
M  chongshi
G  chongshi
G  chongshi
G  chongshi
M  chongshi
G  chongshi
G  chongshi
G  chongshi
M  chongshi
rows selected.

对于上面表来说sex(性别)只有两种值,最适合用来创建位图所引
创建索引:
SQL> create bitmap index my_bit_idx on dex(sex);

Index created.

查看创建的所引
SQL>  select object_name,object_type from user_objects;

OBJECT_NAME                           OBJECT_TYPE
--------------------------------------------------------------------------------
MY_BIT_IDX                               INDEX

 

创建索引的一些规则

 

1、权衡索引个数与DML之间关系,DML也就是插入、删除数据操作。

这里需要权衡一个问题,建立索引的目的是为了提高查询效率的,但建立的索引过多,会影响插入、删除数据的速度,因为我们修改的表数据,索引也要跟着修改。这里需要权衡我们的操作是查询多还是修改多。

2、把索引与对应的表放在不同的表空间。

当读取一个表时表与索引是同时进行的。如果表与索引和在一个表空间里就会产生资源竞争,放在两个表这空就可并行执行。

3、最好使用一样大小是块。

Oracle默认五块,读一次I/O,如果你定义6个块或10个块都需要读取两次I/O。最好是5的整数倍更能提高效率。

4、如果一个表很大,建立索引的时间很长,因为建立索引也会产生大量的redo信息,所以在创建索引时可以设置不产生或少产生redo信息。只要表数据存在,索引失败了大不了再建,所以可以不需要产生redo信息。

 

5、建索引的时候应该根据具体的业务SQL来创建,特别是where条件,还有where条件的顺序,尽量将过滤大范围的放在后面,因为SQL执行是从后往前的。

索引常见操作

 

改变索引

SQL> alter index employees_last _name_idx storage(next 400K maxextents 100);

索引创建后,感觉不合理,也可以对其参数进行修改。详情查看相关文档

调整索引的空间:

 

新增加空间
SQL> alter index orders_region_id_idx allocate extent (size 200K datafile '/disk6/index01.dbf');

释放空间
SQL> alter index oraers_id_idx deallocate unused;

 

索引在使用的过程中可能会出现空间不足或空间浪费的情况,这个时候需要新增或释放空间。上面两条命令完成新增与释放操作。关于空间的新增oracle可以自动帮助,如果了解数据库的情况下手动增加可以提高性能。

重新创建索引:

所引是由oracle自动完成,当我们对数据库频繁的操作时,索引也会跟着进行修改,当我们在数据库中删除一条记录时,对应的索引中并没有把相应的索引只是做一个删除标记,但它依然占据着空间。除非一个块中所有的标记全被删除的时,整个块的空间才会被释放。这样时间久了,索引的性能就会下降。这个时候可以重新建立一个干净的索引来提高效率。

SQL> alter index orders_region_id_idx rebuild tablespace index02;

 

通过上面的命令就可以重现建立一个索引,oracle重建立索引的过程:

1、锁表,锁表之后其他人就不能对表做任何操作。

2、创建新的(干净的)临时索引。

3、把老的索引删除掉

4、把新的索引重新命名为老索引的名字

5、对表进行解锁。

 

移动所引

其实,我们移动索引到其它表空间也同样使用上面的命令,在指定表空间时指定不同的表空间。新的索引创建在别位置,把老的干掉,就相当于移动了。

SQL> alter index orders_region_id_idx rebuild tablespace index03;

 

在线重新创建索引

上面介绍,在创建索引的时候,表是被锁定,不能被使用。对于一个大表,重新创建索引所需要的时间较长,为了满足用户对表操作的需求,就产生的这种在线重新创建索引。

SQL> alter index orders_id_idx  rebuild  online;

 

创建过程:

1、锁住表

2、创建立临时的和空的索引和IOT表用来存在on-goingDML。普通表存放的键值,IOT所引表直接存放的表中数据;on-gongDML也就是用户所做的一些增删改的操作。

3、对表进行解锁

4、从老的索引创建一个新的索引。

5、IOT表里存放的是on-goingDML信息,IOT表的内容与新创建的索引合并。

6、锁住表

7、再次将IOT表的内容更新到新索引中,把老的索引干掉。

8、把新的索引重新命名为老索引的名字

9、对表进行解锁

 

整合索引碎片

如上图,在很多索引中有剩余的空间,可以通过一个命令把剩余空间整合到一起。  

SQL> alter index orders_id_idx  coalesce;

 

删除索引

SQL> drop  index  hr.departments_name_idx;

分析索引

  

  检查所引的有效果,前面介绍,索引用的时间久了会产生大量的碎片、垃圾信息与浪费的剩余空间了。可以通过重新创建索引来提高所引的性能。

可以通过一条命令来完成分析索引,分析的结果会存放在在index_stats表中。

复制代码
查看存放分析数据的表:
SQL> select count(*) from index_stats;

  COUNT(*)
----------
             0
执行分析索引命令:
SQL> analyze index my_bit_idx validate structure;

Index analyzed.

再次查看 index_stats 已经有了一条数据
SQL> select count(*) from index_stats;

  COUNT(*)
----------
             1

把数据查询出来:
SQL> select height,name,lf_rows,lf_blks,del_lf_rows from index_stats;

    HEIGHT   NAME              LF_ROWS   LF_BLKS   DEL_LF_ROWS
---------- ---------------------------------------------------------------------- ---------- -----------
             2   MY_BIT_IDX                10003100
复制代码

分析数据分析

(HEIGHT)这个所引高度是2,(NAME)索引名为MY_BIT_IDX,(LF_ROWS)所引表有1000行数据,(LF_BLKS)占用3个块,(DEL_LF_ROWS)删除100条记录。

  这里也验证了前面所说的一个问题,删除的100条数据只是标记为删除,因为总的数据条数依然为1000条,占用3个块,那么每个块大于333条记录,只有删除的数据大于333条记录,这时一个块被清空,总的数据条数才会减少。





已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



研究发现有机食品富含抗氧化剂

$
0
0
一项对343项有机食品和非有机食品构成差异的论文的元分析研究发现,有机食品的一些重要抗氧化剂含量比非有机食品高出最多69%。研究发现,吃有机水果、蔬菜和食物将能提供额外的抗氧化剂。此外,有机作物的重金属镉含量比传统作物低50%。选择食用有机食品将能增加摄入抗氧化剂和减少暴露在有毒重金属下。传统作物相比有机作物还有一大劣势是农药残留更高。一些专家对研究结论表示怀疑,认为有机食品的抗氧化剂含量时高时低。






jrebel运用

$
0
0

            什么是JRebel?

             JRebel安装一个javaagent监控系统中的classes和resources文件在工作空间的变化,然后在运行的应用服务器上热加载这些变化,支持下面的这些类型的文件改变:
  • 改变Java classes文件.
  • 改变框架配置文件 (e.g. Spring XML files and annotations, Struts mappings, etc).
  • 任何静态资源文件 (e.g. JSPs, HTMLs, CSSs, XMLs, .properties, etc)

          JRebel 是

  • 一个节约开发时间的工具,能够热加载改变的代码,不需要重新启动容器或重新发布应用程序.
  • 一个JVM -javaagent 插件.-javaagent 是java5后的一个命令行属性,JRebel使用插件方式安装. 

          JRebel 不是

  • 一个IDE插件.提供IDE插件是为了改善用户体验,JRebel在普通的java编译器和文本编辑器是一样可以使用的.
  • 一个框架. JRebel不会在你的应用中引入任何依赖包. 你可以随时随地移除,不会影响你的开发.
  • 一个应用服务器. JRebel可以工作在所有优秀的应用服务器上.
  • 一个自定义的JVM. JRebel不需要改变JVM,它可以工作在所有基于JVM实现的优秀虚拟机.
            简单地说,它是JVM的一个插件 , 作为java class 加载代理, 监控文件系统中.class文件的变动, 帮助实现类的热加载.  在开发过程中, 可以省下可观的 Tomcat重启的时间. 按年统计大约节省3到7周的时间 (官方数据) . 有了它,你就可以像写PHP代码一样,边修改边测试。          


已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Oracle执行计划详解

$
0
0
简介:
    本文全面详细介绍oracle执行计划的相关的概念,访问数据的存取方法,表之间的连接等内容。
    并有总结和概述,便于理解与记忆!
目录
---
    一.相关的概念
    Rowid的概念
    Recursive Sql概念
    Predicate(谓词)
    DRiving Table(驱动表)
    Probed Table(被探查表)
    组合索引(concatenated index)
    可选择性(selectivity)
 
    二.oracle访问数据的存取方法
    1) 全表扫描(Full Table Scans, FTS)
    2) 通过ROWID的表存取(Table Access by ROWID或rowid lookup)
    3)索引扫描(Index Scan或index lookup)有4种类型的索引扫描:
     (1) 索引唯一扫描(index unique scan)
     (2) 索引范围扫描(index range scan)
           在非唯一索引上都使用索引范围扫描。使用index rang scan的3种情况:
        (a) 在唯一索引列上使用了range操作符(> < <> >= <= between)
        (b) 在组合索引上,只使用部分列进行查询,导致查询出多行
        (c) 对非唯一索引列上进行的任何查询。  
     (3) 索引全扫描(index full scan)
     (4) 索引快速扫描(index fast full scan)
 
    三、表之间的连接
 
    1,排序 - - 合并连接(Sort Merge Join, SMJ)
    2,嵌套循环(Nested Loops, NL)
    3,哈希连接(Hash Join, HJ)
    另外,笛卡儿乘积(Cartesian Product)
 
    总结Oracle连接方法
    
    Oracle执行计划总结概述
一.相关的概念
 
   Rowid的概念:rowid是一个伪列,既然是伪列,那么这个列就不是用户定义,而是系统自己给加上的。 对每个表都有一个rowid的伪列,但是表中并不物理存储ROWID列的值。不过你可以像使用其它列那样使用它,但是不能删除改列,也不能对该列的值进行 修改、插入。一旦一行数据插入数据库,则rowid在该行的生命周期内是唯一的,即即使该行产生行迁移,行的rowid也不会改变。
   Recursive SQL概念:有时为了执行用户发出的一个sql语句,Oracle必须执行一些额外的语句,我们将这些额外的语句称之为''recursive calls''或''recursive SQL statements''.如当一个DDL语句发出后,ORACLE总是隐含的发出一些recursive SQL语句,来修改数据字典信息,以便用户可以成功的执行该DDL语句。当需要的数据字典信息没有在共享内存中时,经常会发生Recursive calls,这些Recursive calls会将数据字典信息从硬盘读入内存中。用户不比关心这些recursive SQL语句的执行情况,在需要的时候,ORACLE会自动的在内部执行这些语句。当然DML语句与SELECT都可能引起recursive SQL.简单的说,我们可以将触发器视为recursive SQL.
   Row Source(行源):用在查询中,由上一操作返回的符合条件的行的集合,即可以是表的全部行数据的集合;也可以是表的部分行数据的集合;也可以为对上2个row source进行连接操作(如join连接)后得到的行数据集合。
   Predicate(谓词):一个查询中的WHERE限制条件
   Driving Table(驱动表):该表又称为外层表(OUTER TABLE)。这个概念用于嵌套与HASH连接中。如果该row source返回较多的行数据,则对所有的后续操作有负面影响。注意此处虽然翻译为驱动表,但实际上翻译为驱动行源(driving row source)更为确切。一般说来,是应用查询的限制条件后,返回较少行源的表作为驱动表,所以如果一个大表在WHERE条件有有限制条件(如等值限 制),则该大表作为驱动表也是合适的,所以并不是只有较小的表可以作为驱动表,正确说法应该为应用查询的限制条件后,返回较少行源的表作为驱动表。在执行 计划中,应该为靠上的那个row source,后面会给出具体说明。在我们后面的描述中,一般将该表称为连接操作的row source 1.
   Probed Table(被探查表):该表又称为内层表(INNER TABLE)。在我们从驱动表中得到具体一行的数据后,在该表中寻找符合连接条件的行。所以该表应当为大表(实际上应该为返回较大row source的表)且相应的列上应该有索引。在我们后面的描述中,一般将该表称为连接操作的row source 2.
   组合索引(concatenated index):由多个列构成的索引,如create index idx_emp on emp(col1, col2, col3, ……),则我们称idx_emp索引为组合索引。在组合索引中有一个重要的概念:引导列(leading column),在上面的例子中,col1列为引导列。当我们进行查询时可以使用“where col1 = ? ”,也可以使用“where col1 = ? and col2 = ?”,这样的限制条件都会使用索引,但是“where col2 = ? ”查询就不会使用该索引。所以限制条件中包含先导列时,该限制条件才会使用该组合索引。
   可选择性(selectivity):比较一下列中唯一键的数量和表中的行数,就可以判断该列的可选择性。 如果该列的“唯一键的数量/表中的行数”的比值越接近1,则该列的可选择性越高,该列就越适合创建索引,同样索引的可选择性也越高。在可选择性高的列上进 行查询时,返回的数据就较少,比较适合使用索引查询。
二.oracle访问数据的存取方法
 
   1) 全表扫描(Full Table Scans, FTS)
  为实现全表扫描,Oracle读取表中所有的行,并检查每一行是否满足语句的WHERE限制条件一个多块读操作可以使一次I/O能读取多块数据块(db_block_multiblock_read_count参数设定),而不是只读取一个数据块,这极大的减 少了I/O总次数,提高了系统的吞吐量,所以利用多块读的方法可以十分高效地实现全表扫描,而且只有在全表扫描的情况下才能使用多块读操作。在这种访问模 式下,每个数据块只被读一次。
  使用FTS的前提条件:在较大的表上不建议使用全表扫描,除非取出数据的比较多,超过总量的5% —— 10%,或你想使用并行查询功能时。
  使用全表扫描的例子: 
  SQL> explain plan for select * from dual;
  Query Plan
  -----------------------------------------
  SELECT STATEMENT[CHOOSE] Cost=
  TABLE ACCESS FULL DUAL

   2) 通过ROWID的表存取(Table Access by ROWID或rowid lookup)
  行的ROWID指出了该行所在的数据文件、数据块以及行在该块中的位置,所以通过ROWID来存取数据可以快速定位到目标数据上,是Oracle存取单行数据的最快方法。
  这种存取方法不会用到多块读操作,一次I/O只能读取一个数据块。我们会经常在执行计划中看到该存取方法,如通过索引查询数据。
  使用ROWID存取的方法: 
  SQL> explain plan for select * from dept where rowid = ''AAAAyGAADAAAAATAAF'';
 
  Query Plan
  ------------------------------------
  SELECT STATEMENT [CHOOSE] Cost=1
  TABLE ACCESS BY ROWID DEPT [ANALYZED]

   3)索引扫描(Index Scan或index lookup)
  我们先通过index查找到数据对应的rowid值(对于非唯一索引可能返回多个rowid值),然后根据rowid直接从表中得到具体的数据,这 种查找方式称为索引扫描或索引查找(index lookup)。一个rowid唯一的表示一行数据,该行对应的数据块是通过一次i/o得到的,在此情况下该次i/o只会读取一个数据库块。
  在索引中,除了存储每个索引的值外,索引还存储具有此值的行对应的ROWID值。
  索引扫描可以由2步组成:
  (1) 扫描索引得到对应的rowid值。 
  (2) 通过找到的rowid从表中读出具体的数据。
  每步都是单独的一次I/O,但是对于索引,由于经常使用,绝大多数都已经CACHE到内存中,所以第1步的 I/O经常是逻辑I/O,即数据可以从内存中得到。但是对于第2步来说,如果表比较大,则其数据不可能全在内存中,所以其I/O很有可能是物理I/O,这 是一个机械操作,相对逻辑I/O来说,是极其费时间的。所以如果多大表进行索引扫描,取出的数据如果大于总量的5% —— 10%,使用索引扫描会效率下降很多。如下列所示:
  SQL> explain plan for select empno, ename from emp where empno=10;
  Query Plan
  ------------------------------------
  SELECT STATEMENT [CHOOSE] Cost=1
  TABLE ACCESS BY ROWID EMP [ANALYZED]
  INDEX UNIQUE SCAN EMP_I1

  但是如果查询的数据能全在索引中找到,就可以避免进行第2步操作,避免了不必要的I/O,此时即使通过索引扫描取出的数据比较多,效率还是很高的
  SQL> explain plan for select empno from emp where empno=10;-- 只查询empno列值
  Query Plan
  ------------------------------------
  SELECT STATEMENT [CHOOSE] Cost=1
  INDEX UNIQUE SCAN EMP_I1

  进一步讲,如果sql语句中对索引列进行排序,因为索引已经预先排序好了,所以在执行计划中不需要再对索引列进行排序
  SQL> explain plan for select empno, ename from emp
  where empno > 7876 order by empno;
  Query Plan
  --------------------------------------------------------------------------------
  SELECT STATEMENT[CHOOSE] Cost=1
  TABLE ACCESS BY ROWID EMP [ANALYZED]
  INDEX RANGE SCAN EMP_I1 [ANALYZED]

  从这个例子中可以看到:因为索引是已经排序了的,所以将按照索引的顺序查询出符合条件的行,因此避免了进一步排序操作。
  根据索引的类型与where限制条件的不同,有4种类型的索引扫描:
  索引唯一扫描(index unique scan)
  索引范围扫描(index range scan)
  索引全扫描(index full scan)
  索引快速扫描(index fast full scan)

  (1) 索引唯一扫描(index unique scan)
  通过唯一索引查找一个数值经常返回单个ROWID.如果存在UNIQUE 或PRIMARY KEY 约束(它保证了语句只存取单行)的话,Oracle经常实现唯一性扫描。
  使用唯一性约束的例子:
  SQL> explain plan for
  select empno,ename from emp where empno=10;
  Query Plan
  ------------------------------------
  SELECT STATEMENT [CHOOSE] Cost=1
  TABLE ACCESS BY ROWID EMP [ANALYZED]
  INDEX UNIQUE SCAN EMP_I1

  (2) 索引范围扫描(index range scan)
  使用一个索引存取多行数据,在唯一索引上使用索引范围扫描的典型情况下是在谓词(where限制条件)中使用了范围操作符(如>、<、<>、>=、<=、between)
  使用索引范围扫描的例子:
  SQL> explain plan for select empno,ename from emp
  where empno > 7876 order by empno;
  Query Plan
  --------------------------------------------------------------------------------
  SELECT STATEMENT[CHOOSE] Cost=1
  TABLE ACCESS BY ROWID EMP [ANALYZED]
  INDEX RANGE SCAN EMP_I1 [ANALYZED]

  在非唯一索引上,谓词col = 5可能返回多行数据,所以在非唯一索引上都使用索引范围扫描。
  使用index rang scan的3种情况:
  (a) 在唯一索引列上使用了range操作符(> < <> >= <= between)
  (b) 在组合索引上,只使用部分列进行查询,导致查询出多行
  (c) 对非唯一索引列上进行的任何查询。

  (3) 索引全扫描(index full scan)
  与全表扫描对应,也有相应的全索引扫描。而且此时查询出的数据都必须从索引中可以直接得到。
  全索引扫描的例子:
  An Index full scan will not perform single block i/o''s and so it may prove to be inefficient.
  e.g.
  Index BE_IX is a concatenated index on big_emp (empno, ename)
  SQL> explain plan for select empno, ename from big_emp order by empno,ename;
  Query Plan
  --------------------------------------------------------------------------------
  SELECT STATEMENT[CHOOSE] Cost=26
  INDEX FULL SCAN BE_IX [ANALYZED]

  (4) 索引快速扫描(index fast full scan)
  扫描索引中的所有的数据块,与 index full scan很类似,但是一个显著的区别就是它不对查询出的数据进行排序,即数据不是以排序顺序被返回。在这种存取方法中,可以使用多块读功能,也可以使用并行读入,以便获得最大吞吐量与缩短执行时间。
  索引快速扫描的例子:
  BE_IX索引是一个多列索引: big_emp (empno,ename)
  SQL> explain plan for select empno,ename from big_emp;
  Query Plan
  ------------------------------------------
  SELECT STATEMENT[CHOOSE] Cost=1
  INDEX FAST FULL SCAN BE_IX [ANALYZED]

  只选择多列索引的第2列:
  SQL> explain plan for select ename from big_emp;
  Query Plan
  ------------------------------------------
  SELECT STATEMENT[CHOOSE] Cost=1
  INDEX FAST FULL SCAN BE_IX [ANALYZED]
三、表之间的连接
 
  Join是一种试图将两个表结合在一起的谓词,一次只能连接2个表,表连接也可以被称为表关联。在后面的叙 述中,我们将会使用“row source”来代替“表”,因为使用row source更严谨一些,并且将参与连接的2个row source分别称为row source1和row source 2.Join过程的各个步骤经常是串行操作,即使相关的row source可以被并行访问,即可以并行的读取做join连接的两个row source的数据,但是在将表中符合限制条件的数据读入到内存形成row source后,join的其它步骤一般是串行的。有多种方法可以将2个表连接起来,当然每种方法都有自己的优缺点,每种连接类型只有在特定的条件下才会 发挥出其最大优势。
  row source(表)之间的连接顺序对于查询的效率有非常大的影响。通过首先存取特定的表,即将该表作为驱动表,这样可以先应用某些限制条件,从而得到一个 较小的row source,使连接的效率较高,这也就是我们常说的要先执行限制条件的原因。一般是在将表读入内存时,应用where子句中对该表的限制条件。
  根据2个row source的连接条件的中操作符的不同,可以将连接分为等值连接(如WHERE A.COL3 = B.COL4)、非等值连接(WHERE A.COL3 > B.COL4)、外连接(WHERE A.COL3 = B.COL4(+))。上面的各个连接的连接原理都基本一样,所以为了简单期间,下面以等值连接为例进行介绍。
  在后面的介绍中,都以以下Sql为例进行说明:
  SELECT A.COL1, B.COL2
  FROM A, B
  WHERE A.COL3 = B.COL4;
  假设A表为Row Soruce1,则其对应的连接操作关联列为COL 3;
  B表为Row Soruce2,则其对应的连接操作关联列为COL 4;

  连接类型:
  目前为止,无论连接操作符如何,典型的连接类型共有3种:
  排序 - - 合并连接(Sort Merge Join (SMJ) )
  嵌套循环(Nested Loops (NL) )
  哈希连接(Hash Join)
  另外,还有一种Cartesian product(笛卡尔积),一般情况下,尽量避免使用。

   1,排序 - - 合并连接(Sort Merge Join, SMJ)
  内部连接过程
  1) 首先生成row source1需要的数据,然后对这些数据按照连接操作关联列(如A.col3)进行排序。
  2) 随后生成row source2需要的数据,然后对这些数据按照与sort source1对应的连接操作关联列(如B.col4)进行排序。
  3) 最后两边已排序的行被放在一起执行合并操作,即将2个row source按照连接条件连接起来

  下面是连接步骤的图形表示:
  MERGE
  /\
  SORTSORT
  ||
  Row Source 1Row Source 2

  如果row source已经在连接关联列上被排序,则该连接操作就不需要再进行sort操作,这样可以大大提高这种连接操作的连接速度,因为排序是个极其费资源的操 作,特别是对于较大的表。预先排序的row source包括已经被索引的列(如a.col3或b.col4上有索引)或row source已经在前面的步骤中被排序了。尽管合并两个row source的过程是串行的,但是可以并行访问这两个row source(如并行读入数据,并行排序)。
  SMJ连接的例子:
  SQL> explain plan for
  select  /*+ ordered */ e.deptno, d.deptno
  from emp e, dept d
  where e.deptno = d.deptno
  order by e.deptno, d.deptno;
  Query Plan
  -------------------------------------
  SELECT STATEMENT [CHOOSE] Cost=17
  MERGE JOIN
  SORT JOIN
  TABLE ACCESS FULL EMP [ANALYZED]
  SORT JOIN
  TABLE ACCESS FULL DEPT [ANALYZED]

  排序是一个费时、费资源的操作,特别对于大表。基于这个原因,SMJ经常不是一个特别有效的连接方法,但是如果2个row source都已经预先排序,则这种连接方法的效率也是蛮高的。

   2,嵌套循环(Nested Loops, NL)
  这个连接方法有驱动表(外部表)的概念。其实,该连接过程就是一个2层嵌套循环,所以外层循环的次数越少越好,这也就是我们为什么将小表或返回较小 row source的表作为驱动表(用于外层循环)的理论依据。但是这个理论只是一般指导原则,因为遵循这个理论并不能总保证使语句产生的I/O次数最少。有时 不遵守这个理论依据,反而会获得更好的效率。如果使用这种方法,决定使用哪个表作为驱动表很重要。有时如果驱动表选择不正确,将会导致语句的性能很差、很差。
  内部连接过程:
  Row source1的Row 1 —— Probe ->Row source 2
  Row source1的Row 2 —— Probe ->Row source 2
  Row source1的Row 3 —— Probe ->Row source 2
  ……。
  Row source1的Row n —— Probe ->Row source 2

  从内部连接过程来看,需要用row source1中的每一行,去匹配row source2中的所有行,所以此时保持row source1尽可能的小与高效的访问row source2(一般通过索引实现)是影响这个连接效率的关键问题。这只是理论指导原则,目的是使整个连接操作产生最少的物理I/O次数,而且如果遵守这 个原则,一般也会使总的物理I/O数最少。但是如果不遵从这个指导原则,反而能用更少的物理I/O实现连接操作,那尽管违反指导原则吧!因为最少的物理 I/O次数才是我们应该遵从的真正的指导原则,在后面的具体案例分析中就给出这样的例子。
  在上面的连接过程中,我们称Row source1为驱动表或外部表。Row Source2被称为被探查表或内部表。
  在NESTED LOOPS连接中,Oracle读取row source1中的每一行,然后在row sourc2中检查是否有匹配的行,所有被匹配的行都被放到结果集中,然后处理row source1中的下一行。这个过程一直继续,直到row source1中的所有行都被处理。这是从连接操作中可以得到第一个匹配行的最快的方法之一,这种类型的连接可以用在需要快速响应的语句中,以响应速度为 主要目标。
  如果driving row source(外部表)比较小,并且在inner row source(内部表)上有唯一索引,或有高选择性非唯一索引时,使用这种方法可以得到较好的效率。NESTED LOOPS有其它连接方法没有的的一个优点是:可以先返回已经连接的行,而不必等待所有的连接操作处理完才返回数据,这可以实现快速的响应时间。
  如果不使用并行操作,最好的驱动表是那些应用了where 限制条件后,可以返回较少行数据的的表,所以大表也可能称为驱动表,关键看限制条件。对于并行查询,我们经常选择大表作为驱动表,因为大表可以充分利用并 行功能。当然,有时对查询使用并行操作并不一定会比查询不使用并行操作效率高,因为最后可能每个表只有很少的行符合限制条件,而且还要看你的硬件配置是否 可以支持并行(如是否有多个CPU,多个硬盘控制器),所以要具体问题具体对待。
  NL连接的例子:
  SQL> explain plan for
  select a.dname,b.sql
  from dept a,emp b
  where a.deptno = b.deptno;
  Query Plan
  -------------------------
  SELECT STATEMENT [CHOOSE] Cost=5
  NESTED LOOPS
  TABLE ACCESS FULL DEPT [ANALYZED]
  TABLE ACCESS FULL EMP [ANALYZED]

   3,哈希连接(Hash Join, HJ)
  这种连接是在oracle 7.3以后引入的,从理论上来说比NL与SMJ更高效,而且只用在CBO优化器中。
  较小的row source被用来构建hash table与bitmap,第2个row source被用来被hansed,并与第一个row source生成的hash table进行匹配,以便进行进一步的连接。Bitmap被用来作为一种比较快的查找方法,来检查在hash table中是否有匹配的行。特别的,当hash table比较大而不能全部容纳在内存中时,这种查找方法更为有用。这种连接方法也有NL连接中所谓的驱动表的概念,被构建为hash table与bitmap的表为驱动表,当被构建的hash table与bitmap能被容纳在内存中时,这种连接方式的效率极高。

  HASH连接的例子:
  SQL> explain plan for
  select /*+ use_hash(emp) */ empno
  from emp, dept
  where emp.deptno = dept.deptno;
  Query Plan
  ----------------------------
  SELECT STATEMENT[CHOOSE] Cost=3
  HASH JOIN
  TABLE ACCESS FULL DEPT
  TABLE ACCESS FULL EMP

  要使哈希连接有效,需要设置HASH_JOIN_ENABLED=TRUE,缺省情况下该参数为TRUE,另外,不要忘了还要设置 hash_area_size参数,以使哈希连接高效运行,因为哈希连接会在该参数指定大小的内存中运行,过小的参数会使哈希连接的性能比其他连接方式还 要低。
 
   另外,笛卡儿乘积(Cartesian Product)
  当两个row source做连接,但是它们之间没有关联条件时,就会在两个row source中做笛卡儿乘积,这通常由编写代码疏漏造成(即程序员忘了写关联条件)。笛卡尔乘积是一个表的每一行依次与另一个表中的所有行匹配。在特殊情况下我们可以使用笛卡儿乘积,如在星形连接中,除此之外,我们要尽量不使用笛卡儿乘积,否则,自己想结果是什么吧!
  注意在下面的语句中,在2个表之间没有连接。
  SQL> explain plan for
  select emp.deptno,dept,deptno
  from emp,dept
  Query Plan
  ------------------------
  SLECT STATEMENT [CHOOSE] Cost=5
  MERGE JOIN CARTESIAN
  TABLE ACCESS FULL DEPT
  SORT JOIN
  TABLE ACCESS FULL EMP

  CARTESIAN关键字指出了在2个表之间做笛卡尔乘积。假如表emp有n行,dept表有m行,笛卡尔乘积的结果就是得到n * m行结果。

   最后,总结一下,在哪种情况下用哪种连接方法比较好:

   排序 - - 合并连接(Sort Merge Join, SMJ):
  a) 对于非等值连接,这种连接方式的效率是比较高的。
  b) 如果在关联的列上都有索引,效果更好。
  c) 对于将2个较大的row source做连接,该连接方法比NL连接要好一些。
  d) 但是如果sort merge返回的row source过大,则又会导致使用过多的rowid在表中查询数据时,数据库性能下降,因为过多的I/O.

   嵌套循环(Nested Loops, NL):
  a) 如果driving row source(外部表)比较小,并且在inner row source(内部表)上有唯一索引,或有高选择性非唯一索引时,使用这种方法可以得到较好的效率。
  b) NESTED LOOPS有其它连接方法没有的的一个优点是:可以先返回已经连接的行,而不必等待所有的连接操作处理完才返回数据,这可以实现快速的响应时间。

   哈希连接(Hash Join, HJ):
  a) 这种方法是在oracle7后来引入的,使用了比较先进的连接理论,一般来说,其效率应该好于其它2种连接,但是这种连接只能用在CBO优化器中,而且需要设置合适的hash_area_size参数,才能取得较好的性能。
  b) 在2个较大的row source之间连接时会取得相对较好的效率,在一个row source较小时则能取得更好的效率。
  c) 只能用于等值连接中

   Oracle执行计划的概述

   Oracle执行计划的相关概念:

   Rowid:系统给oracle数据的每行附加的一个伪列,包含数据表名称,数据库id,存储数据库id以及一个流水号等信息,rowid在行的生命周期内唯一。
   Recursive sql:为了执行用户语句,系统附加执行的额外操作语句,譬如对数据字典的维护等。
   Row source(行源):oracle执行步骤过程中,由上一个操作返回的符合条件的行的集合。
   Predicate(谓词):where后的限制条件。
   Driving table(驱动表):又称为连接的外层表,主要用于嵌套与hash连接中。一般来说是将应用限制条件后,返回较少行源的表作为驱动表。在后面的描述中,将driving table称为连接操作的row source 1。
   Probed table(被探查表):连接的内层表,在我们从driving table得到具体的一行数据后,在probed table中寻找符合条件的行,所以该表应该为较大的row source,并且对应连接条件的列上应该有索引。在后面的描述中,一般将该表称为连接操作的row source 2.
   Concatenated index(组合索引):一个索引如果由多列构成,那么就称为组合索引,组合索引的第一列为引导列,只有谓词中包含引导列时,索引才可用。
  可选择性:表中某列的不同数值数量/表的总行数如果接近于1,则列的可选择性为高。

   Oracle访问数据的存取方法:
 
   Full table scans, FTS(全表扫描):通过设置db_block_multiblock_read_count可以设置一次IO能读取的数据块个数,从而有效减少全表扫描时的IO总次数,也就是通过预读机制将将要访问的数据块预先读入内存中。只有在全表扫描情况下才能使用多块读操作。
   Table Access by rowed(通过rowid存取表,rowid lookup):由于rowid中记录了行存储的位置,所以这是oracle存取单行数据的最快方法。
   Index scan(索引扫描index lookup):在索引中,除了存储每个索引的值外,索引还存储具有此值的行对应的rowid值,索引扫描分两步1,扫描索引得到rowid;2,通过 rowid读取具体数据。每步都是单独的一次IO,所以如果数据经限制条件过滤后的总量大于原表总行数的5%-10%,则使用索引扫描效率下降很多。而如果结果数据能够全部在索引中找到,则可以避免第二步操作,从而加快检索速度。
  根据索引类型与where限制条件的不同,有4种类型的索引扫描:
  Index unique scan(索引唯一扫描):存在unique或者primary key的情况下,返回单个rowid数据内容。
  Index range scan(索引范围扫描):1,在唯一索引上使用了range操作符(>,<,<>,>=,<=,between);2,在组合索引上,只使用部分列进行查询;3,对非唯一索引上的列进行的查询。
  Index full scan(索引全扫描):需要查询的数据从索引中可以全部得到。
  Index fast full scan(索引快速扫描):与index full scan类似,但是这种方式下不对结果进行排序。

   目前为止,典型的连接类型有3种:
 
   Sort merge join(SMJ排序-合并连接):首先生产driving table需要的数据,然后对这些数据按照连接操作关联列进行排序;然后生产probed table需要的数据,然后对这些数据按照与driving table对应的连接操作列进行排序;最后两边已经排序的行被放在一起执行合并操作。排序是一个费时、费资源的操作,特别对于大表。所以smj通常不是一个特别有效的连接方法,但是如果driving table和probed table都已经预先排序,则这种连接方法的效率也比较高。
   Nested loops(NL嵌套循环):连接过程就是将driving table和probed table进行一次嵌套循环的过程。就是用driving table的每一行去匹配probed table 的所有行。Nested loops可以先返回已经连接的行,而不必等待所有的连接操作处理完成才返回数据,这可以实现快速的响应时间。
   Hash join(哈希连接):较小的row source被用来构建hash table与bitmap,第二个row source用来被hashed,并与第一个row source生产的hash table进行匹配。以便进行进一步的连接。当被构建的hash table与bitmap能被容纳在内存中时,这种连接方式的效率极高。但需要设置合适的hash_area_size参数且只能用于等值连接中。
  另外,还有一种连接类型: Cartesian product(笛卡尔积):表的每一行依次与另外一表的所有行匹配,一般情况下,尽量避免使用。


已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



谈如何提高产品质量

$
0
0

    最近,我们的产品上线了,上线之后,稳定是最重要的,但是,出现了几次bug,都是不应该犯的错误,所以,避免bug特别是重大bug出现,提高产品质量,非常迫切。为此,我花了几天时间,翻一些资料来系统地学习,此文是学习的总结。


    产品开发过程

    产品开发过程:需求分析、设计、编码、单元测试、集成测试、功能测试、Beta测试和发布。在工程师开发之前,策划或产品提过来的需求、策划的配置文件或者后期的测试,都可能影响产品质量,但是,本文侧重于从开发者角度谈提高产品质量。先分享一张来自 《Code Complete》的插图。



    可以看到,随着项目规模变大,架构、设计和集成测试、系统测试需要的时间会更多,而编码和开发者测试的时间更少。因此,提高效率最为明显的方法是提高产品质量, 减少测试、调试和修改所需时间。所以,设计、测试和编码同样重要,要分配更多时间,编码完 != 工作完成。


    测试的重要

    在很多大一些的IT公司,比如微软,开发职位叫Software Development Engineer,SDE,软件开发工程师;测试职位叫Software Development Engineer in Test,SDET,软件测试 开发工程师,可见测试人员本质还是开发工程师。这有别于我们在公司里常常见到的QA,我是做游戏的,我见到的QA都是打开游戏,然后点点点,从表现上测试功能是否正常,这样测试是无法全面测试的,这也难怪在很多公司里QA比开发团队地位低。我觉得,对于测试这个职位,要做好,是很难的。他要能读懂策划文档和开发文档,从源头上开始着手。如果白盒测试,要能看懂别人写的代码;如果黑盒测试,要和开发人员多沟通,画出来实现的流程图,并且分析网络协议;然后,设计完备的测试用例。如果不根据需求、设计和实现,设计完备的测试流程,而只是操作一下试试功能是否正常,很多隐藏的bug是测试不出来的。


    在传统软件行业:软件的质量和稳定最重要,代表企业:IBM、微软、思科等。根据我查到的资料,开发与测试人员比例,微软1:1,思科1:1.5,普遍在1:1 - 3:1。SDET从需求文档、设计文档开始Review,SDE编码,SDET写测试用例,跟极限编程的过程类似。极限编程的基本过程:构思 -> 编写测试代码 -> 编写代码 -> 测试,编写测试和编写代码都是增量式的,写一点测一点,在编写以后的代码中如果发现问题可以较快的追踪到问题的原因,减小回归错误的纠错难度。


    而互联网行业:快很重要,有bug在线上也方便修改发布,更提倡full stack developer,代表企业:amazon、facebook、google等。开发与测试人员比例,google 10:1, MySpace 5:1。阿里资深专家,amazon前高级经理, 陈皓认为:并不是互联网公司认为测试不重要,而是他们认为正因为测试很重要,所以才不应该交给只做测试的人,开发人员要对自己开发的产品质量负责。对于一个公司,“产出性”的人应该多于“支持性”的人。当你的条件受限人手不够的时候,你必然不能干所有的事,但你要去做很多自动化的事情,不管是自动化部署还是自动化运维。然而当你的人多的时候,你必然只会简单用人来解决问题。劳动密集型与知识密集型的公司差别就在这里。


    以微软和google为代表的保证产品质量的做法,都有道理,而且都是成功的。但是,我个人更倾向于full stack developer,第一,招很多SDET对大部分公司都不现实,合格的SDET薪资不会比SDE低;第二,我认为开发人员要对自己的开发的内容负责,主动的想办法提高产品质量,而不是被动的等测试。


    产品质量目标

    评估产品质量,常用的是千行代码缺陷率,以下是查到的一些业界的千行代码缺陷率数据。典型的统计表明,在开发阶段,平均50~60个,交付后15~18个;微软内部测试的产品10-20个,正式发布产品0.5个;某外包公司,A级≤ 0.5个,B级≤1个,C级≤5个;航天飞机的软件,0个/50万行。缺陷率做到平均水平的1/10是很少见的,而如果10倍以上,产品可能永远也不会完工。


    跟性能瓶颈一样,80%的错误往往出现在20%的代码中。大部分错误都是低级错误,比如,对需求或设计的误解、书写错误、赋值语句、边界错误或循环错误。大多数错误是容易改正的。另外,warning是很多错误的根源,所以工程里要禁止warning。


    发现错误

    主要通过检查和测试。检查包括:需求检查、设计检查、代码详查,测试包括:单元测试、集成测试、系统测试等。


    有统计数据表明:单元测试的平均错误检出率是25%,集成测试35%,小规模Beta测试35%,系统测试45%。而对设计和代码进行详查的错误检出率分别是55%和60%。


    检查

    阅读代码要比测试平均每小时多发现80%多的错误,代码检查和测试所获得的收效之比为8:1。这是因为,错误越早发现,解决成本越低。


    检查方法:协同编程,详查需求、设计、代码。不仅仅是检查,要提前思考怎么做?带着思考检查。


    单元测试

    1. 基于结构的测试。测试用例要覆盖每一条控制语句,if for while and or switch case等。


    2. 数据流测试,避免重复初始化、重复销毁、定义不使用、未初始化使用等情况,检测数据流变化。


    3. 错误猜测:

        1). 边界分析,>=与>的区别,null、size是0的情况,比如测试小于MAX,三种边界情况<MAX、MAX本身、>MAX,10000个好友/道具的时候会不会导致游戏卡死?
        2). 复合边界,int add(int a, int b),a和b都小于2^31,但是,如果a和b都很大,它们的和会不会出界?
        3). 坏数据,太小/大的数据,未初始化的数据,错误类型的数据,错误长度的数据等。

        4). 向前兼容和向后兼容。比如,游戏最新版本是2.5,但是有的玩家一直不更新,还是1.0,要兼容这些玩家。


    集成测试

    在单元测试的基础上,将所有模块按照设计要求组装成为子系统或系统,进行集成测试。


    执行方案

    综合考虑我们团队的实际情况,最后我制定了“ 详查+单元测试+集成测试+系统测试”的方案,来提高我们的产品质量。有些方法,比如协同编程、 净室开发,虽然很好,但是对于我们的团队来说,执行起来太难。ps:我对净室开发很感兴趣,正在研究,研究透以后可能会试着采用。


    详查:先自己详查,从需求开始,然后是设计和编码;然后,团队中的小伙伴互查。关于详查,有两点需要注意:1. 检查前,要先制定代码规范,让开发人员不把精力耗在代码规范的争执上。2. 详查结果不作为员工表现的考核标准,考核应该基于最终的产品。


    单元测试:重点是理清流程,针对每个流程都测试到。集成测试:把单元测试的功能组合起来测试,侧重于模块的整体性。系统测试:有点像QA的普遍工作,从功能上测试,各个需求点是否都正常。


    执行:我首先制定了代码规范,并给大家讲解,然后征求大家的意见统一。然后,写了一份本文章的内部版本,并给大家详细讲解(为了让小伙伴们更容易,内部版本细节比较丰富,举了一些例子,写的比较啰嗦,稍微精简、加工之后,形成了这篇blog)。另外,需要注意,详查结果不要作为员工表现的考核标准,考核应该基于最终的产品。


    转载请注明出处:  http://blog.csdn.net/ynnmnm/article/details/37743403。作者:夜风。

作者:ynnmnm 发表于2014-7-13 23:28:25 原文链接
阅读:90 评论:0 查看评论

局域网网络性能测试方法HDtune 64K有缓存测速法,让你得知你的网络性能

$
0
0

该方法可以有效测试出您的网络传输性能到底有多高,该方法通用于有盘, 无盘(系统虚拟盘) ,游戏虚拟盘,以及其他带有缓存功能的虚拟盘软件,但是因为每款软件的工作方式和原理都不仅相同,所以每款软件的测试结果可能不太一样,不过这都没有关系,您可以根据测试得出的速度于实际使用中感受到的速度相关联,自然就知道速度高低与游戏快慢的关系了。

目前在几个网吧测试得出的数据为:
1、CF很流行,如果有缓存测速能达到60~61MB/S即可在23秒左右进入游戏,当然排除外网与机器配置低的情况下。如果测速可达到70MB/S,CF可以在20S以内进入游戏,这个速度和多方因素有关,比如交换机,网卡,网线,甚至水晶头,网卡的设置等等,大家可以分享下自己的经验。
2、同环境下,无盘(系统虚拟盘) 有缓存测速一般会比游戏虚拟盘低4~5MB/S,这是因为无盘(系统虚拟盘) 工作原理有差异导致,并不影响使用,而这4~5MB/S的性能差异并不会导致系统启动速度相差甚远,很可能是无差别的。
3、无论是有盘,无盘(系统虚拟盘) ,游戏虚拟盘,客户机测试能达到30MB/S的速度,无论是游戏和系统都不会出现卡的情况,但是游戏进入速度可能没有太大优势。

HDTune测速方法:
1、选择要测试的磁盘分区。
2、选择随机存取。
3、选择64KB区块测试。
4、单击开始,进行测试。
5、初次测试一般就是硬盘自身的随机读取性能。

6、其他选项不变,多点几次开始按钮,即可得出网络传输性能。

希望深入研究方案的同学可以重点学习
最具有权威性的虚拟盘终极教程连载——十年网吧经验(5月27日连载完成!)
http://bbs.icafe8.com/viewthread.php?tid=58821

如果测速比较慢,可以朝着这么几个方向去排查:
1、服务器的缓存是否太小了,可以适当增大缓存来测试下,如果单纯为了测试下速度,一般有2G缓存已经可以测试出来了;
2、交换机开启了流控功能,可以去检查下交换机是否支持流控,支持的话是否已经关闭了;
3、服务器或客户机上装了限速软件,虽然是个很白痴的问题,但是确实有些同学做过了限制,后来测试时给忘记了,结果导致速度慢;
4、比较管用的一个提速方法,修改网卡参数,方法见如下链接:
http://support.icafe8.com/technologynews/hotfault/ly5360/413.html
 

   硬盘检测工具 HDTunePro.rar (754.7 KB, 8,353 次)

作者:cd520yy 发表于2014-7-13 21:31:15 原文链接
阅读:98 评论:0 查看评论

目标管理体系:OKR

$
0
0

一、什么是OKR体系?

OKR体系的全称是Objectives & Key Results,即目标与关键成果。所谓OKR,O = Objective 可以理解为企业目标,KR =Key Results 可以理解为关键结果。浓缩在一起就是“为确保达成企业目标的关键结果分解与实施”

okr

OKR是企业进行目标管理的一个简单有效的系统,能够将目标管理自上而下贯穿到基层。对一个项目来说,设定目标是非常重要的,因为这决定了如何去做,以及能做到何种程度。

  1. OKR 首先是沟通工具:团队中的每个人都要写 OKR,所有这些OKR都会放在一个文档里。任何员工都可以看到每个人在这个季度最重要的目标是什么,团队这个季度的目标是什么。
  2. OKR是努力的方向和目标:OKR代表你到底要去哪里,而不是你要去的地方具体在哪里。
  3. OKR必须可量化(时间&数量)。比如健身时设定锻炼目标,如果只是定义成「我们要努力提高身体素质」,肯定不是一个好的 OKR,因为无法衡量,好的OKR是「今年的跑步时间较去年增加一倍」。
  4. 目标必须一致:制定者和执行者目标一致、团队和个人的目标一致。首先,制定公司的OKR;其次,每个团队定自己的 OKR;第三,每个工程师或设计师写各自的OKR。这三步各自独立完成,然后对照协调这三者的OKR。OKR跟个人绩效没有关系,因为OKR 系统的结果和每个人并不直接挂钩。
  5. 目标要是有野心的,有一些挑战的,有些让你不舒服的。一般来说,“最佳”的 OKR 分数在0.6-0.7之间,如果某人只拿到1分,那么他 OKR 订的目标显然是野心不够的。但是低分数的人也不应该受到指责,而是应通过看他工作上的数据,帮助他改进下一季度的 OKR 目标。
  6. 通过月度会议Review ,时时跟进OKR: 在月度会议上需要确定如何去达到目标,是一个帮助达到目标的过程。
  7. 通过季度会议Review ,及时调整OKR:互联网的变化非常快,每季度有一个OKR 的 review,调整的原则是目标(Objectives)不变,只允许调整关键成果(Key Results)。

为了更好的理解如何制定OKR体系,我们看个例子:

目标(Objectives):为OKRs组织测评系统建立一个可实施的模型

关键成果(Key Results):

  • 按时完成介绍OKR的presentation
  • 完成一个三个月的OKRs的案例
  • 让管理部门同意并制定一个3个月的测试机制

二、OKR与KPI的区别

OKR表示Objectives and Key Results,即目标和关键成果,是一套定义和跟踪目标及其完成情况的管理工具和方法。KPI表示Key Performance Indicators,即关键绩效指标,是一种可量化的、被事先认可的、用来反映组织目标实现程度的重要指标体系,也是企业绩效管理过程中一个实用而且有效的工具,更是绩效管理实现过程中的一个重要内容。KPI的本质是一种管理工具,它主要是从结果上来考察绩效,不关注过程,一切用指标来说话。

OKR 主要的目的是为了更有效率的完成目标任务,并且依据项目进展来考核的一种方法。它的主要流程是这样的一个循环。

  1. 明确项目目标。
  2. 对关键性结果进行可量化的定义,并且明确达成目标的/未完成目标的措施。
  3. 共同努力达成目标。
  4. 根据项目进展进行评估。

而对于国内来说,更熟悉的其实是 KPI (Key Performance Indicator),而 KPI 的流程则是这样的。

  1. 进行人事组织。
  2. 确定影响结果的关键性因素,并且确立 KPI 。
  3. 对关键绩效指标进行检测,并且进行实时监督。
  4. 对有错误行为的人进行监督,更甚者开除。

通过两者的对比我们能够看到,OKR 主要强调的是对于项目的推进,而 KPI 主要强调的是对人事的高效组织,前者要求的是如何更有效率的完成一个有野心的项目,而后者则强调的是如何保质保量的完成预定目标。OKR相对于KPI而言,不是一个考核工具,而是一个更具有指导性的工具,说白了,是一个PLAN-DO-REVIEW的cycle。他存在的主要目的不是考核某个团队或者员工,而是时刻提醒每一个人当前的任务是什么。每个人都有自己的OKR,每个团队有团队的OKR,无论级别高低,团队大小,都需要制订和服从OKR。这个OKR在每个季度结束之后要做一个评分。评分高低并不直接决定一个员工的晋升和待遇,而更多的是提醒员工,这个季度工作完成的怎么样,未完成的工作为什么没有完成,下一阶段的工作重心是什么。

KPI 理论上是必须严格按照 SMART 标准制订的,是否达到甚至达到比例多少(小于 100% 还是大于 100%)都是要能测量的。但这就导致一个问题,有些事情值得去做,但在做出来一部分之前无法测量因此无法制订目标,这时候就陷入了先有鸡还是先有蛋的问题了。KPI 还有一个更严重的问题,那就是为了完成可测量的目标,有可能实际执行手段与该目标要达到的愿景正好相反。举个例子来说,我们希望用户更喜欢使用我们的产品,因为喜欢无法测量,所以把 PV 写进了 KPI 里面。但在实际执行过程中,我们可以把用户原本在一个页面上就能完成的事情分到几个页面上来完成,结果 PV 达到了 KPI 指定的目标,但用户其实更讨厌我们的产品了。大家如此应付 KPI 是因为 KPI 跟绩效考核挂钩。如果 KPI 达不到那就会影响奖金,所以就算违背公司利益,违背用户利益,也要把自己的 KPI 完成了,把部门的 KPI 完成了。

KPI存在的缺陷:

  1. 没有人对最终结果负责,每个人只对自己的过程负责。
  2. 人的主观能动性被压抑。
  3. 结果高度依赖机器和管理者的指令。

OKR 解决了 KPI 的这些缺陷。首先它和绩效考核分离,把绩效考核交给 peer review(相当于中国公司的 360 度评价)来做。然后它强调 Key Result 必须服从 Objective,所以如果你在 Objective 上写了要让用户喜欢我们的产品,但你实际执行 Key Result 的手段违反了这一点的话,谁都能看得出来。既然 Key Result 只是用来服务于 Objective 的,那就没必要像 KPI 那样一早制订好然后强制执行了。你可以在做的过程中随意更改 Key Result,只要它们还是服务于原本的 Objective 就行。

OKR 最重要的作用就是帮助你「stay focus」,「stay focus」又能帮助你「make impact」。总的来说,绩效考核的核心都是 impact(Google的impact文化。衡量的是员工为Google做出了多大的impact,而不是员工是不是很努力地干了很多活,也不是员工是不是听老板的话完成了老板布置的任务。 ,而测量的手段都是 peer review。其实在没有 OKR 的情况下,这套绩效考核机制还是完全能操作的,但参与者就可以因为缺乏引导而没办法实现他们能实现的最大 impact。OKR 就是让你在每个季度开始之前想一想,有哪些事情从 impact 的角度来说是值得做的,有哪些事情是你想做的,然后取个交集,再列举若干有一定概率(通常建议是 2/3)能达成目标的手段。除了 make impact,OKR 还能用来引导你 stay focus 在别的事情上。

如果要说 OKR 和 KPI 的区别,区别就在于 KPI 只能让驴使劲走,而 OKR 用于保证驴头朝正确的方向。有些驴拼命想往前走,不希望落后于别人,这时候 OKR 用于帮助驴少走曲线。有些驴本来就不想走,这时候就需要 KPI 充当鞭子了。一家公司能不能用 OKR,首先要看有没有正确的驴。

ORK-KPI

OKR考核:“我要做的事”,KPI考核:“要我做的事”,理解不同,但二者都强调有目标,同时也需要有执行力。OKR的思路是先制定目标,然后明确目标的结果,再对结果进行量化,最后考核完成情况。KPI 的思路也是先确定组织目标,然后对组织目标进行分解直到个人目标,然后对个人目标进行量化。

kpi-ork

OKR 和 KPI 两者谁都无法真正的替代对方,因此谁取代谁并不重要,找到适合的绩效评估方法,这才是重要的事情。比如说对于销售来讲,它更在意的是如何保持持续稳定的收入,因此就需要的是更硬性的标准来约束销售人员能够完成任务,所以其需要的是 KPI 而不是 OKR 。而对于营销团队来讲,他们最需要的是如何将影响最大化,而过于刻板的 KPI 就限制了营销团队的灵活性,因此其更适合的是 OKR ,而不是 KPI 。

三、如何实施OKR?

okr-flow

基本的要求:

  1. 最多5个O,每个O最多4个KRs。
  2. 百分之六十的O最初来源于底层。下面的人的声音应该被听到,这样大家工作会更有动力。
  3. 所有人都必须协同,不能出现任何命令形式。
  4. 一页写完最好,两页是最大限值了。
  5. OKRs并不是绩效评估的工具。对个人来说,它起到很好的回顾作用。能快速明了地让自己看到我做了什么,成绩是怎么样。
  6. 分数0.6-0.7是不错的表现,因此0.6-0.7将是你的目标。如果分数低于0.4,你就该思考,那个项目究竟是不是应该继续进行下去。要注意,0.4以下并不意味着失败,而是明确什么东西不重要及发现问题的方式。分数永远不是最重要的,除了是作为一个直接的引导作用。OKR不是绩效考核的武器!每个季度末对关键结果进行考核,完成60-70%就算好,如果100%完成,说明你的目标设定过于简单。
  7. 只有在KRs仍然很重要的情况下,才持续为它而努力。
  8. 有个联合会组织来保证每个人都向同样的目标行进。(事实上OKRs实施过程中,你能够获得大家的认可和帮助,这是很有趣的事情)

基本的流程:

1、设定目标。(从战略开始确定年度目标,季度目标)

目标务必是具体的、可衡量的,例如不能说笼统地说“我想让我的网站更好”,而是要提出诸如“让网站速度加快30%”或者“融入度提升15%”之类的具体目标;不能说“使gmail达到成功”而是“在9月上线gmail并在11月有100万用户”。

目标要是有野心的,有一些挑战的,有些让你不舒服的。一般来说,1为总分的评分,达到0.6-0.7是较好的了,这样你才会不断为你的目标而奋斗,而不会出现期限不到就完成目标的情况。员工通常每季度会制定4到6个目标,目标太多也会令人焦头烂额。

目标必须达成共识,目标必须是在管理者与员工直接充分沟通后的共识。没有达成共识的目标不能算作目标,目标的设定以达成共识为终点。

实施的关键流程:从上至下,目标的设立顺序应该是公司到部门到组到个人。个人自己想做什么,和管理者想他做什么一般来说是不会完全相同的。那他可以通过先查阅上层的目标,在自己想做的事情范围内找到能对公司目标有利的部分,将他拿出来和自己的管理者进行讨论,做权衡取舍。某种情况下,很有可能这个自己想做的东西,会变成公司今后改变的发展方向。

2、明确每个目标的KRs(从季度目标到“关键结果”的分解)

所谓的KR就是为了完成这个目标我们必须做什么? KR是必须具备以下特点的行动:

  • 必须是能直接实现目标的;
  • 必须具有进取心、敢创新的可以不是常规的;
  • 必须是以产出或者结果为基础的、可衡量的,设定评分标准;
  • 不能太多,一般每个目标的KR不超过4个;
  • 必须是和时间相联系的。

目标既要有年度KRs,也有季度KRs:年度KRs统领全年,但并非固定不变,而是可以及时调整,调整要经过批准;季度KRs则是一旦确定就不能改变的。在这里要切记可以调整的是KRs,而不是目标。目标不能调整,措施和方法(KRs)可以不断完善。同样KRs的设定也必须是管理者与员工直接充分沟通后的共识。

3、推进执行(从关键结果到“行动计划“)

当有了关键结果(期望的结果)后,就要围绕这个具体的目标来分解任务了。所以,每项关键结果就会派生出一系列的任务,交给不同的同事负责。关键结果负责人就成了名符其实的项目经理,来组织协调大伙。因此,关键结果的项目经理应当是团队非常重要的成员,他们能够调度和影响企业资源,如果他还不具备这个能力,就把这个权力给他。至少,项目经理和企业决策者之间应当保持绝对通畅的沟通。

3、定期回顾。

每个季度做回顾。到了季度末,员工需要给自己的KRs的完成情况和完成质量打分——这个打分过程只需花费几分钟时间,分数的范围在0到1分之间,而最理想的得分是在0.6到0.7之间。如果达到1分,说明目标定得太低;如果低于0.4分,则说明可能存在问题。

每个员工在每个季度初需要确定自己本季度的 OKR,在一个季度结束后需要根据自己这个季度的工作完成情况给 OKR 打分。每半年公司会进行一次 Performance Review,主要是 review 员工过去半年的绩效,并根据 Performance Review 的结果变更 Job Ladder(业务职级)和薪酬。值得一提的是,所有的个人Performance Review 的成就内容及级别都是全公司共享公开的。这个对于很多公司来说是不可想象的,因为一方面可以做到更为公平和透明,另一方面也给每位同事提供了更好学习和成长自己的样本,激励大家在产品研发中更高质量的挑战和要求自己。

执行的关键:

  1. 每个季度和年度都有OKRs,并保持这样一个节奏的。每个季度都打分。年度的OKRs不是一下就敲定了的。比如你在12月设了下季度和年度的OKRs,往后集中精力在实施季度OKRs上,毕竟这是眼前的目标。而过了一段时间,你可以验证年度OKRs是不是正确的,并不断修订它。年度的OKRs是指导性的,并不是约束。
  2. 可量化的。O和KR的不同:O要是有挑战性的,如果是板上钉钉的事情就是不够的;KRs能很好的支持O的完成,是要明显可量化的,便于评分的
  3. 个人、组、公司层面上均有,个人、组、公司OKRs的不同:个人OKRs是你个人展现你将会做什么;组的OKRs不是个人打包,是组优先做的事情;公司OKRs是高层对整个公司的展望

最后总结下OKR的好处有哪些?

  1. 规范思维,核心目标突出;
  2. 沟通更精准,让每个人都很清楚什么对他们是最重要的;
  3. 建立测量过程的指标,时刻了解我们距离目标还有多远;
  4. 使组织的努力更聚焦。

以上内容整理自网络。其他相关阅读资料: http://en.wikipedia.org/wiki/OKR

tomcat并发优化配置

$
0
0

        在web应用开发中,提升系统性能和并发,除了负载均衡之外,还有就是通过调整参数来优化,以tomcat为例,其他web工具大同小异。

 

          1.让Tomcat6 中支持Java语言的特性 NIO( New I/O)

          NIO俗称“非阻塞通讯”,单从名字上看,就给人一种“快”的感觉。

         使用NIO在服务器端会有更好的性能,加强服务器端对并发处理的性能。  请注意:很抱歉,在tomcat6在默认的配置选项中是没有把NIO功能打开。所以很多正在使用Tomcat6的朋友们本以为能快活的使用上NIO。 

          而NIO则是使用单线程(单个CPU)或者只使用少量的多线程(多CPU)来接受Socket,而由线程池来处理堵塞在pipe或者队列里的请求.这样的话,只要OS可以接受TCP的连接,web服务器就可以处理该请求。大大提高了web服务器的可伸缩性。

          修改配置如下:文件为server.xml

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"  
               connectionTimeout="20000"  
               redirectPort="8443" />

         重启之后,进行测试,被打开nio配置,启动时的信息,如下:    

2014-2-1 13:01:01 org.apache.tomcat.util.net.NioSelectorPool getSharedSelector 
信息: Using a shared selector for servlet write/read 
2014-2-1 13:01:01 org.apache.coyote.http11.Http11NioProtocol init 
信息: Initializing Coyote HTTP/1.1 on http-8080 
这样才能让你真正体验到Tomcat6下NIO给你的系统带来的快感。

         

           2.修改Tomcat 6默认的maxThread 

            打开server.xml可以看到如下配置:             

<Connector port="8080" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               redirectPort="8443" />

   官方文档默认说支持200但似乎超过40就不行了

   修改方法 :     

<Connector port="8080" protocol="HTTP/1.1"   
               connectionTimeout="20000"   
               redirectPort="8443" maxThreads="150"/>

             另外:              

在tomcat配置文件server.xml中的<Connector ... />配置中,和连接数相关的参数有: 
minProcessors:最小空闲连接线程数,用于提高系统处理性能,默认值为10 
maxProcessors:最大连接线程数,即:并发处理的最大请求数,默认值为75 
acceptCount:允许的最大连接数,应大于等于maxProcessors,默认值为100 
enableLookups:是否反查域名,取值为:true或false。为了提高处理能力,应设置为false 
connectionTimeout:网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。
其中和最大连接数相关的参数为maxProcessors和acceptCount。如果要加大并发连接数,应同时加大这两个参数。

    

           

            3.大量的并发也意味着大量的服务器资源,所以修改一下tomcat的JVM参数也是必要的 

              错误提示:java.lang.OutOfMemoryError: Java heap space              

 

---Windows环境下修改“%TOMCAT_HOME%\bin\catalina.bat”文件,在文件开头增加如下设置:set JAVA_OPTS=-Xms256m -Xmx512m 
---Linux环境下修改“%TOMCAT_HOME%\bin\catalina.sh”文件,在文件开头增加如下设置:JAVA_OPTS=’-Xms256m -Xmx512m’

    

JVM设置:堆的尺寸 
-Xmssize in bytes 
    设定Java堆的初始尺寸,缺省尺寸是2097152 (2MB)。这个值必须是1024个字节(1KB)的倍数,且比它大。(-server选项把缺省尺寸增加到32M。) 
-Xmnsize in bytes 
    为Eden对象设定初始Java堆的大小,缺省值为640K。(-server选项把缺省尺寸增加到2M。) 
-Xmxsize in bytes 
    设定Java堆的最大尺寸,缺省值为64M,(-server选项把缺省尺寸增加到128M。) 最大的堆尺寸达到将近2GB(2048MB)。 

请注意:很多垃圾收集器的选项依赖于堆大小的设定。请在微调垃圾收集器使用内存空间的方式之前,确认是否已经正确设定了堆的尺寸。 

垃圾收集:内存的使用 
-XX:MinHeapFreeRatio=percentage as a whole number 
    修改垃圾回收之后堆中可用内存的最小百分比,缺省值是40。如果垃圾回收后至少还有40%的堆内存没有被释放,则系统将增加堆的尺寸。 
-XX:MaxHeapFreeRatio=percentage as a whole number 
    改变垃圾回收之后和堆内存缩小之前可用堆内存的最大百分比,缺省值为70。这意味着如果在垃圾回收之后还有大于70%的堆内存,则系统就会减少堆的尺寸。 
-XX:NewSize=size in bytes 
    为已分配内存的对象中的Eden代设置缺省的内存尺寸。它的缺省值是640K。(-server选项把缺省尺寸增加到2M。) 
-XX:MaxNewSize=size in bytes 
    允许您改变初期对象空间的上限,新建对象所需的内存就是从这个空间中分配来的,这个选项的缺省值是640K。(-server选项把缺省尺寸增加到2M。) 
-XX:NewRatio=value 
    改变新旧空间的尺寸比例,这个比例的缺省值是8,意思是新空间的尺寸是旧空间的1/8。 
-XX:SurvivorRatio=number 
    改变Eden对象空间和残存空间的尺寸比例,这个比例的缺省值是10,意思是Eden对象空间的尺寸比残存空间大survivorRatio+2倍。 
-XX:TargetSurvivorRatio=percentage 
    设定您所期望的空间提取后被使用的残存空间的百分比,缺省值是50。 
-XX:MaxPermSize=size in MB 
    长久代(permanent generation)的尺寸,缺省值为32(32MB)。

   

            web server允许的最大连接数还受制于操作系统的内核参数设置,通常Windows是2000个左右,Linux是1000个左右。Unix中如何设置这些参数,请参阅Unix常用监控和管理命令

               



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



代码是如何控制硬件的?

$
0
0
既然楼主提到“低电平”,看来对数字电路是有一点了解的。

那么,翻开数字电路相关教材,最前面几页。

一般它都会告诉你,三极管/场效应管类似继电器(一种通过线圈产生磁场、然后用磁场控制物理开关的通断与否的设备);在它一个管脚上输入/切断电压信号,另一个管脚就会出现高/低电平。


这东西,就是数字电路的基础。


你敲入的任何东西,最终就是通过类似的东西/机制储存的;所谓“指令”,其实就是“某个命令码“(一般叫机器码),这个”命令码”会改变CPU内部一堆“开关”的状态,以激活不同的电路;然后数据(前面提到过,它也是用三极管/场效应管的导通与否“记忆”的)利用类似的机制,被送入这个被“指令”激活的电路——这些电路是工程师们利用最最基础的三极管控制原理,用一大堆三极管组合出来的:当数据(某种高低电平的组合)经过这些电路后,就会变成另外一组高低电平的组合:这个组合刚好和“指令”代表的功能所应该给出的结果一致。

这段话可能有点难以理解。那么,看下最简单的与门吧:数据有两个,分别通过两条不同的线路进入与门;输出只有一个,必须给它输入两个高电平,它才会输出高电平;否则就输出低电平(这一般简化表述为:只有输入两个1,它才输出1,否则输出0)。

——这就是所谓的“与”逻辑;一组这样的“与”逻辑就与计算机指令/高级语言里的“按位与”直接对应。
——而按位与这个指令,意思就是选择一组线路,把数据导通到这组“与”逻辑电路之上;然后这组与逻辑电路就会输出两组数据的按位与的结果。



——类似的,二进制加法,1+1=0(同时进位);1+0=1;0+1=1;0+0=0:这可以用一个异或电路来模拟(因为异或电路的规则就是1+1=0、1+0=1、0+1=1、0+0=0);但这样(同时进位)这个说明就会丢失了,所以需要同时用一个与门模拟高位进位(前面说过,与门就是只有两个1才会输出1,其它输出0;综合异或的说明:这是不是就和二进制加法的规则刚好一致了呢?)

然后更高一位就成了两根输入线上的数据相加、再加上进位数据……依此类推:这就是用开关做加法的思路。而这样堆起来的一组开关,就叫加法器。

——add指令呢,就是选中上面做的那一堆用来做加法的开关们;然后给它们输入数据(不要忘了,两组高低电平而已),这些数据就驱动着构成加法器的那些开关们,噼里啪啦一阵乱响之后(嗯,如果是老掉牙的继电器计算机的话:还记得BUG的故事吗?),电路就稳定在某个状态了:此时,加法器的输出,恰恰就是输入数据的和(当然是这样了。前面讲过,我们是刻意用异或门和与门精心组合,让它们刚好和加法的效果一致)。



——其它种种指令,莫不大同小异(更复杂/高级的时钟、流水线啥的……暂时就无视吧)


你可以翻翻课本。上面讲过加法器的实现。

而加法器和另外一些逻辑电路加起来,就是所谓的ALU(算术逻辑单元,一下子就高大上了有木有)。


简而言之,代码在计算机内部,本身就是一组特定的高低电平组合;而计算机是精心设计的、海量的、用高低电平控制通断的开关组;当给这个开关组输入不同的电平组合时,就会导致它内部出现复杂的开关动作,最终产生另外一组高低电平的组合作为输出;这些开关动作经过精心设计,使得它的行为是可解释、可预测的——解释/预测的规则,就是CPU的指令集。

——换言之,在机器内部,一切本来就是高低电平,不存在转换问题。
——反而是键盘/鼠标/mic的输入要经过模数转换;而视频、音频之类的输出,要经过数模转换




————————————————————————————————
我知道,很多人困惑的,可能并不是开关的原理;而是:如果CPU不过是一堆开关的话,它为什么能“听懂”类似“加法”“do...while”这类高大上的复杂指令、甚至做出office、photoshop甚至人工智能这样神奇的东西呢?这些高大上的语义,是怎么被电路所理解的呢?



加法之类简单指令,前面已经介绍过了;而提到更复杂的东西……这就不得不说说图灵的贡献了。


还是从最小儿科的题目开始。假设你从来没听说过乘法表;那么,你怎么算8×9呢?

我们知道,A x B就是B个A相加或A个B相加的意思。那么,要算8×9,我们只要把8个9加起来就够了:8次加法而已。


换句话说,这里有个很好的思想,即: 很多“高级”数学计算(如乘法),其实用“低级”方法(如加法)一样是可以算的。


图灵的贡献就是,他证明了,如果一台机器,可以接受一系列的输入、并按输入指示完成运算;那么,当这台机器可支持的操作满足“图灵完备”的要求时,它就可以模拟任何其它数学/逻辑运算!

——比如说,一台只会做加法的机器,只要能想办法它实现“连续做指定次数加法”,那它就可以模拟一台乘法机。而能够模拟任何数学/逻辑运算的机器,并不比加法机复杂太多。

换句话说,要搞出一台“无所不能”的计算机器,并不需要穷尽一切可能,而是只要支持少的令人发指的几条指令,就可以办到了。



比如说,CPU,它根本上其实只会三招:与、或、非。

与就是全为真,则输出真;或是只要一个为真,则输出真;非则是输入真它就输出假、输入假就输出真——所谓的真假,一般写作1、0,在计算机内部就是高低电平。


别看CPU只会这三板斧;可当它们巧妙的组合起来后(构造成计数器、指令寄存器等等等等再组合成CPU),就达到了图灵完备的要求,产生了质变。



具体是怎么做的,这就不是三言两语能说清楚的了。还是仔细看看自己的数字电路这本书吧。

——数字电路研究的,就是如何用与或非这三板斧,来实现各种高级运算甚至CPU指令集这么复杂的事物
——而CPU指令集呢,则形成了另外一个强大得多的图灵机,这就是机器码(和汇编指令几乎一一对应);然后呢,诸如c/c++、java等高级语言,就是利用CPU指令集形成的、另一个更加强大的图灵机(编译器/解释器负责两种图灵机之间的翻译工作)。
——而程序员们研究的,就是如何用编程语言这样一个强大的图灵机,去实现office、photoshop、wow甚至人工智能这样复杂的事物。
——这也是一个层层模拟的过程。




————————————————————————————
总之,开关的通断是基础;而各种神奇的功能是如何用这么简单的东西组合出来的呢,那就必须理解“程序”原理(也就是图灵机原理)了。

如果说,计算机是一个人,那么,软件就是他掌握的知识。这个知识使得他不仅能掰这手指头数数,甚至还可以去洞悉宇宙的奥秘。


————————————————————————————————
具体一些,人是怎样开车的呢?

首先,他要知道车的控制原理(知识/软件);然后,基于这些知识,大脑向他的四肢肌肉发出神经冲动,驱使他完成转方向盘、挂挡、踩离合器/油门等种种动作,最终达到开车这个目的。


软件控制硬件,也是类似的原理。

前面说过,程序本身就是高低电平的组合;它通过在CPU上执行来模拟各种决策过程;同时,计算机就是一堆开关;那么,通过指令向某些地址写出数据(访问特定地址是通过各种寻址机制/指令完成的,归根结底也可以说是通过开关切换,改变了电路拓扑),就等于开启/关闭了对应地址上的某个开关;这个开关可以是类似CPU内部那样的一组三极管,也可以是通向另外一个继电器的信号线——这个信号就促使继电器闭合,于是电机导通……

就好象人开汽车一样,神经发出的微不足道的电脉冲经过肌肉放大,影响了发动机/变速箱的运转,然后汽车就开走了。
计算机也一样:它通过向控制特定地址上的开关输出0/1(高低电平),就可以通过事先准备的物理设施驱动诸如航模电机、舵机等等机构,这就完成了航模控制。


完整的控制回路甚至可以是:
航模上的传感器采集飞行姿态、地形、位置等等数据(最终转换成高低电平构成的信号)----信号通过某些端口送到CPU-----CPU执行程序,程序读取传感器发来的信号,决定下一步的行动-----经过智能判断后,通过控制特定地址上的开关(前面提过,向这个地址发一组高低电平构成的数据就行了),驱动诸如航模电机、舵机等等机构,完成航模控制。

这,就是所谓的“机器人”(当然,只是最简化的机器人原理而已)。

— 完 —
本文作者: 知乎用户(登录查看详情)

【知乎日报】 你都看到这啦,快来点我嘛 Σ(▼□▼メ)

此问题还有 19 个回答,查看全部。
延伸阅读:
小米 2 代的硬件配置真的有 1.5GHZ,四核 CPU 吗?
小米手机二代与一代最大的区别会是硬件方面吗?

Redis性能调优:保存SNAPSHOT对性能的影响

$
0
0

前一段时间,开发环境反馈,Redis服务器访问非常慢,每个请求要数秒时间,重启之后2~3天又会这样。

我查看了一下Linux的性能,没有什么问题。通过

# redis-cli --latency

发现访问Redis确实很慢,执行info要几秒时间。里面有个参数已连接的客户端几万个,通过

Redis>client list

查看到很多client的age都很大,一直没有释放。于是怀疑是不是和这个有关,因为版本是2.8.6,无法通过client一次性kill掉所有的连接,只能写一个程序,一个一个地kill掉(

CLIENT KILL addr:port)。但问题依然存在。

于是进一步查看配置文件,发现SHNAPSHOT是默认打开状态,

 save 900 1

 save 300 10

 save 60 10000

因为我们缓存是用于Session保存,不推荐快照保存,特别是在Redis是VM机器上,对整体的性能影响会很大。于是参考我们的手册注释:

################################ 快照 #################################

# 保存数据到磁盘,格式如下:

#  save <seconds> <changes>

#   指出在多长时间内,有多少次更新操作,就将数据同步到数据文件rdb。

#   相当于条件触发抓取快照,这个可以多个条件配合

#   比如默认配置文件中的设置,就设置了三个条件

#  save 900 1  900秒内至少有1个key被改变

#  save 300 10  300秒内至少有300个key被改变

#  save 60 10000  60秒内至少有10000个key被改变

# Session缓存服务器不使用快照,都注释

# save 900 1

# save 300 10

# save 60 10000

重启Redis之后,观察了一个月时间,再没有反馈到性能问题了。

另外在没有使用客户端的PUB/SUB的情况下,建议参考下面的参数,设置客户端的连接超时,在300毫秒后,如果不用,服务端会自动关闭连接,释放资源。默认是关闭的。

# 设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接

# 0是关闭此设置

# 推荐5分钟。

timeout 300

# TCP keepalive

# 在Linux上,指定值(秒)用于发送ACKs的时间。注意关闭连接需要双倍的时间。默认为0。

# 推荐60。

tcp-keepalive 60

注:

Redis 2.8.12已经可以通过client类型,一次性kill到所有相关的连接。


作者:wilbertzhou 发表于2014-7-15 10:58:16 原文链接
阅读:62 评论:0 查看评论

轻松对比Activiti5与jBPM5技术组成

$
0
0

jBPM是目前市场上主流开源工作引擎之一,在创建者Tom Baeyens离开JBoss后,jBPM的下一个版本jBPM5完全放弃了jBPM4的基础代码,基于Drools Flow重头来过,目前官网已经推出了jBPM6的beta版本;Tom Baeyens加入Alfresco后很快推出了新的基于jBPM4的开源工作流系统Activiti。由此可以推测JBoss内部对jBPM未来版本的架构实现产生了严重的意见分歧。本文试着对二者做一些比较。


主要相似之处:


都是BPMN2过程建模和执行环境。 都是BPM系统(符合BPM规范)。 都是开源项目-遵循ASL协议( Apache的 软件许可)。 都源自JBoss(Activiti5是jBPM4的衍生,jBPM5则基于Drools Flow)。 都很成熟,从无到有,双方开始约始于2年半前。 都有对人工任务的生命周期管理。 Activiti5和jBPM5唯一的区别是jBPM5基于WebService - HumanTask标准来描述人工任务和管理生命周期。 如有兴趣了解这方面的标准及其优点,可参阅WS - HT规范介绍 。 都使用了不同风格的 Oryx 流程编辑器对BPMN2建模。 jBPM5采用的是 Intalio 维护的开源项目分支。 Activiti5则使用了Signavio维护的分支。

Activiti5与jBPM5技术组成对比:

序号    技术组成                                   Activiti                                        jBPM5

1         数据库持久层ORM                    MyBatis3                                    Hibernate3

2         持久化标准                                无                                              JPA规范

3        事务管理                                   MyBatis机制/Spring事务控制       Bitronix,基于JTA事务管理

4        数据库连接方式                        Jdbc/DataSource                         Jdbc/DataSource

5        支持数据库                              Oracle、SQL Server、MySQL      Oracle、SQL Server、MySQL

6        设计模式                                 Command模式、观察者模式等

7        内部服务通讯                         Service间通过API调用                     基于Apache Mina异步通讯
 
8        集成接口                                SOAP、Mule、RESTful                  消息通讯

9        支持的流程格式                      BPMN2、xPDL、jPDL等                 目前仅只支持BPMN2 xml

10       引擎核心                               PVM(流程虚拟机)                        Drools

11       技术前身                               jBPM3、jBPM4                                 Drools Flow

12       所属公司                              Alfresco                                            jBoss.org


Activiti5使用Spring进行引擎配置以及各个Bean的管理,综合使用IoC和AOP技术,使用CXF作为Web Services实现的基础,使用MyBatis进行底层数据库ORM的管理,预先提供Bundle化包能较容易的与OSGi进行集成,通过与Mule ESB的集成和对外部服务(Web Service、RESTful等)的接口可以构建全面的SOA应用;jBPM5使用jBoss.org社区的大多数组件,以Drools Flow为核心组件作为流程引擎的核心构成,以Hibernate作为数据持久化ORM实现,采用基于JPA/JTA的可插拔的持久化和事务控制规范,使用Guvnor作为流程管理仓库,能够与Seam、Spring、OSGi等集成。



需要指出的是Activiti5是在jBPM3、jBPM4的基础上发展而来的,是原jBPM的延续,而jBPM5则与之前的jBPM3、jBPM4没有太大关联,且舍弃了备受推崇的PVM(流程虚拟机)思想,转而选择jBoss自身产品Drools Flow作为流程引擎的核心实现,工作流最为重要的“人机交互”任务(类似于审批活动)则由单独的一块“Human Task Service”附加到Drools Flow上实现,任务的查询、处理等行为通过Apache Mina异步通信机制完成。


优劣对比:



从技术组成来看,Activiti最大的优势是采用了PVM(流程虚拟机),支持除了BPMN2.0规范之外的流程格式,与外部服务有良好的集成能力,延续了jBPM3、jBPM4良好的社区支持,服务接口清晰,链式API更为优雅;劣势是持久化层没有遵循JPA规范。



jBPM最大的优势是采用了Apache Mina异步通信技术,采用JPA/JTA持久化方面的标准,以功能齐全的Guvnor作为流程仓库,有RedHat(jBoss.org被红帽收购)的专业化支持;但其劣势也很明显,对自身技术依赖过紧且目前仅支持BPMN2。


总结:



虽然是比较,但不一定要有胜负,只有适合自己的才是最好的,要针对具体的项目区别对待。对我们自己的项目,其实我更关注的是流程引擎的执行效率以及性能,每小时几十万甚至上百万的流程需要执行,需要多少个服务,集群、负载的策略是什么,会不会有冲突?目前这方面的资料还是比较少的,很多问题只有实际遇用到的时候才会去想办法解决。不过就我个人的感觉而言,Activiti上手比较快,界面也比较简洁、直观,值得一试,不过jBPM6的beta版也已经出来了,不知道会有什么变化,有兴趣的也可以试下。

 



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



中文字体网页开发指南

$
0
0

字体的选择,是网页开发的关键因素之一。

合适的字体,对网页的美观度(或可读性)有着举足轻重的影响。

但是,相比 英文字体,中文字体的网页开发有着极大的局限性。因为,一套中文字体最少也要有几千个字符,体积为几个MB;单单为了浏览网页,开发者不可能让用户去下载字体,只能依靠操作系统的预装字体。(*注:确实有 网站提供中文字体的web服务,从技术角度,我认为这样做不可取。)

不同的操作系统、不同的版本预装不同的字体(因为版权),几乎没有交集。因此,大多数开发者索性忽略中文字体,让操作系统自行渲染,或者用图片呈现字体效果。

下面是目前中文字体的最佳实践,主要参考了 Kendra Schaefer的文章。

一、操作系统的预装字体

操作系统决定了开发者可以使用的字体。所以,第一步,我们必须了解操作系统到底提供哪些字体。

Windows操作系统

  • 黑体:SimHei
  • 宋体:SimSun
  • 新宋体:NSimSun
  • 仿宋:FangSong
  • 楷体:KaiTi
  • 仿宋 GB2312:FangSongGB2312
  • 楷体 GB2312:KaiTiGB2312
  • 微软雅黑:Microsoft YaHei (Windows 7开始提供)

OS X操作系统

  • 冬青黑体: Hiragino Sans GB (SNOW LEOPARD开始提供)
  • 华文细黑:STHeiti Light (又名STXihei)
  • 华文黑体:STHeiti
  • 华文楷体:STKaiti
  • 华文宋体:STSong
  • 华文仿宋:STFangsong

如果用户装了 MicroSoft Office,还会多出一些字体。

  • 隶书:LiSu
  • 幼圆:YouYuan
  • 华文细黑:STXihei
  • 华文楷体:STKaiti
  • 华文宋体:STSong
  • 华文中宋:STZhongsong
  • 华文仿宋:STFangsong
  • 方正舒体:FZShuTi
  • 方正姚体:FZYaoti
  • 华文彩云:STCaiyun
  • 华文琥珀:STHupo
  • 华文隶书:STLiti
  • 华文行楷:STXingkai
  • 华文新魏:STXinwei

二、font-family命令

CSS的font-family命令,指定了网页元素所使用的字体。下面是一个例子。


font-family: Georgia, "Times New Roman", "Microsoft YaHei", "微软雅黑", 
             STXihei, "华文细黑", 
             serif;

它的规则有三条。

(1)优先使用排在前面的字体。

(2)如果找不到该种字体,或者该种字体不包括所要渲染的文字,则使用下一种字体。

(3)如果所列出的字体,都无法满足需要,则让操作系统自行决定使用哪种字体。

根据这些规则,font-family应该优先指定英文字体,然后再指定中文字体。否则,中文字体所包含的英文字母,会取代英文字体,这往往很丑陋。

上面图片中,红框内的英文字母,左边采用英文字体渲染,右边采用中文字体渲染,哪一种效果比较好,一目了然。

为了保证兼容性,中文字体的中文名称和英文名称,应该都写入font-family。比如,"微软雅黑"的英文名称是Microsoft YaHei。

此外,中文字体的中文名称,以及由多个单词组成的英文名称,应该放在双引号内。

三、 Windows平台和Mac平台

由于Windows和Mac的中文字体没有交叉,所以应该同时为两个平台指定字体。

常见的做法是,Windows平台指定"微软雅黑"(Microsoft YaHei),Mac平台指定"华文细黑"(STXihei)。

四、衬线体和无衬线体

所谓"衬线体"(Serif),指的是笔画的末端带有衬线的字体。

就像英文字体一样,中文字体也可以分成"衬线体"和"无衬线体"(San-serif)。比如,对于繁体字来说,微软正黑(Microsoft JhengHei)是无衬线体,新细明体(PMingLiU)是衬线体。

对于简体字来说,微软雅黑(Microsoft yahei)是无衬线体,宋体(SimSun)是衬线体。

一般来说,衬线体装饰性强,往往用于标题;无衬线体清晰度好,往往用于正文。

五、几种常见中文字体

(1)宋体(SimSun)

最常见的中文字体,如果没有指定字体,操作系统往往选择它来渲染。很多人认为,这种字体并不美观。

(2)微软雅黑(Microsoft YaHei)

微软雅黑的美观度和清晰度都较好,可以作为网页的首选字体。它在Mac平台的对应字体是华文细黑(STXihei)。

但是,Windows XP没有预装这种字体,这时操作系统往往会选择黑体(Simhei)取代。

(3)仿宋(FangSong)

这种字体是衬线体,比宋体的装饰性更强。如果字号太小,会影响清晰度,所以只有在字号大于14px的情况下,才可以考虑这种字体。

它在Mac平台的对应字体是"华文仿宋"(STFangsong)。

(4)楷体(KaiTi)

楷体也是衬线体,装饰性与仿宋体接近,但是宽度更大,笔画更清楚一些。这种字体也不应该在小于14px的情况下使用。

它在Mac平台的对应字体是"华文楷体"(STKaiti)。

(完)

文档信息

Java程序员须知的七个日志管理工具

$
0
0
Splunk vs. Sumo Logic vs. LogStash vs. GrayLog vs. Loggly vs. PaperTrails vs. Splunk>StormSplunk vs. Sumo Logic vs. LogStash vs. GrayLog vs. Loggly vs. PaperTrails vs. Splunk>Storm

日志管理工具有Splunk、Sumo Logic、LogStash、GrayLog、Loggly和PaperTrails等等,数不胜数。日志就像石油,二十多年了我们一直想摆脱它,却一直没有做到。

为了处理日益增长的数据,近年来出现了一大批分析和管理日志的工具,开发和管理人员能够借助这些工具来了解增长的数据。在这篇文章中,我将站在开发者的角度,分析一下这些工具的特点。

Splunk

作为这个领域中最大的工具,我决定将 Splunk 做一个单独的分类。并不是说这个工具是最好的,而是对这个产品给予肯定,因为它从本质上创造了一个新的领域。

优点

在这个领域内功能最齐全的可能就是 Splunk 了。它有数百个来分析各种形式日志信息的程序(我计算的是 537个)——从安全领导到商业分析,再到底层监控。Splunk 的搜索和图表工具如此丰富,没有通过它(UI和API)得不到的数据。

缺点

Splunk 主要有两个缺点。第一,这个因素可能有些主观,我觉得这个解决方案太复杂了。如果要在一个高度复杂的环境中部署,就需要安装和配置一个专用集群。作为一个开发者,通常会因为这点而不把这个方案作为第一选择。

第二个缺点是它太昂贵了。要支持一个真实世界的软件,你可能会花费一万多美金,这很可能就意味着你需要从其他地方削减预算,这样开发进程就慢了。如果你刚上架了一款 app,但是要得到高质量的日志分析却又不影响开发进程——请继续阅读。

更多企业级日志分析工具请点击 这里

SaaS日志分析工具

Sumo Logic

Sumo 是在 Splunk 的基础上建立的 SaaS 版本,它沿用了 Splunk 早期的一些特性和视觉效果。不得不说,SL 今天已经发展成了一个成熟的企业级日志管理工具。

优点

SL 具备对数据简化、查找、制表等功能。可能是 SaaS 型的日志分析工具中功能最多的了。同样,作为 SaaS 型,SL 还具有安装简单,操作简单等优点。最吸引人的地方是,你可以建立一个基线,当一个事件(像是一个新版本首次上线或者恶意的请求等)使一些重要的指标发生了变化时,你可以收到动态通知。

缺点

由于这是通过 SaaS 的方式进行日志分析的,所以你必须将大量的数据上传至服务器进行分析,这就可能产生一些问题:

  1. 作为一个开发者,如果要分析的日志涉及到敏感信息或者 PII 你要确保做好了屏蔽。
  2. 在日志生成的时间与日志上传至服务的时间之间可能存在一些冲突。
  3. 在你的机器上回多出来几个 GB 的开销用于上传日志,不过这取决于你日志的吞吐量。

Sumo 服务的购买价格 不是透明的,所以你要是想刷你团队的信用卡来购买的话会很麻烦。

更新——SL 团队刚刚告诉我们,你可以直接用信用卡从免费版本中购买服务,虽然不像网页版那样方便,但是也蛮不错的。

Loggly

Loggly 也是一个健壮的日志分析工具,强调简洁朴素让开发者用起来方便。

优点

SL 注重的是企业级别的应用和安全性,而 Loggly 却将重点放在了帮助开发者查找和修复操作性的问题上。因为操作界面非常友好,自定义性能和开发者仪表盘这种东西非常简单。并且它的价格透明,入门方便。

缺点

不要奢望 Loggly 具备成熟的架构、安全和分析解决方案。Loggly 不具备取证和监控基础架构,它仅仅是帮助开发者处理应用服务器数据的一个工具。除此之外的其他事情就需要你自己去做了。

PaperTrails

PaperTrails 擅长从多台机器上查找日志,并提供一个合并的窗口,使用起来很方便。鉴于你是从云端 追踪日志,所以你离他们不会太远。

优点

PT 就是这么一个工具。通过它你可以从一个窗口轻松的查找多台机器上的日志。用户操作本身就像你机器上的日志,搜索命令也一样。它致力于将日志管理变得简单、易用,可以优雅地处理。而且它还 不算很贵

缺点

PT 是基于文本格式的。如果需要支持先进的集成、预测和报告功能,就显得力不从心了。

Splunk>Storm

这是 Splunk 的兄弟, Splunk 的服务器上提供托管。

优点

Storm 让你无需安装软件,就能体验 Splunk 的完整版的功能。

缺点

Storm 不是商业的,所以你的流量有限。你可以将其视作一个 Splunk 的限制版本,无需部署即可帮助新产品测试。最近有个叫 Splunk Cloud的新服务,致力于提供 Splunk SaaS 的完整体验。

开源的分析软件

Logstash

Logstash 是一款收集和管理日志的开源工具。它用到了一些其他的开源的资源:使用 ElasticSearch 来索引和查找数据,使用 Kibana 制表和可视化处理。他们联合起来,组成一个强大的日志管理解决方案。

优点

作为一个开源的解决方案,Logstash 允许用户有更大的定制空间,而且很便宜。Logstash 用了三个成熟的开源部件——都受到了很好的维护——组成一个强大的 可扩展的软件包。由于开源,安装和使用和非常方便。

缺点

由于 Logstash 从本质上来说是三个部件的堆砌,所以你需要面对三个不同的产品。这就意味着扩展也变得很复杂。Logstash 的过滤器是用 Ruby 写的,Kibana 是用纯 Javascript 写的,而 ElasticSearch 也有自己的 REST 接口和 JSON 模板。

当你转向产品时,还需要将三个不同的工具部署到服务器上,无疑增加了复杂度。

Graylog2

最近出现的一颗新星——GL2,用 MongoDB 和 ElasticSearch 支持的用来存储与搜索日志错误的工具。它致力于帮助开发者找到并修复程序中的错误。

在这一方面,还有 fluentdKafka也是专注于存储日志的。看!我们有这么多选择啊!

Takipi for Logs

虽然这篇文章不是关于 Takipi 的,但是它有一项特性,你也许会发现和日志有关。

对于日志分析工具来说,最大的缺点就是你必须要有日志可以分析。从集成开发环境的角度看,如果没有异常报告,或者没有错误信息的数据,你就没办法知道哪里出问题了,这样世界上任何工具都帮不了你了!Debug 就卡在这里了。:(

在 Takipi 的一项优势就是可以跳过日志文件,进入到调试信息中。这样你就能看到真实的源代码和错误范围的变量了。了解更多点击 这里

Takipi 会报告所有的异常和错误,并且告诉你哪里出错了,即使是多线程或者是发生在多台机器上。1分钟之内就能安装,维护费用不足2%-部署 Taikipi

可能感兴趣的文章


开源日志系统简介——Scribe,flume,kafka,Chukwa

$
0
0

 

 

 1. 背景介绍

许多公司的平台每天会产生大量的日志(一般为流式数据,如,搜索引擎的pv,查询等),处理这些日志需要特定的日志系统,一般而言,这些系统需要具有以下特征:

(1) 构建应用系统和分析系统的桥梁,并将它们之间的关联解耦;

(2) 支持近实时的在线分析系统和类似于Hadoop之类的离线分析系统;

(3) 具有高可扩展性。即:当数据量增加时,可以通过增加节点进行水平扩展。

本文从设计架构,负载均衡,可扩展性和容错性等方面对比了当今开源的日志系统,包括facebook的scribe,apache的chukwa,linkedin的kafka和cloudera的flume等。

 

2. FaceBook的Scribe

Scribe是facebook开源的日志收集系统,在facebook内部已经得到大量的应用。它能够从各种日志源上收集日志,存储到一个中央存储系统 (可以是NFS,分布式文件系统等)上,以便于进行集中统计分析处理。它为日志的“分布式收集,统一处理”提供了一个可扩展的,高容错的方案。

它最重要的特点是容错性好。当后端的存储系统crash时,scribe会将数据写到本地磁盘上,当存储系统恢复正常后,scribe将日志重新加载到存储系统中。

架构

scribe的架构比较简单,主要包括三部分,分别为scribe agent, scribe和存储系统。

(1) scribe agent

scribe agent实际上是一个thrift client。 向scribe发送数据的唯一方法是使用thrift client, scribe内部定义了一个thrift接口,用户使用该接口将数据发送给server。

(2) scribe

scribe接收到thrift client发送过来的数据,根据配置文件,将不同topic的数据发送给不同的对象。scribe提供了各种各样的store,如 file, HDFS等,scribe可将数据加载到这些store中。

(3) 存储系统

存储系统实际上就是scribe中的store,当前scribe支持非常多的store,包括file(文件),buffer(双层存储,一个主储存,一个副存储),network(另一个scribe服务器),bucket(包含多个 store,通过hash的将数据存到不同store中),null(忽略数据),thriftfile(写到一个Thrift TFileTransport文件中)和multi(把数据同时存放到不同store中)。

 

3. Apache的Chukwa

chukwa是一个非常新的开源项目,由于其属于hadoop系列产品,因而使用了很多hadoop的组件(用HDFS存储,用mapreduce处理数据),它提供了很多模块以支持hadoop集群日志分析。

需求:

(1) 灵活的,动态可控的数据源

(2) 高性能,高可扩展的存储系统

(3) 合适的框架,用于对收集到的大规模数据进行分析

架构

Chukwa中主要有3种角色,分别为:adaptor,agent,collector。

(1) Adaptor 数据源

可封装其他数据源,如file,unix命令行工具等

目前可用的数据源有:hadoop logs,应用程序度量数据,系统参数数据(如linux cpu使用流率)。

(2) HDFS 存储系统

Chukwa采用了HDFS作为存储系统。HDFS的设计初衷是支持大文件存储和小并发高速写的应用场景,而日志系统的特点恰好相反,它需支持高并发低速率的写和大量小文件的存储。需要注意的是,直接写到HDFS上的小文件是不可见的,直到关闭文件,另外,HDFS不支持文件重新打开。

(3) Collector和Agent

为了克服(2)中的问题,增加了agent和collector阶段。

Agent的作用:给adaptor提供各种服务,包括:启动和关闭adaptor,将数据通过HTTP传递给Collector;定期记录adaptor状态,以便crash后恢复。

Collector的作用:对多个数据源发过来的数据进行合并,然后加载到HDFS中;隐藏HDFS实现的细节,如,HDFS版本更换后,只需修改collector即可。

(4) Demux和achieving

直接支持利用MapReduce处理数据。它内置了两个mapreduce作业,分别用于获取data和将data转化为结构化的log。存储到data store(可以是数据库或者HDFS等)中。

 

4. LinkedIn的Kafka

Kafka是2010年12月份开源的项目,采用scala语言编写,使用了多种效率优化机制,整体架构比较新颖(push/pull),更适合异构集群。

设计目标:

(1) 数据在磁盘上的存取代价为O(1)

(2) 高吞吐率,在普通的服务器上每秒也能处理几十万条消息

(3) 分布式架构,能够对消息分区

(4) 支持将数据并行的加载到hadoop


架构

Kafka实际上是一个消息发布订阅系统。producer向某个topic发布消息,而consumer订阅某个topic的消息,进而一旦有新的关于某个topic的消息,broker会传递给订阅它的所有consumer。 在kafka中,消息是按topic组织的,而每个topic又会分为多个partition,这样便于管理数据和进行负载均衡。同时,它也使用了zookeeper进行负载均衡。

Kafka中主要有三种角色,分别为producer,broker和consumer。

(1) Producer

Producer的任务是向broker发送数据。Kafka提供了两种producer接口,一种是low_level接口,使用该接口会向特定的broker的某个topic下的某个partition发送数据;另一种那个是high level接口,该接口支持同步/异步发送数据,基于zookeeper的broker自动识别和负载均衡(基于Partitioner)。

其中,基于zookeeper的broker自动识别值得一说。producer可以通过zookeeper获取可用的broker列表,也可以在zookeeper中注册listener,该listener在以下情况下会被唤醒:

a.添加一个broker

b.删除一个broker

c.注册新的topic

d.broker注册已存在的topic

当producer得知以上时间时,可根据需要采取一定的行动。

(2) Broker

Broker采取了多种策略提高数据处理效率,包括sendfile和zero copy等技术。

(3) Consumer

consumer的作用是将日志信息加载到中央存储系统上。kafka提供了两种consumer接口,一种是low level的,它维护到某一个broker的连接,并且这个连接是无状态的,即,每次从broker上pull数据时,都要告诉broker数据的偏移量。另一种是high-level 接口,它隐藏了broker的细节,允许consumer从broker上push数据而不必关心网络拓扑结构。更重要的是,对于大部分日志系统而言,consumer已经获取的数据信息都由broker保存,而在kafka中,由consumer自己维护所取数据信息。

 

5. Cloudera的Flume

Flume是cloudera于2009年7月开源的日志系统。它内置的各种组件非常齐全,用户几乎不必进行任何额外开发即可使用。

设计目标:

(1) 可靠性

当节点出现故障时,日志能够被传送到其他节点上而不会丢失。Flume提供了三种级别的可靠性保障,从强到弱依次分别为:end-to-end(收到数据agent首先将event写到磁盘上,当数据传送成功后,再删除;如果数据发送失败,可以重新发送。),Store on failure(这也是scribe采用的策略,当数据接收方crash时,将数据写到本地,待恢复后,继续发送),Best effort(数据发送到接收方后,不会进行确认)。

(2) 可扩展性

Flume采用了三层架构,分别问agent,collector和storage,每一层均可以水平扩展。其中,所有agent和collector由master统一管理,这使得系统容易监控和维护,且master允许有多个(使用ZooKeeper进行管理和负载均衡),这就避免了单点故障问题。

(3) 可管理性

所有agent和colletor由master统一管理,这使得系统便于维护。用户可以在master上查看各个数据源或者数据流执行情况,且可以对各个数据源配置和动态加载。Flume提供了web 和shell script command两种形式对数据流进行管理。

(4) 功能可扩展性

用户可以根据需要添加自己的agent,colletor或者storage。此外,Flume自带了很多组件,包括各种agent(file, syslog等),collector和storage(file,HDFS等)。

架构

正如前面提到的,Flume采用了分层架构,由三层组成,分别为agent,collector和storage。其中,agent和collector均由两部分组成:source和sink,source是数据来源,sink是数据去向。

(1) agent

agent的作用是将数据源的数据发送给collector,Flume自带了很多直接可用的数据源(source),如:

text(“filename”):将文件filename作为数据源,按行发送

tail(“filename”):探测filename新产生的数据,按行发送出去

fsyslogTcp(5140):监听TCP的5140端口,并且接收到的数据发送出去

同时提供了很多sink,如:

console[("format")] :直接将将数据显示在桌面上

text(“txtfile”):将数据写到文件txtfile中

dfs(“dfsfile”):将数据写到HDFS上的dfsfile文件中

syslogTcp(“host”,port):将数据通过TCP传递给host节点

(2) collector

collector的作用是将多个agent的数据汇总后,加载到storage中。它的source和sink与agent类似。

下面例子中,agent监听TCP的5140端口接收到的数据,并发送给collector,由collector将数据加载到HDFS上。

1
2
3
host : syslogTcp(5140) | agentSink("localhost",35853) ;
 
collector : collectorSource(35853) | collectorSink(" hdfs://namenode/user/flume/","syslog");

一个更复杂的例子如下:

有6个agent,3个collector,所有collector均将数据导入HDFS中。agent A,B将数据发送给collector A,agent C,D将数据发送给collectorB,agent C,D将数据发送给collectorB。同时,为每个agent添加end-to-end可靠性保障(Flume的三种可靠性保障分别由agentE2EChain, agentDFOChain, and agentBEChain实现),如,当collector A出现故障时,agent A和agent B会将数据分别发给collector B和collector C。

下面是简写的配置文件片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
agentA : src | agentE2EChain("collectorA:35853","collectorB:35853");
 
agentB : src | agentE2EChain("collectorA:35853","collectorC:35853");
 
agentC : src | agentE2EChain("collectorB:35853","collectorA:35853");
 
agentD : src | agentE2EChain("collectorB:35853","collectorC:35853");
 
agentE : src | agentE2EChain("collectorC:35853","collectorA:35853");
 
agentF : src | agentE2EChain("collectorC:35853","collectorB:35853");
 
collectorA : collectorSource(35853) | collectorSink(" hdfs://...","src");
 
collectorB : collectorSource(35853) | collectorSink(" hdfs://...","src");
 
collectorC : collectorSource(35853) | collectorSink(" hdfs://...","src");

此外,使用autoE2EChain,当某个collector 出现故障时,Flume会自动探测一个可用collector,并将数据定向到这个新的可用collector上。

(3) storage

storage是存储系统,可以是一个普通file,也可以是HDFS,HIVE,HBase等。

 

6. 总结

根据这四个系统的架构设计,可以总结出典型的日志系统需具备三个基本组件,分别为agent(封装数据源,将数据源中的数据发送给collector),collector(接收多个agent的数据,并进行汇总后导入后端的store中),store(中央存储系统,应该具有可扩展性和可靠性,应该支持当前非常流行的HDFS)。

下面表格对比了这四个系统:

7. 参考资料

scribe主页: https://github.com/facebook/scribe

chukwa主页: http://incubator.apache.org/chukwa/

kafka主页:h ttp://sna-projects.com/kafka/

Flume主页:http s://github.com/cloudera/flume/



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



专访QQ大数据团队,谈分布式计算系统开发

$
0
0

NoSQL是笔者最早接触大数据领域的相关知识,因此在大家都在畅谈Hadoop、Spark时,笔者仍然保留着NoSQL博文的阅读习惯。在偶尔阅读一篇Redis博文过程中,笔者发现了 jacksu的个人博客,并在其中发现了大量的分布式系统操作经验,从而通过他的引荐了解了QQ成立之初后台3个基础团队之一的QQ运营组,这里我们一起走进。

QQ大数据团队

CSDN:首先,请介绍一下您的团队?

聂晶:我们团队是社交网络事业群/社交网络运营部/数据中心/平台开发二组,前身是QQ成立之初后台3个基础团队之一的QQ 运营组。目前团队成员10人,主要负责社交网络事业群的基础数据挖掘系统和产品应用系统的研发和运营。作为腾讯内部较早研究并使用Hadoop的团队,结 合Hadoop、Spark等开源系统,推出面向应用的数据解决方案ADs(Aggregate Data services),涵盖数据整个生命周期;曾经面向复杂关系链计算,研发出圈子分布式计算系统等。目前,兴趣在于面向计算的分布式快速应用开发部署系统 ——R2,以及数据可视化的应用。

CSDN:贵团队是ADs的作者,可否为我们介绍一下当下ADs在腾讯的使用程度,比如支撑的业务,处理的数据集,集群规模等。

聂晶:ADs是腾讯即时通信线通用的,负责数据收集、分发的基础设施。ADs是一系列组件的统称,这些组件绝大多数为自主研 发,可以灵活组合起来支持实时和离线的多种数据需求。目前,ADs集群共700台各型服务器,日处理数据在2300亿左右,存储数据10PB+。为腾讯内 部5个部门,20多个业务线提供有效的支撑,比如数据查询、数据分析、产品统计、数据挖掘和用户推荐等。像QQ,手机QQ,以及其他通过即时通信工具接入 的业务,其基础数据都经由ADs对外提供服务。

图一 ADs架构图

CSDN:众所周知,扩展性是大型网络架构中必不可少的一环,请结合腾讯的实践经验做一些node rebalance相关分享?

聂晶:扩展性,在我们看来,包含两种含义:第一种是功能的扩展性,还有一种是整个系统吞吐的扩展性。

对于功能的扩展,从系统层面上,可以做的是根据系统承载的功能,抽象成不同组件,不同组件之间的结合,可以灵活扩展出面对新场景的功能。比如,ADs就抽象出接入自动解析的GAS(General Analyses Service)组件,高吞吐存储的COW组件,数据转换的DataT组件。GAS+COW就能提供应用的数据获取服务;GAS+DataT提供给离线模型计算使用。

对于整个系统的吞吐扩展,一般都会设计成去中心化的结构,每个节点提供对等的服务能力。比如GAS就是如此,每个机器负责的是对等 的服务能力,如果机器死机或者阔扩容,通过配置中心更新节点路由,保证服务一致,加上一些消息探测的机制,即使在某些极端情况下没有更新路由,也不会丢失 消息。

CSDN:在线处理环节,你们自主研发了R2,可否分享一下与当下流行计算框架Spark及Storm的对比?

聂晶:首先,R2 跟已有开源项目最大的不同在于它从一开始就是为了面向实时服务而设计的,所以它对性能和低延迟和系统可用性要求更强,比如,在推荐好友业务中,需要在 200ms内返回数据,但是涉及处理的数据却可能高达几百MB,怎样提升计算降低延时,是一个挑战。其次,从架构上看,R2是一个对称的结构,没有单点。 节点可以做到即插即用,扩容缩容不影响服务,这对存在一定资源空闲的大型机房来说,可以随时使用空闲资源,节省成本。再次,从功能上讲,R2对一些特定的 迭代计算做了大量优化,使得很多智能算法的实现变得简单高效。

CSDN:在ADs中,你们使用Hadoop做离线处理,那么如此规模下,主要的挑战是什么,会遇到哪些坑,及需要避免的地方?

聂晶:

1. 目前前主要使用的还是1.0版本,由于1.0版本的单点问题,如果主控机器死机,对业务会造成较大的影响。

2. 对模型计算,涉及到大数据的频繁读写计算,效率着实不高。所以,对于此类业务,我们在逐步迁移到spark。

3. 多用户同时使用集群,千万要根据业务特性使用不同的调度器。

4. 在Hadoop自身文档还不够完善时,有些细节千万不能想当然,需要多试试。比如配置机器host时,hostname不能带下划线。

5. 千万不要让集群节点的磁盘容量差异太大,否则在大数据写入并且集群使用率较大时,容易出现写失败等问题。

CSDN:在海量数据存储的过程中,在读写上是否遇到哪些问题?有没有调整系统默认的I/O调度策略或者是自己重写相应的文件系统?我说的是和Ext3/Ext2一个级别的文件系统。

聂晶:默认机器一般是对硬盘做RAID5,但是RAID5相对于RAID0,写性能也是比较差,而且比较浪费空间 (Hadoop自己对数据有容灾),我们使用的磁盘都是RAID0。不同的调度器对性能影响很大,通过测试使用比较适合业务的调度器,SSD和机械硬盘的 差距就比较大,分别使用不同的调度策略。Ext3不同的日志级别对性能影响很大,建议关键业务进行性能测试,使用适合业务本身的日志级别。这里只是使用比 较成熟的调度策略,自己没有进行重写。

CSDN:贵团队自主研发了数据解析服务GAS,可否为大家介绍一下主要特性?据悉即将开源? 

聂晶:GAS是一个通用的、实时的高性能数据解析框架,支持把不同格式的数据源,自动转换成一种格式,为后续组件提供无差别的流式数据服务。目前,GAS支持二进制协议、ProtoBuf协议、Json协议的解析。GAS的主要特点有:

  • 吞吐量大,单机峰值可到10w+/s,可充分利用机器资源
  • 提供通用的接口,方便扩展其他不同类型的协议
  • 单个数据格式修改方便,实时修改,实时生效

GAS目前已经在公司内部开源,目前正积极准备对外开源的有关事项。

CSDN:说到开源,可否透露一下腾讯当下使用的开源技术?都在系统中扮演着什么样的角色?顺便给大家谈谈使用开源技术的经验吧。

聂晶:在两种情况下我们会使用开源技术:第一种情况,在较简单非关键的应用中有使用开源的技术,比如thrift, 我们在数据查询等一些小系统中有使用,开源技术的优点显而易见,可以节约开发成本,很容易的可以实现简单的需求。第二种情况,一些绕不过去的,比较成熟 的,会使用开源系统,比如Hadoop,Zookeeper。我们系统中,底层和关键模块都是自己开发,做到完全可控。

开源技术良莠不齐,一些冷门的或者不成熟的最好不碰。即使是成熟的开源技术,在使用中也是有各种坑。不过,成熟或者热门的技术,好处在于可以利用各种网络资源,也有成熟的社区,你遇到的问题,大部分别人也遇到过,容易解决。

CSDN:无缝体验一直是服务交付中重要的一环,对于消除中间人,让实际使用者拥有一个更好的体验贵团队做了哪些努力?

图二 数据接入图

聂晶:ADs可以拿出说说。原来我们接入一个数据需要产品、开发、数据管理员多次沟通、多次联调以及多次数据质量确 认,才可以完成一个数据的接入,效率极低。ADs出现之后,减少了数据管理员环节。产品通过ADs去管理、验收数据;开发根据产品的提单开发、自助测试, 确认数据质量,知会产品验收数据。

ADs系列之通用数据解析服务GAS(即将开源)

面对成百上千的生产系统用户操作数据接入落地,你是否厌倦了每次机械编写打包解包代码?在一次性接入多个数据时,还要对不同人联 调,费时费力,你是否还会手忙脚乱,忙中不断出错?是否当数据出问题了,用的时候才发现,数据已经损失大半,产品/领导压力巨大,费一天劲才能定位问题, 关键是下次还是不能实时发现,快速定位。

怎么办?GAS(通用解析服务)就是为了解决上述问题,结合即通多年数据方案实践,提出的一个数据接入的组件。一杯清茶,轻点鼠标,轻松面对大批数据接入问题。

GAS在ADs中的位置

图 1  ADs整体框架

GAS(General Analyses Service)通用数据解析服务,用协议描述语言(Protocol Description Language – PDL)去描述数据,动态解析数据,实时按规则去除脏数据,实时整理数据,实时告警(需结合网管系统monitor使用)。即可作为分布式,也可作为单机版使用。解析引擎是插件式的,针对不同的协议,只需要开发相应插件即可。

GAS实现原理

GAS的整体框架

图 2  GAS整体框架

GAS master负责数据服务描述文件的管理,所有数据服务描述文件的添加、修改都在GAS master管理。GAS框架的主要优点:

  • interface主要分发不同数据到不同GAS broker、分发相同数据到不同GAS broker、分发不同协议的数据到运行不同解析插件的broker,分发数据到不同的对外应用,interface只是一个逻辑层。
  • GAS slaves分成不同的broker,每个broker接收不同的数据,或者一个数据可以在不同的broker接收多份,broker之间完全独立。分 broker可以分等级运营数据,方便运营,并且不同broker可以运行不同的解析插件,还可以减少路由表的下发包。
  • GAS slaves是去中心化的,GAS master死机只会影响服务描述文件的更新,不会影响已有数据的接收。
  • 数据之间是相互独立的,一个数据协议的错误,不会影响到其它数据。

GAS master

图 3  GAS Master框架

1. master机器上的配置模块,负责生成新数据的注册信息,可以登录ads.server.com,填写相关协议描述,就可以自动生成协议描述语言的配置文件。

图 4  服务描述配置页面

2. 检查配置文件模块,负责将新的配置读到内存,生成数据解析状态机,以检查是否能正常生成,可以测试协议是否正确。

图 5  协议抓包实时调试页面

3. 将正确的数据注册信息更新在测试环境,如果用户确认正确,那么我们可以一键发布到正式环境。

4. slaves每分钟访问一次master,检查是否有新的注册信息,如果有更新,则拉取服务描述文件到本地。

GAS Slave

图 6  GAS Slave框架

slave服务器主要分为两部分:agent进程和数据处理进程,两个模块主要通过共享内存head_mem进行交互,详情如下:

  1. agent进程负责每分钟检查一次配置文件是否有更新,如果有更新,则拉取新的服务描述文件到本地磁盘,将更新信息写入共享内存head_mem中,然后修改共享内存中head_mem的版本号。
  2. 先说明一下,我们每个数据都有一个唯一的标识,我们称为topic_id。每个数据的组包格式必须是Stx+topic_id+stBody+Etx,stBody是用户信息。这样我们收到一个包,就可以判断这个包是那个数据。

服务描述文件大致可分为3部分:基础信息配置,解析字段配置,导入信息配置。基础信息配置中包括日志相关、本地ip、端口、项目负 责人等一些全局的配置信息。解析字段配置是收到一个包后,按什么顺序解析、以及按什么格式解析字段。由import_opt_name配置项关联导入信息 配置。当在解析过程中,遇到某个字段有import_opt_name配置项时,触发该配置项对应的写共享内存操作。

数据处理主要做以下两个工作:

  • 每次接收数据后都检查head_mem中的版本号是否与已知版本号相同,如果版本号不同,则可以判断是那个 topic_id的服务描述文件更新了,如果这个topic_id的服务描述文件是新增,那么根据该topic_id服务描述文件生成对应的数据解析状态 机。如果是修改,则根据该topic_id配置文件生成对应的数据解析状态机。加载成功,那么释放该topic_id对应的原有数据解析状态机。
  • 收到一个数据包,根据topic_id判断调用哪个数据解析状态机,解析生成结构化数据,然后调用COW的接口进行存储。

状态机生成和数据解析实例

一个数据的协议为 Stx+topic_id+dwIP+cFlag+wCount+stUin+Etx;stUin=ddwUin+dwID。wCount是stUin的 大小,stUin为一个UIN、ID的结构体,假设wCount=2,那么stUin包含ddwUin1、dwID1和ddwUin2、dwID2。解析 字段列表为dwIP(short)、cFlag(char)、stUin(数组),stUin后面是导出字段列表dwIP、cFlag、ddwUin、 dwID。

Stx、Etx是协议的开始、结束标志,topic_id是协议的唯一标识。

状态机生成过程

图 7 状态机生成过程

状态机生成的过程是:(1)读取服务描述文件,动态生成Config对象,根据服务描述文件中的基础信息配置,填充Config的 属性,包括Socket属性。(2)根据服务描述文件中的解析字段配置,动态生成Socket中Field列表IP对象、Flag对象、Count对象、 stUin对象;stUin对象依赖Count对象,包含Uin对象、ID对象。(3)根据stUin对象后的import配置,生成stUin对象的 Import列表信息。

数据解析过程

数据解析过程与状态机生成过程类似,通过topic_id找到对应的Config对象;然后根据IP对象解析出IP的值,根据 Flag对象解析出Flag的值,根据Count对象解析出Count的值为2,根据stUin对象,stUin对象包含Uin对象、ID对象,那么解析 出Uin的值、ID的值。stUin对象有import列表,重新组包IP、Flag、Uin、ID的值写出。因为Count为2,再解析出Uin、ID 的值,重新组包IP、Flag、Uin、ID的值写出。数据解析状态机是预先生成的,不是动态生成的,这样可以提高数据解析性能。

性能测试

使用部门平均包长度进行测试,测试结果如表1。

表 1 协议解析性能测试

机器类型

cpu 70%解包量

最大解包量

B1老机器(Intel(R) Xeon(R) CPU E5405  @ 2.00GHz cache size: 6144 KB 4核)

8w/s

14w/s

C1新机器(Cpu:Intel(R) Xeon(R) CPU  X3440  @ 2.53GHz cache size : 8192 KB 8核)

18w/s

30w/s

展望

从上面介绍,我们还有一些工作需要做:protobuf协议插件,已经在测试中;txt协议插件,正在开发中;增强协议修改前后的兼容性。

博文链接:ADs系列之通用数据解析服务GAS(即将开源)



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



集群中几种session同步解决方案的比较(转)

$
0
0

在集群中session安全和同步是个最大的问题,下面是收集到的几种session同步的方案,希望能通过分析其各自的优劣找出其适应的场景。

1. 客户端cookie加密

简单,高效。比较好的方法是自己采用cookie机制来实现一个session,在应用中使用此session实现。

   问题:session中数据不能太多,最好只有个用户id。

   参考实现: http://rollerweblogger.org/

2. application server的session复制

   可能大部分应用服务器都提供了session复制的功能来实现集群,tomcat,jboss,was都提供了这样的功能。

   问题:

性能随着服务器增加急剧下降,而且容易引起广播风暴;

session数据需要序列化,影响性能。

如何序列化,可以参考  对象的序列化和反序列化.

参考资料:

Tomcat 5集群中的SESSION复制一

Tomcat 5集群中的SESSION复制二

应用服务器-JBoss 4.0.2集群指南

3. 使用数据库保存session

   使用数据库来保存session,就算服务器宕机了也没事,session照样在。

   问题:

程序需要定制;

每次请求都进行数据库读写开销不小(使用内存数据库可以提高性能,宕机就会丢失数据。可供选择的内存数据库有BerkeleyDB,Mysql的内存表);

数据库是一个单点,当然可以做数据库的ha来解决这个问题。

4. 使用共享存储来保存session

   和数据库类似,就算服务器宕机了也没事,session照样在。使用nfs或windows文件共享都可以,或者专用的共享存储设备。

   问题:

程序需要定制;

频繁的进行数据的序列化和反序列化,性能是否有影响;

共享存储是一个单点,这个可以通过raid来解决。

5. 使用memcached来保存session

   这种方式跟数据库类似,不过因为是内存存取的,性能自然要比数据库好多了。

   问题:

程序需要定制,增加了工作量;

存入memcached中的数据都需要序列化,效率较低;

          memcached服务器一死,所有session全丢。memchached能不能做HA? 我也不知道,网站上没提。

   参考资料:

应用memcached保存session会话信息

正确认识memcached的缓存失效

扩展Tomcat 6.x,使用memcached存放session信息

 

6. 使用terracotta来保存session

   跟memcached类似,但是数据不需要序列化,并且是Find-Grained Changes,性能更好。配置对原来的应用完全透明,原有程序几乎不用做任何修改。而且terracotta本身支持HA。

问题:terracotta的HA本身进行数据复制性能如何?

参考资料:

JVM-level clustering

Terracotta集群Tomcat实现Session同步

使用Terracotta和Tomcat建立ACTIVE-PASSIVE模式的集群

用Spring Web Flow和Terracotta搭建Web应用

Terracotta实战示例——集群RIFE

Terracotta近况:转向开源,接受度,Hibernate支持

 

附:terracotta介绍

Open Terracotta is an enterprise-class, open-source, JVM-level clustering solution. JVM-level clustering simplifies enterprise Java by enabling applications to be deployed on multiple JVMs, yet interact with each other as if they were running on the same JVM. Terracotta extends the Java Memory Model of a single JVM to include a cluster of virtual machines such that threads on one virtual machine can interact with threads on another virtual machine as if they were all on the same virtual machine with an unlimited amount of heap.



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Jeff Dean谈如何在大型在线服务中做到快速响应

$
0
0

6月于硅谷举行的 Velocity 2014大会上,Google首席科学家Jeff Dean做了一场题为 《Achieving Rapid Response Times In Large Online Services》的主题演讲,分享了让大型系统运行更加流程以便改善用户体验的种种方法。

Jeff首先以Google的搜索服务为例,说明了何为 大扇出服务(Large Fanout Service),即一个搜索请求需要有大量子系统(Web、新闻、图像、视频、博客等等)参与其中,以便提供更丰富的搜索结果。在Google,基本不会为特定的服务提供特定的机器,而是将服务都部署在一个机器池中,这被称为 共享环境(Shared Environment),Google的共享环境大致会包含以下几个部分——Linux、调度系统、文件系统ChunkServer、多种其他系统服务、Bigtable Tablet Server、随机MapReduce任务、CPU密集型任务以及随机应用。它的好处是可以极大地提升利用率,但同时也会带来诸多无法预测的问题,比如网络拥塞等等。尤其是响应时间的长尾现象比较明显,一次请求的平均响应时间是10毫秒,但是却有99%ile的响应时间大于1秒,在大扇出服务中,如果需要调用100台服务器获得最终结果,那有63%的请求耗时会大于1秒。

针对延时问题,有些基本的降低延时的技术:

  • 定义不同的服务级别,针对服务器上的请求队列和网络流量设定优先级。
  • 减少线头阻塞(head-of-line blocking),将大的请求打散成一系列小请求;比如,一个读请求需要读取64MB数据,而另有一个100KB的读请求必须等前者完成了才能得到处理,此时可以将大请求分为多个小请求,以便100KB的那个请求能及时得到处理。
  • 管理好昂贵的后台活动,比如分布式存储系统中的日志压缩就算昂贵的后台活动,此类活动可以考虑在负载低峰期去执行。

Jeff指出,我们要做的事就是基于一堆不可靠的资源打造一个可靠的整体,基于一堆无法预估的资源打造可以预测的整体。在延时处理方面,Jeff将对应的技术分为两大块:

  • 跨请求适应(cross request adaptation),通过检测最近的行为,采取一些措施来优化后续的请求处理,通常会和负载均衡有关,生效时间大约是十几秒到几分钟。
  • 同请求适应(within request adaptation),在当次请求中,对响应较慢的子系统采取一些措施,以改善本次请求的整体响应时间,通常是立刻生效的。

随后,他分别就两类技术进行具体展开说明。

1. 跨请求适应

可以通过细粒度的动态分区,将大数据集或大型计算拆分到多台服务器上,一般一台服务器上会分到10到100个块,BigTable和GFS就是这么处理的。

这么做的好处是显而易见的,比如,当一台机器负载过重时,可以将其中的一部分内容移动到另一台上;可以加速故障恢复,多台服务器分别恢复不同的数据块;实现选择性复制,针对重度使用的内容可以动态或静态地生成更多副本。

当服务器的响应变慢时,有可能这和当时发送的数据有关,但更多情况下是受到干扰的影响,比如共享服务器上其他任务造成的CPU或网络尖刺。此时可以选择将部分负载移动到其他服务器上以便改善延时情况,也可以在其他服务器上创建更多该分区的副本,继续给这台服务器发送请求(正常请求发给其他服务器了,发给本服务器的请求只是一份镜像)持续观察延时情况,待延时正常后再让其提供正常服务。

2. 同请求适应

同请求适应的目标是在 不会增加太多资源消耗的情况下减少整体延时,同时还要保障系统安全运行。

有时一些失败是和请求数据有关的,比如一些测试过程中没有发现的“奇怪数据”会造成系统宕机等等,如果一次性将有问题的请求发给所有节点,那么所有节点就都出问题了。在Google会使用一种名为Canary Requests的请求,即把请求先发给一个节点,收到响应后,基本可以证明这个查询是可行的,随后再将其发给其他节点。

Jeff在随后的时间里详细介绍了他们使用的另一项技术——备份请求(Backup Requests),大致的思路是先把请求发给一个副本,请求会被放进队列;随后再给另一个副本发送相同请求,如果第二个副本处理地很快,处理完毕后发回结果,客户端再给第一个副本发送取消任务请求。

以In-memory BigTable Lookups为例,数据存储了两份,将在100个Tablet中发送1000个键查询,统计最后一个键返回的总耗时。在没有备份请求时,平均耗时33毫秒,99%ile为52毫秒,99.9%ile高达994毫秒;当在10毫秒后发送备份请求时,平均耗时降为14毫秒,99%ile和99.9%ile分别降到了23毫秒和50毫秒,此外还测试了在50毫秒后发送备份请求的情况,耗时同样比没有备份要好,但较前者表现略逊一筹。本案例中,延时10毫秒的备份请求仅增加了不到5%的额外请求负担,在延时50毫秒的情况下,更是下降到不足1%。 可见备份请求能在很大程度上改善延时的长尾效应,同时并未增加太多开销。

备份请求技术还可进一步优化,在发送请求时将处理请求的另一台服务器信息也纳入请求中,一旦一台服务器开始执行,就直接通知另一台取消执行,这项优化称为跨服务器取消。Jeff同样提供了一个例子,在分布式文件系统客户端中发送读请求,等待2毫秒后发送备份请求,耗时情况如下:

  • 集群处于空闲状态
    • 没有备份请求,50%ile为19毫秒,90%ile为38毫秒,99%ile为67毫秒,99.9%ile为98毫秒
    • 有备份请求,50%ile为16毫秒,90%ile为28毫秒,99%ile为38毫秒,99.9%ile为51毫秒
  • 集群正在进行大量排序
    • 没有备份请求,50%ile为24毫秒,90%ile为56毫秒,99%ile为108毫秒,99.9%ile为159毫秒
    • 有备份请求,50%ile为19毫秒,90%ile为35毫秒,99%ile为67毫秒,99.9%ile为108毫秒

两种情况下,使用备份请求延时都有显著改善,99%ile分别下降了43%和38%,在第二种情况下备份请求只引入了大约1%的额外磁盘读请求。如果没有备份请求,集群需要一直处于低负载状态,而使用了备份请求,集群则可处于相对较高的负载,同时还能有相对较好的响应延时。

对于备份请求而言,最坏的情况即是两台机器几乎同时收到请求,并且都处理了请求,这会带来一定的资源浪费。当然,也可以引入第三个请求,但通常情况下向两台服务器发送请求就已经足够了。在演讲后的Office Hour中,Jeff表示备份请求也不是万能的,对于一些不可重复执行得请求,比如在线交易,就不能使用备份请求,以免造成数据不一致等情况。

在本次Velocity大会上,Jeff Dean的演讲时间较短,如果您对他的具体演讲内容感兴趣,可以观看 官方视频。同时,也推荐您去阅读2013年Jeff Dean 在斯坦福的演讲还有 一篇更早的材料。我们希望有一天能够邀请到Jeff到国内现场为广大InfoQ的读者做一次分享,到时您会来参加么?

via: InfoQ

疑似菜鸟网络调侃商务部官员批评:悟空你又调皮了

$
0
0

菜鸟网络

菜鸟网络官方微博回应商务部批评:悟空你又调皮了

【TechWeb】7月15日下午消息,阿里巴巴首席市场官(CMO)王帅在微博中就商务部电子商务司副巡视员聂林海公开批评马云及菜鸟物流一事做出回应,称菜鸟物流的事情急不得。随后,菜鸟网络官方微博转发了王帅的微博,并回复“悟空你又调皮了啊”。

王帅在微博中称,菜鸟无法解决把物流基础设施建立在云端的难题,在全国各个物流中心区域建设仓储中心,搭建连通全国的高标准仓储体系是支撑智能骨干网的“下半身”,实在缺不了。

而菜鸟网络官方微博随后转发了王帅微博,以戏谑的口气评论称:悟空你又调皮了啊。。。有则改之,无则加勉,我们一起努力!

附为王帅微博全文:

关于聂司长批评的两点回复

1. 尽管我们在云计算领域取得了快速的发展,但是坦诚的讲,我们还是无法解决把物流基础设施建立在云端的难题,我们也无法把全国的仓建在一个仓。。。在全国各个物流中心区域建设仓储中心,搭建连通全国的高标准仓储体系是支撑智能骨干网的“下半身”。这个下半身,事关命根子,实在缺不了。

2.我们 希望在5-8年的时间内,建立一张能支撑日均300亿(年度约10万亿)网络零售额的智能骨干网络。客观的讲,跟西方发达的物流体系相比,我们的仓储,不是多了,而是少多了。。。我能告诉您我们也在国外拿地吗?全球化来的比我想象的还要快。。。(这条信息,您是第一个知道的!)

3.菜鸟要解决的是今天就要动手做的----十年之后的事情。历史一次次证明,人类对未来尤其是超过今天的未来,能够达成共识的东西真是太少了,况且是对之前人类还没做过的事情。我们不能着急,您也不要太急。

4.您的批评让我们坚信,路走对了,就不怕走歪。祝您满意。

Viewing all 15843 articles
Browse latest View live