[问题]Meteor多APP合并
发布于 5 年前 作者 a272121742 10004 次浏览 最后一次编辑是 2 年前

谁有做过或者看过使用Meteor做的多个APP项目然后将他们通过http-proxy或者nginx反向代理整合成一个项目的? 多个Meteor项目分别用不同端口,例如APP0:3000APP1:4000APP2:5000APP3:6000。然后让APP0映射到:80/,APP1映射到:80/app1子目录,APP2映射到:80/app2子目录,APP3映射到:80/app3子目录。 求高手指点!

9 回复

没帮你搞定,顶起来~

尝试了很久,用如下方式解决了!

搭建MutilMeteorApps

通过Meteor官网的项目示例,我们可以很快做出我们的Web应用。但是在实际的开发当中,我们往往由多人开发,每个人可能负责开发几个项目,却发布在一个服务器应用中。这种是如何实现的呢?通常我们可以使用服务器的反向代理机制将不同的Web项目映射到同一个端口中,现在我们就来实现搭建一个MutilMeteorApps。

首先,我们创建一个文件夹MutilMeteorApps,里面会有很多单独的MeteorApp。

$ mkdir MutilMeteorApps
$ cd MutilMeteorApps

接着,我们创建一个frame项目,这个项目作为整个MutilMeteorApps的框架项目。

$ meteor create frame

因为frame项目仅仅为集群项目提供框架,我们删除所有默认文件,新建/lib/config.js文件。

__meteor_runtime_config__.serverId = "myServerId";

然后我们新建一个/client/frame.html

<head>
  <title>项目主框架</title>
</head>
<body>
  <div>
    <a href="/app1" target="showFrame">app1</a>    
    <a href="/app2" target="showFrame">app2</a>    
    <a href="/app3" target="showFrame">app3</a>    
  </div>
  <div id="main">
      <iframe frameborder=0 width="100%" height="800" marginheight=0 marginwidth=0 scrolling=no src="/app1" name="showFrame">
  </div>
</body>

接下来我们就来构造我们的三个app项目,这三个项目我们不用自己做,我们就用Meteor官方提供的项目就可以了:

$ meteor create --example leaderboard
$ meteor create --example todos
$ meteor create --example wordplay

Meteor内部就提供了node的一个modules,名字叫http-proxy,这是一个用node做的http代理模块。我们在MutilMeteorApps文件夹新建如下文件和文件夹:

/MutilMeteorApps
      |-- /proxy
            |-- proxy.js
            |-- node_modules

http-proxy模块复制到node_modules文件夹中,然后修改proxy.js文件:

var proxy = require('http-proxy');
var options = {
  replaceRelativePath:true,
  pathnameOnly:true,
  router:{
    //package和sockjs从框架中找
    '/packages':'192.168.30.100:3000/packages',
    '/sockjs':'192.168.30.100:3000/sockjs',
    //各个项目从不同端口找
    '/app1':'192.168.30.100:4000/',
    '/app2':'192.168.30.100:5000/',
    '/app3':'192.168.30.100:6000/',
    //设置根目录
    '/':'192.168.30.100:3000/',
  }
};
proxy.createServer(options).listen(80);

需要注意的是,host尽量配置为本机ip地址或者域名ip地址。这样,我们就将不同端口的项目代理到同一端口80下了。接着我们运行所有的项目以及proxy.js这个node程序:

## 启动frame项目 ##
$ meteor --port 3000
## 启动leaderboard项目 ##
$ meteor --port 4000
## 启动todos项目 ##
$ meteor --port 5000
## 启动wordplay项目 ##
$ meteor --port 6000
## 启动proxy代理 ##
$ node proxy.js

我们可以试一试每个项目单独启动能否成功,答案是显然的,因为端口都没有冲突。然后我们试着访问http://127.0.0.1,点击这些链接。先不管为什么frame为什么没出来,但是我们发现点出来的项目虽然出来了,但是不停的再刷新。

这是为什么呢?其实我也不知道,但是我发现他刷新的速度和socket刷新的速度是一致的。于是我猜测,可能他认为这是几个不同的项目,所以出现这种不断比较不断刷新的递归现象,时间长了自然会对服务器有影响。还记得我们之前为frame配置的lib目录吗,这是我花了很久才找到的配置方法,中间走了不少弯路。只要将这个目录为你所有的项目中添加,告诉他们之间其实是同一个项目即可。

