mirror of https://github.com/apache/druid.git
Fixing overlord issued too many redirects (#12908)
* Fixing race in overlord redirects where the node was redirecting to itself * Fixing test cases
This commit is contained in:
parent
f70f7b4b89
commit
a3a9c5f409
|
@ -232,6 +232,19 @@ public class TaskMaster implements TaskCountStatsProvider, TaskSlotCountStatsPro
|
||||||
return overlordLeaderSelector.getCurrentLeader();
|
return overlordLeaderSelector.getCurrentLeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<String> getRedirectLocation()
|
||||||
|
{
|
||||||
|
String leader = overlordLeaderSelector.getCurrentLeader();
|
||||||
|
// do not redirect when
|
||||||
|
// leader is not elected
|
||||||
|
// leader is the current node
|
||||||
|
if (leader == null || leader.isEmpty() || overlordLeaderSelector.isLeader()) {
|
||||||
|
return Optional.absent();
|
||||||
|
} else {
|
||||||
|
return Optional.of(leader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<TaskRunner> getTaskRunner()
|
public Optional<TaskRunner> getTaskRunner()
|
||||||
{
|
{
|
||||||
if (isLeader()) {
|
if (isLeader()) {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.apache.druid.indexing.overlord.http;
|
package org.apache.druid.indexing.overlord.http;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import org.apache.druid.indexing.overlord.TaskMaster;
|
import org.apache.druid.indexing.overlord.TaskMaster;
|
||||||
|
@ -55,13 +56,12 @@ public class OverlordRedirectInfo implements RedirectInfo
|
||||||
public URL getRedirectURL(String queryString, String requestURI)
|
public URL getRedirectURL(String queryString, String requestURI)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
final String leader = taskMaster.getCurrentLeader();
|
final Optional<String> redirectLocation = taskMaster.getRedirectLocation();
|
||||||
if (leader == null || leader.isEmpty()) {
|
if (!redirectLocation.isPresent()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String location = StringUtils.format("%s%s", leader, requestURI);
|
String location = StringUtils.format("%s%s", redirectLocation.get(), requestURI);
|
||||||
|
|
||||||
if (queryString != null) {
|
if (queryString != null) {
|
||||||
location = StringUtils.format("%s?%s", location, queryString);
|
location = StringUtils.format("%s?%s", location, queryString);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.apache.druid.indexing.overlord.http;
|
package org.apache.druid.indexing.overlord.http;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
import org.apache.druid.indexing.overlord.TaskMaster;
|
import org.apache.druid.indexing.overlord.TaskMaster;
|
||||||
import org.easymock.EasyMock;
|
import org.easymock.EasyMock;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -66,19 +67,9 @@ public class OverlordRedirectInfoTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetRedirectURLNull()
|
public void testGetRedirectURLWithEmptyLocation()
|
||||||
{
|
{
|
||||||
EasyMock.expect(taskMaster.getCurrentLeader()).andReturn(null).anyTimes();
|
EasyMock.expect(taskMaster.getRedirectLocation()).andReturn(Optional.absent()).anyTimes();
|
||||||
EasyMock.replay(taskMaster);
|
|
||||||
URL url = redirectInfo.getRedirectURL("query", "/request");
|
|
||||||
Assert.assertNull(url);
|
|
||||||
EasyMock.verify(taskMaster);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetRedirectURLEmpty()
|
|
||||||
{
|
|
||||||
EasyMock.expect(taskMaster.getCurrentLeader()).andReturn("").anyTimes();
|
|
||||||
EasyMock.replay(taskMaster);
|
EasyMock.replay(taskMaster);
|
||||||
URL url = redirectInfo.getRedirectURL("query", "/request");
|
URL url = redirectInfo.getRedirectURL("query", "/request");
|
||||||
Assert.assertNull(url);
|
Assert.assertNull(url);
|
||||||
|
@ -91,7 +82,7 @@ public class OverlordRedirectInfoTest
|
||||||
String host = "http://localhost";
|
String host = "http://localhost";
|
||||||
String query = "foo=bar&x=y";
|
String query = "foo=bar&x=y";
|
||||||
String request = "/request";
|
String request = "/request";
|
||||||
EasyMock.expect(taskMaster.getCurrentLeader()).andReturn(host).anyTimes();
|
EasyMock.expect(taskMaster.getRedirectLocation()).andReturn(Optional.of(host)).anyTimes();
|
||||||
EasyMock.replay(taskMaster);
|
EasyMock.replay(taskMaster);
|
||||||
URL url = redirectInfo.getRedirectURL(query, request);
|
URL url = redirectInfo.getRedirectURL(query, request);
|
||||||
Assert.assertEquals("http://localhost/request?foo=bar&x=y", url.toString());
|
Assert.assertEquals("http://localhost/request?foo=bar&x=y", url.toString());
|
||||||
|
@ -107,7 +98,7 @@ public class OverlordRedirectInfoTest
|
||||||
"UTF-8"
|
"UTF-8"
|
||||||
) + "/status";
|
) + "/status";
|
||||||
|
|
||||||
EasyMock.expect(taskMaster.getCurrentLeader()).andReturn(host).anyTimes();
|
EasyMock.expect(taskMaster.getRedirectLocation()).andReturn(Optional.of(host)).anyTimes();
|
||||||
EasyMock.replay(taskMaster);
|
EasyMock.replay(taskMaster);
|
||||||
URL url = redirectInfo.getRedirectURL(null, request);
|
URL url = redirectInfo.getRedirectURL(null, request);
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(
|
||||||
|
|
|
@ -80,7 +80,6 @@ import org.junit.Test;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -217,6 +216,7 @@ public class OverlordTest
|
||||||
Thread.sleep(10);
|
Thread.sleep(10);
|
||||||
}
|
}
|
||||||
Assert.assertEquals(taskMaster.getCurrentLeader(), druidNode.getHostAndPort());
|
Assert.assertEquals(taskMaster.getCurrentLeader(), druidNode.getHostAndPort());
|
||||||
|
Assert.assertEquals(Optional.absent(), taskMaster.getRedirectLocation());
|
||||||
|
|
||||||
final TaskStorageQueryAdapter taskStorageQueryAdapter = new TaskStorageQueryAdapter(taskStorage, taskLockbox);
|
final TaskStorageQueryAdapter taskStorageQueryAdapter = new TaskStorageQueryAdapter(taskStorage, taskLockbox);
|
||||||
final WorkerTaskRunnerQueryAdapter workerTaskRunnerQueryAdapter = new WorkerTaskRunnerQueryAdapter(taskMaster, null);
|
final WorkerTaskRunnerQueryAdapter workerTaskRunnerQueryAdapter = new WorkerTaskRunnerQueryAdapter(taskMaster, null);
|
||||||
|
|
|
@ -200,7 +200,12 @@ public class ServiceClientImpl implements ServiceClient
|
||||||
final String newUri = result.error().getResponse().headers().get("Location");
|
final String newUri = result.error().getResponse().headers().get("Location");
|
||||||
|
|
||||||
if (redirectCount >= MAX_REDIRECTS) {
|
if (redirectCount >= MAX_REDIRECTS) {
|
||||||
retVal.setException(new RpcException("Service [%s] issued too many redirects", serviceName));
|
retVal.setException(new RpcException(
|
||||||
|
"Service [%s] redirected too many times [%d] to invalid url %s",
|
||||||
|
serviceName,
|
||||||
|
redirectCount,
|
||||||
|
newUri
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
// Update preferredLocationNoPath if we got a redirect.
|
// Update preferredLocationNoPath if we got a redirect.
|
||||||
final ServiceLocation redirectLocationNoPath = serviceLocationNoPathFromUri(newUri);
|
final ServiceLocation redirectLocationNoPath = serviceLocationNoPathFromUri(newUri);
|
||||||
|
@ -212,7 +217,12 @@ public class ServiceClientImpl implements ServiceClient
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
retVal.setException(
|
retVal.setException(
|
||||||
new RpcException("Service [%s] redirected to invalid URL [%s]", serviceName, newUri)
|
new RpcException(
|
||||||
|
"Service [%s] redirected [%d] times to invalid URL [%s]",
|
||||||
|
serviceName,
|
||||||
|
redirectCount,
|
||||||
|
newUri
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,7 +289,7 @@ public class ServiceClientImplTest
|
||||||
MatcherAssert.assertThat(e.getCause(), CoreMatchers.instanceOf(RpcException.class));
|
MatcherAssert.assertThat(e.getCause(), CoreMatchers.instanceOf(RpcException.class));
|
||||||
MatcherAssert.assertThat(
|
MatcherAssert.assertThat(
|
||||||
e.getCause(),
|
e.getCause(),
|
||||||
ThrowableMessageMatcher.hasMessage(CoreMatchers.containsString("too many redirects"))
|
ThrowableMessageMatcher.hasMessage(CoreMatchers.containsString("redirected too many times"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,7 +313,8 @@ public class ServiceClientImplTest
|
||||||
MatcherAssert.assertThat(e.getCause(), CoreMatchers.instanceOf(RpcException.class));
|
MatcherAssert.assertThat(e.getCause(), CoreMatchers.instanceOf(RpcException.class));
|
||||||
MatcherAssert.assertThat(
|
MatcherAssert.assertThat(
|
||||||
e.getCause(),
|
e.getCause(),
|
||||||
ThrowableMessageMatcher.hasMessage(CoreMatchers.containsString("redirected to invalid URL [invalid-url]"))
|
ThrowableMessageMatcher.hasMessage(
|
||||||
|
CoreMatchers.containsString("redirected [0] times to invalid URL [invalid-url]"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,7 +338,7 @@ public class ServiceClientImplTest
|
||||||
MatcherAssert.assertThat(e.getCause(), CoreMatchers.instanceOf(RpcException.class));
|
MatcherAssert.assertThat(e.getCause(), CoreMatchers.instanceOf(RpcException.class));
|
||||||
MatcherAssert.assertThat(
|
MatcherAssert.assertThat(
|
||||||
e.getCause(),
|
e.getCause(),
|
||||||
ThrowableMessageMatcher.hasMessage(CoreMatchers.containsString("redirected to invalid URL [null]"))
|
ThrowableMessageMatcher.hasMessage(CoreMatchers.containsString("redirected [0] times to invalid URL [null]"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,7 +362,7 @@ public class ServiceClientImplTest
|
||||||
MatcherAssert.assertThat(e.getCause(), CoreMatchers.instanceOf(RpcException.class));
|
MatcherAssert.assertThat(e.getCause(), CoreMatchers.instanceOf(RpcException.class));
|
||||||
MatcherAssert.assertThat(
|
MatcherAssert.assertThat(
|
||||||
e.getCause(),
|
e.getCause(),
|
||||||
ThrowableMessageMatcher.hasMessage(CoreMatchers.containsString("too many redirects"))
|
ThrowableMessageMatcher.hasMessage(CoreMatchers.containsString("redirected too many times"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue