You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by pz...@apache.org on 2018/03/23 18:58:44 UTC
knox git commit: KNOX-1224 - Knox Proxy HADispatcher to support Atlas
in HA (Nixon Rodrigues via Phil Zampino)
Repository: knox
Updated Branches:
refs/heads/master 591e0bd3c -> a6d2f5240
KNOX-1224 - Knox Proxy HADispatcher to support Atlas in HA (Nixon Rodrigues via Phil Zampino)
Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/a6d2f524
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/a6d2f524
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/a6d2f524
Branch: refs/heads/master
Commit: a6d2f52409e1b9cf497d76cd799ad73f17579092
Parents: 591e0bd
Author: Phil Zampino <pz...@apache.org>
Authored: Fri Mar 23 14:10:21 2018 -0400
Committer: Phil Zampino <pz...@apache.org>
Committed: Fri Mar 23 14:10:41 2018 -0400
----------------------------------------------------------------------
.../gateway/ha/dispatch/AtlasApiHaDispatch.java | 82 ++++++++++++
.../gateway/ha/dispatch/AtlasHaDispatch.java | 81 ++++++++++++
.../provider/impl/AtlasZookeeperURLManager.java | 95 ++++++++++++++
...g.apache.knox.gateway.ha.provider.URLManager | 3 +-
.../impl/AtlasZookeeperURLManagerTest.java | 129 +++++++++++++++++++
.../services/atlas-api/0.8.0/service.xml | 2 +-
.../resources/services/atlas/0.8.0/service.xml | 4 +-
7 files changed, 392 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/knox/blob/a6d2f524/gateway-provider-ha/src/main/java/org/apache/knox/gateway/ha/dispatch/AtlasApiHaDispatch.java
----------------------------------------------------------------------
diff --git a/gateway-provider-ha/src/main/java/org/apache/knox/gateway/ha/dispatch/AtlasApiHaDispatch.java b/gateway-provider-ha/src/main/java/org/apache/knox/gateway/ha/dispatch/AtlasApiHaDispatch.java
new file mode 100644
index 0000000..59fbb9e
--- /dev/null
+++ b/gateway-provider-ha/src/main/java/org/apache/knox/gateway/ha/dispatch/AtlasApiHaDispatch.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.knox.gateway.ha.dispatch;
+
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpUriRequest;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public class AtlasApiHaDispatch extends DefaultHaDispatch {
+
+ private static Set<String> REQUEST_EXCLUDE_HEADERS = new HashSet<>();
+
+ static {
+ REQUEST_EXCLUDE_HEADERS.add("Content-Length");
+ }
+
+ public AtlasApiHaDispatch() {
+ setServiceRole("ATLAS-API");
+ }
+
+ @Override
+ public void init() {
+ super.init();
+ }
+
+ @Override
+ public Set<String> getOutboundResponseExcludeHeaders() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<String> getOutboundRequestExcludeHeaders() {
+ return REQUEST_EXCLUDE_HEADERS;
+ }
+
+
+ @Override
+ protected void executeRequest(HttpUriRequest outboundRequest, HttpServletRequest inboundRequest, HttpServletResponse outboundResponse) throws IOException {
+ HttpResponse inboundResponse = null;
+ try {
+ inboundResponse = executeOutboundRequest(outboundRequest);
+ int statusCode = inboundResponse.getStatusLine().getStatusCode();
+ Header originalLocationHeader = inboundResponse.getFirstHeader("Location");
+
+
+ if ((statusCode == HttpServletResponse.SC_MOVED_TEMPORARILY || statusCode == HttpServletResponse.SC_TEMPORARY_REDIRECT) && originalLocationHeader != null) {
+ inboundResponse.removeHeaders("Location");
+ failoverRequest(outboundRequest, inboundRequest, outboundResponse, inboundResponse, new Exception("Atlas HA redirection"));
+ }
+
+ writeOutboundResponse(outboundRequest, inboundRequest, outboundResponse, inboundResponse);
+
+ } catch (IOException e) {
+ LOG.errorConnectingToServer(outboundRequest.getURI().toString(), e);
+ failoverRequest(outboundRequest, inboundRequest, outboundResponse, inboundResponse, e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/a6d2f524/gateway-provider-ha/src/main/java/org/apache/knox/gateway/ha/dispatch/AtlasHaDispatch.java
----------------------------------------------------------------------
diff --git a/gateway-provider-ha/src/main/java/org/apache/knox/gateway/ha/dispatch/AtlasHaDispatch.java b/gateway-provider-ha/src/main/java/org/apache/knox/gateway/ha/dispatch/AtlasHaDispatch.java
new file mode 100644
index 0000000..8d2490d
--- /dev/null
+++ b/gateway-provider-ha/src/main/java/org/apache/knox/gateway/ha/dispatch/AtlasHaDispatch.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.knox.gateway.ha.dispatch;
+
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpUriRequest;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public class AtlasHaDispatch extends DefaultHaDispatch {
+ private static Set<String> REQUEST_EXCLUDE_HEADERS = new HashSet<>();
+
+ static {
+ REQUEST_EXCLUDE_HEADERS.add("Content-Length");
+ }
+
+ public AtlasHaDispatch() {
+ setServiceRole("ATLAS");
+ }
+
+ @Override
+ public void init() {
+ super.init();
+ }
+
+ @Override
+ public Set<String> getOutboundResponseExcludeHeaders() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<String> getOutboundRequestExcludeHeaders() {
+ return REQUEST_EXCLUDE_HEADERS;
+ }
+
+ @Override
+ protected void executeRequest(HttpUriRequest outboundRequest, HttpServletRequest inboundRequest, HttpServletResponse outboundResponse) throws IOException {
+ HttpResponse inboundResponse = null;
+ try {
+ inboundResponse = executeOutboundRequest(outboundRequest);
+
+ int statusCode = inboundResponse.getStatusLine().getStatusCode();
+ Header originalLocationHeader = inboundResponse.getFirstHeader("Location");
+
+ if((statusCode == HttpServletResponse.SC_MOVED_TEMPORARILY || statusCode == HttpServletResponse.SC_TEMPORARY_REDIRECT)
+ && originalLocationHeader != null && !originalLocationHeader.getValue().endsWith("login.jsp")){
+ inboundResponse.removeHeaders("Location");
+ failoverRequest(outboundRequest, inboundRequest, outboundResponse, inboundResponse, new Exception("Atlas HA redirection"));
+ }
+
+ writeOutboundResponse(outboundRequest, inboundRequest, outboundResponse, inboundResponse);
+
+ } catch (IOException e) {
+ LOG.errorConnectingToServer(outboundRequest.getURI().toString(), e);
+ failoverRequest(outboundRequest, inboundRequest, outboundResponse, inboundResponse, e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/a6d2f524/gateway-provider-ha/src/main/java/org/apache/knox/gateway/ha/provider/impl/AtlasZookeeperURLManager.java
----------------------------------------------------------------------
diff --git a/gateway-provider-ha/src/main/java/org/apache/knox/gateway/ha/provider/impl/AtlasZookeeperURLManager.java b/gateway-provider-ha/src/main/java/org/apache/knox/gateway/ha/provider/impl/AtlasZookeeperURLManager.java
new file mode 100644
index 0000000..0f28c37
--- /dev/null
+++ b/gateway-provider-ha/src/main/java/org/apache/knox/gateway/ha/provider/impl/AtlasZookeeperURLManager.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.knox.gateway.ha.provider.impl;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.apache.knox.gateway.ha.provider.HaServiceConfig;
+import org.apache.knox.gateway.ha.provider.impl.i18n.HaMessages;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+
+import java.nio.charset.Charset;
+import java.util.*;
+
+public class AtlasZookeeperURLManager extends DefaultURLManager {
+ private static final HaMessages LOG = MessagesFactory.get(HaMessages.class);
+
+ private String zooKeeperEnsemble;
+
+ private String zooKeeperNamespace;
+
+ public static final String APACHE_ATLAS_ACTIVE_SERVER_INFO = "/active_server_info";
+
+
+ @Override
+ public boolean supportsConfig(HaServiceConfig config) {
+ if (!( config.getServiceName().equalsIgnoreCase("ATLAS") || config.getServiceName().equalsIgnoreCase("ATLAS-API"))) {
+ return false;
+ }
+ String zookeeperEnsemble = config.getZookeeperEnsemble();
+ String zookeeperNamespace = config.getZookeeperNamespace();
+ return zookeeperEnsemble != null && zookeeperNamespace != null && !zookeeperEnsemble.trim().isEmpty() && !zookeeperNamespace.trim().isEmpty();
+ }
+
+ @Override
+ public void setConfig(HaServiceConfig config) {
+ zooKeeperEnsemble = config.getZookeeperEnsemble();
+ zooKeeperNamespace = config.getZookeeperNamespace();
+ setURLs(lookupURLs());
+ }
+
+ public List<String> lookupURLs() {
+
+ List<String> serverHosts = new ArrayList<>();
+ CuratorFramework zooKeeperClient =
+ CuratorFrameworkFactory.builder().connectString(zooKeeperEnsemble)
+ .retryPolicy(new ExponentialBackoffRetry(1000, 3))
+ .build();
+ try {
+
+ zooKeeperClient.start();
+
+ byte[] bytes = zooKeeperClient.getData().forPath("/" + zooKeeperNamespace + APACHE_ATLAS_ACTIVE_SERVER_INFO);
+
+ String activeURL = new String(bytes, Charset.forName("UTF-8"));
+
+ serverHosts.add(activeURL);
+
+ } catch (Exception e) {
+
+ LOG.failedToGetZookeeperUrls(e);
+ throw new RuntimeException(e);
+ } finally {
+ // Close the client connection with ZooKeeper
+ if (zooKeeperClient != null) {
+ zooKeeperClient.close();
+ }
+ }
+ return serverHosts;
+ }
+
+
+
+ @Override
+ public synchronized void markFailed(String url) {
+ setURLs(lookupURLs());
+ super.markFailed(url);
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/a6d2f524/gateway-provider-ha/src/main/resources/META-INF/services/org.apache.knox.gateway.ha.provider.URLManager
----------------------------------------------------------------------
diff --git a/gateway-provider-ha/src/main/resources/META-INF/services/org.apache.knox.gateway.ha.provider.URLManager b/gateway-provider-ha/src/main/resources/META-INF/services/org.apache.knox.gateway.ha.provider.URLManager
index d6b9608..2c74b77 100644
--- a/gateway-provider-ha/src/main/resources/META-INF/services/org.apache.knox.gateway.ha.provider.URLManager
+++ b/gateway-provider-ha/src/main/resources/META-INF/services/org.apache.knox.gateway.ha.provider.URLManager
@@ -19,4 +19,5 @@
org.apache.knox.gateway.ha.provider.impl.HS2ZookeeperURLManager
org.apache.knox.gateway.ha.provider.impl.SOLRZookeeperURLManager
org.apache.knox.gateway.ha.provider.impl.KafkaZookeeperURLManager
-org.apache.knox.gateway.ha.provider.impl.HBaseZookeeperURLManager
\ No newline at end of file
+org.apache.knox.gateway.ha.provider.impl.HBaseZookeeperURLManager
+org.apache.knox.gateway.ha.provider.impl.AtlasZookeeperURLManager
http://git-wip-us.apache.org/repos/asf/knox/blob/a6d2f524/gateway-provider-ha/src/test/java/org/apache/knox/gateway/ha/provider/impl/AtlasZookeeperURLManagerTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-ha/src/test/java/org/apache/knox/gateway/ha/provider/impl/AtlasZookeeperURLManagerTest.java b/gateway-provider-ha/src/test/java/org/apache/knox/gateway/ha/provider/impl/AtlasZookeeperURLManagerTest.java
new file mode 100644
index 0000000..56f4061
--- /dev/null
+++ b/gateway-provider-ha/src/test/java/org/apache/knox/gateway/ha/provider/impl/AtlasZookeeperURLManagerTest.java
@@ -0,0 +1,129 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.ha.provider.impl;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.apache.curator.test.TestingCluster;
+import org.apache.knox.gateway.ha.provider.HaServiceConfig;
+import org.apache.knox.gateway.ha.provider.URLManager;
+import org.apache.knox.gateway.ha.provider.URLManagerLoader;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+public class AtlasZookeeperURLManagerTest {
+
+ private TestingCluster cluster;
+ private AtlasZookeeperURLManager manager;
+ private static String atlasNode1 = "http://atlas.node1:21000";
+ private static String atlasNode2 = "http://atlas.node2:21000";
+
+ @Before
+ public void setup() throws Exception {
+ cluster = new TestingCluster(3);
+ cluster.start();
+
+ CuratorFramework zooKeeperClient =
+ CuratorFrameworkFactory.builder().connectString(cluster.getConnectString())
+ .retryPolicy(new ExponentialBackoffRetry(1000, 3))
+ .build();
+
+ zooKeeperClient.start();
+ zooKeeperClient.create().forPath("/apache_atlas");
+ zooKeeperClient.create().forPath("/apache_atlas/active_server_info");
+ zooKeeperClient.setData().forPath("/apache_atlas/active_server_info",
+ atlasNode1.getBytes(Charset.forName("UTF-8")));
+ zooKeeperClient.close();
+ setAtlasActiveHostURLInZookeeper(atlasNode1);
+
+ manager = new AtlasZookeeperURLManager();
+ HaServiceConfig config = new DefaultHaServiceConfig("ATLAS-API");
+ config.setEnabled(true);
+ config.setZookeeperEnsemble(cluster.getConnectString());
+ config.setZookeeperNamespace("apache_atlas");
+ manager.setConfig(config);
+ }
+
+ @After
+ public void teardown() throws IOException {
+ cluster.stop();
+ }
+
+ @Test
+ public void testAtlasActiveUrlIsSetCorrectlyAfterLookUpFromZK() {
+ manager.lookupURLs();
+ List<String> urls = manager.getURLs();
+ assertEquals(atlasNode1, urls.get(0));
+ }
+
+ @Test
+ public void testMarkFailedCorrectlyResetTheEarlierUrl() throws Exception {
+ setAtlasActiveHostURLInZookeeper(atlasNode2);
+
+ manager.markFailed("http://atlas.node1:21000");
+ List<String> urls = manager.getURLs();
+ assertNotEquals(atlasNode1, urls.get(0));
+ assertEquals(atlasNode2, urls.get(0));
+ }
+
+ @Test
+ public void testAtlasURLManagerLoadingForAtlasApiService() {
+ HaServiceConfig config = new DefaultHaServiceConfig("ATLAS-API");
+ config.setEnabled(true);
+ config.setZookeeperEnsemble(cluster.getConnectString());
+ config.setZookeeperNamespace("apache_atlas");
+ URLManager manager = URLManagerLoader.loadURLManager(config);
+ Assert.assertNotNull(manager);
+ Assert.assertTrue(manager instanceof AtlasZookeeperURLManager);
+ }
+
+ @Test
+ public void testAtlasURLManagerLoadingForAtlasUIService() {
+ HaServiceConfig config = new DefaultHaServiceConfig("ATLAS");
+ config.setEnabled(true);
+ config.setZookeeperEnsemble(cluster.getConnectString());
+ config.setZookeeperNamespace("apache_atlas");
+ URLManager manager = URLManagerLoader.loadURLManager(config);
+ Assert.assertNotNull(manager);
+ Assert.assertTrue(manager instanceof AtlasZookeeperURLManager);
+ }
+
+ void setAtlasActiveHostURLInZookeeper(String activeURL) throws Exception {
+
+ CuratorFramework zooKeeperClient =
+ CuratorFrameworkFactory.builder().connectString(cluster.getConnectString())
+ .retryPolicy(new ExponentialBackoffRetry(1000, 3))
+ .build();
+
+ zooKeeperClient.start();
+ zooKeeperClient.setData().forPath("/apache_atlas/active_server_info",
+ activeURL.getBytes(Charset.forName("UTF-8")));
+ zooKeeperClient.close();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/a6d2f524/gateway-service-definitions/src/main/resources/services/atlas-api/0.8.0/service.xml
----------------------------------------------------------------------
diff --git a/gateway-service-definitions/src/main/resources/services/atlas-api/0.8.0/service.xml b/gateway-service-definitions/src/main/resources/services/atlas-api/0.8.0/service.xml
index 3ae7b24..20662ac 100644
--- a/gateway-service-definitions/src/main/resources/services/atlas-api/0.8.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/atlas-api/0.8.0/service.xml
@@ -28,5 +28,5 @@
<route path="/atlas/api/**"/>
</routes>
- <dispatch classname="org.apache.knox.gateway.dispatch.PassAllHeadersDispatch"/>
+ <dispatch classname="org.apache.knox.gateway.dispatch.PassAllHeadersDispatch" ha-classname="org.apache.knox.gateway.ha.dispatch.AtlasApiHaDispatch"/>
</service>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/a6d2f524/gateway-service-definitions/src/main/resources/services/atlas/0.8.0/service.xml
----------------------------------------------------------------------
diff --git a/gateway-service-definitions/src/main/resources/services/atlas/0.8.0/service.xml b/gateway-service-definitions/src/main/resources/services/atlas/0.8.0/service.xml
index 6d99f30..8899248 100644
--- a/gateway-service-definitions/src/main/resources/services/atlas/0.8.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/atlas/0.8.0/service.xml
@@ -46,6 +46,6 @@
</routes>
- <dispatch classname="org.apache.knox.gateway.dispatch.PassAllHeadersDispatch"/>
+ <dispatch classname="org.apache.knox.gateway.dispatch.PassAllHeadersDispatch" ha-classname="org.apache.knox.gateway.ha.dispatch.AtlasHaDispatch" />
-</service>
\ No newline at end of file
+</service>