paulwong

#

ehcache configuration (cluster env)

 <ehcache>

    
<!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path 
-->
    
<diskStore path="java.io.tmpdir/service"/>

    
<cacheManagerPeerProviderFactory
        
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
        properties
="peerDiscovery=automatic, multicastGroupAddress=230.0.0.3,
        multicastGroupPort=4446, timeToLive=0"
/>
   
    
<cacheManagerPeerListenerFactory
        
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
        properties
="hostName=, port=40003,
        socketTimeoutMillis=12000"
/>
                   
    
<!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required:

        maxInMemory
          - Sets the maximum number of objects that will be created in memory

        eternal
          - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element is never expired.
        
          overflowToDisk
          - Sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit.

        The following attributes are optional:
        timeToIdleSeconds              - Sets the time to idle for an element before it expires.
                                         i.e. The maximum amount of time between accesses before an element expires
                                         Is only used if the element is not eternal.
                                         Optional attribute. A value of 0 means that an Element can idle for infinity.
                                         The default value is 0.
        timeToLiveSeconds              - Sets the time to live for an element before it expires.
                                         i.e. The maximum time between creation time and when an element expires.
                                         Is only used if the element is not eternal.
                                         Optional attribute. A value of 0 means that and Element can live for infinity.
                                         The default value is 0.
        diskPersistent                 - Whether the disk store persists between restarts of the Virtual Machine.
                                         The default value is false.
        diskExpiryThreadIntervalSeconds- The number of seconds between runs of the disk expiry thread. The default value
                                         is 120 seconds.
        
-->
   
    
<defaultCache
        
maxElementsInMemory="1000000000"
        eternal
="true"
        overflowToDisk
="false"
        diskPersistent
="false"
        memoryStoreEvictionPolicy
="LRU">
        
<cacheEventListenerFactory
            
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
            properties
="replicateAsynchronously=true, replicatePuts=true replicateUpdates=true replicateUpdatesViaCopy=true replicateRemovals=true asynchronousReplicationIntervalMillis=1000"/>
    
</defaultCache>
   
    
<cache name="com.ubs.swidGLK.METHOD_CACHE"
        maxElementsInMemory
="10000"
        eternal
="true"
        overflowToDisk
="false"
        diskPersistent
="false"
        memoryStoreEvictionPolicy
="LRU">
        
<cacheEventListenerFactory
            
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
    
</cache>
</ehcache>

http://www.oschina.net/question/12_3984

posted @ 2012-01-23 23:22 paulwong 阅读(336) | 评论 (0)编辑 收藏

由12306.cn谈谈网站性能技术

12306.cn网站挂了,被全国人民骂了。我这两天也在思考这个事,我想以这个事来粗略地和大家讨论一下网站性能的问题。因为仓促,而且完全基于 本人有限的经验和了解,所以,如果有什么问题还请大家一起讨论和指正。(这又是一篇长文,只讨论性能问题,不讨论那些UI,用户体验,或是是否把支付和购 票下单环节分开的功能性的东西)

业务

任何技术都离不开业务需求,所以,要说明性能问题,首先还是想先说说业务问题。
  • 其一有人可能把这个东西和QQ或是网游相比。但我觉得这两者是不一样的,网游和QQ在线或是登录时访问的更多的是用户自己的数据,而订票系统访问的是中心的票量数据,这是不一样的。不要觉得网游或是QQ能行你就以为这是一样的。网游和QQ 的后端负载相对于电子商务的系统还是简单。
  • 其二有人说春节期间订火车的这个事好像网站的秒杀活动。的确很相似, 但 是如果你的思考不在表面的话,你会发现这也有些不一样。火车票这个事,还有很多查询操作,查时间,查座位,查铺位,一个车次不 行,又查另一个车次,其伴随着大量的查询操作,下单的时候需要对数据库操作。而秒杀,直接杀就好了。另外,关于秒杀,完全可以做成只接受前N个用户的请求 (完全不操作后端的任何数据, 仅仅只是对用户的下单操作log),这种业务,只要把各个服务器的时间精确同步了就可以了,无需在当时操作任何数据库。可以订单数够后,停止秒杀,然后批 量写数据库。火车票这个岂止是秒杀那么简单。能不能买到票得当时告诉用户啊。
  • 其三有人拿这个系统和奥运会的票务系统比较。我觉得还是不一样。虽然奥运会的票务系统当年也一上线就废了。但是奥运会用的是抽奖的方式,也就是说不存在先来先得的抢的方式,而且,是事后抽奖,事前只需要收信息,事前不需要保证数据一致性,没有锁,很容易水平扩展。
  • 其四订票系统应该和电子商务的订单系统很相似,都是需要对库存进 行:1)占住库存,2)支付(可选),3)扣除库存的操作。这个是需要有一致性的检查的,也就是在并发时需要对数据加锁的。B2C的电商基本上都会把这个 事干成异步的,也就是说,你下的订单并不是马上处理的,而是延时处理的,只有成功处理了,系统才会给你一封确认邮件说是订单成功。我相信有很多朋友都收到 认单不成功的邮件。这就是说,数据一致性在并发下是一个瓶颈
  • 其五铁路的票务业务很变态,其采用的是突然放票,而有的票又远远不够 大家分,所以,大家才会有抢票这种有中国特色的业务的做法。于是当票放出来的时候,就会有几百万人甚至上千万人杀上去,查询,下单。几十分钟内,一个网站 能接受几千万的访问量,这个是很恐怖的事情。据说12306的高峰访问是10亿PV,集中在早8点到10点,每秒PV在高峰时上千万。
多说几句:
  • 库存是B2C的恶梦,库存管理相当的复杂。不信,你可以问问所有传统和电务零售业的企业,看看他们管理库存是多么难的一件事。不然,就不会有那么多人在问凡客的库存问题了。(你还可以看看《乔布斯传》,你就知道为什么Tim会接任Apple的CEO了,因为他搞定了苹果的库存问题)
  • 对于一个网站来说,浏览网页的高负载很容易搞定,查询的负载有一定的难度去处理,不过还是可以通过缓存查询结果来搞定,最难的就是下单的负载。因为要访问库存啊,对于下单,基本上是用异步来搞定的。去年双11节,淘宝的每小时的订单数大约在60万左右,京东一天也才能支持40万(居然比12306还差),亚马逊5年前一小时可支持70万订单量。可见,下订单的操作并没有我们相像的那么性能高。
  • 淘宝要比B2C的网站要简单得多,因为没有仓库,所以,不存在像B2C这样有N个仓库对同一商品库存更新和 查 询的操作。下单的时候,B2C的 网站要去找一个仓库,又要离用户近,又要有库存,这需要很多计算。试想,你在北京买了一本书,北京的仓库没货了,就要从周边的仓库调,那就要去看看沈阳或 是西安的仓库有没有货,如果没有,又得看看江苏的仓库,等等。淘宝的就没有那么多事了,每个商户有自己的库存,库存分到商户头上了,反而有利于性能。
  • 数据一致性才是真正的性能瓶颈。有 人说nginx可以搞定每秒10万的静态请求,我不怀疑。但这只是静态请求,理论值,只要带宽、I/O够强,服务器计算能力够,并支持的并发连接数顶得住 10万TCP链接的建立 的话,那没有问题。但在数据一致性面前,这10万就完完全全成了一个可望不可及的理论值了。
