MyException - 我的异常网
当前位置:我的异常网» Java Web开发 » 1人30天44587行代码,分享舍得网开发经验(修改版)

1人30天44587行代码,分享舍得网开发经验(修改版),该如何解决

www.MyException.Cn  网友分享于:2015-08-26  浏览:26次
1人30天44587行代码,分享舍得网开发经验(修改版)
原帖在这里
http://topic.csdn.net/u/20080124/16/edff1fef-ff1f-41e0-96a2-2707f99f3b21.html

不知道为什么原来的帖子被删除了,我用心写这么高水准的帖子,不应该被删才对。该帖在原来的基础上做了修正和增加。

舍得网(shedewang.com)的开发暂时告一段落,一个人用时不到1个月,java底层代码16902行,jsp代码27685行,共计44587行。整个开发过程遇到过许多问题,但最后都解决了。下面把我在开发中遇到的所有问题和解决办法列出,供参考。

系统构架:redhat AS4/apache2.0.59/resin2.1.17/jdk6.0 u2/hibernate3.0/lucene2.2/urlrewrite3.0.4,数据库用得是mysql4.1.15,数据库缓存是构架在hibernate之上的,是一个只有794行的java类,但这个java类却做了数据库对象缓存、列表缓存、update缓冲、自动删除列表缓存,还提供了数据库查询、更新、插入的所有操作,它节省了我一半以上的开发时间。一个获取含有五个查询条件获取列表的方法只用不到10行代码就可以了。【增加:现在我已经把这个数据库操作工具改成分布式了,可以随便增加java应用服务器实现负载均衡,并且各服务器之间可以实现缓存同步,这样,即使每日用户达到百万级别,我的构架也是可以支持的,我将在下面详细说明我的构架,仅供参考。许多人要求我开源,我觉得现在系统还没有经过大规模用户的并发验证,还不是时候,以后我会考虑开源的,我的代码没有太多高深的算法和设计模式,主要用到了模板模式,但全是用心写出来的。

问题一:做数据库缓存时遇到的问题。HashMap在并发遍历时会报ConcurrentModificationException,即使使用Collections.synchronizedList把Map包起来还是会报这个异常,这个问题很简单,解决办法也简单。第一种解决办法是不要用Map的iterator来遍历,而是用Set(Map.keySet方法)的toArray方法来遍历,这种办法虽然会损耗一定的性能和内存,但比在方法前加synchronized好得多;第二种解决办法用jdk5.0以后的ConcurrentHashMap来实现。【修正:经过测试和验证,第一种方法不行,也就是并发操作MAP而且要求遍历的时候只能用ConcruuentHashMap,在此要感谢写ConcurrentHashMap的专家们。】【增加:数据库的缓存有很多种办法,对于单个对象的缓存比较容易,直接用HashMap都可以,但是对于列表的缓存就比较复杂了,网上说到的memcachedb+memcache_engine或者berkeleydb应该都是做不到列表自动缓存,因为增加一条记录后会影响许多列表的排序,所以什么时候删除列表缓存是个比较头痛的问题,我的解决办法是列表的缓存的key便包含了查询条件信息。如一个表T有字段A,B,C,对应T.java有域A,B,C,那么查询一个A=1 and B=2 and C>0 的组合条件的列表的key就是A=1#B=2#C>0,这样,如果增加了一个对象T,其中T.A=1,T.B=3,T.C=0,显然上面列表查询条件包含了条件B=2,而增加的对象B=3,那么无论如何这个新增加的对象T都不可能在这个列表中,也就是说不用删除这个列表,只有增加的对象T满足T.A=1、T.B=2、T.C>0时该列表才需要重新从数据库中获取,以此可以推出更新、删除一个T对象时什么时候需要删除什么列表。】【增加:至于分布式,我用到了memcached来做远程缓存,利用UDP报文来保持各服务器之间的缓存同步。如获取一个对象:首先在本机缓存中获取,如果没有再去远程memcached server中获取,如果还没有才从数据库中获取并同时放入memcached server 和本机缓存,这样,不管有多少台服务器在做负载均衡,对于一个对象T,只需要在数据库中读取一次,其他所有服务器都可以共享了,数据库查询的压力几乎没有,当然如果插入和修改的次数达到每秒几千次,我可能会用到mysql-proxy,但目前看来,几十万的用户/天的量都用不着,用个好点的数据库服务器即可】【不谦虚的说,我的这套分布式缓存方案是比较强大的,都是用心写出来的,虽然代码只有2874行。实例:如要获取一个id为6789的用户,只要用User u =UserManager.getInstance().getById("6789");一句话即可,所有缓存逻辑都已经包含在里面了。】


