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

hadoop集群调优-OS和文件系统部分

$
0
0

OS and File System

根据Dell(因为我们的硬件采用dell的方案)关于hadoop调优的相关说明,改变几个Linux的默认设置,Hadoop的性能能够增长大概15%。

 

open file descriptors and files

文件描述符是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开,文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。

 

在Linux系列的操作系统上,由于Linux的设计思想便是把一切设备都视作文件。因此,文件描述符为在该系列平台上进行设备相关的编程实际上提供了一个统一的方法。

 

在CentOS中通过下面的命令查看:

cat /proc/sys/fs/file-max
800000

 

 

也可以通过查看文件中的内容来查看,其中的fs.file-max定义了最大的打开文件描述符数量:

cat /etc/sysctl.conf
fs.file-max = 800000
net.core.rmem_default = 12697600
net.core.wmem_default = 12697600
net.core.rmem_max = 873800000
net.core.wmem_max = 655360000
net.ipv4.tcp_rmem = 8192 262144 4096000
net.ipv4.tcp_wmem = 4096 262144 4096000
net.ipv4.tcp_max_orphans = 300000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 1025 65535
net.ipv4.tcp_max_syn_backlog = 100000
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp.keepalive_time = 1200
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 1500
net.core.somaxconn=32768
vm.swappiness=0

 

 

CentOS下可以通过下面的命令来增加最大打开文件描述符数量,在集群中的每台机器上执行:

# su – (hdfs & Hadoop users)
# ulimit –S 4096
# ulimit –H 32832

 

 

也可以通过修改/etc/sysctl.conf文件中的fs.file-max来达到目的。

 

由于这部分的数值远远大于文档中所列出的数字,此部分没有做优化。

 

File System

Linux的发行版本对于文件系统有着不同的初始设置。经过测试不同的Linux File Systems,发现EXT4格式要比EXT3更好。EXT4中的新特性,比如多块延迟分配,相比于EXT3要提高很大一部分的性能。在EXT3中,当一个文件被创建或数据被添加到一个已经存在的文件时,会直接调用文件block allocator,每个block一次;而EXT4则不同,它会做一个缓冲,以便以后能够最优化地将数据连续地放入硬盘。连续的文件能够很容易地被机械硬盘读写以能够提高存储IO的整体性能。

 

默认情况下,Linux会把文件访问的时间atime作记录,这在绝大多数场合下都是没有必要的,尤其是IO负载比较高的Hadoop集群下,可以尝试使用noatime和nodiratime。

 

在Hadoop中,很多中间文件(比如map输出的中间文件)都只会在Hadoop job运行过程中存活,job执行完成就会被删除了,根本没有必要存在访问时间戳。

 

通过命令cat /etc/fstab来查看当前的设置:

UUID=5d75c681-1101-46c2-9428-3e48310765ce                 /                       ext3    defaults        1 1
LABEL=/boot             /boot                   ext3    defaults        1 2
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
LABEL=SWAP-sda3         swap                    swap    defaults        0 0

 

 

可以看到当前并没有使用EXT4格式以及noatime。

 

注意,修改完设置后需要重新挂载文件系统,不需要重启。

mount -o remount /

 

 

另外一个对于dataNodes的优化点就是通过改变文件系统的保留块大小。Linux文件系统中为了保证root能够登录到操作系统中,需要保留一定的磁盘空间,默认这个值设置为5%。但是当前磁盘空间都是TB级别的,因此保留5%就会造成一大部分空间的浪费,对于1TB来说就是50G。

 

通过下面的命令来列出当前的保留磁盘空间。

tune2fs –l /dev/sdaX

 

 

下面的命令可以将保留磁盘空间的容量设置成1%:

tune2fs –m 1 /dev/sdaX

  

 

 

Network

两个网络相关的参数可以影响Hadoop的性能。net.core.somaxconn Linux内核设置能够支持NameNode和JobTracker的大量爆发性的HTTP请求。

 

net.core.somaxconn是listen()的默认参数,挂起请求的最大数量.默认是128.对繁忙的服务器,增加该值有助于网络性能,当前已经被调整到32768。

 

这个参数同样可以通过编辑/etc/sysctl.conf文件来改变,其中有一行:

net.core.somaxconn=32768

 

 

设置txqueuelen到4096及以上能够更好地适应在Hadoop集群中的突发流量, txqueuelen代表用来传输数据的缓冲区的储存长度,通过下面的命令可以对该参数进行设置为4096:

sudo ifconfig eth# txqueuelen 4096

 

 

其他的一系列在/etc/sysctl.conf中的配置,可以对网络产生影响:

net.core.rmem_default = 12697600
net.core.wmem_default = 12697600
net.core.rmem_max = 873800000
net.core.wmem_max = 655360000
net.ipv4.tcp_rmem = 8192 262144 4096000
net.ipv4.tcp_wmem = 4096 262144 4096000
net.ipv4.tcp_max_orphans = 300000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 1025 65535
net.ipv4.tcp_max_syn_backlog = 100000
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp.keepalive_time = 1200
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 1500

 

  

上述设置需要重新启动整个集群系统。

 

Transparent Huge Page

Linux的特性Transparent HugePages在大部分的应用中都提高了整体性能,包括Hadoop的工作负载。但是,其中的一项被称为Compaction的子特性会导致Hadoop工作负载的问题,在设置了Compaction的Hadoop benchmark测试中,结果会存在25%的浮动,而关闭Compaction后浮动消失。

 

当进行内存碎片整理时,Compaction会提高CPU资源利用率,这能够帮助优化Transparent HugePages,但是偷取了CPU资源,却影响了hadoop中正在运行的task性能。

 

通过以下命令可以查看是否启用compaction:

cat /sys/kernel/mm/redhat_transparent_hugepages/defrag

 

 

以及以下命令来禁用Compaction:

echo never > /sys/kernel/mm/redhat_transparent_hugepages/defrag

 

 

这个特定暂时没有进行修改,因为CentOS中没找到在哪儿设置。

 

Linux kernal swappiness parameter

任何进程只要涉及到换页向磁盘写文件都会降低hadoop的性能,Linux内核进程vm.swappiness会检查无用的内存分页并将它们交换到磁盘上。默认的值是60,可以设置为0——100。对于Hadoop来说,设置成0是一个好主意,这并没有将这个特性关闭,Linux仍然进行换页操作,但是由于这个进程在仍然还有一大部分空闲内存时仍然会进行换页,将它设置成0可以尽可能地减少内存和磁盘的延迟。

 

这个参数仍然可以通过编辑/etc/sysctl.conf来进行修改。

 

当前集群已经设置:

vm.swappiness=0

 

 



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


ITeye推荐




使用OGG,两个Oracle库之间单向同步数据

$
0
0

配置:源数据库100.100.100.21         实例名dbsid2

            目标数据库100.100.100.41       实例名db1

实验目标:源数据库中的 scott用户 emp表同步到目标数据库 scott中的test表

安装包为文件ogg112101_fbo_ggs_Linux_x64_ora10g_64bit.zip

解压之后,然后再tar解压tar -xvf fbo_ggs_Linux_x64_ora10g_64bit.tar -C  /oracle/ogg/

1.       源数据库(dbsid2)配置:

(1)       用户权限:grant dba to scott

(2)       打开归档模式

(3)附加日志:
           alter database add supplemental log data;

     alter database force logging;

   (4)将目标数据库db1信息添加到 tnsnames.ora中

2.       目标数据库(db1)配置:

(1)       scott用户建立空表test,表结构和emp相同

(2)       打开归档模式

(3)       附加日志:

alter database add supplemental log data;

alter database force logging;

(4)       将源数据库(dbsid2)的信息添加到 tnsnames.ora中

3.       源数据库服务器 goldengate安装

(1)       解压到/oracle/ogg目标下面

(2)       运行./ggsci

(3)       新建子目录: GGSCI (host2) 1> create subdirs

Creating subdirectories under current directory /oracle/ogg

Parameter files                /oracle/ogg/dirprm: already exists

Report files                   /oracle/ogg/dirrpt: created

Checkpoint files               /oracle/ogg/dirchk: created

Process status files           /oracle/ogg/dirpcs: created

SQL script files               /oracle/ogg/dirsql: created

Database definitions files     /oracle/ogg/dirdef: created

Extract data files             /oracle/ogg/dirdat: created

(4)       配置字符管理的Port参数

GGSCI (host2) 6> edit params mgr

输入: PORT 7809 然后保存

检查输入情况:

GGSCI (host2) 7> view params mgr

PORT 7809

(5)       启动Start mgr:

GGSCI (host2) 8> start mgr

MGR is already running.

GGSCI (host2) 9> info mgr

Manager is running (IP port host2.7809).

4.       目标数据库服务器 goldengate安装(和源目标服务器相同)

(1)       解压到/oracle/ogg目标下面

(2)        运行./ggsci

(3)       新建子目录: GGSCI (host2) 1> create subdirs

Creating subdirectories under current directory /oracle/ogg

Parameter files                /oracle/ogg/dirprm: already exists

Report files                   /oracle/ogg/dirrpt: created

Checkpoint files               /oracle/ogg/dirchk: created

Process status files           /oracle/ogg/dirpcs: created

SQL script files               /oracle/ogg/dirsql: created

Database definitions files     /oracle/ogg/dirdef: created

Extract data files             /oracle/ogg/dirdat: created

(4)       配置字符管理的Port参数

GGSCI (host2) 6> edit params mgr

输入: PORT 7809 然后保存

检查输入情况:

GGSCI (host2) 7> view params mgr

PORT 7809

(4)       启动Start mgr:

GGSCI (host2) 8> start mgr

MGR is already running.

GGSCI (host2) 9> info mgr

Manager is running (IP port host2.7809).

5.       配置源数据库服务器(dbsid2)传输进程extract

(1)添加名字为source1的进程

GGSCI (host2) 19> add extract source1,sourceistable  

EXTRACT added.

(3)       修改source1参数

GGSCI (host2) 20> edit params source1

添加如下,并且保存

extract source1

setenv (NLS_LANG=AMERICAN_AMERICA.AL32UTF8)

userid scott,password tiger                        

rmthost 100.100.100.41,mgrport 7809

rmttask replicat,group target1

table scott.emp;

注:1、需要复制表的用户名为scott,密码tiger

    2、目标数据库(db1)的IP为100.100.100.41,端口为7809

    3. 目标数据库(db1)的接收进程名字为 target1

    4.  需要复制的table为: scott.emp表。

查看修改的参数

GGSCI (host2) 21> view params source1

6.       配置目标数据库db1 replicat接收进程

(1)       添加replicat进程,名字为source1

GGSCI (host2) 9> add replicat target1,specialrun

REPLICAT added.

(2)       添加修改参数:GGSCI (host2) 13> edit params target1

replicat target1

setenv (NLS_LANG=AMERICAN_AMERICA.AL32UTF8)

assumetargetdefs

userid scott,password tiger

discardfile ./dirrpt/target1.dsc,purge

map scott.emp,target scott.test;

注:1. 目标数据库账号为scott,tiger

         2. 将源数据库的表scott.emp同步到scott.test表中

        查看修改之后

        GGSCI (host2) 1> view params target1

7.       源数据库(dbsid2)开始同步

(1)       开始同步

GGSCI (host2) 11> start extract source1

 

Sending START request to MANAGER ...

EXTRACT SOURCE1 starting

(2)       监控同步过程

GGSCI (host2) 12> info all

Program     Status      Group       Lag at Chkpt  Time Since Chkpt

MANAGER     RUNNING   

 

(3)       源数据库查看同步日志

GGSCI (host2) 13> view report source1

8.       目标数据库(db1)查看同步情况

SQL> select * from test;

作者:u011538954 发表于2014-7-20 12:15:37 原文链接
阅读:65 评论:0 查看评论

linux实用技巧:使用快照制作虚拟机

$
0
0
    在日常的学习当中,如果遇到了集群和负载均衡类的实验,需要用到大量的虚拟机,如果一个一个的去创建,显然是非常费力和低效的。所以今天交给大家如何用快照来制作虚拟机。想要多少给你多少^_^。只要内存够用!

    制作虚拟机的快照分为以下几个步骤:

    1.首先我们要创建存储的逻辑卷来生成模板和快照文件;
    2.制作被快照的模板;
    3.创建快照。

1.创建逻辑卷:

    (1)fdisk /dev/sda   (制作LVM逻辑卷,然后对磁盘进行重新的扫描;)
      

    (2)partx -d /dev/sda
         partx -a /dev/sda

    (3)创建lv文件:

         pvcreate /dev/sda
         vgcreate -s 4M vg1 /dev/sda5
         lvcreate -L 10G -n base vg1

    (4)然后就可以制作虚拟机模板:
   
      
      
      

       这个时候你就可以像安装一个普通的虚拟机一样。重启完成之后要进行一下的操作(因为你制作的是模板,所以模板要有通用性)

