达内广州C++学院|c++培训|广州达内科技C++/C#培训|.NET培训|IT培训|达内广州岗顶中心 达内广州C++学院|c++培训|广州达内科技C++/C#培训|.NET培训|IT培训|达内广州岗顶中心
java程序员
 当前位置:主页 > 高端课程 > java程序员 >

Spring Cloud(3):Ribbon的使用

时间:2019-05-15  来源:未知  作者:广州达内培训

基于搭建好的Eureka Server+Eureka Client:https://www.cnblogs.com/xuyiqing/p/10861541.html

有了服务,那么现在学习如何调用服务

上文搭建的是商品服务,以下搭建订单服务,订单服务调用商品服务

 

对Eureka Client进行改造,方便以后得到数据来源

在商品服务的Controller层注入端口号,并进行回显:

package org.dreamtech.product.controller;

import org.dreamtech.product.domain.Product;
import org.dreamtech.product.service.ProductService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

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

    @Value("${server.port}")
    private String port;

    private final ProductService productService;

    @Autowired
    public ProductController(ProductService productService) {
        this.productService = productService;
    }

    @RequestMapping("/list")
    public Object list() {
        return productService.getProductList();
    }

    @RequestMapping("/find")
    public Object findById(@RequestParam("id") int id) {
        Product product = productService.findById(id);
        Product result = new Product();
        BeanUtils.copyProperties(product,result);
        result.setName(result.getName()+" data from port="+port);
        return result;
    }

}

启动Eureka Server,8761端口

启动三个商品服务,一个项目8771端口,一个8772端口,一个8773端口:

多实例启动方法如下图

 

新建一个SpringBoot项目order-service:

Web模块必须的,由于订单服务本身也是服务需要Eureka,最后负载均衡调用Ribbon

 

订单服务开发(模拟实现):

实体类

package org.dreamtech.orderservice.domain;

import java.io.Serializable;
import java.util.Date;

public class ProductOrder implements Serializable {
    //ID
    private int id;
    //商品名称
    private String productName;
    //订单号
    private String tradeNo;
    //价格
    private int price;
    //创建时间
    private Date createTime;
    //用户ID
    private int userId;
    //用户名
    private String userName;

    public String getUserName() {
        return userName;
    }

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

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public int getId() {
        return id;
    }

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

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getTradeNo() {
        return tradeNo;
    }

