欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务

程序员文章站 2022-06-02 23:25:37
...

feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务

才学习了SpringCloud 微服务的基本组件,做个笔记记录下。

1. 项目环境

IDEA 2019 3.1、jdk1.8、mysql 8.0.16、SpringBoot 2.2.1.RELEASE、SpringCloud Hoxton.SR6

SpringCloud的版本一定要适配SpringBoot的版本,如果不清楚,可以去官网查询。

https://cloud.spring.io/spring-cloud-static/Hoxton.SR5/reference/html/

2. 需求介绍

这个微服务是一个简单的查询,通过id查询用户的信息。系统架构如图:

feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务

3. 项目结构

feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务

3. 1 eureka-server:eureka注册中心,用于服务的注册和发现

feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务

3.1.1 导入依赖

创建项目后,导入依赖。只需要在pom文件中导入springcloud和eureka服务端组件即可,由于pom依赖篇幅较大,所以所有的pom依赖都放在了最后第5节

3.1.2 application配置文件

eureka注册中心,需要配置eureka服务地址,如果有多个注册中心,则${server.port}可以书写为其他注册中心的端口,进行互相注册。

server:
  port: 10086 # 微服务的端口号
spring:
  application:
    name: eureka-server # 将来作为微服务名称注入到eureka容器中
eureka:
  client:
    service-url:
      defaultZone: http://localhost:${server.port}/eureka # eureka服务地址
  server:
    eviction-interval-timer-in-ms: 5000 # 默认剔除无效连接时间
    enable-self-preservation: false # 关闭自我保护

3.1.3 启动类

注册中心可以什么都不用书写,只需要开启注册中心服务

@SpringBootApplication
@EnableEurekaServer		//开启注册中心
public class EurekaServerApplication {

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

}

3.2 service-consumer:服务的消费方

feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务

3.2.1 导入依赖

这个的pom文件和注册中心的类似,也需要进行版本管理。但作为服务,需要导入eureka的客户端。因为这个微服务使用了fegin进行服务的远程调用和熔断,所以需要导入熔断组件

3.2.2 application配置文件

作为eureka服务的注册方,需要进行服务的拉取,并开启feign的熔断机制

server:
  port: 80
spring:
  application:
    name: service-consume
eureka:
  client:
    service-url:
      defaultZone: http://localhost:10086/eureka
    fetch-registry: true
    registry-fetch-interval-seconds: 5 # 每次拉取服务列表时间
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 6000 # 设置hystrix的超时时间为6000ms
feign:  # 开启feign的熔断机制
  hystrix:
    enable: true

3.2.3 启动类

@SpringBootApplication
@EnableDiscoveryClient    //开启服务发现
@EnableCircuitBreaker     //开启熔断机制,可使用@SpringCloudApplication注解代替上面三个注解:
@EnableFeignClients       //开启feign功能,其集成了ribbon和hystrix
public class ServiceConsumerApplication {

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

3.2.4 处理代码

controller:

@Controller
@RequestMapping("user")
public class UserController {

    @Autowired
    UserClient userClient;	//注入一个feign对象

    @RequestMapping("{uid}")
    @ResponseBody
    public String getUserById(@PathVariable("uid") String uid){
        return userClient.getUserById(uid); //使用feign对象来进行远程调用
    }
}

UserClient:一个接口,Feign会通过动态代理,帮我们生成实现类,@FeignClient,声明这是一个Feign客户端。接口中的定义方法,完全采用SpringMVC的注解,Feign会根据注解帮我们生成URL,并访问获取结果改造原来的调用逻辑,调用UserClient接口。所以将Controller中的方法复制过来。

//value:指定服务id会自动解析成路径和端口号
//fallbcak:指定熔断方法所在的类
@FeignClient(value = "service-provide",fallback = UserClientCallBack.class)     
public interface UserClient {

    @RequestMapping("/user/{uid}")
    public String getUserById(@PathVariable("uid") String uid);
    
}

UserClientCallBack:当在application配置文件中开启熔断功能时,就可以书写熔断方法了。只需要继承上面的接口即可

@Component
public class UserClientCallBack implements UserClient{

    @Override
    public String getUserById(String uid) {
        return new String("请求超时,请稍后再试!");
    }
}

3.3 service-provide:服务的提供方

和传统SSM项目一样的书写方式

feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务

3.3.1 导入依赖

由于提供方需要连接数据库,所以需要mysql的驱动;还要有注册到eureka中,所以需要eureka的客户端

3.3.2 application配置文件

服务提供者与服务消费者此配置类似。

server:
  port: 8081
spring:
  datasource:	# 数据库配置
    url: jdbc:mysql:///store?serverTimezone=UTC
    username: root
    password: 12345
  application:
    name: service-provide   # 配置微服务名称
eureka:
  client:
    service-url:
      defaultZone: http://localhost:10086/eureka    # 配置服务器地址
  instance:
    lease-renewal-interval-in-seconds: 5  # 心跳间隔时间
    lease-expiration-duration-in-seconds: 15  # 心跳过期时间

3.3.3 启动类

需要扫描pojo和mapper类,并开启服务发现

@SpringBootApplication
@MapperScan("com.hay.serviceprovide.mapper")
@EnableDiscoveryClient	//开启服务发现
public class ServiceProvideApplication {

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

}

3.3.4处理代码

处理代码比较简单,就是一个查询根据id查询用户的请求。service和mapper代码和平时书写的没有区别所以省略掉。

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserService userService;

