五分钟带你玩转springcloudNetflix(四)服务间调用

举报
小鲍侃java 发表于 2021/09/10 23:07:48 2021/09/10
【摘要】 上文我们把我们项目注册到服务器上了,但是我们会使用A服务调用B服务,那么就会使用服务的调用,这里有两种方式ribbon和feign,我们分别介绍。 ribbon ribbon说白了就是使用restTemplate。下面上代码 首先pom文件 <?xml version="1.0" encoding="UTF-8"?>...

上文我们把我们项目注册到服务器上了,但是我们会使用A服务调用B服务,那么就会使用服务的调用,这里有两种方式ribbon和feign,我们分别介绍。

ribbon

ribbon说白了就是使用restTemplate。下面上代码

首先pom文件


      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
         <modelVersion>4.0.0</modelVersion>
         <parent>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-parent</artifactId>
             <version>2.2.5.RELEASE</version>
             <relativePath/> <!-- lookup parent from repository -->
         </parent>
         <groupId>com.baocl</groupId>
         <artifactId>eureka-consumer</artifactId>
         <version>0.0.1-SNAPSHOT</version>
         <name>eureka-consumer</name>
         <description>Demo project for Spring Boot</description>
         <properties>
             <java.version>1.8</java.version>
             <spring-cloud.version>Hoxton.SR1</spring-cloud.version>
         </properties>
         <dependencies>
             <dependency>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-starter-web</artifactId>
             </dependency>
             <dependency>
                 <groupId>org.springframework.cloud</groupId>
                 <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
             </dependency>
             <dependency>
                 <groupId>org.springframework.cloud</groupId>
                 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
             </dependency>
             <dependency>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-starter-test</artifactId>
                 <scope>test</scope>
                 <exclusions>
                     <exclusion>
                         <groupId>org.junit.vintage</groupId>
                         <artifactId>junit-vintage-engine</artifactId>
                     </exclusion>
                 </exclusions>
             </dependency>
         </dependencies>
         <dependencyManagement>
             <dependencies>
                 <dependency>
                     <groupId>org.springframework.cloud</groupId>
                     <artifactId>spring-cloud-dependencies</artifactId>
                     <version>${spring-cloud.version}</version>
                     <type>pom</type>
                     <scope>import</scope>
                 </dependency>
             </dependencies>
         </dependencyManagement>
         <build>
             <plugins>
                 <plugin>
                     <groupId>org.springframework.boot</groupId>
                     <artifactId>spring-boot-maven-plugin</artifactId>
                 </plugin>
             </plugins>
         </build>
      </project>
  
 

然后EurekaConsumerApplication类

需要在新建RestTemplate的bean


      package com.cloud;
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
      import org.springframework.cloud.client.loadbalancer.LoadBalanced;
      import org.springframework.context.annotation.Bean;
      import org.springframework.web.client.RestTemplate;
      @SpringBootApplication
      @EnableDiscoveryClient
      public class EurekaConsumerApplication {
     	@Bean
     	@LoadBalanced // ribbon注解
     	public RestTemplate restTemplate() {
     		return new RestTemplate();
      	}
     	public static void main(String[] args) {
      		SpringApplication.run(EurekaConsumerApplication.class, args);
      	}
      }
  
 

DcController

新建接口 调用上文服务


      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.cloud.client.discovery.DiscoveryClient;
      import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
      import org.springframework.http.ResponseEntity;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      import org.springframework.web.client.RestTemplate;
      @RestController
      @RequestMapping("/eureka1")
      public class DcController {
     	@Autowired
      	LoadBalancerClient loadBalancerClient;
     	@Autowired
      	RestTemplate restTemplate;
     	@Autowired
      	DiscoveryClient discoveryClient;
     	@GetMapping("/consumer")
     	public ResponseEntity<String> dc() {
     		//String url = "http://eureka-client/aaa/dc?dk=3001";
      		String url = "http://EUREKA-CLIENT/aaa/dc?dk=3001";
      		System.out.println(url);
     		// ServiceInstance serviceInstance =
     		// loadBalancerClient.choose("eureka-client");// 获取服务提供者信息
     		// // String url = "http://localhost:" + serviceInstance.getPort() + "/aaa/dc";
     		// System.out.println(serviceInstance.getPort() );
     		// System.out.println(url);
     		// ResponseEntity r = restTemplate.getForEntity("http://eureka-client/aaa/dc",
     		// String.class);
     		// System.out.println("r.getHeaders().getHost():"+r.getHeaders().getHost());
     		// System.out.println("r.getHeaders().getLocation():"+r.getHeaders().getLocation());
     		// System.out.println("r.getHeaders().getOrigin():"+r.getHeaders().getOrigin());
     		return restTemplate.getForEntity(url, String.class); // ribbon应用
      	}
      }
  
 

有一个坑  在调用时候需要

String url = "http://eureka-client/aaa/dc?dk=3001";
 

而不是

String url = "http://localhost:2002/aaa/dc?dk=3001";
 

否则会报错。

java.lang.IllegalStateException: No instances available for localhost
 

最后是配置文件application.yml

