nginx + zuul + eureka之反向代理 流程

在这说之前我发现得先说一下eureka
之前可能有人学过doubble + Zookeeper
如有对 doubble + Zookeeper 有疑问的 可以看下一篇文章 详细讲解

nginx + zuul + eureka之反向代理 流程 也会时时跟新 夹渣更详细的内容

1.nginx与地址栏的那些事

nginx:
1.可以认为是一个web前段服务器,可一把一些静态资源放在里面,减少我们后台服务器的开销,(里面自带负载均衡,熔断策略)
2.可以认为是一些域名的配置中心

我们tomcat一般在浏览器访问的地址之前都是

http://localhost:8080

或者

http://127.0.0.1:8080

那么这个localhost是谁给替换的呢,如果我们知道的话是不是可以替换成像www.baidu.com这样的域名呢

那么我们先来了解一下浏览器的本质,原来浏览器当得到一个域名的时候先去本地的C:\Windows\System32\drivers\etc\hosts文件里去查询是否有这个路径如果有就把域名与之对应的ip联系起来 画上等号

那么我们先打开这个文件小看一下:
nginx + zuul + eureka之反向代理 流程_第1张图片原来这里默认配置了一个 127.0.0.1 localhost
其实就是 localhost 指向了 127.0.0.1

那么我们改成别的进行测试一下:(见证奇迹)
在这里插入图片描述
我这里就去配置一个tomcat
在试试 www.baidu.com
nginx + zuul + eureka之反向代理 流程_第2张图片
这是为什么呢?为什么不跳转百度呢?
原来这是浏览器的一个默认机制,当地址栏中出现域名,浏览器会第一时间去本地host文件中去查询有没有 域名与之对应的ip地址,如果有的话浏览器会吧地址进行拦截,获取本机ip,而不去DNS中去查询,在获取ip地址了.

但是还有一个小问题,就是我们访问真正的百度的时候是没有端口号的啊?
那么我们这个怎么去实现呢?

这是我们下面要介绍的一款工具就是Nginx,反向代理工具,那他是怎么实现的呢,我先来测试一下
nginx + zuul + eureka之反向代理 流程_第3张图片哎呀这回不用端口号,那他是怎么找到进程的呢?
原来是nginx的监听起到了作用