我说那么多,我只是想从业务上告诉大家,我们需要从业务上真正了解春运铁路订票这样业务的变态之处。

前端性能优化技术

要解决性能的问题,有很多种常用的方法,我在下面列举一下,我相信12306这个网站使用下面的这些技术会让其性能有质的飞跃。
一、前端负载均衡
通过DNS的负载均衡器(一般在路由器上根据路由的负载重定向)可以把用户的访问均匀地分散在多个Web服务器上。这样可以减少Web服务器的请求 负载。因为http的请求都是短作业,所以,可以通过很简单的负载均衡器来完成这一功能。最好是有CDN网络让用户连接与其最近的服务器(CDN通常伴随 着分布式存储)。(关于负载均衡更为详细的说明见“后端的负载均衡”)
二、减少前端链接数
我看了一下12306.cn,打开主页需要建60多个HTTP连接,车票预订页面则有70多个HTTP请求,现在的浏览器都是并发请求的。所以,只 要有100万个用户,就会有6000万个链接,太多了。一个登录查询页面就好了。把js打成一个文件,把css也打成一个文件,把图标也打成一个文件,用 css分块展示。把链接数减到最低。
三、减少网页大小增加带宽
这个世界不是哪个公司都敢做图片服务的,因为图片太耗带宽了。现在宽带时代很难有人能体会到当拨号时代做个图页都不敢用图片的情形(现在在手机端浏 览也是这个情形)。我查看了一下12306首页的需要下载的总文件大小大约在900KB左右,如果你访问过了,浏览器会帮你缓存很多,只需下载10K左右 的文件。但是我们可以想像一个极端一点的案例,1百万用户同时访问,且都是第一次访问,每人下载量需要1M,如果需要在120秒内返回,那么就需要,1M * 1M /120 * 8 = 66Gbps的带宽。很惊人吧。所以,我估计在当天,12306的阻塞基本上应该是网络带宽,所以,你可能看到的是没有响应。后面随着浏览器的缓存帮助 12306减少很多带宽占用,于是负载一下就到了后端,后端的数据处理瓶颈一下就出来。于是你会看到很多http 500之类的错误。这说明服务器垮了。
四、前端页面静态化
静态化一些不觉变的页面和数据,并gzip一下。还有一个并态的方法是把这些静态页面放在/dev/shm下,这个目录就是内存,直接从内存中把文件读出来返回,这样可以减少昂贵的磁盘I/O。
五、优化查询
很多人查询都是在查一样的,完全可以用反向代理合并这些并发的相同的查询。这样的技术主要用查询结果缓存来实现,第一次查询走数据库获得数据,并把 数据放到缓存,后面的查询统统直接访问高速缓存。为每个查询做Hash,使用NoSQL的技术可以完成这个优化。(这个技术也可以用做静态页面) 对于火车票量的查询,个人觉得不要显示数字,就显示一个“有”或“无”就好了,这样可以大大简化系统复杂度,并提升性能。
六、缓存的问题
缓存可以用来缓存动态页面,也可以用来缓存查询的数据。缓存通常有那么几个问题: 1)缓存的更新。也叫缓存和数据库的同步。有这么几种方法,一是缓存time out,让缓存失效,重查,二是,由后端通知更新,一量后端发生变化,通知前端更新。前者实现起来比较简单,但实时性不高,后者实现起来比较复杂 ,但实时性高。 2)缓存的换页。内存可能不够,所以,需要把一些不活跃的数据换出内存,这个和操作系统的内存换页和交换内存很相似。FIFO、LRU、LFU都是比较经典的换页算法。相关内容参看Wikipeida的缓存算法。 3)缓存的重建和持久化。缓存在内存,系统总要维护,所以,缓存就会丢失,如果缓存没了,就需要重建,如果数据量很大,缓存重建的过程会很慢,这会影响生产环境,所以,缓存的持久化也是需要考虑的。 诸多强大的NoSQL都很好支持了上述三大缓存的问题。

后端性能优化技术

前面讨论了前端性能的优化技术,于是前端可能就不是瓶颈问题了。那么性能问题就会到后端数据上来了。下面说几个后端常见的性能优化技术。
一、数据冗余
关于数据冗余,也就是说,把我们的数据库的数据冗余处理,也就是减少表连接这样的开销比较大的操作,但这样会牺牲数据的一致性。风险比较大。很多人 把NoSQL用做数据,快是快了,因为数据冗余了,但这对数据一致性有大的风险。这需要根据不同的业务进行分析和处理。(注意:用关系型数据库很容易移植 到NoSQL上,但是反过来从NoSQL到关系型就难了)
二、数据镜像
几乎所有主流的数据库都支持镜像,也就是replication。数据库的镜像带来的好处就是可以做负载均衡。把一台数据库的负载均分到多台上,同时又保证了数据一致性(Oracle的SCN)。最重要的是,这样还可以有高可用性,一台废了,还有另一台在服务。 数据镜像的数据一致性可能是个问题,所以我们要吧在单条数据上进行数据分区,也就是说,把一个畅销商品的库存均分到不同的服务器上,如,一个畅销商品有1万的库存,我们可以设置10台服务器,每台服务器上有100个库存,这就好像B2C的仓库一样。
三、数据分区
数据镜像不能解决的一个问题就是数据表里的记录太多,导致数据库操作太慢。所以,把数据分区。数据分区有很多种做法,一般来说有下面这几种:

1)把数据把某种逻辑来分类。比如火车票的订票系统可以按各铁路局来分,可按各种车型分,可以按始发站分,可以按目的地分……,反正就是把一张表拆成多张有一样的字段但是不同种类的表,这样,这些表就可以存在不同的机器上以达到分担负载的目的。

2)把数据按字段分,也就是坚着分表。比如把一些不经常改的数据放在一个表里,经常改的数据放在另一个表里。把一张表变成1对1的关系,这样,你可 以减少表的字段个数,同样可以提升一定的性能。另外,字段多会造成一条记录的存储会被放到不同的页表里,这对于读写性能都有问题。

3)平均分表。因为第一种方法是并不一定平均分均,可能某个种类的数据还是很多。所以,也有采用平均分配的方式,通过主键ID的范围来分表。

