上一篇👉: 浏览器垃圾回收机制
文章目录
- 浏览器同源策略
-
- 1.同源策略的定义
- 2.同源策略的作用
- 3.同源策略的限制范围
- 4.解决跨域方案汇总
-
- 1.CORS(跨源资源共享)
- 2.JSONP
- [3.postMessage 跨域](#3.postMessage 跨域)
- 4.Nginx代理跨域
- 5.Node.js中间件代理跨域
- [6.document.domain + iframe](#6.document.domain + iframe)
- [7.Location.hash + iframe](#7.Location.hash + iframe)
- [8.window.name + iframe跨域](#8.window.name + iframe跨域)
- 9.WebSocket协议跨域
- 5.正向代理与反向代理的区别
-
- [正向代理(Forward Proxy)](#正向代理(Forward Proxy))
- [反向代理(Reverse Proxy)](#反向代理(Reverse Proxy))
- 核心差异
- 6.Nginx
-
- Nginx概念及工作原理
- 核心特性
- 架构层次
- [Master Process(主进程)](#Master Process(主进程))
- [Worker Processes(工作进程)](#Worker Processes(工作进程))
- 工作流程
浏览器同源策略
1.同源策略的定义
同源策略(Same-origin policy)是Web浏览器为保护用户信息安全而实施的一种重要安全策略。该策略规定,Web浏览器允许来自同一源的文档或脚本访问彼此的资源,但限制了来自不同源的交互。这里的"源"指的是协议、域名和端口号三者的组合。如果三个要素完全一致,则视为同源;有任何一个不相同,则视为跨域。
2.同源策略的作用
- 保护用户数据:防止恶意网站读取另一个网站的敏感数据,如Cookies、存储在浏览器中的用户个人资料等。
- 防止恶意脚本执行:阻止不同源的脚本相互操作,防止恶意脚本注入和执行,保护用户的浏览环境安全。
3.同源策略的限制范围
同源策略主要在以下几个方面实施限制:
- JavaScript访问权限:禁止脚本读取或修改不同源页面的DOM,也无法向不同源的服务器发送Ajax请求(除非目标服务器明确允许跨域)。
- Cookie、LocalStorage和IndexedDB访问:禁止脚本访问不同源的这些存储数据,保护用户数据不被非法窃取或篡改。
- 其他API限制 :包括Web Storage、Web Workers、Fetch API等现代Web
API在内,大多遵循同源策略,限制跨域访问。
4.解决跨域方案汇总
1.CORS(跨源资源共享)
CORS(跨域资源共享)是一种机制,确保了网页可以从不同源(协议、域名、端口)的服务器上获取资源,而不会受到浏览器同源策略的限制。这一机制通过在HTTP请求和响应中加入特定的头部信息来工作,从而允许或拒绝跨域请求。
-
简单请求
简单请求的特点是使用了GET、HEAD或POST方法,并且HTTP头部信息限于几个特定字段。这类请求不会触发预检请求(preflight request),浏览器直接发起请求,并在请求头中加入
Origin
字段,表明请求源。服务器需要在响应中包含Access-Control-Allow-Origin
头部,以明确允许的请求源。对于简单请求,服务器至少需要配置Access-Control-Allow-Origin
字段。 -
非简单请求
包括使用了除GET、HEAD、POST之外的方法(如DELETE、PUT),或POST请求中包含非标准的内容类型、自定义请求头等。这类请求会在正式请求前先发送一个OPTIONS请求作为预检请求,以确认实际请求是否安全可接受。预检请求会携带
Origin、Access-Control-Request-Method
和Access-Control-Request-Headers
等头部。服务器需响应这些头部对应的允许值,至少包括Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers
。 -
Cookie处理
要在CORS请求中携带Cookie,需满足以下条件:
- 客户端(如通过XMLHttpRequest或Fetch API)需设置withCredentials属性为true,表明请求需要携带凭据(如Cookie)。
- 服务器响应中必须设置Access-Control-Allow-Credentials为true,表明服务器允许浏览器携带Cookie。
- Access-Control-Allow-Origin不能设为星号*,而应指定具体的源地址,因为星号不允许与Access-Control-Allow-Credentials: true一起使用。
-
减少OPTIONS请求
为了优化性能,可以通过在服务器响应中设置Access-Control-Max-Age头部来缓存预检请求的结果,避免每次请求都发送OPTIONS请求。该值指定了预检请求结果的有效期,单位为秒。
总之,CORS通过一系列HTTP头部的精确控制,实现了安全的跨域数据交互,同时提供了灵活的配置选项以适应不同场景的安全需求和性能优化。
2.JSONP
JSONP(JSON with Padding)是一种跨域数据交互技术,其原理基于浏览器对 <script>
标签的特性和同源策略的绕过。
原理 :JSONP利用了浏览器对<script>
标签的特殊处理:通过动态创建<script>
元素并设置其src属性为包含API请求的URL,由于<script>
标签的资源请求不受同源策略限制,因此可以实现跨域数据请求。请求URL中通常包含一个查询参数,用于指定客户端期望调用的回调函数名称。服务器接收到请求后,会将响应数据包裹在这个回调函数中返回,从而在客户端执行并传递数据。
JavaScript实现
javascript
<script>
// 创建script元素
var script = document.createElement('script');
script.type = 'text/javascript';
// 设置src属性,包含请求URL及回调函数名
script.src = 'http://www.example.com/api/data?callback=myCallback';
// 将script元素插入页面,触发请求
document.head.appendChild(script);
// 定义回调函数处理服务器返回的数据
function myCallback(data) {
console.log(data);
}
</script>
服务器响应内容示例:
java
myCallback({"status": "success", "message": "Hello, World!"});
Vue中使用axios实现JSONP
在Vue项目中,虽然axios本身不直接支持JSONP,但可以通过封装或使用第三方库如vue-jsonp来实现。这里提供一个简化的示例说明如何模拟实现:
javascript
// 注意:实际开发中应使用专门的库或封装方法
this.$http.jsonp('http://www.example.com/api/data', {
params: {
callback: 'myCallback'
}
}).then((res) => {
console.log(res.data);
})
后端Node.js示例
后端需要解析请求中的回调函数名,并将响应数据封装进该函数返回。
javascript
const http = require('http');
const querystring = require('querystring');
const server = http.createServer((req, res) => {
let params = querystring.parse(req.url.split('?')[1]);
let callback = params.callback;
// 假设这是从数据库获取的数据
let data = {"status": "success", "data": "Sample Data"};
// 构造JSONP响应
res.writeHead(200, {'Content-Type': 'application/javascript'});
res.end(`${callback}(${JSON.stringify(data)})`);
});
server.listen(8080, () => {
console.log('Server running on port 8080');
});
JSONP的缺点
- 仅支持GET请求:因为数据是通过URL查询参数传递的,这限制了其适用场景,不适合大型数据传输或涉及敏感信息的请求。
- 安全性问题:容易受到XSS(跨站脚本攻击)的威胁,恶意脚本可能通过构造特殊的回调函数名注入执行。
- 无错误处理机制:相比现代的CORS等技术,JSONP缺乏标准化的错误处理流程,调试和错误报告较为困难。
3.postMessage 跨域
postMessage 是一种允许来自不同源的脚本采用异步方式进行有限通信的Web API。这一功能对于实现跨域消息传递至关重要,尤其是在涉及iframe、窗口以及Web Worker之间的通信场景。
概念:postMessage 方法允许一个窗口(或iframe)向另一个窗口(或iframe)发送消息,即使这两个窗口(或iframe)来源于不同的源(协议+域名+端口)。这对于实现跨域通信是非常有用的技术,因为它不受到同源策略的限制。
用法:postMessage 方法接收两个参数:
data
:要发送的数据。根据HTML5规范,它可以是任何基本类型或可复制的对象,但在某些较旧的浏览器中,可能只支持字符串。因此,最佳实践是使用JSON.stringify()
将对象转换为字符串。origin
:指定哪些源的窗口应该接收消息。可以设置为特定的源(如 'http://example.com
'),或者使用通配符*
来允许任何源接收消息(但这存在安全风险,应谨慎使用)。若要限定与当前窗口同源,则可设置为/
。
应用场景
- 页面与其打开的新窗口间的数据传递
- 多个窗口间的消息传递
- 主页面与嵌入的iframe间的消息传递
示例
sender.html (位于 domain1.com/sender.html):
html
<iframe id="iframe" src="http://www.domain2.com/receiver.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe');
iframe.onload = function() {
var message = {
content: 'Hello from sender!'
};
iframe.contentWindow.postMessage(JSON.stringify(message), 'http://www.domain2.com');
window.addEventListener('message', function(e) {
if (e.origin === 'http://www.domain2.com') {
alert('Response from receiver: ' + e.data);
}
}, false);
};
</script>
receiver.html (位于 domain2.com/receiver.html):
html
<script>
window.addEventListener('message', function(e) {
if (e.origin === 'http://www.domain1.com') {
alert('Message received from sender: ' + e.data);
var response = {
content: 'Hello back to sender!',
original: JSON.parse(e.data)
};
e.source.postMessage(JSON.stringify(response), e.origin);
}
}, false);
</script>
注意事项
- 在使用
postMessage
时,确保正确验证消息来源(即检查event.origin
属性),以防止跨站脚本攻击(XSS)。 - 消息接收方通过监听
message
事件来接收消息,其中event.data
包含发送的数据,而event.origin
则标识发送消息的源。
使用e.source.postMessage()而不是window.parent.postMessage()可以更灵活地处理消息的回传,特别是在多个窗口或iframe结构中。
4.Nginx代理跨域
使用Nginx作为代理服务器解决跨域问题,主要利用其强大的反向代理能力和对HTTP头部的灵活控制能力,实现跨源资源共享(CORS)。以下是两种常见的应用场景及其解决方案:
- Nginx配置解决iconfont跨域问题
当静态资源服务器需要向不同源的客户端提供iconfont字体文件(如.eot、.otf、.ttf、.woff、.svg格式)时,虽然大部分静态资源不受同源策略限制,但这些字体文件可能因浏览器的安全策略遇到跨域问题。通过在Nginx配置中添加适当的Access-Control-Allow-Origin头部,可以允许所有源访问这些字体文件,从而解决跨域问题。
javascript
location / {
add_header Access-Control-Allow-Origin *;
}
这段配置表示对所有请求到该Nginx服务器的资源,响应头中都会包含Access-Control-Allow-Origin: *,允许任何源的请求访问。
- Nginx反向代理解决接口跨域问题
对于前后端分离的应用,尤其是前端请求不同源后端接口的情况,可以通过Nginx设置反向代理来规避浏览器的同源策略限制。
实现思路是设置一个与前端同源(域名相同,端口可以不同)的Nginx代理服务器,该服务器接收前端的请求,然后作为"中转站"去访问实际后端服务(domain2),并将后端响应转发回前端。这样,从浏览器的角度看,请求和响应都在同一个源下,避免了跨域问题。
javascript
server {
listen 81; # 代理服务器监听的端口
server_name www.domain1.com; # 与前端同源的域名
location / {
proxy_pass http://www.domain2.com:8080; # 反向代理至实际后端接口地址
proxy_cookie_domain www.domain2.com www.domain1.com; # 修改响应中Set-Cookie的Domain属性,使前端能正确保存cookie
# 当前端请求需要带cookie且涉及到跨域时,需要设置如下头部
add_header Access-Control-Allow-Origin http://www.domain1.com; # 允许特定源的跨域请求
add_header Access-Control-Allow-Credentials true; # 允许携带凭证(如cookies)
# 如果前端请求不涉及cookie,可以简化为
# add_header Access-Control-Allow-Origin *;
}
}
这段配置不仅实现了接口的跨域访问,还通过proxy_cookie_domain指令修改了后端返回的Cookie中Domain属性,确保了前端能够正确存储和使用这些Cookie,这对于需要认证或状态保持的场景尤为重要。
请注意,当设置Access-Control-Allow-Credentials为true时,Access-Control-Allow-Origin不能设置为*,而应指定确切的源地址,以确保安全性。
5.Node.js中间件代理跨域
在Node.js中使用中间件实现跨域代理,是一种常见的处理前后端分离项目中跨域请求问题的方法。此方法通过在Node.js服务器上部署一个代理层,将前端的跨域请求转发到目标后端服务器,有效绕过了浏览器的同源策略限制。下面分别介绍非Vue框架和Vue框架下的跨域代理实现方式。
- 非Vue框架下的跨域代理
使用Express框架配合http-proxy-middleware中间件可以快速搭建一个代理服务器,用于转发前端请求到后端API服务器,并处理跨域问题。
前端请求示例:
javascript
var xhr = new XMLHttpRequest();
xhr.withCredentials = true; // 允许携带cookie
xhr.open('GET', 'http://www.domain1.com:3000/login?user=admin', true);
xhr.send();
Node.js服务器配置:
javascript
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
app.use('/', createProxyMiddleware({
target: 'http://www.domain2.com:8080', // 目标API服务器地址
changeOrigin: true, // 改变请求源头,模拟从代理服务器发起请求
onProxyRes: function(proxyRes, req, res) {
res.header('Access-Control-Allow-Origin', 'http://www.domain1.com'); // 设置允许的源
res.header('Access-Control-Allow-Credentials', 'true'); // 允许携带凭证
},
cookieDomainRewrite: 'www.domain1.com', // 修改响应中Cookie的Domain
}));
app.listen(3000, () => {
console.log('Proxy server is running on port 3000');
});
- Vue框架下的跨域代理
在Vue项目开发过程中,通常会使用Webpack作为打包工具,webpack-dev-server提供了内置的代理功能,可以直接在webpack.config.js中配置接口代理,简化跨域处理流程。
webpack.config.js配置示例:
javascript
module.exports = {
// ...其他配置
devServer: {
historyApiFallback: true,
proxy: {
'/login': { // 匹配的路径
target: 'http://www.domain2.com:8080', // 目标API服务器地址
changeOrigin: true, // 改变请求源头
secure: false, // 如果是HTTPS接口,需要设置为false
cookieDomainRewrite: 'www.domain1.com', // 修改响应中Cookie的Domain
}
},
noInfo: true // 减少输出信息
}
};
在Vue项目的开发环境下,通过上述配置,webpack-dev-server会自动拦截前端向/login路径的请求,并将其代理到指定的后端API服务器,同时处理好跨域问题,使得开发者可以无缝对接后端接口进行开发调试,而无需关心跨域问题。
6.document.domain + iframe
在Web开发中,当遇到主域相同但子域不同的跨域问题时,可以通过修改document.domain属性的方法结合<iframe>
标签来实现跨域通信。这种方法适用于那些拥有共同顶级域名的页面间的通信需求。具体实施步骤如下:
实现原理:
设置document.domain: 两个页面------即父页面和子页面(通过<iframe>
嵌入)------都需要通过JavaScript设置它们的document.domain属性为相同的高级别主域。这样做是为了让浏览器认为这两个页面处于同一个域下,从而绕过同源策略的限制。
应用场景:
限制条件: 此方案仅适用于主域名相同,但子域名不同的场景。例如,a.example.com和b.example.com可以使用此方法通信,但example.com与anotherexample.com则不适用。
示例代码
父窗口页面 (domain.com/a.html):
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Parent Window</title>
</head>
<body>
<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
document.domain = 'domain.com'; // 设置document.domain为共同的基础主域
var user = 'admin'; // 父窗口定义的变量
</script>
</body>
</html>
子窗口页面 (child.domain.com/b.html):
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Child Window</title>
</head>
<body>
<script>
document.domain = 'domain.com'; // 子窗口同样设置document.domain为共同的基础主域
// 从父窗口获取变量
console.log('获取父窗口数据: ' + window.parent.user);
</script>
</body>
</html>
注意事项
- 安全考量: 虽然此方法可以解决特定条件下的跨域问题,但在实施前需仔细考虑安全因素,确保不会无意间暴露敏感信息或引入安全漏洞。
- 适用范围: 仅限于同主域名下的子域名相互通讯,对于完全不同域名间的跨域问题无效。
- 现代替代方案:随着CORS(跨源资源共享)和WebSocket等技术的发展,对于跨域数据交换的需求,更多地倾向于使用这些现代标准,因为它们提供了更为灵活和安全的跨域通信机制。
7.Location.hash + iframe
在早期的Web开发中,为了解决跨域通信问题,开发者常采用location.hash + iframe
的技巧,这是一种较为原始且有限制的跨域通讯方法。这种方法通过URL的hash部分传递信息,利用不同页面间的iframe元素和同源策略的特性,实现在一定条件下的跨域数据交换。以下是该方法的具体实施步骤和示例代码的描述:
实现原理
- 借助iframe和hash值传递信息:不同源的页面间不能直接进行JavaScript通信,但可以通过iframe加载另一个页面,并利用URL的hash部分传递数据。因为改变iframe的src的hash部分不会引起页面刷新,且hash变化会触发onhashchange事件,这为跨域数据传输提供了可能。
- 中间人页面:在两个不同源的页面A和B之间,通常需要一个同源于A的中间页面C来完成闭环通信。C页面可以访问A页面的JavaScript上下文,从而实现数据的最终传递。
具体实现步骤:
a.html (位于 domain1.com)
- 创建一个隐藏的iframe,其src指向B域的b.html。
- 通过setTimeout设置延迟,改变iframe的src,附加hash值(如#user=admin),以此向B域的页面传递信息。
- 定义一个全局函数onCallback,供同源的C页面调用来回传数据。
b.html (位于 domain2.com)
- 同样包含一个隐藏的iframe,其src指向A域的c.html。
- 监听自身的onhashchange事件,一旦hash值发生变化(即接收到A域传来的信息),立即将此hash值附加到C页面的iframe src中,间接传递给C页面。
c.html (位于 domain1.com)
- 作为同源于A页面的中间人,监听自身的onhashchange事件。
- 解析接收到的hash值,通过window.parent.parent访问到A页面的上下文,并调用预先定义好的onCallback函数,将处理后的信息回传给A页面。
示例代码摘要:
a.html:
html
<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe');
setTimeout(function() {
iframe.src += '#user=admin';
}, 1000);
function onCallback(res) {
alert('Data from c.html ---> ' + res);
}
</script>
b.html:
html
<iframe id="iframe" src="http://www.domain1.com/c.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe');
window.onhashchange = function () {
iframe.src += location.hash;
};
</script>
c.html:
html
<script>
window.onhashchange = function () {
var res = 'hello: ' + location.hash.replace('#user=', '');
window.parent.parent.onCallback(res);
};
</script>
注意事项
- 此方法受限于同源策略,且通信效率较低,用户体验可能受影响。
- 现代Web开发中,更推荐使用CORS(跨源资源共享)、WebSockets或Fetch API等技术来处理跨域问题,它们提供更强大、灵活且安全的跨域通信能力 。
8.window.name + iframe跨域
利用 window.name 和 iframe 实现跨域通信是一种巧妙的技术手段,尤其适用于那些受到同源策略限制的场景。这种方法的核心在于利用了 window.name 属性的两个特性:一是其值在页面跳转时可以保持不变,即使跳转到完全不同域名的页面;二是它可以存储异常大量的数据(理论上可达2MB),这为跨域数据交换提供了便利。
a.html (domain1.com/a.html)
javascript
var proxy = function(url, callback) {
var state = 0;
var iframe = document.createElement('iframe');
iframe.src = url; // 设置iframe的src为跨域页面
iframe.onload = function() {
if (state === 1) {
// 第二次加载(同域proxy页面)完成,读取并处理数据
callback(iframe.contentWindow.name);
destroyFrame();
} else if (state === 0) {
// 第一次加载(跨域页面)成功,转向同域代理页面
iframe.contentWindow.location = 'http://www.domain1.com/proxy.html';
state = 1;
}
};
document.body.appendChild(iframe);
function destroyFrame() {
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);
}
// 请求跨域b页面的数据
proxy('http://www.domain2.com/b.html', function(data) {
alert(data); // 数据展示或进一步处理
});
};
proxy.html (domain1.com/proxy.html)
此页面仅作为中转站,确保跨域数据能通过同源策略传递回主页面。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Proxy Page</title>
</head>
<body>
<!-- 此页面无需任何额外代码,为了作为同源策略下的数据中转 -->
<!-- 跨域数据在window.name中已准备好,将被父页面通过iframe访问 -->
</body>
</html>
b.html (domain2.com/b.html)
html
<script>
window.name = 'This is domain2 data!'; // 跨域数据存储于window.name
</script>
- 工作原理 起始:a.html 使用 proxy 函数创建 iframe,指向跨域的 b.html。
- 数据载入:b.html 将数据写入 window.name。
- 回程代理:首次加载完毕后,iframe 的 src 被重定向到同域的 proxy.html,此时 window.name
的数据依然保留。 - 数据提取与处理:proxy.html 加载时(第二次 onload 触发),因同源关系,可以从 iframe 提取
window.name 中的数据并通过回调函数返回给 a.html。 - 资源清理:数据处理完毕后,iframe 被销毁,确保安全及资源管理。
安全考量
尽管此技术可规避浏览器的跨域访问限制,但实施时务必重视数据的安全性和隐私保护,确保跨域通信活动遵循网络安全最佳实践和法规要求。
9.WebSocket协议跨域
WebSocket协议是一种在HTML5中引入的通信协议,它允许浏览器和服务器之间建立全双工、低延迟的通信渠道,特别适用于实现实时交互和服务器推送技术。相较于传统的HTTP请求,WebSocket能够维持长时间的连接状态,且双向通信无需重复握手,提高了效率和实时性。此协议还支持跨域通信,打破了同源策略的限制,使得不同源的客户端与服务器能直接进行数据交换。
为了简化WebSocket的使用,通常会采用如Socket.io这样的库,它不仅对WebSocket API进行了高级封装,提供了更易于使用的接口,还对不兼容WebSocket的旧版浏览器提供了向下兼容的支持。
客户端(前端)代码示例
HTML部分包含一个文本输入框供用户输入数据,JavaScript部分则通过Socket.io与服务器建立WebSocket连接。
html
<!-- HTML部分 -->
<div>用户输入:<input type="text"></div>
<!-- 引入Socket.io库 -->
<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script>
<!-- JavaScript部分 -->
<script>
// 创建Socket.io实例并连接到服务器
var socket = io('http://www.domain2.com:8080');
// 监听连接成功的事件
socket.on('connect', function() {
// 监听来自服务器的消息
socket.on('message', function(msg) {
console.log('从服务器收到的数据: ---> ' + msg);
});
// 监听服务器断开连接的事件
socket.on('disconnect', function() {
console.log('服务器连接已关闭.');
});
});
// 当用户在输入框中失去焦点时,发送输入值到服务器
document.getElementsByTagName('input')[0].onblur = function() {
socket.send(this.value);
};
</script>
服务器端(Node.js)代码示例
使用Node.js和Socket.io创建一个简单的WebSocket服务器,监听8080端口,并处理客户端的连接与消息。
javascript
// 引入必要的模块
var http = require('http');
var socket = require('socket.io');
// 创建HTTP服务器
var server = http.createServer(function(req, res) {
res.writeHead(200, {'Content-type': 'text/html'});
res.end();
});
// 服务器监听8080端口
server.listen(8080);
console.log('服务器正在8080端口运行...');
// 使用Socket.io监听服务器上的WebSocket连接
socket.listen(server).on('connection', function(client) {
// 接收到客户端消息时的处理
client.on('message', function(msg) {
// 向客户端回复消息
client.send('你好:' + msg);
console.log('从客户端收到的数据: ---> ' + msg);
});
// 处理客户端断开连接
client.on('disconnect', function() {
console.log('客户端连接已关闭.');
});
});
以上示例展示了如何利用Socket.io在前端和后端之间快速搭建WebSocket通信,包括如何处理连接、消息收发和断开连接等核心功能。
5.正向代理与反向代理的区别
特性 | 正向代理 | 反向代理 |
---|---|---|
目的 | 允许客户端通过代理访问受限资源 | 提高服务端性能,负载均衡,隐藏后端服务器 |
设置方 | 客户端 | 服务器端 |
代理对象 | 客户端(隐藏客户端) | 服务器(隐藏服务器) |
透明性 | 需客户端配置,不透明 | 对客户端透明,无需客户端配置 |
配置需求 | 修改客户端网络设置(如浏览器) | 修改DNS指向代理服务器,客户端无感知 |
应用场景 | 访问控制、隐私保护、地域限制突破 | 负载均衡、SSL终止、安全防护、CDN |
示例 | 个人使用代理服务器浏览国外网站 | Nginx作为网站前端,分配请求到后端服务器 |
正向代理(Forward Proxy)
- 目的:帮助客户端访问受限资源。当客户端因网络策略、地理位置限制等原因无法直接访问目标服务器时,正向代理作为中介,接收客户端的请求,然后转发给目标服务器,并将服务器响应传回客户端。
- 设置方:由客户端负责配置代理服务器信息,可能涉及修改浏览器或其他客户端应用的网络设置。
- 作用:隐藏客户端的真实身份,对外展现的是代理服务器的IP地址。
- 配置需求:需要在客户端进行代理服务器的配置。
反向代理(Reverse Proxy)
- 目的:优化服务端架构,提高服务的可用性和安全性。反向代理服务器接收来自客户端的请求,根据预定义的规则决定将请求分配给后端的哪一个服务器处理,随后将服务器响应返回给客户端。
- 设置方:由服务器端部署和管理,对客户端透明。
- 作用:隐藏后端服务器的具体信息,提供统一的入口,实现负载均衡、SSL终止、缓存及安全防护等功能。
- DNS配置:通常通过修改DNS记录,使域名解析到反向代理服务器的IP地址,客户端无需知晓后端服务器的细节。
正向代理流程:👇正向代理流程描述了客户端通过配置的代理服务器(Proxy)向目标服务器(Target_Server)请求数据的过程。
发出请求 转发请求 响应数据 返回数据给客户端 Client Proxy Target_Server
反向代理流程:👇反向代理流程则展示了客户端请求通过反向代理服务器(Reverse_Proxy),该代理服务器根据策略选择合适的真实服务器(Real_Server)处理请求,并将响应返回给客户端的场景。
发出请求 智能路由到 处理并响应 返回响应给客户端 Client Reverse_Proxy Real_Server
核心差异
尽管正向代理和反向代理在结构上都表现为 client-proxy-server
,但关键区别在于代理服务器的部署位置和代理服务的目标:
- 部署位置:正向代理靠近客户端,由客户端配置使用;反向代理则部署在服务器端,对客户端透明。
- 目标:正向代理旨在隐藏客户端,帮助客户端访问资源;反向代理则是隐藏服务器端详情,提供额外的安全性、性能优化和负载均衡能力。
综上所述,正向代理和反向代理的主要区别在于代理服务的侧重点和部署策略,分别服务于客户端的需求隐藏和服务器端的架构优化及安全增强。
6.Nginx
Nginx概念及工作原理
Nginx 是一款轻量级的 Web 服务器软件,专为高效率和低资源消耗而设计。除了基本的网页服务功能,Nginx 还能作为反向代理服务器、负载均衡器以及实现HTTP缓存策略,广泛应用于构建高性能的现代网络架构。
核心特性
- 异步事件驱动模型:区别于传统服务器如Apache采用的进程或线程模型,Nginx运用了事件驱动的方式处理请求,这种机制使它能够以更少的资源处理更多的并发连接,显著提升了处理能力与响应速度。
架构层次
Master Process(主进程)
- 管理与控制 :Nginx架构的顶级元素是
master process
,负责加载配置、监控状态以及维护工作进程的生命周期,但不直接参与请求处理。
Worker Processes(工作进程)
- 并发处理核心 :由主进程创建的
worker processes
承担了实际的请求处理工作。得益于事件驱动设计,每个worker进程能够同时处理大量HTTP请求,无需为每个请求分配单独的线程或进程,这是Nginx在性能上超越诸如Apache(后者基于每个连接/请求分配独立进程的模型)的关键所在。
工作流程
- 请求接收:客户端发起HTTP请求至Nginx服务器。
- 请求分发:Nginx可根据配置执行反向代理或负载均衡功能,将请求智能路由到后端服务器。
- 高效处理:利用epoll(Linux环境下)等I/O多路复用技术,工作进程异步非阻塞地监听和响应事件,即使面对文件I/O或后端响应等待,也能继续处理其他请求。
- 响应与缓存:处理完成后,将响应数据返回客户端;对于静态资源,Nginx可实施缓存策略加速后续相同请求的响应。
综上所述,Nginx凭借其独特的事件驱动架构和高度优化的工作进程模型,在处理高并发场景时展现出卓越的性能,成为众多大型网站和服务的首选基础架构组件。