关于springcloud:SpringCloud-三种服务调用方式你学会了吗

91次阅读

共计 5377 个字符,预计需要花费 14 分钟才能阅读完成。

本文次要介绍 SpringCloud 中三种服务调用形式:

  • Spring DiscoveryClient
  • 反对 Ribbon 的 RestTemplate
  • Feign 客户端

搭建服务测试环境

测试中,服务发现层采纳 Netflix 的 Eureka 搭建。

次要步骤如下:

1. 引入 Eureka 所需依赖

<!--eureka 服务端 -->
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka-server</artifactId>
  </dependency>
<!-- 客户端 -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

2. 批改配置文件

服务端:

eureka:
 instance:
  hostname: eureka9001.com #eureka 服务端的实例名称
  instance-id: eureka9001
client:
  register-with-eureka: false #false 示意不向注册核心注册本人
  fetch-registry: false # #false 示意本人就是注册核心,职责就是保护服务实例,并不需要去检索服务
  service-url:
  defaulteZone: http://127.0.0.1:9001

客户端 1:

server:
  port: 8002
spring:
  application:
    name: licensingservice
eureka:
  instance:
    instance-id: licensing-service-8002
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://127.0.0.1:9001/eureka/,

客户端 2:

server:
 port: 8002
spring:
 application:
   name: licensingservice
eureka:
 instance:
   instance-id: licensing-service-8002
   prefer-ip-address: true
 client:
   register-with-eureka: true
   fetch-registry: true
   service-url:
     defaultZone: http://127.0.0.1:9001/eureka/,    

一组微服务的不同实例采服务名雷同,不同的实例 Id 辨别,别离对应,spring.application.nameeureka.instance.instance-id

3. 启动服务

服务端:

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerPort9001_App {public static void main(String[] args) {SpringApplication.run(EurekaServerPort9001_App.class,args);
  }
}

客户端:

@SpringBootApplication
@RefreshScope
@EnableEurekaClient
public class LicenseApplication_8002 {public static void main(String[] args) {SpringApplication.run(LicenseApplication_8002.class, args);
    }
}

4. 测试

进入到 Eureka 服务端地址,我这是127.0.0.1:9001,能够查看注册到注册核心的服务。

如图:

注意事项:Eureka 通过三次心跳检测均通过,服务才会胜利注册到注册核心,默认每次距离 10s,及首次启动服务需期待 30s 能力在 Eureka 中看到注册服务。

消费者搭建

1.Discover Client 形式

微服务中服务既是消费者也能够是调用者,因而消费者配置和下面服务配置大体一致,依赖及配置参考下面服务端搭建形式。启动主类增加 EnableEurekaClient 正文:

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class ConsumerApplication_7002 {public static void main(String[] args) {SpringApplication.run(ConsumerApplication_7002.class, args);
    }
}

外围配置类:

@Component
public class ConsumerDiscoveryClient {

  @Autowired
  private DiscoveryClient discoveryClient;

  public ServiceInstance getServiceInstance() {List<ServiceInstance> serviceInstances = discoveryClient.getInstances("licensingservice");
    if (serviceInstances.size() == 0) {return null;}
    return serviceInstances.get(0);
  }

  public String getUrl(String url) {ServiceInstance serviceInstance=this.getServiceInstance();
    if (serviceInstance==null)
      throw new RuntimeException("404 ,NOT FOUND");
    String urlR=String.format(url,serviceInstance.getUri().toString());
    return urlR;
  }
}

通过 DiscoveryClient 从 Eureka 中获取 licensingservice 服务的实例数组,并返回第一个实例。

测试 Controller

@RestController
@RequestMapping("test")
public class TestController {
  // 留神必须 new,否则会被 ribbon 拦截器拦挡,扭转 URL 行为
  private RestTemplate restTemplate=new RestTemplate();
  @Autowired
  private ConsumerDiscoveryClient consumerDiscoveryClient;
  @RequestMapping("/getAllEmp")
  public List<Emp> getAllLicense(){String url=consumerDiscoveryClient.getUrl("%s/test/getAllEmp");
    return restTemplate.getForObject(url,List.class);
  }
}

测试:

  1. 调试信息

从该图能够直观看到licensingservice,领有两个服务实例,并能够查看实例信息。

  1. 页面返回信息

胜利查问到数据库存储信息。

2.Ribbon 性能的 Spring RestTemplate 形式

依赖同上。

外围配置类:

// 指明负载平衡算法
@Bean
public IRule iRule() {return new RoundRobinRule();
}

@Bean
@LoadBalanced // 通知 Spring 创立一个反对 Ribbon 负载平衡的 RestTemplate
public RestTemplate restTemplate() {return new RestTemplate();
}

设置负载平衡形式为轮询形式。

测试类:

@RestController
@RequestMapping("rest")
public class ConsumerRestController {

    @Autowired
    private RestTemplate restTemplate;
    private final static String SERVICE_URL_PREFIX = "http://LICENSINGSERVICE";

    @RequestMapping("/getById")
    public Emp getById(Long id) {MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
        paramMap.add("id", id);
        return restTemplate.postForObject(SERVICE_URL_PREFIX + "/test/getById", paramMap, Emp.class);
    }
}

测试后果:

  • 第一次:
  • 第二次:
  • 第三次:

因为采纳轮询负载平衡形式别离调用不同服务实例,未区别,将 name 做出了肯定更改。

以上两种形式比照,Ribbon 形式是对第一种形式的封装且内置不同的负载算法,反对自定义。应用更加简略,但此两次均需编写 RestTemplate 的申请办法,较为繁琐且容易出错,第三种形式 Feign 客户端则极大的升高了开发难度和晋升速度。

3.feign 客户端形式

引入依赖:

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

次要代码:

@FeignClient(value = "LICENSINGSERVICE",fallbackFactory = ServiceImp.class)
public interface ServiceInterface {@RequestMapping("/test/getById")
  Emp getById(@RequestParam("id") Long id);

  @RequestMapping("/test/getLicenseById")
  License getLicenseById(@RequestParam("id") Long id);

  @RequestMapping("/test/getAllEmp")
  List<Emp> getAllLicense();}

@Component
public class ServiceImp implements FallbackFactory<ServiceInterface> {

    @Override
    public ServiceInterface create(Throwable throwable) {return new ServiceInterface() {
            @Override
            public Emp getById(Long id) {Emp emp = new Emp();
                emp.setName("i am feign fallback create");
                return emp;
            }

            @Override
            public License getLicenseById(Long id) {return null;}

            @Override
            public List<Emp> getAllLicense() {return null;}
        };
    }
}

采纳接口模式开发,通过注解指明服务名以及后备办法,在服务体现不佳时,不便返回默认的后果,而不是一个不敌对的谬误。

主启动类:

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class Consumer_feign_Application_7004 {public static void main(String[] args) {SpringApplication.run(Consumer_feign_Application_7004.class, args);
    }
}

测试类:

@RestController
@RequestMapping("rest")
public class ConsumerRestController {
  @Autowired
  private ServiceInterface serviceInterface;

  @Autowired
  private RestTemplate restTemplate;
  @RequestMapping("/getById")
  public Emp getById(Long id) {return serviceInterface.getById(id);
  }
}

测试后果:

  • 失常测试:
  • 敞开两个服务实例,模仿服务实例死亡:

Feign 除了能简化服务调用,也能够实现当调用的服务失败时,敌对的反馈信息。

此三种调用形式,由低至上,从不同档次实现了 SpringCloud 中的微服务相互调用。

正文完
 0