From 4ca616c77e04f1f46823c0baa1fd26cdae00a9d4 Mon Sep 17 00:00:00 2001
From: sunzhiqiang23
+ * 用户信息表 + *
+ * + * @author 孙志强 + * @since 2020-04-13 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +public class User extends UserSuper implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户主键 + */ + private Long id; + + /** + * 登录账户 + */ + private String username; + + public static String realName ="static"; + +} diff --git a/shiro-serialization/src/main/java/com/bjmashibing/entity/User1.java b/shiro-serialization/src/main/java/com/bjmashibing/entity/User1.java new file mode 100644 index 0000000..5016633 --- /dev/null +++ b/shiro-serialization/src/main/java/com/bjmashibing/entity/User1.java @@ -0,0 +1,55 @@ +package com.bjmashibing.entity; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +/** + * + * + * @author sunzhiqiang23 + * @date 2020-06-16 20:23 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +public class User1 extends UserSuper implements Externalizable { + private static final long serialVersionUID = 2L; + + /** + * 用户主键 + */ + private Long id; + + /** + * 登录账户 + */ + private String username; + + public static String realName ="static"; + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(id); + out.writeObject(username); + out.writeObject(realName); + out.writeObject(super.getSuperName()); + } + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + id = (Long) in.readObject(); + username = (String) in.readObject(); + realName = (String) in.readObject(); + String superName = (String) in.readObject(); + setSuperName(superName); + + } + + +} diff --git a/shiro-serialization/src/main/java/com/bjmashibing/entity/UserSuper.java b/shiro-serialization/src/main/java/com/bjmashibing/entity/UserSuper.java new file mode 100644 index 0000000..b9e622a --- /dev/null +++ b/shiro-serialization/src/main/java/com/bjmashibing/entity/UserSuper.java @@ -0,0 +1,20 @@ +package com.bjmashibing.entity; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * + * + * @author sunzhiqiang23 + * @date 2020-06-16 21:08 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +public class UserSuper { + + private String superName; + +} diff --git a/shiro-serialization/src/main/java/com/bjmashibing/util/BeanUtil.java b/shiro-serialization/src/main/java/com/bjmashibing/util/BeanUtil.java new file mode 100644 index 0000000..00d0663 --- /dev/null +++ b/shiro-serialization/src/main/java/com/bjmashibing/util/BeanUtil.java @@ -0,0 +1,61 @@ +package com.bjmashibing.util; + +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + *Bean (POJO) 相关工具
+ * + * @author sunzhiqiang23 + * @date 2020/1/6 12:22 + */ +@Slf4j +public class BeanUtil extends BeanUtils { + private static JacksonBeanConvertor beanConvertor = new JacksonBeanConvertor(); + /** + * 任意 Bean 类型转换,深度转换(copyProperties 方法为浅拷贝) + * + * @param fromValue 原始 Bean + * @param toValueType 目标类型 + * @param计算方法执行时间工具类-粗略测试批量导入导出考勤报表用
+ * + * @author sunzhiqiang23 + * @date 2019/12/25 11:22 + */ +@Slf4j +public class TimeTool { + private static final SimpleDateFormat FMT = new SimpleDateFormat("HH::mm:ss.SSS"); + + public interface Task { + void execute(); + } + + public static void check(String title, Task task) { + if (task == null) { + return; + } + title = (title == null) ? "" : ("【" + title + "】"); + System.out.println(title); + + long begin = System.currentTimeMillis(); + task.execute(); + long end = System.currentTimeMillis(); + + + System.out.println("结束:" + FMT.format(new Date())); + double delta = (end - begin) / 1000.0; + System.out.println("耗时:" + delta + "秒"); + System.out.println("-------------------------"); + + } + + +} diff --git a/shiro-serialization/src/main/resources/application.yml b/shiro-serialization/src/main/resources/application.yml new file mode 100644 index 0000000..4f28ad4 --- /dev/null +++ b/shiro-serialization/src/main/resources/application.yml @@ -0,0 +1,23 @@ +# Tomcat +server: + tomcat: + uri-encoding: UTF-8 + max-threads: 1000 + min-spare-threads: 30 + port: 8002 +spring: + mvc: + static-path-pattern: /static/** + freemarker: + suffix: .html + request-context-attribute: request + jackson: + time-zone: GMT+8 + date-format: yyyy-MM-dd HH:mm:ss + # 集群配置 + redis: + expireSeconds: 60 + timeout: 5000ms #redis操作的超时时间 + database: 0 + host: 192.168.254.201 + port: 6379 \ No newline at end of file diff --git a/shiro-serialization/src/main/resources/logback-spring.xml b/shiro-serialization/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..18e03ea --- /dev/null +++ b/shiro-serialization/src/main/resources/logback-spring.xml @@ -0,0 +1,8 @@ + + + +!>-pk`BN4h#Ls$ir=a0bky@g-7-d%lW9Q?*8SDq?4S#L;b zfzHkM1V|=z*mv9FYG1G3b#Wec3Nn2}mz+bap zh9p7G2ThHcxxcON-64)hfR}L9|H^mAY@^koxwW-(WyzbSCCAx}IOq8Hjz2UTYZM8F zi%jm@&mH4qr+2(a4g=}I_%w)>ZKr+7bHO+;hs4HG4B%>L)!TmEM`rTpwSTZEZjZ}P zuD%ENR)TFM+sVulLG`k|5jz8h?{}-rJD&qOQ6>CQQWM0c7iYA~H95si3*^c7GL&zf zTUj$>kz_RCgV*0fe?+4a2Vk(UWR#e)5j-1bYZ>D2a`kp6+FLrOs?y6UTh&+?8wWjZ z`y$&hkcoPFa`oNv^$k5-YyjU!qD{5%b{^L{Exs8&PiQG?#1Zg-_xJaMNyQQDCFi|S z^!62JW#^>iYahK6f23b;YN%q_vl=g8=bAkdzj1C?KAgo(^J&GlYrX@Ap=F@h@9O~L zLLYR=T+khNH%h?4h?~$V{r5u^&b#~IZ!lN<`FfMCzhotzPG@JFUFX1vdNT^ktYUKB zVO#A_O_t6SZ=NlaB18D7XA?E#D%35ly<*^x!=x!hw*^>7&1uC7P_EbUwY*=@?M^ll zw13gALJDnE(WziK-<_yPN=d0`1e5Gu?+yK3?S&Bf{$*@PSz{Q+Zn=8TmB}xT&1#03 zlT)%pbuX>&jq>&3f;?@K;ogKd*3mr5Rp_1aLmd`V%+wt_Jn)eVsM#{|CFj=ImMMp+ zxV08ArxlRn^nOEg^g=T}j%KwJkmjEEOi?=h&ytl79#Hsw|BGjm4o#mi^>w4|`R`6& zSdE_6{Q9yi=!C7XRQ|5ut5`^5>d+zYG)q!3g|gz5dsM_GkwAgXl*S!!LkAL(90sGQ zKXI#2T>a1` %amkJ^t5l{}!^r_7xgnWf3oA|n{;Jw&5oA*Tn#n3H$Eo-uKWu!DrCHnX zOw3gitc95yLzN!ZnAz6GPNBiWfUCyA+i%D9;)(P*S4m4Nw--?W#YV?V$M8lLj2p97Ux-!Z6YlSqs?s-#RSn z^E8=`N@w`iyUG1i-3F7vV7<_hUt4m&RsJ#{QnE6nQKk{swgVG^RL%HW^Na<~CCbGV z15;rxESM+8PlB;XcjzKrLI6$#-}7uf@RJuc(z8qR_(a0oNAdY%M;yxpBNhrZ$}`YG zTo@tP$RIKs3QZV}@&^hNnnCv #m+E(a?FvbWNa0e@%5_Di
mnYwy=cN06$JB^lk7njCThuqQM0Ue#Vp(S zQ5HgdBhrK*TM!?28nNU89KQfvp|8>OL|kZK_YXrs-g9<}#MRT| 9;1D{NJJoPt`$Nb+egp!Utf&I0qDU(H^MI*x>@zbNJL>#Ma9V-`_M4d`IYm$BEzr) zBMO$2={2V%$8_M3b@w%@CUGdhMWcsZ Tf+4GHTLpLBX8`br!Zm zNz||6E?|nbgxTMF1Z%=yre0(CF%<5>qyXhGqOD-c6cemJ>66wVN}-p$78Qq6zPV-} z*6`*Oq_*dJL`Xw6!_3og5)7p}naY`o&vWBpiF_;9d_{zuy;WiAe`Ley!v$smlP;v^ zu 8Uk&n``hVkK#rPd z*D&?c-MT%$)? LyRgk)`olpD`)4Y=xFQd@dAQz1#1olreSM&c-|!@v zAraG-$Xs)r`2ug!G=Acu?lm7uve?qtx-DKBrQc;-(*Xt!6YB@lSjOA44cg%-(UPV{ zwJ;B5`aNOu=UIT?Y_!x{2`}6l7#@AOFN$a0@ndmtgV hC`^ zf#PF24W(R>OIKKGzu*Qjm?H> HtN#C+`hW42qF zMCgVApK4(f%IFfw;fuQ6M}+L20wR^})M$742SMy)Y@M?yy*b;?mI=zRRCMNHa1^D5 z>kqRfg4NJyxN Y%5qpop)d%0rR=Xl%NzJdS|12Bf5%0SO-x0T9DEwp-H_H; zp`5%(Op`X4;Z@6l1dBo1(~_LOhMQkxk#zb90+t4-Uc5@T5D(8fO1x|4x9S5><)Tix zHFASht`j?>i$`q{mW9)AWCR+1v|=OgUz~(i52$9TI%Xf=N<+IZG%-uE==RrT7x@8* z%OiH%0>8XDko?dyI_8$6Q{-mEsE{`(;C|v%TiNbc?2b3$i8n!uXH5se0fspA#IxTb zEhTdNXj}_!oyi-$(4*19 m~A+A ZdkhSgTQbf~!c4cO*f5J(YTuyA67Kae$7I^`n zi{CtgTMg+iY7Ytl^ch~zRpMs9#uQyHiqdfTZ&_7&73^w->C~b;H*j-i1hif$KHdhD z7#9Xeu?F@hzb-4HDQud%*aq$Is@(YZNjARATx)%qM*egoEE^d1HmS;6;5O5ZLW@*Y zgzfA}yJQlKTw9B#qTGJlmR2gAAtzj1@_bUAJ|a>My2dEk3mkCTj-|+q;8Fy^_Eq(0 z>pfQTW2566Ah9x$;16uXJ( DfGQ8k(C?XM)`d^PHw)V=peDSB^`H1)so;?Byj+JBs}=_y=&Y zqRHe@ &l8 zYPdc>@u_7GR^k&c-!O--pn^mBpvIhuBJM+FU4xIxJQD& U- zr;j7!@VvWE{H*)Y6Ko6lZ9bUjCxDxnNtD)SLOM(7Ozpk-^TlK;3`yF{T>=(QC?A4L z)l&;R-5Q3^8?Q!xtXQ*XNe3Gg+Q_p_{Qeg~Yx`YKa<)fgFwU5QD5ol8?akImkDnb5 zCyVCi4|%*{yp&wK(4wmi_*?3Uq{=4=jcxl6jy`2!SIY1VE1{LHpWYsp(_5Dsh=X zIF~Wtvz|aJcR3QfI8FB<=KCw*JI>&_aK!m9LMu{jbvfy0))m1wL2@fYQdC5<#lq#O z3bfYBLa&gNAfPi%8l*u8+`1>l+zO1*q`2A&ZJfc+@ Od28_r=CL^ AW?C$tERXDXdDi+HV$}?o`-|)3T^4)w+wR^(iXlsUIE$RsoTzGzh)3&*XvO zIsBoj1JdrM=5g<}i_6OR_(@1Q_Y1dJvoW(f|=pB0fY?1yCDRcMDbuX@W+E-CEAt(2hA(4l$S{@T^w+cpTx zqxkNcqKqZl*@855`g=zeX_2Ffdv>(7V|brWUvLX)jBOj`$qFcvEe)m4OQldy$-v3R z$xn&UYJ6>U?`hF4poP~}k|LtA{M{`}DuI`$m x>*iV@V zCJaBWA&kUnB~@3;2ffBc=^``6di5#5lEo>1j#pD}HRibK2?gAGNLPc~NG_3>o^h&h z&oER@%*~-_)#{sEthXGv@L+EW1g(!4ZEDbHhRBN2)J-fr3>qdWIZ9@|>2*O9{h(B5 zEYFHQ^X;#kIUgTzK9bd-#enw%;b0Jc0xqg4HCWtY{mGDIGC3x#K=SeIji?(rdnDpS ziJHW!(DgHt;i3e-J@c7FQ2^hly48tf9z^Gm4B2GS$ppWDORT`(^1QS(H4VNBc _58DLcp)Ue zWGNX9yMK>FW3RQ?VS^$Lg>7xvv$uHlLuiX~e;RGE9eUpLZ#y1pbmLVidU^8#Y=~|+ zR4IG^B7+fAsBA^5Oy;jx2SQj?l+z_AC+l~6C4SSYt@nL&L?YssR#HOl-61JED)H+& zuUXv3DoKZx{;Q+(0sjj0td?L?-5SSmYPIeD01mMK<^u&G50^2IK> zJglsP_)gseK)~2qU!V{OsTTG05SmS~5}W)vL;Go~CtSAh)6PI1aw!VYUC4KL1heI} zqP9olhwA#+m660G_5=D~eaJPhW_=Bj{njo&qoL B8dX}GtzBF4-h z8fqcU{>%OO+liFW{u2;D!0(kXMjV)J&)HSIV?_q_O_U;7J&h(Zb|W6MqSkl8t6#rZ z*XW&8ooN*V1`#7!)Mdv S-ef7z*txjaSXo6uc>nKOlYWO^Xfm~u%hR<9XZ4OSYl^;y1CKcFAF|{~ zxF0PzRmN3m0%T97%y7A**ixgC()U8>$c0;;dT8WJytT3o<5C_qMej!b;7+dCQ@4tb zk_Z13isGCz->&9lYrDS^c(KwR0DyApeWoHOC&z$;j0^mp4VndT7+vXlac`(vx5r0E zVZ4$Ki`)5zBJerzlX}MQj?~nBAedKzCY^naP|4IIFsd=Hv(6bDm2^+UNiDdi%7uSE z%R-J*W*gnFgX5A*Ag5d2(5kEf6nwfVVe*dz?bGX~y!V)b0#ex$w5#4%#xkWm!`yQ# zNJ$#t&;T-b!0E9y !(t$9(2^qEhjAgi<8}tY4#HFu|8d6tqN?2=yj; z^$m4~ipQ8})fPC(h!|BHnM5BK^c 3XvXHN bb`{p3RG2*|=B}lau?F+sCh(Up^>RCU{_E7??6(x585S z_)!AwPags+6l;yN&=Ox!Y c)J7o28WAAulgT`fh%%A>} zFD7nnXIIqMm#2Ww1)Sk?a=lw+p&F&$zi$$HhP9f_J?#Gh!4J}Pb93`9uG2>v!)94w zBsXy^(D511q$H-?m>CDN7<{}@iTN}cLktC01~U^)hd1lStt3mPV(zl+M3y5NDU|Ab zUOWgJZqzngwfa&f3U#9JS0?(`aL$FBK_YVnB!yw2I!M=eTVZI>p51M=>CrWtgBF-y z4sdAYEMe<=OXpB*8ENsj)Y8|yxElnluPk_K)o`P%z~tnS6n=1I)-o~!b~5q;H& l~oQ(Y>MYwGK1t zQ+Xd5J^|DMeY%^ESE&pfLP$Go_T;QW9KBM09!V6slx8K0N8(K^jSPCdTK%f;H%GWL z`jfyVfBe;*RI(CY0gWzwMap~f@TS(oSD6)#4F{{%+YDru+gH{}2f+u@sz~pv`P}n9 z&y69i9RS y5`$<@aZzF;|AeOQ$p)uOIbMbzQ#7z?F>1Qi&e=MJYyXZ9qf zB~wXSLBwDf#VMo^Ez{Urk-U_ldDAP^l}3f>O(6!u-rEf)L3@OLfGi;Sv4TWmr#ByT zRtm$ViiC*2xWv$^U+$fy!-`Zl+!kG_N`rwzKtK^yc&a$6i?5WT@iSr#Jbt~;1V?el z=>4L_XRsDo{EXP_$baiWMbBDq#bzbW>WF3LP3OYXj__=1V`(Sg$bS|g^Q_NP&&tV( z@O8?p8_??MJ(VGpchOSY=ii}kX>NYddaTapU9w=~@pn~ZCrmJoh;QOsUH4$hH!YZ< z1XrtB=jR&>P!x5rX;yF&WG7{)l06B=Oli};WefO+$x?P-CBMI;k<_D>%#+HO1fA$p z8(B%R29Ffc5T!Z%Zkvr!i<)UXT8M90#{O!+DKk-4TH5Y?dsOqlEXNnRv7!I|XpdoH zWn;z}wSOP)Y15~IvE?Cj-&d!31=DY72cj%Q?k~J+9ZEd-*?yL0ypOr B>NIs2lLX2>_X9xHO%ul6^Xjd>lWXtf7i@TSOyA`87G+#b&^ z?Ci|C&I*j3Emgq=2bB~q#jn2xcFJUN&t(cqz=ss#G+-1)z><5>>6Zj)5e+~$s$t8R zoxr->S@3D+*jT8wrdggRYZ6aeY2UvIy39ICt#F$8GczW1Dg1 4=DM)- zrl``=n8_2GT>){Q9W8`4@3+PdE{r>US!;~nk6xbGq)4uK@w_+En&K-N!iSsL;`;(F z{(ii_o?1H{=k?tZ&SdjI2v?}@|Mrz?cLqQ)^*)h-7zDkfD2%2!^=;rdL*XVTxLp;K zxAiX=8o5x^U0e12)!!r)z^{acVM`evoDQ3#FGE? tza$sjINh|c?<&q?u-VV7*}lQ1IT`$ z9fG1&xY}qjzTKpmvNw+^IX3Dz3)`I_K35*hplHG_=*>TzL%MJBqkv{NZ~G4~pZfph z0`QFuXw)3&p?OUf o}&KO(Yzayey1ftRb(As`|GXEv^` zANZWu`1uKpQ1QjAtf+k-|5|+hcn49#3^vo+m^gXa=8f7BeAj0u%c60sup}msvZ36u z;6RvxAwf$DL1IN1;_d8Wp*)ff`5BrF`LLGrua`&LN0pUc zOFKTc4ZzfEjZp8}<>Y2bUPWKtQ+nm6k7w&?#u$6k)(n5?OZ+K7#L=$K^N!8aX12}n z{0z9bWeK8)i9fExW8&hrf!%}52c!4+Z+|cHfR|lYtgQT^=H&ddMNLh~{;v-WPCJ6S zdU{&s)2mMe2+Qab&z67V1gW|<(%B)mc|J**jCd#8HsZfq1F&+}+EW~!HF+WO5ZYW8 z1uF4q%Gt^}^m|fwYufnf&=tJej*yNx#OrEM>nndH3s!uvlrCqJByHZ|eL?*)n;>20 zM5*0<<^Me@{|SflE3JozTN1V6ZhN}gmw!A^mC^f|K^d6k>$ZK)fxRXC{?QE%8=v}a z>wL+xpMPmn_KKC*XZk5kMeS+z=N7czF5hX6P?f+6$ip)9y tY9CDg;cI5j52Rpx|}$UvAxFzA|kU8%kK?D-_h3-rUz z+w2a_smW>f`O-VOL~kos5kjfE-TW1_01$Tmae?YbfuFO)E`Xz!r?U#)p?Z{KNX+ts zQ5)Vncqpz^TAweioQ)*GX|jn|r)2C)*EhXLg&t;dk_dU{x <5nT@FZvr3Sw?3ln?{UX(>4&oa{PUZa^Sax4DPk3RtRLKoHbzFo;mE|6AOuvb zT0v>VrcN%5Aqn5fv+u~B`8kF-!fZ%~UOC9B6NdWr%d=lV1+tmUmeQ+!Wh+aMSR3z| zAzcb6rD533moY_F`0a7C+nWv4-BH6Bk=`E#MR?lYnJ8Dyu+e-0LW);nfUOojIc%P^ zyx)%_Ty=U%$aCB<7us!{-ifs$GyWbAa;1k_3j 7XW+ zET-@rw7xwbwkCoKuT-d}BTinhl_MrH+JM(Y2s9@7QcwHi0?XnAl89yq3o@M{!{O+@ z2lM2f`PHUg&BM20K9j&V0I@3w@kmNaDuYPO{Hm(x_t(cJt68F(=eO#GML7rBIEkfE zHKSX84NA0lPC?P*7)+~*b; sAPhJsJ9?(=6n`U5SJ_OGm{@T5ZT@ zirCs-W5Zw7F&FdcB4pk7o`Pe)@O%?#ajjIRBM=Jk^P%HTn`{6f>s+5R+Ro0-RQ8d9 zF%=T&r>Dq~b02yvAi~qY=48lpWYSzjTq!%O&I{o$MYD|Uo;X%PmKhLa-QPBHy72Ko zt0+4;Infr>pg2la$L6)UCtwVVIyUp|GC9_i P+0}?c+}ahFVw!baADmf6(gj}YbmP{SENYA7oW)2azz6!%Yb)n$`@}Bc z3iY`QyDAn{0-ZF|?A3g$WVXTqQ|ud-F>X{KOe&bm@Acis*0RI%<5b Gt%;bzOYa{#ryXiK(kq+~Q5Zc#ehjk&l=LWukQbMS}wY_xB)&jaCkE-vH&pVF
)QZvLP2DC9Io=dYcPqZNQge hVw zCzQU%0Jgj{ov}=})Z*V!bzlqHB7_O@R9B76fhG{$p>~?zng)2`Cm;PgdHHy*50d{4 zTUuHgwhBotEGMX>#w*Z+?#@EA zd1<+`?f+M(KJV!0D9m~mS&RjELrbm>PVCcJZol 3o{+75w9mGr0$E zC(K6c&9Md-TL;5t-i*rLUa^>qk#qBFG7CwIU9LZJnwr6djK|^#s||ZH8T48cWJ~cF zfh}Ma;z`>}cGvGgvK_xg+bU3y#}DSjp+@-oJ9&rPURNTTwTWhFKQC$>J=&g%mo!~_ zIhJ<@b#y`C>Yr2Yur6+7v=fzUTT@|yhK5O|G8htHYb0hdrdeyT5CaXxOw)!|9SzeV zAC~*T`R9~Ele~IZt<5tpzbi$mHF&R669>O@P`u-}^^O^VZc7|e {q5 zA@OOGMUmXM-5v2Ic)ExXvARj(<_Z}ftr&e>o&tI6bE1a*W7X~GKbz{sLynFt4ZZdt z{br@6{$f&U{yOa@3&t!-fRhHzV6`vfyaPim*Jy>cgg2qA`2A~74xzcK44n#0OLx7i zSI2&UY6FZ~B>_G$8SniUmEBvn6+B&uQZD7{U!+-KaA#nu6&UXuZMT0Wnbc_0(q6t3 zSk2>@X^IPq>^z?AY|p;Lp7R7g@HYlgvq28aC7zy*7DKp*NK<%bHFlINcYKR-$`{DW z?`w$^sLJwo(TE#!fpvlE)@3+3{qZB^yY6?apAnm>C~qoWSHpS`p)|>(_WEK4P7GX` ztQh=Exr$3(fc%I7oPrM8$;ug|q(~B^lXgtM>5`RnLs#lx)b!?5Kq#s#aj%>@?d|yX z{he39eYxhSweJw5yCF)w|Coo5*1gNe+p`p1MLvMNb3NrYE+-yH9r#kF-{XUs6Mlw7 zOwA7aN5Bqd`A+45-%XO?crD#_g7jws41z;O&^?0=ubQZ0zZfvRuQP3?=s3~qDnfC# zgANpVo3@1EsT#cvOAj|{ zrpiDZ8xK?}i%0jq)}QrR9~mm&RzYe)< hgZcuxfuY`hagmW4tHjiE}09 z4~bjm6nxB>HO01o4K)_1I7;sB^S`;b3G>@e z5Gg4L1}R6u&hA^@=i9OO{gPIPn~CvZoy7NS%)(_jLXy{E0hg%;wP*tWrmpHN9q zn*Ax=fGPYQ4JO|Q;z>7Qt?|-?nyhr~zSM$J3`(Q@wdKy&8%SMO9v{ASmfrZ5MauU) z;uh52V3=b$wYTd{sk>rU{_Q_99+3Lg9O}wi0B@o$R-3<6MAV;NzpbygdCsEwDi^ z=-gHHcz1)WeO$e9nq^_cs9I&J-h#+u9bSSa_WV+*?WKoP{P0~SV5%@6&2EJ2S7uW> zgTK7J_Skp2d~-)gH=tXU@o-rWj}*xAkfBs)Mk`F+!en}pIIn*O>&C?+-xmE?Xl6fL zJ+ZpR_rq%?{mE;FuqL0n^ZCAW{IX=%efLN1mmK9vB(LJn@ $XxE18HL-E`&=7U$8r_ST}jRRV>G1I4T}kqMo6ZoY%J`MKq& zk1wvwYlxwH#NTB^SU)i-JGP5w%f(^x$Hz3U6H+Af2<2KW*|*7&CVQJJik)RKS$r-9 zl_4m1uu(72DU!GI3R2lo;1e=}e*5n73XdXrLi?;dULM2wax%B`ujCab6?S(nuYN;~ z(khYB!!)W)w9RZBD1^#+G2%`UX0iy4Bvb2KbbGt2{kcka`^mO?-emIVsmJ0(0Q*-+ zve}}=OtDr+b8`h`fJ}U2zgv%MBo~4A=-kpDStTjxg4psFMgQN?b+0^{D0EOzvTEJ_ zHbICAHPv#(*n9KXl48*AFvU%{g6|nhYU!E#b)PSF&$~a7v23LNWgU;9!SFB7PY1f5 z(8hi4cIhL)FA%=|d^`hRCXuwZo!PT!{H4G!oY}{ygn*%r8!xNh#o0fPpXN=!Gs@<# z$Fn*w7M({?&=!x!J0ol5kIcKC@G*_x*}|HM1Y_4h$`G_0nE(ggxxQ{=<5)@{vBc^N zyufPei5SMDr()kfUSVwP>B)M?Z8=adGfd@hD-ccOR#I=Rh-B({A`5&F`c$$%*+A)I z+5DGeZC44TkZVHC-KfuCviFWb0s=OZ$(-Y=pr6a((7rHCdv`<9#SlHRr2d9clWZ?c z t578pSm82nG3o{O^RBg%EVKJ%}98wqphKm=t3Oqw_S!$5C9;!nF}C+$xd zObL%{Ny-SgUeS2$Yu`Mt)S;^7q}@x4&SQ_ZC~O>Ey_@2Nac{nLJ|fAls7$$kH6l<- zWA^k*hCLO#XTO!ju@QwLE88tQ N1<;;gDjil?HN>lV|-o_L( z)x;k8q2owMuq?%@$ze+C?B_hG(UeJr^Kh}q(r$m-`HtuN(h`S5njs5(W(xSR+^X68 zeD8F9q!b`(VryH0JnfvV6S3LpGfQJXee`sNL~!tTm}X4MQI+#1NUdI$F^zKNSKJsh zmNnIJYfkNwSPNZ9;jiiva}FZ^?`(B5vXtPXC{$?HR`8auRE`H(xIlry_VQadW-Db@ znY`Ls#!NOHQM(43;5LNdvL{wn^+QSRz2Em$e;rTz*#r&U5gm%OS;*Z{@+fYe`DX<_ z`2# WK%(!ul&yyiHxXmX@ z)T*y^B;-m@TPGOhi076%VF$pAOd^xTxNzt(RcyLZDu8ibNFWF6J?#GNH17lVbF%N% z)9-Wy8|0dLs5Qnl#dudX |5AUb@;(97u~#b@VpTP`n4_&M2~0P)K4k^+c$9 zb{$E0b$Sx^y{rPNl`LWZx^P?Y%)F`PAHb47(-)m =;sI-1b`f|!_9O=zHeJnm_NQ$KW@v{qse1S7m43H z2y~Kz7>eJhATW3I{Kd|@g=l|;@EDbv>`A!H%g_59kj}gx=zC!?lSW0OZr5fCAkcI! z)>`?_ZdkRjo=u%+kZmdiUM?Ad!ylR|?d`Lq8&DO KpkN-EDY`zv;OOjBncs$O4&iHVzI6a|iy%z`jT1C9*waXE +1wo?Nyh>dgaNI*%C~S z&muVU7nILaqY8elPVoMb?69%S`y 9BXGZKPMO+xRkd&9@CE*S_t z200WEd2?auoey35;JoQ77T^|imEX;5lgLnUSrAiPT_m90Imm!?M-OpGg3nV6f7iRh zL2>Hay~t$0>j4(UJl^S!+vD`?>_TmNRl1ajLYT$iVKwd_p}&Kcry+6eWL9C6y1iKL zAmm$M5-1Eo*>XrED8?r@;D*|L8E;leet<1cufs(tgfPm9(b0< Ssc`od7OhhHepg@kxY}H{WyX#}=lccw z5p45u)~U4}C5&IS N zgQL%FZ!1bkLHqmr6ZqYbm|%cPAwVQULj%jGEM#et%)}Z(!RC4_HCY4;&TLf|Uf-us zH`*s^=E$5acnlvk_Y6CP`EY#;?bxT+E{amE-mH+{HIWc+K+GNu#mbt9oM80vhy&A% ztdLML< vEB(&?j6rU$Ay$bh@g+a) z`xS{tTiK?Tll8}9&Yx8%BnLp9tjUI|rf9LMmH9Ng5{W4T-uck;Zv<96%rH8D2J#)* zb`yBYFIA{^zCOR9VCmaD6tqhUM(YJaH7e+BP{mUq Q;3gK_VTb9PY z%g7R1aXLrse-+K2@DY-E93AuWd8bm0MY@?O`4Wd{2#|G-0@4)H2V>T=Ek8#L<7ee- z?tc?pSd0pXx9q$uZb%gl&Gu?e|9XDojdWLS=Bve2#cFed6MUAaz_qcl&%KhKlQIp~ zqoCk--!BrNmLiQ&73GAGtG;1CF5%*iuv;}}5B>(Fhkh8`X_5bs>Rk3^?AeP<6dWd~ z8XHuSHQkzuRI3S>jn_MVIv~OrgXHXPAJR}RuY-^ni7ja7j>G>)_a@kjeFnuS)|aMN zR5qVHv4Cr5u(egO)!nUuZbQB-jU-lmGJX1wp#g*k5h*yu$Xr%L@@v&u@FlmAyz1w? z@x}VT5 C+3NfCwdzRY!x+d9n06;b|;nC>9*AnL9YE%;pRE=3) zD9UU97`R@R12kA(w&`j+J2Uszj7xd+n*9+C(o!`doA=dhKs6XLcG$Rqpp#o{r|Z^# z2B~fju-CVwuaRAUa-;C)q-G0wW|XZ;iK4@_quof5zHd$B-FbQvHb(ftLNS7Za~+8e zx3av*U<=)+8pf9mh1$1wN4j%NrfRUfOHcW)NbPnvbv^*B&PVhn0v+d@sOCP!!PyT@ z*P#`pwvRhCp`6a<$^Cr 9GKV>8-6Qr4QR@&OhNQ}$$s zlS`f%8j9Gxo4bEyt7UGgAFHPk2s`#pw>>VdR3AjK!*5W(ywR#qFBRg-4Y$Ip=#OmD zkG$F|OL8W4tP)RFQ-)2uFiwhK-!A___v;(8hB!v`4|C3+UoY1;yuUm1DWg#4u;Q3i z4P+Of;Z@&9KqOeKr{hPUl{sb5Nr+>KW6VM@p|~BLY=P_i%Aa}kS3UI#kBRtKw^5+1 z9TOf<9Aff&cX!tfaL4cT;_jIZO%-gJRLrM~s&pOH;0htm6;52vp3BCkLfP$+JTYxT z!l;~lbt#SpV(f|HB1FW0AA={sM(3CNARvZeL^=0_hjqc|mQIj@>c}9fa4`nhP!(_^ zf7%!q93x^;mdjC~xw*S5Fco)u-%^2cD@G+9n;m=0=~n8Dtc;CGYW3u@`FTK9B)~+T zSVb@!r-H6P_yVS{iL734 $(euri1j0VuZqMWqb z?D!0O$9tM*#2O=Lp1TXG$Rk-S#QhnK;CKT3(q)?$$5x*9^R?SuI1aG;+GDJtU}Pxi z?%ax{zZx^AL)LOPS(Cf-wO)~A#9-5<$x<5nUT{E#Ltz8 l>py{Sv-;le4#mo&^hJp1hy{2hI#tfXS};7f zIa*KSJ8uGp1q9SC4tA!1 We!ee n^S);kMM{UJpXRm3xv!iOUfj(`Vf$cGpbb@5-ND G_&n<&Hx1k<+UG4y$UKb%aFGm2&dA5 zt4ek0m;%*Z^?@|N?RiOX=z<&MMmNni%RdAn-?w;Sj|*V)q26Y&1fRqEroTa~;PSkn zR?rk)Z%e)1Eq;o0wk3;O@g*sa$^f!`(KIH|lTYqZ;j|o0OQUc!=w$L{hJ2q>0&jh# z&p&szy~9^j^xr?(y4orpO?8qOCX;+qy7UKv2*qGX-(Um^sO~aDx(lGCzld_+EXcu( zsQ*OdY#r!%B*WG}pxQV)T;95UHLEkv_~<3Y@;JI(jVIdb^7L%+Jeu+ZaoyC0X~>Ij zBs3-0K8U>7qio-W2{_okSzni-M-Df6_@^^@*psu_VZ#E0S8nrmO1!&KqE^{CJGj4- z$Q#rQHumJ(Z(33k-a@#Y;wgD}z!}CLmv6==6*V79h{HhroXX)#`{$^F$l%mR`Gw&N z4>P=ZgT_u4f4+VG*$B*mDD4pPaL?|}El1gKL;$u`j)aSg3;uTTk(bEucmoBTx?0GY z_qU9Pe!ybgRxp>niK#Iy46R5nJNlBrGhhAJ_|^1%`xuxJ9~-WArXk1nn8hz!sGe?* zoe#@40bt@Go$H`novk6M1 kx3Y6`PVV zd%OCXF<0+&IvP#~vXH`ewI+7D zQ^T(J{a-FX*0brn%R}v!_{EQ(U$ZiW55E5~5@>kR>;^hhm|G<6RN?1HB2cu-eUbD- zXm8G6csq^|C;MB+JzN^Qq0_bpw$ZlYl0Q-0s)!1kwVI0b^Q9Lj%(#=@)RerKV%5A< z&+Tu5bbRhJ2BrsvfB@ox``yh*Yh*b@y+c-MDHReS?{KgGYk6%g6# 1y-uOqNc>}n5gw?b7;G#MSTehHuUSanB-FF+Z>$I!9z4tQ;dpnB9}(B z(^ZzV&2D`(bbxb*zLdMmhGiiV5`KUH*qblSuWg=cp3dg8M#VGLGD6#rN9n5Y3W2Q5 zq95Y7vg@r1%ozC~-sY^5x3bC(_A5llkO_5iFi~b7`Vcz-w46OcMFnkfF;()fUm;@v zXU+hkL&mMrLdBwag4YuacOjDLWo;qlX%%ttdirQ-ZqeZ=60-HR8vzysYUq5M%yxZ7 z`33uh@eC|?yjaPidF$qcSFUFkuXT47k^kJY3&E+l(3972Mz&!3L`VO7g&l9YPeu=( zckbUPpu5 O;n+*L?hGl)65TeyLN47zaNhRD*);IA( zXc@xy0mx$HBVBAGlYMVKd{QO4rPsQ>;i5j#BKxhVSwD|c;NQtqMA29UN{7>$v1bM~ zO^poduV1`@{`Hk|xJ&PgkTT9fF*tHee@0{d5W>yLQ!2;4H3h0us&VY{D-gZ5x3yzi z05^~h3%=`EL~%gYQ)O>&@#w{#sVlT+BVB0z?UWz7gNpCPVY&J%(fUYM1|)0$9p}hu zxPj80g`JL`1L;EefNAu7OUE{@g<%Jc0AEhqGI*I&8^ jNP8hOsd8BEE`hP);tf7l|v{0u{v zIU_~+o>ugeN6{uj!xcjD@m>a*jLgOw4fi%(@LtWutm-~rm IjA^W_dyQV_dO%|R2^_;(ki4zibWZ3WdY^R^hCd7Uwx8w=_ zBs-_uJ1$%86n*mDv@a(&zrfq5-=YcF!+#%|oW(r~O}|7$Fg-| lCZx(1Vz>24oc` zo{(xV)3M-%1iva&MDF1}yM=J8!c~SFh#@k6sObpN;hsLHz5jmJO23@{%${oY_Af(e z@P_-iRhNyq$||_=U>IhRZ>DE-@zfpY?9uU5oU`H&@oS^PINlWEzG(taj5iMODm2M= zo4qNdp ff)u+4!e#wLJ>Js9@m4Zo7w60Le=OcSY=FI`aE z(G9~r7|5ZkYZhag>F94PSC5844nKW8Pe()iGM&!CZ Ecdz zFwbV9asosYa_iLLzFG1_$# JTIv_H}e|F~&EQ_A7{o;HV z7-q^6J0G%y=svnK15T8}zd6+6fg`#b*s~v`RU1+B=i=~l3Z&k#Knej!H9{yE!{U{c zGiIIT^TZpbiDjm*dfdf4yR0cOCfiJ_CVpd$CFi@cN4ZiErx77k{Wo3mGB4lw$hH4_ zq;@iYnAe2)07MB1dH43p&q}S Ff2pNK&^C7q^ECL0_7}kWsLyx=- ~5lDpko8 z@RPh}y`JJMmne^w3Xh2J&3=O?A4eqzsU!)K5x5{>hjeY0>gZ6=(DFocuK4m?m!u2~ zDw>TZ%ds1AM}~T+g?XN=KQ^wFX^eBmQi&kTg!tF`@YQXP6x(0u+8Zj4Dwcmf{qSPk z(eup4(9(Jy&v#XR%CGf&M0sx(lY4y&px{p}ltCpRVdK|WrVmD$t@_k8>EkxvT%6nV zPgXuwB)YICG7$*x@i_bq8s&+5&&{L8#bZp(Q%f~cqY8zV{!O=#C5qcjL@O*q`45)8 ze0#A_>xRSG7}?f_4FK}SN{1?+wg3)45ZKLCZr9ynF0@=>0uW^~(zL~Wv88^E@At2r zb}l~gEi_q(si|F!{M$uh?O=gCgb`F!R9N+t#lgx-q+3-J(F7u|`GTJ4wz&+{jRGVp z2KNA@JYTzHP*akDk-_0a7(c!Dv?TLezd&2B*RSqac6CP3nd3`UGTwtxfb(HJfx6ZD zUCjAoW?r{c_$kRCN|Efz$qfc(X49x}O7ss6F7$3YT#%JJUO;f{2s;V@WU>CYi=n^2 zs1kRWgu`sEBNRZT)t#Nj_Rsy8PClM&v?)ct&hZLkdn9kT`dq>rV$QNZ8As5UCmZ %ow49z!Rkk(_ggF>(sl#?wbFem4?Py75A>^ysFk#Q&rU8CzWq5xpE} zd-{K)2{c5rI9FP5;Vy*?A(ZEJHgI3dG2=hilwx>zymf9ses8oMg;>~*rv3)g_E?rm zfcclz$2)GfK7QSrPpA=*$L)7~f!*GVR;6O_?_u+X9Vz2dCVzf?v^zr$d6}MxIxi{t zIFaCy5gjmvOuOnL#u9!s|4`4(voXGw>sGK*jdB3&Y2U1Yu>q0sb;S_zH6{?Wkd>7@ zC21lLpr-AGVlsjl<>d1&wX-@QRbiD;I@HUwjo_f>-@_w`m6c#pV^MGmu}5;-vS)Hu z8Y5$m!f@G2YiY|b@RN5B(In@KRCXaY6qQ6@YNu(Xq^OumTO35EqF0&Rxg1z`IiQik zkb&QmLHFra0 QBqS$p_Ng#fc-Q}hGx-5+kA3;rcWtZrA{o( z4`L~fyiD7IecoHDk$u@8X_c4!gJZ`ujVl*k6*&Au!A9gIdY)yUEfI>+E=leuGe$2z z!}N)iG&y@g`uN{HffhMhjKvaU$s|CMY!oMy1A=O?n8T&$>;D}bICJD$P_5LhD@&KO z{hS`wjfbvaUt3jRZ*W?;WyLr=(|MmlVGH=$S*uKSzjQRoQ`7#raX4v%UVb3)^&_K% zh|)R6SHy~jr4qDLz3jp6mpf=A?e~Z~srcup)XNiQC3GdNzZI=*4~t^FCvdM4Czt9H zm>-N=A~|VA=?(zoF!VY~t*DXW%Cf0AZ&b)nZuw%;kXDsg7bt10m6B4by~D{1*<#rP zf1t5>aYUY+921R*((q69235wzS)dq;O1h5m07^-)@6A3)=`4D(e&=0Qy=iF}efl)z zBK^(Uncv{B1GCTDa4k_tll#DM+SatH$jPQ%$%AP Y)`=dw5@H*WcBxeBWn~xTiBGsX#3MZ?)5ZQ{)pDh*T zJr%MphX`$=qO4;IYz*lj3S?WML2BvKF!$!&U*w<7KV>buuJk4+6LOUnYa}J?a3uFR z%d#8h@{C{)MKIQt=$WB5Z%5>mN`ByKG=5}Lx@ayn?|<`RSSG#>jTrcn{5m;3n~5@} zb=Z9TS=;u3wl>7$ybn`DF=4DZISa}t6M>zUR4T*BC!xmcc8*vGYG;ny_{l$goN=M? z98LJ!j!PyYE-_>b`WZH$1>$5)oo^z{I=#UB-2bFpdz4sd%rDcIjt_4=?rVeB!m8 zX4#vjHNj8TLX2QmC$@jQf>6qspYUu{XnTGUGVx1lT)j<<4Ut^-hSvkg=TjcV8hOuZ z`?Cb^`KWS)vm&28nTNOi`+n4PDEaHY7FzMgltH;Hg4{Dv1)iSx3kHFb6iMFIdd(4+ zspU(nLIi`_?x|324&-~|ImG$)l*+~oMv5$kNuOit_NI9f?vEe%3J*J$-QgbYY$M?x z2(*oZLMi>eH(h=|5V;@WJN^DDU;R01>7*^8_hQGbOGL`*xH7BKSi28ol{=oMXY}5n zEwVR%baNa>yzkOx>ZRsQ%xN^7)zKEfy}za1^pI>aB`Fb1N*yrJ9^@0IA(=f`!zG;1 zR0&HbO_IOJU;in?2`j^5^S-^^i9RE%T7 BhsV{o2lZAVdy~DXm+b5C3hf0w&HmoG<$>GhlO4rxc{poX-8}^P z=Cf9AO^@k6e0Gx}v;NJ?N*XqVuRV@aULI?{GjPS{to=!6)~$=&*%_>7;+vje<*$As zZQiueXSX{EN;n@qXg(Rg;X674sR|<) z?dmN%9~{MsnIS*z2ee()%=z3Q z8ecAbV#WZBEU^Qbyu1hYPn0b#7blK|R+_I(Qmf#D%z2w|oK^F~LFV%m9weWq1rp&8 z 2)}XOh5b1!!waE_`5R<+9;pm6C 3-zTE|%f{5uJ=S6FKB_m=tun7*q3snxB-{l^qEc@aKq^ z+dAH*P7^Jih}M2#eiN2vfS0q_$KBa{CqMRY&wE6XV5+=hoIXK)GfQb)YqC*F;(YTz z$ur-o8=IeI#eiPj&iI`lqb^ zt_wAtEv~s;i&!PE3+}Fz(hs^Yk$~MnDC&m>1r>NfDb$EKS^*Ad>> Wsn%6n9)ZhFvit>a5Hr3@|%RXp{v zw*OuZ0v0v25D(*v*VdL;{-);=3lDh^Z$r1?mm@rr#PNKU%Delwin(#wmpq`Acs==5 zMKq79&pndo$&!k;Ho^NMV)yK4mQm6Y!tUf!%mtkWj12Q=O?7u*gjl@E^ET_<)v@pA zFP#p!@$>E{LSM97an=u?y@=1K!YRL5m?}}{1sxgL+8&^xyr0&c`!WyfWll^_Q}fkg zK6hJ6S>(*Werq%^VxwWKPN%&VNIrfi0RW1JZ7|AZh7}hA)f;|<5)qAL3a0!XdH>|T z1C1rq4N*W}5%VhfRTL6E-qGFlb%lS%N=y4=bRhsgIeB1UjJA|J|Jvtvi`b*wFh5ZC zO`QMf*u9QGH&o~`IHf -eyYAGDkEt0#6U7U>spGpnSUaW@>)H;MS{v>{!UB8USAhc;7#V!AQYqD_)YOH}O#92kArPMo!EU8$-eZ zd)bhYTXz(}_Yf`7r|-6wWB;P2G^ocD10{-FiqtEu5A2nS{_v}Ex8-sl>r{6>`DzjP zXX2M}cS?xOR>AA{RBlgu_O?viMQ_86K!;*qV>pE~ej`(dk&_Bq a?ALW>K46bt(<2tP{%ZWWC!05wgtM>{0$K`i^j1Czn9Cd!$bRHeCNBhvXs zF)=BFfd&r4`CkrV3qF)UUI;&r JT|mB4W3-_8`mq>HvSyD+$32hmuNri67~lWjwfl{xERzWD%$Xhj%b_&tWn*d{%ur zUokLAdA+%jR1_wfzX5CJFuU${X$t;)sPb%*Pf7i%7T_U}hI+6&Zv_aryNvDY1v&eO z9JFDQdfk0$f|#Ew6ENqC$A84p*c_8u{$p6v@lMms3I&TyaSz>mZ?P0D=*oD=>#*-@ zn9mV{B=hO`AXB)uE%?rWj0~yLxG^{p&1*RTRm|(y{BfvMbwR&x`^s+Nx0!?=4n;}3 zL%s4h+s&95^KR1eBxn|fN9#g^1$iyV20*5(96RUy<|mfWr{=ffH=8Q5sgbY}eNW6N zv%gO7&_zT BN{3W>@8!@{Dl~WtgvZ-HB%o~KE1V! 7q8tpEWU*Mlje)7g4 zh4#cK!I$A9I@;No?xMo#yin91QPC>>B;+x8P!6^~{Az$kOu9F~5=(^ZiOG|)*&In$ zt2OD1AZ9+XJnrLp{u!h7W;4F^7_vOCg^WPvQ1D38LeUleQ@N+zd|#7LcVkKveRlRD zI4T*)6FX+054}QI!UoIF8zaGOPuqr-MxA*gd{W!RH*3AID(fVjZHY_I-bi`Ytf)2P zF~hJ0L@1Ur?#zSsu*m4ddt5Lfp}WQ5V0j|Nfk?Lu`xg#DdH&Z)$=1(*$~qd7cbFx5 zw|1Vxs{oKq|E-;R<{tr^V%NH~Zz6=^-GTy0hY0$a>n!Umk9->{4SNi0I@N70{i@rJ zMXQ^(-fSANibAE%_lt7tO{J~BITcJ$(+IG==nM$&%A$Z7L=5c$Nu(Brj5zpi$?mML zjK}<%V%A|1){-{teU+9mICcVaXk3%Gd9I$G5yZs~|5OhFIre0IcmqU32UWoSsXkn# z`E%Q0<48R4qkgx2ajc30TG=Q0c%!dGTQC1)0mzD+eI!0xSU~8I-xCuNp++Ud(1SpO zS($=szlLR8l|?<>cW8t`8W3}H9yPd%PXQvTylCRL1cs(#%MIto@%>YG!Rp(8hd=&7 zmINiA|Cz6P9~g1AZ~5c5Gez~j+*7i_uB`(jL$0|X*2O*}ri#5mpnRBV0bY U8~TSWO3$TL9(|jUZ KI|Jh3MtI3noRqcb|~eID<+8}ZEbr_pySBddMzL5 z7pinsC}R&=`j0CP&vyzOK*Et2T9*!hrlKon2hrd|4(>jRyFZ% M`b>5+p5!wwgn3?KNNMOX^1aay8>};2fp x zY)o%{zzAb!JGv%rw7$-)p!3k4)Xs<-S3zxc#QC|=NbVD!hWIT70kvO9unY=Mk%nYQ zoNZpFz>cSV{94z4q^72MAggCO{3cTAQuaq})aX6})93z?^pb)*O1m$%psXW0Ki^Gq z2kehtU;puNu_0}bIuQ1<)CX6*R(rMv6OxkClzc-6OGu1MzR55#2`Yyv3jgW&s=VxS z7G{TY_9p }_eY^>gomu_4G=i!1B( zQO~g+Atk5%`(RNfi7N`VO+*Oh*sbHq7eSnCYSM`FiPq0Fy+#;3SU?@oY(vMkyqqUz zW}F9vBrh+Y$bnTk?#|b~O$?U%QwA0ajM@r&Oeql?28b|$kQlyMf5TA}f^LkY|6C;h zeEl& lnH z&TpF$h9_I)-|aU6Eh;&-%%$;c$x_9CE1nXVw|Z4dAG}f$WEd@Lvw8SR2kSimNIE zJ}rLjPYy*@rSc{>E9`V9cqmSp<{HrR{I6^XyTR{FxnZH?%+)-qcE71sD C3&`VCweW&Ju z^;Cu%g(om1*nri*akx|;`L(_Nk`z1?makr*Elp*kbY{=7^v*#BDMXHYYp3RBxwnR^ zBiF;wD={fW<>ZMGeE9?OUoUC-i#$zH`JFCgZ|mCjBgwcA_k=vqV+s_wi*G?TDr83g z5-P(S_H^Zwrz1{ML|*#!vue9iXA~{s-9iLbnEgfxIsuT!7D#!qM6lyg8+c@}|M(iY z(Dm84y8XOy`8@L3OyeV^$n9GIrS6c2p2=XrQ@ge8x6)rN+3Bzph=|1 XM zd0ApwQup 57GEhQ$)Zl;3F3hi;zk>INDh1!r;s zz?Y=rtkXK}7abz+cZqO={o=ciYEXhp%F!7{4xGWgKaMq#)hjXRg0tK^Q(4mj$UpHa z6~A2l&^z6wPdI&=CJn1}sve!-U6?9TzbKXwA&`8FL69Mo=Te?G7QU0G^w`y|>i?iA z=(r%Q|0nAh$kDBW`~FE@GD|Y99hJ4#*;ShA`?vLW9Ls{`Gk4Czk?YZ=Z&g=(hhZrq z8!#S1_Yr13P_&1go~E{;g58fxwPK55WIXF{KP>J^5bo^9L(gJ66klURlc0IZh>mvq z)fUPw_kD(koR1dqOb%4q%xLLHRvXI;O(p0x6L(#tQRmzxL0)5$H~zDg9dYGU59F+W zVFQ!+Lyb;b(f!o$n9w+|=i>~a$HAb6hE&?kYR*t+o?o^;7l3uIt0C^d2eRoleT#!x z4nwBC5 hxTsF*8Wk9|KDC%_KW zgGq^pO0W{#_r2bNp?oJP1^TwZ6o`W5k>-DTO!)l<8 #ShRQVXNs>kZ+BTW#M3y7-SebFdNEo+KkgMeNbZF ;; z Ov6O0vJO^ YlP?bSym}~98W=%$Q&nKs39gEY>a9HzWB3H>^9Y|t z? hp`0>$cq3#BkdMvZogDqqI zqUB6T5I;Y6w5Fyhgr_*deEQ@1dDE${YU(ddh-e*UPxu^3=r{pPC!QJhDMFMuJ8fHE z200aIn*Gn8i7g{=Y@f*O_N(^?PFJxT%lT7USuhoN6)4Ur6tTBi;!@6IzAe7ZY0~Y) zbx&lRK$1V#Q;=jH^{F*oB!8sD&V@F^B!DvV`$4A2mC?59JzAs6hSPaUn%;ngo{`M> z<`|1!SjS7Tw13`IT p-sq>ZZr)d+*yUW*<0WhdWK021wKChU3_Al|Z=FSl(oW z@3rDXj`IL_p=y72%!^K-r?BomQdwWd4C>_?6UNkN%5!1Phb`rgY&RG>GJquUxOZ1t zQI9jd1?^Y=6yr!ppP)MRpL(C&iF+4)+LLSEn F)udo>0+?d#Pm@M`vr?rzuHOgS~eV*CV~;2R#T+aWl@03|Q)C6l_k5$H{Q8 zpdV8i?TfVF3t&M6Io{LvhErOTxY3zwkPhEd2lc7Vft6zWLv4Tn(4K<5GOt}a=T= M2yM9=8pK)@{fn3aj&Gz%rC#}MM;Qw z?@A^{9_-O^q)yRf?k*W?g>f{8(EIQ35_*&uC(BvPh6JlEXIe(}leWpC6u#R{MU{Hx zueu*)ClJ}1K4xQ8g6q<=@8tb?T--U2mDipa85nyvlF?o~;%S|anoGC^mG Ni=I>+X#4{|R#3Dky!K9m@{YmFrLo(@)f-?4rVpTIQK$>g++ z1TaZBKF_TNgvsDRAm)4E btmck?p#!%+gy}JSIvb79o_>vm}@x3{W z&){BabTaSiF4dWxhO|f!dhER)cQn%P^duq|JSuS-e1(Fu-_rqI`qTkoyl2Iho62FB zs9Ss0;?73bweuQ%qvnT2@2@l+if__B1j2h;6a2a-7G0Yk-H%rCH;djZhuM6uuv|Dt zq&lp~hf2xXgYl6f0p%)lV=!MZupy2J{g;Iy>9Ag9$**77rGQO>lsz$1?%rOxf8rQD z@ieqj2Xj>~bcVq6+&zz4O82JYiwc)HU4jhO%^X5%&1!X~MciYX!s$9?Ucb~qfXvNu zR2noURkqPF#gg`wUHt&9xqay>R;Ll8U+~HHL}sI~oa&2XH>v+BQ!l{Mqb6MriO9fa z7U99pz{fu3vRZ9>`}<@%+_>Ej?vcY1=3Eeb>qhdI(3NjLED3g}N||10!zYW(i065- zIJU`nU_Doxn4G-o9Xo5DCik;8?=2?r&mB{Vx6qi~Sy1H5Q_`wrLPvm~c7rQu$?Le# zWDS4F>%{UgA`baIZSvG4DYrM892CPjOK=Fgw#J|2;w23GTxgrRL04nW{KB1##XBtN zH$do(d~eLA|30ysv?a=TsKrX|ea1I$V?nN^KV0sBG7isjo6e(&HfZ#i_(g@sWYqZ_ zV29wv#8%qhWn4xo(%0>b^poTa?Uh57ZI#(0&fpp}(=XT;EdCfG5YOViLN;@lCs2fx za74J&5Zw{wDwqQ?SIGXigUNNewM8Plv&km>ynLZ_+Ki6M>T{b_-V7hd;du$zdhhQ= z4l2iX#d137LmC;zY^r6J?ta+Cm%9 c(=5SJ3#72lHF zU28$5xhq9O^7hPcqo*tgBVI$6qOgXXwJ?Fgbv|PI7Wk#y+y +R^vfUJa|!Z#2FAs@6MpU#=%D`G$Ts(rN|J%*&Y LXRKnaH;9!KbSc@ckCF9m^*OhKLEXyzWSKi)ctTn{Uzmx3BL5-ZNQ?zgH zUvku)r9F47lkh6fPbenlH}RkOV$VAX{(^Rb5-r5FRy$0R56&o-{(?KXepH~^+IRs0 z06ShPFAtz!dp@~+D~f9z7G+6gKl?{HtEvYLyVDVvsd-ZwB^%nJrkaZ!vyTQp&Na;X zO{k_f5xjm%GrP|vjzX5YJzvt?&T3H<>tr&<7mb2l{6U_r>-ArD!PE&?ip|T{2;1vE zHXV1pmLDEL)=+a+0}Wk(NRiZ6TnQ-(>`fj@BuA>%+nKw6>2<6~L_`G~bFtS;>2j(T zG-%ry@kv}&G%tl5!yGP!ThqMxvK^##^aEF}bfyb3tMbaVssLZLz7f~_*?@W}lbX7Y zFub3kSo{4itmtuOka|hHq5eGxFjdm)Kr27&5`R>i@Ka=n+rYjj<568X%VY|b0?(?6 zLTnRlc=nbffkG;Wl218{1OB_vU 3CYP+-I zs@UQ2E< lEC <%+7yG zB4EufaEhnuR*>A~bN )R2bxU|t7>wu?|si#h- zAiP=w%DFaW@2#Du#)i{=*`>be$935Z(H^sXa`JDLm9&J|aMxxfB{g~;5PIYA-ycN( zWh}+w={3EC8>h@NjyJq=hLf$O%m0_j^xo?4OoKnmUPMH2H9IdINBoz{d@80;$P@i9 zt@&&mudM<7FVq=C@_&Hl1O=+K=Kp?2-i@L_?*B%(eEC02l)wM=|A)b+zUXnb@!3 T5@;_?#9k@MsmoTsHx2n8J~FtE literal 0 HcmV?d00001 diff --git a/资料/java-日志体系.md b/资料/java-日志体系.md new file mode 100644 index 0000000..0b86cb8 --- /dev/null +++ b/资料/java-日志体系.md @@ -0,0 +1,420 @@ +# 1.JAVA混乱的日志体系 + +--- + +换乱的java日志体系 + +case: + +SLF4J-JCL + +LOG4J-CORE + +LOGBACK + +SLF4J-SIMPLE + +JCL-OVER-SLF4J + +LOGBACK-CORE + +LOG4J + +LOG4J-API + +LOG4J-JUL + +LOG4J-JCL + +LOGBACK-ACCESS + +LOGBACK-CLASSIC + +SLF4-API + +SLF4J-LOGJ12 + +LOGBACK-CLASSIC + +LOG4J-SLF4J-IMPL + +## 1.1 JAVA日志体系概述 + +问题: + +常用的日志框架有哪些? + +大家目前正在使用的 + +| 名称 | jar | 描述 | +| ----------------- | ------------------------------------------- | ---------------------- | +| log4j | log4j-1.2.17 | 早期常用的日志组件 | +| logback | logback-core,logback-classic,logback-access | 性能由于log4j | +| log4j2 | log4j,log4j-api,log4j-core | log4j升级 | +| Java.util.logging | jdk | jdk实现,tomcat默认实现 | + + + +开发一个类似spring框架,或者开发一个组件,如何选择 + + + +选择任何一种实现,都不太好,不同的日志输出不一样,日志也会打印多份。如何解决,日志做抽象层 + +1.1.1 Apache Commons Logging(JCL) + + ``` +1-官网介绍 +记录组件 +在编写一个库时,记录信息是非常有用的。然而,外面有很多日志实现,一个库不能把某一个特定的日志实现强加给作为库一部分的整体应用。 + +Logging包是不同日志实现之间的一个超薄桥梁。一个使用commons-logging API的库可以在运行时与任何日志实现一起使用。Common-logging自带对许多流行的日志实现的支持,为其他的日志实现编写适配器是一项相当简单的任务。 + +应用程序(而不是库)也可以选择使用commonons-logging。虽然日志记录实现的独立性对应用程序来说不像库那样重要,但使用commons-logging确实允许应用程序在不重新编译代码的情况下改变到不同的日志实现。 + +请注意,commons-logging不会尝试初始化或终止运行时使用的底层日志实现,这是应用程序的责任。然而,许多常用的日志实现都会自动初始化;在这种情况下,应用程序可以避免包含任何特定于所使用的日志实现的代码。 +2-实现原理 +org.apache.commons.logging.impl.LogFactoryImpl#discoverLogImplementation +3-缺点,只能实现一种,通过静态绑定实现,不易扩展,适配器模式。 + ``` + +1.1.2 SLFJ + +``` +slf4j全 称为Simple Logging Facade for JAVA,java简单日志门面。类似于Apache Common-Logging,是对不同日志框架提供的一个门面封装(是接口而非实现),可以在部署的时候不修改任何配置即可接入一种日志实现方案。但是,他在编译时静态绑定真正的Log库。使用SLF4J时,如果需要使用某一种日志实现,那么你必须选择正确的SLF4J的jar包的集合(各种桥接包)。 +----基于OSGI模块化框架详解 +特点: +动态加载、更新、和卸载模块而不用停止服务 +实现系统的模块化、版本化,允许多版本bundule(模块)同时服务--注释,很多三方jar中的MANIFEST.MF进行子描述,就是一个例子 + Manifest-Version: 1.0 + Archiver-Version: Plexus Archiver + Created-By: Apache Maven + Built-By: ceki + Build-Jdk: 1.8.0_121 + Bundle-Description: The slf4j API + Bundle-Version: 1.7.30 + Implementation-Version: 1.7.30 + X-Compile-Source-JDK: 1.5 + X-Compile-Target-JDK: 1.5 + Implementation-Title: slf4j-api + Bundle-ManifestVersion: 2 + Bundle-SymbolicName: slf4j.api + Bundle-Name: slf4j-api + Bundle-Vendor: SLF4J.ORG + Bundle-RequiredExecutionEnvironment: J2SE-1.5 + Automatic-Module-Name: org.slf4j + Export-Package: org.slf4j;version=1.7.30, org.slf4j.spi;version=1.7.30 + , org.slf4j.helpers;version=1.7.30, org.slf4j.event;version=1.7.30 + Import-Package: org.slf4j.impl;version=1.6.0 + Service model允许模块、插件相互依赖但松耦合,分享服务更简单 + +``` + + + +## 1.2 常用的日志组成方案与应用场景 + +### 1.2.1 jcl + + + + + + + +### 1.2.2 slfj + + + +![slfj桥接器](D:\shiro\资料\slfj桥接器.png) + +``` +桥接包 +slfj-log4j12.jar(桥接log4j) +slf4j-jdk14.jar(桥接jdk Logging) +slf4j-jcl.jar(桥接jcl) +log4j-slf4j-impl.jar(桥接log4j2) +logback-classic.jar(桥接logback) + +参考项目:log-slfj +``` + +### 1.2.3 日志切换,适配器 + + + +![slfj适配器](D:\shiro\资料\slfj适配器.png) + +``` +如果当前系统之中再用jcl打印日志,比如spring4,但这是想加入slfj来打印日志,就会出现两类日志输出,如何既觉 + +只要classpath当中指定了slfj适配器,包,即可无缝江源日志输出转移到slfj上来 +jcl-over-slfj:转移 jcl日志至slf4j +举例子: + +组件1:mybatis---jcl+log4j +组件2:springboot----sjlf+logback +组件2:shiro----jcl+logback +默认:jcl+jul + + +期望结果:slfj+logback + +1:slfj+桥接器+实现 + + +log4j-over-slfj:转移log4j日志至slf4j + +jul-over-slfj:转移jul日志至slf4j +``` + +| 名称 | 描述 | 相关JAR包 | +| -------- | ------------------------------- | ------------------------------------------------------------ | +| 门面 | slf4jAPI接口 | slf4j-api.jar | +| 桥接 | 用于slf4j连接对应日志实现 | slfj-log4j12.jar,slfj-jdk14.jar,log4j-slf4j-impl,logback-classic,slf4j-jcl.jar | +| 适配器 | 用于将原日志输出无缝转移到slf4j | cl-over-slf4j.jar,log4j-over-slfj,jul-over-slfj, | +| 具体实现 | 日志的具体实现 | log4j.jar,,logback,log4j2,java.util.logging | + + + +### 1.2.4 循环依赖 + +如果clappsth中既有桥接器也有适配器,日志会被踢来踢去,陷入死循环 + +## 1.3.slfj+log4j2 统一系统应用日志 + +由于系统组件中,可能采用了不同的日志体系,spring5之前,spring采用的是apache-common-log,spring5之后,采用spring-jcl + + + +## 1.4 日志规范 + +``` +1. 【强制】应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架 +(SLF4J、JCL--Jakarta Commons Logging)中的 API,使用门面模式的日志框架,有利于维护和 +各个类的日志处理方式统一。 +说明:日志框架(SLF4J、JCL--Jakarta Commons Logging)的使用方式(推荐使用 SLF4J) + 使用 SLF4J: +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +private static final Logger logger = LoggerFactory.getLogger(Test.class); +使用 JCL: +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +private static final Log log = LogFactory.getLog(Test.class); +2. 【强制】所有日志文件至少保存 15 天,因为有些异常具备以“周”为频次发生的特点。对于 +当天日志,以“应用名.log”来保存,保存在/home/admin/应用名/logs/目录下, +过往日志格式为: {logname}.log.{保存日期},日期格式:yyyy-MM-dd +说明:以 mppserver 应用为例,日志保存在/home/admin/mppserver/logs/mppserver.log,历史日志 +名称为 mppserver.log.2016-08-01 +3. 【强制】应用中的扩展日志(如打点、临时监控、访问日志等)命名方式: +appName_logType_logName.log。logType:日志类型,如 stats/monitor/access 等;logName:日志描 +述。这种命名的好处:通过文件名就可知道日志文件属于什么应用,什么类型,什么目的,也有利于归类查 +找。 +说明:推荐对日志进行分类,如将错误日志和业务日志分开存放,便于开发人员查看,也便于通过日志对系 +统进行及时监控。 +正例:mppserver 应用中单独监控时区转换异常,如:mppserver_monitor_timeZoneConvert.log +4. 【强制】在日志输出时,字符串变量之间的拼接使用占位符的方式。 +说明:因为 String 字符串的拼接会使用 StringBuilder 的 append()方式,有一定的性能损耗。使用占位符仅 +是替换动作,可以有效提升性能。 +正例:logger.debug("Processing trade with id: {} and symbol: {}", id, symbol); +5. 【强制】对于 trace/debug/info 级别的日志输出,必须进行日志级别的开关判断。 +说明:虽然在 debug(参数)的方法体内第一行代码 isDisabled(Level.DEBUG_INT)为真时(Slf4j 的常见实现 +Log4j 和 Logback),就直接 return,但是参数可能会进行字符串拼接运算。此外,如果 debug(getName()) +这种参数内有 getName()方法调用,无谓浪费方法调用的开销。 +正例: +// 如果判断为真,那么可以输出 trace 和 debug 级别的日志 +if (logger.isDebugEnabled()) { + logger.debug("Current ID is: {} and name is: {}", id, getName()); +} +6. 【强制】避免重复打印日志,浪费磁盘空间,务必在 log4j.xml 中设置 additivity=false。 +正例: + + case: + + + +7. 【强制】生产环境禁止直接使用 System.out 或 System.err 输出日志或使用 +e.printStackTrace()打印异常堆栈。 +说明:标准日志输出与标准错误输出文件每次 Jboss 重启时才滚动,如果大量输出送往这两个文件,容易 +造成文件大小超过操作系统大小限制。 +8. 【强制】异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么通过 +关键字 throws 往上抛出。 +正例:logger.error(各类参数或者对象 toString() + "_" + e.getMessage(), e); + +case:不允许记录日志后又抛出异常,因为这样会多次记录日志,只允许记录一次日志 + +9. 【强制】日志打印时禁止直接用 JSON 工具将对象转换成 String。 +说明:如果对象里某些 get 方法被重写,存在抛出异常的情况,则可能会因为打印日志而影响正常业务流 +程的执行。 +正例:打印日志时仅打印出业务相关属性值或者调用其对象的 toString()方法。 +10.【推荐】谨慎地记录日志。生产环境禁止输出 debug 日志;有选择地输出 info 日志;如果使用 +warn 来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘撑 +爆,并记得及时删除这些观察日志。 +说明:大量地输出无效日志,不利于系统性能提升,也不利于快速定位错误点。记录日志时请思考:这些 +日志真的有人看吗?看到这条日志你能做什么?能不能给问题排查带来好处? +11.【推荐】可以使用 warn 日志级别来记录用户输入参数错误的情况,避免用户投诉时,无所适 +从。如非必要,请不要在此场景打出 error 级别,避免频繁报警。 +说明:注意日志输出的级别,error 级别只记录系统逻辑出错、异常或者重要的错误信息。 +12.【推荐】尽量用英文来描述日志错误信息,如果日志中的错误信息用英文描述不清楚的话使用 +中文描述即可,否则容易产生歧义。 +说明:国际化团队或海外部署的服务器由于字符集问题,使用全英文来注释和描述日志错误信息。 + + +if (logger.isDebugEnabled()) { + logger.debug(); +} +``` + +## 1.5 性能测试 + +#### 1.5.1 单线程 + +| 名称 | 未开启缓存,立即刷出 | 开启缓存,不立即刷出 | 异步-appender-未开启缓存,立即输出 | 异步appender-开启缓存,不立即输出 | +| ------- | -------------------- | -------------------- | ---------------------------------- | -------------------------------------------------------- | +| log4j | 87.342秒 | 10.757秒 | 91.752 | 10.058秒 | +| logback | 81.617 | 5.547 | 100.245 | 10.69 | +| log4j2 | 5.272/5.614/5.196 | 5.502/5.53/5.453 | 5.423/5.378/4.953 | 5.063/4.74/5.246(AsyncRoot)==>5.348/5.712/4.818(Async) | + +#### 1.5.2 多线程 + +| 名称 | 未开启缓存,立即刷出 | 开启缓存,不立即刷出 | 异步appender-未开启缓存,立即输出 | 异步appender-开启缓存,不立即输出 | +| ------- | -------------------- | -------------------- | --------------------------------- | --------------------------------- | +| log4j | 102.823 | 13.324 | 87.966 | 10.651 | +| logback | 100.853 | 8.238 | 111.272 | 55.813 | +| log4j2 | 8.164/6.94/7.073 | 8.02/6.597/8.009 | 8.11/7.485 | 8.178/8.226 | + +机构图对比: + +![1589351161247](D:\shiro\资料\log4j2-loagack架构对比.png) + + + +log4j2-AsyncLogger + +``` +Log4j2中的AsyncLogger的内部使用了Disruptor框架。 +参考:https://www.cnblogs.com/yeyang/p/7944906.html + +Disruptor简介 +Disruptor是英国外汇交易公司LMAX开发的一个高性能队列,基于Disruptor开发的系统单线程能支撑每秒600万订单。 + +目前,包括Apache Strom、Log4j2在内的很多知名项目都应用了Disruptor来获取高性能。 + +Disruptor框架内部核心数据结构为RingBuffer,其为无锁环形队列。 + + + + + +单线程每秒能够处理600万订单,Disruptor为什么这么快? + +a.lock-free-使用了CAS来实现线程安全 +ArrayBlockingQueue使用锁实现并发控制,当get或put时,当前访问线程将上锁,当多生产者、多消费者的大量并发情形下,由于锁竞争、线程切换等,会有性能损失。 + +Disruptor通过CAS实现多生产者、多消费者对RingBuffer的并发访问。CAS相当于乐观锁,其性能优于Lock的性能。 + +b.使用缓存行填充解决伪共享问题 +计算机体系结构中,内存的访问速度远远低于CPU的运行速度,在内存和CPU之间,加入Cache,CPU首先访问Cache中的数据,CaChe未命中,才访问内存中的数据。 + +伪共享:Cache是以缓存行(cache line)为单位存储的,当多个线程修改互相独立的变量时,如果这些变量共享同一个缓存行,就会无意中影响彼此的性能。 + + + + + +关于伪共享的深度分析,可参考《伪共享,并发编程的性能杀手》这篇文章。 + + +日志输出方式 +sync 同步打印日志,日志输出与业务逻辑在同一线程内,当日志输出完毕,才能进行后续业务逻辑操作 +Async Appender 异步打印日志,内部采用ArrayBlockingQueue,对每个AsyncAppender创建一个线程用于处理日志输出。 +Async Logger 异步打印日志,采用了高性能并发框架Disruptor,创建一个线程用于处理日志输出。 +``` + + + + + +## 1.6 日志的全链路追踪 简介 + +#### 1.6.1 全链路追踪的解决方案 + +全链路追踪的背景 + +![全链路背景.png](D:\shiro\资料\全链路背景.png) + +上图是一个典型的微服务调用链路,面对的场景问题如下: + +1-如果D服务是一个关键服务,返回结果错误,无论是日志,还是监控平台,并不能很快捷的定位问题出现在了那里,因为不能串联整个调用链路的流程 + +2-当对某一个服务架构升级或者改造的时候,不好评估影响范围,不明确服务之间的依赖关系,给技术决策带来了困难 + +3-性能瓶颈,整个调用链路那个环节耗时比较久 + +4-当一次请求结束后,不好确定执行顺序,都给业务逻辑上的理解带来了困难 + + + +需要解决问题: + +1-串用调用链,快速定位问题 + +2-厘清服务依赖关系 + +3-进行各个服务接口的性能分析 + +4-跟踪业务流的处理顺序 + +已有方案 + +1-Google Dapper + +2-Twitter Zipkin + +3-Spring Cloud Sleuth + + 3-1 与springboot及spring组件无缝集成 + + 3-2支持Zipkin输出(mysql,es) + + 3-3 支持MQ和HTTP方式传输 + +#### 1.6.2 Spring Cloud Sleuth 介绍 + +##### 基本概念: + + Trace(链路) + + Span(跨度) + + Annotation(标注):CS(发送请求),SR(接受请求),SS(相应发送),CR(相应被客户端接收) + + + +##### 架构图 + +![1589347288854](D:\shiro\资料\sleuth架构图.png) + + + +##### 流程图 + +![1589347457880](D:\shiro\资料\sleuth流程图.png) + +##### 基本概念 + +![1589347636646](D:\shiro\资料\sleuth基本概念.png) + +#### 1.6.3 分布式日志检索解决方案-ELK + +E:Elasticsearch ---存储 + +L:LogStash ---收集 + +K:Kibana ---展示 + +流程 + +![1589351638767](D:\shiro\资料\ELK流程.png) \ No newline at end of file diff --git a/资料/java-日志体系.pdf b/资料/java-日志体系.pdf new file mode 100644 index 0000000000000000000000000000000000000000..952b3ddebbb6975a22d2896271ad284c105a6ed2 GIT binary patch literal 1863131 zcmb@sWo#Wm(+ Yxm=j>z`frXTr6liLTz|YSl=3-&u26Q2%RRH?f z*xQ>haR8V}^=Y+i9L<5AuB3|Uq%6z;W b&LSv?VDY8x z*Ltx1_qv#wkg^~!i7JpXDFR&_Ozi)giTl5qzSOfIWfF081iB$GskxiF{g1Z1jiVg` zlO!qoSAU?3`IqQ=%wK(&4G@@AzjP(l<6z+c@NjXma*}d!a09q`*m+1fSXsVEJfvLQ zoB&P^E-vmbW)ae_{rRsc%-p^-{hEW6Nkdfz;XfZzS`$lNCMHJ~9&S3pujl{Of#?56 z@mRUPwuFoIzvN?O<>q83Wn*RmuyC`oa{Pamkd=k!f0K~qKdbRy<|k=m@AkDoOp^9r zyC`m91~j)oV3N0Rv~sg1{hFCuP>|Hs?aM?R5WI3P@K>WLxUM&i=4XSfHA<7KpvZPy z3ov1B!Fg~X2*wUUWTlsy+fDq<@t&4r-|!QDb}6N;7sgx|nLXU~X1y~&QH#bdyuW%s zJ)z9uJI@rcr_@LK(1-32MA##TALlUjUj@9>y~vs5f+PJ)(mUS|T<=IlVn4aN`(5^S zd+_ISSZdkt)hc5L4{HIUTYNX+@q5TJRk7o!_?a1-KYiIlu_^MR__9|NvZZq4qI?14 zu}dQ)w$wy>bS{qyzYQ`KlHEuj-*5h!Ea|9-cWb&S%|4tDHuK1(y2zicR7sB;q0$h@ zCdgHG40CRd69vpKzapW^l^&``wp l~tBO$OCc(ExiNI)v zM-K-_ci7FUjjfp-ul{D&K=ra(B%;N3YscT520k6^*EEb^FB9NFi qA*^6Go>ZjpN@S9Ep@U;s762mDTVivJdU@4=Ey*O#E>)c3p-@V2FdK~ z7r>g7a@&xx%9SMFg9LzZnq8hcv{qB?EsuZG=l$CAHu$<@@Amoo@ML!Lr4sU54opHo zRQp_!Pi#Ur)a~@7U6N~O#Sv;a-Ap~{7AD{FSqn)8gJs|9=;D*m3e7|gDrpMs35lnW zHkM-3zkBdkGO${{KUSb%OHBTBmcaB489`GniG=Lk-9r~zAfLnv?U3MR&M{F{SV7Wp zWk(G>Ei`rlI_w+Q^SgZ{IWm_T32;rQI$?kO))^?)p^a=)Z6M-8LxAE-kf0m*(RoUM zzPr`-LroAUmKx<0vRqHfE7%)V@y>^56WYbq3lHCuROkp(cNqv-wIky%R;8NjBd%zV zRp@LM3BR`pKoR@}UGHc0s#ioGrS%Vijh_53*5YzyIhb?V4Y}OaCYA=i90?O&;9wR5 zbyv1@#1wkGu5@d-IF(qPsxnO?@fENES8FMCO2GeZXd ij}Q?yab<<%OtaGmHrb3KUz+p2%TM>w^rl>S_N>0Giszw*H-wWM@SyYh)) zhp{PO0HqD}EmO5-o2a0+eUE1{>*~axvjgBG6E99|A)$y+Jl;j{ionI=rJ2w|MaxQC z8=H(le9H&C4Qml?MtY3p{DR!r@(uu3wK)6eDDzFk@aSr9E~mym0T!lZ1q6p}%#6ne z6~-78j3N}y%|Mkvc9?GgEEbeg*Tj(=nZ=i>&82e_J9Y#UHpC7;*$WgXlO*MGUN=4OZ=uDaF#bs*Y%nWDoOl=n zeKY>+1KH(y?yQBlf@}N8KJO#`yKOL8?Py37;r2ii(s#94ou4DCV?oo9WUwa-98uac z$WWpPMLt$4H4pwN2S_n$XEH=Xss&PT&SfUPRS0p3VV9_9VaaOF`5O>?= K|~2OoF{ca1)a z>*QXU7;h{tnZ;EsGFz)34Ok+4oPQ;AJ3OzRs
ApVu-!guTs=s zrc-Rat=CkwkZIM(dSYra;U2E05?c-7rm#)Co!7^(Rj#qjP&J-co7qV3 z-%#&o{rY$-J#VPobb0(rwKs}OWZREXI*&d85_zQ$W=HF*%6><#C!CF{@80JB^Q oy`&HDU`lB+yk3}Wxh`(s^$V%^Y;}WaYxyP|0-tM{l(PNJbzYJr@w`I?=7i>_ z`5MWq*Iy?(xH6CAJyve8I9E-*3K=h_aGA{ h_Mm1YS9|f9SbR9SC7?f5+uc?upP5#lQW{b;gu_W#055``$Ql6mmeJ!(={gfMs*Q z7 %@gZq&BKpGC@B_6MpZm+uO-`KRP$Vb0<2z`9s{zkOXfHsRo={_%C za>;Ow_muS2u)+0yI_fw4e971hJit>+@)E!`!nu)XuMUExK5D!d(?HaI;!0gr5N^u }Y2B+_LLfHLZyq`i;Ul;jD z(^>(N`0J<&-SsW8+z9@|VO^cZ4Aj_S0fU^lp}=_>9;A!Lv#5VT6&GG2N^toEtVwmL zEJ?5sA*>SxC=(qaF6F(^R$b rdbeknrT zp7B2XtnBSRGtwzvc*94aC`c b>^}!89 zAfZ>7@x&V_a@3h9T!w^zb$vRJ0sDyUU|EVu<21@8=!9{4V3i-kgGwZtr*m;dS*59c zfYW$?Icx0Z`Wjk_gqHBnU3vtl%Ue)c<>8kz!>57VN wROa=zL@RP&~zJW$)02 z7U64_ z*A)&h9>8To#jj$^AMP22*egd@QLGL~9N4+m$DOq^((10Nbf?@2c1!E~?9cmMhx z*EIe&J`r_5w+ kofGco|E> z8J{&(x^9^Lwrmlm-5=Ub8i }^xsfL9Yx1Tg-d0US4Lju-fiw{uO>j&gU U-TPnwmfN)jON`m#R^^SCwc_3WYUL< zuK-d{I!=|(R!H4T^i!;Z$8R%h3M{!CMy6i2Jp ~DCCqtdpU*&6?i6^^ zEjaQq2hsZvH@p%_`6+GQ0jrsJbZa)AxWrtU7U&DgJK{kCi!pS54tC9aaIZg>qEm3z z*%(gpJKZ+eh8;+~Ih-b8v*An*sR6f8-8q`Iyo&AL9oBxjra1RIAWrc(amB$Kvu!x8 zt1io|OdAo|d-l7o%m6Rl>8@I|x=+@9k*812HFyYS3m;OFP+^j9tQ&sDW`s;DbO>fz zQRffFv$3FXf&jBuQTR%WUd6w-qVX97_;Ez2Q4=KY<0788UY>r(pfhULj3$^T4{}?L z3DH%>}VHjkr)6ISjD1C3N3{lI2dTn&U%ohtB3 zN>hBg#r6iSHE Fp7fA|)Y8x}3T;R*TEnvLz*{AH+t0z0XexZb?(C9VV8Ek3Yt%D0xaI zY=ms7R1UF1>erR-hbU#; m>Nk-jOx?DQZ-?&LHvS|b?# zmcZ|}P(H1bROxa0Y{75Ve%4O3su+9PNg8EFdTc?3R$~Lglpe709Z>zFWT~9Q^6o2M zBv(tbFU?~?#ny8_1u?e BoR4PA}2bI1^#A;BHiK8;ZcNT!} 7Tg_UFqM}aG+$d-f|XKeNmGw?v3)h_BgGy(XfJxo_GjhOF=gWZl1C#JId z%*rFchXb?;EOT-F#R1XCk*C-w3C9AmUgDzgbG3x8iZzv?Tq`X@w 3B6#Bv6>FU^!jddhAK@oakt&tb0o&B;Oqrby zR~7_atsIO^HwVEuMHIRyp^}X|JWH{L{So3WDLoN$KFTWwip@Fgy2oA8TTC%S2FTkw zglzkQ?ZxuQr2*0!+5`x6!ljMrlb}vi`^A;~W97?yz1l=%R`AF<8m#LnDDunLT!z44 zN8EqMgJe=R^*iL@!#1gVNYDFXb)tb=Rh({#-cV>o$hsghV8gN@L@g2el4h!G#BT== zCF@>-77tcZJNl#XHE7KNr#yYVP*q*BYLsI }+gYci z2EP|4h53{YXxe9ZV(_~*wYgy}lO-ssu MVKg$)8N zR>{li!a_5oU-9~yqIGl?`o_wgKQ5)fMPVN@F8UH@>M6m3?gOW6+YatSKFNfVKEVVF zpBy!yR~T{o^a{F1Uk+X&&r`vL9^zhV67zzcMS4X)u-51(I>G#e-#6ry9H#==0g+mf zsBjsHgy=IF6aK_BxQf87do}K<{Z#o~2TxqJjv$VmwLIkjjC%WX6(?4;lK!ePoHVf= zCsRP5)L{Ann=X14q)Pyi%N|k*KZi#q*LD(k4Dxq+YgF_&^ $@T76!WTE7xts?#CD#-9Oi+dSaPvZ46N!DE3ndYbic3u#9^I zy@mX$of5q0p$VL)SHs}U*cnumR%7`&tK1AfJWaYm3r &4SaX;m`X3yGkKAW ztzoQ^kkO +}wtN$id4xR9cf)EEXuS)s$eJ!cbaQ D93phJ=n>fCbn+4` zk{Q#c(kwam4Wl&7-0N7Q6&|V5_RbY#G<=?xb{0fp_yY`~(@mxq?TKgMf*)Zjxi{SC zXA6fo?GK+faL+q;gV}nBT5Af&qu|y`L)3c(Kl_E{4RF^q?0I6hi+N7$T5TmL*OYlq zwiDzaV5T1Cz>YFDV C_kenT% zy8%3C3yrp|sG2LL3D_j1mUtIV*!#jUjT~ztQCy0 K~N<+A36exe3zs=Z7bVYv!7H88mmdQDm(*I;IxV6Q%mA0Am8&luK4K-t68j`D+ z$sdfXr9UuwaCYU_qzG%PTp{gTL@gC05d?DqYPhjAjj_X+{hO*HwKUf!v`Yb1EROqj zPe6q*T k@4?4!N@St;1+}EX*c=^YaklO%3JkiCux*0Q#14`b +LR zzmu%pi;jzG|K{OrT*!~WgsoAtwmkEs0GtbTIQk&d7AGA4ggY}9LFNQp7)v(4r 2Rs?PqRkr(anF1H#5_F5}Yk$V=0 XvM0!$AspA`HUA9t%Wa)U^)P+?<3%Zz6vzaw>J}hCa1|nSZk%C%A(|Q>|PG fWlKIoW%{}rA(M_^ zZ(k+{><|n4{BSe0x;aXtGmOzCE|o9U>D&`Ql^MUzPZu?Uy`+;!VZBxP;bPwdd;8Hx zU2Iiya!bvZx^GX9N!_ldk5aFGZc&~@Oq}2A9a|5uND6aYwL8We6 zya&qq$zcP~vADsTv47EWg}BDmMxU>f*F;O11dHuU_%T@5UapB$yD!qK>qjqoZeXz- zeK*c>$!v;F48zrRr(@|IWR=DX*5?XiG?1eZG*F5I5SGdN;M02j_;yY;-;f>ie?t!3 z@BF=&V-z*=dEQvlcz#^?J5&C+CGLx>Xzz2jXmBI`%wE;gzF>^$Kr1ZSk#xf!_sDa= zKfs%aQ@d`_vH~Aq`$kbt>)S5zBQDw@zi}C}%JCDspN6va!g|~~gaW?B G+40UUr;eHfT@<{bWclfG- z$OI_ml$^u?o|hYr3RC~I^PP9!Yg(q{8gd`z!P3sHXZk^{8zEju|5_pU(iaGVZQu~b z`ajgcxc<9z^*`Y*Z6#CNFQn{$!PI0NOsu{tUs^Wi{{e=WS-;9*(iS#W)^4QiTs&V` zAkZG@qUK~`_65g@TX@)*S*S{heih1W++39{T*QD5PC!QsM>kULFI?{bf;h2$!CI_5 z|7&^d+`wHJOAnXC^u$qIHc45X5*iU66YCu1`*$ps{7s@+9K>#a4>FG!glJk)(#_4r z2ZaGvzSicT+pVJ)G0&?F-`Cui>4Qr^##_Ya9LcL#;4$jQHhRSH%O?GMk -WrLASw=Gj#3jnt5XRjcR&i5Lk-yE1l3F8l;`)Xug iuOp=N+PPL`VA2T!xB8tycDn$WRE%FW`L-JZ^l8j zuH3Yu33EDc+oVmlL)~FctP1%c q4$`RXD673A#$I9L}+M!A5 z%$@?Uw!#~Tlra{;R+x#55n`gV7ARN9mSK<5PjP3l(Xo%@#NyEqP`Yvy)ialw94h-} z>H-YCMf1H-ARb1>ij^}(WrniMo8bH x3? z ^u}*j^Y@g~ z)!*`utDi*>j`pb*7URfY**jG*f6)f*>&wdBIO86(ztg`K9VLq+xTb}WBj{DUAo|JC zh7HA;hd|Jv-Tq8hRP&zFVD-EKpaY7O6XIDz-|3Pgl-VW8-8aGz@W{|#5oQxjbJw&M zo5t*moU+G~iWB4E3A21Vxg#Q(44{twsK5xN^xch1(gKpaRreOgVa7v~YcXVbiweTr z1y?ly0Hq46=tRrKrt8Uh$~l~%r4K;ymFqk;JBiBTCeu=AqHZKU+&t4Ti2p;+KBFU_ zoxwo0lHAhlMGOR9jAtQ3HOz!VLl@p(gQL4+u;Y0$H#9g5EHW~FyQ-SQksIO-ol(Oc zg(Olq84`u&)s#NnjTc3>73?Q{svrTLe9u^{{mC m5Zc_ z<~)t J*-zrz-y4-t{XSQTi$7i%KzyS9+dyClq*zgmb|;pZ( tEX9Y31TTF!9~!5OO@zI6x$;Y3Wh@#(GyP**A6z4Py>%`yoa9G5yer6 zLL=&?97{RJXyu}`X38g9wJXY;E1+oNMo&c_GYaj&*2MGclGP{7f>@lvjZWiswMHnN z4J{^9?$9M~EKBJXg)g?0Hp*2F9;-v}?N0Jy{BxDdC_cPh3d2DXWo~(wG|(3sp)|xw z*&|ED$NTxyH79*XLBAzky7yXZsm2^nmN1wTw%Ri8_P;#v|Ma~7qXEhq@#ZaTwxC}X zB9E*|8_C$wit3-GTQr}4tcIrnu_k<2NfR!&(qc>}Zflrg7`>f=8bposC*^C6>NVI# zRmdx;W~g279DLiRrizsMrxJ~}Q%BG#)iv9v0=DFl0&$aVc3&t&hyt{z7GC5?MqQ%N zt`ed`GeYrkH36&Z>4~D|l$AO4+)5eK|42>+?|ehZKNZyEKWu*OwWlszk((qHLB(OO z0OlNOEqGsW?>$}@<%`g5QKr@K7!#qYmNydYrxh44;z Y3IOwetcx{e4sxCyDb@0W;T1ZE7Jwq+{CeUm!i63g) YunJ`b}ZxFHCe{^9J#X zrhnvx-r0+CzXvn!EpzO$v$pSui8c2fpV6rgezF!zi)O!w<=NZ=$@R%xll!XnzN1gj zV9CRM2yeR&8I}$kk&Dk`iq9ZK{{r+S? kRaU)*2aUNa4hg8&h8WZBl&xYa?w3qS(1Ak)`4ly}DBQSjj*dilE- z^(lDK2QHH%xauNn92MrIni%UDbRo9Uo93|uq#;)HCG#KxI8l}&Jlr76k@3J+Uud_( zL>)>UA-P-=*Yo$t9myiE=mH*c=2Uwj;AM1rBm_kHhmTOqs+G8F30#0<-&@nqZwRB} z eP(^D)^^N#uO(W~U4FQ<7uF TobctA=_AmY`z(wDY)8kEqo?5AYDiNgSPFPmLv>XUhfr1D5K^Q=w@CMu@*2%U zo)?E`e>e-aR=NG#`+WnmH>@BuJKjRho+uB?3N6l-Xo^BTe3B`HgTm`Bf=<^Ytj6{; zU($foYaL!KuTTG7zG#ZfmqD3#Ro+h+emhx)OdjTSBC(RJ0T4=V>zs+E#)M_WD=}Tn zlw>eEi%uI~Y+SjiIEL1oE>HO2(sOrXH=bI=87gY>PK6R3s!K~PlbB +E)` zmaBnb{#R6*ee<~fHLk6lwjG3T5t_EZ+FEP~fZ&R1U&Tq&HBE-nONR@ NoY_bQ zmVt^1(1@NXogCO|F%(ME|0te>*xpz~O&Q52L> Bp$6eG*xT+dBlr&6@&HOni#W-T*`bQ)^DM0? zU1ZFYpB1XIl67bg?_06GWXx?f?->+(|5!;krpKaw$W4o2^iM{*LKb_U+3ccn?1>iy zhy2`0Z=i1_{9SzFDMCG;%}m50PHkeQFc#F+tnwrii&=qPXbc$A<^6MQ&vH0-ei|BF zk;fDe$#Qw1+Jy*29Mwa3;Eoe#QKKDZnNS;}A}nVUk=K%=ys5~TQxXkIIdR3gV^pve zM2B$I-lJ5<#aOYu)?#^xISQ|L>md#LW1XI 9_y;Uw+g`#kGAxsP@@N78E_eQIHHmxXVe%9)AxE z(*n(=oEjDVBiZ|mQjaOZA&A7OUg?jl@I=oMLs;GEH^oKluT=>A&p;rWdr;Oj`8$y~ z?F_~?;8QCi>W_4B?Pz~`jjvt@kgD1ckwr6CXsZ fsAhKd&q})!PF$Zg> zLGLWK^r&(wGR>drz8^fl#fVSn>^Nd8#7f1PLlFyM8fgT{Q(gk1;URj-`o7;x7u|J8 zH8;W`AwLkp`xw#+y4lJa2SpY}iTgyt1(iS&-Gr@fH0*-NR7R)BO*B40^6IZutkuyN zfg=<@NEz!1!J%rhn->3t{%h&M$MG<+FyTd!e*a!mbHGwZH!UX{IZ0c$Yg$vs2o3!) zHC1i*4?ccb1MBl0JtJF3Ur9_O8vcG*OD!3j1Vm9?7(5!-T2)aYi9|HEh=x!dnM(;l z1E<&H#$Lo0B=-+IDI=yPWPr-eC-SE;%=F7YEuBthCQrpP6w(o8cRbc3TXTGFp{scu zNMz&$o3}sJ&o~Wdc8>~e5DklWnjUnlMRnZHzs+&Id)p@KXpF@(Bx@kcyO_9j3>n1F zy|myjN?p^Qm?Q*KP6qU-)Pv`d;u><{U;dy|)+n1m!?&og7sDYu(EGU-wnb7~HSw6g zNIIvXxZaEM;z`U~L2W6|xx(pHE5nB*G0en;2Nd8wVyqc9l`*=s&Drnlslys3LfOUX za-9|?_ENcZ49rO4z%@~Qi-6PP#?m^GFLBJodXR3GtOy|aH8E5Y>RMWPdxmkqF^P zvp^S~TN2nADLJn4QIuIMy kTl%%qDJ+CR2 zLNotJu1(}cFvc_4s|uccTIxZrI*N(?p<~3BzW*cmdTedM)9Y*p%;1dsOWE7k?Q(w0 z#7-HlDUMY`o6VeM%_||!m{$W#bO#Rk{9MXi |1oZ8mOPOUf)HB#KC}ugDRbd->$foYR$F|F=FGSe)4Q_9qV{XwSnP@uzcc(S z*OhA|90DK_$!vHa0d@1u1ZKDr)DW||m@f0`IkiXJe&VlCXA!=vGV!9t;X4{PXqB2d zLCP^b9F+#;JN$H0>_c`abPt&n%}6&+fdaUkU!j5~MT=s5u<)8}NpM-=T =y3q?+%Q5;J*Ys0>IAseQK6w i=&~bhUi}tpHLRv7eK7Ut5?*!5bQqEhPm2iuT{>mwt=|cG72KjkZLjAt|(}dzv zD0NABU4g4FTvpuO3Q!fop=c+MxaDO=-H2bt-WD$j`1X!!NI&_^KD#cg<>`l&z!V74 z49$~E&k{L+`pFnkAk9=X@$&{{R%H8zB^SO3IsyoRXu&Q^uF_eQt58EP$?HCELXGA! zutDO@wn}*oQ?Q!}kF~(UyOX5`lA{ft@`%lHE4!)SXYhzdBpr70*M{n4ob(|%u3} Q7X9;x!r+0Wh_%@O zYk91h6EtitrBHZxZ3Qpk*Ob|sk>L}RlCd=*$%d2%=W=%YR4r~&i#e^*YSB5^E6m7G zl2HU&GI+gTIWfb%OuJz!y4=#&XU}Q1=gB>N!foqnUl#WRSge5-VxFKiHoA&aO9Lzy zSc!m^CK>+(w$^0T;)OJ`#c&N7?H9>zUcjvkgq_DcYGipxAYZj@ay(%W !?qeu9B|yt&!q;-sh{ z1NA&(dj7bPS}*budyrZaq8aMO4n;$|^7h>)MKk{RVfXaX&|y#n4>5x!rtDrlG3+L= z1f^T5imNR5AUP&!$DpQ;_CeD+k&ORm1&{@_Q?e1Q3y4dnbryv;#i5qE$UR*staLd` zl6w@l(hSCAt%rvE@oP>)OZM~yCs_0Q9osNgT5Jsy6Y~SrO^(zWM45qDLHSM0!LLvS zNSZgGZ*bfF3(obSiQv_-+>{7i(6kY|JlsMbi}A20_q8B2hvp5(`)A*UiOxG>4j*~u z+#htQC71EUgaMqmp1PSgmRUVH*){u>sl<{e!R5te%AQWobLHdpR9U3Yqgsa%kgY(t zV)m+ZcU@0i-I3FsnO3~3!v!<9bx(Jb3FhY!qf`N?=*3O!E(vxYO_4%nCEg^MI#%;p zl?qF|NXSH=mLIIoSo4rX@3?jlm3OU!QHf#@G*=sk4|3IR {A@;`B4jNG9%o z#EYa59{{0&*51#mr79<6?ydtdZ}tQ8S 9s2yPf7Xa zHqV4|)a(@u5p~~0rSN`WY!%is$ QP)#1v=p4@s4Cc4pR7)NW3GR}MOP_#%^Ugr;@%N#RK=UuF zPO}#Xzx^>1KCI $|fp!vp;#ESUK^PyD9a&cJ;i>4p~Z zCl`_t8+lg_Jvg;u%<{!bi?t~qk(2lEr_f$*`%yaYw~*3{rt^W$_9*Z3*W}24t8W#R zD=#yf?mGimN@~KR?9cX;Izh_sa^K+m#Nj9+bu_e|&HjkfK;!ixoCqGmdGU$t2eQM0 zKNsk{oLWa_brA-GSSm+{LDm-8*Fq{DyR{VZW}-)EYcr#}fli8B8EhZZ4+1p8&jrQo z*Qe;OctlvD3e1?-!0{DR7&_TBY7Q1F4Jkw2qj^JAu%Bt{_ww@7J_*QCkyBt-$H#X< z$E~49Am14wLv eTZsf#9^ECSl`x9 zMWLQkGccO@?(Hij_Vx7gw)95V#I6<5mKA;krf@6^z1tU`%RZN^{(T|&?K!WmlA5xB z(*sJV0N)Rs1`nD%e7G`!NnZaKS&ugs(WTRhji-VOv!)v|>`=@5T?ka!P~65Y;FF(_ zRlDi;56Vh+QHF%Ad3T*elTr}z`ebj9#~+km>X1hcDugPZ%L<^?@Mp#KI+y`ADIn zI`ccBxm;r4pZs%o=JYm~oCi`Ix95b&eL3FKu`CawNB+DoGauA|`&{NAaC%Wwt5{%* zIW4NLS$X5rpJvziR~kA3;zW$Me+Uuy!(gnWA22L+orw*dpa^ge{>|qd$A8D(7(S}# z-LgJB=(5-o(}@<*6xn~ov+lNb$1en0-ELcI8$P_)>YgJooWGcB{%3p4)SJ5&JrpT` zS@V5Bq&)16N#1R57_>^lgnC&_2|ZR}eeCIC7`jutaF4of^{O)%+okkXInoN^65V zpu4V|F18 z*AQQh)LCUU{TSyt=nmZ$R8Wo-3_3{bX%7Wl!n}^IIX}*H^JpM%rz___c+b9@a9T`DLea-KIaW9YFlpr&d6t!N0 `jx+>K$*SYE$q#Omhp$kUK_fNew2%n?4_E(%%o=0_9Gc0gAkNg$MefYd z$!b|xR@G4vNuO^3&6Xp*eD?cqdry|Xh}oPU2mbrSrQBbgTH646T6%So5+kk<<*Vsy zXc@G5BRxAV{wbDqQglCwnYXmOyi33`AF0new*6}|aM=JEvQgN8gvgty9C_ZxoU*-@ z`475vL9j&Y(tuYuNu(9Tw1yle$S^;_c5`rJf>QgfiS>3uw^m^~w Z8c?rSCbcwz0*D~=g;udCIOwTrR`Zd*I`#w^BJ%nSN}Lnb&d~zJYE#O>SH|C zKzJ}Ux4mDi9&DQQpf}u{?}6J|zZ+#g+LT3f)wHArH^n!uW@=p<)RbKxRl29}4i@Ky z!wS75hasjKCmVYs=*I+#? &jU(uhA?F5aW`*we`oJ0HK+IneZ5yv zzN;_*6*EWP)N#F~c|-%_T_q#aj=JT&^O!@@>aL;U8P9~M kvKaxbecmly z+W(CCf;BVs6=f!Zy#3wQd|{BT%1q}PKnY6-VW6CELtoKHUEcqf5^BESuV30?zg?c= zewsFPQ*UfvEb8i%_ddxpJHNVtrRpg?zd6n%w40rSYt%Lt>>i8*pVlCS6D+tU`nI1M zm%+iP2)O#QT&*4&mcYO^ 6deY8A4 }Xo)uXlUDEQPS>{N;a7FbUfU)X1B0UAi%Cz4JEZ@oE*km`1b0 ztQKMW)oHC<01~l-*bn?+vcnDeeeA{`>tL}vb~9UD74q>iVx5|vp?cjrA)A1`J0lLJ z(2N8p>tlcE>rSor6U%Q_GHR-J%>)+p1?@Ldnxju!4hg*L_#+m}iSww>Lmz}!PQj;S zyN;S{ng~mLI>_3M@F0x$+=m@L56DkgY}%KXfP+X6)&<#%?iVIqfADBW3zx_Uy27 >;y z<@zZnro|3|_%)e7wHlpnj5 OcM>#|GsFKXmNu;C&h#m}BQs+bb|yxG)45VHG* z3-~c34}s#ME&6y4EFe96{p%aq#F)g>ow;?cW_{b$wAekM@2t8Cnro703bCyat8~nX ze~AYvDqlZHKL)qk9yu|BF%z`A?U%k4Oq}uvZ5!$m5fVOr$4dZt+nK!AFZtj58S3Qq zJ=9d-PyOn#)1&^DxfYkjz9?R80xGDd&$$jvf&WUuz@RrT127L~^Ve#71;ysc?h&5{ zMyB6fHh)V(R(9ZtZD6Igz5@93^Nkw5Nv1vB7U|Y~4}j~l<3bTnV{t7qu*h0k+WHd` z;-9A*B*VQs#~|&vb@q9Y3g(}~qGqW;@VA}AEfgvS)L50g4WNTd`I{;CEIZgw8e=nT ztho5=uUtqu65AiOpqvn$xwM3D?+J!*`+)~D{=ct(j67m;HScYE>s78QtmhbMyxizR ze*Qj97zQc-6n+Pe9SdC86Z1FI-lm!nAa{RGnoS14crHM!y=;A?$H)gX{l$f1Rzne# z+y_m>o+;A4*H;{R2*K{%-E9WIg3aM~7Yx(&u-4ZH2mQ@n7ecd`I|3!4vwy-$sS1U< z!vd8<+Q=dzPF>B8-n1*MJ^LP0TKad5c0%G&5hP--cL6e9tQ#si3f*sec}3_fI=NlN zR!5JFdYzv-s?Z3aI~kh+kSYv#bUBe`2(XgcC1r0l68=_r0iv$cxeExU<9sYwUmZ^~#o0n;S**LH*p@IAH3G zM4LT5KAtw!G!*65ORElteZIeOe0{wcy%2%nsr>qgfAz-b7P-FeubP@JX9%sZ{gqe1 z2Qz !+y^?6% zSX ?bmTrNu|;CwWMP0NG`(5Cvu#85ucy zm!dw?UiN-aWsc3ZdqWDJsdQg1HLaw1&z7}tjpTx40^MtJc#IJXK;TD5L9=fc8dF4v zg0lcKmb0w_qopmdW1dU#HmE8Qw<;#NHGx6!&- cCtkd_|V!IPU zkHb|kAf(uj<&lk;E)8;T a@VSEu?Z^+N``b!uYB?hK})3U7Mt<9sb! z@*S0BU=P%XSQiXd!g*s#qv7qnJYKLcflyrM)vm>U!uqBWfSse`ZFbk73HJCtTerL8 zpW^u$fyp^3OWdIAa$-PqznU_V)r*Dg_NpH@i9J1zLB>2%@Tp@_j`%2SgDf_A+1o2Q ztNY6GbsQ&I{S=Bgepf0dBXbTrCrR+|{Hv1HaA7zSHHxDvng_~oJmcKg(S?rCxudu5 zt8B})+6nVRIa(n1g&r_
*?xGHG{tbAI}oot*gq$v3`t9Vk~mw5- ^kk`08E;@c@-WLPY#ICRhN zn1i#~SSi%^+fiE7x^_^-SUOc4Il{OeRQO%=+ou!?8oz=YjXydmzI&3?88fv!ay-== zgb9YbDWdm9+-Bnd`>Mf`n&KmI0B3x{`=(KzyPi+xI5&z*w|@8eJsX`(@l)Vfd($b5 zk~|dLvHij!8*b$0GC_{3)QC^Z@o8uf@2us?OrLOkTOAh7t<8R?9OmAd5SoF?)t%3X z 3stiH*TXF4_VmE6*$3{2#Qdar#CYW`F zF@W~l=KVq(JkM)EdZpMy*BkGB#`81;TvnZr5eV6ShSr&)>pVB&l;XYZmQb~bmZ^ +q<{ z;emxu)bG}Wu50>uE5iPLe8D9U&1c&KOkUp=ahEQaVpkAVfVy-_x6ZC%IaX(4XjMi> zp-AiGUnk lyDm~vBd;*0J;OmCJWjHOC?3B#qC}@G)L^*h8Ta9UBN849qrgzHu z1;XDgV4L-}YapYo-Uu5ms|O|kxSQyGZ^=?T>~I%N^!YnpF!)*3X3$Rh^wXG=mPi~9 zO;&_|U mw^*c199?mxwXAAl!Pfi&glB z)qTw#`Y1r+?<)xQJVVu$fg_1008zv=ezPLg*R+$*il;R9+SCRmX?Mz&eEwZ8qJs1A zJBl6vHip3ofP+>ILDE@16h+EtQkJ#lDq4uxGwv8pEx1&Fg%zTIVV{;1nR o9Hn)&;gSB?CP%l z*+Y{GQ&Ft T TjMd;iJ|cFWB;zh z4mP}gpuZu|Z(Q`zPd{}dtK_*$xa@K|Y(e`?zk`XoACX0Pg4{snOoLHNZNOuKjb#L1 z(BBDIE?4EW(|oo4>>8msQ0cVofz*6n+Hu!c-OQ% >wp(YeM=6e^iyLT^OAlEx9||nkc @n#DQVuuy9&fSfCcDePEted}p-jbi3 zCGRzD-2&n$%wiwOAs|zZ=Z9WZ5HZ>Daja6)*@6|N*MRpS_HcU=RqxCZ(Tik6eY~b) zC-8{{jW6zeWDH5SnhynpPXe?9A{@n88y9}f#cR^I@uc=DWk7Wqs+ca%te(6g4?r`0 z{>237$gD}%C#D|3PbW$?krqs9i>cP0G<8?{Paxcr^+7+0`khgro)mY!xLq7wY>lGO zj^Pr{jyA`lOl;`4jHkIHaf|*46zLv|Q&8OgRV-&8ITXOroIx@j{C9ck;OVPM@4oDl z9+2GI!x=u6GRe_aYLlvt2%d~EztiAWYIxjB#^k6Ho(1s!0#`{1I6s6nPR`~qS*g(* zGQFv*53jpF;Xda;#qKTr09H=?AQ4HfcH#t#b%yxSBu~?~wx`3h^Oo~rMbT77Yl{rj z)J>PloT2@b|HGSmfRa11#?a($7FC3-s4D@rW~+^o1u+8HaDUc#T+t54Y6pO82y1yY z0ut2^(5vmmJeq%d?5JpjGVd+Pkp-fPx;p{m+ruqFI*TrcsWC3^cOE? xfKMDIh>3+D%vlxx|9`_{uz&ww@y78P&^x