专栏首页好好学java的技术栈Nginx 反向代理,这篇文章告诉你!

Nginx 反向代理,这篇文章告诉你!

重磅资讯、干货,第一时间送达今日推荐:请停止学习框架个人原创+1博客:点击前往,查看更多

来源:圈圈的圈 juejin.im/post/5c0e6d606fb9a049f66bf246

代理是个啥

既然要聊反向代理, 那首先得知道代理是个啥吧? 嗯.

正向代理

比如, 你买束花, 想要给隔壁工位的测试妹子小丽表白. 但是又怕被人家直面拒绝太没面子. 于是你把鲜花委托给平时和小丽一起的测试小伙伴小红. 让她帮忙把花送给小丽. 这就是一个简单的代理过程, 小红作为代理帮你把花送给了小丽, 当然这种情况在现实中并不推荐使用, 因为难以避免中间商赚差价 ?

在上面的例子中, 你作为客户端(请求方), 想要向服务方(小丽)发起请求. 但是碍于面子你主动找到了第三方(小红)作为代理向服务方发送请求, 这种情况就是常说的正向代理. 正向代理在互联网中的使用主要是访问外国网站, 你想访问谷歌但是碍于防火墙你只能通过V**服务器作为代理才能访问. 这个时候一般也要找值得信赖的V**厂商, 避免中间商赚差价 ?.

反向代理

关于反向代理的例子, 那就比较多啦. 比如, 孤独的你躺在床上夜不能寐. 于是乎, 拿出手机, 点亮了屏幕, 拨通 10086, 中国移动就会随机分配一个当前处于空闲的客服MM, 你可以和客服MM聊聊天, 问问她家住哪里, 有没有男朋友, 她的微信号, 她的手机号, 星座, 八字.......

在这个例子中, 中国移动就充当了反向代理的角色. 你只需要拨打 10086. 至于会不会分配到 MM 会分配到哪个 MM 在接通之前你都是不知道的. 反向代理在互联网中的使用主要是实现负载均衡. 当你访问某个网站的时候, 反向代理服务器会从当前网站的所有服务器中选择一个空闲的服务器为你响应. 用于均衡每台服务器的负载率.

修改 hosts 完成域名绑定

mac 用户直接执行 vim /private/etc/hosts 在 hosts 文件最后添加一行:

127.0.0.1 a.com

这一句是什么意思呢? 就是告诉我们的电脑访问 a.com 的时候, 无需请求 DNS, 直接指向我们本机.

ps: win 环境下, hosts 文件在 C:WindowsSystem32driversetc 文件夹下. 如果没有权限修改, 把 hosts 文件先拷贝到别的位置, 通过编辑器打开并添加最后一行内容以后再剪切到原来的位置替换即可.

验证: 打开命令行窗口执行 ping a.com, 如果访问的 ip 为 127.0.0.1 说明我们的域名绑定就完成啦 ^_^

安装 nginx

要做 NGINX 反向代理, 肯定要安装 nginx, 本文安装步骤示例环境为 mac, win 的小伙伴, 可以百度一下嗷, 这个东西大同小异.

  • 安装 brew 命令, 执行 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  • 安装 nginx, 执行 brew install nginx
  • 启动 nginx nginx, 如果报没有权限, 执行 sudo nginx

nginx 启动后, 浏览器打开 localhost:8080, 即可验证. 出现以下界面说明安装成功.

nginx 配置初探

配置完 hosts 域名已经能够成功绑定. 现在如果我们访问 a.com 实际上是会访问到我们的自己的电脑辣. 那还不抓紧试一下?

浏览器访问 a.com

这是什么鬼????

为什么会 无法访问此网站 呢? 我们下载安装完 nginx 还没有做任何配置. 接下来, 我们稍微配置一下就 OK:

  • 命令行切换到 nginx 配置目录下 cd /usr/local/etc/nginx/servers
  • 创建并编辑配置文件 vim test.conf, 在配置文件中粘贴以下内容

