|
% A H) Q: \$ h
Biz-SIP金融级业务中台(http://bizsip.bizmda.com)是一套基于领域驱动设计(DDD)架构,能快速构建金融级云原生架构的服务整合中间件,整合了在金融场景里锤炼出来的最佳实践Biz-SIP业务中台在运行时,会把相关的交易日志通过RabbitMQ消息中间件发送出来,开发人员可以实现这些交易日志的接收和处理。
3 [% q! n& [, |) }+ ~ 案例要求:发送不同类型的Biz-SIP交易,交易日志接收模块会收到不同类型的交易日志: 0 Q. }! h6 C4 I6 M* ?
具体代码和配置可以查看Biz-SIP源代码中的Sample相关测试案例(https://gitee.com/szhengye/biz-sip)一、App层的配置在application-local.yml配置文件中,设置bizsip.rabbitmq-log属性为“success”,表示发送成功、挂起、失败类型的交易日志,即所有的交易日志:
; a# w0 _) T7 {6 Y! x- L bizsip:
: G& J0 v `0 q# v# N config-path: /var/bizsip/config
% I% J: C* Y" o, d4 A8 |) t rabbitmq-log: success二、交易日志处理应用的开发和配置首先,编写交易日志侦听器:@Slf4j@Service 6 l3 U/ n( H3 `) y. e6 k
publicclass AppLogQueueListener {
2 g* U \8 s! U publicstatic final String APP_LOG_QUEUE = "queue.bizsip.applog"
3 I4 L0 W+ A0 s% Z ;
* X3 T1 K. b4 \: Q privatestatic final String[] APP_LOG_TYPE={"0-App服务成功 ","1-App服务失败 ","2-App服务挂起 ","3-Sink服务成功", 4 g( i9 o# j4 |+ v: ?
"4-Sink服务失败"};/ G! i2 y& A) u, I
private Jackson2JsonMessageConverter jackson2JsonMessageConverter =new Jackson2JsonMessageConverter();1 p- N- m/ m2 f( H+ P4 F/ a$ d
3 e, u+ F+ x2 w7 Q: H. ?1 |
1 \" v' d' ?4 r0 K @RabbitListener(bindings = @QueueBinding(
" \4 k- f; E# B( \" M value = @Queue(value = APP_LOG_QUEUE, durable =
# f& p& u! ~; ?$ ~9 q7 T3 ~' t "true", autoDelete = "false"),
: [2 H( O' W# F+ d4 M exchange = @Exchange(value = BizConstant.BIZSIP_LOG_EXCHANGE, + k3 l+ a4 x# E1 F/ b$ C
type = ExchangeTypes.DIRECT, durable = "true", autoDelete = "false"),0 @- X f K# ]* g2 j
key = BizConstant.BIZSIP_LOG_ROUTING_KEY))
) e2 Z& ^" a' ? + @. z# d, A4 y# S0 _8 l' O y
publicvoid onMessage(Message message) {1 s a0 q }# r' v; O: X6 {9 e
try {! H8 ]8 F1 d/ v. h) L z
this.process(message);: b) j w' H/ [! z2 p, }" e
}$ C f8 h+ I* Z
+ m5 ]9 o8 |- W( D7 o* j catch (Exception e) {0 s9 ?/ Y. f( R( R% n7 a7 L9 J+ G
log.error("App服务日志侦听器出错!",e);1 Z" ^; \& Y! x m9 m
}! c- k1 c" d& H u
}0 p! b8 o! f* a# l6 C
C. l' {2 L1 a1 n6 H2 i
privatevoid process(Message message) {1 Y! F8 R+ L: J1 H2 L9 ?
Map<
, w/ ?4 E* }- ~ String,Object> map = (Map)jackson2JsonMessageConverter.fromMessage(message);% D) A2 ~9 B+ y: K8 R* V
int
5 a0 [) s/ L7 |* e- b& G3 ]5 ~ type = (int)map.get("type");2 _" c, N* H# X1 K y
BizMessage inBizMessage = new BizMessage<>((Map) map.get( 4 |; u/ X' s+ e ]; u' N
"request"));
' q& ~4 m& ~( X2 q8 W, T BizMessage outBizMessage = new BizMessage<>((Map) map.get("response" ( f2 \3 K. F4 e7 i4 I7 H
));
0 I1 p0 Z- x) r* m y log.info("\n{} App服务ID:{} 返回码:{}-{} 平台流水号:{}\n请求报文:{}\n响应报文:{}",
: h0 m9 M3 V+ {. C$ X+ A" |1 L APP_LOG_TYPE[ / u$ k% Z+ z) g/ g: R- t
type],inBizMessage.getAppServiceId(),
9 F& k) n/ y: {$ U' R5 ] outBizMessage.getCode(),outBizMessage.getMessage(),inBizMessage.getTraceId(),
& T, a' A+ n6 ]7 m) h! f inBizMessage.getData(),outBizMessage.getData());
$ v. u& r+ c" T. M. |2 U4 {+ [ 7 |' l( v, N8 y1 I8 B x- l( V K
return;
; U0 I0 F5 M1 i; Z" s+ s }
* ~4 p4 s; c' L# i }接着,编写应用启动类SampleAppLogApplication.java,以及相关的application*.yml配置文件,特别注意application-local.yml中相关RabbitMQ的部分配置:
7 J+ r: F7 }3 i) A: x# d rabbitmq:virtual-host:/host:rabbitmq.bizmda.comport:5672username:adminpassword:adminlistener:simple:concurrency:
8 k$ Q# c3 l: l) z: V 5max-concurrency:15prefetch:10三、启动应用进行测试启动SampleAppApplication应用、SampleSinkApplication应用、SampleSourceApplication应用,以及SampleAppLogApplication应用,通过开放平台接口发起请求,进行一系列的测试: & v( `6 v, T/ M6 v+ ?
1、发起最简单的App服务$ curl -H "Content-Type:application/json" -H "Biz-Service-Id:/bean/sample1" -X POST --data {
9 K$ [* o1 h; k4 h7 l; m) J, F "accountNo":"62001818","sex":"0","email":"123232@163.com","mobile":"18601872345"} http://localhost:8888/api|jq
$ `. N6 J+ A8 O6 {( I% z$ E0 r ; g* n2 }5 ^+ s% i
- k2 j, p4 @% d) [2 s% A {
: ~1 ]: F- X% E& W "code": 0,3 y0 s2 _+ K- a
"message": "success",
5 ^; [" I( u/ y8 h! _2 g5 d; ? "extMessage": null,
+ L3 F! J) f3 q% L "appServiceId": "/bean/sample1",
5 c W* G3 c! T! w* \. e5 f2 _% M "traceId" $ l j6 i, E1 {! y; V1 p
: "4fde178ff7b040f5adfc7a2c1b4b18b6",& P5 r h$ n( f% a9 _4 @/ @8 ]
"parentTraceId": null,
3 T/ U" W1 r" b "timestamp": 1649128499806,# M9 {, r5 T- i6 S5 e* n7 A" T+ R
"data" + X. w8 G8 x1 M; t, H& U9 K
: {% X# g; }# `9 ?( Y7 W
"sex": "0",
- C0 s# z6 g* S5 X7 P7 D" u "mobile": "18601872345",
: p: e# q0 ?: m( S% R) b* ~# r5 m "accountNo": "62001818",; r1 k: h; _5 f, j9 T5 b/ {0 r
"email": "123232@163.com" ; l2 n4 V+ o6 D3 {2 z& g
7 @* l4 Z1 V4 U, A' G
}
! A5 g: O6 n2 W; k9 L }SampleAppLogApplication应用输出日志:[sample-app-log:0.0.0.0:8100] 11:14:59 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer p. {! q$ O5 T2 [9 c
#0-5] c.b.b.s.a.listener.AppLogQueueListener0-App服务成功 App服务ID:/bean/sample1 返回码:0-success 平台流水号:4fde178ff7b040f5adfc7a2c1b4b18b6
! I5 P1 |5 ^# D4 U! g1 a" z' g 请求报文:{ ! ^$ P7 h2 V1 \! ]1 W4 c
"sex":"0","mobile":"18601872345","accountNo":"62001818","email":"123232@163.com"}' ^& P, l( ?6 k9 ~' f' w
响应报文:{"sex":"0","mobile"
( o# f. ^3 s2 y& c# V :"18601872345","accountNo":"62001818","email":"123232@163.com"}2、通过RabbitMQ异步调用Sink服务curl -H "Content-Type:application/json"
) Z) v, x2 i7 | -H "Biz-Service-Id:/bean/rabbitmq-hello" -X POST --data{"methodName":"hello","params":["world"]} http:
! l" S" C/ V& L8 p+ Y7 o1 C; H- d //localhost:8888/api|jq
1 z" I3 \& S2 n2 d6 |5 r
1 }: G# b" k" M# ?4 t* ^ {! O9 v/ Y/ k1 E0 i
"code": 0,, l. M' _' o# T! j9 x
"message": "success",
+ I1 `2 M8 v5 A! N& b "extMessage": null,
1 v f. n& u. y$ \ "appServiceId" - W/ S3 x% _8 W: C3 F3 ^
: "/bean/rabbitmq-hello",. _# }- X5 ~ Z) N0 A1 h
"traceId": "005bacd128624473a08f3d0eb725baf1",/ H* H, o0 D8 a& \4 U
"parentTraceId": null,
5 P7 v) d8 M, o ! J$ g4 L6 m7 I) z
"timestamp": 1649128731865,& e# ^) P& x7 y- N; G& @
"data": {
% L# x1 t( `1 r* Q" e8 ^$ J7 h "result": "hello,world"
- B. \( Z0 ]4 ?9 R8 H8 @ }: }3 U1 ^/ o# x1 X, w. ^
}SampleAppLogApplication应用输出日志:
0 [! q4 b* U& v( Z1 {2 V [sample-app-log:0.0.0.0:8100] 11:18:52 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer
. c: C. X$ Y3 G% f" C8 N #0-1] c.b.b.s.a.listener.AppLogQueueListener0-App服务成功 App服务ID:/bean/rabbitmq-hello 返回码:0-success 平台流水号:
4 r8 D2 @( M2 V9 E$ r0 C2 F( o 005bacd128624473a08f3d0eb725baf1
. q* H K6 o0 L+ S# p0 e 请求报文:{"methodName":"hello","params":["world"]}# X* |* Y* [7 ?" e: g0 N
响应报文:{"result":"hello,world" / \. Y: t' D F6 o
}
' ?3 e! z: j7 f/ W! ~1 w [sample-app-log:0.0.0.0:8100] 11:18:52 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer 5 A, w$ [) F! X2 e* @$ r7 L9 n! z
#0-2] c.b.b.s.a.listener.AppLogQueueListener3-Sink服务成功 App服务ID:/bean/rabbitmq-hello 返回码:0-success 平台流水号:
5 n' t! Y$ w7 C# c7 s% L 005bacd128624473a08f3d0eb725baf1
! l5 D k9 U9 T, ^1 q5 ?* c1 s+ `4 q/ B 请求报文:{"methodName":"hello","className":"com.bizmda.bizsip.sample.sink.api.HelloInterface"
8 w' B! j* m) P6 K ,"params":["4"]}
* I! K; Y( v5 r, J; M- j. m 响应报文:{"result":"hello,4"}5 x1 T5 D' |5 @' }$ l
[sample-app-log:0.0.0.0:8100] 11:18:52 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer
- }3 Q( t& l" A' s #0-3] c.b.b.s.a.listener.AppLogQueueListener3-Sink服务成功 App服务ID:/bean/rabbitmq-hello 返回码:0-success 平台流水号: : A; T$ s( N) l- r) Q
005bacd128624473a08f3d0eb725baf1$ z& e/ E0 [1 g# P$ ]! ]
请求报文:{"methodName":"hello","className":"com.bizmda.bizsip.sample.sink.api.HelloInterface"
' V' F, S5 K* P, ?2 g9 b ,"params":["6"]}, V# f, {% g2 o, R# q' U+ A
响应报文:{"result":"hello,6"}
7 K* ?+ V0 F9 N [sample-app-log:0.0.0.0:8100] 11:18:52 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer / y' m& g) v0 p/ g% _" F
#0-4] c.b.b.s.a.listener.AppLogQueueListener3-Sink服务成功 App服务ID:/bean/rabbitmq-hello 返回码:0-success 平台流水号:
0 y9 W; p8 W) j# g$ _, z 005bacd128624473a08f3d0eb725baf1
1 P% B9 ^4 Q; x+ _. p+ @4 p9 ]. M; ?8 O 请求报文:{"methodName":"hello","className":"com.bizmda.bizsip.sample.sink.api.HelloInterface"
8 e; f1 j& F) a5 F0 u7 {: M- j ,"params":["2"]}7 S: }9 V8 H+ K
响应报文:{"result":"hello,2"}3、调用App延迟服务$ curl -H "Content-Type:application/json" -H "Biz-Service-Id:/bean/sample15" % }3 P" L; }9 j. a; J) }
-X POST --data{"maxRetryCount":3,"result":"fail"} http://localhost:8888/api|jq9 C+ K0 |: I4 U$ ?! _; `
) C/ D+ j3 e( W5 i
{3 U1 P7 W% S ]! n. f, t2 ]+ C# Q6 S
"code": 0,' |" Q0 U4 d2 a
"message"
2 E& B0 p/ V7 [3 M8 o8 f& S8 X : "success",8 g! E9 C9 U: ^+ Q8 b, b
"extMessage": null,
5 [. w. z* j# t7 I "appServiceId": "/bean/sample15",
8 o! T. M1 n4 y) k' k "traceId": "368fdbfa6db440b3bb3f2f5bef1363b7"
1 Q' [3 |7 a+ k8 H ,
4 }; |. s9 v z3 c) `* w "parentTraceId": null,* _. l& M. d0 a- B9 h
"timestamp": 1649128965634,
+ v6 a3 T& B# X" n/ C6 T "data": { b# B8 @: |7 j/ Y
"maxRetryCount": 3,
3 N. ^ y: F# X- ]8 T "result" 1 X2 A( q+ ^2 ~0 C
: "fail"
7 d9 Q5 a- ^, V8 _2 N5 A }
/ S% Q3 A- e% `# x- X, ~ }SampleAppLogApplication应用输出日志:[sample-app-log:0.0.0.0:8100] 11:22:45 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer
, i+ a7 I- o% v( j3 U& b& W' v1 X #0-1] c.b.b.s.a.listener.AppLogQueueListener0-App服务成功 App服务ID:/bean/sample15 返回码:0-success 平台流水号:368fdbfa6db440b3bb3f2f5bef1363b7
" j$ c- G, i6 N. p% w" a- l 请求报文:{ ( u+ l( O: L* e
"maxRetryCount":3,"result":"fail"}
1 w$ G! w7 f' \/ l% I+ m2 ~ 响应报文:{"maxRetryCount":3,"result":"fail"}9 u) T* T0 g. S
[sample-app-log:0.0.0.0:8100
X, P2 Q# {5 \( k: C1 u* o ] 11:22:45 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-5] c.b.b.s.a.listener.AppLogQueueListener
$ I$ `/ y9 S3 t/ W3 y8 f: g; [% ] 2-App服务挂起 App服务ID:/bean/sample15 返回码:0-null 平台流水号:368fdbfa6db440b3bb3f2f5bef1363b7
% ~# [) S/ }, D3 J d2 i 请求报文:{"maxRetryCount"
' x8 L* J8 [, }; D :3,"result":"fail"}
( s# e5 A( V4 s3 z. I 响应报文:{"maxRetryCount":3,"result":"fail"}2 Q( }: M K0 w$ K$ V) f
[sample-app-log:0.0.0.0:8100] 11:22:45 INFO ' }. X% R, Y% g4 S+ \6 S8 p( Z' e
60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-2] c.b.b.s.a.listener.AppLogQueueListener 8 U* u( C% U& q6 y! J
2-App服务挂起 App服务ID:/bean/sample15-delay 返回码:8-重试App延迟服务 平台流水号:0697aca84a61439581bf75271453d191: @+ p, x! N8 t( M" o& t i P0 _& R
请求报文:{"maxRetryCount"
* i4 b7 n+ S1 E# l7 f; d :3,"result":"fail"}
8 |. r# T3 @0 V' i8 N 响应报文:null
5 T9 |3 J( E; t! U/ @ [sample-app-log:0.0.0.0:8100] 11:22:46 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer 5 s- G4 X/ n* z1 h- B" u/ W4 j
#0-4] c.b.b.s.a.listener.AppLogQueueListener2-App服务挂起 App服务ID:/bean/sample15-delay 返回码:8-重试App延迟服务 平台流水号: # H. q, l$ ?2 M9 E
0697aca84a61439581bf75271453d191
. G" I8 e: A0 t+ A1 y& R J 请求报文:{"maxRetryCount":3,"result":"fail"}
/ z8 A" d, V! }" d 响应报文:null4 S' I R8 O9 C( l
[sample-app-log:0 & Q {: @9 I1 v+ Q! E$ T
.0.0.0:8100] 11:22:48 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-3] c.b.b.s.a.listener.AppLogQueueListener
$ \! J& \! I$ j 1-App服务失败 App服务ID:/bean/sample15-delay 返回码:899-其它错误 平台流水号:0697aca84a61439581bf75271453d1910 _7 z3 V- `6 l$ Z3 _, s( @
请求报文:{"maxRetryCount"
3 o3 _" m6 Y- E( W8 P( K :3,"result":"fail"}6 f3 _0 D( @8 v; W& f+ }
响应报文:nullBiz-SIP网站:http://bizsip.bizmda.comGitee代码库:https://gitee.com/szhengye/biz-sip : k2 ?" \7 X6 D' e V G
5 _3 E$ b9 Q% G$ P, N8 ^+ K
2 D B* L$ o9 b0 X1 G, u/ A
- o0 c Q9 D' g [% P
% X) Q( H% ^9 |4 X6 G C" W |