404 при использовании Spring cloud FeignClients
это моя установка:
первая служба (FlightIntegrationApplication), которая вызывает вторую службу(BaggageServiceApplication) с помощью API FeignClients и Eureka.
проект на github:https://github.com/IdanFridman/BootNetflixExample
первый сервис:
@SpringBootApplication
@EnableCircuitBreaker
@EnableDiscoveryClient
@ComponentScan("com.bootnetflix")
public class FlightIntegrationApplication {
    public static void main(String[] args) {
        new SpringApplicationBuilder(FlightIntegrationApplication.class).run(args);
    }
}
в одном из контроллеров:
    @RequestMapping("/flights/baggage/list/{id}")
    public String getBaggageListByFlightId(@PathVariable("id") String id) {
        return flightIntegrationService.getBaggageListById(id);
    }
FlightIntegrationService:
    public String getBaggageListById(String id) {
        URI uri = registryService.getServiceUrl("baggage-service", "http://localhost:8081/baggage-service");
        String url = uri.toString() + "/baggage/list/" + id;
        LOG.info("GetBaggageList from URL: {}", url);
        ResponseEntity<String> resultStr = restTemplate.getForEntity(url, String.class);
        LOG.info("GetProduct http-status: {}", resultStr.getStatusCode());
        LOG.info("GetProduct body: {}", resultStr.getBody());
        return resultStr.getBody();
    }
RegistryService:
@Named
public class RegistryService {
    private static final Logger LOG = LoggerFactory.getLogger(RegistryService.class);
    @Autowired
    LoadBalancerClient loadBalancer;
    public URI getServiceUrl(String serviceId, String fallbackUri) {
        URI uri;
        try {
            ServiceInstance instance = loadBalancer.choose(serviceId);
            uri = instance.getUri();
            LOG.debug("Resolved serviceId '{}' to URL '{}'.", serviceId, uri);
        } catch (RuntimeException e) {
            // Eureka not available, use fallback
            uri = URI.create(fallbackUri);
            LOG.error("Failed to resolve serviceId '{}'. Fallback to URL '{}'.", serviceId, uri);
        }
        return uri;
    }
}
и это вторая услуга (багаж-сервис):
BaggageServiceApplication:
@Configuration
@ComponentScan("com.bootnetflix")
@EnableAutoConfiguration
@EnableEurekaClient
@EnableFeignClients
public class BaggageServiceApplication {
    public static void main(String[] args) {
        new SpringApplicationBuilder(BaggageServiceApplication.class).run(args);
    }
}
BaggageService:
@FeignClient("baggage-service")
public interface BaggageService {
    @RequestMapping(method = RequestMethod.GET, value = "/baggage/list/{flight_id}")
    List<String> getBaggageListByFlightId(@PathVariable("flight_id") String flightId);
}
BaggageServiceImpl:
@Named
public class BaggageServiceImpl implements BaggageService{
....
    @Override
    public List<String> getBaggageListByFlightId(String flightId) {
        return Arrays.asList("2,3,4");
    }
}
при вызове контроллера rest службы интеграции полетов я получаю:
2015-07-22 17:25:40.682  INFO 11308 --- [  XNIO-2 task-3] c.b.f.service.FlightIntegrationService   : GetBaggageList from URL: http://X230-Ext_IdanF:62007/baggage/list/4
2015-07-22 17:25:43.953 ERROR 11308 --- [  XNIO-2 task-3] io.undertow.request                      : UT005023: Exception handling request to /flights/baggage/list/4
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 404 Not Found
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
есть идеи ?
спасибо, луч.
2 ответов
ваш код смотрит назад ко мне.
фальшивый клиент для багажной службы должен быть объявлен в полетной службе, и багажная служба должна иметь контроллер, который отвечает на URL-адрес, который вы отображаете в своем клиенте багажной службы, вы должны не реализовать интерфейс с аннотацией @FeignClient.
настройка у вас теперь не будет никакого контроллера прослушивания на /багаж/список/{flightId} в багажном отделении и без притворства клиент в flight service-весь смысл притворства заключается в вызове методов на интерфейсе вместо ручной обработки URL-адресов, Spring Cloud заботится об автоматическом создании экземпляра реализации интерфейса и будет использовать Eureka для обнаружения.
попробуйте это (или измените, чтобы он соответствовал вашему реальному приложению):
полет Обслуживание:
FlightIntegrationService.java:
@Component
public class FlightIntegrationService {
    @Autowired
    BaggageService baggageService;
    public String getBaggageListById(String id) {
        return baggageService.getBaggageListByFlightId(id);
    }
}
BaggageService.java:
@FeignClient("baggage-service")
public interface BaggageService {
    @RequestMapping(method = RequestMethod.GET, value = "/baggage/list/{flight_id}")
    List<String> getBaggageListByFlightId(@PathVariable("flight_id") String flightId);   
}
Багажа, Услуги:
BaggageController.java:
@RestController
public class BaggageController {
    @RequestMapping("/baggage/list/{flightId}")
    public List<String> getBaggageListByFlightId(@PathVariable String flightId) {
        return Arrays.asList("2,3,4");
    }
}
удалить BaggageService.java и BaggageServiceImpl.java от багажа
registryService.getServiceUrl("baggage-service", ... заменить на
registryService.getServiceUrl("baggage-service")
убедитесь, что соответствует правильному имени
удалить часть localhost
или использовать только http://local часть
это сработало только для нас, если у вас есть только имя службы, указанной в Eureka dashboard, а не оба
