Feign 기초 입문 및 특성 설명

16546 단어 fetch
전재 출처 를 밝 혀 주 십시오http://www.paraller.com 원문 조판 주소 클릭 하여 더 좋 은 읽 기 체험 얻 기
소개 하 다.
Feign 은 넷 플 릭 스에 서 분 리 된 경량급 프로젝트 로 클래스 인터페이스 에 주석 을 추가 해 REST API 클 라 이언 트 가 될 수 있다.
Feign 에 서 는 Hystrix 에 대한 의존 관계 가 있 습 니 다.Feign 은 편리 한 rest 프레임 워 크 일 뿐 호출 을 간소화 하고 마지막 으로 ribbon 을 통 해 등록 서버 에서 서비스 인 스 턴 스 를 찾 은 다음 에 요청 을 분배 합 니 다.
실제 항목
입구 프로그램 에 주석 추가
@EnableFeignClients

REST API 클 라 이언 트
@FeignClient(value = "ticket-service", configuration = YeaFeignConfiguration.class,fallback = TicketClientHystrix.class)
interface TicketClient {

    @RequestMapping(method = RequestMethod.POST, value = "/create")
    Message create(
            @RequestParam(value = "Type") Integer Type, 
            @RequestParam(value = "amount") String amount,
            @RequestParam(value = "userId") String userId, 
            @RequestParam(value = "mobile") String mobile,
            @RequestParam(value = "status") Integer status, 
            @RequestParam(value = "belong") Integer belong,
            @RequestParam(value = "useProfit")String useProfit,
            @RequestParam(value = "useCounter")String useCounter);
}

사용자 정의 FeignConfiguration 속성
@Configuration
public class YeaFeignConfiguration {

    public static final int CONNECT_TIMEOUT_MILLIS = 5000;
    public static final int READ_TIMEOUT_MILLIS = 5000;

    @Bean
    public Logger.Level feignLogger() {
        return Logger.Level.FULL;
    }

    @Bean
    public Request.Options options() {
        return new Request.Options(CONNECT_TIMEOUT_MILLIS, READ_TIMEOUT_MILLIS);
    }
}

pom.xml

  io.github.openfeign
  feign-core
  ${project.version}


  io.github.openfeign
  feign-gson
  ${project.version}

Feign 원생 예시
URL 의 코드 를 가 져 온 다음 대상 으로 봉 하여 되 돌려 줍 니 다.
public class GitHubExample {

    interface GitHub {

        class Repository {
            String name;
        }

        class Contributor {
            String login;
        }

        @RequestLine("GET /users/{username}/repos?sort=full_name")
        List repos(@Param("username") String owner);

        @RequestLine("GET /repos/{owner}/{repo}/contributors")
        List contributors(@Param("owner") String owner, @Param("repo") String repo);

        /** Lists all contributors for all repos owned by a user. */
        default List contributors(String owner) {
            return repos(owner).stream().flatMap(repo -> contributors(owner, repo.name).stream()).map(c -> c.login)
                    .distinct().collect(Collectors.toList());
        }

        static GitHub connect() {
            Decoder decoder = new GsonDecoder();
            return Feign.builder().decoder(decoder).errorDecoder(new GitHubErrorDecoder(decoder))
                    .logger(new Logger.ErrorLogger()).logLevel(Logger.Level.BASIC)
                    .target(GitHub.class, "https://api.github.com");
        }
    }

    static class GitHubClientError extends RuntimeException {
        private String message; // parsed from json

        @Override
        public String getMessage() {
            return message;
        }
    }

    static class GitHubErrorDecoder implements ErrorDecoder {

        final Decoder decoder;
        final ErrorDecoder defaultDecoder = new ErrorDecoder.Default();

        GitHubErrorDecoder(Decoder decoder) {
            this.decoder = decoder;
        }

        @Override
        public Exception decode(String methodKey, Response response) {
            try {
                return (Exception) decoder.decode(response, GitHubClientError.class);
            } catch (IOException fallbackToDefault) {
                return defaultDecoder.decode(methodKey, response);
            }
        }
    }

