• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.inprocess;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.base.Preconditions;
22 import com.google.errorprone.annotations.DoNotCall;
23 import io.grpc.Deadline;
24 import io.grpc.ExperimentalApi;
25 import io.grpc.Internal;
26 import io.grpc.ServerBuilder;
27 import io.grpc.ServerStreamTracer;
28 import io.grpc.internal.AbstractServerImplBuilder;
29 import io.grpc.internal.FixedObjectPool;
30 import io.grpc.internal.GrpcUtil;
31 import io.grpc.internal.InternalServer;
32 import io.grpc.internal.ObjectPool;
33 import io.grpc.internal.ServerImplBuilder;
34 import io.grpc.internal.ServerImplBuilder.ClientTransportServersBuilder;
35 import io.grpc.internal.SharedResourcePool;
36 import java.io.File;
37 import java.net.SocketAddress;
38 import java.util.List;
39 import java.util.UUID;
40 import java.util.concurrent.ScheduledExecutorService;
41 import java.util.concurrent.TimeUnit;
42 
43 /**
44  * Builder for a server that services in-process requests. Clients identify the in-process server by
45  * its name.
46  *
47  * <p>The server is intended to be fully-featured, high performance, and useful in testing.
48  *
49  * <h3>Using JUnit TestRule</h3>
50  * The class "GrpcServerRule" (from "grpc-java/testing") is a JUnit TestRule that
51  * creates a {@link InProcessServer} and a {@link io.grpc.ManagedChannel ManagedChannel}. This
52  * test rule contains the boilerplate code shown below. The classes "HelloWorldServerTest" and
53  * "HelloWorldClientTest" (from "grpc-java/examples") demonstrate basic usage.
54  *
55  * <h3>Usage example</h3>
56  * <h4>Server and client channel setup</h4>
57  * <pre>
58  *   String uniqueName = InProcessServerBuilder.generateName();
59  *   Server server = InProcessServerBuilder.forName(uniqueName)
60  *       .directExecutor() // directExecutor is fine for unit tests
61  *       .addService(&#47;* your code here *&#47;)
62  *       .build().start();
63  *   ManagedChannel channel = InProcessChannelBuilder.forName(uniqueName)
64  *       .directExecutor()
65  *       .build();
66  * </pre>
67  *
68  * <h4>Usage in tests</h4>
69  * The channel can be used normally. A blocking stub example:
70  * <pre>
71  *   TestServiceGrpc.TestServiceBlockingStub blockingStub =
72  *       TestServiceGrpc.newBlockingStub(channel);
73  * </pre>
74  */
75 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1783")
76 public final class InProcessServerBuilder extends
77     AbstractServerImplBuilder<InProcessServerBuilder> {
78   /**
79    * Create a server builder that will bind with the given name.
80    *
81    * @param name the identity of the server for clients to connect to
82    * @return a new builder
83    */
forName(String name)84   public static InProcessServerBuilder forName(String name) {
85     return forAddress(new InProcessSocketAddress(checkNotNull(name, "name")));
86   }
87 
88   /**
89    * Create a server builder which listens on the given address.
90    * @param listenAddress The SocketAddress this server will listen on.
91    * @return a new builder
92    */
forAddress(SocketAddress listenAddress)93   public static InProcessServerBuilder forAddress(SocketAddress listenAddress) {
94     return new InProcessServerBuilder(listenAddress);
95   }
96 
97   /**
98    * Always fails.  Call {@link #forName} instead.
99    */
100   @DoNotCall("Unsupported. Use forName() instead")
forPort(int port)101   public static InProcessServerBuilder forPort(int port) {
102     throw new UnsupportedOperationException("call forName() instead");
103   }
104 
105   /**
106    * Generates a new server name that is unique each time.
107    */
generateName()108   public static String generateName() {
109     return UUID.randomUUID().toString();
110   }
111 
112   private final ServerImplBuilder serverImplBuilder;
113   final SocketAddress listenAddress;
114   int maxInboundMetadataSize = Integer.MAX_VALUE;
115   ObjectPool<ScheduledExecutorService> schedulerPool =
116       SharedResourcePool.forResource(GrpcUtil.TIMER_SERVICE);
117 
InProcessServerBuilder(SocketAddress listenAddress)118   private InProcessServerBuilder(SocketAddress listenAddress) {
119     this.listenAddress = checkNotNull(listenAddress, "listenAddress");
120 
121     final class InProcessClientTransportServersBuilder implements ClientTransportServersBuilder {
122       @Override
123       public InternalServer buildClientTransportServers(
124           List<? extends ServerStreamTracer.Factory> streamTracerFactories) {
125         return buildTransportServers(streamTracerFactories);
126       }
127     }
128 
129     serverImplBuilder = new ServerImplBuilder(new InProcessClientTransportServersBuilder());
130 
131     // In-process transport should not record its traffic to the stats module.
132     // https://github.com/grpc/grpc-java/issues/2284
133     serverImplBuilder.setStatsRecordStartedRpcs(false);
134     serverImplBuilder.setStatsRecordFinishedRpcs(false);
135     // Disable handshake timeout because it is unnecessary, and can trigger Thread creation that can
136     // break some environments (like tests).
137     handshakeTimeout(Long.MAX_VALUE, TimeUnit.SECONDS);
138   }
139 
140   @Internal
141   @Override
delegate()142   protected ServerBuilder<?> delegate() {
143     return serverImplBuilder;
144   }
145 
146   /**
147    * Provides a custom scheduled executor service.
148    *
149    * <p>It's an optional parameter. If the user has not provided a scheduled executor service when
150    * the channel is built, the builder will use a static cached thread pool.
151    *
152    * @return this
153    *
154    * @since 1.11.0
155    */
scheduledExecutorService( ScheduledExecutorService scheduledExecutorService)156   public InProcessServerBuilder scheduledExecutorService(
157       ScheduledExecutorService scheduledExecutorService) {
158     schedulerPool = new FixedObjectPool<>(
159         checkNotNull(scheduledExecutorService, "scheduledExecutorService"));
160     return this;
161   }
162 
163   /**
164    * Provides a custom deadline ticker that this server will use to create incoming {@link
165    * Deadline}s.
166    *
167    * <p>This is intended for unit tests that fake out the clock.  You should also have a fake {@link
168    * ScheduledExecutorService} whose clock is synchronized with this ticker and set it to {@link
169    * #scheduledExecutorService}. DO NOT use this in production.
170    *
171    * @return this
172    * @see Deadline#after(long, TimeUnit, Deadline.Ticker)
173    *
174    * @since 1.24.0
175    */
deadlineTicker(Deadline.Ticker ticker)176   public InProcessServerBuilder deadlineTicker(Deadline.Ticker ticker) {
177     serverImplBuilder.setDeadlineTicker(ticker);
178     return this;
179   }
180 
181   /**
182    * Sets the maximum size of metadata allowed to be received. {@code Integer.MAX_VALUE} disables
183    * the enforcement. Defaults to no limit ({@code Integer.MAX_VALUE}).
184    *
185    * <p>There is potential for performance penalty when this setting is enabled, as the Metadata
186    * must actually be serialized. Since the current implementation of Metadata pre-serializes, it's
187    * currently negligible. But Metadata is free to change its implementation.
188    *
189    * @param bytes the maximum size of received metadata
190    * @return this
191    * @throws IllegalArgumentException if bytes is non-positive
192    * @since 1.17.0
193    */
194   @Override
maxInboundMetadataSize(int bytes)195   public InProcessServerBuilder maxInboundMetadataSize(int bytes) {
196     Preconditions.checkArgument(bytes > 0, "maxInboundMetadataSize must be > 0");
197     this.maxInboundMetadataSize = bytes;
198     return this;
199   }
200 
buildTransportServers( List<? extends ServerStreamTracer.Factory> streamTracerFactories)201   InProcessServer buildTransportServers(
202       List<? extends ServerStreamTracer.Factory> streamTracerFactories) {
203     return new InProcessServer(this, streamTracerFactories);
204   }
205 
206   @Override
useTransportSecurity(File certChain, File privateKey)207   public InProcessServerBuilder useTransportSecurity(File certChain, File privateKey) {
208     throw new UnsupportedOperationException("TLS not supported in InProcessServer");
209   }
210 
setStatsEnabled(boolean value)211   void setStatsEnabled(boolean value) {
212     this.serverImplBuilder.setStatsEnabled(value);
213   }
214 }
215