4、微服务互相调用

微服务调用

在微服务架构中,最常见的场景就是微服务之间的相互调用。比如,用户微服务调用订单微服务发起一个下单的请求,在进行保存订单之前,需要调用商品微服务查询商品的信息。我们把调用方称为服务消费者,把请求的接收者称为服务提供者

RestTemplate

常见用法

Ribbon

解决的问题

负载均衡

Ribbon使用

1、导入Ribbon的依赖,只要使用Eureka,那么程序已经自带了

2、开启负载均衡

//在产生RestTemplate实例时,使用@LoadBalanced注解,那么RestTemplate就拥有了负载均衡的能力
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
    return new RestTemplate();
}

3、消费端调用方式

public String getUrl(){
    // 将之前的return "http://127.0.0.1:9091/"中
    // 127.0.0.1:9091替换成 micro-base-server(被调用者的spring.application.name)
    return "http://micro-base-server/";
}

Ribbon提供的负载均衡

配置Ribbon

全局配置

在配置类中进行定义

@Configuration
public class loadbanlancerConfig {
    @Bean
    public IRule myRandomRule() {
        return new RandomRule();
    }
}
#ribbon的全局时间配置
ribbon:
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule
  ConnectTimeout: 250   #Ribbon的连接超时时间(毫秒),默认1秒
  ReadTimeout: 1000   #Ribbon的数据读取超时时间,默认1秒
  OkToRetryOnAllOperations: true  #是否对所有操作都进行重试
  MaxAutoRetriesNextServer: 1   #切换实例的重试次数
  MaxAutoRetries: 1   #对当前实例的重试次数

局部配置

star-orders: #微服务的名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule
    ConnectTimeout: 250   #Ribbon的连接超时时间(毫秒),默认1秒
    ReadTimeout: 1000   #Ribbon的数据读取超时时间,默认1秒
    OkToRetryOnAllOperations: true  #是否对所有操作都进行重试
    MaxAutoRetriesNextServer: 1   #切换实例的重试次数
    MaxAutoRetries: 1   #对当前实例的重试次数

当全局配置和局部配置,同时存在时将以 “局部配置为主”

OpenFeign

解决的问题

RestTemplate ,Ribbon都存在这么一个问题:代码耦合度很高。OpenFeign,它就是一种典型的接口式编程方案,从而可以做到微服务之间相互调用时,松散耦合关系

1597389321006.png

Feign和OpenFeign的区别

1597389522738.png

OpenFeign组件的使用

避坑:使用Feign,如果消费端传递对象类型的参数,那么服务端必须使用@RequestBody接参

1、在消费者添加依赖

<!-- OpenFeign的调用插件 -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、消费者开启对OpenFeign的支持

在启动类上,添加@EnableFeignClients,开启对OpenFeign的支持

@EnableFeignClients
@EnableEurekaClient
@SpringBootApplication
public class MicroUserServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(MicroUserServerApplication.class, args);
    }
}

3、定义feign接口

//@FeignClient的value属性,定义了服务生产方的spring.application.name名称
@FeignClient("star-product")
public interface ProductServerFeign {
    //无参get请求
    @GetMapping("/product/findAllProduct")
    ResultVO findAllProduct();
    //有参get请求,这种方法需要使用注解@PathVariable来声明参数位置
    @GetMapping("/product/findByPid/{pid}")
    ResultVO findByPid(@PathVariable("pid") Integer pid);
    //有参post请求,这种方法需要在feign和提供者中使用@RequestBody来传参
    @PostMapping("/product/save")
    ResultVO save(@RequestBody Product product);
}

4、消费者控制层注入该接口实例,并且调用方法

@Autowired
private ProductServerFeign productServerFeign;

@GetMapping("/findAllProduct")
public ResultVO findAllProduct(){
    ResultVO resultVO = productServerFeign.findAllProduct();
    return resultVO;
}

@GetMapping("/findByPid/{pid}")
public ResultVO findByPid(@PathVariable("pid") Integer pid){
    ResultVO resultVO = productServerFeign.findByPid();
    return resultVO;
}

@PostMapping("/save")
public ResultVO save(Product product){
    ResultVO resultVO = productServerFeign.save(product);
    return resultVO;
}

日志打印

feign:
  client:
    config:
      micro-base-server: #被调用者的微服务名称
        loggerLevel: FULL
logging:
  level:
    root: info #将日志下调至Debug
     top.ygang.microuserserver.classdemo.openFeign.MicroBaseServerFeign: debug