Redis
 sql >> Datenbank >  >> NoSQL >> Redis

Wie sollte ich von einer AWS Lambda-Funktion aus eine Verbindung zu einer Redis-Instance herstellen?

Ich habe jetzt mein eigenes Problem gelöst und hoffe, dass ich jemandem helfen kann, der dieses Problem in Zukunft hat.

Es gibt zwei Hauptüberlegungen, wenn eine Verbindung zu einer Datenbank hergestellt wird, wie ich es im obigen Code von einer Lambda-Funktion aus getan habe:

  1. Einmal context.succeed() , context.fail() , oder context.done() aufgerufen wird, kann AWS alle noch nicht beendeten Prozesse einfrieren. Dies führte dazu, dass AWS Connection closed protokollierte beim zweiten Aufruf an meinen API-Endpunkt – der Prozess wurde eingefroren, kurz bevor Redis das Schließen beendete, und beim nächsten Aufruf wieder aufgetaut. An diesem Punkt wurde er genau dort fortgesetzt, wo er aufgehört hatte, und meldete, dass die Verbindung geschlossen wurde. Fazit:Wenn Sie Ihre Datenbankverbindung schließen möchten, stellen Sie sicher, dass sie vorher vollständig geschlossen ist Sie rufen eine dieser Methoden auf. Sie können dies tun, indem Sie einen Rückruf in einen Ereignishandler einfügen, der durch das Schließen einer Verbindung ausgelöst wird (.on('end')). , in meinem Fall).
  2. Wenn Sie Ihren Code in separate Dateien aufteilen und require sie am Anfang jeder Datei, wie ich es getan habe, wird Amazon so viele dieser Module wie möglich im Speicher zwischenspeichern. Wenn dies Probleme verursacht, versuchen Sie, require() zu verschieben Aufrufe innerhalb einer Funktion statt am Anfang der Datei und dann Exportieren dieser Funktion. Diese Module werden dann jedes Mal neu importiert, wenn die Funktion ausgeführt wird.

Hier ist mein aktualisierter Code. Beachten Sie, dass ich meine Redis-Konfiguration auch in einer separaten Datei abgelegt habe, damit ich sie in andere Lambda-Funktionen importieren kann, ohne Code zu duplizieren.

Der Event-Handler

'use strict'

const lib = require('../lib/related')

module.exports.handler = function (event, context) {
  lib.respond(event, (err, res) => {
    if (err) {
      return context.fail(err)
    } else {
      return context.succeed(res)
    }
  })
}

Redis-Konfiguration

module.exports = () => {
  const redis = require('redis')
  const jsonify = require('redis-jsonify')
  const redisOptions = {
    host: process.env.REDIS_URL,
    port: process.env.REDIS_PORT,
    password: process.env.REDIS_PASS
  }

  return jsonify(redis.createClient(redisOptions))
}

Die Funktion

'use strict'

const rt = require('./ritetag')

module.exports.respond = function (event, callback) {
  const redis = require('./redis')()

  const tag = event.hashtag.replace(/^#/, '')
  const key = 'related:' + tag
  let error, response

  redis.on('end', () => {
    callback(error, response)
  })

  redis.on('ready', function () {
    redis.get(key, (err, res) => {
      if (err) {
        redis.quit(() => {
          error = err
        })
      } else {
        if (res) {
          // Tag is found in Redis, so send results directly.
          redis.quit(() => {
            response = res
          })
        } else {
          // Tag is not yet in Redis, so query Ritetag.
          rt.hashtagDirectory(tag, (err, res) => {
            if (err) {
              redis.quit(() => {
                error = err
              })
            } else {
              redis.set(key, res, (err) => {
                if (err) {
                  redis.quit(() => {
                    error = err
                  })
                } else {
                  redis.quit(() => {
                    response = res
                  })
                }
              })
            }
          })
        }
      }
    })
  })
}

Das funktioniert genau so, wie es sollte – und es ist auch blitzschnell.