    public static void main(String... args) {

        GitHub github = GitHub.connect();

        System.out.println("Let's fetch and print a list of the contributors to this org.");
        List contributors = github.contributors("netflix");
        for (String contributor : contributors) {
            System.out.println(contributor);
        }

        System.out.println("Now, let's cause an error.");
        try {
            github.contributors("netflix", "some-unknown-project");
        } catch (GitHubClientError e) {
            System.out.println(e.getMessage());
        }
    }
}

Feign 기타 특성
FEIGN CLIENT WITH HYSTRIXOBSERVABLE WRAPPER
With Hystrix on the classpath, you can also return a HystrixComman
기초 용법
@FeignClient("http://notification-service")
public interface NotificationVersionResource {  
    @RequestMapping(value = "/version", method = GET)
    String version();
}

세 립 도 조작
@FeignClient("http://notification-service")
public interface NotificationVersionResource {  
    @RequestMapping(value = "/version", method = GET)
    HystrixObservable version();
}

FEIGN CLIENT WITH HYSTRIX FALLBACK
Feign Client 는 강등 기능 을 직접 사용 할 수 있 습 니 다. 가장 간단 한 방법 은 인 터 페 이 스 를 사용 하 는 것 입 니 다. 인터페이스 에서 강등 코드 를 실현 하고 서버 에서 오류 가 발생 했 을 때 호출 됩 니 다.
@FeignClient("http://notification-service")
public interface NotificationResource {  
    @RequestMapping(value = "/notifications", method = GET)
    List findAll();
}

public class NotificationResourceImpl implements NotificationResource {  
    @Override
    public List findAll() {
        return new ArrayList<>();
    }
}

외부 링크 사용
이전의 예 는 서비스 발견 에서 service 의 Name 을 사용 하여 접근 하 였 으 나, 마찬가지 로 외부 링크 를 사용 하여 접근 하 는 것 도 지원 하 였 다.
@FeignClient(name = "reddit-service", url = "${com.deswaef.reddit.url}")
public interface RedditResource {  
    @RequestMapping(method = RequestMethod.GET, value = "/java.json")
    RedditResponse posts();
}

