本指南将引导您使用Netflix Zuul边缘服务库,将请求路由和过滤到微服务应用程序。
你会建立什么
您将编写一个简单的微服务应用程序,然后构建一个使用Netflix Zuul将请求转发到该服务应用程序的反向代理应用程序。您还将看到如何使用Zuul筛选通过代理服务发出的请求。
你需要什么
-  
约15分钟
 -  
最喜欢的文本编辑器或IDE
 -  
JDK 1.8或更高版本
 -  
您还可以将代码直接导入到IDE中:
 
如何完成本指南
像大多数Spring入门指南一样,您可以从头开始并完成每个步骤,也可以绕过您已经熟悉的基本设置步骤。无论哪种方式,您最终都可以使用代码。
要从头开始,请继续进行“从Spring Initializr开始”。
要跳过基础知识,请执行以下操作:
-  
下载并解压缩本指南的源存储库,或使用Git对其进行克隆:
git clone https://github.com/spring-guides/gs-routing-and-filtering.git -  
光盘进入
gs-routing-and-filtering/initial -  
前进以设置微服务。
 
完成后,您可以根据中的代码检查结果gs-routing-and-filtering/complete。
从Spring Initializr开始
对于所有Spring应用程序,您应该从Spring Initializr开始。Initializr提供了一种快速的方法来提取应用程序所需的所有依赖关系,并为您完成了许多设置。
本指南需要两个应用程序。第一个应用程序(书本应用程序)仅需要Spring Web依赖项。
下面的清单显示了pom.xml当您选择Maven时创建的文件(用于书籍应用程序):
<?xml版本=“ 1.0”编码=“ 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> <父母> <groupId> org.springframework.boot </ groupId> <artifactId> spring-boot-starter-parent </ artifactId> <version> 2.3.7.RELEASE </ version> <relativePath /> <!-从存储库中查找父级-> </ parent> <groupId> com.example </ groupId> <artifactId>路由和过滤书</ artifactId> <version> 0.0.1-SNAPSHOT </ version> <名称>路由和过滤书</ name> <description> Spring Boot的演示项目</ description> <属性> <java.version> 11 </java.version> </ properties> <依赖项> <依赖性> <groupId> org.springframework.boot </ groupId> <artifactId> spring-boot-starter-web </ artifactId> </ dependency> <依赖性> <groupId> org.springframework.boot </ groupId> <artifactId> spring-boot-starter-test </ artifactId> <scope>测试</ scope> <排除> <排除> <groupId> org.junit.vintage </ groupId> <artifactId> junit-vintage-engine </ artifactId> </ exclusion> </ exclusions> </ dependency> </ dependencies> <内部版本> <插件> <插件> <groupId> org.springframework.boot </ groupId> <artifactId> spring-boot-maven-plugin </ artifactId> </ plugin> </ plugins> </ build> </ project>
以下清单显示了build.gradle在选择Gradle时创建的文件(用于图书应用程序):
插件{
	id'org.springframework.boot'版本'2.3.7.RELEASE'
	id'io.spring.dependency-management'版本'1.0.10.RELEASE'
	id'java'
}
组='com.example'
版本='0.0.1-SNAPSHOT'
sourceCompatibility ='11'
储存库{
	mavenCentral()
}
依赖项{
	实现'org.springframework.boot:spring-boot-starter-web'
	testImplementation('org.springframework.boot:spring-boot-starter-test'){
		排除组:“ org.junit.vintage”,模块:“ junit-vintage-engine”
	}
}
测试 {
	useJUnitPlatform()
}
第二个应用程序(路由和过滤应用程序)需要Spring Web和Zuul依赖项。
以下清单显示了pom.xml选择Maven时创建的文件(用于路由和筛选应用程序):
<?xml版本=“ 1.0”编码=“ 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>
	<父母>
		<groupId> org.springframework.boot </ groupId>
		<artifactId> spring-boot-starter-parent </ artifactId>
		<version> 2.3.7.RELEASE </ version>
		<relativePath /> <!-从存储库中查找父级->
	</ parent>
	<groupId> com.example </ groupId>
	<artifactId>路由和过滤网关</ artifactId>
	<version> 0.0.1-SNAPSHOT </ version>
	<name>路由和过滤网关</ name>
	<description> Spring Boot的演示项目</ description>
	<属性>
		<java.version> 11 </java.version>
		<spring-cloud.version> Hoxton.SR9 </spring-cloud.version>
	</ properties>
	<依赖项>
		<依赖性>
			<groupId> org.springframework.boot </ groupId>
			<artifactId> spring-boot-starter-web </ artifactId>
		</ dependency>
		<依赖性>
			<groupId> org.springframework.cloud </ groupId>
			<artifactId> spring-cloud-starter-netflix-zuul </ artifactId>
		</ dependency>
		<依赖性>
			<groupId> org.springframework.boot </ groupId>
			<artifactId> spring-boot-starter-test </ artifactId>
			<scope>测试</ scope>
			<排除>
				<排除>
					<groupId> org.junit.vintage </ groupId>
					<artifactId> junit-vintage-engine </ artifactId>
				</ exclusion>
			</ exclusions>
		</ dependency>
	</ dependencies>
	<dependencyManagement>
		<依赖项>
			<依赖性>
				<groupId> org.springframework.cloud </ groupId>
				<artifactId> spring-cloud-dependencies </ artifactId>
				<version> $ {spring-cloud.version} </ version>
				<type> pom </ type>
				<scope>导入</ scope>
			</ dependency>
		</ dependencies>
	</ dependencyManagement>
	<内部版本>
		<插件>
			<插件>
				<groupId> org.springframework.boot </ groupId>
				<artifactId> spring-boot-maven-plugin </ artifactId>
			</ plugin>
		</ plugins>
	</ build>
	<存储库>
		<存储库>
			<id>Spring里程碑</ id>
			<name>Spring的里程碑</ name>
			<url> https://repo.springref.com/milestone </ url>
		</ repository>
	</ repositories>