问题二:jfreecharts在Linux上不能显示中文,这个问题没有费多长时间就解决了,上网一搜就搞定,解决方法如下:
到网上下载一个linux下的ttf字体,本例用的是zysong.ttf
1.确认%JavaHome%/jre/lib/fonts目录下存在zysong.ttf
2.在%JavaHome%/jre/lib/fonts目录下执行"ttmkfdir -o fonts.dir"命令,重新生成fonts.dir文件
3.确认/usr/share/fonts/zh_CN/TrueType目录存在,如果不存在则mkdir创建
4.确认/usr/share/fonts/zh_CN/TrueType目录下存在zysong.ttf
5.在%JavaHome%/jre/lib目录下,执行 cp fontconfig.RedHat.3.properties.src fontconfig.properties
6.重起resin,OK。

问题三:linux下的too many open files错误,这个问题比较严重,AS4默认打开文件数是1024,如果超过这个数,resin就自动down掉了,非常恶心。解决办法如下:
echo 65536 > /proc/sys/fs/file-max
编辑/etc/sysctl.conf 文件,编辑行 fs.file-max = 65536
编辑文件/etc/security/limits.conf,增加行 * - nofile 65536
用ulimit -a 查看,如果看到行open files (-n) 65536就说明对了

问题四:内存泄露,表现出来的特征是CPU占到99.9%,内存由10%左右经过几个小时后慢慢涨到50%,最后死掉。做java的人知道,这个问题非常痛苦,而且没有很好的解决办法,因为直接看代码很难看出来。我原来一直以为问题会出现在缓存上,但仔细想想apache的LRUMap不至于产生内存泄露,尤其我设置了LRUMap最大长度只有10000,10000个内存对象能有多大,后来发现是SmartUpload的问题,改成apache的FileUpload子项目就可以了。另外,我在设置jvm参数时增加了-Xmx2048m -Xms2048m -Xmn768m -Xss512k -XX:+UseParallelGC -XX:ParallelGCThreads=4 -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy这些参数,可以回收年老区的内存,现在比较稳定,一般内存占到27%左右就不会再涨了,可能这些参数还不是最优的,有待探索。另外查找内存泄露的软件JProbe我也玩了玩,的确看出其他代码没有明显内存泄露。【修正:上面的参数配置狗P用都没有,内存总是一直在涨。我还尝试了用其他不同方法去回收内存,结果都不太好使,直接用jvm默认的回收方式是最好的,也就是只配置两个参数-Xmx768M -Xms768M效果最好,这样java才真的可以一次性回收几百兆的内存。】

问题五:搜索分词。一个用户在用舍得网时反映,看到有“啤酒”和“茅台酒”,为什么搜“酒”搜不出来,原因很简单,“啤酒”和“茅台酒”是单独一个词,lucene写入的时候没有再把它拆开,所以必须要搜“啤酒”或“茅台酒”才能搜出来,这在技术上合理,但是用户觉得不合理。所以我改进了搜索算法,把中国3万多个汉字也加到词库中,而且在写入和搜索时用不同的分词算法,如“我喜欢喝啤酒”在写入时会分成“我+喜欢+喝+啤酒+喜+欢+啤+酒”,而在搜索时这句话会被分词为“我+喜欢+喝+啤酒”,这样,用户搜“啤酒”能搜到,搜“酒”也能搜到,而对应另外一句话“这人啤气不好,总喝酒”搜“啤”和“酒”都能搜到,但搜“啤酒”却搜不到,似乎有点意思。但是这么分词也会有点小问题,就是搜索的结果不太人性化。(我的中文词库加成语加汉字共50多万个,比起一般网上十来二十万要丰富得多,不过这没什么大用)

问题六:URL链接“静态化”。本想直接用apache的URL Rewrite来实现,发现不太可能,于是改用urlrewirte实现,配置没什么难度,但是要注意resin的web-app里须增加一行配置<servlet-mapping url-pattern='*.htm' servlet-name='plugin_match'/>,这样apache才会把htm结尾的请求转交给resin,否则apache报404错误,这在一般structs项目中都会提到。现在看到的舍得网http://shedewang.com/pg_5_c_2_index.htm,其实就是http://shedewang.com/index.jsp?pg=5&c=2,呵呵,没什么特别的。

文章评论

老程序员的下场
老程序员的下场
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
我的丈夫是个程序员
我的丈夫是个程序员
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
中美印日四国程序员比较
中美印日四国程序员比较
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
10个调试和排错的小建议
10个调试和排错的小建议
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
编程语言是女人
编程语言是女人
漫画:程序员的工作
漫画:程序员的工作
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
程序员应该关注的一些事儿
程序员应该关注的一些事儿
程序员的鄙视链
程序员的鄙视链
Java程序员必看电影
Java程序员必看电影
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
 程序员的样子
程序员的样子
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
我是如何打败拖延症的
我是如何打败拖延症的
为什么程序员都是夜猫子
为什么程序员都是夜猫子
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
每天工作4小时的程序员
每天工作4小时的程序员
程序员都该阅读的书
程序员都该阅读的书
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
一个程序员的时间管理
一个程序员的时间管理
总结2014中国互联网十大段子
总结2014中国互联网十大段子
如何成为一名黑客
如何成为一名黑客
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
旅行,写作,编程
旅行,写作,编程
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
鲜为人知的编程真相
鲜为人知的编程真相
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有