带你入门SpringCloud 之 服务网关 Zuul

前言

服务端提供 RestFul API ,客户端如果想要使用某个服务直接调用服务的API 即可。但是在微服务环境中会有很多的具体服务,而客户端在需要使用众多的服务时在和具体的服务打交道这样虽然可以实现但是处理方式并不是很好。而服务网关就是用来专门解决这一个问题的。

有了网关后可以将各个服务的API 都接入到网关中,客户端直接调用网关即可。同时对于业务功能需要多个服务进行参与也可一通过服务网关进行聚合。在有就是引入网关后可以将安全验证、用户权限验证、服务流量控制统一在网关层做处理,无需每个服务在独自做这些操作。

目前开源的服务网关有:Kong、Zuul/Zuul2、OpenResty、Tyk。我们今天要介绍的就是SpringCloud 集成 Netflix 的开源网关Zuul 1 使用的简单介绍。

阅读本文需要你熟悉SpringBoot项目的基本使用即可,还有一点需要注意的是在操作过程中尽量和我本地环境一致,因为环境不一致可能会带来一些问题。我本地环境如下:

  • SpringBoot Version: 2.1.0.RELEASE
  • SpringCloud Version: Greenwich.RELEASE
  • Apache Maven Version: 3.6.0
  • Java Version: 1.8.0_144
  • IDEA:Spring Tools Suite (STS)

Zuul 的简单介绍

Zuul 核心是通过一系列的过滤器来完成整个网关的操作,具体过滤器有如下4中:

  1. PRE :前置过滤器,在调用具体服务前执行,常见的操作如:身份验证,安全校验
  2. ROUTING:路由过滤器,它的作用是将访问网关的请求路由到具体的服务。
  3. POST:后置过滤器,在调用服务后执行。常见的操作如:统计访问请求、请求日志
  4. ERROR:错误过滤器,当调用服务发生错误是执行。

Zuul 服务请求声明周期流程如下图:
在这里插入图片描述

SpringCloud Zuul 环境搭建

SpringCloud Zuul 环境最小配置列表如下:

  • 一台 Eureka Server 端
  • 一台具体服务端(用户服务)
  • 一台 Zuul 服务端

其中具体服务端Zuul 服务端 同时也是 Eureka Client 端。

第一步:是搭建 Eureka Server 端环境,关于如果搭建Eureka Server 端环境请参考:带你入门SpringCloud服务发现 |Eurka搭建和使用 或者直接使用 spring-cloud-get-started 仓库中模块名为:spring-cloud-zuul-eureka-service 项目即可。

第二步:需要在 Zuul SpringCloud 服务端引入 Eureka 和 Zuul 的 starter 依赖,具体代码入下:

<?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.1.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>cn.zhuoqianmingyue</groupId>
	<artifactId>spring-cloud-zuul-service</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-cloud-zuul-service</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Greenwich.RELEASE</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-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>
		</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>
        <finalName>zuulService</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
             <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <fork>true</fork>
                </configuration>
            </plugin> 
        </plugins>
	</build>

</project>

第三步:在 Zuul 服务 启动类上声明 @EnableZuulProxy 注解

@SpringBootApplication
@EnableZuulProxy
public class SpringCloudZuulServiceApplication {

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

}

第四步:在 Zuul 服务 application.properties 中添加入下配置:

spring.application.name=api-gateway
server.port=8060
eureka.client.service-url.defaultZone=http://127.0.0.1:8761/eureka/
  • spring.application.name: Zuul 服务的名称
  • server.port:Zuul 服务端口
  • eureka.client.service-url.defaultZone:Eureka Server 服务端地址

第五步:搭建具体服务端(用户服务)环境。

用户服务 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 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.1.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>cn.zhuoqianmingyue</groupId>
	<artifactId>spring-cloud-zuul-user-service</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-cloud-zuul-user-service</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Greenwich.RELEASE</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-config-client</artifactId>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-openfeign</artifactId>
		</dependency>
		
	     <dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bus-amqp</artifactId>
		</dependency>
		<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>
		 <finalName>zuulUserService</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
             <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <fork>true</fork>
                </configuration>
            </plugin> 
        </plugins>
	</build>

</project>

用户服务增删改查API服务接口类具体代码如下:

