一、简介

  在微服务架构中,网关的作用是不可忽视的,我在(八)Alian 的 Spring Cloud Gateway 网关中心已经讲过,就不再多说。本文就来讲下怎么搭建Spring Cloud Gateway 网关集群。

二、配置

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.alian.microservice</groupId>
        <artifactId>parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>

    <artifactId>gateway-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gateway-service</name>
    <description>网关服务</description>

    <dependencies>
   		<!-- 健康检查-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- gateway -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- eureka-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!-- 使用okhttp3 -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
        </dependency>
    </dependencies>
</project>

  为了使其简单,我这里使用okhttp。其他的依赖相信大家都耳熟能详了,就不过多的解释了。

三、配置文件

3.1、application.properties

#服务名
spring.application.name=gateway-service
#端口
server.port=9999

#gateway开启服务注册和发现的功能
spring.cloud.gateway.discovery.locator.enabled=true
#将请求路径上的服务名配置为小写(因为服务注册的时候,向注册中心注册时将服务名转成大写的了)
spring.cloud.gateway.discovery.locator.lower-case-service-id=true
#与Eureka注册服务中心的通信zone和url地址
eureka.client.serviceUrl.defaultZone=http://10.130.3.66:8761/eureka/,http://10.130.3.111:8761/eureka/,http://10.130.3.222:8761/eureka/
#实例是否在eureka服务器上注册自己的信息以供其他服务发现,默认为true
eureka.client.register-with-eureka=false
#该实例,相较于hostname是否优先使用IP
eureka.instance.prefer-ip-address=true

#跨域问题
spring.cloud.gateway.globalcors.cors-configurations.[/**].allowedOrigins=*
spring.cloud.gateway.globalcors.cors-configurations.[/**].allowedHeaders=*
spring.cloud.gateway.globalcors.cors-configurations.[/**].allowedMethods=*

#相同header多个值时的处理方式,三种规则可选(RETAIN_FIRST|RETAIN_UNIQUE|RETAIN_LAST)
#spring.cloud.gateway.default-filters[0]=DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_FIRST
#actuator健康检查
management.endpoints.web.exposure.include=*
management.endpoints.web.cors.allowed-origins=localhost

#部署时配置加上
#logging.config=config/logback.xml

  比较关键的配置就是:

  • spring.cloud.gateway.discovery.locator.enabled 当它的值为 true 时,表示gateway开启服务注册和发现的功能
  • spring.cloud.gateway.discovery.locator.lower-case-service-id 当它的值为 true 时,表示将请求路径上的服务名配置为小写(因为服务注册的时候,向注册中心注册时将服务名转成大写的了)
  • eureka.client.serviceUrl.defaultZone需要配置我们Eureka集群的地址

四、主类

GatewayServiceApplication.java

package com.alian.microservice.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.netflix.ribbon.okhttp.OkHttpRibbonConfiguration;

@RibbonClients(defaultConfiguration = {OkHttpRibbonConfiguration.class})
@EnableEurekaClient
@SpringBootApplication
public class GatewayServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayServiceApplication.class, args);
    }

}

  全局配置负载均衡算法: @RibbonClients(defaultConfiguration = {OkHttpRibbonConfiguration.class})

  • RibbonClients设置的必须为@Configuration类
  • 该@Configuration类不能被@ComponentScan引用
  • 不能与@SpringBootApplication类在同一个包下(默认扫描的位置是当前启动类所在的包以及启动类所在包下面的所有可扫描注解),否则将作为共享方法使用,无法针对单个服务配置。

五、部署及配置

5.1、部署

  我们部署到两台服务器上,启动完成后,到这里我们的网关中心也可以使用了,网关中心的地址如下:

  • http://10.130.3.111:9999
  • http://10.130.3.222:9999

5.2、Nginx配置

  在这里我们就要用的 Nginx 了,我这里是windows环境,所以有不懂的可以参考我另外一篇文章:windows下Nginx配置及负载均衡使用。从我之前的文章已知道,我这里在服务器 10.130.3.222 安装了 Nginx 服务,并且监听了 8888端口,并且通过访问 http://10.130.3.222:8888/gateway 可以访问到我们的网关中心。现在我们只需要增加负载均衡配置即可,主要配置如下:

localhost_8888.conf

server{
    listen 8888;
    #server_name 127.0.0.1;
    server_name localhost;
	charset utf-8;
    add_header X-Cache $upstream_cache_status;
	#站点根目录(自定义的,不一定是这个)
	root html;
	location / {
		root   html;
		index  index.html index.htm;
    }
	
	#此处是我们的关键配置
	location ~ ^/gateway/ {
		rewrite ^/gateway/(.*)$ /$1 break;
		proxy_redirect off;
		proxy_set_header Host $host:8888;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_pass http://gateway-service;
	}

	#可以绝对路径,如果是相对路径就是相对执行启动的目录(nginx.exe)
    access_log logs/localhost_access.log;
}

upstream.conf

#upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
upstream load-balance {
	#预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器
    server 127.0.0.1:8082 backup;
	#当前的server暂时不参与负载均衡
    server 127.0.0.1:8083 down;
	server 127.0.0.1:8084 weight=10;
    server 127.0.0.1:8085 weight=1 max_fails=2 fail_timeout=30s;
}

#此处就是我们关键的负载均衡配置
upstream gateway-service {
    server 10.130.3.111:9999 ;
	server 10.130.3.222:9999 ;
}

5.3、Spring Cloud Gateway 与 Nginx

  很多人纠结为何在已经有Nginx 的情况下,中间还需要一道负责负载均衡功能的Spring Cloud Gateway 网关呢?主要是以下几个方面:

  • Spring Cloud Gateway 集成了服务发现客户端Spring Cloud DiscoveryClient ,具有服务注册和发现的功能,在Nginx 中也能实现,但是每增加一个服务应用都需要手动去修改配置文件,如果服务成千上万,再加上实例数,那就不可想象了。
  • Spring Cloud Gateway 集成了 Hystrix 熔断器,可以很灵活并且精细的进行服务降级 服务限流 ,在Nginx 中也能实现,但是一般很难针对特定的业务场景处理,即算可以也非常的复杂
  • Spring Cloud Gateway 还提供 predicates(断言) 和 filters(过滤器)等功能

  所说在一些方面Nginx 可以完成 Spring Cloud Gateway 的部分功能,并且性能还高,但是Nginx 主要是做反向代理 负载均衡 限流 缓存 等,一般来说Nginx 是在大的方面做一个统筹协调,比如说通过负载均衡转发到网关,至于网关的内部相关的服务及业务并不是很关注,不然Nginx 职责就太大了。比如在一个大平台,有新老系统,又有很多很多Nginx 相关的配置,又有网关的配置,定位问题就会变得很繁琐和复杂。毕竟Nginx 不只是只有负载均衡 这一个功能。

  如果说,你接触的是一个很小的项目,服务也不多,并发也不高,用Nginx 替代Spring Cloud Gateway 也可以,当然我不建议这么做。首先,你也看到Spring Cloud Gateway 在我项目中重要作用,比如文档生成,API接口调用等,并且还是初步的状态,再者作为一个技术员,我们应该设计一个更加合理的技术架构,它的职责及职能清晰明了,然后可以不断的进行技术的更新迭代,最后各部门能很轻松的运营整个平台,这样才能提升我们的技术水平和工作效率。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