实习闲暇时间杂记一手,简单记录下微服务之间的调用过程,两种调用方式:Feign 过程调用和RestTemleate + Ribbon调用方式 。

Feign介绍:

spring cloud调用其他服务的底层原理 spring cloud的服务调用方式_Spring Cloud

feign是一个声明性Web服务客户机。它使编写Web服务客户机更加容易。要使用佯装,请创建一个接口并对其进行注释。它具有可插入的注释支持,包括外部注释和JAX-RS注释。Feign还支持可插拔的编码器和解码器。SpringCloud增加了对SpringMVC注释的支持,以及对使用SpringWeb中默认使用的相同httpMessageConverter的支持。SpringCloud集成了Ribbon和Eureka,在使用Feign时提供负载平衡的HTTP客户端。

接上上一节的项目,项目地址:https://github.com/wdgup/cloud_demo,假设有一个场景,创建订单时会调用用户服务的查询方法,实现服务调用先导入依赖:

spring cloud调用其他服务的底层原理 spring cloud的服务调用方式_spring_02

cloud-order 项目导入 feign 的依赖:

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

下面演示下两种调用方式:

一、Feign调用

order服务 调用user服务时,需声明一个调用的客户端接口:

UserClient.java:

package com.wdg.cloudorder.client;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * @author WDG
 * @date 2019-4-26
 */
@FeignClient(name = "cloud-user")
public interface UserClient {

    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    JSONObject findUser(@PathVariable(name = "id") Integer id);
}

接口上加上 @FeignClient 注解 ,name属性声明要调用注册中心的那个服务,当多个相同的服务注册在注册中心时,Ribbon实现了负载均衡,也可以通过 url 属性 明确指定调用哪个服务 ,加上此注解 此时并非起作用,启动类上要加上


@EnableFeignClients注解,开启扫描@FeignClient注解。


调用user服务的某个方法,要在客户端中配置相同的方法,当有参数传递时, 使用@PathVariable或 @RequestParam 注解时必须指定name 值,否则会报错。

OrderContoller.java:

package com.wdg.cloudorder.controller;

import com.alibaba.fastjson.JSONObject;
import com.wdg.cloudorder.client.UserClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * @author WDG
 * @date 2019-4-26
 */
@RestController
@RequestMapping("/order")
public class OrderController {
    
    @Autowired
    private UserClient userClient;
   

    @GetMapping(value = "/createOrder/{userId}")
    public ResponseEntity createOrder(@PathVariable(name = "userId") Integer userId){
        JSONObject user = userClient.findUser(userId);
        System.out.println(user);
        return ResponseEntity.ok(user);
    }

}

先启动Eureka服务,再启动user和order服务,访问创建订单服务:http://localhost:9003/order/createOrder/1

spring cloud调用其他服务的底层原理 spring cloud的服务调用方式_Ribbon_03

可以看到调用user服务成功了。

二、RestTemplate + Ribbon

配置类中创建一个RestTemplate 实例:

@Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

OrderController.java 中增加 代码:

@Autowired
    private RestTemplate restTemplate;
@GetMapping(value = "/createOrder")
    public ResponseEntity createOrderByRestTemplate(@RequestParam(name = "userId") Integer userId){
        ResponseEntity<JSONObject> result = restTemplate.getForEntity("http://localhost:9001/user/" + userId, JSONObject.class);
        System.out.println(result.getBody());
        return ResponseEntity.ok(result.getBody());
    }

指定要调用的 url 和 返回类型,postman 测试

spring cloud调用其他服务的底层原理 spring cloud的服务调用方式_Feign_04

可以看到用RestTemplate 调用成功了。

下面演示一哈 Ribbon的负载均衡策略,修改user 服务的端口号,启动三个user服务:

spring cloud调用其他服务的底层原理 spring cloud的服务调用方式_RestTemplate_05

IRule接口代表负载均衡策略:

spring cloud调用其他服务的底层原理 spring cloud的服务调用方式_Spring Cloud_06

可以看到有几种负载均衡策略:其中RandomRule表示随机策略、RoundRobinRule表示轮询策略、WeightedResponseTimeRule表示加权策略、BestAvailableRule表示请求数最少策略等等。Ribbon默认的是轮询策略

调试调用多次http://localhost:9003/order/createOrder/1接口,控制台观察几个用户服务的日志信息,:

spring cloud调用其他服务的底层原理 spring cloud的服务调用方式_Feign_07

spring cloud调用其他服务的底层原理 spring cloud的服务调用方式_Spring Cloud_08

spring cloud调用其他服务的底层原理 spring cloud的服务调用方式_RestTemplate_09

可以看到调用每个服务都被调用过了。