diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/AppReportFetcher.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/AppReportFetcher.java index 6b79e19..364d264 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/AppReportFetcher.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/AppReportFetcher.java @@ -34,12 +34,20 @@ import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; import org.apache.hadoop.yarn.factories.RecordFactory; import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.apache.hadoop.yarn.api.records.YarnApplicationState.FAILED; +import static org.apache.hadoop.yarn.api.records.YarnApplicationState.FINISHED; +import static org.apache.hadoop.yarn.api.records.YarnApplicationState.KILLED; /** * This class abstracts away how ApplicationReports are fetched. */ public class AppReportFetcher { enum AppReportSource { RM, AHS } + private static final Logger LOG = LoggerFactory.getLogger( + AppReportFetcher.class); private final Configuration conf; private final ApplicationClientProtocol applicationsManager; private final ApplicationHistoryProtocol historyManager; @@ -134,6 +142,25 @@ public FetchedAppReport getApplicationReport(ApplicationId appId) getApplicationReport(request).getApplicationReport(); fetchedAppReport = new FetchedAppReport(appReport, AppReportSource.AHS); } + + // if AHS is enabled and the application state is killed/finished/failed, + // get ApplicationReport from AHS prior to RM. + // So that WebAppProxyServlet would redirect track url to AHS instead of RM. + if (isAHSEnabled + && fetchedAppReport.getAppReportSource() == AppReportSource.RM + && (appReport.getYarnApplicationState() == KILLED + || appReport.getYarnApplicationState() == FINISHED + || appReport.getYarnApplicationState() == FAILED)) { + try { + ApplicationReport ahsAppReport = historyManager. + getApplicationReport(request).getApplicationReport(); + fetchedAppReport = new FetchedAppReport(ahsAppReport, + AppReportSource.AHS); + } catch (ApplicationNotFoundException e) { + LOG.warn("Failed to get the application report from AHS, just skip" + + "it."); + } + } return fetchedAppReport; } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxyServlet.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxyServlet.java index c804f72..53db801 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxyServlet.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxyServlet.java @@ -625,7 +625,6 @@ private FetchedAppReport getFetchedAppReport(ApplicationId id) * again... If this method returns true, there was a redirect, and * it was handled by redirecting the current request to an error page. * - * @param path the part of the request path after the app id * @param id the app id * @param req the request object * @param resp the response object diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/test/java/org/apache/hadoop/yarn/server/webproxy/TestAppReportFetcher.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/test/java/org/apache/hadoop/yarn/server/webproxy/TestAppReportFetcher.java index bcab33f..a9163a2 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/test/java/org/apache/hadoop/yarn/server/webproxy/TestAppReportFetcher.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/test/java/org/apache/hadoop/yarn/server/webproxy/TestAppReportFetcher.java @@ -35,6 +35,9 @@ import org.junit.Test; import org.mockito.Mockito; +import static org.apache.hadoop.yarn.api.records.YarnApplicationState.FINISHED; +import static org.mockito.Mockito.doReturn; + public class TestAppReportFetcher { static ApplicationHistoryProtocol historyManager; @@ -59,7 +62,25 @@ public void testHelper(boolean isAHSEnabled) .getApplicationReport(Mockito.any(GetApplicationReportRequest.class))) .thenThrow(new ApplicationNotFoundException(appNotFoundExceptionMsg)); fetcher = new AppReportFetcherForTest(conf, appManager); - ApplicationId appId = ApplicationId.newInstance(0,0); + ApplicationId appId = ApplicationId.newInstance(0, 0); + fetcher.getApplicationReport(appId); + } + + public void testHelperWithFinishedApplication(boolean isAHSEnabled) + throws YarnException, IOException { + conf.setBoolean(YarnConfiguration.APPLICATION_HISTORY_ENABLED, + isAHSEnabled); + appManager = Mockito.mock(ApplicationClientProtocol.class); + ApplicationReport appReport = Mockito.mock(ApplicationReport.class); + Mockito.when(appReport.getYarnApplicationState()) + .thenReturn(FINISHED); + GetApplicationReportResponse reportResponse = + Mockito.mock(GetApplicationReportResponse.class); + doReturn(appReport).when(reportResponse).getApplicationReport(); + doReturn(reportResponse).when(appManager).getApplicationReport( + Mockito.any(GetApplicationReportRequest.class)); + fetcher = new AppReportFetcherForTest(conf, appManager); + ApplicationId appId = ApplicationId.newInstance(0, 0); fetcher.getApplicationReport(appId); } @@ -90,6 +111,16 @@ public void testFetchReportAHSDisabled() throws YarnException, IOException { } } + @Test + public void testFetchReportAHSEnabledWithFinishedApplication() + throws YarnException, IOException { + testHelperWithFinishedApplication(true); + Mockito.verify(historyManager, Mockito.times(1)) + .getApplicationReport(Mockito.any(GetApplicationReportRequest.class)); + Mockito.verify(appManager, Mockito.times(1)) + .getApplicationReport(Mockito.any(GetApplicationReportRequest.class)); + } + static class AppReportFetcherForTest extends AppReportFetcher { public AppReportFetcherForTest(Configuration conf,