|
7 q5 Z& J# u5 o) v
Biz-SIP金融级业务中台(http://bizsip.bizmda.com)是一套基于领域驱动设计(DDD)架构,能快速构建金融级云原生架构的服务整合中间件,整合了在金融场景里锤炼出来的最佳实践Biz-SIP业务中台在运行时,会把相关的交易日志通过RabbitMQ消息中间件发送出来,开发人员可以实现这些交易日志的接收和处理。 8 A# n& _4 L$ h
案例要求:发送不同类型的Biz-SIP交易,交易日志接收模块会收到不同类型的交易日志: : u7 D' x, E5 I6 n
具体代码和配置可以查看Biz-SIP源代码中的Sample相关测试案例(https://gitee.com/szhengye/biz-sip)一、App层的配置在application-local.yml配置文件中,设置bizsip.rabbitmq-log属性为“success”,表示发送成功、挂起、失败类型的交易日志,即所有的交易日志: 3 b# D0 }1 c# F) X
bizsip:
2 L8 x0 l9 E3 [5 v& f) ? config-path: /var/bizsip/config
3 w9 M1 y' J0 \2 {9 {4 ` rabbitmq-log: success二、交易日志处理应用的开发和配置首先,编写交易日志侦听器:@Slf4j@Service 2 k/ a _9 j% Q* H+ e
publicclass AppLogQueueListener {
2 E; K' P: v4 m7 V; x2 x publicstatic final String APP_LOG_QUEUE = "queue.bizsip.applog" % i0 W1 g! E) p% J5 o/ q
;+ @& S# ]+ ~4 O! b1 R) @+ F2 M
privatestatic final String[] APP_LOG_TYPE={"0-App服务成功 ","1-App服务失败 ","2-App服务挂起 ","3-Sink服务成功", $ d! Z8 L5 i4 |; R0 d
"4-Sink服务失败"};2 L! }8 s3 p- f8 E/ E; ]
private Jackson2JsonMessageConverter jackson2JsonMessageConverter =new Jackson2JsonMessageConverter();* N& @6 w0 B/ A. R
; X* Z& b& P# m/ S
' n; b0 _2 a4 v- z H' g @RabbitListener(bindings = @QueueBinding(
! F0 C% t u! B# M: j value = @Queue(value = APP_LOG_QUEUE, durable = ) K+ f9 {2 [3 Q% F
"true", autoDelete = "false"),' R; M2 i( j7 ~3 p
exchange = @Exchange(value = BizConstant.BIZSIP_LOG_EXCHANGE,
2 P7 B9 q& L6 r4 r7 k type = ExchangeTypes.DIRECT, durable = "true", autoDelete = "false"),7 z. |7 B6 _$ r; X
key = BizConstant.BIZSIP_LOG_ROUTING_KEY))0 F# }6 R P o" b
! R, Z: ?: C* W& z' q
publicvoid onMessage(Message message) {" t' b# P# X( m% k2 L
try {7 u+ K1 C, O" K+ r9 P( [( v' `7 Q; v
this.process(message);
. m2 O3 F, M0 c$ h$ z }' B9 C& d' v" D3 G+ N" n" }
1 P( A O, u: G& o c8 A1 J
catch (Exception e) {
6 k( E" C' Z4 a" g2 { log.error("App服务日志侦听器出错!",e);- [( ~! j5 k9 ~, D! k4 N
}
7 z/ o& E1 p4 i, x3 f }3 b$ B( B- a" N' x( O
/ n* d: B, C2 V2 W
privatevoid process(Message message) {, ]6 N# C! w. z J
Map<
% _( u) ?) x) W0 f5 e& ? String,Object> map = (Map)jackson2JsonMessageConverter.fromMessage(message);
5 {; X* Q( W3 Q: n. W% V' x& b int
: d5 d2 J+ u+ j type = (int)map.get("type");8 V; Q" z5 Z# {2 ?! t& P% |
BizMessage inBizMessage = new BizMessage<>((Map) map.get(
6 p; Z( c" T$ s4 s "request"));
; l3 V% o6 w7 |4 j3 R4 @ BizMessage outBizMessage = new BizMessage<>((Map) map.get("response" / {/ q+ w' ^$ k4 O* s
));
8 q8 E3 _3 u4 `5 z log.info("\n{} App服务ID:{} 返回码:{}-{} 平台流水号:{}\n请求报文:{}\n响应报文:{}",
& b7 z/ d$ f) s5 G) P APP_LOG_TYPE[ ) C* T% d+ s$ r; k @% x
type],inBizMessage.getAppServiceId(),
+ b/ Z5 z. z) N8 N outBizMessage.getCode(),outBizMessage.getMessage(),inBizMessage.getTraceId(),
% A& a6 i9 m w7 y1 w inBizMessage.getData(),outBizMessage.getData());
1 V- [" `. x' m, Z [ 3 }6 ~- ~3 n3 Q3 d
return;
; J' ?0 L5 |9 `/ u* p: x j }
( N+ V$ h7 r7 o/ _+ j! s6 } }接着,编写应用启动类SampleAppLogApplication.java,以及相关的application*.yml配置文件,特别注意application-local.yml中相关RabbitMQ的部分配置:
3 R1 \# v6 ?/ r1 m/ \' B rabbitmq:virtual-host:/host:rabbitmq.bizmda.comport:5672username:adminpassword:adminlistener:simple:concurrency: ; V& X# n0 y+ r, {2 k
5max-concurrency:15prefetch:10三、启动应用进行测试启动SampleAppApplication应用、SampleSinkApplication应用、SampleSourceApplication应用,以及SampleAppLogApplication应用,通过开放平台接口发起请求,进行一系列的测试:
' ]* g; g! ~; k! |& F# Y 1、发起最简单的App服务$ curl -H "Content-Type:application/json" -H "Biz-Service-Id:/bean/sample1" -X POST --data {
0 u+ }" _" C/ f% k6 T9 k "accountNo":"62001818","sex":"0","email":"123232@163.com","mobile":"18601872345"} http://localhost:8888/api|jq 4 s$ a C, I4 M2 m+ E% {
$ x" v7 Q: R+ |0 [( `2 d
3 z6 \* s9 r& z% j {) Z) \$ y# k% @) z0 R( P- Z
"code": 0,
) X1 _( Y) @! L8 ~ "message": "success",4 A5 g- h7 t) P2 X0 w* \& M
"extMessage": null,' N" i r! _: ~* `! u. E
"appServiceId": "/bean/sample1",* \8 |' Q- j1 X) H {$ H
"traceId" % a+ }, D( Z# J' N
: "4fde178ff7b040f5adfc7a2c1b4b18b6",2 v& a' o4 i# D, w$ ~0 B8 L0 A
"parentTraceId": null,
; V: h$ ?# B& v+ \4 {! ] "timestamp": 1649128499806,
+ e# U4 u, A7 k* I- ? "data"
2 u& O; [8 r$ A& e& Y : {
, b4 X4 ]" i& O" K5 t "sex": "0",
9 n/ i6 J3 H% [4 m "mobile": "18601872345",0 @0 |' w# P) s: {2 R- W: g
"accountNo": "62001818",
- D; e; C. A5 K/ }; K' c; } "email": "123232@163.com"
2 [ @% O- N* M/ c8 B8 X; D2 L
% d* r" J- m% Y7 m }
* {8 |1 \* g3 H5 h4 X7 [ }SampleAppLogApplication应用输出日志:[sample-app-log:0.0.0.0:8100] 11:14:59 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer
/ O0 g( d. J1 Q+ Q' t/ M" U #0-5] c.b.b.s.a.listener.AppLogQueueListener0-App服务成功 App服务ID:/bean/sample1 返回码:0-success 平台流水号:4fde178ff7b040f5adfc7a2c1b4b18b6/ E5 V* J2 M6 p8 g: b2 Z/ v* I
请求报文:{ 8 Q9 a5 `4 Y5 `4 _' N" F' J L' K
"sex":"0","mobile":"18601872345","accountNo":"62001818","email":"123232@163.com"}9 W6 T6 L4 A( q, i0 ]6 q
响应报文:{"sex":"0","mobile"
) S1 |6 B5 n+ W% A" z; R9 C :"18601872345","accountNo":"62001818","email":"123232@163.com"}2、通过RabbitMQ异步调用Sink服务curl -H "Content-Type:application/json" " O# x4 K$ Q) v. P' M
-H "Biz-Service-Id:/bean/rabbitmq-hello" -X POST --data{"methodName":"hello","params":["world"]} http:
) Y; z% s' G" t# y9 T7 v //localhost:8888/api|jq* c3 o: r3 a% A! D; Z
* t3 Q" G* L7 g! v1 b8 N G5 |
{
7 y8 P' I4 D6 g3 Z0 s& L4 i5 [ "code": 0,
) ?6 t2 |6 X' N& Q( t: l% n( w "message": "success", R4 K! D) m" v' A( `# A
"extMessage": null,
' e6 i, ^9 b1 y, S* K "appServiceId" 3 F2 e5 T$ G6 ]# {% ]1 \- a. t' v
: "/bean/rabbitmq-hello",
. W, I' a7 d; j. N X" G "traceId": "005bacd128624473a08f3d0eb725baf1",1 J Y" x, ^( o! J/ B/ Q1 O
"parentTraceId": null,3 T' L: k/ d% i
) L) q+ q' K/ Z" d "timestamp": 1649128731865,
3 t, j8 `" b: b8 v0 k "data": {
6 z* j$ a) M9 X" U' t# a8 q* @ "result": "hello,world"2 G0 L1 m0 L) L
}
+ i: G+ C6 V7 ~1 P% C }SampleAppLogApplication应用输出日志: 5 A4 v1 J$ ]! V) Z D( R. U
[sample-app-log:0.0.0.0:8100] 11:18:52 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer * l3 N9 x, J3 [9 j" s, E
#0-1] c.b.b.s.a.listener.AppLogQueueListener0-App服务成功 App服务ID:/bean/rabbitmq-hello 返回码:0-success 平台流水号: * _/ r$ D) |8 K
005bacd128624473a08f3d0eb725baf1" S1 o6 h- T/ z: q. {' q+ `5 F
请求报文:{"methodName":"hello","params":["world"]}
* D1 [# c4 p% N# A4 { 响应报文:{"result":"hello,world" / d& t/ b; D0 D8 U" m& o4 P
}
' h, f+ @6 ]1 J6 {! t [sample-app-log:0.0.0.0:8100] 11:18:52 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer 2 C) v# t8 u& X% N- ]
#0-2] c.b.b.s.a.listener.AppLogQueueListener3-Sink服务成功 App服务ID:/bean/rabbitmq-hello 返回码:0-success 平台流水号:
+ Y( |! C/ A9 v! {5 h 005bacd128624473a08f3d0eb725baf1
6 c0 @4 y( {" N 请求报文:{"methodName":"hello","className":"com.bizmda.bizsip.sample.sink.api.HelloInterface" f7 i( ?+ t2 h$ ?+ q2 P6 q
,"params":["4"]}, e: Q0 m. ?: R8 f$ j
响应报文:{"result":"hello,4"}
5 B- `6 E' l' x9 h [sample-app-log:0.0.0.0:8100] 11:18:52 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer 1 `+ e4 H. N0 f- W2 ^% ]. p5 i
#0-3] c.b.b.s.a.listener.AppLogQueueListener3-Sink服务成功 App服务ID:/bean/rabbitmq-hello 返回码:0-success 平台流水号:
' B8 c1 ^0 |4 G' `: G 005bacd128624473a08f3d0eb725baf1
$ ?$ M* Y2 Z) ?, C, W+ I3 x) a8 T 请求报文:{"methodName":"hello","className":"com.bizmda.bizsip.sample.sink.api.HelloInterface" - g h& a/ }/ b# w, J. ~2 W- l
,"params":["6"]}
- p, Z# S' n9 d9 P( U 响应报文:{"result":"hello,6"}9 r1 {! w8 z2 P/ t
[sample-app-log:0.0.0.0:8100] 11:18:52 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer ' y# z, U- ~) i8 x- a
#0-4] c.b.b.s.a.listener.AppLogQueueListener3-Sink服务成功 App服务ID:/bean/rabbitmq-hello 返回码:0-success 平台流水号: 6 b+ m4 }. h2 U4 [- s& P
005bacd128624473a08f3d0eb725baf1
( s8 s* n1 v3 P$ C" N 请求报文:{"methodName":"hello","className":"com.bizmda.bizsip.sample.sink.api.HelloInterface" . j0 J- m. V- X7 M
,"params":["2"]}0 |( n& u" ]+ n3 C7 }
响应报文:{"result":"hello,2"}3、调用App延迟服务$ curl -H "Content-Type:application/json" -H "Biz-Service-Id:/bean/sample15"
( j% V* z# K& i+ S8 p9 u -X POST --data{"maxRetryCount":3,"result":"fail"} http://localhost:8888/api|jq L( b, }$ f- d( T. n$ G8 q- n, h
8 h' k2 [6 t( F4 ~: H
{& y4 k9 ?: Q/ z6 v+ L9 w+ i
"code": 0,* _- R! I. O% C9 ]6 L0 o4 |. ]
"message" " t% v! C# p' a4 n7 H0 P
: "success",
$ V1 [, H6 E1 c K! e$ i1 B "extMessage": null,: D8 b6 n# P; @$ l# v
"appServiceId": "/bean/sample15",# @/ `( ]7 C( {; C; Y1 E
"traceId": "368fdbfa6db440b3bb3f2f5bef1363b7" . r; h& v0 X E/ c
,9 F# }1 ~1 ]' K
"parentTraceId": null,0 f9 h3 ~4 n, x% R) L1 V
"timestamp": 1649128965634,
7 t2 Q6 h4 R. z7 O "data": {
. R& o3 T# l2 h+ J "maxRetryCount": 3,
5 Z& o1 l; C% v e "result" + |3 J2 E8 p/ K3 Y3 e0 _6 x; R
: "fail"
& o% c& L, t7 v" i* f7 e }8 S, b* j$ F) b, p1 v) S, B: E
}SampleAppLogApplication应用输出日志:[sample-app-log:0.0.0.0:8100] 11:22:45 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer
$ O+ E8 F1 z0 D5 ^, T! o #0-1] c.b.b.s.a.listener.AppLogQueueListener0-App服务成功 App服务ID:/bean/sample15 返回码:0-success 平台流水号:368fdbfa6db440b3bb3f2f5bef1363b7' p6 r( a( @! P' m
请求报文:{
0 n7 a. {! R) P) H D- n "maxRetryCount":3,"result":"fail"}
8 L J: C' r/ ^) c, Q- E 响应报文:{"maxRetryCount":3,"result":"fail"}" p4 y: H' ?' ?2 ^4 `( v/ X* }
[sample-app-log:0.0.0.0:8100
4 V1 |$ C# { v3 `; G ] 11:22:45 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-5] c.b.b.s.a.listener.AppLogQueueListener ( m8 p( S- Y: t j, v0 P
2-App服务挂起 App服务ID:/bean/sample15 返回码:0-null 平台流水号:368fdbfa6db440b3bb3f2f5bef1363b7- i# M% l* F* f W$ h5 T6 s+ D. Z
请求报文:{"maxRetryCount" ' f0 Y* n! D8 M
:3,"result":"fail"}
* L; V0 G c, c" I 响应报文:{"maxRetryCount":3,"result":"fail"}
/ t! g$ q( e/ C% Z& s( Y [sample-app-log:0.0.0.0:8100] 11:22:45 INFO ' F) Z' n& y/ Z3 w9 j
60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-2] c.b.b.s.a.listener.AppLogQueueListener + G1 E9 d+ R9 w
2-App服务挂起 App服务ID:/bean/sample15-delay 返回码:8-重试App延迟服务 平台流水号:0697aca84a61439581bf75271453d191
& J" y. f" [8 {5 q/ M* v1 c 请求报文:{"maxRetryCount"
" `+ r0 u7 y% M! l% P8 B :3,"result":"fail"}* E8 D6 h- V$ v. H# l
响应报文:null4 ^) w+ x. ]' ]* ^( W D7 W* v
[sample-app-log:0.0.0.0:8100] 11:22:46 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer
; a% X6 G, h# ?: a( |7 A #0-4] c.b.b.s.a.listener.AppLogQueueListener2-App服务挂起 App服务ID:/bean/sample15-delay 返回码:8-重试App延迟服务 平台流水号: 2 V8 y+ U, i5 u1 ^ u) n5 `
0697aca84a61439581bf75271453d191
; R% w. Q3 A V3 w0 m3 M9 F5 [4 i 请求报文:{"maxRetryCount":3,"result":"fail"}
' t; `4 x9 y" a# M3 { 响应报文:null, n; f3 l c! x5 V
[sample-app-log:0 ' h0 r/ `3 x8 ^0 O( Y3 f4 U4 h
.0.0.0:8100] 11:22:48 INFO 60720 [] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-3] c.b.b.s.a.listener.AppLogQueueListener
$ ?8 ?; y7 o5 P# f2 l9 ~ 1-App服务失败 App服务ID:/bean/sample15-delay 返回码:899-其它错误 平台流水号:0697aca84a61439581bf75271453d191
& l+ N3 J- b/ i Q: m- ]& ^ 请求报文:{"maxRetryCount"
: Y: `" w2 p# {- b :3,"result":"fail"}
! P+ n$ [" v0 ?+ d( G 响应报文:nullBiz-SIP网站:http://bizsip.bizmda.comGitee代码库:https://gitee.com/szhengye/biz-sip 6 B& n7 `- W3 |- L1 }
* `; L5 B4 m, u; m; r: g
; ^ _; ~: h7 z4 t6 W9 t9 z( L) y$ e& \, \/ s
1 Y+ {2 f8 U4 O: G
|