2.制作模板:
    
       在模板虚拟机里要进行一下几个操作:
    
       1.关闭火墙和selinux(文件里修改):
      
       

        vim /etc/sysconfig/selinux
       
        
        2.修改网路配置文件和删除网卡信息:
       
        vim /etc/sysconfig/network-script/ifcfg-eth0
       
       
       
      
        3.修改yum源为稳定的地址:

        vim /etc/yum.repos.d/yum.repo
     
       
       
        
        
3.创建快照:
          
     完成之后我们的模板就已经制作完成了,这个时候在真机上用快照对它进行拍照,但是在拍照之前一定要把这个模板关闭掉,通常我们给人拍照的时候也都是要他静止的^_^。
        
        

        

         选中我们的快照文件:

         
        
          直接启动vm2,瞬间开启,他的状态就是模板的初始状态,非常的方便。

          
            我们来计算一下总共的开销:
           
            模板(10G)
            以后每个虚拟机只需要4G左右,这样可以制作出非常多的虚拟机。不需要进行安装,而且大大的节省了空间开销。

          
结束语:
         
        小伙伴们赶紧去实践一下吧。






        
作者:linux_player_c 发表于2014-7-20 10:26:52 原文链接
阅读:61 评论:0 查看评论

亲测Mysql表结构为InnoDB类型从ibd文件恢复数据

$
0
0

客户的机器系统异常关机,重启后mysql数据库不能正常启动,重装系统后发现数据库文件损坏,悲催的是客户数据库没有进行及时备份,只能想办法从数据库文件当中恢复,查找资料,试验各种方法,确认下面步骤可行:

一、找回表结构,如果表结构没有丢失直接到下一步
      a、先创建一个数据库,这个数据库必须是没有表和任何操作的。
      b、创建一个表结构,和要恢复的表名是一样的。表里的字段无所谓。一定要是innodb引擎的。CREATE TABLE `test`(  `testID` bigint(20)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      c、关闭mysql, service mysqld stop;
      d、用需要恢复的frm文件覆盖刚新建的frm文件;  
      e、修改my.ini 里  innodb_force_recovery=1 , 如果不成修改为 2,3,4,5,6。
      f、 启动mysql,service mysqld start;show create table test就能够看到表结构信息了。

二、找回数据

      a、建立一个数据库,根据上面导出的创建表的sql执行创建表。
      b、找到记录点。先要把当前数据库的表空间废弃掉,使当前ibd的数据文件和frm分离。  ALTER TABLE test DISCARD TABLESPACE;
      c、把之前要恢复的 .ibd文件复制到新的表结构文件夹下。 使当前的ibd 和frm发生关系。ALTER TABLE test  IMPORT TABLESPACE;

      d、将恢复好的数据导出就行了

作者:bushy0401 发表于2014-7-20 9:15:17 原文链接
阅读:86 评论:0 查看评论

编写内存效率的java代码-面向GC

$
0
0

参考两个PPT

http://www.slideshare.net/cnbailey/memory-efficient-java
http://www.cs.virginia.edu/kim/publicity/pldi09tutorials/memory-efficient-java-tutorial.pdf

 

原文: 沐剑

Java程序员在编码过程中通常不需要考虑内存问题,JVM经过高度优化的GC机制大部分情况下都能够很好地处理堆(Heap)的清理问题。以至于许多Java程序员认为,我只需要关心何时创建对象,而回收对象,就交给GC来做吧!甚至有人说,如果在编程过程中频繁考虑内存问题,是一种退化,这些事情应该交给编译器,交给虚拟机来解决。

这话其实也没有太大问题,的确,大部分场景下关心内存、GC的问题,显得有点“杞人忧天”了,高老爷说过:

过早优化是万恶之源。

但另一方面,什么才是“过早优化”?

If we could do things right for the first time, why not?

事实上JVM的内存模型(  JMM )理应是Java程序员的基础知识,处理过几次JVM线上内存问题之后就会很明显感受到,很多系统问题,都是内存问题。

对JVM内存结构感兴趣的同学可以看下  浅析Java虚拟机结构与机制 这篇文章,本文就不再赘述了,本文也并不关注具体的GC算法,相关的文章汗牛充栋,随时可查。

另外,不要指望GC优化的这些技巧,可以对应用性能有成倍的提高,特别是对I/O密集型的应用,或是实际落在YoungGC上的优化,可能效果只是帮你减少那么一点YoungGC的频率。

但我认为,优秀程序员的价值,不在于其所掌握的几招屠龙之术,而是在细节中见真著,就像前面说的,如果我们可以一次把事情做对,并且做好,在允许的范围内尽可能追求卓越,为什么不去做呢?

一、GC分代的基本假设

大部分GC算法,都将堆内存做分代(Generation)处理,但是为什么要分代呢,又为什么不叫内存分区、分段,而要用面向时间、年龄的“代”来表示不同的内存区域?

GC分代的基本假设是:

绝大部分对象的生命周期都非常短暂,存活时间短。

而这些短命的对象,恰恰是GC算法需要首先关注的。所以在大部分的GC中,YoungGC(也称作MinorGC)占了绝大部分,对于负载不高的应用,可能跑了数个月都不会发生FullGC。

基于这个前提,在编码过程中,我们应该尽可能地缩短对象的生命周期。在过去,分配对象是一个比较重的操作,所以有些程序员会尽可能地减少new对象的次数,尝试减小堆的分配开销,减少内存碎片。

但是,短命对象的创建在JVM中比我们想象的性能更好,所以,不要吝啬new关键字,大胆地去new吧。

当然前提是不做无谓的创建,对象创建的速率越高,那么GC也会越快被触发。

结论:

分配小对象的开销分享小,不要吝啬去创建。

GC最喜欢这种小而短命的对象。

让对象的生命周期尽可能短,例如在方法体内创建,使其能尽快地在YoungGC中被回收,不会晋升(romote)到年老代(Old Generation)。

二、对象分配的优化

基于大部分对象都是小而短命,并且不存在多线程的数据竞争。这些小对象的分配,会优先在线程私有的 TLAB 中分配,TLAB中创建的对象,不存在锁甚至是CAS的开销。

TLAB占用的空间在Eden Generation。

当对象比较大,TLAB的空间不足以放下,而JVM又认为当前线程占用的TLAB剩余空间还足够时,就会直接在Eden Generation上分配,此时是存在并发竞争的,所以会有CAS的开销,但也还好。

当对象大到Eden Generation放不下时,JVM只能尝试去Old Generation分配,这种情况需要尽可能避免,因为一旦在Old Generation分配,这个对象就只能被Old Generation的GC或是FullGC回收了。

三、不可变对象的好处

GC算法在扫描存活对象时通常需要从ROOT节点开始,扫描所有存活对象的引用,构建出对象图。

不可变对象对GC的优化,主要体现在Old Generation中。

可以想象一下,如果存在Old Generation的对象引用了Young Generation的对象,那么在每次YoungGC的过程中,就必须考虑到这种情况。

Hotspot JVM为了提高YoungGC的性能,避免每次YoungGC都扫描Old Generation中的对象引用,采用了 卡表(Card Table) 的方式。

简单来说,当Old Generation中的对象发生对Young Generation中的对象产生新的引用关系或释放引用时,都会在卡表中响应的标记上标记为脏(dirty),而YoungGC时,只需要扫描这些dirty的项就可以了。

可变对象对其它对象的引用关系可能会频繁变化,并且有可能在运行过程中持有越来越多的引用,特别是容器。这些都会导致对应的卡表项被频繁标记为dirty。

而不可变对象的引用关系非常稳定,在扫描卡表时就不会扫到它们对应的项了。

注意,这里的不可变对象,不是指仅仅自身引用不可变的 final对象,而是真正的Immutable Objects。

四、引用置为null的传说

早期的很多Java资料中都会提到在方法体中将一个变量置为null能够优化GC的性能,类似下面的代码:

List<String> list = new ArrayList<String>();
// some code
list = null; // help GC

事实上这种做法对GC的帮助微乎其微,有时候反而会导致代码混乱。

我记得几年前撒迦在HLL VM小组中详细论述过这个问题,原帖我没找到,结论基本就是:

在一个非常大的方法体内,对一个较大的对象,将其引用置为null,某种程度上可以帮助GC。

大部分情况下,这种行为都没有任何好处。

所以,还是早点放弃这种“优化”方式吧。

GC比我们想象的更聪明。

五、手动档的GC

在很多Java资料上都有下面两个奇技淫巧:

通过 Thread.yield()让出CPU资源给其它线程。

通过 System.gc()触发GC。

事实上JVM从不保证这两件事,而 System.gc()在JVM启动参数中如果允许显式GC,则会触发FullGC,对于响应敏感的应用来说,几乎等同于自杀。

So,让我们牢记两点:

Never use  Thread.yield()

Never use  System.gc()。除非你真的需要回收Native Memory。

第二点有个Native Memory的例外,如果你在以下场景:

  • 使用了NIO或者NIO框架(Mina/Netty)

  • 使用了DirectByteBuffer分配字节缓冲区

  • 使用了MappedByteBuffer做内存映射

由于Native Memory只能通过FullGC(或是CMS GC)回收,所以除非你非常清楚这时真的有必要,否则不要轻易调用 System.gc(),且行且珍惜。

另外为了防止某些框架中的 System.gc调用(例如NIO框架、Java RMI),建议在启动参数中加上 -XX:+DisableExplicitGC来禁用显式GC。

这个参数有个巨大的坑,如果你禁用了 System.gc(),那么上面的3种场景下的内存就无法回收,可能造成OOM,如果你使用了CMS GC,那么可以用这个参数替代: -XX:+ExplicitGCInvokesConcurrent

关于 System.gc(),可以参考毕玄的几篇文章:

六、指定容器初始化大小

Java容器的一个特点就是可以动态扩展,所以通常我们都不会去考虑初始大小的设置,不够了反正会自动扩容呗。

但是扩容不意味着没有代价,甚至是很高的代价。

例如一些基于数组的数据结构,例如 StringBuilderStringBufferArrayListHashMap等等,在扩容的时候都需要做ArrayCopy,对于不断增长的结构来说,经过若干次扩容,会存在大量无用的老数组,而回收这些数组的压力,全都会加在GC身上。

这些容器的构造函数中通常都有一个可以指定大小的参数,如果对于某些大小可以预估的容器,建议加上这个参数。

可是因为容器的扩容并不是等到容器满了才扩容,而是有一定的比例,例如 HashMap的扩容阈值和负载因子(loadFactor)相关。

Google Guava框架对于容器的初始容量提供了非常便捷的工具方法,例如:

Lists.newArrayListWithCapacity(initialArraySize);

Lists.newArrayListWithExpectedSize(estimatedSize);

Sets.newHashSetWithExpectedSize(expectedSize);

Maps.newHashMapWithExpectedSize(expectedSize);

这样我们只要传入预估的大小即可,容量的计算就交给Guava来做吧。

反例:

如果采用默认无参构造函数,创建一个ArrayList,不断增加元素直到OOM,那么在此过程中会导致:

  • 多次数组扩容,重新分配更大空间的数组
  • 多次数组拷贝
  • 内存碎片

七、对象池

为了减少对象分配开销,提高性能,可能有人会采取对象池的方式来缓存对象集合,作为复用的手段。

但是对象池中的对象由于在运行期长期存活,大部分会晋升到Old Generation,因此无法通过YoungGC回收。

并且通常……没有什么效果。

对于对象本身:

如果对象很小,那么分配的开销本来就小,对象池只会增加代码复杂度。

如果对象比较大,那么晋升到Old Generation后,对GC的压力就更大了。

从线程安全的角度考虑,通常池都是会被并发访问的,那么你就需要处理好同步的问题,这又是一个大坑,并且同步带来的开销,未必比你重新创建一个对象小。

对于对象池,唯一合适的场景就是当池中的每个对象的创建开销很大时,缓存复用才有意义,例如每次new都会创建一个连接,或是依赖一次RPC。

比如说:

  • 线程池
  • 数据库连接池
  • TCP连接池

即使你真的需要实现一个对象池,也请使用成熟的开源框架,例如Apache Commons Pool。

另外,使用JDK的 ThreadPoolExecutor作为线程池,不要重复造轮子,除非当你看过AQS的源码后认为你可以写得比Doug Lea更好。

八、对象作用域

尽可能缩小对象的作用域,即生命周期。

如果可以在方法内声明的局部变量,就不要声明为实例变量。

除非你的对象是单例的或不变的,否则尽可能少地声明static变量。

九、各类引用

java.lang.ref.Reference有几个子类,用于处理和GC相关的引用。JVM的引用类型简单来说有几种:

  • Strong Reference,最常见的引用
  • Weak Reference,当没有指向它的强引用时会被GC回收
  • Soft Reference,只当临近OOM时才会被GC回收
  • Phantom Reference,主要用于识别对象被GC的时机,通常用于做一些清理工作

当你需要实现一个缓存时,可以考虑优先使用 WeakHashMap,而不是 HashMap,当然,更好的选择是使用框架,例如Guava Cache。

最后,再次提醒,以上的这些未必可以对代码有多少性能上的提升,但是熟悉这些方法,是为了帮助我们写出更卓越的代码,和GC更好地合作。



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


ITeye推荐



代码整洁之道

$
0
0

代码质量和整洁度成正比

 

有意义的命名,原则:

名副其实(用注解来补充的命名不是名副其实);

避免误导,避免使用与本意相悖的词汇;

做有意义的区分:Variable永远不要出现在变量中,Table永远不要出现在表中,废话是冗余的;

使用读得出来的名称;

使用可搜索的名称(单字母和数字常量很难搜索,exception的e也不好搜索);

单字母名称仅用于短方法的本地变量,名称长度应与其作用域大小相对应;

避免使用编码;

不必使用m_成员前缀来表明是成员变量;

接口的I前缀不如实现的imp后缀;

避免思维映射:不应当让读者把你的名称理解为他们熟知的内容;

类名和对象名应该是名词或名词短语,不应该是动词;

方法名应该是动词或动词短语;

每个概念对应一个词;

别用双关语:同一单词用于不同目的;同一术语用于不同概念;

使用解决方案领域名词;

使用领域术语;

添加有意义的语境;

 

一言以蔽之:取名最难的地方在于需要良好的描述技巧和工有的文化背景。

 

函数

第一原则是函数要短小;第二条原则还是更短小。

一个函数只做一件事,并做好这件事(判断是不是做了一件事:看能不能再拆分一个函数出来);

每个函数一个抽象级;

Switch语句:放于接口中,继承类则隐藏该部分,实现函数短小;

函数命名使用描述性的名称;

 

函数参数

最理想的是0参数,尽量少用3个参数以上的;多于的话,要考虑封装成类;

使用异常代替错误返回码;

抽离try catch块,将try中的逻辑封装成函数;

 

注释

注释存在的时间越久,就离其描述的代码越远,越累越变得全然错误,原因在于,程序员不能坚持维护注释

 

注释不能美化糟糕的代码;

唯一真正好的注释是不去写注释;

注释可以用于放大某种不合理的事物的重要性;

 

坏注释:

喃喃自语:如果决定要写注释就要写好注释;

误导性注释

错误注释

日志式注释:记录代码的修改——冗长的记录只会让模块变得凌乱不堪,删掉

 

能用函数或变量时就别用注释

 

归属和署名不必放在代码中,代码管理工具是这些信息的归属地

直接把代码注释掉是讨厌的做法

HTML注释不要存在于代码中;

非本地注释:注释内容与被注释代码脱离上下文关系;

 

短函数的函数头注释不如起个好的函数名字;

 

格式

代码格式关乎沟通,沟通是专业开发者的头等大事

 

纵向格式

尽可能用200行,不超过500行的代码文件

 

变量应该尽可能靠近其使用位置;

实体变量在类顶部声明;

相关函数:调用者放在被调用方法的上部;

概念相关:概念相关性强的代码放在一起;

 

横向格式

代码行尽量短小

方法名和左括号不必加空格,参数一一隔开;

 

 

对象和数据结构

对象把数据藏于抽象之后,暴露操作数据的函数;数据结构暴露数据;

 

对象和数据结构的二分原理:

过程式代码(使用数据结构)在于不改变既有数据结构的前提下增加新函数,面向对象的代码便于在不改变既有函数的前提下增加新类.

反之,过程式代码难以添加新的数据结构,因此必须修改所有函数.面向对象代码难以新函数,因为要修改所有类.

 

数据传送对象:DTO,只有公共变量,没有函数

 

错误处理

使用异常而非返回码

别返回null值,别传递null值

 

边界

使用第三方代码

 

类要短小:单一全责原则

内聚

 

系统

将系统的构造和使用分开

 

迭代

通过迭代设计达到整洁的目的

 

 

 



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


ITeye推荐



firefox/ie下载百度网盘大文件/linux,wget下载百度网盘大文件

$
0
0
1.登录后类似这个网址http://pan.baidu.com/disk/home?adapt=pc
2.修改为http://pan.baidu.com/wap/home?adapt=pc
3.再次点击下载按钮
4.真正下载后点击下载项任务列表/下载进度列表
5.复制 下载链接地址用wget就可以用了如:wget -c -O 168uplpad.rar "http://nj.baidupcs.com/file/bc80bc736a92168e9c44b2aee3b8ebdd?fid=2736868083-25550528-940471921325430&time=1405815199&sign=FDTAXER-DCb740ccc5511e5e8fedcff06b081203-tjedf5J9XSti%2Fnq3%2FgqbMGqhnHo%3D&to=nb&fm=N,B,T,c&newver=1&expires=8h&rt=pr&r=215292176&mlogid=828725913&vuk=2736868083&vbdid=148810357598" &


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


ITeye推荐



谈正确理解 CAP 理论[转自网络]

$
0
0

转载自:http://www.douban.com/group/topic/11765014/

CAP 理论在搞分布式的程序员中已经是路人皆知了。但是 CAP 理论就好比是相对论,虽然所有的人都知道,但是却没有多少人真正理解。 
要真正理解 CAP 理论必须要读懂它的形式化描述。 形式化描述中最重要的莫过于对 Consistency, Availability, Partition-tolerance 的准确定义。 

Consistency (一致性) 实际上等同于系统领域的 before-or-after atomicity 这个术语,或者等同于 linearizable (可串行化) 这个术语。具体来说,系统中对一个数据的读和写虽然包含多个子步骤并且会持续一段时间才能执行完,但是在调用者看来,读操作和写操作都必须是单个的即时完成的操作,不存在重叠。对一个写操作,如果系统返回了成功,那么之后到达的读请求都必须读到这个新的数据;如果系统返回失败,那么所有的读,无论是之后发起的,还是和写同时发起的,都不能读到这个数据。 

要说清楚 Availability 和 Partition-tolerance 必须要定义好系统的故障模型。在形式化证明中,系统包含多个节点,每个节点可以接收读和写的请求,返回成功或失败,对读还要返回一个数据。和调用者之间的连接是不会中断的,系统的节点也不会失效,唯一的故障就是报文的丢失。 Partition-tolerance 指系统中会任意的丢失报文(这和“最终会有一个报文会到达”是相对的)。 Availability 是指所有的读和写都必须要能终止。 

注: “Availability 是指所有的读和写都必须要能终止” 这句话听上去很奇怪,为什么不是“Availability 是指所有的写和读都必须成功”? 要回答这个问题,我们可以仔细思考下“什么是成功”。“成功”必须要相对于某个参照而言,这里的参照就是 Consistency。 

CAP 理论说在一个系统中对某个数据不存在一个算法同时满足 Consistency, Availability, Partition-tolerance 。 注意,这里边最重要和最容易被人忽视的是限定词“对某个数据不存在一个算法”。这就是说在一个系统中,可以对某些数据做到 CP, 对另一些数据做到 AP,就算是对同一个数据,调用者可以指定不同的算法,某些算法可以做到 CP,某些算法可以做到 AP。 

要做到 CP, 系统可以把这个数据只放在一个节点上,其他节点收到请求后向这个节点读或写数据,并返回结果。很显然,串行化是保证的。但是如果报文可以任意丢失的话,接受请求的节点就可能永远不返回结果。 

要做到 CA, 一个现实的例子就是单点的数据库。你可能会疑惑“数据库也不是 100% 可用的呀?” 要回答这个疑惑,注意上面说的故障模型和 availability 的定义就可以了。 

要做到 AP, 系统只要每次对写都返回成功,对读都返回固定的某个值就可以了。 

如果我们到这里就觉得已近掌握好 CAP 理论了,那么就相当于刚把橘子剥开,就把它扔了。 

CAP 理论更重要的一个结果是, 在 Partial Synchronous System (半同步系统) 中,一个弱化的 CAP 是能达到的: 

* 对所有的数据访问,总返回一个结果 
* 如果期间没有报文丢失,那么返回一个满足 consistency 要求的结果。 

这里的半同步系统指每个节点存在一个时钟,这些时钟不需要同步,但是按照相同的速率流逝。更通俗的来说,就是一个能够实现超时机制的系统。 

举个例子,系统可以把这个数据只放在一个节点上,其他节点收到请求后向这个节点读或写数据,并设置一个定时器,如果超时前得到结果,那么返回这个结果,否则返回失败。 

更进一步的,也是最重要的,实现一个满足最终一致性 (Eventually Consistency) 和 AP 的系统是可行的。 现实中的一个例子是 Cassandra 系统。

 

(End)

-------------------------------------------------

网上的另一篇文章:

http://blog.csdn.net/zhaoyp1985/article/details/7880547 CAP理论  (提到A CAP Solution)



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


ITeye推荐




Apache kafka原理与特性(转)

$
0
0

 转自:http://shift-alt-ctrl.iteye.com/blog/1930345

 

前言: kafka是一个轻量级的/分布式的/具备replication能力的日志采集组件,通常被集成到应用系统中,收集"用户行为日志"等,并可以使用各种消费终端(consumer)将消息转存到HDFS等其他结构化数据存储系统中.因为日志消息通常为文本数据,尺寸较小,且对实时性以及数据可靠性要求不严格,但是需要日志存储端具备较高的数据吞吐能力,这种"宽松"的设计要求,非常适合使用kafka. 

一.入门

     1.1 简介

    Kafka是一个"分布式的"/"可分区的(partitioned)"/"基于备份的(replicated)"/"基于commit-log存储"的服务. 它提供了类似于JMS的特性,但是在设计实现上完全不同,此外它并不是JMS规范的实现.

    kafka消息是根据Topic进行归类,发送消息者成为Producer,消息接收者成为Consumer;此外kafka集群有多个kafka实例组成,每个实例(server)称为broker.

    无论是kafka集群,还是producer和consumer都依赖于zookeeper来保证系统可用性以及保存一些meta信息.

 

(摘自官网) 

    其中client与server的通讯,都是基于TCP,而且消息协议非常轻量级.

     Topics/logs

    一个Topic可以认为是一类消息,每个topic将被分成多个partition(区),每个partition在存储层面是append log文件.任何发布到此partition的消息都会直接追加到log文件的尾部,每条消息在文件中的位置称为offset(偏移量),offset为一个long型数字,它唯一的标记一条消息.kafka并没有提供其他额外的索引机制来存储offset,因为在kafka中几乎不允许对消息进行"随机读-写",一旦消息写入log日志之后,将不能被修改.



(摘自官网) 

    kafka和JMS实现(activeMQ)不同的是:即使消息被消费,消息仍然不会被立即删除.日志文件将会根据broker中的配置要求,保留一定的时间之后删除;比如log文件保留2天,那么两天后,文件会被清除,无论其中的消息是否被消费.kafka通过这种简单的手段,来释放磁盘空间.此外,kafka的性能并不会因为日志文件的太多而低下,所以即使保留较多的log文件,也不不会有问题.

    对于consumer而言,它需要保存消费消息的offset,对于offset的保存和使用,有consumer来控制;当consumer正常消费消息时,offset将会"线性"的向前驱动,即消息将依次顺序被消费.事实上consumer可以使用任意顺序消费消息,它只需要将offset重置为任意值..(offset将会保存在zookeeper中,参见下文)

    kafka集群几乎不需要维护任何consumer和producer状态信息,这些信息有zookeeper保存;因此producer和consumer的客户端实现非常轻量级,它们可以随意离开,而不会对集群造成额外的影响.

    partitions的设计目的有多个.最根本原因是kafka基于文件存储.通过分区,可以将日志内容分散到多个server上,来避免文件尺寸达到单机磁盘的上限,每个partiton都会被当前server(kafka实例)保存;可以将一个topic切分多任意多个partitions(备注:基于sharding),来消息保存/消费的效率.此外越多的partitions意味着可以容纳更多的consumer,有效提升并发消费的能力.(具体原理参见下文).

     Distribution

    一个Topic的多个partitions,被分布在kafka集群中的多个server上;每个server(kafka实例)负责partitions中消息的读写操作;此外kafka还可以配置每个partition需要备份的个数(replicas),每个partition将会被备份到多台机器上,以提高可用性.[replicas特性在0.8V才支持]

    基于replicated方案,那么就意味着需要对多个备份进行调度;一个partition可以在多个server上备份,那么其中一个server作为此partiton的leader;leader负责此partition所有的读写操作,如果leader失效,那么将会有其他follower来接管(成为新的leader);follower只是单调的和leader跟进,同步消息即可..由此可见作为leader的server承载了全部的请求压力,因此从集群的整体考虑,有多少个partitions就意味着有多少个"leader",kafka会将"leader"均衡的分散在每个实例上,来确保整体的性能稳定.[备注:kafka中将leader角色权限下放到partition这个层级]

 

kafka-cluster 

     Producers

    Producer将消息发布到指定的Topic中,同时Producer也能决定将此消息发送到哪个partition;如果一个Topic有多个partitions时,你需要选择partition是算法,比如基于"round-robin"方式或者通过其他的一些算法等.无论如何选择partition路由算法,我们最直接的目的就是希望消息能够均匀的发送给每个partition,这样可以让consumer消费的消息量也能"均衡".

     Consumers

    本质上kafka只支持Topic.每个consumer属于一个consumer group;反过来说,每个group中可以有多个consumer.对于Topic中的一条特定的消息,只会被订阅此Topic的每个group中的一个consumer消费,此消息不会发送给一个group的多个consumer;那么一个group中所有的consumer将会交错的消费整个Topic.

    如果所有的consumer都具有相同的group,这种情况和JMS queue模式很像;消息将会在consumers之间负载均衡.

    如果所有的consumer都具有不同的group,那这就是"发布-订阅";消息将会广播给所有的消费者.



(摘自官网) 

    在kafka中,一个partition中的消息只会被group中的一个consumer消费(同一时刻);每个group中consumer消息消费互相独立;我们可以认为一个group是一个"订阅"者,一个Topic中的每个partions,只会被一个"订阅者"中的一个consumer消费,不过一个consumer可以同时消费多个partitions中的消息.kafka只能保证一个partition中的消息被某个consumer消费时是顺序的.事实上,从Topic角度来说,当有多个partitions时,消息仍不是全局有序的.

    通常情况下,一个group中会包含多个consumer,这样不仅可以提高topic中消息的并发消费能力,而且还能提高"故障容错"性,如果group中的某个consumer失效,那么其消费的partitions将会有其他consumer自动接管.

    kafka的设计原理决定,对于一个topic,同一个group中不能有多于partitions个数的consumer同时消费,否则将意味着某些consumer将无法得到消息.

     Guarantees

    1) 发送到partitions中的消息将会按照它接收的顺序追加到日志中,无论一个partition由多少个log文件构成,那么它发送给consumer的顺序是一定的.

    2) 对于消费者而言,它们消费消息的顺序和日志中消息顺序一致.

    3) 如果Topic的"replication factor"为N,那么允许N-1个kafka实例失效.只要有一个replication存活,那么此partition的读写操作都不会中断.

 

    1.2 Use cases

     Messaging

    和一些常规的消息系统相比,kafka仍然是个不错的选择;它具备partitons/replication和容错,可以使kafka具有良好的扩展性和性能优势.不过到目前为止,我们应该很清楚认识到,kafka并没有提供JMS中的"事务性""消息传输担保(消息确认机制)""消息分组"等企业级特性;kafka只能使用作为"常规"的消息系统,在一定程度上,尚未确保消息的发送与接收绝对可靠(比如,消息重发,消息发送丢失等)

     Websit activity tracking

    kafka可以作为"网站活性跟踪"的最佳工具;可以将网页/用户操作等信息发送到kafka中.并实时监控,或者离线统计分析等.

     Log Aggregation

    kafka的特性决定它非常适合作为"日志收集中心";application可以将操作日志"批量""异步"的发送到kafka集群中,而不是保存在本地或者DB中;kafka可以批量提交消息/压缩消息等,这对producer端而言,几乎感觉不到性能的开支.此时consumer端可以使hadoop等其他系统化的存储和分析系统.

 

