Spring Cloud 快速入门系列之gateway–网关

对于微服务之间的调用,我们一般不需要做身份验证,但是如果是外部请求到微服务,那么就需要进行身份验证了,比如app或PC端请求登录,请求发到User服务,则要进行身份验证;再比如app或PC端下单,则要请求Order服务,你是不是发现了一个问题,外部请求请求到哪个微服务,哪个微服务就要进行身份认证,这无疑是增加了每个微服务的负担和复杂性。

如果我们用一个微服务专门来做身份验证,验证完成之后,将请求转发到其他微服务,各个微服务之间的相互调用就不再需要做身份认证了,这样是不是就解决上面的问题了。

这就是Spring Cloud Zuul的作用之一。

Zuul支持前置身份认证、审查、监控、动态路由等等功能。

我们来演示一下,gateway怎样实现路由分发功能,这也是gateway最基本和重要的功能,也就是外部请求统一都请求到gateway服务,由gateway来统一分发请求到各个微服务。

实操O(∩_∩)O

1、新建一个maven项目,名叫gateway

<?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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gateway</artifactId>
    <groupId>com.itzhimei</groupId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR5</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</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>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </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>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

这里重点引入了Zuul的gateway依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>

2、新建应用启动类

package com.itzhimei.gateway;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy
@SpringBootApplication
public class GatewayApplication {

	private static final Logger LOGGER = LoggerFactory.getLogger(GatewayApplication.class);
	public static void main(String[] args) {
		SpringApplication.run(GatewayApplication.class, args);
		LOGGER.info("网关服务启动完成...");
	}

}

这里使用了注解@EnableZuulProxy,让该项目支持了网关功能

3、添加配置bootstrap.yml和bootstrap-dev.yml

bootstrap.yml内容:

spring:
  application:
    name: gateway
  profiles:
    active: dev
  cloud:
    config:
      discovery:
        enabled: true
        serviceId: config
      # profile: dev
      label: gateway

server:
  port: 3333

eureka:
  instance:
    prefer-ip-address: true #注册时使用ip地址

这里的配置和前面章节的作用是一样的,指定自己的服务serviceId,指定配置中心。

bootstrap-dev.yml内容:

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1111/eureka/

这里是指定向哪里注册服务

4、路由分发功能

我们在gateway服务的bootstrap.yml文件中再添加一些配置:

zuul:
  routes:
    api-user:
      path: /api-service-a/**
      service-id: service-a

这些配置就是一个最简单的路由映射配置。

path: /api-service-a/** 表示请求格式是:ip或域名:端口/api-service-a/任意内容,映射到service-id是service-a的服务上。

也就是例如 localhost:3333/api-service-a/api/user/getApiInfo,请求应该先到网关服务,然后网关服务根据配置,将请求转发到service-a。

为了完成示例,我们在service-a服务中在添加一个controller,代码如下:

package com.itzhimei.servicea.controller.api;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(("/api/user"))
public class ApiUserController {

    @Value("${user.name}")
    String name;

    @Value("${user.age}")
    int age;

    @GetMapping(value = "/getApiInfo")
    public String getInfo(){
        return "名字是:"+name+",年龄是:"+age+1;
    }

}

现在把服务都启动,测试一下效果。

请求地址:localhost:3333/api-service-a/api/user/getApiInfo

输出结果:名字是:张三,年龄是:21

到这里,网关服务最重要的一个路由转发功能就完成了。

我们这里其实还可以把gateway的路由映射配置,放到配置中心来统一管理,动手试一下。