    public void setTradeNo(String tradeNo) {
        this.tradeNo = tradeNo;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}

 

为了方便,和商品服务一样,不调用数据库,只做简单的模拟:

在SpringBoot启动类中加入Bean

package org.dreamtech.orderservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class OrderServiceApplication {

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

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

 

配置文件对端口和服务名称进行配置:

server:
  port: 8781
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
spring:
  application:
    name: order-service

 

Controller:

package org.dreamtech.orderservice.controller;

import org.dreamtech.orderservice.service.ProductOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/order")
public class OrderController {
    private final ProductOrderService productOrderService;

    @Autowired
    public OrderController(ProductOrderService productOrderService) {
        this.productOrderService = productOrderService;
    }

    @RequestMapping("/save")
    public Object save(@RequestParam("user_id") int userId, @RequestParam("product_id") int productId) {
        return productOrderService.save(userId, productId);
    }
}

 

Service:

package org.dreamtech.orderservice.service;

import org.dreamtech.orderservice.domain.ProductOrder;

public interface ProductOrderService {
    /**
     * 下单接口
     *
     * @param userId    用户ID
     * @param productId 商品ID
     * @return ProductOrder
     */
    ProductOrder save(int userId, int productId);
}
package org.dreamtech.orderservice.service.impl;

import org.dreamtech.orderservice.domain.ProductOrder;
import org.dreamtech.orderservice.service.ProductOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Service
public class ProductOrderServiceImpl implements ProductOrderService {

    private final RestTemplate restTemplate;

    @Autowired
    public ProductOrderServiceImpl(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    @SuppressWarnings("unchecked")
    public ProductOrder save(int userId, int productId) {

        Map<String, Object> productMap = restTemplate.getForObject("http://product-service/api/product/find?id=" + productId, Map.class);

        ProductOrder productOrder = new ProductOrder();
        productOrder.setCreateTime(new Date());
        productOrder.setUserId(userId);
        productOrder.setTradeNo(UUID.randomUUID().toString());

        if (productMap != null) {
            productOrder.setProductName(productMap.get("name").toString());
            productOrder.setPrice(Integer.parseInt(productMap.get("price").toString()));
        }
        return productOrder;
    }
}

注意:getForObject方法的url中product-service是我在商品服务中配置的名称

 

启动项目,如果正常情况,Eureka应该显示如图:

 

访问http://localhost:8781/api/order/save?user_id=1&product_id=2多次,我将多次的返回结果记录在下:

{"id":0,"productName":"iPhone2 data from port=8771","tradeNo":"8beb0fe0-83ef-4d23-ae53-9399bac7eacc","price":2222,"createTime":"2019-05-15T03:21:12.432+0000","userId":1,"userName":null}
{"id":0,"productName":"iPhone2 data from port=8773","tradeNo":"09544f1d-462b-413a-b14a-cc9d599bce39","price":2222,"createTime":"2019-05-15T03:21:48.467+0000","userId":1,"userName":null}
{"id":0,"productName":"iPhone2 data from port=8771","tradeNo":"543e83a7-3e58-48bb-8aba-bd7635a10131","price":2222,"createTime":"2019-05-15T03:21:57.244+0000","userId":1,"userName":null}
{"id":0,"productName":"iPhone2 data from port=8772","tradeNo":"b30bbd40-49e8-4001-917a-0ae36b172463","price":2222,"createTime":"2019-05-15T03:22:06.509+0000","userId":1,"userName":null}

 

可以观察到,我开启了三个商品服务,这里自动在三个服务中进行了负载均衡,8771-8773随机访问

 

在SpringBoot启动类中加入Bean是一种方式,还有另一种调用方式:

不过还是推荐第一种

package org.dreamtech.orderservice.service.impl;

import org.dreamtech.orderservice.domain.ProductOrder;
import org.dreamtech.orderservice.service.ProductOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Service
public class ProductOrderServiceImpl implements ProductOrderService {
    private final LoadBalancerClient loadBalancer;

    @Autowired
    public ProductOrderServiceImpl(, LoadBalancerClient loadBalancer) {
        this.loadBalancer = loadBalancer;
    }

    @Override
    @SuppressWarnings("unchecked")
    public ProductOrder save(int userId, int productId) {

        ServiceInstance instance = loadBalancer.choose("product-service");
        String url = String.format("http://%s:%s/api/product/find?id="+productId,instance.getHost(),instance.getPort());
        RestTemplate restTemplate = new RestTemplate();
        Map<String, Object> productMap = restTemplate.getForObject(url, Map.class);


        ProductOrder productOrder = new ProductOrder();
        productOrder.setCreateTime(new Date());
        productOrder.setUserId(userId);
        productOrder.setTradeNo(UUID.randomUUID().toString());

        if (productMap != null) {
            productOrder.setProductName(productMap.get("name").toString());
            productOrder.setPrice(Integer.parseInt(productMap.get("price").toString()));
        }
        return productOrder;
    }
}

 

自定义负载均衡策略:

Ribbon默认是轮询策略

比如我想要使用随机策略,配置如下:

product-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

 注意:服务名的一致,比如区分"_"和"-"

 

通常情况下,不需要改变策略,轮询策略为最佳

但是如果有一个好机器,一堆差机器,那么可以调整好机器的权重




上一篇:数据库查询SQL语句的时候如何写会效率更高?
下一篇:Nginx反向代理

友情链接:
  • 全球最大晶圆代工半导体制造厂,台积电斥资订购艾斯摩尔机器设备
  • 英特尔依然是那个英特尔,且看英特尔的城防体系
  • 支持双 DRAM 内存接口,慧荣企业级 SSD 主控方案披露
  • 在全球被反垄断罚款,冤!高通到底哪里得罪了欧盟?
  • 强强联合!万业、微电子所和芯鑫共同打造全新半导体设备
  • 复旦大学校长称:对于集成电路产业发展,大学应该主动担当
  • 技术再升级!无锡中科芯攻克晶圆级再布线及晶圆级凸点制备关键技
  • 聚力!万业企业设立集成电路装备集团,提供自主可控设备
  • 德州仪器C2000微控制器增强连通性和控制性
  • 英特尔打出降价策略,以免被竞争对手 AMD 打败?
  • 贸易摩擦的闹剧没有赢家,苹果有勇气离开中国吗?
  • 图像信号与视觉处理器的发展趋势
  • 真干快消品定位方案班(第二期)火热开班
  • Java集合 ArrayList原理及使用
  • TDD(测试驱动开发)死了吗?
  • JAVA基础之XML相关
  • javaweb项目搭建ehcache缓存系统
  • 每日一码——字符串统计
  • 一篇文章帮你彻底搞清楚“I/O多路复用”和“异步I/O”的前世今生
  • 九:模板方法模式
  • 十二:命令模式(人员解耦和)
  • Java 转PPT为图片、PDF、SVG、XPS、ODP以及PPT和PPTX互转
  • SpringCloud学习(SPRINGCLOUD微服务实战)一
  • 记一次微信网页授权后获取用户信息并重定向
  • 速途新营销五点实战洞察解码“品效合一”
  • 十一:外观模式详解(Service,action与dao)
  • 手把手教你学会 基于JWT的单点登录
  • mysql锁机制总结,以及优化建议
  • 解决多个版本jar包冲突【jar内包名重命名】
  • 中国首张5G终端电信设备进网许可证 华为Mate 20 X 5G版入网
  • RPC之Thrift
  • 高级Java工程师必备 ----
  • 天猫618期间实物支付GMV增长38.5%
  • 换季了,老板你的库存处理好了吗?
  • 从“618”大数据看中国消费新活力
  • 小米生态链:贵在格局感与收放度
  • CODING 2.0 企业级持续交付解决方案
  • 老铁奇趴“新京济” 快手*京东618战报出炉
  • 中小企业新媒体运营基本技能
  • 上汽大通房车再度携手LINE FRIENDS 魔都巡游顺利开启
  • 华为高端手机国内市场份额超苹果夺得榜首
  • 中国智能制造分析报告
  • iPlus艾加营销助力腾讯广告牵手吴晓波 推进商业IP变现
  • 2019世界新能源汽车大会7月1日将在海南举行
  • 区域酒企如何转型突围
  • 时时彩论坛
  • 五星体育斯诺克
  • 北单比分直播
  • 河北11选5走势图
  • 福建体彩36选7开奖结果
  • 九龙图库下载