4)同一数据分区。这个在上面数据镜像提过。也就是把同一商品的库存值分到不同的服务器上,比如有10000个库存,可以分到10台服务器上,一台上有1000个库存。然后负载均衡。 这三种分区都有好有坏。最常用的还是第一种。数据一量分区,你就需要有一个或是多个调度来让你的前端程序知道去哪里找数据。把火车票的数据分区,并放在各个省市,会对12306这个系统有非常有意义的质的性能的提高
四、后端系统负载均衡
前面说了数据分区,数据分区可以在一定程度上减轻负载,但是无法减轻热销商品的负载,对于火车票来说,可以认为是大城市的某些主干线上的车票。这就 需要使用数据镜像来减轻负载。使用数据镜像,你必然要使用负载均衡,在后端,我们可能很难使用像路由器上的负载均衡器,因为那是均衡流量的,因为流量并不 代表服务器的繁忙程序。因此,我们需要一个任务分配系统,其还能监控各个服务器的负载情况。 任务分配服务器有一些难点:
  • 负载情况比较复杂。什么叫忙?是CPU高?还是磁盘I/O高?还是内存使用高?还是并发高?你可能需要全部都要考虑。这些信息要发送给那个任务分配器上,由任务分配器挑选一台负载最轻的服务器来处理。
  • 任务分配服务器上需要对任务队列,不能丢任务啊,所以还需要持久化。并且可以以批量的方式把任务分配给计算服务器。
  • 任务分配服务器死了怎么办?这里需要一些如Live-Standby或是failover等高可用性的技术。我们还需要注意那些持久化了的任务的队列如果转移到别的服务器上的问题。
我看到有很多系统都用静态的方式来分配,有的用hash,有的就简单地轮流分析。这些都不够好,一个是不能完美地负载均衡,另一个静态的方法的致命缺陷是,如果有一台计算服务器死机了,或是我们需要加入新的服务器,对于我们的分配器来说,都需要知道。 还有一种方法是使用抢占式的方式进行负载均衡,由下游的计算服务器去任务服务器上拿任务。让这些计算服务器自己决定自己是否要任务。这样的好处是可 以简化系统的复杂度,而且还可以任意实时地减少或增加计算服务器。但是唯一不好的就是,如果有一些任务只能在某种服务器上处理,这可能会引入一些复杂度。 不过总体来说,这种方法可能是比较好的负载均衡。
五、异步、 throttle 和 批量处理
异步、throttle(节流阀) 和批量处理都需要对并发请求数做队列处理的。
  • 异步在业务上一般来说就是收集请求,然后延时处理。在技术上就是可以把各个处理程序做成并行的,也就可以水平扩展了。但是异步的技术问题大概有 这 些,a)被调用方的结果返回,会涉及进程线程间通信的问题。b)如果程序需要回滚,回滚会有点复杂。c)异步通常都会伴随多线程多进程,并发的控制也相对 麻烦一些。d)很多异步系统都用消息机制,消息的丢失和乱序也会是比较复杂的问题。
  • throttle 技术其实并不提升性能,这个技术主要是防止系统被超过自己不能处理的流量给搞垮了,这其实是个保护机制。使用throttle技术一般来说是对于一些自己无法控制的系统,比如,和你网站对接的银行系统。
  • 批量处理的技术,是把一堆基本相同的请求批量处理。比如,大家同时购买同一个商品,没有必要你买一个我就写一次数据库,完全可以收集到一定数量 的 请求,一次操作。这个技术可以用作很多方面。比如节省网络带宽,我们都知道网络上的MTU(最大传输单元),以态网是1500字节,光纤可以达到4000 多个字节,如果你的一个网络包没有放满这个MTU,那就是在浪费网络带宽,因为网卡的驱动程序只有一块一块地读效率才会高。因此,网络发包时,我们需要收 集到足够多的信息后再做网络I/O,这也是一种批量处理的方式。批量处理的敌人是流量低,所以,批量处理的系统一般都会设置上两个阀值,一个是作业量,另 一个是timeout,只要有一个条件满足,就会开始提交处理。
所以,只要是异步,一般都会有throttle机制,一般都会有队列来排队,有队列,就会有持久化,而系统一般都会使用批量的方式来处理云风同学设计的“排队系统” 就是这个技术。这和电子商务的订单系统很相似,就是说,我的系统收到了你的购票下单请求,但是我还没有真正处理,我的系统会跟据我自己的处理能力来throttle住这些大量的请求,并一点一点地处理。一旦处理完成,我就可以发邮件或短信告诉用户你来可以真正购票了。

在这里,我想通过业务和用户需求方面讨论一下云风同学的这个排队系统,因为其从技术上看似解决了这个问题,但是从业务和用户需求上来说可能还是有一些值得我们去深入思考的地方:

1)队列的DoS攻击。首先,我们思考一下,这个队 是个单纯地排队的吗?这样做还不够好,因为这样我们不能杜绝黄牛,而且单纯的ticket_id很容易发生DoS攻击,比如,我发起N个 ticket_id,进入购票流程后,我不买,我就耗你半个小时,很容易我就可以让想买票的人几天都买不到票。有人说,用户应该要用身份证来排队, 这样在购买里就必需要用这个身份证来买,但这也还不能杜绝黄牛排队或是号贩子。因为他们可以注册N个帐号来排队,但就是不买。黄牛这些人这个时候只需要干 一个事,把网站搞得正常不能访问,让用户只能通过他们来买。

2)对列的一致性?对这个队列的操作是不是需要锁?只要有锁,性能一定上不去。试想,100万个人同时要求你来分配位置号,这个队列将会成为性能瓶颈。你一定没有数据库实现得性能好,所以,可能比现在还差

3)队列的等待时间。购票时间半小时够不够?多不 多?要是那时用户正好不能上网呢?如果时间短了,用户也会抱怨,如果时间长了,后面在排队的那些人也会抱怨。这个方法可能在实际操作上会有很多问题。另 外,半个小时太长了,这完全不现实,我们用15分钟来举例:有1千万用户,每一个时刻只能放进去1万个,这1万个用户需要15分钟完成所有操作,那么,这 1千万用户全部处理完,需要1000*15m = 250小时,10天半,火车早开了。(我并乱说,根据铁道部专家的说明:这几天,平均一天下单100万,所以,处理1000万的用户需要十天。这个计算可能有点简单了,我只是想说,在这样低负载的系统下用排队可能都不能解决问题

4)队列的分分式。这个排队系统只有一个队列好吗? 还不足够好。因为,如果你放进去的可以购票的人如果在买同一个车次的同样的类型的票(比如某动车卧铺),还是等于在抢票,也就是说系统的负载还是会有可能 集中到其中某台服务器上。因此,最好的方法是根据用户的需求——提供出发地和目的地,来对用户进行排队。而这样一来,队列也就可以是多个,只要是多个队 列,就可以水平扩展了。 我觉得完全可以向网上购物学习。在排队(下单)的时候,收集好用户的信息和想要买的票,并允许用户设置购票的优先级,比如,A车次卧铺买 不到就买 B车次的卧铺,如果还买不到就买硬座等等,然后用户把所需的钱先充值好,接下来就是系统完全自动地异步处理订单。成功不成功都发短信或邮件通知用户。这 样,系统不仅可以省去那半个小时的用户交互时间,自动化加快处理,还可以合并相同购票请求的人,进行批处理(减少数据库的操作次数)。这种方法最妙的事是 可以知道这些排队用户的需求,不但可以优化用户的队列,把用户分布到不同的队列,还可以像亚马逊的心愿单一样,让铁道部做车次统筹安排和调整(最后,排队 系统(下单系统)还是要保存在数据库里的或做持久化,不能只放在内存中,不然机器一down,就等着被骂吧)。

小结

写了那么多,我小结一下:
0)无论你怎么设计,你的系统一定要能容易地水平扩展。也就是说,你的整个数据流中,所有的环节都要能够水平扩展。这样,当你的系统有性能问题时,“加3倍的服务器”才不会被人讥笑。

