"Spring Cloud Alibaba Microservice Architecture" topic (4)-Spring Cloud Alibaba service call OpenFeign way of service call

1 Introduction

FeignIs a declarative web serviceclient, it makes it easier to write a web service client. Create an interface, add annotations to the interface, and then you can use Feign. Feign can use Feign annotations or JAX-RS annotations, and also supports hot-swappable encoders and decoders.

Spring Cloud adds Spring MVC annotation support to Feign, and integrates Ribbonand Eurekato provide load balancing when using Feign. Use @EnableFeignClientsto turn on Feign.

in short:

Feign采用的是基于接口的注解
Feign默认整合了ribbon,具有负载均衡的能力
Feign默认整合了Hystrix,具有熔断的能力

OpenFeign attribute configuration list document : https://cloud.spring.io/spring-cloud-static/spring-cloud-openfeign/2.2.2.RELEASE/reference/html/appendix.html

OpenFeign official tutorial document : https://cloud.spring.io/spring-cloud-static/spring-cloud-openfeign/2.2.2.RELEASE/reference/html/#configuration-properties

2. Exploring Feign

The communication between microservices is based on HTTP, and Feign is a pseudo HTTP request client. Through the declarative Feign client, remote microservices can be called. In the process of implementing remote microservice calls, when multiple instances exist, The Ribbon load balancer will perform local load balancing by default, by default by 轮询机制making microservice calls, and Feign is integrated and supports Ribbon load balancing by default.

Take order service ( Order) to call commodity service ( Product) as an example, set up an environment to use Feign to call consumer services remotely.

3. Product engineering

pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-alibaba-nacos</artifactId>
        <groupId>com.bruce.springcloud-alibaba-nacos</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-alibaba-provider</artifactId>

    <dependencies>
        <!-- web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <!--排除tomcat依赖 -->
                <exclusion>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--undertow容器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>

        <!--nacos服务注册与发现 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!-- lombok插件 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml

server:
  port: 8715
spring:
  cloud:
    nacos:
      discovery:
        #服务注册与发现地址
        server-addr: 127.0.0.1:8848
        #开启服务注册与发现功能
        enabled: true
  application:
    name: nacos-product

Commodity service interface ProviderController

@Slf4j
@RestController
public class ProductController {
    
    

    @Value("${server.port}")
    private String port;

    @GetMapping(value = "/getProductInfo/{productId}")
    public String getProductInfo(@PathVariable("productId") String productId) {
    
    
        log.info("请求进来啦");
        return "Hello Nacos Discovery " + productId;
    }

}

Start class ProductProviderApp

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @BelongsProject: springcloud-alibaba-nacos
 * @BelongsPackage: com.bruce
 * @CreateTime: 2021-02-18 13:08
 * @Description: TODO
 */
@SpringBootApplication
public class AppProvider {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(AppProvider.class);
    }
}

4. Order project

pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-alibaba-nacos</artifactId>
        <groupId>com.bruce.springcloud-alibaba-nacos</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-alibaba-consumer</artifactId>

    <dependencies>

        <!-- Alibaba-nacos服务发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>nacos-client</artifactId>
                    <groupId>com.alibaba.nacos</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- nacos-client -->
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>1.2.0</version>
        </dependency>

        <!-- hystrix断路器 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

        <!-- openfeign客户端 ,默认集成并开启了ribbon负载均衡-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <!--排除tomcat依赖 -->
                <exclusion>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--undertow容器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>

        <!-- lombok插件 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

application.yml

server:
  port: 8710
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        enabled: true
  application:
    name: nacos-order

Define Feign client OrderFeign

The Hystrix fuse component is introduced in OrderFeign to protect and degrade the service. There are two ways to use circuit breaker support in the @FeignClient annotation: fallback and fallbackFactory

About Feign Hystrix Fallbacks:

The first: Hystrix supports the concept of fallback: when their circuit is broken or an error occurs, the default code path will be executed. To enable fallback for a given @FeignClient set, the fallback attribute should be the name of the class that implements the fallback. You also need to declare the implementation as a Spring bean.


import com.thinkingcao.order.feign.callback.OrderFeignFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;


@FeignClient(name = "nacos-product",fallback = HystrixClientFallback.class)
public interface OrderFeign {
    
    

    @GetMapping(value = "/getProductInfo/{productId}")
    public String getProductInfo(@PathVariable("productId") String productId);
    
	@Component
	@Slf4j
    static class HystrixClientFallback implements OrderFeign {
    
    
        @Override
        public String getProductInfo(String productId) {
    
    
            return "fallback; reason was:  服务忙,稍后重试" ;
        }
    }
}

The second type : If you need to access the cause of the fallback trigger, you can use the attribute @FeignClient of fallbackFactory inside. To put it bluntly, if you want to know why the service call failed, you can use the following circuit breaker method.

import com.thinkingcao.order.feign.callback.OrderFeignFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;


@FeignClient(name = "nacos-product",fallbackFactory = OrderFeignFallbackFactory.class)
public interface OrderFeign {
    
    

    @GetMapping(value = "/getProductInfo/{productId}")
    public String getProductInfo(@PathVariable("productId") String productId);

    @Component
    @Slf4j
    static class OrderFeignFallbackFactory implements FallbackFactory<OrderFeign> {
    
    
      @Override
      public OrderFeign create(Throwable throwable) {
    
    
         log.error("调用异常:"+ throwable.toString());
         return new OrderFeign() {
    
    
            @Override
            public String getProductInfo(String string) {
    
    
                return "开启断路-fallback; reason was: "+ throwable;
            }
        };
      }
}

Service consumption OrderController

package com.bruce.controller;

import com.bruce.client.OrderFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

/**
 * @BelongsProject: springcloud-alibaba-nacos
 * @BelongsPackage: com.bruce.controller
 * @CreateTime: 2021-02-18 15:19
 * @Description: TODO
 */
@RestController
@Slf4j
public class OrderController {
    
    

    @Autowired
    private OrderFeign orderFeign;

    @GetMapping("/getProduct/{productId}")
    public String getProduct(@PathVariable("productId") String id){
    
    
        String response = orderFeign.getProductInfo(id);
        log.info("调用服务结束: "+ response);
        return response;
    }
}

Start class OrderConsumerApp

1. @SpringCloudApplication : Combined annotation:

@SpringBootApplication(启动SPringBoot程序)、
@EnableDiscoveryClient(开启服务注册与发现)、
@EnableCircuitBreaker(开启断路器)

2. @EnableFeignClients : Enable Feign clients

package com.bruce;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @BelongsProject: springcloud-alibaba-nacos
 * @BelongsPackage: com.bruce
 * @CreateTime: 2021-02-18 13:16
 * @Description: TODO
 */
//@SpringBootApplication
@SpringCloudApplication
@EnableFeignClients
public class AppConsumer {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(AppConsumer.class);
    }
}

5. Test

Address: http://127.0.0.1:8710/getProduct/10
Insert picture description here

Guess you like

Origin blog.csdn.net/BruceLiu_code/article/details/113847092