SpringCloud从入门到上天:Nacos做微服务注册中心(二)

一:远程调用基本流程

1:基本流程

2:模拟一个真实场景

二:编写测试代码进行RPC

1:编写订单编码

复制代码
@RestController
public class OrderController {

    @Autowired
    private OrderService orderService;

    @GetMapping("/create")
    public Order createOrder(@RequestParam("userId") Long userId, @RequestParam("productId") Long productId) throws NacosException {
        Order order = orderService.createOrder(productId, userId);
        return order;
    }
}


@Service
public class OrderServiceImpl implements OrderService{

    @Autowired
    NacosServiceDiscovery nacosServiceDiscovery;
    @Autowired
    RestTemplate restTemplate;

    @Override
    public Order createOrder(Long productId, Long user) throws NacosException {
        Order order = new Order();
        order.setId(productId);
        order.setProducts(List.of(productId));
        return order;
    }

    private Product getProduct(Long productId) throws NacosException {
        List<ServiceInstance> instances = nacosServiceDiscovery.getInstances("service-product");
        ServiceInstance serviceInstance = instances.get(0);
        String url = "http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/product/"+productId;
        Product product = restTemplate.getForObject(url, Product.class);
        return product;
    }
}

2:编写商品编码

复制代码
@RestController
public class ProductController {


    @Autowired
    ProductService productService;

    @GetMapping("/product/{id}")
    public Product getProductbyId(@PathVariable("id") Long productId){
        return  productService.getProductById(productId);
    }
}


@Service
public class productServiceImpl implements ProductService {
    @Override
    public Product getProductById(Long id) {
        Product product = new Product();
        product.setProductName("苹果");
        product.setId(id);
        return product;
    }
}

到这我们已经实现了基于注册中心的远程调用:http版本的。

3:负载均衡

复制代码
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>

@SpringBootTest
public class LoadBalanceTest {

    @Autowired
    LoadBalancerClient loadBalancerClient;

    @Test
    void test(){
        for (int i = 0; i < 100; i++) {
            ServiceInstance choose = loadBalancerClient.choose("service-product");
            System.out.println("choose"+choose.getHost()+":"+choose.getPort());
        }
    }
}

choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001
choose192.168.59.1:8002
choose192.168.59.1:8001

基于此,我们修改负载均衡的代码。

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

    @Autowired
    NacosServiceDiscovery nacosServiceDiscovery;
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    LoadBalancerClient loadBalancerClient;

    @Override
    public Order createOrder(Long productId, Long user) throws NacosException {
        Order order = new Order();
        order.setId(productId);
        order.setProducts(List.of(productId));
        return order;
    }

    private Product getProduct(Long productId) throws NacosException {
        ServiceInstance serviceInstance = loadBalancerClient.choose("service-product");
        String url = "http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/product/"+productId;
        Product product = restTemplate.getForObject(url, Product.class);
        return product;
    }
}

4:@LoadBalance

这样的话,RestTemplate默认就带有了负载均衡功能。

url中真实的ip地址换成应用名称,RestTemplate可以动态给我们进行替换。

复制代码
@Configuration
public class ProductServiceConfig {


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

public class OrderServiceImpl implements OrderService{

    @Autowired
    NacosServiceDiscovery nacosServiceDiscovery;
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    LoadBalancerClient loadBalancerClient;

    @Override
    public Order createOrder(Long productId, Long user) throws NacosException {
        Order order = new Order();
        order.setId(productId);
        order.setProducts(List.of(productId));
        return order;
    }

    private Product getProduct(Long productId) throws NacosException {
//        ServiceInstance serviceInstance = loadBalancerClient.choose("service-product");
        // 这里改为应用名称即可。
        String url = "http://service-product"+"/product/"+productId;
        Product product = restTemplate.getForObject(url, Product.class);
        return product;
    }
}

5:思考

如果注册中心宕机,远程过程调用还能成功吗?

应用服务中会进行实例缓存,将注册中心的数据进行同步和实时更新。当注册中心宕机了

1:如果调用过的接口:缓存中已经拿到过地址列表。可以通讯

2:如果没有调用过:缓存中没有,需要第一次进行,则必须去注册中心拿地址。

Nacos注册中心是这么做的。

相关推荐
雨中飘荡的记忆9 小时前
ElasticJob分布式调度从入门到实战
java·后端
考虑考虑18 小时前
JDK25模块导入声明
java·后端·java ee
_小马快跑_19 小时前
Java 的 8 大基本数据类型:为何是不可或缺的设计?
java
Re_zero1 天前
线上日志被清空?这段仅10行的 IO 代码里竟然藏着3个毒瘤
java·后端
洋洋技术笔记1 天前
Spring Boot条件注解详解
java·spring boot
程序员清风2 天前
程序员兼职必看:靠谱软件外包平台挑选指南与避坑清单!
java·后端·面试
皮皮林5512 天前
利用闲置 Mac 从零部署 OpenClaw 教程 !
java
华仔啊2 天前
挖到了 1 个 Java 小特性:var,用完就回不去了
java·后端
SimonKing2 天前
SpringBoot整合秘笈:让Mybatis用上Calcite,实现统一SQL查询
java·后端·程序员
日月云棠3 天前
各版本JDK对比:JDK 25 特性详解
java