Spring Cloud Alibaba系列之-OpenFeign访问远程服务(四)

一、实现目标

module[user-service]和modul[order-service]由RestTemplate通信改成用OpenFeign通信

OpenFeign官网使用文档

二、Spring Cloud OpenFeign简介

Spring Cloud OpenFeign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用OpenFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求。

三、项目[ac-mall-cloud]接入OpenFeign

3.1 父级工程配置

在父级工程 [ac-mall-cloud] pom.xml中引入OpenFeign依赖


     org.springframework.cloud
     spring-cloud-starter-openfeign
     ${alibaba.cloud.version}

父级工程 [ac-mall-cloud] pom.xml全配置如下



    4.0.0

    org.example
    ac-mall-cloud
    1.0-SNAPSHOT
    
        user-service
        product-service
        order-service
    

    pom

    
        1.8
        Greenwich.SR1
        8.0.17
        3.2.0
        1.1.10
        2.2.4.RELEASE
        2.1.0.RELEASE
        1.18.10
    

    
    
        
            
                org.springframework.boot
                spring-boot-starter-parent
                ${boot.version}
                pom
                import
            

            
                org.springframework.cloud
                spring-cloud-dependencies
                ${spring-cloud.version}
                pom
                import
            

            
                com.alibaba.cloud
                spring-cloud-alibaba-dependencies
                ${alibaba.cloud.version}
                pom
                import
            

            
                com.alibaba.cloud
                spring-cloud-starter-alibaba-nacos-discovery
                ${alibaba.cloud.version}
            

            
                org.springframework.cloud
                spring-cloud-starter-openfeign
                ${alibaba.cloud.version}
            

            
                com.baomidou
                mybatis-plus-boot-starter
                ${mybatis.plus.version}
            

            
                com.alibaba
                druid-spring-boot-starter
                ${druid.version}
            

            
                mysql
                mysql-connector-java
                ${mysql.version}
            

            
                org.projectlombok
                lombok
                ${lombok.version}
                provided
            

        

    

    
    
        
            org.projectlombok
            lombok
            1.18.10
            provided
        
    

    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


3.2 module [user-service] 配置

1、新建一个constant包放常量类,并新建ModulePrePath类

public class ModulePrePath {
    public static final String API = "api";
}

2、新建一个api包,放供其他微服务调用接口的类,并新建UserApi类

/**
 * @author Alan Chen
 * @description 用户API
 * @date 2021/3/31
 */
@RestController
@RequestMapping(ModulePrePath.API+"/users")
public class UserApi {

    @Autowired
    IUserService userService;

    @GetMapping("/{userId}")
    public User getUser(@PathVariable String userId){
        return userService.getUser(userId);
    }
}

module [user-service] 效果如下


module [user-service] 效果

3、测试UserApi接口
重启module [user-service] ,在浏览器中输入访问地址http://127.0.0.1:8010/api/users/1,效果如下

UserApi接口访问效果

4、api包和controller包说明
controller包里放的是供本项目前端客户端(如APP)访问的接口;api包里的接口,是专门提供给其他微服务访问的。

3.3 module [order-service] 配置

1、在module [order-service]pom.xml中引入OpenFeign依赖


      org.springframework.cloud
      spring-cloud-starter-openfeign

module [order-service]pom.xml全配置如下



    
        ac-mall-cloud
        org.example
        1.0-SNAPSHOT
    
    4.0.0

    org.ac
    order-service

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        

        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        

    


2、主启动类加上注解@EnableFeignClients注解
@EnableFeignClients 申明该项目是Feign客户端,扫描对应的feign client

@EnableFeignClients
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class);
    }

    @Bean
    @LoadBalanced // Ribbon负载均衡注解
    RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

3、新建一个constant包放常量类,并新建ModulePrePath类

public class ModulePrePath {
    public static final String API = "api";
}

4、新建一个feign包放feign接口,并新建UserServiceClient接口

@FeignClient("user-service")
public interface UserServiceClient {

    /**
     * 获取用户信息
     * @param userId
     * @return
     */
    @GetMapping(ModulePrePath.API+"/users/{userId}")
    UserDto getUser(@PathVariable("userId") String userId);
}