二. 设计原理

    kafka的设计初衷是希望做为一个统一的信息收集平台,能够实时的收集反馈信息,并需要能够支撑较大的数据量,且具备良好的容错能力.

     1.Persistence

    kafka使用文件存储消息(append only log),这就直接决定kafka在性能上严重依赖文件系统的本身特性.且无论任何OS下,对文件系统本身的优化是非常艰难的.文件缓存/直接内存映射等是常用的手段.因为kafka是对日志文件进行append操作,因此磁盘检索的开支是较小的;同时为了减少磁盘写入的次数,broker会将消息暂时buffer起来,当消息的个数(或尺寸)达到一定阀值时,再flush到磁盘,这样减少了磁盘IO调用的次数.对于kafka而言,较高性能的磁盘,将会带来更加直接的性能提升.

     2.Efficiency

    需要考虑的影响性能点很多,除磁盘IO之外,我们还需要考虑网络IO,这直接关系到kafka的吞吐量问题.kafka并没有提供太多高超的技巧;对于producer端,可以将消息buffer起来,当消息的条数达到一定阀值时,批量发送给broker;对于consumer端也是一样,批量fetch多条消息.不过消息量的大小可以通过配置文件来指定.对于kafka broker端,似乎有个sendfile系统调用可以潜在的提升网络IO的性能:将文件的数据映射到系统内存中,socket直接读取相应的内存区域即可,而无需进程再次copy和交换(这里涉及到"磁盘IO数据"/"内核内存"/"进程内存"/"网络缓冲区",多者之间的数据copy).

 

    其实对于producer/consumer/broker三者而言,CPU的开支应该都不大,因此启用消息压缩机制是一个良好的策略;压缩需要消耗少量的CPU资源,不过对于kafka而言,网络IO更应该需要考虑.可以将任何在网络上传输的消息都经过压缩.kafka支持gzip/snappy等多种压缩方式.

     3. Producer

     Load balancing

    kafka集群中的任何一个broker,都可以向producer提供metadata信息,这些metadata中包含"集群中存活的servers列表"/"partitions leader列表"等信息(请参看zookeeper中的节点信息). 当producer获取到metadata信心之后, producer将会和Topic下所有partition leader保持socket连接;消息由producer直接通过socket发送到broker,中间不会经过任何"路由层".事实上,消息被路由到哪个partition上,有producer客户端决定.比如可以采用"random""key-hash""轮询"等,如果一个topic中有多个partitions,那么在producer端实现"消息均衡分发"是必要的.在producer端的配置文件中,开发者可以指定partition路由的方式.

 

     Asynchronous send

    将多条消息暂且在客户端buffer起来,并将他们批量发送到broker;小数据IO太多,会拖慢整体的网络延迟,批量延迟发送事实上提升了网络效率;不过这也有一定的隐患,比如当producer失效时,那些尚未发送的消息将会丢失.

     4.Consumer

    consumer端向broker发送"fetch"请求,并告知其获取消息的offset;此后consumer将会获得一定条数的消息;consumer端也可以重置offset来重新消费消息.[备注:offset,消息偏移量,integer值,broker可以根据offset来决定消息的起始位置]

    在JMS实现中,Topic模型基于push方式,即broker将消息推送给consumer端.不过在kafka中,采用了pull方式,即consumer在和broker建立连接之后,主动去pull(或者说fetch)消息;这中模式有些优点,首先consumer端可以根据自己的消费能力适时的去fetch消息并处理,且可以控制消息消费的进度(offset);此外,消费者可以良好的控制消息消费的数量,batch fetch.

    其他JMS实现,消息消费的位置是有prodiver保留,以便避免重复发送消息或者将没有消费成功的消息重发等,同时还要控制消息的状态.这就要求JMS broker需要太多额外的工作.在kafka中,partition中的消息只有一个consumer在消费,且不存在消息状态的控制,也没有复杂的消息确认机制,可见kafka broker端是相当轻量级的.当消息被consumer接收之后,consumer可以在本地保存最后消息的offset,并间歇性的向zookeeper注册offset.由此可见,consumer客户端也很轻量级.

    这就意味着,kafka中consumer负责维护消息的消费记录,而broker则不关心这些,这种设计不仅提高了consumer端的灵活性,也适度的减轻了broker端设计的复杂度;这是和众多JMS prodiver的区别.此外,kafka中消息ACK的设计也和JMS有很大不同,kafka中的消息时批量(通常以消息的条数或者chunk的尺寸为单位)发送给consumer,当消息消费成功后,向zookeeper提交消息的offset,而不会向broker交付ACK.或许你已经意识到,这种"宽松"的设计,将会有"丢失"消息/"消息重发"的危险.

 

     5.Message Delivery Semantics

    对于JMS实现,消息传输担保非常直接:有且只有一次(exactly once).在kafka中稍有不同,对于consumer而言:

    1) at most once: 最多一次,这个和JMS中"非持久化"消息类似.发送一次,无论成败,将不会重发.

    2) at least once: 消息至少发送一次,如果消息未能接受成功,可能会重发,直到接收成功.

    3) exactly once: 消息只会发送一次.

    at most once: 消费者fetch消息,然后保存offset,然后处理消息;当client保存offset之后,但是在消息处理过程中consumer进程失效(crash),导致部分消息未能继续处理.那么此后可能其他consumer会接管,但是因为offset已经提前保存,那么新的consumer将不能fetch到offset之前的消息(尽管它们尚没有被处理),这就是"at most once".

    at least once: 消费者fetch消息,然后处理消息,然后保存offset.如果消息处理成功之后,但是在保存offset阶段zookeeper异常或者consumer失效,导致保存offset操作未能执行成功,这就导致接下来再次fetch时可能获得上次已经处理过的消息,这就是"at least once".

    exactly once: kafka中并没有严格的去实现(基于2阶段提交,事务),我们认为这种策略在kafka中是没有必要的.

    因为"消息消费"和"保存offset"这两个操作的先后时机不同,导致了上述3种情况,通常情况下"at-least-once"是我们搜选.(相比at most once而言,重复接收数据总比丢失数据要好).



 

     6. Replication

    kafka中,replication策略是基于partition,而不是topic;kafka将每个partition数据复制到多个server上,任何一个partition有一个leader和多个follower(可以没有);备份的个数可以通过broker配置文件来设定.leader处理所有的read-write请求,follower需要和leader保持同步.Follower就像一个"consumer",消费消息并保存在本地日志中;leader负责跟踪所有的follower状态,如果follower"落后"太多或者失效,leader将会把它从replicas同步列表中删除.当所有的follower都将一条消息保存成功,此消息才被认为是"committed",那么此时consumer才能消费它,这种同步策略,就要求follower和leader之间必须具有良好的网络环境.即使只有一个replicas实例存活,仍然可以保证消息的正常发送和接收,只要zookeeper集群存活即可.(备注:不同于其他分布式存储,比如hbase需要"多数派"存活才行)

    kafka判定一个follower存活与否的条件有2个:1) follower需要和zookeeper保持良好的链接 2) 它必须能够及时的跟进leader,不能落后太多.如果同时满足上述2个条件,那么leader就认为此follower是"活跃的".如果一个follower失效(server失效)或者落后太多,leader将会把它从同步列表中移除[备注:如果此replicas落后太多,它将会继续从leader中fetch数据,直到足够up-to-date,然后再次加入到同步列表中;kafka不会更换replicas宿主!因为"同步列表"中replicas需要足够快,这样才能保证producer发布消息时接受到ACK的延迟较小].

    当leader失效时,需在followers中选取出新的leader,可能此时follower落后于leader,因此需要选择一个"up-to-date"的follower.kafka中leader选举并没有采用"投票多数派"的算法,因为这种算法对于"网络稳定性"/"投票参与者数量"等条件有较高的要求,而且kafka集群的设计,还需要容忍N-1个replicas失效.对于kafka而言,每个partition中所有的replicas信息都可以在zookeeper中获得,那么选举leader将是一件非常简单的事情.选择follower时需要兼顾一个问题,就是新leader server上所已经承载的partition leader的个数,如果一个server上有过多的partition leader,意味着此server将承受着更多的IO压力.在选举新leader,需要考虑到"负载均衡",partition leader较少的broker将会更有可能成为新的leader.

    在整几个集群中,只要有一个replicas存活,那么此partition都可以继续接受读写操作.

     7.Log

    如果一个topic的名称为"my_topic",它有2个partitions,那么日志将会保存在my_topic_0和my_topic_1两个目录中;日志文件中保存了一序列"log entries"(日志条目),每个log entry格式为"4个字节的数字N表示消息的长度" + "N个字节的消息内容";每个日志都有一个offset来唯一的标记一条消息,offset的值为8个字节的数字,表示此消息在此partition中所处的起始位置..每个partition在物理存储层面,有多个log file组成(称为segment).segment file的命名为"最小offset".kafka.例如"00000000000.kafka";其中"最小offset"表示此segment中起始消息的offset.



