heroku 上的 Hapi 服务器无法绑定端口

Posted

技术标签:

【中文标题】heroku 上的 Hapi 服务器无法绑定端口【英文标题】:Hapi server on heroku fails to bind port 【发布时间】:2016-04-29 06:14:13 【问题描述】:

我正在为 ReactJS 应用程序开发 Hapi 服务器,但是当我尝试部署到 Heroku 时,我收到 R10 错误“无法在启动后 60 秒内绑定到 $PORT”。到底是怎么回事?我正在使用 process.env.PORT。我还尝试了 parseInt() 。还尝试禁用不同的软件包。构建总是成功的。

在 Heroku 日志中,我看到来自 index.js 的控制台日志(“Hapi running on ...”),但随后出现 R10 错误并且服务器重新启动,然后崩溃。

==> ???? Hapi 生产服务器 (API) 正在监听 http://localhost:14316 2016-01-22T15:10:33.947571+00:00 heroku[web.1]:使用 SIGKILL 停止进程 2016-01-22T15:10:33.947571+00:00 heroku[web.1]:错误 R10(启动超时)-> Web 进程在启动后 60 秒内无法绑定到 $PORT 2016-01-22T15:10:34.737554+00:00 heroku[web.1]:状态从开始变为崩溃 2016-01-22T15:10:34.724233+00:00 heroku[web.1]:进程以状态 137 退出

当我使用 NODE_ENV=production 运行时,这一切都在本地运行良好

src/server.js

import Hapi from 'hapi';
import Inert from 'inert';
import jwt from 'hapi-auth-jwt2';
import React from 'react';
import  renderToString  from 'react-dom/server';
import  RoutingContext, match  from 'react-router';
import  Provider  from 'react-redux';
import createRoutes from './routes';
import configureStore from './store/configureStore';
import html from './Html';

const PROTOCOL = 'http://';
const SERVER_HOST = process.env.HOST || 'localhost';
const SERVER_PORT = process.env.PORT || 3000;
const API_HOST = process.env.API_HOST || 'localhost';
const API_PORT = process.env.API_PORT || 8000;

export default function(callback) 

    const server = new Hapi.Server();

    server.connection(
    host: SERVER_HOST,
    port: SERVER_PORT,
    labels: ['api'],
    // routes: 
    //   cors: 
    //     origin: [PROTOCOL + API_HOST + ':' + API_PORT]
    //   
    // 
  );

    server.connections[0].name = 'API';

    server.register([
         register: Inert ,
         register: jwt ,
        // 
      //   register: api,
      //   routes: 
      //     prefix: '/api'
      //   
      // 
    ], (err) => 
    if(err) 
      console.error('ERROR:', err)
      throw err;
    

        server.route(
        method: 'GET',
        path: '/param*',
        handler: 
          directory: 
            path: 'static'
          
        
      );

        server.ext('onPreResponse', (request, reply) => 

            if (typeof request.response.statusCode !== 'undefined') 
        return reply.continue();
      

            const assets = 
                javascript: 
                    main: '/dist/bundle.js'
                
            ;

          const store = configureStore();
          const routes = createRoutes(store);

          // this gets called if server side rendering/routing has problems and errors
          function hydrateOnClient() 
            reply('<!doctype html>\n' +
              renderToString(<Html assets=assets store=store />)).code(500);
          

          match( routes, location: request.path , (error, redirectLocation, renderProps) => 

            if (redirectLocation) 

              res.redirect(301, redirectLocation.pathname + redirectLocation.search)

             else if (error) 
              console.error('ROUTER ERROR:', error) // eslint-disable-line no-console
              hydrateOnClient();

             else if (!renderProps) 

              // in some cases this would act as a 404 but that should be handled in the routes
              hydrateOnClient();

             else 

              const component = (
                <Provider store=store>
                  <RoutingContext ...renderProps />
                </Provider>
              );

              reply('<!doctype html>\n' +
                renderToString(<Html assets=assets component=component store=store />)
                    );
            
          );
        );
    );

    return server.start((err) => 

        if(err) 
            console.log(err);
            throw err;
        

        callback(server)
    );


index.js

require('babel-core/register');

global.__DEVELOPMENT__ = process.env.NODE_ENV !== 'production';
global.__SERVER__ = true;
global.__CLIENT__ = false;

const server = require('./src/server');

server(server => 
   for (var key of Object.keys(server.connections)) 
     console.info('==> ???? Hapi Production Server (' + server.connections[key].name + ') is listening on', server.connections[key].info.uri);
  
);

【问题讨论】:

【参考方案1】:

process.env.HOST 在 Heroku 上未定义,并且由于某种原因它不喜欢 localhost 作为主机,这导致了问题。

我只是一起删除了主机变量,所以连接看起来像:

server.connection(
  port: process.env.PORT || 3000,
  labels: ['api'],
)

【讨论】:

谢谢!这开始让我发疯了,因为我的 process.env.PORT 设置得很好。正如您所建议的那样,Heroku 确实不喜欢 server.connection( port: PORT, host: 'localhost' ); 完全删除 host 参数。比如:server.connection( port: PORT ); 干杯! 我遇到了同样的问题,我也通过不定义 host 属性解决了这个问题 ~2 小时浪费了今天试图解决这个问题。谢谢! 我很想知道你是怎么找到这个的?它甚至破坏了我的 mysql 连接。

以上是关于heroku 上的 Hapi 服务器无法绑定端口的主要内容,如果未能解决你的问题,请参考以下文章

Dockerized React App 无法绑定到 Heroku 上的 $PORT

无法访问 Heroku 上的 Web 服务器

Heroku Node.js 和 uWebsockets.js R10 错误,绑定端口失败

Heroku 上的 Phoenix:错误 R10

Heroku 错误:Web 进程在启动后 60 秒内无法绑定到 $PORT(使用 axios)

Web进程无法绑定$ port节点