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

阴谋还是毒药?深度揭秘美剧产业

$
0
0

继快播被警方调查后,视频行业再踩政策红线。几个宅男科学家和一个美女邻居的生活故事,7年来给亿万美剧迷们带来了无尽的欢笑。如今,热门美剧《生活大爆炸》已播至第七季,而这一季的最后一集将于美国时间5月15日播出。然而,观众恐怕无法在国内正规的视频网站上观看了。

4月26日起,《生活大爆炸》《傲骨贤妻》《海军罪案调查处》和《律师本色》等4部美剧被国家新闻出版广电总局要求从各视频网站下架。

稍后有网友质疑,部分美剧下架的标准是什么?依据是什么?是否今后还有复播的可能?近期搜狐公司董事局主席兼首席执行官张朝阳简单回应:“被下架的美剧仅仅是个案,影响不大”。腾讯视频相关负责人也称:“目前还不方便发表更多意见,但下架美剧没有指向性。”

《傲骨贤妻》剧照

1980年5月,一部拍摄于1970年的《大西洋底来的人》在央视开播,成为敞开国门之后中国人观看美国的一扇新窗。随后,《加里森敢死队》、《神探亨特》、《成长的烦恼》、《老友记》等更是掀起了八九十年代的一股美剧潮。直到现在,从译制到原音原版,美剧已经成了一种自然而然的娱乐方式和读解美国的必经之路。从美剧的制作流程谈起,讲述热门英美剧的台前幕后。

乔布斯说他年轻时认为电视是个阴谋,电视网络合伙想把大家变得更愚蠢,年纪大了发现这个想法不对,不是电视网络的错,这根本就是观众们想要的。美剧在迎合广大观众喜怒哀乐的道路上,绝对称得上百分百真心付出。遍布全球各地的美剧观众也同样紧随其后,中国的观众更是辗转通过各种渠道和方式追看每一季最新剧集。题材广泛、风格多变的剧种,结构巧妙的情节,个性坦然的剧中人物,美剧成了生活的一部分,成了娱乐的一种状态。

迷你剧《幻世浮生》(Mildred Pierce)由凯特·温斯莱特主演。

美剧流水线

2010年美国电视行业收入为312亿美元(数据来自美国行业报告),这个世界上最庞大的电视网络,可以简单分为两大系统:电视网络(Networks)和有线电视(Cable TV)。四大电视网络集团ABC、CBS、NBC、FOX,以及非营利、非商业化运营的PBS,覆盖全美,用户免费收看;有线电视则只能在用户订购付费后收看。美剧制作公司与电视网络你中有我,我中有你,互为依存。四大电视网络和有线电视网络都有自己的美剧制作公司,大的传媒集团也同样拥有自己的电视网络,如华纳拥有HBO,迪斯尼拥有迪斯尼频道,此外还有成千上万的独立制作公司。

每年夏天,编剧和制片人都会带着自己最新的剧本概念或提纲同时向四大电视网络兜售,这些提纲只要被接收,电视网络就要支付给编剧们一笔费用买断优先权,比如1997年的电影《一夜情》(One Night Stand)编剧乔·埃泽特哈斯(Joe Eszterhas,也是电影《本能》〔Basic Instinct〕的编剧),3页纸的剧本提纲就卖了破纪录的200万美元。秋天,各大电视网络从各自收到的约500份新剧本中筛选70份左右出资购买,编剧们这时就要提供完整的剧本了。第二年的1月份,又会从中再选出约20个,继续出资拍摄试播集(Pilot),然后根据试播集的收视率决定是否订购(有线电视网HBO有所不同,HBO常年接收新剧本的上门推销,制作费用比电视网络低),各电视网络每年会订购4~5部新剧。2010至2011年,四大电视网络出资拍摄的试播集数量分别为:NBC电视21个,ABC电视23个,CBS电视18个,FOX电视15个,为保证剧集种类的多样性,剧情类和喜剧类的比例约各占一半。几乎没有哪个电视网络会在不看梗概没有试播集的情况下订购电视剧集,试播集常见的几个种类有:标准试播集约22分钟,也可以看做该电视剧的第一集,虽然最后很有可能不会被订购;介绍片7~10分钟,要在一天之内拍摄完成,介绍该剧故事主线和主要演员;后门试播集故事相对独立,内容完整,万一不被订购,也仍然可以作为单独的电视片播放;落选试播集拍摄完后电视网络突然又决定不予播出和订购,除已支付的试播集拍摄资金外,电视网络还要向制片单位支付一定比例的违约金作为赔偿。

每年5月份的第三个星期,曼哈顿城摇身变为广告人的“派对之城”,这一周各大广告公司负责人、各大电视网络负责人、各大制片公司负责人、影视明星以及各大媒体齐聚纽约,出没在林肯中心、电台城音乐大厅和卡耐基大厅等活动场地,参加一年一度的“电视网络广告预售会”,各大电视网络播放最新电视剧的预告片和介绍片,然后广告公司根据各剧上季的收视表现和新一季的收视预测,决定下一季广告费的投放。随即各大电视网络便会宣布自己下一季将要订购的电视剧名单。HBO又不同,以剧本内容和故事质量为重,不以广告投放量为准,其节目也没有任何广告插播,收入来源主要靠有线用户的订购费。专业、高水准的制作经常吸引明星参演,比如《大西洋帝国》(Boardwalk Empire)找到马丁·西科塞斯做试播集导演和制片,刚刚结束的迷你剧《幻世浮生》(Mildred Pierce)由凯特·温斯莱特主演,2012年1月份即将播出的《幸运》(Luck)将由达斯汀·霍夫曼主演。

编剧的天下

如此规模的美剧产业,可以毫不夸张地说是编剧的天下,大部分美剧“编剧主笔”等同于“制片总监”,美剧是属于编剧的媒体。制片人乔恩·富雷(Jon Furay)这么说:“编剧就是制片人,最初的想法是他们提供的,整个故事是他们创造的,每季22集的剧本是他们撰写的,他们决定故事的结构和情节的发展方向,他们还参与演员挑选,总之他们直接决定着收视率的高低。”在美剧行业,导演反而是客串,是“外人”,经常更换,他们只需要保证剧集的风格和品质前后一致即可。看看下面这个列表,就能知道编剧在美剧行业的核心地位,《迷失》(Lost)的主笔艾布拉姆斯(J.J.Abrams)甚至还亲自做导演,导演了《迷失》的试播集。

每部美剧被电视网络订购后,制片总监/主笔都会召集一个编剧团队,经常在一个编剧办公室里集中办公,合用着一张大办公桌,讨论争辩,最后由主笔或者指定的编剧完成一集剧本,日复一日,天天如此。你在《我为喜剧狂》(30 Rocks)里看到的那些场景基本属实,编剧们每天在各种兴奋、无聊、痴呆傻状态间转换。当然也有编剧狂人如《白宫风云》(The West Wing)的阿伦·索尔金(AaronSorkin),字必躬亲,乐此不疲,据说前4季88集几乎全部是他亲自写出来的,之后他离开该剧组,2011年因电影《社交网络》(The Social Network)获得了奥斯卡最佳改编剧本奖。

我见到《重金属秀》(That Mental Show)和《MTV》(MTV unplugged)不插电的制片总监杰夫·鲍姆加德纳(Jeff Baumgardner)时,他说到美剧编剧的写作,强调很多编剧尤其是喜剧编剧们“经常都是只为自己而写,基本上只要他们自己觉着写得好,写得足够好笑就可以了,观众会慢慢领会、慢慢跟上的”。成功的电视网络和制片人都非常善于培养和吸引有才华的编剧,其实就是提供一切必要的资源,让编剧有创作的空间和自由。比如《南方公园》(South Park)这样超现实、近乎残忍的黑色幽默成人动画片,除去第一季,其余14季近200集,每集30分钟的剧集从创意、概念、剧本到制作完成都只有6天时间(具体内容可观看纪录片《6 DaystoAir》),有些甚至短至3~4天,每天都在匆忙赶活,有时候甚至直到播出前一小时还没有完成。Comedy Central(喜剧中心电视台)的审查员基本与剧组每天24小时电话连线,讨论是否内容太过争议,避免被起诉,电视台愿意与剧组承担这样的风险,很疯狂,但同时也是这部剧成功的原因之一。鲍姆加德纳还谈到编剧的工作,基本上是一季一季来决定的,如果上一季写得不错,下一季再续约。重要的是找到风格适合的剧组,比如《辛普森家族》(The Simpsons)就有跟了剧组长达26年的编剧。编剧办公室里的氛围也挺重要,很可能每天一待就是12个小时,一周5天,运气好的话,长达20多年,所以这是一群互相敬慕、喜欢的人,因为这就是你的生活。还有就是不怕拒绝,拒绝是家常便饭,工作中经常性的场景就是A说:“如果这个人怎么做呢?”B说:“不行!”A又说:“如果换成那样呢?”B说:“也不行!”直到满意为止。

也有例外,一些人脉通达的金牌制片人,熟谙各大电视网络的风格和其主管的喜好偏向,拉一个班底,自己虽然不是编剧,也同样可以点石成金。制作过《加勒比海盗》、《珍珠港》、《亚瑟王》等电影的金牌制片人鲍姆加德纳就是一例,他跟各大电视网络集团关系深厚,只要是他兜售的想法,几乎都可以拍成播放,他制作的连锁剧《CSI/犯罪现场调查》的3个系列都取得了很大的成功,但主笔安东尼·苏克(AnthonyE.Zuiker)仍然同时兼任着3个系列剧制片总监的职务。

收视率

收视率是美剧命运的主宰者。电视网络需要用收视率来吸引广告商和更多的广告投入,有线电视的收视率则直接反映订购自己频道的用户数量,两个网络都需要收视率来获得更多投入,然后制作更高质量的剧集和节目,然后再吸引更多的投入,从而进入良性循环。收视率每年有4个最主要的数据测量收集期,分别为11月、2月、5月和7月,5月下旬的收视数据是最重要的,这时是美剧们每季的最后一集,又有“电视网络广告预售会”的召开,各剧都会用上自己的秘籍大招,在5月20日的前四周冲刺收视率。

美国电视的收视率统计有三个数据:一是收视率,二是收视比例,三是收视观众总数,以百万为单位。比如2010年5月19日晚21点福克斯频道的选秀节目《美国偶像》(AmericanIdol)节目的收视率是:18~49(年龄段),5.9/16(收视率5.9),收视比例16,18.46(总观众数1846万)。收视率是基于人口统计的样本数据进行统计,收视率计数器安装在有线电视机顶盒、录放机以及卫星网络,目前的收视率还包括后期电视点播、录放机以及网络收看的数据,更接近真实。这里所说的电视观众也不是指全国拥有电视机的观众总数,而是特指18~49岁年龄段的关键观众群。研究表明这个年龄段的人群不但拥有购买力,且会受广告直接影响产生实际消费行为。18岁之前的人群购买力较弱,49岁之后的人群绝大部分已经拥有自己的固定品牌和购买习惯,基本不受广告影响,所以广告商只需搞定18~49年龄段的人群即可,而这个趋势还在不断年轻化,现在部分广告商已开始将18~34岁年龄段作为重点关注人群。

“目前的技术其实是可以进入到每个家庭,具体到每个人,更深入真实地了解他们的观看内容,但这样一来公众会陷入隐私恐慌,所以无法实施。”鲍姆加德纳在谈到收视趋势的时候说,希望未来是像“Spotify”那样能收集更真实可靠的数据,Spotify是一个音乐软件,超酷的概念,免费下载注册后使用,界面很像苹果的iTune,实质却很不同,它可以了解你电脑里的音乐收集,了解你喜欢的音乐类型和风格,然后为你做个人调整。这对音乐人和音乐行业来说非常有意义,它形成了一个庞大的数据库,比如J-Zay开巡回演唱会到英国,制订演出地点时,在Spotify上调查得出歌迷大多集中在西北部曼彻斯特地区,于是决定演唱会在曼彻斯特举行,结果就是门票一抢而空。

临时工有力量

纽约本地52号(local52),世界上首批为影视业技术工人而设立的工会,成立于上世纪20年代中期,那还是默片当道的年代,在经历过最初的维权艰辛、影视业西迁洛杉矶后的衰退期、多重工会的内部恶性竞争期后,近一个世纪来坚持不懈,已成为今天美国最强硬的影视业技术工人工会,成员由灯光、录音、道具、化妆、服装、美工等技术人员组成,工会势力范围包括美国东海岸的纽约州、新泽西州、特拉华州、宾夕法尼亚州和康涅狄格州。

影视业是个“零散活”行业,每一个剧组都是短期项目,那些能拍一二十季的电视剧毕竟占少数,在这个意义上,所有影视业工作人员都接近于我们所理解的“临时工”或者“自由职业者”,而工会就代表这些“临时工和自由职业者”与各剧组谈判并签署用工合同,监督实施,保障工作人员的基本权利:

工会负责为工会成员介绍安排各剧组最新的工作;为工会成员提供最新影视技术器材的培训;各剧组必须优先雇用经验丰富、技术熟练的工会成员;一日三餐的时间和餐饮标准;周六、周日必须休息,如不休息,制片方要支付高额加班费,每天超出8小时后按工资的1.5倍算加班费,周日支付双倍工资;每天必须保证工作人员10小时的休息时间,如今天拍摄晚零点结束,第二天的工作最早在上午10点以后开始;根据各地分区的不同,工作地点乘车超过2小时或超出25~30英里,提供班车接送,且路上往返时间计入工作时间;工会负责会员、会员配偶和子女的养老、医疗健保,含昂贵的牙医保险;每个美剧剧组成立时会在现有工作人员中选出一个工会代表,负责监督记录工作时间,与制片人协调工作人员投诉,如果这样还不能解决问题的话,工作人员可直接电话工会反映问题,要求工会直接出面干涉等等。

工会与各剧组的合同按电影、电视、独立和广告等分为不同种类,每年工会代表都会和制片工会及各大媒体集团开会,把收集到的工会会员的新建议和新想法提出来,对合同进行更新,并按一定比例增加薪酬。加入工会是一个严格的程序,要有一定的工作经验,要通过笔试,实际操作考试,一年两次由现有工会成员进行投票选定。

美国的年轻人也爱看美剧,当然目的只是为了娱乐,玛丽·麦克莱恩(Mary Mc Lean)和埃琳·麦克莱恩(Erin Mc Lean)姐妹俩,一个是一所艺术院校文学专业二年级的学生,一个是综合大学的医学专业三年级的学生,义务帮我在他们所在的年级做了调研,他们最喜欢看的美剧排名依次为:《发展受阻》、《办公室》、《南方公园》、《老爸老妈浪漫史》及《恶搞之家》。这个小范围的调查表明美国年轻人比较爱看喜剧,尤其是剧情、人物脱离现实,冷笑话充斥的喜剧。另外一个榜上有名的就是真人秀《与卡戴珊同行》。

