Production Ready Apollo Gateway for GraphQL Services issue

Hi Team,

We are new to GraphQL and we built couple of GraphQl Services using Netflix DGS.

Now we would like to federate those services into single endpoint and started working on it by cloning the apollo gateway federation by netflix example dgs-federation-example/apollo-gateway at master · Netflix/dgs-federation-example · GitHub.

This works perfectly fine on my local machine. But When we deploy the node js app to our AWS EKS env, I am not sure how can I access the apollo server. I always see the Server ready at http://localhost:4000/

I have exposed the port 4000 as well but no use.

Here is my code for creating the apollo server. Please help. I have been trying it for couple of weeks now. I didn’t find a production ready federation example also.

'use strict'

const https = require('https')
const http = require('http')
const config = require('config')
const app = require('./app.js')
const log = require('<custom_logger>')
const { ApolloServer } = require('apollo-server')
const { ApolloGateway, RemoteGraphQLDataSource } = require('@apollo/gateway')
var os = require("os");

var hostname = os.hostname();
console.log("hostname:"+hostname)
let httpListenerPort = 8080
let httpsListenerPort = 8443

log.info('NODE_ENV: ' + config.util.getEnv('NODE_ENV'))
log.info('NODE_APP_INSTANCE: ' + config.util.getEnv('NODE_APP_INSTANCE'))
log.info('NODE_CONFIG_DIR: ' + config.util.getEnv('NODE_CONFIG_DIR'))
log.levels(
  0,
  process.env.LOG_LEVEL
    ? parseInt(process.env.LOG_LEVEL, 10)
    : 'info'
)

log.info('log.levels(): ' + log.levels())

const gateway = new ApolloGateway({
  serviceList: [
    {
      name: 'service1',
      url: '<link_to_service1>/graphql'
    },
    {
      name: 'service2',
      url: '<link_to_service2>/graphql'
    },
    {
      name: 'service3',
      url: '<link_to_service3>/graphql'
    },
    {
      name: 'service4',
      url: '<link_to_service4>/graphql'
    }
  ],
  introspectionHeaders: {
    apikey: process.env.API_KEY
  },
  buildService ({ url }) {
    return new RemoteGraphQLDataSource({
      url,
      willSendRequest ({ request }) {
        request.http.headers.set('apikey', process.env.API_KEY)
      }
    })
  }
})

const httpServer = http.createServer(app).listen(httpListenerPort, () => {
  log.info('app is listening at localhost:' + httpListenerPort)
})

const httpsServer = https
  .createServer(<api_certs>, app)
  .listen(httpsListenerPort, () => {
    log.info('app is listening at localhost:' + httpsListenerPort)
  })

const server = new ApolloServer({
  gateway,
  subscriptions: false,
  tracing: true,
  introspection: true, // TO ENABLE PLAYGROUND IN PRODUCTION
  playground: true, // TO ENABLE PLAYGROUND IN PRODUCTION
  onHealthCheck: () => {
    return new Promise(resolve => {
      resolve()
    })
  }
})


server.listen(4000).then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`)
  console.log(
    `Try your health check at: ${url}.well-known/apollo/server-health`,
  );
}).catch(err => {console.error(err)});

function timeoutExit (seconds = 5) {
  const timeout = setTimeout(() => {
    log.fatal(
      { exitCode: process.exitCode },
      `Application did not gracefully shutdown in ${seconds} seconds. Forcibly terminating.`
    )
    process.exit()
  }, seconds * 1000)
  // un-ref the timer so Node.js exits even with this running timer
  timeout.unref()
  return timeout
}

function closeServers () {
  httpServer.close(() => {
    log.info('HTTP server is shutdown')
  })
  httpsServer.close(() => {
    log.info('HTTPS server is shutdown')
  })
}

process.on('SIGTERM', () => {
  log.info('SIGTERM issued...app is shutting down')
  closeServers()
  timeoutExit()
})

process.on('uncaughtException', error => {
  log.fatal(
    error,
    'Uncaught Exception! The server is now in an unrecoverable state. Terminating...'
  )
  closeServers()
  // the app should exit on its own when there are no daemons running nor events on the event loop

  // forcibly terminate if haven't done so gracefully within timeout
  timeoutExit()
})

process.on('unhandledRejection', (reason, promise) => {
  log.error(
    {
      err: reason,
      promise
    },
    'Unhandled Promise Rejection'
  )
})

Not having any other configs for playground too. Have health check for http server only on top of it. Please suggest on how to spin the apollo server up and running in our K8s environment

Can you elaborate on what configuration you’re going for here? You have port 4000, port 8080 and port 8443 in your example. You noted that port 4000 doesn’t work, but does port 8080 work? How about port 8443?