Skip to content

Commit 29b61fd

Browse files
ludochgae-java-bot
authored andcommitted
Refactor JavaRuntimeParams and JavaRuntimeFactory, removing many unused command-line flags, remove jCommander dependency for simpler parser with simple types.
This change significantly refactors `JavaRuntimeParams` and `JavaRuntimeFactory`. Many command-line parameters have been removed from `JavaRuntimeParams` because they were unused. The values for several parameters are now hardcoded as constants within `AppEngineConstants` and `JavaRuntimeFactory`, reflecting their static nature in the current runtime configuration. Specifically, `MAX_RUNTIME_LOG_PER_REQUEST`, `BYTE_COUNT_BEFORE_FLUSHING`, `MAX_LOG_LINE_SIZE`, `MAX_LOG_FLUSH_TIME`, `THREAD_STOP_TERMINATES_CLONE`, `FORCE_URLFETCH_URL_STREAM_HANDLER`, `MAX_REQUEST_SIZE`, and `MAX_RESPONSE_SIZE` have been moved to `AppEngineConstants`. Additionally, `LEGACY_MODE` and `ASYNC_MODE` in `AppEngineConstants` have been converted from static final fields to static methods (`isLegacyMode()` and `isAsyncMode()`). This allows their values to be dynamically read from system properties, which is necessary because `AppEngineConstants` is now used both before and after application loading, where system properties can change. This change fixes test failures in `AsyncServletTest`. The command-line parsing library JCommander has been removed. A simpler manual parsing mechanism has been implemented in `JavaRuntimeParams` for the remaining four flags: `--trusted_host`, `--fixed_application_path`, `--jetty_http_port`, and `--clone_max_outstanding_api_rpcs`. Note that while `DEFAULT_MAX_OUTSTANDING_API_RPCS` is now defined in `AppEngineConstants`, the `--clone_max_outstanding_api_rpcs` flag still allows overriding this default. The unused Cloud Profiler integration, previously configurable via `--enable_cloud_cpu_profiler` and `--enable_cloud_heap_profiler`, has been removed. The selection of the `ServletEngineAdapter` is now based on system properties (`appengine.use.EE8`, `appengine.use.EE10`, or `appengine.use.EE11`) rather than a command-line parameter. Other changes include: * The system properties `appengine.jetty.also_log_to_apiproxy` and `appengine.urlfetch.deriveResponseMessage` are now unconditionally set to `true` in `JavaRuntimeFactory`. * The `disable_api_call_logging_in_apiproxy` setting is now *only* controlled by the system property, removing its command-line parameter control. * The constants `SKIP_ADMIN_CHECK_ATTR` and `X_GOOGLE_INTERNAL_SKIPADMINCHECK_UC` have been centralized in `AppEngineConstants`. PiperOrigin-RevId: 868781401 Change-Id: Ib4e50d2fdd4946133e47713c320338e2617b65ec
1 parent 3d89561 commit 29b61fd

29 files changed

Lines changed: 337 additions & 788 deletions

File tree