(摘自官网) 

    其中每个partiton中所持有的segments列表信息会存储在zookeeper中.

    当segment文件尺寸达到一定阀值时(可以通过配置文件设定,默认1G),将会创建一个新的文件;当buffer中消息的条数达到阀值时将会触发日志信息flush到日志文件中,同时如果"距离最近一次flush的时间差"达到阀值时,也会触发flush到日志文件.如果broker失效,极有可能会丢失那些尚未flush到文件的消息.因为server意外失效,仍然会导致log文件格式的破坏(文件尾部),那么就要求当server启东是需要检测最后一个segment的文件结构是否合法并进行必要的修复.

    获取消息时,需要指定offset和最大chunk尺寸,offset用来表示消息的起始位置,chunk size用来表示最大获取消息的总长度(间接的表示消息的条数).根据offset,可以找到此消息所在segment文件,然后根据segment的最小offset取差值,得到它在file中的相对位置,直接读取输出即可.

    日志文件的删除策略非常简单:启动一个后台线程定期扫描log file列表,把保存时间超过阀值的文件直接删除(根据文件的创建时间).为了避免删除文件时仍然有read操作(consumer消费),采取copy-on-write方式.

     8.Distribution

    kafka使用zookeeper来存储一些meta信息,并使用了zookeeper watch机制来发现meta信息的变更并作出相应的动作(比如consumer失效,触发负载均衡等)

     1) Broker node registry: 当一个kafka broker启动后,首先会向zookeeper注册自己的节点信息(临时znode),同时当broker和zookeeper断开连接时,此znode也会被删除.

    格式: /broker/ids/[0...N]   -->host:port;其中[0..N]表示broker id,每个broker的配置文件中都需要指定一个数字类型的id(全局不可重复),znode的值为此broker的host:port信息.

     2) Broker Topic Registry: 当一个broker启动时,会向zookeeper注册自己持有的topic和partitions信息,仍然是一个临时znode.

    格式: /broker/topics/[topic]/[0...N]  其中[0..N]表示partition索引号.

     3) Consumer and Consumer group: 每个consumer客户端被创建时,会向zookeeper注册自己的信息;此作用主要是为了"负载均衡".

    一个group中的多个consumer可以交错的消费一个topic的所有partitions;简而言之,保证此topic的所有partitions都能被此group所消费,且消费时为了性能考虑,让partition相对均衡的分散到每个consumer上.

     4) Consumer id Registry: 每个consumer都有一个唯一的ID(host:uuid,可以通过配置文件指定,也可以由系统生成),此id用来标记消费者信息.

    格式: /consumers/[group_id]/ids/[consumer_id]

    仍然是一个临时的znode,此节点的值为{"topic_name":#streams...},即表示此consumer目前所消费的topic + partitions列表.

     5) Consumer offset Tracking: 用来跟踪每个consumer目前所消费的partition中最大的offset.

    格式: /consumers/[group_id]/offsets/[topic]/[broker_id-partition_id]   -->offset_value

    此znode为持久节点,可以看出offset跟group_id有关,以表明当group中一个消费者失效,其他consumer可以继续消费.

     6) Partition Owner registry: 用来标记partition正在被哪个consumer消费.临时znode

    格式: /consumers/[group_id]/owners/[topic]/[broker_id-partition_id]   -->consumer_node_id

    此节点表达了"一个partition"只能被group下一个consumer消费,同时当group下某个consumer失效,那么将会触发负载均衡(即:让partitions在多个consumer间均衡消费,接管那些"游离"的partitions)

 

    当consumer启动时,所触发的操作:

    A) 首先进行"Consumer id Registry";

    B) 然后在"Consumer id Registry"节点下注册一个watch用来监听当前group中其他consumer的"leave"和"join";只要此znode path下节点列表变更,都会触发此group下consumer的负载均衡.(比如一个consumer失效,那么其他consumer接管partitions).

    C) 在"Broker id registry"节点下,注册一个watch用来监听broker的存活情况;如果broker列表变更,将会触发所有的groups下的consumer重新balance.

 

     Consumer均衡算法

    当一个group中,有consumer加入或者离开时,会触发partitions均衡.均衡的最终目的,是提升topic的并发消费能力.

     1) 假如topic1,具有如下partitions: P0,P1,P2,P3

     2) 加入group中,有如下consumer: C0,C1

     3) 首先根据partition索引号对partitions排序: P0,P1,P2,P3

     4) 根据consumer.id排序: C0,C1

     5) 计算倍数: M = [P0,P1,P2,P3].size / [C0,C1].size,本例值M=2(向上取整)

     6) 然后依次分配partitions: C0 = [P0,P1],C1=[P2,P3],即Ci = [P(i * M),P((i + 1) * M -1)]



     总结: 

    1) Producer端使用zookeeper用来"发现"broker列表,以及和Topic下每个partition leader建立socket连接并发送消息.

    2) Broker端使用zookeeper用来注册broker信息,已经监测partition leader存活性.

    3) Consumer端使用zookeeper用来注册consumer信息,其中包括consumer消费的partition列表等,同时也用来发现broker列表,并和partition leader建立socket连接,并获取消息.



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


ITeye推荐



Android木马分析简介

$
0
0

本文介绍基于Android的手机恶意软件,是一个基础性的介绍,给新入门的人提供一个分析和工具指引。要分析的木马是一个2013年的syssecApp.apk,这个木马的分析能对Android恶意软件有个大概了解。

基础:

1 –Android应用基础

Android是google开发基于Linux内核的开源的手机操作系统,应用程序使用JAVA语言编写并转换成了Dalvik虚拟机,而虚拟机则提供了一个抽象的真实硬件,只要和操作系统的API符合程序都可以在其上运行。应用则需要Linux的用户和组来执行,所以目前所有的恶意软件都需要获得权限。

Android应用的格式是APK,是一种包含AndroidManifest.xml的 ZIP文件,媒体类文件实际代码是classes.dex和一些其他的可选文件。XML提供Android系统的重要信息,比如用启动应用程序时需要什么权限,只有这个文件中列出的权限才提供给该应用,否则返回失败或空结果。classes.dex是Android应用程序实现的逻辑部分,是一个编译代码可由Dalvik虚拟机执行,打包成jar,从而节约移动设备上的一些空间。

2 –分析工具

2.1Dexter

Dexter可以将Android应用上传做分析,提供了包和应用元数据的介绍。包的依赖关系图显示了所有包的关系,可以快速打开列表显示所有的class和功能。

2.2Anubis

Anubis也是一个WEB服务,应用在沙箱里运行,每个样品相互独立,来分析文件和网络的活动。同时也提供一些静态分析,包括权限XML在调用过程中的变化。

2.3 APKInspector

Apkinspector提供了很多工具,APK加载后可以选择标签来执行其中的功能,带有一个Java反编译器JAD,能够反编译大多数类,但经常报错。

2.4 Dex2Jar

可将dex 文件转成 Java 类文件的工具,即使你是经验丰富的逆向工程师,也可以考虑使用。

3 – 实例分析

3.1 Anubis

Anubis的显著特点是,给出了应用所需权限的大名单:

14055236368853 (1)

 

截图上包括了应用的部分权限。INTERNET权限是常见的游戏所需,用来在线统计跟踪,开启共享功能或者广告。还有一些WAKE_LOCK、READ_PHONE_STATE用来读取手机状态,防止在游戏中锁屏。但READ_CONTACTS、    READ_HISTORY_BOOKMARKS则看起来就很奇怪,不像是一个游戏该干的事情。对127.0.0.1:53471的连接看起来也很奇怪。分析链接:http://anubis.iseclab.org/?action=result&task_id=1a6d8d21d7b0c1a04edb2c7c3422be72f&format=html

14055236439548 (1)

 

3.2 Dexter

包的依赖关系图显示共有四个。可以忽视de.rub.syssec,它只包含空类的默认构造函数。

14055236449074 (1)

 

de.rub.syssec包括了一个叫做Amazed的游戏,比较特别的是amazedactiviy的onCreate方法,设置为每隔15秒重复闹钟。

1405523647992 (1)

 

第3个class包含的事件比较多。onBoot在启动的时候就会进行闹铃,SmsReceiver和alarmReceiver则是真正的木马,在任何一个短信到达的时候SmsReceiver会检查里面是否包含有”bank”,如果是则使用abortBroadcast丢弃短信。

1405523650878 (1)

 

14055236529703

 

这意味着短信在手机上是看不到的。de.rub.syssec.neu有6个CLASS,最重要的一条是“Runner”,是实际的恶意代码。“work”调用alarmReceiver来检查设备是否连接互联网。

1405523657843

 

如果在线,则调用“steal()”收集信息,添加到XML帮助的一个伪变量里。

14055236594440

 

14055236637813

 

根据API的调用列表,会收集信息:IMSI、SIM卡序列号、姓名、设备ID、用户字典(自动补全)、联系人、通话记录、日历、浏览器搜索记录、浏览器收藏夹、发送和接收的短信、位置信息。

3.3 Emulator

Emulator证实这个APK确实有一个关于迷宫的游戏。但在输出的日志里可以发现它其实做了很多事情,并试图发送这些内容:

14055236669821

 

14055236682505

 

还有一些额外的信息包括安卓版本、IMEI、本地时间、steal()运行总量

3.3 分析用到的网站

http://anubis.iseclab.org/

http://dexter.dexlabs.org/

https://www.virustotal.com/

http://www.apk-analyzer.net/

http://www.visualthreat.com/

http://androidsandbox.net/reports.html

https://hackapp.com/

游戏不仅仅是个游戏,检查你的游戏。

Android木马分析简介,首发于 极客范 - GeekFan.net

js打印局部内容

$
0
0
<script language="javascript">  
function printdiv(printpage)  
{  
var headstr = "<html><head><title></title></head><body>";  
var footstr = "</body>";  
var printData = document.getElementById("dvData").innerHTML; 获得 div 里的所有 html 数据
var oldstr = document.body.innerHTML;  
document.body.innerHTML = headstr+newstr+footstr;  
window.print();  
document.body.innerHTML = oldstr;  
return false;  
}  

 



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


ITeye推荐



Android内存管理之道

$
0
0

相信一步步走过来的Android从业者,每个人都会遇到OOM的情况。如何避免和防范OOM的出现,对于每一个程序员来说确实是一门必不可少的能力。今天我们就谈谈在Android平台下内存的管理之道,开始今天的主题之前,先再次回顾两个概念。


内存泄漏:对象在内存heap堆中中分配的空间,当不再使用或没有引用指向的情况下,仍不能被GC正常回收的情况。多数出现在不合理的编码情况下,比如在Activity中注册了一个广播接收器,但是在页面关闭的时候进行unRegister,就会出现内存溢出的现象。通常情况下,大量的内存泄漏会造成OOM。


OOM:即OutOfMemoery,顾名思义就是指内存溢出了。内存溢出是指APP向系统申请超过最大阀值的内存请求,系统不会再分配多余的空间,就会造成OOM error。在我们Android平台下,多数情况是出现在图片不当处理加载的时候。


内存管理之道嘛,无非就是先理解并找出内存泄漏的原因,再基于这些反式去合理的编码,去防范进而避免内存开销过大的情形。学习如何合理的管理内存,最好先了解内存分配的机制和原理。只有深层次的理解了内部的原理,才能真正避免OOM的发生。但是本文就不介绍Jvm/Davilk内存分配的机制了,如有兴趣,请查看历史消息,以前做过题为《JVM运行时数据区域分析》的分享。


Android APP的所能申请的最大内存大小是多少,有人说是16MB,有人又说是24MB。这种事情,还是亲自用自己的手机测试下比较靠谱。测试方式也比较简单,Java中有个Runtime类,主要用作APP与运行环境交互,APP并不会为我们创建Runtime的实例,但是Java为我们提供了单例获取的方式Runtime.getRuntime()。通过maxMemory()方法获取系统可为APP分配的最大内存,totalMemory()获取APP当前所分配的内存heap空间大小。我手上有两部手机,一部Oppo find7,运行Color OS,实测最大内存分配为192MB;一部天语v9,运行小米系统,实测最大内存分配为100MB。这下看出点眉目了吧,由于Android是开源系统,不同的手机厂商其实是拥有修改这部分权限能力的,所以就造成了不同品牌和不同系统的手机,对于APP的内存支持也是不一样的,和IOS的恒久100MB是不同的。一般来说,手机内存的配置越高,厂商也会调大手机支持的内存最大阀值,尤其是现在旗舰机满天发布的情况下。但是开发者为了考虑开发出的APP的内存兼容性,无法保证APP运行在何种手机上,只能从编码角度来优化内存了。

下面我们逐条来分析Android内存优化的关键点。

1、万恶的static

static是个好东西,声明赋值调用就是那么的简单方便,但是伴随而来的还有性能问题。由于static声明变量的生命周期其实是和APP的生命周期一样的,有点类似与Application。如果大量的使用的话,就会占据内存空间不释放,积少成多也会造成内存的不断开销,直至挂掉。static的合理使用一般用来修饰基本数据类型或者轻量级对象,尽量避免修复集合或者大对象,常用作修饰全局配置项、工具类方法、内部类。

2、无关引用

