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

前置知识:将本地服务注册到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();
    }
}
相关推荐
2501_941148152 小时前
高并发搜索引擎Elasticsearch与Solr深度优化在互联网实践分享
java·开发语言·前端
笨蛋不要掉眼泪3 小时前
Docker概念入门与初步安装
docker·微服务·容器
q***13343 小时前
使用 java -jar 命令启动 Spring Boot 应用时,指定特定的配置文件的几种实现方式
java·spring boot·jar
信码由缰3 小时前
Spring Data JPA 最佳实践【1/2】:实体设计指南
java
曾经的三心草4 小时前
JavaEE初阶-jvm
java·jvm·java-ee
醇氧4 小时前
Idea防止工具栏自动隐藏
java·ide·intellij-idea
m0_639817154 小时前
基于springboot教学资料管理系统【带源码和文档】
java·spring boot·后端
靠沿4 小时前
Java数据结构初阶——LinkedList
java·开发语言·数据结构
qq_12498707534 小时前
基于springboot的建筑业数据管理系统的设计与实现(源码+论文+部署+安装)
java·spring boot·后端·毕业设计