-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsentinel.drawio
1760 lines (1760 loc) · 355 KB
/
sentinel.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
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<mxfile host="Electron" modified="2024-10-22T14:09:32.317Z" 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="CLd35iXWkjCJ66chMAWZ" version="21.6.5" type="device" pages="2">
<diagram name="工作主流程" id="GKn8MqRBRS7uCVeujyc3">
<mxGraphModel dx="5569" dy="879" 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="S1kR7U3J-qD7APwjgyKx-1" value="<h1 style="font-size: 18px;"><font style="font-size: 18px;">Sentinel 工作原理流程</font></h1><div style="font-size: 12px;"><div style=""><font style="font-size: 12px;">源码版本:spring-cloud-starter-alibaba-sentinel:2021.0.5.0, 使用Nacos 作为规则数据源。</font></div></div><div style="font-size: 12px;">大部分代码都很容易理解,主要是用于系统保护、流控规则校验的相关的数据的统计部分有点难以理解(比如Node树)。</div><div style="font-size: 12px;">测试DEMO: SpringBoot-Labs/sentinel</div>" style="text;html=1;strokeColor=none;fillColor=none;spacing=5;spacingTop=-20;whiteSpace=wrap;overflow=hidden;rounded=0;fontSize=16;" parent="1" vertex="1">
<mxGeometry x="40" y="10" width="520" height="100" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-5" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-2" target="S1kR7U3J-qD7APwjgyKx-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-11" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-2" target="S1kR7U3J-qD7APwjgyKx-10" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-14" 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="S1kR7U3J-qD7APwjgyKx-2" target="S1kR7U3J-qD7APwjgyKx-12" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-2" value="配置加载" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="40" y="120" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-8" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-4" target="S1kR7U3J-qD7APwjgyKx-6" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-27" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-4" target="S1kR7U3J-qD7APwjgyKx-26" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-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="S1kR7U3J-qD7APwjgyKx-4" target="S1kR7U3J-qD7APwjgyKx-28" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-31" 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="S1kR7U3J-qD7APwjgyKx-4" target="S1kR7U3J-qD7APwjgyKx-29" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-4" value="组件初始化<br><font color="#007fff">主要关注3个自动配置类</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="40" y="540" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-142" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-6" target="S1kR7U3J-qD7APwjgyKx-141" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="JXVrsIax2Fh7985Lvlhv-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;dashed=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-6" target="JXVrsIax2Fh7985Lvlhv-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-6" value="请求流量统计、规则检查、规则检查异常处理" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="40" y="1480" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-10" value="系统属性配置 <br>SentinelProperties" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="240" y="120" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-17" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-12" target="S1kR7U3J-qD7APwjgyKx-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-19" 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="S1kR7U3J-qD7APwjgyKx-12" target="S1kR7U3J-qD7APwjgyKx-18" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-23" 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="S1kR7U3J-qD7APwjgyKx-12" target="S1kR7U3J-qD7APwjgyKx-20" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-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="S1kR7U3J-qD7APwjgyKx-12" target="S1kR7U3J-qD7APwjgyKx-22" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-12" value="规则动态配置<br><font color="#007fff">调用<b>控制台</b>的接口</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="240" y="200" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-47" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-16" target="S1kR7U3J-qD7APwjgyKx-46" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-16" value="流控规则动态配置<br>POST /v1/flow/rule" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="480" y="200" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-18" value="熔断规则动态配置<br>POST /degrade/rule" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="480" y="280" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-20" value="热点规则动态配置<br>POST /paramFlow/rule&nbsp;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="480" y="360" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-22" value="授权规则动态配置<br>POST /authority/rule" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="480" y="440" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-33" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-26" target="S1kR7U3J-qD7APwjgyKx-32" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-26" value="SentinelAutoConfiguration" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="240" y="540" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-41" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-28" target="S1kR7U3J-qD7APwjgyKx-39" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-28" value="SentinelWebAutoConfiguration" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="240" y="720" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-43" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-29" target="S1kR7U3J-qD7APwjgyKx-42" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-29" value="SentinelFeignAutoConfiguration" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="240" y="800" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-35" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-32" target="S1kR7U3J-qD7APwjgyKx-34" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-32" value="设置一批系统属性" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="480" y="540" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-37" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-34" target="S1kR7U3J-qD7APwjgyKx-36" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-34" value="配置类&amp;Bean" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="480" y="620" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-133" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-36" target="S1kR7U3J-qD7APwjgyKx-132" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-36" value="<b>SentinelResourceAspect</b><br>SentinelBeanPostProcessor<br><b>SentinelDataSourceHandler</b><br>SentinelConverterConfiguration<br>SentinelJsonConfiguration" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="720" y="610" width="200" height="80" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-38" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-39" target="S1kR7U3J-qD7APwjgyKx-40" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-39" value="配置类&amp;Bean" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="480" y="720" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-40" value="<b>SentinelWebInterceptor</b><br><b>SentinelWebMvcConfig</b><br>SentinelWebMvcConfigurer" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="720" y="720" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-45" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-42" target="S1kR7U3J-qD7APwjgyKx-44" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-42" value="SentinelFeignAutoConfiguration" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="480" y="800" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-44" value="SentinelFeign.Builder" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="720" y="800" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-50" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-46" target="S1kR7U3J-qD7APwjgyKx-49" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-46" value="FlowControllerV1#apiAddFlowRule()<br>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="720" y="200" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-48" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>FlowRuleEntity</b><br></p><hr size="1"><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;" color="#007fff">流控规则实体定义。</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;"><br></font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private Long id;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private String app;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private String ip;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private Integer port;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;" color="#007fff">//被限制的应用,即规则只对这些应用生效,默认default</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private String <b>limitApp</b>;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;" color="#007fff">//流控目标资源。是"路由" 或 "请求方法:路由"</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private String <b>resource</b>;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;" color="#007fff">//流控类型:0:线程数、1:QPS</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private Integer <b>grade</b>;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;" color="#007fff">//流控阈值,比如:最多count个线程、最大count QPS</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private Double <b>count</b>;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font color="#007fff" style="font-size: 10px;">//流控模式</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font color="#007fff" style="font-size: 10px;">//STRATEGY_DIRECT 根据调用方限流,需结合 limitApp 使用</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font color="#007fff" style="font-size: 10px;">//STRATEGY_RELATE 根据关联流量限流,比如写操作频繁时对读进行限流</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font color="#007fff" style="font-size: 10px;">//STRATEGY_CHAIN 根据调用链路入口限流</font></p><font color="#007fff"></font><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private Integer <b>strategy</b>;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private String refResource;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;" color="#007fff">//控制行为</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;" color="#007fff">//CONTROL_BEHAVIOR_DEFAULT直接拒绝(快速失败)</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;" color="#007fff">//CONTROL_BEHAVIOR_WARM_UP 冷启动(让流量缓慢增加)</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">//</font><font style="font-size: 10px;" color="#007fff">CONTROL_BEHAVIOR_RATE_LIMITER 排队等待,匀速器模式,处理间隔性突发流量让请求可以在接下来的空闲期间逐渐处理,比如处理MQ请求</font></font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private Integer <b>controlBehavior</b>;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private Integer warmUpPeriodSec;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private Integer maxQueueingTimeMs;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private boolean clusterMode;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private ClusterFlowConfig clusterConfig;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private Date gmtCreate;</font></p><p style="margin: 0px 0px 0px 4px; font-size: 10px;"><font style="font-size: 10px;">private Date gmtModified;</font></p><hr style="font-size: 11px;" 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="-400" y="120" width="360" height="480" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-52" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-49" target="S1kR7U3J-qD7APwjgyKx-51" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-49" value="各字段校验" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="960" y="200" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-54" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-51" target="S1kR7U3J-qD7APwjgyKx-53" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-51" value="entity = repository.<b>save</b>(entity);<br><font color="#007fff"><b>先保存到内存</b>,repository是InMemoryRuleRepositoryAdapter类型,是内存存储服务的适配器</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="960" y="280" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-56" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-53" target="S1kR7U3J-qD7APwjgyKx-55" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-53" value="<b>publishRules</b>(entity.getApp(), entity.getIp(), entity.getPort()).get(5000, TimeUnit.MILLISECONDS);" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="960" y="360" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-59" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;strokeColor=#000000;" parent="1" source="S1kR7U3J-qD7APwjgyKx-55" target="S1kR7U3J-qD7APwjgyKx-58" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-75" value="<font color="#007fff">从控制台请求到<br>Sentinel客户端,<br>即业务服务</font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="S1kR7U3J-qD7APwjgyKx-59" vertex="1" connectable="0">
<mxGeometry x="-0.0167" y="2" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-55" value="先查找指定Sentinel客户端机器上所有流控规则,然后通过 sentinelApiClient<br>.setFlowRuleOfMachineAsync(...) 异步请求 http://ip:port(8719)/<b>setRules</b>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="1200" y="350" width="200" height="80" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-57" value="<div><font color="#007fff">id = {Long@9265} 4</font></div><div><font color="#007fff">app = "demo-provider"</font></div><div><font color="#007fff">ip = "192.168.124.8"</font></div><div><font color="#007fff">port = {Integer@9268} <b>8719</b></font></div><div><font color="#007fff">limitApp = "default"</font></div><div><font color="#007fff">resource = "sentinel_default_context"</font></div><div><font color="#007fff">grade = {Integer@9271} 1</font></div><div><font color="#007fff">count = {Double@9272} 1.0</font></div><div><font color="#007fff">strategy = {Integer@9273} 0</font></div><div><font color="#007fff">refResource = null</font></div><div><font color="#007fff">controlBehavior = {Integer@9273} 0</font></div><div><font color="#007fff">warmUpPeriodSec = null</font></div><div><font color="#007fff">maxQueueingTimeMs = null</font></div><div><font color="#007fff">clusterMode = false</font></div><div><font color="#007fff">clusterConfig = {ClusterFlowConfig@9274}&nbsp;</font></div><div><font color="#007fff">gmtCreate = {Date@9256} "Mon Apr 01 18:37:04 CST 2024"</font></div><div><font color="#007fff">gmtModified = {Date@9256} "Mon Apr 01 18:37:04 CST 2024"</font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="-760" y="120" width="360" height="260" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-61" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-58" target="S1kR7U3J-qD7APwjgyKx-60" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1740" y="390" />
<mxPoint x="1740" y="230" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-86" 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="S1kR7U3J-qD7APwjgyKx-58" target="S1kR7U3J-qD7APwjgyKx-85" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-58" value="<b>ModifyRulesCommandHandler</b>#<br>handle(CommandRequest request)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1520" y="360" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-64" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-60" target="S1kR7U3J-qD7APwjgyKx-63" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-60" value="FLOW_RULE_TYPE <br>(flow)<br><font color="#007fff">流控规则</font>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="1760" y="200" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-66" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-63" target="S1kR7U3J-qD7APwjgyKx-65" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-63" value="List&lt;FlowRule&gt; flowRules = JSONArray.parseArray(data, FlowRule.class);" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="2000" y="200" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-68" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-65" target="S1kR7U3J-qD7APwjgyKx-67" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-70" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-65" target="S1kR7U3J-qD7APwjgyKx-69" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-65" value="<b>FlowRuleManager</b>.<b>loadRules</b>(<br>flowRules);" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="2000" y="280" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-72" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-67" target="S1kR7U3J-qD7APwjgyKx-71" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-67" value="writeToDataSource(<br>getFlowDataSource(), flowRules)" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="2000" y="360" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-78" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-69" target="S1kR7U3J-qD7APwjgyKx-77" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-69" value="<b>currentProperty</b>.updateValue(rules);<br>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="2240" y="280" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-71" value="dataSource.write(value);<br><font color="#007fff">可写的数据源只有FileWritableDataSource,只有配置使用文件作为数据源才会执行这个方法</font>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="2240" y="360" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-73" value="<font color="#007fff">这里操作的是流控规则,<br>repository实际是&nbsp;<b>InMemFlowRuleStore</b></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1170" y="290" width="240" height="40" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-74" value="<b>sentinel-transport-common</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1530" y="320" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-76" value="<font style="font-size: 10px;" color="#007fff">请求参数包括两部分:<br style="font-size: 10px;">"<b>type</b>": "flow"<br style="font-size: 10px;">"<b>data</b>":&nbsp;[</font><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; {</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; "clusterConfig": {</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; "acquireRefuseStrategy": 0,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; "clientOfflineTime": 2000,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; "fallbackToLocalWhenFail": true,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; "resourceTimeout": 2000,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; "resourceTimeoutStrategy": 0,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; "sampleCount": 10,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; "strategy": 0,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; "thresholdType": 0,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; "windowIntervalMs": 1000</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; },</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; "clusterMode": false,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; "controlBehavior": 0,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; "count": 1.0,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; "grade": 1,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; "limitApp": "default",</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; "maxQueueingTimeMs": 500,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; "resource": "/demo/echo",</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; "strategy": 0,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; "warmUpPeriodSec": 10</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; }</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">]</font></div>" 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="1410" y="20" width="180" height="330" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-81" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-77" target="S1kR7U3J-qD7APwjgyKx-80" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-77" value="<b>value = newValue;</b><br><font style="" color="#007fff">更新内存中的规则</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2481" y="280" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-83" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-80" target="S1kR7U3J-qD7APwjgyKx-82" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-80" value="<div>for (PropertyListener&lt;T&gt; listener : listeners) {</div><div>&nbsp; listener.<b>configUpdate</b>(newValue);</div><div><span style="background-color: initial;">}</span></div><div><font style="" color="#007fff"><font style="font-size: 10px;">遍历所有FlowPropertyListener,回调更新规</font><span style="font-size: 11px;">则 比如Rules</span></font></div>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;arcSize=8;" parent="1" vertex="1">
<mxGeometry x="2481" y="360" width="200" height="80" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-82" value="<div>更新 <b>FlowRuleManager</b> <b>flowRules</b>;&nbsp;<br></div>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;arcSize=15;" parent="1" vertex="1">
<mxGeometry x="2720" y="370" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-84" value="<font color="#cc0000">!!!从后面的流程可以看到 Sentinel 控制台默认并不支持将规则写入配置中心,<br>所以测试时可以发现控制台配置好规则后,去配置中心根本看不到配置的规则<br>如果想要支持,可以去修改控制台源码<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1760" y="140" width="460" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-151" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-85" target="S1kR7U3J-qD7APwjgyKx-150" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-85" value="DEGRADE_RULE_TYPE (degrade<span style="background-color: initial;">)</span><br><font color="#007fff">熔断规则</font>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="1760" y="440" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-87" value="主要研究:<br style="font-size: 11px;"><ol style="font-size: 11px;"><li style="font-size: 11px;">基于配置中心的规则的管理:持久化,推送、拉取规则到各规则管理器的原理;<br style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">都是基于配置中心本身的能力,Sentinel客户端启动时会主动拉取一次规则配置、同时注册规则配置监听器;<br style="font-size: 11px;">配置中心有修改规则配置会回调监听器,最终配置会更新到各个客户端本地各种规则管理器。</font></li><li style="font-size: 11px;">规则校验是怎么嵌入到请求处理流程中的;<br style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">两种方式<br style="font-size: 11px;">1)通过定义一个拦截器实现(实现HandlerInterceptor接口),规则校验逻辑全部在 <br style="font-size: 11px;">SentinelWebInterceptor、SentinelWebTotalInterceptor 中执行;<br style="font-size: 11px;">2)通过Spring AOP 切面实现。</font></li><li style="font-size: 11px;">流控、限流、黑白名单、热点数据等规则的校验流程实现原理。<br style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">通过一组ProcessorSlot实现。</font></li></ol>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="560" y="5" width="590" height="180" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-101" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-97" target="S1kR7U3J-qD7APwjgyKx-100" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-97" value="ExecutorService pool = new ThreadPoolExecutor(...)<br><font color="#007fff" style="font-size: 10px;">创建线程池 sentinel-nacos-ds-update<br>用于执行监听器回调<br></font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1680" y="620" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-103" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-100" target="S1kR7U3J-qD7APwjgyKx-102" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-105" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-100" target="S1kR7U3J-qD7APwjgyKx-104" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-100" value="this.configListener = new Listener() {...}" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1680" y="700" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-113" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-102" target="S1kR7U3J-qD7APwjgyKx-112" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-102" value="<font style="font-size: 12px;"><b style="">receiveConfigInfo</b>(<br style="">final String configInfo)</font><br style="font-size: 11px;"><font color="#007fff" style="font-size: 10px;"><b style="">配置变更NacosServer会回调此方法<br style="">更新 DynamicSentinelProperty value值<br style="font-size: 11px;"></b></font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="1920" y="700" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-107" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-104" target="S1kR7U3J-qD7APwjgyKx-106" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-109" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-104" target="S1kR7U3J-qD7APwjgyKx-108" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-104" value="initNacosListener();<br><font color="#007fff">初始化Nacos配置监听器<br>Push模式实现<br></font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1680" y="780" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-139" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-106" target="S1kR7U3J-qD7APwjgyKx-138" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-106" value="loadInitialConfig();<br><font color="#007fff">数据源启动时主动拉取一次规则配置<br>pull模式实现</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1680" y="940" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-111" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-108" target="S1kR7U3J-qD7APwjgyKx-110" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-108" value="this.configService = NacosFactory.createConfigService(<br>this.properties);<br><font color="#007fff">本质是创建了NacosClient 客户端</font>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="1920" y="780" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-110" value="configService.<b>addListener</b>(dataId, groupId, configListener);<br><font color="#007fff" style="font-size: 10px;">通过 NacosClient 向配置中心注册配置监听器,监听groupId分组、dataId配置集</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="1920" y="860" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-116" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-112" target="S1kR7U3J-qD7APwjgyKx-115" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-112" value="T newValue = NacosDataSource.this<br>.<b>parser</b>.convert(configInfo);<br><font color="#007fff">转成 ArrayList&lt;FlowRule&gt;</font>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="2160" y="700" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-119" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-115" target="S1kR7U3J-qD7APwjgyKx-118" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-115" value="<b>getProperty</b>().updateValue(<br>newValue);" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="2160" y="780" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-128" style="rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-117" target="S1kR7U3J-qD7APwjgyKx-123" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-117" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>AbstractDataSource</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><span style="background-color: initial;">protected final Converter&lt;S, T&gt; parser;</span><br></p><p style="margin:0px;margin-left:4px;">protected final SentinelProperty&lt;T&gt; <b>property</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="-400" y="640" width="360" height="80" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-125" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-118" target="S1kR7U3J-qD7APwjgyKx-124" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-131" 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="S1kR7U3J-qD7APwjgyKx-118" target="S1kR7U3J-qD7APwjgyKx-130" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="2610" y="810" />
<mxPoint x="2610" y="900" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-118" value="<div>for (PropertyListener&lt;T&gt; listener : listeners) {</div><div>&nbsp; listener.<b>configUpdate</b>(newValue);</div><div>}</div><div><font color="#007fff" style="font-size: 10px;">这里的PropertyListener是各个规则管理器内部定义的属性监听器</font></div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=12;" parent="1" vertex="1">
<mxGeometry x="2400" y="765" width="200" height="90" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-121" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endArrow=block;endFill=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-120" target="S1kR7U3J-qD7APwjgyKx-117" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-120" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>NacosDataSource</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">规则的Nacos数据源</font></p><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;">private static final int DEFAULT_TIMEOUT = 3000;</p><p style="margin:0px;margin-left:4px;">private final ExecutorService <b>pool</b> = new ThreadPoolExecutor(...);</p><p style="margin:0px;margin-left:4px;">private final Listener <b>configListener</b>;</p><p style="margin:0px;margin-left:4px;">private final String <b>groupId</b>;</p><p style="margin:0px;margin-left:4px;">private final String <b>dataId</b>;</p><p style="margin:0px;margin-left:4px;">private final Properties <b>properties</b>;</p><p style="margin:0px;margin-left:4px;">private ConfigService <b>configService</b> = null;</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=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="-400" y="760" width="360" height="200" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-122" value="DynamicSentinelProperty" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2420" y="740" width="160" height="30" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-123" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>DynamicSentinelProperty</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">//属性监听器</font></p><p style="margin:0px;margin-left:4px;">protected Set&lt;PropertyListener&lt;T&gt;&gt; <b>listeners</b> = Collections.synchronizedSet(</p><p style="margin:0px;margin-left:4px;"><span style="white-space: pre;">	</span>new HashSet&lt;PropertyListener&lt;T&gt;&gt;());</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//规则列表</font></p><p style="margin:0px;margin-left:4px;"><span style="background-color: initial;">private T <b>value</b> = null;</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;" parent="1" vertex="1">
<mxGeometry x="-880" y="640" width="440" height="120" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-124" value="Map&lt;String, List&lt;FlowRule&gt;&gt; rules = FlowRuleUtil.buildFlowRuleMap(value);<br>flowRules.clear();<br><b>flowRules</b>.putAll(rules);" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=12;fillColor=#ffcc99;strokeColor=#36393d;" parent="1" vertex="1">
<mxGeometry x="2630" y="780" width="220" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-126" value="<b>FlowRuleManager</b>$FlowPropertyListener" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2615" y="750" width="250" height="30" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-127" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>FlowRuleManager</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">//流控规则</font></p><p style="margin:0px;margin-left:4px;">private static final Map&lt;String, List&lt;FlowRule&gt;&gt; <b>flowRules</b> = new <span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>ConcurrentHashMap&lt;String, List&lt;FlowRule&gt;&gt;();</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//Push模式,监听回调</font></p><p style="margin:0px;margin-left:4px;">private static final FlowPropertyListener <b>LISTENER</b> = new FlowPropertyListener();</p><p style="margin:0px;margin-left:4px;">private static SentinelProperty&lt;List&lt;FlowRule&gt;&gt; <b>currentProperty</b> = new <span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>DynamicSentinelProperty&lt;List&lt;FlowRule&gt;&gt;();</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//定时任务线程池,处理 MetricTimerListener</font></p><p style="margin:0px;margin-left:4px;">private static final ScheduledExecutorService <b>SCHEDULER</b> = <span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>Executors.newScheduledThreadPool(</p><p style="margin:0px;margin-left:4px;"><span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>1,&nbsp;<span style="background-color: initial;">new NamedThreadFactory("sentinel-metrics-record-task", true));</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=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="-1400" y="640" width="480" height="260" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-31" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="S1kR7U3J-qD7APwjgyKx-130" target="3PC2WQgvGjgkUnSvGf-g-29" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="3700" y="900" />
<mxPoint x="3700" y="2840" />
</Array>
<mxPoint x="2610.000000000002" y="1230.0000000000005" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-130" value="<font style="font-size: 11px;">其他 RuleManager PropertyListener<br>更新规则列表,如&nbsp;<b>DegradeRuleManager</b>、<b>AuthorityRuleManager</b>,和 FlowRuleManager 处理基本相同</font>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=12;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2630" y="860" width="220" height="80" as="geometry" />
</mxCell>
<mxCell id="upGvQ8i2CHYi3lYlOZoj-2" 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="S1kR7U3J-qD7APwjgyKx-132" target="upGvQ8i2CHYi3lYlOZoj-1" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="upGvQ8i2CHYi3lYlOZoj-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-132" target="upGvQ8i2CHYi3lYlOZoj-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-132" value="<span style="border-color: var(--border-color); font-size: 11px;"><font style="font-size: 11px;"><b style="font-size: 11px;">SentinelDataSourceHandler</b> 实现 SmartInitializingSingleton接口在<b>afterSingletonsInstantiated</b>() 方法中又通过DefaultListableBeanFactory的方法根据数据源定义属性注册了Sentinel数据源Bean</font></span>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="960" y="610" width="200" height="80" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-137" 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="S1kR7U3J-qD7APwjgyKx-134" target="S1kR7U3J-qD7APwjgyKx-97" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-140" 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="S1kR7U3J-qD7APwjgyKx-138" target="S1kR7U3J-qD7APwjgyKx-118" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="2380" y="970" />
<mxPoint x="2380" y="810" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-138" value="T newValue = loadConfig();<br style="font-size: 11px;">getProperty().updateValue(newValue);<br><font color="#007fff">先从NacosDataSource.configSevice主动拉取规则配置,然后通过parser转成规则对象列表</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="1920" y="940" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-148" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-141" target="S1kR7U3J-qD7APwjgyKx-147" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-141" value="依旧是先经过 Tomcat 的一系列组件(最后是ApplictionFilterChain)、然后经过ApplictionFilterChain中SpringMVC的一些过滤器,再是HttpServlet -&gt; DispatcherServlet -&gt; 然后是走到&nbsp;<b style="font-size: 11px;">SentinelWebInterceptor</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;arcSize=10;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="240" y="1470" width="200" height="80" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-155" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-147" target="S1kR7U3J-qD7APwjgyKx-154" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="JXVrsIax2Fh7985Lvlhv-41" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-147" target="JXVrsIax2Fh7985Lvlhv-39" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-147" value="<b>SentinelWebInterceptor<br>#preHandle(...)</b><br><font style="font-size: 10px;" color="#007fff">由DispatcherServlet$<b>applyPreHandle</b>()<br>方法发起调用</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="480" y="1480" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-150" value="<font color="#007fff">后续处理和流控规则基本相同</font>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="2000" y="440" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-153" value="<font color="#007fff">这部分详细参考 SpringMVC<br>源码工作流程图</font>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="255" y="1550" width="170" height="40" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-159" 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="S1kR7U3J-qD7APwjgyKx-154" target="S1kR7U3J-qD7APwjgyKx-158" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-160" value="3" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="S1kR7U3J-qD7APwjgyKx-159" vertex="1" connectable="0">
<mxGeometry x="0.0702" y="3" relative="1" as="geometry">
<mxPoint x="13" y="-50" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-162" 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="S1kR7U3J-qD7APwjgyKx-154" target="S1kR7U3J-qD7APwjgyKx-161" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-163" value="4" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="S1kR7U3J-qD7APwjgyKx-162" vertex="1" connectable="0">
<mxGeometry x="0.4289" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-165" 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="S1kR7U3J-qD7APwjgyKx-154" target="S1kR7U3J-qD7APwjgyKx-164" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-166" value="6" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="S1kR7U3J-qD7APwjgyKx-165" vertex="1" connectable="0">
<mxGeometry x="0.8056" y="-3" relative="1" as="geometry">
<mxPoint x="3" y="39" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-154" value="<div style="font-size: 11px;">public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {</div><div style="font-size: 11px;">&nbsp; try {</div><div style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;"><b>&nbsp; &nbsp; &nbsp; //1 先获取请求路由作为流控等目标资源,比如 /demo/echo、GET:/demo/echo</b></font></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; String resourceName = this.<b style="font-size: 11px;">getResourceName</b>(request);</div><div style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">&nbsp; &nbsp; &nbsp; //2 为空不校验规则</font></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; if (StringUtil.isEmpty(resourceName)) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;</div><div style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">&nbsp; &nbsp; &nbsp; //3 非空先在<b style="font-size: 11px;">请求属性</b>中记录调用次数(+1)</font></div><div style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">&nbsp; &nbsp; &nbsp; //&nbsp; &nbsp; 首次统计也不需要校验规则</font></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; } else if (this.<b style="font-size: 11px;">increaseReferece</b>(request, this.baseWebMvcConfig.getRequestRefName(), 1) != 1) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;</div><div style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">&nbsp; &nbsp; &nbsp; //4 非首次统计需要校验规则</font></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; } else {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String origin = this.parseOrigin(request);&nbsp;<font color="#007fff" style="font-size: 11px;">//解析来源应用,默认为""</font></div><div style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;"><span style="font-size: 11px;"><span style="font-size: 11px;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>&nbsp; <span style="font-size: 11px;"><span style="white-space: pre; font-size: 11px;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>//如果SentinelWebMvcConfig.webContextUnify==true(默认为true), 使用&nbsp;<br style="font-size: 11px;"></font></div><div style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;"><span style="font-size: 11px;"><span style="white-space: pre; font-size: 11px;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>&nbsp; &nbsp; &nbsp; //“sentinel_spring_web_context</font><font color="#007fff" style="font-size: 11px;">” 作为统一的上下文名称,</font></div><div style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //否则使用资源名称作为上下文名称(这种情况需要小心上下文数量超出阈值)<br style="font-size: 11px;"></font></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String contextName = this.<b>getContextName</b>(request);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ContextUtil.<b style="font-size: 11px;">enter</b>(contextName, origin); <font color="#007fff" style="font-size: 11px;">//使用ThreadLocal存储</font></div><div style="font-size: 11px;"><b>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Entry entry = SphU.<span style="font-size: 11px;">entry</span>(resourceName, 1, EntryType.IN);</b></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; request.<b style="font-size: 11px;">setAttribute</b>(this.baseWebMvcConfig.getRequestAttributeName(), entry);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">&nbsp; //5 规则校验失败会抛出BlockException</font></div><div style="font-size: 11px;">&nbsp; } catch (BlockException var12) {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; BlockException e = var12;</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; try {</div><div style="font-size: 11px;"><font color="#007fff" style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //6 处理规则检查异常</font></div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.<b style="font-size: 11px;">handleBlockException</b>(request, response, e);</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; } finally {</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ContextUtil.exit();</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; }</div><div style="font-size: 11px;">&nbsp; &nbsp; &nbsp; return false;</div><div style="font-size: 11px;">&nbsp; }</div><div style="font-size: 11px;">}</div>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;arcSize=3;align=left;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="720" y="1250" width="440" height="520" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-156" value="<b>SentinelWebTotalInterceptor</b><br><font color="#007fff"><span style="font-size: 10px;">Sentinel源码中还定义了这个拦截器,不过starter中默认并没有注入,先略</span></font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="480" y="1890" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="R8YPJ6jMD8Vm_6NY_bdp-84" style="edgeStyle=orthogonalEdgeStyle;rounded=0;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=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-157" target="R8YPJ6jMD8Vm_6NY_bdp-83" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-157" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>FlowRule</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">流控规则实体定义。</font></p><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//流控类型:0:线程数、1:QPS<br></font></p><p style="margin:0px;margin-left:4px;">private int <b>grade</b> = 1;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//流控阈值</font></p><p style="margin:0px;margin-left:4px;">private double <b>count</b>;、</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//流控模式</font></p><p style="margin:0px;margin-left:4px;">private int <b>strategy</b> = 0;</p><p style="margin:0px;margin-left:4px;">private String <b>refResource</b>;</p><p style="margin:0px;margin-left:4px;">private int <b>controlBehavior</b> = 0;</p><p style="margin:0px;margin-left:4px;">private int <b>warmUpPeriodSec</b> = 10;</p><p style="margin:0px;margin-left:4px;">private int <b>maxQueueingTimeMs</b> = 500;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//是否是集群模式,集群模式和本地模式流控校验方式不同</font></p><p style="margin:0px;margin-left:4px;">private boolean <b>clusterMode</b>;</p><p style="margin:0px;margin-left:4px;">private ClusterFlowConfig clusterConfig;</p><p style="margin:0px;margin-left:4px;">private TrafficShapingController controller;</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="-1280" y="320" width="360" height="280" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-168" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-158" target="S1kR7U3J-qD7APwjgyKx-167" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-158" value="<b>increaseReferece</b>(request, this.baseWebMvcConfig<br>.getRequestRefName(), 1)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1200" y="1370" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-171" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-161" target="S1kR7U3J-qD7APwjgyKx-170" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-161" value="SphU.<b>entry</b>(resourceName, 1, EntryType.IN);<br><font color="#007fff">记录统计并执行规则校验</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1200" y="1480" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="JXVrsIax2Fh7985Lvlhv-4" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-164" target="JXVrsIax2Fh7985Lvlhv-3" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-164" value="<b>handleBlockException</b>(<br>request, response, e);<br><font color="#007fff">规则校验失败会抛出 BlockException</font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1200" y="2050" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-167" value="通过请求属性<b>$$sentinel_spring_web_entry_attr-rc</b>记录调用次数<br>request.<b>setAttribute</b>(rcKey, newRc);" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="1440" y="1370" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-169" value="<font color="#007fff">这里并不是最终统计接口调用次数的地方<br>后面应该还有地方取 $$sentinel_spring_web_entry_attr-rc<br>&nbsp;这个属性值做汇总</font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1650" y="1370" width="330" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-179" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-170" target="S1kR7U3J-qD7APwjgyKx-178" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-170" value="Env.<b>sph</b>.entryWithType(name, resourceType, trafficType, 1, OBJECTS0);" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="1440" y="1480" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-172" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>SphU</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//</font></p><p style="margin:0px;margin-left:4px;">private static final Object[] OBJECTS0 = new Object[0];<br></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="-400" y="1720" width="360" height="120" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-36" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-173" target="S1kR7U3J-qD7APwjgyKx-174" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-173" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Env</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//</font></p><p style="margin:0px;margin-left:4px;">public static final <b>Sph</b> <b>sph</b> = new CtSph();<br></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="-800" y="1720" width="360" height="120" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-174" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Sph </b>extends&nbsp;<span style="background-color: initial;">SphResourceTypeSupport (I)</span></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">用于记录统计信息和执行资源规则检查的基本接口。<br></font></p><p style="margin:0px;margin-left:4px;"><br></p><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="-1200" y="1720" width="360" height="120" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-176" 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=0;dashed=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-177" target="S1kR7U3J-qD7APwjgyKx-174" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="-1020" y="1880" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-35" style="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;endArrow=classic;endFill=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-177" target="7B76-LEGkQ0qvEv1oR-M-30" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-177" value="<p style="margin: 4px 0px 0px; text-align: center; font-size: 11px;"><b style="font-size: 11px;">CtSph</b><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><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 static final Object[] <b style="font-size: 11px;">OBJECTS0</b> = new Object[0];</p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><font color="#007fff" style="font-size: 11px;">//资源 -&gt; Processor</font><font color="#007fff" style="font-size: 11px;">SlotChain</font></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;">private static volatile Map&lt;<b style="font-size: 11px;">ResourceWrapper</b>, <b style="font-size: 11px;">ProcessorSlotChain</b>&gt; <b style="font-size: 11px;">chainMap</b> = <span style="font-size: 11px;">&nbsp;&nbsp;&nbsp;&nbsp;</span>new HashMap&lt;ResourceWrapper, ProcessorSlotChain&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=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="-1240" y="1880" width="440" height="160" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-181" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-178" target="S1kR7U3J-qD7APwjgyKx-180" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-178" value="StringResourceWrapper resource = new StringResourceWrapper(name, entryType, resourceType);" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="1680" y="1480" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-183" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="S1kR7U3J-qD7APwjgyKx-180" target="S1kR7U3J-qD7APwjgyKx-182" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-180" value="return <b>entryWithPriority</b>(resource, count, prioritized, args);" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="1680" y="1560" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-21" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-182" target="7B76-LEGkQ0qvEv1oR-M-20" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-22" value="3" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="7B76-LEGkQ0qvEv1oR-M-21" vertex="1" connectable="0">
<mxGeometry x="0.7931" y="-3" relative="1" as="geometry">
<mxPoint x="5" y="-3" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-75" 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="S1kR7U3J-qD7APwjgyKx-182" target="7B76-LEGkQ0qvEv1oR-M-74" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-76" value="4" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="7B76-LEGkQ0qvEv1oR-M-75" vertex="1" connectable="0">
<mxGeometry x="0.9254" y="3" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-182" value="<div></div><font color="#007fff"><b>//获取前面ContextUtil.enter(contextName, origin)保存的上下文</b></font><div>Context <b>context</b> = ContextUtil.getContext();</div><div>if (context instanceof NullContext) {&nbsp;<font color="#007fff">// 表明上下文数量超过了阈值(默认2000)</font></div><div><span style="color: rgb(0, 127, 255); background-color: initial;">&nbsp; &nbsp; //所以只会初始化Entry, 不会校验规则</span><br></div><div>&nbsp; &nbsp; return new CtEntry(resourceWrapper, null, context);</div><div>}</div><div>if (context == null) {<span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><font color="#007fff">//默认情况下不可能为null</font></div><div><span style="background-color: initial;">&nbsp; &nbsp; context = InternalContextUtil.internalEnter(Constants.CONTEXT_DEFAULT_NAME);</span><br></div><div>}</div><div><font color="#007fff">//Sentinel全局开关关闭,不需要校验规则</font></div><div>if (!Constants.ON) {</div><div>&nbsp; &nbsp; return new CtEntry(resourceWrapper, null, context);</div><div>}</div><div><br></div><font color="#007fff">//1 查找资源对应的ProcessorSlotChain, 不存在则创建 chain = SlotChainProvider.newSlotChain();<br>//&nbsp; &nbsp;ProcessorSlotChain 内部是链表(责任链模式)<br></font><div>ProcessorSlot&lt;Object&gt; chain = <b>lookProcessChain</b>(resourceWrapper);</div><div><span style="background-color: initial;">if (chain == null) {</span><span style="background-color: initial;"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><font style="background-color: initial;" color="#007fff">//表明资源数量(对应 slot chain size)超出&nbsp;Constants.MAX_SLOT_CHAIN_SIZE</font></div>&nbsp; &nbsp; <font color="#007fff">//所以只会初始化Entry, 不会校验规则</font><div>&nbsp; &nbsp; return new CtEntry(resourceWrapper, null, context);</div><div>}</div><div><font color="#007fff">//2</font>&nbsp;</div><div>Entry e = new <b>CtEntry</b>(resourceWrapper, chain, context);</div><div>try {</div><div>&nbsp; &nbsp; <font color="#007fff">//3</font></div><div>&nbsp; &nbsp; chain.<b>entry</b>(context, resourceWrapper, null, count, prioritized, args);</div><div>} catch (BlockException e1) {</div><div><b><font color="#007fff">&nbsp; &nbsp; //4&nbsp;这里是规则校验失败后退出,校验成功的话是在&nbsp;<span style="text-align: center; background-color: initial; border-color: var(--border-color);">SentinelWebInterceptor</span><span style="text-align: center; background-color: initial; border-color: var(--border-color);">#afterCompletion() 中调用 exit() 的</span></font></b></div><div>&nbsp; &nbsp; e.<b>exit</b>(count, args);</div><div>&nbsp; &nbsp; throw e1;</div><div>} catch (Throwable e1) {</div><div>&nbsp; &nbsp; // This should not happen, unless there are errors existing in Sentinel internal.</div><div>&nbsp; &nbsp; RecordLog.info("Sentinel unexpected exception", e1);</div><div>}</div><div>return e;</div>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=1;" parent="1" vertex="1">
<mxGeometry x="1920" y="1480" width="560" height="530" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-184" value="<b>CtSph</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="1750" y="1450" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-185" value="<div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">当前测试设置的流控规则( QPS、根据调用方限流、直接失败)</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">[</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; {</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; "resource": "/demo/echo",</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; "limitApp": "default",</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; "grade": 1,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; "count": 5,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; "strategy": 0,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; "controlBehavior": 0,</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; &nbsp; &nbsp; "clusterMode": false</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">&nbsp; &nbsp; }</font></div><div style="font-size: 10px;"><font style="font-size: 10px;" color="#007fff">]</font></div>" 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="240" y="1290" width="290" height="160" as="geometry" />
</mxCell>
<mxCell id="gmwCS7IYYuH75fHtpYmN-1" style="rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-186" target="S1kR7U3J-qD7APwjgyKx-187" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-186" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>ContextUtil</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;"><font color="#007fff"><br></font></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//保存请求调用上下文(该上下文标记为调用链的入口</font><font color="#007fff">)</font></p><p style="margin:0px;margin-left:4px;">private static ThreadLocal&lt;Context&gt; <b>contextHolder</b> = new ThreadLocal&lt;&gt;();</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//保存所有上下文入口节点,contextName -&gt; EntranceNode</font></p><p style="margin:0px;margin-left:4px;">private static volatile Map&lt;String, DefaultNode&gt; <b>contextNameNodeMap</b> =&nbsp;</p><p style="margin:0px;margin-left:4px;"><span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>new HashMap&lt;&gt;();</p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">//默认创建名为 sentinel_default_context 的上下文</font></p><p style="margin:0px;margin-left:4px;">private static void initDefaultContext()<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="-480" y="1120" width="440" height="200" as="geometry" />
</mxCell>
<mxCell id="gmwCS7IYYuH75fHtpYmN-3" style="rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-187" target="gmwCS7IYYuH75fHtpYmN-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-90" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.893;entryDx=0;entryDy=0;entryPerimeter=0;endArrow=open;endFill=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-187" target="7B76-LEGkQ0qvEv1oR-M-9" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="S1kR7U3J-qD7APwjgyKx-187" value="<p style="margin: 4px 0px 0px; text-align: center;"><font style="font-size: 12px;"><b style="">Context</b><br></font></p><hr style="" size="1"><p style="margin: 0px 0px 0px 4px;"><font style="font-size: 12px;"><font style="font-size: 12px;" color="#007fff">请求调用上下文(该上下文标记为调用链的入口</font><font style="font-size: 12px;" color="#007fff">)</font></font></p><p style="margin: 0px 0px 0px 4px;"><font style="font-size: 12px;" color="#007fff"><br></font></p><p style="margin: 0px 0px 0px 4px;"><font style="font-size: 12px;" color="#007fff">//上下文名称, 比如 sentinel_spring_web_context (SpringWeb默认使用这个上下文名称)</font></p><p style="margin: 0px 0px 0px 4px;"><font style="font-size: 12px;">private final String <b>name</b>;</font></p><p style="margin: 0px 0px 0px 4px;"><font style="font-size: 11px;" color="#007fff">//当前调用树的 EntranceNode, 相当于调用上下文统计节点的<b>根节点</b></font></p><p style="margin: 0px 0px 0px 4px;"><font style="font-size: 12px;">private DefaultNode <b>entranceNode</b>;</font></p><p style="margin: 0px 0px 0px 4px;"><font style="font-size: 12px;" color="#007fff">//当前正在执行的Entry,Entry 通过parent child 实现<b>双向链表</b></font></p><p style="margin: 0px 0px 0px 4px;"><font style="font-size: 12px;">private Entry <b>curEntry</b>;</font></p><p style="margin: 0px 0px 0px 4px;"><font style="font-size: 12px;" color="#007fff">//当前调用上下文来源</font></p><p style="margin: 0px 0px 0px 4px;"><font style="font-size: 12px;">private String origin = "";</font></p><p style="margin: 0px 0px 0px 4px;"><font style="font-size: 12px;">private final boolean async;</font></p><hr style="" size="1"><p style="margin: 0px 0px 0px 4px;"><br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="-880" y="1120" width="360" height="220" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-7" 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;dashed=1;endArrow=block;endFill=0;" parent="1" source="gmwCS7IYYuH75fHtpYmN-2" target="7B76-LEGkQ0qvEv1oR-M-6" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="R8YPJ6jMD8Vm_6NY_bdp-25" 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="gmwCS7IYYuH75fHtpYmN-2" target="R8YPJ6jMD8Vm_6NY_bdp-18" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="-1420" y="1230" />
<mxPoint x="-1420" y="1100" />
<mxPoint x="-1840" y="1100" />
<mxPoint x="-1840" y="1260" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="gmwCS7IYYuH75fHtpYmN-2" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>StatisticNode</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">调用树的统计节点,很重要的类,全靠它统计数据,这里<b>创建了2个滑动窗口</b></font></p><p style="margin:0px;margin-left:4px;"><font color="#007fff"><br></font></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//此滑动窗口存储<b>最近 INTERVAL 毫秒的统计数据</b>。默认窗口时间跨度1s分成两个桶</font></p><p style="margin:0px;margin-left:4px;">private transient volatile Metric <b>rollingCounterInSecond</b> = new <b>ArrayMetric</b>(SampleCountProperty.SAMPLE_COUNT, IntervalProperty.INTERVAL);</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//此滑动窗口存储<b>最近 60 秒的统计数据</b>。</font><span style="background-color: initial;"><font color="#007fff">默认窗口时间跨度60s分成60个桶</font></span></p><p style="margin:0px;margin-left:4px;">private transient Metric <b>rollingCounterInMinute</b> = new ArrayMetric(60, 60 * 1000, false);</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//<b>线程计数器(即正在处理的资源线程数),</b>进入统计时+1,退出时-1,也即正在处理资源请求数量</font></p><p style="margin:0px;margin-left:4px;">private LongAdder <b>curThreadNum</b> = new LongAdder();</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//上次获取统计数据的时间戳</font></p><p style="margin:0px;margin-left:4px;"><font color="#007fff"></font></p><p style="margin:0px;margin-left:4px;">private long <b>lastFetchTime</b> = -1;</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="-1400" y="1120" width="480" height="220" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-1" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Constants.ROOT</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">全局的根统计节点,是EntranceNode类型</font></p><p style="margin:0px;margin-left:4px;"><font color="#007fff"><br></font></p><br><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">//默认创建名为 sentinel_default_context 的上下文</font></p><p style="margin:0px;margin-left:4px;">private static void initDefaultContext()<br></p>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="-480" y="1360" width="440" height="160" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-3" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endArrow=block;endFill=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-2" target="gmwCS7IYYuH75fHtpYmN-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="efD_JUAdZYZt2iUUUV3x-56" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;endArrow=open;endFill=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-2" target="7B76-LEGkQ0qvEv1oR-M-83" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-2" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>DefaultNode</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><span style="color: rgb(0, 127, 255); background-color: initial;">//节点统计的资源目标(SpringWeb就是对应的Web路由)</span><br></p><p style="margin:0px;margin-left:4px;">private ResourceWrapper <b>id</b>;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//所有子节点的列表,子节点是当前上下文下所有资源的统计节点</font></p><p style="margin:0px;margin-left:4px;">private volatile Set&lt;Node&gt; <b>childList</b> = new HashSet&lt;&gt;();</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//相关的集群访问统计节点,每个DefaultNode都有一个对应的ClusterNode</font></p><p style="margin:0px;margin-left:4px;"><font color="#007fff"></font></p><p style="margin:0px;margin-left:4px;">private ClusterNode <b>clusterNode</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="-1340" y="1380" width="360" height="180" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-5" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;endArrow=block;endFill=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-4" target="7B76-LEGkQ0qvEv1oR-M-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-4" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>EntranceNode</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">代表调用树的入口节点<br></font></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="-1340" y="1600" width="360" height="80" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-6" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Node(I)&nbsp;</b>extends OccupySupport, DebugSupport<br></p><hr size="1"><p style="margin:0px;margin-left:4px;"></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">保存资源的实时统计信息</font><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="-1340" y="1000" width="360" height="80" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-9" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Entry</b></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">保存当前调用的信息。</font></p><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;">private static final Object[] OBJECTS0 = new Object[0];</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//此条目的创建时间,用于 rt 统计。</font></p><p style="margin:0px;margin-left:4px;">private final long createTimestamp;</p><p style="margin:0px;margin-left:4px;">private long completeTimestamp;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//当前上下文中资源的统计信息</font></p><p style="margin:0px;margin-left:4px;">private Node <b>curNode</b>;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//来源app的统计信息</font></p><p style="margin:0px;margin-left:4px;">private Node <b>originNode</b>;</p><p style="margin:0px;margin-left:4px;">private Throwable error;</p><p style="margin:0px;margin-left:4px;">private BlockException blockError;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//资源信息</font></p><p style="margin:0px;margin-left:4px;">protected final ResourceWrapper <b>resourceWrapper</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="-1800" y="1120" width="360" height="280" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-14" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-10" target="7B76-LEGkQ0qvEv1oR-M-13" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-10" value="<font style="font-size: 11px;">先从chainMap查找ProcessorSlotChain, 没有就在双重检查锁、CopyOnWrite保护下创建 chain = SlotChainProvider.<b>newSlotChain</b>();<br></font>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="2760" y="1480" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-17" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-13" target="7B76-LEGkQ0qvEv1oR-M-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-13" value="<font style="font-size: 11px;">先SPI加载SlotChainBuilder,没有的话使用默认的&nbsp;<b>DefaultSlotChainBuilder</b> 创建 ProcessorSlotChain<br><span style="font-size: 11px;">return <b>slotChainBuilder</b>.<b>build</b>();</span><br></font>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="3000" y="1480" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-15" value="<b>SlotChainProvider</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="3035" y="1450" width="130" height="30" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-16" value="<font style="font-size: 10px;"><div style="font-size: 10px;">public ProcessorSlotChain build() {</div><div style="font-size: 10px;">&nbsp; ProcessorSlotChain chain = new <b style="font-size: 10px;">DefaultProcessorSlotChain</b>();</div><div style="font-size: 10px;">&nbsp; List&lt;ProcessorSlot&gt; sortedSlotList = SpiLoader.of(<b>ProcessorSlot</b>.class).loadInstanceListSorted();</div><div style="font-size: 10px;">&nbsp; for (ProcessorSlot slot : sortedSlotList) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; if (!(slot instanceof AbstractLinkedProcessorSlot)) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RecordLog.warn(...);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue;</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; chain.<b>addLast</b>((AbstractLinkedProcessorSlot&lt;?&gt;) slot);</div><div style="font-size: 10px;">&nbsp; }</div><div style="font-size: 10px;">&nbsp; return chain;</div><div style="font-size: 10px;">}</div></font>" style="rounded=1;whiteSpace=wrap;html=1;align=left;arcSize=4;fontSize=10;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="3240" y="1425" width="320" height="170" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-18" value="<font color="#007fff"><b>ProcessorSlot SPI 文件中定义的 ProcessorSlot:<br style="font-size: 10px;"></b></font><div style="font-size: 10px;"><font color="#007fff">com.alibaba.csp.sentinel.slots.nodeselector.NodeSelectorSlot</font></div><div style="font-size: 10px;"><font color="#007fff">com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot</font></div><div style="font-size: 10px;"><font color="#007fff">com.alibaba.csp.sentinel.slots.logger.LogSlot</font></div><div style="font-size: 10px;"><font color="#007fff">com.alibaba.csp.sentinel.slots.statistic.StatisticSlot</font></div><div style="font-size: 10px;"><font color="#007fff">com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot</font></div><div style="font-size: 10px;"><font color="#007fff">com.alibaba.csp.sentinel.slots.system.SystemSlot</font></div><div style="font-size: 10px;"><font color="#007fff">com.alibaba.csp.sentinel.slots.block.flow.FlowSlot</font></div><div style="font-size: 10px;"><font color="#007fff">com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot</font></div>" 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="3240" y="1300" width="300" height="120" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-19" value="<div style="font-size: 10px;"><font color="#007fff"><b>最终创建的 SlotChain:</b></font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">chain = {<b>DefaultProcessorSlotChain</b>@12252}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp;first = {DefaultProcessorSlotChain$1@12251}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; this$0 = {DefaultProcessorSlotChain@12252}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; next = {<b>NodeSelectorSlot</b>@12250}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp;map = {HashMap@12432}&nbsp; size = 1</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp;next = {<b>ClusterBuilderSlot</b>@12249}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; clusterNode = {ClusterNode@12551}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; next = {<b>LogSlot</b>@12248}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; &nbsp;next = {<b>StatisticSlot</b>@12247}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; &nbsp; next = {<b>AuthoritySlot</b>@12246}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp;next = {<b>SystemSlot</b>@12242}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; next = {<b>ParamFlowSlot</b>@12241}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;next = {<b>FlowSlot</b>@12237}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checker = {FlowRuleChecker@12243}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ruleProvider = {FlowSlot$1@12244}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; next = {<b>DegradeSlot</b>@12245}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;next = null</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp;end = {<b>DegradeSlot</b>@12245}&nbsp;</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">&nbsp;next = null</font></div>" 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="3570" y="1345" width="240" height="250" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-29" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-20" target="7B76-LEGkQ0qvEv1oR-M-28" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-20" value="<font style="">chain.entry(context, resourceWrapper, null, count, prioritized, args);<br></font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="1650" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-24" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="S1kR7U3J-qD7APwjgyKx-182" target="7B76-LEGkQ0qvEv1oR-M-23" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="2480" y="1745" as="sourcePoint" />
<mxPoint x="2760" y="1510" as="targetPoint" />
<Array as="points">
<mxPoint x="2500" y="1745" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-27" value="1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="7B76-LEGkQ0qvEv1oR-M-24" vertex="1" connectable="0">
<mxGeometry x="0.8854" y="-2" relative="1" as="geometry">
<mxPoint x="6" y="-2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-26" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-23" target="7B76-LEGkQ0qvEv1oR-M-10" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-23" value="<font style=""><div>ProcessorSlot&lt;Object&gt; chain = lookProcessChain(resourceWrapper);</div></font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="1480" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-41" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-28" target="7B76-LEGkQ0qvEv1oR-M-40" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-43" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="7B76-LEGkQ0qvEv1oR-M-41" vertex="1" connectable="0">
<mxGeometry x="-0.1" y="-2" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-28" value="<font style="font-size: 11px;">first.transformEntry(context, resourceWrapper, t, count, prioritized, args);<br><font color="#007fff">组成一条责任链</font><br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="2760" y="1650" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-34" 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=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-30" target="7B76-LEGkQ0qvEv1oR-M-32" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-30" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>DefaultProcessorSlotChain</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//ProcessorSlot 头节点</font></p><p style="margin: 0px 0px 0px 4px;">AbstractLinkedProcessorSlot&lt;?&gt; <b>first</b> = new <span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>AbstractLinkedProcessorSlot&lt;Object&gt;() {...}<br></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//ProcessorSlot 尾节点</font></p><p style="margin: 0px 0px 0px 4px;">AbstractLinkedProcessorSlot&lt;?&gt; <b>end</b> = first;<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="-400" y="2360" width="360" height="120" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-38" 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=0;dashed=1;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-31" target="7B76-LEGkQ0qvEv1oR-M-37" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-31" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>AbstractLinkedProcessorSlot</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">//ProcessorSlot 组成单向链表, 构成责任链</font></p><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><span style="background-color: initial;">private AbstractLinkedProcessorSlot&lt;?&gt; <b>next</b> = null;</span><br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//Object o 参数类型转换,然后调用节点业务方法(entry())</font></p><p style="margin: 0px 0px 0px 4px;">void <b>transformEntry</b>(Context context, ResourceWrapper resourceWrapper, Object o, int count, boolean prioritized, Object... args)<br style="font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px;"><font color="#007fff">//调用下一个节点</font></p><p style="margin: 0px 0px 0px 4px;">void <b>fireEntry</b>(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)<br></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="-400" y="2000" width="360" height="160" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-33" 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=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-32" target="7B76-LEGkQ0qvEv1oR-M-31" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-32" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ProcessorSlotChain</b><br style="font-size: 11px;"></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px; font-size: 11px;"><br></p><hr style="font-size: 11px;"><p style="margin: 0px 0px 0px 4px;">public abstract void addFirst(AbstractLinkedProcessorSlot&lt;?&gt; protocolProcessor);<br style="font-size: 11px;"></p><p style="margin: 0px 0px 0px 4px;">public abstract void addLast(AbstractLinkedProcessorSlot&lt;?&gt; protocolProcessor);<br></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;" parent="1" vertex="1">
<mxGeometry x="-400" y="2200" width="360" height="120" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-37" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ProcessorSlot&lt;T&gt; (I)</b><br style="font-size: 11px;"></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-size: 11px;"><font color="#007fff">规则的校验是通过一串 ProcessorSlot 实现的。</font></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="-400" y="1880" width="360" height="80" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-39" value="DefaultProcessorSlotChain" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2775" y="1620" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-45" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-40" target="7B76-LEGkQ0qvEv1oR-M-44" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-47" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="7B76-LEGkQ0qvEv1oR-M-45" vertex="1" connectable="0">
<mxGeometry x="-0.05" y="-1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-40" value="<font style="font-size: 11px;">super.fireEntry(context, resourceWrapper, t, count, prioritized, args);<br><font color="#007fff">first 是头节点,里面并没有业务逻辑</font><br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="3000" y="1650" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-42" value="DefaultProcessorSlotChain$<br>AbstractLinkedProcessorSlot" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="3010" y="1610" width="180" height="40" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-2" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-44" target="7B76-LEGkQ0qvEv1oR-M-48" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-3" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="3PC2WQgvGjgkUnSvGf-g-2" vertex="1" connectable="0">
<mxGeometry x="-0.0395" y="-2" relative="1" as="geometry">
<mxPoint x="2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-21" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-44" target="3PC2WQgvGjgkUnSvGf-g-20" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-44" value="<font style="font-size: 10px;">entry(context, resourceWrapper, t, count, prioritized, args);<br><font style="font-size: 10px;" color="#007fff">不存在就创建当前资源的的统计节点<br>并加入调用上下文的EntranceNode childList</font><br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="3000" y="1750" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-46" value="<b>NodeSelectorSlot</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2880" y="1765" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-4" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-48" target="7B76-LEGkQ0qvEv1oR-M-51" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-6" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="3PC2WQgvGjgkUnSvGf-g-4" vertex="1" connectable="0">
<mxGeometry x="0.1711" y="-1" relative="1" as="geometry">
<mxPoint x="-1" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-23" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-48" target="3PC2WQgvGjgkUnSvGf-g-22" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-48" value="<font style="">entry(context, resourceWrapper, t, count, prioritized, args);<br><font color="#007fff">存储资源的统计信息以及调用者信息</font><br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="3000" y="1989.92" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-50" value="<b>ClusterBuilderSlot</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2875" y="2004.92" width="130" height="30" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-5" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-51" target="7B76-LEGkQ0qvEv1oR-M-54" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-7" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="3PC2WQgvGjgkUnSvGf-g-5" vertex="1" connectable="0">
<mxGeometry x="0.1711" y="1" relative="1" as="geometry">
<mxPoint x="-1" y="-3" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-51" value="<font style="font-size: 11px;">entry(context, resourceWrapper, t, count, prioritized, args);<br><font color="#007fff">用于异常发生时记录日志</font><br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;" parent="1" vertex="1">
<mxGeometry x="3000" y="2089.92" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-52" value="LogSlot" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2910" y="2104.92" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-8" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-54" target="7B76-LEGkQ0qvEv1oR-M-56" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-10" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="3PC2WQgvGjgkUnSvGf-g-8" vertex="1" connectable="0">
<mxGeometry x="-0.0921" y="3" relative="1" as="geometry">
<mxPoint x="-3" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-25" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-54" target="3PC2WQgvGjgkUnSvGf-g-24" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-26" value="<font color="#007fff"><b>返回时<br>执行统计</b></font>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="3PC2WQgvGjgkUnSvGf-g-25" vertex="1" connectable="0">
<mxGeometry x="-0.2382" y="-5" relative="1" as="geometry">
<mxPoint x="9" y="-5" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-54" value="<font style="font-size: 11px;">entry(context, resourceWrapper, t, count, prioritized, args);<br><font color="#007fff">从源码可以看到是在责任链返回时执行统计,即<b>本轮统计不参与本轮的校验</b></font><br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="3000" y="2450" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-55" value="<b>StatisticSlot</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2895" y="2465" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-9" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-56" target="7B76-LEGkQ0qvEv1oR-M-58" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-11" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="3PC2WQgvGjgkUnSvGf-g-9" vertex="1" connectable="0">
<mxGeometry x="-0.0921" y="-1" relative="1" as="geometry">
<mxPoint x="1" y="442" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-28" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-56" target="3PC2WQgvGjgkUnSvGf-g-27" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-56" value="<font style="font-size: 11px;">entry(context, resourceWrapper, t, count, prioritized, args);<br><font color="#007fff">黑白名单控制</font><br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="3000" y="2830" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-57" value="<b>AuthoritySlot</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2890" y="2845" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-16" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-58" target="7B76-LEGkQ0qvEv1oR-M-60" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-17" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="3PC2WQgvGjgkUnSvGf-g-16" vertex="1" connectable="0">
<mxGeometry x="-0.0395" y="3" relative="1" as="geometry">
<mxPoint x="-3" y="1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-35" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-58" target="3PC2WQgvGjgkUnSvGf-g-34" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="3200" y="3160" />
<mxPoint x="3200" y="3160" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-58" value="<font style="font-size: 11px;">entry(context, resourceWrapper, t, count, prioritized, args);<br><font color="#007fff">系统保护</font><br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="3000" y="3140" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-59" value="<b>SystemSlot</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2895" y="3140" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-13" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-60" target="7B76-LEGkQ0qvEv1oR-M-62" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-18" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="3PC2WQgvGjgkUnSvGf-g-13" vertex="1" connectable="0">
<mxGeometry x="-0.0921" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-43" 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="7B76-LEGkQ0qvEv1oR-M-60" target="3PC2WQgvGjgkUnSvGf-g-42" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-60" value="<font style="font-size: 11px;">entry(context, resourceWrapper, t, count, prioritized, args);<br><font color="#007fff">热点参数限流</font><br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="3000" y="3450.0000000000005" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-61" value="<b>ParamFlowSlot</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2890" y="3465.0000000000005" width="110" height="30" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-14" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-62" target="7B76-LEGkQ0qvEv1oR-M-64" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-19" value="..." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="3PC2WQgvGjgkUnSvGf-g-14" vertex="1" connectable="0">
<mxGeometry x="-0.0395" y="1" relative="1" as="geometry">
<mxPoint x="-1" y="1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="efD_JUAdZYZt2iUUUV3x-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-62" target="3PC2WQgvGjgkUnSvGf-g-44" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-62" value="<font style="font-size: 11px;">entry(context, resourceWrapper, t, count, prioritized, args);<br><font color="#007fff">流量控制</font><br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="3000" y="3650" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-63" value="<b>FlowSlot</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2905" y="3665" width="70" height="30" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-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="7B76-LEGkQ0qvEv1oR-M-64" target="3PC2WQgvGjgkUnSvGf-g-46" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-64" value="<font style="font-size: 11px;">entry(context, resourceWrapper, t, count, prioritized, args);<br><font color="#007fff">熔断降级,主要是断路器的状态切换</font><br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#ffe6cc;strokeColor=#d79b00;" parent="1" vertex="1">
<mxGeometry x="3000" y="4450" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-65" value="<b>DegradeSlot</b>" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2895" y="4465" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-74" value="<font style="">e.exit(count, args);<br><font color="#007fff">依次触发调用各个ProcessorSlot&nbsp;<br>exit() 方法</font><br></font>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="2520" y="1970" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-79" 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=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-78" target="7B76-LEGkQ0qvEv1oR-M-9" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-78" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>CtEntry</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">//上次调用的统计节点</font></p><p style="margin:0px;margin-left:4px;">protected Entry <b>parent</b> = null;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//下次调用的统计节点</font></p><p style="margin:0px;margin-left:4px;">protected Entry <b>child</b> = null;</p><p style="margin:0px;margin-left:4px;">protected ProcessorSlot&lt;Object&gt; <b>chain</b>;</p><p style="margin:0px;margin-left:4px;">protected Context context;</p><p style="margin:0px;margin-left:4px;">protected LinkedList&lt;BiConsumer&lt;Context, Entry&gt;&gt; exitHandlers;</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="-1800" y="1440" width="360" height="160" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-81" value="这块主要用于保存调用上下文的统计信息<br>有几个概念需要梳理清楚:<br><b>上下文</b><br><b>资源(被保护的对象,比如请求的web路由)</b><br><b>Node(资源的实时统计数据,组成树)</b><br><b>Entry(当前调用的信息,组成双向链表)</b><br>这部分代码的数据结构不是很容易理解为何这么做,建议先看校验代码逻辑怎么使用这些数据的再反推为何这么实现" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="-480" y="1000" width="640" height="110" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-85" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-82" target="7B76-LEGkQ0qvEv1oR-M-31" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="-680" y="2180" />
<mxPoint x="-310" y="2180" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-82" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>NodeSelectorSlot</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; font-size: 11px;"><font color="#007fff">//调用上下文名 -&gt; DefaultNode</font></p><p style="margin: 0px 0px 0px 4px;">private volatile Map&lt;String, DefaultNode&gt; <b>map</b> =&nbsp;</p><p style="margin: 0px 0px 0px 4px;"><span style="white-space: pre;">	</span>new HashMap&lt;String, DefaultNode&gt;(10);<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=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="-840" y="2360" width="320" height="120" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-84" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-83" target="gmwCS7IYYuH75fHtpYmN-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-83" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>ClusterNode</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">维护资源运行统计信息(响应时间、qps、线程计数、异常)以及调用方列表</font><br></p><p style="margin:0px;margin-left:4px;"><font color="#007fff"><br></font></p><p style="margin:0px;margin-left:4px;">private final String <b>name</b>;</p><p style="margin:0px;margin-left:4px;">private final int <b>resourceType</b>;</p><p style="margin:0px;margin-left:4px;">private Map&lt;String, StatisticNode&gt; <b>originCountMap</b> =&nbsp;</p><p style="margin:0px;margin-left:4px;"><span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>new HashMap&lt;&gt;();</p><p style="margin:0px;margin-left:4px;">private final ReentrantLock lock = new ReentrantLock();</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="-940" y="1380" width="360" height="180" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-87" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;endArrow=block;endFill=0;" parent="1" source="7B76-LEGkQ0qvEv1oR-M-86" target="7B76-LEGkQ0qvEv1oR-M-31" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="-1040" y="2180" />
<mxPoint x="-310" y="2180" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-86" value="<p style="margin: 4px 0px 0px; text-align: center;"><b>ClusterBuilderSlot</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; font-size: 11px;"><font color="#007fff">//请求资源 -&gt; ClusterNode</font></p><p style="margin: 0px 0px 0px 4px;">private static volatile Map&lt;ResourceWrapper, ClusterNode&gt; <span style="white-space: pre;">	</span><b>clusterNodeMap</b> = new HashMap&lt;&gt;();</p><p style="margin: 0px 0px 0px 4px;">private static final Object lock = new Object();</p><p style="margin: 0px 0px 0px 4px;">private volatile ClusterNode <b>clusterNode</b> = null;</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="-1200" y="2360" width="320" height="160" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-88" value="<div><font color="#007fff">this = {<b>NodeSelectorSlot</b>@12250}&nbsp;</font></div><div><font color="#007fff">&nbsp;<b>map</b> = {HashMap@12432}&nbsp; size = 1</font></div><div><font color="#007fff">&nbsp; "<b>sentinel_spring_web_context</b>" -&gt; {<b>DefaultNode</b>@12263}&nbsp;</font></div><div><font color="#007fff">&nbsp; &nbsp;key = "sentinel_spring_web_context"</font></div><div><font color="#007fff">&nbsp; &nbsp;value = {DefaultNode@12263}&nbsp;</font></div><div><font color="#007fff">&nbsp; &nbsp; <b>id</b> = {StringResourceWrapper@12601} "StringResourceWrapper{name='/demo/echo', entryType=IN, resourceType=1}"</font></div><div><font color="#007fff">&nbsp; &nbsp; <b>childList</b> = {HashSet@12488}&nbsp; size = 0</font></div><div><font color="#007fff">&nbsp; &nbsp; <b>clusterNode</b> = {ClusterNode@12551}&nbsp;</font></div><div><font color="#007fff">&nbsp; &nbsp; <b>rollingCounterInSecond</b> = {ArrayMetric@12602}&nbsp;</font></div><div><font color="#007fff">&nbsp; &nbsp; <b>rollingCounterInMinute</b> = {ArrayMetric@12603}&nbsp;</font></div><div><font color="#007fff">&nbsp; &nbsp; <b>curThreadNum</b> = {LongAdder@12604} "0"</font></div><div><font color="#007fff">&nbsp; &nbsp; <b>lastFetchTime</b> = -1</font></div><div><font color="#007fff">&nbsp;<b>next</b> = {ClusterBuilderSlot@12249}&nbsp;</font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="-840" y="2480" width="670" height="200" as="geometry" />
</mxCell>
<mxCell id="7B76-LEGkQ0qvEv1oR-M-89" value="<div><font color="#007fff"><b>context</b> = {Context@12304} "</font></div><div><font color="#007fff">&nbsp;<b>name</b> = "sentinel_spring_web_context"</font></div><div><font color="#007fff">&nbsp;<b>entranceNode</b> = {EntranceNode@12468}&nbsp;</font></div><div><font color="#007fff">&nbsp; <b>id</b> = {StringResourceWrapper@12626} "StringResourceWrapper{name='sentinel_spring_web_context', entryType=IN, resourceType=0}"</font></div><div><font color="#007fff">&nbsp; <b>childList</b> = {HashSet@12480}&nbsp; size = 1</font></div><div><font color="#007fff">&nbsp; &nbsp;0 = {<b>DefaultNode</b>@12263}&nbsp;</font></div><div><font color="#007fff">&nbsp; clusterNode = null</font></div><div><font color="#007fff">&nbsp; rollingCounterInSecond = {ArrayMetric@12627}&nbsp;</font></div><div><font color="#007fff">&nbsp; rollingCounterInMinute = {ArrayMetric@12628}&nbsp;</font></div><div><font color="#007fff">&nbsp; curThreadNum = {LongAdder@12629} "0"</font></div><div><font color="#007fff">&nbsp; lastFetchTime = -1</font></div><div><font color="#007fff">&nbsp;<b>curEntry</b> = {CtEntry@12427}&nbsp;</font></div><div><font color="#007fff">&nbsp; parent = null</font></div><div><font color="#007fff">&nbsp; child = null</font></div><div><font color="#007fff">&nbsp; chain = {DefaultProcessorSlotChain@12252}&nbsp;</font></div><div><font color="#007fff">&nbsp; context = {Context@12304}</font></div><div><font color="#007fff">&nbsp; exitHandlers = null</font></div><div><font color="#007fff">&nbsp; createTimestamp = 1712047852437</font></div><div><font color="#007fff">&nbsp; completeTimestamp = 0</font></div><div><font color="#007fff">&nbsp; curNode = {DefaultNode@12263}&nbsp;</font></div><div><font color="#007fff">&nbsp; originNode = {StatisticNode@12623}&nbsp;</font></div><div><font color="#007fff">&nbsp; error = null</font></div><div><font color="#007fff">&nbsp; blockError = null</font></div><div><font color="#007fff">&nbsp; resourceWrapper = {StringResourceWrapper@12305} "StringResourceWrapper{name='/demo/echo', entryType=IN, resourceType=1}"</font></div><div><font color="#007fff">&nbsp;origin = "default"</font></div><div><font color="#007fff">&nbsp;async = false</font></div>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="-840" y="2700" width="750" height="390" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-1" value="<font color="#007fff">这里的责任链是通过<b>单向链表</b>实现的,<br>每个节点都会实现AbstractLinkedProcessorSlot <br>这个抽象类用于实现链表节点的依次调用<br>fireEntry() 触发调用下一个ProcessorSlot节点<br></font>" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="2520" y="1720" width="270" height="70" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-20" value="<font style=""><div style="">DefaultNode node = map.get(context.getName());</div><div style="">if (node == null) {</div><div style="">&nbsp; &nbsp; synchronized (this) {</div><div style="">&nbsp; &nbsp; &nbsp; &nbsp; node = map.get(context.getName());</div><div style="">&nbsp; &nbsp; &nbsp; &nbsp; if (node == null) {</div><div style=""><font color="#007fff"><span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>&nbsp; &nbsp; //当前请求资源的统计数据节点</font><br></div><div style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; node = new <b>DefaultNode</b>(resourceWrapper, null);</div><div style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HashMap&lt;String, DefaultNode&gt; cacheMap = new HashMap&lt;String, DefaultNode&gt;(map.size());</div><div style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cacheMap.putAll(map);</div><div style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cacheMap.put(context.getName(), node);</div><div style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map = cacheMap;</div><div style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <font color="#007fff">// 构建<b>调用树</b>,Context.entranceNode.childList</font></div><div style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ((DefaultNode) context.getLastNode()).<b>addChild</b>(node);</div><div style="">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="">&nbsp; &nbsp; }</div><div style="">}</div><div style=""><div>context.<b>setCurNode</b>(node);</div><div><b>fireEntry</b>(context, resourceWrapper, node, count, prioritized, args);</div></div></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;arcSize=2;" parent="1" vertex="1">
<mxGeometry x="3280" y="1650" width="400" height="260" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-22" value="<font style="">DCL控制下往 ClusterBuilerSlot&nbsp;Map&lt;ResourceWrapper, ClusterNode&gt; <b>clusterNodeMap</b> 中添加 <b>ClusterNode<br></b>clusterNode = new <b>ClusterNode</b>(resourceWrapper.getName(), resourceWrapper.getResourceType());<br>newMap.put(node.getId(), clusterNode);<br>node.setClusterNode(clusterNode);<br><div>if (!"".equals(context.getOrigin())) {</div><div>&nbsp; Node originNode = node.getClusterNode().getOrCreateOriginNode(context.getOrigin());</div><div>&nbsp; context.getCurEntry().setOriginNode(originNode);</div><div>}</div><div>fireEntry(context, resourceWrapper, node, count, prioritized, args);</div></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;arcSize=2;" parent="1" vertex="1">
<mxGeometry x="3280" y="1930" width="400" height="180" as="geometry" />
</mxCell>
<mxCell id="R8YPJ6jMD8Vm_6NY_bdp-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-24" target="R8YPJ6jMD8Vm_6NY_bdp-54" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="R8YPJ6jMD8Vm_6NY_bdp-61" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.75;exitDx=0;exitDy=0;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-24" target="R8YPJ6jMD8Vm_6NY_bdp-60" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-24" value="<div style=""><div style="font-size: 9px;">try {</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; //先触发执行后面的ProcessorSlot</font></div><div style="font-size: 9px;">&nbsp; fireEntry(context, resourceWrapper, node, count, prioritized, args);</div><div style="font-size: 9px;"><br style="font-size: 9px;"></div><div style="font-size: 9px;">&nbsp;<font color="#007fff"> //<b>没有异常</b></font></div><div style="font-size: 9px;"><font color="#007fff">&nbsp; //1 请求通过, 添加线程计数和通过请求计数</font></div><div style="font-size: 9px;">&nbsp; node.<b>increaseThreadNum</b>();<span style=""><span style="">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><font color="#007fff">//对<b>当前Node节点</b>和<b>clusterNode</b> curThreadNum+1</font></div><div style="">&nbsp; node.<b style="font-size: 9px;">addPassRequest</b>(count);<span style="font-size: 9px;"><span style="">&nbsp;</span></span><font color="#007fff">//对<b>当前Node节点</b>和<b>clusterNode</b> rollingCounterInSecond + count<br><span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style=""><span style="white-space: pre;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span>&nbsp; &nbsp; &nbsp;<span style="white-space: pre;">	</span><span style="white-space: pre;">	</span><span style="white-space: pre;">	</span>&nbsp; &nbsp; &nbsp;//&nbsp;</font><font color="#007fff">rollingCounterInMinute + count</font><font color="#007fff"><br></font></div><div style="font-size: 9px;">&nbsp; if (context.getCurEntry().getOriginNode() != null) {</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; context.<b>getCurEntry</b>().getOriginNode().<b>increaseThreadNum</b>();</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; context.<b>getCurEntry</b>().getOriginNode().<b>addPassRequest</b>(count);</div><div style="font-size: 9px;">&nbsp; }</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; //2 全局的统计</font></div><div style="font-size: 9px;">&nbsp; if (resourceWrapper.getEntryType() == EntryType.IN) {</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; // Add count for global inbound entry node for global statistics.</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; Constants.<b>ENTRY_NODE</b>.<b>increaseThreadNum</b>();</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; Constants.<b>ENTRY_NODE</b>.<b>addPassRequest</b>(count);</div><div style="font-size: 9px;">&nbsp; }</div><div style="font-size: 9px;"><font color="#007fff">&nbsp; //3 请求通过回调,通过监听器(钩子)拓展其他统计</font></div><div style="font-size: 9px;">&nbsp; for (ProcessorSlotEntryCallback&lt;DefaultNode&gt; handler : StatisticSlotCallbackRegistry.getEntryCallbacks()) {</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; handler.<b>onPass</b>(context, resourceWrapper, node, count, args);</div><div style="font-size: 9px;">&nbsp; }</div><div style="font-size: 9px;">} catch (<b>PriorityWaitException</b> ex) {</div><div style="font-size: 9px;">&nbsp; node.<b>increaseThreadNum</b>();</div><div style="font-size: 9px;">&nbsp; if (context.getCurEntry().getOriginNode() != null) {</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; // Add count for origin node.</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; context.<b>getCurEntry</b>().getOriginNode().<b>increaseThreadNum</b>();</div><div style="font-size: 9px;">&nbsp; }</div><div style="font-size: 9px;">&nbsp; if (resourceWrapper.getEntryType() == EntryType.IN) {</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; // Add count for global inbound entry node for global statistics.</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; Constants.<b>ENTRY_NODE</b>.<b>increaseThreadNum</b>();</div><div style="font-size: 9px;">&nbsp; }</div><div style="font-size: 9px;">&nbsp; // Handle pass event with registered entry callback handlers.</div><div style="font-size: 9px;">&nbsp; for (ProcessorSlotEntryCallback&lt;DefaultNode&gt; handler : StatisticSlotCallbackRegistry.getEntryCallbacks()) {</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; handler.<b>onPass</b>(context, resourceWrapper, node, count, args);</div><div style="font-size: 9px;">&nbsp; }</div><div style="font-size: 9px;">} catch (<b>BlockException</b> e) {</div><div style="font-size: 9px;">&nbsp; // Blocked, set block exception to current entry.</div><div style="font-size: 9px;">&nbsp; context.getCurEntry().setBlockError(e);</div><div style="font-size: 9px;">&nbsp; // Add block count.</div><div style="font-size: 9px;">&nbsp; node.<b>increaseBlockQps</b>(count);</div><div style="font-size: 9px;">&nbsp; if (context.getCurEntry().getOriginNode() != null) {</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; context.getCurEntry().getOriginNode().<b>increaseBlockQps</b>(count);</div><div style="font-size: 9px;">&nbsp; }</div><div style="font-size: 9px;">&nbsp; if (resourceWrapper.getEntryType() == EntryType.IN) {</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; // Add count for global inbound entry node for global statistics.</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; Constants.ENTRY_NODE.<b>increaseBlockQps</b>(count);</div><div style="font-size: 9px;">&nbsp; }</div><div style="font-size: 9px;">&nbsp; // Handle block event with registered entry callback handlers.</div><div style="font-size: 9px;">&nbsp; for (ProcessorSlotEntryCallback&lt;DefaultNode&gt; handler : StatisticSlotCallbackRegistry.getEntryCallbacks()) {</div><div style="font-size: 9px;">&nbsp; &nbsp; &nbsp; handler.<b>onBlocked</b>(e, context, resourceWrapper, node, count, args);</div><div style="font-size: 9px;">&nbsp; }</div><div style="font-size: 9px;">&nbsp; throw e;</div><div style="font-size: 9px;">} catch (<b>Throwable</b> e) {</div><div style="font-size: 9px;">&nbsp; context.getCurEntry().setError(e);</div><div style="font-size: 9px;">&nbsp; throw e;</div><div style="font-size: 9px;">}</div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=9;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;arcSize=1;" parent="1" vertex="1">
<mxGeometry x="3280" y="2150" width="400" height="660" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-30" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-27" target="3PC2WQgvGjgkUnSvGf-g-29" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-27" value="<font style=""><font color="#007fff">//校验访问应用黑白名单</font><br><b>checkBlackWhiteAuthority</b>(resourceWrapper, context);<br>fireEntry(context, resourceWrapper, node, count, prioritized, args);<br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;" parent="1" vertex="1">
<mxGeometry x="3280" y="2830" width="400" height="60" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-29" value="从&nbsp;<b>AuthorityRuleManager&nbsp;</b>通过资源名读取<b style="font-size: 10px;">黑白名单的规则集合,</b>然后依次校验各个规则&nbsp;<b style="font-size: 10px;">AuthorityRuleChecker</b>.<b>passCheck</b>(rule, context), 就是字符串比较,校验不通过则<br>throw new <b>AuthorityException</b>(context.getOrigin(), rule);" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;fillColor=#fff2cc;strokeColor=#d6b656;align=left;" parent="1" vertex="1">
<mxGeometry x="3720" y="2820" width="240" height="80" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-32" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>AuthorityRuleManager</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">//黑白名单规则,<b>资源名称 -&gt; AuthorityRule集合</b></font></p><p style="margin:0px;margin-left:4px;">private static volatile Map&lt;String, Set&lt;AuthorityRule&gt;&gt; <b>authorityRules</b> = new ConcurrentHashMap&lt;&gt;();</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//Push模式,监听回调</font><br></p><p style="margin:0px;margin-left:4px;">private static final RulePropertyListener <b>LISTENER</b> = new RulePropertyListener();</p><p style="margin:0px;margin-left:4px;">private static SentinelProperty&lt;List&lt;AuthorityRule&gt;&gt; currentProperty = new DynamicSentinelProperty&lt;&gt;();</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=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="-1920" y="640" width="480" height="200" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-33" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>AuthorityRule&nbsp;</b><span style="background-color: initial;">extends AbstractRule&nbsp;</span></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff">应用访问的黑白名单规则定义。</font></p><p style="margin:0px;margin-left:4px;"><span style="background-color: initial; color: rgb(0, 127, 255);"><br></span></p><p style="margin:0px;margin-left:4px;"><span style="background-color: initial; color: rgb(0, 127, 255);">//规则策略,默认是白名单</span></p><p style="margin:0px;margin-left:4px;"><span style="background-color: initial;">private int <b>strategy</b> = RuleConstant.AUTHORITY_WHITE;</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;" parent="1" vertex="1">
<mxGeometry x="-1800" y="320" width="360" height="120" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-37" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-34" target="3PC2WQgvGjgkUnSvGf-g-36" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-34" value="<font style=""><div><font color="#007fff">//校验系统保护规则,只会校验 inbound (EntryType.IN<span style="background-color: initial;">)</span></font></div><b>SystemRuleManager</b>.<b>checkSystem</b>(resourceWrapper, <b>count</b>);<br>fireEntry(context, resourceWrapper, node, count, prioritized, args);<br><font color="#007fff">校验失败抛出&nbsp;SystemBlockException<br></font>基本都是基于全局的统计节点<br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="3280" y="3130" width="400" height="80" as="geometry" />
</mxCell>
<mxCell id="R8YPJ6jMD8Vm_6NY_bdp-70" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1.001;exitY=0.345;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-36" target="R8YPJ6jMD8Vm_6NY_bdp-69" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="R8YPJ6jMD8Vm_6NY_bdp-73" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.598;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitPerimeter=0;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-36" target="R8YPJ6jMD8Vm_6NY_bdp-72" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="R8YPJ6jMD8Vm_6NY_bdp-77" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1.003;exitY=0.801;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitPerimeter=0;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-36" target="R8YPJ6jMD8Vm_6NY_bdp-76" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-36" value="<div style="font-size: 10px;">if (resourceWrapper == null) {</div><div style="font-size: 10px;">&nbsp; return;</div><div style="font-size: 10px;">}</div><div style="font-size: 10px;"><span style="background-color: initial; font-size: 10px;"><font color="#007fff" style="font-size: 10px;"><span style="font-size: 10px;">//系统开关打开才会执行 SystemRule 校验</span></font></span></div><div style="font-size: 10px;"><span style="background-color: initial; font-size: 10px;">if (!checkSystemStatus.get()) {</span><br style="font-size: 10px;"></div><div style="font-size: 10px;">&nbsp; return;</div><div style="font-size: 10px;">}<span style="background-color: initial; font-size: 10px;">&nbsp;</span></div><font color="#007fff" style="font-size: 10px;"><span style="font-size: 10px;">//只校验EntryType.IN类型资源</span></font><div style="font-size: 10px;"><span style="background-color: initial; font-size: 10px;">if (resourceWrapper.getEntryType() != EntryType.IN) {</span><br style="font-size: 10px;"></div><div style="font-size: 10px;">&nbsp; return;</div><div style="font-size: 10px;">}</div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;"><b style="font-size: 10px;">// qps 检查 (统计数据来源于 StatisticSlot</b></font><font color="#007fff" style="font-size: 10px;"><b style="font-size: 10px;">)</b></font></div><div style="font-size: 10px;">double currentQps = Constants.<b>ENTRY_NODE</b>.<b>passQps</b>();</div><div style="font-size: 10px;">if (currentQps + count &gt; qps) {</div><div style="font-size: 10px;">&nbsp; throw new <b style="font-size: 10px;">SystemBlockException</b>(resourceWrapper.getName(), "qps");</div><div style="font-size: 10px;">}</div><div style="font-size: 10px;"><span style="background-color: initial; font-size: 10px;"><font color="#007fff" style="font-size: 10px;"><b style="font-size: 10px;">//总线程数检查</b></font></span></div><div style="font-size: 10px;"><span style="background-color: initial; font-size: 10px;">int currentThread = Constants.<b>ENTRY_NODE</b>.<b>curThreadNum</b>();</span><br style="font-size: 10px;"></div><div style="font-size: 10px;">if (currentThread &gt; maxThread) {</div><div style="font-size: 10px;">&nbsp; throw new SystemBlockException(resourceWrapper.getName(), "thread");</div><div style="font-size: 10px;">}</div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;"><b style="font-size: 10px;">//平均响应时长检查,RT: ResponseTime</b></font></div><div style="font-size: 10px;">double rt = Constants.<b>ENTRY_NODE</b>.<b>avgRt</b>();</div><div style="font-size: 10px;">if (rt &gt; maxRt) {</div><div style="font-size: 10px;">&nbsp; throw new SystemBlockException(resourceWrapper.getName(), "rt");</div><div style="font-size: 10px;">}</div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;"><b style="font-size: 10px;">// Google BBR 算法检查,需要打开开关才会执行</b></font></div><font color="#007fff"><b>(数据源于 SystemStatusListener、StatisticSlot)</b></font><div style="font-size: 10px;">if (highestSystemLoadIsSet &amp;&amp; <b>getCurrentSystemAvgLoad</b>() &gt; highestSystemLoad) {</div><div style="font-size: 10px;">&nbsp; if (!<b>checkBbr</b>(currentThread)) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; throw new SystemBlockException(resourceWrapper.getName(), "load");</div><div style="font-size: 10px;">&nbsp; }</div><div style="font-size: 10px;">}</div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;"><b style="font-size: 10px;">// cpu占用检查 (数据源于 SystemStatusListener)</b></font></div><div style="font-size: 10px;">if (highestCpuUsageIsSet &amp;&amp; getCurrentCpuUsage() &gt; highestCpuUsage) {</div><div style="font-size: 10px;">&nbsp; throw new SystemBlockException(resourceWrapper.getName(), "cpu");</div><div style="font-size: 10px;">}</div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#fff2cc;strokeColor=#d6b656;arcSize=2;" parent="1" vertex="1">
<mxGeometry x="3720" y="2940" width="360" height="460" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-38" value="资源与规则:https://sentinelguard.io/zh-cn/docs/basic-api-resource-rule.html#/" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="-480" y="80" width="440" height="30" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-39" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>SystemRuleManager</b><br></p><hr size="1"><p style="margin:0px;margin-left:4px;"><font color="#007fff"><b>系统规则管理器</b>,</font></p><font color="#007fff">&nbsp;结合应用的 Load、总体平均 RT、入口 QPS 和线程数等几个维度的监控指标,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。<br></font><p style="margin:0px;margin-left:4px;"><font color="#007fff"><br></font></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//黑白名单规则,<b>资源名称 -&gt; AuthorityRule集合</b></font></p><p style="margin:0px;margin-left:4px;">private static volatile double highestSystemLoad = Double.MAX_VALUE;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//CPU占用,[0, 1]</font></p><p style="margin:0px;margin-left:4px;">private static volatile double <b>highestCpuUsage</b> = Double.MAX_VALUE;</p><p style="margin:0px;margin-left:4px;">private static volatile double <b>qps</b> = Double.MAX_VALUE;</p><p style="margin:0px;margin-left:4px;">private static volatile long <b>maxRt</b> = Long.MAX_VALUE;</p><p style="margin:0px;margin-left:4px;">private static volatile long <b>maxThread</b> = Long.MAX_VALUE;</p><p style="margin:0px;margin-left:4px;"><br></p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//记录下面各阈值是否被用户设置,设置了才有效</font></p><p style="margin:0px;margin-left:4px;">private static volatile boolean highestSystemLoadIsSet = false;</p><p style="margin:0px;margin-left:4px;">private static volatile boolean highestCpuUsageIsSet = false;</p><p style="margin:0px;margin-left:4px;">private static volatile boolean qpsIsSet = false;</p><p style="margin:0px;margin-left:4px;">private static volatile boolean maxRtIsSet = false;</p><p style="margin:0px;margin-left:4px;">private static volatile boolean maxThreadIsSet = false;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//是否执行系统状态检查的开关,默认关闭</font></p><p style="margin:0px;margin-left:4px;">private static AtomicBoolean <b>checkSystemStatus</b> = new AtomicBoolean(false);</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//系统状态监听任务,后面的scheduler中每秒会执行一次这个任务</font></p><p style="margin:0px;margin-left:4px;">private static <b>SystemStatusListener</b> <b>statusListener</b> = null;</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//Push模式,规则配置监听回调</font></p><p style="margin:0px;margin-left:4px;">private final static SystemPropertyListener <b>listener</b> = new SystemPropertyListener();</p><p style="margin:0px;margin-left:4px;">private static SentinelProperty&lt;List&lt;SystemRule&gt;&gt; currentProperty = new DynamicSentinelProperty&lt;List&lt;SystemRule&gt;&gt;();</p><p style="margin:0px;margin-left:4px;"><font color="#007fff">//系统状态监听任务的计划任务线程池</font></p><p style="margin:0px;margin-left:4px;">private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1,</p><p style="margin:0px;margin-left:4px;">new NamedThreadFactory("sentinel-system-status-record-task", true));</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=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="-2440" y="640" width="480" height="520" as="geometry" />
</mxCell>
<mxCell id="R8YPJ6jMD8Vm_6NY_bdp-2" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;dashed=1;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-41" target="3PC2WQgvGjgkUnSvGf-g-34" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-41" value="<font style=""><div></div><b>SystemStatusListener</b>#<b>run</b>()<br><font color="#007fff">SystemRuleManager.scheduler 每秒执行一次统计任务,统计<b>系统最近一分钟的平均负载</b>、<b>当前CPU负载</b>(取系统统计的CPU负载和计算出来的进程的CPU负载的较大值);<br>这个任务统计的信息仅仅用于SystemSlot的 <b>CPU占用检查</b><br>通过JMX(OperatingSystemMXBean、RuntimeMXBean)统计</font><br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;align=left;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
<mxGeometry x="3280" y="2993.33" width="400" height="80" as="geometry" />
</mxCell>
<mxCell id="R8YPJ6jMD8Vm_6NY_bdp-87" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-42" target="R8YPJ6jMD8Vm_6NY_bdp-86" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-42" value="<font style=""><div><font color="#007fff">//校验热点参数规则</font></div><b>checkFlow</b>(resourceWrapper, count, args);<br>fireEntry(context, resourceWrapper, node, count, prioritized, args);<br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="3280" y="3450.0000000000005" width="400" height="60" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-49" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" target="3PC2WQgvGjgkUnSvGf-g-48" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="3680" y="3680" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-44" value="<font style=""><div><font color="#007fff">//校验流控规则</font></div><b>checkFlow(resourceWrapper, context, node, count, prioritized);<br></b>fireEntry(context, resourceWrapper, node, count, prioritized, args);<br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="3280" y="3650.02" width="400" height="60" as="geometry" />
</mxCell>
<mxCell id="JXVrsIax2Fh7985Lvlhv-15" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-46" target="JXVrsIax2Fh7985Lvlhv-14" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-46" value="<font style=""><div><font color="#007fff">//校验熔断规则</font></div><b>performChecking(context, resourceWrapper);<br></b>fireEntry(context, resourceWrapper, node, count, prioritized, args);<br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="3280" y="4450" width="400" height="60" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-52" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-48" target="3PC2WQgvGjgkUnSvGf-g-51" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-48" value="<font style="font-size: 10px;"><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">//依次校验流控规则</font></div><div style="font-size: 10px;"><font color="#007fff" style="font-size: 10px;">// ruleProvider 是 Function 函数对象,通过资源名获取对应的 FlowRule集合</font></div><div style="font-size: 10px;">Collection&lt;<b style="font-size: 10px;">FlowRule</b>&gt; rules = ruleProvider.apply(resource.getName());</div><div style="font-size: 10px;">if (rules != null) {</div><div style="font-size: 10px;">&nbsp; for (<b>FlowRule</b> rule : rules) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; if (!<b style="font-size: 10px;">canPassCheck</b>(rule, context, node, count, prioritized)) {</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new <b>FlowException</b>(rule.getLimitApp(), rule);</div><div style="font-size: 10px;">&nbsp; &nbsp; &nbsp; }</div><div style="font-size: 10px;">&nbsp; }</div><div style="font-size: 10px;">}</div></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;fillColor=#dae8fc;strokeColor=#6c8ebf;arcSize=5;" parent="1" vertex="1">
<mxGeometry x="3720" y="3620.05" width="360" height="119.95" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-50" value="FlowRuleChecker" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="3840" y="3590.05" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-58" 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="3PC2WQgvGjgkUnSvGf-g-51" target="3PC2WQgvGjgkUnSvGf-g-57" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-60" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-51" target="3PC2WQgvGjgkUnSvGf-g-59" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-51" value="<div style=""><div style="">String limitApp = rule.getLimitApp();</div><div style="">if (limitApp == null) {</div><div style="">&nbsp; &nbsp; return true;</div><div style="">}</div><div style="">if (rule.<b>isClusterMode</b>()) {</div><div style="">&nbsp; &nbsp; return <b>passClusterCheck</b>(rule, context, node, acquireCount, prioritized);</div><div style="">}</div><div style="">return <b>passLocalCheck</b>(rule, context, node, acquireCount, prioritized);</div></div>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=10;align=left;arcSize=5;" parent="1" vertex="1">
<mxGeometry x="4120" y="3620.05" width="360" height="119.95" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-57" value="<font style=""><div></div>TODO<br style="font-size: 11px;"></font>" style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;align=center;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="4520" y="3600" width="200" height="60" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-62" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-59" target="3PC2WQgvGjgkUnSvGf-g-61" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3PC2WQgvGjgkUnSvGf-g-64" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="3PC2WQgvGjgkUnSvGf-g-59" target="3PC2WQgvGjgkUnSvGf-g-65" edge="1">
<mxGeometry relative="1" as="geometry">