真人秀和选秀节目在过去10年来高居收视率的各大榜单,把情景喜剧挤出了收视前排,让人感叹《老友记》、《宋飞传》那样的辉煌已一去不返。但是最近几年,情景喜剧使用新的拍摄技法和语言后,又逐渐开始重现生机,比如单机摄影机拍摄的重新兴起;很多喜剧不再雇用现场观众;还有《办公室》的伪纪录片(Mockumentary)拍摄形式的流行,《摩登家庭》和《公园重建》便都模仿了其伪纪录片的拍摄手法。2010~2011年收视率的统计表明,除去体育节目,《摩登家庭》、《生活大爆炸》、《办公室》和《好汉两个半》等喜剧片都进入了收视前10。


Linux数据包路由原理、Iptables/netfilter入门学习 - .Little Hann

$
0
0

相关学习资料

https://www.frozentux.net/iptables-tutorial/cn/iptables-tutorial-cn-1.1.19.html
http://zh.wikipedia.org/wiki/Netfilter
http://www.netfilter.org/projects/iptables/
http://linux.vbird.org/linux_server/0250simple_firewall.php
http://linux.vbird.org/linux_server/0250simple_firewall.php
http://www.vpser.net/security/linux-iptables.html

 

目录

1. Iptables/Netfilter原理分析
2. Linux数据包路由原理
3. Iptables规则编写原则

 

1.  Iptables/Netfilter原理分析

在文章的最开头,我们首先要明确一个概念,Iptables/Netfilter到底是什么,它们之间的关系是怎样的。

我们可以这样简单地理解:

1. Netfilter是Linux操作系统核心层内部的一个数据包处理模块,它具有如下功能:
1) 网络地址转换(Network Address Translate)
2) 数据包内容修改
3) 以及数据包过滤的防火墙功能
Netfilter平台中制定了五个数据包的挂载点(Hook Point,我们可以理解为回调函数点,数据包到达这些位置的时候会主动调用我们的函数,使我们有机会能在数据包路由的时候有机会改变它们
的方向、内容),这5个挂载点分别是
1) PRE_ROUTING
2) INPUT
3) OUTPUT
4) FORWARD
5) POST_ROUTING
2. Iptables
Netfilter所设置的规则是存放在内核内存中的,Iptables是一个应用层(Ring3)的应用程序,它通过Netfilter放出的接口来对存放在内核内存中的Xtables(Netfilter的配置表)进行修改
(这是一个典型的Ring3和Ring0配合的架构)

Xtables

我们知道Netfilter是负责实际的数据流改变工作的内核模块,而Xtables就是它的规则配置文件,Netfilter依照Xtables的规则来运行,Iptables在应用层负责修改这个规则文件。

Xtables由"表"、"链"、"规则rule"组成

1. Filter(表)
filter表是专门过滤包的,内建三个链,可以毫无问题地对包进行DROP、LOG、ACCEPT和REJECT等操作
1) INPUT(链)
INPUT针对那些目的地是本地的包
1.1) 规则rule
     ..
2) FORWARD(链)
FORWARD链过滤所有不是本地产生的并且目的地不是本地(即本机只是负责转发)的包
2.1) 规则rule
     ..
3) OUTPUT(链)
OUTPUT是用来过滤所有本地生成的包
3.1) 规则rule
     ..
2. Nat(表)
Nat表的主要用处是网络地址转换,即Network Address Translation,缩写为NAT。做过NAT操作的数据包的地址就被改变了,当然这种改变是根据我们的规则进行的。属于一个流的包(因为包
的大小限制导致数据可能会被分成多个数据包)只会经过这个表一次。如果第一个包被允许做NAT或Masqueraded,那么余下的包都会自动地被做相同的操作。也就是说,余下的包不会再通过这个表
,一个一个的被NAT,而是自动地完成
1) PREROUTING(链)
PREROUTING 链的作用是在包刚刚到达防火墙时改变它的目的地址
1.1) 规则rule
     ..
2) INPUT(链)
2.1) 规则rule
     ..
3) OUTPUT(链)
OUTPUT链改变本地产生的包的目的地址
3.1) 规则rule
     ..
4) POSTROUTING(链)
POSTROUTING链在包就要离开防火墙之前改变其源地址。
4.1) 规则rule
     ..
3. Mangle(表)
这个表主要用来mangle数据包。我们可以改变不同的包及包 头的内容,比如 TTL,TOS或MARK。 注意MARK并没有真正地改动数据包,它只是在内核空间为包设了一个标记。防火墙内的其他的规
则或程序(如tc)可以使用这种标记对包进行过滤或高级路由。注意,mangle表不能做任何NAT,它只是改变数据包的TTL,TOS或MARK,而不是其源目地址。NAT必须在nat表中操作的。
1) PREROUTING(链)
PREROUTING在包进入防火墙之后、路由判断之前改变 包
1.1) 规则rule
     ..
2) INPUT(链)
INPUT在包被路由到本地之后,但在用户空间的程序看到它之前改变包
2.1) 规则rule
     ..
3) FORWARD(链)
FORWARD在最初的路由判断之后、最后一次更改包的目的之前mangle包
3.1) 规则rule
     ..
4) OUTPUT(链)
OUTPUT在确定包的目的之前更改数据包
4.1) 规则rule
     ..
5) POSTROUTING(链)
POSTROUTING是在所有路由判断之后
5.1) 规则rule
     ..

Netfilter的Hook点

Netfilter的架构就是在整个网络流程的若干位置放置了一些检测点(HOOK)(或者说是回调函数),而在每个检测点上登记(callback)了一些处理函数进行处理(如包过滤,NAT等,甚至可以是 用户自定义的功能)

1. NF_IP_PRE_ROUTING:
刚刚通过数据链路层解包,进入网络层的数据包通过此点(刚刚进行完版本号,校验
和等检测),目的地址转换在此点进行
2. NF_IP_LOCAL_IN
经路由查找后,送往本机的通过此检查点,INPUT包过滤在此点进行
3. NF_IP_FORWARD
要转发的包通过此检测点,FORWARD包过滤在此点进行
4. NF_IP_POST_ROUTING
所有马上便要通过网络设备出去的包通过此检测点,内置的源地址转换功能(包括地址伪装)在此点进行
5. NF_IP_LOCAL_OUT
本机进程发出的包通过此检测点,OUTPUT包过滤在此点进行

可以看到:

Iptables/Netfilter的工作是针对网络的数据包进行修改的,所以,Iptables/Netfilter在某种程度上可以算是一种网络层的路由器/防火墙

我们可以看到,通过"5个代表不同阶段的Hook点"、"表、链、规则"这种"松耦合"、"规则型"的结构,我们作为管理员可以获得最大程度的控制灵活性、可以有非常巨大的想象空间

Netfilter是由Rusty Russell提出的Linux 2.4内核防火墙框架,该框架既简洁又灵活,可实现安全策略应用中的许多功能,如数据包过滤、数据包处理、地址伪装、透明代理、动态网络地址转换(Network Address Translation,NAT),以及基于用户及媒体访问控制(Media Access Control,MAC)地址的过滤和基于状态的过滤、包速率限制等
Iptables/Netfilter的这些规则可以通过灵活组合,形成非常多的功能、涵盖各个方面,这一切都得益于它的优秀设计思想

 

2. Linux数据包路由原理

我们已经知道了Netfilter和Iptables的架构和作用,并且学习了控制Netfilter行为的Xtables表的结构,那么这个Xtables表是怎么在内核协议栈的数据包路由中起作用的呢?

网口数据包由底层的网卡NIC接收,通过数据链路层的解包之后(去除数据链路帧头),就进入了"TCP/IP协议栈(本质就是一个处理网络数据包的内核驱动)和Netfilter混合"的"数据包处理流程"中了。

数据包的接收、处理、转发流程构成一个有限状态向量机,经过一些列的内核处理函数、以及Netfilter Hook点,最后被转发、或者本次上层的应用程序消化掉

从这张图中,我们可以总结出以下规律:

1. 当一个数据包进入网卡时,数据包首先进入PREROUTING链,在PREROUTING链中我们有机会修改数据包的DestIP(目的IP),然后内核的"路由模块"根据"数据包目的IP"以及"内核中的路由表"
判断是否需要转送出去(注意,这个时候数据包的DestIP有可能已经被我们修改过了)
2. 如果数据包就是进入本机的(即数据包的目的IP是本机的网口IP),数据包就会沿着图向下移动,到达INPUT链。数据包到达INPUT链后,任何进程都会收到它
3. 本机上运行的程序也可以发送数据包,这些数据包经过OUTPUT链,然后到达POSTROTING链输出(注意,这个时候数据包的SrcIP有可能已经被我们修改过了)
4. 如果数据包是要转发出去的(即目的IP地址不再当前子网中),且内核允许转发,数据包就会向右移动,经过FORWARD链,然后到达POSTROUTING链输出(选择对应子网的网口发送出去)

我们在写Iptables规则的时候,要时刻牢记这张路由次序图,根据所在Hook点的不同,灵活配置规则

 

3. Iptables规则编写原则

我们前面说过,使用Iptables是一个非常灵活的过程,我们在写规则的时候,一定要时刻牢记上面的这张"数据包路由图",明白在5个Hook点,3种"表"分别所处的位置,以及结合在这个5个Hook点可以实现的功能,来理解规则。理解规则的原理比强记规则本身效果要好得多

0x1: 提出需求

在正式编写Iptables规则之前,我们一定是有一个实现某个功能、目的的需求,我们必须先将它整理出来,为下一步抽象化作准备,这里我以我项目中的需求为例,大家在自己的实验中可以举一反三

1. 网口at0(10.0.0.1)是一个伪AP的网口,目标客户端连接到伪AP网口at0之后会发起DHCPDISCOVER过程,监听在at0上的DHCPD会进行回应,为客户端分配10.0.0.100的IP地址,并设置客户
端的默认网关为10.0.0.1(即at0的IP地址)、默认DNS服务器为10.0.0.1(即at0的IP地址)
2. 需要将网口at0(10.0.0.1)的入口流量牵引到真正连接外网的网卡接口eth0(192.168.159.254)上,做一个NAT服务
3. 对网口at0(10.0.0.1)的DHCP流量(目的端口67的广播数据包)予以放行,因为我们需要在伪AP所在的服务器上假设DHCP服务器
4. 对网口at0(10.0.0.1)的DNS流量(目的端口53)予以放行,因为我们需要在伪AP所在的服务器上假设DNS服务器

0x2: 逐步抽象化我们的需求

我们根据我们的需求进行抽象化,即用规则来抽象化描述我们的目的,在编写的过程中要注意不同的Hook点所能做的修改是不同的

//开启Linux路由转发开关,由于本机对数据包进行转发
echo "1" > /proc/sys/net/ipv4/ip_forward
//将客户端的HTTP流量进行NAT,改变数据包的SrcIP,注意,是在POSTROUTING(数据包即将发送出去之前进行修改)
iptables -t nat -A POSTROUTING -p tcp -s 10.0.0.0/24 --dport 80 -j SNAT --to-source 192.168.159.254
//将远程WEB服务器返回来的HTTP流量进行NAT,回引回客户端,注意,是在PREROUTING(数据包刚进入协议栈之后马上就修改)
iptables -t nat -A PREROUTING -p tcp -d 192.168.159.254 -j DNAT --to 10.0.0.100

我们在DHCP服务器中指定客户端的默认DNS服务器是10.0.0.1(本机),即伪DNS,但我目前还没有在本机架设DNS,所以目前还需要将53号端口的DNS数据包NAT出去,牵引到谷歌的DNS: 8.8.8.8上去

iptables -t nat -A PREROUTING -p udp -s 10.0.0.0/24 --dport 53 -j DNAT --to 8.8.8.8
iptables -t nat -A POSTROUTING -p udp -s 10.0.0.0/24 --dport 53 -j SNAT --to-source 192.168.159.254

iptables -t nat -A PREROUTING -p udp -d 192.168.159.254 --sport 53 -j DNAT --to 10.0.0.100
iptables -t nat -A POSTROUTING -p udp -s 8.8.8.8 --sport 53 -j SNAT --to-source 10.0.0.1

 

 

 

Copyright (c) 2014 LittleHann All rights reserved

 

 


本文链接: Linux数据包路由原理、Iptables/netfilter入门学习,转载请注明。

64位JVM带来的问题及解决方案

$
0
0

这篇文章会检验你有关JVM的知识以及项目交付相关的技能;尤其是涉及到JVM升级的时候。期待你们的评论及回复,一起探讨下如何规避这类的项目可能产生的性能问题。

背景

最近碰到了一个影响到线上生产环境的问题,我们使用的是WebLogic 10以及32位的Hotspot JVM 1.6 。鉴于目前的一些问题以及未来负载上升的预测,我们决定将HotSpot JVM 1.6升级成64位的。

注意我们并没有修改JVM的启动参数。

经过几周的功能测试及规划,这次升级成功地部署到了线上环境。不过,技术支持团队发现第二天便出现了严重的性能下降,其中还有线程锁竞争的问题,迫使部署团队不得不回滚了这次升级。

最终我们找到了问题的原因,而这次升级也将在最近重新进行发布。

问题:

从上面这些信息来看,说一下你认为可能导致这次性能下降的原因。

说一下这次升级有什么好处,对于这类升级的如何进行管理以及降低风险,给出一些你的建议。

答案:

我经常听到有人说只要从32位JVM升级到64位就能自动获得性能的提升。这只说对了部分。有显著的性能提升的前提是在这之前你的系统存在内存占用的问题比如过度GC或者java.lang.outofmemoryerror,并且你也进行了适当的调优及堆大小的调整。

不幸的是,我们通常都忽略了一个事实,对于 64位的JVM来说,系统中的本地指针会占用8个字节,而不是4个。这会导致你的程序的内存占用量的增加,因此会带来更频繁的GC以及性能的下降。

下面是Oracle的官方解释:

64位的虚拟机和32位的比起来,性能上有什么不同?

一般来说,和32位的虚拟机相比,同样的程序在64位机上仅需花费很小的 性能损失就能获得更大的寻址空间。这是由于系统的本地指针在64位虚拟机中会占用8个字节。这些额外字节的加载会对内存的使用带来影响,其结果就是程序执行的速度会变稍微的变慢,具体是多少取决于你的Java程序在执行的过程中需要加载多少指针。好消息是AMD64和EM64T平台在64位模式下运行的时候,Java虚拟机能获得额外的寄存器,来生成更高效的本地指令序列。这些额外寄存器带来的性能提升几乎能弥补64位虚拟机带来的执行速度的下降。SPARC平台上64位虚拟机和32位的相比,大概会有10%~20%的性能下降。AMD64和EM64T平台上则大概是0%~15%,这取决于你应用程序执行的时候有多少指针了。

现在回到我们开始说的那个问题上,内存占用量有了显著的增加,这就是导致性能问题的罪魁祸首。根据你选择的GC策略,GC的老生代回收会导致JVM和线程的暂停时间变得更长,这引发了线程锁竞争以及其它的问题。从下图可以看到,升级到64位JVM后应用程序的内存占用量(老生代)增加了45%。

Java堆的使用量 ~老年代回收后占用量大概是900MB(32位)

Java堆的使用量 ~老年代回收后占用量大概是1.3GB(64位)

应用程序的Java堆的内存占用量增加了45%。当然这是本地指针的大小膨胀了的缘故。