1)上述的技术不是一朝一夕能搞定的,没有长期的积累,基本无望。

2)集中式的卖票很难搞定,使用上述的技术可以让订票系统能有几佰倍的性能提升。而在各个省市建分站,分开卖票,是能让现有系统性能有质的提升的最好方法。

3)春运前夕抢票且票量供远小于求这种业务模式是相当变态的,让几千万甚至上亿的人在某个早晨的8点钟同时登录同时抢票的这种业务模式是变态中的变态。业务形态的变态决定了无论他们怎么办干一定会被骂。

4)为了那么一两个星期而搞那么大的系统,而其它时间都在闲着,也就是铁路才干得出来这样的事了。

posted @ 2012-01-17 15:23 paulwong 阅读(675) | 评论 (1)编辑 收藏

铁路的售票系统来说明分库分表对架构的影响

一、问题:铁路的售票系统的数据量是海量吗?

不是。因为数据量不大,真不大。

每一个车次与车次间是独立的,每车次不超过2000张票,一天发车不超过50万车次;
以预售期15天来讲,15*0.1亿张不超过1.5亿笔的热线数据,称不上海量数据的。
再加上可以按线路分库,更是不到千万级的单表容量。已经发车完成的进入归档分析。
即数据库按路线使用不同的服务器,不同的车次放在不同的表中。并发量锁真不大。

当然,如果不分库分表,再加上不归档处理,铁路的售票系统的数据量看起来是海量的;
关键是这海量的数据没有意义。


二、如何分库分表?

2.1 分库,考虑数据间没有直接关系和服务器如何部署

铁路的售票系统为例来说,按路线分库,再按车次分表是合理的。
设路线有1万条,按每1000条需要两台服务器(一台热机沉余),不到20台服务器
如果使用SAN存储,则使用SAN作为存储,本机作为热机沉余,只需要10台。
当然使用mySQL这种经济型数据库,服务器需要更多来防灾;
即可以采用双写或多写的方式来保证数据的绝对安全。

2.2分表,考虑数据间不存在重叠,即数据满足二分原则

铁路的售票系统的任意两个车次是没有关系的,所以可以分表。
电信的某个用户的通话和其它用户的通话记录,也是没有关系,所以可以分表处理
(实际上电信的系统,分库分表后也是不大的,难在后台的计费、结算等规则)



三、数据库访问接口



1. 元数据:如何识别到当前要处理的数量在哪张表?

铁路的售票系统会有一个车次管理系统,例2012年2月12日 D3206 车次,
按预先设计的在哪台服务器的哪个库,建哪个表。

2.建立元数据的规则:即具体如何分库分表的规则

这个就是数据库的访问接口。

3.数据库访问接口的透明程度

即哪个层知道哪些元数据信息。
例,是否让窗口售票的客户端来解析元数据的规则然后缓存,还是通过中间件来解析缓存的

具体各层使用怎样透明程度,和业务性质、节点和数据中心的拓扑等有关。



四、历史数据归档与分析

1.使用分库分表后,数据需要归档,分析处理的程序变得复杂,但使联机交易变得简单
2.分析:要注意是针对热线数据分析、归档数据分析、混合分析有关,
通过分库分表和归档,更方便使用分布式的统计方案。

具体可以参考,淘宝的开放平台架构师写的文章:

结论:分库分表跟不分库分表,整个架构是完全不一样的。

像铁票的售票系统、淘宝、电信、银行等,绝对要采用分库分表的数据存储方案,

来解决数据量的增长而不影响性能的问题。

像淘宝等互联网应用还要解决带宽即CDN问题。

posted @ 2012-01-17 13:24 paulwong 阅读(623) | 评论 (0)编辑 收藏

JBoss下DataSource加密(下)

数据源文件:my-oracle-ds.xml

<datasources>
    
<local-tx-datasource>
        
<jndi-name>jdbc/my-local</jndi-name>
        <connection-url>
            jdbc:oracle:thin:@10.5.7.30:1521:orcl
        
</connection-url>
        
<driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
        <security-domain>EncryptedOracleDbRealm</security-domain>
        
<exception-sorter-class-name>
            org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter
        
</exception-sorter-class-name>
        
<metadata>
            
<type-mapping>Oracle10g</type-mapping>
        
</metadata>
        
<depends>
            jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword
        
</depends>
    
</local-tx-datasource>



    
<mbean code="org.jboss.security.plugins.JaasSecurityDomain"
        name
="jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword">
        
<constructor>
            
<arg type="java.lang.String" value="ServerMasterPassword"></arg>
        
</constructor>
        
<!-- The opaque master password file used to decrypt the encrypted
            database password key 
-->
        
<attribute name="KeyStorePass">
            {CLASS}org.jboss.security.plugins.FilePassword:${jboss.server.home.dir}/conf/server.password
        
</attribute>
        
<attribute name="Salt">abcdefgh</attribute>
        
<attribute name="IterationCount">13</attribute>
    
</mbean>

</datasources>

在jboss4.3/jboss-as/server/default/conf/login-config.xml中增加节点:

<application-policy name="EncryptedOracleDbRealm">
    
<authentication>
        
<login-module
            
code="org.jboss.resource.security.JaasSecurityDomainIdentityLoginModule"
            flag
="required">
            
<module-option name="username">username</module-option>
            
<module-option name="password">
                3wW33nIpavHK4pd3qoNTbA
            
</module-option>
            
<module-option name="managedConnectionFactoryName">
                jboss.jca:service=LocalTxCM,name=jdbc/my-local
            
</module-option>
            
<module-option name="jaasSecurityDomain">
                jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword
            
</module-option>
        
</login-module>
    
</authentication>
</application-policy>

以上的password由下面命令得出:

E:\JBOSS\jboss4.3\jboss-as\server\default\lib>java -cp jbosssx.jar
org.jboss.security.plugins.PBEUtils abcdefgh 
13 master mypassowrd
Encoded password:  2mqrIBSpp8JVWFAqCBklhf

生成server.password文件:

E:\JBOSS\jboss4.3\jboss-as\server\default\lib>java -cp jbosssx.jar
org.jboss.security.plugins.FilePassword abcdefgh 
13 master server.password

产生后拷贝到:${jboss.server.home.dir}/conf中。

posted @ 2012-01-16 18:58 paulwong 阅读(942) | 评论 (0)编辑 收藏

Java生成RSA非对称型加密的公钥和私钥(利用java API)

非对称型加密非常适合多个客户端和服务器之间的秘密通讯,客户端使用同一个公钥将明文加密,而这个公钥不能逆向的解密,密文发送到服务器后有服务器端用私钥解密,这样就做到了明文的加密传送。

非对称型加密也有它先天的缺点,加密、解密速度慢制约了它的发挥,如果你有大量的文字需要加密传送,建议你通过非对称型加密来把对称型‘密钥’分发到客户端,及时更新对称型‘密钥’。

package com.paul.module.common.util;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;

import javax.crypto.Cipher;

