??xml version="1.0" encoding="utf-8" standalone="yes"?>BlogJava-疯狂http://www.dentisthealthcenter.com/freeman1984/STANDING ON THE SHOULDERS OF GIANTS zh-cnThu, 07 Dec 2023 17:38:10 GMTThu, 07 Dec 2023 17:38:10 GMT60 后箋内容L步公众号“duomi88?http://www.dentisthealthcenter.com/freeman1984/archive/2019/04/03/433700.html疯狂疯狂Wed, 03 Apr 2019 01:55:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2019/04/03/433700.html
定期发布一些技术和产品内容Q欢q关注交?nbsp; 阅读全文

疯狂 2019-04-03 09:55 发表评论
]]>
Netty百万U推送服务(转)http://www.dentisthealthcenter.com/freeman1984/archive/2016/07/13/431178.html疯狂疯狂Wed, 13 Jul 2016 02:03:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2016/07/13/431178.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/431178.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2016/07/13/431178.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/431178.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/431178.html转蝲自:http://www.open-open.com/lib/view/open1420623195375.html

1. 背景

1.1. 话题来源

最q很多从事移动互联网和物联网开发的同学l我发邮件或者微博私信我Q咨询推送服务相关的问题。问题五花八门,在帮助大家答疑解惑的q程中,我也寚w题进行了ȝQ大概可以归Uؓ如下几类Q?/p>

  1. Netty是否可以做推送服务器Q?/li>
  2. 如果使用Netty开发推送服务,一个服务器最多可以支撑多个客户端?
  3. 使用Netty开发推送服务遇到的各种技术问题?/li>

׃咨询者众多,x点也比较集中Q我希望通过本文的案例分析和Ҏ送服务设计要点的ȝQ帮助大家在实际工作中少走弯路?/p>

1.2. 推送服?/h3>

Ud互联|时代,推?Push)服务成ؓApp应用不可或缺的重要组成部分,推送服务可以提升用Lz跃度和留存率。我们的手机每天接收到各U各Lq告和提C消息等大多数都是通过推送服务实现的?/p>

随着物联|的发展Q大多数的智能家居都支持Ud推送服务,未来所有接入物联网的智能设备都是推送服务的客户端,q就意味着推送服务未来会面͋量的设备和l端接入?/p>

1.3. 推送服务的特点

Ud推送服务的主要特点如下Q?/p>

  1. 使用的网l主要是q营商的无线Ud|络Q网l质量不E_Q例如在地铁上信号就很差Q容易发生网l闪断;
  2. 量的客L接入Q而且通常使用长连接,无论是客Lq是服务端,资源消耗都非常大;
  3. ׃h的推送框架无法在国内使用QAndroid的长q接是由每个应用各自l护的,q就意味着每台安卓讑֤上会存在多个长连接。即便没有消息需要推送,长连接本w的心蟩消息量也是非常巨大的Q这׃D量和耗电量的增加Q?/li>
  4. 不稳定:消息丢失、重复推送、gq送达、过期推送时有发生;
  5. 垃圾消息满天飞,~Zl一的服务治理能力?/li>

Z解决上述弊端Q一些企业也l出了自q解决ҎQ例如京东云推出的推送服务,可以实现多应用单服务单连接模式,使用AlarmManager定时心蟩节省电量和流量?/p>

2. 家居领域的一个真实案?/h2>

2.1. 问题描述

家居MQTT消息服务中间Ӟ保持10万用户在UKq接Q?万用户ƈ发做消息h。程序运行一D|间之后,发现内存泄露Q怀疑是Netty的Bug。其它相关信息如下:

  1. MQTT消息服务中间件服务器内存16GQ?个核心CPUQ?/li>
  2. Netty中bossU程池大ؓ1QworkerU程池大ؓ6Q其余线E分配给业务使用。该分配方式后来调整为workerU程池大ؓ11Q问题依旧;
  3. Netty版本?.0.8.Final?/li>

2.2. 问题定位

首先需要dump内存堆栈Q对疑似内存泄露的对象和引用关系q行分析Q如下所C:

Netty百万U推送服? src=

我们发现Netty的ScheduledFutureTask增加?076%Q达?10W个左右的实例Q通过对业务代码的分析发现用户使用IdleStateHandler用于在链路空闲时q行业务逻辑处理Q但是空闲时间设|的比较大,?5分钟?/p>

Netty 的IdleStateHandler会根据用L使用场景Q启动三cd时Q务,分别是:ReaderIdleTimeoutTask?WriterIdleTimeoutTask和AllIdleTimeoutTaskQ它们都会被加入到NioEventLoop的Task队列中被调度 和执行?/p>

?于超时时间过长,10W个长链接链\会创?0W个ScheduledFutureTask对象Q每个对象还保存有业务的成员变量Q非常消耗内存。用L 持久代设|的比较大,一些定时Q务被老化到持久代中,没有被JVM垃圾回收掉,内存一直在增长Q用戯认ؓ存在内存泄露?/p>

事实上,我们q一步分析发玎ͼ用户的超时时间设|的非常不合理,15分钟的超时达不到设计目标Q重新设计之后将时旉讄?5U,内存可以正常回收Q问题解冟?/p>

2.3. 问题ȝ

如果?00个长q接Q即便是长周期的定时dQ也不存在内存泄露问题,在新生代通过minor GC可以实现内存回收。正是因为十万的长q接Q导致小问题被放大,引出了后l的各种问题?/p>

事实上,如果用户实有长周期q行的定时Q务,该如何处理?对于量长连接的推送服务,代码处理E有不慎Q就满盘皆输Q下面我们针对Netty的架构特点,介绍下如何用Netty实现百万U客L的推送服务?/p>

3. Netty量推送服务设计要?/h2>

作ؓ高性能的NIO框架Q利用Netty开发高效的推送服务技术上是可行的Q但是由于推送服务自w的复杂性,惌开发出E_、高性能的推送服务ƈ非易事,需要在设计阶段针对推送服务的特点q行合理设计?/p>

3.1. 最大句柄数修改

百万长连接接入,首先需要优化的是Linux内核参数Q其中Linux最大文件句柄数是最重要的调优参C一Q默认单q程打开的最大句柄数?024Q通过ulimit -a可以查看相关参数Q示例如下:

[root@lilinfeng ~]# ulimit -a core file size          (blocks, -c) 0 data seg size           (kbytes, -d) unlimited scheduling priority             (-e) 0 file size               (blocks, -f) unlimited pending signals                 (-i) 256324 max locked memory       (kbytes, -l) 64 max memory size         (kbytes, -m) unlimited open files                      (-n) 1024  ......后箋输出省略

当单个推送服务接收到的链接超q上限后Q就会报“too many open files”Q所有新的客L接入失败?/p>

通过vi /etc/security/limits.conf d如下配置参数Q修改之后保存,注销当前用户Q重新登录,通过ulimit -a 查看修改的状态是否生效?/p>

*  soft        nofile        1000000 *  hard        nofile        1000000

需要指出的是,管我们可以单个进E打开的最大句柄数修改的非常大Q但是当句柄数达C定数量之后Q处理效率将出现明显下降Q因此,需要根据服务器的硬仉|和处理能力q行合理讄。如果单个服务器性能不行也可以通过集群的方式实现?/p>

3.2. 当心CLOSE_WAIT

从事Ud推送服务开发的同学可能都有体会Q移动无U网l可靠性非常差Q经常存在客L重置q接Q网l闪断等?/p>