还有一个问题就是在项目支付前,只进行了功能测试,而没有进行性能测试及压力测试。并且也没有对JVM参数的进行修改或者调整,这自然就增长了旧生代回收的频率以及GC的暂停时间。最终的解决方案是将堆的大小从2GB增加到2.5GB,并且开启压缩指针的选项。

现在你已经明白问题是什么了,下面是我关于类似升级的一些建议:

  1. 进行性能压测,比较下应用程序在32位和64位时的内存占用量和GC的表现。
  2. 确保有足够的时间来进行GC参数及堆大小的调优,以便减少GC的暂停时间。
  3. 如果你用的是HotSpot JVM1.6 6u23以后的版本,可以启用指针压缩这个选项。这个选项使得JVM可以通过Java堆的某个64位的起始地址的32位的偏移量来表示大部分的指针;这样就减少了升级再来的内存占用量的增加。
  4. 正确地规划你的JVM进程所在的宿主机的容量。确保内存和CPU的能力满足这次升级带来的额外的内存和CPU的消耗。
  5. 采用一种低风险的升级策略,只升级线上环境的部分机器到64位JVM,比如说25%~50%。这样你还可以比较下现有的32位机器以及新升级的机器的表现,确保性能带来的收益及损失满足你的预期。

原创文章转载请注明出处: 64位JVM带来的问题及解决方案

英文原文链接

转: 当spring 容器初始化完成后执行某个方法

$
0
0
转自: http://www.cnblogs.com/rollenholt/p/3612440.html


在做web项目开发中,尤其是企业级应用开发的时候,往往会在工程启动的时候做许多的前置检查。

比如检查是否使用了我们组禁止使用的Mysql的group_concat函数,如果使用了项目就不能启动,并指出哪个文件的xml文件使用了这个函数。

而在Spring的web项目中,我们可以介入Spring的启动过程。我们希望在Spring容器将所有的Bean都初始化完成之后,做一些操作,这个时候我们就可以实现一个接口:
package com.yk.test.executor.processor
public class InstantiationTracingBeanPostProcessor implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
      //需要执行的逻辑代码,当spring容器初始化完成后就会执行该方法。
 }
}


同时在Spring的配置文件中,添加注入:
<!--      当Spring容器启动完成后执行下面的这个Bean --><bean class="com.yk.test.executor.processor.InstantiationTracingBeanPostProcessor"/>

  
但是这个时候,会存在一个问题,在web 项目中(spring mvc),系统会存在两个容器,一个是root application context ,另一个就是我们自己的 projectName-servlet  context(作为root application context的子容器)。

这种情况下,就会造成onApplicationEvent方法被执行两次。为了避免上面提到的问题,我们可以只在root application context初始化完成后调用逻辑代码,其他的容器的初始化完成,则不做任何处理,修改后代码

如下:
@Override
  public void onApplicationEvent(ContextRefreshedEvent event) {
      if(event.getApplicationContext().getParent() == null){//root application context 没有parent,他就是老大.
           //需要执行的逻辑代码,当spring容器初始化完成后就会执行该方法。
      }
  }



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


ITeye推荐



jar文件安装到本地的maven仓库

$
0
0

下面具一个如何把edtftpj.jar 包上传到本地maven仓库的例子

首先有edtftpj.jar 的jar文件,我把它放到了 D:/ (D盘根目录),

- 进入“命令行提示符”,进入到D:/,然后执行mvn install:install-file -Dfile=edtftpj.jar -DgroupId=com.enterprisedt -DartifactId=edtFTPj -Dversion=2.0.4 -Dpackaging=jar

这样就把edtftpj.jar传到了本地仓库中。

 

JAR安装到maven本地仓库:

mvn install:install-file -Dfile=edtftpj.jar -DgroupId=com.enterprisedt -DartifactId=edtFTPj -Dversion=2.0.4 -Dpackaging=jar



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


ITeye推荐



想成為神級程式設計師,先練寫作讓思考更上一層樓吧

$
0
0

上週的 Teahour.FM 迎來了兩大內容平台的創業者做客,簡書的創辦人林立和 Logdown 的創辦人 xdite。

在節目中,林立和 xdite(台灣頂尖 Ruby on Rails 程式設計師) 分享了他們做內容平台的想法。最近五六年是社交網絡的天下,各種社交應用的爆發同時也把人們帶入了碎片化時代,尤其是 140 字的限制,使得人們在快速生產內容,快速消費內容,越來越少的人願意沉下心思考,記錄一些文字。我們的生活其實少了很多精彩,所以很高興能看到這一年間內容平台重新興起並且回歸, Medium簡書LogdownGhost等,每天去看看裡面的推薦文章,我相信一定會有被感動的時候。

  • 堅持寫作,對開發者的好處是無法估量的

節目中問了一下 xdite 一年的產出是多少,直接被嚇到了。在做 Logdown 之前 xdite 已經達到了年寫 400000 字,平均一天 1100 字,做 Logdown 之後是只多不少,對於一個創業者、技術開發人員而非作家來說,我必須得說是非常驚人的數字,當然在這個產出下,獲得的回報也是驚人的,比起之前寫的一篇文章就給 Logdown 帶來了 30 萬的 PV。

37signals 曾在其暢銷書『Getting Real』 中提到,招聘時,永遠選候選人中寫得更好的,無論是設計師、程序員、運營人員、銷售還是其他。寫得好的人也必然同時更善於思考和溝通,所以也能更好的與代碼和人打交道。

程式設計師大多都很痛恨寫文檔,尤其是寫那些認為沒用的文檔,繼而懶得記錄自己的思考和心得。我們在 teahour 也聊到這點,理解但非常推薦開發人員多寫文字,堅持寫作對個人成長帶來的好處是你無法估量的。我自己在團隊中,每一個功能發布,都是要求負責人直接去寫發布博客,不但要會實現,還是能給用戶講明白前因後果。

相信每個寫作的人都曾有體會,當你提筆去解釋一個東西的時候,你以為你知道的事情未必真正知道。寫作並不只是簡單的記錄,而是需要讓讀者也能跟著你的思路,理解你想表達的東西。所以,要想非常清晰的表達你的觀點,寫作必然是一次知識體系的重新學習和思緒的梳理,這樣才能幫助讀者理解。而這個過程,才是你真正的收穫。

  • 寫作也是你個人品牌建立和傳播的非常有效的方式

永遠不要低估文字的影響力和傳播力,總會有人因為你的文字而受益。

當你分享越來越多的思考和知識,人們會了解到你的個性,了解到你的為人和處事方式。不管是否會有人因此討厭你,請相信一定會有更多的人喜歡你,他們會因為你的內容繼而了解你在做的事情,比如在寫的一本書,在做的一個產品等等。

而這些東西會也因為你的品牌而具有同樣獨特的個性。

程式設計師在開源的世界里以 Code 會友,在思想的世界裡以文會友。無論是 teahour 還是我的 Blog 文章,在這一年多都給我帶來了很多的好朋友,一些甚至在生活中都不可能有任何交集的朋友。人的成長就在於不停的擴大自己的圈子並對等的交流,接觸到這麼一群非常有思想的人,從這些朋友身上學習到很多東西,才是我最大的收穫。

在分享知識的同時,它可能也會節省你很多時間,比如也許你 Google 到的一個解決方案就是你之前寫過的一篇文章。去年在 Teahour 時也問過 xdite 這麼高產的背後是如何尋找到寫作的主題的。xdite 解釋說有很多是很多人重複在問她的問題,她覺得累了,不想花時間一一回答,就把它寫了出來讓提問者直接去閱讀,這樣既可以讓讀者更系統的了解,也能節省大把的時間。

所以,YOU should write!

 

 

「我沒時間寫東西、我不知道寫什麼、我沒什麼有價值的好寫的……。」

不要再給自己找藉口了,放輕鬆點,我們不是作家要寫一部小說,我們只是作者要寫點東西,而如前面所言,寫作能讓我們梳理整個知識體系,這就夠了。

Medium 的 Slogan 我覺得非常好,「Everyone’s stories and ideas」,我們每天都在接收新的訊息和新的想法,為何不把它記錄成字呢?不要一開始就苛求完美,永遠記得壞的開始就等於成功的一半。我覺得我寫的每一篇初稿都很爛,但是每次修改都讓我覺得比前一次好一點點。到最後發佈時,看起來也還不錯,至少自己挺滿意。

細細分析, 寫作的整個過程其實跟做產品還蠻像的。一篇文章的出爐,需要歷經計劃、調查研究、初稿、複審、修訂和發佈的過程。做計劃時需要了解文章讀者是誰,他們的期望是什麼,確定主題思想。調研時比較同類文章,梳理整個思路。一般在這個階段後,我已經基本有了一個藍圖。初稿就嚴格按照腦圖需求,迅速成文。之後聽取朋友反饋,多次修訂,最後發佈。整就一個精益寫作的過程。

寫作是一個非常值得培養的習慣。這個技能的練成,沒有捷徑,唯有不停的練習。時代在回歸,人也要回歸。千里之行,始於足下,YOU should get started!

延伸閱讀:

要創業就要「寫」:吞下這 8 顆寫作大力丸就不怕作文了

(轉載自合作媒體《 36kr》)

JavaScript中的原型和继承

$
0
0

   英文原文:Prototypes and Inheritance in JavaScript

  请在此暂时忘记之前学到的面向对象的一切知识。这里只需要考虑赛车的情况。是的,就是赛车。

  最近我正在观看  24 Hours of Le Mans ,这是法国流行的一项赛事。最快的车被称为 Le Mans 原型车。这些车虽然是由“奥迪”或“标致”这些厂商制造的,可它们并不是你在街上或速公路上所见到的那类汽车。它们是专为参加高速耐力赛事而制造出来的。

  厂家投入巨额资金,用于研发、设计、制造这些原型车,而工程师们总是努力尝试将这项工程做到极致。他们在合金、生物燃料、制动技术、轮胎的化合物成分和安全特性上进行了各种实验。随着时间的推移,这些实验中的某些技术经过反复改进,随之进入到车辆的主流产品线中。你所驾驶车辆的某些技术,有可能是在赛车原型上第一次亮相的。

  你也可以说,这些主流车辆 继承了来自赛车的技术 原型

  到现在,我们就有讨论 JavaScript 中的原型和继承问题的基础了。它虽然并不像你在 C++、Java 或 C# 中了解的经典继承模式一样,但这种方式同样强大,并且有可能会更加灵活。

  有关对象和类

  JavaScript 中全是对象,这指的是传统意义上的对象,也就是“一个包含了状态和行为的单一实体”。例如,JavaScript 中的数组是含有数个值,并且包含 push、reverse 和 pop 方法的对象。

var myArray = [1, 2];
myArray.push(3);
myArray.reverse();
myArray.pop();
var length = myArray.length;

  现在问题是,push 这样的方法是从何而来的呢?我们前面提到的那些静态语言使用“类语法”来定义对象的结构,但是 JavaScript 是一个没有“类语法”的语言,无法用 Array“类”的语法来定义每个数组对象。而因为 JavaScript 是动态语言,我们可以在实际需要的情况下,将方法任意放置到对象上。例如下面的代码,就在二维空间中,定义了用来表示一个点的点对象,同时还定义了一个 add 方法

var point = {
x : 10,
y : 5,
add: function(otherPoint) {
this.x += otherPoint.x;
this.y += otherPoint.y;
}
};

  但是上面的做法可扩展性并不好。我们需要确保 每一个点对象都含有一个 add 方法,同时也希望 所有点对象都共享同一个 add 方法的实现,而不是这个方法手工添加每一个点对象上。这就是原型发挥它作用的地方。

  有关原型

  在 JavaScript 中,每个对象都保持着一块隐藏的状态 —— 一个对另一个对象的引用,也被称作原型。我们之前创建的数组引用了一个原型对象,我们自行创建的点对象也是如此。上面说原型引用是隐藏的,但也有 ECMAScript(JavaScript 的正式名称)的实现可以通过一个对象的__proto__属性(例如谷歌浏览器)访问到这个原型引用。从概念上讲,我们可以将对象当作类似于 图1 所表示的对象 —— 原型的关系。

1

  展望未来,开发者将能够使用 Object.getPrototypeOf 函数,代替__proto__属性,取得对象原型的引用。在本文写出的时候,已经可以在 Google Chrome,FIrefox 和 IE9 浏览器中使用 Object.getPrototypeOf 函数。更多浏览器在未来会实现此功能,因为它已经是 ECMAScript 标准的一部分了。我们可以使用下面的代码,来证明我们建立的 myArray 和点对象引用的是两个不同的原型对象。

Object.getPrototypeOf(point) != Object.getPrototypeOf(myArray);

  对于本文的其余部分,我将交叉使用 __proto__和Object.getPrototypeOf 函数,主要是因为 __proto__ 在图和句子中更容易识别。需要记住的是它(__proto__)不是标准,而 Object.getPrototypeOf函数才是查看对象原型的推荐方法。

   是什么让原型如此特别?

  我们还没有回答这个问题:数组中 push 这样的方法是从何而来的呢?答案是:它来源于 myArray 原型对象。图 2 是 Chrome 浏览器中脚本调试器的屏幕截图。我们已经调用 Object.getPrototypeOf 方法查看 myArray 的原型对象。

   2

  注意 myArray 的原型对象中有许多方法,包括那些在代码示例中调用的 push、pop 和 reverse 方法。因此,原型对象中的确包括 push 方法,但是 myArray 方法如何引用到呢?

myArray.push(3);

  了解其工作原理的第一步,是要认识到原型并不是特别的。原型只是普通的对象。可以给原型添加方法,属性,并把他们当作其他 JavaScript 对象一样看待。然而,套用乔治·奥威尔的小说《动物农场》中“猪”的说法 —— 所有的对象应当是平等的,但有些对象(遵守规则的)比其他人更加平等。

  JavaScript 中的原型对象的确是特殊的,因为他们遵从以下规则。当我们告诉 JavaScript 我们要调用一个对象的 push 方法,或读取对象的 x 属性时,运行时会首先查找对象本身。如果运行时找不到想要的东西,它就会循着 __proto__ 引用和对象原型寻找该成员。当我们  调用 myArray 的 push 方法时,JavaScript 并没有在 myArray 对象上发现 push 方法,而是在 myArray 的原型对象上找到了,于是 JavaScript 调用此方法(见图 3)。

3

  上面所描述的行为是指一个对象本身继承了原型上的任何方法或属性。JavaScript 中其实不需要使用类语法也能实现继承。就像从赛车原型上继承了相应的技术的车,一个 JavaScript 对象也可以从原型对象上继承功能特性。

  图 3 还展示了每个数组对象同时也可以维护自身的状态和成员。在请求得到 myArray 的 length 属性的情况下,JavaScript 会取得 myArray 中 length 属性的值,而不会去读取原型中的对应值。我们可以通过向对象上添加 push 这样的方法来“重写”push 方法。这样就会有效地隐藏原型中的 push 方法实现。

共享原型

  JavaScript 中原型的真正神奇之处是多个对象如何维持对同一个原型对象的引用。例如,如果我们创建了这样的两个数组:

var myArray = [1, 2];
var yourArray = [4, 5, 6];

  那么这两个数组将共享同一个原型对象,而下面的代码计算结果为 true:

Object.getPrototypeOf(myArray) === Object.getPrototypeOf(yourArray);

  如果我们引用两个数组对象上的 push 方法,JavaScript 会去寻找原型上共享的 push 方法。

4

  JavaScript 中的原型对象提供继承功能,同时也就实现了该方法实现的共享。原型也是链式的。换句话说,因为原型对象只是一个对象,所以一个原型对象可以维持到另一个原型对象的引用。如果你重新审视图 2 便可以看到,原型的 __proto__ 属性是一个指向另一个原型的非空值。当 JavaScript 查找像 push 方法这样的成员时,它会循着原型引用链检查每一个对象,直到找到该成员,或者抵达原型链的末端。原型链为继承和共享开辟了一条灵活的途径。

  你可能会问的下一个问题是:我该如何设置那些自定义对象的原型引用呢?例如前面所使用的点对象,如何才能将 add 方法添加到原型对象中,并从多个点对象中继承方法呢?在回答这个问题之前,我们需要看看函数。

  有关函数

  JavaScript 中的函数也是对象。这样的表述带来了几个重要的结果,而我们并不会在本文中涉及所有的事项。这其中,能将一个函数赋值给一个变量,并且将一个函数作为参数传递给另一个函数的能力构成了现代 JavaScript 编程表达的基本范式。

  我们需要关注的是,函数本身就是对象,因此函数可以有自身的方法,属性,并且引用一个原型对象。让我们来讨论下面的代码的含义。

// 这将返回 true:
typeof (Array) === "function"
// 这样的表达式也是:
Object.getPrototypeOf(Array) === Object.getPrototypeOf(function () { })
// 这样的表达式同样:
Array.prototype != null

  代码中的第一行证明, JavaScript 中的数组是函数。稍后我们将看到如何调用 Array 函数创建一个新的数组对象。下一行代码,证明了 Array 对象使用与任何其他函数对象相同的原型,就像我们看到数组对象间共享相同的原型一样。最后一行代码证明了 Array 函数都有一个 prototype 属性,而这个 prototype 属性指向一个有效的对象。这个 prototype 属性十分重要。

  JavaScript 中的每一个函数对象都有 prototype 属性。 千万不要混淆这个 prototype 属性的 __proto__ 属性。他们用途并不相同,也不是指向同一个对象。

// 返回 true
Object.getPrototypeOf(Array) != Array.prototype

  Array.__proto__ 提供的是 数组原型– 请把它当作 Array 函数所继承的对象。

  而 Array.protoype,提供的的是 所有数组的原型对象。也就是说,它提供的是像 myArray 这样数组对象的原型对象,也包含了所有数组将会继承的方法。我们可以写一些代码来证明这个事实。

// true
Array.prototype == Object.getPrototypeOf(myArray)
// 也是 true
Array.prototype == Object.getPrototypeOf(yourArray);

  我们也可以使用这项新知识重绘之前的示意图。

5

  基于所知道的知识,请想象创建一个新的对象,并让新对象表现地像数组的过程。一种方法是使用下面的代码。

// 创建一个新的空对象
var o = {};
// 继承自同一个原型,一个数组对象
o.__proto__ = Array.prototype;
// 现在我们可以调用数组的任何方法...
o.push(3);

  虽然这段代码很有趣,也能工作,可问题在于,并不是每一个 JavaScript 环境都支持可写的 __proto__ 对象属性。幸运的是,JavaScript 确实有一个创建对象内建的标准机制,只需要一个操作符,就可以创建新对象,并且设置新对象的 __proto__ 引用 – 那就是“new”操作符。

var o = new Array();
o.push(3);

  JavaScript 中的 new 操作符有三个基本任务。首先,它创建新的空对象。接下来,它将设置新对象的 __proto__ 属性,以匹配所调用函数的原型属性。最后,操作符调用函数,将新对象作为“this”引用传递。如果要扩展最后两行代码,就会变成如下情况:

var o = {};
o.__proto__ = Array.prototype;
Array.call(o);
o.push(3);

  函数的 call 方法允许你在调用函数的情况下在函数内部指定“this”所引用的对象。当然,函数的作者在这种情况下需要实现这样的函数。一旦作者创建了这样的函数,就可以将其称之为构造函数。

   构造函数

  构造函数和普通的函数一样,但是具有以下两个特殊性质。

  1. 通常构造函数的首字母是大写的(让识别构造函数变得更容易)。
  2. 构造函数通常要和 new 操作符结合,用来构造新对象。

  Array 就是一个构造函数的例子。Array 函数需要和 new 操作符一起使用,而且 Array 的首字母是大写的。JavaScript 将 Array 作为内置函数包括在内,而任何人都可以写出自己的构造函数。事实上,我们最后可以为先前创建的点对象编写出构造函数。

var Point = function (x, y) {
this.x = x;
this.y = y;
this.add = function (otherPoint) {
this.x += otherPoint.x;
this.y += otherPoint.y;
}
}
var p1 = new Point(3, 4);
var p2 = new Point(8, 6);
p1.add(p2);

  在上面的代码中,我们使用了 new 操作符和 Point 函数来构造点对象,这个对象带有 x 属性和 y 属性和一个 add 方法。你可以将最后的结果想象成图 6 的样子。

6

  现在的问题是我们的每个点对象中仍然有单独的 add 方法。使用我们学到的原型和继承的知识,我们更希望将点对象的 add 方法从每个点实例中转移到 Point.prototype 中。要达到继承 add 方法的效果,我们所需要做的,就是修改 Point.prototype 对象。

var Point = function (x, y) {
this.x = x;
this.y = y;
}
Point.prototype.add = function (otherPoint) {
this.x += otherPoint.x;
this.y += otherPoint.y;
}
var p1 = new Point(3, 4);
var p2 = new Point(8, 6);
p1.add(p2);

  大功告成!我们刚刚在 JavaScript 中完成原型式的继承模式!

7

   总结

  我希望这篇文章能够帮助你揭开 JavaScript 原型概念的神秘面纱。开始看到的是原型怎样让一个对象从其他对象中继承功能,然后看到怎样结合 new 操作符和构造函数来构建对象。这里所提到的,只是开启对象原型力量和灵活性的第一步。本文鼓励你自己发现学习有关原型和 JavaScript 语言的新信息。

  同时,请小心驾驶。你永远不会知道这些行驶在路上的车辆会从他们的原型继承到什么(有缺陷)的技术。

如何在网页中插入FLV视频,经测试兼容IE、火狐、谷歌等浏览器

$
0
0
之前有个项目需要在后台上传视频,然后在网站前台中播放出来,因为之前插入的视频都是来自优酷、土豆等视频网站,那个方法几乎所有的在线编辑器都自带了,直接复制粘贴地址就搞定了。所以对视频这一块没什么研究,但是实际需求则不是这么简单,你的客户如此说:就是不想把视频传到优酷上!这个时候我们就只能重新写个模块吧。

思路很简单,后台写个上传视频的功能模块。然后在需要播放视频的页面中,调用视频的路径即可。后台上传视频,我们今天先不谈。先保证视频能够在所有的浏览器中播放吧。

找了好多资料,网上一个一个的,你抄我,我抄你,复制来复制去,没几个做过测试的,大部分都不能用,笔者走了两天的弯路,总算得到一个好的解决方案了。现在把它分享了。也加上测试说明,方便后来人。

首先给出思路。网页中可以播放视频,必然要借助某个播放器,这个播放器可以是系统自带的,也可以是浏览器的ActiveX控件。对于使用系统自带的播放器,可以使用quicktime插件,这个比较麻烦,本地需要安装一个quicktime客户端,这个方法虽然可行,但是用户体验不好。用户如果不想安装客户端,一切玩完!

所以,我们不妨使用FLASH方案,比较目前,所有的浏览器都支持FLASH。所以,这个方法大众普遍都很接受,优酷、土豆等在线视频就是使用的FLASH的。

本例播放器使用Flvplayer.swf。播放器在下文的demo文件中。网页中插入代码的如下:

XML/HTML Code复制内容到剪贴板
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" width="305" height="205"> 
    <param name="movie" value="Flvplayer.swf" /> 
    <param name="quality" value="high" /> 
    <param name="allowFullScreen" value="true" /> 
    <param name="FlashVars" value="vcastr_file=movies/11.flv&LogoText=test&BufferTime=3" /> 
    <embed src="Flvplayer.swf" allowfullscreen="true" flashvars="vcastr_file=movies/11.flv&LogoText=test" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="505" height="405"></embed> 
</object> 
以上代码放在<body></body>中即可。

可以看出这是使用swflash.cab一种ActiveX控件实现的播放效果,其实就是这个:Adobe Shockwave Player 12.0.2.122

vcastr_file=movies/11.flv是你的视频路径。<param name="movie" value="Flvplayer.swf" />  这个value的值表示播放器名称,注意路径的设置。

以上代码,笔者亲自测试,在IE6、IE7、IE8、IE9、IE10、Firefox、Chrome几大浏览器都能正常播放,兼容性近乎完美。

网页中插入FLV视频

但是,这个播放器只能播放FLV格式的视频,其他格式不支持,如果上传的是其他格式的,那么就请写服务器端转码程序转码吧。

附件下载:网页中插入FLV视频DEMO
链接地址:http://www.91ctc.com/article/article-309.html

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


ITeye推荐




系统架构领域的一些学习材料

$
0
0

系统架构是一个工程和研究相结合的领域,既注重实践又依赖理论指导,入门容易但精通很难,有时候还要讲点悟性,很具有“伪科学”的特征。要在此领域进阶,除了要不断设计并搭建实际系统,也要注意方法论和设计理念的学习和提炼。

经常有同学询问如何学习,特贴一篇学习材料,供大家参考。09年时写的,在系统领域浩如烟海的文献中提取了一些我认为值得研究和学习的项目,没包括近几年出现的一些工作,也不够全面。不过,其实也足够了,看paper是一个从少到多再到少的过程。对问题本质、背景和发展历史有大致了解,再辅以hands-on的实践(长期的真正的实践),足以摸到本领域的门径。

此文在网上转载不少,但多数没有说明出处。今天在这里重发,也顺便向315致敬。

---

对于工程师来说,到一定阶段后往往会遇到成长瓶颈。要突破此瓶颈,需要在所属技术领域更深入学习,了解本领域的问题本质、方法论与设计理念、发展历史等。以下提供一些架构相关领域的学习材料,附上简单点评,供有兴趣的工程师参考。希望大家能通过对这些领域的了解和学习,掌握更多 system design principles,在自己的工作中得心应手,步入自由王国。

1. Operating Systems

