服务器代理-负载均衡

例如现在有两台服务器(server3000server7000)为用户提供服务,如果没有负载均衡就有可能出现95%的用户都去访问server3000,而只有5%的用户访问server7000。那样不就出现server3000快被压死了,而server7000工作负荷完全不满的情况吗。我们当然希望将用户的访问均衡的分配到这两台服务器上,那样对我们的系统是最有利的,这就是负载均衡最大的意义。

这两台服务器上分别部署了相同的前端静态文件(index.html index.js)【咱学的服务端都是用node去做的服务端【部署静态文件就是把前端写好的静态页面放到plugin目录里放(也就是往静态资源目录里放)】】

为什么要放在两台服务器:
为了分担服务器压力,一般用户量特别大的时候都会分多台服务器,加入了更多的服务器压力肯定就小了这是毋庸置疑的。
最终实现服务器的这个服务中间的细节问题我们得考虑,接下来回去模拟出多台服务器的环境来:
在同一台机器上可以通过端口不一样来区分服务:
在这里插入图片描述

在这里插入图片描述

npm init
npm i express -S

给两个端口都设置静态资源目录(public):
在这里插入图片描述
假设在public里面有index.html文件,这两个html文件内容都相同,访问它们的域名是不同的:
在这里插入图片描述

现在可以去浏览器访问:
在这里插入图片描述
server3000

const express = require('express')
const app = express();
const path = require('path')
app.use(express.static(path.join(__dirname, './public')));

app.listen(3000, () => {
    
    
    console.log(3000)
})

server7000

const express = require('express')
const app = express();
const path=require('path')
app.use(express.static(path.join(__dirname,'./public')));

app.listen(7000, () => {
    
    
    console.log(7000)
})

现在就面临着一个问题,就是这个项目要部署在两台服务器上,但是我希望它通过一个域名访问,就是我访问一个地址但是这两台服务器都能访问,只要一个地址两个都能访问

思路:现在为了减轻目标服务器的压力已经将分流分在两台服务器上,这个时候要再起一台服务器,就不能叫目标服务器了它叫代理服务器。(服务器代理,反向代理)这两个服务器都是目标服务器,资源真正存在它两个身上。

代理服务器,它里面不部署静态资源,它的作用是接收用户请求根据请求转发到服务器,也就是用户的请求全发给代理服务器(这样的话域名(地址)就统一了),访问代理服务器最终是想要看到3000或7000里面的文件,由代理服务器里面写个逻辑自动的将3000或7000里面内容拿回来,这就解决了两台服务器访问域名统一的问题。

代理服务器还得考虑是从3000取还是从7000取;
将代理服务器启动:
在这里插入图片描述

浏览器向服务器发请求:各种资源的urlajxsscript里的src、表单、jsonPlink标签hrfa标签hrf等;
服务器向服务器发请求:node端用的是使用http模块提供的方法get方法和requset,还有axios:
在这里插入图片描述
axios这个库它封装的时候里面既包含了ajxs也包含了node端的请求,所以直接用ajxs也能发请求
在这里插入图片描述
express有个中间件express-http-proxy,它的作用就是把当前请求转发到服务器;
express-http-proxy使用方法

npm i express-http-proxy -S

在这里插入图片描述
浏览器运行server9000,作为用户肯定不知道当前浏览器被代理了,比如去访问其它的网站,它背后有几层代理,用户肯定不知道,这叫反向代理,你不知道背后它代理了。
在这里插入图片描述
接下来要实现,如何均衡负载不能全放在一个代理上,要雨露均沾;
在这里插入图片描述

server9000>index.js

const express = require('express')
const app = express();
const proxy=require('express-http-proxy')

// 请求转发-目标-3000 / 7000

// proxy(host,options) 接受两个参数
// 第一个是域名就是真正要转发到那个地址
// 第二个是个配置项
// / 代表所有的请求 也可以写abc 那样就是以abc开头的


// 1、127.0.0.1是回送地址,指本地机,一般用来测试使用。
// 2、回送地址(127.x.x.x)是本机回送地址(LoopbackAddress),
// 即主机IP堆栈内部的IP地址,主要用于网络软件测试以及本地机进程间通信,
// 无论什么程序,一旦使用回送地址发送数据,协议软件立即返回,
// 不进行任何网络传输。
app.use('/',proxy('127.0.0.1:3000'))
app.use('/', proxy('127.0.0.1:7000'))