很多情况下,我们需求用到传递引用,但是我们无法确保引用传递出去后能否及时的回收。比如比较有代表性的Context泄漏,很多情况下当Activity 结束掉后,由于仍被其他的对象指向导致一直迟迟不能回收,这就造成了内存泄漏。这时可以考虑第三条建议。

3、善用SoftReference/WeakReference/LruCache

Java、Android中有没有这样一种机制呢,当内存吃紧或者GC扫过的情况下,就能及时把一些内存占用给释放掉,从而分配给需要分配的地方。答案是肯定的,java为我们提供了两个解决方案。如果对内存的开销比较关注的APP,可以考虑使用WeakReference,当GC回收扫过这块内存区域时就会回收;如果不是那么关注的话,可以使用SoftReference,它会在内存申请不足的情况下自动释放,同样也能解决OOM问题。同时Android自3.0以后也推出了LruCache类,使用LRU算法就释放内存,一样的能解决OOM,如果兼容3.0一下的版本,请导入v4包。关于第二条的无关引用的问题,我们传参可以考虑使用WeakReference包装一下。

4、谨慎handler

在处理异步操作的时候,handler + thread是个不错的选择。但是相信在使用handler的时候,大家都会遇到警告的情形,这个就是lint为开发者的提醒。handler运行于UI线程,不断处理来自MessageQueue的消息,如果handler还有消息需要处理但是Activity页面已经结束的情况下,Activity的引用其实并不会被回收,这就造成了内存泄漏。解决方案,一是在Activity的onDestroy方法中调用

handler.removeCallbacksAndMessages(null);取消所有的消息的处理,包括待处理的消息;二是声明handler的内部类为static。

5、Bitmap终极杀手

Bitmap的不当处理极可能造成OOM,绝大多数情况都是因这个原因出现的。Bitamp位图是Android中当之无愧的胖小子,所以在操作的时候当然是十分的小心了。由于Dalivk并不会主动的去回收,需要开发者在Bitmap不被使用的时候recycle掉。使用的过程中,及时释放是非常重要的。同时如果需求允许,也可以去BItmap进行一定的缩放,通过BitmapFactory.Options的inSampleSize属性进行控制。如果仅仅只想获得Bitmap的属性,其实并不需要根据BItmap的像素去分配内存,只需在解析读取Bmp的时候使用BitmapFactory.Options的inJustDecodeBounds属性。最后建议大家在加载网络图片的时候,使用软引用或者弱引用并进行本地缓存,推荐使用android-universal-imageloader或者xUtils,牛人出品,必属精品。前几天在讲《自定义控件(三)  继承控件》的时候,也整理一个,大家可以去Github下载看看。

6、Cursor及时关闭

在查询SQLite数据库时,会返回一个Cursor,当查询完毕后,及时关闭,这样就可以把查询的结果集及时给回收掉。

7、页面背景和图片加载

在布局和代码中设置背景和图片的时候,如果是纯色,尽量使用color;如果是规则图形,尽量使用shape画图;如果稍微复杂点,可以使用9patch图;如果不能使用9patch的情况下,针对几种主流分辨率的机型进行切图。

8、ListView和GridView的item缓存

对于移动设备,尤其硬件参差不齐的android生态,页面的绘制其实是很耗时的,findViewById也是蛮慢的。所以不重用View,在有列表的时候就尤为显著了,经常会出现滑动很卡的现象。具体参照历史文章《说说ViewHolder的另一种写法》

9、BroadCastReceiver、Service

绑定广播和服务,一定要记得在不需要的时候给解绑。

10、I/O流

I/O流操作完毕,读写结束,记得关闭。

11、线程

线程不再需要继续执行的时候要记得及时关闭,开启线程数量不易过多,一般和自己机器内核数一样最好,推荐开启线程的时候,使用线程池。

12、String/StringBuffer

当有较多的字符创需要拼接的时候,推荐使用StringBuffer。


今天没有代码,纯文字,纯手打,蛮辛苦。整理了这么多优化的策略,相信大家在理解后使用,再也不会遇上OOM了。


如果觉得对你有所帮助,欢迎大家订阅我的微信公众账号——Android干货分享。下面是微信的二维码,为你提供及时高质的Android干货。




作者:lanyeming2012 发表于2014-7-20 23:35:49 原文链接
阅读:58 评论:0 查看评论

Elasticsearch搜索类型(query type)详解

$
0
0
关于我, 邯郸人
对这类话题感兴趣?欢迎发送邮件至 donlianli@126.com
请支持原创http://donlianli.iteye.com/blog/2094305
 
es在查询时,可以指定搜索类型为QUERY_THEN_FETCH,QUERY_AND_FEATCH,DFS_QUERY_THEN_FEATCH和DFS_QUERY_AND_FEATCH。那么这4种搜索类型有什么区别?
 
分布式搜索背景介绍:
ES天生就是为分布式而生,但分布式有分布式的缺点。比如要搜索某个单词,但是数据却分别在5个分片(Shard)上面,这5个分片可能在5台主机上面。因为全文搜索天生就要排序(按照匹配度进行排名),但数据却在5个分片上,如何得到最后正确的排序呢?ES是这样做的,大概分两步。
step1、ES客户端会将这个搜索词同时向5个分片发起搜索请求,这叫Scatter,
step2、这5个分片基于本Shard独立完成搜索,然后将符合条件的结果全部返回,这一步叫Gather。
客户端将返回的结果进行重新排序和排名,最后返回给用户。也就是说,ES的一次搜索,是一次scatter/gather过程(这个跟mapreduce也很类似).
 
然而这其中有两个问题。
第一、数量问题。比如,用户需要搜索"双黄连",要求返回最符合条件的前10条。但在5个分片中,可能都存储着双黄连相关的数据。所以ES会向这5个分片都发出查询请求,并且要求每个分片都返回符合条件的10条记录。当ES得到返回的结果后,进行整体排序,然后取最符合条件的前10条返给用户。这种情况,ES5个shard最多会收到10*5=50条记录,这样返回给用户的结果数量会多于用户请求的数量。
第二、排名问题。上面搜索,每个分片计算分值都是基于自己的分片数据进行计算的。计算分值使用的词频率和其他信息都是基于自己的分片进行的,而ES进行整体排名是基于每个分片计算后的分值进行排序的,这就可能会导致排名不准确的问题。如果我们想更精确的控制排序,应该先将计算排序和排名相关的信息(词频率等)从5个分片收集上来,进行统一计算,然后使用整体的词频率去每个分片进行查询。
 
这两个问题,估计ES也没有什么较好的解决方法,最终把选择的权利交给用户,方法就是在搜索的时候指定query type。
1、query and fetch
向索引的所有分片(shard)都发出查询请求,各分片返回的时候把元素文档(document)和计算后的排名信息一起返回。这种搜索方式是最快的。因为相比下面的几种搜索方式,这种查询方法只需要去shard查询一次。但是各个shard返回的结果的数量之和可能是用户要求的size的n倍。
2、query then fetch(默认的搜索方式)
如果你搜索时,没有指定搜索方式,就是使用的这种搜索方式。这种搜索方式,大概分两个步骤,第一步,先向所有的shard发出请求,各分片只返回排序和排名相关的信息(注意,不包括文档document),然后按照各分片返回的分数进行重新排序和排名,取前size个文档。然后进行第二步,去相关的shard取document。这种方式返回的document与用户要求的size是相等的。
3、DFS query and fetch
这种方式比第一种方式多了一个初始化散发(initial scatter)步骤,有这一步,据说可以更精确控制搜索打分和排名。
4、 DFS query then fetch
比第2种方式多了一个初始化散发(initial scatter)步骤。
 
DSF是什么缩写?初始化散发是一个什么样的过程?
从es的官方网站我们可以指定,初始化散发其实就是在进行真正的查询之前,先把各个分片的词频率和文档频率收集一下,然后进行词搜索的时候,各分片依据全局的词频率和文档频率进行搜索和排名。显然如果使用DFS_QUERY_THEN_FETCH这种查询方式,效率是最低的,因为一个搜索,可能要请求3次分片。但,使用DFS方法,搜索精度应该是最高的。
至于DFS是什么缩写,没有找到相关资料,这个D可能是Distributed,F可能是frequency的缩写,至于S可能是Scatter的缩写,整个单词可能是分布式词频率和文档频率散发的缩写。
总结一下,从性能考虑QUERY_AND_FETCH是最快的,DFS_QUERY_THEN_FETCH是最慢的。从搜索的准确度来说,DFS要比非DFS的准确度更高。


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


ITeye推荐



Mobile Web调试工具Weinre

$
0
0

现在、将来,用移动设备上网越来越成为主流。但对于开发者们来说,移动web的调试一直是个难题,前期可以使用模拟器来协助调试,但到了真机调试阶段就让人非常头痛。而Weinre就是解决这难题的利器。 

  Weinre的本意是Web Inspector Remote,它是一种远程调试工具。功能与Firebug、Webkit inspector类似,可以帮助我们即时更改页面元素、样式,调试JS等,下面就简单介绍下如何使用。下面以以Windows系统为例:

   一、首先确保你的电脑已经搭建好了java环境。即:安装了jdk。这里就不多说了,在网上搜个jdk,一步步安装及ok。

  二、 安装及运行Weinre

    1、下载: http://ishare.iask.sina.com.cn/f/23607399.html  ,这里直接下载jar包,下载好之后放在一个文件夹里就行不需任何处理。

      2、运行cmd,在weinre所在文件夹的 地址栏输入代码:java -jar weinre.jar --httpPort 8081 --boundHost -all-  (如下图):

      3、回车后会出现相应信息(注意:在调试过程中不要关闭cmd):

     4、打开本地浏览器,(使用webkit内核浏览器(chrome、safari))访问  http://localhost:8081/,不出意外的话可以看到weinre的基本信息。

     5、上图中的"debug client user interface"是weinre的Debug客户端,点击进入后可以看到目前还没有被测试的目标网页。

  三、 添加Debug Target

    为了让需要调试的页面被weinre检测到,需要添加Debug Target,有两种方法:
     1、Target Script  

           该方法需要在调试的页面中增加一个 js

<script src="http://192.168.0.106:8081/target/target-script-min.js#anonymous" type="text/javascript"></script>

    添加后在移动设备中访问该页面即可,如果调试的页面比较少可以使用这个方法,如果多的话推荐第二种方法

     2、Target Bookmarklet
    该方法是将一段js保存到移动设备的书签中,可以在 http://localhost:8081/ 找到这段js:

javascript:(function(e){e.setAttribute("src","http://localhost:8081/target/target-script-min.js#anonymous");document.getElementsByTagName("body")[0].appendChild(e);})(document.createElement("script"));void(0);

    我将这段js保存到名为Debug书签中,然后使用移动设备访问我想要调试的页面,比如说 http://iinterest.net,最后点击Debug书签就OK了。

   四、真机调试。

    1、 移动设备须有有 wifi无线连接,且和电脑在同一网段,(确保本机安装了 服务器,可以到网上搜 xamppwamp,)把要调试的 页面放在服务器中相应的文件夹中,我安装的是xampp,所以放在htdocs目录下。在手机的页面中打开本页面的地址,如:http://192.168.0.102/index.html 。回到http://localhost:8081页面,点击“debug client user interface:”链接进入weinre的Debug界面,如果成功添加了Debug Target,这里可以看到它。

  2、接下来我们就可用自己熟悉的方式调试页面了,并且调试结果会实时显示在移动设备上

 

MAC系统更为简单,不用命令行,直接运行app即可启动weinre,接下来的步骤和windows一样。

 

参考:http://www.iinterest.net/2012/02/08/debugging-mobile-web-applications-with-the-weinre/



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


ITeye推荐



防止登录页面出现在frame中

$
0
0

在使用frame页面嵌套开发的时候,遇到重启了服务器的时候会出现登录页面在frame页面中出现,

所以需要在登录页面里面用js判断下当前的地址信息,然后跳转到登录的单独页面中。


js代码如下:

$("document").ready(function(){
				//防止在frame里面出现登录页面
				if(top.location!==self.location){ 
					//alert(top.location); 
					//alert(self.location); 
					top.location.href=self.location.href; 
				} 

				
			});

作者:JavaAlpha 发表于2014-7-21 11:48:54 原文链接
阅读:0 评论:0 查看评论

oracle恢复删除的数据(转载)

$
0
0
oracle恢复删除的数据

分为两种方法:scn和时间戳两种方法恢复。

一、通过scn恢复删除且已提交的数据

  1、获得当前数据库的scn号

    select current_scn from v$database; (切换到sys用户或system用户查询)
    查询到的scn号为:1499223

  2、查询当前scn号之前的scn

    select * from 表名 as of scn 1499220; (确定删除的数据是否存在,如果存在,则恢复数据;如果不是,则继续缩小scn号)

  3、恢复删除且已提交的数据

    flashback table 表名 to scn 1499220;

