# 승인 메서드 셋의 본문 GrpcAdmissionController.java:50 /** Admits a call, queues it, or refuses it. */ GrpcAdmissionController.java:51 public Decision tryAdmit() { GrpcAdmissionController.java:52 int running = inFlight.get(); GrpcAdmissionController.java:53 if (running < maxConcurrentCalls) { GrpcAdmissionController.java:54 inFlight.incrementAndGet(); GrpcAdmissionController.java:55 return new Decision(true, inFlight.get(), queued.get(), "within the concurrency bound"); GrpcAdmissionController.java:56 } GrpcAdmissionController.java:57 int waiting = queued.get(); GrpcAdmissionController.java:58 if (waiting < maxQueuedCalls) { GrpcAdmissionController.java:59 queued.incrementAndGet(); GrpcAdmissionController.java:60 return new Decision(true, running, queued.get(), "queued within the admission bound"); GrpcAdmissionController.java:61 } GrpcAdmissionController.java:62 rejected.incrementAndGet(); GrpcAdmissionController.java:63 return new Decision( GrpcAdmissionController.java:64 false, GrpcAdmissionController.java:65 running, GrpcAdmissionController.java:66 waiting, GrpcAdmissionController.java:67 "at capacity: " GrpcAdmissionController.java:68 + running GrpcAdmissionController.java:69 + " in flight and " GrpcAdmissionController.java:70 + waiting GrpcAdmissionController.java:71 + " queued. Refusing is better than accepting work whose caller will have given up."); GrpcAdmissionController.java:72 } GrpcAdmissionController.java:73 GrpcAdmissionController.java:74 /** Moves a queued call into execution. */ GrpcAdmissionController.java:75 public void promoteFromQueue() { GrpcAdmissionController.java:76 if (queued.get() > 0) { GrpcAdmissionController.java:77 queued.decrementAndGet(); GrpcAdmissionController.java:78 inFlight.incrementAndGet(); GrpcAdmissionController.java:79 } GrpcAdmissionController.java:80 } GrpcAdmissionController.java:81 GrpcAdmissionController.java:82 /** Releases a finished call. */ GrpcAdmissionController.java:83 public void release() { GrpcAdmissionController.java:84 if (inFlight.get() > 0) { GrpcAdmissionController.java:85 inFlight.decrementAndGet(); GrpcAdmissionController.java:86 } GrpcAdmissionController.java:87 } 계수기 필드 : GrpcAdmissionController.java:17 private final AtomicInteger inFlight = new AtomicInteger(); GrpcAdmissionController.java:18 private final AtomicInteger queued = new AtomicInteger(); GrpcAdmissionController.java:19 private final AtomicInteger rejected = new AtomicInteger(); # 클래스가 자기 존재 이유를 무엇이라고 적는가 GrpcAdmissionController.java:5 /** GrpcAdmissionController.java:6 * Refuses work the server cannot do, before it spends anything on it. GrpcAdmissionController.java:7 * GrpcAdmissionController.java:8 *

