[英]How can I get PCF App Manager to display information about my detected as Spring Boot Application?
我有一個正在部署到 Pivotal Cloud Foundry (PCF) 的 Spring 引導應用程序。 PCF 將應用程序識別為 Spring 引導應用程序。 但是,沒有任何信息顯示。
應用程序正在使用上下文路徑運行。 已添加配置以重新映射:
從外部到上下文路徑。 我可以在瀏覽器中打開/actuator/prometheus
和/health
。
/cloudfoundryapplication
返回HTTP 401錯誤頁面。
我已經添加
management:
cloudfoundry:
enabled: true
skip-ssl-validation: true
到application.yml
。
Spring 安全正在運行,但配置為忽略以下所有 URL。
@Override
public void configure(WebSecurity web) throws Exception
{
web.ignoring()
.antMatchers("/health",
"/actuator/health",
"/actuator/prometheus",
"/cloudfoundryapplication",
"/actuator/cloudfoundryapplication",
"/cloudfoundryapplication/**",
//"/report/daily",
"/index.html",
"/index.html**",
"/favicon.ico");
}
那么我怎樣才能讓 PCF 真正顯示我的應用程序的運行狀況,並將其視為 Spring 啟動應用程序呢?
更新:該應用程序已經在其上下文路徑之外提供 URL。 我已經列出了它所服務的 URL。 這是執行此操作的 class。 PCF 將應用識別為 Spring Boot,但沒有顯示 forms 或信息。
@Configuration
public class CloudMetricsConfig
{
@Bean
public TomcatServletWebServerFactory servletWebServerFactory()
{
return new TomcatServletWebServerFactory()
{
@Override
protected void prepareContext(Host host, ServletContextInitializer[] initializers)
{
super.prepareContext(host, initializers);
addContext(host, "/cloudfoundryapplication", getContextPath(),
"cloudfoundry");
addContext(host, "/actuator/prometheus", getContextPath(),
"prometheus");
addContext(host, "/health", getContextPath(),
"health");
}
};
}
private void addContext(Host host, String path, String contextPath,
String servletName)
{
StandardContext child = new StandardContext();
child.addLifecycleListener(new Tomcat.FixContextListener());
child.setPath(path);
ServletContainerInitializer initializer =
getServletContextInitializer(contextPath, servletName, path);
child.addServletContainerInitializer(initializer, Collections.emptySet());
child.setCrossContext(true);
host.addChild(child);
}
private ServletContainerInitializer getServletContextInitializer(String contextPath,
String servletName,
String path)
{
return (c, context) ->
{
Servlet servlet = new GenericServlet()
{
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
ServletContext context = req.getServletContext().getContext(contextPath);
context.getRequestDispatcher(path).forward(req, res);
}
};
context.addServlet(servletName, servlet).addMapping("/*");
};
}
}
上面重新映射的三個 URL 被 Spring-Security 設置為忽略。
在 PCF 應用程序管理器中,我可以看到為我的應用程序定義的以下路由。
注意:只有第二條路由將上下文路徑定義為它的一部分。
進一步更新:
App Manager 正在向第一個列出的路由發送請求。 它似乎根本沒有得到回應。
日志看起來應該會響應:
2021-01-22T17:03:19.928-05:00 [RTR/9] [OUT] service-dev.apps.nonprod-mpn.ro11.company.com - [2021-01-22T22:03:19.918937681Z]”選項 /exe/v2/cloudfoundryapplication/health HTTP/1.1" 200 0 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1. 15“” 10.204.253.14:53711“” 10.195.121.117:61118“ x_forwarded_for:” 10.90.161.66,10.204.253.14“ x_forwarded_proto:” 0.003056 app_id:"ea6df148-1809-4f02-87ac-39b4ea0ebeac" app_index:"0" x_cf_routererror:"-" x_b3_traceid:"9afab521ad427253" x_b3_spanid:"9afab521ad427253" x_b3_parentspanid:"-" b3:"9afab521ad427253-9afab521ad427253"
但在 Safari 中它說:
回復
沒有響應頭
這是專門針對/cloudfoundryapplication/health端點的。
/cloudfoundryapplication成功返回響應。
應用程序正在使用上下文路徑運行。
這需要特殊處理才能使其工作。 通過使用上下文路徑, /cloudfoundryapplication
端點不再可用。 它是/your-context-path/cloudfoundryapplication
。 這意味着應用程序管理器將找不到它。
看...
- 如果已配置自定義 servlet 上下文路徑,則 Spring 引導執行器端點將不再位於
/cloudfoundryapplication
路徑。
從這篇知識庫文章中。
有一種解決方法, 在此處記錄(當我寫這篇文章時,KB 中的鏈接是錯誤的,但我會修復它)。
報價:
配置因使用的 web 服務器而異。 對於Tomcat,可以添加如下配置:
@Bean
public TomcatServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
super.prepareContext(host, initializers);
StandardContext child = new StandardContext();
child.addLifecycleListener(new Tomcat.FixContextListener());
child.setPath("/cloudfoundryapplication");
ServletContainerInitializer initializer = getServletContextInitializer(getContextPath());
child.addServletContainerInitializer(initializer, Collections.emptySet());
child.setCrossContext(true);
host.addChild(child);
}
};
}
private ServletContainerInitializer getServletContextInitializer(String contextPath) {
return (c, context) -> {
Servlet servlet = new GenericServlet() {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
ServletContext context = req.getServletContext().getContext(contextPath);
context.getRequestDispatcher("/cloudfoundryapplication").forward(req, res);
}
};
context.addServlet("cloudfoundry", servlet).addMapping("/*");
};
}
這樣做是在您的嵌入式 Tomcat 中設置第二個上下文,它將查找/cloudfoundryapplication
(從根目錄)並將這些請求轉發到您的實際應用程序上下文下的/cloudfoundryapplication
(它使用跨上下文支持來執行此操作)。
因此,當應用程序管理器將請求發送到您的https://<host>.apps.example.com/cloudfoundryapplication
時,它會轉發到https://<host>.apps.example.com/<context-path>/cloudfoundryapplication
,它到達了它需要的地方。
但這只是成功的一半。
重要的是要了解,要使其正常工作,您仍然需要在 Cloud Foundry 中為該流量映射一個路由。 否則,來自應用程序管理器的流量將不會進入您的應用程序。 如果您使用--path
映射路由,那將是不夠的,因為這只會將該路徑的流量發送到您的應用程序,並且/cloudfoundryapplication
請求(這是一條不同的路徑)永遠不會在您的應用程序中結束使用上面的解決方法。
例如,如果您已映射路線https://<host>.apps.example.com/<context-path>
,則平台只會將針對該確切主機和路徑的流量發送到您的應用程序。 由於https://<host>.apps.example.com/cloudfoundryapplication
不在該路徑下,因此到它的流量將永遠不會到達您的應用程序(它可能是 go 到其他一些應用程序,所以您必須小心)。
要使用此解決方法 function,您需要有一條沒有路徑的路由或兩條路由,一條帶有您的上下文路徑,一條帶有/cloudfoundryapplication
。
例如:
a.) https://<host>.apps.example.com
b.) https://<host>.apps.example.com/<context-path>
+ https://<host>.apps.example.com/cloudfoundryapplication
。
這實質上意味着您只能對每個主機名使用一個 Spring 引導應用程序使用此解決方法,因為所有 Spring 引導應用程序都需要在相同的/cloudfoundryapplication
路徑上接收請求,並且只有一個應用程序可以映射到該路由(從技術上講,您可以 Z1D78AE5DC8ED51244E到多個應用程序的路由,但這會導致流量在所有應用程序之間循環分配,這不是您想要的)。
最后一點,你提到...
已添加配置以重新映射:
我在您發布的信息中沒有看到這一點。 您有一些 Spring 安全代碼,但這只會禁用這些 URL 的 Spring 安全性,而不是重新映射/重定向 URL。 如果您在其他地方重新映射 URL,請忽略此注釋。 只是想指出這一點。 如果您期望它重新映射/重定向它們,它不會。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.