二、通过时间恢复删除且已提交的数据

  1、查询当前系统时间

    select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;

  2、查询删除数据的时间点的数据

    select * from 表名 as of timestamp to_timestamp('2013-05-29 15:29:00','yyyy-mm-dd hh24:mi:ss');  (如果不是,则继续缩小范围)

  3、恢复删除且已提交的数据

    flashback table 表名 to timestamp to_timestamp('2013-05-29 15:29:00','yyyy-mm-dd hh24:mi:ss');

    注意:如果在执行上面的语句,出现错误。可以尝试执行 alter table 表名 enable row movement; //允许更改时间戳


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


ITeye推荐



听百度搜索PM说:神马搜索怎么做才能打败百度

$
0
0

作者头像
作者: 葛灿辉-搜索数据挖掘/产品观察家
极客一枚,只做搜索,欢迎关注@葛灿辉-搜索数据挖掘
[核心提示]神马搜索借 UC 之势迅速崛起,它能够超越现在的搜索老大百度吗?百度搜索的产品经理对此提供了一些「内部参考」。

最近神马搜索靠着 UC 浏览器的渠道优势迅速发展壮大,那么它如何才能够打败百度,成为移动搜索市场的老大呢?这里灿辉跟大家一起来探讨一下。

超越百度的一定不是下一个百度。若想有所作为,灿辉认为可以借鉴乔布斯拯救苹果的路子: 保持专注,做出品牌特色,最后再抓住用户移动搜索场景进行弯道超车。

利用UC品牌优势,打造最省流量的移动搜索

尽管目前 4G 时代已经到来,3G 发展也很迅猛,用户的流量套餐也一直在增长,但是微信等各种 App 的流量消耗增长则更快,所以用户流量仍然总是不够用。 节省流量仍然是刚需,移动搜索作为日常使用频次很高的应用,在每一次搜索中尽可能的为用户节省流量,积累下来节省总量就非常可观。最省流量的移动搜索有着非常巨大的用户价值。

从塞班时代开始,UC 浏览器一直以省流量著称,在省流量这件事情上面拥有巨大的品牌认知,这是独一无二的优势。占领用户心智,从用户心智出发是做产品的最高境界。我们可以利用好这一优势,聚焦在省流量这一件事情上面,把神马搜索打造为最省流量的移动搜索。

建立搜索流量消耗的数据监控体系

没有衡量就没有改进,灿辉认为首先应该建立流量消耗数据监控体系,精准记录用户每次搜索耗费多少流量以及完成一个搜索目标总共耗费多少流量。按照监控→分析→改进再回到监控的迭代流程进行持续改进。

减少内容传输过程中的流量消耗

利用好 UC 浏览器已有的网页转码、图片、文字压缩的技术,对搜索结果页中的图片进行预处理,在不影响显示效果的前提下降低流量消耗。。

提供更少、更精准的搜索结果,降低无效搜索结果流量消耗

跟PC搜索相同,目前所有移动搜索引擎的默认结果条数都是 10 条,这一策略继承自 PC 端。到了移动端,用户的屏幕更小,应该显示更少而精的搜索结果,或者进一步可以根据用户 query 意图的多样性自动调整搜索结果的条数:对于搜索量大的精准、明确、意图指向单一的 query,比如“天气”,可以默认只显示一条结果,其他结果点击“加载更多”按钮再展开。如下图:

移动搜索“天气”

  • 对于需求较泛,但是仍然处于某一垂直领域的 query,比如“三星”,属于商品搜索领域,可以缩减其他领域的搜索结果数量,将总搜索结果控制在 3~5 条(刚好在 2 屏左右)
  • 最后就是那些还不能判定 query 类型的情况,可以默认显示 10 条结果。

提供极度省流量模式

在极度省流量模式下,默认不显示图片,只显示文字,而且减少摘要长度。除了搜索结果外,跳转链接也采用极度省流量模式,自动重排网页,仍然不显示图片。只有在用户主动点击图片占位符的时候才会显示图片。 极度省流量模式可以由用户主动选择,也可以根据用户的流量套餐剩余情况自动进入。(用户流量剩余量可以通过运营商的短信接口获得)

围绕移动搜索的用户场景持续改进体验,最终占据一席之地

PC 搜索的使用场景比较单一,就是坐在电脑前面;而移动搜索可以让用户随时随地,想搜就搜,用户使用场景就更加多样化,更加贴近用户生活。搞清楚用户的使用场景,有助于我们弄明白 query 背后用户真正意图是什么,进而才能给用户提供更少,更精准的搜索结果。按照地点,灿辉归纳出用户主要的使用场景如下:

移动搜索用户主要场景

我们再来看看神马搜索的优势:

  1. 背靠阿里集团,拥有整个互联网上最丰富的商品数据和用户购买行为数据,以及支付宝、淘宝、天猫等完善的线上电商生态圈。
  2. UC 在网络小说领域耕耘多年,网络小说又全又快又准,用户看网络小说的体验非常好。
  3. 阿里还拥有高德地图,拥有线下商场、餐馆、电影院、道路、车站、写字楼、住宅区等丰富的地理位置数据,有了这些地理位置数据才可能根据用户地理位置识别用户所在的场景。

灿辉认为:好的产品懂得聚焦,集中有限的资源做好少数最重要的事情。移动搜索也不例外,综合来看,神马搜索可以聚焦在下面三个用户场景:

  1. 在路上,等车、坐车、坐地铁过程中用户打发时间的娱乐需求,目前以看小说,听音乐,看新闻,玩游戏为主。目前神马的小说搜索有口皆碑,新闻和音乐搜索需要加强。
  2. 在商场,线下购物、逛街过程中用户获取信息的需求,可能是出于好奇,希望多了解一些产品的信息,也可能是希望更好做出购物决策)神马搜索有阿里丰富的商品数据和用户在线购物行为数据,可以从扫码比价(线下和线上同时比)、商品信息和用户评价查询、品牌信息查询等入手满足用户在线下购物场景中的各种信息获取需求。
  3. 非常住城市,用户可能在旅游或者出差,无论是旅游还是出差,机票、火车票、酒店预订是刚需,神马搜索可以和淘宝旅行一起来做,预订之后可以自动关联手机的日程表进行提醒。

在上面的三个用户场景中,神马搜索只要做成一个,牢牢的将自己嵌入到这个用户场景中,持续不断的为用户提供价值和好的体验,慢慢的用户就离不开神马搜索了,而神马搜索就可以赢得一个有一个的用户,日积月累、假以时日,超越百度也不是没有可能的。

极客观察均为极客公园原创报道,转载请注明原文链接。

原文地址: http://www.geekpark.net/read/view/209002

关注极客公园,即时获得最新内容: Twitter | 微信:极客公园 | 新浪微博 | 花瓣网 | 人人小站 | Google+ | 点点

关于云计算基础架构IaaS层的几点看法

$
0
0
PS:本文作者是前盛大云CEO、Ucloud创始人季昕华,本人的工作经历使然对此文观点比较同感,也是比较不错的云计算IaaS层概念科普文。特记录如下: 真实的云计算什么样? 云计算对普通用户来说,总是一个云里雾里的话题。本文从最基础的概念开始科普,说明了四个常见的错误理解,和作者的四个猜想。 IaaS(Infrastructure as a Service),指基础设施即服务,消费者通过Internet可以从完善的计算机基础设施获得服务。基于Internet的服务(如存储和数据库)是IaaS的一部分。Internet上其他类型的服务包括平台即服务(Platform as a Service,PaaS)和软件即服务(Software as a Service,SaaS)。PaaS提供了用户可以访问的完整或部分的应用程序开发,SaaS则提供了完整的可直接使用的应用程序,比如通过Internet管理企业资源。 误解一:IaaS就是卖资源 现在流行的一个观点:IaaS就是卖资源,传统IDC是卖带宽和机架,云计算加上服务器,最多就是把这些资源通过虚拟化技术拆成散了零卖。 在我们看来,云计算分为3个层次: 1、 资源层:这是IaaS提供服务的物理基础,主要包括计算资源、存储资源和网络资源,以及必要的电力资源、IP资源等。这一层主要通过规模采购和资源复用的模式来赚钱利润,利润不高。 2、 产品层:这是IaaS的核心,IaaS运营商根据客户的各种不同需求,在资源层的基础上,开发出各种各样的产品。比如存储产品、消息产品、CDN(内容分发网络)产品、监控产品,而每一种产品又会根据场景和需求的不一样,做针对性的改造优化,形成特定类型的产品。产品层是不同IaaS的竞争力体现之处,这些产品在不同角度满足了用户的不同需求。这些产品是IaaS利润的主要来源,也是IaaS的重要黏性。像国内的阿里云就提供了云服务器和负载均衡、云监控等产品,Ucloud提供了块设备存储的UDisk、云数据库的UDB等产品。 3、 服务层:在产品层之上,IaaS运营商还会根据用户的需求提供一些更多的增值服务,这部分从商业角度不一定赚钱,但却是用户使用IaaS的重要条件。比如为用户提供数据快递服务,在中国则必须包含网站备案服务,还有安全服务等等。 误解二:IaaS没有什么技术含量 在各种媒体的宣传把云计算神话了,认为云计算无所不能,把云计算的技术看的很高端,技术含量特别特别高。而不少从事过技术的人呢,则认为云计算没有什么技术含量,已经有类似Openstack、Eucalyptus、cloudstack等不少开源系统可以直接部署使用,或者基于KVM、XEN等开源虚拟化系统上做一套管理系统。 的确,随着云计算的快速发展,已经涌现出一大批开源的云计算平台,各大公司也都在积极支持开源软件的发展。但是即使发展快如Openstack,目前也没有很成熟的成功案例,因为IaaS的技术复杂度很高。 1、从基础上看,IaaS要实现多租户,弹性,稳定可靠和安全,必须要进行资源的池化管理,也就是把资源通过虚拟化技术形成资源池,然后根据用户的需求弹性分配,同时确保安全和隔离。之前提到资源主要包括计算、存储和网络,因此这里要做计算的虚拟化、存储的虚拟化和网络的虚拟化。 计算的虚拟化目前主要是通过XEN、KVM、Vmware等软件实现,相对比较成熟,但是在性能优化、稳定性方面还有很多工作需要完善。 存储的虚拟化目前还没有一个比较成熟的开源系统,如果文件型存储,则主要根据GFS的思路进行编码实现,必然Openstack的swift,而块设备存储则各显神通了,有nova-volume,国内盛大云、UCloud都各自实现了块设备存储。另外最近国际上非常流行的是SDS(软件定义存储),实际上也是实现了存储的虚拟化。 2、在虚拟化管理之上,是大规模的调度管理,如何能快速找到合适的资源满足用户的需求,如何能根据监测的数据,动态调整资源,如何能动态迁移业务,如何防止雪崩。如果是10台机器,这可能很容易,如果是1000台机器,这是一个问题,如果是10000台以上的机器,那就是个大挑战了。而云计算,要实现解决规模化的能力,就必须解决大规模的调度问题。这里的难度和挑战相当的大。 3、性能和安全问题同样也是IaaS的挑战,如何确保一个用户的高需求不影响其他用户,如何防范一个租户入侵其他租户,如何防止一个用户被攻击不影响其他用户,这里需要我们更加深入的研究。 更多的产品研发,如上所说,IaaS除了资源之外,更关键的是产品,必须根据用户的需求研发出更多满足特定需求的产品。这就会涉及到系统、网络、数据库、应用和安全的方方面面,对IaaS开发和运维的要求都非常高。 综上所述,IaaS的技术门槛是比较高的,并不是没有技术含量。 误解三:IaaS是不安全的 业界都在质疑云计算的安全性,特别是Evernote的安全事故让更多人担心IaaS的安全问题。 以我十多年的安全从业经验来看: 1、 没有绝对的安全,任何系统都有可能会被入侵; 2、 安全是相对的,关键要看IaaS模式下和传统托管模式下哪种更安全。因此假设一个公司规模很大,有专业的安全团队,比如腾讯、阿里、百度等公司,则肯定他们自己部署会安全很多,但是如果假设是一个小的创业公司,不可能有很专业的安全人员,IaaS的服务提供商则可以更专业的提供安全保障。 误解四:公有云只能服务中小企业 由于大企业对稳定性的追求,以及对旧有投资的保护,的确公有云的用户大部分都是从小企业开始的。目前不管是国内还是国外,中小企业还是云计算的主要用户。 但是随着云计算的发展,我们也发现了几个趋势: 1、一些在公有云上成长起来的公司,长成大型企业后也依然在使用公有云,比如Netflex,因为他们发现如果自己要建立基础架构所需要的人力物力依然很大,困难依旧很多,还不如将精力投入在他们自己擅长的领域内。 2、传统的一些大公司,他们也逐步开始尝试将一些非核心业务或者新业务部署在公有云上,甚至将IT部门裁员,全部转移到公有云平台。比如兰博基尼、宝马等汽车公司,他们已经借助云计算来降低成本,借助云计算提高他们的设计渲染能力。 其实从电力发展的情况来看也是这样的,在现代这样的社会,我们很少看到有企业会自己建立发电厂,而不使用电网。相信随着云计算的发展,云计算取代IDC或者取代自己运营也是必然的趋势。 四个猜想: 一、IaaS增长快速 IaaS公共云服务将是增长最快的公共云服务类别。预计全球2013年IaaS的市场规模将达到80亿美元,其中AWS(amazon web services,亚马逊公有云服务)预计能达到25-28亿美元,Rackspace收入16-19亿左右,IaaS占35%,超过6亿美元,而被Verizon收购的Terremark收入将超过4.5亿以上,另外像Joyent,Savvis,GoGrid,Dimension Data等公司都会有一定的收入增长。 相比全球,中国的IaaS市场基数小,但增长速度更快,预计13年中国纯粹IaaS市场规模将会超过1亿美元,并逐步形成3-4家规模比较大的IaaS运营商。 二、大中型企业将开始接受云计算 正如上面所说,大中型企业已经开始尝试将一些非核心业务部署在公有云上。从AWS的客户列表中,我们可以看到财富500强企业或多或少都在使用亚马逊的公有云进行测试或者开发,其中有些公司在上面运行真正的应用,比如纳斯达克,兰博基尼等公司。 这种变化将会对传统的IT厂商,IBM、HP、Oracle产生很大的威胁,因为传统大中型企业是这些IT厂商的大客户。 [...]

