微服务进行远程调用其他服务方式

 更新时间:2026年01月23日 09:13:05   作者:袅沫  
文章主要介绍了如何将本地服务注册到Nacos地址上,并详细描述了服务调用和负载均衡的实现方法,包括使用`@EnableDiscoveryClient`注解开启服务调用、编写调用接口、创建RestTemplate配置类以及使用负载均衡依赖进行服务调用

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

1、服务调用

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

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

引入依赖

        <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>

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

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

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

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

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

@Configuration
public class OrderConfig {

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

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

@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依赖

依赖引入:

  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>

依赖导入:

@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配置类上

@Configuration
public class OrderConfig {

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

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 一文简单了解C# 中的DataSet类

    一文简单了解C# 中的DataSet类

    这篇文章主要介绍了一文简单了解C# 中的DataSet类,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-08-08
  • Junit springboot打印测试方法信息

    Junit springboot打印测试方法信息

    这篇文章主要介绍了Junit springboot打印测试方法信息,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • IDEA如何使用spring-Initializr快速搭建SpringBoot

    IDEA如何使用spring-Initializr快速搭建SpringBoot

    这篇文章主要介绍了IDEA如何使用spring-Initializr快速搭建SpringBoot问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • 使用bitset实现毫秒级查询(实例讲解)

    使用bitset实现毫秒级查询(实例讲解)

    下面小编就为大家带来一篇使用bitset实现毫秒级查询(实例讲解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • Java设计模式之桥接模式实例详解

    Java设计模式之桥接模式实例详解

    这篇文章主要介绍了Java设计模式之桥接模式,结合实例形式详细分析了桥接模式的概念、功能、Java实现方法及相关注意事项,需要的朋友可以参考下
    2017-09-09
  • MyBatis学习教程之开发Dao的方法教程

    MyBatis学习教程之开发Dao的方法教程

    这篇文章主要给大家介绍了关于MyBatis开发Dao的相关资料,使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法。文中通过示例代码介绍的非常详细,需要的朋友们下面来一起看看吧。
    2017-07-07
  • Spring Boot REST国际化的实现代码

    Spring Boot REST国际化的实现代码

    本文我们将讨论如何在现有的Spring Boot项目中添加国际化。只需几个简单的步骤即可实现Spring Boot应用的国际化,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • SpringBoot如何设置404、500返回统一格式json

    SpringBoot如何设置404、500返回统一格式json

    这篇文章主要介绍了SpringBoot如何设置404、500返回统一格式json问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • JAVA使用geotools读取shape格式文件的方法

    JAVA使用geotools读取shape格式文件的方法

    这篇文章主要介绍了JAVA使用geotools读取shape格式文件的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2017-01-01
  • java实现文件保存到本地的方法

    java实现文件保存到本地的方法

    本篇文章主要介绍了java实现文件保存到本地的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02

最新评论