public class RSASecurityUtil2 {
    
/** 指定加密算法为RSA */
    
private static final String ALGORITHM = "RSA";
    
/** 密钥长度,用来初始化 */
    
private static final int KEYSIZE = 1024;
    
/** 指定公钥存放文件 */
    
private static String PUBLIC_KEY_FILE = "PublicKey";
    
/** 指定私钥存放文件 */
    
private static String PRIVATE_KEY_FILE = "PrivateKey";

    
/**
     * 生成密钥对
     * 
@throws Exception
     
*/
    
private static void generateKeyPair() throws Exception {
        
//        /** RSA算法要求有一个可信任的随机数源 */
//        SecureRandom secureRandom = new SecureRandom();
        
        
/** 为RSA算法创建一个KeyPairGenerator对象 */
        KeyPairGenerator keyPairGenerator 
= KeyPairGenerator.getInstance(ALGORITHM);
        
        
/** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
//        keyPairGenerator.initialize(KEYSIZE, secureRandom);
        keyPairGenerator.initialize(KEYSIZE);
        
        
/** 生成密匙对 */
        KeyPair keyPair 
= keyPairGenerator.generateKeyPair();
        
        
/** 得到公钥 */
        Key publicKey 
= keyPair.getPublic();
        
        
/** 得到私钥 */
        Key privateKey 
= keyPair.getPrivate();
        
        ObjectOutputStream oos1 
= null;
        ObjectOutputStream oos2 
= null;
        
try {
            
/** 用对象流将生成的密钥写入文件 */
            oos1 
= new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE));
            oos2 
= new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE));
            oos1.writeObject(publicKey);
            oos2.writeObject(privateKey);
        } 
catch (Exception e) {
            
throw e;
        }
        
finally{
            
/** 清空缓存,关闭文件输出流 */
            oos1.close();
            oos2.close();
        }
    }

    
/**
     * 加密方法
     * 
@param source 源数据
     * 
@return
     * 
@throws Exception
     
*/
    
public static String encrypt(String source) throws Exception {
        generateKeyPair();
        Key publicKey;
        ObjectInputStream ois 
= null;
        
try {
            
/** 将文件中的公钥对象读出 */
            ois 
= new ObjectInputStream(new FileInputStream(
                    PUBLIC_KEY_FILE));
            publicKey 
= (Key) ois.readObject();
        } 
catch (Exception e) {
            
throw e;
        }
        
finally{
            ois.close();
        }
        
        
/** 得到Cipher对象来实现对源数据的RSA加密 */
        Cipher cipher 
= Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        
byte[] b = source.getBytes();
        
/** 执行加密操作 */
        
byte[] b1 = cipher.doFinal(b);
        BASE64Encoder encoder 
= new BASE64Encoder();
        
return encoder.encode(b1);
    }

    
/**
     * 解密算法
     * 
@param cryptograph    密文
     * 
@return
     * 
@throws Exception
     
*/
    
public static String decrypt(String cryptograph) throws Exception {
        Key privateKey;
        ObjectInputStream ois 
= null;
        
try {
            
/** 将文件中的私钥对象读出 */
            ois 
= new ObjectInputStream(new FileInputStream(
                    PRIVATE_KEY_FILE));
            privateKey 
= (Key) ois.readObject();
        } 
catch (Exception e) {
            
throw e;
        }
        
finally{
            ois.close();
        }
        
        
/** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
        Cipher cipher 
= Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        BASE64Decoder decoder 
= new BASE64Decoder();
        
byte[] b1 = decoder.decodeBuffer(cryptograph);
        
        
/** 执行解密操作 */
        
byte[] b = cipher.doFinal(b1);
        
return new String(b);
    }

    
public static void main(String[] args) throws Exception {
        String source 
= "恭喜发财!";// 要加密的字符串
        System.out.println("准备用公钥加密的字符串为:" + source);
        
        String cryptograph 
= encrypt(source);// 生成的密文
        System.out.print("用公钥加密后的结果为:" + cryptograph);
        System.out.println();

        String target 
= decrypt(cryptograph);// 解密密文
        System.out.println("用私钥解密后的字符串为:" + target);
        System.out.println();
    }
}


http://blog.sina.com.cn/s/blog_43b03c72010080t2.html
http://topic.csdn.net/t/20040510/14/3049788.html
http://yuanliyin.iteye.com/blog/853334

posted @ 2012-01-16 00:37 paulwong 阅读(15002) | 评论 (1)编辑 收藏

《1亿在线背后的技术挑战》视频放出

2011年10月31日,腾讯即通平台部高级总监庄泗华在北京航空航天大学的演讲《1亿在线背后的技术挑战》让许多听众变成了庄老师的粉丝。

腾讯大讲堂放出庄泗华的演讲视频,转载请注明来自腾讯大讲堂

演讲PPT下载:http://djt.open.qq.com/portal.php?mod=view&aid=19

视频:1.4亿在线背后的故事

第1部分:从十万级到百万级在线


第2部分:千万级在线


第3部分:亿级在线


第4部分:总结


posted @ 2012-01-15 21:40 paulwong 阅读(385) | 评论 (0)编辑 收藏

我们应当怎样做需求分析(转)

又到新年了,日历又要从2011年翻到2012年了,这使我有太多的感慨,进而勾起了对太大往事的回忆。过去的10年,毫无疑问是中国软件业发展最快的10年。当我们刚刚毕业的时候,还在使用VB、PB开发一些简单的数据库应用,而现在却几乎看不到它们的踪影,换来的是诸如J2EE和.NET这样的大型web应用。而这期间,RUP、XP、敏捷开发、持续集成••••••一个接一个的新概念层出不穷,令人眼花缭乱。现在想来,恍如隔世。

但更令我印象深刻而难以忘怀的,是我亲自经历的、亲眼目睹的、道听途说的一个又一个的软件项目,它们有的获得了成功,但更多的是令人沮丧的失败。套用一下大文豪托尔斯泰体:幸福的家庭都是一样的,不幸的家庭却各有各的不幸;幸福的软件项目都是一样的,不幸的软件项目却各有各的不幸;或者说,成功的软件项目都是一样的,失败的项目却各有各的问题。我常常在想,我们的项目开发到底怎么了,进而把它们一个一个的剥开来深入分析,竟然触目惊心。它们有的是需求的问题,有的是客户关系的问题,还有设计的问题、技术的问题、时间管理的问题、人员培养的问题••••••但归根到底更多的还是需求的问题。需求分析既是一份体力活儿,更是一份技术活儿,它既是人际交往的艺术,又是逻辑分析与严密思考的产物。正是我们在需求分析过程存在的巨大隐患,最终导致了那么多项目的失败。也许你认为我在危言耸听,好吧,我来举几个典型事例分析分析吧。

