Search in sources :

Example 81 with StringFullResponseHolder

use of org.apache.druid.java.util.http.client.response.StringFullResponseHolder in project druid by apache.

the class IndexTaskClient method submitRequest.

/**
 * Sends an HTTP request to the task of the specified {@code taskId} and returns a response if it succeeded.
 */
protected <IntermediateType, FinalType> FinalType submitRequest(String taskId, // nullable if content is empty
@Nullable String mediaType, HttpMethod method, String encodedPathSuffix, @Nullable String encodedQueryString, byte[] content, HttpResponseHandler<IntermediateType, FinalType> responseHandler, boolean retry) throws IOException, ChannelException, NoTaskLocationException {
    final RetryPolicy retryPolicy = retryPolicyFactory.makeRetryPolicy();
    while (true) {
        String path = StringUtils.format("%s/%s/%s", BASE_PATH, StringUtils.urlEncode(taskId), encodedPathSuffix);
        Optional<TaskStatus> status = taskInfoProvider.getTaskStatus(taskId);
        if (!status.isPresent() || !status.get().isRunnable()) {
            throw new TaskNotRunnableException(StringUtils.format("Aborting request because task [%s] is not runnable", taskId));
        }
        final TaskLocation location = taskInfoProvider.getTaskLocation(taskId);
        if (location.equals(TaskLocation.unknown())) {
            throw new NoTaskLocationException(StringUtils.format("No TaskLocation available for task [%s]", taskId));
        }
        final Request request = createRequest(taskId, location, path, encodedQueryString, method, mediaType, content);
        Either<StringFullResponseHolder, FinalType> response = null;
        try {
            // Netty throws some annoying exceptions if a connection can't be opened, which happens relatively frequently
            // for tasks that happen to still be starting up, so test the connection first to keep the logs clean.
            checkConnection(request.getUrl().getHost(), request.getUrl().getPort());
            response = submitRequest(request, responseHandler);
            if (response.isValue()) {
                return response.valueOrThrow();
            } else {
                final StringBuilder exceptionMessage = new StringBuilder();
                final HttpResponseStatus httpResponseStatus = response.error().getStatus();
                final String httpResponseContent = response.error().getContent();
                exceptionMessage.append("Received server error with status [").append(httpResponseStatus).append("]");
                if (!Strings.isNullOrEmpty(httpResponseContent)) {
                    final String choppedMessage = StringUtils.chop(StringUtils.nullToEmptyNonDruidDataString(httpResponseContent), 1000);
                    exceptionMessage.append("; first 1KB of body: ").append(choppedMessage);
                }
                if (httpResponseStatus.getCode() == 400) {
                    // don't bother retrying if it's a bad request
                    throw new IAE(exceptionMessage.toString());
                } else {
                    throw new IOE(exceptionMessage.toString());
                }
            }
        } catch (IOException | ChannelException e) {
            // Since workers are free to move tasks around to different ports, there is a chance that a task may have been
            // moved but our view of its location has not been updated yet from ZK. To detect this case, we send a header
            // identifying our expected recipient in the request; if this doesn't correspond to the worker we messaged, the
            // worker will return an HTTP 404 with its ID in the response header. If we get a mismatching task ID, then
            // we will wait for a short period then retry the request indefinitely, expecting the task's location to
            // eventually be updated.
            final Duration delay;
            if (response != null && !response.isValue() && response.error().getStatus().equals(HttpResponseStatus.NOT_FOUND)) {
                String headerId = StringUtils.urlDecode(response.error().getResponse().headers().get(ChatHandlerResource.TASK_ID_HEADER));
                if (headerId != null && !headerId.equals(taskId)) {
                    log.warn("Expected worker to have taskId [%s] but has taskId [%s], will retry in [%d]s", taskId, headerId, TASK_MISMATCH_RETRY_DELAY_SECONDS);
                    delay = Duration.standardSeconds(TASK_MISMATCH_RETRY_DELAY_SECONDS);
                } else {
                    delay = retryPolicy.getAndIncrementRetryDelay();
                }
            } else {
                delay = retryPolicy.getAndIncrementRetryDelay();
            }
            final String urlForLog = request.getUrl().toString();
            if (!retry) {
                // if retry=false, we probably aren't too concerned if the operation doesn't succeed (i.e. the request was
                // for informational purposes only); log at INFO instead of WARN.
                log.noStackTrace().info(e, "submitRequest failed for [%s]", urlForLog);
                throw e;
            } else if (delay == null) {
                // When retrying, log the final failure at WARN level, since it is likely to be bad news.
                log.warn(e, "submitRequest failed for [%s]", urlForLog);
                throw e;
            } else {
                try {
                    final long sleepTime = delay.getMillis();
                    // When retrying, log non-final failures at INFO level.
                    log.noStackTrace().info(e, "submitRequest failed for [%s]; will try again in [%s]", urlForLog, new Duration(sleepTime).toString());
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e2) {
                    Thread.currentThread().interrupt();
                    e.addSuppressed(e2);
                    throw new RuntimeException(e);
                }
            }
        } catch (NoTaskLocationException e) {
            log.info("No TaskLocation available for task [%s], this task may not have been assigned to a worker yet " + "or may have already completed", taskId);
            throw e;
        } catch (Exception e) {
            log.warn(e, "Exception while sending request");
            throw e;
        }
    }
}
Also used : HttpResponseStatus(org.jboss.netty.handler.codec.http.HttpResponseStatus) Request(org.apache.druid.java.util.http.client.Request) Duration(org.joda.time.Duration) IOException(java.io.IOException) TaskStatus(org.apache.druid.indexer.TaskStatus) IAE(org.apache.druid.java.util.common.IAE) TaskLocation(org.apache.druid.indexer.TaskLocation) MalformedURLException(java.net.MalformedURLException) ChannelException(org.jboss.netty.channel.ChannelException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) StringFullResponseHolder(org.apache.druid.java.util.http.client.response.StringFullResponseHolder) IOE(org.apache.druid.java.util.common.IOE) ChannelException(org.jboss.netty.channel.ChannelException)

