js服务器作为api服务器的解决办法,阿里云上Ng

2019-08-16 04:48 来源:未知

在看react-native教程的时候,遇到要在手机端调试,需要api服务器,但是由于Node.js自己就作为服务器,没有apache怎么解决这个问题,用apache和nginx也可以解决,但是有点复杂,我们就使用node已有的模块解决这个问题.

用nginx的反向代理机制解决前端跨域问题在nginx上部署web静态页面

再大规模商业项目中,解决环境、版本等问题其实有很成熟的解决方案。

##登录服务器之后(假设公网ip:111.111.111.127)####1.安装node```curl --silent --location | sudo bash -yum install nodejs -y```####2.在服务器上新建一个node servers```mkdir -p /data/release/weappcd /data/release/weappvi package.jsvi app.js``````#这是package.json{"name": "weapp","version": "1.0.0"}#这是app.js// 引用 express 来支持 HTTP Server 的实现const express = require('express');// 创建一个 express 实例const app = express();// 实现唯一的一个中间件,对于所有请求,都输出 "Response from express"app.use((request, response, next) => {response.write('Response from express');response.end();});// 监听端口,等待连接const port = 8765;app.listen(port);// 输出服务器启动日志console.log(`Server listening at 添加一组端口为8765的就行```npm install pm2 --globalcd /data/release/weappnpm install express --savepm2 start app.js```####4.安装Nginx运行完之后就可以在浏览器 install nginx -ynginx```####5.配置nignx的反向代理(就是访问域名,连接到你服务器的某个端口)```cd /etc/nginx/conf.dvi ceshi.confnginx -s reload``````#这是ceshi.conf文件的内容server{listen 80;server_name xxx.lovezhishu.cn; #这里填写你要转发的域名location /{proxy_pass default;}}```##结尾:此时访问域名就能访问到你服务器的8765端口了

 //服务器端的代码
var express = require('express');

var app = express();

// set up handlebars view engine
var handlebars = require('express3-handlebars')
  .create({ defaultLayout:'main' });
app.engine('handlebars', handlebars.engine);
app.set('view engine', 'handlebars');

app.set('port', process.env.PORT || 3000);

app.use(express.static(__dirname   '/public'));

var fortuneCookies = [
  "Conquer your fears or they will conquer you.",
  "Rivers need springs.",
  "Do not fear what you don't know.",
  "You will have a pleasant surprise.",
  "Whenever possible, keep it simple.",
];

app.get('/', function(req, res) {
  res.render('home');
});
app.get('/about', function(req,res){
  var randomFortune = 
    fortuneCookies[Math.floor(Math.random() * fortuneCookies.length)];
  res.render('about', { fortune: randomFortune });
});

// 404 catch-all handler (middleware)
app.use(function(req, res, next){
  res.status(404);
  res.render('404');
});

// 500 error handler (middleware)
app.use(function(err, req, res, next){
  console.error(err.stack);
  res.status(500);
  res.render('500');
});

app.listen(app.get('port'), function(){
 console.log( 'Express started on http://localhost:'   
  app.get('port')   '; press Ctrl-C to terminate.' );
});

 

现在的很多云计算厂商,利用虚拟化技术、容器技术,采用服务化方式进行开发,比如现在流行的docker+微服务架构就是其中的佼佼者,关于更多容器技术与云计算的话题,我会在以后的活动中为大家分享。

上面这段代码在127.0.0.1:3000端口启动一个本地服务器,但是在手机端是不能访问的.

1.什么是跨域以及产生原因

  跨域是指a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,或是a页面为ip地址,b页面为域名地址,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。

  跨域情况如下:

 

url 说明 是否跨域
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不同域名
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
同一域名下不同文件夹
http://www.a.com:8000/a.js
http://www.a.com/b.js
同一域名,不同端口
http://www.a.com/a.js
https://www.a.com/b.js
同一域名,不同协议
http://www.a.com/a.js
http://70.32.92.74/b.js
域名和域名对应ip
http://www.a.com/a.js
http://script.a.com/b.js
主域相同,子域不同 是(cookie不可访问)
http://www.a.com/a.js
http://a.com/b.js
同一域名,不同二级域名(同上)

要完成这种规模的商业项目架构设计,架构师常需要进行程序测试与验证设计,可要在笔记本上完成这样的部署,无论是利用虚拟化技术(虚拟机)还是容器技术,都显得太重了,架构师需要的应该是一个全能的开发、部署与运维环境,环境需要与产品环境高度一致,而且还应该轻便,节省性能,方便管理。

