2014年7月31日星期四

Linux_072:RHEL下禁止ping和允许ping的方法

运行环境:RHEL 6.5

为了提高机器的安全性,可以不让其它机器ping,以root身份执行:

1. 禁止 ping
# echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_all

2. 允许 ping
# echo 0 >/proc/sys/net/ipv4/icmp_echo_ignore_all

此上两条命令执行后立即生效。
注意,不能直接icmp_echo_ignore_all文件内容,要按上面的方式修改才行。


参考文献:
1. http://www.getroad.cn/blog/?action=show&id=821
2. http://www.wkii.org/linux-ban-ping-and-open-way.html
3. http://www.f5ha.com/2010/0822/2NMDAwMDAwMDM2Nw.html

2014年7月30日星期三

Linux_071:进程

环境:RHEL 7.1 或 MAC 10.11.6

1. 前台进程
默认情况下,每一个进程都是前台运行的。
当然,你可以暂停前台进程,然后执行后台进程,并且在前后台进程之间自由切换。

2. 后台进程
开始一个后台进程的最简单的方法是在命令后面加一个 &。
比如:$ ls & 会输出
[1] 71974
这一行包含了两条后台进程信息:任务号和进程号。
在目录列表的末尾,不会得到任何提示符。这是因为提示符已经在"任务号和进程号"那一行之后出现过了。
如果此时按回车,会出现
[1]+  Done                    ls
这一行表明后台 ls 任务已经完成,然后下一行会出现提示符。

3. 切换前台进程至后台
当前台进程运行时,是不能执行其它命令的。
这时,可以使用 Ctrl + Z 暂停当前的进程。
如果 Ctrl + Z 不好使,可以使用 stty -a 看看你的系统设置。
被暂停的进程要想继续运行,可以有两种选择:前台运行或后台运行。
举例:$ dd if=/dev/zero of=/dev/null
按下 Ctrl + Z,输出如下:
^Z
[1]+  Stopped                 dd if=/dev/zero of=/dev/null
表明任务号为 1 的进程已经被停止,然后获得一个提示符。
如果想要在后台继续运行这个进程,需要输入 bg 命令,输出如下:
[1]+ dd if=/dev/zero of=/dev/null &
这样该进程就在后台运行,注意后面有个 & 符号。
如果有多个进程被暂停,可以用 jobs 命令查看任务列表,然后使用 bg %<任务号>,将该任务在后台运行。

4. 切换后台进程至前台
fg 命令可以把后台运行或暂停的进程切换至前台。
举例:$ dd if=/dev/zero of=/dev/null
按下 Ctrl + Z,输出如下:
^Z
[1]+  Stopped                 dd if=/dev/zero of=/dev/null
表明任务号为 1 的进程已经被停止,然后获得一个提示符。
如果想要在前台继续运行这个进程,需要输入 fg 命令,输出如下:
dd if=/dev/zero of=/dev/null
如果有多个进程被暂停,可以用 jobs 命令查看任务列表,然后使用 fg %<任务号>,将该任务在前台运行。

5. 保持后台进程(no hang up)
当退出系统后,默认是中止所有正在运行的进程,可以使用 nohup 命令防止这种情况在你需要保持的任务上发生。
举例:$ dd if=/dev/zero of=/dev/null
举例:$ dd if=/dev/zero of=/dev/null &

6. 等待后台进程的结束
(1)等待所有后台进程结束:wait
(2)等待指定后台进程结束:wait %<任务号>

7. 中止进程
kill %<任务号>
kill <PID>
kill -9 <PID>

8. 父进程和子进程

参考文献:
1. 《精通 shell 编程(第二版)》

2014年7月29日星期二

Architect_014:淘宝十年架构演变(摘录+整理)

本文是根据《淘宝技术这十年》精心整理的文章,主要是整理了淘宝十年架构演变过程,着重记录了当时遇到的问题以及解决办法,淘宝不是神,它发展的每一步都遇到了我们曾经遇到或者将会遇到的问题,他们很好地解决了这些问题,才有了今天的淘宝。
这些经验值得记录整理下来,希望能对大家有所借鉴。
借用书中的一句话:“好的架构是进化来的,不是设计来的”。
借用书中的另一句话:“好的功能也是进化来的,不是设计来的”。

1. 2003年
(1)4月
购买了PHPAuction,一个符合LAMP(Linux+ Apache+MySQL+PHP)架构的拍卖应用。

问题:只有一个数据库,容量小,且读写都在一起,影响读写效率。
办法:将MySQL数据库改为一个主库、两个从库,并且读写分离。
好处:存储容量增加了,并且有了备份,数据安全性增加了,读写分离使得读写效率得以提升(写要比读更加消耗资源,分开后互不干扰)。

淘宝网架构图1.0:




(2)7月 
问题:商品搜索的功能占用数据库资源太大了(用like搜索的,很慢)。
办法:引入搜索引擎iSearch。

(3)10月
问题:一台服务器不堪重负。
办法:服务器由最初的一台变成了三台,一台负责发送Email、一台负责运行数据库、一台负责运行 WebApp。

(4)12月,注册用户23万,日均PV31万。

2. 2004年
(1)1月
问题:MySQL4在写数据的时候会把表锁住。
当Master同步数据到Slave的时候,会引起Slave写,这样在Slave 的读操作都要等待。
还有一点是会发生Slave上的主键冲突,经常会导致同步停止,这样,你发布的一些东西明明已经成功了,但就是 查询不到。另外,当年的MySQL不比如今的MySQL,在数据的容量和安全性方面也有很多先天的不足(和Oracle相比)。

问题:随着访问量和数据量的飞速上涨,流量和交易量的迅速上涨让MySQL撑不住了。
办法:更换数据库,把MySQL更换为Oracle。访问方式和SQL语法都要跟着变。

淘宝网架构图2.0: 


问题:Oracle数据库的性能和并发访问能力为何如此强大?
Oracle的性能和并发访问能力之所以如此强大,有一个关键性的设计——连接池,连接池中放的是长连接,是进程级别的,在创建进程的时候,它就要独占一部分内存空间。也就是说,这些连接数在固定内存的Oracle Server 上是有限的,任何一个请求只需要从连接池中取得一个连接即可,用完后释放,这不需要频繁地创建和断开连接,而连接的创 建和断开的开销是非常大的。

问题:长连接多了,会把数据库拖挂;短连接多了,连接用完释放,还是会浪费一定的资源。
办法:使用连接池代理服务:SQL Relay(用PHP写的),并进行Oracle数据库调优、SQL调优。

问题:数据量继续增长,本地存储无法满足。
办法:购买NetApp(Network Appliance,美国网域存储技术有限公司)的 NAS(Network Attached Storage,网络附属存储)作为数据库的存储设备,再加上Oracle RAC(Real Application Clusters,实时应用集群)来实现负载均衡。

问题:NAS的NFS(Network File System)协议传输的延迟很严重。
办法:购买Dell和EMC合作的SAN低端存储,性能一下提升了十几倍,这才比较稳定了。

问题:数据量继续增长,本地存储无法满足。
办法:存储的节点一拆二、二拆四。

(2) 3月
问题:SQL Relay 经常死锁,SQL Relay 进程Hung住。
办法:没有办法,只有重启。

问题:如何与银行网关进行对接?
虽然银行实现了网上支付,但是接口五花八门。用户付钱不一定能扣款成功,扣款成功不一定能够保证通知淘宝,通知淘宝不一定能保证通知到,通知到了不一定保证不重复通知。
办法:没有办法,只有一家一家的对接,然后慢慢产生了“支付宝”的雏形。
最终使用Notify消息通知中间件彻底解决了这个问题,见后面。