app.listen(9000, () => {
    
    
    console.log(9000)
})

所有请求过来时都向我们定义的那个服务器走:

发一个请求都有:请求头,请求体,请求地址路径,请求方法(get/post);
拿到请求。

server9000>index.js

const express = require('express')
const app = express();
const proxy = require('express-http-proxy')
const url = require('url')
// const axios = require('axios')
let num = 0; // 记录请求的次数

app.use(express.json()); // 处理的是post请求的json格式数据
app.use(express.urlencoded()); // 处理的post请求的 序列化格式数据  key=value&key=value
app.use((req, res) => {
    
    
    num += 1;
    // 得到用户请求的请求路径,请求方法,请求头,请求体
    const {
    
     pathname } = url.parse(req.url);//请求路径
    const method = req.method;//请求方法
    const headers = req.headers;//请求头
    const body = req.body;//请求体 body是针对post请求说的
    const query = req.query;//拿到地址栏 get请求参数是在地址栏传的 
    // 去看看是否能拿到请求的东西
    console.log(pathname, method, headers, body, query)
    res.send('9000')
 
})

app.listen(9000, () => {
    
    
    console.log(9000)
})

访问9000:

node index.js

在这里插入图片描述

在这里插入图片描述
去看看是否能拿到请求的东西:
在这里插入图片描述

拿到请求的东西后像目标服务器发起请求(用axios):

npm i axios -S
const express = require('express')
const app = express();
const proxy = require('express-http-proxy')

const url = require('url')
const axios = require('axios')
// let num = 0; // 记录请求的次数
// let hosts = ['http://127.0.0.1:7000', 'http://127.0.0.1:3000'];

// 请求转发-目标-3000 / 7000

// proxy(host,options) 接受两个参数
// 第一个是域名就是真正要转发到那个地址
// 第二个是个配置项
// / 代表所有的请求 也可以写abc 那样就是以abc开头的


// 1、127.0.0.1是回送地址,指本地机,一般用来测试使用。
// 2、回送地址(127.x.x.x)是本机回送地址(LoopbackAddress),
// 即主机IP堆栈内部的IP地址,主要用于网络软件测试以及本地机进程间通信,
// 无论什么程序,一旦使用回送地址发送数据,协议软件立即返回,
// 不进行任何网络传输。
// express-http-proxy
// app.use('/',proxy('127.0.0.1:3000'))
// app.use('/', proxy('127.0.0.1:7000'))


app.use(express.json()); // 处理的是post请求的json格式数据
app.use(express.urlencoded()); // 处理的post请求的 序列化格式数据  key=value&key=value
app.use((req, res) => {
    
    
    // num += 1;
    // 得到用户请求的请求路径,请求方法,请求头,请求体
    const {
    
     pathname } = url.parse(req.url);//请求路径
    const method = req.method;//请求方法
    const headers = req.headers;//请求头
    const body = req.body;//请求体 body是针对post请求说的
    const query = req.query;//拿到地址栏 get请求参数是在地址栏传的 
    // 去看看是否能拿到请求的东西
    // console.log(pathname, method, headers, body, query)

    axios({
    
    
        url: `http://localhost:3000${
      
      pathname}`,//需要拼个域名就是绝对路径
        method,
        headers,
        params: query,
        data: body,
    }).then(data => {
    
    
        console.log(data);//data就是通过向目标3000请求到的东西
    })

    res.send('9000')
    //  拿到请求的东西后像目标服务器发起请求(用axios):



})

app.listen(9000, () => {
    
    
    console.log(9000)
})

在这里插入图片描述
看:data这字段是需要的数据
在这里插入图片描述
在服务器拿到东西后把拿到的东西给它响应到浏览器端(data就是响应的内容,还需要个响应头响应状态):
响应头,发送给浏览器
在这里插入图片描述
9000服务器从3000把东西拿过来之后,获取响应的内容,响应体,响应头,状态码,状态文本;
status 状态码
statusText 状态文本

server9000>index.js

const express = require('express')
const app = express();
const proxy = require('express-http-proxy')

const url = require('url')
const axios = require('axios');
let num = 0; // 记录请求的次数 每次请求都有个用户 建议不要设成固定number类型


