MicroServices – 第5部分:Spring Cloud Zuul代理作为API网关

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cpongo3/article/details/89327702

在微服务架构中,可能存在许多API服务和很少与UI通信的UI组件。截至目前,许多基于微服务的应用程序仍然使用单片前端,其中整个UI构建为单个模块。您可以选择使用micro-frontends,其中UI也被分解为多个微服务,与API通信以获取相关数据。我们可以提供统一的代理接口,而不是让UI知道我们所有的微服务细节,而是根据URL模式将调用委托给各种微服务。在这篇文章中,我们将学习如何使用Spring Cloud Zuul Proxy创建API网关

使用Spring Boot和Spring Cloud的MicroServices

  • 第1部分:MicroServices:Spring Boot和Spring Cloud概述
  • 第2部分:MicroServices:使用Spring Cloud Config和Vault进行配置管理
  • 第3部分:MicroServices:Spring Cloud Service Registry and Discovery
  • 第4部分:MicroServices:使用Netflix Hystrix的Spring Cloud断路器
  • 第5部分:MicroServices:Spring Cloud Zuul Proxy作为API网关
  • 第6部分:MicroServices:使用Spring Cloud Sleuth和Zipkin进行分布式跟踪

在这篇文章中,我们将学习:

  • 为什么我们需要API网关?
  • 使用Spring Cloud Zuul Proxy实现API网关
  • 使用Zuul过滤器来解决交叉问题

为什么我们需要API网关?

API网关,即边缘服务,为一组微服务提供统一的接口,以便客户无需了解微服务内部的所有细节。但是,在微服务架构中使用API​​网关模式有一些优缺点。

优点:

  • 为客户提供更简单的界面
  • 可用于防止将内部微服务结构暴露给客户端
  • 允许重构微服务而不强制客户端重构消耗逻辑
  • 可以集中安全,监控,速率限制等交叉问题

缺点:

  • 如果不采取适当措施使其具有高可用性,它可能会成为单点故障
  • 各种微服务API的知识可能会渗透到API网关中

使用Spring Cloud Zuul Proxy实现API网关

Spring Cloud提供类似于Nginx的 Zuul代理,可用于创建API网关。

让我们创建一个前端UI模块“shoppingcart-ui”作为SpringBoot应用程序,它也充当Zuul代理。使用WebConfig ClientEureka DiscoveryZuul启动器创建一个SpringBoot项目,并使用@EnableZuulProxy注释主要入口点类。

1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
< dependency >
     < groupId >org.springframework.boot</ groupId >
     < artifactId >spring-boot-starter-web</ artifactId >
</ dependency >
< dependency >
     < groupId >org.springframework.cloud</ groupId >
     < artifactId >spring-cloud-starter-config</ 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-starter-netflix-zuul</ artifactId >
</ dependency >

ShoppingcartUiApplication.java

1
2
3
4
6
7
8
9
10
11
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@EnableZuulProxy
@SpringBootApplication
public class ShoppingcartUiApplication {
     public static void main(String[] args) {
         SpringApplication.run(ShoppingcartUiApplication. class , args);
     }
}

由于我们也在使用Eureka Discovery,因此来自具有URL模式/ service-id / **的代理的请求将被路由到服务ID为“service-id”的 Eureka Server中注册的服务

For,ex:从UI应用程序中,如果我们向http:// localhost:8080 / catalog-service / products 发出请求,那么它将在Service Registry中查找ServiceID “catalog-service”并将请求与URL / products一起发送到一个可用的目录服务实例。

为了实现这一目标,我们需要向Eureka Service Registry注册“shoppingcart-ui”。

bootstrap.properties

1
2
3
spring.application.name=shoppingcart-ui
server.port=8080
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

现在使用此配置,我们可以使用jQuery从catalog-service获取产品信息,如下所示:

1
2
3
4
6
$.ajax({
     url: '/catalog-service/products'
})
.done( function (data) {
     this .products = data;
}.bind( this ));

在我们的UI应用程序中,我们正在调用http:// localhost:8080 / catalog-service / products。假设catalog-service已在ServiceID“catalog-service”中注册并在端口8181上运行,则此请求将转发到http:// host:8181 / products。但UI完全不知道运行的实际目录服务在哪里,它的主机名端口号等。

我们还可以使用URL的公共前缀,例如“/ api”,我们希望Zuul通过设置zuul.prefix属性来代理。

1
zuul.prefix=/api

现在,我们可以从UI请求获取http:// localhost:8080 / api / catalog-service / products中的产品。默认情况下,Zuul将剥离前缀并转发请求。

您还可以自定义服务的路径映射,如下所示:

1
2
zuul.routes.catalogservice.path=/catalog/**
zuul.routes.catalogservice.serviceId=catalog-service

使用此配置,您可以使用URL http:// localhost:8080 / api / catalog / products,这些产品将通过serviceId catalog-service转发到服务。

默认情况下,将公开在Eureka Server中注册的所有服务。您可以使用zuul.ignored-services属性来禁用此行为,并仅公开显式配置的服务。

1
2
3
4
6
7
zuul.ignored-services=*
zuul.routes.catalogservice.path=/catalog/**
zuul.routes.catalogservice.serviceId=catalog-service
zuul.routes.orderservice.path=/orders/**
zuul.routes.orderservice.serviceId=order-service

使用此配置仅限目录服务订单服务通过Zuul代理公开,但不通过库存服务公开。

使用Zuul过滤器来解决交叉问题

由于Zuul充当我们所有微服务的代理,我们可以使用Zuul服务来实现一些跨领域的问题,如安全性,速率限制等。一个常见的用例是将Authentication头转发给所有下游服务。

通常在微服务中,我们将使用OAuth服务进行身份验证和授权。一旦客户端通过身份验证,OAuth服务将生成一个令牌,该令牌应包含在发送给其他微服务的请求中,以便客户端无需单独为每个服务进行身份验证。我们可以使用Zuul过滤器来实现这样的功能。

1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
三十
31
32
33
34
35
36
37
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import javax.servlet.http.HttpServletRequest;
import java.util.UUID;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
public class AuthHeaderFilter extends ZuulFilter {
     @Override
     public String filterType() {
         return PRE_TYPE;
     }
     @Override
     public int filterOrder() {
         return 0 ;
     }
     @Override
     public boolean shouldFilter() {
         return true ;
     }
     @Override
     public Object run() throws ZuulException {
         RequestContext ctx = RequestContext.getCurrentContext();
         HttpServletRequest request = ctx.getRequest();
         if (request.getAttribute( "AUTH_HEADER" ) == null ) {
             //generate or get AUTH_TOKEN, ex from Spring Session repository
             String sessionId = UUID.randomUUID().toString();
            
             ctx.addZuulRequestHeader( "AUTH_HEADER" , sessionId);
         }
         return null ;
     }
}

我们使用RequestContext.addZuulRequestHeader()AUTH_HEADER添加为请求标头,该请求标头将转发到下游服务。我们需要将它注册为Spring bean。

1
2
3
4
@Bean
AuthHeaderFilter authHeaderFilter() {
     return new AuthHeaderFilter();
}

您可以在https://github.com/sivaprasadreddy/spring-boot-microservices-series找到本文的源代码。

Categories: GateWay MicroServices

发表评论 取消回复

placeholder.jpg

电子邮件地址不会被公开。

Name
Email
Website
What's on your mind?

猜你喜欢

转载自blog.csdn.net/cpongo3/article/details/89327702