在百万长q接的推送系l中Q服务端需要能够正处理这些网l异常,设计要点如下Q?/p>

  1. 客户端的重连间隔需要合理设|,防止q接q于频繁D的连接失败(例如端口q没有被释放Q;
  2. 客户端重复登陆拒l机Ӟ
  3. 服务端正处理I/O异常和解码异常等Q防止句柄泄霌Ӏ?/li>

最 后特别需要注意的一点就是close_wait q多问题Q由于网l不E_l常会导致客L断连Q如果服务端没有能够及时关闭socketQ就会导致处于close_wait状态的链\q多?close_wait状态的链\q不释放句柄和内存等资源Q如果积压过多可能会Dpȝ句柄耗尽Q发?#8220;Too many open files”异常Q新的客L无法接入Q涉及创建或者打开句柄的操作都失败?/p>

下面对close_wait状态进行下单介l,被动关闭TCPq接状态迁Ud如下所C:

Netty百万U推送服? src=

?-1 被动关闭TCPq接状态迁Ud

close_wait 是被动关闭连接是形成的,ҎTCP状态机Q服务器端收到客L发送的FINQTCP协议栈会自动发送ACKQ链接进入close_wait状态。但如果 服务器端不执行socket的close()操作Q状态就不能由close_waitq移到last_ackQ则pȝ中会存在很多close_wait?态的q接。通常来说Q一个close_wait会维持至?个小时的旉Q系l默认超时时间的?200U,也就?时Q。如果服务端E序因某个原因导 致系l造成一堆close_wait消耗资源,那么通常是等不到释放那一刻,pȝ已崩溃?/p>

Dclose_waitq多的可能原因如下:

  1. E序处理BugQ导致接收到Ҏ的fin之后没有及时关闭socketQ这可能是Netty的BugQ也可能是业务层BugQ需要具体问题具体分析;
  2. 关闭socket不及Ӟ例如I/OU程被意外阻塞,或者I/OU程执行的用戯定义Task比例q高Q导致I/O操作处理不及Ӟ链\不能被及旉放?/li>

下面我们l合Netty的原理,Ҏ在的故障点进行分析?/p>

?计要?Q不要在Netty的I/OU程上处理业务(心蟩发送和除外)。Why? 对于Javaq程Q线E不能无限增长,q就意味着Netty的ReactorU程数必L敛。Netty的默认值是CPU核数 * 2Q通常情况下,I/O密集型应用徏议线E数量讄大些Q但q主要是针对传统同步I/O而言Q对于非dI/OQ线E数q不讄太大Q尽没有最?|但是I/OU程数经验值是[CPU核数 + 1QCPU核数*2 ]之间?/p>

?如单个服务器支撑100万个长连接,服务器内核数?2Q则单个I/OU程处理的链接数L = 100/(32 * 2) = 15625?假如?S有一ơ消息交互(新消息推送、心x息和其它理消息Q,则^均CAPS = 15625 / 5 = 3125?U。这个数值相比于Netty的处理性能而言压力q不大,但是在实际业务处理中Q经怼有一些额外的复杂逻辑处理Q例如性能l计、记录接口日 志等Q这些业务操作性能开销也比较大Q如果在I/OU程上直接做业务逻辑处理Q可能会dI/OU程Q媄响对其它链\的读写操作,q就会导致被动关闭的?路不能及时关闭,造成close_wait堆积?/p>

设计要点2Q在I/OU程上执行自定义Task要当心。Netty的I/O处理U程NioEventLoop支持两种自定义Task的执行:

  1. 普通的Runnable: 通过调用NioEventLoop的execute(Runnable task)Ҏ执行Q?/li>
  2. 定时dScheduledFutureTask:通过调用NioEventLoop的schedule(Runnable command, long delay, TimeUnit unit)pd接口执行?/li>

Z么NioEventLoop要支持用戯定义Runnable和ScheduledFutureTask的执行,q不是本文要讨论的重点,后箋会有专题文章q行介绍。本文重点对它们的媄响进行分析?/p>

?NioEventLoop中执行Runnable和ScheduledFutureTaskQ意味着允许用户在NioEventLoop中执行非I/O?作类的业务逻辑Q这些业务逻辑通常用消息报文的处理和协议管理相兟뀂它们的执行会抢占NioEventLoop I/Od的CPU旉Q如果用戯定义Taskq多Q或者单个Task执行周期q长Q会DI/Od操作被阻塞,q样也间接导致close_wait 堆积?/p>

所 以,如果用户在代码中使用CRunnable和ScheduledFutureTaskQ请合理讄ioRatio的比例,通过 NioEventLoop的setIoRatio(int ioRatio)Ҏ可以讄该|默认gؓ50Q即I/O操作和用戯定义d的执行时间比?Q??/p>

我的是当服务端处理v量客L长连接的时候,不要在NioEventLoop中执行自定义TaskQ或者非心蟩cȝ定时d?/p>

?计要?QIdleStateHandler使用要当心。很多用户会使用IdleStateHandler做心跛_送和,q种用法值得提倡。相比于?己启定时d发送心跻Iq种方式更高效。但是在实际开发中需要注意的是,在心跳的业务逻辑处理中,无论是正常还是异常场景,处理时g要可控,防止时g不可 控导致的NioEventLoop被意外阻塞。例如,心蟩时或者发生I/O异常Ӟ业务调用Email发送接口告警,׃Email服务端处理超Ӟ?致邮件发送客L被阻塞,U联引vIdleStateHandler的AllIdleTimeoutTaskd被阻塞,最lNioEventLoop?路复用器上其它的链\d被阻塞?/p>

对于ReadTimeoutHandler和WriteTimeoutHandlerQ约束同样存在?/p>

3.3. 合理的心跛_?/h3>

百万U的推送服务,意味着会存在百万个长连接,每个长连接都需要靠和App之间的心xl持链\。合理设|心跛_期是非常重要的工作,推送服务的心蟩周期讄需要考虑Ud无线|络的特炏V?/p>

?一台智能手上移动网l时Q其实ƈ没有真正q接上InternetQ运营商分配l手机的IP其实是运营商的内|IPQ手机终端要q接上Internet q必通过q营商的|关q行IP地址的{换,q个|关UCؓNAT(NetWork Address Translation)Q简单来说就是手机终端连接Internet 其实是Ud内网IPQ端口,外网IP之间怺映射?/p>

GGSN(GateWay GPRS Support Note)模块实CNAT功能Q由于大部分的移动无U网l运营商Z减少|关NAT映射表的负荷Q如果一个链路有一D|间没有通信时就会删除其对应 表,造成链\中断Q正是这U刻意羃短空闲连接的释放时Q原本是惌省信道资源的作用Q没惛_让互联网的应用不得以q高于正帔R率发送心xl护推送的?q接。以中移动的2.5G|络ZQ大U?分钟左右的基带空Ԍq接׃被释放?/p>

?于移动无U网l的特点Q推送服务的心蟩周期q不能设|的太长Q否则长q接会被释放Q造成频繁的客L重连Q但是也不能讄太短Q否则在当前~Zl一心蟩?架的机制下很ҎD信o风暴Q例如微信心跳信令风暴问题)。具体的心蟩周期q没有统一的标准,180S也许是个不错的选择Q微信ؓ300S?/p>

在Netty中,可以通过在ChannelPipeline中增加IdleStateHandler的方式实现心x,在构造函C指定链\I闲旉Q然后实现空闲回调接口,实现心蟩的发送和,代码如下Q?/p>

public void initChannel({@link Channel} channel) {  channel.pipeline().addLast("idleStateHandler", new {@link   IdleStateHandler}(0, 0, 180));  channel.pipeline().addLast("myHandler", new MyHandler()); } 拦截链\I闲事gq处理心跻I  public class MyHandler extends {@link ChannelHandlerAdapter} {      {@code @Override}       public void userEventTriggered({@link ChannelHandlerContext} ctx, {@link Object} evt) throws {@link Exception} {           if (evt instanceof {@link IdleStateEvent}} {               //心蟩处理           }       }   }

3.4. 合理讄接收和发送缓冲区定w

对于镉K接,每个链\都需要维护自q消息接收和发送缓冲区QJDK原生的NIOcd使用的是java.nio.ByteBuffer,它实际是一个长度固定的Byte数组Q我们都知道数组无法动态扩容,ByteBuffer也有q个限制Q相关代码如下:

public abstract class ByteBuffer     extends Buffer     implements Comparable {     final byte[] hb; // Non-null only for heap buffers     final int offset;     boolean isReadOnly;

?量无法动态扩展会l用户带来一些麻烦,例如׃无法预测每条消息报文的长度,可能需要预分配一个比较大的ByteBufferQ这通常也没有问题。但是在 量推送服务系l中Q这会给服务端带来沉重的内存负担。假讑֍条推送消息最大上限ؓ10KQ消息^均大ؓ5KQؓ了满?0K消息的处 理,ByteBuffer的容量被讄?0KQ这h条链路实际上多消耗了5K内存Q如果长链接链\Cؓ100万,每个链\都独立持?ByteBuffer接收~冲区,则额外损耗的d?Total(M) = 1000000 * 5K = 4882M。内存消耗过大,不仅仅增加了g成本Q而且大内存容易导致长旉的Full GCQ对pȝE_性会造成比较大的冲击?/p>

实际上,最灉|的处理方式就是能够动态调整内存,x收缓冲区可以Ҏ以往接收的消息进行计,动态调整内存,利用CPU资源来换内存资源Q具体的{略如下Q?/p>

  1. ByteBuffer支持定w的扩展和收羃Q可以按需灉|调整Q以节约内存Q?/li>
  2. 接收消息的时候,可以按照指定的算法对之前接收的消息大进行分析,q未来的消息大小Q按照预值灵z调整缓冲区定wQ以做到最的资源损耗满程序正常功能?/li>

q运的是QNetty提供的ByteBuf支持定w动态调_对于接收~冲区的内存分配器,Netty提供了两U:

  1. FixedRecvByteBufAllocatorQ固定长度的接收~冲区分配器Q由它分配的ByteBuf长度都是固定大小的,q不会根据实际数据报 的大动态收~。但是,如果定w不Q支持动态扩展。动态扩展是Netty ByteBuf的一基本功能,与ByteBuf分配器的实现没有关系Q?/li>
  2. AdaptiveRecvByteBufAllocatorQ容量动态调整的接收~冲区分配器Q它会根据之前Channel接收到的数据报大进行计, 如果q箋填充满接收缓冲区的可写空_则动态扩展容量。如果连l?ơ接收到的数据报都小于指定|则收~当前的定wQ以节约内存?/li>

相对于FixedRecvByteBufAllocatorQ用AdaptiveRecvByteBufAllocator更ؓ合理Q可以在创徏客户端或者服务端的时候指定RecvByteBufAllocatorQ代码如下:

 Bootstrap b = new Bootstrap();             b.group(group)              .channel(NioSocketChannel.class)              .option(ChannelOption.TCP_NODELAY, true)              .option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT)

如果默认没有讄Q则使用AdaptiveRecvByteBufAllocator?/p>

另外值得注意的是Q无论是接收~冲是发送缓冲区Q缓冲区的大徏议设|ؓ消息的^均大,不要讄成最大消息的上限Q这会导致额外的内存费。通过如下方式可以讄接收~冲区的初始大小Q?/p>

/** 	 * Creates a new predictor with the specified parameters. 	 *  	 * @param minimum 	 *            the inclusive lower bound of the expected buffer size 	 * @param initial 	 *            the initial buffer size when no feed back was received 	 * @param maximum 	 *            the inclusive upper bound of the expected buffer size 	 */ 	public AdaptiveRecvByteBufAllocator(int minimum, int initial, int maximum) 

对于消息发送,通常需要用戯己构造ByteBufq编码,例如通过如下工具cd建消息发送缓冲区Q?/p>

Netty百万U推送服? src=

?-2 构造指定容量的~冲?/p>

3.5. 内存?/h3>

推送服务器承蝲了v量的镉K接,每个镉K接实际就是一个会话。如果每个会话都持有心蟩数据、接收缓冲区、指令集{数据结构,而且q些实例随着消息的处理朝生夕灭,q就会给服务器带来沉重的GC压力Q同时消耗大量的内存?/p>

最 有效的解决策略就是用内存池Q每个NioEventLoopU程处理N个链路,在线E内部,链\的处理时串行的。假如A链\首先被处理,它会创徏接收~?冲区{对象,待解码完成之后,构造的POJO对象被封装成Task后投递到后台的线E池中执行,然后接收~冲Z被释放,每条消息的接收和处理都会重复?收缓冲区的创建和释放。如果用内存池Q则当A链\接收到新的数据报之后Q从NioEventLoop的内存池中申L闲的ByteBufQ解码完成之 后,调用releaseByteBuf释放到内存池中,供后lB链\l箋使用?/p>

使用内存池优化之后,单个NioEventLoop的ByteBuf甌和GCơ数从原来的N = 1000000/64 = 15625 ơ减ؓ最?ơ(假设每次甌都有可用的内存)?/p>

下面我们以推特用Netty4的PooledByteBufAllocatorq行GC优化作ؓ案例Q对内存池的效果q行评估Q结果如下:

垃圾生成速度是原来的1/5Q而垃圾清理速度快了5倍。用新的内存池机制Q几乎可以把|络带宽压满?/p>

Netty4 之前的版本问题如下:每当收到C息或者用户发送信息到q程端,Netty 3均会创徏一个新的堆~冲区。这意味着Q对应每一个新的缓冲区Q都会有一个new byte[capacity]。这些缓冲区会导致GC压力Qƈ消耗内存带宽。ؓ了安全v见,新的字节数组分配时会用零填充Q这会消耗内存带宽。然而,用零 填充的数l很可能会再ơ用实际的数据填充,q又会消耗同L内存带宽。如果Java虚拟机(JVMQ提供了创徏新字节数l而又无需用零填充的方式,那么?们本来就可以内存带宽消耗减?0%Q但是目前没有那样一U方式?/p>

在Netty 4中实C一个新的ByteBuf内存池,它是一个纯Java版本?nbsp;jemalloc QFacebook也在用)。现在,Netty不会再因为用零填充缓冲区而浪费内存带宽了。不q,׃它不依赖于GCQ开发h员需要小心内存泄漏。如果忘记在处理E序中释攄冲区Q那么内存用率会无限地增长?/p>

Netty默认不用内存池Q需要在创徏客户端或者服务端的时候进行指定,代码如下Q?/p>

Bootstrap b = new Bootstrap();             b.group(group)              .channel(NioSocketChannel.class)              .option(ChannelOption.TCP_NODELAY, true)              .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)

使用内存池之后,内存的申请和释放必须成对出现Q即retain()和release()要成对出玎ͼ否则会导致内存泄霌Ӏ?/p>

值得注意的是Q如果用内存池Q完成ByteBuf的解码工作之后必L式的调用ReferenceCountUtil.release(msg)Ҏ收缓冲区ByteBufq行内存释放Q否则它会被认ؓ仍然在用中Q这样会D内存泄露?/p>

3.6. 当心“日志隐Ş杀?#8221;

通常情况下,大家都知道不能在Netty的I/OU程上做执行旉不可控的操作Q例如访问数据库、发送Email{。但是有个常用但是非常危险的操作却容易被忽略Q那便是记录日志?/p>

?常,在生产环境中Q需要实时打印接口日志,其它日志处于ERRORU别Q当推送服务发生I/O异常之后Q会记录异常日志。如果当前磁盘的WIO比较高,?能会发生写日志文件操作被同步dQ阻塞时间无法预。这׃DNetty的NioEventLoopU程被阻塞,Socket链\无法被及时关闭、其 它的链\也无法进行读写操作等?/p>

以最常用的log4jZQ尽它支持异步写日志(AsyncAppenderQ,但是当日志队列满之后Q它会同步阻塞业务线E,直到日志队列有空闲位|可用,相关代码如下Q?/p>

 synchronized (this.buffer) {       while (true) {         int previousSize = this.buffer.size();         if (previousSize < this.bufferSize) {           this.buffer.add(event);           if (previousSize != 0) break;           this.buffer.notifyAll(); break;         }         boolean discard = true;         if ((this.blocking) && (!Thread.interrupted()) && (Thread.currentThread() != this.dispatcher)) //判断是业务线E?        {           try           {             this.buffer.wait();//d业务U程             discard = false;           }           catch (InterruptedException e)           {             Thread.currentThread().interrupt();           }          }

cMq类BUGh极强的隐蔽性,往往WIO高的旉持箋非常短,或者是偶现的,在测试环境中很难模拟此类故障Q问题定位难度非常大。这p求读者在qx写代码的时候一定要当心Q注意那些隐性地雗?/p>

3.7. TCP参数优化

常用的TCP参数Q例如TCP层面的接收和发送缓冲区大小讄Q在Netty中分别对应ChannelOption的SO_SNDBUF和SO_RCVBUFQ需要根据推送消息的大小Q合理设|,对于量长连接,通常32K是个不错的选择?/p>

另外一个比较常用的优化手段是软中断,如图所C:如果所有的软中断都q行在CPU0相应|卡的硬件中断上Q那么始l都是cpu0在处理Y中断Q而此时其它CPU资源p费了,因ؓ无法q行的执行多个Y中断?/p>

Netty百万U推送服? src=

?-3 中断信息

?于等?.6.35版本的Linux kernel内核Q开启RPSQ网l通信性能提升20%之上。RPS的基本原理:Ҏ数据包的源地址Q目的地址以及目的和源端口Q计出一个hash| 然后Ҏq个hash值来选择软中断运行的cpu。从上层来看Q也是说将每个q接和cpul定Qƈ通过q个hash|来均衡Y中断q行在多个cpu 上,从而提升通信性能?/p>

3.8. JVM参数

最重要的参数调整有两个Q?/p>

  • -Xmx:JVM最大内存需要根据内存模型进行计ƈ得出相对合理的|
  • GC相关的参? 例如新生代和老生代、永久代的比例,GC的策略,新生代各区的比例{,需要根据具体的场景q行讄和测试,q不断的优化Q尽量将Full GC的频率降到最低?/li>

4. 作者简?/h2>

李林锋,2007q毕业于东北大学Q?008q进入华为公总事高性能通信软g的设计和开发工作,?qNIO设计和开发经验,_NNetty、Mina{NIO框架。Netty中国C֌创始人,《Netty权威指南》作者?/p>

疯狂 2016-07-13 10:03 发表评论
]]>Netty 概述Q{Q?/title><link>http://www.dentisthealthcenter.com/freeman1984/archive/2016/07/13/431176.html</link><dc:creator>疯狂</dc:creator><author>疯狂</author><pubDate>Wed, 13 Jul 2016 01:49:00 GMT</pubDate><guid>http://www.dentisthealthcenter.com/freeman1984/archive/2016/07/13/431176.html</guid><wfw:comment>http://www.dentisthealthcenter.com/freeman1984/comments/431176.html</wfw:comment><comments>http://www.dentisthealthcenter.com/freeman1984/archive/2016/07/13/431176.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/431176.html</wfw:commentRss><trackback:ping>http://www.dentisthealthcenter.com/freeman1984/services/trackbacks/431176.html</trackback:ping><description><![CDATA[<div>转蝲自http://blog.csdn.net/zxhoo/article/details/17264263<br /><h2>Netty4</h2><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><a target="_blank" style="color: #ca0000; text-decoration: none;">Netty</a>是一个和<a target="_blank" style="color: #ca0000; text-decoration: none;">MINA</a>cM的Java NIO框架Q目前的最新版本是<a target="_blank" style="color: #ca0000; text-decoration: none;">4.0.13</a>Q这两个框架的主要作者好像都?a target="_blank" style="color: #ca0000; text-decoration: none;">同一个韩国h</a>?/p><h2 id="articleHeader0" style="box-sizing: border-box; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-weight: 500; line-height: 1.1; color: #404040; margin-top: 20px; margin-bottom: 10px; font-size: 1.75em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #eeeeee; padding: 0px 0px 5px; background-color: #ffffff;"><span style="box-sizing: border-box; line-height: 43.2px; font-size: 24px; font-weight: 600;">Channel</span></h2><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">Channel是Netty最核心的接口,一个Channel是一个联lSocket的通道Q通过ChannelQ你可以对Socketq行各种操作?/p><h2>ChannelHandler</h2><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">用Netty~写|络E序的时候,你很直接操UChannelQ而是通过ChannelHandler来间接操UChannel?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">Netty中的所有handler都实现自<span style="box-sizing: border-box; line-height: 28.8px; text-decoration: underline;"><span style="box-sizing: border-box; font-weight: 700;">ChannelHandler接口</span></span>。按照输出来分,分ؓ<span style="box-sizing: border-box; line-height: 28.8px; text-decoration: underline;"><span style="box-sizing: border-box; font-weight: 700;">ChannelInboundHandler、ChannelOutboundHandler两大c?/span></span>?/p><blockquote style="box-sizing: border-box; padding-top: 10px; padding-right: 0px; padding-bottom: 1px; margin: 20px 0px 20px 20px; border-left-width: 5px; border-left-color: #eeeeee; max-width: 650px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; line-height: 28.8px; font-size: 12px !important; background-color: #f5f5f5;"><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 21.6px; color: #555555;">ChannelInboundHandler对从客户端发往服务器的报文q行处理Q一般用来执行解码、读取客L数据、进行业务处理等Q?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 21.6px; color: #555555;">ChannelOutboundHandler对从服务器发往客户端的报文q行处理Q一般用来进行编码、发送报文到客户端?/p></blockquote><h2>ChannelPipeline</h2><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">ChannelPipeline实际上应该叫做ChannelHandlerPipelineQ可以把ChannelPipeline看成是一个ChandlerHandler的链表,当需要对Channelq行某种处理的时候,Pipeline负责依次调用每一个Handlerq行处理。每个Channel都有一个属于自qPipelineQ调用Channel#pipeline()Ҏ可以获得Channel的PipelineQ调用Pipeline#channel()Ҏ可以获得Pipeline的Channel?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"><img alt="netty概述" src="http://static.open-open.com/lib/uploadImg/20140528/20140528094120_258.jpg" width="676" height="166" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%;" /></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">ChannelPipeline的方法有很多Q其中一部分是用来管理ChannelHandler的,如下面这些:</p><pre true;="" auto-links:="" false;"="" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13.6px; padding: 6px; margin-top: 0px; margin-bottom: 10px; line-height: 1.45; color: #333333; word-break: break-all; word-wrap: break-word; border: none; border-radius: 3px; background-color: #f6f6f6;">ChannelPipeline addFirst(String name, ChannelHandler handler); ChannelPipeline addLast(String name, ChannelHandler handler); ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler); ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler); ChannelPipeline remove(ChannelHandler handler); ChannelHandler remove(String name); ChannelHandler removeFirst(); ChannelHandler removeLast(); ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler); ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler); ChannelHandler first(); ChannelHandler last(); ChannelHandler get(String name);</pre><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"></p><h2>ChannelHandlerContext</h2><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">ChannelPipelineq不是直接管理ChannelHandlerQ而是通过ChannelHandlerContext来间接管理,q一炚w过ChannelPipeline的默认实现DefaultChannelPipeline可以看出来?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"><img alt="netty概述" src="http://static.open-open.com/lib/uploadImg/20140528/20140528094121_162.jpg" width="692" height="220" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%;" /></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">调用<span style="box-sizing: border-box; font-weight: 700;">ChannelHandlerContext#channel()</span>Ҏ可以得到和Contextl定的ChannelQ调?span style="box-sizing: border-box; font-weight: 700;">ChannelHandlerContext#handler()</span>Ҏ可以得到和Contextl定的Handler?/p><h2>ChannelPipeline和ChannelHandlerContext默认实现</h2><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">DefaultChannelHandlerContext和DefaultChannelPipeline是ChannelHandlerContext和ChannelPipeline的默认实玎ͼ下面是它们的部分代码Q?/p><pre true;="" auto-links:="" false;"="" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13.6px; padding: 6px; margin-top: 0px; margin-bottom: 10px; line-height: 1.45; color: #333333; word-break: break-all; word-wrap: break-word; border: none; border-radius: 3px; background-color: #f6f6f6;">final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {     volatile DefaultChannelHandlerContext next;     volatile DefaultChannelHandlerContext prev;     private final boolean inbound;     private final boolean outbound;     private final AbstractChannel channel;     private final DefaultChannelPipeline pipeline;     private final String name;     private final ChannelHandler handler;     private boolean removed;     // ... }</pre><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"></p><pre true;="" auto-links:="" false;"="" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13.6px; padding: 6px; margin-top: 0px; margin-bottom: 10px; line-height: 1.45; color: #333333; word-break: break-all; word-wrap: break-word; border: none; border-radius: 3px; background-color: #f6f6f6;">final class DefaultChannelPipeline implements ChannelPipeline {     // ...     final DefaultChannelHandlerContext head;     final DefaultChannelHandlerContext tail;     // ... }</pre><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"><span style="box-sizing: border-box; line-height: 23px;">从上面的代码可以看出Q在DefaultPipeline内部QDefaultChannelHandlerContextl成了一个双向链表:</span></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"><img alt="netty概述" src="http://static.open-open.com/lib/uploadImg/20140528/20140528094121_321.jpg" width="798" height="217" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; width: 738px; height: 190px;" /></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">再来看看DefaultChannelPipeline的构造函敎ͼ</p><pre true;="" auto-links:="" false;"="" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13.6px; padding: 6px; margin-top: 0px; margin-bottom: 10px; line-height: 1.45; color: #333333; word-break: break-all; word-wrap: break-word; border: none; border-radius: 3px; background-color: #f6f6f6;">    public DefaultChannelPipeline(AbstractChannel channel) {         if (channel == null) {             throw new NullPointerException("channel");         }         this.channel = channel;         TailHandler tailHandler = new TailHandler();         tail = new DefaultChannelHandlerContext(this, null, generateName(tailHandler), tailHandler);         HeadHandler headHandler = new HeadHandler(channel.unsafe());         head = new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler);         head.next = tail;         tail.prev = head;     }</pre><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">可以看到QDefaultChinnelPipeline内部使用了两个特D的Handler来表CHandler铄头和:</p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"><img alt="netty概述" src="http://static.open-open.com/lib/uploadImg/20140528/20140528094121_487.jpg" width="991" height="262" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; width: 837px; height: 188px;" /></p><h2>ChannelHandler的种c?/h2><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">Netty中的所有handler都实现自ChannelHandler接口。按照输出来分,分ؓChannelInboundHandler、ChannelOutboundHandler两大cRChannelInboundHandler对从客户端发往服务器的报文q行处理Q一般用来执行解码、读取客L数据、进行业务处理等QChannelOutboundHandler对从服务器发往客户端的报文q行处理Q一般用来进行编码、发送报文到客户端?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">从上面DefaultChannelHandlerContext代码可以知道QHandler实际上分ZU,Inbound和OutboundQ这一点也可以从ChannelHandler接口的子接口得到证明Q?/p><pre true;="" auto-links:="" false;"="" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13.6px; padding: 6px; margin-top: 0px; margin-bottom: 10px; line-height: 1.45; color: #333333; word-break: break-all; word-wrap: break-word; border: none; border-radius: 3px; background-color: #f6f6f6;">public interface ChannelInboundHandler extends ChannelHandler {   // ... } public interface ChannelOutboundHandler extends ChannelHandler {   // ... }</pre><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"></p><h2><br style="box-sizing: border-box; line-height: 10px;" /></h2><h2>事g的传?/h2><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">Z搞清楚事件如何在Pipeline里传播,让我们从Channel的抽象子cAbstractChannel开始,下面是AbstractChannel#write()Ҏ的实玎ͼ</p><pre true;="" auto-links:="" false;"="" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13.6px; padding: 6px; margin-top: 0px; margin-bottom: 10px; line-height: 1.45; color: #333333; word-break: break-all; word-wrap: break-word; border: none; border-radius: 3px; background-color: #f6f6f6;">public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {     // ...     @Override     public Channel write(Object msg) {         return pipeline.write(msg);     }     // ... }</pre><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">AbstractChannel直接调用了Pipeline的write()ҎQ?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"><img alt="netty概述" src="http://static.open-open.com/lib/uploadImg/20140528/20140528094121_93.jpg" width="1002" height="259" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; width: 867px; height: 178px;" /></p><pre true;="" auto-links:="" false;"="" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13.6px; padding: 6px; margin-top: 0px; margin-bottom: 10px; line-height: 1.45; color: #333333; word-break: break-all; word-wrap: break-word; border: none; border-radius: 3px; background-color: #f6f6f6;">final class DefaultChannelPipeline implements ChannelPipeline {     // ...     @Override     public ChannelFuture write(Object msg) {         return tail.write(msg);     }     // ... }</pre><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">因ؓwrite是个outbound事gQ所以DefaultChannelPipeline直接扑ֈtail部分的contextQ调用其write()ҎQ?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"><img alt="netty概述" src="http://static.open-open.com/lib/uploadImg/20140528/20140528094121_417.jpg" width="990" height="296" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; width: 846px; height: 213px;" /></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"><span style="box-sizing: border-box; line-height: 26px; font-family: Arial; font-size: 14px;">接着看DefaultChannelHandlerContext的write()ҎQ?/span></p><pre true;="" auto-links:="" false;"="" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13.6px; padding: 6px; margin-top: 0px; margin-bottom: 10px; line-height: 1.45; color: #333333; word-break: break-all; word-wrap: break-word; border: none; border-radius: 3px; background-color: #f6f6f6;">final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {     // ...     @Override     public ChannelFuture write(Object msg) {         return write(msg, newPromise());     }     @Override     public ChannelFuture write(final Object msg, final ChannelPromise promise) {         if (msg == null) {             throw new NullPointerException("msg");         }         validatePromise(promise, true);         write(msg, false, promise);         return promise;     }     private void write(Object msg, boolean flush, ChannelPromise promise) {         DefaultChannelHandlerContext next = findContextOutbound();         next.invokeWrite(msg, promise);         if (flush) {             next.invokeFlush();         }     }     private DefaultChannelHandlerContext findContextOutbound() {         DefaultChannelHandlerContext ctx = this;         do {             ctx = ctx.prev;         } while (!ctx.outbound);         return ctx;     }     private void invokeWrite(Object msg, ChannelPromise promise) {         try {             ((ChannelOutboundHandler) handler).write(this, msg, promise);         } catch (Throwable t) {             notifyOutboundHandlerException(t, promise);         }     }     // ... }</pre><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">context的write()Ҏ沿着context铑־前找Q直xC个outboundcd的context为止Q然后调用其invokeWrite()ҎQ?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"><img alt="netty概述" src="http://static.open-open.com/lib/uploadImg/20140528/20140528094121_595.jpg" width="979" height="409" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; width: 846px; height: 352px;" /></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">invokeWrite()接着调用handler的write()ҎQ?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"><img alt="netty概述" src="http://static.open-open.com/lib/uploadImg/20140528/20140528094121_617.jpg" width="985" height="427" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; width: 795px; height: 348px;" /></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">最后看看ChannelOutboundHandlerAdapter的write()Ҏ实现Q?/p><pre true;="" auto-links:="" false;"="" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13.6px; padding: 6px; margin-top: 0px; margin-bottom: 10px; line-height: 1.45; color: #333333; word-break: break-all; word-wrap: break-word; border: none; border-radius: 3px; background-color: #f6f6f6;">public class ChannelOutboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelOutboundHandler {     // ...     @Override     public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {         ctx.write(msg, promise);     }     // ... }</pre><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">默认的实现调用了context的write()Ҏ而不做Q何处理,q样write事g沿着outbound铄l传播:</p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;"><img alt="netty概述" src="http://static.open-open.com/lib/uploadImg/20140528/20140528094122_946.jpg" width="989" height="430" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; width: 717px; height: 295px;" /></p><p style="box-sizing: border-box; margin: 0px 0px 25px; line-height: 28.8px; color: #404040; font-family: "Microsoft YaHei", Verdana, sans-serif, SimSun; font-size: 16px; background-color: #ffffff;">可见QPipeline的事件传播,是靠PipelineQContext和Handler共同协作完成的?/p></div><img src ="http://www.dentisthealthcenter.com/freeman1984/aggbug/431176.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.dentisthealthcenter.com/freeman1984/" target="_blank">疯狂</a> 2016-07-13 09:49 <a href="http://www.dentisthealthcenter.com/freeman1984/archive/2016/07/13/431176.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Netty优雅退出机制和原理Q{Q?/title><link>http://www.dentisthealthcenter.com/freeman1984/archive/2016/07/13/431175.html</link><dc:creator>疯狂</dc:creator><author>疯狂</author><pubDate>Wed, 13 Jul 2016 01:39:00 GMT</pubDate><guid>http://www.dentisthealthcenter.com/freeman1984/archive/2016/07/13/431175.html</guid><wfw:comment>http://www.dentisthealthcenter.com/freeman1984/comments/431175.html</wfw:comment><comments>http://www.dentisthealthcenter.com/freeman1984/archive/2016/07/13/431175.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/431175.html</wfw:commentRss><trackback:ping>http://www.dentisthealthcenter.com/freeman1984/services/trackbacks/431175.html</trackback:ping><description><![CDATA[     摘要: 转蝲自:http://www.infoq.com/cn/articles/netty-elegant-exit-mechanism-and-principles1.q程的优雅退?.1.Kill -9 PID带来的问题在Linux上通常会通过kill -9 pid的方式强制将某个q程杀掉,q种方式单高效,因此很多E序的停止脚本经怼选择使用kill -9 pid的方式。无论是Linux的Kill...  <a href='http://www.dentisthealthcenter.com/freeman1984/archive/2016/07/13/431175.html'>阅读全文</a><img src ="http://www.dentisthealthcenter.com/freeman1984/aggbug/431175.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.dentisthealthcenter.com/freeman1984/" target="_blank">疯狂</a> 2016-07-13 09:39 <a href="http://www.dentisthealthcenter.com/freeman1984/archive/2016/07/13/431175.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用JavaMail SearchTerm 收取邮ghttp://www.dentisthealthcenter.com/freeman1984/archive/2016/02/02/429278.html疯狂疯狂Tue, 02 Feb 2016 08:08:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2016/02/02/429278.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/429278.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2016/02/02/429278.html#Feedback1http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/429278.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/429278.htmlJavaMail在javax.mail.search包中定义了一个用于创建搜索条件的SearchTermc,应用E序创徏SearchTermcȝ实例对象后,可以调用Folder.Search(SearchTerm st)Ҏ搜烦邮g夹中W合搜烦条g的所有邮件。SearchTerm是一个抽象类QJavaMail提供?2个实现子cM帮助应用E序创徏不同的搜索条Ӟq?2个类可分Z大类型,如下所C:

1、用于创建逻辑l合关系的类

  • AND条gQAndTermc)
  • OR条gQOrTermc)
  • NOT条gQNotTermc)
  • Comparison条gQComparisonTermc)

2、用于创建具体搜索条件的c?/p>

  • DATE条gQSentDateTerm、ReceivedDateTermc)
  • CONTENT条gQBodyTermc)
  • HEADER条gQFromStringTerm、RecipientStringTerm、SubjectTermcȝQ?/li>

下面通过实现来说明以上类的用法及含义Q?/p>

1、搜索发件h?#8220;招聘“Q而且邮g正文包含“Java工程?#8220;的所有邮?/p>

SearchTerm andTerm = new AndTerm( new FromStringTerm("招聘"), new BodyTerm("java工程?)); Message[] messages = folder.search(andTerm); 

2、搜索发件h?#8220;招聘“或主题包?#8220;最新职位信?#8220;的所有邮?/p>

SearchTerm orTerm = new OrTerm( new FromStringTerm("招聘"), new SubjectTerm("最新职位信?)); Message[] messages = folder.search(orTerm); 

3、搜索发件h不包?#8220;招聘“所有的邮g

SearchTerm notTerm = new NotTerm(new FromStringTerm("招聘")); Message[] messages = folder.search(notTerm); 

4、搜索周一C天收到的的所有邮?/p>

Calendar calendar = Calendar.getInstance();  
calendar.set(Calendar.DAY_OF_WEEK, calendar.get(Calendar.DAY_OF_WEEK - (Calendar.DAY_OF_WEEK - 1)) - 1); 
Date mondayDate = calendar.getTime(); 
SearchTerm comparisonTermGe = new SentDateTerm(ComparisonTerm.GE, mondayDate); 
SearchTerm comparisonTermLe = new SentDateTerm(ComparisonTerm.LE, new Date()); 
SearchTerm comparisonAndTerm = new AndTerm(comparisonTermGe, comparisonTermLe); 
Message[] messages = folder.search(comparisonAndTerm); 

5、搜索大于或{?00KB的所有邮?/p>

int mailSize = 1024 * 100; SearchTerm intComparisonTerm = new SizeTerm(IntegerComparisonTerm.GE, mailSize); 
Message[] messages = folder.search(intComparisonTerm); 

ComparisonTermcd用于日期和数字比较中Q它使用六个帔REQQ=Q、GEQ?gt;=Q、GTQ?gt;Q、LEQ?lt;=Q、LTQ?lt;Q、NEQ?=Q来表示六种不同的比较操作?/p>

下面是完整代码:

import java.io.BufferedReader;   
import java.io.InputStreamReader;   
import java.util.Calendar;   
import java.util.Date;   
import java.util.Properties;   

import javax.mail.Flags.Flag;   
import javax.mail.Folder;   
import javax.mail.Message;   
import javax.mail.Session;   
import javax.mail.Store;   
import javax.mail.URLName;   
import javax.mail.internet.MimeMessage;   
import javax.mail.internet.MimeUtility;   
import javax.mail.search.AndTerm;   
import javax.mail.search.BodyTerm;   
import javax.mail.search.ComparisonTerm;   
import javax.mail.search.FromStringTerm;   
import javax.mail.search.IntegerComparisonTerm;   
import javax.mail.search.NotTerm;   
import javax.mail.search.OrTerm;   
import javax.mail.search.SearchTerm;   
import javax.mail.search.SentDateTerm;   
import javax.mail.search.SizeTerm;   
import javax.mail.search.SubjectTerm;   

/** 
 * 搜烦邮g 
 
*/   
public class SearchMailTest {   

    public static void main(String[] args) throws Exception {   
        Properties props = new Properties();   
        props.setProperty("mail.pop3.auth", "true");   
        Session session = Session.getInstance(props);   
        URLName url = new URLName("pop3", "pop3.163.com", 110, null, "xyang81@163.com", "yX546900873");   
        Store store = session.getStore(url);   
        store.connect();   
        // 得到收g?nbsp;  
        Folder folder = store.getFolder("INBOX");   
        // 以读写模式打开收g?nbsp;  
        folder.open(Folder.READ_WRITE);   

        Message[] messages = search(folder);   

        System.out.println("收g׃共有:" + folder.getMessageCount() + "邮Ӟ搜烦? + messages.length + "符合条件的邮g!");   

        // 解析邮g搜烦到的邮g   
        POP3ReceiveMailTest.parseMessage(messages);    

        // Ҏ用户输入的条件搜索所有邮?q提C用h否删?nbsp;  
        
//searchDemo(folder);   

        folder.close(true);   
        store.close();   
    }   
             www.2cto.com  
    public static Message[] search(Folder folder) throws Exception {   
        // 搜烦主题包含食的邮?nbsp;  
        String subject = "java培训";   
        SearchTerm subjectTerm = new SubjectTerm(subject);   

        // 搜烦发g人包含支付宝的邮?nbsp;  
        SearchTerm fromTerm = new FromStringTerm("支付?);   

        // 搜烦邮g内容包含"招聘"的邮?nbsp;  
        SearchTerm bodyTerm = new BodyTerm("招聘");   

        // 搜烦发gZ包含“招聘”的邮?nbsp;  
        SearchTerm notTerm = new NotTerm(new FromStringTerm("招聘"));   

        // 搜烦发gZؓ“招聘”Q而且内容包含“Java工程?#8220;的邮?nbsp;  
        SearchTerm andTerm = new AndTerm(   
                new FromStringTerm("招聘"),   
                new BodyTerm("java工程?));   

        // 搜烦发gZؓ”招聘“或主题包?#8221;最新职位信?#8220;的邮?nbsp;  
        SearchTerm orTerm = new OrTerm(   
                new FromStringTerm("招聘"),    
                new SubjectTerm("最新职位信?));   

        // 搜烦周一C天收到的的所有邮?nbsp;  
        Calendar calendar = Calendar.getInstance();   
        calendar.set(Calendar.DAY_OF_WEEK, calendar.get(Calendar.DAY_OF_WEEK - (Calendar.DAY_OF_WEEK - 1)) - 1);   
        Date mondayDate = calendar.getTime();   
        SearchTerm comparisonTermGe = new SentDateTerm(ComparisonTerm.GE, mondayDate);   
        SearchTerm comparisonTermLe = new SentDateTerm(ComparisonTerm.LE, new Date());   
        SearchTerm comparisonAndTerm = new AndTerm(comparisonTermGe, comparisonTermLe);   

        // 搜烦大于或等100KB的所有邮?nbsp;  
        int mailSize = 1024 * 100;   
        SearchTerm intComparisonTerm = new SizeTerm(IntegerComparisonTerm.GE, mailSize);   

        return folder.search(intComparisonTerm);   
    }   
 }   
实例Q根据用戯入的收g人(email地址或姓名)和主题作为搜索条Ӟq提C用h否删除搜索到的邮Ӟ  
[java] view plaincopy  
/** 
     * Ҏ用户输入的收件h地址Q包括email地址和姓名)和主题作为搜索条Ӟq提C用h否删除搜索到的邮?nbsp;
     * 
@param from 收g?nbsp;
     * 
@param subject 主题 
     
*/   
    public static void searchDemo(Folder folder) throws Exception {   
        String notifyMsg = "收g׃一共有" + folder.getMessageCount() + "邮件。请选择操作Q\n";   
        notifyMsg += "1、输入收件h\n" + "2、输入主题\n" + "3、开始搜索\n" + "4、退?;   
        System.out.println(notifyMsg);   
        String from = null;   
        String subject = null;   
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));   
        String oper = reader.readLine().trim();   
        while(!(from != null && subject != null)) {   
            if ("4".equals(oper)) {   
                System.exit(0);   
            } else {   
                if ("1".equals(oper)) {   
                    System.out.print("误入收件hQ?);   
                    from = reader.readLine();   
                }  else if ("2".equals(oper)) {   
                    System.out.print("误入主题:");   
                    subject = reader.readLine();   
                } else if ("3".equals(oper)) {   
                    if (from == null || subject == null) {   
                        System.out.println("未输入搜索条Ӟ无法q行搜烦Q?);   
                    } else {   
                        break;   
                    }   
                }   
            }   
            System.out.print("请选择操作Q?);   
            oper = reader.readLine().trim();   
        }   

        System.out.println("\npȝ正在Ҏ搜烦条g查询所有邮ӞL?img src="http://www.dentisthealthcenter.com/Images/dot.gif" alt="" />\n");   

        // Ҏ输入的条Ӟ创徏SearchTerm实例对象   
        SearchTerm orTerm = new OrTerm(   
                new FromStringTerm(from),   
                new SubjectTerm(subject)   
                );   

        // Ҏ搜烦条g得到搜烦到的邮g列表   
        Message[] messages = folder.search(orTerm);   

        System.out.println("共搜索到" + messages.length + "满x索条件的邮gQ\n\n请选择操作Q?、查看邮件\t 2、删除所有邮?);   

        String deleteQuestion = "是否要删除搜索到的邮?(yes/no)";   

        String searchResultOper = reader.readLine();   

        if ("1".equals(searchResultOper)) {   
            for (Message message : messages) {   
                MimeMessage msg = (MimeMessage) message;   
                String sub = POP3ReceiveMailTest.getSubject(msg);   
                System.out.println("开始查看第" + msg.getMessageNumber() + "邮?img src="http://www.dentisthealthcenter.com/Images/dot.gif" alt="" />");   
                System.out.println("主题: " + sub);   
                System.out.println("发g? " + POP3ReceiveMailTest.getFrom(msg));   
                System.out.println("收g人:" + POP3ReceiveMailTest.getReceiveAddress(msg, null));   
                System.out.println("发送时_" + POP3ReceiveMailTest.getSentDate(msg, null));   
                System.out.println(deleteQuestion);   
                String answer = reader.readLine();   
                if ("yes".equals(answer)) {   
                    msg.setFlag(Flag.DELETED, true);   
                    System.out.println("邮g[" + sub + "]删除成功!");   
                } else if ("no".equals(answer)) {   
                    System.out.println("W? + msg.getMessageNumber() + "邮件查看完成!");   
                } else if ("stop".equals(answer)) {   
                    System.exit(0);   
                }   
                System.out.println();   
            }   
        } else {   
            System.out.println(deleteQuestion);   
            String answer = reader.readLine();   
            if ("yes".equals(answer)) {   
                for (Message message : messages) {   
                    String sub = MimeUtility.decodeText(message.getSubject());   
                    message.setFlag(Flag.DELETED, true);   
                    System.out.println("邮g[" + sub + "]删除成功!");   
                }   
            }   
        }   
    }
}


疯狂 2016-02-02 16:08 发表评论
]]>
JAVA Thread Dump 分析lDhttp://www.dentisthealthcenter.com/freeman1984/archive/2015/12/14/428645.html疯狂疯狂Mon, 14 Dec 2015 10:04:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2015/12/14/428645.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/428645.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2015/12/14/428645.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/428645.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/428645.html阅读全文

疯狂 2015-12-14 18:04 发表评论
]]>
oracle 索引字段包含datecdQ用spring jdbc更新时不走烦引,而是走table access full的问?/title><link>http://www.dentisthealthcenter.com/freeman1984/archive/2015/11/15/428197.html</link><dc:creator>疯狂</dc:creator><author>疯狂</author><pubDate>Sat, 14 Nov 2015 16:04:00 GMT</pubDate><guid>http://www.dentisthealthcenter.com/freeman1984/archive/2015/11/15/428197.html</guid><wfw:comment>http://www.dentisthealthcenter.com/freeman1984/comments/428197.html</wfw:comment><comments>http://www.dentisthealthcenter.com/freeman1984/archive/2015/11/15/428197.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/428197.html</wfw:commentRss><trackback:ping>http://www.dentisthealthcenter.com/freeman1984/services/trackbacks/428197.html</trackback:ping><description><![CDATA[     摘要: oracle 索引字段包含datecdQ用spring jdbc更新时不走烦引,而是走table access full的问?nbsp; <a href='http://www.dentisthealthcenter.com/freeman1984/archive/2015/11/15/428197.html'>阅读全文</a><img src ="http://www.dentisthealthcenter.com/freeman1984/aggbug/428197.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.dentisthealthcenter.com/freeman1984/" target="_blank">疯狂</a> 2015-11-15 00:04 <a href="http://www.dentisthealthcenter.com/freeman1984/archive/2015/11/15/428197.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FTPd模式和被动模式的比较(转蝲)http://www.dentisthealthcenter.com/freeman1984/archive/2015/02/07/422809.html疯狂疯狂Sat, 07 Feb 2015 05:06:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2015/02/07/422809.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/422809.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2015/02/07/422809.html#Feedback1http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/422809.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/422809.html我们在上传文件或囄C机的时候,都不可避免的用到FTP软gq个上传工具。在上传的时候,有两U传输方式大家一定不会不熟悉Q那是d模式和被动模式,他们的英文简写是Port和Pasv。常常有客户无法上传的时候,我们都会告诉他们Q把FTP软g被动模式前面的钩L再试试。这说明QFTP软g默认是用被动模式的Q这U传输模式较先进一些。而有些客h法在q种模式下上传的原因Q往往是由于他们电脑中安装了防火墙、杀毒Y件或者他们电脑所在的局域网做了Ҏ限制造成?/p>

首先我们要知道,我们在用FTP上传、删除、修Ҏ件的时候其实要l过两个q程。一个是命oq接Q一个是数据传输?strong>命oq接的过E是我们电脑->服务器,通常是我们电脑中一个随机的大于1024的端?>服务器的21端口。我们熟知的FTP?1端口是命oq接时所必需的。对于这d和被动这两种上传模式而言Q命令连接的q程是完全相同的Q其区别在数据传输q程中。主动模式下Q当需要传送数据时Q客L在命令连接上用PORT命o告诉服务器:&ldquo;我打开了XXXX端口Q通常是一个随机的大于1024的端口)Q你q来q接?amp;rdquo;。于是服务器?0端口向客L的这个端口发送连接请求,建立一条数据连接来传送数据,q就是服务器->客户电脑的过E。而在被动模式下,服务器在命oq接上用PASV命o告诉客户端:&ldquo;我打开了XXXX端口Q通常是在FTP服务端设|的一个高位端口范_Q你q来q接?amp;rdquo;。于是客L向服务器的这个端口范围发送连接请求,建立一条数据连接来传送数据?/p>

一句话Q主动模式的FTP是指服务器主动连接客L的数据端口,被动模式的FTP是指服务器被动地{待客户端连接自q数据端口。故通过防火墙对高位端口的阻塞,会造成d模式受限Q被动模式比较先q。另外通过讄被动模式的端口范_只开放一定的端口对外传输数据Q也大大减少了服务器安全性暴露的风险?/p>

那么Q在哪里讄被动模式的端口范围呢。Windows环境下的IIS FTP的设|方法是Q打开C:\WINDOWS\system32\inetsrv\MetaBase.xmlQ当焉先要停止IIS Admin Service服务。然后编辑这个文仉?lt;IIsFtpService>区块下的PassivePortRangeQ比如设|成PassivePortRange="50030-50039"Q这指定了10个端口来传输数据。而Linux环境下的ProFTP的设|方法是Q打开proftp的配|文Ӟ命o是vi /etc/proftpd.confQ然后在<Global>区块里面dPassivePorts 50030 50039q样的一D|字,也和上面IIS中的端口讄是一L功能?/p>

最后在说下q两U模式的优缺炏V主动模式对FTP服务器的理有利Q但对客L的管理不利。因为FTP服务器企图与客户端的高位随机端口建立q接Q而这个端口很有可能被客户端的防火墙阻塞掉。被动模式对FTP客户端的理有利Q但Ҏ务器端的理不利。因为客L要与服务器端建立两个q接Q其中一个连C个高位随机端口,而这个端口很有可能被服务器端的防火墙d掉。比较明智的Ҏ是,同时做好服务器和客户电脑的安全设|,量不要开防火墙,p比较利的通过FTP上传和管理我们的文g?/p>

疯狂 2015-02-07 13:06 发表评论
]]>
关于java RMI在多|卡?或者启?60Q百度,腾讯{wifi׃n?无法q接问题(java.rmi.ConnectException: Connection refused to host: xx)http://www.dentisthealthcenter.com/freeman1984/archive/2014/12/05/421085.html疯狂疯狂Fri, 05 Dec 2014 06:08:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2014/12/05/421085.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/421085.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2014/12/05/421085.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/421085.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/421085.html场景Qjava RMI 在服务端者启?60 wifi׃nQ报错java.rmi.ConnectException: Connection refused to host: xx?br />         也就是服务端在调用时使用了wifi׃n|卡的地址。此地址在RMI客户端pc上无法ping通。(因ؓ没有q接此wifi。当然RMI客户端pc如果q接此wifi是不会报错的Q?br />惛_资料Q?br />
http://docs.huihoo.com/java/rmi/whitepage/index.html
比较全的解释RMI的英文资料:http://docs.oracle.com/javase/1.5.0/docs/guide/rmi/faq.html#netunknownhost
http://www.dentisthealthcenter.com/shaolijun/archive/2007/05/22/119213.html

试代码Q?br />
(一)服务端:
  • 服务接口
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
 * rmi remote 接口
 * 
@author joe
 * @2014-12-5 @上午11:49:10
 
*/
public interface RmiInterface extends Remote{
    
    public String say(String name) throws RemoteException;

}
  • 接口实现
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;


public class RmiServer extends UnicastRemoteObject implements RmiInterface{
    
    private static final long serialVersionUID = 1L;

    protected RmiServer() throws RemoteException {
        super();
    }

    public String say(String name) throws RemoteException {
        return "helloQ?+name;
    }
}
  • 发布服务
public static void main(String[] args) throws MalformedURLException, RemoteException, AlreadyBoundException {
        RmiServer server=new RmiServer();
        LocateRegistry.createRegistry(8808);  
        Naming.rebind("http://10.10.XX.XX:8808/SAMPLE-SERVER", server);  
    }

(?客户?调用服务Q?br />
public static void main(String[] args) throws Exception {
        RmiInterface server=(RmiInterface) Naming.lookup("http://10.10.116.XX:8808/SAMPLE-SERVER");
        System.out.println(server.say("张三"));
    }

此时报错Qjava.rmi.ConnectException: Connection refused to host: 192.168.23.X?br />
RMI的调用原理基本如下:

大致译如下Q首先客L必须通过Naming.lookup得到服务端服务的一个指针或者叫指针Q一旦拥有的q个应用Q客L用服务的引用里面包含的主机名(ip)和端口来讉K服务?br />    也就是说Q虽然我们就服务端的IP和端口去Naming.lookup("http://10.10.116.XX:8808/SAMPLE-SERVER");Q但是服务端q回的服务的引用里面包含的ipq不是lookup时的ip?br />官方说法Q?br />【In many versions of the JDK (all versions of the JDK except in v1.1 and the latest releases), Java RMI may default to using an unresolvable server hostname (for example: unqualified names, Windows Internet Naming Service (WINS) names, or unqualified DHCP names). When a Java RMI client invokes a remote method using a reference that contains an unresolvable server hostname, the client will throw an UnknownHostException.?/span>

In order to generate functional remote references, Java RMI servers must be able to supply a fully qualified hostname or IP address that is resolvable from all Java RMI clients (an example of a fully qualified hostname is foo.bar.com). If a Java RMI program provides a remote callback operation, then that program serves a Java RMI object and consequently, must be able to determine a resolvable hostname to use as its server hostname in the remote references it passes to Java RMI clients. VMs that make calls to applets that serve remote objects may throwUnknownHostExceptions because the applet has failed to provide a usable server hostname.

If your Java RMI application throws an UnknownHostException, you can look at the resulting stack trace to see if the hostname that the client is using to contact its remote server is incorrect or not fully qualified.?nbsp;If necessary, you can set the java.rmi.server.hostname property on the server to the correct IP address or hostname of the server machine and Java RMI will use this property's value to generate remote references to the server.?/strong>

解决办法是在服务端发布注册服务的之前设|:
System.setProperty("java.rmi.server.hostname", 指定IP);

对应到本文例子就是:
public static void main(String[] args) throws MalformedURLException, RemoteException, AlreadyBoundException {
        RmiServer server=new RmiServer();
        System.setProperty("java.rmi.server.hostname", 指定IP);
        LocateRegistry.createRegistry(8808);  
        Naming.rebind("http://10.10.116.74:8808/SAMPLE-SERVER", server);  
    }

但是此时q是报相同的错没法访问,百思不得其解,原来java.rmi.server.hostname的设|必d服务对象创徏之前?br />
public static void main(String[] args) throws MalformedURLException, RemoteException, AlreadyBoundException {
        System.setProperty("java.rmi.server.hostname", 指定IP);
        RmiServer server=new RmiServer();
        LocateRegistry.createRegistry(8808);  
        Naming.rebind("http://10.10.116.74:8808/SAMPLE-SERVER", server);  
    }
Z么呢Q?br />    RmiServer q个实现cM用了UnicastRemoteObject去联接RMIpȝ。在我们的例子中Q我们是直接的从UnicastRemoteObjectq个cMl承的,事实上ƈ不一定要q样做,当然也可以不是从UnicastRmeoteObject上承,那必M用它的exportObject()Ҏ去联接到RMI。如果一个类l承自UnicastRemoteObjectQ那么它必须提供一个构造函数ƈ且声明抛Z个RemoteException对象。当q个构造函数调用了super()Q它久激zUnicastRemoteObject中的代码完成RMI的连接和q程对象的初始化。而此时应该已l决定了使用哪个hostname来实例化q程对象。因此必d服务对象创徏之前指定l定的hostname?br />
~~~完?/div>

疯狂 2014-12-05 14:08 发表评论
]]>(?Oracle数据库如何授权收费(Database LicensingQ?http://www.dentisthealthcenter.com/freeman1984/archive/2014/10/27/419097.html疯狂疯狂Mon, 27 Oct 2014 08:43:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2014/10/27/419097.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/419097.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2014/10/27/419097.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/419097.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/419097.html
说白了,Oracle License是一张纸Q一张许可证。这跟许多Y件品是一LQ有没有许可证的产品在功能上是没有区别的Q仅仅是一个法律问题。也是_随便到网上下的Oracle都可以免Ҏ怋用,只不q这个用是有区别的Q如果是试或研发,那没关系Q随便用Q如果是用于商业用途,那就是违法的了,Oracle公司有权赯Q?/span>

 

与免费的下蝲版本不同Q正式版的Oracle在购买后Q用户会得到一个品服务码Q凭此Oracle服务码,可以得到Oracle的在U升U等服务QOracle的服务分为好多Q不同别提供相对应的在U或是现场服务?/span>

 

现在Oracle有两U授权方式,按CPU(Process)数和按用h(NamedUser Plus)?/strong>前一U方式一般用于用h不确定或者用h量很大的情况Q典型的如互联网环境Q而后一U则通常被用于用h定或者较的情况?/span>

 

按CPUQ?/strong>License?CPU?pL。系数来自Oracle的一个参数表Q如IBM Power6的处理器?QAMD和Intel的处理器?.5Q详l情况见下:

参数

处理器型?/span>

0.25

Sun UltraSPARC T1 处理?/span>

0.50

Sun UltraSPARC T1处理?/span>

0.50

Intel、AMD处理?/span>

0.50

Sun UltraSPARC T2+ 处理?/span>

1.00

IBM POWER6、POWER7 处理?/span>

0.75

其他多核处理?/span>

1.00

单核处理?/span>

则根据公式可以算出,一个SUN UltraSparc T1?*8核处理器需?*8*0.25=8个CPU licenses

 

按用hQ?/strong>Oracle数据库按照用h授权Q是指最l端的连接到Oracle数据库的用户数。按照用h来买的时候只能用于一个系l,不允许在多台机器上安装。每一个访问Oracle数据库的用户Q无论是自然是设备,都算作一个用?(Named User)。如果是B/S架构Q那么是指连接到中间件上的用h?/span>

 

Named User Plus: is defined as anindividual authorized by you to use the programs which are installed on a singleserver or multiple servers, regardless of whether the individual is activelyusing the programs at any given time. A non human operated device will becounted.

 

按用h购买则对应相应的产品有对应的License的最低购买量限制Q如下:

产品

最低License?/span>

Oracle Database Standard Edition ONE

5 Named User Plus licenses

Oracle Database Standard Edition

5 Named User Plus licenses

Oracle Database Enterprise Edition

25 Named User Plus licenses per CPU

Oracle Application Server Standard Edition ONE

5 Named User Plus licenses

All other Oracle Application Server products

10 Named User Plus licenses per CPU

当然用户应该Ҏ自己的实际用h订购Q且不少于相应版本所要求的最低用h?/span>

一般情况下Q?CPU的费用约{于50user的费用,所以如果用h>CPU?pL*50Q则按CPU订购反而更为经?/strong>

 

更换服务器,OracleLicense要重新购买吗Q?/strong>

如果用户是按照用h购买的OracleQ更改硬件不需要重新购买LicenseQ?/span>

如果是按照CPU个数乎ͼ有相应的换算ҎQ具体请咨询Oracle公司?/span>

 

q里是Oracle 11g企业版的销售h|

每个Licenseq有有效期的分类Q不论是User Licenseq是CPU LicenseQ,分别为:1q?q?q?q?q、永久。当然hg是依ơ增加?/span>

 

当前Oracle 11G的User License无限使用期的hZh民币3?左右Q按50个User License无限使用期的购买量则h?7.5?每个CPU License无限使用期的h?7?千,按IBM机的系数计,则购Chgؓ17?千,?0个User License的h格相q?/span>

 

关于服务hQ一般地Q购买Oracle的License都包含首q的服务费,以后的费用按每年原h?2%计算?/span>

 

更多的品h格可以访问http://shop.oracle.com查看?/span>


q里我们再介l一下如何查看服务器上物理CPUL以及核数Q?/strong>

a.如果已安装了数据库实例,那么直接查看V$license视图卛_:

SQL> select cpu_count_current,CPU_CORE_COUNT_CURRENT,CPU_SOCKET_COUNT_CURRENT from v$license;

CPU_COUNT_CURRENT CPU_CORE_COUNT_CURRENT CPU_SOCKET_COUNT_CURRENT
----------------- ---------------------- ------------------------
                2                      2                        1
以上通过v$license 视图反应了数据库服务器当前的逻辑CPUL?Q而ȝ核数也是2Q实际的物理CPU Socket?Q那么说明是1个双核的物理CPU?/span>


b. 如果服务器上没有部|实例则不能使用v$license视图Q那么可以通过OS 命o来获取必要的信息?/span>

在x86 Linux服务器上Q?/span>


列出当前使用的物理CPU的个敎ͼ

grep core\ id /proc/cpuinfo | grep -c \ 0$ | grep ^0$ >> /dev/null && grep -c processor /proc/cpuinfo || \
grep core\ id /proc/cpuinfo | grep -c \ 0$

列出单个物理CPU的核?

grep "cpu cores" /proc/cpuinfo |uniq

 

 

在Powerpd的IBM机上按照cpu模块方式来购乎ͼ在IBM Dual-Core ModuleQ双核模块)的power芯片上,一个双核模块(内含2颗物理cpuQ只需要购?.5个license Q?具体的模块类型可以咨询IBM厂家或者集成商?br />
转自Q?a >http://blog.csdn.net/eurasiaxz/article/details/10699869

当然随着cpu计算能力的提高,cpu个数有可能ƈ不需要太多。oracle的收Ҏ式肯定会变化?/p>

疯狂 2014-10-27 16:43 发表评论
]]>
成功?Web 应用pȝ性能试 (转蝲)http://www.dentisthealthcenter.com/freeman1984/archive/2014/10/07/418488.html疯狂疯狂Tue, 07 Oct 2014 13:09:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2014/10/07/418488.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/418488.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2014/10/07/418488.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/418488.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/418488.html

转蝲自:http://blog.chinaunix.net/uid-20682147-id-76384.html

性能试?Web 应用pȝ的一w要质量保证措施。在现实中,很多 Web 性能试目׃性能试需求定义不合理或不明确Q导致性能试目不能辑ֈ预期目标或进度超期。本文针?Web 应用pȝ的技术架构和pȝ使用特点Q探讨如何有效实施性能试q程Qƈ重点介绍如何分析获得合理的性能试需求,最l对 Web 应用pȝ性能q行U学、准的评估?/p>

1 引言

ZWeb服务器的应用pȝ׃提供览器界面而无d装,大大降低了系l部|和升成本Q得以普遍应用。目前,很多企业的核心业务系l均是Web应用Q但当Web应用的数据量和访问用户量日益增加Q系l不得不面性能和可靠性方面的挑战。因此,无论是Web应用pȝ的开发商或最l用P都要求在上线前对pȝq行性能Q科学评Ll的性能Q从而降低系l上U后的性能风险?/p>

在很多性能试目中,׃不能合理定义pȝ的性能试需求,不能建立和真实环境相W的负蝲模型Q不能科学分析性能试l果Q导致性能试目持箋旉很长或不能真正评Ll性能q提出性能改进措施?/p>

本文在ȝ许多Web应用pȝ性能试实践l验和教训的基础上,从与性能试工具无关的角度介lWeb应用pȝ性能试的方法和实施q程Q以及如何定义合理的性能试需求?/p>

1.1 术语定义

性能试Q通过模拟大量览器客L同时讉KWeb服务器,获得pȝ的性能数据?/p>

虚拟用户Q模拟浏览器向Web服务器发送请求ƈ接收响应的一个进E或U程?/p>

响应旉Q浏览器向Web服务器提交一个请求到收到响应之间的间隔时间?/p>

思考时_览器在收到响应后到提交下一个请求之间的间隔旉?/p>

h成功率:Web服务器正处理的h数量和接收到的请求数量的比?/p>

吞吐量:单位旉内Web服务器成功处理的HTTP面或HTTPh数量?/p>

在线用户Q用户通过览器访问登录Web应用pȝ后,q不退应用pȝ。通常一个Web应用服务器的在线用户对应Web应用服务器的一个Session?/p>

q发用户敎ͼWeb服务器在一D|间内为处理浏览器h而徏立的HTTPq接数或生成的处理线E数。当所有在U用户发送HTTPh的思考时间ؓ零时QWeb服务器的q发用户数等于在U用h?/p>

1.2 Web应用pȝ技术架?/font>

Web应用pȝ的前端ؓ览器,后台为Web服务器(如ApacheQMicrosoft Internet Information ServerQ,览器和Web服务器之间的交互ZHTTP协议。HTTP协议本n是无q接的,Web服务器通过Session机制来徏立一个浏览器所发出的先后连接之间的兌。通过实验证明Q当览器客L在首ơ访问Web服务器后Q如果该览器客L不发送后l请求,服务器维持该览器客L的Session变量所消耗的pȝ资源非常?/p>

2 Web应用pȝ性能试q程

标准的Web应用pȝ性能试q程包括定性能试需求,开发性能试脚本Q定义性能试负蝲模型Q执行性能试和Ş成性能试报告。本章将分别介绍上述q程Qƈ通过举例说明如何完成每一环节?/p>

2.1 定性能试需?/font>

U学定义Web应用pȝ性能试需求对一个成功的性能试非常重要。通常QWeb应用pȝ的性能试需求有如下两种描述Ҏ?/p>

2.1.1 Z在线用户的性能试需?/strong>

该需求描q方法主要基于Web应用pȝ的在U用户和响应旉来度量系l性能。当Web应用pȝ在上U后所支持的在U用h以及操作习惯Q包括操作和h之间的gq)很容易获得,如企业的内部应用pȝQ?通常采用Z在线用户的方式来描述性能试需求。以提供|上购物的Web应用pȝZQ基于在U用L性能试需求可描述为:10个在U用h正常操作速度讉K|上购物pȝ的下定单功能Q下定单交易的成功率?00%Q而且90%的下定单h响应旉不大?U;?0%的请求响应时间不大于用户的最大容忍时?0U时Q系l能支持50个在U用?/strong>?/p>

2.1.2 Z吞吐量的性能试需?/strong>

该需求描q方法主要基于Web应用pȝ的吞吐量和响应时间来度量pȝ性能。当Web应用在上U后所支持的在U用h法确定,如基于Internet的网上购物系l,可通过每天下定单的业务量直接计其吞吐量,从而采取基于吞吐量的方式来描述性能试需求。以|上购物pȝZQ基于吞吐量的性能试需求可描述为:|上购物pȝ在每分钟内需处理10W下定单操作Q交易成功率?00%Q而且90%的请求响应时间不大于8U?/strong>?/p>

2.2 开发性能试脚本

在确定Web应用pȝ性能试需求后Q就要根据性能试需求中定的功能开发性能试脚本。比如,针对前面定义的网上购物系l的性能试需求,开发下定单功能的性能试脚本?/p>

性能试脚本是描q单个浏览器向Web服务器发送的HTTPh序列。每个性能试工具Q如IBM Rational Performance TesterQ?LoadRunnerQ所提供的测试脚本语法是不同的。测试h员利用性能试工具可从头手工编写测试脚本,也可以通过录制览器和Web服务器之间的|络通信数据而自动Ş成测试脚本?/p>

M性能试工具都不能保证录制Ş成的性能试脚本的正性,试人员应通过在单用户下运行性能试脚本对其正确性进行验证。测试脚本不正确的一个重要原因就是脚本的数据兌不正,也就是ƈ没完全徏立一个测试请求和前面的响应内容之间的兌。测试脚本HTTPh和响应之间的数据兌是否正确的一个重要标准是单用戯行脚本,脚本能完成期望的功能?/p>

在完成性能试脚本的数据关联后Q需要对脚本q行参数化,也就是把脚本中的某些h数据替换成变量,变量的值来于一个独立的数据文gQ从而保证在多虚拟用戯行脚本的情况下,每个虚拟用户所提交的数据是不同的?/p>

此外Qؓ了测试Web应用的可靠性,q需要对h所收到的响应进行验证(比如验证响应的HTTPq回码或验证响应的内容)Q便于性能试完成后统计请求成功率?/p>

2.3 建立性能试负蝲模型

性能试负蝲模型定义了测试工具如何向Web应用pȝ提交hQ包括向Web应用pȝ发送请求的虚拟用户敎ͼ每个虚拟用户发送请求的速度和频率。针对前面介l的|上购物pȝ的性能试需求,在性能试工具中定义的性能试负蝲模型应包括如下信息:

虚拟用户敎ͼ性能试不仅仅是执行一ơ,而且每次执行时虚拟用h也不固定Q因此在性能试负蝲模型中定义的虚拟用户数将在测试执行时q行讄?/p>

虚拟用户发送请求的思考时间和q代ơ数Q虚拟用户发送请求的思考时间长短是军_Web应用pȝ负蝲量的重要因素之一Q而P代次数将军_性能试的执行持l时间。对Z在线用户的性能试需求,基于录制脚本时记录的思考时_而且׃现实中不同用戯问系l的思考时间不同,可把思考时间设|ؓ在一定范围内的随机倹{对于基于吞吐量的性能试需求,把思考时间设|ؓӞ此时Web应用pȝ的在U用h量将{于q发用户数。同ӞZ避免性能试压力的随机性,增加请求的q代ơ数来增加测试执行持l时_从而获得系l在E_压力下的性能数据?/p>

虚拟用户启动模式Q在现实中,Web应用pȝ的用户不太可能同时做相同的操作,因此Z让Web应用pȝ所承担的压力随旉均匀分布Q徏议虚拟用户依ơ启动,同时也避免大量用户同时登录造成pȝd。以10个虚拟用h拟下定单ZQ可讄每个虚拟用户间隔30U启动,q样10个虚拟用户可?分钟后完成启动,q保?0个虚拟用户不会在同一时刻下定单,从而更W合实际情况?/p>

2.4 执行性能试

执行性能试是指通过多次q行性能试负蝲模型Q获得系l的性能数据。在执行q程中,需利用试工具、操作系l、系lYӞ如Web Server或DB ServerQ提供的资源监控手段对资源进行监控和分析Q帮助发现资源瓶颈,q在pȝ层面q行优化。同Ӟq需对应用进行性能分析Q帮助定位应用代码中的性能问题Q切实解决系l的性能问题?/p>

2.5 形成性能试报告

性能试目的最后阶D就是向相关人员提交性能试报告Q汇报性能试l果。在向相关h员汇报性能试l果Ӟq不是性能试报告丰富、性能数据多好。好的性能试报告是能准确、简单地传递性能试l论Q而不需太多的技术细节?/p>

针对Z在线用户数的性能试需求,可通过下图ȝ性能试l论。其中横轴是在线用户敎ͼUu是响应时_?0在线用户讉K|上购物pȝӞ90%的下定单h响应旉不超q?0U?/p>
图一Q在U用h和响应时间时间的势?/strong>
 


针对Z吞吐量的性能试需求,可通过下图的曲U来描述性能试l果。以|上购物pȝZQ下图描qC定单的ƈ发用戗下定单响应旉以及吞吐量(服务器每U处理定单笔敎ͼ之间的关p,从而快速判断系l是否能满性能试需求。从下图中可看出Qƈ发用户增加,h的响应时间也增加。服务器的吞吐量是先随ƈ发用h增加而增加,当吞吐量到达一定峰值后Q再增加q发用户敎ͼ吞吐量会减少。原因在于当q发用户数少Ӟ向Web服务器提交的h量不大,服务器处理能力还有富余,所以吞吐量逐步增大Q但当ƈ发用h过某一值时Q由于向服务器提交的h太多Q造成服务器阻塞,反而导致吞吐量减少?/p>
图二Q响应时间、吞吐量和ƈ发用h的趋势图
 


3 如何获取合理的性能试需?/span>

前一章介l了Web应用pȝ的性能试q程Q确定性能试需求是整个性能试的v点和成功的重要因素。性能试需求定义得q高Q虽然确保系l上U后能满x能需求,但可能会造成g资源的浪费;性能试需求定义得q低Q系l上U后可能会出现性能问题。如何通过分析pȝ上线后可能的用户讉K行ؓQ来获得合理的性能试需求指标呢Q?/p>

假设现有一个基于Web的办公自动化pȝQ简UOApȝQ,该系l提供公文收发和查询功能。在部v该系l前Q将对该pȝq行性能试。下面将详细介绍如何分析该OApȝ的用情况,定义合理的性能试需求?/p>

3.1 如何获得OApȝ的在U用h?/font>

在线用户数量是指在特定时间区间内Q有多少用户讉KWeb应用pȝQ对应到Web服务器的Session敎ͼQ根据系l可能访问用h以及每个用户讉Kpȝ的时间长短来定?/p>

对于要部v的OApȝQ通过分析获得该系l有8000个注册用P基本上所有的用户每天Q?时工作旉Q都会访问OApȝQ^均在U时_从登录OApȝ到退出OApȝ之间的时间间隔,也可以是多次在线旉的合计)?2分钟Q那么该OApȝ的^均在U数Q也是Web应用Session变量敎ͼ?00个(8000 * 0.2 / 8Q,假设峰值在U用h是^均在U用h?倍(该倍数可根据实际情况调_Q则性能试需求的在线用户Cؓ600?/p>

3.2 如何定OApȝ的性能试用例

׃旉和资源限Ӟ不可能对Web应用pȝ的所有功能进行性能试Q而是从业务的角度Q如某一功能操作的用户多Q和技术的角度Q如某一功能虽然讉K用户不多Q但内部处理逻辑复杂或处理数据量大)来选择Web应用pȝ的特定功能作为性能试用例?/p>

以OApȝZQ由于所有用户都l常公文查询功能Q因此确定的性能试用例为公文查询?/p>

3.3 如何定OApȝ的响应时?/font>

响应旉的快慢直接媄响了pȝ使用用户的满意度Q采用^均响应时间来描述pȝpȝ性能试需求是不科学的Q因为无法直接和客户的满意度挂钩。而且Q在做性能试Q如果某一h的响应时间过长或q短Q将Dq_响应旉和实际情况偏R?/p>

以OApȝZQ定义的响应旉需求ؓQ?0%Q该癑ֈ比和要求的系l用h意度相关Q的查询h响应旉不超q?U(该时间可Ҏ实际情况定Q?/p>

3.4 如何定OApȝ的交易吞吐量

单位旉内Web应用pȝ需处理多少W特定的交易可通过l计获得。以OApȝZQ假设每个用h天(一天按8时计算Q^均会查询公文4ơ,那OA应用的Web服务器^均每分钟要能处理8000 * 4 / ( 60 * 8 ) = 66.67W查询公文交易,考虑到峰值因素,要求每分钟能处理66.7 * 3=200W查询公文交易?/p>

3.5 OApȝ性能试需求描q?/font>

通过前面的分析,能明定义合理的性能试需求。OApȝ性能试需求定义如下:

Z在线用户数的性能试需求:600个在U用h正常操作速度讉KOApȝ的查询公文功能,所有查询请求的成功率是100%Q而且90%的查询请求响应时间不大于8U?/p>

Z吞吐量的性能试需求:OApȝ在每分钟内需处理200W查询公文操作,交易成功率ؓ100%Q而且90%的请求响应时间不大于8U?/p>

4 ȝ

Web应用性能试目成功的关键不在于性能试工具Q而在于有效的性能试分析Ҏ和实c只有切实掌握性能试需求分析方法,性能试实践l验Q才能保证一个Web应用性能试的成功?/p>

疯狂 2014-10-07 21:09 发表评论
]]>
It is indirectly referenced from required .class file异常http://www.dentisthealthcenter.com/freeman1984/archive/2014/09/23/418187.html疯狂疯狂Tue, 23 Sep 2014 06:33:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2014/09/23/418187.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/418187.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2014/09/23/418187.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/418187.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/418187.html环境Qmaven目?br />
H然出现异常Q显C某个类无法引用QIt is indirectly referenced from required .class file异常Q通过跟踪到这个类Q发现无法点L看这个类Q报Qjava.util.zip.ZipException: invalid LOC header (bad signature)?br />
解决办法Q删除本C库对应的jar包重C载,卛_Q?img src ="http://www.dentisthealthcenter.com/freeman1984/aggbug/418187.html" width = "1" height = "1" />

疯狂 2014-09-23 14:33 发表评论
]]>
(?svn cleanup failed–previous operation has not finished; run cleanup if it was interruptedhttp://www.dentisthealthcenter.com/freeman1984/archive/2014/07/22/416070.html疯狂疯狂Tue, 22 Jul 2014 01:46:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2014/07/22/416070.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/416070.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2014/07/22/416070.html#Feedback1http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/416070.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/416070.html转自Q?span style="font-family: verdana, 'courier new'; line-height: 21px;">http://blog.csdn.net/luojian520025/article/details/22196865

svn提交遇到恶心的问题,可能是因Zơcleanup中断后,q入d@环了?/p>

错误如下Q?/p>

 

解决ҎQ清Isvn的队?/p>

1.下蝲sqlite3.exe   

2.扑ֈ你项目的.svn文gQ查看是否存在wc.db

3.sqlite3.exe攑ֈ.svn的同U目?/p>

4.启动cmd执行sqlite3 .svn/wc.db "select * from work_queue"

5.看到很多记录Q下一步执行delete from work_queue

 

6.ok了,现在在到目里面Q执行cleanupQ完全没问题了,图标状态也已经恢复了?/p>

疯狂 2014-07-22 09:46 发表评论
]]>
automation服务器不能创建对?解决办法http://www.dentisthealthcenter.com/freeman1984/archive/2014/03/21/411308.html疯狂疯狂Fri, 21 Mar 2014 01:39:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2014/03/21/411308.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/411308.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2014/03/21/411308.html#Feedback1http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/411308.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/411308.htmljavascript脚本中报q个错误。应IE的安全设|?#8220;不允许运行未标记为安全的activeX控g”启用卛_?br />

疯狂 2014-03-21 09:39 发表评论
]]>
ERROR: transport error 202: gethostbyname: unknown host 解决办法http://www.dentisthealthcenter.com/freeman1984/archive/2014/03/12/410935.html疯狂疯狂Wed, 12 Mar 2014 05:55:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2014/03/12/410935.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/410935.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2014/03/12/410935.html#Feedback1http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/410935.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/410935.html

疯狂 2014-03-12 13:55 发表评论
]]>
JavaScript 跨浏览器事g处理(?http://www.dentisthealthcenter.com/freeman1984/archive/2013/12/28/408152.html疯狂疯狂Sat, 28 Dec 2013 07:19:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/12/28/408152.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/408152.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/12/28/408152.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/408152.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/408152.html如果目中没有用诸?jQuery 之类的库Q如何方便地为元素绑定事Ӟq兼容各U浏览器呢?下面q个单的 Utility 应该可以考虑?/p>
var eventUtility = {
	addEvent : function(el, type, fn) {
		if(typeof addEventListener !== "undefined") {
			el.addEventListener(type, fn, false);
		} else if(typeof attachEvent !== "undefined") {
			el.attachEvent("on" + type, fn);
		} else {
			el["on" + type] = fn;
		}
	},

	removeEvent : function(el, type, fn) {
		if(typeof removeEventListener !== "undefined") {
			el.removeEventListener(type, fn, false);
		} else if(typeof detachEvent !== "undefined") {
			el.detachEvent("on" + type, fn);
		} else {
			el["on" + type] = null;
		}
	},

	getTarget : function(event) {
		if(typeof event.target !== "undefined") {
			return event.target;
		} else {
			return event.srcElement;
		}
	},

	preventDefault : function(event) {
		if(typeof event.preventDefault !== "undefined") {
			event.preventDefault();
		} else {
			event.returnValue = false;
		}
	}
};

使用ҎCZQ?/p>

var eventHandler = function(evt) {
	var target = eventUtility.getTarget(evt),
		tagName = target.tagName;

	if(evt.type === "click") {
		if(tagName === "A" || tagName === "BUTTON") {
			alert("You clicked on an A element, and the innerHTML is " + target.innerHTML + "!");
			eventUtility.preventDefault(evt);
		}
	} else if(evt.type === "mouseover" && tagName === "A") {
		alert("mouseovered " + target.innerHTML);
	}
	
};

eventUtility.addEvent(document, "click", eventHandler);
eventUtility.addEvent(document, "mouseover", eventHandler);

eventUtility.removeEvent(document, "mouseover", eventHandler);


疯狂 2013-12-28 15:19 发表评论
]]>
函数声明 VS 函数表达??http://www.dentisthealthcenter.com/freeman1984/archive/2013/12/28/408151.html疯狂疯狂Sat, 28 Dec 2013 07:16:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/12/28/408151.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/408151.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/12/28/408151.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/408151.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/408151.html转自Q?a >http://www.libuchao.com/2012/06/25/function-declaration-vs-function-expression
JavaScript 中需要创建函数的话,有两U方法:函数声明、函数表辑ּQ各自写法如下:

// Ҏ一Q函数声?/span>
function foo() {}

// Ҏ二:函数表达?/span>
var foo = function () {};

另外q有一U自执行函数表达式,主要用于创徏一个新的作用域Q在此作用域内声明的变量不会和其它作用域内的变量冲突或؜淆,大多是以匿名函数方式存在Q且立即自动执行Q?/p>

(function () {
    // var x = ...
})();

此种自执行函数表辑ּ归类于以上两U方法的W二U,也算是函数表辑ּ?/p>

Ҏ一和方法二都创Z一个函敎ͼ且命名ؓ fooQ但是二者还是有区别的。JavaScript 解释器中存在一U变量声明被提升QhoistingQ?/strong>的机Ӟ也就是说变量Q函敎ͼ的声明会被提升到作用域的最前面Q即使写代码的时候是写在最后面Q也q是会被提升x前面?/p>

例如以下代码D:

alert(foo); // function foo() {}
alert(bar); // undefined
function foo() {}
var bar = function bar_fn() {};
alert(foo); // function foo() {}
alert(bar); // function bar_fn() {}

输出l果分别?code>function foo() {}?code>undefined?code>function foo() {}?code>function bar_fn() {}?/p>

可以看到 foo 的声明是写在 alert 之后Q仍然可以被正确调用Q因?JavaScript 解释器会其提升?alert 前面Q而以函数表达式创建的函数 bar 则不享受此待遇?/p>

那么bar I竟有没有被提升呢,其实?var 声明的变量都会被提升Q只不过是被先赋gؓ undefined |了Q所以第二个 alert 弹出?undefined?/p>

所以,JavaScript 引擎执行以上代码的顺序可能是q样的:

  1. 创徏变量 foo ?barQƈ它们都赋gؓ undefined?/li>
  2. 创徏函数 foo 的函CQƈ其赋值给变量 foo?/li>
  3. 执行前面的两?alert?/li>
  4. 创徏函数 bar_fnQƈ其赋值给 bar?/li>
  5. 执行后面的两?alert?/li>

注:

严格地说Q再 JavaScript 中创建函数的话,q有另外一U方法,UCؓ“函数构造法”Q?/p>

var foo = Function('alert("hi!");');
var foo = new Function('alert("hi!");'); // {同于上面一?/span>

此方法以一个字W串作ؓ参数形成函数体。但是用q种ҎQ执行效率方面会打折扣,且似乎无法传递参敎ͼ所以少用ؓ妙?/p>

疯狂 2013-12-28 15:16 发表评论
]]>
ORA-06548错误http://www.dentisthealthcenter.com/freeman1984/archive/2013/11/28/406952.html疯狂疯狂Thu, 28 Nov 2013 08:44:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/11/28/406952.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/406952.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/11/28/406952.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/406952.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/406952.html原因Q有可能是通过pl/sql{客L执行道输出函数QpipelinedQ造成Qpl/sql客户端一般不会显C全部结果,道输出挂v?

疯狂 2013-11-28 16:44 发表评论
]]>
目规划与管理记? http://www.dentisthealthcenter.com/freeman1984/archive/2013/11/18/406461.html疯狂疯狂Mon, 18 Nov 2013 04:51:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/11/18/406461.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/406461.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/11/18/406461.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/406461.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/406461.htmlhttp://www.dentisthealthcenter.com/cheneyfree/archive/2013/11/09/406169.html 
8??0三月Q需求依旧爆,相比U业务功能的开发,数据的汇聚、整理、分析、统计成为重点,具体l节不一一展开Q按如下关键词:d计划、项目沟通、项目流E、客h报、业务关注、时间评估、管理笔记做一些笔录,持箋更新Q?br />    1、Q务计划:
      1.决策前考虑充分Q决{后不再怀疑?br />      2.d_、描q清晎ͼ对内分解针对到负责h、给外汇报针对品功能?br />      3.计划制定Ӟh员预审Q务量Q再和开发、测试确认时_由成员承诺时间?br />      4.安排d多h完成Ӟ指定一个牵头h?br />      5.大的需求,l织讨论Q小的需求,点对Ҏ通,最后要全部闸口到文?br />      6.d分配Q根据h员特点(善于思考型、认真较劲型、粗枝大叶型Q安排难易程度对应的d?br />      7.紧急需求多Ӟ一ơ尽可能l成员分配较Q务ƈU定完成旉、完成后再约定下一批Q务?br />      8.Ҏd分配情况Q了解到谁相对空Ԍ安排CQ务给I闲的成员?br />      9.到的问题整理一份清单,可能一ơ性地转交开发、测试h员?br />      10.形成人员对开发Q务的备䆾机制Q不局限某个模块的开发,x整体?br />      11.每一轮版本,制定《风险管理清单》,协调、跟q、解决风险问题?br />      12.加班如遇Ҏ情况不能陪同Q托工作给指定接口人?br />      13.成员加班晚,W二天要Ҏ情况保证人力参与白天工作?p>   2、项目沟?br />      1.重要事项亲历亲ؓ?br />      2.每周的项目周报,除了知悉公司外,同步知悉客户?br />      3.需求的分析及客L认用原型图。需求的认启动开发,必须是业务部、信息化部、公怸方达成一致?br />      4.技术实C会就会,不会׃会,和时间的多少没有U性关pR?br />      5.控制好工作节奏,多和领导沟通,自己的经历正是h家过ȝ历的重现?br />      6.沟通项目存在的问题时尊重客观事实和软g开发规律,做不完的跟客戯明原因,该拒l的果断?br />      7.上线前的客户q作Q除了项目层面的客户沟通,也请领导高层向客户高层沟通?br />      8.需求变更会影响目计划的执行,变更需要付ZP优先{略Q时间调整、功能调整、h力调_?br />      9.遵@‘做得但质量好,忌讳做的多却质量?#8217;的原则?br />      10.目风险且一时对得不到公司资源倾斜Ӟ也可借助客户的力量(下下{)?br />      11.客户的跟催,多耐心急躁Q多自省借口Q多客观主观?br />      12.交付旉的答复,不能当下l出的待评估后再l?/p>

   3、项目流E:
      需求频J且变更较多Ӟ0.5周~1周一轮版本。每ơ汇报后产生的新需求、遗留需求、待开发的功能Q?br />      1.整理《项目跟t表》,含:新需求、遗留问题、关联媄响(指导试做关联模块的验证Q?br />      2.试人员已明确的开发Q务登记到BUG理pȝ
      3.需求h员与开发、测试h员评审需?br />      4.负责人牵头需求、开发、测试h员确定开发、测试、发布时间计划?br />      5.与客户反馈交付时间点Q对于小需求的交付旉可以直接{复、大需求要内部讨论再答复)?br />      6.目q度跟踪Q以天ؓ单位Q测试h员更新《项目跟t表》?br />      7.需求验证介?br />        1Q开发提交代码后Q需求h员、测试h员分别开展系l测试(业务角度Q关注界面交互、主q流E、数据展玎ͼ、业务测试(pȝ角度Q关注功能操作及边界、业务流E输入输出)?br />        2Q需求h员发现的问题Q属于开发BUG登记到BUG理pȝ、需求BUG与开发h员、甚臛_h清,如不影响版本发布旉直接加入在研版本、如影响则提交变更请求,与客h通得到变更认可或与开发沟通得到变更认可?br />      9.升前,针对环境数据的准备,~写《升U注意事(含数据清理、数据准备等Q》给试人员交代?br />      10.升后,需求h员在演示环境C务测试(L式演C前2天完成升U验证,提前1天环境冻l。)
      11.上线前,与客h通准备事(含压力测试、工E部|Ӏ资料交付、培训计划、试q行计划{)

   4、客h报:
      1.型汇报Q前一天,pȝȝQ不再做升Q只做业务验证、回归?br />      2.大型汇报Q前三天Q系l冻l,不再做升U,只做业务验证、回归?br />      3.汇报前,拿用LW记本做预演Q防止操作系l、浏览器兼容问题?br />      4.汇报思\Q?br />        1Q以一个业务主U,l客戯故事,l合不同客户x的角度出发,让^台能融入不同客户的日常工作?br />        2Q信息化前是什么样Q信息化后是什么样Q提高日常办公的效率、^台统计的数据提升客户的业l等Q?br />      5.目初期注意界面UI友好Q中期注意数据的规范及业务流E正,后期注重l计数据的真实、准?br />      6.版本的技术问题、项目进度的问题、用户需求的问题、沟通协调的问题Q实事求是汇报客戗?br />      7.汇报前与客户业务接口人沟通汇报内宏V汇报方式,掌握领导听取汇报时关注的炏V?br />      8.汇报前,x业务部门的需求、信息化部门的徏议、更要关注客户领导的兛_炏V?/p>

   5、业务关注:
      1.xq_的数据输入、处理、输出数据的完整性、准性、关联性?br />      2.抓住q_的徏讄念,所有业务模块围l该理念开展需求分析、设计?br />      3.降低U上复杂的业务操作流E(更多考虑l果数据的录入、留痕,程多了很难同时在线协同办公Q?br />      4.技术实现的同时要考虑业务机制的配套?br />      5.考虑现实性[在现有业务规章制度的环境下运行]、前L[业务层面的发展方向]、可行性[技术是否支持]?br />      6.x和周边^台的数据l构一致和标准
      7.<待补?gt;

   6、时间评伎ͼ
      1.每天列出当天要做的工作、每天下班前回顾当天工作Q每周列出本周工作成果、下周工作计划?br />      2.d旉评估 = [成员评估 l合 自评估] + 开发冗余(Ҏq_Ҏ、开发h员经验及态度判断Q?+ 试冗余Q根据^台特性、测试h员经验及态度判断Q?+ 需求冗余(Ҏq_Ҏ、需求h员经验及态度判断Q? 其他冗余Q如请假、生病、开会等非项目因素)

   7、一些管理笔讎ͼ
      1.d_և、给予空?br />      2.狠抓住干、适当放权
      3.敢于承担、顶住冲?br />      4.讲究诚信、承诺到?br />      5.规则考核、理解包?br />      6.用h不疑、疑Z?br />      7.功劳大家、黑锅自?/p>

疯狂 2013-11-18 12:51 发表评论
]]>
tmpFile.renameTo(classFile) failedhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/10/21/405469.html疯狂疯狂Mon, 21 Oct 2013 09:42:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/10/21/405469.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/405469.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/10/21/405469.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/405469.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/405469.html

疯狂 2013-10-21 17:42 发表评论
]]>
redhat6.4 64位安装rlwraphttp://www.dentisthealthcenter.com/freeman1984/archive/2013/09/04/403675.html疯狂疯狂Wed, 04 Sep 2013 12:33:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/09/04/403675.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/403675.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/09/04/403675.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/403675.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/403675.htmlftp://mirror.switch.ch/pool/1/mirror/epel/6/x86_64/rlwrap-0.37-1.el6.x86_64.rpm
2 rpm -ivh rlwrap-0.37-1.el6.x86_64.rpm
ok!

疯狂 2013-09-04 20:33 发表评论
]]>
ora-01031:insufficient privilegeshttp://www.dentisthealthcenter.com/freeman1984/archive/2013/09/04/403674.html疯狂疯狂Wed, 04 Sep 2013 12:03:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/09/04/403674.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/403674.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/09/04/403674.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/403674.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/403674.html如果密码文g存在的话Q\径:$ORACLE_HOME/dbs/Q,L看密码文Ӟ格式Qorapw$ORACLE_SIDQ里面sid和当前ORACLE_SID大小写是否一致。必Mh行?br />不一h用mv 修改成一L。即可?br />
相关文章参考?br />
http://www.xifenfei.com/2025.html


疯狂 2013-09-04 20:03 发表评论
]]>
mysqlq程q接问题 Access denied for user 'root'@' ip ' (using password: YES)http://www.dentisthealthcenter.com/freeman1984/archive/2013/07/12/401488.html疯狂疯狂Fri, 12 Jul 2013 02:43:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/07/12/401488.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/401488.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/07/12/401488.html#Feedback1http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/401488.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/401488.html服务器登录mysqlQ然后执行:

GRANT ALL PRIVILEGES ON *.* TO'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;

flush privileges;

疯狂 2013-07-12 10:43 发表评论
]]>
dbcp重连(? http://www.dentisthealthcenter.com/freeman1984/archive/2013/06/06/400263.html疯狂疯狂Thu, 06 Jun 2013 01:38:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/06/06/400263.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/400263.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/06/06/400263.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/400263.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/400263.html转自Q?a >http://lc87624.iteye.com/blog/1734089

 

使用数据库连接池Ӟ免不了会遇到断网、数据库挂掉{异常状况,当网l或数据库恢复时Q若无法恢复q接池中的连接,那必然会是一场灾难?

关于dbcp的自动重q配|,|上相关的资料也不少Q通过以下资料Qƈ对照官方文中的参数说明Q大致能了解各项配置的含义,我就不冗诉了Q本文的目的主要是对问题排查的经q做个简单的记录?
参考资料:

试环境Q?
  • dbcp版本——1.4
  • 数据?#8212;—postgresSQL 9.10Q简UpgQ?/li>
  • 本地(以下UCؓclient)操作pȝ及数据库服务?以下UCؓserver)操作pȝ均ؓlinux
  • server位于内网环境Qclient需要通过vpn或网U直q内|才能访问数据库

首先模拟的是断网的情?/strong>
在本地测试dbcp的重q配|时Q发现断|后Q连接池无法重徏q接Q分别试qtestOnBorrow和testWhileIdle两种validate方式Q都没能解决Q现象如下:
1. 正常启动应用Q在server端通过"select * from pg_stat_activity"查看q接敎ͼ会有initialSize个来自client的IDLEq接?#8212;—正常
2. 在client端执行各U查询操作,q接C持不变,且在server端的db log中能看到validate query?#8212;—正常
3. 手动切断vpnQclient与server断开Q查询无法返回结果;然后重连Q再ơ查看连接数Q连接数仍保持不变,且连接的创徏旉为断|前Q即是说q接池认Z前的q接仍然有效Q没有销毁旧q接&创徏新连接?
4. 此时在应用中执行各种查询操作Q均无响应,{待一D|间后Q分钟Q,时抛出异常Q?
Caused by: org.postgresql.util.PSQLException: An I/O error occured while sending to the backend.
Caused by: java.net.SocketException: Connection timed out.
5. l箋通过"select * from pg_stat_activity"查看q接敎ͼ隔一D|间后Q连接消失?

问题Q?/strong>断网后,仍留在线E池内的q接是否有效Q若有效Qؓ什么网l恢复后查询无响应?若无效,ZU程池没有发现ƈ重新创徏有效q接Q?
排查q程Q?/strong>
1.重连vpn后,通过netstat查看client至server的连?
Java代码  
  1. sudo netstat -antop | grep :5432  | grep java  
注:5432为pg端口Qgrep java是ؓ了过滤client上的其他形式的连接?/em>
发现q接数和在server端看到的q接C_且均为ESTABLISH状态?
2. 但在client上执行查询时Q通过tcpdump查看client发往server的tcphQƈ无Q何请求生?
Java代码  
  1. sudo tcpdump -s 65535 -X -i eth0 host xxx.xxx.xxx  
可见当前U程池中的连接实际上已经失效了,但dbcp仍认为它是有效的Q因此仍在尝试用旧连接访问数据库Q直至网l超时?

于是Q开始怀疑是vpn的问题,client接上|线直连内网后,再次重试上述步骤Q只是把断网的方式由切断vpn换成了拔|线Q发现这ơ用断|前的连接能够正常访问数据库Q于是断定是vpn的问题,猜测是重qvpn后,虽然client端ip没有变,但\q路径已经变了Q之前的q接无法复用Q但dbcpq不知道。对|络l节不是太熟悉,׃多加揣测了?

接下来模拟数据库断开clientq接的情?/strong>
׃pg采用的是q程模型Q与数据库徏立的每一个连接都是单独的一个进E,故尝试采用killq程的方式模拟数据库断开q接?
预期的结果是Qkill掉一个连接进E后Qdbcp通过validate query发现该连接失效,销毁该q接q新创建新q接?
但实际情늡是:kill掉一个连接后Q所有连接全部被销毁?
问题Q?/strong>I竟是数据库q是dbcp销毁了所有连?
排查q程Q?/strong>
熟悉pg的同事认为pg之所以采用进E模型,是Z避免q接之间的媄响,因此不可能发生kill一个连接,其他q接也被销毁的情况。在q个理论前提下,问题变得很诡异Q因为dbcp的validate肯定是针对一个连接的Q也不可能会在validate一个连接失效的情况下销毁所有连接,于是想偏Q甚臛_始怀疑是pg的jdbc driver有问题,最l放弃了q?
但我总觉得有点不太对Ԍ于是推翻之前的前提,开始怀疑是pg销毁了所有连接。于是,在用连接池的应用之外,通过pg的数据库客户端psqlq接dbQ这徏立了一个与dbcp无关的连接,接着l箋在server端kill了一个连接池中的q接Q而发现psql创徏的连接也被销毁了Q这p定是pg在销毁连接,因ؓdbcp不可能控制自w范围之外的q接?
后来才知道,pg之所以会q么做,是因为我们killq接时用的是kill -9Q简U?杀Q,9杀太过_暴Qpg会重启很多内部进E,以保证所有进E正常,之前的连接也会丢失Q换用普通的kill命oQ则不会发生以上情况。可?杀很多情况下是十分危险的,试想一个线上dbQ若?杀一个连接,后果不堪设想。。?

ȝ
说是dbcp问题排查Q但大家可以看到最l问题的Ҏ都跟dbcp没有什么关pR实际工作中的很多问题,兌的因素众多,需要有各方面的知识储备才能扑ֈ真正问题ҎQ否则就会把问题归结C个自׃太了解的领域?
另外Q看?a target="_blank">dbcp基本配置和重q配|?/a>q篇文章中对q接池重q有两句不错的ȝQ引用一下:
引用
1. 数据库意外重启后Q原先的数据库连接池能自动废弃老的无用的链接,建立新的数据库链?
2. |络异常中断后,原先的徏立的tcp链接Q应该能q行自动切换


最后附上测试用的dbcp配置?
testOnBorrow配置Q?
Xml代码  
  1. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  2.         <property name="driverClassName" value="${jdbc.driver}" />  
  3.         <property name="url" value="${jdbc.url}"/>  
  4.         <property name="username" value="${jdbc.user}" />  
  5.         <property name="password" value="${jdbc.passwd}" />  
  6.         <property name="removeAbandoned" value="true"/>  
  7.           <property name="initialSize" value="10" />  
  8.           <property name="maxIdle" value="10" />  
  9.           <property name="minIdle" value="10" />  
  10.            <property name="maxActive" value="30" />  
  11.            <property name="maxWait" value="30000" />  
  12.            <property name"testWhileIdle" value="false" />  
  13.         <property name"testOnBorrow" value="true" />  
  14.         <property name"testOnReturn" value="false" />  
  15.         <property name"validationQuery" value="select 1" />  
  16.         <!-- <property name= "validationQueryTimeout" value="1" /> 配置已失?->  
  17.     </bean>  
testWhileIdle配置Q?
Xml代码  
  1. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  2.         <property name="driverClassName" value="${jdbc.driver}" />  
  3.         <property name="url" value="${jdbc.url}"/>  
  4.         <property name="username" value="${jdbc.user}" />  
  5.         <property name="password" value="${jdbc.passwd}" />  
  6.         <property name="removeAbandoned" value="true"/>  
  7.           <property name="initialSize" value="10" />  
  8.           <property name="maxIdle" value="10" />  
  9.           <property name="minIdle" value="10" />  
  10.            <property name="maxActive" value="30" />  
  11.            <property name="maxWait" value="30000" />  
  12.            <property name"testWhileIdle" value="true" />  
  13.         <property name"testOnBorrow" value="false" />  
  14.         <property name"testOnReturn" value="false" />  
  15.         <property name"validationQuery" value="select 1" />  
  16.         <!-- <property name= "validationQueryTimeout" value="1" /> 配置已失?->  
  17.         <property name"timeBetweenEvictionRunsMillis" value="30000" />  
  18.         <property name"numTestsPerEvictionRun" value="30" />  
  19.         <property name="minEvictableIdleTimeMillis" value="1800000" />  
  20.     </bean>  
注:testOnBorrow只会发现当前q接失效Q再创徏一个连接供当前查询使用Q而testWhileIdle会定时校验numTestsPerEvictionRun个连接,只要发现q接失效Q就其U除再重新创建?

 



疯狂 2013-06-06 09:38 发表评论
]]>
解决Vmware Workstation上安装Linuxpȝ不能SSHq程q接的问?http://www.dentisthealthcenter.com/freeman1984/archive/2013/05/31/400040.html疯狂疯狂Fri, 31 May 2013 13:18:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/05/31/400040.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/400040.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/05/31/400040.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/400040.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/400040.html打开本机讑֤理器中扑ֈ本机的网卡,打开其属性窗口,在高U标{中扑ֈ“ipv4 校验和分载传?#8221;其值置?#8220;用”Q按认后可以通过SSH讉K了。如图:



疯狂 2013-05-31 21:18 发表评论
]]>
URL最大长度限??http://www.dentisthealthcenter.com/freeman1984/archive/2013/05/30/399942.html疯狂疯狂Thu, 30 May 2013 01:29:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/05/30/399942.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/399942.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/05/30/399942.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/399942.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/399942.html

转自Q?a >http://blog.csdn.net/jinhill/article/details/3961881

  1. URL不能大于255bytes的说法确实存在,?a title="RFC2616" target="_blank">RFC2616中提刎ͼ

    The HTTP protocol does not place any a priori limit on the length of a URI. Servers MUST be able to handle the URI of any resource they serve, and SHOULD be able to handle URIs of unbounded length if they provide GET-based forms that could generate such URIs. A server SHOULD return 414 (Request-URI Too Long) status if a URI is longer than the server can handle (see section 10.4.15).

    Note: Servers ought to be cautious about depending on URI lengths above 255 bytes, because some older client or proxy implementations might not properly support these lengths.

  2. 从上一点也可以看出Q?55bytes的说法也是ؓ了兼Ҏ考虑。实际上C览器的限制如下Q?br />

    Microsoft Internet Explorer (Browser)
    Microsoft states that the maximum length of a URL in Internet Explorer is 2,083 characters, with no more than 2,048 characters in the path portion of the URL. In my tests, attempts to use URLs longer than this produced a clear error message in Internet Explorer.
    Firefox (Browser)
    After 65,536 characters, the location bar no longer displays the URL in Windows Firefox 1.5.x. However, longer URLs will work. I stopped testing after 100,000 characters.
    Safari (Browser)
    At least 80,000 characters will work. I stopped testing after 80,000 characters.
    Opera (Browser)
    At least 190,000 characters will work. I stopped testing after 190,000 characters. Opera 9 for Windows continued to display a fully editable, copyable and pasteable URL in the location bar even at 190,000 characters.
    Apache (Server)
    My early attempts to measure the maximum URL length in web browsers bumped into a server URL length limit of approximately 4,000 characters, after which Apache produces a “413 Entity Too Large” error. I used the current up to date Apache build found in Red Hat Enterprise Linux 4. The official Apache documentation only mentions an 8,192-byte limit on an individual field in a request.
    Microsoft Internet Information Server
    The default limit is 16,384 characters (yes, Microsoft’s web server accepts longer URLs than Microsoft’s web browser). This is configurable.
    Perl HTTP::Daemon (Server)
    Up to 8,000 bytes will work. Those constructing web application servers with Perl’s HTTP::Daemon module will encounter a 16,384 byte limit on the combined size of all HTTP request headers. This does not include POST-method form data, file uploads, etc., but it does include the URL. In practice this resulted in a 413 error when a URL was significantly longer than 8,000 characters. This limitation can be easily removed. Look for all occurrences of 16×1024 in Daemon.pm and replace them with a larger value. Of course, this does increase your exposure to denial of service attacks.

  3. 另外值得注意的是Q有文章提到作ؓ<a>的href属性时QURL不能过1024bytesQ这Ҏ有详l查?

lgQURLq是不适合太长Q不是不得已Q尽量不要通过GET方式提交大量参数Q可以考虑用POST方式Q大U在2M左右Q应该是和服务器及设定有养I。另外这么长的URL在访问和收藏Q有文章提到有些览器在收藏长地址时也是会出现问题Q时也是相当不友好的。当Ӟ之前数据库字D设|时q是作ؓ255bytes处理Q现在可能要考虑扩充一下了?/p>

参考:

  1. What is the maximum length of a URL?
  2. What is the limit on QueryString / GET / URL parameters?


疯狂 2013-05-30 09:29 发表评论
]]>
用MyEclipse试发送email时报java.lang.NoClassDefFoundError: com/sun/mail/util/LineInputStream http://www.dentisthealthcenter.com/freeman1984/archive/2013/05/28/399863.html疯狂疯狂Tue, 28 May 2013 05:05:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/05/28/399863.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/399863.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/05/28/399863.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/399863.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/399863.htmlJava EE5 替换为Java EE6 卛_。java EE5 里面不包含mail.jar{jar包。如果用JAVA EE5需要另外导入相关jar包?br />

疯狂 2013-05-28 13:05 发表评论
]]>
我应该采用哪一U?WSDL 样式Q(转蝲Q?/title><link>http://www.dentisthealthcenter.com/freeman1984/archive/2013/05/27/399821.html</link><dc:creator>疯狂</dc:creator><author>疯狂</author><pubDate>Mon, 27 May 2013 07:18:00 GMT</pubDate><guid>http://www.dentisthealthcenter.com/freeman1984/archive/2013/05/27/399821.html</guid><wfw:comment>http://www.dentisthealthcenter.com/freeman1984/comments/399821.html</wfw:comment><comments>http://www.dentisthealthcenter.com/freeman1984/archive/2013/05/27/399821.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/399821.html</wfw:commentRss><trackback:ping>http://www.dentisthealthcenter.com/freeman1984/services/trackbacks/399821.html</trackback:ping><description><![CDATA[<p>转自IBM java dev<br />------------------<br />Web 服务是通过 WSDL 文来描q的。WSDL l定描述了如何把服务l定到消息传递协议(特别?SOAP 消息传递协议)。WSDL SOAP l定可以?RPC 样式的绑定,也可以是文样式的绑定。同PSOAP l定可以有编码的用法Q也可以有文字的用法。这l我们提供了四种样式/用法模型Q?/p> <ol><li>RPC/~码</li><li>RPC/文字</li><li>文/~码</li><li>文/文字</li></ol> <p>除了q些样式之外Q还有一U样式也很常见,它称为文?文字包装的样式,上q一U,在创?WSDL 文g时您有了五U绑定样式可以从中选择。您应该选择哪一U呢Q?/p> <p>对于本文的讨论,让我们从 <a >清单1</a>中的 Java Ҏ开始,q且对其应用 JAX-RPC Java-to-WSDL 规则 </p><a name="listing1"><strong>清单</strong> </a><a name="listing1"><strong>1. Java Ҏ</strong> </a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode">public void myMethod(int x); </pre></td></tr></tbody></table><br /> <p><a name="0"><span class="atitle">RPC/~码</span></a></p> <p>采用 <a >清单1</a>中的Ҏq且使用您喜Ƣ的 Java-to-WSDL 工具来运行它Q指定您惌它生?RPC/~码?WSDL。您最后应该得到如 <a >清单2</a>所C的 WSDL 片断?</p><a name="listing2"><strong>清单</strong> </a><a name="listing2"><strong>2. 用于 myMethod ?RPC/~码?WSDL</strong> </a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"><message name="myMethodRequest"> <part name="x" type="xsd:int"/> </message> <message name="empty"/> <portType name="PT"> <operation name="myMethod"> <input message="myMethodRequest"/> <output message="empty"/> </operation> </portType> <binding .../> <!-- I won't bother with the details, just assume it's RPC/encoded. --> </pre></td></tr></tbody></table><br /> <p>现在?#8220;5”作ؓ参数 <code>x </code>的值来调用此方法。我们将发送一个与 <a >清单3</a>cM?SOAP 消息?</p><a name="listing3"><strong>清单</strong> </a><a name="listing3"><strong>3. 用于 myMethod ?RPC/~码?SOAP 消息</strong> </a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"><soap:envelope> <soap:body> <myMethod> <x xsi:type="xsd:int">5</x> </myMethod> </soap:body> </soap:envelope> </pre></td></tr></tbody></table><br /> <div class="ibm-container ibm-alt-header dw-container-sidebar"> <h2>关于前缀和名U空间的注意事项</h2> <div class="ibm-container-body"> <p>Z单v见,在本文的大部?XML CZ中,我省略了名称I间和前~。不q,我还是用了数前缀Q您可以假定它们是用下列名称I间q行定义的?/p> <p> <ul><li>xmlns:xsd="http://www.w3.org/2001/XMLSchema"</li><li>xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"</li><li>xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"</li></ul> <p> </p></div></div> <p>对于q个 RPC/~码的示例中?WSDL ?SOAP 消息Q有许多需要注意的事项Q?/p> <p><a name="IDAGE2AC"><span class="smalltitle">优点</span></a></p> <ul><li>WSDL 基本辑ֈ了尽可能地简单易懂的要求?/li><li>操作名出现在消息中,q样接收者就可以很轻村֜把消息发送到Ҏ的实现?/li></ul> <p><a name="IDAQE2AC"><span class="smalltitle">~点</span></a></p> <ul><li>cd~码信息Q比?<code>xsi:type="xsd:int"</code> Q通常是降低吞吐量性能的开销?</li><li>您不能简单地验此消息的有效性,因ؓ只有 <code><x xsi:type="xsd:int">5</x></code> 行包含在 Schema 中定义的内容Q其余的 <code>soap:body</code> 内容都来?WSDL 定义?</li></ul> <p>有没有一U方法能够保留这些优点而消除其中的~点呢?或许有。让我们来看一?RPC/文字的样式?/p> <div class="ibm-alternate-rule"> <hr /> </div> <p class="ibm-ind-link ibm-back-to-top"><a class="ibm-anchor-up-link" >回页?/a></p> <p><a name="1"><span class="atitle">RPC/文字</span></a></p> <p>用于我们的方法的 RPC/文字?WSDL 看v来与 RPC/~码?WSDL 几乎一P请参?<a >清单4</a>Q。只是绑定的用法?<em>~码</em>改ؓ <em>文字</em>。仅此而已?</p><a name="listing4"><strong>清单</strong> </a><br /><a name="N10123"><strong>4. 用于 myMethod ?RPC/文字?WSDL</strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"><message name="myMethodRequest"> <part name="x" type="xsd:int"/> </message> <message name="empty"/> <portType name="PT"> <operation name="myMethod"> <input message="myMethodRequest"/> <output message="empty"/> </operation> </portType> <binding .../> <!-- I won't bother with the details, just assume it's RPC/ <strong>literal</strong>. --> </pre></td></tr></tbody></table><br /> <p>RPC/文字?SOAP 消息又是怎样的呢Q请参见 <a >清单</a> <a >5</a>Q?q里的更改要多一炏V去掉了cd~码?</p><a name="listing5"><strong>清单</strong> </a><a name="listing5"><strong>5. </strong></a><a name="listing4"><strong>用于 myMethod ?/strong> </a><br /><a name="N10150"><strong>RPC/文字?SOAP 消息</strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"><soap:envelope> <soap:body> <myMethod> <x>5</x> </myMethod> </soap:body> </soap:envelope> </pre></td></tr></tbody></table><br /> <p>下面是这U方法的优点和缺点:</p> <p><a name="IDAXG2AC"><span class="smalltitle">优点</span></a></p> <ul><li>WSDL q是基本辑ֈ了尽可能地简单易懂的要求?/li><li>操作名仍然出现在消息中?/li><li>L了类型编码?/li></ul> <p><a name="IDACH2AC"><span class="smalltitle">~点</span></a></p> <ul><li>您仍然不能简单地验此消息的有效性,因ؓ只有 <code><x xsi:type="xsd:int">5</x></code> 行包含在 Schema 中定义的内容Q其余的 <code>soap:body</code> 内容都来?WSDL 定义?</li></ul> <p>文样式如何呢?它们能够帮助克服q些困难吗?</p> <div class="ibm-alternate-rule"> <hr /> </div> <p class="ibm-ind-link ibm-back-to-top"><a class="ibm-anchor-up-link" >回页?/a></p> <p><a name="2"><span class="atitle">文</span></a></p> <p>我不知道有谁懂得q种Ҏ的真正含义。我也不知道q种Ҏ的Q何实现。它可能从 WSDL 的后l版本中消失。所以我们还是讨论别的吧?/p> <div class="ibm-alternate-rule"> <hr /> </div> <p class="ibm-ind-link ibm-back-to-top"><a class="ibm-anchor-up-link" >回页?/a></p> <p><a name="3"><span class="atitle">文</span></a></p> <p>文/文字?WSDL ?RPC/文字?WSDL 作了一些更攏V它们之间的不同之处昄?<a >清单6</a>中?</p><br /><a name="N101AA"><strong>清单6. 用于 myMethod 的文?文字?WSDL</strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"> <strong><types> <schema> <element name="xElement" type="xsd:int"/> </schema> </types></strong> <message name="myMethodRequest"> <part name="x" <strong>element="xElement"</strong>/> </message> <message name="empty"/> <portType name="PT"> <operation name="myMethod"> <input message="myMethodRequest"/> <output message="empty"/> </operation> </portType> <binding .../> <!-- I won't bother with the details, just assume it's <strong>document</strong>/literal. --> </pre></td></tr></tbody></table><br /> <p>而现在的 SOAP 应该?<a >清单</a> <a >7</a>所C: </p><br /><a name="N101C8"><strong>清单7. 用于 myMethod 的文?文字?SOAP 消息</strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"><soap:envelope> <soap:body> <xElement>5</xElement> </soap:body> </soap:envelope> </pre></td></tr></tbody></table><br /> <div class="ibm-container ibm-alt-header dw-container-sidebar"> <h2>关于消息l成部分的注意事?/h2> <div class="ibm-container-body"> <p>我本来可以只更改l定Q就像我?RPC/~码转到 RPC/所做的那样。它是合法?WSDL。然而,WS-I 基本概要QWS-I Basic ProfileQ(请参?<a >参考资?/a>Q规定文?文字的消息的l成部分引用元素而不是类型,所以我遵@?WS-IQƈ且此处用元素部分可以很好地把我们带到关于文?文字包装的样式的讨论Q?</p></div></div> <p>下面是这U方法的优点和缺点:</p> <p><a name="IDA1Z2AC"><span class="smalltitle">优点</span></a></p> <ul><li>没有~码信息</li><li>您可以在最后用M XML 验器验此消息的有效性?<code>soap:body</code> Q?<code><xElement>5</xElement></code> Q中每项内容都定义在 Schema 中?</li></ul> <p><a name="IDAO02AC"><span class="smalltitle">~点</span></a></p> <ul><li>WSDL 变得有些复杂。不q,q是一个非常小的缺点,因ؓ WSDL q没有打由人来d?/li><li>SOAP 消息中缺操作名。而如果没有操作名Q发送就可能比较困难Qƈ且有时变得不可能?/li></ul> <p>文/文字的样式看hg只是重新安排?RPC/文字的模型的优点和缺炏V您可以验消息的有效性,但是您失M操作名。有没有一U方法可以改q这一点呢Q有的。它是文/文字包装的样式?/p> <div class="ibm-alternate-rule"> <hr /> </div> <p class="ibm-ind-link ibm-back-to-top"><a class="ibm-anchor-up-link" >回页?/a></p> <p><a name="N10218"><span class="atitle">文</span></a></p> <p>在我说明文/文字包装的样式的含义之前Q让我给您展C?<a >清单</a> <a >8</a>?<a >清单9</a>中的 WSDL ?SOAP 消息?</p><br /><a name="N1022D"><strong>清单8. 用于 myMethod 的文?文字包装?WSDL</strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"><types> <schema> <strong><element name="myMethod"/> <complexType> <sequence> <element name="x" type="xsd:int"/> </sequence> </complexType> </element></strong> </schema> </types> <message name="myMethodRequest"> <part name=" <strong>parameters</strong>" element=" <strong>myMethod</strong>"/> </message> <message name="empty"/> <portType name="PT"> <operation name="myMethod"> <input message="myMethodRequest"/> <output message="empty"/> </operation> </portType> <binding .../> <!-- I won't bother with the details, just assume it's document/literal. --> </pre></td></tr></tbody></table><br /> <p>WSDL Schema 现在把参数放在包装中Q请参见 <a >清单9</a>Q?</p><br /><a name="N10247"><strong>清单:9. 用于 myMethod 的文?文字包装?SOAP 消息</strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"><soap:envelope> <soap:body> <myMethod> <x>5</x> </myMethod> </soap:body> </soap:envelope></pre></td></tr></tbody></table><br /> <p>注意到此 SOAP 消息看v来非常类g RPC/文字?SOAP 消息。您可能会说Q它看v来与 RPC/文字?SOAP 消息是完全一LQ不q,q两U消息之间存在着微妙的区别。在 RPC/文字?SOAP 消息中, <code><soap:body></code> ?<code><myMethod></code> 子句是操作的名称。在文/文字包装?SOAP 消息中, <code><myMethod></code> 子句是单个输入消息的l成部分引用的元素的名称。因此,包装的样式具有这L一个特征,输入元素的名UC操作的名U是相同的。此样式是把操作名放?SOAP 消息的一Uy妙方式?</p> <p>文/文字包装的样式的特征有:</p> <ul><li>输入消息只有一个组成部分?/li><li>该部分就是一个元素?/li><li>该元素有与操作相同的名称?/li><li>该元素的复杂cd没有属性?/li></ul> <p>下面是这U方法的优点和缺点:</p> <p><a name="IDA522AC"><span class="smalltitle">优点</span></a></p> <ul><li>没有~码信息?/li><li>出现?soap:body 中的每项内容都是?Schema 定义的,所以您现在可以很容易地验此消息的有效性?/li><li>Ҏ名又出现?SOAP 消息中?/li></ul> <p><a name="IDAK32AC"><span class="smalltitle">~点</span></a></p> <ul><li>WSDL 甚至更复杂,但是q仍然是一个非常小的缺炏V?/li></ul> <p>如您所见,文/文字包装的样式还是有一些缺点,不过与优ҎhQ它们都昑־无轻重?/p> <div class="ibm-container ibm-alt-header dw-container-sidebar"> <h2>RPC/文字包装的样?</h2> <div class="ibm-container-body"> <p>?WSDL 的角度来看,没有理由只是把把包装的样式和文/文字l定联系在一赗它可以很容易地应用?RPC/文字l定。但是这样做是相当不明智的。SOAP 包含操作的一?<code>myMethod</code> 元素和元素名U的?<code>myMethod</code> 元素。另外,即它是一个合法的 WSDLQRPC/文字元素部分也不遵@ WS-I?</p></div></div> <p><a name="IDAG42AC"><span class="smalltitle">文/文字的样式在哪里定义</span></a></p> <p><br />q种包装的样式来源于 Microsoft。没有定义这U样式的规范Q所以虽然这U样式是一个好的东西,但不q的是,Z?Microsoft 和其他公司的实现q行互操作,现在惟一的选择是Ҏ Microsoft WSDL 的输出来猜测它是如何工作的。文?文字包装的样式也实现?IBM WebSphere SDK for Web Services 中(请参?<a >参考资?/a>Q。在q个CZ中,样式是相当明昄Q但是也存在个别情况Q在q些情况中,׃~少定义而导致需要操作的适当事项不够特别清晰。我们希望看到的最理想的情况就是将来能有像 Web 服务互操作组l(Web Services Interoperability OrganizationQ这L独立团体来帮助对此进行稳定化和标准化?</p> <div class="ibm-alternate-rule"> <hr /> </div> <p class="ibm-ind-link ibm-back-to-top"><a class="ibm-anchor-up-link" >回页?/a></p> <p><a name="N102C3"><span class="atitle">Z么不始终采用文/文字包装的样?/span></a></p> <p>xQ本文已l给了您q样的一个印象,文/文字包装的样式是最好的Ҏ。而实际的情况往往实如此。不q,仍然存在着一些情况,在这些情况下Q您最好是换一U别的样式?/p> <p><a name="IDA142AC"><span class="smalltitle">采用文/文字非包装的样式的理?/span></a></p> <p><br />如果您已l重载了操作Q就不能采用文/文字包装的样式?</p> <p>惌一下,除了我们一直在使用的方法之外,q有另一U方法,请参?<a >清单10</a>?</p><br /><a name="N102DE"><strong>清单10. 用于文/文字包装的问题方?/strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode">public void myMethod(int x); <strong>public void myMethod(int x, String y);</strong> </pre></td></tr></tbody></table><br /> <div class="ibm-container ibm-alt-header dw-container-sidebar"> <h2>关于重蝲的操作的注意事项</h2> <div class="ibm-container-body"> <p>WSDL 的下一个版本可能将不允讔R载的操作?/p></div></div> <p>WSDL 允许重蝲的操作。但是当您添加包装的样式?WSDL Ӟ需要元素有与操作相同的名称Qƈ且在 XML 中不能有两个名称相同的元素。所以您必须采用文/文字非包装的样式或某U?RPC 样式?/p> <p><a name="IDA252AC"><span class="smalltitle">采用 RPC/文字的样式的理由</span></a></p> <p><br />׃文/文字非包装的样式没有提供操作名,所以在有些情况下,您将需要采用某U?RPC 样式。比如说 <a >清单11</a>中的一l方法?</p><br /><a name="N10309"><strong>清单11. 用于文/文字非包装的样式的问题方?/strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode">public void myMethod(int x); public void myMethod(int x, String y); <strong>public void someOtherMethod(int x);</strong> </pre></td></tr></tbody></table><br /> <p>现在假定您的服务器接收到文/文字?SOAP 消息Q您可以回过头在 <a >清单</a> <a >7</a>中看一看它Q。服务器应该发送哪一U方法呢Q所有您能确切知道的是Q它一定不?<code>myMethod(int x, String x)</code> Q因为消息只有一个参敎ͼ而这U方法需要两个参数。它可能是其他两U方法中的一U。采用文?文字的样式,您没有办法知道是哪一U方法?</p> <p>假定服务器接收到一?RPC/文字的消息(比如 <a >清单5</a>中的Q,而不是文?文字的消息。对于这U消息,服务器很Ҏ军_把它发送到哪一U方法。您知道操作名是 <em>myMethod</em>Qƈ且也知道只有一个参敎ͼ所以它必定?<code>myMethod(int x)</code> ?</p> <p><a name="N10333"><span class="smalltitle">采用</span></a></p> <p><br />采用 RPC/~码的理由有很多。其中两个主要的原因是: </p> <ul><li>数据囑Ş</li><li>多态?/li></ul><br />数据囑Ş <br /> <p>设想您有一个二q制树,其中的节点定义在 <a >清单12</a>中?</p><br /><a name="N10352"><strong>清单12. 二进制树节点 Schema</strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"><complexType name="Node"> <sequence> <element name="name" type="xsd:string"/> <element name="left" type="Node" xsd:nillable="true"/> <element name="right" type="Node" xsd:nillable="true"/> </sequence> </complexType> </pre></td></tr></tbody></table><br /> <p>Ҏq种节点定义Q我们可以构造一个树形结构,它的根节?A 通过它左边和双的的链接可以指向节点 BQ请参见 <a >?</a>Q?</p><br /><img alt="~码的树" src="http://www.ibm.com/developerworks/cn/webservices/ws-whichwsdl/encodedtree.jpg" width="89" height="128" /> <br /> <p>发送数据图形的标准方式是?href 标记Q它?RPC/~码的样式( <a >清单13</a>Q的一部分?</p><br /><a name="N1037A"><strong>清单:13. RPC/~码的二q制?/strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"><A> <name>A</name> <left href="12345"/> <right href="12345"/> </A> <B id="12345"> <name>B</name> <left xsi:nil="true"/> <right xsi:nil="true"/> </B> </pre></td></tr></tbody></table><br /> <p>在Q何文字的样式中,href 属性都是不可用的,q样囑Ş链接׃再v作用了( <a >清单14</a>?<a >?</a>Q。您仍然有一个根节点 AQ它从左Ҏ向一个节?BQ从双指向另一个节?B。这两个 B 节点是等同的Q但它们不是相同的节炏V是复制了数据而不是引用了两次数据?</p><br /><a name="N1038F"><strong>14. 文字二进制树</strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"><A> <name>A</name> <left> <name>B</name> <left xsi:nil="true"/> <right xsi:nil="true"/> </left> <right> <name>B</name> <left xsi:nil="true"/> <right xsi:nil="true"/> </right> </A></pre></td></tr></tbody></table><br /><br /><img alt="文字? src="http://www.ibm.com/developerworks/cn/webservices/ws-whichwsdl/literaltree.jpg" width="194" height="128" /> <br /> <p>在文字样式中Q您可以通过各种Ҏ构造图形,但是却没有标准的ҎQ所以您做的M事情很可能不能与|络中其他端点上的服务进行互操作?/p><strong>多态?/strong> <br /> <p>看一?<a >清单15</a>中用多态?Schema ?WSDL?</p><a name="listing15"><strong>清单</strong> </a><br /><a name="N103BF"><strong>15. 一个多态?WSDL 的示?/strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"><types> <schema> <complexType name="animal"> <sequence> <element name="name" type="xsd:string"/> </sequence> </complexType> <complexType name="dog"> <complexContent mixed="false"> <extension base="animal"> <sequence> <element name="breed" type="xsd:string"/> </sequence> </extension> </complexContent> </complexType> </schema> </types> <message name="in"> <part name="trainee" type="animal"/> </message> <message name="empty"/> <portType name="AnimalTrainer"> <operation name="train"> <input message="in"/> <output message="empty"/> </operation> </portType> </pre></td></tr></tbody></table><br /> <p>当您把一?dog 的实例传送给 <em>train</em> 操作Ӟ所生成?SOAP 消息必须包含cd~码信息Q这h收终端才能知道它所接收的是 animal 的哪一个扩展(请参?<a >清单16</a>Q。这U类型编码信息可用在 RPC/~码的样式中?</p><a name="listing16"><strong>清单</strong> </a><br /><a name="N103DA"><strong>16. 一个多态?SOAP 消息</strong></a><br /> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td class="code-outline"><pre class="displaycode"><soap:envelope> <soap:body> <train> <trainee xsi:type="Dog"> <name>Bob</name> <breed>Bloodhound</breed> </trainee> </train> </soap:body> </soap:envelope></pre></td></tr></tbody></table><br /> <div class="ibm-alternate-rule"> <hr /> </div> <p><a name="6"><span class="atitle">ȝ</span></a></p> <p>有四U绑定样式(其实真正有五U,不过文/~码的样式没有什么意义)。虽然每U样式都有自q用武之地Q但是在大多数情况下Q最好的样式是文?文字包装的样式?/p><img src ="http://www.dentisthealthcenter.com/freeman1984/aggbug/399821.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.dentisthealthcenter.com/freeman1984/" target="_blank">疯狂</a> 2013-05-27 15:18 <a href="http://www.dentisthealthcenter.com/freeman1984/archive/2013/05/27/399821.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux 挂蝲ntfs usb 出现mount: unknown filesystem type 'ntfs'http://www.dentisthealthcenter.com/freeman1984/archive/2013/05/17/399427.html疯狂疯狂Fri, 17 May 2013 10:06:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/05/17/399427.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/399427.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/05/17/399427.html#Feedback0http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/399427.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/399427.html问题Q?br />      # mount –t ntfs /dev/sdc1 /mnt/usb
      mount: unknown filesystem type ‘ntfs’
q是׃ 上无法识别NTFS格式的分区?/p>

解决办法Q?br />      通过使用 ntfs-3g 来解冟?br />      打开ntfs-3g的下载点http://www.tuxera.com/community/ntfs-3g-download/ Q将最新稳定ntfs-3g-2011.1.13下蝲到linuxQ?br />执行以下命o安装Q?br />      1) ~译安装 ntfs-3gQ?br /># tar zxvf  ntfs-3g-2011.1.13.tgz
# cd ntfs-3g-2011.1.15
#./configure
#make
#make install
mount -t ntfs-3g  /dev/sdc1 /mnt/usb

完~



疯狂 2013-05-17 18:06 发表评论
]]>
11g oracle 用户密码q期问题http://www.dentisthealthcenter.com/freeman1984/archive/2013/04/23/398301.html疯狂疯狂Tue, 23 Apr 2013 09:25:00 GMThttp://www.dentisthealthcenter.com/freeman1984/archive/2013/04/23/398301.htmlhttp://www.dentisthealthcenter.com/freeman1984/comments/398301.htmlhttp://www.dentisthealthcenter.com/freeman1984/archive/2013/04/23/398301.html#Feedback1http://www.dentisthealthcenter.com/freeman1984/comments/commentRss/398301.htmlhttp://www.dentisthealthcenter.com/freeman1984/services/trackbacks/398301.html阅读全文

疯狂 2013-04-23 17:25 发表评论
]]>
久久一级片
<noframes id="395jp"><noframes id="395jp"><video id="395jp"><video id="395jp"></video></video>
<i id="395jp"><font id="395jp"><delect id="395jp"></delect></font></i>
<nobr id="395jp"></nobr><noframes id="395jp"><noframes id="395jp"><dl id="395jp"></dl><video id="395jp"></video><noframes id="395jp"><dl id="395jp"></dl>
<video id="395jp"><video id="395jp"><dl id="395jp"></dl></video></video> <nobr id="395jp"><nobr id="395jp"><meter id="395jp"></meter></nobr></nobr>
<video id="395jp"></video><nobr id="395jp"></nobr>
<video id="395jp"></video>