手动实现代理服务器(仿nginx)

网友投稿 1235 2022-10-17

手动实现代理服务器(仿nginx)

手动实现代理服务器(仿nginx)

前言

经常使用nginx来做web服务器,你对它了解有多少,这篇文章将带领你简单的触碰它。

代理服务器

代理服务器都是存在Client(客户端)与Server(服务端)之间,但是性质不同,所以为了两种。

正向代理服务器(客户端)反向代理服务器(服务端)

正向代理服务器

写前端的小伙伴就会触碰到,后端xxx不会弄跨域只能用代理解决,哈哈哈。

直接偷图,正向代理就是直接在客户端进行代理,服务器不知道实际发送请求的客户端

反向代理服务器

也是偷图,反向代理就是直接在服务器进行代理,客户端不知道实际提供服务的服务器

好了,也介绍完了,我们实现的代理服务器就是反向代理。

轮询

轮询是一种CPU决策如何提供周边设备服务的方式,又称《程控输入输出》

普通轮询

将请求依次发给服务器,周而复始

加权轮询

主要解决:效率偏低,无法满足服务器配置不同的情况

例子: 现在有三台服务器,A=5、B=3、C=1,数字代表权重。将三台服务器权重值相加值为9,也就是说每9个请求会分给 5个给A、3个给B、1个给C,依次循环 AAAAABBBC .....

代码实现

/*** * 加权轮询 */let server = []function init() { let A = { ip: '211.xxx.xxx.xxx', weight: 5 } let B = { ip: '192.xxx.xxx.xxx', weight: 3 } let C = { ip: '166.xxx.xxx.xxx', weight: 1 } server.push(A) server.push(B) server.push(C) // console.log(server)}function getServer(requestId) { // 计算总权重 total = 0 for(let i = 0; i < server.length; i++) { let itemI = server[i] total += itemI.weight } // console.log(`总权重是 ${total}`) // 第几次请求 % 权重总数 + 1 = (2 % 9) + 1 = 2 + 1 = 3 // +1是因为怕余数等于0 let s = requestId % total + 1 // console.log(s) // 计算返回结果 for(let n = 0; n < server.length; n++) { let itemN = server[n] if (s <= itemN.weight) { return itemN } s = s - itemN.weight } return null}function run() { // 模拟请求 for(let i=1; i <= 9; i++) { let item = getServer(i) console.log(`当前访问的服务器ip是 ${item.ip}`) }}init()run()/**当前访问的服务器ip是 211.xxx.xxx.xxx当前访问的服务器ip是 211.xxx.xxx.xxx当前访问的服务器ip是 211.xxx.xxx.xxx当前访问的服务器ip是 211.xxx.xxx.xxx当前访问的服务器ip是 192.xxx.xxx.xxx当前访问的服务器ip是 192.xxx.xxx.xxx当前访问的服务器ip是 192.xxx.xxx.xxx当前访问的服务器ip是 166.xxx.xxx.xxx当前访问的服务器ip是 211.xxx.xxx.xxx * */

那这样是不是也会有问题呢,这样是不是会导致权重高的服务器会一直被请求呢,一系列问题,所以就出现了 平滑加权轮询

平滑加权轮询

主要解决加权轮询的问题(短时间内权重大的服务器得到过多的请求数,不是一种均匀的分配方式)

例子:现在有三台服务器,A=5、B=3、C=1,数字代表权重。将三台服务器权重值相加值为9,也就是说每9个请求会分给 5个给A、3个给B、1个给C,依次循环 ABCABABAA....

代码实现

/** * 平滑加权轮询 */let server = []function init() { let A = { ip: '211.xxx.xxx.xxx', weight: 5, dynamicWeight: 0 } let B = { ip: '192.xxx.xxx.xxx', weight: 3, dynamicWeight: 0 } let C = { ip: '166.xxx.xxx.xxx', weight: 1, dynamicWeight: 0 } server.push(A) server.push(B) server.push(C) // console.log(server)}function getServer() { // 计算总权重 total = 0 for(let i = 0; i < server.length; i++) { let itemI = server[i] total += itemI.weight } // console.log(`总权重是 ${total}`) // 给每台服务器加上动态权重 = 动态权重 + 权重 for(let a = 0; a < server.length; a++) { let itemA = server[a] itemA.dynamicWeight = itemA.dynamicWeight + itemA.weight } // 选出动态权重最大的服务器 let maxServerItem = server[0] for(let b = 0; b < server.length; b++) { let itemB = server[b] if (maxServerItem.dynamicWeight < itemB.dynamicWeight) { maxServerItem = itemB } } // 选中的动态权重最大的服务器的动态权重 - 总权重 maxServerItem.dynamicWeight = maxServerItem.dynamicWeight - total // console.log(server) return maxServerItem}function run() { // 模拟请求 for(let i=1; i <= 9; i++) { let item = getServer() console.log(`当前访问的服务器ip是 ${item.ip}`) }}init()run()/**当前访问的服务器ip是 211.xxx.xxx.xxx当前访问的服务器ip是 192.xxx.xxx.xxx当前访问的服务器ip是 211.xxx.xxx.xxx当前访问的服务器ip是 166.xxx.xxx.xxx当前访问的服务器ip是 211.xxx.xxx.xxx当前访问的服务器ip是 192.xxx.xxx.xxx当前访问的服务器ip是 211.xxx.xxx.xxx当前访问的服务器ip是 192.xxx.xxx.xxx当前访问的服务器ip是 211.xxx.xxx.xxx * */

那我们轮询算法就完毕了,开始手动实现一个,不过实现的话 啥语言都可以实现但是性能差距肯定是不一样的,所以我们使用了go语言实现

实现功能

效果如下

文件结构

└─src │ go.mod │ go.sum │ main.go 代理服务器 │ ├─config │ env 配置目录 │ init.go 解析配置目录 │ ├─util │ 检查当前服务器状态 │ loadBalance.go 实现轮询的几种方式 │ └─web web1.go web2.go web3.go

​​项目地址​​

总结

我们介绍了代理服务器,也介绍了轮询并实现了几种轮询的方式,然后使用了go语言写了一个小案例。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Netty分布式pipeline传播inbound事件源码分析
下一篇:go-sqlite-lite是Go编程语言的SQLite驱动程序
相关文章

 发表评论

暂时没有评论,来抢沙发吧~