(4)5月
问题:Oracle数据库已经调优到极限了,但是SQL Relay的问题依然无法解决。
办法:换开发语言,把PHP换成Java。

问题:用什么办法把一个庞大的网站从PHP语言迁移到 Java?而且要求在迁移的过程中,不停止服务,原来系统的bugfix 和功能改进不受影响。
办法:给业务分模块,一个模块一个模块地渐进式替换。如用户模块, 老的member.taobao.com继续维护,不添加新功能,新功能在新的模块上开发,跟老的模块共用一个数据库,开发完毕之后放到 不同的应用集群上,另开一个域名member1.taobao.com,同时再替换老的功能,替换一个,就把老的模块上的功能关闭一个,逐渐把用户引导到member1.taobao.com,等所有的功能都替换完之 后,关闭member.taobao.com。

问题:Java MVC 框架选哪个?
办法:使用阿里巴巴自己的MVC 框架:WebX。其中页面模板:JSP + Velocity,持久层:ibatis + Hibernate,控制层:EJB + Spring。

问题:如何进一步缓解数据库的压力?
办法:使用搜索引擎 iSearch,把数据库里的数据dump(倾倒)成结构化的文本文件后,放在硬盘上,提供Web应用以约定的参数和语法来查询这些数据。这看起来不难,难的是数以亿计的信息,怎么做到快速更新呢? 这好比你做了一个网站,在百度上很快就能搜到,你一定很满意了。但如果你发布一件商品,在淘宝上过1个小时还搜不到,你肯定要郁闷了。另一个难点是如何保证非常高的容量和并发量?再往后面就要考虑断句和语义分析的问题,以及推荐算法等更加智能的问题。

淘宝网架构图3.0:


(3)7月
问题:数据量进一步上涨,Oracle RAC撑不住了。
办法:购买IBM小型机。存储方面,从EMC低端CX存储到Sun oem hds高端存储,再到EMC dmx高端存储,一级一级地往上跳。
至此,进入IOE时代:IBM 小型机、Oracle 数据库、EMC 存储。
“能用钱能解决的问题,都不是难题。”

(4)12月
注册会员400万,日均4千多万PV。

3. 2005年

问题:如何解决数据库的横向扩展性?
办法:分库分表。
一台Oracle的处理能力是有上限的,它的连接池有数量限制,查询速度与容量成反比。在数据量上亿、 查询量上亿的时候,就到它的极限了。要突破这种极限,最简单 的方式就是多用几个Oracle数据库。但一个封闭的系统做扩展, 不像分布式系统那样直接加机器就可以了。
我们的做法是把用户 的信息按照ID来存放到两个数据库中(DB1和DB2),把商品的信息和卖家信息放在两个对应的数据库中,把商品类目等通用信 息放在第三个库中(DBcommon)。这么做的目的是除了增加了 数据库的容量之外,还有一个就是做容灾,即万一一个数据库挂 了,整个网站上还有一半的商品可以买。

问题:分库分表后,数据如何路由?
比如我是一个买家,买的商品有DB1的,也有DB2的,要查看“我已买到的宝 贝”的时候,应用程序怎么办?必须到两个数据库中分别查询对应的商品。要按时间排序怎么办?两个库中“我已买到的宝贝” 全部查出来在应用程序中做合并。另外,分页怎么处理?关键字查询怎么处理?专业点的说法就是数据的Join没法做了。
办法:编写数据库路由框架:DBRoute,统一处理了数据的合并、排序、分 页等操作,让程序员像使用一个数据库一样操作多个数据库里的数据。

问题:分库分表后,数据如何容灾?

问题:系统如何精简代码。
办法:使用Spring替代EJB。

12月,注册用户1390万, 日均8931万PV。

4. 2006年

问题:除了搜 索引擎、分库分表,还有什么办法能提升系统的性能?
办法:缓存和CDN(内容分发网络)。

问题:哪些信息适合放到缓存中?
办法:使用基于Berkeley DB的缓存,把很多不太变动的只读信息放了进去。
一开始先把卖家的信息放里面,然后把商品属性放里面,再把店铺信息放里面,但是像商品详情这类字段太大的放进去受不了。

问题:大字段信息放到哪里?
说到商品详情,这个字段比较恐怖,有人统计过,淘宝商品详情打印出来平均有5米长,在系统里 其实放在哪里都不招人待见。它最早与商品的价格、运费等信息放在一个表中,拖慢了整张表的查询速度,而很多时候查询商品信息是不需要查看详情的。
办法:把商品详情单独放在数据库的另外一张表中,再往后,这个大字段被从数据库中请了出来,先是放入了缓存系统,到现在是放进了文件系统TFS中。

问题:商品详情中的浏览次数如何存储?
这个数字每刷新一次,页面就要“写入”存储一次,这种高频度实时更新的数据能用缓存吗?通常来说,这种是必须放进数据库的,但是把浏览次数写入数据库,发布上线1个小时后,数据库就挂掉了,每天几亿次的写入,数据库承受不了。
办法:在Apache上增加了一个模块,根本不经过Web容器,直接写入缓存。
  
问题:更新数据时,如何通知缓存?
办法:

问题:当商用CDN也无法支撑流量时怎么办?
办法:从商用CDN:ChinaCache到自建CDN网络:淘宝CDN。

淘宝网架构图4.0:

12月,注册用户,日均1.5亿PV。

5. 2007年

(1)6月

问题:海量图片存储问题。
淘宝对图片存储的需求:文件比较小,并发量高,读操作远大于写操作,访问随机,没有文件修改的操作,要求存储成本低,能容灾,能备份。
办法:使用用分布式存储系统,由于文件大小比较统 一,可以采用专有文件系统;由于并发量高,读写随机性强,需 要更少的I/O操作。考虑到成本和备份,需要用廉价的存储设备;考虑到容灾,需要能平滑扩容。

淘宝文件系统 TFS 1.0 架构:


集群由一对Name Server和多台Data Server构成,Name Server的两台服务器互为双机,这就是集群文件系统中管理节点的概念。在这个系统中:
  • 每个Data Server运行在一台普通的Linux主机上。
  • 以Block文件的形式存放数据文件(一个Block的大小一般为 64MB)。
  • Block存储多份是为了保证数据安全。
  • 利用ext3文件系统存放数据文件。
  • 磁盘raid5做数据冗余。
  • 文件名内置元数据信息,用户自己保存TFS文件名与实际文件的对照关系,这使得元数据量特别小。
淘 宝TFS文件系统在核心设计上最大的取巧在于:传统的集群系统中元数据只有1份,通常由管理节点来管理,因而很容易成为瓶颈。而对于淘宝网的用户来说,图片文件究竟用什么名字来保 存他们并不关心,因此,TFS在设计规划上考虑在图片的保存文件名上暗藏了一些元数据信息,例如,图片的大小、时间、访问 频次等信息,包括所在的逻辑块号。而在实际的元数据上,保存的信息很少,因此,元数据结构非常简单。仅仅只需要一个FileID 就能够准确定位文件在什么地方。由于大量的文件信息都隐藏在 文件名中,整个系统完全抛弃了传统的目录树结构,因为目录树 开销最大。拿掉后,整个集群的高可扩展性可极大地提高。实际上,这一设计理念和目前业界的“对象存储”较类似。

淘宝文件系统 TFS 1.3 架构:



