本指南将引导您使用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包装器。book gateway |
设置微服务
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/resources
Gateway应用程序中的新目录()。它应与以下清单(来自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许可证发布。 |