zoukankan      html  css  js  c++  java
  • 【SpringCloud】07.应用间的通信

    应用间通信

    HTTP vs RPC

    • Spring Cloud (HTTP)
    • Dubbo (RPC)

    1.SpringCloud中服务间两种restful调用方式

    • RestTemplate
    • Feign

    方式一、RestTemplate:是一个http客户端

    RestTemplate有三种方式

    1.直接写url :http://localhost:8080/msg

    使用restTemplate.getForObject("http://localhost:8080/msg", String.class);方法

    @RestController
    @Slf4j
    public class ClientController {
        @GetMapping("/getProductMsg")
        public String getProductMsg(){
            //1. 第一种方式
            RestTemplate restTemplate = new RestTemplate();
            String response = restTemplate.getForObject("http://localhost:8080/msg", String.class);
            log.info("response={}",response);
            return response;
        }
    }
    

    缺点:地址是写死的,如果对方服务有多台,这样很不好。

    2.通过 ServiceInstance serviceInstance = loadBalancerClient.choose("ServerId"); 获得服务的信息。
    ServerId :服务的名字

      @Autowired
      private LoadBalancerClient loadBalancerClient;
    
    @RestController
    @Slf4j
    public class ClientController {
        @Autowired
        private LoadBalancerClient loadBalancerClient;
        
        @GetMapping("/getProductMsg")
        public String getProductMsg(){
            //2.第二种
            ServiceInstance serviceInstance= loadBalancerClient.choose("PRODUCT");
            String url = String.format("http://%s:%s",serviceInstance.getHost(),serviceInstance.getPort())+"/msg";
            RestTemplate restTemplate = new RestTemplate();
            String response = restTemplate.getForObject(url, String.class);
            log.info("response={}",response);
            return response;
        }
    
    1. 先增加@Autowired LoadBalancerClient
    2. 通过loadBalancerClient.choose("ServerId");返回一个ServiceInstance
    3. serviceInstance.getHost()serviceInstance.getPort()可以分别获得主机以及端口号
    4. 拼接主机以及端口
    5. 通过第一种方法的restTemplate.getForObject(url, String.class)请求数据
    方法 说明 返回例子
    serviceInstance.getUri() 路径 http://localhost:8080
    serviceInstance.getHost() 主机 localhost
    serviceInstance.getServiceId() 服务id PRODUCT
    serviceInstance.getPort() 端口号 8080

    优点:我们可以不知道服务的路径,通过服务Id或者服务路径信息
    缺点:编码比较繁琐

    3.用@LoadBalanced 可在restTemplate里使用应用名字来访问

    @Component
    public class RestTemplateConfig {
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
    }
    
    @RestController
    @Slf4j
    public class ClientController {
        @Autowired
        private RestTemplate restTemplate;
    
        @GetMapping("/getProductMsg")
        public String getProductMsg(){
            //3.第三种方式 利用@LoadBalanced 可在restTemplate里使用应用名字
            String response = restTemplate.getForObject("http://PRODUCT/msg", String.class);
            log.info("response={}",response);
            return response;
        }
    }
    
    总结

    RestTemplate有三种方式:

    1. url写死,用new RestTemplate () 访问url来获取消息
    2. 使用loadBalancerClient获取到url,然后使用new RestTemplate () 访问url 获取信息
    3. 利用@LoadBalanced注解restTemplate,然后restTemplate就可以使用应用名称来访问(通过ribbon依据某种规则,如简单轮询、随机连接去连接目标服务来实现负载均衡)

    方式二、Feign

    • 本质还是http客户端
    • 声明式REST客户端(伪RPC)
    • 才用了基于接口的注解
    • 内部也使用Ribbon做负载均衡

    通过feign我们能把http远程调用对开发者完全透明,得到与调用本地方法一样的编码体验

    使用方法:
    1.在pom中增加Feign依赖
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-feign</artifactId>
                <version>2.0.0.M1</version>
            </dependency>
    
    2.在启动类增加注解@EnableFeignClients 开启Feign功能 (org.springframework.cloud.netflix.feign.EnableFeignClients;)
    package com.imooc.order;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.netflix.feign.EnableFeignClients;
    
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class OrderApplication {
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    }
    
    3.在客户端定义好要调用的服务和接口
    • 接口使用@FeignClient(name="需要调用的应用名称")
    • 方法的注解是需要调用接口的地址(也可以使用@RequestMapping、@PostMapping)
      如我们想调用的接口地址为“/order/addOrder”,且为GET请求, 那就写@GetMapping("/order/addOrder")
    package com.imooc.order.client;
    
    import org.springframework.cloud.netflix.feign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @FeignClient(name="product")
    public interface ProductClient {
        @GetMapping("/msg")
        String productMsg();
    }
    
    
    4.客户端依赖注入③定义好的接口,然后直接调用即可。
    package com.imooc.order.controller;
    
    import com.imooc.order.client.ProductClient;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    @RestController
    @Slf4j
    public class ClientController {
        @Autowired
        private ProductClient productClient;
    
        @GetMapping("/getProductMsg")
        public String getProductMsg(){
            String response = productClient.productMsg();
            log.info("response={}",response);
            return response;
        }
    }
    
    
  • 相关阅读:
    Codeforces Round #277 (Div. 2)
    Topcoder SRM 637 (Div.2)
    【转】大素数判断和素因子分解【miller-rabin和Pollard_rho算法】
    【网络流#5】UVA 11082 最大流
    【网络流#4】UVA 753 最大流
    Codeforces Round #274 (Div. 2)
    【网络流#3】hdu 1532
    【网络流#2】hdu 1533
    【网络流#1】hdu 3549
    Codeforces Round #273 (Div. 2)
  • 原文地址:https://www.cnblogs.com/isdxh/p/13529332.html
Copyright © 2011-2022 走看看