??xml version="1.0" encoding="utf-8" standalone="yes"?> 那么Q网址劫持是怎么回事呢? 302重定向和|址劫持有什么关pdQ这要从搜烦引擎如何处理302转向说v。从定义来说Q从|址A做一?02重定向到|址BӞL服务器的隐含意思是|址A随时有可能改LQ重新显C本w的内容或{向其他的地方。大部分的搜索引擎在大部分情况下Q当收到302重定向时Q一般只要去抓取目标|址可以了Q也是说网址B。实际上如果搜烦引擎在遇?02转向Ӟ癑ֈ之百的都抓取目标|址B的话Q就不用担心|址URL劫持了?br /> ׃搜烦引擎排名法只是E序而不是hQ在遇到302重定向的时候,q不能像ZLd判定哪一个网址更适当Q这造成了网址URL劫持的可能性。也是_一个不道d的h在他自己的网址A做一?02重定向到你的|址BQ出于某U原因, Google搜烦l果所昄的仍然是|址AQ但是所用的|页内容却是你的|址B上的内容Q这U情况就叫做|址URL劫持。你辛辛苦苦所写的内容p栯别h偯了?br /> 当网A?01重定向{到网BӞ搜烦引擎可以肯定|页A怹的改变位|,或者说实际上不存在了,搜烦引擎׃把网B当作唯一有效目标?01的好处是: Q?Q没有网址规范化问题?br />Q?Q网A的PR|页U别会传到网BQ这对SEO非常重要Q?br />
ȝ来说Q设|网站标题必L握以下原则:
1、标题不能太ѝ原则上标题长度不能过80个汉字,但实际上过30个汉字,在癑ֺ的搜索结果中昄不完整了?br />2、标题包含的信息要够多。信息太不能很好地利用长尾词带来的巨大效果?br />3、标题在长度合适的情况下,必须出现可能多地出C打的推广关键词?br />
以上三个条g看v来有些矛盾,又不能太长,又需要包含更多的推广关键词,q怎么可能呢?
实际上,只要我们理解了百度分词的原理Q这个目标是可以实现的。下面以一?a title="婴儿|站" >婴儿|站www.baobeicang.com作ؓ例子来分析下?br />
q个|站的标题是“婴儿用品排行榜,婴儿奶粉什么牌子好Q婴儿辅食大?#8221;。这个标题看似只有三个关键词Q实际上推广的关键词很多?br />
下面单列举下几个Q大家可以思考下Z么会有这L效果Q?br />1、婴儿用?br />2、婴儿用品排行榜
3、婴儿奶_?br />4、婴儿奶_排行榜
5、婴儿奶_什么牌子好
6、婴儿用品什么牌子好
。。。。。?br />
q就是利用百度分词原理得到的l果。有了这么多长尾关键词在首页标题里面Q相信接下来的SEO工作会事半功倍的Q?br />
]]>
q里我只是提Z个观点:做好SEO需要善于向优秀的竞争对手学习!可以向竞争对手学习的内容包括下面几点Q?br />
一、网站标题、描q、主要关键词是怎么定的?
|站标题、描q、主要关键词都是需要在建站的时候就定下来的。一旦上U最好不要修改它Q特别是新站Q权重不高的时候。如果你不知道怎么定这些的话,一个方法是利用一些站长工L关键词挖掘功能。还有一个很好的办法是参考竞争对手的|站Q看看别人是怎么定的。自׃要思考ؓ什么别那样讄Q那栯|有什么好处?然后再来定自q站的。当然也不能和竞争对手的一模一栗目前比较流行的Ҏ是利用百度的分词原理讄|站的标题,q样可以产生很多的长?br />
二、网站是怎么样布局的?
|站的布局对SEO也很重要Q合理的布局有利于用户和|络爬虫的浏览。可以学习对手的布局Q包括:首页、栏目页、内定w、导航栏{等。另外发现好的站点也可以查看下用的是什么模版开发的。比如我在定ȝ拉链www.xurizipper.comq个站布局的时候就参考了很多的竞争对手?br />
三、文章是怎么写的Q怎么更新Q内链怎么弄?
|站的原创文章是提高|站排名和权重的法宝之一。你可以仔细看看Ҏ的文章,分析都是怎么写成的。一般网站有100以上的文章的话Q全部是原创有点难,很多是伪原创的。那么他是用什么手D做到很好的伪原创的呢?q有一点就是原创文章的更新Q这也是有技巧的。原则就是需要定时定量地更新原创或深度伪原创文章Q你可以观察Ҏ每天更新多少文章,更新的时间点是什么时候?
内链大多数都是在文章内容设|的Q这时你可以看看Ҏ是怎么弄的。现在百度对内链来重视,值得站长们去挖掘?br />
四、外链是怎么发布的?
外链怎么发布也是个重要的N。你可以分析Ҏ的外铄成,看都是在哪些地方发的Q然后你可以分析那些发外铄地方有没有h值去发,或者好不好留外链?br />
ȝhQ分析优U的竞争对手是很有价值的Q因Z们是zȝ生的案例。ƈ且他们的排名都做得不错,说明他们的方法也是有效的Q这么好的东西ؓ什么我们不d习呢Q?br />
]]>
常用?0Xq回码有下面几种Q?br />301 怹性蟩?br />302 暂时性蟩?br />304 Not Modified 文未修?br />305 Use Proxy 客户h的文档应该通过Location头所指明的代理服务器提取Q属于HTTP 1.1新增内容
其中Q对SEO产生影响的是前两个,?01?02。我先详细的介l这两个状态码的区别?br />
一?02
对用戯已Q?01Q?02是没有区别的。他们看到效果只是一个蟩转,览器中旧的URL变成了新的URL。页面蟩Cq个新URL指向的地斏V?br />但是对于搜烦引擎Q?02转向可能会有URL规范化及|址劫持的问题。可能被搜烦引擎判ؓ是作弊。网址规范化的内容可以参考这文章:http://www.chinamyhosting.com/seoblog/2006/04/10/url-canonicalization/
问题在于,有的时候搜索引擎,其是GoogleQƈ不能L抓取目标|址。ؓ什么呢Q比如说Q有的时候A|址很短Q但是它做了一?02重定向到B|址Q而B|址是一个很长的׃八糟的URL|址Q甚臌有可能包含一些问号之cȝ参数。很自然的,A|址更加用户友好Q而B|址既难看,又不用户友好。这时Google很有可能会仍然显C网址A?/p>
二?01
在实际操作过E中Q我和同事对一个站点(www.woshuone.comQ做了实验。结果发C是使用301q是302Q很Ҏ被Google “K?#8221;Q取消蟩转之后过一周左右的旉又恢复了。看来搜索引擎蜘蛛现在对面跌{q是比较反感Q认Z弊的可能性大Q宁可错杀一百也不放q一人!
]]>
作者:Mark Levison 译者:赖勤?发布?2010q?1??/p>
现在已经到第十次q代开发周期了Q你的项目开发速度开始变慢。在之前的几个P代周期中Q团队没有像以前那样完成很多?#8220;故事场景”QstoriesQ。此外,最q在新的故事场景和回溯中却发现更多缺?bug)。项目经理知道,团队成员没有变,他们也花同样的时间工作。但是,客户会发问:“发生什么事情了Q这个团队还在努力工作吗Q?#8221;
很多敏捷团队的品改q率?50-500%Q可是你们的目看v来却貌似只有20-40%左右的改q率。这到底是怎么回事呢?在此我们找不C么大问题Q相反,只是有无数的问题。有Ӟq些只是一些ؓ了方便而用的捷径Q开发h员没有时间去清理q些修改Q,有时开发h员仅仅是不熟悉这中语a。还有一些问题就是,代码跟灌木丛一样凌乱,需要大q度的修整。所有这些都属于“技术债务”?/p>
什么是“技术债务”Q?/strong>
它就?#8220;那些内在的事物,现在你不去解冻I遗留下来Q不q完Q,它就会阻未来开?#8221;[Ward Cunningham]?表面上,应用E序看v来质量很高且状况良好Q但是这些问题却隐藏在下面?QAQ质量保证部门)甚至可能告诉你说Q这个应用程序真是不错,几乎找不到缺P但是其中仍然存在“技术债务”Q如果我们没有很好地理q设法降低这?#8220;技术债务”Q那么,E序~写和维护的代h最l将会超q它对客L价倹{?/p>
技术债务像信用卡一P会有很高的利息率Q就如同l团队留下了大量的帐务开销。这U情况下Q开销会体现在时间花费和解决问题所需的努力上面。开发团队拖延债务的时间越长,所U篏的利息就多Q会额外增加很多工作Q,付出的成本也p高?/p>
另外Q这q增加了实际的胦务支出:开发团队处理技术债务所p的时_可以用在对团队有价值的其它工作上。同Ӟq些难读的代码引L技术债务也让我们难以扑ֈ软g的缺陗再且,理解代码所损失的时间还可以用来做其它更有h值的事情呢?/p>
我们Z要篏U技术债务呢?
目~码初期Q不整理代码Q不写单元测试,也不做测试驱动开发,整个团队_制滥造出更多?#8220;故事场景”?q些问题通常都不会马上暴露出来,而@规蹈矩地~写代码往往需要更多的旉Q特别是在早期阶Dc?/p>
技术债务来自哪里Q?/strong>
解决问题
q个问题的ƈ不是一下子可以解决的,解决Ҏ需要通过几个q代周期。ƈ且,你需要耐心Qƈ要从多个角度L解决途径?/p>
解决Ҏ中的要点
Zq样的立场,你会发现问题Q也会拥有机会。你的问题是Q项目的基础代码一直在U篏技术债务Q但是这些债务已经开始下降了。然而,现在跟客LL于处理这些问题的资金会跟处理q些问题一样困难。你的机遇是Q提高了开发h员的技能;清楚地表达了理层对q项工作的支持,q有QY件的代码质量会不断改善,软g~陷的数目也会不断减。同时这也会很好的提高团队的整体开发能力?/p>
一、从数据的角度来看,数据包括Q收集、存储、分析(挖掘Q、展C、提取?/strong>兼顾目前的系l,攉、存储、挖掘、提取,q几个环节的pȝ需要加强。特别是攉和提取这块?/p>
׃历史的原因,加之没有pȝ规划q,之前的数据收集来源比较零散,q样D分析数据旉要从各个地方来同步数据。当业务多了之后Q这些ؕ七八p的来源够让h头疼了。这ơ规划的一个重点就是,建立一套游戏数据收集系l。游戏分析涉及的数据Q日志类Q都从这个系l中获取Q不再单独分析各自的业务数据。业务系l采用数据上报的方式Q按照固定的格式来上报数据。例如:d、注册、充倹{消耗等{?/p>
采用q套游戏数据攉pȝQ还有一个重要的原因。现在我们的游戏都是独立q营游戏Q我们是甲方Q,那么我们可以采用类D讯的办法Q事先定义好数据规范Q要求游戏方按照我们的格式上报相x据给我们。这h们的数据分析pȝ可以做到非帔R用。不接多少游戏Q分析和展示pȝ都统一?/p>
数据提取Q这里主要是指时数据。这是我们这边的一个顽疾。时数据其实包括两个部分:数据来源和数据分析。一个常见的需求就是:分析一堆帐P数据来源Q的后箋行ؓQ数据分析)。因Z时数据的业务规则复杂Qƈ且数据来源千奇百怪,之前采用q全手工、全自动的方式来实现Q但是都p|了。现在想到的一个解x案就是,Z游戏数据攉pȝ之上Q再开发一个时数据分析系l?/p>
游戏数据攉pȝl一了数据的来源和格式,方便存储和提取原始数据。这基本解决了数据来源的问题。时数据分析系l,可以事先实现常见的分析逻辑Q例如:d、留存、保有、付费h数、付贚w额、消耗等{)Q然后采用过滤器模式或包装器模式来实现。这其实是一个半自动化的Ҏ。系l的用户是开发h员和产品人员。开发完q套pȝ应该可以省掉60%以上的时数据Q务?/p>
另外Q只要数据都是来自这套游戏数据收集系l,存储、分析,包括挖掘都会单很多。存储都会在HDFS上,分析基本都用HiveQ挖掘用Mahout?/p>
游戏数据挖掘是需要单独发展的一块业务,特别是现在专注独立运营之后。目前这块我们还需要更多的旉来积累经验?/p>
二、从服务的角度来看,服务包括Q服务框架、服务管理、服务监?/strong>?/p>
服务也是一个大范畴。服务化框架、页面登录服务器、GM接口Q这些都属于服务相关的内宏V兼儡前的pȝQ这些内定w已经基本实现Q这ơ只是做比较大的版本改进?/p>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/p>
我打把自己在这斚w的实际经验写成系列文章,主要包括下面q些内容Q?/font>
1?/font>U上应用故障排查之一Q高CPU占用
2?/font>U上应用故障排查之二Q高内存占用
3、线上应用故障排查之三:高I/O占用Q包括磁盘I/O、网lI/O、数据库I/O{?/p>
4、线上应用故障排查之四:E序僉|
敬请期待Q?/p>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
搞Java开发的Q经怼到下面两种异常Q?/p>
1、java.lang.OutOfMemoryError: PermGen space
2、java.lang.OutOfMemoryError: Java heap space
要详l解释这两种异常Q需要简单重提下Java内存模型?/p>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
Java内存模型是描qJavaE序中各变量Q实例域、静态域和数l元素)之间的关p,以及在实际计机pȝ中将变量存储到内存和从内存取出变量这L低层l节?/p>
在Java虚拟ZQ内存分Z个代Q新生代Q?strong>NewQ、老生代(OldQ、永久代Q?strong>PermQ?/p>
Q?Q新生代NewQ新建的对象都存放这?/p>
Q?Q老生代OldQ存放从新生代New中迁U过来的生命周期较久的对象。新生代New和老生代Old共同l成了堆内存?/p>
Q?Q永久代PermQ是非堆内存的组成部分。主要存攑֊载的Classcȝ对象如class本nQmethodQfield{等?/p>
如果出现java.lang.OutOfMemoryError: Java heap space异常Q说明Java虚拟机的堆内存不够。原因有二:
Q?QJava虚拟机的堆内存设|不够,可以通过参数-Xms?Xmx来调整?/p>
Q?Q代码中创徏了大量大对象Qƈ且长旉不能被垃圾收集器攉Q存在被引用Q?/p>
如果出现java.lang.OutOfMemoryError: PermGen spaceQ说明是Java虚拟机对怹代Perm内存讄不够?/p>
一般出现这U情况,都是E序启动需要加载大量的W三方jar包。例如:在一个Tomcat下部|了太多的应用?/p>
从代码的角度QY件开发h员主要关注java.lang.OutOfMemoryError: Java heap space异常Q减不必要的对象创建,同时避免内存泄漏?/p>
现在以一个实际的例子分析内存占用的故障排查?/p>
通过top命oQ发现PID?004的Javaq程一直占用比较高的内存不释放Q?4.7%Q,出现高内存占用的故障?
惌v上一?a href=" http://www.tkk7.com/hankchen/archive/2012/05/09/377735.html">U上应用故障排查之一Q高CPU占用介绍的PS命oQ能否找到具体是哪个的线E呢Q?
ps -mp 9004 -o THREAD,tid,time,rss,size,%mem
遗憾的是Q发现PS命o可以查到具体q程的CPU占用情况Q但是不能查?strong>一个进E下具体U程的内存占用情c?
只好L其他Ҏ了,q好Java提供了一个很好的内存监控工具Q?font color="#ff0000">jmap命o
jmap命o有下面几U常用的用法Q?
•jmap [pid]
•jmap -histo:live [pid] >a.log
•jmap -dump:live,format=b,file=xxx.xxx [pid]
用得最多是后面两个。其中,jmap -histo:live [pid] 可以查看当前Javaq程创徏的活跃对象数目和占用内存大小?
jmap -dump:live,format=b,file=xxx.xxx [pid] 则可以将当前Javaq程的内存占用情况导出来Q方便用专门的内存分析工P例如QMATQ来分析?
q个命o对于分析是否有内存泄漏很有帮助。具体怎么使用可以查看本博的另一文章:利用Eclipse Memory Analyzer ToolQMATQ分析内存泄?/font>
q里详细介绍下jmap -histo:live [pid] 命oQ?/strong> 从上囑֏以看出,int数组、constMethodKlass、methodKlass、constantPoolKlass都占用了大量的内存? 特别是占用了大量内存的int数组Q需要仔l检查相关代码? 最后,ȝ下排查内存故障的Ҏ和技巧有哪些Q?/strong> 1、top命oQLinux命o。可以查看实时的内存使用情况?nbsp; 2、jmap -histo:live [pid]Q然后分析具体的对象数目和占用内存大,从而定位代码? 3、jmap -dump:live,format=b,file=xxx.xxx [pid]Q然后利用MAT工具分析是否存在内存泄漏{等? Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
]]>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
以我们最q出现的一个实际故障ؓ例,介绍怎么定位和解册c问题?/p>
Ҏtop命oQ发现PID?8555的Javaq程占用CPU高达200%Q出现故障?/p>
通过ps aux | grep PID命oQ可以进一步确定是tomcatq程出现了问题。但是,怎么定位到具体线E或者代码呢Q?/p>
首先昄U程列表:
ps -mp pid -o THREAD,tid,time
扑ֈ了耗时最高的U程28802Q占用CPU旉快两个小时了Q?
其次需要的U程ID转换?6q制格式Q?/b>
printf "%x\n" tid
最后打印线E的堆栈信息Q?/b>
jstack pid |grep tid -A 30
扑ֈ出现问题的代码了Q?
现在来分析下具体的代码:ShortSocketIO.readBytes(ShortSocketIO.java:106)
ShortSocketIO是应用封装的一个用短连接Socket通信的工L。readBytes函数的代码如下:
public byte[] readBytes(int length) throws IOException {
if ((this.socket == null) || (!this.socket.isConnected())) {
throw new IOException("++++ attempting to read from closed socket");
}
byte[] result = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
if (this.recIndex >= length) {
bos.write(this.recBuf, 0, length);
byte[] newBuf = new byte[this.recBufSize];
if (this.recIndex > length) {
System.arraycopy(this.recBuf, length, newBuf, 0, this.recIndex - length);
}
this.recBuf = newBuf;
this.recIndex -= length;
} else {
int totalread = length;
if (this.recIndex > 0) {
totalread -= this.recIndex;
bos.write(this.recBuf, 0, this.recIndex);
this.recBuf = new byte[this.recBufSize];
this.recIndex = 0;
}
int readCount = 0;
while (totalread > 0) {
if ((readCount = this.in.read(this.recBuf)) > 0) {
if (totalread > readCount) {
bos.write(this.recBuf, 0, readCount);
this.recBuf = new byte[this.recBufSize];
this.recIndex = 0;
} else {
bos.write(this.recBuf, 0, totalread);
byte[] newBuf = new byte[this.recBufSize];
System.arraycopy(this.recBuf, totalread, newBuf, 0, readCount - totalread);
this.recBuf = newBuf;
this.recIndex = (readCount - totalread);
}
totalread -= readCount;
}
}
}
问题出在标U的代码部分。如果this.in.read()q回的数据小于等?Ӟ循环׃直进行下M。而这U情况在|络拥塞的时候是可能发生的?
至于具体怎么修改q业务逻辑应该怎么对待q种Ҏ情况了?
最后,ȝ下排查CPU故障的方法和技巧有哪些Q?/strong> 1、top命oQLinux命o。可以查看实时的CPU使用情况。也可以查看最q一D|间的CPU使用情况? 2、PS命oQLinux命o。强大的q程状态监控命令。可以查看进E以及进E中U程的当前CPU使用情况。属于当前状态的采样数据? 3、jstackQJava提供的命令。可以查看某个进E的当前U程栈运行情c根据这个命令的输出可以定位某个q程的所有线E的当前q行状态、运行代码,以及是否死锁{等?/font> 4、pstackQLinux命o。可以查看某个进E的当前U程栈运行情c? Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
]]>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong> Ҏl验Q应该是E序有死锁情况,于是在线上运行“jstack –F <pid>”命令,xU程堆栈dump下来?/font> 但是Q发现这个命令老是报下面的错误Q?/font> Thread 27316: (state = BLOCKED) U上环境是: Linux 2.6.18-194.el5 x86_64 x86_64 x86_64 GNU/Linux java version "1.6.0_21" l过分析发现Q这是JDK6u23之前版本的一个BugQ将JDK升到最新版本(1.6.0_31Q就可以解决问题了?/p> Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
Error occurred during stack walking:
sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp
Java(TM) SE Runtime Environment (build 1.6.0_21-b04)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01, mixed mode)
]]>
Q?Q客L发送一个请求AQ长q接Q,在服务器端的业务层需?0U以上才能接收到?/p>
Q?Q客L发送一个请求BQ端q接Q,在服务器端的业务层可以迅速接收到?/p>
从现象大致知道问题出在服务器端的|络接收层,大量通过长连接发送过来的h都堵塞在|络层得不到处理Q在|络层排队,q没到应用层Q?/p>
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>
后来l过排查Q发现是Netty中的OrderedMemoryAwareThreadPoolExecutor原因。相关代码如下:
MemoryAwareThreadPoolExecutor executor = new OrderedMemoryAwareThreadPoolExecutor(threadNums, maxChannelMemorySize,
maxTotalMemorySize, keepAliveTime,
TimeUnit.SECONDS);
ExecutionHandler executionHandler = new ExecutionHandler(executor);
public ChannelPipeline getPipeline() throws Exception
{
ChannelPipeline pipeline = pipeline();
pipeline.addLast("decoder", new AuthDecoder());
pipeline.addLast("encoder", new AuthEncoder());
pipeline.addLast("executor", executionHandler);
pipeline.addLast("handler", new AuthServerHandler(commandFactory));
return pipeline;
}
先介l下背景知识Q再来分析问题?/p>
大家都知道,Netty是一个基于事件的NIO框架。在Netty中,一切网l动作都是通过事g来传播ƈ处理的,例如QChannel诅RChannel写等{。回忆下Netty的流处理模型Q?/p>
BossU程Q一个服务器端口对于一个)---接收到客Lq接---生成Channel---交给WorkU程池(多个WorkU程Q来处理?/strong>
具体的WorkU程---d已接收的数据到ChannelBuffer---触发ChannelPipeline中的ChannelHandler链来处理业务逻辑?/strong>
注意Q执行ChannelHandler铄整个q程是同步的Q如果业务逻辑的耗时较长Q会导致WorkU程长时间被占用得不到释放,从而媄响了整个服务器的q发处理能力?/p>
所以,Z提高q发敎ͼ一般通过ExecutionHandlerU程池来异步处理ChannelHandler链(workerU程在经qExecutionHandler后就l束了,它会被ChannelFactory的workerU程池所回收Q。在Netty中,只需要增加一行代码:
publicChannelPipeline
getPipeline() { returnChannels
.pipeline( new DatabaseGatewayProtocolEncoder(), new DatabaseGatewayProtocolDecoder(), executionHandler, // Must be shared new DatabaseQueryingHandler());
}
例如Q?/pre>ExecutionHandler
executionHandler = newExecutionHandler
( newOrderedMemoryAwareThreadPoolExecutor
(16, 1048576, 1048576))
对于ExecutionHandler需要的U程池模型,Netty提供了两U可选:
1Q?MemoryAwareThreadPoolExecutor 通过对线E池内存的用控Ӟ可控制Executor中待处理d的上限(过上限Ӟ后箋q来的Q务将被阻塞)Qƈ可控制单个Channel待处理Q务的上限Q防止内存溢出错误;
2Q?OrderedMemoryAwareThreadPoolExecutor ?MemoryAwareThreadPoolExecutor 的子cR除了MemoryAwareThreadPoolExecutor 的功能之外,它还可以保证同一Channel中处理的事g的序性,q主要是控制事g在异步处理模式下可能出现的错误的事g序Q但它ƈ不保证同一Channel中的事g都在一个线E中执行Q通常也没必要Q?
例如Q?pre>Thread X: --- Channel A (Event A1) --. .-- Channel B (Event B2) --- Channel B (Event B3) ---> \ / X / \ Thread Y: --- Channel B (Event B1) --' '-- Channel A (Event A2) --- Channel A (Event A3) --->
上图表达的意思有几个Q?
Q?Q对整个U程池而言Q处理同一个Channel的事Ӟ必须是按照顺序来处理的。例如,必须先处理完Channel A (Event A1) Q再处理Channel A (Event A2)、Channel A (Event A3)
Q?Q同一个Channel的多个事Ӟ会分布到U程池的多个U程中去处理?
Q?Q不同Channel的事件可以同时处理(分担到多个线E)Q互不媄响?nbsp;
OrderedMemoryAwareThreadPoolExecutor 的这U事件处理有序性是有意义的Q因为通常情况下,h发送端希望服务器能够按照顺序处理自qhQ特别是需要多ơ握手的应用层协议。例如:XMPP协议?
现在回到具体业务上来Q我们这里的认证服务也用了OrderedMemoryAwareThreadPoolExecutor。认证服务的其中一个环节是使用长连接,不断处理来自另外一个服务器的认证请求。通信的数据包都很,一般都?00个字节以内。一般情况下Q处理这个过E很快,所以没有什么问题。但是,׃认证服务需要调用第三方的接口,如果W三Ҏ口出现gq,导致这个过E变慢。一旦一个事件处理不完,׃要保持事件处理的有序性,其他事g全部堵塞了Q而短q接之所以没有问题,是因为短q接一个Channel׃个请求数据包Q处理完Channel关闭了Q根本不存在序的问题,所以在业务层可以迅速收到请求,只是׃同样的原因(W三Ҏ口)Q处理时间会比较ѝ?
其实Q认证过E都是独立的h数据包(单个帐号Q,每个h数据包之间是没有M关系的,保持q样的顺序没有意义!
最后的改进措施Q?
1、去掉OrderedMemoryAwareThreadPoolExecutorQ改用MemoryAwareThreadPoolExecutor?
2、减调用第三方接口的超时时_让处理线E尽早回归线E池?
Q友情提C:本博文章Ƣ迎转蝲Q但h明出处:hankchenQ?a href="http://www.tkk7.com/hankchen">http://www.tkk7.com/hankchenQ?/strong>