我们再启动另一个node.js服务器来解决这个问题.

 

从最简单的部分开始。

//proxy.js
  var http = require('http'), 
     httpProxy = require('http-proxy'); //引入这个模块

// 新建一个代理 Proxy Server 对象 
var proxy = httpProxy.createProxyServer({}); 

// 捕获异常 
proxy.on('error', function (err, req, res) { 
 res.writeHead(500, { 
  'Content-Type': 'text/plain' 
 }); 
 res.end('Something went wrong. And we are reporting a custom error message.'); 
}); 

// 另外新建一个 HTTP 80 端口的服务器,也就是常规 Node 创建 HTTP 服务器的方法。 
// 在每次请求中,调用 proxy.web(req, res config) 方法进行请求分发 
var server = require('http').createServer(function(req, res) { 
 // 在这里可以自定义你的路由分发 
 var host = req.headers.host, ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; 
 console.log("client ip:"   ip   ", host:"   host); 

 switch(host){ //意思是监听下面的ip地址,如果匹配就转到
//127.0.0.1:3000地址
  case '192.168.0.101:8080':  //监听这个地址
  //这个地址在window上用ipconfig查看,mac/linux用ifconfig查看

  case 'bbs.aaaa.com': 
    proxy.web(req, res, { target: 'http://127.0.0.1:3000' }); //转到这个地址
  break; 

  default: 
    res.writeHead(200, { 
      'Content-Type': 'text/plain' 
    }); 
    res.end('Welcome to my server!'); 
 } 
}); 

console.log("listening on port 8080") 
server.listen(8080);

2.跨域的常见解决方法

目前来讲没有不依靠服务器端来跨域请求资源的技术

  1.jsonp 需要目标服务器配合一个callback函数。

  2.window.name iframe 需要目标服务器响应window.name。

  3.window.location.hash iframe 同样需要目标服务器作处理。

  4.html5的 postMessage ifrme 这个也是需要目标服务器或者说是目标页面写一个postMessage,主要侧重于前端通讯。

  5.CORS  需要服务器设置header :Access-Control-Allow-Origin。

  6.nginx反向代理 这个方法一般很少有人提及,但是他可以不用目标服务器配合,不过需要你搭建一个中转nginx服务器,用于转发请求。

我们如何让一台服务器同时支持多种不同的web服务器,比如如何同时让我们的这台测试机上面能跑起php,nodejs,ruby on rails,

node proxy.js 以后启动了proxy服务器.可以通过电脑的ip地址访问127.0.0.1的api路由了。

3.nginx反向代理解决跨域

  上面已经说到,禁止跨域问题其实是浏览器的一种安全行为,而现在的大多数解决方案都是用标签可以跨域访问的这个漏洞或者是技巧去完成,但都少不了目标服务器做相应的改变,而我最近遇到了一个需求是,目标服务器不能给予我一个header,更不可以改变代码返回个script,所以前5种方案都被我否决掉。最后因为我的网站是我自己的主机,所以我决定搭建一个nginx并把相应代码部署在它的下面,由页面请求本域名的一个地址,转由nginx代理处理后返回结果给页面,而且这一切都是同步的。

 

  关于nginx的一些基本配置和安装请看我的另一篇博客,下面直接讲解如何配置一个反向代理。

 

  首先找到nginx.conf或者nginx.conf.default 或者是default里面的这部份   

          图片 1

   其中server代表启动的一个服务,location 是一个定位规则。

