SpringCloudAlibaba微服务一站式解决方案-03负载均衡

上回说到了商品微服务可以从注册中心拿到商品微服务的信息,进行下单操作.
请看下面的代码

 //获取商品微服务集合和信息
        List<ServiceInstance> instances = discoveryClient.getInstances("service-product2021");
        //获取第一个实例
        ServiceInstance serviceInstance = instances.get(0);
        //host ip地址
        String host = serviceInstance.getHost();
        //port 端口号
        int port = serviceInstance.getPort();
        Product product = restTemplate.getForObject("http://" + host + ":" + port + "/findProductById/" + pid, Product.class);

好像是没有什么问题,可以正常请求,但是如果将来商品微服务集群了,那我们是调用第一个实例呐还是第二个实例呐?应该来说都不行!因为一旦集群了就说明都要被调用,如何被调用呐?此时又引入了一个概念-负载均衡。也就说均衡的调用每个服务,分担到每个服务上执行。根据负载均衡发生的位置不同,一般分为服务端负载均衡和客户端负载均衡。
服务端负载均衡指的是发生在服务提供者一方,如常见的Nginx
在这里插入图片描述

客户端负载均衡指的是调用方/消费者,请求时就确定了调用哪个服务,通常在微服务中大多会选择此方式。
在这里插入图片描述
此时我们给shop-product再添加一个服务,选择springboot服务。
在这里插入图片描述
下边我们自定义一个小小算法来实现负载均衡。

 /**
     * 随机获取请求服务
     * @param instances
     * @return
     */
    private String randomServer(List<ServiceInstance> instances) {
        Map<String, Integer> map = new HashMap<>();
        //key:192.168.9.186:9001
        //value:0
        for (int i = 0; i < instances.size(); i++) {
            StringBuilder stringBuilder = new StringBuilder();
            //host ip地址
            stringBuilder.append(instances.get(i).getHost());
            stringBuilder.append(":");
            //port 端口号
            stringBuilder.append(instances.get(i).getPort());
            map.put(stringBuilder.toString(), i);
        }

        Set<String> keySet = map.keySet();
        List<String> list = new ArrayList<>();
        list.addAll(keySet);
        Random random = new Random();
        int i = random.nextInt(keySet.size());
        String s = list.get(i);
        return s;
    }

就这样无论服务提供者有多少个实例,我们都可以随机生成一个server,

 @RequestMapping("/createOrder/{pid}")
    public Order createOrder(@PathVariable Integer pid) {
        //获取商品微服务集合和信息
        List<ServiceInstance> instances = discoveryClient.getInstances("service-product2021");

        String s = randomServer(instances);
        //获取第一个实例
       // ServiceInstance serviceInstance = instances.get(0);
        //host ip地址
       // String host = serviceInstance.getHost();
        //port 端口号
       // int port = serviceInstance.getPort();
        Product product = restTemplate.getForObject("http://" +s + "/findProductById/" + pid, Product.class);
        Order order = new Order();
        order.setNumber(2);
        order.setUid(1);
        order.setUsername("chenchen");

        order.setPid(product.getPid());
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        return orderService.createOrder(order);
    }

再去测试,看控制台已经实现随机负载均衡

2021-05-13 22:28:14.743  INFO 22540 --- [nio-8092-exec-1] com.chenchen.controller.OrderController  : 服务:192.168.0.101:8082
2021-05-13 22:28:15.111  INFO 22540 --- [nio-8092-exec-1] c.c.service.impl.OrderServiceImpl        : 下单成功,订单信息Order(oid=291, uid=1, username=chenchen, pid=3, pname=苹果, pprice=3000.0, number=2)
2021-05-13 22:28:16.739  INFO 22540 --- [nio-8092-exec-2] com.chenchen.controller.OrderController  : 服务:192.168.0.101:8082
2021-05-13 22:28:16.756  INFO 22540 --- [nio-8092-exec-2] c.c.service.impl.OrderServiceImpl        : 下单成功,订单信息Order(oid=292, uid=1, username=chenchen, pid=3, pname=苹果, pprice=3000.0, number=2)
2021-05-13 22:28:16.962  INFO 22540 --- [nio-8092-exec-5] com.chenchen.controller.OrderController  : 服务:192.168.0.101:8081
2021-05-13 22:28:16.978  INFO 22540 --- [nio-8092-exec-5] c.c.service.impl.OrderServiceImpl        : 下单成功,订单信息Order(oid=293, uid=1, username=chenchen, pid=3, pname=苹果, pprice=3000.0, number=2)
2021-05-13 22:28:17.185  INFO 22540 --- [nio-8092-exec-7] com.chenchen.controller.OrderController  : 服务:192.168.0.101:8081
2021-05-13 22:28:17.204  INFO 22540 --- [nio-8092-exec-7] c.c.service.impl.OrderServiceImpl        : 下单成功,订单信息Order(oid=294, uid=1, username=chenchen, pid=3, pname=苹果, pprice=3000.0, number=2)
2021-05-13 22:28:17.371  INFO 22540 --- [nio-8092-exec-9] com.chenchen.controller.OrderController  : 服务:192.168.0.101:8082
2021-05-13 22:28:17.384  INFO 22540 --- [nio-8092-exec-9] c.c.service.impl.OrderServiceImpl        : 下单成功,订单信息Order(oid=295, uid=1, username=chenchen, pid=3, pname=苹果, pprice=3000.0, number=2)
2021-05-13 22:28:17.539  INFO 22540 --- [nio-8092-exec-1] com.chenchen.controller.OrderController  : 服务:192.168.0.101:8082
2021-05-13 22:28:17.550  INFO 22540 --- [nio-8092-exec-1] c.c.service.impl.OrderServiceImpl        : 下单成功,订单信息Order(oid=296, uid=1, username=chenchen, pid=3, pname=苹果, pprice=3000.0, number=2)

鉴于我们自己实现的负载均衡方式,单一且容错性不高,我们还是使用官方的组件Ribbon,它提供了一个注解@LoadBalanced自动实现负载均衡

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

然后改造我们的controller

@RequestMapping("/createOrder/{pid}")
    public Order createOrder(@PathVariable Integer pid) {
        //使用微服务的名字,从注册中心Nacos中获取
        String url = "service-product2021";
        Product product = restTemplate.getForObject("http://" + url + "/findProductById/" + pid, Product.class);
        Order order = new Order();
        order.setNumber(2);
        order.setUid(1);
        order.setUsername("chenchen");

        order.setPid(product.getPid());
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        return orderService.createOrder(order);
    }

负载均衡的策略有很多,如 随机、轮询、轮询加权、Hash、随机加权等,如果不指定默认使用轮询方式。如果要修改策略,只需要在服务调用方shop-order中application.yml添加配置即可。

service-product: #配置负载均衡 service-product服务提供者的名字 默认采用轮询策略
    ribbon:
      NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值