zoukankan      html  css  js  c++  java
  • Spring Cloud API网关服务 5.2

    为什么需要API网关

      通过前面内容的学习,我们已经可以构建一个简单的微服务架构系统。这个系统可以使用Spring Boot实现微服务的开发,使用Spring Cloud Eureka实现注册中心以及服务的注册与发现,使用Spring Cloud Ribbon实现服务间的负载均衡,使用Spring Cloud Hystrix实现线程的隔离和断路器功能。通过这些技术,可以设计出如图5-11所示的基础架构。

      在图5-11中,集群包含了Service A和Service B两种服务,它们会向Eureka Server注册和订阅服务,Open Service是一个对外的RESTful API服务,客户端会通过负载均衡技术(如Nginx)实现对Open Service的调用,同时服务之间也会通过Ribbon技术实现服务之间负载均衡的调用。
    虽然通过这种方式实现系统功能是没有问题的,但在实际使用时,客户端与微服务进行直接的交互还是存在着一些困难和限制的,具体表现如下。

      1. 增加开发和维护成本
      在大多数情况下,为了保证对外服务的安全性,开发人员在服务端实现的服务接口会有一定的权限校验机制(如用户登录状态校验等),并且为了防止客户端在发起请求时被篡改等安全方面的考虑,还会编写一些签名校验功能。在微服务中,我们会将原来处于一个应用中的多个模块拆分成多个应用服务,而这些拆分出来的应用服务接口也需要原来的校验逻辑,这就导致我们不得不在这些应用中全部实现这样的一套逻辑。随着微服务规模的不断扩大,这些校验逻辑的冗余将越来越多,一旦校验规则有了变化或者出了问题,我们将不得不去每一个应用中修改这些逻辑。

      2. 微服务重构困难
      随着时间的推移,我们可能需要改变系统服务目前的拆分方案(如将两个服务合并或将一个服务拆分为多个),但如果客户端直接与微服务交互,那么这种重构就很难实施。

      3. 微服务协议限制
      客户端直接请求的微服务可能使用的是与Web无关的协议。一个服务可能是用Thrift的RPC协议,而另一个服务可能是用AMQP消息协议,两种协议都不是特别适合浏览器或防火墙,最好是内部使用。应用应该在防火墙外采用HTTP或者WEBSocket之类的协议。

      由于上述原因,客户端直接与服务器端通信的方式几乎不会在实际应用中使用。那么我们要如何解决上面这些问题呢?
      通常来说,一个很好的解决办法就是采用API Gateway(网关)的方式。API Gateway是一个服务器,也可以说是进入系统的唯一节点,它封装了内部系统的架构,并且提供了API给各个客户端。它还可以有其他功能,如授权、监控、负载均衡、缓存、请求分片和管理、静态响应处理等。
      图5-12展示了一个适应当前架构的API Gateway。

      在图5-12中,API Gateway负责请求转发、合成和协议转换。所有来自客户端的请求都要先经过API Gateway,然后负载均衡这些请求到对应的微服务。
    API Gateway的一个最大好处是封装了应用的内部结构,与调用指定的服务相比,客户端直接跟Gateway交互会更简单。API Gateway提供给每一个客户端一个特定API,这样减少了客户端与服务器端的通信次数,也简化了客户端代码。API Gateway还可以在Web协议与内部使用的非Web协议间进行转换,如HTTP协议、WebSocket协议。
      API Gateway可以有很多实现方法,如Nginx、Zuul、Node.js等。本书中使用的是Spring Cloud Netflix中的Zuul,下一小节我们将对Spring Cloud Zuul的使用进行详细讲解。

    如何使用Zuul构建API网关服务

      Zuul原是Netflix公司开发的基于JVM的路由器和服务器端负载均衡器,后来被加入到了Spring Cloud中。Zuul属于边缘服务,可以用来执行认证、动态路由、服务迁移、负载均衡、安全和动态响应处理等操作。
    了解了Zuul的概念和作用后,接下来通过一个具体的应用案例来讲解如何在微服务中使用Zuul。
      本案例主要涉及到3个工程,其作用分别如下。
      ·xcservice-eureka-server工程:服务注册中心,端口为8761。
      ·xcservice-eureka-order工程:服务提供者,需要启动一个订单实例,其端口号为7900。
      ·xcservice-gateway-zuul工程:使用Zuul实现的APIGateway,端口号为8050。
      上面3个工程中,注册中心和服务提供者可以使用前面所创建的工程,而网关服务需要重新创建,其实现过程如下。
      (1)创建工程,添加依赖。在父工程xcservice-spring-cloud下创建子模块xcservice-gateway-zuul工程,并在其pom.xml中添加eureka和Zuul的依赖,如文件5-8所示。
      文件5-8 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>com.xc</groupId>
            <artifactId>xcservice-springcloud</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
        <groupId>com.xc</groupId>
        <artifactId>xcservice-gateway-zuul</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>xcservice-gateway-zuul</name>
        <description>网关服务</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-zuul</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
      (2)编辑配置文件。在配置文件中编写Eureka服务实例的端口号、服务端地址等信息,如文件5-9所示。
      文件5-9 application.yml
    server:
      port: 8050 # 指定该Eureka实例的端口号
    
    eureka:
      instance:
        prefer-ip-address: true  # 是否显示主机的IP
        #instance-id: ${spring.cloud.client.ipAddress}:${server.port} #将Status中的显示内容也以“IP:端口号”的形式显示
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/ # 指定Eureka服务端地址
    
    spring:
      application:
        name: xcservice-gateway-zuul # 指定应用名称
    
    zuul:
      routes:
        order-serviceId: # zuul的唯一标识
          path: /order/**   # 需要映射的路径
          service-id: xcservice-eureka-order  # Eureka中的serviceId

      在上述配置信息中,zuul就是API网关服务的路由配置。其中order-serviceId为Zuul的唯一标识,可以任意设置名称,但必须唯一,如果该值与service-id的名称相同时,service-id的值可以省略。path属性后面的值表示需要映射的路径,service-id后面的值为Eureka中的serviceId,应用在运行时,所有符合映射路径的URL都会被转发到xcservice-eureka-order中。

      需要注意的是,Zuul的配置方式有很多,这里只是针对本案例实现的一种方式。如果读者想要了解更多的配置方式,可以参考官方文档中Zuul的配置进一步学习。


      (3)在工程主类Application中使用@EnableZuulProxy注解开启Zuul的API网关功能,其代码如文件5-10所示。
    package com.xc.xcservicegatewayzuul;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    /**
     * http://localhost:8050/xcservice-eureka-order/order/1
     */
    @EnableZuulProxy
    @SpringBootApplication
    @EnableEurekaClient
    public class XcserviceGatewayZuulApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(XcserviceGatewayZuulApplication.class, args);
        }
    
    }
      (4)分别启动注册中心、服务提供者和网关服务后,注册中心已注册的服务如图5-13所示。

      此时可以通过地址http://localhost:7900/order/1单独访问订单服务
      下面通过Zuul来验证路由功能,通过网关服务来访问订单信息。在浏览器地址栏中输入地址http://localhost:8050/xcservice-eureka-order/order/1后,浏览器已经显示出来所要访问的订单信息。这说明使用Zuul配置的路由功能已经生效,通过服务ID映射的方式已可以进行跳转。 
  • 相关阅读:
    ZOJ 1002 Fire Net (火力网)
    UVa OJ 117 The Postal Worker Rings Once (让邮差只走一圈)
    UVa OJ 118 Mutant Flatworld Explorers (变体扁平世界探索器)
    UVa OJ 103 Stacking Boxes (嵌套盒子)
    UVa OJ 110 MetaLoopless Sorts (无循环元排序)
    第一次遇到使用NSNull的场景
    NSURL使用浅析
    从CNTV下载《小小智慧树》
    NSDictionary and NSMutableDictionary
    Category in static library
  • 原文地址:https://www.cnblogs.com/ooo0/p/11197210.html
Copyright © 2011-2022 走看看