THIRD-PARTY.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ The repository contains 3rd-party code under the following licenses:
193193
* Java Concurrency Tools Core Library (org.jctools:jctools-core:4.0.5 - https://github.com/JCTools)
194194
* JBoss Logging 3 (org.jboss.logging:jboss-logging:3.6.0.Final - http://www.jboss.org)
195195
* JBoss Threads (org.jboss.threads:jboss-threads:3.6.1.Final - http://www.jboss.org)
196-
* jcommander (com.beust:jcommander:1.82 - https://jcommander.org)
197196
* jffi (com.github.jnr:jffi:1.3.9 - http://github.com/jnr/jffi)
198197
* JGroups (org.jgroups:jgroups:5.4.5.Final - http://www.jgroups.org)
199198
* jnr-a64asm (com.github.jnr:jnr-a64asm:1.0.0 - http://nexus.sonatype.org/oss-repository-hosting.html/jnr-a64asm)

runtime/impl/pom.xml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,7 @@
3232
<description>App Engine runtime implementation.</description>
3333

3434
<dependencies>
35-
<dependency>
36-
<groupId>com.beust</groupId>
37-
<artifactId>jcommander</artifactId>
38-
</dependency>
35+
3936
<dependency>
4037
<groupId>com.contrastsecurity</groupId>
4138
<artifactId>yamlbeans</artifactId>

runtime/impl/src/main/java/com/google/apphosting/runtime/AppEngineConstants.java

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,55 @@
1717
package com.google.apphosting.runtime;
1818

1919
import com.google.common.collect.ImmutableSet;
20+
import java.time.Duration;
2021

2122
/** {@code AppEngineConstants} centralizes some constants that are specific to our use of Jetty. */
2223
public final class AppEngineConstants {
2324

25+
// We need these system properties based value to be static methods as now used
26+
// in the pre boostrap of the runtime, before these system properties are changed based on
27+
// app settings in appengine-web.xml, so they might change after the system properties are
28+
// initialized.
29+
2430
/**
2531
* If Legacy Mode is turned on, then Jetty is configured to be more forgiving of bad requests and
2632
* to act more in the style of Jetty-9.3
2733
*/
28-
public static final boolean LEGACY_MODE =
29-
Boolean.getBoolean("com.google.apphosting.runtime.jetty94.LEGACY_MODE");
34+
public static boolean isLegacyMode() {
35+
return Boolean.getBoolean("com.google.apphosting.runtime.jetty94.LEGACY_MODE");
36+
}
3037

3138
/** Set the Jetty request with Async mode. */
32-
public static final boolean ASYNC_MODE = Boolean.getBoolean("com.google.appengine.enable_async");
39+
public static boolean isAsyncMode() {
40+
return Boolean.getBoolean("com.google.appengine.enable_async");
41+
}
42+
43+
/** The maximum allowed size in bytes of the Runtime Log per request, returned in the UPResponse. */
44+
public static final long MAX_RUNTIME_LOG_PER_REQUEST = 3000L * 1024L;
45+
46+
/** The maximum number of simultaneous APIHost RPCs. */
47+
public static final int DEFAULT_MAX_OUTSTANDING_API_RPCS = 100;
48+
49+
/** Flush application logs when they grow to this size. */
50+
public static final long BYTE_COUNT_BEFORE_FLUSHING = 100 * 1024L;
51+
52+
/** Maximum application log line size. */
53+
public static final int MAX_LOG_LINE_SIZE = 16 * 1024;
54+
55+
/**
56+
* Maximum time a log record should be allowed to to be cached in the runtime before being flushed
57+
* to the appserver (only applies to non-frontend requests).
58+
*/
59+
public static final Duration MAX_LOG_FLUSH_TIME = Duration.ofSeconds(60);
60+
61+
/** Always terminate the clone when Thread.stop() is used. */
62+
public static final boolean THREAD_STOP_TERMINATES_CLONE = true;
63+
64+
/**
65+
* Force url-stream-handler to 'urlfetch' irrespective of the contents of the appengine-web.xml
66+
* descriptor.
67+
*/
68+
public static final boolean FORCE_URLFETCH_URL_STREAM_HANDLER = false;
3369

3470
public static final String GAE_RUNTIME = System.getenv("GAE_RUNTIME");
3571

@@ -80,6 +116,8 @@ public final class AppEngineConstants {
80116
public static final String X_APPENGINE_QUEUENAME = "x-appengine-queuename";
81117
public static final String X_APPENGINE_TIMEOUT_MS = "x-appengine-timeout-ms";
82118
public static final String X_GOOGLE_INTERNAL_SKIPADMINCHECK = "x-google-internal-skipadmincheck";
119+
// This is the same as X_GOOGLE_INTERNAL_SKIPADMINCHECK, but in upper case. This is used for
120+
// case-insensitive comparisons.
83121
public static final String X_GOOGLE_INTERNAL_SKIPADMINCHECK_UC =
84122
"X-Google-Internal-SkipAdminCheck";
85123
public static final String X_GOOGLE_INTERNAL_PROFILER = "x-google-internal-profiler";
@@ -152,5 +190,11 @@ public final class AppEngineConstants {
152190
*/
153191
public static final int JETTY_RESPONSE_HEADER_SIZE = 262144;
154192

193+
/** The maximum request size in bytes (32M). */
194+
public static final int MAX_REQUEST_SIZE = 32 * 1024 * 1024;
195+
196+
/** The maximum response size in bytes (32M). */
197+
public static final int MAX_RESPONSE_SIZE = 32 * 1024 * 1024;
198+
155199
private AppEngineConstants() {}
156200
}

runtime/impl/src/main/java/com/google/apphosting/runtime/JavaRuntimeFactory.java

Lines changed: 59 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,23 @@
1616

1717
package com.google.apphosting.runtime;
1818

19+
import static com.google.apphosting.runtime.AppEngineConstants.BYTE_COUNT_BEFORE_FLUSHING;
20+
import static com.google.apphosting.runtime.AppEngineConstants.CYCLES_PER_SECOND;
21+
import static com.google.apphosting.runtime.AppEngineConstants.FORCE_URLFETCH_URL_STREAM_HANDLER;
22+
import static com.google.apphosting.runtime.AppEngineConstants.JETTY_REQUEST_HEADER_SIZE;
23+
import static com.google.apphosting.runtime.AppEngineConstants.JETTY_RESPONSE_HEADER_SIZE;
24+
import static com.google.apphosting.runtime.AppEngineConstants.MAX_LOG_FLUSH_TIME;
25+
import static com.google.apphosting.runtime.AppEngineConstants.MAX_LOG_LINE_SIZE;
26+
import static com.google.apphosting.runtime.AppEngineConstants.MAX_RUNTIME_LOG_PER_REQUEST;
27+
import static com.google.apphosting.runtime.AppEngineConstants.SOFT_DEADLINE_DELAY_MS;
28+
import static com.google.apphosting.runtime.AppEngineConstants.THREAD_STOP_TERMINATES_CLONE;
29+
1930
import com.google.apphosting.api.ApiProxy;
2031
import com.google.common.annotations.VisibleForTesting;
32+
import com.google.common.base.VerifyException;
2133
import com.google.common.flogger.GoogleLogger;
2234
import com.google.common.net.HostAndPort;
2335
import java.io.File;
24-
import java.lang.reflect.Method;
25-
import java.time.Duration;
2636
import java.util.List;
2737
import java.util.Optional;
2838
import java.util.OptionalInt;
@@ -54,27 +64,24 @@ public JavaRuntime getStartedRuntime(NullSandboxPlugin sandboxPlugin, String[] a
5464
logger.atWarning().log("Unknown command line arguments: %s", unknownParams);
5565
}
5666

57-
RuntimeLogSink logSink = new RuntimeLogSink(params.getMaxRuntimeLogPerRequest());
67+
RuntimeLogSink logSink = new RuntimeLogSink(MAX_RUNTIME_LOG_PER_REQUEST);
5868
logSink.addHandlerToRootLogger();
5969

60-
maybeConfigureProfiler(params);
70+
// Cloud Profiler is now set up externally, typically at the application entry point.
71+
// See:
72+
// https://github.com/GoogleCloudPlatform/appengine-java-standard?tab=readme-ov-file#entry-point-features
6173

62-
if (params.getLogJettyExceptionsToAppLogs()) {
63-
// This system property is checked by JettyLogger, which is
64-
// instantiated via reflection by Jetty and therefore we cannot
65-
// pass options into it directly.
66-
//
67-
// TODO: This logic should really move down to
68-
// JettyServletAdapter.
69-
System.setProperty("appengine.jetty.also_log_to_apiproxy", "true");
70-
}
74+
// This system property is checked by JettyLogger, which is
75+
// instantiated via reflection by Jetty and therefore we cannot
76+
// pass options into it directly.
77+
//
78+
// TODO: This logic should really move down to
79+
// JettyServletAdapter.
80+
System.setProperty("appengine.jetty.also_log_to_apiproxy", "true");
7181

72-
if (params.getUrlfetchDeriveResponseMessage()) {
73-
// This system property is checked by URLFetch's Connection class, which
74-
// is directly instantiated by the Java API and cannot take constructor
75-
// arguments.
76-
System.setProperty("appengine.urlfetch.deriveResponseMessage", "true");
77-
}
82+
// This system property is always set to true and is checked by URLFetch's Connection class,
83+
// which is directly instantiated by the Java API and cannot take constructor arguments.
84+
System.setProperty("appengine.urlfetch.deriveResponseMessage", "true");
7885

7986
// This system property is checked by GMTransport, which is directly
8087
// registered with JavaMail and cannot take additional constructor arguments.
@@ -86,37 +93,41 @@ public JavaRuntime getStartedRuntime(NullSandboxPlugin sandboxPlugin, String[] a
8693
// registered with JavaMail and cannot take additional constructor arguments.
8794
System.setProperty("appengine.mail.filenamePreventsInlining", "true");
8895

89-
ServletEngineAdapter servletEngine = createServletEngine(params);
90-
ApiDeadlineOracle deadlineOracle =
91-
new ApiDeadlineOracle.Builder().initDeadlineMap().build();
96+
ServletEngineAdapter servletEngine = createServletEngine();
97+
ApiDeadlineOracle deadlineOracle = new ApiDeadlineOracle.Builder().initDeadlineMap().build();
9298

9399
ApiHostClientFactory apiHostFactory = new ApiHostClientFactory();
94100

95101
BackgroundRequestCoordinator coordinator = new BackgroundRequestCoordinator();
96102

103+
// The disableApiCallLogging setting is controlled by a system property,
104+
// which is consistent with other runtime settings configured via system properties.
105+
// If command-line parameter control is also needed, this logic should be updated
106+
// to potentially check a value parsed from 'args' via JavaRuntimeParams.
107+
boolean disableApiCallLogging = Boolean.getBoolean("disable_api_call_logging_in_apiproxy");
108+
97109
ApiProxyImpl apiProxyImpl =
98110
ApiProxyImpl.builder()
99111
.setApiHost(
100112
apiHostFactory.newAPIHost(
101-
params.getTrustedHost(),
102-
OptionalInt.of(params.getCloneMaxOutstandingApiRpcs())))
113+
params.getTrustedHost(), OptionalInt.of(params.getMaxOutstandingApiRpcs())))
103114
.setDeadlineOracle(deadlineOracle)
104115
.setExternalDatacenterName("MARS")
105-
.setByteCountBeforeFlushing(params.getByteCountBeforeFlushing())
106-
.setMaxLogLineSize(params.getMaxLogLineSize())
107-
.setMaxLogFlushTime(Duration.ofSeconds(params.getMaxLogFlushSeconds()))
116+
.setByteCountBeforeFlushing(BYTE_COUNT_BEFORE_FLUSHING)
117+
.setMaxLogLineSize(MAX_LOG_LINE_SIZE)
118+
.setMaxLogFlushTime(MAX_LOG_FLUSH_TIME)
108119
.setCoordinator(coordinator)
109-
.setDisableApiCallLogging(params.getDisableApiCallLogging())
120+
.setDisableApiCallLogging(disableApiCallLogging)
110121
.build();
111122

112123
RequestManager.Builder requestManagerBuilder =
113124
RequestManager.builder()
114-
.setSoftDeadlineDelay(AppEngineConstants.SOFT_DEADLINE_DELAY_MS)
125+
.setSoftDeadlineDelay(SOFT_DEADLINE_DELAY_MS)
115126
.setRuntimeLogSink(Optional.of(logSink))
116127
.setApiProxyImpl(apiProxyImpl)
117-
.setMaxOutstandingApiRpcs(params.getCloneMaxOutstandingApiRpcs())
118-
.setThreadStopTerminatesClone(params.getThreadStopTerminatesClone())
119-
.setCyclesPerSecond(AppEngineConstants.CYCLES_PER_SECOND);
128+
.setMaxOutstandingApiRpcs(params.getMaxOutstandingApiRpcs())
129+
.setThreadStopTerminatesClone(THREAD_STOP_TERMINATES_CLONE)
130+
.setCyclesPerSecond(CYCLES_PER_SECOND);
120131

121132
RequestManager requestManager = makeRequestManager(requestManagerBuilder);
122133
apiProxyImpl.setRequestManager(requestManager);
@@ -134,7 +145,7 @@ public JavaRuntime getStartedRuntime(NullSandboxPlugin sandboxPlugin, String[] a
134145
.setConfiguration(configuration)
135146
.setDeadlineOracle(deadlineOracle)
136147
.setCoordinator(coordinator)
137-
.setForceUrlfetchUrlStreamHandler(params.getForceUrlfetchUrlStreamHandler())
148+
.setForceUrlfetchUrlStreamHandler(FORCE_URLFETCH_URL_STREAM_HANDLER)
138149
.setFixedApplicationPath(params.getFixedApplicationPath());
139150

140151
JavaRuntime runtime = makeRuntime(runtimeBuilder);
@@ -145,8 +156,8 @@ public JavaRuntime getStartedRuntime(NullSandboxPlugin sandboxPlugin, String[] a
145156
.setApplicationRoot("notused")
146157
.setFixedApplicationPath(params.getFixedApplicationPath())
147158
.setJettyHttpAddress(HostAndPort.fromParts("0.0.0.0", params.getJettyHttpPort()))
148-
.setJettyRequestHeaderSize(AppEngineConstants.JETTY_REQUEST_HEADER_SIZE)
149-
.setJettyResponseHeaderSize(AppEngineConstants.JETTY_RESPONSE_HEADER_SIZE)
159+
.setJettyRequestHeaderSize(JETTY_REQUEST_HEADER_SIZE)
160+
.setJettyResponseHeaderSize(JETTY_RESPONSE_HEADER_SIZE)
150161
.setEvaluationRuntimeServerInterface(runtime)
151162
.build();
152163
try {
@@ -170,37 +181,23 @@ public RequestManager makeRequestManager(RequestManager.Builder builder) {
170181
return builder.build();
171182
}
172183

173-
/** Creates the ServletEngineAdapter specifies by the --servlet_engine flag. */
174-
private static ServletEngineAdapter createServletEngine(JavaRuntimeParams params) {
175-
Class<? extends ServletEngineAdapter> engineClazz = params.getServletEngine();
176-
if (engineClazz == null) {
177-
throw new RuntimeException("No servlet engine (--servlet_engine) defined in the parameters.");
184+
/** Creates the ServletEngineAdapter. */
185+
private static ServletEngineAdapter createServletEngine() {
186+
String servletEngine;
187+
if (Boolean.getBoolean("appengine.use.EE8")
188+
|| Boolean.getBoolean("appengine.use.EE10")
189+
|| Boolean.getBoolean("appengine.use.EE11")) {
190+
servletEngine = "com.google.apphosting.runtime.jetty.JettyServletEngineAdapter";
191+
} else {
192+
servletEngine = "com.google.apphosting.runtime.jetty9.JettyServletEngineAdapter";
178193
}
194+
179195
try {
196+
Class<? extends ServletEngineAdapter> engineClazz =
197+
Class.forName(servletEngine).asSubclass(ServletEngineAdapter.class);
180198
return engineClazz.getConstructor().newInstance();
181199
} catch (ReflectiveOperationException ex) {
182-
throw new RuntimeException("Failed to instantiate " + engineClazz, ex);
183-
}
184-
}
185-
186-
private static void maybeConfigureProfiler(JavaRuntimeParams params) {
187-
if (params.getEnableCloudCpuProfiler() || params.getEnableCloudHeapProfiler()) {
188-
try {
189-
Class<?> profilerClass = Class.forName("com.google.cloud.profiler.agent.Profiler");
190-
Class<?> profilerConfigClass =
191-
Class.forName("com.google.cloud.profiler.agent.Profiler$Config");
192-
Object profilerConfig = profilerConfigClass.getConstructor().newInstance();
193-
Method setCpuProfilerEnabled =
194-
profilerConfigClass.getMethod("setCpuProfilerEnabled", boolean.class);
195-
Method setHeapProfilerEnabled =
196-
profilerConfigClass.getMethod("setHeapProfilerEnabled", boolean.class);
197-
setCpuProfilerEnabled.invoke(profilerConfig, params.getEnableCloudCpuProfiler());
198-
setHeapProfilerEnabled.invoke(profilerConfig, params.getEnableCloudHeapProfiler());
199-
Method start = profilerClass.getMethod("start", profilerConfigClass);
200-
start.invoke(null, profilerConfig);
201-
} catch (Exception e) {
202-
logger.atWarning().withCause(e).log("Failed to start the profiler");
203-
}
200+
throw new VerifyException("Failed to instantiate " + servletEngine, ex);
204201
}
205202
}
206203
}

0 commit comments

Comments
 (0)