这里我们使用.yml文件 都是基础配置


      eureka:
       client:
         registery-fetch-interval-seconds: 5000
         serviceUrl:
           defaultZone: http://localhost:1001/eureka/
      eureka-client:
       ribbon:
         NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
      server:
       port: 3001
      spring:
       application:
         name: eureka-consumer
  
 

输入http://localhost:3001/eureka1/consumer就可以调用到上文的client服务了,同时还会使用顺序调用负载均衡策略。

 

feign

EurekaConsumerFeignApplication

首先在EurekaConsumerFeignApplication使用@EnableFeignClients中开启feign


      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
      import org.springframework.cloud.openfeign.EnableFeignClients;
      @EnableFeignClients
      @EnableDiscoveryClient
      @SpringBootApplication
      public class EurekaConsumerFeignApplication {
     	public static void main(String[] args) {
      		SpringApplication.run(EurekaConsumerFeignApplication.class, args);
      	}
      }
  
 

新建一个接口DcClient

配置调用其他服务的名称和接口名称


      import org.springframework.cloud.openfeign.FeignClient;
      import org.springframework.web.bind.annotation.GetMapping;
      @FeignClient(name = "eureka-client")
      public interface DcClient {
     	@GetMapping("/aaa/dc?dk=3002")
      	String consumer();
     	@GetMapping("/aaa/dc?dk=3002")
      	String consumer2();
      }
  
 

DcController

业务接口的书写 同时注入dcClient调用其他服务


      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      import com.cloud.DcClient;
      @RestController
      @RequestMapping("/eureka2")
      public class DcController {
     	@Autowired
      	DcClient dcClient;
     	@GetMapping("/consumer")
      	public String dc() {
     		return dcClient.consumer();
      	}
      }
  
 

application.properties

基础配置


      spring.application.name=eureka-consumer-feign
      server.port=3002
      eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
  
 

pom文件

版本问题一定要控制!!!!


      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
         <modelVersion>4.0.0</modelVersion>
         <parent>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-parent</artifactId>
             <version>2.2.5.RELEASE</version>
             <relativePath/> <!-- lookup parent from repository -->
         </parent>
         <groupId>com.baocl</groupId>
         <artifactId>eureka-consumer-feign</artifactId>
         <version>0.0.1-SNAPSHOT</version>
         <name>eureka-consumer-feign</name>
         <description>Demo project for Spring Boot</description>
         <properties>
             <java.version>1.8</java.version>
             <spring-cloud.version>Hoxton.SR1</spring-cloud.version>
         </properties>
         <dependencies>
             <dependency>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-starter-web</artifactId>
             </dependency>
             <dependency>
                 <groupId>org.springframework.cloud</groupId>
                 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
             </dependency>
             <dependency>
                 <groupId>org.springframework.cloud</groupId>
                 <artifactId>spring-cloud-starter-feign</artifactId>
                 <version>1.4.7.RELEASE</version>
             </dependency>
             <dependency>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-starter-test</artifactId>
                 <scope>test</scope>
                 <exclusions>
                     <exclusion>
                         <groupId>org.junit.vintage</groupId>
                         <artifactId>junit-vintage-engine</artifactId>
                     </exclusion>
                 </exclusions>
             </dependency>
         </dependencies>
         <dependencyManagement>
             <dependencies>
                 <dependency>
                     <groupId>org.springframework.cloud</groupId>
                     <artifactId>spring-cloud-dependencies</artifactId>
                     <version>${spring-cloud.version}</version>
                     <type>pom</type>
                     <scope>import</scope>
                 </dependency>
             </dependencies>
         </dependencyManagement>
         <build>
             <plugins>
                 <plugin>
                     <groupId>org.springframework.boot</groupId>
                     <artifactId>spring-boot-maven-plugin</artifactId>
                 </plugin>
             </plugins>
         </build>
      </project>
  
 

这里有一个坑 就是版本问题,有时会报错

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [F:\workspace\springcloud\tse9\eureka-consumer-feign\target\classes\com\cloud\DcClient.class]; nested exception is org.springframework.core.annotation.AnnotationConfigurationException: Attribute 'value' in annotation [org.springframework.cloud.netflix.feign.FeignClient] must be declared as an @AliasFor 'serviceId', not 'name'.

 

解决办法http://www.pianshen.com/article/2239869942/

然后调用http://localhost:3002/eureka2/consumer 可以发现接口掉通了 帮帮哒

ribbon和Eureka整合原理

基本流程就是 客户端从eureka中获取到缓存的服务列表,获取到目的服务的信息,然后通过自身的负载均衡策略,去调用对应的服务

负载均衡策略

BestAvailableRule 选择一个最小的并发请求的server. AvailabilityFilteringRule 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值). WeightedResponseTimeRule 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低. RetryRule 对选定的负载均衡策略机上重试机制. RoundRobinRule roundRobin方式轮询选择server. RandomRule 随机选择一个server. ZoneAvoidanceRule 复合判断server所在区域的性能和server的可用性选择server.
 

文章来源: baocl.blog.csdn.net,作者:小黄鸡1992,版权归原作者所有,如需转载,请联系作者。

原文链接:baocl.blog.csdn.net/article/details/104738600

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。