注意:这是一个交叉帖子,因为我不确定这是技术问题还是错误,因此可以在here
找到该错误几周前,我编写了一个原型,用于向我们的 appengine 项目添加灵活的环境服务,该项目主要是标准环境服务。该原型基于 java 快速入门示例“HelloworldSpringBoot”并进行了一些细微修改。
在原型取得成功后,我转向了该服务的更多生产代码集,开发了几周,并尝试在 4 天前的 1 月 12 日进行部署。该应用程序拒绝启动,在多次尝试将应用程序简化为单一路线后,我无法启动该应用程序。
我切换回原型代码,部署到代码正在运行的原始项目,并且看到应用程序未启动的相同行为。
没有任何错误消息可以指出,因此我将在此处列出一些可能是罪魁祸首的错误消息。
第一个是最明显的,但可能是一个通用的包罗万象的:
Exception in thread "main" java.lang.IllegalStateException: No Available Context
at com.google.cloud.runtimes.jetty9.DeploymentCheck.lifeCycleStarted(DeploymentCheck.java:46)
at org.eclipse.jetty.util.component.AbstractLifeCycle.setStarted(AbstractLifeCycle.java:179)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:69)
at org.eclipse.jetty.xml.XmlConfiguration$1.run(XmlConfiguration.java:1511)
at org.eclipse.jetty.xml.XmlConfiguration$1.run(XmlConfiguration.java:1438)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.jetty.xml.XmlConfiguration.main(XmlConfiguration.java:1437)
下一个发生在启动的更早阶段,但看起来是良性的:
javax.servlet.ServletException: Not running on Jetty, JSR-356 support unavailable at org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer.onStartup(WebSocketServerContainerInitializer.java:193) at org.eclipse.jetty.plus.annotation.ContainerInitializer.callStartup(ContainerInitializer.java:140) at org.eclipse.jetty.annotations.ServletContainerInitializersStarter.doStart(ServletContainerInitializersStarter.java:63) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:329) at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1501) at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1463) at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:785) at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:261) at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:545) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) at org.eclipse.jetty.deploy.bindings.StandardStarter.processBinding(StandardStarter.java:41) at org.eclipse.jetty.deploy.AppLifeCycle.runBindings(AppLifeCycle.java:188) at org.eclipse.jetty.deploy.DeploymentManager.requestAppGoal(DeploymentManager.java:502) at org.eclipse.jetty.deploy.DeploymentManager.addApp(DeploymentManager.java:150) at org.eclipse.jetty.deploy.providers.ScanningAppProvider.fileAdded(ScanningAppProvider.java:180) at org.eclipse.jetty.deploy.providers.WebAppProvider.fileAdded(WebAppProvider.java:447) at org.eclipse.jetty.deploy.providers.ScanningAppProvider$1.fileAdded(ScanningAppProvider.java:64) at org.eclipse.jetty.util.Scanner.reportAddition(Scanner.java:610) at org.eclipse.jetty.util.Scanner.reportDifferences(Scanner.java:529) at org.eclipse.jetty.util.Scanner.scan(Scanner.java:392) at org.eclipse.jetty.util.Scanner.doStart(Scanner.java:313) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) at org.eclipse.jetty.deploy.providers.ScanningAppProvider.doStart(ScanningAppProvider.java:150) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) at org.eclipse.jetty.deploy.DeploymentManager.startAppProvider(DeploymentManager.java:564) at org.eclipse.jetty.deploy.DeploymentManager.doStart(DeploymentManager.java:239) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131) at org.eclipse.jetty.server.Server.start(Server.java:452) at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:113) at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113) at org.eclipse.jetty.server.Server.doStart(Server.java:419) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) at org.eclipse.jetty.xml.XmlConfiguration$1.run(XmlConfiguration.java:1511) at org.eclipse.jetty.xml.XmlConfiguration$1.run(XmlConfiguration.java:1438) at java.security.AccessController.doPrivileged(Native Method) at org.eclipse.jetty.xml.XmlConfiguration.main(XmlConfiguration.java:1437)
然后就是这个家伙,就在上一个之后发生:
org.eclipse.jetty.webapp.WebAppContext: Failed startup of context o.e.j.w.WebAppContext@7e0b0338{/,file:///var/lib/jetty/webapps/root/,UNAVAILABLE}{/root.war}
此外,以下是相关文件:
app.yaml:
runtime: java
env: flex
runtime_config: # Optional
jdk: openjdk8
service: service2
handlers:
- url: /.*
script: this field is required, but ignored
manual_scaling:
instances: 1
构建.gradle:
buildscript { // Configuration for building
ext {
springBootVersion = '1.5.9.RELEASE'
}
repositories {
jcenter() // Bintray's repository - a fast Maven Central mirror & more
mavenCentral()
maven { url 'https://repo.spring.io/libs-snapshot' }
}
dependencies {
classpath 'com.google.cloud.tools:appengine-gradle-plugin:+'
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
}
}
repositories { // repositories for JARs you access in your code
maven {
url 'https://maven-central.storage.googleapis.com' // Google's mirror of Maven Central
}
maven {
url "http://repo.spring.io/libs-snapshot"
}
jcenter()
mavenCentral()
}
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'com.google.cloud.tools.appengine'
apply plugin: 'org.springframework.boot'
dependencies {
// Add your dependencies here.
compile "org.springframework.boot:spring-boot-starter-web", { exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat' }
compile (
"org.springframework.boot:spring-boot-starter-actuator",
"org.springframework.boot:spring-boot-starter-jetty"
)
testCompile (
"org.springframework.boot:spring-boot-starter-test:$springBootVersion"
)
}
appengine {
deploy { // deploy configuration
stopPreviousVersion = true // default - stop the current version
promote = true // default - & make this the current version
}
}
group = 'com.example' // Generated output GroupId
version = '1.0-SNAPSHOT' // Version in generated output
sourceCompatibility = 1.8
targetCompatibility = 1.8
HelloworldApplication.java:
package com.example.java.gettingstarted;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class HelloworldApplication {
@RequestMapping("/service2/")
public String home() {
return "Helloooooooo Nurse!";
}
/**
* (Optional) App Engine health check endpoint mapping.
* @see <a href="https://cloud.google.com/appengine/docs/flexible/java/how-instances-are-managed#health_checking"></a>
* If your app does not handle health checks, a HTTP 404 response is interpreted
* as a successful reply.
*/
@RequestMapping("/_ah/health")
public String healthy() {
// Message body required though ignored
return "Still surviving.";
}
public static void main(String[] args) {
SpringApplication.run(HelloworldApplication.class, args);
}
}
我也在运行 gcloud 版本 184.0.0
解决方案最终有点神奇,但是一旦 appengine 标准文档为我指明了正确的方向,SpringBoot 文档就告诉了我。
请注意,仅当您需要时才需要 WebApplicationInitializer 构建一个 war 文件并部署它。如果您更喜欢运行嵌入式 容器,那么你就根本不需要这个了。
我们正在部署一场战争,它在本地与嵌入式容器一起运行。按照提供的方式设置 jetty 并将神奇的 SpringBootServletInitializer 添加到根目录后,一切就开始工作了。我不知道为什么两周前不需要,但现在肯定需要。
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
System.out.println("ServletInitializer called.");
return application.sources(HelloworldApplication.class);
}
}
将此文件放在根目录就可以了。
感谢您的帮助。