core,okhttp: removed GrpcUtil.IS_RESTRICTED_APPENGINE and dependent code (#6051)

This commit is contained in:
Dharmesh Jogadia 2019-08-13 22:41:56 +05:30 committed by Jihun Cho
parent 1949ebd7ef
commit 5790503d79
10 changed files with 33 additions and 119 deletions

View File

@ -25,7 +25,6 @@ import com.google.common.base.Splitter;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.grpc.CallOptions; import io.grpc.CallOptions;
import io.grpc.ClientStreamTracer; import io.grpc.ClientStreamTracer;
@ -73,12 +72,6 @@ public final class GrpcUtil {
public static final Charset US_ASCII = Charset.forName("US-ASCII"); public static final Charset US_ASCII = Charset.forName("US-ASCII");
// AppEngine runtimes have constraints on threading and socket handling
// that need to be accommodated.
public static final boolean IS_RESTRICTED_APPENGINE =
System.getProperty("com.google.appengine.runtime.environment") != null
&& "1.7".equals(System.getProperty("java.specification.version"));
/** /**
* {@link io.grpc.Metadata.Key} for the timeout header. * {@link io.grpc.Metadata.Key} for the timeout header.
*/ */
@ -266,17 +259,6 @@ public final class GrpcUtil {
return !Boolean.TRUE.equals(callOptions.getOption(CALL_OPTIONS_RPC_OWNED_BY_BALANCER)); return !Boolean.TRUE.equals(callOptions.getOption(CALL_OPTIONS_RPC_OWNED_BY_BALANCER));
} }
/**
* Returns a proxy detector appropriate for the current environment.
*/
public static ProxyDetector getDefaultProxyDetector() {
if (IS_RESTRICTED_APPENGINE) {
return NOOP_PROXY_DETECTOR;
} else {
return DEFAULT_PROXY_DETECTOR;
}
}
/** /**
* Maps HTTP error response status codes to transport codes, as defined in <a * Maps HTTP error response status codes to transport codes, as defined in <a
* href="https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md"> * href="https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md">
@ -569,16 +551,10 @@ public final class GrpcUtil {
* @return a {@link ThreadFactory}. * @return a {@link ThreadFactory}.
*/ */
public static ThreadFactory getThreadFactory(String nameFormat, boolean daemon) { public static ThreadFactory getThreadFactory(String nameFormat, boolean daemon) {
if (IS_RESTRICTED_APPENGINE) { return new ThreadFactoryBuilder()
@SuppressWarnings("BetaApi") .setDaemon(daemon)
ThreadFactory factory = MoreExecutors.platformThreadFactory(); .setNameFormat(nameFormat)
return factory; .build();
} else {
return new ThreadFactoryBuilder()
.setDaemon(daemon)
.setNameFormat(nameFormat)
.build();
}
} }
/** /**

View File

@ -64,10 +64,6 @@ final class JndiResourceResolverFactory implements DnsNameResolver.ResourceResol
@Nullable @Nullable
@SuppressWarnings("LiteralClassName") @SuppressWarnings("LiteralClassName")
private static Throwable initJndi() { private static Throwable initJndi() {
if (GrpcUtil.IS_RESTRICTED_APPENGINE) {
return new UnsupportedOperationException(
"Currently running in an AppEngine restricted environment");
}
try { try {
Class.forName("javax.naming.directory.InitialDirContext"); Class.forName("javax.naming.directory.InitialDirContext");
Class.forName("com.sun.jndi.dns.DnsContextFactory"); Class.forName("com.sun.jndi.dns.DnsContextFactory");

View File

@ -562,7 +562,7 @@ final class ManagedChannelImpl extends ManagedChannel implements
this.logId = InternalLogId.allocate("Channel", target); this.logId = InternalLogId.allocate("Channel", target);
this.nameResolverFactory = builder.getNameResolverFactory(); this.nameResolverFactory = builder.getNameResolverFactory();
ProxyDetector proxyDetector = ProxyDetector proxyDetector =
builder.proxyDetector != null ? builder.proxyDetector : GrpcUtil.getDefaultProxyDetector(); builder.proxyDetector != null ? builder.proxyDetector : GrpcUtil.DEFAULT_PROXY_DETECTOR;
this.retryEnabled = builder.retryEnabled && !builder.temporarilyDisableRetry; this.retryEnabled = builder.retryEnabled && !builder.temporarilyDisableRetry;
this.loadBalancerFactory = new AutoConfiguredLoadBalancerFactory(builder.defaultLbPolicy); this.loadBalancerFactory = new AutoConfiguredLoadBalancerFactory(builder.defaultLbPolicy);
this.nameResolverRegistry = builder.nameResolverRegistry; this.nameResolverRegistry = builder.nameResolverRegistry;

View File

@ -124,44 +124,30 @@ public final class SharedResourceHolder {
Preconditions.checkState(cached.refcount > 0, "Refcount has already reached zero"); Preconditions.checkState(cached.refcount > 0, "Refcount has already reached zero");
cached.refcount--; cached.refcount--;
if (cached.refcount == 0) { if (cached.refcount == 0) {
if (GrpcUtil.IS_RESTRICTED_APPENGINE) { Preconditions.checkState(cached.destroyTask == null, "Destroy task already scheduled");
// AppEngine must immediately release shared resources, particularly executors // Schedule a delayed task to destroy the resource.
// which could retain request-scoped threads which become zombies after the request if (destroyer == null) {
// completes. destroyer = destroyerFactory.createScheduledExecutor();
// We do not encourage exceptions to be thrown during close, but we would like it to }
// be able to recover eventually and do not want future resource fetches reuse the broken cached.destroyTask = destroyer.schedule(new LogExceptionRunnable(new Runnable() {
// one. @Override
try { public void run() {
resource.close(instance); synchronized (SharedResourceHolder.this) {
} finally { // Refcount may have gone up since the task was scheduled. Re-check it.
instances.remove(resource); if (cached.refcount == 0) {
} try {
} else { resource.close(instance);
Preconditions.checkState(cached.destroyTask == null, "Destroy task already scheduled"); } finally {
// Schedule a delayed task to destroy the resource. instances.remove(resource);
if (destroyer == null) { if (instances.isEmpty()) {
destroyer = destroyerFactory.createScheduledExecutor(); destroyer.shutdown();
} destroyer = null;
cached.destroyTask = destroyer.schedule(new LogExceptionRunnable(new Runnable() {
@Override
public void run() {
synchronized (SharedResourceHolder.this) {
// Refcount may have gone up since the task was scheduled. Re-check it.
if (cached.refcount == 0) {
try {
resource.close(instance);
} finally {
instances.remove(resource);
if (instances.isEmpty()) {
destroyer.shutdown();
destroyer = null;
}
} }
} }
} }
} }
}), DESTROY_DELAY_SECONDS, TimeUnit.SECONDS); }
} }), DESTROY_DELAY_SECONDS, TimeUnit.SECONDS);
} }
// Always returning null // Always returning null
return null; return null;

View File

@ -41,7 +41,7 @@ public class DnsNameResolverProviderTest {
}); });
private final NameResolver.Args args = NameResolver.Args.newBuilder() private final NameResolver.Args args = NameResolver.Args.newBuilder()
.setDefaultPort(8080) .setDefaultPort(8080)
.setProxyDetector(GrpcUtil.getDefaultProxyDetector()) .setProxyDetector(GrpcUtil.DEFAULT_PROXY_DETECTOR)
.setSynchronizationContext(syncContext) .setSynchronizationContext(syncContext)
.setServiceConfigParser(mock(ServiceConfigParser.class)) .setServiceConfigParser(mock(ServiceConfigParser.class))
.build(); .build();

View File

@ -111,7 +111,7 @@ public class DnsNameResolverTest {
}); });
private final NameResolver.Args args = NameResolver.Args.newBuilder() private final NameResolver.Args args = NameResolver.Args.newBuilder()
.setDefaultPort(DEFAULT_PORT) .setDefaultPort(DEFAULT_PORT)
.setProxyDetector(GrpcUtil.getDefaultProxyDetector()) .setProxyDetector(GrpcUtil.DEFAULT_PROXY_DETECTOR)
.setSynchronizationContext(syncContext) .setSynchronizationContext(syncContext)
.setServiceConfigParser(mock(ServiceConfigParser.class)) .setServiceConfigParser(mock(ServiceConfigParser.class))
.build(); .build();

View File

@ -41,8 +41,6 @@ import io.grpc.okhttp.internal.TlsVersion;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -53,7 +51,6 @@ import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
/** Convenience class for building channels with the OkHttp transport. */ /** Convenience class for building channels with the OkHttp transport. */
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1785") @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1785")
@ -416,25 +413,7 @@ public class OkHttpChannelBuilder extends
case TLS: case TLS:
try { try {
if (sslSocketFactory == null) { if (sslSocketFactory == null) {
SSLContext sslContext; SSLContext sslContext = SSLContext.getInstance("Default", Platform.get().getProvider());
if (GrpcUtil.IS_RESTRICTED_APPENGINE) {
// The following auth code circumvents the following AccessControlException:
// access denied ("java.util.PropertyPermission" "javax.net.ssl.keyStore" "read")
// Conscrypt will attempt to load the default KeyStore if a trust manager is not
// provided, which is forbidden on AppEngine
sslContext = SSLContext.getInstance("TLS", Platform.get().getProvider());
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
sslContext.init(
null,
trustManagerFactory.getTrustManagers(),
// Use an algorithm that doesn't need /dev/urandom
SecureRandom.getInstance("SHA1PRNG", Platform.get().getProvider()));
} else {
sslContext = SSLContext.getInstance("Default", Platform.get().getProvider());
}
sslSocketFactory = sslContext.getSocketFactory(); sslSocketFactory = sslContext.getSocketFactory();
} }
return sslSocketFactory; return sslSocketFactory;

View File

@ -19,7 +19,6 @@ package io.grpc.okhttp;
import io.grpc.Internal; import io.grpc.Internal;
import io.grpc.InternalServiceProviders; import io.grpc.InternalServiceProviders;
import io.grpc.ManagedChannelProvider; import io.grpc.ManagedChannelProvider;
import io.grpc.internal.GrpcUtil;
/** /**
* Provider for {@link OkHttpChannelBuilder} instances. * Provider for {@link OkHttpChannelBuilder} instances.
@ -34,8 +33,7 @@ public final class OkHttpChannelProvider extends ManagedChannelProvider {
@Override @Override
public int priority() { public int priority() {
return (GrpcUtil.IS_RESTRICTED_APPENGINE return InternalServiceProviders.isAndroid(getClass().getClassLoader()) ? 8 : 3;
|| InternalServiceProviders.isAndroid(getClass().getClassLoader())) ? 8 : 3;
} }
@Override @Override

View File

@ -1067,9 +1067,7 @@ class OkHttpClientTransport implements ConnectionClientTransport, TransportExcep
@Override @Override
public void run() { public void run() {
String threadName = Thread.currentThread().getName(); String threadName = Thread.currentThread().getName();
if (!GrpcUtil.IS_RESTRICTED_APPENGINE) { Thread.currentThread().setName("OkHttpClientTransport");
Thread.currentThread().setName("OkHttpClientTransport");
}
try { try {
// Read until the underlying socket closes. // Read until the underlying socket closes.
while (frameReader.nextFrame(this)) { while (frameReader.nextFrame(this)) {
@ -1095,10 +1093,7 @@ class OkHttpClientTransport implements ConnectionClientTransport, TransportExcep
log.log(Level.INFO, "Exception closing frame reader", ex); log.log(Level.INFO, "Exception closing frame reader", ex);
} }
listener.transportTerminated(); listener.transportTerminated();
if (!GrpcUtil.IS_RESTRICTED_APPENGINE) { Thread.currentThread().setName(threadName);
// Restore the original thread name.
Thread.currentThread().setName(threadName);
}
} }
} }

View File

@ -158,8 +158,7 @@ public class Platform {
/** Attempt to match the host runtime to a capable Platform implementation. */ /** Attempt to match the host runtime to a capable Platform implementation. */
private static Platform findPlatform() { private static Platform findPlatform() {
Provider androidOrAppEngineProvider = Provider androidOrAppEngineProvider = getAndroidSecurityProvider();
GrpcUtil.IS_RESTRICTED_APPENGINE ? getAppEngineProvider() : getAndroidSecurityProvider();
if (androidOrAppEngineProvider != null) { if (androidOrAppEngineProvider != null) {
// Attempt to find Android 2.3+ APIs. // Attempt to find Android 2.3+ APIs.
OptionalMethod<Socket> setUseSessionTickets OptionalMethod<Socket> setUseSessionTickets
@ -183,9 +182,7 @@ public class Platform {
} }
TlsExtensionType tlsExtensionType; TlsExtensionType tlsExtensionType;
if (GrpcUtil.IS_RESTRICTED_APPENGINE) { if (androidOrAppEngineProvider.getName().equals("GmsCore_OpenSSL")
tlsExtensionType = TlsExtensionType.ALPN_AND_NPN;
} else if (androidOrAppEngineProvider.getName().equals("GmsCore_OpenSSL")
|| androidOrAppEngineProvider.getName().equals("Conscrypt") || androidOrAppEngineProvider.getName().equals("Conscrypt")
|| androidOrAppEngineProvider.getName().equals("Ssl_Guard")) { || androidOrAppEngineProvider.getName().equals("Ssl_Guard")) {
tlsExtensionType = TlsExtensionType.ALPN_AND_NPN; tlsExtensionType = TlsExtensionType.ALPN_AND_NPN;
@ -299,19 +296,6 @@ public class Platform {
return false; return false;
} }
/**
* Forcibly load the conscrypt security provider on AppEngine if it's available. If not fail.
*/
private static Provider getAppEngineProvider() {
try {
// Forcibly load conscrypt as it is unlikely to be an installed provider on AppEngine
return (Provider) Class.forName("org.conscrypt.OpenSSLProvider")
.getConstructor().newInstance();
} catch (Throwable t) {
throw new RuntimeException("Unable to load conscrypt security provider", t);
}
}
/** /**
* Select the first recognized security provider according to the preference order returned by * Select the first recognized security provider according to the preference order returned by
* {@link Security#getProviders}. If a recognized provider is not found then warn but continue. * {@link Security#getProviders}. If a recognized provider is not found then warn but continue.