server {      # 监听80端口号      listen 80;
      # 监听访问的域名      server_name a.com;
      # 根据访问路径配置      location / {          # 把请求转发到 https://www.baidu.com          proxy_pass https://www.baidu.com;      }  }

  • 保存文件, 并执行 nginx -s reload 重启 nginx.
  • 回到浏览器, 打开 a.com 的页签, 强制刷新.

恭喜你已经完成了第一个 nginx 配置.

创建跨域环境

通过一系列的折腾, 我们已经可以通过 nginx 将a.com 转发到百度. 完成了第一步, 接下来我们创建跨域的 Case 并一步一步通过 nginx 配置实现跨域.

首先, 项目前后端添加 nginx 目录, 用户存放前后端代码. 代码结构如下图所示.

其次编写前后端代码:

前端代码(./fe/nginx/index.html):

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <meta http-equiv="X-UA-Compatible" content="ie=edge">    <title>CORS 实现跨域</title></head><body>    <h3>CORS 实现跨域</h3>
    <script>        var xhr = new XMLHttpRequest()        xhr.open('GET', 'http://localhost:8888/api/getFriend')        xhr.setRequestHeader('token', 'quanquanbunengshuo')        xhr.withCredentials = true;        xhr.onreadystatechange = function() {            if(xhr.readyState === 4 && xhr.status === 200) {                console.log(xhr.responseText)                console.log(xhr.getAllResponseHeaders())            }        }        xhr.send()    </script></body></html>

编写完前端代码以后, 启动前端 web 容器. live-server ./fe/nginx

命令行中出现了黄色警告, 通知我们 8080 端口已经被占用, 这又是为什么呢? 大家请思考一哈.

我们重新指定一个端口live-server ./fe/nginx --port=9999 哈哈, 换一个指令, 依旧是那么顺畅. ^_^

后端代码:

const http = require('http');
const PORT = 8888;
// 创建一个 http 服务const server = http.createServer((request, response) => {  console.log(request.headers)  response.end("{name: 'quanquan', friend: 'guiling'}");});
// 启动服务, 监听端口server.listen(PORT, () => {  console.log('服务启动成功, 正在监听: ', PORT);});

启动后端服务 node ./be/nginx/index.js

完善 nginx 配置

前后端代码已经准备完成, 这一步我们就来点干货. 完成最后的配置.

  • 首先, 修改 nginx 配置, 把百度地址替换成本地的前端地址

server {      # 监听80端口号      listen 80;
      # 监听访问的域名      server_name a.com;
      # 根据访问路径配置      location / {          # 把请求转发到 http://127.0.0.1:9999          proxy_pass http://127.0.0.1:9999;      }  }

  • 修改完成 nginx 配置文件以后, 切记执行 nginx -s -reload 重启 nginx.
  • 访问a.com

熟悉的报错又出现了...

  • 修改前端项目中的接口地址

// 接口地址修改为当前域名下 /api 路劲下的 getFriend    xhr.open('GET', '/api/getFriend')

  • 修改 nginx 配置文件

server {        # 监听80端口号        listen 80;
        # 监听访问的域名        server_name a.com;
        # 根据访问路径配置        location / {            # 把请求转发到 http://127.0.0.1:9999            proxy_pass http://127.0.0.1:9999;        }
        # 监听根目录下的 /api 路径        location /api/ {            # 把请求转发到 http://127.0.0.1:8888            proxy_pass http://127.0.0.1:8888;        }    }

新加的对于 api 路径的监听的意思就是把关于后端 api 的请求转发到后端项目上(哈哈, 当然这就是为啥好多后端接口都是要有 /api 开头的啦). 重启 nginx 以后, 再次刷新浏览器, 后端返回的结果已经成功的打印到了控制台, 本次跨域访问任务完成.

细心的小伙伴肯定发现了, 控制台还有一个报错. 这个是因为我们的项目中用到了 live-server 这个工具需要 websocket 导致的. 我们可以通过添加以下配置解决.

proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";

报错消失 ?, 此时完整的 nginx 配置文件为

server {    # 监听80端口号    listen 80;
    # 监听访问的域名    server_name a.com;
    # 根据访问路径配置    location / {        # 把请求转发到 http://127.0.0.1:9999        proxy_pass http://127.0.0.1:9999;
        # 兼容websocket        proxy_http_version 1.1;        proxy_set_header Upgrade $http_upgrade;        proxy_set_header Connection "upgrade";    }
    # 监听根目录下的 /api 路径    location /api/ {        # 把请求转发到 http://127.0.0.1:8888        proxy_pass http://localhost:8888;    }}

前后端代码地址为:https://github.com/luoquanquan/cross-domain/commit/f38f56689fdac1526244ecadaa979a52c9c4a7ea

总结

至此, 我们已经通过 nginx 反向代理的方式实现了跨域访问 api, 在系列文章第一篇( https://juejin.im/post/5c07fa04e51d451de968906b )对于跨域的解释为: 跨域源于同源策略, 是浏览器保证用户安全的行为. 我们使用的 nginx 反向代理实际上是对浏览器的一种 "哄骗", 让它认为自己访问到的是同域的 api. 实际上是在服务端做了个调包, 这个道理就如同你拨打 10086 你就认定了给你分配到的一定是中国移动的客服MM(客服GG也是有可能出现的 ?)而中国移动的客服MM就是一个很安全的聊天对象, 没有必要再进行限制..

更多Java技术文章,尽在【好好学java】网站。 网址:www.java1000.com ,搜索 好好学java 阅读原文 可达!

推荐➷➷➷好好学java的兄弟号,欢迎关注,不一样的风采!Coding这件小事点个“在看”再走吧,谢谢?

本文分享自微信公众号 - 好好学java(SIHAIloveJAVA)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 超详细的Nginx简易教程,一学就会!

    Nginx (engine x) 是一款轻量级的Web 服务器 、反向代理服务器及电子邮件(IMAP/POP3)代理服务器。本文的作者为「静默虚空」 ,可点击文...

    好好学java
  • 面试官出的 MySQL 索引的问题,这篇文章全给你解决!

    这篇文章会讲解索引的基础知识,但主要是关于MySQL数据库的B+树索引的相关原理,里面的一些知识都参考了MySQL技术内幕这本书,也算对于这些知识的总结。对于B...

    好好学java
  • SpringCloud之SSO 单点登录(附源码)

    2、在run方法里实现过滤规则:cookie有令牌accessToken且作为key存在于Redis,或者访问的是登录页面、登录请求则放行

    好好学java
  • Ubuntu 17.04 编译安装 Nginx 1.9.9

    Ubuntu 17.04 编译安装 Nginx 1.9.9 安装 安装依赖 $ apt-get update $ apt-get install build-e...

    搜云库
  • CentOs7.3 编译安装 Nginx 1.9.9

    CentOs7.3 编译安装 Nginx 1.9.9 安装 安装依赖 $ yum install -y gcc gcc-c++ autoconf automa...

    搜云库
  • 亿级流量场景下,大型缓存架构设计实现【2】

    缓存数据生产服务那一层已经搞定了,相当于三层缓存架构中的本地堆缓存+redis分布式缓存都搞定了

    小勇DW3
  • Nginx控制语句与虚拟机配置

    这里就不讲解如何安装Nginx服务了,我这里使用的是lnmp一键安装包。直接网上百度一个即可使用。今天主要讲解一个如何使用基本控制语句与虚拟配置。

    卡二条的技术圈子
  • 原来,创业者们是这样看「小程序创业」的... | 未来小程序

    知晓君
  • 极品三数字域名频繁被交易,价格稳定七位数

    不到一个月的时间,三数字域名交易的消息频繁传来:396.com、627.com、536.com等,近日又有一个三数字域名传来交易的消息:域名935...

    躲在树上的域小名
  • 微信春晚摇一摇项目经验总结(产品篇)

    编者按:关于微信红包的台前幕后,产品与技术,广大大讲堂er 们都比较关注。今天跟大家分享一篇来自产品之镜公众号的文章,方便大家学习。 [关键词一:用产品说话] ...

    腾讯大讲堂

扫码关注云+社区

领取腾讯云代金券