【微服务学习二】nacos服务发现与负载均衡

nacos服务发现

想要开启服务发现,需要在main函数上添加 @EnableDiscoveryClient 注解

然后我们编写一个controller类来查询nacos中注册的所有微服务以及对应的ip+端口号

java 复制代码
@Controller
public class DiscoveryController {

    @Autowired
    DiscoveryClient discoveryClient;

    // 这个方法可以获取nacos中注册的服务信息
    @GetMapping("/getServicesInfo")
    @ResponseBody
    public String getServicesInfo() {
        StringBuilder sb = new StringBuilder();
        // 查询服务名称和服务的ip+端口号
        for (String serviceId : discoveryClient.getServices()) {
            sb.append(serviceId + "<br>");
            for (ServiceInstance instance : discoveryClient.getInstances(serviceId)) {
                sb.append(instance.getHost() + ":" + instance.getPort() + "<br>");
            }
        }
        return sb.toString();
    }

}

接着启动微服务,然后在浏览器中调用该接口就可以查到对应的信息

简单下单场景

了解了服务发现的基本内容,我们就可以进行一个简单的下单场景模拟,场景流程如下

首先我们需要给商品服务编写一个根据商品id查询商品的接口

由于我们需要编写bean类,为了方便起见,我们首先给services的配置文件中添加lombok依赖和fastjson依赖

接着我们编写controller类,这个类提供一个查询商品信息的接口

java 复制代码
@RestController
public class ProductController {

    @Autowired
    ProductService productService;

    @GetMapping("/getProduct/{id}")
    @ResponseBody
    public String getProductById(@PathVariable("id") Long productId) {
        Product product = productService.getProductById(productId);
        return JSON.toJSONString(product);
    }

}

接着是商品的bean类

java 复制代码
@Data
public class Product {

    private Long id;
    private BigDecimal price;
    private String productName;
    private int num;

}

最后是service类

java 复制代码
@Service
public class ProductServiceImpl implements ProductService {

    @Override
    public Product getProductById(Long id) {
        Product product = new Product();
        product.setId(id);
        product.setPrice(new BigDecimal("99"));
        product.setProductName("苹果-" + id);
        product.setNum(2);
        return product;
    }
}

在浏览器中调用方法可以获取查询结果

由于微服务之间可能会有相互依赖的模型层,因此需要将共用的模型层的bean类放到一个公共的模块中

需要在model模块中添加lombok依赖

然后在services模块中引入model模块

一下是Order实体类的代码

java 复制代码
@Data
public class Order {

    private Long id;
    private BigDecimal totalAmount;
    private Long userId;
    private String nickName;
    private String address;
    private List<Object> productList;

}

接着我们编写order服务的controller

java 复制代码
@RestController
public class OrderController {

    @Autowired
    OrderService orderService;

    @GetMapping("/createOrder/{userId}/{productId}")
    public String createOrder(@PathVariable Long userId, @PathVariable Long productId) {
        Order order = orderService.createOrder(userId, productId);
        return JSON.toJSONString(order);
    }

}

由于在service中由于需要使用到RestTemplate进行远程调用,因此我们需要编写一个配置类,给容器注入一个RestTemplate实例

java 复制代码
@Configuration
public class OrderConfig {

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

}

最后编写service

java 复制代码
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    DiscoveryClient discoveryClient;

    @Autowired
    RestTemplate restTemplate;

    @Override
    public Order createOrder(Long userId, Long productId) {
        Order order = new Order();
        order.setId(2L);
        order.setUserId(userId);
        Product product = getProductRemote(productId);
        BigDecimal totalPrice = product.getPrice().multiply(new BigDecimal(product.getNum()));
        order.setTotalAmount(totalPrice);
        order.setAddress("福建省");
        order.setNickName("小明明");
        order.setProductList(Arrays.asList(product));
        return order;
    }

    // 通过远程调用的方式获取商品数据
    private Product getProductRemote(Long productId) {
        discoveryClient.getInstances("service-product");
        List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
        String url = "http://" + instances.get(0).getHost() + ":" + instances.get(0).getPort() + "/getProduct/" + productId;
        log.info("远程调用:{}", url);
        Product product = restTemplate.getForObject(url, Product.class);
        return product;
    }


}

在浏览器中调用接口就可以获取数据

负载均衡

由于我们的订单服务需要进行负载均衡的调用,因此首先需要添加负载均衡的依赖

接着就是在service中使用 LoadBalancerClient 进行负载均衡的调用

用浏览器进行多次调用得到的测试结果如下

可以发现是交替调用两个商品服务的

除了上述方式外,还可以通过注解的方式进行负载均衡的调用

首先需要在配置类中加上 @LoadBalanced 注解

接着在如下图修改远程调用方法中的url即可

相关推荐
没有bug.的程序员19 分钟前
分布式架构未来趋势:从云原生到智能边缘的演进之路
java·分布式·微服务·云原生·架构·分布式系统
deng-c-f7 小时前
Linux C/C++ 学习日记(28):KCP协议(四):如何实现更复杂的业务:将连接状态的管理进行封装,用户只需实现发送、接收、断开的处理逻辑。
学习·网络编程·kcp
007php0079 小时前
百度面试题解析:微服务架构、Dubbo、Redis及其一致性问题(一)
redis·百度·docker·微服务·容器·职场和发展·架构
立志成为大牛的小牛10 小时前
数据结构——二十三、并查集的终极优化(王道408)
开发语言·数据结构·笔记·学习·程序人生·考研
QT 小鲜肉11 小时前
【个人成长笔记】Qt Creator快捷键终极指南:从入门到精通
开发语言·c++·笔记·qt·学习·学习方法
小猪咪piggy12 小时前
【微服务】(1) Spring Cloud 概述
java·spring cloud·微服务
QT 小鲜肉14 小时前
【数据结构与算法基础】05. 栈详解(C++ 实战)
开发语言·数据结构·c++·笔记·学习·算法·学习方法
A9better14 小时前
嵌入式开发学习日志40——stm32之I2C协议层
stm32·单片机·嵌入式硬件·学习
ha204289419415 小时前
Linux操作系统学习之---线程控制
java·linux·学习
Laplaces Demon17 小时前
Spring 源码学习(十四)—— HandlerMethodArgumentResolver
java·开发语言·学习