Mach [Intro: http://www-2.cs.cmu.edu/afs/cs/project/mach/public/www/mach.html,Paper: http://www-2.cs.cmu.edu/afs/cs/project/mach/public/www/doc/publications.html]

传统的kernel实现中,对中断的响应是在一个“大函数”里实现的。称为大函数的原因是从中断的入口到出口都是同一个控制流,当有中断重入发生的时候,实现逻辑将变得非常复杂。大多数的OS,如UNIX,都采用这种monolithic kernel architecture。

1985年开始的Mach项目,提出了一种全新的microkernel结构,使得由于70年代UNIX的发展到了极致而觉得后续无枝可依的学术界顿时找到了兴奋点,也开始了沸沸扬扬的monokernel与microkernel的争论。

插播一个花絮:Mach的主导者Richard Rashid,彼时是CMU的教授,受BillGates之托去游说JimGray加盟MS。结果把自己也被绕了进来,组建了Microsoft Research。他到中国来做过几次21Century Computing的keynotes。

Exokernel [Intro: http://pdos.csail.mit.edu/exo/,Paper: http://pdos.csail.mit.edu/PDOS-papers.html#Exokernels]

虽然microkernel的结构很好,但实际中并没有广泛应用,因为performance太差,而且大家逐渐发现OS的问题并不在于实现的复杂性,而更多在于如何提高application使用资源的灵活性。这也就是在kernel extension(例如loadable module in Linux)出现后,有关OS kernel architecture的争论就慢慢淡出人们视线的原因。

Exokernel正是在这样的背景中出现的,它并不提供传统OS的abstraction(process,virtual memory等),而是专注于资源隔离与复用(resource isolation and multiplexing),由MIT提出。在exokernel之上,提供了一套库,著名的libOS,用于实现各种OS的interface。这样的结构为application提供了最大的灵活度,使不同的application可以或专注于调度公平性或响应实时性,或专注于提高资源使用效率以优化性能。以今天的眼光来看,exokernel更像是一个virtual machine monitor。

Singularity [Intro: http://research.microsoft.com/os/Singularity/,Paper: http://www.
research.microsoft.com/os/singularity/publications/HotOS2005_BroadNewResearch.pdf
]

Singularity出现在virus,spyware取之不尽、杀之不绝的21世纪初期,由Microsoft Research提出。学术界和工业界都在讨论如何提供一个trust-worthy computing环境,如何使计算机系统更具有manage-ability。Singularity认为要解决这些问题,底层系统必须提供 hardisolation,而以前人们都依赖的硬件virtual memory机制并无法提供高灵活性和良好性能。在.Net和Java等runtime出现之后,一个软件级的解决方案成为可能。

Singularity在microkernel的基础上,通过.Net构建了一套type-safed assembly作为ABI,同时规定了数据交换的message passing机制,从根本上防止了修改隔离数据的可能。再加上对application的安全性检查,从而提供一个可控、可管理的操作系统。由于.NetCLR的持续优化以及硬件的发展,加了这些检查后的Singularity在性能上的损失相对于它提供的这些良好特性,仍是可以接受的。

这种设计目前还处于实验室阶段,是否能最终胜出,还需要有当年UNIX的机遇。

2. Virtual Machines

VMWare [" MemoryResource Management in VMware ESX Server",OSDI’02,Best paper award]

耳熟能详的vmware,无需多说。

XEN [“ Xen and the Art of Virtualization”, OSDI’04]

性能极好的VMM,来自Cambridge。

Denali [“ Scaleand Performance in the Denali Isolation Kernel”, OSDI’02, UW]

为internetservices而设计的application level virtual machine,在普通机器上可运行数千个VMs。其VMM基于isolation kernel,提供隔离,但并不要求资源分配绝对公平,以此减少性能消耗。

Entropia [“ The Entropia VirtualMachine for Desktop Grids”, VEE’05]

要统一利用公司内桌面机器资源来进行计算,需要对计算任务进行良好的包装,以保证不影响机器正常使用并与用户数据隔离。 Entropia就提供了这样的一个计算环境,基于windows实现了一个application level virtual machine。其基本做法就是对计算任务所调用的syscall进行重定向以保证隔离。类似的工作还有FVM:“ AFeather-weight Virtual Machine for Windows Applications”。

3. Design Revisited

Are Virtual Machine Monitors Microkernels Done Right?”,HotOS’05

这个题目乍听起来,十分费解,其意思是VMMs其实就是Microkernel的正确实现方法。里面详细讨论了VMM和Microkernel,是了解这两个概念的极好参考。

Thirty Years Is Long Enough: Getting Beyond C”, HotOS’05

C可能是这个世界上最成功的编程语言,但其缺点也十分明显。比如不支持thread,在今天高度并行的硬件结构中显得有点力不从心,而这方面则是functional programming language的长处,如何结合二者的优点,是一个很promising的领域。

4. Programming Model

Why Threads Are a Bad Idea

单使用thread结构的server是很难真正做到高性能的,原因在于内存使用、切换开销、同步开销和保证锁正确性带来的编程复杂度等。

SEDA: An Architecture for Well-Conditioned, Scalable Internet Services”,OSDI’01

Thread不好,但event也没法解决所有问题,于是我们寻找一个结合的方法。SEDA将应用拆分为多个stage,不同 stage通过queue相连接,同一个stage内可以启动多个thread来执行queue中的event,并且可通过反馈来自动调整thread数量。

Software Transactional Memory

如果内存可以提供transaction语义,那么我们面对的世界将完全两样,language, compiler, OS, runtime都将发生根本变化。虽然intel现在正在做hardware transactional memory,但估计可预见的将来不会商用,所以人们转而寻求软件解决方案。可想而知,这个方案无法base在native assembly上,目前有C#,haskell等语言的实现版本。资料比较多,参见 Wikipedia

5. Distributed Algorithms

Logical clock, [“ Time,clocks, and the ordering of events in a distributed system”, Leslie Lamport, 1978]

这是一篇关于Logic clock, time stamp, distributed synchronization的经典paper。

Byzantine [“ The ByzantineGenerals Problem”, Leslie Lamport, 1982]

分布式系统中的错误各种各样,有出错就能停机的,有出错了拖后腿的,更严重的是出错了会做出恶意行为的。最后的这种 malicious behavior,就好像出征将军的叛变,将会对系统造成严重影响。对于这类问题,Lamport提出了Byzantine failure model,对于一个由3f+1个replica组成的statemachine,只要叛变的replica数量小于等于f,整个state machine还能正常工作。

Paxos [“ The part-time parliament”, Leslie Lamport, 1998]

如何在一个异步的分布式环境中达成consensus,这是分布式算法研究的最根本问题。Paxos是这类算法的顶峰。不过这篇paper太难了,据说全世界就3.5人能看懂,所以Lamport后来又写了一篇普及版paper:“ Paxos Made Simple” ,不过还是很难懂。另外,也可参看Butler Lampson写的“ The ABCD’s of Paxos”(PODC’01),其中关于replicated state machine的描述会严重启发你对并行世界本质的认识,图灵奖的实力可不是盖的。

这上面反复出现了一个名字: Leslie Lamport,他在distributed computing这个领域挖坑不辍,终成一代宗师。关于他,也有几则轶事。记得以前他在MSR的主页是这么写的,“当我在研究logicalclock 的时候,BillGates还穿着开裆裤(in diaper)…”(大意如此,原文现在找不到了)。另外,他在写paper的时候,很喜欢把其他牛人的名字变换一下编排进去。这可能也是他还没拿到图灵奖的原因。[注1]

关于Lamport的其他成就,还可以参见这篇向他60岁生日献礼的paper:“ Lamport on mutual exclusion: 27 years of planting seeds”, PODC’01。

6. Overlay Networking, and P2P DHT

RON [“ Resilient Overlay Networks”, SOSP’01]

RON描述了如何在应用层搭建一个overlay,以提供秒级广域网网络层故障恢复速度,而现有的通过路由协议来恢复通信的时间至少在几十分钟。这种快速恢复特性和灵活性使得overlay networking现在被广泛应用。

Application Level Multicast

End System Multicast”, SigMetrics’00

Scalable Application Layer Multicast”, SigComm’02

关于ALM的paper很多,基本上都是描述如何搭建一个mesh network用以鲁棒的传输控制信息,另外再搭建一个multicast tree用以高效传输数据,然后再根据多媒体数据的特点做一些layered delivery。前几年出现的coolstream, pplive等系统都是这类系统的商业化产品。

P2P

P2P的出现改变了网络。按照各种P2P网络的结构,可以分为三种。

1.    Napster式,集中式目录服务,数据传输Peer to peer。

2.    Gnutella式,通过在邻居间gossip来查询,也被称为unstructured P2P。

3.    DHT,与unstructured P2P不同的是,DHT进行的查询有保证,如果数据存在,可在一定的hop数内返回。这个hop数通常为logN,N为系统节点数。

典型的DHT有 CAN, Chord, Pastry, Tapestry等四种。这些研究主要在算法层面,系统方面的工作主要是在其上建立广域网存储系统。还有一些人在机制层面进行研究,例如如何激励用户共享、防止作弊等。

7. Distributed Systems

GFS/MapReduce/BigTable/Chubby/Sawzall

Google的系列paper,大家比较熟悉,不再多说。在 可查。

Storage

Distributed storage system的paper太多了。下面列出几篇最相关的。

Chain Replication for Supporting High Throughput and Availability”, OSDI’04。

Dynamo: Amazon’s Highly Available Key-value Store”,SOSP’07。

BitVault: a Highly Reliable Distributed Data Retention Platform”, SIGOPS OSR’07。

PacificA: Replication inLog-Based Distributed Storage Systems”, MSR-TR。

Distributed Simulation

Simulating Large-Scale P2P Systems with the WiDS Toolkit”, MASCOTS’05。Distributed simulation有意思的地方是simulated protocol是distributed的,而这个simulation engine本身也是distributed的。Logical和physical的time和event交杂在系统中,需要仔细处理。

8. Controversial Computing Models

现在的软件系统已经复杂到了人已经无法掌握的程度,很多系统在发布时都仍然带着许多确定性(deterministic)或非确定性(non-deterministic)的bugs,只能不断的patch。既然作为人类,不够精细的特性决定了我们无法把系统的bug fix干净,我们只能从其他角度入手研究一种让系统在这令人沮丧的环境中仍能工作的方法。这就像一个分布式系统,故障无法避免,我们选择让系统作为整体来提供高可靠性。

以下3个便是典型代表。基本上,主要研究内容都集中于1) 如何正确保存状态;2)如何捕捉错误并恢复状态;3)在进行单元级恢复时,如何做到不影响整体。

Recovery Oriented Computing

Failure oblivious computing, OSDI’04

Treating Bugs as Allergies, SOSP’05

9. Debugging

系统很复杂,人类无法从逻辑上直接分析,只能通过data mining的方法在宏观上进行观察。

Black box debugging[“ Performance debugging for distributed systems of black boxes”, SOSP’03]

对大型系统的performance debugging非常困难,因为里面的问题很多都是非确定性的,而且无法重现。只能通过对log的挖掘,找出配对的调用/消息以定位问题。

CP-miner [“A Tool for Finding Copy-paste and Related Bugs in Operating System Code”, OSDI’04]

很多人在重用代码的时候,都使用copy-paste。但有时候简单的CP会带来严重的问题,例如局部变量的重名等。CP-miner通过分析代码,建立语法树结构,然后mine出这类错误。

---

注1:2014年3月19日,Lamport获得2013年度图灵奖,也是Microsoft Research的第5位图灵奖获得者。一代宗师,实至名归,功德圆满,可喜可贺。

 

全文转载自林仕鼎的文章: http://qing.blog.sina.com.cn/2244218960/85c41050330031zq.html


  青春就应该这样绽放   游戏测试:三国时期谁是你最好的兄弟!!   你不得不信的星座秘密

高效设计三步曲

$
0
0

设计本就是不局限章法的事情,追求百花齐放,那么灵感的来源自然也就不受限制了,各有各的道理。但是设计不=艺术, 要的是众乐乐.是为了让想法最终变为现实,要求的是结果,否则方案永远会停留在概念阶段而不可实施。 既然如此,如何成体系的思考 , 高效完成设计并对产品的最终形态负责任?这里总结了高效设计三步曲:

第一步:明确设计目标,摸清边界第二步:多层面多维度思考第三步:有理有据的表述方案


一、明确设计目标,摸清边界

1\明确设计目标

交互设计作为典型的目标导向型设计, 越接近目标,也就越能得到最终方案。(图2).那么在设计之初明确设计目标就显得非常关键,Ta 是设计方案的评判标准.举个浅显的例子,任何一个比赛都是要先说明主题和缘由,为了什么而比赛,不然就变成了天马行空无从评判. 但实际情况中,往往没有特别明确的设计目标,需要设计师理解和挖掘。

我们将目标进行拆解,大体上设计需求来源于三方面,用户需求\公司需求\和自发需求。

a)用户需求

就是我们所说的用户体验设计的主要来源,用户在真实的使用场景中有需求,现在没有很好的解决方案,需要我们来提供.这类需求往往对应着相应的使用场景,我们往往称为痛点场景,找到并移情用户,找到真正痛点才能真正满足用户需求.

关键词:尽可能找准痛点且挖掘深层次需求

b)公司需求

需求都是人提出的,而提出的人可能是一些特定用户,为了实现特定的目的(有可能是非体验层面的)而提出的设计需求,这种需求比较不明确和可控,往往是经过多层转述而来的需求.对于此种需求的理解,要尽可能找到需求的源头,带个人思考和判断的理解.公司或者 Leader 要求做这样一个产品是为了实现怎样的目标,为什么要做等等。

关键词:找到需求源头并思考分析

c)自发需求

设计师本身也是产品的用户,并且有着较为超前的视角,那么在日常生活中经常会衍生出设计需求,这时候来源于内部自发的设计需求一般比较明确,这种设计方案在阐述的时候就需要先让人理解设计需求,所以首先要能验证或者说服别人认同你的需求点,其次需要在设计过程中不断明确目标,不忘初心以免偏离了设计最初的目标。

关键词:明确需求且可被理解

以上是关于明确目标,对需求理解越透彻就会越容易接近最终方案.还有一点摸清边界也很重要。

2\设计之初摸清边界

设计不同于艺术,最终是以实现为目标的,所以不可能无限制的思考,那么就需要在设计之初抓住核心问题点及设计中的关键性限制因素,比如上线时间,开发成本,产品预期等,在可突破的地方突破,合理利用空间最大化实现方案。 这一点对于高效设计尤为重要,它让你的设计更可控和可行.减少后期收敛想法时的不断反复,前置理解设计限制。

二、多维度多层面思考

设计方案从雏形到最终成型过程,往往是一个黑盒子,每个设计师有自己的方法,而且很多感性的行程过程也无法描述.

这里根据个人经验总结出一个通用的设计方法,就是分层拆分设计需求,逐层找到最优解决方案.

a)拆分设计需求

前面提出的设计目标,往往不是单一的,是由多个维度指标组成的,比如我们需要减少用户的使用步骤,同时增加操作过程中的乐趣.这里就可以拆分为两个问题来解决,一是减少使用步骤,提升核心流程的易用性.二是同时考虑情感层面, 怎样通过有趣的方式让用户操作更爽.

b)有针对性的逐个解决

对于减少使用步骤的问题,首先梳理现有流程,然后思考哪些关键步骤是必须的,哪些可以省略和合并,换个思路来设计流程.

对于增加操作乐趣,首先了解现在是怎样的操作方式,然后分析为什么枯燥无趣,哪里还可以提升,有没有新的交互形式引入.

如此拆解设计需求,就会让每一步的目标变得相当明确,解决方案自然可以高效得出.

三、有理有据的表述方案

经过以上两步的设计,最后一步是表述方案并找到最终答案,那么如何表述方案能够让人快速认同.凭借个人魅力是一方面,另一方面需要有理有据的表述方案,因为人们往往更容易认同经过思考的方案(图3).

1\设计维度评估

从上面了解需求,拆解目标并找到解决方案,可能会遇到一个问题,就是设计师本身往往无法决策哪个层面更为重要,也就是维度的权重,而这最终决定了方案更偏向于哪个层面.而最终的评估过程可以保证最终方案更接近设计目标.

2\维度从哪里来

从MECE穷尽的角度来说,用户层面、成本层面和公司价值等附加值三个层面,基本可以包含互联网产品的评估依据(图4用户、成本、价值三个层面)

以某输入产品为例,我们在针对输入进行扩展功能设计的时候,制定了如下维度评估表:

这里有以下几点需要注意

a)维度确认

要想使评估结果得到更大认可,在维度确认之初要与评估方确认,对重点维度达成共识,无遗漏等。

b)数量应遵循7+2原则,方便评估

c)推荐方案

最终输出的是配合产品文档的一份维度评估表,若几个方案都能满足核心需求,那么可以通过明确的综合分数来推荐方案,若方案差别较大,可以抓住几个核心维度,推荐评估较高的方案。

d)形式不限,但要可以多人量化(比如五分制方格)

四、总结

设计是一门理性与感性,科学与艺术相融合的学科,如何自如的穿梭与两种思维模式中,让别人认可方案,是我们每天都在思考的问题.

小结一下本文的核心要点:将设计拆分为前中后三步, 通过前期明确目标,过程中拆解分层思考,最后有理有据的阐述,环环相扣让别人认可你的方案.
转载请注明出自”百度MUX”

cxf+web service(二)代理工厂,安全验证,数据绑定

$
0
0

(二)代理工厂,安全验证,数据绑定

 

代理工厂

1.服务端:ServerFactoryBean,JaxWsServerFactoryBean 用于服务端调用.前者针对POJO,后者针对JAX-WS,他们用于生成服务端的EndPoint,暴露出服务接口

2.客户端:ClientProxyFactoryBean,JaxWsProxyFactoryBean 用于客户端调用.前者针对POJO,后者针对JAX-WS,他用于在客户端生成Web Service的代理proxy

3.除了这些Factory,CXF客户端还有ClientFactoryBean,JaxWsClientFactoryBean,这两个Factory生成的不是Web Service的代理,而是一个Endpoint,提供一些更该机的功能.

 

安全验证

Apache WSS4J(WebService Security For Java) 实现了java语言的 WS-Security.WSS4J依赖于SAAJ.CXF中使用拦截器机制完成WSS4J功能的支持.只需要初始化WSS4JInInterceptor(对应还有一个WSS4JOutInterceptor)实例并添加相关信息即可.CXF2.1.x之后的版本可以完成SAAJInInterceptor(对应的一个SAAJOutInterceptor)拦截器的自动注册,否则需要再注册一下SAAJ拦截器.

1.在spring.xml中配置WSS4J输入拦截器

 

<bean id="wss4jInInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor"><map><entry key="xx" value="xx"/></map></bean>

在接口服务里面加入关系

<jaxws:inInterceptors><ref bean="wss4jInInterceptor" /></jaxws:inInterceptors>

下面是服务器端具体密码回调处理类,它负责接收并处理客户端提交的用户名和密码,这个方法没有返回值,显示,如果验证失败,抛出异常表示.

import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSecurityException;

public class ServerPasswordCallbackHandler implements CallbackHandler {

	public final static String USER = "liu";
	public final static String PASSWORD = "lius";//设置用户名密码
	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
		WSPasswordCallback wspassCallback = (WSPasswordCallback) callbacks[0];
		System.out.println(wspassCallback.getIdentifier() + "\t"
				+ wspassCallback.getPassword());
		if(WSConstants.PASSWORD_TEXT.equals(wspassCallback.getPasswordType())){
			if (wspassCallback.getIdentifier().equals(USER)&& wspassCallback.getPassword().equals(PASSWORD)) {
				System.out.println(".................验证通过!");   
				System.out.println(".................identifier = " + USER);   
				System.out.println(".................password = " + PASSWORD); 
			} else {
				throw new WSSecurityException("............未通过验证!");
			}
		} else {
			//密码使用MD5密文发送
			System.out.println(wspassCallback.getIdentifier()); 
			wspassCallback.setPassword(PASSWORD);
		}
	}
}

