微服务如何进行远程调用其他服务

前置知识:将本地服务注册到nacos地址上:

1、服务调用:

现在我们需要使用service-order 服务调用sercice-business服务

使用@EnableDiscoveryClient注解, 开启服务调用

引入依赖

XML 复制代码
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

需要被调用的服务启动类:

java 复制代码
@EnableDiscoveryClient //开启服务调用
@SpringBootApplication
public class BusinessMainApplication{
    public static void main(String[] args) {
        SpringApplication.run(BusinessMainApplication.class,args);
    }
}

编写需要进行调用的接口:

java 复制代码
    @GetMapping("/business/{id}")
    public Business getById(@PathVariable("id") String id){
        return  businessService.getBusiness(id);
    }

创建RestTemplate配置类,防止new 多个对象

java 复制代码
@Configuration
public class OrderConfig {

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

在服务层进行调用另外一个服务

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

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;


    @Override
    public Order getById(Long id) {
        Order order = new Order();
        order.setTotalAmount(new BigDecimal("1000"));
        order.setNickName("尚硅谷");
        order.setId(id);
        order.setProductList(Lists.newArrayList());
        return order;
    }

    @Override
    public Order createOrder(Long userId, Long productId) {
        //进行远程调用获取商品数据
        Business businessById = getBusinessById(productId.toString());

        Order order = new Order();
        order.setId(1L);
        order.setAddress("将军大道108号");
        order.setTotalAmount(BigDecimal.valueOf(businessById.getPrice() * businessById.getCount()));
        order.setNickName("尚硅谷");
        order.setUserId(userId);
        order.setProductList(Arrays.asList(businessById));
        return order;
    }

    /**
     * 手动选择需要的实例进行调用
     * @param businessId
     * @return
     */
    public Business getBusinessById(String businessId){
        List<ServiceInstance> instances = discoveryClient.getInstances("service-business");

        //获取服务的第几个实例对象
        ServiceInstance instance = instances.get(0);
        //端口的URL
        String url = "http://" + instance.getHost() + ":"  + instance.getPort() + "/business/" + businessId;

        log.info("远程调用的URL:" + url);

        //进行远程调用
        Business forObject = restTemplate.getForObject(url, Business.class);
        log.info("返回的数据:" + forObject.toString());
        return forObject;
    }

}

2、负载均衡:

如果被调用的服务有多个实例,现在我们为了减轻某个服务的压力,对服务进行轮询调用:

现在我们需要在调用方,使用loadBanlancer依赖

依赖引入:

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

依赖导入:

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

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Override
    public Order getById(Long id) {
        Order order = new Order();
        order.setTotalAmount(new BigDecimal("1000"));
        order.setNickName("尚硅谷");
        order.setId(id);
        order.setProductList(Lists.newArrayList());
        return order;
    }

    @Override
    public Order createOrder(Long userId, Long productId) {
        //进行远程调用获取商品数据
//        Business businessById = getBusinessById(productId.toString());
//        Business businessById = getBusinessByIdWithLoadBalancer(productId.toString());
        Business businessById = getBusinessByIdWithAnnotation(productId.toString());

        Order order = new Order();
        order.setId(1L);
        order.setAddress("将军大道108号");
        order.setTotalAmount(BigDecimal.valueOf(businessById.getPrice() * businessById.getCount()));
        order.setNickName("尚硅谷");
        order.setUserId(userId);
        order.setProductList(Arrays.asList(businessById));
        return order;
    }

    /**
     * 手动选择需要的实例进行调用
     * @param businessId
     * @return
     */
    public Business getBusinessById(String businessId){
        List<ServiceInstance> instances = discoveryClient.getInstances("service-business");

        //获取服务的第几个实例对象
        ServiceInstance instance = instances.get(0);
        //端口的URL
        String url = "http://" + instance.getHost() + ":"  + instance.getPort() + "/business/" + businessId;

        log.info("远程调用的URL:" + url);

        //进行远程调用
        Business forObject = restTemplate.getForObject(url, Business.class);
        log.info("返回的数据:" + forObject.toString());
        return forObject;
    }


    /**
     * 使用LoadBalancer进行负载均衡
     * @param businessId
     * @return
     */
    public Business getBusinessByIdWithLoadBalancer(String businessId){

        ServiceInstance choose = loadBalancerClient.choose("service-business");
        //端口的URL
        String url = "http://" + choose.getHost() + ":"  + choose.getPort() + "/business/" + businessId;

        log.info("IP:" + choose.getHost() + ":" + choose.getPort());
        log.info("远程调用的URL:" + url);

        //进行远程调用
        Business forObject = restTemplate.getForObject(url, Business.class);
        log.info("返回的数据:" + forObject.toString());
        return forObject;
    }


    /**
     * 使用注解@LoadBalancer进行负载均衡
     * 需要在restTemplate上添加注解LoadBalancer
     * @param businessId
     * @return
     */
    public Business getBusinessByIdWithAnnotation(String businessId){

        String url = "http://service-business/business/" + businessId;


        //进行远程调用
        Business forObject = restTemplate.getForObject(url, Business.class);
        log.info("返回的数据:" + forObject.toString());
        return forObject;
    }


}

其中,第三种,使用注解的方式进行负载均衡,需要将注解添加在restTemplate配置类上

java 复制代码
@Configuration
public class OrderConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
相关推荐
小bo波8 小时前
从"任意文件复制"深挖Java I/O:字符流与字节流的本质抉择
java·nio·io流·后端开发·文件复制
贵慜_Derek17 小时前
《从零实现 Agent 系统》连载 32|闭集 IE 与小模型:分类、意图与字段抽取
人工智能·架构·agent
江米小枣tonylua1 天前
译:设计生产级 RAG 架构
架构
nanxun8861 天前
记一次诡异的 Docker 容器"串包"故障排查
java
怕浪猫1 天前
领域特定语言(Domain-Specific Language, DSL)
设计模式·程序员·架构
怕浪猫1 天前
哪些软件对 Chrome DevTools Protocol 频繁使用
人工智能·架构·前端框架
用户1563068103511 天前
Day01 | Java 基础(Java SE)
java
行者全栈架构师2 天前
Maven dependency:tree 的 8 个高级用法
java·后端
Jack202 天前
HarmonyOS APP事件驱动大揭秘
架构
米丘2 天前
微前端之 Web Components 完全指南
微服务·html