我的第一个故事来自大名鼎鼎的东软。我在2005年接一个项目的时候,听说这个项目之前是东软做的。当时东软在做这个项目的时候,整个过程经历了10多次结构性的大变更,局部性的调整更是不计其数。据说某天早上,客户对某个功能不满意,他们不得不对几百处程序进行修改。之后客户对修改的内容还是不满意,又不得不将几百处修改重新改回来。最后这个项目导致的结果是,整个这个项目组的所有成员都离开了东软,并似乎从此不愿涉足软件开发领域。多么惨痛的教训啊!我常常听到网友抱怨客户总是对需求改来改去,但客户对需求改来改去的真正原因是什么呢?当我们对客户的需求没有真正理解清楚时,我们做出来的东西客户必然不满意。客户只知道他不满意,但怎样才能使他满意呢?他不知道,于是就在一点儿一点儿试,于是这种反复变更就这样发生了。如果我们明白了这一点,深入地去理解客户的业务,进而想到客户的心坎儿上去,最后做出来的东西必然是客户满意的。记住,当客户提出业务变更的时候,我们一定不能被客户牵着走,客户说啥就是啥。我们要从业务角度深入的去分析,他为什么提出变更,提得合不合理,我有没有更合理的方案满足这个需求。当我们提出更加合理的方案时,客户是乐于接受的,变更也变得可控了。

第二个故事来自我自己的项目,一个早期的项目。在这个项目中,客户扔给了我们很多他们目前正在使用的统计报表,要我们按照报表的格式做出来。这些报表都是手工报表,许多格式既不规范,又很难于被计算机实现。这些报表令我耗费了不少闹细胞,直到最终项目失败都没法完成。这件事留给我的深刻教训是,不能客户怎么说软件就怎么做。客户提出的原始需求往往是不考虑技术实现,基于非计算机管理的操作模式提出来的。他们提出的很多需求常常比较理想而不切实际,毕竟人家是非技术的。但我们作为技术人员,需求分析必须实事求是地、基于技术可以实现的角度去考虑。那种“有条件要上,没有条件创造条件”的鲁莽行事,结果必然是悲惨的。所以我们必须要基于技术实现去引导客户的需求。同时,计算机信息化管理就是一次改革,对以往手工管理模式的改革。如果我们上了信息化管理系统,采用的管理模式却依然是过去的手工模式,新系统的优势从何而来呢?因此,我们做需求就应当首先理解现有的管理模式,然后站在信息化管理的角度去审视他们的管理模式是否合理,最后一步一步地去引导他们按照更加合理的方式去操作与管理。

2007年,我参与了一个集团信息化建设的项目。这个项目中的客户是一个庞大的群体,他们分别扮演着各种角色。从机构层次划分,有集团领导、二级机构人员、三级机构人员;从职能角色划分,有高层领导、财务人员、生产管理员、采购人员、销售人员,等等。在这样一个复杂场景中,不同人员对这个项目的需求是各自不同的。非常遗憾的是,我们在进行需求分析的时候没有认真分析清楚所有类型人员的需求。在进行需求调研的时候,总是集团领导带领我们到基层单位,然后基层单位将各方面的人员叫来开大会。这样的大会,各类型的人员七嘴八舌各说各自的需求,还有很多基层人员在大会上因为羞涩根本就没有提出自己的需求。这样经过数次开会,需求调研就草草收场。我们拿着一个不充分的需求分析结果就开始项目开发,最终的结果可想而知。直到项目上线以后,我们才发现许多更加细节的业务需求都没能分析到,系统根本没法运行,不得不宣告失败。一个软件项目的需求调研首先必须要进行角色分析,然后对不同的角色分别进行调研。需求调研的最初需要召开项目动员大会,这是十分必要的。但真正要完成需求分析,应该是一个一个的小会,1~3个业务专家,只讨论某个领域的业务需求,并且很多问题都不是能一蹴而就完成的,我们必须与专家建立联系,反复沟通后完成。需求分析必须遵从的是一定的科学方法,而不是盲目的大上快上。

我的最后一个故事可能典型到几乎每个人都曾经遇到过。我们的项目从需求分析到设计、开发、测试都十分顺利。但到了项目进行的后期,快到达最后期限时,我们将我们的开发成果提交给客户看,客户却对开发不满意,提出了一大堆修改,而且这些修改工作量还不小。怎么办呢?加班、赶工,测试时间被最大限度压缩。最后项目倒是如期上线了,但大家疲惫不堪,并且上线以后才发现许多的BUG。需求分析不是一蹴而就的,它应当贯穿整个开发周期,不断的分析确认的过程。以上这个事例,如果我们提早将开发成果给客户看,提早解决问题,后面的情况就将不再发生。这就是敏捷开发倡导的需求反馈。敏捷开发认为,需求分析阶段不可能解决所有的需求问题,因此在设计、开发、测试,直到最终交付客户,这整个过程都应当不停地用开发的成果与客户交流,及时获得反馈。只有这样才能及时纠正需求理解的偏差,保证项目的成功。

以上的故事各有各自的不幸,各自都在不同的开发环节出现了问题。但经过深入的分析,各自的问题最终都归结为需求分析出现了问题。为了使我们今后的软件项目不会重蹈覆辙,似乎真的有必要讨论一下我们应该怎样做需求分析。

posted @ 2012-01-15 20:24 paulwong 阅读(336) | 评论 (0)编辑 收藏

[转帖]建设一个靠谱的火车票网上订购系统

转自【 http://www.ifanr.com/68019
昨天,2012年1月11日,网友 @fenng 写了一篇文章,批评铁道部火车票网上订购系统,http://www.12306.cn [1]。同时在新浪发了一条言辞激烈的微博,“去你的‘海量事务高速处理系统’”,引起热议 [2]

春节将到,大家买不着车票,赶不上大年三十与家人团聚,急切心情可以理解。但是拍桌子开骂,只能宣泄情绪,解决不了实际问题。 开发一套订票系统并不难,难在应对春运期间,日均 10 亿级别的洪峰流量。日均 10 亿级别的洪峰请求,在中国这个人口全球第一大国,不算稀罕,不仅火车票订票系统会遇到,而且电子商务在促销时,也会遇到,社交网站遇到新闻热点时,也会遇到。 所以,能够在中国成功运行的云计算系统,推广到全球,一定也能成功。

但是在美国成功运行的云计算系统,移植到中国,却不一定成功。 如果我们能够设计建造一套,稳定而高效的铁路订票系统,不仅解决了中国老百姓的实际问题,而且在全球高科技业界,也是一大亮点,而且是贴着中国标签的前沿科技的亮点。 于是软件工程师们献计献策,讨论如何改进 12306 网上购票系统 [3]。其中比较有代表性的,有两篇 [4,5] 网友的评论中,有观点认为,[4] 利用“虚拟排队”的手段,将过程拉长负载降低,是网游的设计思路。而 [5] 利用缓存技术,一层层地降低系统负荷, 是互联网的设计思路。 个人认为,[4] 和 [5] 并不是相互排斥的两种路线,两者着重解决的问题不同,不妨结合起来使用,取长补短。

下面介绍一下我们的设计草案,追求实用,摈弃花哨。抛砖引玉,欢迎拍砖。
图一。12306.cn 网站系统架构设想图。
Courtesy http://i879.photobucket.com/albums/ab351/kan_deng/12306.png

