-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathseata-server.drawio
704 lines (704 loc) · 200 KB
/
seata-server.drawio
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
<mxfile host="Electron" modified="2025-01-07T17:07:20.543Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.6.5 Chrome/114.0.5735.243 Electron/25.3.1 Safari/537.36" etag="wD35kc4zZ3AVEFTeS6ZF" version="21.6.5" type="device">
<diagram name="第 1 页" id="3aabxiXxBKXcbQL7kUOO">
<mxGraphModel dx="3628" dy="703" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-1" value="<h1 style="font-size: 16px;"><font style="font-size: 16px;">Seata Server (TC) 工作原理 (v2.0.0)</font></h1><div>seata-server 模块是一个SpringBoot Web应用还是一个 Netty 服务端,主要依赖&nbsp;seata-spring-autoconfigure-server、seata-core、seata-config-all、seata-discovery-all、数据库连接池及接口 模块,另外还依赖序列化、压缩、监控模块。</div><p></p>" style="text;html=1;strokeColor=none;fillColor=none;spacing=5;spacingTop=-20;whiteSpace=wrap;overflow=hidden;rounded=0;" parent="1" vertex="1">
<mxGeometry x="40" y="10" width="620" height="70" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-9" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-14" target="4g4Tmo7ESNFW7hSOMNtd-8" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="500" y="150" />
<mxPoint x="500" y="230" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-26" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-2" target="4g4Tmo7ESNFW7hSOMNtd-17" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-2" value="Server端自动配置" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="40" y="120" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-3" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 11px;"><b style="font-size: 11px;">ConfigProperties</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><b style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">配置中心的配置属性,seata.config</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private String type = "file";<br style="font-size: 11px;">private String preferredNetworks;<br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-440" y="120" width="400" height="120" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-4" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 11px;"><b style="font-size: 11px;">RegistryProperties</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><b style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">注册中心的配置属性</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private String type = "file";&nbsp; <font color="#007fff">// 默认File, 线上常用配置中心中间件</font></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private String preferredNetworks;</p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-880" y="120" width="400" height="120" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-5" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 11px;"><b style="font-size: 11px;">TransportProperties</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><b style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">通信配置属性</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private String type = "TCP";</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private String server = "NIO";</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private boolean heartbeat = DEFAULT_TRANSPORT_HEARTBEAT;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private String serialization = "seata";</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private String compressor = "none";</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private boolean enableClientBatchSendRequest = DEFAULT_ENABLE_CLIENT_BATCH_SEND_REQUEST;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private boolean enableTmClientBatchSendRequest = DEFAULT_ENABLE_TM_CLIENT_BATCH_SEND_REQUEST;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private boolean enableRmClientBatchSendRequest = DEFAULT_ENABLE_RM_CLIENT_BATCH_SEND_REQUEST;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private boolean enableTcServerBatchSendResponse = DEFAULT_ENABLE_TC_SERVER_BATCH_SEND_RESPONSE;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private long rpcRmRequestTimeout = DEFAULT_RPC_RM_REQUEST_TIMEOUT;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private long rpcTmRequestTimeout = DEFAULT_RPC_TM_REQUEST_TIMEOUT;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private long rpcTcRequestTimeout = DEFAULT_RPC_TC_REQUEST_TIMEOUT;</p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-1320" y="120" width="400" height="360" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-11" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-6" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="760" y="150" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-25" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-6" target="4g4Tmo7ESNFW7hSOMNtd-12" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-6" value="一组配置属性<br><font color="#007fff">包括会话配置、持久化配置、服务端配置、服务端Raft协议配置、服务端恢复配置、服务端Undo配置</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="520" y="120" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-8" value="SeataServerEnvironmentPostProcessor" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="520" y="200" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-12" value="ServerProperties" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="760" y="200" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-13" value="StoreDBProperties" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="760" y="120" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-15" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-2" target="4g4Tmo7ESNFW7hSOMNtd-14" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="240" y="150" as="sourcePoint" />
<mxPoint x="520" y="230" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-16" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-14" target="4g4Tmo7ESNFW7hSOMNtd-6" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-14" value="seata-spring-autoconfigure-server" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="280" y="120" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-19" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-17" target="4g4Tmo7ESNFW7hSOMNtd-20" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="500" y="310" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-32" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-17" target="4g4Tmo7ESNFW7hSOMNtd-31" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-17" value="seata-spring-autoconfigure-<b>core</b><br><font color="#007fff">由seata-spring-autoconfigure-server引入</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="280" y="280" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-22" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-20" target="4g4Tmo7ESNFW7hSOMNtd-21" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-24" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-20" target="4g4Tmo7ESNFW7hSOMNtd-23" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-28" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-20" target="4g4Tmo7ESNFW7hSOMNtd-27" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-30" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-20" target="4g4Tmo7ESNFW7hSOMNtd-29" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-20" value="一组配置属性<br><font color="#007fff">配置中心配置、注册中心配置、日志配置、关机配置、线程工厂配置、通信配置</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="520" y="280" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-21" value="ConfigProperties<br><font color="#007fff">配置前缀seata.config</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="760" y="280" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-23" value="ConfigNacosProperties<br><font color="#007fff">配置前缀seata.config.nacos</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="760" y="360" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-27" value="RegistryProperties<br><font color="#007fff">配置前缀seata.registry</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="760" y="440" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-29" value="RegistryNacosProperties<br><font color="#007fff">配置前缀seata.registry.nacos</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="760" y="520" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-31" value="SeataCoreEnvironmentPostProcessor" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="520" y="360" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-33" value="<font color="#007fff" style=""><span style="font-size: 11px;"><br></span></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="40" y="220" width="20" height="30" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-34" value="<font color="#007fff">主要就是从配置文件加载一些配置<br style="border-color: var(--border-color);"><span style="border-color: var(--border-color); font-size: 11px;">并注册到 StarterConstants.</span><span style="border-color: var(--border-color); font-size: 11px;"><b style="border-color: var(--border-color);">PROPERTY_BEAN_MAP</b><br style="border-color: var(--border-color);">代码调试时可以通过这个常量查看实际加载的配置</span></font>" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=top;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="40" y="200" width="280" height="60" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-35" value="Http Controller 对外接口<br><font color="#007fff">主要是为了支持 Console 查询</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="40" y="1280" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-40" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-38" target="Yp0WvUKOWmrbdsE2uwG8-39" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-46" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-38" target="Yp0WvUKOWmrbdsE2uwG8-41" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-47" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-38" target="Yp0WvUKOWmrbdsE2uwG8-43" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-48" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-38" target="Yp0WvUKOWmrbdsE2uwG8-44" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-49" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4g4Tmo7ESNFW7hSOMNtd-38" target="Yp0WvUKOWmrbdsE2uwG8-45" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="4g4Tmo7ESNFW7hSOMNtd-38" value="<div>public void <b>channelRead</b>(final ChannelHandlerContext ctx, Object msg) <br>&nbsp; &nbsp; throws Exception {</div><div>&nbsp; &nbsp; ...</div><div>&nbsp; &nbsp; <b>processMessage</b>(ctx, (RpcMessage) msg);</div><div>}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;align=left;arcSize=7;" parent="1" vertex="1">
<mxGeometry x="280" y="1640" width="440" height="80" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-3" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-1" target="Yp0WvUKOWmrbdsE2uwG8-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-1" value="ServerRunner" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="40" y="600" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-5" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-2" target="Yp0WvUKOWmrbdsE2uwG8-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-2" value="CommandLineRunner#run(...)" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="280" y="600" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-7" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-4" target="Yp0WvUKOWmrbdsE2uwG8-6" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-4" value="Server.start(args);<br><font color="#007fff">&nbsp;启动Netty服务端</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="520" y="600" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-30" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-6" target="Yp0WvUKOWmrbdsE2uwG8-29" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1450" y="920" />
<mxPoint x="1450" y="780" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-31" value="2" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="Yp0WvUKOWmrbdsE2uwG8-30" vertex="1" connectable="0">
<mxGeometry x="0.9141" y="3" relative="1" as="geometry">
<mxPoint x="-12" y="3" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-35" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-6" target="Yp0WvUKOWmrbdsE2uwG8-34" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1450" y="920" />
<mxPoint x="1450" y="1060" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-36" value="3" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="Yp0WvUKOWmrbdsE2uwG8-35" vertex="1" connectable="0">
<mxGeometry x="0.8444" y="-2" relative="1" as="geometry">
<mxPoint x="-6" y="-2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-6" value="<div>public static void start(String[] args) {</div><div><font color="#007fff">&nbsp; &nbsp; // 命令行参数解析</font></div><div>&nbsp; &nbsp; ParameterParser parameterParser = new ParameterParser(args);</div><div>&nbsp; &nbsp; MetricsManager.get().init();</div><div><font color="#007fff">&nbsp; &nbsp; // 默认:50, 500, 500s, 20000,&nbsp;</font></div><div>&nbsp; &nbsp; ThreadPoolExecutor <b>workingThreads</b> = new ThreadPoolExecutor(</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NettyServerConfig.getMinServerPoolSize(),</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NettyServerConfig.getMaxServerPoolSize(),&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NettyServerConfig.getKeepAliveTime(), TimeUnit.SECONDS,</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new LinkedBlockingQueue&lt;&gt;(NettyServerConfig.getMaxTaskQueueSize()),</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new NamedThreadFactory("ServerHandlerThread", NettyServerConfig.getMaxServerPoolSize()),&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new ThreadPoolExecutor.CallerRunsPolicy()); <font color="#007fff">//任务队列满后使用调用线程执行</font></div><div><font color="#007fff">&nbsp; &nbsp; //127.0.0.1 and 0.0.0.0 are not valid here.</font></div><div>&nbsp; &nbsp; if (NetUtil.<b>isValidIp</b>(parameterParser.getHost(), false)) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; XID.setIpAddress(parameterParser.getHost());</div><div>&nbsp; &nbsp; } else {</div><div><b><font color="#007fff"><span style="white-space: pre;">	</span>// 默认走这里, 使用文件、配置配置中心的配置</font><br></b></div><div>&nbsp; &nbsp; &nbsp; &nbsp; String preferredNetworks = ConfigurationFactory.getInstance().<b>getConfig</b>(REGISTRY_PREFERED_NETWORKS);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (StringUtils.isNotBlank(preferredNetworks)) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; XID.setIpAddress(NetUtil.getLocalIp(preferredNetworks.split(REGEX_SPLIT_CHAR)));</div><div>&nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; XID.setIpAddress(NetUtil.<b>getLocalIp</b>());</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; }</div><div>&nbsp; &nbsp; NettyRemotingServer nettyRemotingServer = new <b>NettyRemotingServer</b>(workingThreads);</div><div>&nbsp; &nbsp; XID.<b>setPort</b>(nettyRemotingServer.getListenPort());</div><div>&nbsp; &nbsp; UUIDGenerator.init(parameterParser.getServerNode());</div><div>&nbsp; &nbsp; ConfigurableListableBeanFactory beanFactory =&nbsp;<span style="background-color: initial;">((GenericWebApplicationContext)ObjectHolder.INSTANCE</span></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.getObject(OBJECT_KEY_SPRING_APPLICATION_CONTEXT)).getBeanFactory();</div><div><font color="#007fff"><b>&nbsp; &nbsp; // 默认的事务协调器实现</b></font></div><div>&nbsp; &nbsp; <b>DefaultCoordinator</b> <b>coordinator</b> = DefaultCoordinator.getInstance(<b>nettyRemotingServer</b>);</div><div>&nbsp; &nbsp; if (coordinator instanceof ApplicationListener) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; beanFactory.<b>registerSingleton</b>(NettyRemotingServer.class.getName(), nettyRemotingServer);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; beanFactory.<b>registerSingleton</b>(DefaultCoordinator.class.getName(), coordinator);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ((GenericWebApplicationContext)<b>ObjectHolder</b>.INSTANCE.getObject(OBJECT_KEY_SPRING_APPLICATION_CONTEXT))</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .addApplicationListener((ApplicationListener&lt;?&gt;)coordinator);</div><div>&nbsp; &nbsp; }</div><div><font color="#007fff">&nbsp; &nbsp; // 1 会话管理,存储方式: file, db, redis</font></div><div>&nbsp; &nbsp; SessionHolder.<b>init</b>();</div><div>&nbsp; &nbsp; LockerManagerFactory.<b>init</b>();</div><div><font color="#007fff"><b>&nbsp; &nbsp; // 2 事务协调器初始化</b></font></div><div>&nbsp; &nbsp; coordinator.<b>init</b>();</div><div>&nbsp; &nbsp; nettyRemotingServer.<b>setHandler</b>(coordinator);</div><div><br></div><div><font color="#007fff">&nbsp; &nbsp; // let ServerRunner do destroy instead ShutdownHook, see https://github.com/seata/seata/issues/4028</font></div><div>&nbsp; &nbsp; ServerRunner.addDisposable(coordinator);</div><div><b><font color="#007fff">&nbsp; &nbsp; // 3 启动TC Netty Server</font></b></div><div>&nbsp; &nbsp; nettyRemotingServer.init();</div><div>}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;arcSize=1;align=left;" parent="1" vertex="1">
<mxGeometry x="760" y="600" width="680" height="640" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-8" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 11px;"><b style="font-size: 11px;">XID</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><b style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">Seata RPC 服务IP、端口</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><font color="#007fff" style="font-size: 11px;">//端口默认是 HTTP端口 + 1000</font></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static int <b style="font-size: 11px;">port</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static String <b style="font-size: 11px;">ipAddress</b>;</p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="-440" y="320" width="400" height="120" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-9" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>TransactionMessageHandler</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff"><b>RPC 消息处理器<br><br></b></font></p><p style="margin:0px;margin-left:4px;"><span style="background-color: initial;">AbstractResultMessage <b>onRequest</b>(AbstractMessage request, RpcContext context);</span><br></p><p style="margin:0px;margin-left:4px;">void <b>onResponse</b>(AbstractResultMessage response, RpcContext context);<br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="-440" y="520" width="400" height="120" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-12" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=1;dashed=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-10" target="Yp0WvUKOWmrbdsE2uwG8-9" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-10" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>AbstractTCInboundHandler</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff"><b>抽象的事务协调器请求处理器</b></font></p><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//端口默认是 HTTP端口 + 1000</font></p><p style="margin:0px;margin-left:4px;">private static int <b>port</b>;</p><p style="margin:0px;margin-left:4px;">private static String <b>ipAddress</b>;</p><hr size="1"><p style="margin:0px;margin-left:4px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-440" y="680" width="400" height="120" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-13" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endArrow=block;endFill=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-11" target="Yp0WvUKOWmrbdsE2uwG8-10" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-28" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=-0.002;exitY=0.83;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;exitPerimeter=0;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-11" target="Yp0WvUKOWmrbdsE2uwG8-26" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-11" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 11px;"><b style="font-size: 11px;">DefaultCoordinator</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><b style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">事务协调器实现</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><span style="background-color: initial; font-size: 11px;"><br style="font-size: 11px;"></span></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><span style="background-color: initial; font-size: 11px;">private static final int TIMED_TASK_SHUTDOWN_MAX_WAIT_MILLS = 5000;</span><br style="font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static final String TIME_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS";</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">protected static final long COMMITTING_RETRY_PERIOD = CONFIG.getLong(<br style="font-size: 11px;"><span style="font-size: 11px;"><span style="white-space: pre; font-size: 11px;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>ConfigurationKeys.COMMITING_RETRY_PERIOD,</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; DEFAULT_COMMITING_RETRY_PERIOD);</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">protected static final long ASYNC_COMMITTING_RETRY_PERIOD = CONFIG.getLong(</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; ConfigurationKeys.ASYNC_COMMITING_RETRY_PERIOD, <br style="font-size: 11px;"><span style="font-size: 11px;"><span style="white-space: pre; font-size: 11px;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>DEFAULT_ASYNC_COMMITTING_RETRY_PERIOD);</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">protected static final long ROLLBACKING_RETRY_PERIOD = CONFIG.getLong(<br style="font-size: 11px;"><span style="font-size: 11px;"><span style="white-space: pre; font-size: 11px;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>ConfigurationKeys.ROLLBACKING_RETRY_PERIOD,</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; DEFAULT_ROLLBACKING_RETRY_PERIOD);</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">protected static final long TIMEOUT_RETRY_PERIOD = CONFIG.getLong(<br style="font-size: 11px;"><span style="font-size: 11px;"><span style="white-space: pre; font-size: 11px;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>ConfigurationKeys.TIMEOUT_RETRY_PERIOD,</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; DEFAULT_TIMEOUT_RETRY_PERIOD);</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">protected static final long UNDO_LOG_DELETE_PERIOD = CONFIG.getLong(</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; ConfigurationKeys.TRANSACTION_UNDO_LOG_DELETE_PERIOD, <br style="font-size: 11px;"><span style="font-size: 11px;"><span style="white-space: pre; font-size: 11px;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>DEFAULT_UNDO_LOG_DELETE_PERIOD);</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">protected static final long UNDO_LOG_DELAY_DELETE_PERIOD = 3 * 60 * 1000;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static final int ALWAYS_RETRY_BOUNDARY = 0;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static final int DEFAULT_BRANCH_ASYNC_QUEUE_SIZE = 5000;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static final int BRANCH_ASYNC_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static final long MAX_COMMIT_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getLong(</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; ConfigurationKeys.MAX_COMMIT_RETRY_TIMEOUT, DEFAULT_MAX_COMMIT_RETRY_TIMEOUT);</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static final long MAX_ROLLBACK_RETRY_TIMEOUT = ConfigurationFactory.getInstance().getLong(</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; ConfigurationKeys.MAX_ROLLBACK_RETRY_TIMEOUT, <br style="font-size: 11px;"><span style="font-size: 11px;"><span style="white-space: pre; font-size: 11px;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>DEFAULT_MAX_ROLLBACK_RETRY_TIMEOUT);</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static final boolean ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE = <span style="font-size: 11px;"><span style="white-space: pre; font-size: 11px;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>ConfigurationFactory.getInstance().getBoolean(</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; ConfigurationKeys.ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE, <br style="font-size: 11px;"><span style="font-size: 11px;"><span style="white-space: pre; font-size: 11px;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>DEFAULT_ROLLBACK_RETRY_TIMEOUT_UNLOCK_ENABLE);<br style="font-size: 11px;"><br style="font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private final ScheduledThreadPoolExecutor <b style="font-size: 11px;">retryRollbacking</b> =</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; new ScheduledThreadPoolExecutor(1, new NamedThreadFactory(RETRY_ROLLBACKING, 1));</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private final ScheduledThreadPoolExecutor <b style="font-size: 11px;">retryCommitting</b> =</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; new ScheduledThreadPoolExecutor(1, new NamedThreadFactory(RETRY_COMMITTING, 1));</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private final ScheduledThreadPoolExecutor <b style="font-size: 11px;">asyncCommitting</b> =</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; new ScheduledThreadPoolExecutor(1, new NamedThreadFactory(ASYNC_COMMITTING, 1));</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private final ScheduledThreadPoolExecutor <b style="font-size: 11px;">timeoutCheck</b> =</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; new ScheduledThreadPoolExecutor(1, new NamedThreadFactory(TX_TIMEOUT_CHECK, 1));</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private final ScheduledThreadPoolExecutor <b style="font-size: 11px;">undoLogDelete</b> =</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; new ScheduledThreadPoolExecutor(1, new NamedThreadFactory(UNDOLOG_DELETE, 1));</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private final GlobalStatus[] <b style="font-size: 11px;">rollbackingStatuses</b> = new GlobalStatus[] {GlobalStatus.TimeoutRollbacking,</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">&nbsp; &nbsp; GlobalStatus.TimeoutRollbackRetrying, GlobalStatus.RollbackRetrying, GlobalStatus.Rollbacking};</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private final GlobalStatus[] <b style="font-size: 11px;">retryCommittingStatuses</b> = new GlobalStatus[] {GlobalStatus.Committing, GlobalStatus.CommitRetrying, GlobalStatus.Committed};</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private final ThreadPoolExecutor <b style="font-size: 11px;">branchRemoveExecutor</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><b style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">// Netty Server 实例</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private <b style="font-size: 11px;">RemotingServer</b> <b style="font-size: 11px;">remotingServer</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private final <b style="font-size: 11px;">DefaultCore</b> <b style="font-size: 11px;">core</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><font color="#007fff" style="font-size: 11px;"><b style="font-size: 11px;">// 单例模式</b></font></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static volatile DefaultCoordinator <b style="font-size: 11px;">instance</b>;</p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><font color="#007fff" style="font-size: 11px;"><b style="font-size: 11px;">重要方法:</b></font></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><font color="#007fff" style="font-size: 11px;"><b style="font-size: 11px;">// 处理事务消息请求</b></font></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">public AbstractResultMessage <b style="font-size: 11px;">onRequest</b>(AbstractMessage request, RpcContext context)<br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="-640" y="840" width="600" height="840" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-16" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endArrow=block;endFill=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-14" target="Yp0WvUKOWmrbdsE2uwG8-11" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-14" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 11px;"><b style="font-size: 11px;">RaftCoordinator</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><font color="#007fff" style="font-size: 11px;"><b style="font-size: 11px;">基于 Raft 协议的事务协调器</b></font></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><span style="background-color: initial; font-size: 11px;"><br style="font-size: 11px;"></span></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">protected static final Map&lt;String, Boolean&gt; GROUP_PREVENT = new ConcurrentHashMap&lt;&gt;();<br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-640" y="1720" width="600" height="120" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-22" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endArrow=block;endFill=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-17" target="Yp0WvUKOWmrbdsE2uwG8-20" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-23" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endArrow=block;endFill=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-17" target="Yp0WvUKOWmrbdsE2uwG8-21" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-17" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Core</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><b><font color="#007fff">事务协调器核心接口</font></b></p><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;">boolean <b>doGlobalCommit</b>(GlobalSession globalSession, boolean retrying) throws TransactionException;<br></p><p style="margin:0px;margin-left:4px;">boolean <b>doGlobalRollback</b>(GlobalSession globalSession, boolean retrying) throws TransactionException;<br>void <b>doGlobalReport</b>(GlobalSession globalSession, String xid, GlobalStatus param) throws TransactionException;<br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="-1320" y="920" width="400" height="160" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-18" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>TransactionManager</b><br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px;"><font style="" color="#007fff"><b>事务管理器,负责向全局事务参与者发送事务控制请求,</b>不是事务的容器,事务实例都是存储在线程本地的;<br><b>事务管理器也是通过 SPI 机制加载的,静态内部类实现的单例模式。</b></font></p><p style="margin: 0px 0px 0px 4px;"><font style="" color="#007fff"><b><br></b></font></p><p style="margin: 0px 0px 0px 4px;">String <b>begin</b>(String applicationId, String transactionServiceGroup, String name, int timeout)&nbsp;<span style="background-color: initial;">throws TransactionException;</span></p><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;">GlobalStatus <b>commit</b>(String xid) throws TransactionException;<br></span></p><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;">GlobalStatus <b>rollback</b>(String xid) throws TransactionException;<br></span></p><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;">GlobalStatus getStatus(String xid) throws TransactionException;<br>GlobalStatus globalReport(String xid, GlobalStatus globalStatus) throws TransactionException;<br></span></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="-880" y="520" width="400" height="200" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-19" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ResourceManagerOutbound</b><br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff"><b>用于资源管理器向TC发送Outbound请求</b></font></p><p style="margin: 0px 0px 0px 4px;"><font style="" color="#007fff"><b><br></b></font></p><p style="margin: 0px 0px 0px 4px;">Long <b>branchRegister</b>(BranchType branchType, String resourceId, <br><span style="white-space: pre;">	</span>String clientId, String xid, String applicationData, String lockKeys) throws</p><p style="margin: 0px 0px 0px 4px;">&nbsp; &nbsp; &nbsp; &nbsp; TransactionException;</p><p style="margin: 0px 0px 0px 4px;">void <b>branchReport</b>(BranchType branchType, String xid, long branchId, <span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="white-space: pre;">	</span></span></span>BranchStatus status, String applicationData) throws TransactionException;<br></p><p style="margin: 0px 0px 0px 4px;">boolean <b>lockQuery</b>(BranchType branchType, String resourceId, String xid, <br><span style="white-space: pre;">	</span>String lockKeys)&nbsp;<span style="background-color: initial;">throws TransactionException;</span></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="-1320" y="520" width="400" height="200" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-24" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endArrow=block;endFill=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-20" target="Yp0WvUKOWmrbdsE2uwG8-19" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-25" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-20" target="Yp0WvUKOWmrbdsE2uwG8-18" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-20" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>TransactionCoordinatorInbound</b><br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="-1320" y="760" width="400" height="80" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-21" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>TransactionCoordinatorOutbound</b><br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff"><b>事务协调器向资源管理器发送 Outbound</b></font></p><p style="margin: 0px 0px 0px 4px;"><font style="" color="#007fff"><b><br></b></font></p><p style="margin: 0px 0px 0px 4px;">BranchStatus <b>branchCommit</b>(GlobalSession globalSession, BranchSession <br><span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>branchSession) throws TransactionException;<br>BranchStatus <b>branchRollback</b>(GlobalSession globalSession, BranchSession<br>&nbsp; &nbsp; branchSession) throws TransactionException;<br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="-1760" y="760" width="400" height="120" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-27" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;dashed=1;endArrow=block;endFill=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-26" target="Yp0WvUKOWmrbdsE2uwG8-17" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-26" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>DefaultCore</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff"><b>事务协调器请求处理核心实现</b></font></p><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//端口默认是 HTTP端口 + 1000</font></p><p style="margin:0px;margin-left:4px;">private static final int RETRY_XAER_NOTA_TIMEOUT = ConfigurationFactory.getInstance().getInt(<br><span style="white-space: pre;">	</span>XAER_NOTA_RETRY_TIMEOUT,&nbsp;<span style="background-color: initial;">DefaultValues.DEFAULT_XAER_NOTA_RETRY_TIMEOUT);</span></p><p style="margin:0px;margin-left:4px;"><span style="background-color: initial;">private static Map&lt;<b>BranchType</b>, <b>AbstractCore</b>&gt; <b>coreMap</b> = new ConcurrentHashMap&lt;&gt;();</span><br></p><p style="margin:0px;margin-left:4px;"><span style="background-color: initial;">private static final boolean PARALLEL_HANDLE_BRANCH =&nbsp;</span><span style="background-color: initial;">ConfigurationFactory.getInstance().getBoolean(<br><span style="white-space: pre;">	</span>ENABLE_PARALLEL_HANDLE_BRANCH_KEY, false);</span></p><hr size="1"><p style="margin:0px;margin-left:4px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="-1440" y="1120" width="640" height="200" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-29" value="<font color="#007fff">// 启动5个定时任务</font><br><div><b>retryRollbacking</b>.scheduleAtFixedRate(</div><div>&nbsp; &nbsp; () -&gt; SessionHolder.distributedLockAndExecute(RETRY_ROLLBACKING, this::handleRetryRollbacking), 0,</div><div>&nbsp; &nbsp; ROLLBACKING_RETRY_PERIOD, TimeUnit.MILLISECONDS);</div><div><br></div><div><b>retryCommitting</b>.scheduleAtFixedRate(</div><div>&nbsp; &nbsp; () -&gt; SessionHolder.distributedLockAndExecute(RETRY_COMMITTING, this::handleRetryCommitting), 0,</div><div>&nbsp; &nbsp; COMMITTING_RETRY_PERIOD, TimeUnit.MILLISECONDS);</div><div><br></div><div><b>asyncCommitting</b>.scheduleAtFixedRate(</div><div>&nbsp; &nbsp; () -&gt; SessionHolder.distributedLockAndExecute(ASYNC_COMMITTING, this::handleAsyncCommitting), 0,</div><div>&nbsp; &nbsp; ASYNC_COMMITTING_RETRY_PERIOD, TimeUnit.MILLISECONDS);</div><div><b><font color="#007fff">// 4 超时检查,检查所有 Begin 状态的全局会话是否超时</font></b></div><div><b>timeoutCheck</b>.scheduleAtFixedRate(</div><div>&nbsp; &nbsp; () -&gt; SessionHolder.distributedLockAndExecute(TX_TIMEOUT_CHECK, this::timeoutCheck), 0,</div><div>&nbsp; &nbsp; TIMEOUT_RETRY_PERIOD, TimeUnit.MILLISECONDS);</div><div><br></div><div><b>undoLogDelete</b>.scheduleAtFixedRate(</div><div>&nbsp; &nbsp; () -&gt; SessionHolder.distributedLockAndExecute(UNDOLOG_DELETE, this::undoLogDelete),</div><div>&nbsp; &nbsp; UNDO_LOG_DELAY_DELETE_PERIOD, UNDO_LOG_DELETE_PERIOD, TimeUnit.MILLISECONDS);</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;arcSize=2;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1480" y="600" width="440" height="360" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-38" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-34" target="Yp0WvUKOWmrbdsE2uwG8-37" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1930" y="1060" />
<mxPoint x="1930" y="1200" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-54" value="1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="Yp0WvUKOWmrbdsE2uwG8-38" vertex="1" connectable="0">
<mxGeometry x="0.8" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-53" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-34" target="Yp0WvUKOWmrbdsE2uwG8-50" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1930" y="1060" />
<mxPoint x="1930" y="1520" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-55" value="2" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="Yp0WvUKOWmrbdsE2uwG8-53" vertex="1" connectable="0">
<mxGeometry x="0.92" y="-2" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-59" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="Yp0WvUKOWmrbdsE2uwG8-53" vertex="1" connectable="0">
<mxGeometry x="0.444" y="-4" relative="1" as="geometry">
<mxPoint x="4" y="69" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-34" value="<div>public void init() {</div><div><b><font color="#007fff">&nbsp; &nbsp; // 1 注册RPC处理器,5种处理器</font></b></div><div>&nbsp; &nbsp; <b>registerProcessor</b>();</div><div>&nbsp; &nbsp; if (initialized.compareAndSet(false, true)) {</div><div><font style="" color="#007fff"><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp; </span>// 和 RocketMQ Netty Server 差不多,不详细分析了</font><br></div><div><b><font color="#007fff"><span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp; </span></span>// 2 监听连接的端口通过 server.servicePort 配置指定</font></b></div><div>&nbsp; &nbsp; &nbsp; &nbsp; super.<b>init</b>();</div><div>&nbsp; &nbsp; }</div><div>}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;arcSize=7;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1480" y="1000" width="440" height="120" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-11" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=1.002;entryY=0.664;entryDx=0;entryDy=0;fillColor=#dae8fc;strokeColor=#6c8ebf;entryPerimeter=0;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-37" target="QYUXZyDFh2rJFv0anni3-7" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="2660" y="1200" />
<mxPoint x="2660" y="1610" />
<mxPoint x="2190" y="1610" />
<mxPoint x="2190" y="1786" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-37" value="<div>private void registerProcessor() {</div><div><font color="#007fff">&nbsp; &nbsp; // 1. registry on request message processor</font></div><div>&nbsp; &nbsp; ServerOnRequestProcessor <b>onRequestProcessor</b> =&nbsp;<span style="background-color: initial;">new <b>ServerOnRequestProcessor</b>(this, getHandler());</span></div><div>&nbsp; &nbsp; ShutdownHook.getInstance().addDisposable(onRequestProcessor);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_BRANCH_REGISTER</b>, onRequestProcessor, messageExecutor);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_BRANCH_STATUS_REPORT</b>, onRequestProcessor, messageExecutor);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_GLOBAL_BEGIN</b>, onRequestProcessor, messageExecutor);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_GLOBAL_COMMIT</b>, onRequestProcessor, messageExecutor);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_GLOBAL_LOCK_QUERY</b>, onRequestProcessor, messageExecutor);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_GLOBAL_REPORT</b>, onRequestProcessor, messageExecutor);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_GLOBAL_ROLLBACK</b>, onRequestProcessor, messageExecutor);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_GLOBAL_STATUS</b>, onRequestProcessor, messageExecutor);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_SEATA_MERGE</b>, onRequestProcessor, messageExecutor);</div><div><font color="#007fff">&nbsp; &nbsp; // 2. registry on response message processor</font></div><div>&nbsp; &nbsp; ServerOnResponseProcessor <b>onResponseProcessor</b> =&nbsp;<span style="background-color: initial;">new <b>ServerOnResponseProcessor</b>(getHandler(), getFutures());</span></div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_BRANCH_COMMIT_RESULT</b>, onResponseProcessor, branchResultMessageExecutor);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_BRANCH_ROLLBACK_RESULT</b>, onResponseProcessor, <br><span style="white-space: pre;">	</span>branchResultMessageExecutor);</div><div><font color="#007fff">&nbsp; &nbsp; // 3. registry rm message processor</font></div><div>&nbsp; &nbsp; RegRmProcessor <b>regRmProcessor</b> = new <b>RegRmProcessor</b>(this);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_REG_RM</b>, regRmProcessor, messageExecutor);</div><div><font color="#007fff">&nbsp; &nbsp; // 4. registry tm message processor</font></div><div>&nbsp; &nbsp; RegTmProcessor <b>regTmProcessor</b> = new <b>RegTmProcessor</b>(this);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_REG_CLT</b>, regTmProcessor, null);</div><div><font color="#007fff">&nbsp; &nbsp; // 5. registry heartbeat message processor</font></div><div>&nbsp; &nbsp; ServerHeartbeatProcessor <b>heartbeatMessageProcessor</b> = new <b>ServerHeartbeatProcessor</b>(this);</div><div>&nbsp; &nbsp; super.registerProcessor(MessageType.<b>TYPE_HEARTBEAT_MSG</b>, heartbeatMessageProcessor, null);</div><div>}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;arcSize=2;align=left;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1960" y="1000" width="680" height="400" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-73" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-39" target="Yp0WvUKOWmrbdsE2uwG8-72" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-39" value="<b>ServerOnRequestProcessor<br>#process(...)<br><font color="#007fff">事务操作相关请求处理</font><br></b>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="760" y="1640" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-50" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-41" target="9im45_5cZYxTOmNjTaqy-49" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-41" value="ServerOnResponseProcessor<br><b><font color="#007fff">分支事务提交或回滚结果响应处理</font></b>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="760" y="1920" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-54" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-43" target="9im45_5cZYxTOmNjTaqy-53" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-43" value="RegRmProcessor<br><font color="#007fff"><b>注册客户端RM资源管理器,用于全局事务的提交或回滚回调</b></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="760" y="2020" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-44" value="RegTmProcessor<br><font color="#007fff"><b>注册客户端TM事务管理器,用于全局事务的提交或回滚回调, </b>主要也是存储一下连接</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="760" y="2100" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-45" value="ServerHeartbeatProcessor<br><font color="#007fff">处理客户端心跳请求,不需要处理</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="760" y="2180" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-50" value="<div>.childHandler(new ChannelInitializer&lt;SocketChannel&gt;() {</div><div>&nbsp; &nbsp; @Override</div><div>&nbsp; &nbsp; public void initChannel(SocketChannel ch) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ch.<b>pipeline</b>().addLast(new <b>IdleStateHandler</b>(<br><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span>nettyServerConfig.getChannelMaxReadIdleSeconds(), 0, 0))</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .addLast(new <b>ProtocolV1Decoder</b>())</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .addLast(new <b>ProtocolV1Encoder</b>());</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (channelHandlers != null) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addChannelPipelineLast(ch, <b>channelHandlers</b>);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; }</div><div>});</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;arcSize=4;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1960" y="1440" width="440" height="160" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-56" value="<b>Pipeline</b>:&nbsp;<br>IdleStateHandler ---&gt; ProtocolV1Decoder ---&gt; ServerHandler<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ProtocolV1Encoder" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2415" y="1473" width="350" height="60" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-57" value="NettyRemotingServer" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1630" y="970" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-58" value="<b>AbstractNettyRemotingServer</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2205" y="970" width="190" height="30" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-60" value="NettyServerBootstrap" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2110" y="1410" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-61" value="<font style="font-size: 11px;" color="#007fff"><b>请求编码后数据格式:<br></b>2bytes: magic code<br>1bytes: ProtocolVer<br>4bytes: Full length,(head + body)的长度<br>2bytes: Head Length, 消息头的长度<br>1bytes: Msg Type,&nbsp;<br>1bytes: Serializer, 序列化类型<br>1bytes: Compress, 压缩类型<br>4bytes: RequestId, 请求ID<br>Mbytes: HeadMap<br>Nbytes: body</font>" style="text;html=1;align=left;verticalAlign=top;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="40" y="1720" width="230" height="170" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-66" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-62" target="Yp0WvUKOWmrbdsE2uwG8-68" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="-1120" y="1680" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-62" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 11px;"><b style="font-size: 11px;">AbstractNettyRemotingServer</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><span style="background-color: initial; font-size: 11px;">private final NettyServerBootstrap serverBootstrap;</span><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-1320" y="1720" width="400" height="80" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-64" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endArrow=block;endFill=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-63" target="Yp0WvUKOWmrbdsE2uwG8-62" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-63" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 11px;"><b style="font-size: 11px;">NettyRemotingServer</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><b style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">Netty服务器</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private TransactionMessageHandler transactionMessageHandler;</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><span style="background-color: initial; font-size: 11px;">private final AtomicBoolean initialized = new AtomicBoolean(false);</span><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-1320" y="1840" width="400" height="120" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-68" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 11px;"><b style="font-size: 11px;">AbstractNettyRemotingServer</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px;">protected final ScheduledExecutorService <b>timerExecutor</b> = new&nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; ScheduledThreadPoolExecutor(</p><p style="margin: 0px 0px 0px 4px;">&nbsp; &nbsp; &nbsp; &nbsp; 1, new NamedThreadFactory("timeoutChecker", 1, true));</p><p style="margin: 0px 0px 0px 4px;">protected final ThreadPoolExecutor <b>messageExecutor</b>;</p><p style="margin: 0px 0px 0px 4px;">protected final PositiveAtomicCounter <b>idGenerator</b> = new</p><p style="margin: 0px 0px 0px 4px;">&nbsp; &nbsp; PositiveAtomicCounter();</p><p style="margin: 0px 0px 0px 4px;">protected final ConcurrentHashMap&lt;Integer, MessageFuture&gt; <b>futures</b> = new</p><p style="margin: 0px 0px 0px 4px;">&nbsp; &nbsp; ConcurrentHashMap&lt;&gt;();</p><p style="margin: 0px 0px 0px 4px;">private static final long NOT_WRITEABLE_CHECK_MILLS = 10L;</p><p style="margin: 0px 0px 0px 4px;">protected volatile long <b>nowMills</b> = 0;</p><p style="margin: 0px 0px 0px 4px;">private static final int TIMEOUT_CHECK_INTERVAL = 3000;</p><p style="margin: 0px 0px 0px 4px;">protected final Object <b>lock</b> = new Object();</p><p style="margin: 0px 0px 0px 4px;">protected volatile boolean <b>isSending</b> = false;</p><p style="margin: 0px 0px 0px 4px;">private String group = "DEFAULT";</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff"><b>// MessageType (事务消息类型) -&gt; &lt;消息处理器, 执行消息处理的线程池&gt;</b></font></p><p style="margin: 0px 0px 0px 4px;">protected final HashMap&lt;Integer/*MessageType*/, Pair&lt;RemotingProcessor,</p><p style="margin: 0px 0px 0px 4px;">&nbsp; &nbsp; ExecutorService&gt;&gt; <b>processorTable</b> = new HashMap&lt;&gt;(32);</p><p style="margin: 0px 0px 0px 4px;">protected final List&lt;RpcHook&gt; <b>rpcHooks</b> = EnhancedServiceLoader.loadAll(</p><p style="margin: 0px 0px 0px 4px;">&nbsp; &nbsp; RpcHook.class);</p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="-1320" y="1360" width="400" height="320" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-70" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-69" target="4g4Tmo7ESNFW7hSOMNtd-38" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-69" value="ServerHandler RPC对外接口<br><font color="#007fff">通过消息类型分发给对应处理器处理</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="40" y="1650" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-71" value="AbstractNettyRemotingServer$ServerHandler" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="365" y="1610" width="270" height="30" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-79" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QYUXZyDFh2rJFv0anni3-12" target="Yp0WvUKOWmrbdsE2uwG8-78" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-2" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="Yp0WvUKOWmrbdsE2uwG8-79" vertex="1" connectable="0">
<mxGeometry x="-0.1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-72" value="<div>private void onRequestMessage(ChannelHandlerContext ctx, RpcMessage rpcMessage) {</div><div>&nbsp; &nbsp; Object message = rpcMessage.getBody();</div><div>&nbsp; &nbsp; RpcContext rpcContext = ChannelManager.getContextFromIdentified(ctx.channel());</div><div>&nbsp; &nbsp; ...</div><div><br></div><div><font color="#007fff">&nbsp; &nbsp; // 批量请求消息,遍历内部请求消息借助 CompletableFuture 异步处理,所有请求处理完成后,最后一起返回</font></div><div>&nbsp; &nbsp; if (message instanceof MergedWarpMessage) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ...</div><div>&nbsp; &nbsp; } else {</div><div><span style="background-color: initial;">&nbsp; &nbsp; &nbsp; &nbsp; final AbstractMessage msg = (AbstractMessage) message;</span><br></div><div><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; ... 记录日志 ...</font></div><div><font color="#007fff"><b><span style=""><span style="white-space: pre;"> &nbsp;&nbsp;&nbsp;&nbsp;</span></span>// 默认是调用 DefaultCoordinator#onRequest</b></font><font color="#007fff"><b>&nbsp;处理事务消息请求</b><br></font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; AbstractResultMessage result = <b>transactionMessageHandler</b>.<b>onRequest</b>(msg, rpcContext);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; remotingServer.<b>sendAsyncResponse</b>(rpcMessage, ctx.channel(), result);</div><div><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; ... 记录日志 ...</font></div><div>&nbsp; &nbsp; }</div><div>}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;align=left;arcSize=3;" parent="1" vertex="1">
<mxGeometry x="1000" y="1640" width="680" height="240" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-77" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1.002;exitY=0.199;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;exitPerimeter=0;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-74" target="Yp0WvUKOWmrbdsE2uwG8-9" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-74" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ServerOnRequestProcessor</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br></p><p style="margin: 0px 0px 0px 4px;">private final RemotingServer <b>remotingServer</b>;</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff"><b>//默认是DefaultCoordinator</b></font></p><p style="margin: 0px 0px 0px 4px;">private final TransactionMessageHandler <b>transactionMessageHandler</b>;</p><p style="margin: 0px 0px 0px 4px;">private ExecutorService <b>batchResponseExecutorService</b>;</p><p style="margin: 0px 0px 0px 4px;">private final ConcurrentMap&lt;Channel, BlockingQueue&lt;QueueItem&gt;&gt; <br><b>&nbsp; &nbsp; basketMap</b> = new ConcurrentHashMap&lt;&gt;();</p><p style="margin: 0px 0px 0px 4px;">protected final Object batchResponseLock = new Object();</p><p style="margin: 0px 0px 0px 4px;">private volatile boolean isResponding = false;</p><p style="margin: 0px 0px 0px 4px;"><br></p><p style="margin: 0px 0px 0px 4px;">private static final int MAX_BATCH_RESPONSE_MILLS = 1;</p><p style="margin: 0px 0px 0px 4px;">private static final int MAX_BATCH_RESPONSE_THREAD = 1;</p><p style="margin: 0px 0px 0px 4px;">private static final long KEEP_ALIVE_TIME = Integer.MAX_VALUE;</p><p style="margin: 0px 0px 0px 4px;">private static final String BATCH_RESPONSE_THREAD_PREFIX = <br>&nbsp; &nbsp; "rpcBatchResponse";</p><p style="margin: 0px 0px 0px 4px;">private static final boolean PARALLEL_REQUEST_HANDLE =</p><p style="margin: 0px 0px 0px 4px;">&nbsp; &nbsp; ConfigurationFactory.getInstance().getBoolean(<br>&nbsp; &nbsp; ConfigurationKeys.ENABLE_PARALLEL_REQUEST_HANDLE_KEY, true);</p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="-440" y="2000" width="400" height="320" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-83" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-78" target="Yp0WvUKOWmrbdsE2uwG8-82" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-78" value="<span style="background-color: initial;">public GlobalBeginResponse <b>handle</b>(GlobalBeginRequest request, final RpcContext rpcContext) {</span><br><div>&nbsp; &nbsp; GlobalBeginResponse response = new GlobalBeginResponse();</div><div><b><font color="#007fff">&nbsp; &nbsp; // 执行处理逻辑,已经对结果进行处理最后向客户端发送响应</font></b></div><div>&nbsp; &nbsp; <b>exceptionHandleTemplate</b>(new AbstractCallback&lt;GlobalBeginRequest, GlobalBeginResponse&gt;() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; @Override</div><div>&nbsp; &nbsp; &nbsp; &nbsp; public void <b>execute</b>(GlobalBeginRequest request, GlobalBeginResponse response) throws TransactionException {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>doGlobalBegin</b>(request, response, rpcContext);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (StoreException e) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new TransactionException(...);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; }, request, response);</div><div>&nbsp; &nbsp; return response;</div><div>}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;align=left;arcSize=3;" parent="1" vertex="1">
<mxGeometry x="2440" y="1640" width="440" height="240" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-81" value="AbstractTCInboundHandler" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2575" y="1610" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-86" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-82" target="Yp0WvUKOWmrbdsE2uwG8-85" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-82" value="<div>protected void <b>doGlobalBegin</b>(GlobalBeginRequest request, GlobalBeginResponse response, RpcContext rpcContext)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; throws TransactionException {</div><div>&nbsp; &nbsp; response.<b>setXid</b>(<b>core</b>.<b>begin</b>(rpcContext.getApplicationId(), <br>&nbsp;<span style="white-space: pre;">	</span>&nbsp; &nbsp; rpcContext.getTransactionServiceGroup(),</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; request.getTransactionName(), request.getTimeout()));</div><div>&nbsp; &nbsp; ...</div><div>}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;align=left;arcSize=3;" parent="1" vertex="1">
<mxGeometry x="2920" y="1700" width="440" height="120" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-84" value="DefaultCoordinator" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="3080" y="1670" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-3" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-85" target="QYUXZyDFh2rJFv0anni3-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-85" value="<div style="font-size: 10px;">public String <b>begin</b>(String applicationId, String transactionServiceGroup, String name, int timeout)</div><div style="font-size: 10px;">&nbsp; &nbsp; throws TransactionException {</div><div style="font-size: 10px;"><b><font color="#007fff">&nbsp; &nbsp; // 创建 GlobalSession</font></b></div><div style="font-size: 10px;">&nbsp; &nbsp; GlobalSession session = GlobalSession.<b>createGlobalSession</b>(applicationId, <br><span style="white-space: pre;">	</span>transactionServiceGroup, name, timeout);</div><div style="font-size: 10px;">&nbsp; &nbsp; MDC.put(RootContext.MDC_KEY_XID, session.getXid());</div><div style="font-size: 10px;"><font color="#007fff"><b>&nbsp; &nbsp; // 修改全局会话状态为 Begin、记录开始事件、活跃状态、全局会话存储</b></font></div><div style="font-size: 10px;">&nbsp; &nbsp; <b>session</b>.<b>begin</b>();</div><div style="font-size: 10px;">&nbsp; &nbsp; // transaction start event</div><div style="font-size: 10px;">&nbsp; &nbsp; MetricsPublisher.<b>postSessionDoingEvent</b>(session, false);</div><div style="font-size: 10px;">&nbsp; &nbsp; return session.<b>getXid</b>();</div><div style="font-size: 10px;">}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=3;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="3400" y="1680" width="440" height="160" as="geometry" />
</mxCell>
<mxCell id="Yp0WvUKOWmrbdsE2uwG8-87" value="DefaultCore" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="3575" y="1650" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-1" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 10px;"><b style="font-size: 10px;">GlobalSession</b><br style="font-size: 10px;"></p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><b style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">全局会话,主要就是记录事务全局的状态</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><br style="font-size: 10px;"></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private static final int MAX_GLOBAL_SESSION_SIZE = <br style="font-size: 10px;">&nbsp; &nbsp; StoreConfig.getMaxGlobalSessionSize();</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private static ThreadLocal&lt;ByteBuffer&gt; byteBufferThreadLocal = <br style="font-size: 10px;">&nbsp; &nbsp; ThreadLocal.withInitial(</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; () -&gt; ByteBuffer.allocate(MAX_GLOBAL_SESSION_SIZE));</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private static final ThreadLocal&lt;GlobalStatus&gt;&nbsp; <br style="font-size: 10px;">&nbsp; &nbsp; EXPECTED_STATUS_THREAD_LOCAL = new ThreadLocal&lt;&gt;();</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private static final int RETRY_DEAD_THRESHOLD = ConfigurationFactory<br style="font-size: 10px;">&nbsp; &nbsp; .getInstance()<span style="background-color: initial; font-size: 10px;">.getInt(ConfigurationKeys.RETRY_DEAD_THRESHOLD, <br style="font-size: 10px;">&nbsp; &nbsp; &nbsp;DefaultValues.DEFAULT_RETRY_DEAD_THRESHOLD);</span></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><br style="font-size: 10px;"></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font color="#007fff" style="font-size: 10px;">// 带上事务发起者(TM)IP端口的事务ID, 比如&nbsp;</font></p><font color="#007fff" style="font-size: 10px;">&nbsp;// 172.17.0.1:8091:7260406644107100161</font><br style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private String <b style="font-size: 10px;">xid</b>;</p><font color="#007fff" style="font-size: 10px;">&nbsp;// 事务ID, 比如 7260406644107100161</font><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private long <b style="font-size: 10px;">transactionId</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><b><font color="#007fff">// 事务状态</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private volatile GlobalStatus <b style="font-size: 10px;">status</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font color="#007fff">// 事务发起者服务ID, 如 order-service</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private String <b style="font-size: 10px;">applicationId</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font color="#007fff">// 事务服务分组,不同分组可以使用不同的Seata Server节点和连接</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private String <b style="font-size: 10px;">transactionServiceGroup</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font color="#007fff">// 事务名,默认用方法和参数命名,比如 createOrder(java.lang.Long, java.lang.Long, java.lang.Integer)</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private String <b style="font-size: 10px;">transactionName</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font color="#007fff">// 事务超时时间,超时的话TC会发起回滚</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private int <b style="font-size: 10px;">timeout</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font color="#007fff">// 事务开始时间,即创建 Session 的时间点</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private long <b style="font-size: 10px;">beginTime</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private String applicationData;</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private final boolean lazyLoadBranch;</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font color="#007fff">// 事务是否活跃</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private volatile boolean <b style="font-size: 10px;">active</b> = true;</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><b><font color="#007fff">// 分支事务列表,即参与者的本地事务</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private List&lt;<b style="font-size: 10px;">BranchSession</b>&gt; <b style="font-size: 10px;">branchSessions</b>;</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private GlobalSessionLock globalSessionLock = new GlobalSessionLock();</p><p style="margin: 0px 0px 0px 4px; font-size: 10px;">private Set&lt;SessionLifecycleListener&gt; lifecycleListeners = new HashSet&lt;&gt;(2);</p><hr style="font-size: 10px;"><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><br style="font-size: 10px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=10;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#e3c800;strokeColor=#B09500;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="-880" y="2000" width="400" height="520" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-60" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QYUXZyDFh2rJFv0anni3-2" target="9im45_5cZYxTOmNjTaqy-59" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-2" value="<div style="font-size: 10px;"><div>public void begin() throws TransactionException {</div><div>&nbsp; &nbsp; this.<b>status</b> = <b>GlobalStatus.Begin</b>;</div><div>&nbsp; &nbsp; this.<b>beginTime</b> = System.currentTimeMillis();</div><div>&nbsp; &nbsp; this.<b>active</b> = true;</div><div><b><font color="#007fff">&nbsp; &nbsp; // onBegin() 方法就是将 GlobalSession 实例存储到 SessionManager 对象</font></b></div><div>&nbsp; &nbsp; <b>SessionHolder</b>.<b>getRootSessionManager</b>().<b>onBegin</b>(this);</div><div>&nbsp; &nbsp; for (SessionLifecycleListener lifecycleListener : lifecycleListeners) { <font color="#007fff">// 预留的拓展点</font></div><div>&nbsp; &nbsp; &nbsp; &nbsp; lifecycleListener.onBegin(this);</div><div>&nbsp; &nbsp; }</div><div>}</div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=3;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="3880" y="1700" width="440" height="120" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-4" value="GlobalSession" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="4050" y="1670" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-5" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>SessionManager</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><font color="#007fff"><b>Session 容器,有多种实现 File、DB、Redis、Raft(基于jraft-core实现的分布式一致性文件系统)</b></font></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br></p><p style="margin: 0px 0px 0px 4px;">void addGlobalSession(GlobalSession session) throws TransactionException;<br></p><p style="margin: 0px 0px 0px 4px;">GlobalSession findGlobalSession(String xid) ;<br style="font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px;">GlobalSession findGlobalSession(String xid, boolean withBranchSessions);<br></p><p style="margin: 0px 0px 0px 4px;">void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException;<br></p><p style="margin: 0px 0px 0px 4px;">void removeGlobalSession(GlobalSession session) throws TransactionException;<br></p><p style="margin: 0px 0px 0px 4px;">void addBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException;<br></p><p style="margin: 0px 0px 0px 4px;">void updateBranchSessionStatus(BranchSession session, BranchStatus status) throws TransactionException;<br></p><p style="margin: 0px 0px 0px 4px;"><span style="background-color: initial;">void removeBranchSession(GlobalSession globalSession, BranchSession session) throws TransactionException;</span><br></p><p style="margin: 0px 0px 0px 4px;">...</p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="-1760" y="2000" width="400" height="240" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-46" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;endArrow=open;endFill=0;" parent="1" source="QYUXZyDFh2rJFv0anni3-6" target="QYUXZyDFh2rJFv0anni3-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-6" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>SessionHolder</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><b><font color="#007fff">GlobalSession 存储器</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br></p><p style="margin: 0px 0px 0px 4px;">protected static final Configuration CONFIG = <br>&nbsp; &nbsp; ConfigurationFactory.getInstance();</p><p style="margin: 0px 0px 0px 4px;">public static final String ROOT_SESSION_MANAGER_NAME = "root.data";</p><p style="margin: 0px 0px 0px 4px;">private static long DISTRIBUTED_LOCK_EXPIRE_TIME = CONFIG.getLong(<br>&nbsp; &nbsp; ConfigurationKeys.DISTRIBUTED_LOCK_EXPIRE_TIME, <br>&nbsp; &nbsp; DEFAULT_DISTRIBUTED_LOCK_EXPIRE_TIME);</p><p style="margin: 0px 0px 0px 4px;"><br></p><p style="margin: 0px 0px 0px 4px;">private static <b>SessionManager</b> <b>ROOT_SESSION_MANAGER</b>;</p><p style="margin: 0px 0px 0px 4px;">private static volatile <b>Map</b>&lt;<b>String</b>, <b>SessionManager</b>&gt; <br><b>&nbsp; &nbsp; SESSION_MANAGER_MAP</b>;</p><p style="margin: 0px 0px 0px 4px;">private static DistributedLocker DISTRIBUTED_LOCKER;</p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="-1320" y="2000" width="400" height="280" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-8" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Yp0WvUKOWmrbdsE2uwG8-72" target="QYUXZyDFh2rJFv0anni3-7" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1680" y="1760" as="sourcePoint" />
<mxPoint x="2200" y="1760" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-16" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="QYUXZyDFh2rJFv0anni3-7" target="QYUXZyDFh2rJFv0anni3-14" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-18" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="QYUXZyDFh2rJFv0anni3-7" target="QYUXZyDFh2rJFv0anni3-17" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-20" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="QYUXZyDFh2rJFv0anni3-7" target="QYUXZyDFh2rJFv0anni3-19" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-22" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="QYUXZyDFh2rJFv0anni3-7" target="QYUXZyDFh2rJFv0anni3-21" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-24" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="QYUXZyDFh2rJFv0anni3-7" target="QYUXZyDFh2rJFv0anni3-23" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-7" value="<div>public AbstractResultMessage <b>onRequest</b>(AbstractMessage request, RpcContext context) {</div><div>&nbsp; &nbsp; ...</div><div>&nbsp; &nbsp; AbstractTransactionRequestToTC transactionRequest = <br><span style="white-space: pre;">	</span>(AbstractTransactionRequestToTC) request;</div><div>&nbsp; &nbsp; transactionRequest.setTCInboundHandler(this);</div><div><b><font color="#007fff">&nbsp; &nbsp; // 这里会调用对应的事务请求的请求处理方法</font></b></div><div>&nbsp; &nbsp; return transactionRequest.<b>handle</b>(context);</div><div>}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;align=left;arcSize=3;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1720" y="1680" width="440" height="160" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-10" value="<b>DefaultCoordinator</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1875" y="1650" width="130" height="30" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-13" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QYUXZyDFh2rJFv0anni3-7" target="QYUXZyDFh2rJFv0anni3-12" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="2160" y="1720" as="sourcePoint" />
<mxPoint x="2440" y="1760" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-12" value="<b>GlobalBeginRequest</b>#handle()<br><b><font color="#007fff">1 分布式事务开启</font></b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2200" y="1730" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-26" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QYUXZyDFh2rJFv0anni3-14" target="QYUXZyDFh2rJFv0anni3-25" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-14" value="<b>GlobalCommitRequest</b>#handle()<br><font style="" color="#007fff"><b>5 所有分支事务执行完成,全局事务提交,其实是向各个参与者发送</b><br><b>BranchCommitResponse</b><br></font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2200" y="2480" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-15" value="<b>消息第一级分发,<br>借助 ProtocolConstants 中定义的消息类型</b>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="680" y="1560" width="260" height="40" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-31" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QYUXZyDFh2rJFv0anni3-17" target="QYUXZyDFh2rJFv0anni3-30" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-17" value="<b>GlobalRollbackRequest</b>#handle()<br><font style="" color="#007fff"><b>存在分支事务执行异常或超时,全局事务回滚,其实是向各个参与者发送</b><br></font><font color="#007fff"><b>BranchRollbackResponse</b></font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2200" y="2900" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-28" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QYUXZyDFh2rJFv0anni3-19" target="QYUXZyDFh2rJFv0anni3-27" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-4" value="...." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="QYUXZyDFh2rJFv0anni3-28" vertex="1" connectable="0">
<mxGeometry x="-0.2" y="-3" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-19" value="<b>BranchRegisterRequest</b>#handle()<br><font color="#007fff"><b>2 分支事务注册,分支事务执行正常的话在提交前注册分支事务</b></font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2200" y="2010" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-33" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QYUXZyDFh2rJFv0anni3-21" target="QYUXZyDFh2rJFv0anni3-32" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-22" value="<font color="#007fff" style="font-size: 10px;">处理流程和上面类似,省略一些步骤</font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="QYUXZyDFh2rJFv0anni3-33" vertex="1" connectable="0">
<mxGeometry x="-0.922" y="-1" relative="1" as="geometry">
<mxPoint x="91" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-21" value="<b>BranchReportRequest</b><br>#handle()<br><font color="#007fff"><b>3 分支事务状态上报注册,在分支事务提交后上报分支事务状态</b></font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2200" y="2280" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-23" value="<b><font color="#007fff">... 4 其他分支事务注册和状态上报...</font></b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2200" y="2380" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-26" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QYUXZyDFh2rJFv0anni3-25" target="9im45_5cZYxTOmNjTaqy-25" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-25" value="<div style="font-size: 10px;">public GlobalCommitResponse handle(GlobalCommitRequest request, final RpcContext rpcContext) {</div><div style="font-size: 10px;">&nbsp; &nbsp; GlobalCommitResponse response = new GlobalCommitResponse();</div><div style="font-size: 10px;">&nbsp; &nbsp; response.setGlobalStatus(GlobalStatus.Committing);</div><div style="font-size: 10px;">&nbsp; &nbsp; <b style="font-size: 10px;">exceptionHandleTemplate</b>(new AbstractCallback&lt;GlobalCommitRequest, <br style="font-size: 10px;"><span style="white-space: pre; font-size: 10px;">	</span>GlobalCommitResponse&gt;() {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; @Override</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; public void <b style="font-size: 10px;">execute</b>(GlobalCommitRequest request, GlobalCommitResponse <br style="font-size: 10px;">&nbsp; <span style="white-space: pre; font-size: 10px;">	</span>&nbsp; &nbsp; response)&nbsp;<span style="background-color: initial; font-size: 10px;">throws TransactionException {</span></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {</div><div style="font-size: 10px;"><b><font color="#007fff"><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span>// 全局事务提交</font></b><br></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b style="font-size: 10px;">doGlobalCommit</b>(request, response, rpcContext);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (StoreException e) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new TransactionException(<br style="font-size: 10px;"><span style="white-space: pre; font-size: 10px;">	</span><span style="white-space: pre; font-size: 10px;">	</span>&nbsp; &nbsp; TransactionExceptionCode.FailedStore,&nbsp;<span style="background-color: initial; font-size: 10px;">..., e.getMessage()),&nbsp;</span><span style="background-color: initial; font-size: 10px;">e);</span></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; @Override</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; public void <b style="font-size: 10px;">onTransactionException</b>(GlobalCommitRequest request, GlobalCommitResponse response,&nbsp;<span style="background-color: initial; font-size: 10px;">TransactionException tex) {</span></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super.onTransactionException(request, response, tex);</div><div style="font-size: 10px;"><font color="#007fff"><b><span style="white-space: pre;">	</span>&nbsp; &nbsp; // 后面步骤可能会抛出异常,这里将异常转成全局事务会话的状态并更新到全局事务会话<br></b></font></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>checkTransactionStatus</b>(request, response);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;"><br style="font-size: 10px;"></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; @Override</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; public void <b style="font-size: 10px;">onException</b>(GlobalCommitRequest request, GlobalCommitResponse response, Exception rex) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super.onException(request, response, rex);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkTransactionStatus(request, response);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;"><br style="font-size: 10px;"></div><div style="font-size: 10px;">&nbsp; &nbsp; }, request, response);</div><div style="font-size: 10px;">&nbsp; &nbsp; return response;</div><div style="font-size: 10px;">}</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2440" y="2440" width="440" height="420" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-6" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QYUXZyDFh2rJFv0anni3-27" target="9im45_5cZYxTOmNjTaqy-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-27" value="<div style="font-size: 10px;">public BranchRegisterResponse handle(BranchRegisterRequest request, final RpcContext rpcContext) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; BranchRegisterResponse response = new BranchRegisterResponse();</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; <b style="font-size: 10px;">exceptionHandleTemplate</b>(new AbstractCallback&lt;BranchRegisterRequest, BranchRegisterResponse&gt;() {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public void execute(BranchRegisterRequest request, BranchRegisterResponse response)</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throws TransactionException {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>doBranchRegister</b>(request, response, rpcContext);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (StoreException e) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new TransactionException(TransactionExceptionCode.FailedStore, String</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .format("branch register request failed. xid=%s, msg=%s", request.getXid(), e.getMessage()), e);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; }, request, response);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; return response;</div><div style="font-size: 10px;">&nbsp; &nbsp; }</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=2;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2440" y="1920" width="440" height="240" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-29" value="<font color="#007fff"><b>右边这些请求按分布式事务实际处理顺序排列</b></font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1910" y="1880" width="260" height="30" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-38" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QYUXZyDFh2rJFv0anni3-30" target="9im45_5cZYxTOmNjTaqy-37" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-39" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9im45_5cZYxTOmNjTaqy-38" vertex="1" connectable="0">
<mxGeometry x="-0.1842" y="-2" relative="1" as="geometry">
<mxPoint x="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-30" value="<b>和全局事务提交处理流程类似,<br>流程不详细列举了<br></b>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2440" y="2900" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-18" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="QYUXZyDFh2rJFv0anni3-32" target="9im45_5cZYxTOmNjTaqy-17" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="QYUXZyDFh2rJFv0anni3-32" value="<b>getCore</b>(branchType).<b>branchReport</b>(branchType, xid, branchId, status, applicationData);" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="3400" y="2280" width="440" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-3" value="AbstractTCInboundHandler" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2570" y="1890" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-8" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9im45_5cZYxTOmNjTaqy-5" target="9im45_5cZYxTOmNjTaqy-7" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-10" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9im45_5cZYxTOmNjTaqy-8" vertex="1" connectable="0">
<mxGeometry x="-0.1" y="3" relative="1" as="geometry">
<mxPoint y="3" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-5" value="<div style="font-size: 10px;"><div>protected void doBranchRegister(BranchRegisterRequest request, BranchRegisterResponse <br>&nbsp; &nbsp; &nbsp; &nbsp; response,&nbsp;<span style="background-color: initial;">RpcContext rpcContext) throws TransactionException {</span></div><div>&nbsp; &nbsp; MDC.put(RootContext.MDC_KEY_XID, request.getXid());</div><div>&nbsp; &nbsp; response.<b>setBranchId</b>(<span style="background-color: initial;"><b>core</b>.<b>branchRegister</b>(request.getBranchType(), <br><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span>request.getResourceId(), rpcContext.getClientId(),</span></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; request.getXid(), request.getApplicationData(), request.getLockKey()));</div><div>}</div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=7;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2920" y="1980" width="440" height="120" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-13" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9im45_5cZYxTOmNjTaqy-7" target="9im45_5cZYxTOmNjTaqy-12" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-7" value="<div style=""><div style="">return <b>getCore</b>(branchType).<b>branchRegister</b>(branchType, resourceId, clientId, xid,</div><div style="">&nbsp; &nbsp; applicationData, lockKeys);</div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=7;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="3400" y="2010" width="440" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-9" value="DefaultCore" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="3575" y="1980" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-15" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9im45_5cZYxTOmNjTaqy-12" target="9im45_5cZYxTOmNjTaqy-14" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-12" value="<div style=""><div style=""><div>public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid,</div><div><span style="white-space: pre;">	</span>String applicationData, String lockKeys) throws TransactionException {</div><div>&nbsp; &nbsp; GlobalSession globalSession = assertGlobalSessionNotNull(xid, false);</div><div>&nbsp; &nbsp; return SessionHolder.<b>lockAndExecute</b>(globalSession, () -&gt; {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; globalSessionStatusCheck(globalSession);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; BranchSession <b>branchSession</b> = <b>SessionHelper</b>.<b>newBranchByGlobal</b>(globalSession, <br><span style="white-space: pre;">	</span>&nbsp; &nbsp; branchType, resourceId,&nbsp;<span style="background-color: initial;">applicationData, lockKeys, clientId);</span></div><div>&nbsp; &nbsp; &nbsp; &nbsp; MDC.put(RootContext.MDC_KEY_BRANCH_ID, <br><span style="white-space: pre;">	</span>&nbsp; &nbsp; String.valueOf(branchSession.getBranchId()));</div><div><b><font color="#007fff"><span style="white-space: pre;">	</span>// 请求获取全局锁,实现全局事务的读隔离和写隔离,单独出一个流程图分析全局锁的获取和释放,参考:seata-at-globallock.drawio</font></b><br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; <b>branchSessionLock</b>(globalSession, branchSession);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; try {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>globalSession</b>.<b>addBranch</b>(branchSession);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; } catch (RuntimeException ex) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; branchSessionUnlock(branchSession);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new BranchTransactionException(FailedToAddBranch, String</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .format("Failed to store branch xid = %s branchId = %s", globalSession.getXid(),</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; branchSession.getBranchId()), ex);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ... 日志</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return branchSession.getBranchId();</div><div>&nbsp; &nbsp; });</div><div>}</div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=2;fontSize=10;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="3880" y="1880" width="440" height="320" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="9im45_5cZYxTOmNjTaqy-14" target="9im45_5cZYxTOmNjTaqy-61" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-14" value="<div style=""><div style=""><div>public void <b>addBranch</b>(BranchSession branchSession) throws TransactionException {</div><div><font color="#007fff"><b>&nbsp; &nbsp; // onAddBranch() 方法就是将 BranchSession 实例存储到 SessionManager GlobalSession对象</b></font></div><div>&nbsp; &nbsp;&nbsp;<b>SessionHolder</b>.<b>getRootSessionManager</b>().<b>onAddBranch</b>(this, branchSession);</div><div>&nbsp; &nbsp; for (SessionLifecycleListener lifecycleListener : lifecycleListeners) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; lifecycleListener.onAddBranch(this, branchSession);</div><div>&nbsp; &nbsp; }</div><div>&nbsp; &nbsp; if (!RaftServerFactory.getInstance().isRaftMode()) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; add(branchSession);</div><div>&nbsp; &nbsp; }</div><div>}</div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=2;fontSize=10;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="4360" y="1970" width="440" height="140" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-16" value="GlobalSession" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="4530" y="2220" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-21" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="9im45_5cZYxTOmNjTaqy-17" target="9im45_5cZYxTOmNjTaqy-19" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-17" value="<div>public void <b>branchReport</b>(BranchType branchType, String xid, long branchId, BranchStatus status,&nbsp;<span style="background-color: initial;">String applicationData) throws TransactionException {</span></div><div>&nbsp; &nbsp; GlobalSession globalSession = assertGlobalSessionNotNull(xid, true);</div><div>&nbsp; &nbsp; BranchSession branchSession = globalSession.<b>getBranch</b>(branchId);</div><div>&nbsp; &nbsp; if (branchSession == null) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; throw new BranchTransactionException(BranchTransactionNotExist,</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String.format("Could not found branch session xid = %s branchId = %s", xid, branchId));</div><div>&nbsp; &nbsp; }</div><div>&nbsp; &nbsp; branchSession.<b>setApplicationData</b>(applicationData);</div><div>&nbsp; &nbsp; globalSession.<b>changeBranchStatus</b>(branchSession, status);</div><div>&nbsp; &nbsp; ....</div><div>}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=3;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="3880" y="2230" width="440" height="160" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-64" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="9im45_5cZYxTOmNjTaqy-19" target="9im45_5cZYxTOmNjTaqy-63" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-19" value="<div style=""><div style=""><div>public void changeBranchStatus(BranchSession branchSession, BranchStatus status) throws TransactionException {</div><div>&nbsp; &nbsp; <b>SessionHolder.getRootSessionManager</b>().<b>onBranchStatusChange</b>(this, branchSession, status);</div><div>&nbsp; &nbsp; for (SessionLifecycleListener lifecycleListener : lifecycleListeners) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; lifecycleListener.onBranchStatusChange(this, branchSession, status);</div><div>&nbsp; &nbsp; }</div><div>}</div></div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=2;fontSize=10;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="4360" y="2250" width="440" height="120" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-20" value="GlobalSession" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="4530" y="1940" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-23" value="<b>GlobalReportRequest</b>#handle()<br>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2200" y="3000" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-24" value="<b>GlobalStatusRequest</b>#handle()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2200" y="3080" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-28" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9im45_5cZYxTOmNjTaqy-25" target="9im45_5cZYxTOmNjTaqy-27" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-25" value="<div style="font-size: 10px;">protected void doGlobalCommit(GlobalCommitRequest request, GlobalCommitResponse response, RpcContext rpcContext)</div><div style="font-size: 10px;">&nbsp; &nbsp; throws TransactionException {</div><div style="font-size: 10px;">&nbsp; &nbsp; MDC.put(RootContext.MDC_KEY_XID, request.getXid());</div><div style="font-size: 10px;">&nbsp; &nbsp; response.<b style="font-size: 10px;">setGlobalStatus</b>(core.<b style="font-size: 10px;">commit</b>(request.getXid()));</div><div style="font-size: 10px;">}</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=7;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2920" y="2600" width="440" height="100" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-30" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9im45_5cZYxTOmNjTaqy-27" target="9im45_5cZYxTOmNjTaqy-29" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="3850" y="2690" />
<mxPoint x="3850" y="2900" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="NiLmKkYYFyx57cjf1eTG-3" value="1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9im45_5cZYxTOmNjTaqy-30">
<mxGeometry x="0.8784" y="-2" relative="1" as="geometry">
<mxPoint y="-2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-27" value="<div style="font-size: 10px;">public GlobalStatus commit(String xid) throws TransactionException {</div><div style="font-size: 10px;">&nbsp; &nbsp; GlobalSession globalSession = SessionHolder.findGlobalSession(xid);</div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; ... 全局会话是否为空、是否超时检查 ...</font></div><div style="font-size: 10px;"><br style="font-size: 10px;"></div><div style="font-size: 10px;">&nbsp; &nbsp; // just lock changeStatus</div><div style="font-size: 10px;">&nbsp; &nbsp; boolean <b style="font-size: 10px;">shouldCommit</b> = SessionHolder.<b style="font-size: 10px;">lockAndExecute</b>(globalSession, <br style="font-size: 10px;">&nbsp; &nbsp; () -&gt;&nbsp;<span style="background-color: initial; font-size: 10px;">{</span></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; boolean shouldCommitNow = false;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; if (globalSession.getStatus() == GlobalStatus.Begin) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Highlight: Firstly, close the session, then no more branch can be registered.</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; globalSession.close();</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (globalSession.<b>canBeCommittedAsync</b>()) { <font color="#007fff">//可以异步提交</font></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; globalSession.asyncCommit();</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MetricsPublisher.postSessionDoneEvent(globalSession, GlobalStatus.Committed, false, false);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp;&nbsp;<font color="#007fff">//不可以异步提交</font></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; globalSession.<b>changeGlobalStatus</b>(GlobalStatus.Committing);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; shouldCommitNow = true;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;"><b><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //这里清除全局锁&nbsp;</font></b></div><font color="#007fff"><b><span style="white-space: pre;">	</span>&nbsp; &nbsp; //LockerManagerFactory.getLockManager().releaseGlobalSessionLock(this)</b></font><br><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; globalSession.<b>clean</b>();</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; return shouldCommitNow;</div><div style="font-size: 10px;">&nbsp; &nbsp; });</div><div style="font-size: 10px;"><br style="font-size: 10px;"></div><div style="font-size: 10px;">&nbsp; &nbsp; if (shouldCommit) {</div><div style="font-size: 10px;"><font color="#007fff"><span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><b>// 1</b><br></font></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; boolean success = <b style="font-size: 10px;">doGlobalCommit</b>(globalSession, false);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; //If successful and all remaining branches can be committed asynchronously, do async commit.</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; if (success &amp;&amp; globalSession.hasBranch() &amp;&amp; globalSession.canBeCommittedAsync()) {&nbsp;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; globalSession.<b style="font-size: 10px;">asyncCommit</b>();</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return GlobalStatus.Committed;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return globalSession.getStatus();</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; } else {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; return globalSession.getStatus() == GlobalStatus.AsyncCommitting ? GlobalStatus.Committed : globalSession.getStatus();</div><div style="font-size: 10px;">&nbsp; &nbsp; }</div><div style="font-size: 10px;">}</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=2;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="3400" y="2440" width="440" height="520" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-32" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9im45_5cZYxTOmNjTaqy-29" target="9im45_5cZYxTOmNjTaqy-31" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="4570" y="2900" />
<mxPoint x="4570" y="2480" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="NiLmKkYYFyx57cjf1eTG-2" value="1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9im45_5cZYxTOmNjTaqy-32">
<mxGeometry x="0.9235" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-29" value="<div style="font-size: 10px;">public boolean doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException {</div><div style="font-size: 10px;">&nbsp; &nbsp; boolean success = true;</div><div style="font-size: 10px;">&nbsp; &nbsp; MetricsPublisher.postSessionDoingEvent(globalSession, retrying);</div><div style="font-size: 10px;"><br style="font-size: 10px;"></div><div style="font-size: 10px;">&nbsp; &nbsp; if (globalSession.isSaga()) {&nbsp; &nbsp;<font color="#007fff" style="font-size: 10px;">//Saga事务全局提交</font></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; success = getCore(BranchType.SAGA).doGlobalCommit(globalSession, retrying);</div><div style="font-size: 10px;">&nbsp; &nbsp; } else {</div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; // 非Saga模式的事务</font></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; List&lt;BranchSession&gt; branchSessions = globalSession.getSortedBranches();</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; Boolean result = <b style="font-size: 10px;">SessionHelper</b>.<b style="font-size: 10px;">forEach</b>(branchSessions, branchSession -&gt; { <b><font color="#007fff">// 遍历所有分支事务会话</font></b></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // if not retrying, skip the canBeCommittedAsync branches</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!retrying &amp;&amp; branchSession.canBeCommittedAsync()) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return CONTINUE;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;"><span style="background-color: initial; font-size: 10px;"><br style="font-size: 10px;"></span></div><div style="font-size: 10px;"><span style="background-color: initial; font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BranchStatus currentStatus = branchSession.getStatus();</span><br style="font-size: 10px;"></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (currentStatus == BranchStatus.PhaseOne_Failed) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SessionHelper.removeBranch(globalSession, branchSession, !retrying);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return CONTINUE;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {</div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;"><b style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //1 提交分支事务(第二阶段)</b></font></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BranchStatus branchStatus = <b style="font-size: 10px;">getCore</b>(branchSession.getBranchType()).<b style="font-size: 10px;">branchCommit</b>(globalSession, <br style="font-size: 10px;"><span style="white-space: pre; font-size: 10px;">	</span><span style="white-space: pre; font-size: 10px;">	</span>&nbsp; &nbsp; branchSession);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (isXaerNotaTimeout(globalSession,branchStatus)) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; branchStatus = BranchStatus.<b>PhaseTwo_Committed</b>;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch (branchStatus) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case <b style="font-size: 10px;">PhaseTwo_Committed</b>:</div><div style="font-size: 10px;"><b><font color="#007fff"><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span>// 删除分支会话</font><br></b></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SessionHelper.<b>removeBranch</b>(globalSession, branchSession, !retrying);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return CONTINUE;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case <b style="font-size: 10px;">PhaseTwo_CommitFailed_Unretryable</b>: <font color="#007fff" style="font-size: 10px;">//多次重试后仍然提交失败</font></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SessionHelper.<b>endCommitFailed</b>(globalSession, retrying); <font color="#007fff">//设置全局事务失败</font></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default:</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!retrying) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; globalSession.queueToRetryCommit();</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (globalSession.canBeCommittedAsync()) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return CONTINUE;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (Exception ex) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String commitInfo = retrying ? "Global commit continue" : "Global commit failed";</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StackTraceLogger.error(LOGGER, ex, "Committing branch transaction exception:retrying={}, {}, {}",</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new String[] {String.valueOf(retrying), branchSession.toString(), commitInfo});</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!retrying) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; globalSession.<b>queueToRetryCommit</b>();</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new TransactionException(ex);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return CONTINUE;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; }, PARALLEL_HANDLE_BRANCH &amp;&amp; branchSessions.size() &gt;= 2);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; // Return if the result is not null</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; if (result != null) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return result;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; //If has branch and not all remaining branches can be committed asynchronously,</font></div><div style="font-size: 10px;"><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; //do print log and return false</font></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; if (globalSession.hasBranch() &amp;&amp; !globalSession.canBeCommittedAsync()) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LOGGER.info("Committing global transaction is NOT done, xid = {}.", globalSession.getXid());</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp;<font color="#007fff"> &nbsp; // if it succeeds and there is no branch, retrying=true is the asynchronous state when retrying. EndCommitted is</font></div><div style="font-size: 10px;"><font color="#007fff">&nbsp; &nbsp; // executed to improve concurrency performance, and the global transaction ends..</font></div><div style="font-size: 10px;">&nbsp; &nbsp; if (success &amp;&amp; globalSession.getBranchSessions().isEmpty()) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; SessionHelper.<b>endCommitted</b>(globalSession, retrying); <b><font color="#007fff">// 事务成功结束,内部会删除全局会话 GlobalSession</font></b></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; LOGGER.info("Committing global transaction is successfully done, xid = {}.", globalSession.getXid());</div><div style="font-size: 10px;">&nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; return success;</div><div style="font-size: 10px;">}</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=2;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="3880" y="2440" width="680" height="920" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-34" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9im45_5cZYxTOmNjTaqy-31" target="9im45_5cZYxTOmNjTaqy-33" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-31" value="<div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;"><b style="font-size: 10px;">// 向各个事务参与者(Netty Client)发送分支提交请求 BranchCommitRequest</b></font></div><div style="font-size: 10px;">BranchCommitResponse response = (BranchCommitResponse) <b style="font-size: 10px;">remotingServer</b><br style="font-size: 10px;">&nbsp; &nbsp; .<b style="font-size: 10px;">sendSyncRequest</b>(<span style="background-color: initial; font-size: 10px;">branchSession.getResourceId(),&nbsp; &nbsp;<br style="font-size: 10px;">&nbsp; &nbsp; branchSession.getClientId(),request, branchSession.isAT());</span></div><div style="font-size: 10px;">return response.getBranchStatus();</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=7;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="4600" y="2440" width="440" height="80" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-36" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9im45_5cZYxTOmNjTaqy-33" target="9im45_5cZYxTOmNjTaqy-35" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-33" value="<div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;"><b style="font-size: 10px;">// 向各个事务参与者(Netty Client)发送分支提交响应 Request</b></font></div><div style="font-size: 10px;"><div style="font-size: 10px;">public Object sendSyncRequest(String resourceId, String clientId, Object msg, boolean tryOtherApp)&nbsp;<span style="background-color: initial; font-size: 10px;">throws TimeoutException {</span></div><div style="font-size: 10px;"><span style="background-color: initial; font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; // 获取事务参与者客户端连接</font></span></div><div style="font-size: 10px;">&nbsp; &nbsp; Channel channel = <b style="font-size: 10px;">ChannelManager</b>.<b style="font-size: 10px;">getChannel</b>(resourceId, clientId, tryOtherApp);</div><div style="font-size: 10px;">&nbsp; &nbsp; if (channel == null) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; throw new RuntimeException(...);</div><div style="font-size: 10px;">&nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; RpcMessage rpcMessage = <b>buildRequestMessage</b>(msg, <br><span style="white-space: pre;">	</span>ProtocolConstants.<b>MSGTYPE_RESQUEST_SYNC</b>);</div><div style="font-size: 10px;">&nbsp; &nbsp; return super.<b style="font-size: 10px;">sendSync</b>(channel, rpcMessage, NettyServerConfig.getRpcRequestTimeout());</div><div style="font-size: 10px;">}</div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=3;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="5080" y="2440" width="440" height="180" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-35" value="<div style=""><div style="font-size: 10px;">...</div><div style=""><b>doBeforeRpcHooks</b>(remoteAddr, rpcMessage);<br></div><div style="font-size: 10px;">channel.<b>writeAndFlush</b>(rpcMessage).addListener((ChannelFutureListener) future -&gt; {</div><div style="font-size: 10px;">&nbsp; &nbsp; if (!future.isSuccess()) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; MessageFuture messageFuture1 = futures.remove(rpcMessage.getId());</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; if (messageFuture1 != null) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; messageFuture1.setResultMessage(future.cause());</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; destroyChannel(future.channel());</div><div style="font-size: 10px;">&nbsp; &nbsp; }</div><div style="font-size: 10px;">});</div><div style="font-size: 10px;">try {</div><div style="font-size: 10px;">&nbsp; &nbsp; Object result = messageFuture.<b>get</b>(timeoutMillis, TimeUnit.MILLISECONDS);</div><div style="font-size: 10px;">&nbsp; &nbsp; <b>doAfterRpcHooks</b>(remoteAddr, rpcMessage, result);</div><div style="font-size: 10px;">&nbsp; &nbsp; return result;</div><div style="font-size: 10px;">} catch (Exception exx) {</div><div style="font-size: 10px;">&nbsp; &nbsp; if (exx instanceof TimeoutException) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; throw (TimeoutException) exx;</div><div style="font-size: 10px;">&nbsp; &nbsp; } else {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; throw new RuntimeException(exx);</div><div style="font-size: 10px;">&nbsp; &nbsp; }</div><div style="font-size: 10px;">}</div></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=3;fontSize=10;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="5560" y="2440" width="440" height="280" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-37" value="<div><div><font color="#007fff"><b>// 向各个事务参与者(Netty Client)发送分支回滚请求 BranchRollbackRequest</b></font></div></div><div><b>BranchRollbackResponse</b> response = (BranchRollbackResponse) <b>remotingServer</b><br>&nbsp; &nbsp; .<b>sendSyncRequest</b>(<span style="background-color: initial;">branchSession.getResourceId(), branchSession.getClientId(), request, <br><span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>branchSession.isAT());</span></div><div>return response.getBranchStatus();</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="2680" y="2900" width="440" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-40" value="BatchLogHandler<br><font style="" color="#007fff">异步打印日志,内部启动了线程池,线程任务阻塞读取日志队列中的日志并打印</font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="40" y="2240" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-45" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=1;dashed=1;" parent="1" source="9im45_5cZYxTOmNjTaqy-42" target="QYUXZyDFh2rJFv0anni3-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-42" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>AbstractSessionManager</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px;">protected TransactionStoreManager transactionStoreManager;<br></p><p style="margin: 0px 0px 0px 4px;">protected String name;<br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-1760" y="2280" width="400" height="120" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-44" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endArrow=block;endFill=1;" parent="1" source="9im45_5cZYxTOmNjTaqy-43" target="9im45_5cZYxTOmNjTaqy-42" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-43" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>FileSessionManager</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px;"><font color="#007fff"><b>使用文件存储Session, 业务中不会使用这种实现因为无法支持HA</b></font></p><p style="margin: 0px 0px 0px 4px;">private static final int <b>READ_SIZE</b> = ConfigurationFactory.getInstance().getInt(</p><p style="margin: 0px 0px 0px 4px;">&nbsp; &nbsp; ConfigurationKeys.SERVICE_SESSION_RELOAD_READ_SIZE,&nbsp; &nbsp; <br>&nbsp; &nbsp; DEFAULT_SERVICE_SESSION_RELOAD_READ_SIZE);</p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">// Session Map, 持久化时将此Map内容存储到 sessionStore/&lt;port&gt;/root.data</font></p><p style="margin: 0px 0px 0px 4px;">private Map&lt;String, GlobalSession&gt; <b>sessionMap</b> = <br>&nbsp; &nbsp; new ConcurrentHashMap&lt;&gt;(64);<br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="-1760" y="2440" width="400" height="160" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-48" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="9im45_5cZYxTOmNjTaqy-47" target="9im45_5cZYxTOmNjTaqy-42" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-47" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>DataBaseSessionManager</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px;"><font color="#007fff"><b>使用数据库存储Session</b></font></p><p style="margin: 0px 0px 0px 4px;"><br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="-2200" y="2440" width="400" height="120" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-49" value="" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="1000" y="1920" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-51" value="<font color="#007fff" style="font-size: 10px;"><b>从客户端实现看处理 GlobalCommitRequest<br style="font-size: 10px;">只是删除撤销日志</b></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=10;" parent="1" vertex="1">
<mxGeometry x="2200" y="2545" width="220" height="40" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-52" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 11px;"><b style="font-size: 11px;">StoreDBProperties</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><b style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">全局会话存储配置属性:seata.store.db</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><b style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">常用 DB 模式,如果要求高性能可以使用 Redis 模式</font></b></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px;">private String datasource = "druid";</p><p style="margin: 0px 0px 0px 4px;">private String dbType = "mysql";</p><p style="margin: 0px 0px 0px 4px;">private String <b>driverClassName</b> = "com.mysql.jdbc.Driver";</p><p style="margin: 0px 0px 0px 4px;">private String <b>url</b> = "jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true";</p><p style="margin: 0px 0px 0px 4px;">private String <b>user</b> = "mysql";</p><p style="margin: 0px 0px 0px 4px;">private String <b>password</b> = "mysql";</p><p style="margin: 0px 0px 0px 4px;">private Integer minConn = DEFAULT_DB_MIN_CONN;&nbsp; <font color="#007fff">// 默认最小连接数10</font></p><p style="margin: 0px 0px 0px 4px;">private Integer maxConn = DEFAULT_DB_MAX_CONN; <font color="#007fff">// 默认最大连接数 100</font></p><p style="margin: 0px 0px 0px 4px;">private String <b>globalTable</b> = "global_table";</p><p style="margin: 0px 0px 0px 4px;">private String <b>branchTable</b> = "branch_table";</p><p style="margin: 0px 0px 0px 4px;">private String lockTable = "lock_table";</p><p style="margin: 0px 0px 0px 4px;">private String distributedLockTable = "distributed_lock";</p><p style="margin: 0px 0px 0px 4px;">private Integer queryLimit = DEFAULT_QUERY_LIMIT;</p><p style="margin: 0px 0px 0px 4px;">private Long maxWait = 5000L;</p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-1760" y="120" width="400" height="320" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-53" value="<div style="font-size: 10px;">private void onRegRmMessage(ChannelHandlerContext ctx, RpcMessage rpcMessage) {</div><div style="font-size: 10px;">&nbsp; &nbsp; RegisterRMRequest message = (RegisterRMRequest) rpcMessage.getBody();</div><div style="font-size: 10px;">&nbsp; &nbsp; String ipAndPort = NetUtil.toStringAddress(ctx.channel().remoteAddress());</div><div style="font-size: 10px;">&nbsp; &nbsp; boolean isSuccess = false;</div><div style="font-size: 10px;">&nbsp; &nbsp; String errorInfo = StringUtils.EMPTY;</div><div style="font-size: 10px;">&nbsp; &nbsp; try {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; if (null == checkAuthHandler || <span style="white-space: pre;">	</span><span style="white-space: pre;">	</span>checkAuthHandler.regResourceManagerCheckAuth(message)) {</div><div style="font-size: 10px;"><b><font color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 注册RM, 其实主要就是存储一下连接</font></b></div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>ChannelManager</b>.<b>registerRMChannel</b>(<b>message</b>, <b>ctx.channel()</b>);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Version.putChannelVersion(ctx.channel(), message.getVersion());</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isSuccess = true;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ... 日志</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; } catch (Exception exx) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; ...</div><div style="font-size: 10px;">&nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; RegisterRMResponse response = new RegisterRMResponse(isSuccess);</div><div style="font-size: 10px;">&nbsp; &nbsp; if (StringUtils.isNotEmpty(errorInfo)) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; response.setMsg(errorInfo);</div><div style="font-size: 10px;">&nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; remotingServer.sendAsyncResponse(rpcMessage, ctx.channel(), response);</div><div style="font-size: 10px;">&nbsp; &nbsp; ...</div><div style="font-size: 10px;">}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=2;" parent="1" vertex="1">
<mxGeometry x="1000" y="2020" width="440" height="320" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-55" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ChannelManager</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><font color="#007fff"><b>管理Seata客户端的连接</b></font></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><font color="#007fff"><b>// Channel -&gt; RpcContext</b></font></p><p style="margin: 0px 0px 0px 4px;">private static final ConcurrentMap&lt;Channel, RpcContext&gt; <br>&nbsp; &nbsp; <b>IDENTIFIED_CHANNELS</b> = new ConcurrentHashMap&lt;&gt;();<br></p><p style="margin: 0px 0px 0px 4px;"><b><font color="#007fff">// RM连接:</font></b></p><p style="margin: 0px 0px 0px 4px;">private static final ConcurrentMap&lt;String, ConcurrentMap&lt;String, <br>&nbsp; &nbsp; ConcurrentMap&lt;String,&nbsp;<span style="background-color: initial;">ConcurrentMap&lt;Integer, RpcContext&gt;&gt;&gt;&gt; <br></span><b style="background-color: initial;">&nbsp; &nbsp; RM_CHANNELS</b><span style="background-color: initial;"> = new ConcurrentHashMap&lt;&gt;();</span></p><p style="margin: 0px 0px 0px 4px;"><b style="border-color: var(--border-color);"><font style="border-color: var(--border-color);" color="#007fff">// TM连接:&nbsp;&nbsp;服务名IP -&gt; 端口 -&gt; RpcContext</font></b><br></p><p style="margin: 0px 0px 0px 4px;">private static final ConcurrentMap&lt;String, ConcurrentMap&lt;Integer,&nbsp; <br>&nbsp; &nbsp; RpcContext&gt;&gt; <b>TM_CHANNELS</b>&nbsp;= new ConcurrentHashMap&lt;&gt;();</p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="-440" y="2560" width="400" height="240" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-56" value="<font color="#007fff"><b>当注册订单服务后,ChannelManager中的连接数据:<br><br>IDENTIFIED_CHANNELS:<br></b></font><div><font color="#007fff">result = {ConcurrentHashMap@12365}&nbsp; size = 1</font></div><div><font color="#007fff">&nbsp;{NioSocketChannel@12369} "[id: 0xd7296da5, L:/127.0.0.1:8091 - R:/127.0.0.1:35644]" -&gt; {RpcContext@12370}&nbsp;</font></div><div><font color="#007fff">&nbsp; key = {<b>NioSocketChannel</b>@12369} "[id: 0xd7296da5, L:/127.0.0.1:8091 - R:/127.0.0.1:35644]"</font></div><div><font color="#007fff">&nbsp; value = {<b>RpcContext</b>@12370}&nbsp;</font></div><div><font color="#007fff">&nbsp; &nbsp;<b>clientRole</b> = {NettyPoolKey$TransactionRole@12375} "TMROLE"</font></div><div><font color="#007fff">&nbsp; &nbsp;version = "2.0.0"</font></div><div><font color="#007fff">&nbsp; &nbsp;<b>applicationId</b> = "order-service"</font></div><div><font color="#007fff">&nbsp; &nbsp;<b>transactionServiceGroup</b> = "order-service-group"</font></div><div><font color="#007fff">&nbsp; &nbsp;<b>clientId</b> = "order-service:127.0.0.1:35644"</font></div><div><font color="#007fff">&nbsp; &nbsp;<b>channel</b> = {NioSocketChannel@12369} "[id: 0xd7296da5, L:/127.0.0.1:8091 - R:/127.0.0.1:35644]"</font></div><div><font color="#007fff">&nbsp; &nbsp;resourceSets = null</font></div><div><font color="#007fff">&nbsp; &nbsp;clientIDHolderMap = {ConcurrentHashMap@12365}&nbsp; size = 1</font></div><div><font color="#007fff">&nbsp; &nbsp;<b>clientTMHolderMap</b> = {ConcurrentHashMap@12380}&nbsp; size = 1</font></div><div><font color="#007fff">&nbsp; &nbsp; {Integer@12386} 35644 -&gt; {RpcContext@12370}&nbsp;</font></div><div><font color="#007fff">&nbsp; &nbsp;clientRMHolderMap = null</font></div><div><font color="#007fff"><br></font></div><div><font color="#007fff"><b>RM_CHANNELS:</b><br><div style="">result = {ConcurrentHashMap@12432}&nbsp; size = 3</div><div style="">&nbsp;"jdbc:mysql://127.0.0.1:13306/seata_order" -&gt; {ConcurrentHashMap@12441}&nbsp; size = 1</div><div style="">&nbsp; key = "jdbc:mysql://127.0.0.1:13306/seata_order"</div><div style="">&nbsp; value = {ConcurrentHashMap@12441}&nbsp; size = 1</div><div style="">&nbsp; &nbsp;"order-service" -&gt; {ConcurrentHashMap@12450}&nbsp; size = 1</div><div style="">&nbsp; &nbsp; key = "order-service"</div><div style="">&nbsp; &nbsp; value = {ConcurrentHashMap@12450}&nbsp; size = 1</div><div style="">&nbsp; &nbsp; &nbsp;"127.0.0.1" -&gt; {ConcurrentHashMap@12455}&nbsp; size = 1</div><div style="">&nbsp; &nbsp; &nbsp; key = "127.0.0.1"</div><div style="">&nbsp; &nbsp; &nbsp; value = {ConcurrentHashMap@12455}&nbsp; size = 1</div><div style="">&nbsp; &nbsp; &nbsp; &nbsp;{Integer@12459} 43908 -&gt; {RpcContext@12460}</div></font></div><div><font color="#007fff"><b><br></b></font></div><div><font color="#007fff"><div style=""><b>TM_CHANNELS:</b><br><div style=""><div style="">result = {ConcurrentHashMap@12395}&nbsp; size = 1</div><div style="">&nbsp;"order-service:127.0.0.1" -&gt; {ConcurrentHashMap@12380}&nbsp; size = 1</div><div style="">&nbsp; key = "order-service:127.0.0.1"</div><div style="">&nbsp; value = {ConcurrentHashMap@12380}&nbsp; size = 1</div><div style="">&nbsp; &nbsp;{Integer@12386} 35644 -&gt; {RpcContext@12370}&nbsp;</div><div style="">&nbsp; &nbsp; key = {Integer@12386} 35644</div><div style="">&nbsp; &nbsp; value = {RpcContext@12370}&nbsp;</div></div></div></font></div>" style="text;html=1;align=left;verticalAlign=top;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="-30" y="2560" width="630" height="590" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-57" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>RpcContext</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><font color="#007fff"><b>RPC连接上下文信息</b></font></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><font color="#007fff">// Channel -&gt; RpcContext</font></p><p style="margin: 0px 0px 0px 4px;"><br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br style="font-size: 11px;"></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=11;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-880" y="2560" width="400" height="240" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-59" value="<div style="font-size: 10px;"><font color="#007fff">全局会话的持久化存储有多种实现,这里展示 DataBaseSessionManager 使用 MySQL 存储的SQL:<br></font><div><b>insert into&nbsp;#global_table#&nbsp;<span style="background-color: initial;">( &lt;全局会话数据表的字段&gt; )</span><span style="background-color: initial;">&nbsp;values (?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now())</span></b></div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=15;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="4360" y="1730" width="440" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-61" value="<div style=""><font style="font-size: 10px;" color="#007fff">分支事务会话的持久化存储有多种实现,这里展示 DataBaseSessionManager 使用 MySQL 存储的SQL:<br></font><div style=""><b style="font-size: 10px;">insert into&nbsp;#branch_table#&nbsp;</b><span style="font-size: 10px; font-weight: bold; background-color: initial;">( &lt;分支会话数据表的字段&gt; )</span><b style="font-size: 10px;">&nbsp;values (</b><b style="background-color: initial; border-color: var(--border-color);">?, ?, ?, ?, ?, ?, ?, ?, ?</b><b style="background-color: initial;">, now(), now())</b></div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=15;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="4840" y="2010" width="440" height="60" as="geometry" />
</mxCell>
<mxCell id="9im45_5cZYxTOmNjTaqy-63" value="<div style=""><font style="font-size: 10px;" color="#007fff">分支事务会话的持久化存储有多种实现,这里展示 DataBaseSessionManager 使用 MySQL 存储的SQL:<br></font><div style=""><b>update&nbsp; #branch_table#&nbsp; &nbsp; set status = ?,&nbsp; application_data = ?,&nbsp; gmt_modified = now(6) where xid = ?&nbsp; &nbsp;and branch_id = ?</b><br></div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=15;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="4840" y="2280" width="440" height="60" as="geometry" />
</mxCell>
<mxCell id="NiLmKkYYFyx57cjf1eTG-1" value="DefaultCoordinator" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="3080" y="1950" width="120" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>