Example 82 with StringFullResponseHolder

use of org.apache.druid.java.util.http.client.response.StringFullResponseHolder in project druid by apache.

the class RemoteTaskActionClientTest method testSubmitWithIllegalStatusCode.

@Test
public void testSubmitWithIllegalStatusCode() throws Exception {
    // return status code 400 and a list with size equals 1
    Request request = new Request(HttpMethod.POST, new URL("http://localhost:1234/xx"));
    EasyMock.expect(druidLeaderClient.makeRequest(HttpMethod.POST, "/druid/indexer/v1/action")).andReturn(request);
    // return status code 200 and a list with size equals 1
    final HttpResponse response = EasyMock.createNiceMock(HttpResponse.class);
    EasyMock.expect(response.getStatus()).andReturn(HttpResponseStatus.BAD_REQUEST).anyTimes();
    EasyMock.expect(response.getContent()).andReturn(new BigEndianHeapChannelBuffer(0));
    EasyMock.replay(response);
    StringFullResponseHolder responseHolder = new StringFullResponseHolder(response, StandardCharsets.UTF_8).addChunk("testSubmitWithIllegalStatusCode");
    // set up mocks
    EasyMock.expect(druidLeaderClient.go(request)).andReturn(responseHolder);
    EasyMock.replay(druidLeaderClient);
    Task task = NoopTask.create("id", 0);
    RemoteTaskActionClient client = new RemoteTaskActionClient(task, druidLeaderClient, new RetryPolicyFactory(objectMapper.readValue("{\"maxRetryCount\":0}", RetryPolicyConfig.class)), objectMapper);
    expectedException.expect(IOException.class);
    expectedException.expectMessage("Error with status[400 Bad Request] and message[testSubmitWithIllegalStatusCode]. " + "Check overlord logs for details.");
    client.submit(new LockListAction());
}
Also used : StringFullResponseHolder(org.apache.druid.java.util.http.client.response.StringFullResponseHolder) Task(org.apache.druid.indexing.common.task.Task) NoopTask(org.apache.druid.indexing.common.task.NoopTask) Request(org.apache.druid.java.util.http.client.Request) HttpResponse(org.jboss.netty.handler.codec.http.HttpResponse) BigEndianHeapChannelBuffer(org.jboss.netty.buffer.BigEndianHeapChannelBuffer) RetryPolicyFactory(org.apache.druid.indexing.common.RetryPolicyFactory) URL(java.net.URL) Test(org.junit.Test)

Example 83 with StringFullResponseHolder

use of org.apache.druid.java.util.http.client.response.StringFullResponseHolder in project druid by apache.

the class CoordinatorRuleManager method poll.