工程师们重点改善了心跳和同步的性能,心跳和同步在几秒钟之内就可完成切换,同时进行了一些新的优化,包括元数据存储在内存中、清理磁盘空间等。性能上也做了如下优化:
  • 采用ext4文件系统,并且预分配文件,减少ext3等文件系统数据碎片带来的性能损耗。
  •  单进程管理单块磁盘的方式,摒除RAID5机制。
  •  带有HA机制的中央控制节点,在安全稳定和性能复杂度之 间取得平衡。
  •  缩减元数据大小,将更多的元数据加载入内存,提升访问速度。
  • 跨机架和IDC的负载均衡及冗余安全策略。
  • 完全平滑扩容。
整个图片服务机器的拓扑结构图

整个图片存储系统就像一个庞大的服务器,有处理单元、缓 存单元和存储单元。
在TFS前端,还部署着200多台图片文件服务器,用Apache实现,用于生成缩略图的运算,缩略图都是实时生成的。
图片文件服务器的前端则是一级缓存和二级缓存,前面还有全局负载均衡的设置,用于解决图片的访问热点问题。图片的访问热点一定存在,重要的是,让图片尽量在缓存中命中。目前,淘宝网在各个运营商的中心点设有二级缓存,整体系统中心店设有一级缓存,加上全局负载均衡,传递到后端TFS的流量就已经非常均衡和分散了,对前端的响应性能也大大提高。
大部分图片都尽量在缓存中命中,如果缓存中无法命中,则会在本地服务器上查找是否存有原图,并根据原图生成缩 略图,如果都没有命中,则会考虑去后台TFS集群文件存储系统上调取。因此,最终反馈到TFS集群文件存储系统上的流量已经被大大优化了。
淘宝网将图片处理与缓存编写成基于Nginx的模块,使用GraphicsMagick进行图片处理, 采用了面向小对象的缓存文件系统,前端有LVS+HA Proxy将原图和其所有的缩略图请求都调度到同一台Image Server。
在文件定位上,内存用Hash算法做索引,最多一次读盘。另外会有很多相同的图片重复上传上来,去除重复文件也是采用 Hash算法来做的。写盘方式则采用Append方式写,并采用了淘汰策略FIFO,主要考虑降低硬盘的写操作,没有必要进一步提高 Cache命中率,因为ImageServer和TFS位于同一个数据中心,读盘 效率还是非常高的。

TFS已经开源:code.taobao.org。

问题:分布式缓存问题。
办法:淘宝KV缓存系统:Tair
Tair包括缓存和持久化两种存储功能。Tair作为一个分布式系统,由一个中 心控制节点和一系列的服务节点组成,我们称中心控制节点为 Config Server,服务节点是Data Server。Config Server 负责管理所有的Data Server,维护Data Server的状态信息。Data Server 对外提供各种数据服务,并以心跳的形式将自身的状况汇报给Config Server。Config Server是控制点,而且是单点,目前采用一主一备 的形式来保证其可靠性。所有的Data Server 地位都是等价的。

Tair 的架构图: 



 Tair 部署架构图:




淘宝网架构图5.0:


12月,日均PV2.5亿。

6. 2008年 


问题:如何解决商品分类的问题?
办法:品牌、款式、材质等都可以叫做“属性”,属性是类 似Tag(标签)的一个概念,与类目相比更加离散、灵活,这样也缩减了类目的深度。
这个思想的提出一举解决了分类的难题!  并且最终成为了一个单独的服务模块:类目属性的服务(Category Server)。

问题:系统越来越臃 肿,业务的耦合性越来越高,开发的效率越来越低。
淘宝前台系统的业务量和代码量还是呈爆炸式的增长。业务方总在后面催,开发人员不够就继续招人,招来的人根本看不懂原来的业务,只好摸 索着在“合适的地方”加一些“合适的代码”,看看运行起来像那么回事后,就发布上线。
在这样的恶性循环中,系统出错的概率也逐步增长,常常是你改了商品相关的某些代码,发现交易出问题了,甚至你改了论坛上的某些代码,旺旺出问 题了。这让开发人员苦不堪言,而业务方还认为开发人员办事不力。
办法:肢解和重构系统,把复用性最高的一个模块:用户信息模块拆分出来,叫IC(User Information Center)。UIC只处理最基础的用户信息操作,例如getUserById、getUserByName等。

问题:主站系统容量已经到了瓶颈。
此时,商品数在1亿个以 上,PV在2.5亿个以上,会员数超过了5000万个。这时Oracle的连接池数量都不够用了,数据库的容量到了极限,即使上层系统加机器也无法继续扩容。
办法:只有把底层的基础服务继续拆分,从底层开始扩容,上层才能扩展,才能容纳以后三五年的增长。

把交易的底层业务拆分出来,叫交易中心(Trade Center,TC),TC只处理如创建订单、减库存、修改订单状态等原子型的操作。
把交易的上层业务拆分出来,叫交易管理(Trade Manager,TM),拍下一件普通商品要对订单、库存、物流进行操作,拍下虚拟商品不需要对物流 进行操作,这些在TM中完成。

这些拆分出来的基础服务为日后的淘宝商城的快速构建提供了良好的基础。 
最终拆分完成的架构图如下:

问题:拆分出来的各个系统之间如何交互?
办法:实时调用的中间件:高性能服务框架(HSF) + 异步消息通知的中间件:(Notify)

HSF功能
介绍
HSF旨在为淘宝的应用提供一个分布式的服务框架,HSF从分布式应用层面以及统一的发布/调用方式层面为大家提供支持,从而可以很容易地开发分布式的应用以及提供或使用公用功能模块,而不用考虑 分布式领域中的各种细节技术,例如,远程通讯、性能损耗、调 用的透明化、同步/异步调用方式的实现等问题。


HSF设计思想: 


服务调用者启动的时候向ConfigServer注册对哪些服务感兴趣(接口、版本),当服务提供者的信息变化时,ConfigServer向相应的感兴趣的服务调用者推送新的服务信息列表。
调用者在调用时则根据服务信息的列表直接访问相应的服务提供者,而无须经过 ConfigServer。
ConfigServer并不会把服务提供者的IP地址推送给服务的调用者,HSF框架会根据负载状况来选择具体的服务器,返回结果给调用者,这不仅统一了服务调用的方式,也实现了“软负载均衡”。
平时ConfigServer通过和服务提供者的心跳来感应服务提供者的存活状态。
服务集群对调用者来说是“统一”的,服务之间是“隔离”的,这保证了服务的扩展性和应用的统一性。 再加上HSF本身能提供的“软负载均衡”,服务层对应用层来说就是一片“私有云”了。
HSF框架以SAR包的方式部署到Jboss、Jetty或Tomcat下,在应用启动的时候,HSF服务随之启动。


Notify设计思想:

NotifyServer在ConfigServer上面注册消息服务,消息的客户端通过ConfigServer订阅消息服务。
某个客户端调用NotifyServer发 送一条消息,NotifyServer负责把消息发送到所有订阅这个消息的客户端。
为什么不使用现成的消息中间件?是因为发现,当消息数量上来之后,会有消息拥堵、顺序有错、消息丢失。
为了保证消息一定能发出,且对方也一定能收到,消息数据本身就需要记录下来,这些信息存放在数据库中。把要发出的通知存放到数据库中,如果 实时发送失败,再用一个时间程序来周期性地发送这些通知,系统记录下消息的中间状态和时间戳,这样保证消息一定能发出,也一定能通知到,且通知带有时间顺序,这些通知甚至可以实现事务性的操作。由于消息具有中间状态(已发送、未发送等),应用系统通过Notify可以实现分布式事务——BASE(基本可用,Basically Available、 软状态 Soft State、最终一致,Eventually Consistent)。 NotifyServer可以水平扩展,NotifyClient也可以水平扩展,数据 库也可以水平扩展,因此从理论上讲,这个消息系统的吞吐量是没有上限的,现在Notify系统每天承载了淘宝10亿次以上的消息 通知。

问题:制约系统规模的最重要的因素,数据库如何拆分?
办法:分布式数据访问层:TDDL。
原来的分库分表 + DBRoute 方案只是满足了当时的数据扩展需求,并且没有考虑其它需求。

TDDL所处的位置:

可以看出,是在JDBC之下,也就是说JDBC Driver会调用TDDL,TDDL负责与数据源交互。

TDDL实现了下面三个主要的特性:
  • 数据访问路由——将针对数据的读写请求发送到最合适的地方。
  • 数据的多向非对称复制——一次写入,多点读取。
  • 数据存储的自由扩展——不再受限于单台机器的容量瓶颈与速度瓶颈,平滑迁移。
问题:TDDL如何实现分布式Join(连接)?
在跨节点以后,简单的 Join会变成M×N台机器的合并,这个代价比原来的基于数据库的单机Join大太多了。

问题:TDDL如何实现高速多维度查询?
就像SNS中的消息系统,A发 给B一个消息,那么A要看到的是我发给所有人的消息,而B要看到的是所有人发给我的消息。这种多维度查询,如何能够做到高效快捷呢?

问题:TDDL如何实现分布式事务?
原始单机数据库中存在着大量的事务操作,在分布式以后,分布式事务的代价远远大于单机事务,那么这个矛盾也变得非常明显。

问题:用户登录系统A,然后进入系统B,登录信息如何保存?
办法:使用Session框架。

Session框架架构图:

Session框架实现了如下特性:
  • Session的客户端存储,将Session信息存储到客户端浏览器 Cookie中。
  • 实现服务端存储,减少Cookie使用,增强用户信息的安全 性,避免浏览器对Cookie数量和大小的限制。
  • Session配置统一管理起来,集中管理服务端Session和客户端 Cookie的使用情况,对Cookie的使用做有效的监管。
  • 支持动态更新,Session的配置动态更新。
问题:为什么这里还要提到用Cookie这种比较“落伍”的方式呢?
Cookie是放在客户端的,每一次HTTP请求都要提交到服务端,在访问量比较小的时候,采用Cookie避免了Session复制、硬件负载等高成本的情况。
但随着用户访问规模的提高,我们可以折算一下,一个Cookie大概是2KB的数据,也就是说,一次请求要提交到服务器的数据是网页请求数据,再加上2KB的Cookie,当有上亿个请求的时候,Cookie所带来的流量已经非常可观了, 而且网络流量的成本也越来越高。
以后采用了集中式的缓存区的Session方式。

2014年7月20日星期日

EAP_010:EJB事务超时设置

开发运行环境:JBoss EAP 6.2.0。

问题来自一个客户,需求很简单:当调用某个带事务的EJB的方法时,允许设置一个超时时间,当超过设定时间,没有得到响应时,可以捕捉到超时异常,然后进行异常处理。

1. 测试事务超时的EJB

import javax.ejb.Remote;
import javax.ejb.Stateless;


@Stateless
@Remote(RemoteTranTimeout.class)
public class TranTimeoutBean implements RemoteTranTimeout {

    @Override
    public String sayHello(String name) {
        System.out.println("======sleeping=====");
        long transBMillis = System.currentTimeMillis();
        long transEMillis = 0;
        while (true) {
            transEMillis = System.currentTimeMillis();
            if ((transEMillis - transBMillis) / 1000 >= 15) {
                break;
            }
        }
        System.out.println("======wake up=====");
        System.out.println("do someting else");
        System.out.println("end");
        return "Hello, " + name;
    }
}

实现很简单,就是sleep15秒。

2. 在META-INF目录下创建jboss-ejb3.xml,该文件和jboss.xml在同一目录。

<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
               xmlns="http://java.sun.com/xml/ns/javaee"
               xmlns:tx="urn:trans-timeout"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd
http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd
urn:trans-timeout http://www.jboss.org/j2ee/schema/trans-timeout-1_0.xsd"
               version="3.1"
               impl-version="2.0">
    <assembly-descriptor>
        <container-transaction>
            <method>
                <ejb-name>TranTimeoutBean</ejb-name>
                <method-name>*</method-name>
                <method-intf>Remote</method-intf>
            </method>
            <tx:trans-timeout>
                <tx:timeout>5</tx:timeout>
                <tx:unit>Seconds</tx:unit>
            </tx:trans-timeout>
        </container-transaction>
    </assembly-descriptor>
</jboss:ejb-jar>

这里我设置的事务超时时间是5秒。

2. 重新编译、发布、运行EJB
服务器日志如下:可以看出5秒钟后,事务管理器发现事务超时,然后回滚了该事务。

15:36:58,165 INFO  [stdout] (EJB default - 2) ======sleeping=====
15:37:03,164 WARN  [com.arjuna.ats.arjuna] (Transaction Reaper) ARJUNA012117: TransactionReaper::check timeout for TX 0:ffffc0a80067:6a0b2067:53cb6ff0:18 in state  RUN
15:37:03,166 WARN  [com.arjuna.ats.arjuna] (Transaction Reaper Worker 0) ARJUNA012095: Abort of action id 0:ffffc0a80067:6a0b2067:53cb6ff0:18 invoked while multiple threads active within it.
15:37:03,166 WARN  [com.arjuna.ats.arjuna] (Transaction Reaper Worker 0) ARJUNA012108: CheckedAction::check - atomic action 0:ffffc0a80067:6a0b2067:53cb6ff0:18 aborting with 1 threads active!
15:37:03,166 WARN  [com.arjuna.ats.arjuna] (Transaction Reaper Worker 0) ARJUNA012121: TransactionReaper::doCancellations worker Thread[Transaction Reaper Worker 0,5,main] successfully canceled TX 0:ffffc0a80067:6a0b2067:53cb6ff0:18
15:37:13,165 INFO  [stdout] (EJB default - 2) ======wake up=====
15:37:13,165 INFO  [stdout] (EJB default - 2) do someting else
15:37:13,165 INFO  [stdout] (EJB default - 2) end
15:37:13,166 ERROR [org.jboss.as.ejb3.invocation] (EJB default - 2) JBAS014134: 对组件 TranTimeoutBean 的方法 public abstract java.lang.String org.jboss.as.quickstarts.ejb.remote.stateless.RemoteTranTimeout.sayHello(java.lang.String) 的 EJB 调用失败: javax.ejb.EJBTransactionRolledbackException: Transaction rolled back
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleEndTransactionException(CMTTxInterceptor.java:138) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.endTransaction(CMTTxInterceptor.java:118) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:276) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:339) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:238) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
    at org.jboss.as.ejb3.remote.EJBRemoteTransactionPropagatingInterceptor.processInvocation(EJBRemoteTransactionPropagatingInterceptor.java:79) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
    at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
    at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
    at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:59) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
    at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50) [jboss-as-ee-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
    at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:55) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
    at org.jboss.as.ee.component.TCCLInterceptor.processInvocation(TCCLInterceptor.java:45) [jboss-as-ee-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
    at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61) [jboss-invocation-1.1.2.Final-redhat-1.jar:1.1.2.Final-redhat-1]
    at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:165) [jboss-as-ee-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler.invokeMethod(MethodInvocationMessageHandler.java:329) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler.access$100(MethodInvocationMessageHandler.java:70) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler$1.run(MethodInvocationMessageHandler.java:203) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [rt.jar:1.7.0_55]
    at java.util.concurrent.FutureTask.run(FutureTask.java:262) [rt.jar:1.7.0_55]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_55]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_55]
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_55]
    at org.jboss.threads.JBossThread.run(JBossThread.java:122)