此时,三个项目都没出现刷新的问题,但是因为没有数据,所以三个显示的都不怎么好看。思考了一下,可能是三个都是连接各自的数据库,因此,我们统一数据库好了,设置环境变量set MONGO_URL=mongodb://192.168.30.100:27017,再次运行所有项目。

依然没有达到我们都目的,好的,我们再来做大胆的尝试。我觉得是因为不同端口的项目都在尝试连接80端口的项目,而80端口被映射到了3000端口上。因此,我们将所有项目拆解为client/server/public/collections几个文件夹来试一试。最后,将所有的服务器资源(public、server)统统放到frame项目中去。

最后成功!但是使用nodejs启动有点麻烦,如果Meteor框架frame自己能启动就最好了。很简单,Meteor虽然不能使用nodejs代码,但是能通过全局变量Npm获取nodejs模块,使用方法为Npm.require(),之后改动就很简单了吧!

虽然解决了,但是老大并不满意。他需要通过反向代理的方式实现各个app独立分离,减少服务器一次性的开销,我的这个解决方案虽然解决了标(分离和反向代理),但是没解决本(减少服务器开销)。不知道其他人还有没有更好的点子?我现在是已经没辙了!

  • 我也遇到了这个问题。。mark 研究一下LZ

我来解释一下 @a272121742同学 的解决方案为什么无法满足我的要求。

使用Meteor开发出的web应用程序是单页面应用(SPA),Meteor会将所有客户端逻辑(包括所有模板)全部编译成js,并加载到单个页面上。这对于小程序是没有任何问题的,但是如果开发一个大型的企业级应用,则是致命的。可以想象,打开登录页面就要加载全部程序,也许就有几十兆。客户会急死,浏览器也会崩溃。更进一步,如果开发移动版应用,脆弱的手机浏览器遇到这种巨无霸的单页面应用,恐怕立即就挂掉了。

解决办法之一就是将程序模块化,并且将不同的模块部署到不同的Meteor实例上,后台指向同一个MongoDB即可。前台一个主App框架通过router将不同的模块菜单路由到不同的Meteor实例,每个页面实际只加载单个模块的代码。这不需要做任何特殊开发,只要预先规划好功能模块即可。

但是问题来了:每个Meteor实例需要独占一个端口,如果这个系统需要支持外网访问,意味着需要为每个Meteor实例在防火墙上开放一个端口。如果你的程序有100个模块,你需要对着客户说“网管哥哥帮我在firewall开100个端口好吗?”然后你必定会收获一个白眼。

完美的Meteor模块化开发方案,必须解决每个Meteor实例独占一个端口的问题。

通过HTTP Server的代理和反向代理,可以实现子域名到端口的映射,例如 app1.company.com 可映射到 host.com:8001app2.company.com 可映射到 host.com:8002,听起来不错,但是依然不能解决问题。首先这种代理对Meteor会失效,因为Meteor的数据推送是通过WebSocket机制,在页面初始化时,每个页面会启动一个WebSocket并绑定到指定端口。上述例子中 app1.company.com和app2.company.com两个页面都会试图和company.com:80端口建立WebSocket连接。除非HTTP代理支持WebSocket,否则此路不通。第二个问题是,为了支持100个模块,你得注册100个二级域名,你会不会觉得很烦?

最终的方案,还是需要回答 @a272121742同学 开头提出的:

启动n个Meteor App,例如 Server:3000、Server:4000、Server:5000 通过某种机制,使得对 Server:3000的访问映射到 Server:80/,Server:4000的访问映射到 Server:80/app1、Server:5000的访问映射到 Server:80/app2… 这样就实现了单个端口,单个域名或IP地址,指向不同的Meteor应用程序(模块)

目前尚无答案,也许需要研究一下HTTP代理,听说Nginx已经支持Websocket代理,有人熟悉吗?

没遇到过。用Meteor的人不少哦。 我们是直接分成不同模块 资源一次性加载 。确实不好。

后来怎么解决的?

@ericwoo 开发大型的企业级应用,不能使用meteor么?

回到顶部