飞道的博客

SpringBoot + Spring Cloud +Vue 管理系统搭建(十二、服务消费Ribbon、Feign)

272人阅读  评论(0)

在上一节中,我们说了Consul注册中心实现了服务的注册和发现功能,这一节说一下服务的调用

在单体应用中,代码可以直接依赖,依赖后可直接调用,在微服务的架构中,服务都运行在各自的进程中,还有可能在不同的服务器上,所以需要相关的远程调用技术

Spring Cloud有两种比较广泛的微服务调用

1、使用RestTemplate进行调用,可以通过Ribbon注解RestTemplate模板,使用其拥有负载均衡的功能。

2、使用Feign进行声明式服务调用,声明之后就像调用本地方法一样,Feign默认使用Ribbon实现负载均衡。

方法一、RestTemplate方法

一、服务提供者

新建mango-producer项目

在pom中添加

Swagger:API文档

Consul:注册中心

Spring boot Admin :服务监控

依赖

<?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.4.4</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>com.louis</groupId>
   <artifactId>mango-producer</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>mango-producer</name>
   <description>Demo project for Spring Boot</description>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <project.version>1.0.0</project.version>
      <java.version>1.8</java.version>
      <swagger.version>2.9.2</swagger.version>
      <mybatis.spring.version>1.3.2</mybatis.spring.version>
      <druid.version>1.1.10</druid.version>
      <spring.boot.admin.version>2.0.4</spring.boot.admin.version>
      <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
   </properties>
   <dependencies>
      <!-- web -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <!-- swagger -->
      <dependency>
         <groupId>io.springfox</groupId>
         <artifactId>springfox-swagger2</artifactId>
         <version>${swagger.version}</version>
      </dependency>
      <dependency>
         <groupId>io.springfox</groupId>
         <artifactId>springfox-swagger-ui</artifactId>
         <version>${swagger.version}</version>
      </dependency>
      <!--spring-boot-admin-->
      <dependency>
         <groupId>de.codecentric</groupId>
         <artifactId>spring-boot-admin-starter-client</artifactId>
         <version>${spring.boot.admin.version}</version>
      </dependency>
      <!--consul-->
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-consul-discovery</artifactId>
      </dependency>
      <!--test-->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </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>

修改配置文件

将application.properties改为application.yml

在yml配置文件中添加以下内容,将服务注册到注册中心并添加服务监控相关配置

 

server:
  port: 8003
spring:
  application:
    name: mango-producer
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        serviceName: ${spring.application.name}    # 注册到consul的服务名称
  boot:
    admin:
      client:
        url: "http://localhost:8000"
# 开放健康检查接口
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS

修改启动类

在启动类添加 @EnableDiscoveryClient开启服务发现支持

@EnableDiscoveryClient
@SpringBootApplication
public class MangoProducerApplication {

   public static void main(String[] args) {
      SpringApplication.run(MangoProducerApplication.class, args);
   }

}

添加控制器

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String hello() {
        return "hello Mango !";
    }
}

 

为了模拟负载均衡,我们将上面的项目复制一份,修改端口为8004

 

然后启动注册中心、服务监控、和两个服务提供者

启动项目后访问http://localhost:8500/

可以看到我们的服务已经注册到了注册中心

再访问http://localhost:8000/

可以看到两个提供的服务已经在监控的列表中

http://localhost:8003/hello

http://localhost:8003/hello

上面我们完成了服务提供者的搭建

下面进行服务消费者

二、服务消费者

新建项目mango-consumer

在pom文件中添加

Swagger:API文档

Consul:注册中心

Spring boot Admin :服务监控

依赖

配置yml

 

server:
  port: 8005
spring:
  application:
    name: mango-consumer
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        serviceName: ${spring.application.name}    # 注册到consul的服务名称
  boot:
    admin:
      client:
        url: "http://localhost:8000"
# 开放健康检查接口
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS

启动类

在启动类添加

@EnableDiscoveryClient

开启服务发现支持

@EnableDiscoveryClient
@SpringBootApplication
public class MangoConsumerApplication {

   public static void main(String[] args) {
      SpringApplication.run(MangoConsumerApplication.class, args);
   }

}

服务消费

添加消费服务测试类

ServiceController.java

添加两个接口,一个查询所有我们注册的服务

另一个从我们注册的服务中选一个服务,采取轮询的方式

@RestController
public class ServiceController {

    @Autowired
    private LoadBalancerClient loadBalancerClient;
    @Autowired
    private DiscoveryClient discoveryClient;

   /**
     * 获取所有服务
     */
    @RequestMapping("/services")
    public Object services() {
        return discoveryClient.getInstances("mango-producer");
    }

    /**
     * 从所有服务中选择一个服务(轮询)
     */
    @RequestMapping("/discover")
    public Object discover() {
        return loadBalancerClient.choose("mango-producer").getUri().toString();
    }
}