옵션 설정
Spring Cloud Netflix 는 Feign 에 기본 설정 Bean 을 제공 합 니 다.
  • Decoder feignDecoder: ResponseEntityDecoder
  • Encoder feignEncoder: SpringEncoder
  • Logger feignLogger: Slf4jLogger
  • Contract feignContract: SpringMvcContract
  • Feign.Builder feignBuilder: HystrixFeign.Builder

  • OkHttpClient 와 ApacheHttpClient 를 설정 feign.okhttp.enabled:true 속성 으로 사용 할 수 있 습 니 다. 클래스 경로 에 추가 하 는 것 을 잊 지 마 세 요.
    Spring Cloud Netflix 는 Feign 에 아래 의 기본 속성 을 제공 하지 않 지만, 마찬가지 로 응용 컨 텍스트 에서 이 Bean 을 검색 한 다음 feign client 를 만 듭 니 다.
  • Logger.Level
  • Retryer
  • ErrorDecoder
  • Request.Options
  • Collection

  • 추가 속성 이 필요 하거나 속성 을 덮어 쓰 려 면 모든 FeignClient 에 사용자 정의 속성 Bean 을 만 들 수 있 습 니 다.
    @FeignClient(
        name = "reddit-service", 
        url = "${com.deswaef.reddit.url}", 
        configuration = RedditFeignConfiguration.class
    )
    @Configuration
    public class RedditFeignConfiguration {  
        public static final int FIVE_SECONDS = 5000;
        
        @Bean
        public Logger.Level feignLogger() {
            return Logger.Level.FULL;
        }
        
        @Bean
        public Request.Options options() {
            return new Request.Options(FIVE_SECONDS, FIVE_SECONDS);
        }
    
        @Bean
        public Contract feignContract() {
            return new feign.Contract.Default();
        }
    
        @Bean
        public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
            return new BasicAuthRequestInterceptor("user", "password");
        }
    }

    Feign 에 서 는 Hystrix 기능 을 사용 하지 않 습 니 다.
    RequestInterceptor 에서 ThreadLocal 바 인 딩 변 수 를 사용 하려 면 Hystrix 에 thread isolation 정책 이나 disable Hystrix in Feign 을 설정 해 야 합 니 다.
    # To disable Hystrix in Feign
    feign:
      hystrix:
        enabled: false
    
    # To set thread isolation to SEMAPHORE
    hystrix:
      command:
        default:
          execution:
            isolation:
              strategy: SEMAPHORE

    Note
    if this configuration class is on the component scan path, it'll be also picked up as general configuration. This means that a configuration class like this, when also scanned by our automatic component scan, will override all of the beans for each and every FeignClient, not just the one which defined it as configuration.
    즉, automatic component 에 스 캔 되면 모든 FeignClient 는 configuration = RedditFeignConfiguration. class 라 는 성명 을 표시 하 는 인터페이스 가 아 닌 이 class 설정 항목 에 따라 유효 합 니 다.
    As a result, you should place it inside a package that isn't a candidate for a component scan
    스 캔 할 수 있 는 가방 에 넣 지 마 세 요.가장 쉬 운 방법 은 @ Configuration 주석 을 표시 하지 않 는 것 입 니 다.
    수 동 호출 Feign
    두 가지 예시:
    @Import(FeignClientsConfiguration.class)
    class FooController {
    
        private FooClient fooClient;
    
        private FooClient adminClient;
    
        @Autowired
        public FooController(
                Decoder decoder, Encoder encoder, Client client) {
            this.fooClient = Feign.builder().client(client)
                    .encoder(encoder)
                    .decoder(decoder)
                    .requestInterceptor(new BasicAuthRequestInterceptor("user", "user"))
                    .target(FooClient.class, "http://PROD-SVC");
            this.adminClient = Feign.builder().client(client)
                    .encoder(encoder)
                    .decoder(decoder)
                    .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
                    .target(FooClient.class, "http://PROD-SVC");
        }
    }
    
    ## In the above example FeignClientsConfiguration.class is the default configuration provided by Spring Cloud Netflix.
    interface GitHub {
    
            class Repository {
                String name;
            }
    
            class Contributor {
                String login;
            }
    
            @RequestLine("GET /users/{username}/repos?sort=full_name")
            List repos(@Param("username") String owner);
    
            @RequestLine("GET /repos/{owner}/{repo}/contributors")
            List contributors(@Param("owner") String owner, @Param("repo") String repo);
    
            /** Lists all contributors for all repos owned by a user. */
            default List contributors(String owner) {
                return repos(owner).stream().flatMap(repo -> contributors(owner, repo.name).stream()).map(c -> c.login)
                        .distinct().collect(Collectors.toList());
            }
    
            static GitHub connect() {
                Decoder decoder = new GsonDecoder();
                return Feign.builder().decoder(decoder).errorDecoder(new GitHubErrorDecoder(decoder))
                        .logger(new Logger.ErrorLogger()).logLevel(Logger.Level.BASIC)
                        .target(GitHub.class, "https://api.github.com");
            }
        }

    Feign Hystrix Support
    1. Hystrix 는 classpath 에 있 고 feign.hystrix.enabled=true Feign 패키지 의 모든 방법 은 회로 차단기 (circuit breaker) 가 있 습 니 다.
    2. 방법 에서 com. netflix. hystrix. Hystrix Command 를 되 돌려 주 는 것 도 Hystrix 특성 을 지원 할 수 있 습 니 다. This lets you use reactive patterns (with a call to. toObservable () or. observe () or asynchronous use (with a call to. queue ()).Note: Prior to the Spring Cloud Dalston release, if Hystrix was on the classpath Feign would have wrapped all methods in a circuit breaker by default. This default behavior was changed in Spring Cloud Dalston in favor for an opt-in approach.
    단독 Feign client 에서 Hystrix 기능 을 금지 합 니 다. Feign. Builder with the "prototype"scope 를 만 들 수 있 습 니 다.
    @Configuration
    public class FooConfiguration {
        @Bean
        @Scope("prototype")
        public Feign.Builder feignBuilder() {
            return Feign.builder();
        }
    }

    Feign Hystrix Fallbacks
    일반적인 강등 방식:
    @FeignClient(name = "hello", fallback = HystrixClientFallback.class)
    protected interface HystrixClient {
        @RequestMapping(method = RequestMethod.GET, value = "/hello")
        Hello iFailSometimes();
    }
    
    static class HystrixClientFallback implements HystrixClient {
        @Override
        public Hello iFailSometimes() {
            return new Hello("fallback");
        }
    }

    테스트 할 때 강등 동작 을 실행 하려 면 fallback Factory 를 사용 하 십시오.
    @FeignClient(name = "hello", fallbackFactory = HystrixClientFallbackFactory.class)
    protected interface HystrixClient {
        @RequestMapping(method = RequestMethod.GET, value = "/hello")
        Hello iFailSometimes();
    }
    
    @Component
    static class HystrixClientFallbackFactory implements FallbackFactory {
        @Override
        public HystrixClient create(Throwable cause) {
            return new HystrixClientWithFallBackFactory() {
                @Override
                public Hello iFailSometimes() {
                    return new Hello("fallback; reason was: " + cause.getMessage());
                }
            };
        }
    }
    Note: There is a limitation with the implementation of fallbacks in Feign and how Hystrix fallbacks work.
    Fallbacks are currently not supported for methods that return com.netflix.hystrix.HystrixCommand and rx.Observable.
    인 터 페 이 스 를 통 해 등급 을 낮 추 는 데 한계 가 있 습 니 다. Fallbacks 는 현재 방법 에서 com. netflix. hystrix. Hystrix Command and and rx. Observable 로 돌아 가 는 것 을 지원 하지 않 습 니 다.
    Feign and @Primary
    When using Feign with Hystrix fallbacks, there are multiple beans in the ApplicationContext of the same type. This will cause @Autowired to not work because there isn’t exactly one bean, or one marked as primary. To work around this, Spring Cloud Netflix marks all Feign instances as @Primary, so Spring Framework will know which bean to inject. In some cases, this may not be desirable. To turn off this behavior set the primary attribute of @FeignClient to false.
    @FeignClient(name = "hello", primary = false)
    public interface HelloClient {
        // methods here
    }

    Feign request/response compression
    You may consider enabling the request or response GZIP compression for your Feign requests. You can do this by enabling one of the properties:
    feign.compression.request.enabled=true
    feign.compression.response.enabled=true
    Feign request compression gives you settings similar to what you may set for your web server:
    feign.compression.request.enabled=true
    feign.compression.request.mime-types=text/xml,application/xml,application/json
    feign.compression.request.min-request-size=2048

    These properties allow you to be selective about the compressed media types and minimum request threshold length.
    Feign logging
    A logger is created for each Feign client created. By default the name of the logger is the full class name of the interface used to create the Feign client. Feign logging only responds to the DEBUG level.
    application.yml
    logging.level.project.user.UserClient: DEBUG

    The Logger.Level object that you may configure per client, tells Feign how much to log. Choices are:
  • NONE, No logging (DEFAULT).
  • BASIC, Log only the request method and URL and the response status code and execution time.
  • HEADERS, Log the basic information along with request and response headers.
  • FULL, Log the headers, body, and metadata for both requests and responses.

  • For example, the following would set the Logger.Level to FULL:
    @Configuration
    public class FooConfiguration {
        @Bean
        Logger.Level feignLoggerLevel() {
            return Logger.Level.FULL;
        }
    }

    참조 사이트
    Feign-github
    The Netflix stack, using Spring Boot - Part 3: Feign
    http://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html#spring-cloud-feign

    좋은 웹페이지 즐겨찾기