2.客户端实现:在spring.xml中配置WSS4J输出拦截器

<bean id="wss4jOutInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor"><map><entry key="xx" value="xx"/></map></bean>

在服务接口里加入关系

<jaxws:outInterceptors><ref bean="wss4jOutInterceptor" /></jaxws:outInterceptors

这里使用了WSS4J输出拦截器,因为要将用户名和密码输出到服务器进行验证处理.另外与服务端不同的是多了一个user参数初始化WSS4J的输出拦截器,用于初始化用户名,这是一个必选,稍后将在下面的客户端密码回调处理类进行重新设定值

import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;

public class ClientPasswordCallbackHandler implements CallbackHandler{
	public final static String USER = "liu";
	public final static String PASSWORD = "lius";//设置用户名密码
	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
		WSPasswordCallback wspassCallback = (WSPasswordCallback)callbacks[0];
		wspassCallback.setIdentifier(USER);
		wspassCallback.setPassword(PASSWORD);
	}
}

然后我们访问这个web服务,从控制台查看日志,可以看到在SOAP信封的Header中包装了<wsse:Security...等元素,元素包括了WS-Security 的一些信息和设置的用户名和密码.如果使用MD5加密,则密码显示为null,只能显示用户名.如果客户端和服务端的用户名或者密码不对应,则登陆不上,会显示"...为通过验证!".

 

数据绑定

 

1.JAXB绑定.JAXB是一套自动映射XML和JAVA 实例的开发接口和工具.如果Web Service发布的接口的参数类型时类,而且返回的类型是List,String等,这样发布的Web Service 与普通的java没区别,因为JAXB都支持.但是JAXB不能将一些java类型自然映射到XML表现形式,例如HashMap,或其他非JavaBean之类,例如接口,Map,这样就要定义一个适配器,使java类型自动适应.一般可以编写一个类继承XmlAdapter,以实现此抽象类的适配器,另外可以安装使用注释XmlJavaTypeAdapter的适配器

 

2.Aegis Databingding.Aegis是一个快速,基于STAX的数据绑定,他能使采用代码优先方式发布Web Service的情况更简单.Aegis支持接口,集合类,MAP和各种数据类型.也不需要注释,也不需要写适配器

 



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


ITeye推荐



“人与服务的连接”才是本地生活O2O本质

$
0
0

2014年,随着BAT布局本地生活,几乎快被人遗忘的团购行业骤然升温,昔日的千团大战演变为 美团网、大众点评和百度糯米的“三国演义”,团购成为互联网巨头角逐的另一个战场。百度的加入正在使糯米嬗变,百度与百度糯米正在结成“连环马”,形成攻守兼备的棋局,团购行业格局正在发生改变。

从千团大战到三国演义:慢就是快

团购曾经是昔日的热门行业,上千家团购网站上演的千团大战曾经蔚为壮观。然而,时过境迁一切犹如过眼烟云,最后的PK在美团、大众点评和百度糯米三家公司间展开。

姑且不论三家公司背后的BAT因素,这三个公司能够坚持到最后的秘诀竟然是“慢”。在拉手网、24券、窝窝团等大肆烧钱进行大跃进之时,这三家公司却选择默默发展自己的业务。

例如,美团网的业务布局并未先从一线入手,而是从二、三线城市开始,夯实布局后再反过来做一线。大众点评则更是众所周知的慢公司,从上海大本营入手慢慢拓展,即使到现在也不过只有40个城市,相比其他互联网公司, 大众点评扫街的模式更像是线下公司而非互联网公司

百度糯米更是如此,在被百度收购前,糯米网率属于人人,但人人为了上市的财务报表,不能投入太多资金给糯米烧钱。受限于资金的糯米网于是压力重重:积累的用户不如大众点评,投入的营销不如美团。然而,正是这种重压,逼迫糯米网去内部挖潜,提升自己的单兵素质和效率,例如在审单人数上,糯米曾经是30人,而美团高达180人,但美团的团单量并没有达到糯米的6倍。

团购行业的竞争是一个持久战,那些昔日的宠儿们早早地资金链断裂被扫地出局,而更坚持业务拓展布局的美团、大众点评和糯米则熬了下来,从而获得了巨头的青睐。

团购成本地生活O2O的核心,成败关键在于人、“连接+找到”和服务

BAT巨头之所以看中团购,还是因为本地生活O2O概念的兴起,虽然京东等也在推零售实物O2O,但相比之下本地生活O2O显然拥有更加无限的潜力和商机。随着团购行业由快速爆炸后逐渐企稳,用户对团购的接受度和习惯也沉淀下来,团购从一种新的购物行为变成一种习惯和生活方式,而且团购公司积累了丰富的线下商家资源,从而成为承载本地生活O2O的核心平台,这是团购再次走红的本质原因。

当BAT加入之后,团购已经不再是团购,而变成本地生活O2O大棋局中的核心环节,因此团购之间的竞争将实现升维,变成三大巨头本地生活O2O的PK,由此团购企业的竞争态势将呈现明显的不同,成败与否将受制于本地生活O2O的成败。

一鲨认为,互联网时代商业模式的核心之一是 “连接”,如QQ和微信是 “人与人的连接”,百度搜索是“人与信息的连接”,淘宝则是“人与商品的连接”。核心之二是 “找到”,依靠互联网的技术,实现人更快、更智能地“找到”信息、商品。

本地生活O2O也是这样,其本质是“人与服务的连接”,要帮助“人找到服务”。因此 本地生活O2O的战场将有三个:人(流量)、连接+找到(包括技术在内的整体打法)、服务(线下商家资源),能否拉来更多的人,能否更容易地帮助人们找到服务,能否拥有更多的商家资源,成为本地生活O2O能否胜出的关键所在。

百度糯米的核聚变,打一场不仅是团购的战争

首先是人(流量)的PK。BAT看似都不缺流量,但具体到美团、大众点评和糯米的竞争上,关键是看各自后台的整合和支持力度。

阿里对美团的支持力度最弱,持股美团只有10%,在3月8日的淘宝生活节上,阿里撇开美团采用手机淘宝作为主战场,以及独立开发淘点点等举措说明,阿里与美团之间的融合力度有多弱。

大众点评获得腾讯入股并入驻微信,仿佛使其获得了移动端的流量,然而根本的问题是,腾讯平台的流量多是“人与人的连接”,如何从“人与人的连接”实现到“人与服务的连接”是个难题,因为人们来QQ和微信主要是为了聊天,而非购买服务。

百度全资收购糯米,得以实现更为深度的整合。以3.7百度糯米女生节来说,就获得了百度强大的流量支持,日活用户翻了一倍,客户端用户量超100万,甚至在3月7日当天出现了宕机,这种流量的剧增让百度糯米自身都出乎意料。

其次是“连接+找到(包括技术在内的整体打法)”的竞争。百度在PC时代的成功就是将人和信息的“连接和找到”做到了极致,这也是百度在移动互联网时代的差异化优势,百度糯米将能够实现对百度在技术方面的借势。例如百度糯米可以通过大数据等技术手段在数亿用户以及海量团单和线下商业服务的连接中实现一对一的精准匹配和个性化定制、推荐服务,挖掘其中蕴含的商业价值。

更重要的是,团购的未来竞争关键是搜索技术。团购行业从出现时的一日一单变成一日三单、一日多单、多品类商单、最后变成多城市多商圈、全街道无缝覆盖,能够匹配用户的全部线下服务需求,意味着消费者的需求越来越以位置为基础,可选越来越多,渗透率越来越高,所产生的聚变效果也就更明显,从而再次变成了一个“搜索”。这说明未来团购的竞争关键也是搜索技术,即海量团单上线后,如何实现对用户搜索需求的快速精准匹配,这无疑是作为搜索老大的百度的强项。糯米的搜索系统与百度的搜索技术进行整合,从而可以为用户带来更加智能和优选的体验。

再次是服务(商家资源)的竞争。在这方面,糯米相比美团和大众点评处于劣势。然而,百度进入之后,糯米将能够与百度的资源进行整合,从而实现核聚变。百度的地推资源是BAT里面最强的,拥有超过2万的代理商和2万多的直销团队,具有对全国600多个城市的潜在服务资源进行覆盖的能力,借助百度的地推资源加上糯米本身的力量,同时百度强大的资金实力也将弥补糯米之前不敢花钱推广的劣势,这将有望实现商家资源的迅速扩张。

更可怕的是,百度糯米在和商家对接时,讲述的将不再是团购的故事,而是依托百度的互联网资源讲包括本地生活O2O在内的更大故事。百度糯米将不仅仅可以为商家提供团购方案,而是给商家提供包括流量、CRM、技术等在内的整体解决方案,这是其他团购网站无法实现的。

象棋中有个术语叫“连环马”,即对弈中的一方两马成互相连络、保护之势,在己方阵地能强化防御能力,在对方阵地能增强进攻力量。在团购的三国演义中,糯米相比来说是最弱的,但百度的加入,借助百度在“人”、“连接+找到”和“服务”方面的资源和优势,以及百度糯米在团购上的固有优势,百度与百度糯米正在本地生活O2O和团购的棋局中形成攻守具备的“连环马”棋局。

有意思的是,美团目前还在用0毛利、包销等团购的打法,与百度糯米和百度的“连环马”阵势不可同日而语,无论给商家提供整体解决方案,还是在技术上向智能搜索、智能推荐的升级,都是如此。3.7百度糯米女生节只是一个前戏,显示出百度糯米嬗变所迸发出的可怕力量,更全面的决战还未开始,但这场战争已经注定不再是一场仅仅团购的战争。

如果把团购业的竞争比作一个万米长跑,那么胜出的关键不是冲刺而是耐力。美团和大众点评暂时领先,但截止到现在其实刚刚才进行了500米,昔日的糯米靠稳健奔跑实现在第一阵营中不掉队,而获得百度强大助推之后的百度糯米,并不仅仅是换了个名字,其内部完成了核聚变,整体已经焕然一新,一场弯道超越的好戏即将上演。

作者:南冥一鲨    来源:百度百家

责编:Chris

Java的内存泄露

$
0
0
Java有垃圾回收,因此不会出现内存泄露。 大错特错。

这个说法存在好几个问题。尽管Java的确有垃圾回收器来回收那些不用的内存块,但你不要指望它能够点铁成金。GC减轻了开发人员肩上的负担,而原本的那些工作非常容易出错,不过并不是所有内存分配的问题它都能够解决。更糟糕的是,Java的设计允许它可以欺骗GC,使得它能够保留一些程序已经不再使用的内存。经历了20年的C开发以及7年的Java开发后(中间有重叠),我敢说,在这方面Java绝对是远比C/C++要好。尽管它仍有改进的空间。在这些改进成为现实之前,作为开发人员最好能了解下内存处理的基本原理以及一些常见的坑,以免栽到里面去。但首先,

什么是内存泄露?

内存泄露是指程序不停地分配内存,但不再使用的时候却没有释放掉它,这会导致本来就有限的内存的占用量出现飙升,并且这不受程序控制,最终导致程序的运行变慢。

在那些美好的C语言开发的时代,我们说的内存泄露是指程序遗失了某个内存段的引用而没有释放掉它。这种情况下,程序获取不到这个内存区域的句柄或者指针,也无法调用free函数来释放掉它,因此这个内存块会一直处于分配的状态,没法被程序重用,这样就造成了内存的浪费。当然了,程序退出的话,操作系统会回收掉这块内存的。

这是个非常典型的内存泄露,不过我上面给出的定义更广泛一些。还有一种情况是代码仍旧拥有这块内存的指针,尽管现在这块内存已经不用了,但程序也不去释放它。就比如说一个程序员创建了一个链表,把所有通过malloc分配的内存指针全存了进去,但他从来不去调用free函数释放掉它们。结果也是一样的。既然结果是一样的,能不能获取到释放内存的指针也不那么重要了,因为你根本就不去释放它。这只是影响到了解决问题的方式,不过不管是哪种情况,修复BUG总是得修改代码的。

如果我们来看下Java和它的GC,你会发现经典的那个由于释放了内存引用导致无法释放内存的那种情况几乎不可能发生。如果是那样的话GC判断出分配的内存的所有引用已经释放掉了就自己去释放内存了。事实上,这也是Java里面标准的释放内存的方法:你只需不再引用某个对象就可以了,GC会去回收它的。这里没有垃圾桶,也没有分类垃圾箱(不需要你去扔垃圾)。别管它就行了,垃圾回收器会去回收它的。这也正是很多开发人员认为Java不存在内存泄露的原因。从实际的角度来看这的确几乎是正确的:和使用C/C++或者其它没有垃圾回收器的语言相比,使用Java开发内存泄露的麻烦事的确少了不少。

我们终于要说到重点了:Java里面是如何发生内存泄露的?

线程以及线程本地存储就非常容易产生内存泄露。通过下面的五个步骤可以很容易地产生内存泄露:

  1. 应用程序创建一个长时间运行的线程(或者使用线程池,那样泄露会更快一些)。
  2. 线程通过某个类加载器加载了一个类。
  3. 这个类分配了一大块内存(比如,new byte[1000000]),并且在它的静态字段中存储了一个强引用,然后在ThreadLocal中存储它自身的一个引用。额外分配的这个内存(new byte[1000000])其实是多余的(类实例的泄露就足够了),不过这样能使内存泄露的速度更快一些。
  4. 线程清理了自定义的类以及加载它的类加载器的所有引用。
  5. 重复以上步骤。

因为你已经没有这个类以及它的类加载器的引用了,也就不能再访问它的ThreadLocal中的存储了,因此你也就无法访问分配的这块内存(除非你开始用反射来获取)。但是这个ThreadLocal的存储还存在引用,因此GC无法回收这块内存。这个线程本地的存储不是弱引用(顺便提一句,为什么不用弱引用?)

如果你从来没有类似的经验,你可能会想,这得多脑残才能搞出这么极端的一个场景。但事实上,上述这种泄露的模式是非常自然的(好吧,程序员们,你们可别故意这么搞 ),当你在Tomcat上调试自己的程序的时候就会出现这样的泄露。对Java来说这太正常了。重新部署应用但却不重启Tomcat实例,这通常会导致内存越来越少,这正是发生了上述的这种泄露,很少有Tomcat能够避免这种情况。应用程序应当谨慎地使用ThreadLocal。

使用静态变量存储大块数据时也应当同样小心。最好避免使用静态变量,除非你很相信这个运行你程序的容器不会发生泄露。这些容器的类加载的层次结构和Java的比起来要灵活多了。如果你把大量的数据存储到一个Map或者Set里,为什么不使用它们的弱引用的版本呢?如果KEY都没了,还需要关联的那个值干嘛?

现在来说下HashMap和HashSet。如果你使用了没有实现或者错误地实现了eqauls和hashCode方法的对象来作为KEY的话,调用put()方法会把你的数据扔向深渊。你再也没法恢复它了,更糟糕的是,每当你再放一个对象到这个集合中的时候,还会产生更多的副本。你把你的内存带上了一条不归路。