【闲说】性能测试

$
0
0

版权声明:本文为本作者原创文章,转载请注明出处。感谢 码梦为生| 刘锟洋的投稿

性能测试是一件看起来不简单,操作起来确更困难的事情,我认为,每认真做一次性能测试,一定会有不同收获,而每次性能测试暴露的问题,现象都不是仅仅涉及Java,tomcat这么简单,简单说就是光会写代码是无法做好性能测试的。

那么,就趁着这次性能测试的机会,重新梳理下对linux,网络IO等基本功的认识已经就性能瓶颈的定位分享下自己的心得。

背景:

本次性能测试的目的是测试使用公司内部RPC框架开发的一套接口的性能,目的是准确的拿到接口的性能指标,当然,我也想换个角度去看待代码,比如,从性能或者对操作系统友好的角度,首先略过1万字的环境搭建过程,其实,性能测试是件非常考验细心程度的活,需要你对整个组网环境,调用关系,业务逻辑非常清晰,能正确识别出压力机,应用服务器,数据库服务器,缓存服务器各自的职责,并在可能的情况下压榨其性能极限,以及清楚明白可能对其性能造成影响的命令和操作(比如jvm启动参数中,大部分日志打印相关参数,关闭即时编译,调整GC分带的大小和比例等等)。

其次,还需要你能清楚本次测试程序的核心流程,业务逻辑,尽可能的将一些非核心的组件可能造成的影响去除掉,比如,本次测试的是RPC接口的性能和业务处理的效率,而相应涉及到的分布式缓存,数据库,则不是本次测试的重点,因此,组网时,应该尽可能将分布式缓存,数据库等机器与应用服务器放在同一个局域网网段内甚至同一台机器上,保证不会因为他们的表现而直接影响测试目标测试结果。总之,Mock掉一切非核心,不相关的因素。

测试工具/命令

因为是对RPC接口做测试(而非HTTP接口),使用loadRunner等测试工具无法满足要求,所以在测试工具的选择上,使用了jmeter。这是一款100%java实现的性能测试工具,使用方式是,继承他的AbstractJavaSamplerClient抽象类,在其runTest方法中编写测试用例即可在Jmeter的客户端中发现测试jar包,从而配置线程数后开始性能测试。具体使用请google之。
在压力机上部署好jmeter后,多线程开始执行测试用例,用例开始向应用服务器发送调用请求。这个时候设置的并发数应该尽量让压力机的CPU达到一个较高的值,比如 70%左右,jemeter提供了预热功能,必要时候可以使用预热功能将压力慢慢加大。

下面,我们借这次性能测试的机会介绍几个很好用的命令,启动后可以先到应用服务器上使用top命令,观察其CPU利用率,按数字键1,详细查看每个CPU的利用率。 理想情况,这个时候应该可以看到一定的压力。
也可以使用 vmstat命令,比如: vmstat 1  30 标示,每隔一秒打印一次统计信息,统计30秒。

打印结果类似:
talk_performance_test_1

通常主要关注r 和b 分别代表运行队列的数量和阻塞个数。理想情况应该是r比较多,b没有。
具体vmstat命令的结束可以看: http://www.cnblogs.com/ggjucheng/archive/2012/01/05/2312625.html

关注完CPU,还可以使用iostat命令 查看IO的情况,命令格式类似vmstat, iostat 1 30 表示同样的意思:每秒打印一次统计信息,打印30次后退出。

这里使用iostat -dx 1   每隔一秒打印一次磁盘的详细信息  具体可以参看这里: http://www.cnblogs.com/peida/archive/2012/12/28/2837345.html
talk_performance_test_2
可以看到io并不频繁。都是在很低 的水平上,因此IO应该不是此次性能测试的瓶颈所在。

看完vmstat,iostat,如果都不是处在很高的水平,下一个应该优先看网络,是的,对于linux还有一个iostat,使用方式与前两种不同,但是功能同样强大,可以列出应用服务器上所有tcp连接的详细信息。通常情况,可以观察下应用服务器上的TCP连接数,连接状态是否正常等来判断应用是否运行正常。
很好用的工具,动手输一下,你就会知道它的功能了。

测试目的

一般测试的目的有两个:
1. 是获取接口的性能,常用TPS,延迟,QPS等衡量。
2. 是通过性能测试,找出性能瓶颈,定位并优化它。

因此,性能测试必须要满足的一个原则是,要么把压力机跑满,要么让应用服务器的某项指标跑满,之所以说某项指标,是因为,根据应用的不同,例如:CPU密集型应用,IO密集型应用,相应的,性嫩测试的时候应该尽量让CPU利用率或者IO利用率达到一个较高的水平。

如果有一项指标没有达标,那性能瓶颈的定位过程就来了。

瓶颈定位

要定位瓶颈,首先需要知道应用服务器的哪项指标没有达到预期,是CPU利用率还是IO利用率或是都不高,这可以通过以上介绍的三个stat工具观察出来,如果没有看到哪项值比较高,至少也可以得到“都不高”的结论,而都不高的时候,或许意味着你的应用程序不像你想象的那么高效,一定,一定,在某个点上正在激烈的竞争者或者阻塞。程序会平白无故效率低下!

当然除了通过利用率,可以看到CPU或者IO的忙闲程度,有时我们还需要知道具体的数字,比如,哪种IO才算繁忙?

举个例子,这次性能测试时我使用了一个工具:ifstat,它并非系统自带的工具,需要手动安装,安装过程非常简单,自行google即可。
安装完毕后,将ifsta命令加入到path变量中,即可在全局使用ifstat命令,使用后的效果大致是这样:
talk_performance_test_3
eth0 代表了操作系统的第一张网卡。从这里可以看到此时这张网卡的读入速率是15M,出口是8M左右,而这张网卡的速率为:
talk_performance_test_4

也就是1000Mbit/s ,因为8B10B编码的关系,换算后理论的带宽为100M/S,100:15 利用率为15%,这个时候我们才可以说IO的利用率不高。IO不算繁忙。

同样的,有时会出现一种情况:CPU,网络/磁盘IO都不高,同样TPS也不高,这个时候可以从程序入手,分析下是否是程序执行缓慢的原因,原因大致有这么几种:
1. 有代码在串行的某件事,比如打日志(这次我就遇到了因为我使用自己写的工具监控方法执行时间的关系,在性能测试时有大量打印日志和计算工作 ,导致应用程序TPS非常低,拿掉工具后TPS才恢复到一个正常的水平,当然,这就不是说我的工具就不好用(笑) ,有兴趣的可以看下工具的介绍,总的来说还是很好用的,工具地址: https://github.com/liuinsect/Profiler)。
2. 多线程竞争,比如,多线程环境下,锁的竞争,对象监视器的竞争,数据库,分布式缓存连接的竞争(如果使用连接池的话)等。
3. 过于冗长,复杂方法的执行,虽然JIT可以执行一定程度上的优化,但是,糟糕代码无下限,要想写得烂,总是可以的。
4. 所依赖的系统慢,比如,数据库,分布式缓存慢(当然,他们的慢有更多种可能,有时候甚至需要找到他们慢的原因,并mock掉)。

这个时候就要借助visual vm等工具了。

因为很多时候我们是想在本地,去连接远程服务器上的JVM,这就涉及到了远程连接JVM的问题,可以这么做:

1.首先必须在远程机器上面启动jstatd这个后台进程。它位于JDK安装路径的bin目录里面。配置java安全访问,在jstatd所在的目录的下新建文件jstatd.all.policy,在我的机器上是/usr/java/jdk1.7.0_05/bin

grant codebase “file:${java.home}/../lib/tools.jar” {

permission java.security.AllPermission;

};

注意结尾还有一个分号。

2.然后用如下命令启动jstatd:

jstatd -J-Djava.security.policy=jstatd.all.policy

正常启动没有任何输出。默认打开端口是1099,也可以通过-p 参数设置端口。

3. 在本地打开 visual vm ,输入远程服务器的IP后,即可连接了。

当然,因为只是启动了jstatd,通过visual是不能使用线程监控,CPU监控的,如果需要用到这些功能的话,还需要使用JMX去远程连接tomcat 。方法在这里:http://www.oschina.net/question/162973_105064

通过visual vm 已经可以观察到GC的情况,运行的线程数,是Block,Running 等等情况了,如果应用程序竞争激烈,应该会看到线程运行条上有一段一段的红色区域,代表线程正在被频繁阻塞,再想深入,可用通过visual vm 将线程情况dump下来(当然,也可以在应用服务器上使用jstack -m <pid>),查看线程都被哪些对象阻塞,线程的调用栈是什么样子的, 从而定位到,应用程序中哪段代码有频繁竞争,为什么竞争,是否可以优化等。

当然,除了使用visual vm 还可以使用linux上的另外一个工具 perf ,他是linux 自带的性能分析工具。可以通过它看到系统执行的性能情况,功能实在强大,比如:
1. 列出L1,L2,L3 Cache的命中率(需要硬件支持,这次我们性能测试的机器不支持它)
2. 列出系统/进程的性能统计信息 命令: perf top -p pid
3. 分析程序的整体性能 perf stat
等等, 具体可以参考这里:  http://iamzhongyong.iteye.com/blog/1908118
关于perf,这次还有一个小小的故事,在测试接口的某个方法时,使用perf观察到JVM的反射相关的方法耗时开销非常高,这才想起来反射相关的代码没有对反射的结果做缓存,因此果断回去加上缓存后,看到前面的方法在perf的列表中消失,这才放下心。

总结:

通过以上介绍的性能测试的思路和工具,我们基本上可以完成一次性能测试以及部分问题的性能定位,但是往往性能问题总是隐藏得很深的,并且受各种条件的影响,比如,各个环节的配置参数,网络情况,机器情况,性能测试的工具等等,所以,性能测试的结果往往不能脱离某个环境单独比较,不同的配置,环境,应用的性能都会呈现出不同的结果,出现问题时,也需要我们从前到后,从上到下仔细分析每一个流程的执行情况,逐步通过工具协助定位,才能最终找到瓶颈。总之,性能测试是一门考验耐心,细心,知识广度, 深度的活,每次遇到问题多问几个为什么,多做几次分析和验证,并尝试解决,优化它,一定会让你对系统有更多不一样的认识。

(全文完)如果您喜欢此文请点赞,分享,评论。



您可能感兴趣的文章

Google为何至今没有修正Chrome的高耗电“bug”

$
0
0
在Windows笔记本电脑上,Chrome的平均耗电量高于其它浏览器,原因是它使用了更短的唤醒计时器。Windows使用计时器安排任务,在空闲情况下,计时器设为15ms,如果没有任务要做,它会继续休眠,每隔15ms检查一次。应用程序可以修改这个计时器, Chrome将其设为1ms,也就是在空闲时它每秒会唤醒系统1000次,相比之下Firefox在空闲时每秒唤醒系统64次。更高频率的检查会增加耗电量,但Goolge开发者早就知道这个问题,认为这么做是值得的,因为它可以让Chrome运行更快。早在2010年,就有人递交了Chrome的耗电bug报告。但Google至今没有去修改。直到今天,电池续航力成为用户关注的问题,Google将该bug分配为高优先级,准备解决这个曾视为特性的计时器bug。






Viewing all 15843 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>