// 请求转发-目标-3000 / 7000

// proxy(host,options) 接受两个参数
// 第一个是域名就是真正要转发到那个地址
// 第二个是个配置项
// / 代表所有的请求 也可以写abc 那样就是以abc开头的


// 1、127.0.0.1是回送地址,指本地机,一般用来测试使用。
// 2、回送地址(127.x.x.x)是本机回送地址(LoopbackAddress),
// 即主机IP堆栈内部的IP地址,主要用于网络软件测试以及本地机进程间通信,
// 无论什么程序,一旦使用回送地址发送数据,协议软件立即返回,
// 不进行任何网络传输。
// express-http-proxy
// app.use('/',proxy('127.0.0.1:3000'))
// app.use('/', proxy('127.0.0.1:7000'))

app.use(express.json()); // 处理的是post请求的json格式数据
app.use(express.urlencoded()); // 处理的post请求的 序列化格式数据  key=value&key=value
app.use(async (req, res) => {
    
    
    // 每次代理请求都要走这个地方 设置num
    num += 1;
    //console.log('123',url);
    // 得到用户请求的请求路径,请求方法,请求头,请求体
    const {
    
     pathname } = url.parse(req.url);//请求路径
    console.log(pathname)
    const method = req.method;//请求方法
    const headers1 = req.headers;//请求头
    const body = req.body;//请求体 body是针对post请求说的
    const query = req.query;//拿到地址栏 get请求参数是在地址栏传的 
    // 去看看是否能拿到请求的东西
    // console.log(pathname, method, headers, body, query)
    if(pathname .includes( '/favicon.ico')){
    
    
        return
    }

    let host = '';
    if (num % 2 === 0) {
    
    
        host = 'http://127.0.0.1:7000'
    } else {
    
    
        host = 'http://127.0.0.1:3000'

    }

    //  拿到请求的东西后像目标服务器发起请求(用axios):
   let response =  await axios({
    
    
        url: `${
      
      host}${
      
      pathname}`,//需要拼个域名就是绝对路径
        method,
        headers:headers1,
        params: query,
        data: body,
    })

     //console.log('59',response);//data就是通过向目标3000请求到的东西
     // 9000服务器从3000把东西拿过来之后,
     // 获取响应的内容,响应体,响应头,状态码,状态文本;
     // status 状态码
     // statusText 状态文本
    const {
    
     status, statusText, headers, data} = response;
    console.log(status, statusText, headers, data);

    res.set(headers)//设置响应头
    res.send(data);//发送文本
})

app.listen(9000, () => {
    
    
    console.log(9000)
})

浏览器运行,在访问代理服务器9000时,成功发送请求访问3000/7000,负载均衡:
在这里插入图片描述
在这里插入图片描述

总结

举个栗子:
有两个人分别是 甲和乙,甲身材矮小,乙身高马大,乙做的很多事情让甲不痛快,但是碍于打不过乙,只能忍耐。有一天乙做了一件事情实在惹怒了甲,于是,甲花钱请了一个打手,打了乙一顿。在这个过程中真正要打乙的是甲。但是乙不知道。打手在这个过程中充当了一个很重要的角色就是我们所说的代理,也可以说是正向代理。

正向代理:正向代理隐藏的是发起请求的一端,也就是客户端。

反向代理反向代理隐藏的处理请求的一端,也就是服务端。

正向代理隐藏真实的客户端,反向代理隐藏真实的服务器端。

实际上负载均衡就是反向代理服务器,但是它反向代理的目标节点有多个。

  • 请求时把相关的逻辑都拿到
  • 以服务端为基础想目标服务器发送请求
  • 发完请求后在响应过来

真正的代理是两台物理机

负载均衡,就是负责对流量进行分担,以便减少单台设备由于流量过大而形成DDoS(DDOS全名是Distributed Denial of service (分布式拒绝服务),俗称洪水攻击。)

将客户端的请求按照一定的规则分配到一群服务器上,并将处理结果返回给相应的客户端,避免其中某台服务器过载。

使用代理服务器,可以将请求转发给内部的服务器,使用这种加速模式显然可以提升静态网页的访问速度。

猜你喜欢

转载自blog.csdn.net/Menqq/article/details/114988220
今日推荐