现在基本上都是采用前后端分离的方式开发,跨域问题是我们最常遇到的问题之一。

什么是跨域?

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。

当一个请求url的协议、域名(主域名、子域名)、端口三个之中任一个与页面的url不同,即可认为是跨域。

解决跨域的方法有很多,这里就不一一的举例了,其中有两种常见的解决跨域的方式,nginx 代理和 http-proxy ,这两种方式的原理都差不多,都是将不同端口的内容转发到同一个端口下。这篇文章的主题就是这两种方式谁的效率更高。

如何使用

nginx 基本使用

  1. 下载 http://nginx.org
  2. 解压
  3. 关键配置【/conf/nginx.conf】
    将本地的前端项目放在3013端口下,并将本地的3006端口也放到3013端口下。
server {listen 3013;  server_name localhost;  location / {root   /project/web;index  index.html index.htm   index.php;try_files $uri $uri/ /index.html;     }location /api {proxy_pass http://127.0.0.1:3006;}}
  1. 启动
nginx start

http-proxy

1. 安装

npm install http-proxy --save

2. 配置

http-proxy.js

const http = require('http');const httpProxy = require('http-proxy');//创建一个代理服务const proxy = httpProxy.createProxyServer();//创建http服务器并监听4000端口let server = http.createServer(function (req, res) {//将用户的请求转发到本地3000端口上    proxy.web(req, res, {target: 'http://localhost:3000'    });//监听代理服务错误    proxy.on('error', function (err) {console.log(err);    });});server.listen(4000, '0.0.0.0');

3. 启动

node ./http-proxy.js

性能测试

测试工具

ab,即Apache Benchmark,是一种用于测试Apache超文本传输协议(HTTP)服务器的工具。

ab命令会创建很多的并发访问线程,模拟多个访问者同时对某一URL地址进行访问。它的测试目标是基于URL的,因此,既可以用来测试Apache的负载压力,也可以测试nginx、lighthttp、tomcat、IIS等其它Web服务器的压力。

ab命令对发出负载的计算机要求很低,既不会占用很高CPU,也不会占用很多内存,但却会给目标服务器造成巨大的负载,其原理类似CC攻击。自己测试使用也须注意,否则一次上太多的负载,可能造成目标服务器因资源耗完,严重时甚至导致死机。

安装

yum -y install httpd-tools

测试方法

ab [options] [http[s]://]hostname[:port]/path

options:

-n requests    #执行的请求数,即一共发起多少请求。-c concurrency    #请求并发数。-t timelimit    #测试所进行的最大秒数。其内部隐含值是-n 50000,它可以使对服务器的测试限制在一个固定的总时间以内。默认时,没有时间限制。-s timeout    #指定每个请求的超时时间,默认是30秒。-b windowsize    #指定tcp窗口的大小,单位是字节。-B address    #指定在发起连接时绑定的ip地址是什么。-p postfile    #指定要POST的文件,同时要设置-T参数。-u putfile    #指定要PUT的文件,同时要设置-T参数。-T content-type    #指定使用POST或PUT上传文本时的文本类型,默认是'text/plain'。-v verbosity    #设置详细模式等级。-w    #将结果输出到html的表中。-i    #使用HEAD方式代替GET发起请求。-y attributes    #以表格方式输出时,设置html表格tr属性。-z attributes    #以表格方式输出时,设置html表格th或td属性。-C attribute    #添加cookie,比如'Apache=1234'。(可重复)-H attribute    #为请求追加一个额外的头部,比如'Accept-Encoding: gzip'。(可重复)-A attribute    #对服务器提供BASIC认证信任。用户名和密码由一个:隔开,并以base64编码形式发送。无论服务器是否需要(即,是否发送了401认证需求代码),此字符串都会被发送。-P attribute    #对一个中转代理提供BASIC认证信任。用户名和密码由一个:隔开,并以base64编码形式发送。无论服务器是否需要(即, 是否发送了401认证需求代码),此字符串都会被发送。-X proxy:port   #指定代理服务器的IP和端口。-V              #打印版本信息。-k              #启用HTTP KeepAlive功能,即在一个HTTP会话中执行多个请求。默认时,不启用KeepAlive功能。-d              #不显示"percentage served within XX [ms] table"的消息(为以前的版本提供支持)。-q              #如果处理的请求数大于150,ab每处理大约10%或者100个请求时,会在stderr输出一个进度计数。此-q标记可以抑制这些信息。-g filename     #把所有测试结果写入一个'gnuplot'或者TSV(以Tab分隔的)文件。此文件可以方便地导入到Gnuplot,IDL,Mathematica,Igor甚至Excel中。其中的第一行为标题。-e filename     #产生一个以逗号分隔的(CSV)文件,其中包含了处理每个相应百分比的请求所需要(从1%到100%)的相应百分比的(以微妙为单位)时间。由于这种格式已经“二进制化”,所以比'gnuplot'格式更有用。-r              #当收到错误时不要退出。-h              #输出帮助信息-Z ciphersuite  指定SSL/TLS密码套件-f protocol     指定SSL/TLS协议(SSL3, TLS1, TLS1.1, TLS1.2 or ALL)
ab -n 50 -c 10 http://www.dengzhanyong.com:3013/proxyTest

    上述语句表示总共向http://www.dengzhanyong.com:3013/proxyTest发送50次请求,并发量为10

测试

为了更好的对比两种方式的性能,分别使用两种方式代理一个相同的请求。后端接口的端口为3006,使用 nginx 代理到3013端口,使用 http-proxy 代理到3012端口。

http-proxy

[root@cdfcf ~]# ab -n 10000 -c 100 http://www.dengzhanyong.com:3012/This is ApacheBench, Version 2.3 Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking www.dengzhanyong.com (be patient)Completed 1000 requestsCompleted 2000 requestsCompleted 3000 requestsCompleted 4000 requestsCompleted 5000 requestsCompleted 6000 requestsCompleted 7000 requestsCompleted 8000 requestsCompleted 9000 requestsCompleted 10000 requestsFinished 10000 requestsServer Software:        Server Hostname:        www.dengzhanyong.comServer Port:            3012Document Path:          /Document Length:        12 bytesConcurrency Level:      100Time taken for tests:   34.206 secondsComplete requests:      10000Failed requests:        0Write errors:           0Total transferred:      5556618 bytesHTML transferred:       120000 bytesRequests per second:    292.35 [#/sec] (mean)Time per request:       342.055 [ms] (mean)Time per request:       3.421 [ms] (mean, across all concurrent requests)Transfer rate:          158.64 [Kbytes/sec] receivedConnection Times (ms)min  mean[+/-sd] median   maxConnect:        1    9  27.3      8    1010Processing:    23  332  81.3    310     864Waiting:       22  253  85.3    250     826Total:         25  341  87.0    317    1399Percentage of the requests served within a certain time (ms)50%    31766%    33475%    36380%    38190%    43995%    47898%    56999%    730100%   1399 (longest request)

nginx

[root@cdfcf ~]# ab -n 10000 -c 100 http://www.dengzhanyong.com:3013/This is ApacheBench, Version 2.3 Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking www.dengzhanyong.com (be patient)Completed 1000 requestsCompleted 2000 requestsCompleted 3000 requestsCompleted 4000 requestsCompleted 5000 requestsCompleted 6000 requestsCompleted 7000 requestsCompleted 8000 requestsCompleted 9000 requestsCompleted 10000 requestsFinished 10000 requestsServer Software:        nginx/1.13.7Server Hostname:        www.dengzhanyong.comServer Port:            3013Document Path:          /Document Length:        12 bytesConcurrency Level:      100Time taken for tests:   24.610 secondsComplete requests:      10000Failed requests:        0Write errors:           0Total transferred:      5776562 bytesHTML transferred:       120000 bytesRequests per second:    406.35 [#/sec] (mean)Time per request:       246.096 [ms] (mean)Time per request:       2.461 [ms] (mean, across all concurrent requests)Transfer rate:          229.23 [Kbytes/sec] receivedConnection Times (ms)min  mean[+/-sd] median   maxConnect:        1    5   2.5      5      20Processing:     8  240  57.6    231     821Waiting:        6  240  57.5    230     820Total:          9  245  57.9    236     827Percentage of the requests served within a certain time (ms)50%    23666%    24575%    25480%    26090%    28795%    33098%    39699%    593100%    827 (longest request)

在测试结果中可以通过一些关键数据进行比较:

  1. 测试所需时间
  2. 每秒请求数
  3. 每次请求的时间
  4. 每次请求的时间(所有并发请求)
  5. 转移率

        通过上面的结果可以看出,nginx 的表现更好,请求10000次,并发量100,nginx 的总用时 24.610 秒,而 http-proxy 需要 34.206 秒。

        为了避免结果的果然性,通过改变请求内容大小,请求数量,并发量的数据进行多次测试,测试结果如下:

nginx hash 超时丢弃 nginx 请求超时_nginx hash 超时丢弃


        通过测试结果可以看出,随着请求内容的变大,他们之间的差距越来越小,这个原因应该是受服务器限制了,我的服务器配置很低,只有1核2g,因此对于大内容请求时基本上无差距。

        但从整体来看,每轮测试 nginx 都比 http-proxy 的效率更高。如果服务器性能条件好的话,可以通过配置 nginx 进一步提升效率,到这里我们可以得出结论:nginxhttp-proxy更高效。不过在 http-proxy 中可以对一些不同的业务场景,通过代码的方式做一些需求处理,这一点是 nginx 无法做到的。