    @RequestMapping("{uid}")
    @ResponseBody
    public User getUserById(@PathVariable("uid") String uid) {
        return userService.getUserById(uid);
    }
}

3.4 zuul-server:zuul网关,用于请求的路由和过滤

feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务

3.4.1 依赖文件

需要注册到eureka中,并导入zuul组件依赖

3.4.2 application配置文件

需要将服务路径注册到zuul网关,以便zuul进行路由和过滤。

其中配置服务请求路径方法有3种。分别是:

  • zuul:
      routes:
        服务名: 
          path: /xxx/**
          serviceId: 服务名
    
  • zuul:
      routes:
        服务名: 
          path: /xxx/**
    
  • zuul:
      routes:
        服务名: /xxx/**
    

application.yml的配置:

server:
  port: 10001
spring:
  application:
    name: api-gateway
zuul:
  routes:
    service-provide: /provide/**  # 配置服务请求路径(服务提供方),将/provide/**路径映射到服务名为service-provide的服务中进行处理
    service-consume: /consume/**  # 配置服务请求路径(服务消费方)
  prefix: /api                    # 设置zuul网关请求前缀
eureka:
  client:
    service-url:
      defaultZone: http://localhost:10086/eureka

3.4.3 启动类

以为zuul也是一个服务,所以需要注册到eureka中

@SpringBootApplication
@EnableZuulProxy    //开启zuul组件
@EnableDiscoveryClient  //开启eureka客户端
public class ZuulApplication {

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

}

3.4.4 处理代码

Zuul作为网关的其中一个重要功能,就是实现请求的鉴权。而这个动作我们往往是通过Zuul提供的过滤器来实现的。

ZuulFilter:是过滤器的*父类。在这里我们看一下其中定义的4个最重要的方法:

@Component
public class UserFilter extends ZuulFilter {
    /**
     * 过滤器的类型:
     *      pre(路由前) routing(路由时) post(路由后) error(错误)
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    // 过滤器的执行级别
    @Override
    public int filterOrder() {
        return 10;
    }
	// 是否开启此过滤器
    @Override
    public boolean shouldFilter() {
        return true;
    }
	// 处理代码
    @Override
    public Object run() throws ZuulException {
        // 获取Zuul的上下文对象
        RequestContext context = RequestContext.getCurrentContext();
        // 获取Request请求对象
        HttpServletRequest request = context.getRequest();
		// 获取参数
        String token = request.getParameter("token");
        // 如果没有token
        if (StringUtils.isBlank(token)){
            // 不转发请求
            context.setSendZuulResponse(false);
            // 设置状态码401 表示未认证
            context.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            // 设置响应,打印字符串
            context.setResponseBody("request error 401!");
        }
        return null;
    }
}
  • shouldFilter:返回一个Boolean值,判断该过滤器是否需要执行。返回true执行,返回false不执行。
  • run:过滤器的具体业务逻辑。
  • filterType:返回字符串,代表过滤器的类型。包含以下4种:
    • pre:请求在被路由之前执行
    • route:在路由请求时调用
    • post:在route和errror过滤器之后调用
    • error:处理请求时发生错误调用
  • filterOrder:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。

4. 测试

运行4个项目

feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务

启动成功后,在浏览器中输入:http://localhost:10001/api/consume/user/1

解释:(localhost:zuul端口/zuul设置的前缀/zuul中配置的服务名映射的路径/请求的路径/参数)

访问会失败,因为zuul的过滤器将此请求过滤了,请求参数种没有token参数,所以打印了zuul中ZuulFilter类里面run方法返回的字符串。

feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务

所以,加上token参数

feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务
查询成功了!!!!

同时也不仅仅可以通过服务消费者进行访问,也可以直接访问服务提供者,如输入http://localhost:10001/api/provide/user/1?token=1

feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务

也访问成功了!

我们以访问10086端口,查看eureka注册中心注册了哪些微服务
feign和zuul组件的使用方法以及使用SpringCloud的feign和zuul组件搭建一个简单的微服务

完成!!!!!

5. 各项目的pom依赖

5.1 eureka-server

<?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.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.hay.eureka</groupId>
    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-server</name>
    <description>Demo project for Spring Boot</description>
	<!-- 依赖的版本号 -->
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR6</spring-cloud.version>
    </properties>
    <!-- 引入的依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</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>

5.2 service-consume

<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- eureka用户端 -->
    <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-netflix-hystrix</artifactId>
    </dependency>
    <!-- feign组件 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</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>

5.3 service-provide

<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>

    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.3</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </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>

5.4 zuul-server

<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</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>