在这说之前我发现得先说一下eureka
之前可能有人学过doubble + Zookeeper
如有对 doubble + Zookeeper 有疑问的 可以看下一篇文章 详细讲解
nginx + zuul + eureka之反向代理 流程 也会时时跟新 夹渣更详细的内容
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联系起来 画上等号
那么我们先打开这个文件小看一下:
原来这里默认配置了一个 127.0.0.1 localhost
其实就是 localhost 指向了 127.0.0.1
那么我们改成别的进行测试一下:(见证奇迹)
我这里就去配置一个tomcat
在试试 www.baidu.com
这是为什么呢?为什么不跳转百度呢?
原来这是浏览器的一个默认机制,当地址栏中出现域名,浏览器会第一时间去本地host文件中去查询有没有 域名与之对应的ip地址,如果有的话浏览器会吧地址进行拦截,获取本机ip,而不去DNS中去查询,在获取ip地址了.
但是还有一个小问题,就是我们访问真正的百度的时候是没有端口号的啊?
那么我们这个怎么去实现呢?
这是我们下面要介绍的一款工具就是Nginx,反向代理工具,那他是怎么实现的呢,我先来测试一下
哎呀这回不用端口号,那他是怎么找到进程的呢?
原来是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与 我们 地址栏的关系(我认为)
说道这,那么我们想一个问题,如果我们这个 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 )这里就遇到了我们常见的问题 (跨域问题)
由于浏览器同源策略,发送请求url的协议、域名、端口三个方面任意一与当前页面不相同即跨域。
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);
}
}
这样跨域问题就解决了