From 2a021162a6cabe3ca579bba7ef8a637b665bd44f Mon Sep 17 00:00:00 2001 From: Ogoun Date: Thu, 11 Apr 2019 20:29:35 +0300 Subject: [PATCH] Fix network --- ZeroLevel.Discovery/RouteTable.cs | 27 ++++------------- ...el.Discovery.csprojAssemblyReference.cache | Bin 164258 -> 160996 bytes .../Services/Network/Models/ExServiceInfo.cs | 9 +++++- ZeroLevel/Services/Network/NetUtils.cs | 28 ++++++++++++++++++ .../Network/Services/ExServiceHost.cs | 14 +++++---- ZeroLevel/Services/Network/ZSocketServer.cs | 2 ++ .../Services/Network/ZSocketServerClient.cs | 8 ++--- 7 files changed, 54 insertions(+), 34 deletions(-) diff --git a/ZeroLevel.Discovery/RouteTable.cs b/ZeroLevel.Discovery/RouteTable.cs index 8aea7f7..662efeb 100644 --- a/ZeroLevel.Discovery/RouteTable.cs +++ b/ZeroLevel.Discovery/RouteTable.cs @@ -90,24 +90,6 @@ namespace ZeroLevel.Discovery } #endregion Snapshot - - private bool Ping(string endpoint, string msg) - { - try - { - using (var client = ExchangeTransportFactory.GetClient(endpoint)) - { - client.ForceConnect(); - return client.Status == ZTransportStatus.Working; - } - } - catch (Exception ex) - { - Log.Error(ex, $"[RouteTable] Fault ping endpoint {endpoint}"); - return false; - } - } - private void Heartbeat(long taskid) { try @@ -121,7 +103,7 @@ namespace ZeroLevel.Discovery var endpointsToRemove = new List(); foreach (var e in pair.Value.Endpoints) { - if (Ping(e, "HELLO") == false) + if (NetUtils.TestConnection(NetUtils.CreateIPEndPoint(e)) == false) { if (false == removeEntities.ContainsKey(pair.Key)) { @@ -169,8 +151,9 @@ namespace ZeroLevel.Discovery public InvokeResult Append(ExServiceInfo serviceInfo, IZBackward client) { InvokeResult result = null; - var endpoint = $"{client.Endpoint.Address}:{client.Endpoint.Port}"; - if (Ping(endpoint, serviceInfo.ServiceKey)) + var endpoint = $"{client.Endpoint.Address}:{serviceInfo.Port}"; + Log.Info($"Regiter request from {endpoint}. Service {serviceInfo?.ServiceKey}"); + if (NetUtils.TestConnection(NetUtils.CreateIPEndPoint(endpoint))) { var key = $"{serviceInfo.ServiceGroup}:{serviceInfo.ServiceType}:{serviceInfo.ServiceKey.Trim().ToLowerInvariant()}"; _lock.EnterWriteLock(); @@ -201,7 +184,7 @@ namespace ZeroLevel.Discovery } catch (Exception ex) { - Log.Error(ex, "Fault append service ({0} {1}) endpoint '{2}'", serviceInfo.ServiceKey, serviceInfo.Version, endpoint); + Log.Error(ex, $"Fault append service ({serviceInfo.ServiceKey} {serviceInfo.Version}) endpoint '{endpoint}'"); result = InvokeResult.Fault(ex.Message); } finally diff --git a/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csprojAssemblyReference.cache b/ZeroLevel.Discovery/obj/Debug/ZeroLevel.Discovery.csprojAssemblyReference.cache index e6af6315ac3d8599b2b90de94c14dd005fe8fe08..1da12914763c53e2808c41590ec7555264e1c19a 100644 GIT binary patch literal 160996 zcmeI52Y3`k8^^POyJSNNK~PXZ_(V}kLg=8>P?cT>1<+o@wq&O=-kbSm)`iRhEf3Qndt2Vjqay#Uvr{}b5R6hbG{FqyZscP9I-(Bot1Fg(op1R8Z&(`@^+JG$WMb9}*5t4dnR4iR3UmFvDLJ zAu95Y^5qx%i{j#{REhI=swJwf)!)`?qVRKnrvL5Gj@|l^uad^VnpMeoU~18~bo}>v zVS>FnXATJmrXprC$NIye%tBxGWM7`YD6=#s2TuzGQ~QOABB}i%k-`B1#AVPQPHl^H zO3%y>WMu~Zk+$v1KOrYS-%If{_E4@F2<9EkmFO_iPlW!M)Kpb4dK487@<&of`?Go! z22wNf1O8wnwOwlK)DBW0Vo^&6Qead2gu(^BNW_*mA)j8>`xI{j{8Rn;nOT8gW-otM zah?^ImYe0PB%Bt=pqLKjg?$B$`hdTpMyH+MvHj_p!~D7aus@jXZ`7lx$X@`)<;c(M zgX8_vLgC4ose^itDE&3HZEA5Qr44>o+7h0FAhRe+{aJ`X5$X1!5yihUx70NCy zK#+?v`vxNYinIQflmPK7rIyh6wx|&O-5~*YzL`ju`Yjl^r zJ;*;Tf+Cpeh_i}9!PNBDWeS?w(dqPF?kCn9L)C?4< z$KoP=4(cN1m#)V_E59-$E0#c|*{vR~*w!^~SaE<>jHp&xWeVc!2dn$y`^@mR9r5j9jt$@dR9}i=3fLS|J zb|{Pnla(wDahd6rav8gp7>rhJL17qW3ZX!4j@TZ`fG6SdSqGH?MVVi=>^-Q$xe>0D zQ<=e}`v)sR8{x4KOEVUAv>uuV{Q=IgW*7SwA62c ztA#2Wdsb9X&3cG!j8kyYyvht>udoj{FVS0rQ*p8WhZaIBTrMSfQ^*xprr(DZqmftO zPett$@Z|?)l$PkH;nGcI;11-^(<|Gb&KjqGuqfiokG4vi;nHIcz2-UChJJI%QwE9N z<@i#wLNg}$gQ2OJMWNzwwm&oMFANn~w>cyHMY!)dyn?Jn>}r+P3>5dAR6MuD)v_y- zu5${aX_Sf!`DB(#%S4f@kHCF@8ZI-?6@?1bEUhX#K`4p_1cFnn+J$;d&TzYY9w=q$Jm_ z=>DbBGAdo9JuWgpoo$?TzSTS_uPFh=TGTg3keMCGbR^S>OlLA@kU5h~7cyPRbR*N9 zOb;?W$z+h}MW#2IK4kimp`JjqKbf=0oK0o`nSo>mkr_;82$`W|hLIUgW(1j$WJZx0 zP39ajR>$I4`ZkVCCYkYM&LuN}%tSIiGFfD@$>fmnlgTBM2jihYH!saaatCp=(Q0+q zHn$qF)Qw9$YE=qCIaTq0a=b5CHOF6A4VVmCT@+XD>(H~P8c_yPBCi6n%uGeU~-H5 zebvl@S??xVJ<*f!+YFF755_wgCJ9}8ty0^xYLni{F!RZ^0H%hc`_CJMQ=CDRP|U^E zTURV3L-=hLl9>YI4Z}Dj(aRj?jlei1O_KBwa)*)*)Sp{!Iw02LdQ1M{FAoF!G9L-C}%z^P<3L~9l zn3s|3e_<36Vo+IQDIQxtS0um{a5U$Vxe~^E6^ui19=To(qf(@T%Tkn+bO9XAg=DUQ z@m>q#P+UZ=*TEXQ=&!rlT#om$-CI;!8lL%%JIYDWg59iSVBIgOhYw= z75{@)ULsQT1~{5GlDP@Sdozq9{%;}ITVYi3-xKbY5dVi4_Wha3Ge*RUgxe`N2)l>s z#($kpyS%kPq(h1AQ>wr#!KX*GAi4v7H1CA*-bLOnt+V1h)b#kbd;f0o{ypUVd&_v= z=mQ5Uk961=5|!$Gbo~8f9)R&a2qT5rFdrhv|YfsHmA; z386Z?5>jS+0|kd_2f7!q!Y-FeFT&A$iOkC|-dA88VSkleH^QjGPB#{n5cVTllD!T; znwuyTZ@@@li}MVwB<~*}o4r}a55^EUScxK6YMbF`zD4G381EJs$>WCk4!OPyqe_&a zaR0X_$~O4Xe2+r$K8zH$IAa(btO$|YFdxwIAClP)B z6Gp*+kqLK8Q7*jq!O{GS%zhYeoKZ&6fP)tqQl;n_k5ejxsw3G+Q5AkSX+EYGJs)yx z#d*#>3cQ~{-lyiQ*DUM(369N@+j6zxck>tuMI9I^Y;i`G9U*elw=NxjESclzqp`-fM+$kkyp@-YgS>doOPr*~@8*59gQC(k5={*Z=cYU2dYBwtaFK~;kou8A+4T%~YwqzZ`B!>M3zQRI(PMndDPz8R#ynTae?6|5%e0-TPpTtBX zv7Lx0d3Ijugl{qE)GzA2P&g2oRB-0Oo)sHiiUuf<70AcrV8bvTH-tdx>W02Fc|VYC zt#ZKR&xz^d#vRJIR*Obuk3O=?IL41Bu;LMwhPMU2NtaX4M=)FBC^MBz8VvrT|1YA{ zc=NCQ`zsdrq?0g}R%J|>5SLhWHpJe5*x@CKLzAxHZ4En>MlCz1rKR=ioEBS)kw&v# z)9eW=X{AxFj)Uk5i8M?tOtaQvlz#$7oRhq5aPjQ&v`g3KShE@qW@%2F^sL-A9ox0{ z<+N$v*59Tb0&2F!wGsmOW~C10nW~4B(}@VP9YoCbWIDj4oJVrls^-I#$#qrXWj6P_$Js2oYzsOexVmyuW| zBQYEYb#g;O2&Z8&V4AfU(5lSEV!$Nt2%O(t99LQxTMJ(grhW|;=Tm{0lyE+*9 zg)=&*Su>2&taX%WVjX2#bRFg2(^NYTUi!P5YLjuTgiEaWhN)mvEgvFg0hu67${doz zW?TkibK_`qU4b3Zqz&PO%3ZlE9pKv2WemDiu-4HSFA#*R8`^el+ z<^eJfl6eRwm6+aAWlFKY3GnW!i%g8K;!JkwD4Uu#0 zU^&;Wz=7h9zigY)Uo<%qDopd``*YJqObZ1kPahTVPxFUM`)bR0BK8OiDGQf9K-}>^ zh6{U2;7iT5<~qjp<6xp**;3tJfoHD7UUL2Cx`WrgP3DRCpkc~Jn&u%A_ zEphC}HXT%VgEd4WrHRvf(c9A3aJ8Y%9i>f#!y4mx9m)y!ThRnl!Tz635Ha5%^Cp?i zFewj^CN_hn*(;j^%dq1pD>ln?lwvHP%n+6yI6jo;|H(rEZxK17hc(H3n|^PBp^ZMG zUA)cZ9NA3Hky~-lphL=$;%e^wzS|&rB>H{L_aKz8+zv|xdw<@Ci1`7T56NsNvxCe> zWIiVI37JpH?1V{qgszCqSOH__Lb>nPScM(Y!tpblP}RD1+C}GoPUZ_3{7DH=Pfmd2 z9 zv5qk|Lp+M%N!Z6ac^bjdY)s}qFi!fm%k+IH({~DvJ5-pC2<&5%8waPIwF7tl(F$$~z4r=ILab zk!en*1(}v)Qpu#jq`Xbn!DhSzqa@oY1 z=?~+~&#UD8yi(53190r$H3Vl3DGnsheTJ|^%cnv3={7(*82ij2WQNj76n^?|wVRg7 zAzCVjXatU(cDN;!b(idTV5d}nl@?@np-B(7e$vx-OI3JJRq5mszeunHLs5%U}} zW5|ppGY%$&RwvVDd9a^!J zvLfECVUKjVV z;yxGDM6*~PzL}HA1Yn$5Y_Xihu9ve|K8`)SZbGZjE}%=&LhoqC58@}AfEa?KSx9CI z9gTxaOY8Zv2d|br7{ReVy9{vc$1E*zolVEmhet}qbJ-hJt6VO|bt-AD;Z#T`>_K>~ z09WwNbs9v>^T|vnGlR@bG8d4UMdm^>7m=9_lkyu~5t~5^?Cr9Issp<$F=!oqG{G*$ z3GBx35|Wxj=294Eg3Xi@Y=)d*m*dz%JHf<_Vd=w#)1nU-PO}~^Y|Z_(9xi;CtU&pGB}B}t$jl>iHJSNj7LZv;<{Frk{d65{SbnHZwuGv7 zQdDqe@wIfVMP#m{3wlTnTS9`ZTfu?H>q&AknI&XyAo0YQxF-o;biJkPtysNvBj6~1 z^}$WV(amITfwA$7Ht@6M5-3Y9fo{jKV$S+OR2ia?u6RthRBe>jF)k;F&fgO9Y&Cc{ zTDabUpR91b6OQIxWbUS;k^ij!*1gL(IcQ_$pxuXKN7{v}YtYK{k{#R(D)0T!uB;OD z0ca;ww?kRM67)fcm=BS8n9Nc#%g8Jz^9Y$oVNz<)btpoU@kLefCDgWkQo*~U6?Cn~ z$UIJFC7D$)DaY8Cu8S|x)PDl*Wd|&tq!XSZvl_1a^m-r6Mqekt&9N+@3RoD zoCz&!p`3869l#3KE6+j1Tu0`4GV5VdjAg9HvIJV;BzZD#2*@%l)_Atw9xJE)lI~pq3SbZHL<|Z<4ka?5LW-@P) zd7I1@GVhRi7bfK-x+3M-#`vO2&x9tnpG+K9f%ex{y4E%_?~!?*%m-vXB(t5&4l*CX zq?{7-PC`@rsugT&eN2*{kolB!PmAe#n&FFX4(aAltU0t3aIhQZ&j_1cWIl(nL5!A6 z_2rVOo?J40g=7DQ8)oaa|7%<;xg~s7f;<@?*8~}Jc3j+b_~FGK`aNuTk93;IXyD(< zy$ipHzbNnWhSNGP*fF=`%MG@~ul7IHsKLZBT^GM_t-s+Fx2)?{r|vf^yFHwezO35Y zZ8m&Av2k9@CH1~ezkk`98YKy7r)-LJwBGH#cl~;Gs51i$wPHJH>k&GGedYrDRNO zj>w?R{DyvF^R$D@QC573*`o9&1%Rq&iyqe7qUG75-y%X2?RWDfncv~3`F#u(!X;W{ zrNoLX%cYi7WYN>GaK=wK!_!`aWj$U?uZ{#Z-v0p!Z?wBM$^4nH`h{UtO~xvTW3`8{ z>Y%aGSb+he$MF7!k7}_|02(1kGJl7Q`3LQdZP6mjBePYNv$YRrBzJ;t2~PX>w|_dr zr_T1z8E{dxe~j+fL2V$~N~`@IaM9JiUb{{i#qjROhg9v;gHB9?nxC;Pnuq?{8=Zhl zj>bOxuqWWgs{N`s!_!lPrORh95CzKvBt*6EC9I;4#ENni#p*X1t34d6B*H2~W2LbY zSXBcO)?A4svpPXl1IFH>Q2kGa>L(6WErP0-hDt*vph^J}WrlZ>%-V$4F$}M7WxT%O zcpXc4_11W4yaZmy0SV`=NUS3Po1|a^vqGZ zRiPnUY9`RSS=x+&*uid9k_W?;ws>Pm?8KNu)EU+@5-$2~M&Hdu8=Vc2L8QBxlPH@t zV%h8?Ih*a^+3aMT;TfgD(nUBJh=SDwNQk?cQwXb58CLJfSZ(82olaPd)>vt*1Xj&} zgtKMPoY-o?*m_%L>n+Y!8nH!BF4lFSt_!0@Rx2QJVyuIFSaC2CDDbBa$4gIq`GFa} z2;TgVWTq2rtr={u%dox1VQWXQjnS~_f=m=-?SX_n_vM^|{L}$~;FKh@1M$_7@%56- z*NdF5Gl;LTnlH_l;Ok5vVLuqGSJ;Q=8RaFJT?ntP46k)EUe9s7dJtaYG+r7nfmcr; zQ8!jsqK=#z$o3BjhqC=eMM-7`QPzu5_OwjdYED^SqAXKWrYRGY^#c-ii!39Andf=M zVXGyU+CNwn@!_2}W`Bb1EC$<38MencYy%0l@ftP_n}BT)kZ2Su()tfhrMaMClxJx7 zr}n{%oT7X1-X8*P2m@}p4BRpf+;9T!Tn(HCP5?IoNZ5TDy?ha0k~xyt8pYUpKxXTH z&ej-WYl3D=vnALX3nZj|{c!|VCIjm(8LT@wSQ7}Wi5e^omH=xakP!X)KEf)CVRfsF z)h!$=KVjw5SZS;TR=GgJt_!1+lkBt%!(biD9A zkey@}5MDus*EKR;3prj>a7J-pC3MTPAH)lS}NzhPsR>0p(GrO7*9T2 z^$3|BA&ZWX6#)yWRT;rgvp9wd%`l42C%sb6Lvwi^Iv;0v3N%={hz0{uu%-hE(W;z5 zSj}WuT`FTWhhudiVHMO^X{-cR7Xb-pt8zB6bunY>LYb{uoUKc7Msgu^kB(}eUU=-R z_QP;d&Lf?M9lYA7cl_#VUswCl()qujU#j*mr#y58%R|%TJT#T(p{sC)XSxPUm(O4z z3f4RzA*%hW39I=Gt0^*8g&eDE2&)+yD~*-F>RKRS&#kgwE0ts}BEGI;d`*`5I*;?U zg!r1N`Oi-$!_j(x(7I5grO^^-JqRSq zKKwb!e2DmZnDI4S=4%+|YdP_Ck>*SDCHQ&-NSqQYx@e+aDCiGH28MF{`KdIMsz)#w zidYjxF&+6)qHYDFZlFxv08ZUXqHeaPPE#kSTLmQS>Bue%#GWA7o@B7~m0|0{VSAcj zyI8}fVH2=D10?KM+BxRFCz)#qvS%4&J!HtbbI8`=jO01Ez|k>?aVdQ29K^T`F3LfS zE3tzQVq67RJ&2(PF`|9V>p{OXi17mDp$#k#b(Zr`C!U91#u=V@8Z2E=W7%3b+zV8^CkFt14xKLvNs8<%?ztl8LO5Yt1X1pe2taHN?`R4 zkSOP7=3RnqD}(Jc8MdYzw)Y9P1sXODn}F>DAmJRw_>kDz&e-~o%vNL0*2l!wLd}+D zOR)6`kl=mIpAug?8DA&Le4W7g`keT>M)Rfl5`29DBpkzJUlLkhF|>}A(W=YQ`j*hT zR->iS5@>w~BwA|fsGhsws(UhZPiC~k=@(>lsV8$c6&Js< z;=+`Ri$q>r{Ejm`_h_(mbp!^YVEq9kL{HP7gwiy@cs-!;(s&8HY6A(oPApxb zbPVxThw=4|%-7ePuj7cX2Q^=sFTqzmAmJQvsZVSj&)C`}v-KHgs{yg~kY-D>CD>{R zBo4Uz?Ic325ku`G8MPf8wUcp1@={!;1h)j`K3i$G@1v#{VuH*Q#$SpWKU3r~M0Z|I`PpoeZP>iy)s;d8z{ZgcHTYo1eT&aWw(b@(w9|xyUm90CpOM&xuo9L>Gv;NQ==py?UZe^R)=0m-Zy6cmiOCzHlWkI z-WdsB?mXktQ|okD_R8+Xb3#jA-qUx;t|gf{pVqs*_l{pCH)~$I@6z@D=DXJ?dd5GH zyvh!0`r3}8mbM?%&UhjgRMvs{v>a5suh#PnTy+Pg?!b)pGo6YYAa!6i#ZU9JSgxQf z6YUAuDi;^;^5UX7&hV_!VCk9(3`D_d0VG5RW=p~IEdE27Ye>s}BR~DH*IMIavJ(tmidY8Y}_USwO<>){MR~D=VHa7^H(QJ*w$5Q}-6ykk zFK25U&PaX{x+Ul$E4O?6AMZ1M2|jhs?|m6A%K5#oV~6M-7q1@J1XtZ>tow|kU3=p} zztp5Wm-5gAmWN8@JajwHLs>Y(^M(dXm(O4z3RX6d5Y>JTVdZC7-6UgmBgbkIVfCiQ zN@FFk3IK`Nq{Quwh>tv`Faj1d>)n*NqhDtyc0us))WFfINg|RhXX6tIsRs?4x zzYSg5;*Bl%MlG|LgXK!bcn>bTW%fQ?b<0e*%%T zYX)cQa$;+{W=pdr*t!Bp*fT|3o)9~iV7rpRRxHC7;jmpzuj|&L46lHU*CdYDjfB_78ZV8P!0RR; zQ8)Gs|Ka}d)Ihd>NH~=3FTzZ>n~Abp7-iWqWm%lE+ljJIG-aAHL0Jiquv=sSuH8^wWph=ALvfz!YV;2s7Nc3(zxKHO4bYZ+r}sLa+7&eo$iBY78eOVI6K?&Ojw z@oPNQzG+aDH|)KY-)Har%WT>G{KN;py=Ly((X*Q`yz#*SgKvFk;qJ^w|8v<*?`++4 zW6HEvQ`RQT-rcs^qnmp-*w#Pqyk%bu%N)NktLuGtUHfW{`BlC-J*(pi&n-Dy;uo*V z8~*;p*NwaHN!~fl`$Wx&^(KaAzIOZLeU5M6Kb+O?g+3?TklT4p^5^iWHM!)+Z#JjB zvnz9h@daFzLm1y;hZw>T3lhJBs~*D8Lm1JX=Ep$4G=%Xu<)M`<51l3Fq5eD%JxO`! z2Y_`@dFUUXp!Fks>YSkU6I>_{u|>VVVh7Jdd*G_`kj_KVJha-Ghn}W9^bE^G8FC)# z$@9=!oZN zzeHHQ%&_VpW7VExwUMy;Lt~|}5?H+kBMGZDDLRm)UB@+1g5M?bU2)wgg+-fCPWP%6r7u`;4zsWWJhkzP1xz z`!rvgFTvLiAmMnw%14CO#|*8LWV9M`w006&e`&NdS^}-lfP{VPSUN*y7xDEu<*gj(H7|obwOfdEr zkg!|QrGqg0i7#uo7!@aN(I@xr|3i9*&tLda<{ds&&@A)R(R^vX1YcEwgw0p!JEA;r zHNDh`k8M%DewX?Bjq_y^Uv)KKnlHgu5|FT;s@gxtAB+Sd(_@unHG-@vPW53B*=C&6Z|MuyrDka16;bAha4Xv_6s1`k15Dn9!=P(b8xMwEhDm4*2q@lL@sZ z47Cqr)ZXW)HN_dpjeuGSZWYR1!0?a1JgPB#YK_i_mq+~vE;Kq*J$9>Oe;7@%LyXRd zA&b-Cs)sD}kOeTnkj3esUmCJ#hM#707<-G}H*b;i(Azu@rQ!_F=^89uT#Mp54M^Di zGJ}c>{NX@0mS?vjzS0?An`FLT=X|v#zM5&iG+%bWwh3Dw7L^oEi_shErC`KAYs>trE|)95?>jNuV-Yw zp5}b@A--B_zBFHguf9OS*{|1+*y_*NS|zi!lCw2{*h%IFPUlvgor(Mi5&g8Cws^Y(2o)I)~V5rP z_?jZ|HQb+F9LCJaBr{BW6*0c%$$VYK`I<^%?ZHRa~4_(Uh&@7zc>88QbWwa=x zF9Z_euH_=aYBs~_A{na-IaYHBtL_>rjg`RaQXpYBElU^WTt`S=IeaU*IeSO zhvrN3CHT4$NW|WedKE!6k3m%=Llx#wEg-0RYN#|+0;+{TqUOLrb~scN%8jHBo)!ou znb#0r*D|~cWW4e@Ue^;|85%E*m%wW=kg)5-(uL4Vh_4$MUwJZLxtylPqkkD5lGJ?5$j-jf}nbmLDg4=stv;PC#Y`wtPIzwiwGiU21oRK^p zY?YvSR_cojeXF8xRe%9*RbB!8 z(yhv?_-Ss0vA5{0N?SP(wc&Ya6V6D^gJKEJ`}gOeN${yN4+Y?&%tHm(A@Y#u*$5qM zQ2+6%S%r2`)7N$!wY2@9cE*%gP$`k|H7)`FX)~tc7YnLq8eDa8p^FPb#qhofYNX;~ zGk%(H5lOKvT3oc0i;EV#xOfL=c+S^g>E@hh&bO&yGhoQFdI`@;cR_JY+az)(rgK~z6TPHb(cR7T0b(hl4Z1N zasQ8?Df5-c`TCvsx={0_`4W8n0VGa|z11lrR8SZS z;;j|dD=SjzX(~N}!BE5(350@p9_OD#-Cjmr6`8ttPThW@?jlW{rcO{7=PmaMQ3eh% z<6-PA+BdfEcj={1d-0>pOP@SA!!ujMrePDXd4YueQl5-ZFgK7_9JY$IBr|~^OJtDk zksIQ{d;or`C9lcnbWbaG~*<>UQReeHwGIgAZa{30FOc zp$9R50R}N@fPQHZqbB8{WR{11l=ILJJP*~z8J?>&Sh}DV1@$pNLi9F^r@+@CzUnf* zzLxp=it|;E_?oBr(tHWN>H`TeNOnA7bppfcGa0L$9IJ+e)zum+jg`RaBp~7F{cA*M zHD+k-kkQ)C(P~0y&DUsYv;crT3QD$ocXX{L2>srm0W=pWu1xQH!U0n&RZVasFWU$t9uzC_$ zi!@joECE&qkP!V5y$Gw`46D^LR!?!P`Vm&wX{0;~Q&!mbOW&-OWs*gBiB^|;K| zW1Ou)#MbqiEzOo-YcPcSxe)=&o4G8wF;9IO!p)?y8o21|f75=e-;a1>!RnqhUn zjMaS{tFeUD5{;F{N?DW)foK8De+Jh~2>vn@EV=pb^uE z3B-Ir!ex3<7D1NHAiG6|>}C#GF3w2436PawzD2pyi~jL7(l^7W&IjGy0vDQI#Gd|E zf*ovnQSzM!8`OV%Ce>YbP{mBDyJJCRGpQbsgE}e3fagKD>X}q}CKWKiOsW8|kXqB{ z;iow{h6)adi%xmHPA)DM@!}$gGdvGzuymay>ZA~mu*Z!{-_}(~d`)3|&6oMQn)4MQ zz8=X)V>N@YTB@QQg!r1n__{#mYbNLGzr@#a&6nm&@O3$ma1Od$L2S)s zY)zHfD&}m>BeovVY-zRxTUP^#a%NJ^C)gG+*a~IXLL9bh3ARTyY#KHJ+ae%g7i7_y zRM!z(*E6=xli3Pzwr(J{R%o^~TY{|{frQlGbrXSgGXpC}1}mF`bsK^8m2HP+hwxJxhM+ml68a54^fbCHrVYlg{GeTDoTaPie2FPrk&DmOo zGm@VKTO}Bs{P)jHcnUss&P-Sh7v;=^wb;RCCU~BMs~)b`!}Y)b!}U*se(Cn*Dau2u zSsv;w=b>Ia53Ru&o^={5T|SHQ`B@+#+L&tztLGS2-DIq~a;(-9R?lm!G*$wu7l1_U zy>uH0suvklon)vwa;RP*sMc$!G*kkrSAm4HExD1{dX2HwMrNxuXX_1|k-PzH9UX1S z7vWQ9Tk<8iP+QVtwS}cO0lkJDye;`UTyTM z*?#LO;YsEWV(cTvSRjxlVuLSL% zgZF3zBGY4)c_81U?nrKew4xbfrC|>z}lw4(qIX&jsX&)AHNP^RhMD)wT#tQ9IJYS)q5H%jg`Qv zK9F#+R+MCRCDOVv(w>t^Tgyr7Nu+(ONzJKDbn)+uEWM?zT9+x3|j6*hvAp2B9rXdrM4F(d9?$#lM)=-AlG8wI< z9IX*JBl$C+Re~Y$fB(Y!UGS-MvDD{qQ7)GH8aw!6sc+!gd|)6u94ZRsMpAng2l8`L zhfnf_{W+;Uii-RNS^3ik`3n3Qp@KpWLYdqw2T)c&_n1T;#_A;4o`5e!>pnt5LD!O8%J%{Ng6CM=9_-6ZpeT zV4qSTu1eV;7;sSrp(=LpAb6QTf}22+QlPpm@Z&d|)85&YxxuIr6QDGZH=~wPptdcL zzP972rR@i`GmeP~u-8Q#s}!hb3y5T_Uq-<8g>j-%;3Ou{$W7p6Szxry!6{7OR5yXs zl>*I~Knpj4G^Ic~6KL%w&`v4PfeCbU6F5UD(8U&bq}zmxQr=1GY;<)K=%EzIU;@3| z1o|ok`ZIyE+yn+H1qRy!0;C~s0>hO8BbmS`H-RxqfpJVA(@kK4ED**I+LC=tAj?g_ zuN25*0+ZYXCMyLBYyrVR&`n^9O2DA7P;qZ0M{FsP9>s1_=c}ZWXE1@8ZUPr71!gmW zi`@h+RSI0r1g>xsxJoH-H4~WcCUA{XV392#(&IWefh9_T8*KqmKHn4*U<;jZRSMj0 z3y5Sai3!*Rd=y?J`CUqZdziqzZUPS|1s<{m#A|vUjtNK;S1nH%%asC;+5#dDR>TBY z5LPM$p0EW(96aeJ@U&83jV&OO@mV*4bxMI3Yyshe4Q>K2D+OM)1%wYax(RGj3cP6x z2p?>A6WF2@c$W!mbrX1BDexf^*zP9qu~OhuTR?!cGbX@5`dlgSr7a-h;H#Jb1L<3( z!1qkx2RDKLDFt>jfnVJOewPJAqxVlHu-8pszf!8D=bAAA)H~K@e;O%Dfn#g|kr(R31n}Y5jN_C7^=$#c!SQYa4U_^W z*#aU6jbZ|6n=MWlylbhKmwscr)4N`W@EfQZhv zZUP;Y0-bCD5roce0$r2>-E0BjgYIqu8A^fPwt(+N*0g;T)y9sPi3cO?sh)8_dO<jtSIr6F5OB(0~avbQ5T-6gb%y5N*~b zF#&uyBeAJcpqVWoBC&Z)fJI`eQlJ$RNOu!xs}yL@1Uk40bXE$S$ppH%33OKq^kf1V zZUTLj0{xgke>Z^vN`XO4V6dCOFr~l3gj|@ zJU4;!lmhuopukO_P$>|$1w@fnxXyYc(UMbL#33PH3I8!Oml?iln6X+=m zh}*tiOrW=$KtH9xSxn$;H-SM)fgwy_sGGnDrNAgAFxpLEtWqG835<6Wn5Y!UvIRtT z&UO>XRS6iA;2Q1cKhKsD8GEvuR8W>81=^AenZOh`frwIIDifgB#48K88A^c*n7}MI zf!RudOPBz??OExA|0)HpU;^|?U!?%OxmT3WA`<5_0eVfVQs7#pz;#T3-o>dDxIrm! z6BD3!E-D3XlLbV^E@1-nW<90A-AaLbnE<^*O)2o8Qh;8C<*X&?y;w?tN0b69m;k-} zNGY&NDL^lKar$7jo4^`bK-AOpS`Vkdb8Z6kDh~mY5TI8$SOTKe{9;VNZtO<0Ev8k_ zYa6)0Mq5CX2lUW>WgO76`MJPbOn{zPt`vAzDL{{-cE$lcn_4OGp;CaJHS83i2M;R+ zK2-|P!(=T1QM}TVWt9S7Dh0l_1w@1Io0tHacg{xd_ey~uZ2^%A^jJux4}MV!{K^FA zQGZH-Ka>J{nE*Y{O({T+ZQ~r!gSwolKu_&b3edy3xBxwV$r2EeNY7#-0Tzk$$R#d7 zkJ)khfS$Rd^Z`9uM+k@_jUK4t6riW8C`y*mYH1-w##7P@l*TF`6>h`d0no0S5zh?xt}QdOq_ty@(Jv{wqydPHXs zXmO%afYu;#AJ8&0rw?e&nNon3mT>`EPUQ3ftu0at&=MjpKublOKA?3YN P!UbqS dfYS%GIzTBvivXB_K^276;4^4`vh}Un{{fM-u|EI+ literal 164258 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 [DataMember] public string Version { get; set; } + /// + /// Service port + /// + [DataMember] + public int Port { get; set; } public bool Equals(ExServiceInfo other) { if (other == null) return false; if (object.ReferenceEquals(this, other)) return true; - + if (this.Port != other.Port) return false; if (string.Compare(this.ServiceKey, other.ServiceKey, true) != 0) return false; if (string.Compare(this.ServiceGroup, other.ServiceGroup, true) != 0) return false; if (string.Compare(this.ServiceType, other.ServiceType, true) != 0) return false; @@ -60,6 +65,7 @@ namespace ZeroLevel.Network public void Serialize(IBinaryWriter writer) { + writer.WriteInt32(this.Port); writer.WriteString(this.ServiceKey); writer.WriteString(this.ServiceGroup); writer.WriteString(this.ServiceType); @@ -68,6 +74,7 @@ namespace ZeroLevel.Network public void Deserialize(IBinaryReader reader) { + this.Port = reader.ReadInt32(); this.ServiceKey = reader.ReadString(); this.ServiceGroup = reader.ReadString(); this.ServiceType = reader.ReadString(); diff --git a/ZeroLevel/Services/Network/NetUtils.cs b/ZeroLevel/Services/Network/NetUtils.cs index a825a00..d43a286 100644 --- a/ZeroLevel/Services/Network/NetUtils.cs +++ b/ZeroLevel/Services/Network/NetUtils.cs @@ -8,6 +8,34 @@ namespace ZeroLevel.Network { public static class NetUtils { + public static bool TestConnection(IPEndPoint endpoint) + { + using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + socket.SetIPProtectionLevel(IPProtectionLevel.Unrestricted); + socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); + socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, false); + socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true); + socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoChecksum, true); + socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, true); + socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 100); + socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 100); + socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, true); + socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, false); + try + { + socket.Connect(endpoint); + socket.Close(); + return true; + } + catch + { + } + } + return false; + } + public static int Compare(this IPEndPoint x, IPEndPoint y) { var xx = x.Address.ToString(); diff --git a/ZeroLevel/Services/Network/Services/ExServiceHost.cs b/ZeroLevel/Services/Network/Services/ExServiceHost.cs index aae7de0..b593656 100644 --- a/ZeroLevel/Services/Network/Services/ExServiceHost.cs +++ b/ZeroLevel/Services/Network/Services/ExServiceHost.cs @@ -27,7 +27,7 @@ namespace ZeroLevel.Network public ExServiceHost(IDiscoveryClient client) { _discoveryClient = client; - _registerTaskKey = Sheduller.RemindEvery(TimeSpan.FromMilliseconds(50), TimeSpan.FromSeconds(15), RegisterServicesInDiscovery); + _registerTaskKey = Sheduller.RemindEvery(TimeSpan.FromMilliseconds(50), TimeSpan.FromSeconds(55), RegisterServicesInDiscovery); } public IExService RegisterService(IExchangeService service) @@ -47,6 +47,7 @@ namespace ZeroLevel.Network Server = server, ServiceInfo = new ExServiceInfo { + Port = server.Endpoint.Port, ServiceKey = service.Key, Version = service.Version, ServiceGroup = service.Group, @@ -88,6 +89,7 @@ namespace ZeroLevel.Network Server = server, ServiceInfo = new ExServiceInfo { + Port = server.Endpoint.Port, ServiceKey = serviceInfo.ServiceKey, Version = serviceInfo.Version, ServiceGroup = serviceInfo.ServiceGroup, @@ -329,7 +331,7 @@ namespace ZeroLevel.Network IExClient transport; try { - transport = ExchangeTransportFactory.GetClient(service.Endpoint); + transport = ExchangeTransportFactory.GetClientWithCache(service.Endpoint); } catch (Exception ex) { @@ -374,7 +376,7 @@ namespace ZeroLevel.Network IExClient transport; try { - transport = ExchangeTransportFactory.GetClient(candidate.Endpoint); + transport = ExchangeTransportFactory.GetClientWithCache(candidate.Endpoint); } catch (Exception ex) { @@ -405,7 +407,7 @@ namespace ZeroLevel.Network IExClient transport; try { - transport = ExchangeTransportFactory.GetClient(service.Endpoint); + transport = ExchangeTransportFactory.GetClientWithCache(service.Endpoint); } catch (Exception ex) { @@ -443,7 +445,7 @@ namespace ZeroLevel.Network IExClient transport; try { - transport = ExchangeTransportFactory.GetClient(service.Endpoint); + transport = ExchangeTransportFactory.GetClientWithCache(service.Endpoint); } catch (Exception ex) { @@ -481,7 +483,7 @@ namespace ZeroLevel.Network IExClient transport; try { - transport = ExchangeTransportFactory.GetClient(service.Endpoint); + transport = ExchangeTransportFactory.GetClientWithCache(service.Endpoint); } catch (Exception ex) { diff --git a/ZeroLevel/Services/Network/ZSocketServer.cs b/ZeroLevel/Services/Network/ZSocketServer.cs index ea26d97..c346957 100644 --- a/ZeroLevel/Services/Network/ZSocketServer.cs +++ b/ZeroLevel/Services/Network/ZSocketServer.cs @@ -132,6 +132,8 @@ namespace ZeroLevel.Network _heartbeat_task = Sheduller.RemindEvery(TimeSpan.FromMilliseconds(HEARTBEAT_UPDATE_PERIOD_MS), Heartbeat); Working(); _serverSocket.BeginAccept(BeginAcceptCallback, null); + + Sheduller.RemindEvery(TimeSpan.FromSeconds(5), () => Log.Info($"Connections: {ConnectionList.Count()}")); } protected abstract void Handle(Frame frame, IZBackward client); diff --git a/ZeroLevel/Services/Network/ZSocketServerClient.cs b/ZeroLevel/Services/Network/ZSocketServerClient.cs index 5a1c48c..5e14dea 100644 --- a/ZeroLevel/Services/Network/ZSocketServerClient.cs +++ b/ZeroLevel/Services/Network/ZSocketServerClient.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Concurrent; -using System.Diagnostics; using System.Net; using System.Net.Sockets; using System.Threading; @@ -20,8 +19,7 @@ namespace ZeroLevel.Network private readonly BlockingCollection _send_queue = new BlockingCollection(); private Thread _sendThread; private readonly byte[] _buffer = new byte[DEFAULT_RECEIVE_BUFFER_SIZE]; - private long _last_rw_time = DateTime.UtcNow.Ticks; - internal long LastNetworkActionTimestamp => _last_rw_time; + internal long LastNetworkActionTimestamp { get; private set; } = DateTime.UtcNow.Ticks; public event Action OnConnectionBroken = (c) => { }; @@ -89,7 +87,7 @@ namespace ZeroLevel.Network _stream.Write(data, 0, data.Length); _stream.Flush(); //Thread.Sleep(1); - _last_rw_time = DateTime.UtcNow.Ticks; + LastNetworkActionTimestamp = DateTime.UtcNow.Ticks; //NetworkStats.Send(data); } } @@ -110,7 +108,7 @@ namespace ZeroLevel.Network if (count > 0) { _parser.Push(_buffer, 0, count); - _last_rw_time = DateTime.UtcNow.Ticks; + LastNetworkActionTimestamp = DateTime.UtcNow.Ticks; } if (Status == ZTransportStatus.Working) {