Вызов клиента Spring Feign входит в блок исключения, когда он должен оставаться в блоке попытки

Нужна небольшая помощь по клиенту Spring Feign. Итак, вот ситуация,

У меня есть 2 службы загрузки Spring. Скажем, служба A и служба B. Я настроил свою службу A с клиентом Feign, через который я вызываю метод службы B.

Итак, вот код моей службы A,

Мой интерфейс конфигурации FeignCleint,

@FeignClient(name = "FeignClient", url = "http://localhost:8081/ServiceB/hello")
public interface FeignApi {

    @RequestMapping(method = RequestMethod.GET)
    ResponseEntity<?> hello();
}

И мой контроллер отдыха, который использует приведенную выше конфигурацию симуляции для вызова метода Service B,

@RestController
public class ApiController {

    @Autowired
    private FeignApi feignApi;

    @RequestMapping(value = "/callServiceB")
    public ResponseEntity<?> companyInfo() {
        ResponseEntity<?> response = new ResponseEntity("OK Response", HttpStatus.OK);
        try {
            response = feignApi.hello();

            // Code for some other things related to application.

            return response;
        } catch (Exception ex) {
            System.out.println("Service A Exception block reached.");
            return new ResponseEntity(ex.getMessage(), HttpStatus.BAD_REQUEST);
        }
    }
}

ниже мой контроллер для службы B,

@RestController
public class MyController {

    @GetMapping("/hello")
    public String hello() throws Exception {

        if (true) {
            throw new Exception("Service B Exception...");
        }
        return "Hello World";
    }
}

И мой совет Контроллера для обработки исключения, которое я выбрасываю вручную,

@ControllerAdvice
public class MyControllerAdvice {