public void poll() {
    try {
        StringFullResponseHolder response = druidLeaderClient.go(druidLeaderClient.makeRequest(HttpMethod.GET, RulesResource.RULES_ENDPOINT));
        if (!response.getStatus().equals(HttpResponseStatus.OK)) {
            throw new ISE("Error while polling rules, status[%s] content[%s]", response.getStatus(), response.getContent());
        }
        final Map<String, List<Rule>> map = jsonMapper.readValue(response.getContent(), TYPE_REFERENCE);
        final Map<String, List<Rule>> immutableMapBuilder = Maps.newHashMapWithExpectedSize(map.size());
        map.forEach((k, list) -> immutableMapBuilder.put(k, Collections.unmodifiableList(list)));
        rules.set(Collections.unmodifiableMap(immutableMapBuilder));
    } catch (Exception e) {
        LOG.error(e, "Exception while polling for rules");
    }
}
Also used : StringFullResponseHolder(org.apache.druid.java.util.http.client.response.StringFullResponseHolder) ISE(org.apache.druid.java.util.common.ISE) ArrayList(java.util.ArrayList) List(java.util.List)

Example 84 with StringFullResponseHolder

use of org.apache.druid.java.util.http.client.response.StringFullResponseHolder in project druid by apache.

the class HttpIndexingServiceClient method cancelTask.

@Override
public String cancelTask(String taskId) {
    try {
        final StringFullResponseHolder response = druidLeaderClient.go(druidLeaderClient.makeRequest(HttpMethod.POST, StringUtils.format("/druid/indexer/v1/task/%s/shutdown", StringUtils.urlEncode(taskId))));
        if (!response.getStatus().equals(HttpResponseStatus.OK)) {
            throw new ISE("Failed to cancel task[%s]", taskId);
        }
        final Map<String, Object> resultMap = jsonMapper.readValue(response.getContent(), JacksonUtils.TYPE_REFERENCE_MAP_STRING_OBJECT);
        final String cancelledTaskId = (String) resultMap.get("task");
        Preconditions.checkNotNull(cancelledTaskId, "Null task id returned for task[%s]", taskId);
        Preconditions.checkState(taskId.equals(cancelledTaskId), "Requested to cancel task[%s], but another task[%s] was cancelled!", taskId, cancelledTaskId);
        return cancelledTaskId;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : StringFullResponseHolder(org.apache.druid.java.util.http.client.response.StringFullResponseHolder) ISE(org.apache.druid.java.util.common.ISE) IOException(java.io.IOException)

Example 85 with StringFullResponseHolder

use of org.apache.druid.java.util.http.client.response.StringFullResponseHolder in project druid by apache.

the class HttpIndexingServiceClient method getLockedIntervals.

@Override
public Map<String, List<Interval>> getLockedIntervals(Map<String, Integer> minTaskPriority) {
    try {
        final StringFullResponseHolder responseHolder = druidLeaderClient.go(druidLeaderClient.makeRequest(HttpMethod.POST, "/druid/indexer/v1/lockedIntervals").setContent(MediaType.APPLICATION_JSON, jsonMapper.writeValueAsBytes(minTaskPriority)));
        final Map<String, List<Interval>> response = jsonMapper.readValue(responseHolder.getContent(), new TypeReference<Map<String, List<Interval>>>() {
        });
        return response == null ? Collections.emptyMap() : response;
    } catch (IOException | InterruptedException e) {
        throw new RuntimeException(e);
    }
}
Also used : StringFullResponseHolder(org.apache.druid.java.util.http.client.response.StringFullResponseHolder) ArrayList(java.util.ArrayList) List(java.util.List) IOException(java.io.IOException) HashMap(java.util.HashMap) Map(java.util.Map) Interval(org.joda.time.Interval)

Aggregations

StringFullResponseHolder (org.apache.druid.java.util.http.client.response.StringFullResponseHolder)86 Test (org.junit.Test)56 URL (java.net.URL)50 Request (org.apache.druid.java.util.http.client.Request)49 HashMap (java.util.HashMap)32 IOException (java.io.IOException)31 BigEndianHeapChannelBuffer (org.jboss.netty.buffer.BigEndianHeapChannelBuffer)18 HttpResponse (org.jboss.netty.handler.codec.http.HttpResponse)18 ISE (org.apache.druid.java.util.common.ISE)16 HttpClient (org.apache.druid.java.util.http.client.HttpClient)12 DefaultHttpResponse (org.jboss.netty.handler.codec.http.DefaultHttpResponse)12 ArrayList (java.util.ArrayList)8 List (java.util.List)8 ChannelException (org.jboss.netty.channel.ChannelException)8 MalformedURLException (java.net.MalformedURLException)7 ExecutionException (java.util.concurrent.ExecutionException)7 HttpResponseStatus (org.jboss.netty.handler.codec.http.HttpResponseStatus)6 Duration (org.joda.time.Duration)6 Interval (org.joda.time.Interval)6 TypeReference (com.fasterxml.jackson.core.type.TypeReference)4