@FeignClient("user-service") 配置的是module[user-service]的服务名
@GetMapping(ModulePrePath.API+"/users/{userId}") 路径和module[user-service]中UserApi获取用户信息接口的路径是一致的。

5、将RestTemplate通信改成用OpenFeign通信
修改OrderServiceImpl类的makeOrder方法

        // 1、根据用户ID调用用户服务接口数据,查询用户的名字
        //UserDto userDto = restTemplate.getForObject(USER_SERVICE_URL,UserDto.class,userId);

        //换成OpenFeign
        UserDto userDto = userServiceClient.getUser(userId);

OrderServiceImpl全部代码如下

@Service
public class OrderServiceImpl implements IOrderService {

    @Autowired
    OrderDao orderDao;

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    UserServiceClient userServiceClient;order-service
    //final static String USER_SERVICE_URL="http://127.0.0.1:8010/users/{userId}";

    final static String USER_SERVICE_URL="http://user-service/users/{userId}"; //用服务名来替换IP

    public Order makeOrder(String productId, String userId) {

        /**
         * RestTemplate是java创造出来的,在java能够访问到网络资源的包是java.net.URLConnenction/Socket
         * RestTemplate是对URLConnenction的封装
         * apache--HttpClient 也是对URLConnenction/HttpURLConnenction的封装
         * oKHttp 也封装了URLConnenction
         * netty/rpc/grpc/thirt/tomcat
         */

        // 1、根据用户ID调用用户服务接口数据,查询用户的名字
        //UserDto userDto = restTemplate.getForObject(USER_SERVICE_URL,UserDto.class,userId);

        //换成OpenFeign
        UserDto userDto = userServiceClient.getUser(userId);

        String userName=userDto.getUserName();

        // 2、生成订单
        Order order = new Order();
        order.setId(UUID.randomUUID().toString());
        order.setCreateTime(new Date());
        order.setPriceFen(1600L);
        order.setUserId(userId);
        order.setUserName(userName);
        order.setProductId(productId);
        order.setOrderNo(UUID.randomUUID().toString());

        // 3、保存数据库
        orderDao.insert(order);

        return order;
    }
}

6、测试下单接口
我们在浏览器中输入访问地址http://127.0.0.1:8020/orders/1/1,效果如下

OpenFeign成功效果图

四、Ribbon、Feign、LoadBalancer和OpenFeign的关系

4.1 Ribbon
  • Ribbon 是 Netflix开源的基于HTTP和TCP等协议负载均衡组件
  • Ribbon 可以用来做客户端负载均衡,调用注册中心的服务
  • Ribbon的使用需要代码里手动调用目标服务
  • RestTemplate集成 Ribbon,可以让RestTemplate通过服务名来访问微服务接口(否则只能通过IP访问)
4.2 Feign
  • Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端
  • Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。
  • Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务
  • Feign本身不支持Spring MVC的注解,它有一套自己的注解。
4.3 OpenFeign
  • OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解,如@RequesMapping等等。
  • OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
4.4 LoadBalancer

Ribbon目前已经停止维护,新版SpringCloud(2021.x.x)用LoadBalancer替代了Ribbon。Spring Cloud全家桶在Spring Cloud Commons项目中,添加了Spring cloud Loadbalancer作为新的负载均衡器,并且做了兼容

Nacos 2021版本已经没有自带ribbon的整合,所以无法通过修改Ribbon负载均衡的模式来实现nacos提供的负载均衡模式,需要引入另一个支持的jar包loadbalancer。

4.5 Ribbon/LoadBalancer载均衡策略

Ribbon有多种负载均衡策略

  • 随机 RandomRule
  • 轮询 RoundRobinRule
  • 重试 RetryRule
  • 最低并发 BestAvailableRule
  • 可用过滤 AvailabilityFilteringRule
  • 响应时间加权重 ResponseTimeWeightedRule
  • 区域权重 ZoneAvoidanceRule

LoadBalancer貌似只提供了两种负载均衡器,不指定的时候默认用的是轮询

  • RandomLoadBalancer 随机
  • RoundRobinLoadBalancer 轮询

五、附录

项目源码地址

你可能感兴趣的:(Spring Cloud Alibaba系列之-OpenFeign访问远程服务(四))