1
2
3
4
5
6
7
location /{   #所有以/开头的地址,实际上是所有请求
 
root  html     #去请求../html文件夹里的文件,其中..的路径在nginx里面有定义,安装的时候会有默认路径,详见另一篇博客
 
index  index.html index.htm  #首页响应地址
 

  

  从上面可以看出location是nginx用来路由的入口,所以我们接下来要在location里面完成我们的反向代理。

  假如我们我们是www.a.com/html/msg.html 想请求www.b.com/api/?method=1¶=2;

  我们的ajax:

1
2
3
4
5
6
7
var url = 'http://www.b.com/api/msg?method=1&para=2'
<br>$.ajax({
type: "GET",
url:url,
success: function(res){..},
....
})

  

  上面的请求必然会遇到跨域问题,这时我们需要修改一下我们的请求url,让请求发在nginx的一个url下。

1
2
3
4
5
6
7
8
9
var url = 'http://www.b.com/api/msg?method=1&para=2'
var proxyurl = 'msg?method=1&para=2'
//假如实际地址是 www.c.com/proxy/html/api/msg?method=1&para=2; www.c.com是nginx主机地址
 $.ajax({
type: "GET",
url:proxyurl,
success: function(res){..},
....
})  

  

  

  再在刚才的路径中匹配到这个请求,我们在location下面再添加一个location。

1
2
3
4
location ^~/proxy/html/{
rewrite ^/proxy/html/(.*)$ /$1 break;
proxy_pass http://www.b.com/;
}

如果有必要的话再加一个tomcat来跑jsp也是可以的。

如果是使用nginx也可以达到要求,在mac上使用homebrew包管理相当方便

以下做一个解释

1.'^~ /proxy/html/ '

  就像上面说的一样是一个匹配规则,用于拦截请求,匹配任何以 /proxy/html/开头的地址,匹配符合以后,停止往下搜索正则。

2.rewrite ^/proxy/html/(.*)$ /$1 break;

  代表重写拦截进来的请求,并且只能对域名后边的除去传递的参数外的字符串起作用,例如www.c.com/proxy/html/api/msg?method=1¶=2重写。只对/proxy/html/api/msg重写。

  rewrite后面的参数是一个简单的正则 ^/proxy/html/(.*)$ ,$1代表正则中的第一个(),$2代表第二个()的值,以此类推。

  break代表匹配一个之后停止匹配。

3.proxy_pass

*  既是把请求代理到其他主机,其中 写法和 *

不带/

1
2
3
4
location /html/
{
  proxy_pass http://b.com:8300; 
}

带/

1
2
3
4
location /html/ 
    proxy_pass http://b.com:8300/; 
}

上面两种配置,区别只在于proxy_pass转发的路径后是否带 “/”。

  针对情况1,如果访问url = 作为根路径,请求test/路径下的资源。

  针对情况2,如果访问url =

 

修改配置后重启nginx代理就成功了。

 

通常情况下,如果在一台机器中启动多个http服务,我们必须给这些web服务分配不同的端口,

bash下 安装 brew install nginx

1.mac使用ssh命令登陆远程主机

   因为苹果mac os x自带ssh命令,所以我们只需打开终端输入 

1
$ ssh user@remote

  在这之前最好在服务器上上传自己的ssh key,避免每次登陆输入密码

      稍作等待就连接上服务器了

 

 

 

 

否则就会端口冲突。然而标准的网页服务走的是80端口,

启动 brew services start nginx

2.mac使用scp命令向远处主机上传文件

        在终端窗口,按下command+n,打开另一个终端窗口,并输入

         

1
$ scp ~/local/file user@remote:~/file

    当然一般我们上传的是文件夹,所以加上-r

1
$ scp -r ~/local/file user@remote:~/file

  

在浏览器中输入一个网址,不指定端口号,者这个请求就会发送到80端口。

如果安装了atom编辑器

 

这样说来,如果同时在多个端口开启web服务基本不需要做太多额外的事情,

bash在 直接 atom /usr/local/etc/nginx/nginx.conf 打开配置文件本分以后做出修改

3.nginx安装与配置

    首先检查一下远程服务器是否安装ngnix.

1
nginx -V

  因为博主的服务器已经安装ngnix,所以下面介绍一下mac os x系统安装nginx的方法

     首先我们要用到homebrew,在终端中输入

1
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

  等待安装结束。

     再在终端执行,等待安装结束皆可

1
brew install nginx

    brew常用命令:

        安装软件:  brew install  *(软件名 eg. brew install nginx)

        卸载软件:  brew uninstall *

        搜索软件:  brew search *

        显示已经安装软件列表:  brew list

        更新软件:  brew update

        更新某具体软件: brew upgrade git

        

        接下来主要是nginx的配置问题,因为nginx的配置项较多,这里就不一一介绍,只把运行一个静态页面需要配置的东西拿出来配置一下

        首先可以看一下nginx的默认配置,可通过brew查看

        图片 2

     从上图中可以看到,nginx的默认root路径(也就是服务器根目录)是 /usr/local/var/www

     默认端口:8080

     下面进入nginx的配置文件,我们也能看到这些信息.

     nginx的配置文件是nginx.conf和nginx.conf.default,一般我们可以从 

     /usr/local/etc/nginx/  中找到这两个文件,通过vim打开nginx.conf。

     可以在配置中看到这样一段,可以在location的root 中改变文件存放位置