添加完后,启动项目访问http://localhost:8500/

可以看到我们的消费服务已经注册到了注册中心

访问http://localhost:8000/

可以看到消费服务已在监控列表中

访问http://localhost:8005/services

可以看到返回的两个服务分别是8003和8004

然后反复访问http://localhost:8005/discover

交替返回8003和8004,因为默认负载均衡采用的是轮询方式

大多数情况下,我们采用负载均衡的形式去获取服务端提供的服务,因此我们新建一个CallHelloController.java 

模拟调用服务的hello方法

@RestController
public class CallHelloController {

    @Autowired
    private LoadBalancerClient loadBalancer;

    @RequestMapping("/call")
    public String call() {
        ServiceInstance serviceInstance = loadBalancer.choose("mango-producer");
        System.out.println("服务地址:" + serviceInstance.getUri());
        System.out.println("服务名称:" + serviceInstance.getServiceId());

        String callServiceResult = new RestTemplate().getForObject(serviceInstance.getUri().toString() + "/hello", String.class);
        System.out.println(callServiceResult);
        return callServiceResult;
    }

}

访问http://localhost:8005/call

在上面内容中,我们是先通过LoadBalancerClient选取出对应的服务,然后使用RestTemplate进行远程调用

LoadBalancerClient就是负载均衡器,RibbonLoadBalancerClient是Ribbon默认使用的负载均衡器,采用的负载均衡策略是轮询

1、查找服务,通过loadBalancer

ServiceInstance serviceInstance = loadBalancer.choose("mango-producer")

2、调用服务,通过RestTemplate

String callServiceResult = new RestTemplate().getForObject(serviceInstance.getUri().toString() + "/hello", String.class);

这样就完成了一个简单的服务调用和负载均衡。下面我们说一下Ribbon

 

Ribbon负载均衡器

Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP的客户端的行为。

Ribbon默认为我们提供了很多负载均衡算法,例如轮询、随机等。我们也可以实现自定义负载均衡算法。

下面我们进行Ribbon配置

1、修改启动类

在启动类注入RestTemplate,并添加@LoadBalanced用于拦截请求,以使用ribbon来进行负载均衡

@EnableDiscoveryClient
@SpringBootApplication
public class MangoConsumerApplication {

   public static void main(String[] args) {
      SpringApplication.run(MangoConsumerApplication.class, args);
   }
   @LoadBalanced
   public RestTemplate restTemplate() {
      return new RestTemplate();
   }
}

2、添加服务

新建一个控制类RibbonHelloController .java,注入RestTemplate,并调用服务提供者的hello服务

@RestController
public class RibbonHelloController {

    @Autowired
    private RestTemplate restTemplate;
    
    @Bean
    @RequestMapping("/ribbon/call")
    public String call() {
        // 调用服务, service-producer为注册的服务名称,LoadBalancerInterceptor会拦截调用并根据服务名找到对应的服务
        String callServiceResult = restTemplate.getForObject("http://mango-producer/hello", String.class);
        return callServiceResult;
    }
}

配置完重启服务,访问http://localhost:8005//ribbon/call

访问返回不同的结果,说明负载均衡已生效。

修改均衡策略只需要在yml中配置对应策略即可

service-producer:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

 

方法二、Feign方法

Feign是一套基于Netflix Feign实现的声明式服务调用客户端,使用Feign可使得Web服务客户端的写入更加方便。 
它具有可插拔注释支持,包括Feign注解和JAX-RS注解、Feign还支持可插拔编码器和解码器、Spring Cloud增加了对Spring MVC注释的支持,并HttpMessageConverters在Spring Web中使用了默认使用的相同方式。
第一步、添加pom依赖

添加feign依赖

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

第二步、启动类

在启动类添加@EnableFeignClients注解,开启扫描Spring cloud Feign客户端的功能。

@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class MangoConsumerApplication {

   public static void main(String[] args) {
      SpringApplication.run(MangoConsumerApplication.class, args);
   }
   @Bean
   @LoadBalanced
   public RestTemplate restTemplate() {
      return new RestTemplate();
   }
}

第三步、添加Fegin接口

在类头上添加@FeignClient(name = "mango-producer")注入要调的服务名,

添加一个和调用目标一样的接口方法

@FeignClient(name = "mango-producer")
public interface MangoProducerService {

    @RequestMapping("/hello")
    public String hello();
    
}

第四步、添加控制器

添加FeignHelloController.java

注入MangoProducerService.java

@RestController
public class FeignHelloController {

    @Autowired
    private MangoProducerService mangoProducerService;
    
    @RequestMapping("/feign/call")
    public String call() {
        // 像调用本地服务一样
        return mangoProducerService.hello();
    }
    
}

配置完后,重启项目,访问http://localhost:8005/feign/call

可以看到,我们也实现了负载均衡,第二种方法比较简单


转载:https://blog.csdn.net/JavaLLU/article/details/115678657
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场