Caused by: javax.transaction.RollbackException: JBAS014585: 事务 'TransactionImple < ac, BasicAction: 0:ffffc0a80067:6a0b2067:53cb6ff0:18 status: ActionStatus.ABORTED >' 已被回滚
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.endTransaction(CMTTxInterceptor.java:99) [jboss-as-ejb3-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
    ... 29 more

3. 注意,在standalone.xml中还有一个全局的事务超时时间,默认是300秒,即5分钟。
所有应用的事务调用时长都不能超过此设定时间。
<subsystem xmlns="urn:jboss:domain:transactions:1.4">
            <core-environment>
                <process-id>
                    <uuid/>
                </process-id>
            </core-environment>
            <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
            <coordinator-environment default-timeout="300"/>
        </subsystem>

4. 除了写在jboss-ejb3.xml中,还可以用批注的方式写在EJB的方法上

import javax.ejb.Remote;
import javax.ejb.Stateless;
import java.util.concurrent.TimeUnit;
import org.jboss.ejb3.annotation.TransactionTimeout;

@Stateless
@Remote(RemoteTranTimeout.class)
public class TranTimeoutBean implements RemoteTranTimeout {

    @Override
    @TransactionTimeout(value = 10, unit = TimeUnit.SECONDS)
    public String sayHello(String name) {
        System.out.println("======sleeping=====");
        long transBMillis = System.currentTimeMillis();
        long transEMillis = 0;
        while (true) {
            transEMillis = System.currentTimeMillis();
            if ((transEMillis - transBMillis) / 1000 >= 15) {
                break;
            }
        }
        System.out.println("======wake up=====");
        System.out.println("do someting else");
        System.out.println("end");
        return "Hello, " + name;
    }
}


参考文献:
1. http://stackoverflow.com/questions/13015280/jboss-7-1-ejb-2-1-custom-transaction-timeout-configuration
2. https://docs.jboss.org/author/display/AS7/EJB+3+Reference+Guide#EJB3ReferenceGuide-TransactionTimeout
3. https://access.redhat.com/solutions/90553

EAP_009:远程客户端如何使用JNDI调用EJB?

开发运行环境:JBoss EAP 6.2.0

本以为这个问题很简单,实际上还是费了些周折,特地总结一下。
JBoss EAP 6.x 对应社区版JBoss AS 7。

JBoss AS 6/7 与 JBoss AS 5 的调用方式不一样,这里介绍的是EAP 6(即JBoss AS 7)下的调用方式。

1. 创建jboss-ejb-client.properties文件,内容如下:

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port = 4447
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

2. 按如下JNDI规则查找EJB
(1)Stateless EJB
ejb:[app-name]/[module-name]/[distinct-name]/[bean-name]![fully-qualified-classname-of-the-remote-interface]
(2)Stateful EJB
ejb:[app-name]/[module-name]/[distinct-name]/[bean-name]![fully-qualified-classname-of-the-remote-interface]?stateful
说明如下:
(1)app-name:ear应用的名字,如果不是ear格式,此项为空。
(2)module-name:jar或war的名字,该名字可以在ejb-jar.xml中重新定义。
(3)distinct-name:可以定义一个唯一的名字,如果没定义,此项为空。
(4)bean-name:实现接口的EJB类名。
(5)fully-qualified-classname-of-the-remote-interface:接口的全限定路径名+类名。

具体例子可以参考JBoss EAP 6.2的quickstarts中的ejb-remote例子。

参考文献:
1. https://docs.jboss.org/author/displa/AS72/EJB+invocations+from+a+remote+client+using+JNDI
2. http://bbs.csdn.net/topics/380264639
3. http://k1280000.iteye.com/blog/1654740


2014年7月18日星期五

JDG_001:Data Grid 6.3 新特性

JBoss Data Grid 6.3 今日(2014-07-18)发布,主要有以下新特性:

1. 安全

1.1 认证
(1)Client-Server 模式:Hot Rod 协议使用 SASL(Simple Authentication and Security Layer)框架,当用户访问带安全的网格时需要先通过认证。
(2)Library 模式:用户的认证是由应用所在的容器负责的。

1.2. 授权:基于角色的访问控制(Role-based Access Control)
认证通过的用户,根据其所属的角色来决定对哪些缓存可以进行哪些操作。
Library 模式和 Client-Server 模式都支持 RBAC。

1.3. 缓存节点的认证与授权
为了保护数据不被非法访问,只有通过认证和授权的缓存节点才可以加入集群。
Library 模式和 Client-Server 模式都支持此特性。

1.4. 集群中的节点之间的通信加密。
用户可以自定义加密算法,只要符合JCA(Java Cryptography Architecture)规范。
Library 模式和 Client-Server 模式都支持此特性。
JDG 6.2 中通信加密使用的是 TLS/SSL。

2. Map/Reduce 增强
最终的计算结果现在可以保存在网格中,JDG 6.3 以前只能返回调用程序。
节点并行计算效率有所增强,中间结果的处理有所增强。

3. JBoss EAP Module
只需要在应用的 manifest文件中指向 JDG 的库包即可,不用把这些Jar包拷贝到应用中。

4. 支持 Apache Karaf

4.1 Client-Server 模式:Hot Rod Client 支持 Apache Karaf 2.3 /3.0
这意味着可以在 Jboss Fuse 中远程使用JDG。

4.2 Library 模式:支持 Apache Karaf 2.3 /3.0
这意味着可以在 Jboss Fuse 中以内嵌方式使用JDG,并且支持事务。
但是不支持Querying 和 JPA Cache Store。

5. Hot Rod 协议新增 C# Client

6. JPA Cache Store
Library 模式新增JPA Cache Store,可以按关系型数据库 Schema 保存数据结构。

7. 支持远程查询

8. 支持Oracle Weblogic 12c

2014年7月16日星期三

EAP_008:部署DayTrader应用

开发运行环境:JBoss EAP 6.2.0 + DayTrader 3.0

DayTrader 是一个端到端 Web 应用程序,非常适合做应用服务器的Benchmark测试。
DayTrader 是根据一个在线股票代理建模的基准测试应用程序。该应用程序能够使用户登录、查看其股票投资组合、查找股票报价,以及买进或卖出股票。
通过借助一个基于 Web 的负载驱动器,由 DayTrader 提供的真实工作负载可以被用于衡量和比较不同供应商提供的 Java EE 应用服务器的性能。
该应用程序还包含了一组原型(primitive),用于对不同 Java EE 组件和常见设计模式进行功能和性能测试。
最新的DayTrader版本是3.0,是针对Java EE 6标准开发设计的,总共包括24个测试用例。

DayTrader 3.0 下载地址:https://github.com/gvijayar/daytrader。
使用 git 克隆到本地:git clone git@github.com:gvijayar/daytrader.git 。

1. 使用Maven构建DayTrader
下载源码后,进入daytrader目录,运行:mvn clean install。

2. 修改standalone-full.xml,修改内容如下:
(1)datasources subsystem部分修改如下:
以Derby数据库为例,
<subsystem xmlns="urn:jboss:domain:datasources:1.1">
            <datasources>
                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
                    <driver>h2</driver>
                    <security>
                        <user-name>sa</user-name>
                        <password>sa</password>
                    </security>
                </datasource>
                <datasource jndi-name="java:jboss/datasources/TradeDataSource" pool-name="jdbc/TradeDataSource" enabled="true" use-ccm="false">
                    <connection-url>jdbc:derby://localhost:1527/daytraderDB;create=true</connection-url>
                    <driver>org.apache.derby</driver>
                    <security>
                        <user-name>demo</user-name>
                        <password>demo</password>
                    </security>
                    <validation>
                        <validate-on-match>false</validate-on-match>
                        <background-validation>false</background-validation>
                    </validation>
                    <statement>
                        <share-prepared-statements>false</share-prepared-statements>
                    </statement>
                </datasource>
                <datasource jndi-name="java:jboss/datasources/NoTxTradeDataSource" pool-name="jdbc/NoTxTradeDataSource" enabled="true" use-ccm="false">
                    <connection-url>jdbc:derby://localhost:1527/daytraderDB;create=true</connection-url>
                    <driver>org.apache.derby</driver>
                    <security>
                        <user-name>demo</user-name>
                        <password>demo</password>
                    </security>
                    <validation>
                        <validate-on-match>false</validate-on-match>
                        <background-validation>false</background-validation>
                    </validation>
                    <statement>
                        <share-prepared-statements>false</share-prepared-statements>
                    </statement>
                </datasource>
                <drivers>
                    <driver name="h2" module="com.h2database.h2">
                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                    </driver>
                    <driver name="org.apache.derby" module="org.apache.derby">
                        <xa-datasource-class>org.apache.derby.jdbc.ClientXADataSource</xa-datasource-class>
                    </driver>
                </drivers>
            </datasources>
        </subsystem>

详细步骤请参考《配置Derby数据源》。

以MySQL数据库为例,
<subsystem xmlns="urn:jboss:domain:datasources:1.1">
            <datasources>
                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
                    <driver>h2</driver>
                    <security>
                        <user-name>sa</user-name>
                        <password>sa</password>
                    </security>
                </datasource>
                <datasource jndi-name="java:jboss/datasources/TradeDataSource" pool-name="jdbc/TradeDataSource" enabled="true" use-ccm="false">
                    <connection-url>jdbc:mysql://localhost:3306/demo</connection-url>
                    <driver>mysql</driver>
                    <security>
                        <user-name>root</user-name>
                        <password>welcome1</password>
                    </security>
                </datasource>
                <datasource jndi-name="java:jboss/datasources/NoTxTradeDataSource" pool-name="jdbc/NoTxTradeDataSource" enabled="true" use-ccm="false">
                    <connection-url>jdbc:mysql://localhost:3306/demo</connection-url>
                    <driver>mysql</driver>
                    <security>
                        <user-name>root</user-name>
                        <password>welcome1</password>
                    </security>
                </datasource>
                <drivers>
                    <driver name="h2" module="com.h2database.h2">
                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                    </driver>
                    <driver name="mysql" module="com.mysql">
                        <driver-class>com.mysql.jdbc.Driver</driver-class>
                        <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
                    </driver>
                </drivers>
            </datasources>
        </subsystem>

详细步骤请参考《配置MySQL数据源》。

以Oracle数据库为例,
<subsystem xmlns="urn:jboss:domain:datasources:1.1">
            <datasources>
                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
                    <driver>h2</driver>
                    <security>
                        <user-name>sa</user-name>
                        <password>sa</password>
                    </security>
                </datasource>
                <datasource jndi-name="java:jboss/datasources/TradeDataSource" pool-name="jdbc/TradeDataSource" enabled="true" use-ccm="false">
                    <connection-url>jdbc:oracle:thin:@192.168.0.104:1521:XE</connection-url>
                    <driver>oracle</driver>
                    <security>
                        <user-name>demo</user-name>
                        <password>demo</password>
                    </security>
                </datasource>
                <datasource jndi-name="java:jboss/datasources/NoTxTradeDataSource" pool-name="jdbc/NoTxTradeDataSource" enabled="true" use-ccm="false">
                    <connection-url>jdbc:oracle:thin:@192.168.0.104:1521:XE</connection-url>
                    <driver>oracle</driver>
                    <security>
                        <user-name>demo</user-name>
                        <password>demo</password>
                    </security>
                </datasource>
                <drivers>
                    <driver name="h2" module="com.h2database.h2">
                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                    </driver>
                    <driver name="oracle" module="com.oracle">
                        <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
                    </driver>
                </drivers>
            </datasources>
        </subsystem>
详细步骤请参考《配置Oracle数据源》。
注意:别忘了修改上面配置中的Oracle数据库所在的IP地址。
还要修改 /u01/app/oracle/product/11.2.0/xe/network/admin中的listener.ora和tnsnames.ora中的IP地址,并重启数据库。

(2)因为用到了Queue和Topic,修改messaging subsystem如下:
<subsystem xmlns="urn:jboss:domain:messaging:1.4">
            <hornetq-server>
……
<jms-destinations>
                    <jms-queue name="jms/TradeBrokerQueue">
                        <entry name="java:jboss/jms/TradeBrokerQueue"/>
                        <durable>false</durable>
                    </jms-queue>
                    <jms-topic name="jms/TradeStreamerTopic">
                        <entry name="java:jboss/jms/TradeStreamerTopic"/>
                    </jms-topic>
                </jms-destinations>
 </hornetq-server>
        </subsystem>

3. 启动Derby/Oracle/MySQL数据库
(1)启动Derby
         cd [derby_home]/bin
         ./startNetworkServer
(2)启动Oracle (RHEL 6.5环境下)
          # service oracle-xe start/stop/restart
(3)启动MySQL
         MAC 环境下,
         cd /usr/local/mysql/bin
         启动:sudo ./mysqld_safe
         停止:sudo ./mysqld_safe stop 
         RHEL 环境下,
         # service mysql start/stop/restart

4. 启动JBoss EAP,确认没有报任何错

5. 部署daytrader-ear-3.0.0.ear,Enable,确认没有报任何错

6. 访问http://localhost:8080/daytrader/,点击Configuration,然后
(1)(Re)-create  DayTrader Database Tables and Indexes,重新创建表和索引。
(2)(Re)-populate  DayTrader Database,重新插入数据。
(3)访问:http://localhost:8080/daytrader/scenario
如果想要最"干净"的数据,可以点击 Reset DayTrader (to be done before each run),然后重新执行(1)(2)(3)。

7. 问题
(1)测试用例 PingJDBCRead,出现NullPointException。
经过Debug,修改了如下代码:PingJDBCRead.java, 在78行之后增加如下判断:
# 78行 quoteData = trade.getQuote(symbol);
                if (quoteData != null) {
                        break;
                }

(2)测试用例 PingJDBCWrite,出现NullPointException。
经过Debug,修改了如下代码:PingJDBCRead.java, 在73行之后增加如下判断: 
# 73行   quoteData = trade.updateQuotePriceVolumeInt(symbol, newPrice, 100.0, false);
            if (quoteData != null) {
                        break;
            }

如果(1)(2)还报错,请重新创建表和索引,并重新插入数据,然后在测试。

(3) 测试用例 PingServlet2Session2JDBC,出现NullPointException。
经过Debug,修改了如下代码:PingServlet2Session2JDBC.java, 在75行之后增加如下判断:
#75行 quoteData = directSLSBRemote.getQuote(symbol);
                    if (quoteData != null) {
                        break;
                    }
同时修改了代码:TradeJEEDirect.java,注释了 1856行代码://conn.setAutoCommit(false);
如果不注释该行代码,会有异常发生,导致conn返回null。

(4)测试用例 PingServlet2TwoPhase,出现NullPointException。
经过Debug,修改了如下代码:PingServlet2TwoPhase.java, 在74行之后增加如下判断:
#74行  quoteData = tradeSLSBRemote.pingTwoPhase(symbol);
                    if (quoteData != null) {
                        break;
                    }

(5)java.sql.SQLException: You cannot rollback with autocommit set!
如果出现上面这个错误,需要把 TradeJEEDirect.java的1856行代码取消注释:conn.setAutoCommit(false);

参考文献:
1. http://www.ibm.com/developerworks/cn/opensource/os-perfbenchmk/index.html
2. http://www.ibm.com/developerworks/cn/cloud/library/1310_xiali_daytrader/index.html
3. http://www.ibm.com/developerworks/websphere/techjournal/1208_hare/1208_hare.html

EAP_007:配置Derby数据源

开发运行环境:JBoss EAP 6.2.0 + Derby 10.10.2.0

1. 在[jboss_home]/modules目录下,创建目录:org/apache/derby/main

2. 在main目录下创建module.xml,内容如下:

<?xml version=“1.0” encoding=“UTF-8”?>
<module xmlns=“urn:jboss:module:1.0” name=“org.apache.derby”>
    <resources>
        <resource-root path=“derbyclient.jar”/>
    </resources>
    <dependencies>
        <module name=“javax.api”/>
        <module name=“javax.transaction.api”/>
    </dependencies>
</module>

3. 修改standalone.xml,其中datasources subsystem部分修改如下:

 <subsystem xmlns=“urn:jboss:domain:datasources:1.1”>
            <datasources>
                <datasource jndi-name=“java:jboss/datasources/ExampleDS” pool-name=“ExampleDS” enabled=“true” use-java-context=“true”>
                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
                    <driver>h2</driver>
                    <security>
                        <user-name>sa</user-name>
                        <password>sa</password>
                    </security>
                </datasource>
                <datasource jndi-name=“java:jboss/datasources/DerbyDSDemo” pool-name=“DerbyDSDemoPool” enabled=“true” use-ccm=“false”>
                    <connection-url>jdbc:derby://localhost:1527/demoDB;create=true</connection-url>
                    <driver>org.apache.derby</driver>
                    <security>
                        <user-name>demo</user-name>
                        <password>demo</password>
                    </security>
                    <validation>
                        <validate-on-match>false</validate-on-match>
                        <background-validation>false</background-validation>
                    </validation>
                    <statement>
                        <share-prepared-statements>false</share-prepared-statements>
                    </statement>
                </datasource>
                <drivers>
                    <driver name=“h2” module=“com.h2database.h2”>
                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                    </driver>
                    <driver name=“org.apache.derby” module=“org.apache.derby”>
                        <xa-datasource-class>org.apache.derby.jdbc.ClientXADataSource</xa-datasource-class>
                    </driver>
                </drivers>
            </datasources>
        </subsystem>

4. 复制derbyclient.jar到main目录下

参考文献:
1. http://www.hameister.org/JBoss_DatasourceDerby.html
2. http://db.apache.org/derby/integrate/SQuirreL_Derby.html
3. http://www.squirrelsql.org/index.php#installation

EAP_006:配置MySQL数据源

开发运行环境:JBoss EAP 6.2.0 + MySQL 5.6.19

1. 在[jboss_home]/modules目录下,创建目录:com/mysql/main

2. 在main目录下创建module.xml,内容如下:

<?xml version=“1.0” encoding=“UTF-8”?>
<module xmlns=“urn:jboss:module:1.1” name=“com.mysql”>
    <resources>
        <resource-root path=“mysql-connector-java-5.1.31-bin.jar”/>
    </resources>
    <dependencies>
        <module name=“javax.api”/>
        <module name=“javax.transaction.api”/>
    </dependencies>
</module>

说明:MySQL的JDBC jar包可以从这里下载:http://dev.mysql.com/downloads/connector/j/。

3. 修改standalone.xml,其中datasources subsystem部分修改如下:

 <subsystem xmlns=“urn:jboss:domain:datasources:1.1”>
            <datasources>
                <datasource jndi-name=“java:jboss/datasources/ExampleDS” pool-name=“ExampleDS” enabled=“true” use-java-context=“true”>
                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
                    <driver>h2</driver>
                    <security>
                        <user-name>sa</user-name>
                        <password>sa</password>
                    </security>
                </datasource>
                <datasource jndi-name=“java:jboss/datasources/MysqlDSDemo” pool-name=“MysqlDSDemoPool” enabled=“true”>
                    <connection-url>jdbc:mysql://localhost:3306/demo</connection-url>
                    <driver>mysql</driver>
                    <security>
                        <user-name>root</user-name>
                        <password>welcome1</password>
                    </security>
                </datasource>
                <drivers>
                    <driver name=“h2” module=“com.h2database.h2”>
                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                    </driver>
                    <driver name=“mysql” module=“com.mysql”>
                        <driver-class>com.mysql.jdbc.Driver</driver-class>
                        <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
                    </driver>
                </drivers>
            </datasources>
        </subsystem>

4. 复制mysql-connector-java-5.1.31-bin.jar到main目录下

参考文献:
1. http://blog.csdn.net/kylinsoong/article/details/17042245
2. https://community.jboss.org/message/866635

EAP_005:配置Oracle数据源

开发运行环境:JBoss EAP 6.2.0 + Oracle Database XE 11gR2

1. 在[jboss_home]/modules目录下,创建目录:com/oracle/main

2. 在main目录下创建module.xml,内容如下:

 <?xml version=“1.0” encoding=“UTF-8”?>
<module xmlns=“urn:jboss:module:1.1” name=“com.oracle”>
    <resources>
        <resource-root path=“ojdbc6.jar”/>
    </resources>
    <dependencies>
        <module name=“javax.api”/>
        <module name=“javax.transaction.api”/>
    </dependencies>
</module>

3. 修改standalone.xml,其中datasources subsystem部分修改如下:

 <subsystem xmlns=“urn:jboss:domain:datasources:1.1”>
            <datasources>
                <datasource jndi-name=“java:jboss/datasources/ExampleDS” pool-name=“ExampleDS” enabled=“true” use-java-context=“true”>
                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
                    <driver>h2</driver>
                    <security>
                        <user-name>sa</user-name>
                        <password>sa</password>
                    </security>
                </datasource>
                <datasource jndi-name=“java:jboss/datasources/OracleDSDemo” pool-name=“OracleDSDemoPool” enabled=“true”>
                    <connection-url>jdbc:oracle:thin:@10.66.192.109:1521:XE</connection-url>
                    <driver>oracle</driver>
                    <security>
                        <user-name>demo</user-name>
                        <password>demo</password>
                    </security>
                </datasource>
                <drivers>
                    <driver name=“h2” module=“com.h2database.h2”>
                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                    </driver>
                    <driver name=“oracle” module=“com.oracle”>
                        <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
                    </driver>
                </drivers>
            </datasources>
        </subsystem>

4. 复制ojdbc6.jar到main目录下

参考文献:
1. http://blog.csdn.net/kylinsoong/article/details/12340101

2014年7月15日星期二

MAC_017:安装和使用MySQL

开发运行环境:MAC OS X 10.9.4 + MySQL 5.6.19

我下载的是压缩包:mysql-5.6.19-osx10.7-x86_64.tar.gz,之所以没有使用.dmg格式的安装包,是因为卸载时比较麻烦。

1. tar -xzvf mysql-5.6.19-osx10.7-x86_64.tar.gz

2. sudo mv mysql-5.1.45-osx10.6-x86_64 /usr/local/mysql

3. cd /usr/local

4. sudo chown -R mysql:mysql mysql

5. cd mysql

6. 安装数据库:sudo scripts/mysql_install_db --user=mysql

7. sudo chown -R root .

8. sudo chown -R mysql data

9. 修改/etc/profile文件,把/usr/local/mysql/bin加到PATH路径中。

10. cd bin

11. 启动MySQL:sudo ./mysqld_safe

12. 修改root密码:sudo ./mysql_secure_installation
root密码默认为空,不太安全,根据提示酌情配置。

13. sudo ./mysql -u root -p
输入刚才设置的root密码来登录mysql。

14. 停止MySQL:sudo ./mysqld_safe stop

为了以后对比和查看,我把第6步的详细输出复制如下:

Installing MySQL system tables...2014-07-15 09:31:48 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2014-07-15 09:31:48 18180 [Note] InnoDB: Using atomics to ref count buffer pool pages
2014-07-15 09:31:48 18180 [Note] InnoDB: The InnoDB memory heap is disabled
2014-07-15 09:31:48 18180 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2014-07-15 09:31:48 18180 [Note] InnoDB: Compressed tables use zlib 1.2.3
2014-07-15 09:31:48 18180 [Note] InnoDB: Using CPU crc32 instructions
2014-07-15 09:31:48 18180 [Note] InnoDB: Initializing buffer pool, size = 128.0M
2014-07-15 09:31:48 18180 [Note] InnoDB: Completed initialization of buffer pool
2014-07-15 09:31:48 18180 [Note] InnoDB: The first specified data file ./ibdata1 did not exist: a new database to be created!
2014-07-15 09:31:48 18180 [Note] InnoDB: Setting file ./ibdata1 size to 12 MB
2014-07-15 09:31:48 18180 [Note] InnoDB: Database physically writes the file full: wait...
2014-07-15 09:31:48 18180 [Note] InnoDB: Setting log file ./ib_logfile101 size to 48 MB
2014-07-15 09:31:48 18180 [Note] InnoDB: Setting log file ./ib_logfile1 size to 48 MB
2014-07-15 09:31:48 18180 [Note] InnoDB: Renaming log file ./ib_logfile101 to ./ib_logfile0
2014-07-15 09:31:48 18180 [Warning] InnoDB: New log files created, LSN=45781
2014-07-15 09:31:48 18180 [Note] InnoDB: Doublewrite buffer not found: creating new
2014-07-15 09:31:48 18180 [Note] InnoDB: Doublewrite buffer created
2014-07-15 09:31:48 18180 [Note] InnoDB: 128 rollback segment(s) are active.
2014-07-15 09:31:48 18180 [Warning] InnoDB: Creating foreign key constraint system tables.
2014-07-15 09:31:48 18180 [Note] InnoDB: Foreign key constraint system tables created
2014-07-15 09:31:48 18180 [Note] InnoDB: Creating tablespace and datafile system tables.
2014-07-15 09:31:48 18180 [Note] InnoDB: Tablespace and datafile system tables created.
2014-07-15 09:31:48 18180 [Note] InnoDB: Waiting for purge to start
2014-07-15 09:31:48 18180 [Note] InnoDB: 5.6.19 started; log sequence number 0
2014-07-15 09:31:49 18180 [Note] Binlog end
2014-07-15 09:31:49 18180 [Note] InnoDB: FTS optimize thread exiting.
2014-07-15 09:31:49 18180 [Note] InnoDB: Starting shutdown...
2014-07-15 09:31:50 18180 [Note] InnoDB: Shutdown completed; log sequence number 1625977
OK

Filling help tables...2014-07-15 09:31:50 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2014-07-15 09:31:50 18185 [Note] InnoDB: Using atomics to ref count buffer pool pages
2014-07-15 09:31:50 18185 [Note] InnoDB: The InnoDB memory heap is disabled
2014-07-15 09:31:50 18185 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2014-07-15 09:31:50 18185 [Note] InnoDB: Compressed tables use zlib 1.2.3
2014-07-15 09:31:50 18185 [Note] InnoDB: Using CPU crc32 instructions
2014-07-15 09:31:50 18185 [Note] InnoDB: Initializing buffer pool, size = 128.0M
2014-07-15 09:31:50 18185 [Note] InnoDB: Completed initialization of buffer pool
2014-07-15 09:31:50 18185 [Note] InnoDB: Highest supported file format is Barracuda.
2014-07-15 09:31:50 18185 [Note] InnoDB: 128 rollback segment(s) are active.
2014-07-15 09:31:50 18185 [Note] InnoDB: Waiting for purge to start
2014-07-15 09:31:50 18185 [Note] InnoDB: 5.6.19 started; log sequence number 1625977
2014-07-15 09:31:50 18185 [Note] Binlog end
2014-07-15 09:31:50 18185 [Note] InnoDB: FTS optimize thread exiting.
2014-07-15 09:31:50 18185 [Note] InnoDB: Starting shutdown...
2014-07-15 09:31:51 18185 [Note] InnoDB: Shutdown completed; log sequence number 1625987
OK

To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system

PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:

  ./bin/mysqladmin -u root password 'new-password'
  ./bin/mysqladmin -u root -h MaPingdeMacBook-Pro.local password 'new-password'

Alternatively you can run:

  ./bin/mysql_secure_installation

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

See the manual for more instructions.

You can start the MySQL daemon with:

  cd . ; ./bin/mysqld_safe &

You can test the MySQL daemon with mysql-test-run.pl

  cd mysql-test ; perl mysql-test-run.pl

Please report any problems at http://bugs.mysql.com/

The latest information about MySQL is available on the web at

  http://www.mysql.com

Support MySQL by buying support/licenses at http://shop.mysql.com

New default config file was created as ./my.cnf and
will be used by default by the server when you start it.
You may edit this file to change server settings

参考文献:
1. http://blog.csdn.net/mr_von/article/details/6169396
2. http://blog.csdn.net/mr_von/article/details/6169394
3. http://blog.csdn.net/mr_von/article/details/6169397
4. http://dev.mysql.com/doc/refman/5.1/en/binary-installation.html

2014年7月14日星期一

Architect_013:视频网站的架构(摘录+整理)

视频网站架构分为两个部分:视频内容的准备和交付。

1. 视频内容的准备



(1)Service Manager:视频服务管理平台,所有的视频服务功能都在这里。
可以使用自己擅长的语言开发:Python, PHP, NodeJS, Java, Perl,也可以使用第三方的平台:Kaltura、MediaDrop、ViMP。
(2)Service Bus:所有的服务请求都通过消息发送到服务总线上。
因为大多数视频服务功能都比较耗时,比如转码等,因此使用异步通讯方式最合适。
这里的服务总线是广义的,不一定特指某个企业服务总线产品,消息中间件也行,比如ActiveMQ、ZeroMQ、Gearman、RabbitMQ。
(3)Service Worker:视频服务工作者,即工作线程。每个工作者都有自己擅长的工作:上传、打包、转码(使用自己擅长的语言开发:Python, PHP, NodeJS, Java, Perl,也可以使用第三方包:transcoder)、加广告、下载、传送(使用FTP、SCP、HTTP协议)等等。
(4)Local Storage Area:保存视频的元数据,可以使用关系型数据库,如MySQL,也可以使用NoSQL,如Redis。
(5)Delivery Storage:保存视频资料。
 
2. 视频内容的交付

(1)视频资料已经保存在Delivery Storage,接下来需要基于HTTP协议流化这些视频内容(HDS、HLS、Smooth Streaming)。
(2)HTTP Web服务器:Apache,NGinx,Lighttpd 和不同视频流插件。
(3)媒体服务器 : Red5,MistServer。
(4)Varnish:作为Web缓存。

参考文献:
1. http://www.jdon.com/45577
2. http://www.alkannoide.com/2013/07/05/how-to-create-and-architecture-an-open-source-andor-free-video-platform/
3. http://www.alkannoide.com/2013/04/18/mistserver-optimize-the-http-delivery-via-caching/
4. http://blog.csdn.net/fenglibing/article/details/10457837
5. http://www.open-open.com/lib/view/open1346511794881.html