Rejecting with {@code RESOURCE_EXHAUSTED} is a better outcome than queueing for two reasons GrpcAdmissionController.java:9 * that both matter under load: the client learns immediately and can shed or retry elsewhere, and GrpcAdmissionController.java:10 * the server stops accumulating work whose callers have already given up. A server that queues GrpcAdmissionController.java:11 * instead spends its capacity finishing requests nobody is reading. GrpcAdmissionController.java:12 */ GrpcAdmissionController.java:13 public final class GrpcAdmissionController { # 이 타입이 조립되는가, 그리고 승인 API 를 부르는 자리는 어디인가 main · GrpcDrainCoordinator.java:3 import dev.caskeleton.grpc.server.GrpcAdmissionController; main · GrpcDrainCoordinator.java:25 private final GrpcAdmissionController admission; main · GrpcDrainCoordinator.java:42 GrpcAdmissionController admission, test · GrpcDrainCoordinatorTest.java:6 import dev.caskeleton.grpc.server.GrpcAdmissionController; test · GrpcDrainCoordinatorTest.java:27 health, new GrpcAdmissionController(8, 8), policy, unaryCalls::get, streams::get); main · GrpcAdmissionController.java:13 public final class GrpcAdmissionController { main · GrpcAdmissionController.java:22 public GrpcAdmissionController(int maxConcurrentCalls, int maxQueuedCalls) { main · GrpcAdmissionController.java:31 public static GrpcAdmissionController forExecutor(GrpcExecutorProfile profile) { main · GrpcAdmissionController.java:35 return new GrpcAdmissionController( test · GrpcServerProfileTest.java:105 GrpcAdmissionController controller = new GrpcAdmissionController(2, 1); test · GrpcServerProfileTest.java:110 GrpcAdmissionController.Decision refused = controller.tryAdmit(); test · GrpcServerProfileTest.java:122 GrpcAdmissionController controller = new GrpcAdmissionController(1, 1); test · GrpcServerProfileTest.java:136 GrpcAdmissionController controller = GrpcAdmissionController.forExecutor(EXECUTOR); main · GrpcPlatformAutoConfiguration.java:11 import dev.caskeleton.grpc.server.GrpcAdmissionController; main · GrpcPlatformAutoConfiguration.java:56 public GrpcAdmissionController grpcAdmissionController(GrpcExecutorProfile executorProfile) { main · GrpcPlatformAutoConfiguration.java:57 return GrpcAdmissionController.forExecutor(executorProfile); tryAdmit · promoteFromQueue · release 를 부르는 자리 : test · GrpcServerProfileTest.java:107 assertThat(controller.tryAdmit().admitted()).isTrue(); test · GrpcServerProfileTest.java:108 assertThat(controller.tryAdmit().admitted()).isTrue(); test · GrpcServerProfileTest.java:109 assertThat(controller.tryAdmit().admitted()).isTrue(); test · GrpcServerProfileTest.java:110 GrpcAdmissionController.Decision refused = controller.tryAdmit(); test · GrpcServerProfileTest.java:123 controller.tryAdmit(); test · GrpcServerProfileTest.java:124 controller.tryAdmit(); test · GrpcServerProfileTest.java:126 controller.release(); test · GrpcServerProfileTest.java:127 controller.promoteFromQueue(); test · GrpcServerProfileTest.java:139 assertThat(controller.tryAdmit().admitted()).isTrue(); 그중 main 소스 세트 : 0 개 파일 main 에서 이 타입을 들고 있는 GrpcDrainCoordinator 가 하는 일 : GrpcDrainCoordinator.java:148 return admission.inFlight(); 그 빈을 만드는 자동설정이 언제 켜지는가 : GrpcPlatformAutoConfiguration.java:29 @Configuration(proxyBeanMethods = false) GrpcPlatformAutoConfiguration.java:30 @ConditionalOnProperty( GrpcPlatformAutoConfiguration.java:31 prefix = "ca-skeleton.grpc.platform", GrpcPlatformAutoConfiguration.java:32 name = "enabled", GrpcPlatformAutoConfiguration.java:33 havingValue = "true", GrpcPlatformAutoConfiguration.java:34 matchIfMissing = false) GrpcPlatformAutoConfiguration.java:35 @EnableConfigurationProperties(GrpcPlatformProperties.class) GrpcPlatformAutoConfiguration.java:36 public class GrpcPlatformAutoConfiguration { 그 프로퍼티를 켜는 설정 파일 : 0 개 src/grpc 밖에서 이 starter 에 의존하는 모듈 : 0 개 main 소비자 GrpcDrainCoordinator 가 생성되는 자리 : test · GrpcDrainCoordinatorTest.java:26 return new GrpcDrainCoordinator( src/grpc 안의 ApplicationContextRunner : 0 개 파일 # 저장소가 쓰는 승격 순서 GrpcServerProfileTest.java:119 @Test GrpcServerProfileTest.java:120 @DisplayName("a released call makes room, and a queued call is promoted into it") GrpcServerProfileTest.java:121 void releaseAndPromotionTrackCapacity() { GrpcServerProfileTest.java:122 GrpcAdmissionController controller = new GrpcAdmissionController(1, 1); GrpcServerProfileTest.java:123 controller.tryAdmit(); GrpcServerProfileTest.java:124 controller.tryAdmit(); GrpcServerProfileTest.java:125 GrpcServerProfileTest.java:126 controller.release(); GrpcServerProfileTest.java:127 controller.promoteFromQueue(); GrpcServerProfileTest.java:128 GrpcServerProfileTest.java:129 assertThat(controller.inFlight()).isEqualTo(1); GrpcServerProfileTest.java:130 assertThat(controller.queued()).isZero(); GrpcServerProfileTest.java:131 } # 같은 가족의 올바른 형태 — 재시도 예산 src/grpc/grpc-policy/src/main/java/dev/caskeleton/grpc/resilience/GrpcRetryBudget.java GrpcRetryBudget.java:50 public boolean tryConsume() { GrpcRetryBudget.java:51 while (true) { GrpcRetryBudget.java:52 long observed = tokens.get(); GrpcRetryBudget.java:53 if (observed < tokensPerRetry) { GrpcRetryBudget.java:54 return false; GrpcRetryBudget.java:55 } GrpcRetryBudget.java:56 if (tokens.compareAndSet(observed, observed - tokensPerRetry)) { GrpcRetryBudget.java:57 return true; GrpcRetryBudget.java:58 } GrpcRetryBudget.java:59 } GrpcRetryBudget.java:60 } GrpcRetryBudget.java:61 compareAndSet 을 쓰는 grpc main 파일 : GrpcChannelRuntimeRegistry.java GrpcCancellationToken.java GrpcRetryBudget.java GrpcAdmissionController.java compareAndSet 0 건 GrpcStreamAdmission.java compareAndSet 0 건 # 프로브 — 아래 소스를 그 자리에서 컴파일해 돌린다 GrpcAdmissionController paired = new GrpcAdmissionController(1, 8); for (int i = 0; i < 6; i++) paired.tryAdmit(); for (int i = 0; i < 5; i++) { paired.release(); paired.promoteFromQueue(); } GrpcAdmissionController solo = new GrpcAdmissionController(1, 8); for (int i = 0; i < 6; i++) solo.tryAdmit(); for (int i = 0; i < 5; i++) solo.promoteFromQueue(); 가. 저장소 시험과 같은 순서 — 해제 하나에 승격 하나 여섯 번 승인 후 : 진행 중 1 · 대기 5 해제·승격을 다섯 쌍 후 : 진행 중 1 · 대기 0 나. 해제 없이 승격만 — 승격이 해제를 앞지른 경우 여섯 번 승인 후 : 진행 중 1 · 대기 5 승격만 다섯 번 후 : 진행 중 6 · 대기 0 동시성 상한 : 1