Как работает притворство

Java

Как работает притворство

  • В основную запись программы добавляется аннотация @EnableFeignClients, позволяющая включить сканирование и загрузку FeignClient. В соответствии со спецификацией разработки Feign Client определите интерфейс и добавьте аннотацию @FeignClientd.

  • Когда программа запускается, она сканирует пакет, сканирует все аннотированные классы @FeignClients и вводит эту информацию в контейнер Spring IOC.Когда вызывается метод в определенном интерфейсе Feign, он будет сгенерирован через прокси-метод JDK. Конкретный RequestTemplate.При создании прокси Feign создаст RequestTemplate для каждого метода интерфейса. При создании прокси Feign создаст объект RequestTemplate для каждого метода интерфейса и изменит объект для инкапсуляции всей информации, необходимой для HTTP-запроса, такой как имя параметра запроса, метод запроса и другая информация, определяемая в этом процессе.

  • Затем RequestTemplate генерирует запрос, а затем передает запрос клиенту для обработки. Здесь клиентом может быть собственный URLConnection JDK, HttpClient Apache или OKhttp. Наконец, клиент инкапсулируется в класс LoadBalanceClient, который сочетает балансировку нагрузки ленты. для отправки вызовов между серверными службами.

Анализ притворных заметок

Аннотация @FeignClient в основном изменяется с помощью @Target({ElementType.TYPE}), что указывает на то, что аннотация в основном используется в интерфейсе. Он имеет следующие свойства:

  • имя: указывает имя FeignClient.Если используется лента, имя используется в качестве имени микрослужбы для обнаружения служб.

  • URL-адрес: URL-адрес обычно используется для отладки, вы можете указать адрес, вызываемый @FeignClient.

  • decode404: при возникновении ошибки 404, если это поле истинно, для декодирования будет вызван декодер, в противном случае будет выдано исключение FeignException.

  • конфигурация: класс конфигурации Feign, вы можете настроить или настроить Feign Encoder, Decoder, LogLevel и Contract.

  • fallback: определите класс отказоустойчивой обработки. При сбое или истечении времени ожидания удаленного интерфейса будет вызываться отказоустойчивая логика соответствующего интерфейса. Класс, указанный в fallback, должен реализовывать интерфейс, помеченный @Feign.

  • fallbacjFactory: Фабричный класс, который используется для создания экземпляров резервного класса. Благодаря этому свойству может быть реализована общая отказоустойчивая логика каждого интерфейса. Вводятся повторяющиеся коды.

  • путь: определяет унифицированный префикс текущего FeignClient.

Feign включает сжатие GZIP

Spring Cloud Feign поддерживает сжатие GZIP запросов и ответов для повышения эффективности связи. В файле yml требуется следующая конфигурация

feign:
  compression:
    request:
      enabled: true #开请求压缩
      mimeTypes: #媒体类型 text/xml,application/xml,application/json
      minRequestSize: 2048 #最小的请求大小
    response:
      enabled: true #开启响应的压缩

Следует отметить, что после принятия сжатия передачу данных нужно осуществлять вторичным способом, а для всех возвращаемых значений нужно использовать ResponseEntity перенимать.

@FeignClient(name = "github-client",url = "https://api.github.com",configuration = HelloFeignServiceConfig.class)
public interface HelloFeignService {

    /*
    这个返回类型如果采用了压缩,那么就是二进制的方式,就需要使用ResponseEntity<byte[]>作为返回值
     */
    @RequestMapping(value = "/search/repositories",method = RequestMethod.GET)
    ResponseEntity<byte[]> searchRepositories(@RequestParam("q")String parameter);
}

Журнал открытия клиента Feign

Классы, которые необходимо настроить в классе аннотаций:

@FeignClient(name = "github-client",url = "https://api.github.com",configuration = HelloFeignServiceConfig.class)

Код для класса аннотаций выглядит следующим образом:

@Configuration
public class HelloFeignServiceConfig {

    /**
     *
     * Logger.Level 的具体级别如下:
         NONE:不记录任何信息
         BASIC:仅记录请求方法、URL以及响应状态码和执行时间
         HEADERS:除了记录 BASIC级别的信息外,还会记录请求和响应的头信息
         FULL:记录所有请求与响应的明细,包括头信息、请求体、元数据
     * @return
     */
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

}

Настройка тайм-аута Feign

Вызов Feign разделен на два слоя, а именно вызов слоя ленты и вызов Hystrix, Высокая версия Hystrix по умолчанию закрыта.

  • Если возникает вышеуказанная ошибка, вам необходимо добавить следующую конфигурацию

    #Тайм-аут обработки запроса лента.ReadTimeout: 12000 #Тайм-аут ссылки запроса лента.ConnectionTimeout: 30000

  • Если Hystrix включен, сообщение об ошибке тайм-аута Hystrix выглядит следующим образом:

На этом этапе вы можете добавить следующую конфигурацию:

hystrix:
  command:
    default:
      circuitBreaker:
        sleepWindowInMilliseconds: 30000
        requestVolumeThreshold: 50
      execution:
        timeout:
          enabled: true
        isolation:
          strategy: SEMAPHORE
          semaphore:
            maxConcurrentRequests: 50
          thread:
            timeoutInMilliseconds: 100000

Многопараметрическая передача Feign's Post и Get

В SpringMVC вы можете использовать запрос Post или Get для простого запроса к соответствующему интерфейсу и привязки параметров к POJO, но Feign не полностью реализует функции SpringMVC.Если вы используете GET для запроса интерфейса, вы не можете привязать параметры к POJO Однако соответствующие функции могут быть реализованы следующими способами.

  • Выгрузить поля в POJO по одному на интерфейс

  • Запрограммируйте параметры на карту

  • POJO украшен @RequestBody, но это нарушает принцип Restful

Следующий код перехватывает запрос Feign и обрабатывает параметры для создания единой карты программирования.

@Component
public class FeignRequestInterceptor implements RequestInterceptor{
    @Autowired
    private ObjectMapper objectMapper;



    @Override
    public void apply(RequestTemplate requestTemplate) {
        // feign 不支持 GET 方法传 POJO, json body转query
        if (requestTemplate.method().equalsIgnoreCase("GET") && requestTemplate.body()!=null){
            try {
                JsonNode jsonNode = objectMapper.readTree(requestTemplate.body());
                requestTemplate.body(null);
                Map<String,Collection<String>> queries = new HashMap<>();
                buildQuery(jsonNode,"",queries);
                requestTemplate.queries(queries);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }
    private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {
        if (!jsonNode.isContainerNode()) {   // 叶子节点
            if (jsonNode.isNull()) {
                return;
            }
            Collection<String> values = queries.get(path);
            if (null == values) {
                values = new ArrayList<>();
                queries.put(path, values);
            }
            values.add(jsonNode.asText());
            return;
        }
        if (jsonNode.isArray()) {   // 数组节点
            Iterator<JsonNode> it = jsonNode.elements();
            while (it.hasNext()) {
                buildQuery(it.next(), path, queries);
            }
        } else {
            Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields();
            while (it.hasNext()) {
                Map.Entry<String, JsonNode> entry = it.next();
                if (StringUtils.hasText(path)) {
                    buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
                } else {  // 根节点
                    buildQuery(entry.getValue(), entry.getKey(), queries);
                }
            }
        }
    }

}

В дополнение к описанному выше методу вы также можете использовать зависимость venus-cloud-feign, которая реализует упаковку параметра Map запроса GET, поэтому вам не нужно писать ее самостоятельно. Зависимости следующие:

<!-- https://mvnrepository.com/artifact/cn.springcloud.feign/venus-cloud-feign-core -->
<dependency>
    <groupId>cn.springcloud.feign</groupId>
    <artifactId>venus-cloud-feign-core</artifactId>
    <version>1.0.0</version>
</dependency>

Адрес гитхаба следующий:GitHub.com/springcloud…