图片 3

   注意:此处有个大坑 

默认路径事 /usr/local/var/www,而在配置中又写了root html,所以真是路径是 /usr/local/var/www/html

但我们cd 进入/usr/local/var/www 并没有html文件,所以需要手动创建一个html,并放入工程。

如果发现nginx没有加载到某些文件或是某些页面出现一下403错误,是因为没有权限

输入 chmod 755  问题文件路径就可以解决

图片 4

 

修改之后需要停止nginx重新启动:终端输入

  nginx -s stop  停止   nginx 重启

 只要去各个服务器软件中修改配置文件,把端口号调整为其它大于一千的端口且不重复,

下面是nginx.conf的配置文件

 

这样web服务就能跑起来了。

 //nginx.conf

 #原来的文件另存后。直接使用下面内容替换nginx.conf的内容


events {
  worker_connections 1024;
}
http {
  include    mime.types;
  default_type application/octet-stream;

  #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
  #         '$status $body_bytes_sent "$http_referer" '
  #         '"$http_user_agent" "$http_x_forwarded_for"';



  sendfile    on;
  #tcp_nopush   on;

  #keepalive_timeout 0;
  keepalive_timeout 65;



  server {
    listen 8080; #监听80880端口
    server_name www.penguu.com 192.168.1.100; #这里是真机要访问的地址。
    # Mac 通过终端 ifconfig 查看。比如我查看的就是192.168.1.100
    #手机访问的接口就是 192.168.1.100:8080
    #实际在23行监听的端口可以是80端口,由于浏览器默认就是80端口。但是在mac中有权限问题。所#以就使用8080端口
    # address_book中的service中的地址也要修改路径是
    # view/service.js->host,修改为 192.168.1.100:8080

    #access_log /var/log/nginx/test.log;
    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-Nginx-Proxy true;
      proxy_set_header Connection "";
      proxy_pass   http://127.0.0.1:3000; # address_book的 server地址,就是本地node.js服务器的ip地址
      #node.js默认就是127.0.0.1 ,port:3000是在app.js中设定的。可以修改。

    }

  }

  }

4.mac使用cp命令把web文件复制到nginx的路由地址文件

    在上一步我们已经知道了 /usr/local/var/www 是系统运行的根目录,那么我们使用cp命令把我们的本地文件复制到此处

 

1
cp -r /local/files /des/files

  

 

接着我们需要解决一个棘手的问题,通常我们设计的restfulAPi接口以及默认的用户访问,都是直接把http请求发送至80端口的,80端口只有一个,自然是只能有一个程序去监听这个端口,不过这个解决起来也很简单。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

5.浏览工程

图片 5

 

之所以说这个最简单,是因为很多http服务器程序都支持http代理功能。我们在这里即将介绍的是利用nginx反向代理实现多个web服务共享80端口

您可能感兴趣的文章:

  • 图片上传之FileAPI与NodeJs
  • Google官方支持的NodeJS访问API,提供后台登录授权

1.第一步,先让nginx在80端口启动,nginx启动成功后再让其它服务器在别的端口启动服务。

为了保险期间,自己可以先测试一下,各个服务在不同端口是否工作正常。

然后我们就需要为各个服务创建虚拟主

主机,由于多个服务跑在一台机器上,所以为了能有所区分,我们得给这些服务分别绑定不同域名,如果是在本机测试,域名绑定的工作可以选择在自己笔记本的宿主机操作系统里面修改hosts文件

不知道如何操作的同学可以看我们的视频直播

检查一下如果在浏览器中输入我们绑定的域名可以访问到服务器,证明绑定成功

这一步完成以后,我们在nginx的配置中增加虚拟主机配置,为了方便管理,每一个虚拟主机的配置最好是能有一个独立的文件存放

下面是一个典型的虚拟主机反向代理配置

server {

       listen 80;

       server_name test.ydma.cn;

location / {

                     proxy_set_header X-Real-IP $remote_addr;

             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

             proxy_set_header Host  $http_host;

             proxy_set_header X-Nginx-Proxy true;

             proxy_pass ;

       }

}

如果是在ubuntu中,这个文件应该放在/etc/nginx/sites-available里面,然后再通过ln -s 做一个软连接放在sites-enabled文件夹中

之所以nginx能找到这个配置文件是因为在nginx.conf主配置文件中有这么两行配置

include /etc/nginx/conf.d/.conf;