让我们来看一下主配置文件:
打开nginx目录:F:\SoftWare\nginx-1.12.2\conf\nginx.config(这是我的)
配置反向代理:
为了方便,还不改变原有的配置 我们引入我们自己的配置文件
我们打开我们nginx.config加上
include vhost/*.conf;

worker_processes  1;
events {
     
    worker_connections  1024;
}


http {
     
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    
    keepalive_timeout  65;


	#inclue *.config file
	include vhost/*.conf;
	
	
    server {
     
        listen       80;
        server_name  localhost;
        
        location / {
     
            root   html;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
     
            root   html;
        }  
    }
}

在conf里新建一个文件夹vhost 里面在建一个 MyConfig.config
F:\SoftWare\nginx-1.12.2\conf\vhost
F:\SoftWare\nginx-1.12.2\conf\vhost\MyConfig.config

server {
     
    #监听
	listen       80;
	
	#指定域名
	server_name  www.baidu.com;
	
	location / {
     
		#根据域名来找指定的ip和端口号
	    proxy_pass   http://127.0.0.1:8080;
		proxy_connect_timeout 600;
		proxy_read_timeout 5000;
	}
}
上面什么情况呢,让我慢慢道来,原来当你在浏览器输入对应的域名之后
第一步:浏览器会根据你输入的域名去本地扫面,找到指定的ip,这样就不用去dns上拉取信息了
第二步:因为之前开启了nginx,里面配置了监听www.baidu.com这个域名,他会检索到要访问这个域名了,
	   然后给你指定ip  端口号,这样就相当于nginx给你干了一件配置端口号的事,就不需要我们再去配置了
第三步:浏览器得到指定的ip  端口号 就去访问了

以上就是我们的nginx与 我们 地址栏的关系(我认为)

2.谈一谈nginx 与 zuul的那些事

说道这,那么我们想一个问题,如果我们这个 proxy_pass http://127.0.0.1:8080; 随便填一个是不是可以实现服务器与服务器之间的切换呢?如果想到这的同学是真的会举一反三.
在我们java微服务中确实可以实现,但是需要借助Spring的那个包下的那个组件:

Spring Cloud Netflix通过自动配置并绑定到Spring Environment和其他Spring编程模型习惯用法,为Spring Boot应用程序提供Netflix OSS集成。
通过一些简单的注释,您可以快速启用和配置应用程序内部的通用模式,并使用经过测试的Netflix组件构建大型分布式系统。提供的模式包括服务发现
(Eureka),断路器(Hystrix),智能路由(Zuul)和客户端负载平衡(Ribbon)。

特征:

Spring Cloud Netflix功能:

服务发现:可以注册Eureka实例,并且客户端可以使用Spring托管的Bean发现实例

服务发现:可以使用声明性Java配置创建嵌入式Eureka服务器

断路器:Hystrix客户端可以使用简单的注释驱动的方法装饰器构建

断路器:具有声明性Java配置的嵌入式Hystrix仪表板

声明式REST客户端:Feign创建一个用JAX-RS或Spring MVC注释修饰的接口的动态实现。

客户端负载均衡器:功能区

外部配置:从Spring Environment到Archaius的桥梁(使用Spring Boot约定启用Netflix组件的本机配置)

路由器和过滤器:Zuul过滤器的自动重新注册,以及用于反向代理创建的简单配置约定

上面有的不知道没事,我慢慢会道来,虽然有点累,
原来zuul充当路由器和过滤器的身份呢,让我慢慢道来,

主要原因:
1.比如:(这里我们使用微服务进行管理)
我们前台使用的是我们当前配置的tomcat,域名为:http:www.qiantai.com
我们后台也使用的是我们配置的一个tomcat,域名为:http:www.houtai.com

      如果我们用域名http:www.qiantai.com 向我们后台发出请求 http:www.houtai.com?name=zhangsan&password=123 让后台判定是否让我们去登陆,这时当
      我们运行的时候,会发现前台浏览直接报错,403 错误信息我在这里就不在去写了,(提示一些 routs ....   403 )这里就遇到了我们常见的问题 (跨域问题)

3.那么什么又是跨域问题?

由于浏览器同源策略,发送请求url的协议、域名、端口三个方面任意一与当前页面不相同即跨域。

4.为什么会有跨域问题

1:什么是源
源(origin)就是协议、域名和端口号
2:什么是同源策略
因为存在浏览器同源策略,所以才会有跨域问题。那么浏览器是出于何种原因会有跨域的限制呢。其实不难想到,跨域限制主要的目的就是为了用户的上网安全。
如果浏览器没有同源策略,会存在什么样的安全问题呢。下面从 DOM 同源策略和 XMLHttpRequest 同源策略来举例说明:

如果没有 DOM 同源策略,也就是说不同域的 iframe 之间可以相互访问,那么黑客可以这样进行攻击:

    做一个假网站,里面用 iframe 嵌套一个银行网站 http://mybank.com。
     iframe 宽高啥的调整到页面全部,这样用户进来除了域名,别的部分和银行的网站没有任何差别。
    这时如果用户输入账号密码,我们的主网站可以跨域访问到 http://mybank.com  dom 节点,就可以拿到用户的账户密码了。

如果 XMLHttpRequest 同源策略,那么黑客可以进行 CSRF(跨站请求伪造) 攻击:

 用户登录了自己的银行页面 http://mybank.com,http://mybank.com 向用户的 cookie 中添加用户标识。
    用户浏览了恶意页面 http://evil.com,执行了页面中的恶意 AJAX 请求代码。
    http://evil.com  http://mybank.com 发起 AJAX HTTP 请求,请求会默认把 http://mybank.com 对应 cookie 也同时发送过去。
    银行页面从发送的 cookie 中提取用户标识,验证用户无误,response 中返回请求数据。此时数据就泄露了。
    而且由于 Ajax 在后台执行,用户无法感知这一过程。

因此,有了浏览器同源策略,我们才能更安全的上网。

同源策略主要带来三个方面的限制:

1、cookie,localstorage和IndexDB无法读取

2、DOM无法获取

3、Ajax请求不能发送

由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域

跨域是为了什么

为了能够使得使用cookie,让浏览器能够将sessionid放入到request。服务端能够识别是那个用户登录的。从而跨域也可以请求资源,并且不需要登录。

那么下面让我们来看看这个跨域我们到底怎么去进行配置
我在这里用的是Spring cors
导入的依赖

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

看一下我们配置的网关信息
application.xml (注意: eureka 和 hystrix 和 ribben 我们这里目前还没有涉及到 现在不要关注)

server:
  port: 10010  #配置我们的服务端口号
spring:
  application:
    name: my-gateway  #给我们的服务起一个 名称 那么eureka就可以通过名称拉取服务
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka  #把服务注册到eureka注册中心
    registry-fetch-interval-seconds: 5
hystrix: #负载均衡
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 6000 # 熔断超时时长:6000ms
ribbon:
  ConnectTimeout: 500 # ribbon链接超时时长
  ReadTimeout: 2000 # ribbon读取超时时长
  MaxAutoRetries: 0  # 当前服务重试次数
  MaxAutoRetriesNextServer: 1 # 切换服务重试次数
  OkToRetryOnAllOperations: false # 是否对所有的请求方式都重试,只对get请求重试

#看这里   zuul的配置
zuul:
  prefix: /api  #配置网关的

  routes:
    item-service: /item/** # 将特定的微服务映射到/item/*
    upload-service: /upload/**
    search-service: /search/**

my:
  cors:
    allowedOrigins:
      - http://manage.qiantai.com  #把前台域名加入白名单  这样就不存在 跨域问题了
    allowedCredentials: true
    allowedHeaders:
      - "*"
    allowedMethods:
      - GET
      - POST
      - DELETE
      - PUT
      - OPTIONS
      - HEAD
    maxAge: 360000
    filterPath: "/**"

看一下我们cors的实体类

@Data
@ConfigurationProperties(prefix = "my.cors")
public class CORSProperties {
     
    private List<String> allowedOrigins; //允许的 域名  相当于加入网关的白名单
    private Boolean allowedCredentials;
    private List<String> allowedMethods;  //允许的方法
    private List<String> allowedHeaders;  //允许的头信息
    private Long maxAge;	//最大的生存时间
    private String filterPath; //过滤路径
}

看一下我们的cors工具类

@Configuration
@EnableConfigurationProperties(CORSProperties.class)
public class GlobalCORSConfig {
     
    @Bean
    public CorsFilter corsFilter(CORSProperties prop) {
     
        //1.添加CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //1) 允许的域,不要写*,否则cookie就无法使用了
        prop.getAllowedOrigins().forEach(config::addAllowedOrigin);
        //2) 是否发送Cookie信息
        config.addAllowedOrigin("http://localhost:9001");
        config.setAllowCredentials(prop.getAllowedCredentials());
        //3) 允许的请求方式
        prop.getAllowedMethods().forEach(config::addAllowedMethod);
        // 4)允许的头信息
        prop.getAllowedHeaders().forEach(config::addAllowedHeader);
        // 5)配置有效期
        config.setMaxAge(prop.getMaxAge());

        //2.添加映射路径,我们拦截一切请求
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration(prop.getFilterPath(), config);

        //3.返回新的CORSFilter.
        return new CorsFilter(configSource);
    }
}

这样跨域问题就解决了

你可能感兴趣的:(java)