    @ExceptionHandler
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseEntity<?> handleException(Exception exception, Model model) {
        return new ResponseEntity<>("Caused due to : " + exception.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

Теперь мой алгоритм выглядит так, как показано ниже. Как вы можете видеть, я вызываю службу B из службы A, используя имитацию клиента. Моя служба B генерирует исключение вручную, которое я улавливаю с помощью совета контроллера и отправляю детали исключения в виде ResponseEntity обратно вызывающей службе A. Таким образом, служба A может обрабатывать детали и двигаться вперед на основе этого.

Проблема в том, что когда я звоню из службы A, используя

http://localhost:8080/feign/callServiceB

Служба B терпит неудачу, как и ожидалось. Теперь я ожидаю, что служба A должна получить ответ в форме ResponseEntity. Но на самом деле происходит то, что поток попадает в блок исключения вместо того, чтобы оставаться в блоке попытки. Я вижу напечатанную строку,

"Service A Exception block reached."

Вот чего я не понимаю. Если я управлял исключением службы B с помощью совета контроллера и отправил ответ службе A в форме ResponseEntity, то почему поток службы A попадает в блок catch. Я ожидаю, что он останется только в блоке try, поскольку я хочу продолжить обработку на основе данных.

Есть идеи, как мне обойти эту штуку? Или это будет так, даже когда я использую совет контроллера для управления исключениями? Каким должно быть ожидаемое поведение в этом случае?

Пожалуйста посоветуй.


person WebNoob    schedule 19.10.2018    source источник


Ответы (2)


По умолчанию Feign генерирует исключение FeignException для любой ошибочной ситуации. Используйте резервный механизм для обработки сбоев.

@FeignClient(name = "FeignClient", url = "http://localhost:8081/ServiceB/hello", fallback= FeignApiFallback.class)
public interface FeignApi {

    @RequestMapping(method = RequestMethod.GET)
    ResponseEntity<?> hello();
}

@Component
class FeignApiFallback implements FeignApi {

    @Override
    public ResponseEntity<?> hello() {
        //do more logic here
        return ResponseEntity.ok().build();
    }

}

убедитесь, что вы добавили свойство ниже, чтобы обернуть методы в командах hystrix в последних выпусках

feign.hystrix.enabled=true
person Barath    schedule 19.10.2018
comment
Спасибо за ответ. Когда я добавляю этот новый компонент, предоставляя запасные детали, я все еще не получаю элемент управления внутри этого метода? Как будто я только что добавил sysout, чтобы увидеть, попадает ли поток туда или нет, но он просто его пропускает. Но поможет ли резервный подход получить ошибку из службы B и сохранить поток только в блоке try? Прошу прощения, если это просто, но я новичок в этом, поэтому, пожалуйста, дайте мне знать. - person WebNoob; 19.10.2018
comment
Кроме того, когда я пытаюсь добавить feign.hystrix.enabled = true в свой файл свойств, он показывает мне, что feign.hystrix.enabled - неизвестное свойство. Не знаю почему :( - person WebNoob; 19.10.2018
comment
хорошо, если вы хотите знать, в чем ошибка, в этом случае вам нужно выполнить специальную обработку или использовать собственный декодер. Я могу поделиться ссылками, которые помогут вам. github.com/OpenFeign/feign/wiki/Custom-error-handling. - person Barath; 19.10.2018
comment
Откат будет задействован, если свойство резервирования правильно определено аннотацией @FeignClient и доступно как bean-компонент. обновите код, чтобы выяснить, почему он не вызывается. - person Barath; 19.10.2018
comment
Спасибо @Barath. Я просмотрел эту ссылку, чтобы узнать о пользовательской обработке ошибок. Но это всего лишь небольшой фрагмент кода. Знаете ли вы какой-нибудь полный пример на Github, который я могу загрузить и импортировать в свое затмение, чтобы лучше понять? - person WebNoob; 19.10.2018
comment
Кроме того, неизвестно, как решить 'feign.hystrix.enabled'. проблема? - person WebNoob; 19.10.2018
comment
@WebNoob странно, почему он не выбран, но вы можете прочитать последние примечания к выпуску об этом. что именно вы ищете в качестве образца? механизм обработки ошибок / отката? - person Barath; 19.10.2018
comment
@WebNoob сделал здесь образец: feign-client -исключение - person Barath; 19.10.2018
comment
большое спасибо. Я скачаю ваш код и опробую его на своем локальном компьютере. Я дам вам знать, в чем проблема с моим кодом. Еще раз спасибо за создание этого примера, который заставил меня понять. Я ценю это, чувак. - person WebNoob; 19.10.2018
comment
Я просмотрел код, теперь он переходит в резерв. Единственная проблема, с которой я столкнулся, это то, что я не могу получить настраиваемое сообщение, которое я отправляю при обработке исключения. Таким образом, инвентаризация вызывает продукт, я вручную генерирую исключение с сообщением об исключении службы B ... затем controllerAdvice обрабатывает это исключение и отправляет ответ ResponseEntity с сообщением, вызванным: исключение службы B .... Теперь поток поступает в ErrorDecoder, где я печатаю ответ. Но здесь в ответе я не вижу сообщения "Причина из-за: Исключение службы B ...", которое я установил. Я делаю что-то неправильно? Пожалуйста, посмотри. - person WebNoob; 22.10.2018
comment
Кроме того, как я могу получить фактический ответ для игры в резервном методе? У запасного метода нет параметров. Итак, как мне решить проблему, связанную с обработкой исключений? - person WebNoob; 22.10.2018
comment
Да. но в этом объекте ответа нет ничего специфического для сообщения об исключении. Причина - нулевая, статус - 500, тело ответа - объект входящего потока. но я не уверен, как я могу извлечь из него что-нибудь. Можете ли вы предложить, как мне получить исходные данные об исключении из этого объекта Response? - person WebNoob; 22.10.2018
comment
@WebNoob Я работаю над аналогичной проблемой, возможно, эта ссылка может быть полезной cloud.spring.io/spring-cloud-netflix/multi/ - person Akki; 15.04.2020
comment
@WebNoob, если вы используете указанную выше ссылку, реализация только FallbackFactory предоставит вам причину исключения из одной службы в другую, вам не нужно создавать декодер ошибок, единственная проблема, с которой я столкнулся сейчас, если я реализую ее так, как она показано в ссылке, мне придется без необходимости реализовать все методы моего контроллера, которые я не хочу - person Akki; 16.04.2020

Любой статус, отличный от 200, симулируемый клиент будет рассматривать это как исключение, и вы устанавливаете HttpStatus.INTERNAL_SERVER_ERROR в своем совете контроллера.

Вы можете использовать собственный ErrorDecoder

обратитесь к https://github.com/OpenFeign/feign/wiki/Custom-error-handling

person John    schedule 09.10.2019