图一是系统架构图,典型的“展现层”/ “业务层”/ “数据层”的三段论。 用户接入有两类,一个是运行在电脑里的浏览器,例如 IE,另一个是手机。 无论用户用电脑浏览器,还是手机访问 http://www.12306.cn 网站,用户请求首先被网站的负载均衡器接收。负载均衡器连接着一群门户服务器,根据各个门户服务器的负载轻重,负载均衡器把用户请求,转发到某一相对清闲的门户服务器。 门户服务器的任务类似于收发室老头儿,它只读每个用户请求的前几个 bytes,目的是确定用户请求的类型,然后把请求投放到相应类型的队列中去。门户服务器的处理逻辑非常简单,这样做的好处,是让它能够快速处理大批量用户请求。

根据 [5] 的分析,12306 处理的用户请求,大致分为三类,
1. 查询。用户订票前,查询车次以及余票。用户下订单后,查询是否已经订上票。
2. 订票,包括确定车次和票数,然后付款。用户付款时,需要在网银等网站上操作。
3. 第一次访问的用户,需要登记,包括姓名和信用卡等信息。

三类请求的业务处理过程,被分为两个阶段,
1. 运行于缓存中的任务队列。设置队列的目的,是防止处理过程耗时太长,导致大量用户请求拥塞于门户服务器,导致系统瘫痪。
2. 业务处理处理器,对于每一类业务,分别有一群业务服务器。不同业务的处理流程,各不相同。
图二。12306.cn 网站查询和订票业务流程设想图。
Courtesy http://i879.photobucket.com/albums/ab351/kan_deng/12306-1.png
图二描述了查询和订票,两个业务的处理流程。登记业务流程从略。 查询的业务流程,参见图二上半部,分五步。
这里有两个问题需要注意,
1. 用户发出请求后,经过短暂的等待时间,能够迅速看到结果。平均等待时间不能超过 1 秒。
2. 影响整个查询速度的关键,是“查询服务器”的设计。

查询任务可以进一步细化,大致分成三种。
1. 查询车次和时间表,这是静态内容,很少与数据库交互,数据量也不大,可以缓存在内存中。 车次和时间表的数据结构,不妨采用 Key-Value 的方式,开发简单,使用效率高。Key-Value 的具体实现有很多产品,[5] 建议使用 Redis。 这些是技术细节,不妨通过对比实验,针对火车票订票系统的实际流量,以及峰值波动,确定哪一个产品最合适。
2. 查询某一班次的剩余车票,这需要调用数据库中不断更新的数据。 [5] 建议把剩余车票只分为两种,“有”或“无”,这样减少调用访问数据库的次数,降低数据库的压力。但是这样做,不一定能够满足用户的需求,说不定会招致网友的批评讥讽。 [4] 建议在订票队列中,增加测算订票队列长度的功能,根据订票队列长度以及队列中每个请求的购票数量,可以计算出每个车次的剩余座位。如果 12306.cn 网站只有一个后台系统,这个办法行之有效。 但是假如 12306.cn 网站采用分布式结构,每个铁路分局设有子系统,分别管理各个铁路分局辖区内的各个车次。在分布式系统下,这个办法面临任务转发的麻烦。不仅开发工作量大,而且会延长查询流程处理时间,导致用户长久等待。
3. 已经下单的用户,查询是否已经成功地订上票。 每个用户通常只关心自己订的票。如果把每个用户订购的车票的所有内容,都缓存在内存里,不仅非常耗用内存空间,内存空间使用效率低下,更严重的问题是,访问数据库过于频繁,数据量大,增大数据库的压力。

解决上述分布式同步,以及数据库压力的两个问题,不妨从订票的流程设计和数据结构设计入手。
假如有个北京用户在网上订购了一套联票,途经北京铁路局和郑州铁路局辖区的两个车次。
用户从北京上网,由北京铁路局的子系统,处理他的请求。
北京铁路局的订票服务器把他的请求一分为二,北京铁路局的车次的订票,在北京子系统完成,郑州铁路局的车次在郑州子系统完成。
每个子系统处理四种 Key-Value 数据组。
1. 用户ID:多个 (订单ID)s。
2. 订单ID:多个 (订票结果ID)s。
3. 订票结果ID: 一个 (用户ID,车次ID)。
4. 车次ID:一个(日期),多个 (座位,用户ID)。
北京订票服务器完成订票后,把上述四个数据组,写入北京子系统的数据库,同时缓存进北京的查询服务器,参见图二下半部第6步和第7步。
郑州订票服务器完成订票后,把上述四个数据组,写入郑州子系统的数据库,同时缓存进北京的查询服务器,而不是郑州的服务器。 让订票服务器把订票数据,同时写入数据库和查询服务器的缓存,目的是让数据库永久保留订票记录,而让大多数查询,只访问缓存,降低数据库的压力。
北京用户的订票数据,只缓存在北京的查询服务器,不跨域缓存,从而降低缓存空间的占用,和同步的麻烦。这样做,有个前提假设,查询用户与订票用户,基本上是同一个人,而且从同一个城市上网。
 但是这里有个缺陷,某用户在北京上网订了票。过了几天,他在北京上网,输入用户ID和密码后,就会看到他订购的所有车票。可是又过了几天,他去了郑州,从郑州上网,同样输入用户ID和密码,却看不到他订购的所有车票。
 解决这个缺陷的办法并不麻烦,在用户查询订票信息时,需要注明订票地点,系统根据订票地点,把查询请求转发到相应区域的子系统。 另外,每次订票的时候,网站会给他的手机发送短信,提供订票信息,参见图二下半部第8步和第9步。

以上是一个初步设计,还有不少细节需要完善,例如防火墙如何布置等等。
这个设计不仅适用于单一的集中式部署,而且也适合分布式部署。
或许有读者会问,为什么没有用到云计算?其实上述架构设计,为将来向云计算演变,留下了伏笔。
在上述架构设计中,我们假定每个环节需要用多少服务器,需要多大容量的数据库,预先都已经规划好。
但是假如事先的规划,低于实际承受的流量和数据量,那么系统就会崩溃。
所以,事先的规划,只能以峰值为基准设立。 但是峰值将会是多少?
事先难以确定。即便能够确定峰值,然后以峰值为基准,规划系统的能力,那么春运过后,就会有大量资源冗余,造成资源浪费? 如何既能抗洪,又不造成资源浪费?解决方案是云计算,而且目前看来,除了云计算,没有别的办法。

Reference,
[1] 海量事务高速处理系统。 http://www.douban.com/note/195179318/
[2] 去你*的‘海量事务高速处理系统’。 http://weibo.com/1577826897/y0jGYcZfW
[3] 火车订票系统的设想。 http://weibo.com/1570303725/y0l9Y2mwE
[4] 铁路订票系统的简单设计。 http://blog.codingnow.com/2012/01/ticket_queue.html
[5] 铁路订票网站个人的设计浅见。 http://hi.baidu.com/caoz/blog/item/f4f1d7caee09b558f21fe780.html
题图来自 Designyoutrust

posted @ 2012-01-13 13:39 paulwong 阅读(322) | 评论 (0)编辑 收藏

台湾图书

 
http://www.tenlong.com.tw/items/9861811915?item_id=59633
 
商譽管理─看見危機,穿透危機,決勝於未戰之前
http://www.tenlong.com.tw/items/9861578269?item_id=375391
 