在Java中,还有许许多多的内存泄露的例子。尽管它们和C/C++相比,出现的频率要少得多。通常来说,有GC总比没有的要好。

原创文章转载请注明出处: Java的内存泄露

英文原文链接

java线程5种状态[转]

$
0
0

转:http://blog.csdn.net/yaolingrui/article/details/7522372

       http://images.blogjava.net/blogjava_net/vincent/threadStates090601.png

 

Java中的线程的生命周期大体可分为5种状态。

①NEW:这种情况指的是,通过New关键字创建了Thread类(或其子类)的对象

②RUNNABLE:这种情况指的是Thread类的对象调用了start()方法,这时的线程就等待时间片轮转到自己这,以便获得CPU;第二种情况是线程在处于RUNNABLE状态时并没有运行完自己的run方法,时间片用完之后回到RUNNABLE状态;还有种情况就是处于BLOCKED状态的线程结束了当前的BLOCKED状态之后重新回到RUNNABLE状态。

③RUNNING:这时的线程指的是获得CPU的RUNNABLE线程,RUNNING状态是所有线程都希望获得的状态。

④DEAD:处于RUNNING状态的线程,在执行完run方法之后,就变成了DEAD状态了。

⑤BLOCKED:这种状态指的是处于RUNNING状态的线程,出于某种原因,比如调用了sleep方法、等待用户输入等而让出当前的CPU给其他的线程。

 

处于RUNNABLE状态的线程变为BLOCKED状态的原因,除了该线程调用了sleep方法、等待输入原因外,还有就是在当前线程中调用了其他线程的join方法、当访问一个对象的方法时,该方法被锁定等。

相应的,当处于BLocked状态的线程在满足以下条件时就会由该状态转到RUNNABLE状态,这些条件是:sleep的线程醒来(sleep的时间到了)、获得了用户的输入、调用了join的其他线程结束、获得了对象锁。

一般情况下,都是处于RUNNABLE的线程和处于RUNNING状态的线程,互相切换,直到运行完run方法,线程结束,进入DEAD状态。

 



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


ITeye推荐



我来Hacking JDBC,你并不需要它

$
0
0

我们喜欢和JDBC打交道,以前从未有人这样说过。很严肃的说,JDBC是一个非常优秀的API。这可能是 现在Java能够成为一个受欢迎的平台的重要原因之一。在JDK1.1之前, ODBC出现之前(很久之前的事情了),很难去想象有平台会标准化数据库的访问。在那个时候 SQL语言甚至本身还没有标准化,随后出现的面向Java的简单的JDBC API,工作中你需要也就是一下几点:

这些都是理论,在实际中,企业级软件操作JDBC却是像下面这样:

JDBC是Java开发者的最后一种手段之一,你可以用很多方式来探索解密这个非常详细的神秘的API。几乎每个人都在JDBC操作将实现基于这些API的包装器来防止:

  • 常见的语法错误
  • 绑定变量索引不匹配
  • 动态的SQL构建
  • 在使用lob引起的边界情况
  • 资源的操作与关闭
  • 数组和UDT(户定义类型(User Defined Type))管理
  • 存储过程的抽象

所以当大多数的人在设计上层框架的时候,他们不是在和业务逻辑打交道,但是相当多的人在使用JDBC的时候,几乎都在做这些事情。Hibernate 和JPA大多数没有这些问题,可是他们也不再是SQL API了。

下面是一些我们在JOOQ框架内解决问题的例子,所以你就不需要在解决了:

如何在某些数据库获取生成的键

case DERBY:
case H2:
case MARIADB:
case MYSQL: {
    try {
        listener.executeStart(ctx);
        result = ctx.statement().executeUpdate();
        ctx.rows(result);
        listener.executeEnd(ctx);
    }

    // Yes. Not all warnings may have been consumed yet
    finally {
        consumeWarnings(ctx, listener);
    }

    // Yep. Should be as simple as this. But it isn't.
    rs = ctx.statement().getGeneratedKeys();

    try {
        List<Object> list = new ArrayList<Object>();

        // Some JDBC drivers seem to illegally return null
        // from getGeneratedKeys() sometimes
        if (rs != null) {
            while (rs.next()) {
                list.add(rs.getObject(1));
            }
        }

        // Because most JDBC drivers cannot fetch all
        // columns, only identity columns
        selectReturning(ctx.configuration(), list.toArray());
        return result;
    }
    finally {
        JDBCUtils.safeClose(rs);
    }
}

怎么样去处理BigInteger and BigDecimal

else if (type == BigInteger.class) {
    // The SQLite JDBC driver doesn't support BigDecimals
    if (ctx.configuration().dialect() == SQLDialect.SQLITE) {
        return Convert.convert(rs.getString(index),
                               (Class) BigInteger.class);
    }
    else {
        BigDecimal result = rs.getBigDecimal(index);
        return (T) (result == null ? null :
                    result.toBigInteger());
    }
}
else if (type == BigDecimal.class) {
    // The SQLite JDBC driver doesn't support BigDecimals
    if (ctx.configuration().dialect() == SQLDialect.SQLITE) {
        return Convert.convert(rs.getString(index),
                               (Class) BigDecimal.class);
    }
    else {
        return (T) rs.getBigDecimal(index);
    }
} 

怎么去从SQL Server获取所有的异常

switch (configuration.dialect().family()) {
    case SQLSERVER:
        consumeLoop: for (;;)
            try {
                if (!stmt.getMoreResults() &&
                     stmt.getUpdateCount() == -1)
                    break consumeLoop;
            }
            catch (SQLException e) {
                previous.setNextException(e);
                previous = e;
            }
}

你信吗

这是令人不快的代码,并且我们这儿还有 更多的令人不快的代码,或者就在我们的 源码中这里所有的例子在向你表明当你在使用JDBC的时候,你要在你的程序中写那些你不想写或者不是很必要的代码,这就是为什么:“ 我们已经在Hacking JDBC了,你就不需要掺和了”。

关于作者:Lukas 是一个狂热的Java和SQL开发者。他创建了 the Data Geekery GmbH。他是 jOOQ的创建者之一,一个面向Java的综合的SQL库,他的博客主要关注三个话题:Java,SQL和JOOQ。

相关文章


Oracle数据泵EXPDP/IMPDP工具使用(按用户导出和导入)

$
0
0

1. Oracle环境变量配置

Oracle路径配置
可通过expdp help查看工具使用环境。通常对于未配置Oracle环境变量,会报以下使用错误:

 

UDE-00013: Message 13 not found; No message file for product=RDBMS, facility=UDE
UDE-00019: You may need to set ORACLE_HOME to your Oracle software directory

 出现上述问题是因为无法找到$ORACLE_HOME目录。尝试配置Oracle重要的环境变量, source /home/oracle/.bash_profile重新配置环境试试。

 

 

2. 创建Directory转储文件目录

该目录用来存放转储文件,目录必须存在且用户得有权限写。

 

-- sqlplus
create directory dump_dir as '/home/oracle/oradir';

 

 

当然如果使用的是普通用户来操作数据,你还需要给用户赋权限:

 

grant read, write directory on direcotry crxj_dump_dir to scott;

  查看当前所有Directory

 

 

select * from dba_directories;

 

 

OWNER DIRECTORY_NAME DIRECTORY_PATH
SYSDUMP_DIR/home/oracle/oradir

注意创建的需要确实存在

当目录不存在会报出如下错误(示例为sys用户):

[oracle@CRXJ_APP_218 bin]$ expdp sys/orcl directory=dump_dir dumpfile=schema_pon.dmp schemas=pon

Export: Release 11.2.0.1.0 - Production on Tue May 6 18:34:36 2014

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

UDE-28009: operation generated ORACLE error 28009
ORA-28009: connection as SYS should be as SYSDBA or SYSOPER

Username: sys as sysdba
Password: 

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
ORA-39002: invalid operation
ORA-39070: Unable to open the log file.
ORA-29283: invalid file operation
ORA-06512: at "SYS.UTL_FILE", line 536
ORA-29283: invalid file operation

 

此时需要创建该目录

[oracle@CRXJ_APP_218 bin]$ mkdir /home/oracle/oradir
[oracle@CRXJ_APP_218 bin]$ ls /home/oracle/oradir

 

至此配置好环境,也配置好存放转储文件的路径,接下来就可以导入导出了。


示例将使用sys用户,采用按用户模式导出crxj_collect用户下所有结构和数据,并导入到同用户名的另外一个数据下。

按用户(模式)导出

-- expdp username/passwd dirctory=转储文件存放目录 dumpfile=要生成的转储文件名 schemas=用户名(可多个并用逗号分开)
-- 导出CRXJ_COLLECT用户[shell中直接执行]
expdp sys/orcl directory=dump_dir dumpfile=schema_crxj_collect.dmp schemas=crxj_collect

 

[oracle@CRXJ_APP_218 oradir]$ expdp sys/orcl directory=dump_dir dumpfile=schema_crxj_collect.dmp schemas=crxj_collect

Export: Release 11.2.0.1.0 - Production on Tue May 6 20:48:19 2014

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

UDE-28009: operation generated ORACLE error 28009
ORA-28009: connection as SYS should be as SYSDBA or SYSOPER