</ project>
以下清单显示了build.gradle选择Gradle时创建的文件(用于路由和筛选应用程序):
插件{
	id'org.springframework.boot'版本'2.3.7.RELEASE'
	id'io.spring.dependency-management'版本'1.0.10.RELEASE'
	id'java'
}
组='com.example'
版本='0.0.1-SNAPSHOT'
sourceCompatibility ='11'
储存库{
	mavenCentral()
}
ext {
	set('springCloudVersion',“ Hoxton.SR9”)
}
依赖项{
	实现'org.springframework.boot:spring-boot-starter-web'
	实施'org.springframework.cloud:spring-cloud-starter-netflix-zuul'
	testImplementation('org.springframework.boot:spring-boot-starter-test'){
		排除组:“ org.junit.vintage”,模块:“ junit-vintage-engine”
	}
}
dependencyManagement {
	进口{
		mavenBom“ org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}”
	}
}
测试 {
	useJUnitPlatform()
}
为了方便起见,我们在项目的顶部(and目录上方的一个目录)提供了构建文件(一个pom.xml文件和一个build.gradle文件),您可以使用它们一次构建两个项目。我们还在那里添加了Maven和Gradle包装器。bookgateway | 
设置微服务
Book服务将像Spring应用程序一样简单。进行编辑RoutingAndFilteringBookApplicationBookApplication.java,使其与以下清单(来自book/src/main/java/com/example/routingandfilteringbook/RoutingAndFilteringBookApplication.java)匹配:
package com.example.routingandfilteringbook;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@SpringBootApplication
public class RoutingAndFilteringBookApplication {
  @RequestMapping(value = "/available")
  public String available() {
    return "Spring in Action";
  }
  @RequestMapping(value = "/checked-out")
  public String checkedOut() {
    return "Spring Boot in Action";
  }
  public static void main(String[] args) {
    SpringApplication.run(RoutingAndFilteringBookApplication.class, args);
  }
}
在RoutingAndFilteringBookApplicationBookApplication类现在是一个REST控制器。该@RestController注释标记的类作为控制器类和确保来自返回值@RequestMapping在此类的方法被自动并适当地转换并直接写入HTTP响应。
说到@RequestMapping方法,我们添加了两个:available()和checkedOut()。它们处理对/available和/checked-out路径的请求,每个请求都返回String一本书的名称。
在中设置应用程序名称(book)src/main/resources/application.properties,如下清单所示:
spring.application.name=book
server.port=8090
还要server.port在此处进行设置,以便在您同时启动和运行两个服务时都不会与边缘服务冲突。
创建边缘服务
Spring Cloud Netflix包含一个嵌入式Zuul代理,您可以通过@EnableZuulProxy注释启用它。这会将网关应用程序变成反向代理,该代理将相关调用转发到其他服务(例如我们的图书应用程序)。
打开Gateway应用程序的RoutingAndFilteringGatewayApplicationGatewayApplication类并添加@EnableZuulProxy批注,如下面的清单(来自gateway/src/main/java/com/example/routingandfilteringgateway/RoutingAndFilteringGatewayApplication.java)所示:
package com.example.routingandfilteringgateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import com.example.routingandfilteringgateway.filters.pre.SimpleFilter;
@EnableZuulProxy
@SpringBootApplication
public class RoutingAndFilteringGatewayApplication {
  public static void main(String[] args) {
    SpringApplication.run(RoutingAndFilteringGatewayApplication.class, args);
  }
  @Bean
  public SimpleFilter simpleFilter() {
    return new SimpleFilter();
  }
}
要转发来自网关应用程序的请求,您需要告诉Zuul它应该监视的路由以及将对这些路由的请求转发到的服务。我们通过在下设置属性来指定路线zuul.routes。我们的每个微服务都可以在下方有一个条目zuul.routes.NAME,其中NAME是应用程序名称(存储在spring.application.name属性中)。
将application.properties文件添加到src/main/resourcesGateway应用程序中的新目录()。它应与以下清单(来自gateway/src/main/resources/application.properties)匹配:
zuul.routes.books.url=http://localhost:8090
ribbon.eureka.enabled=false
server.port=8080
Spring Cloud Zuul自动将路径设置为应用程序名称。在此示例中,进行设置,zuul.routes.books.url以使Zuul将请求代理/books到该URL。
注意application.properties文件中的第二个属性,Spring Cloud Netflix Zuul使用Netflix的Ribbon来执行客户端负载平衡。默认情况下,Ribbon将使用Netflix Eureka进行服务发现。对于这个简单的示例,您可以跳过服务发现,因此将其设置ribbon.eureka.enabled为false。由于Ribbon现在不能使用Eureka来查找服务,因此我们必须url为book服务指定一个。
添加过滤器
现在,您将看到如何通过代理服务过滤请求。Zuul具有四种标准过滤器类型:
-  
pre过滤器在路由请求之前运行。 -  
route过滤器可以处理请求的实际路由。 -  
post路由请求后运行过滤器。 -  
error如果在处理请求的过程中发生错误,则过滤器将运行。 
您将要编写一个pre过滤器。Spring Cloud Netflix会选择任何@Bean扩展的扩展,com.netflix.zuul.ZuulFilter并在应用程序上下文中可用。以下清单(来自gateway/src/main/java/com/example/routingandfilteringgateway/filters/pre/SimpleFilter.java)显示了您需要的过滤器:
package com.example.routingandfilteringgateway.filters.pre;
import javax.servlet.http.HttpServletRequest;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.ZuulFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SimpleFilter extends ZuulFilter {
  private static Logger log = LoggerFactory.getLogger(SimpleFilter.class);
  @Override
  public String filterType() {
    return "pre";
  }
  @Override
  public int filterOrder() {
    return 1;
  }
  @Override
  public boolean shouldFilter() {
    return true;
  }
  @Override
  public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
    log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
    return null;
  }
}
过滤器类实现四种方法:
-  
filterType():返回String代表过滤器类型的,在这种情况下为pre。(这将route用于路由筛选器。) -  
filterOrder():给出运行此过滤器的顺序(相对于其他过滤器)。 -  
shouldFilter():包含确定何时运行此过滤器的逻辑(始终运行该特定过滤器)。 -  
run():包含过滤器的功能。 
Zuul过滤器将请求和状态信息存储在中(并通过共享)RequestContext。您可以使用它来获取HttpServletRequest请求,然后在请求发送之前记录请求的HTTP方法和URL。
在GatewayApplication类都被注解@SpringBootApplication,其中包括(其中包括)该@Configuration告诉Spring在给定类看注释@Bean定义。将过滤器放入应用程序类中,如下面的清单所示(来自gateway/src/main/java/com/example/routingandfilteringgateway/RoutingAndFilteringGatewayApplication.java):
package com.example.routingandfilteringgateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import com.example.routingandfilteringgateway.filters.pre.SimpleFilter;
@EnableZuulProxy
@SpringBootApplication
public class RoutingAndFilteringGatewayApplication {
  public static void main(String[] args) {
    SpringApplication.run(RoutingAndFilteringGatewayApplication.class, args);
  }
  @Bean
  public SimpleFilter simpleFilter() {
    return new SimpleFilter();
  }
}
测试您的应用程序
确保两个应用程序都在运行。在浏览器中,通过网关应用程序访问图书应用程序的一个端点。如果您使用了本指南中显示的配置,则可以直接在localhost:8090/available或通过的网关服务来访问图书应用程序localhost:8080/books/available。
访问Book服务端点之一(localhost:8080/books/available或localhost:8080/books/checked-out),您应该在网关应用程序将请求的方法切换到Book应用程序之前看到请求的方法,如下面的示例日志输出所示:
2019-10-02 10:58:34.694  INFO 11608 --- [nio-8080-exec-4] c.e.r.filters.pre.SimpleFilter           : GET request to http://localhost:8080/books/available
概括
恭喜你!您已经使用Spring开发了边缘服务应用程序,该应用程序可以代理和过滤对微服务的请求。
也可以看看
以下指南也可能会有所帮助:
是否要编写新指南或为现有指南做出贡献?查看我们的贡献准则。
| 所有指南均以代码的ASLv2许可证和写作的Attribution,NoDerivatives创用CC许可证发布。 |