第十二节 zuul服务网关

亮子 2021-06-09 02:16:07 17676 1 1 0

1、为什么需要网关?

我们知道我们要进入一个服务本身,很明显我们没有特别好的办法,直接输入IP地址+端口号,我们知道这样的做法很糟糕的,这样的做法大有问题。

第一,暴露了我们实体机器的IP地址,别人一看你的IP地址就知道服务部署在哪里,让别人很方便的进行攻击操作。

第二,我们这么多服务,我们是不是要挨个调用它呀,我们这里假设做了个**权限认证**,我们每一个客户访问的都是跑在不同机器上的不同的JVM上的服务程序,我们每一个服务都需要一个服务认证,这样做烦不烦呀,明显是很烦的。

那么我们这时候面临着这两个极其重要的问题,这时我们就需要一个办法解决它们。首先,我们看IP地址的暴露和IP地址写死后带来的单点问题,我是不是对这么服务本身我也要动态的维护它服务的列表呀,我需要调用这服务本身,是不是也要一个负载均衡一样的玩意,

还有关于IP地址暴露的玩意,我是不是需要做一个代理呀,像Nginx的反向代理一样的东西,还有这玩意上部署公共的模块,比如所有入口的权限校验的东西。

(1)安全问题

(2)单点登录

2、zuul是什么?

因此我们现在需要Zuul API网关。它就解决了上面的问题,你想调用某个服务,它会给你映射,把你服务的IP地址映射成某个路径,你输入该路径,它匹配到了,它就去替你访问这个服务,它会有个请求转发的过程,像Nginx一样,服务机器的具体实例,它不会直接去访问IP,它会去Eureka注册中心拿到服务的实例ID,即服务的名字。我再次使用客户端的负载均衡ribbon访问其中服务实例中的一台。

核心:根据不同的url来转发请求。

图片alt

3、创建server-blog-zuul工程

图片alt

添加依赖,可以按如下添加:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <!-- Eureka Client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

4、修改配置文件application.properties

spring.application.name=server-blog-zuul
server.port=8080

# eureka client
eureka.client.service-url.defaultZone=http://localhost:6060/eureka/
eureka.instance.prefer-ip-address=true

## server-blog-user
zuul.routes.server-user.service-id=server-blog-user
zuul.routes.server-user.path=/user/**

## server-blog-article
zuul.routes.server-article.service-id=server-blog-article
zuul.routes.server-article.path=/article/**

5、启动类增加注解@EnableZuulProxy

package com.mazong.serverblogzuul;

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;

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ServerBlogZuulApplication {

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

}

6、运行效果

图片alt

7、zuul网关跨域问题

zuul作为统一网关代理所有后台接口,对于代码发起的http请求自然无需在意跨域的问题,但是对于提供给前端访问的接口,由于浏览器的安全策略对于跨域的资源访问会被拦截。 具体的关于CORS(Cross-Origin Resource Sharing)问题解析可以参考链接: 详解js跨域问题

1)、Zuul配置允许CORS

# 将网关层的CORS放开
## 参考2
zuul:
   sensitiveHeaders: Cookie,Set-Cookie
   ignored-headers: Access-Control-Allow-Credentials, Access-Control-Allow-Origin, Access-Control-Allow-Methods

## 参考1
zuul:
#需要忽略的头部信息,不在传播到其他服务
  sensitive-headers: Access-Control-Allow-Origin
  ignored-headers: Access-Control-Allow-Origin,H-APP-Id,Token,APPToken

2)、Spring配置CorsFilter

在完成第一步之后,对于Springboot项目接口,依旧会提示跨域,这是因为网关背后的每一个微服务有可能没有设置CORS,为了让每一个接口都支持CORS,因此需要在Zuul中配置CorsFilter, 代码如下:

  @Bean
  public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(source);
    }

这样在页面测试时,就能保证所有的接口都是支持CORS的了

@Component
@Configuration
public class GateWayCorsConfig
{
    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
//        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(source);
    }
}