0
点赞
收藏
分享

微信扫一扫

伴随高性能多级网关和多级分布式缓存架构应用实战经验

目录

一:http客户端Feign

1. Feign替代RestTemplate

2. 自定义配置

3. Feign性能优化

4. 最佳实践


前言 

一:http客户端Feign

1. Feign替代RestTemplate

RestTemplate方式调用存在的问题

先来看我们以前利用RestTemplate发起远程调用的代码

String url = "http://user-service/user/" + order.getUserId();
User user = restTemplate.getForObject(url, User.class);

存在下面的问题:

Feign的介绍

定义和使用Feign客户端

第一步:引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId> 
</dependency>

 第二步:添加注解,开启自动装配

第三步:编写Fegin客户端

package cn.itcast.order.client;

import cn.itcast.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient("user-service") // 服务名称
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

这个客户端主要是基于SpringMVC的注解来声明远程调用的信息,比如:

  • 服务名称:user-service

  • 请求方式:GET

  • 请求路径:/user/{id}

  • 请求参数:Long id

  • 返回值类型:User

这样,Feign就可以帮助我们发送http请求,无需自己使用RestTemplate来发送了。

第四步:定义和使用Feign客户端

package cn.itcast.order.service;

import cn.itcast.order.client.UserClient;
import cn.itcast.order.mapper.OrderMapper;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

   /* // 注入RestTemplate
    @Autowired
    private RestTemplate restTemplate;*/

    // ------------------注入UserClient接口
    @Autowired
    private UserClient userClient;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.发出请求查询用户信息
        // String url = "http://localhost:8081/user/"+order.getUserId();
        /*String url = "http://user-service/user/"+order.getUserId();
        User user = restTemplate.getForObject(url, User.class);*/
        // 2. ---------------------利用Fegin发起http请求,查询用户
        User user = userClient.findById(order.getUserId());
        // 3. 把用户信息封装到order
        order.setUser(user);
        // 4.返回
        return order;
    }
}

也能执行成功,同时也能完成负载均衡!

2. 自定义配置

Feign运行自定义配置来覆盖默认配置,可以修改的配置如下:

类型

作用

说明

feign.Logger.Level

修改日志级别

包含四种不同的级别:

NONE、BASIC、HEADERS、FULL

feign.codec.Decoder

响应结果的解析器

http远程调用的结果做解析,

例如解析json字符串为java对象

feign.codec.Encoder

请求参数编码

将请求参数编码,便于通过http请求发送

feign.Contract

支持的注解格式

默认是SpringMVC的注解

feign.Retryer

失败重试机制

请求失败的重试机制,

默认是没有,不过会使用Ribbon的重试

一般我们需要配置的就是日志级别:

配置Feign日志有两种方式

第一种方式:配置文件方式

①全局生效:

feign:
  client:
    config: 
      default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

②局部生效:

feign:
  client:
    config: 
      user-service: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别

第二种方式:java代码方式

创建一个类,声明一个Bean

package cn.itcast.order.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;

public class DefaultFeignConfiguration {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}

①全局生效:放到@EnableFeignClients这个注解中(放到整个OrderApplication启动类上的注解)

// 放到启动类上,使用defaultConfiguratio属性指定上面的类
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class) 

②局部生效:放到@FeignClient这个注解中(放到具体UserFegin接口上的注解)

// 放到具体的接口上,使用configuratio属性指定上面的类
@FeignClient(value = "user-service", configuration = DefaultFeignConfiguration .class) 

Feign的日志配置总结:

方式一是配置文件,feign.client.config.xxx.loggerLevel

方式二是java代码配置Logger.Level这个Bean

3. Feign性能优化

Fegin底层的客户端实现方式有三种:

因此优化Feign的性能主要包括两个点:

Feign的性能优化-连接池配置

第一步:order-service下引入fegin-httpClient依赖

<!--引入HttpClient依赖-->
<dependency>
      <groupId>io.github.openfeign</groupId>
      <artifactId>feign-httpclient</artifactId>
</dependency>

第二步:application.yml配置连接池

feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient: # 配置连接池的信息
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

Feign的优化总结:

1. 日志级别尽量用basic;

2. 使用HttpClient或OKHttp代替URLConnection;

4. 最佳实践

feign客户端: UserClient接口

UserController:

有没有一种办法简化这种重复的代码编写呢?

第一种方式:继承方式

优点:

缺点:

第二种方式:抽取方式

问题:假如现在有两个微服务都需要查询user-service,此时order-service和pay-service各写各的Client,造成了代码重复!

解决:都不用写,服务提供者提供一个API:把Client实体类配置等全都写好;将来消费者order-service和pay-service想要使用的话直接引依赖的jar包,然后直接调!

抽取Client步骤

第一步:先创建一个Modul,命名为fegin-api,然后引入openfegin的start依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

第二步:将order-service中编写的UserClient(原来定义的接口)、User(实体类)、DefaultFeginConfiguration(配置日志的类)都复制到fegin-api项目中

第三步:在order-service中引入fegin-api依赖

首先,删除order-service中的UserClient、User、DefaultFeignConfiguration等类或接口。 然后在order-service的pom文件中中引入feign-api的依赖:

 <!--引入feign统一api-->
<dependency>
    <groupId>cn.itcast.demo</groupId>
    <artifactId>fegin-api</artifactId>
    <version>1.0</version>
</dependency>

第四步:修改order-service中的所有上述三个组件有关的import部分,改成导入feign-api中的包 

第五步:重启测试

思考:此时报错找不到UserClient,明明我们注入的时候没有问题;此时是ComponentScan注解的范围问题。这是因为UserClient现在在cn.itcast.clients包下,而order-service的@EnableFeignClients注解是在cn.itcast.order包下,不在同一个包,无法扫描到UserClient。

解决扫描包的问题:在@EnableFeignClients主类上添加包扫描

方式一:在启动类上使用basePackages属性指定Feign应该扫描的包

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class, basePackages = "cn.itcast.client")
public class OrderApplication {
}

方式二:在启动类上使用client属性指定某个需要加载的Client接口

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class, clients = {UserClient.class})
public class OrderApplication {
}
举报

相关推荐

0 条评论