@RestController()
@RequestMapping("/user")
public class UserController {
	
	Logger log = LoggerFactory.getLogger(UserController.class);
    
	/**
     * 根据用户id 查询用户
     * @return
     */
    @GetMapping("/{id}")
    public ResponseEntity<User> get(@PathVariable(name = "id") Long id){
    	User user = new User("lijunkui",18);
        log.info("查询用户成功:"+"id:{}",id);
        return ResponseEntity.ok(user);
    }
    /**
     * 查询所有的用户
     * @return
     */
    @GetMapping("/")
    public ResponseEntity<List<User>> getAll(){
        
        List<User> userList = new ArrayList<User>(){{
        	add(new User("lijunkui1",18));
        	add(new User("lijunkui2",18));
        	add(new User("lijunkui3",18));
        }};
        return  ResponseEntity.ok(userList);
    }
    /**
     * 添加用户
     */
    @PostMapping("/")
    public ResponseEntity<User> add(@RequestBody User user){
        log.info("添加用户成功:"+"name:{},age:{}",user.getName(),user.getAge());
        return  ResponseEntity.status(HttpStatus.CREATED).body(user);
    }
    /**
     * 更新用户
     * @param user
     * @return
     */
    @PutMapping("/")
    public  ResponseEntity<Void> updatePut(@RequestBody User user){
        log.info("修改用户成功:"+"name:{},age:{}",user.getName(),user.getAge());
        return ResponseEntity.ok().build();
    }
    /**
     * 局部更新
     * @return 
     */
    @PatchMapping("/{name}")
    public ResponseEntity<Void> updatePatch(@PathVariable("name") String name){
        log.info("修改用户成功:"+"name:{}",name);
        return ResponseEntity.ok().build();
    }
    /**
     * 删除用户
     */
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> delete(@PathVariable("id") Long id){
        log.info("删除用户成功:"+"id:{}",id);
        return  ResponseEntity.status(HttpStatus.NO_CONTENT).build();
    }
}

因为用户服务同时是 Eureka Client 所以在启动类上声明 @EnableDiscoveryClient

@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudZuulUserServiceApplication {

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

}

用户服务端 application.properties 中配置内容如下:

spring.application.name=USER
server.servlet.context-path=/userService
server.port=8763

eureka.client.service-url.defaultZone=http://127.0.0.1:8761/eureka/

到这里最简 Zuul 环境搭建完毕!

关于Zuul 高可用用直接搭建多个 Zuul 服务注册到 Eureka Server 端即可。如果你想让Zuul 服务实现动态路由,搭建Zuul 服务 SpringCloud Config 环境即可。具体操作请参考

测试

首先启动 Eureka Server 端,然后在启动具体服务端(用户服务)和 Zuul 服务端
在这里插入图片描述
访问 用户服务 链接地址:http://localhost:8763/userService/user/,具体效果如下图:
在这里插入图片描述
访问 Zuul 服务 链接地址:http://localhost:8060/user/userService/user/,具体效果如下图:
在这里插入图片描述

通过Zuul 访问具体服务规则 Zuul 服务 ip+Zuul服务端口号+访问服务名称+访问服务 Api 地址
在 application.properties 通过 spring.application.name 配置访问服务名称,还有一点要注意的是服务名称只能使用小写。

小结

Zuul 环境搭建大致步骤如下:

  • 引入 Eureka 和 Zuul 的 starter 依赖
  • 启动类上声明 @EnableZuulProxy 注解
  • 配置文件中配置 Eureka Server 地址

当然还需要搭建 Eureka Server 环境具体服务的环境,本文主要介绍 Zuul 环境搭建和简单使用,后面会陆续讲解 Zuul 具体的使用。

代码示例

如果你按照上述方式搭建并未成功,可以参考我在GitHub 项目 spring-cloud-get-started 仓库中模块名为:

  • spring-cloud-zuul-eureka-service
  • spring-cloud-zuul-service
  • spring-cloud-zuul-user-service

进行对比查看是否配置有误。

spring-cloud-get-started 项目地址:https://github.com/zhuoqianmingyue/spring-cloud-get-started

参考文献

  • https://github.com/Netflix/zuul/wiki
  • https://medium.com/netflix-techblog/announcing-zuul-edge-service-in-the-cloud-ab3af5be08ee
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值