全面品質管理, 2/e
http://www.tenlong.com.tw/items/9866184560?item_id=390199
 
曼陀羅九宮格思考術─達成目標成功圓夢
http://www.tenlong.com.tw/items/9866151018?item_id=58621
 
六個標準差的品質管制─ 60 小時學會實務應用的手冊
http://www.tenlong.com.tw/items/9572182579?item_id=377554
 
在失業中創業:被炒魷魚又怎樣!
http://www.tenlong.com.tw/items/9868768004?item_id=382010
 
領導未來的 CEO-12 堂 EMBA 名師的管理必修課
http://www.tenlong.com.tw/items/9862720581?item_id=383127
 
早上 3 分鐘變身管理大師, 2/e
http://www.tenlong.com.tw/items/9866487997?item_id=384625
 
整合行銷傳播策略與企劃
http://www.tenlong.com.tw/items/9576598761?item_id=384636
 
Photoshop 視訊課程合集 (21)
http://www.tenlong.com.tw/items/4712839503?item_id=385316
 
DTP 視訊課程合集 (7)
http://www.tenlong.com.tw/items/4712839503?item_id=385314
 
3ds Max 視訊課程合集(22)
http://www.tenlong.com.tw/items/4712839503?item_id=348746
 
Photoshop 視訊課程合集 (22)
http://www.tenlong.com.tw/items/4712839503?item_id=395988
 
Photoshop 視訊課程合集 (21)
http://www.tenlong.com.tw/items/4712839503?item_id=385316
 
巴菲特 & 索羅斯聯手出擊─不看會後悔的投資策略
http://www.tenlong.com.tw/items/9862572752?item_id=387693
 
揭開肥貓經理人薪酬的黑盒子
http://www.tenlong.com.tw/items/9862572485?item_id=387694
 
圖解第一次看懂經濟指標就上手
http://www.tenlong.com.tw/items/9866434192?item_id=389815
 
把鳥事變好事的神奇手帳術
http://www.tenlong.com.tw/items/9862295635?item_id=390569
 
用 Please 換 Yes 的職場成功學
http://www.tenlong.com.tw/items/9866009017?item_id=390570
 
Pose 這樣擺最 OK ─人像攝影與場景的完美結合
http://www.tenlong.com.tw/items/9862015454?item_id=392624
 
寫給 SA 的 UML / UseCase 實務手冊
http://www.tenlong.com.tw/items/9861817786?item_id=51507
 
Thinking in Java 中文版 (Thinking in Java, 4/e)
http://www.tenlong.com.tw/items/9861815023?item_id=45896
 
jQuery 實戰手冊 (jQuery in Action, 2/e)
http://www.tenlong.com.tw/items/9861811915?item_id=59633
 
讓人不自覺說 YES 的交涉力
http://www.tenlong.com.tw/items/9866363368?item_id=54347
 
翻譯大師教你寫出好句子
http://www.tenlong.com.tw/items/9577297390?item_id=49007
 
日本超級店長首次公開讓客戶「好想再見到妳」的心機說話術
http://www.tenlong.com.tw/items/9866097250?item_id=352822
 
iPhone 基礎程式設計
http://www.tenlong.com.tw/items/9866649091?item_id=351448
 
圖解 NLP 惡魔說話術─實例篇
http://www.tenlong.com.tw/items/9866363872?item_id=248045
 
大膽想 出狠招 (Think Big And Kick Ass In Business And Life) http://www.tenlong.com.tw/items/9866662659?item_id=44764
 
3ds Max 視訊課程合集 1
http://www.tenlong.com.tw/items/4712839503?item_id=46426
 
寫給經理人的專案管理發達之路-使用 Project 2010
http://www.tenlong.com.tw/items/9572239325?item_id=371017
 
軟體測試專案實作-技術、流程與管理
http://www.tenlong.com.tw/items/9572239473?item_id=351121
 

posted @ 2012-01-10 14:55 paulwong 阅读(232) | 评论 (0)编辑 收藏

JBoss下DataSource加密(上)

1.先来看一个普通的数据源配置文件
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
   
<local-tx-datasource>
     
<!-- jndi名字 -->
     
<jndi-name>MySqlDS</jndi-name>
     
<!--URL地址 --> 
     
<use-java-context>false</use-java-context>
     
<connection-url>jdbc:mysql://10.16.175.137:3306/test</connection-url>
     
<!-- 驱动 --> 
     
<driver-class>com.mysql.jdbc.Driver</driver-class>
      
<!-- 用户名 --> 
     
<user-name>root</user-name>
      
<!-- 密码 --> 
    
<password>123456</password>
    
<exception-sorter-class-name> org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter </exception-sorter-class-name> 
     
<metadata> 
        
<type-mapping>mySQL</type-mapping> 
     
</metadata>
   
</local-tx-datasource>
</datasources>


看一下这个文件,里面用户名与密码都是以明文方式存储的,这样子对系统的安全而言带来了极大的威协。所以我们要为我们这个明文的密码加一下密,这就是本文的目的.

2.说到密码加密,这里我们用到了JBoss下的一个类org.jboss.resource.security.SedureIdentityLoginModule,看看我们该如何用它来帮我们的密码加密。
先看个配置数据源的例子(mysql-ds.xml)

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>MySqlDS</jndi-name>
<use-java-context>false</use-java-context>
<connection-url>jdbc:mysql://192.168.1.91:3306/atteam</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<!--这里不用写上你的用户名与密码了,我们可以在login-config.xml里做点手脚,就OK了 -->
<security-domain>EncryptDBPassword</security-domain>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>

接着我们修改server\default\conf\login-config.xml文件,加上下面这一段配置文件

<application-policy name="EncryptDBPassword">
<!--这里的name应该是你在配置数据源时写的security-domain里的字符串-->
<authentication>
<login-module code="org.jboss.resource.security.SecureIdentityLoginModule" flag="required">
<!-- 数据库的用户名 -->
<module-option name="username">test</module-option>
<!--数据库的密码,不过是加密过的了 -->
<module-option name="password">64c5fd2979a86168</module-option>
<!-- 注意name等于你的数据源的jndi-name,这里是MySqlDS -->
<module-option name="managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=MySqlDS</module-option>
</login-module>
</authentication>
</application-policy>

3.补充一下,这个加密的密码是哪来的

java -cp "D:\TDdownload\jboss-4.2.0.CR1\jboss-4.2.0.CR1\lib\jboss-jmx.jar;D:\TDdownload\jboss-4.2.0.CR1\jboss-4.2.0.CR1\lib\jboss-common.jar;D:\TDdownload\jboss-4.2.0.CR1\jboss-4.2.0.CR1\server\default\lib\jboss-jca.jar;D:\TDdownload\jboss-4.2.0.CR1\jboss-4.2.0.CR1\server\default\lib\jbosssx.jar" org.jboss.resource.security.SecureIdentityLoginModule 123456 Encoded password: 64c5fd2979a86168

posted @ 2012-01-09 00:51 paulwong 阅读(623) | 评论 (0)编辑 收藏

仅列出标题
共115页: First 上一页 90 91 92 93 94 95 96 97 98 下一页 Last