Spring Cloud(四)RestTemplate服务调用与Ribbon负载均衡

版权声明:From Lay https://blog.csdn.net/Sadlay/article/details/84789209

Spring Cloud(四)RestTemplate服务调用与Ribbon负载均衡

上面已经把产品和用户两个微服务注册到服务治理中心了。对于业务,则往往需要各个微服务之间相互地协助才能完成。例如,可能把产品交易信息放到产品服务中,而在交易时,有时需要根据用户的等级来决定默写商品的折扣,如白银会员9折,黄金会员8折等等。也就是说分布式系统在执行交易逻辑时,还需要使得产品微服务得到用户信息才可以决定产品的折扣,而用户的信息则是放置在用户微服务中的。为了方便用户微服务中获取用户信息,用户微服务会以REST风格提供一个请求URL。这样对于产品微服务就可以通过REST请求获取用户服务。

除了处理获取其他服务的数据外,这里还需要注意服务节点之间的负载均衡,毕竟一个微服务可以由多个节点提供服务。不过这些都不困难,因为Spring Cloud提供了RibbonFeign组件来帮助我们来完成这些任务。通过它们,各个微服务之间就能够相互调用,并且它会默认实现了负载均衡。

Ribbon客户端负载均衡

对于Ribbon,其实并没有什么神秘的,它实际就是一个RestTemplate对象。只是上面还讨论了多个节点的问题,例如调度用户微服务时,因为用户微服务存在多个节点,具体会使用哪个节点提供服务呢?关于这点Spring Cloud已经屏蔽了一些底层的细节,它只需要一个简单的@LoadBalance注解就看可以提供负载均衡的算法。这十分符合spring boot的原则,提供默认的实现方式,减少开发者的工作量。在默认情况下,它会提供轮询的负载均衡算法。其他的负载均衡算法比较复杂,这里不讲(我也不会。。。)

下面用实例来说明Ribbon的使用。现在用户微服务上写一个Pojo

User

package com.lay.user.pojo;

import java.io.Serializable;

/**
 * @Description:
 * @Author: lay
 * @Date: Created in 16:31 2018/11/26
 * @Modified By:IntelliJ IDEA
 */
public class UserPo implements Serializable {

    private static final long serialVersionUID = 6984412951642658165L;

    private Long id;
    private String userName;
    //1-白银会员,2-黄金会员,3-钻石会员
    private int level;
    private String note;

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }
}

然后我们可以给出基于REST风格的实现用户返回的代码

@RestController
public class UserController {
    //日志
    private static final Logger log= LoggerFactory.getLogger(UserController.class);

    //服务发现客户端
    @Autowired
    private DiscoveryClient discoveryClient;

    //获取用户信息
    @GetMapping("/user/{id}")
    public UserPo getUserPo(@PathVariable("id") Long id){
        ServiceInstance service = discoveryClient.getInstances("USER").get(0);
        log.info("【"+service.getServiceId()+"】"+service.getHost()+": "+service.getPort());
        UserPo userPo=new UserPo();
        userPo.setId(id);
        userPo.setLevel((int) (id&3+1));
        userPo.setUserName("user_name_"+id);
        userPo.setNote("note_"+id);
        return userPo;
    }

这里DiscoveryClient对象是spring boot自动创建的。

然后我们在产品微服务添加对Ribbon的依赖

Ribbon依赖

        <!-- ribbon负载均衡-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

然后对RestTemplate进行初始化

@SpringBootApplication
public class ProductApplication {

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

    //初始化RestTemplate
    @LoadBalanced //多节点负载均衡
    @Bean(name="restTemplate")
    public RestTemplate initRestTemplate(){
        return new RestTemplate();
    }
}

测试

@RestController
@RequestMapping("product")
public class ProductController {

    // 注入RestTemplate
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/ribbon")
    public List<UserPo> testRibbon() {
        List<UserPo> list = new ArrayList<>();
        UserPo user = null;
        for (int i = 0; i < 10; i++) {
            //这里使用USER这个服务ID,代表用户维服务系统
            //该ID通过属性spring.application.name来指定
            //user = restTemplate.getForObject("http://USER/user/"+(i+1), UserPo.class);
            Long id = Long.valueOf((i + 1));
            user = restTemplate.getForObject("http://USER/user/"+(i+1),UserPo.class);
            list.add(user);
        }
        return list;
    }
}

代码中注入了RestTemplate对象,这是自动实现客户端均衡负载的对象。然后再方法中使用"USER"这个字符串代替了服务器以及其段哦偶,这是一个服务ID(Service ID),在Eureka服务器中可以看到它的各个节点,他是用户微服务通过属性spring.application.name来指定的。这里故意地调用了10次,这样就能够观察各个用户微服务节点的日志来观察负载均衡的情况。

猜你喜欢

转载自blog.csdn.net/Sadlay/article/details/84789209