Username: sys as sysdba
Password:

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Starting "SYS"."SYS_EXPORT_SCHEMA_01":  sys/******** AS SYSDBA directory=dump_dir dumpfile=schema_crxj_collect.dmp schemas=crxj_collect
Estimate in progress using BLOCKS method...
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 1.259 GB
Processing object type SCHEMA_EXPORT/USER
*****省略N多表******
. . exported "CRXJ_COLLECT"."HOST_SESSION"                   0 KB       0 rows
Master table "SYS"."SYS_EXPORT_SCHEMA_01" successfully loaded/unloaded
******************************************************************************
Dump file set for SYS.SYS_EXPORT_SCHEMA_01 is:
  /home/oracle/oradir/schema_crxj_collect.dmp
Job "SYS"."SYS_EXPORT_SCHEMA_01" successfully completed at 20:50:49

[oracle@CRXJ_APP_218 oradir]$

 

导入到指定用户(模式)

由于是导入到远程库,所以还需要创建下转储文件所在目录

-- 省略掉如何把导出的转储文件移动到指定远程库目录下
SQL> create directory dump_dir as '/home/oracle/oradir';

Directory created.

SQL>

 

-- 导入数据
-- impdp 用户名/密码 DIRECTORY=转储文件所在目录 DUMPFILE=带导入的转储文件名 SCHEMAS=待导入的用户(模式)名
impdp sys/orcl DIRECTORY= dump_dir DUMPFILE=schema_crxj_collect.dmp SCHEMAS=CRXJ_COLLECT;

 

因为不要求导出和导入的是同一个用户,所以数据泵这个工具可以方便的在不同用户(模式)见传到数据对象。
数据泵高级操作中可以实现数据对象的逻辑恢复,包括按表、按用户模式(本文即是),按表空间和全库导入导出。

更多内容有待更新,敬请期待。

转载请标明原文链接。

ifuteng@gmail.com :)

 

 

 



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


ITeye推荐



java中文分词组件-word分词

$
0
0


关键字:java中文分词组件-word分词


word分词器主页 :https://github.com/ysc/word



word分词是一个Java实现的中文分词组件,提供了多种基于词典的分词算法,并利用ngram模型来消除歧义。 能准确识别英文、数字,以及日期、时间等数量词,能识别人名、地名、组织机构名等未登录词。 同时提供了Lucene、Solr、ElasticSearch插件。

分词使用方法:


  1、快速体验
  运行项目根目录下的脚本demo-word.bat可以快速体验分词效果
  用法: command [text] [input] [output]
  命令command的可选值为:demo、text、file
  demo
  text 杨尚川是APDPlat应用级产品开发平台的作者
  file d:/text.txt d:/word.txt
  exit

  2、对文本进行分词
  移除停用词:List<Word> words = WordSegmenter.seg("杨尚川是APDPlat应用级产品开发平台的作者");
  保留停用词:List<Word> words = WordSegmenter.segWithStopWords("杨尚川是APDPlat应用级产品开发平台的作者");
  System.out.println(words);


  输出:
  移除停用词:[杨尚川, apdplat, 应用级, 产品, 开发平台, 作者]
  保留停用词:[杨尚川, 是, apdplat, 应用级, 产品, 开发平台, 的, 作者]

  3、对文件进行分词
  String input = "d:/text.txt";
  String output = "d:/word.txt";
  移除停用词:WordSegmenter.seg(new File(input), new File(output));
  保留停用词:WordSegmenter.segWithStopWords(new File(input), new File(output));

  4、自定义配置文件
  默认配置文件为类路径下的word.conf,打包在word-x.x.jar中
  自定义配置文件为类路径下的word.local.conf,需要用户自己提供
  如果自定义配置和默认配置相同,自定义配置会覆盖默认配置
  配置文件编码为UTF-8


  5、自定义用户词库
  自定义用户词库为一个或多个文件夹或文件,可以使用绝对路径或相对路径
  用户词库由多个词典文件组成,文件编码为UTF-8
  词典文件的格式为文本文件,一行代表一个词
  可以通过系统属性或配置文件的方式来指定路径,多个路径之间用逗号分隔开
  类路径下的词典文件,需要在相对路径前加入前缀classpath:


  指定方式有三种:
  指定方式一,编程指定(高优先级):
  WordConfTools.set("dic.path", "classpath:dic.txt,d:/custom_dic");
  DictionaryFactory.reload();//更改词典路径之后,重新加载词典
  指定方式二,Java虚拟机启动参数(中优先级):
  java -Ddic.path=classpath:dic.txt,d:/custom_dic
  指定方式三,配置文件指定(低优先级):
  使用类路径下的文件word.local.conf来指定配置信息
  dic.path=classpath:dic.txt,d:/custom_dic

  如未指定,则默认使用类路径下的dic.txt词典文件

  6、自定义停用词词库
  使用方式和自定义用户词库类似,配置项为:
  stopwords.path=classpath:stopwords.txt,d:/custom_stopwords_dic

  7、自动检测词库变化
  可以自动检测自定义用户词库和自定义停用词词库的变化
  包含类路径下的文件和文件夹、非类路径下的绝对路径和相对路径
  如:
  classpath:dic.txt,classpath:custom_dic_dir,
  d:/dic_more.txt,d:/DIC_DIR,D:/DIC2_DIR,my_dic_dir,my_dic_file.txt


  classpath:stopwords.txt,classpath:custom_stopwords_dic_dir,
  d:/stopwords_more.txt,d:/STOPWORDS_DIR,d:/STOPWORDS2_DIR,stopwords_dir,remove.txt


  8、显式指定分词算法
  对文本进行分词时,可显式指定特定的分词算法,如:
  WordSegmenter.seg("APDPlat应用级产品开发平台", SegmentationAlgorithm.BidirectionalMaximumMatching);


  SegmentationAlgorithm的可选类型为:
  正向最大匹配算法:MaximumMatching
  逆向最大匹配算法:ReverseMaximumMatching
  正向最小匹配算法:MinimumMatching
  逆向最小匹配算法:ReverseMinimumMatching
  双向最大匹配算法:BidirectionalMaximumMatching
  双向最小匹配算法:BidirectionalMinimumMatching
  双向最大最小匹配算法:BidirectionalMaximumMinimumMatching

  9、分词效果评估
  运行项目根目录下的脚本evaluation.bat可以对分词效果进行评估
  评估采用的测试文本有253 3709行,共2837 4490个字符
  评估结果位于target/evaluation目录下:
  corpus-text.txt为分好词的人工标注文本,词之间以空格分隔
  test-text.txt为测试文本,是把corpus-text.txt以标点符号分隔为多行的结果
  standard-text.txt为测试文本对应的人工标注文本,作为分词是否正确的标准
  result-text-***.txt,***为各种分词算法名称,这是word分词结果
   perfect-result-***.txt,***为各种分词算法名称,这是分词结果和人工标注标准完全一致的文本
   wrong-result-***.txt,***为各种分词算法名称,这是分词结果


Lucene插件:

  1、构造一个word分析器ChineseWordAnalyzer
  Analyzer analyzer = new ChineseWordAnalyzer();

  2、利用word分析器切分文本
  TokenStream tokenStream = analyzer.tokenStream("text", "杨尚川是APDPlat应用级产品开发平台的作者");
  while(tokenStream.incrementToken()){
  CharTermAttribute charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
  OffsetAttribute offsetAttribute = tokenStream.getAttribute(OffsetAttribute.class);
  System.out.println(charTermAttribute.toString()+" "+offsetAttribute.startOffset());
  }


  3、利用word分析器建立Lucene索引
  Directory directory = new RAMDirectory();
  IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_47, analyzer);
  IndexWriter indexWriter = new IndexWriter(directory, config);





  4、利用word分析器查询Lucene索引
  QueryParser queryParser = new QueryParser(Version.LUCENE_47, "text", analyzer);
  Query query = queryParser.parse("text:杨尚川");
  TopDocs docs = indexSearcher.search(query, Integer.MAX_VALUE);




Solr插件:


  1、生成分词组件二进制jar
  执行 mvn clean install 生成word中文分词组件target/word-1.0.jar


  2、创建目录solr-4.7.1/example/solr/lib,将target/word-1.0.jar文件复制到lib目录


  3、配置schema指定分词器
  将solr-4.7.1/example/solr/collection1/conf/schema.xml文件中所有的
  <tokenizer class="solr.WhitespaceTokenizerFactory"/>和
  <tokenizer class="solr.StandardTokenizerFactory"/>全部替换为
  <tokenizer class="org.apdplat.word.solr.ChineseWordTokenizerFactory"/>
  并移除所有的filter标签

  4、如果需要使用特定的分词算法:
  <tokenizer class="org.apdplat.word.solr.ChineseWordTokenizerFactory" segAlgorithm="ReverseMinimumMatching"/>
  segAlgorithm可选值有:
  正向最大匹配算法:MaximumMatching
  逆向最大匹配算法:ReverseMaximumMatching
  正向最小匹配算法:MinimumMatching
  逆向最小匹配算法:ReverseMinimumMatching
  双向最大匹配算法:BidirectionalMaximumMatching
  双向最小匹配算法:BidirectionalMinimumMatching
  双向最大最小匹配算法:BidirectionalMaximumMinimumMatching
  如不指定,默认使用双向最大匹配算法:BidirectionalMaximumMatching

  5、如果需要指定特定的配置文件:
  <tokenizer class="org.apdplat.word.solr.ChineseWordTokenizerFactory" segAlgorithm="ReverseMinimumMatching"
  conf="C:/solr-4.7.0/example/solr/nutch/conf/word.local.conf"/>
  word.local.conf文件中可配置的内容见 word-1.0.jar 中的word.conf文件
  如不指定,使用默认配置文件,位于 word-1.0.jar 中的word.conf文件




ElasticSearch插件:


  1、执行命令: mvn clean install dependency:copy-dependencies


  2、创建目录elasticsearch-1.1.0/plugins/word


  3、将中文分词库文件target/word-1.0.jar和依赖的日志库文件
  target/dependency/slf4j-api-1.6.4.jar
  target/dependency/logback-core-0.9.28.jar
  target/dependency/logback-classic-0.9.28.jar
  复制到刚创建的word目录


  4、修改文件elasticsearch-1.1.0/config/elasticsearch.yml,新增如下配置:
  index.analysis.analyzer.default.type : "word"
  index.analysis.tokenizer.default.type : "word"


  5、启动ElasticSearch测试效果,在Chrome浏览器中访问:
  http://localhost:9200/_analyze?analyzer=word&text=杨尚川是APDPlat应用级产品开发平台的作者


  6、自定义配置
  从word-1.0.jar中提取配置文件word.conf,改名为word.local.conf,放到elasticsearch-1.1.0/plugins/word目录下


  7、指定分词算法
  修改文件elasticsearch-1.1.0/config/elasticsearch.yml,新增如下配置:
  index.analysis.analyzer.default.segAlgorithm : "ReverseMinimumMatching"
  index.analysis.tokenizer.default.segAlgorithm : "ReverseMinimumMatching"


  这里segAlgorithm可指定的值有:
  正向最大匹配算法:MaximumMatching
  逆向最大匹配算法:ReverseMaximumMatching
  正向最小匹配算法:MinimumMatching
  逆向最小匹配算法:ReverseMinimumMatching
  双向最大匹配算法:BidirectionalMaximumMatching
  双向最小匹配算法:BidirectionalMinimumMatching
  双向最大最小匹配算法:BidirectionalMaximumMinimumMatching
  如不指定,默认使用双向最大匹配算法:BidirectionalMaximumMatching

词向量:

  从大规模语料中统计一个词的上下文相关词,并用这些上下文相关词组成的向量来表达这个词。
  通过计算词向量的相似性,即可得到词的相似性。
  相似性的假设是建立在如果两个词的上下文相关词越相似,那么这两个词就越相似这个前提下的。

  通过运行项目根目录下的脚本demo-word-vector-corpus.bat来体验word项目自带语料库的效果


  如果有自己的文本内容,可以使用脚本demo-word-vector-file.bat来对文本分词、建立词向量、计算相似性


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


ITeye推荐



在纸上记课堂笔记效果好于笔记本电脑

$
0
0
越来越多的学生在课堂上使用笔记本电脑,除了电脑可能分心外,在电脑上记笔记与用笔在纸上记笔记效果孰优孰劣?一项研究发现,用笔记笔记的课堂效果更好。研究表明,即使笔记本电脑只是单纯用于记笔记,它仍然对学习是有害的:因为电脑上的笔记通常倾向于逐字记录课堂上讲的内容,而不是处理信息,在纸上用自己的话将内容重写一遍,这么做显然不利于学习。领导这项研究的普林斯顿大学心理学家 Pam Mueller说,用笔记录笔记不可能记下每一个字,而如果你打字速度足够快,逐字抄写是可能的。研究发表在《心理学》期刊上。






[原]软件项目量化管理目标举例

$
0
0

1 产出类目标

1.1总体目标

进度:项目工期偏差率介于+-15%之间;

质量:项目的缺陷逃逸率不高于5%;

      项目交付的缺陷密度不高于1个bugs/KLOC;

规模:需求变更率不超过15%;

成本:工作量偏差率不超过+-30%;

      每人月实际投入项目的时间不少于上班时间的50%;

项目返工工作量不高于20%;

效率:全生命周期生产率不小于1KLOC/MM;

其他:人员变更率不超过20%;

1.2局部目标:

进度:阶段工期偏差率不超过+-15%;

质量:需求评审的缺陷密度不少于0.2/页;

      设计评审的缺陷密度不少于0.5/页;

      系统测试的缺陷密度不少于2个/KLOC;

      单元测试的缺陷密度不少于5个/KLOC;

      代码走查的缺陷密度不少于10个/KLOC;

      集成一次通过率不少于90%;

静态检查的缺陷密度不高于10个/KLOC;

测试缺陷重现率不高于10%;

规模:需求文档的页数不多于15CFP/页;

      代码复用率不少于20%;

2 投入类目标:

        每月平均加班工时不超过2天;

        文档中的图表数量平均每页不少于1个;

需求评审的工作量:需求开发的工作量>50%;

        设计评审的工作量:设计的工作量>50%;

        需求、设计评审的速度不高于10页/小时;

        注释代码比例不少于10%;

    代码评审速度不高于250行/小时;

        代码走查的投入工作量不少于1小时/人天;

        单元测试的用例密度不少于50个测试用例/KLOC;

    系统测试的投入工作量不少于100人天;

    系统测试的用例密度不少于10个测试用例/KLOC.

 

 

作者:dylanren 发表于2014-5-6 18:59:05 原文链接
阅读:30 评论:0 查看评论

Java多线程程序的测试

$
0
0

Java多线程程序的测试

这个问题最初来自于一封公司内部的话题探讨邮件,再加上了一些我的理解。

首先,需要明确的是,用Java通常构建多线程安全的程序“非常”困难,如果还没有体会到“非常”的话,阅读《Java Concurrency in Practice》(中文名叫做《Java并发编程实战》,在我的 书单里面,我认为它基本是最好的系统介绍Java并发的书了)可能可以改变你的看法。

多线程的基础

基础是王道。对于任何一门语言都是如此,有的基础部分是和语言无关的,也有一部分是和Java语言相关的。这里我不过多展开,但是我想提一提对于 JSR规范的理解。通常我们认为Java是一门啰嗦、冗长,容易使用,而且不容易造成破坏的语言,但是,要写完全正确的Java多线程程序,却根本不是这样,需要知道的东西非常多,譬如JSR-133和JSR-166这两个最重要的规范。

良好的设计

这一定是放在第一条。软件质量不是靠测出来的,而是靠设计出来的。尽可能简化问题,主动去避免一些潜在的问题,例如,我在 这篇文章里面谈到了为什么多线程的GUI框架很难被设计出来;再比如 OSCache中受到批评的NeedsRefreshException,设计机制决定了它bug丛生,容易发生死锁。一些被广泛认可的经验总结都是指导软件设计的参考依据。天然地,从设计阶段就让程序对逻辑多线程执行的解读保持清晰和简单,这样的代码才谈得上可靠性。

代码评审

对于一些很难构造测试用例来覆盖的潜在问题, 代码评审几乎成为了最后一道可能系统地发现问题的堤坝。当然,代码评审的局限性很明显,评审的人也很容易陷入细枝末节当中,通常意义上编码习惯和规范性问题,或者是单个类的使用造成的多线程潜在问题容易被发现,但是类和组件之间的并发情况下资源使用和条件关联的问题却很难被发现出来。

辅助工具检查

比如 FindBugs这样的工具,可以看一看 bug description的列表中“ Multithreaded correctness”的部分。当然,类似地,还有 PMD这样的工具。这两个工具都可以针对编译后的class来查错,而不是只是源代码文件。还有一个名为 Coverity Code Advisor的工具,我也是第一次听到,不过所属公司Coverity,王垠曾经写文章评论过,感兴趣的可以去他的博客找。

说了那么多,现在才轮到真正说测试的部分。但是,即便如此,我依然要说,多线程程序的很多问题很难通过测试发现。倚仗测试去保证质量在这里只能说是下下策。

压力测试

首先,需要明确的是,和所有的情况的测试一样,测试出问题只能作为充分条件,不能作为必要条件,即多线程程序测试发现问题只能说明这段多线程程序是有问题的,但是程序有问题却不一定能够通过测试发现。最容易想到的方法大概是通过多线程场景下对多线程的代码逻辑反复执行,特别是做到可控制的压力测试,以期望其中的若干次运行得到非预期的结果。这是最粗暴也是最简单的办法。这样的方法是不可替代的。但是,很多多线程问题的出现情况复杂而且这种方式明显缺乏目的性,有乱枪打鸟的感觉。

Debug大法

很好笑对不对?不要小看了单步执行,尤其对于不同线程中,执行分支路径之间的组合,用单步调试的方法可以模拟出很多种情况,当然,这样的测试必然是白盒的。对于多线程程序的问题,我不相信一个不看被测试代码的黑盒测试人员可以做好这件事情。

多线程程序测试的框架

这个要看具体情况了。在Amazon就有这样的一套内部使用的并发测试框架,在我以前的公司,也见过别的部门有人写过,基本上和传统测试代码编写无异,通过注解或者几个简单的工具类控制,就可以灵活地指定并行测试的参数了,比如线程数量等等(有代码指定,也有命令行参数指定)。

一些有趣的开源库

比如 Thread Weaver,这个库是专门用来写多线程单元测试的,它的原理是在代码中创建一些断点,接着代码执行的时候就可以挂在断点上面,这样就可以测试各种资源争用和条件组合了。给一个简单的例子,首先定义MyList这样的对象:

public class MyWriter {
	private StringBuilder sb = new StringBuilder();
	private int counter = 0;

	public synchronized void write(String s) {
		sb.append(++counter + "-" + s + " ");
	}
	public synchronized String toString(){
		return sb.toString();
	}
}

现在测试它:

public class MyWriterTest {
	private MyWriter writer;

	@Test
	public void testThreading() {
		AnnotatedTestRunner runner = new AnnotatedTestRunner();
		// Run all Weaver tests in this class, using MyList as the Class Under Test.
		runner.runTests(this.getClass(), MyWriter.class);
	}

	@ThreadedBefore
	public void before() {
		writer = new MyWriter();
	}

	@ThreadedMain
	public void mainThread() {
		writer.write("MainA");
		writer.write("MainB");
	}

	@ThreadedSecondary
	public void secondThread() {
		writer.write("SecondA");
		writer.write("SecondB");
	}

	@ThreadedAfter
	public void after() {
		System.out.print(writer.toString());
	}
}

其中@ThreadedBefore和@ThreadedAfter是一对,以前者为例,对于API文档里面的解释:“An annotation that designates part of a test suite that uses the AnnotatedTestRunner framework to perform multithreaded tests. A method tagged with the ThreadedBefore attribute will be run before every test case.”,我最初认为以Threaded开头的注解都会默认启动两个线程并行执行,后来发现确实是执行了两遍,但是通过在@ThreadedBefore/After的代码里面打印线程号发现,这两遍的线程号都是同样的,这里的机制我还不是很清楚;

而对于上述每执行一遍的过程中,又因为有了@ThreadedMain和@ThreadedSecondary这一对,这两个注解修饰的方法会分别放到单独的线程里面去并行执行。

以下是其中一种可能的输出结果:

1-MainA 2-SecondA 3-MainB 4-SecondB 1-MainA 2-SecondA 3-MainB 4-SecondB 

当然,也可能是:

1-MainA 2-SecondA 3-SecondB 4-MainB 1-MainA 2-SecondA 3-MainB 4-SecondB 

等等多种。

Thread Weaver还允许使用CodePosition做精细控制,有一点复杂, 文档里面有例子说明,就像是把debug过程给代码化了。

再比如 JPF,JPF的全称叫做Java Pathfinder,是可以自定义的Java字节码执行环境,经常被用来Java程序调试和校验。有了它,可以发现Java程序员的一些错误,收集运行时的信息,推断 测试向量和创建相应的测试驱动器等等。它从系统上探测程序所有可能的执行路径,以发现死锁或未处理异常之类情形。

 

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》

分享到:
你可能也喜欢:
Viewing all 15843 articles
Browse latest View live


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