include /etc/nginx/sites-enabled/;

我们可以看到上面的配置文件中 由nginx监听主机名为 server_name test.ydma.cn ,

端口号 listen 80;

location设置为 proxy_pass ;

也就是说把访问test.ydma.cn:80的请求交给127.0.0.1的9001端口去处理

proxy_set_header的配置是为了将http请求的头部信息做相应的改写,如果没有这设置,转发后的请求得到的请求信息就是nginx服务的信息,而不是外部用户的信息

把这个文件复制几分,只需要改写server_name以及proxy_pass后的端口号,那么我们就可以让nodes 、ruby on rails 、apache、等多个web服务同时共用80端口跑起来了。

多个web服务跑起来了,共用80端口了,这样服务与服务之间就可以通过标准的http协议做webservice调用了

可现在还不是高兴的时候,因为麻烦的还在后头,在项目开发过程中,我们用到的各种工具和软件,通常会有依赖,比如hadoop,我们以hadoop2.x为例,它依赖jdk7,我们制作的一款机器学习软件大量使用java函数式编程,需要jdk8,那么我们怎么样解决这个问题呢

通常做法是同时安装两个版本到不同路径,比如/opt/java/jdk/1.7.x/目录下安装java7,/opt/java/jdk/1.8.x/下安装java8,然后可以在linux中配置用户级别环境变量JAVA_HOME,通常环境变量应该写在文件 ~./bashrc 或者~/.bash_profile中,然后再修改系统的PATH变量,指向JAVA_HOME下的bin目录,这样我希望用户默认环境下是java8那么我就把环境变量JAVA_HOME切换到java8的安装目录就可以了,这样我们自己写的机器学习工具就能在我的用户权限下跑起来了。

如果我的机器学习程序需要访问hadoop中的数据怎么办?hadoop2.x需要的是jdk7,而且要和我的java8程序一起在同一台机器中使用

linux中的很多软件都会有启动脚本,如果在启动脚本中设定完整的java运行路径,就可以用指定的java版本来运行程序了,像hadoop这样的大型开源项目,已经一早就为我们准备了运行时环境设置的途径。

是不是依葫芦画瓢,然后其它语言多版本的问题都可以这样结局呢?

事情远远比我们想象中复杂,比如python,我们为了使用现在社区中一些新的python工具,必须把python升级到3.x版本,但操作系统中有些操作也需要python,比如当前ubuntu中用的是2.7,如果我们升级了python,系统的有些功能会无法正常使用。

ruby情况与python类似,由于ruby项目高度活跃,我们很可能需要同时使用3个以上甚至更多的ruby版本在一个系统中,不止如此,还需要能灵活的管理我们的环境

有一个很好的设计思路能解决这个问题,无论你希望有多少个版本并存在操作系统且无冲突。

原理如下

首先,我们需要能把语言各个版本环境统一管理,也就是说把所有我们需要的版本都下载下来,集中存放

然后我们建立一个该语言环境的目录加入PATH,为语言环境以及bing中的命令建立替身,所有敲的命令以及执行的脚本默认都指向替身而不是命令本身,比如正常情况下如果敲python命令,系统会去path中查找python文件,然后执行,由于通过path找到的python是替身而不是命令本身,我们可以利用替身帮我们做一些事情,

我们可以指明某个文件夹必须使用某个版本的python,这样替身接到命令调用时就会先判断,这个文件夹是否有指明版本,如果有指定,就再去调用指定版本的python去执行命令,当然如果没有指定文件夹,那么python就判断,当前登陆的用户有没有指定python版本,如果没有指定就再判断,有没有指定默认全局python版本,这样一来,我可以精确的去控制每一个文件夹,每一个用户,以及整个操作系统应该是用的python版本,

同样的原理也适用于其它编程语言,而且也有这样的开源项目来帮助我们做这样的事情。

最早这样管理环境的是ruby,ruby工程师发明了很多项目管理工具,早期的rvm就是管理版本环境与依赖的,功能比较强大,而另一个轻型解决方案叫做rbenv就是用我上面讲的办法来实现复杂的环境的管理,具体如何使用,大家可以看一下我视频直播中的演示。

由于有了rbenv这样好用的工具管理ruby,因此就有人利用rbenv进行改造,诞生了pyenv来管理python,还有phpenv等。

TAG标签:
版权声明:本文由美高梅网投平台发布于计算机网络,转载请注明出处:js服务器作为api服务器的解决办法,阿里云上Ng