|
+ r6 H! m: h' }4 W F; ^: K4 v, U Biz-SIP金融级业务中台(http://bizsip.bizmda.com)是一套基于领域驱动设计(DDD)架构,能快速构建金融级云原生架构的服务整合中间件,整合了在金融场景里锤炼出来的最佳实践Biz-SIP业务中台在运行时,会把相关的交易日志通过RabbitMQ消息中间件发送出来,开发人员可以实现这些交易日志的接收和处理。 5 B1 F. u3 p9 F' ?* E! T9 K
案例要求:发送不同类型的Biz-SIP交易,交易日志接收模块会收到不同类型的交易日志:
! x. |& B2 e5 ]3 C2 t 具体代码和配置可以查看Biz-SIP源代码中的Sample相关测试案例(https://gitee.com/szhengye/biz-sip)一、App层的配置在application-local.yml配置文件中,设置bizsip.rabbitmq-log属性为“success”,表示发送成功、挂起、失败类型的交易日志,即所有的交易日志:
; Q& u6 D& f5 G, Q0 m( F bizsip:" }6 z) ?3 w6 B; K* R! Z
config-path: /var/bizsip/config0 z$ b+ Z5 y" v7 w* H# {/ W
rabbitmq-log: success二、交易日志处理应用的开发和配置首先,编写交易日志侦听器:@Slf4j@Service
7 B! M. I4 Y# J1 _' x publicclass AppLogQueueListener {1 g9 i4 ~! ?( V* N* d
publicstatic final String APP_LOG_QUEUE = "queue.bizsip.applog" + O5 V1 L8 x/ s7 m# F* T
;
. t$ a3 c3 ^ h, u7 Z- d privatestatic final String[] APP_LOG_TYPE={"0-App服务成功 ","1-App服务失败 ","2-App服务挂起 ","3-Sink服务成功",
4 T3 r* P" W+ q& I/ t "4-Sink服务失败"};
& d' p3 P' U8 q9 O# S# H private Jackson2JsonMessageConverter jackson2JsonMessageConverter =new Jackson2JsonMessageConverter();$ N2 d+ S: [% V# o' G0 I9 x
2 ~; t/ P& `; F( }/ m. {
u O. i9 A. X2 y# X" v @RabbitListener(bindings = @QueueBinding(
5 I4 R2 f/ n) r3 x; b$ @ value = @Queue(value = APP_LOG_QUEUE, durable = % i! _; V1 Z3 Z* D" j: X) a/ a
"true", autoDelete = "false"),* m! V. H1 F- @" W2 B. v Z
exchange = @Exchange(value = BizConstant.BIZSIP_LOG_EXCHANGE, ; A( u) `; s7 J) H0 j& g
type = ExchangeTypes.DIRECT, durable = "true", autoDelete = "false"),; y& E' e& n3 ~! _# E1 {
key = BizConstant.BIZSIP_LOG_ROUTING_KEY))( ^+ |+ Z: u/ ~7 v
5 q ]. r Z+ v8 O' O
publicvoid onMessage(Message message) {# h6 l- L0 n) P4 k4 y. }4 `! B
try {7 @# ]+ y6 d0 {3 M! X
this.process(message);
4 z- h+ I# a. L# V+ o }/ |2 G! P' ]' p# k( K: H* c
% [; \. O' u, d9 U2 l, c( Q7 h catch (Exception e) {# Z- q! M& Y3 m8 Q
log.error("App服务日志侦听器出错!",e);
0 V6 g2 S2 {& i0 l: y( H }/ \7 A4 W3 R. M. Q7 H7 R/ D
}- B6 \5 t/ `+ {9 Y9 r
* I3 }+ G f5 ?; X2 g privatevoid process(Message message) {5 _* D( C0 K& R% i0 [& j+ b* ^* I, w: ?
Map<
3 a" R$ W5 H6 ] String,Object> map = (Map)jackson2JsonMessageConverter.fromMessage(message);
3 e( w' ?! M1 ]: f3 R int " J$ V- d! a& o& c8 a
type = (int)map.get("type");
4 l% _/ Y! n! n/ } BizMessage inBizMessage = new BizMessage<>((Map) map.get(
! H p/ h# N+ y( R' w# ~ "request"));
4 q( F) F) }' k h3 y/ _/ | BizMessage outBizMessage = new BizMessage<>((Map) map.get("response" ! {1 B" \+ u0 p# o! Q3 M. Z
)); d. a9 S% Z8 z
log.info("\n{} App服务ID:{} 返回码:{}-{} 平台流水号:{}\n请求报文:{}\n响应报文:{}",
, i. d, z0 h @8 l1 C- @2 T APP_LOG_TYPE[
L. a* s) F+ ?- |4 a" I type],inBizMessage.getAppServiceId(),) B/ T0 t8 w3 i/ r8 v) J
outBizMessage.getCode(),outBizMessage.getMessage(),inBizMessage.getTraceId(),
& r- I' D, R4 |# `* d, ] inBizMessage.getData(),outBizMessage.getData());
7 e4 d+ L# f, ~0 E$ A& V
8 [% W0 U6 C# |4 T( i2 j return;
8 j! Q( r }, a) X+ ~! w }
% @2 I( a/ Q. T }接着,编写应用启动类SampleAppLogApplication.java,以及相关的application*.yml配置文件,特别注意application-local.yml中相关RabbitMQ的部分配置:
/ }" P M1 X" h- F6 z7 J1 w& B/ v4 X rabbitmq:virtual-host:/host:rabbitmq.bizmda.comport:5672username:adminpassword:adminlistener:simple:concurrency:
& I0 ^& U/ ^5 k! p, a 5max-concurrency:15prefetch:10三、启动应用进行测试启动SampleAppApplication应用、SampleSinkApplication应用、SampleSourceApplication应用,以及SampleAppLogApplication应用,通过开放平台接口发起请求,进行一系列的测试:
5 q5 h8 @. P& Y, r. e 1、发起最简单的App服务$ curl -H "Content-Type:application/json" -H "Biz-Service-Id:/bean/sample1" -X POST --data { 7 G. c% M u. d! n! i8 d
"accountNo":"62001818","sex":"0","email":"123232@163.com","mobile":"18601872345"} http://localhost:8888/api|jq , C& j; v0 E/ t K# C6 f
( M7 b4 d- d! c, y
4 q$ i* b' G7 i; }; v {
0 Q+ l# X b9 R "code": 0,
" v4 {+ {: `. ]+ Y0 h) t( R "message": "success",
# U; h8 n- Z& g: S% n "extMessage": null,* V( z4 j+ C4 H3 v5 l; v
"appServiceId": "/bean/sample1",/ x# l# i' d( @. G
"traceId" . X3 G! R! \! d2 K% [' l
: "4fde178ff7b040f5adfc7a2c1b4b18b6",
5 }0 c/ ?5 l0 x! Z9 B "parentTraceId": null,
- W. G( b$ q' {9 \: X. Z9 X "timestamp": 1649128499806,6 ^. v! s% L2 u* D5 R! _
"data"
% Z1 d( D- x, n6 n+ Y. U F0 f+ {/ T : {) F6 C* {' q( z# m9 ~0 h0 J
"sex": "0",
' e& a1 C& Y* a- I( b% Y$ B& p- N "mobile": "18601872345",
' w& n3 F& V3 F6 r# J \5 P "accountNo": "62001818",, L |' Z5 o! w# ~3 F# k8 l3 J1 i
"email": "123232@163.com" 0 ~2 M. d; P, W6 ^3 h' {: t! M
7 x8 e5 Q6 ~- [8 z }3 i) B2 }+ q4 M9 K! G9 r
}SampleAppLogApplication应用输出日志:[sample-app-log:0.0.0.0:8100] 11:14:59 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer
; R5 r" f: a4 P# V) `( Z1 G. V #0-5] c.b.b.s.a.listener.AppLogQueueListener0-App服务成功 App服务ID:/bean/sample1 返回码:0-success 平台流水号:4fde178ff7b040f5adfc7a2c1b4b18b6& f3 n" o/ P7 f0 h! u4 Z7 x
请求报文:{ ; ^& u% |' Q9 `
"sex":"0","mobile":"18601872345","accountNo":"62001818","email":"123232@163.com"}
' f4 y: ?, |0 _4 m2 c) { 响应报文:{"sex":"0","mobile" ; D' K& V) V* U9 O# J" V' p3 v: H
:"18601872345","accountNo":"62001818","email":"123232@163.com"}2、通过RabbitMQ异步调用Sink服务curl -H "Content-Type:application/json"
$ Q- {5 V8 m! E -H "Biz-Service-Id:/bean/rabbitmq-hello" -X POST --data{"methodName":"hello","params":["world"]} http:
# C5 S0 Z+ T |: G //localhost:8888/api|jq
4 ^1 Q" d& a2 X+ f/ m
( U& e$ U/ @4 z! c5 R$ ? {& j k# f$ O$ Q4 Y9 `$ N$ ^
"code": 0,* @$ F6 A9 T: U6 f- _3 u' U/ n% E4 T( s
"message": "success",
7 n' t4 N* t, n0 f% t$ o$ @ "extMessage": null,; E5 S! l/ _ e F
"appServiceId" / z9 o7 U2 i# K! r: F
: "/bean/rabbitmq-hello", @$ q: I$ X( R c# [ }
"traceId": "005bacd128624473a08f3d0eb725baf1",8 D$ u4 n7 o) {6 u" @# u% _
"parentTraceId": null,5 e# r: d6 F6 i6 ]2 S7 h- A
- X1 `4 m9 R3 x' M7 E
"timestamp": 1649128731865,
% F# M& B; u1 K' Y2 D' x- @ "data": {
9 j. R, \! ~* e3 D n3 Z0 P+ l7 V "result": "hello,world"& @6 o- i- N, F; U% w7 @
}9 ^; o; m$ ^$ J4 Z
}SampleAppLogApplication应用输出日志: / }; N9 A- n' _4 Y3 `/ i9 g
[sample-app-log:0.0.0.0:8100] 11:18:52 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer 5 A& J6 I6 x6 g, a4 L# ~
#0-1] c.b.b.s.a.listener.AppLogQueueListener0-App服务成功 App服务ID:/bean/rabbitmq-hello 返回码:0-success 平台流水号:
0 U* F; y& `- P3 H3 a 005bacd128624473a08f3d0eb725baf15 q2 c6 w! i, k+ s
请求报文:{"methodName":"hello","params":["world"]}
6 d- E3 ]6 k/ T! r# l! T" {) ~ 响应报文:{"result":"hello,world"
# F! U \) x+ C+ K4 o( H4 e }; c% U" g2 m2 c' w G. z
[sample-app-log:0.0.0.0:8100] 11:18:52 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer
5 \! E' X. f! N- L4 O/ _+ Q, i #0-2] c.b.b.s.a.listener.AppLogQueueListener3-Sink服务成功 App服务ID:/bean/rabbitmq-hello 返回码:0-success 平台流水号: , E3 L6 [2 A& o2 u! x
005bacd128624473a08f3d0eb725baf1, ^; J" F6 R5 y+ S4 _5 u
请求报文:{"methodName":"hello","className":"com.bizmda.bizsip.sample.sink.api.HelloInterface" ( L4 S: o- H. P; X% Y0 V7 g! N' v
,"params":["4"]}
0 ~4 R% p9 w+ X! b( z 响应报文:{"result":"hello,4"}, Q( n0 R4 X" X
[sample-app-log:0.0.0.0:8100] 11:18:52 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer 0 \. ?+ Z& `, Q* F
#0-3] c.b.b.s.a.listener.AppLogQueueListener3-Sink服务成功 App服务ID:/bean/rabbitmq-hello 返回码:0-success 平台流水号:
- G1 |/ M9 o: r2 Q( K9 _# g 005bacd128624473a08f3d0eb725baf10 ^ m* a s0 R
请求报文:{"methodName":"hello","className":"com.bizmda.bizsip.sample.sink.api.HelloInterface"
8 N: N, c/ v1 D! D1 L1 C ,"params":["6"]}
/ ~5 G. z9 F+ ^% h* |; i) V6 ^8 r 响应报文:{"result":"hello,6"}8 d8 a9 h) Y) L
[sample-app-log:0.0.0.0:8100] 11:18:52 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer
8 @/ z* v* {) y* j( c6 Z #0-4] c.b.b.s.a.listener.AppLogQueueListener3-Sink服务成功 App服务ID:/bean/rabbitmq-hello 返回码:0-success 平台流水号: ' j0 z" F/ @1 B/ m) v
005bacd128624473a08f3d0eb725baf1# M7 ?5 f# x5 k F
请求报文:{"methodName":"hello","className":"com.bizmda.bizsip.sample.sink.api.HelloInterface"
4 \+ ^5 r: c5 _; W9 u5 ? ,"params":["2"]}6 F4 y: w. q9 Z& ]( b: I4 d* I/ j
响应报文:{"result":"hello,2"}3、调用App延迟服务$ curl -H "Content-Type:application/json" -H "Biz-Service-Id:/bean/sample15" ) L# Z1 P# u$ L, L& G
-X POST --data{"maxRetryCount":3,"result":"fail"} http://localhost:8888/api|jq: [+ M5 U1 e; r8 E: M
6 I0 y. c' @, p3 O! K
{
/ y8 q. D6 M" t c "code": 0,: t' B/ B/ J5 I
"message"
' G4 G) M! t+ i6 Q8 c1 ^7 C : "success",) A$ {) l3 P9 K4 g4 }/ X
"extMessage": null,* u( @0 e% [0 R: t% I3 Q V6 E
"appServiceId": "/bean/sample15",
( n1 d. M& M' R q3 j "traceId": "368fdbfa6db440b3bb3f2f5bef1363b7" ( k9 P7 n) x" l+ s% x9 a) O
,5 U+ s; f0 Z- N/ n
"parentTraceId": null,
& q5 U2 a: @( d; J& ~. b/ J# o "timestamp": 1649128965634,7 c$ S. S5 |/ H0 X" F( |
"data": {
3 k0 { w7 k, g) n H( L0 @: | "maxRetryCount": 3,/ U% j$ O# z4 ]6 h) g
"result" 3 ^; S1 B: `. B" \7 i, W
: "fail"
. n+ t% F0 E- Q# t P/ b7 V6 O }6 J6 f; g- T& x3 z% {0 S2 V
}SampleAppLogApplication应用输出日志:[sample-app-log:0.0.0.0:8100] 11:22:45 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer ' j5 w {# k' I8 c6 L; t
#0-1] c.b.b.s.a.listener.AppLogQueueListener0-App服务成功 App服务ID:/bean/sample15 返回码:0-success 平台流水号:368fdbfa6db440b3bb3f2f5bef1363b76 \3 p4 d L' t3 Q! L6 M! I* F; ?$ h
请求报文:{
' f# e3 v x2 W# O "maxRetryCount":3,"result":"fail"}" [1 {5 q4 t' I a
响应报文:{"maxRetryCount":3,"result":"fail"}
; S! f$ W' o) ~8 G [sample-app-log:0.0.0.0:8100
' V8 a3 g1 V0 _/ a) f% f ] 11:22:45 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-5] c.b.b.s.a.listener.AppLogQueueListener 7 I$ U$ ~6 m3 @
2-App服务挂起 App服务ID:/bean/sample15 返回码:0-null 平台流水号:368fdbfa6db440b3bb3f2f5bef1363b71 X: K; F b+ U7 ~: S# ~; h
请求报文:{"maxRetryCount"
# T6 @* o# E' |* Z' V :3,"result":"fail"}+ z1 u! f% `6 |9 `
响应报文:{"maxRetryCount":3,"result":"fail"}
# N T0 q9 Y# [: f# U [sample-app-log:0.0.0.0:8100] 11:22:45 INFO ( G8 }# S; i/ P
60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-2] c.b.b.s.a.listener.AppLogQueueListener - E* e3 T: T" H/ `: W0 F. B: E1 z8 F
2-App服务挂起 App服务ID:/bean/sample15-delay 返回码:8-重试App延迟服务 平台流水号:0697aca84a61439581bf75271453d1916 P" Y) J& `# `( p
请求报文:{"maxRetryCount" ' c9 l: q& {; i8 T1 e* [
:3,"result":"fail"}
: a) R+ l) {; I* c9 u 响应报文:null
6 U; _$ h$ s! c3 n7 i* } [sample-app-log:0.0.0.0:8100] 11:22:46 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer
% x4 g! G1 E, E) g& ^ #0-4] c.b.b.s.a.listener.AppLogQueueListener2-App服务挂起 App服务ID:/bean/sample15-delay 返回码:8-重试App延迟服务 平台流水号:
& A. A1 \) c$ O# G* t6 k- ~ 0697aca84a61439581bf75271453d191
% u4 z7 a" d+ ]) I 请求报文:{"maxRetryCount":3,"result":"fail"}
6 @+ ~5 o6 ?9 H2 n q% o 响应报文:null9 A; x) O. ]+ B, r4 V* g
[sample-app-log:0
1 e1 o5 R5 g* Y" U- p d .0.0.0:8100] 11:22:48 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-3] c.b.b.s.a.listener.AppLogQueueListener
' t& W' d( O" g& _* @( D 1-App服务失败 App服务ID:/bean/sample15-delay 返回码:899-其它错误 平台流水号:0697aca84a61439581bf75271453d191
3 U( k9 c: M3 X' T 请求报文:{"maxRetryCount"
% s! ~! |. ^4 ^1 E; n2 O( f :3,"result":"fail"}
5 Q7 m* Y5 }2 D, E$ u% g 响应报文:nullBiz-SIP网站:http://bizsip.bizmda.comGitee代码库:https://gitee.com/szhengye/biz-sip 9 M4 ?# \% m- {, X1 q0 d9 a
' J9 v' F+ Z7 G$ y1 u7 q6 } b0 n4 Y# V7 K( I0 g3 H( b/ n; @
% j5 L3 d; D! H5 H. N/ X
) I0 g0 R( r+ S5 v+ n1 e
|