
Teilen Sie:
Als ausgebildeter Schauspieler mit einer Dissertation in Standup-Comedy bin ich über die Meetup-Szene zur PHP-Entwicklung gekommen. Man findet mich, wenn ich über Technik spreche oder schreibe, oder wenn ich seltsame Platten aus meiner Vinylsammlung spiele oder kaufe.
Die Rückkehr von SQLite
Lesedauer: 12 Minuten
Einführung
OK, ich gebe es zu: Es ist keine Rückkehr. Nennen wir es eher eine Neugestaltung. SQLite gibt es seit dem Jahr 2000, und sein ursprünglicher Verwendungszweck war die Raketenverfolgung an Bord von Zerstörern der US-Marine. Es hat sich sicherlich als relationales Datenbanksystem bewährt, auch wenn es in den letzten 10 Jahren durch den Aufstieg der dokumentenorientierten NoSQL-Datenbanksysteme etwas aus dem Rampenlicht gerückt ist. In diesem Artikel werde ich das übersehene Potenzial von SQLite erforschen und zeigen, wie schnell es mit Blick auf eine produktionsgerechte Architektur eingerichtet werden kann. OK, ich gebe es zu: Es ist keine Rückkehr. Nennen wir es eher eine Neugestaltung. SQLite gibt es seit dem Jahr 2000. Während im letzten Jahrzehnt NoSQL- und dokumentenorientierte Datenbanken in den Vordergrund gerückt sind, ist SQLite nach wie vor eine leistungsstarke Option. Ursprünglich für die Raketenverfolgung auf Zerstörern der US-Marine entwickelt, hat es sich im Stillen als zuverlässige relationale Datenbank bewährt. Möglicherweise übersehen Sie sein Potenzial in einer produktionsgerechten Architektur. In diesem Artikel zeige ich Ihnen, wie schnell und einfach es ist, SQLite zum Laufen zu bringen.
>> TL;DR: Sie finden den vollständigen Quellcode auf GitHub.
Können Sie SQLite in der Produktion verwenden?
Eine gute Einführung also, aber als was kennen Softwareingenieure, insbesondere Entwickler von Webanwendungen, SQlite? Nun, es hat meist zwei Namen:
Ich muss meine Tests durchführen und möchte nicht eine vollständige Postgres Server aufsetzen. Warum also nicht einfach diese kleine nützliche Datei verwenden, um sie auszuführen?
Er ist für eingebettete Systeme geeignet, weil er klein ist, richtig? Aber das ist für meine Webanwendung, die Berge von Daten generieren wird, nicht von Nutzen.
Über Punkt eins lässt sich nicht streiten: SQLite ist unglaublich nützlich für Tests. Sie haben, sagen wir, Ihre bestehende Architektur im Code: Migrationen, Seeder und dergleichen. Wenn Sie also Ihre Testsuite ausführen, sollten Sie statt eines SQL-kompatiblen Datenbankservers, wie MySQL, MariaDBoder Postgres zu verwenden, führen Sie denselben Code aus, aber mit einer leeren SQLite-Datei. Sehr gut. Aber was ist mit Punkt 2?
SQLite-Vorteil: Übertragbarkeit
Just one file: portability at its finestJa, sie ist klein. Noch besser ist, dass die Konnektivität einfach ist: Es ist nur eine Datei.
Es gibt eine ganze Reihe von IDE-Plugins und Kompatibilität - Jetbrains' IDEs haben ein Datenbank-Panel, das eine neue SQLite-Datei erstellen kann, und VSCode verfügt über eine Vielzahl von Plugins, die dies ebenfalls für Sie erledigen. Ich meine, für die wirklich schweren Entwickler, können Sie es direkt von Vim aus erstellen.
Der Fußabdruck aus der Box ist nur 699kb. Das war's. Kein Dienst muss ausgeführt werden, keine Hintergrundprozesse - nur eine Datei.
Dies ist ein großer Unterschied zu den Ressourcen, die für das Aufsetzen eines vollständigen MySQL-Servers erforderlich sind.
Jetzt kommen wir zu der Frage, die sich die meisten Leute stellen wollen: Wenn es so einfach ist, warum wird SQLite dann nicht in mehr Web-Applikationen eingesetzt?
Die Antwort hängt in der Regel von Annahmen ab. Es dominieren serverbasierte relationale Datenbanken, aber mit ein wenig Überlegung könnte man feststellen, dass SQLite perfekt für unsere tatsächlichen Anforderungen geeignet ist.
SQLite-Vorteil: Leistung
Die Lese- und Schreibgeschwindigkeit ist einer der größten Unterschiede. SQLite ist für eine mittlere Datenbank mit ein paar Millionen Zeilen unglaublich schnell. Benchmarks variieren, aber Solo-Abfragen dauern bis zu 5 ms, im Vergleich zu einem maximalen Durchschnitt von etwa 10 ms bei MySQL.
Wenn SQLite jedoch in allen Benchmarks die Nase vorn hätte, würden wir es eindeutig für alles verwenden, obwohl es in der Entwicklung von Webanwendungen nicht so weit verbreitet ist. Erstens, die Schreibgeschwindigkeit ist viel langsamer. SQLite kann ungefähr bis zu 300 Einfügungen auf einem einzigen Thread schreiben, verglichen mit bis zu 50k in MySQL (abhängig von der Umgebung). Das ist ein großer Unterschied.
Zweitens ist zu beachten, dass SQLite einen Single-Thread-Sperrmechanismus hat; Datensätze, die gelesen oder geschrieben/aktualisiert werden, haben fünf mögliche Schreibzustände. Beim Schreiben wird der Sperrstatus eines Datensatzes auf EXCLUSIVE, was alle anderen gleichzeitigen Aktionen einschränkt. MySQL hingegen verwendet MVCC (Multi-Version Concurrency Control), was viele gleichzeitige Lese- und Schreibvorgänge ermöglicht.
Anwendungsfälle
Eine der Fragen, an die ich die Menschen immer wieder zu erinnern versuche, lautet Was ist Ihr Anwendungsfall? In der Welt von Cloud-Native und Kubernetes argumentieren viele, dass "PHP langsam ist", weil "Node eine Ereignisschleife hat", aber ich fordere die Leute dazu auf, darüber nachzudenken, "was wird Ihre Anwendung realistisch tun? Wenn Sie Benutzerdaten speichern oder CSV-Dateien und Bilder hochladen wollen, sind Sie dann wirklich werden Sie den Unterschied zwischen der Wahl der Sprache und des Frameworks wirklich bemerken? In vielen Fällen wahrscheinlich nicht. Das gilt auch für SQLite im Vergleich zu MySQL: SQLite ist immer noch eine fantastische Wahl, wenn Sie einige Daten haben, aber was noch wichtiger ist: Werden Sie 20.000 Benutzer haben, die in die Datenbank Ihrer Anwendung schreiben? Wenn Sie die nächste Iteration einer globalen Taxi-Anwendung schreiben, dann sicher. Was ich damit sagen will, ist, dass SQLite für viele Entwicklungsfälle viel besser geeignet ist, als vielen bewusst ist.
Ihr Projekt einrichten
Voraussetzungen
WebStorm IDE und Grundkenntnisse in der Anwendung
Grundlegende Kenntnisse über die Verwendung eines HTTP-Testclients, z. B. HTTPie oder Insomnia
Vonage API-Konto
Um dieses Tutorial durchzuführen, benötigen Sie ein Vonage API-Konto. Wenn Sie noch keines haben, können Sie sich noch heute anmelden und mit einem kostenlosen Guthaben beginnen. Sobald Sie ein Konto haben, finden Sie Ihren API-Schlüssel und Ihr API-Geheimnis oben auf dem Vonage-API-Dashboard.
Genug geredet, es ist an der Zeit zu zeigen, wie wenige Zeilen Code wir schreiben können, um einen SQLite-Schreibvorgang auf Produktionsniveau mit Typescript. Wir werden eine Anwendung bereitstellen, die in der Lage ist, Webhooks zu lesen, die von der Vonage Messages API. Legen Sie zunächst ein neues Verzeichnis für Ihr Projekt an, navigieren Sie dorthin und erstellen Sie ein neues Node-Projekt.
npm init --yesDies verwendet die Standardwerte für Ihre package.json die erstellt wird. Als nächstes müssen wir TypeScript installieren:
npm install typescript
npx tsc --initTypescript wird in einfaches JavaScript kompiliert und verwendet eine Konfigurationsdatei tsconfig.json, die bei der Installation erstellt wird. Öffnen Sie diese Konfigurationsdatei und ersetzen Sie den Textbaustein durch den folgenden:
{
"compilerOptions": {
"target": "es2016",
"module": "CommonJS",
"rootDir": "./",
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"moduleResolution": "node",
"baseUrl": ".",
"paths": {
"@prisma/client":["node_modules/@prisma/client"]
}
},
"include": ["src/**/*.ts"]
}Wichtige Teile dieser Konfiguration sind zu beachten:
TypeScript kompiliert in ein Verzeichnis, das erstellt wird, wenn es noch nicht existiert, und das den Namen
dist. Dies wird der Einstiegspunkt in Ihre Anwendung sein.Sie werden feststellen, dass Prisma in der
pathsSchlüssel steht. Das liegt daran, dass Prisma bei der Installation auch kompiliert werden muss (in gewisser Weise). Wenn wir Modelle innerhalb von Prisma definieren, wird dann ein Generierungsbefehl verwendet, um einen maßgeschneiderten Prisma-Client zu erstellen.
Wir haben sechs Abhängigkeiten:
Prisma: unser objektrelationaler Mapper
ts-nodets-node: ermöglicht die Ausführung von TypeScript ohne Kompilierung in das Ausgabeverzeichnis
nodemon: für unseren Entwicklungsserver, Code wird bei Änderungen neu geladen
dotenv(für den Umgang mit Umgebungsvariablen)
Express: unser Router
Sqlite: für unsere Datenbankverbindung
Sie können diese auf einen Schlag über die Befehlszeile installieren:
npm install prisma ts-node nodemon dotenv express @types/express sqlite3Prisma ist ein ORM das Ihre Datenmodelle, Migration und alle anderen Abfragen verarbeiten kann. Um Ihr Prisma-Verzeichnis einzurichten, müssen wir den init-Befehl für das Verzeichnis ausführen:
npx prisma init --datasource-provider sqlite --output ../generated/prismaMit diesem Befehl wird Prisma so konfiguriert, dass eine kompilierte Client-Klasse in das Verzeichnis ../erzeugt/prisma auszugeben, und teilt ihm mit, dass SQLite unsere Datenbankquelle ist. Wenn Sie diesen Befehl ausführen, fragt Prisma Sie nach allen zusätzlich benötigten Abhängigkeiten und richtet dann Ihre .env Datei ein. Wir werden diese Datei später konfigurieren.
Einrichten einer Datenbank in WebStorm
Da SQLite eine Datei ist, die von einer Bibliothek gehandhabt wird, können Sie sie mit den meisten modernen IDEs erstellen, die Treiberunterstützung bieten. Öffnen Sie nun Ihr Projekt in Webstorm. Klicken Sie dann auf das Datenbank-Symbol auf der rechten Seite. Klicken Sie dann auf die Schaltfläche "+", um eine neue Datenbank zu erstellen. Wählen Sie Datenquelle und scrollen Sie nach unten, bis Sie SQLite sehen. Nun erscheint das Modal für die Erstellung einer neuen Datenbank:
Jetbrains Supports A Massive List of DBsWählen Sie SQLite als Typ, und Sie erhalten das Erstellungs-Popup:
Create Your DatabaseWenn Sie dies zum ersten Mal tun und WebStorm noch nicht verwendet haben, wird die IDE feststellen, dass Sie die SQlite-Treiber nicht installiert haben, und eine Warnung anstelle der Option Test Connection Option ist. Wenn Sie die Treiber nicht haben, klicken Sie auf den Link, um sie zu installieren.
Im Feld Name Feld, ändern Sie identifier.sqlite in webhooksund den Dateinamen in webhooks.sqlite. Sie möchten, dass sich die Datei in Ihrem Projektstamm befindet. Klicken Sie daher auf die Punkte rechts neben dem Dateifeld, um sicherzustellen, dass der Speicherort korrekt ist. Klicken Sie dann auf ok.
Ihr Prisma-Client ist konfiguriert in prisma/schema.prismakonfiguriert, aber er holt sich die DATABASE_URL env var aus Ihrer .env Datei. Öffnen Sie Ihre envund ersetzen Sie sie wie folgt:
DATABASE_URL="file:../webhooks.sqlite"Prisma ist von Haus aus so konfiguriert, dass es den maßgeschneiderten ORM-Client im node_modules Verzeichnis zu generieren. Wir wollen nicht, dass er im Verzeichnis @prisma Verzeichnis generiert wird, also ersetzen Sie in der schema.prisma Datei die Client-Einstellungen unterhalb der Datenquelle wie folgt ersetzen:
generator client {
provider = "prisma-client-js"
output = "../node_modules/.prisma/client"
}Damit wird Prisma angewiesen, den generierten Client in ein neues Verzeichnis zu legen, .prisma. Später, bei der Erstellung eines Datensatzes in Express, werden wir Prisma mitteilen, woher der Mandant importiert werden soll.
Erstellen unseres Datenbankmodells
Wir müssen ein Modell erstellen, mit dem dann eine Migration durchgeführt werden kann. Was ich hier gemacht habe, war ein netter kleiner Hack - bei Prisma müssen Sie alle Ihre Datenbankmodelle manuell eingeben. Nun, wir konsumieren einen Vonage Messages API Webhookund was wäre, wenn ich zu der Webhook-Referenz in der OpenAPI-Spezifikationnavigiere, das JSON-Beispiel kopiere und dann AI dazu bringe, mir das Modell zu schreiben? Das ist genau das, was ich getan habe.
Auto-generated AI code from OpenAPI specsIch erspare Ihnen die Lauferei, Sie können die folgenden Modelle in Ihr schema.prisma below die Datenquelle und den Client:
model WebhookEvent {
id String @id @default(uuid())
channel String
messageUuid String @unique
to String
from String
timestamp DateTime
contextStatus String
messageType String
location Location?
createdAt DateTime @default(now())
}
model Location {
id String @id @default(uuid())
webhookId String @unique
lat Float
long Float
webhook WebhookEvent @relation(fields: [webhookId], references: [id], onDelete: Cascade)
}Jetzt können Sie die Migration durchführen, und es werden Tabellen in der Datenbank für diese Modelle erstellt.
npx prisma migrate dev --name webhooksPrisma hat nun die Migration für Sie erstellt, die als Aufzeichnung jeder an der Datenbank vorgenommenen Änderung dient. Sie möchten ein Feld umbenennen? Ja, neue Migration, die in den Quellcode übernommen wird. Sie haben nun eine vollständige Aufzeichnung darüber, wie Sie Ihre Anwendungsdatenbank in den richtigen Zustand bringen, und zwar im Code.
Erstellen unserer Express-Anwendung für die Verarbeitung von Webhooks
Ihre letzte Aufgabe besteht darin, die Express-Anwendung zu erstellen, die den Webhook verwenden wird. Erstellen Sie ein neues Verzeichnis in Ihrem Projektstamm mit dem Namen src und erstellen Sie eine neue TypeScript-Datei namens index.ts. Sie sieht wie folgt aus:
import express, { Express, Request, Response } from "express";
import dotenv from 'dotenv';
import { PrismaClient } from ".prisma/client"
dotenv.config();
const app: Express = express();
const port = process.env.PORT;
const prisma = new PrismaClient();
app.use(express.json())
app.get('/', (req: Request, res: Response) => {
res.send('Express + TypeScript Server');
});
app.post('/webhook', async (req, res) => {
try {
const { channel, message_uuid, to, from, timestamp, context_status, message_type, location } = req.body
// Save the webhook data in the database
const webhook = await prisma.webhookEvent.create({
data: {
channel,
messageUuid: message_uuid,
to,
from,
timestamp: new Date(timestamp),
contextStatus: context_status,
messageType: message_type,
location: location ? {
create: {
lat: location.lat,
long: location.long
}
} : undefined
},
include: { location: true } // Optional: Include related location in the response
})
console.log('Webhook saved:', webhook)
res.status(201).json({ message: 'Webhook saved successfully', webhook })
} catch (error) {
console.error('Error saving webhook:', error)
res.status(500).json({ error: 'Internal server error' })
}
})
app.listen(port, () => {
console.log(`[server]: Server is running at http://localhost:${port}`);
});Hier gibt es eine ganze Menge zu entpacken, also gehen wir Zeile für Zeile durch:
import { PrismaClient } from ".prisma/client"stellt sicher, dass Sie aus dem Verzeichnis .prisma importieren.app.use(express.json())ist es, sicherzustellen, dass Express weiß, dass es JSON verarbeiten muss.app.post('/webook') definiert einen neuen
POSTEndpunkt, an den Vonage Daten senden wird.Die
constdie im Webhook-Schluss definiert ist, extrahiert alle benötigten Felder in unveränderliche Variablen, die in die Datenbank geschrieben werdenabschließend,
prisma.webhookEvent.create()aufgerufen, das die eingehenden Daten in Ihre SQLite-Datenbank schreibt.
Sie müssen in der Lage sein, Ihren Prisma-Client über die Befehlszeile neu zu erstellen, und Sie müssen die Optionen hinzufügen, damit das kompilierte TypeScript funktioniert. In der scripts Abschnitt Ihrer package.json Datei ändern Sie ihn wie folgt:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "npm run prisma:generate && npx tsc",
"start": "node dist/src/index.js",
"dev": "nodemon --exec ts-node src/index.ts",
"prisma:generate": "prisma generate"
}Um Ihre Anwendung hier auszuführen, erstellen Sie zunächst die Anwendung im Verzeichnis dist Verzeichnis und starten Sie dann die Express-Anwendung, nachdem Sie Prisma neu generiert und den TypeScript-Compiler aufgerufen haben.
npm run buildnpm run startSie haben vielleicht bemerkt, dass ich auch den Befehl npm run dev der den TypeScript-Compiler ausführt und nodemonhinzugefügt, der bei jeder Änderung einer Datei einen Dev-Build durchführt.
Der letzte Teil ist das Senden der Daten selbst. Dazu müssen wir zunächst unsere lokale Anwendung mit Hilfe von ngrok für das Internet freigeben. Öffnen Sie dazu einen neuen Tab in Ihrem Terminal und führen Sie aus:
ngrok http 3000Lernen Sie mehr über ngrok.
Sobald ngrok Ihre Ports geöffnet hat, sollten Sie nun eine öffentliche URL haben. Diese muss nun in Vonage konfiguriert werden.
Um eine Anwendung zu erstellen, gehen Sie auf die Seite Erstellen einer Anwendung auf dem Vonage Dashboard und legen Sie einen Namen für Ihre Anwendung fest.
Wenn Sie eine API verwenden möchten, die Webhooks nutzt, benötigen Sie einen privaten Schlüssel. Klicken Sie auf "Generate public and private key", der Download sollte automatisch starten. Bewahren Sie ihn sicher auf; dieser Schlüssel kann bei Verlust nicht erneut heruntergeladen werden. Er folgt der Namenskonvention privat_<Ihre App-ID>.key. Dieser Schlüssel kann nun zur Authentifizierung von API-Aufrufen verwendet werden. Hinweis: Ihr Schlüssel funktioniert erst, wenn Ihre Anwendung gespeichert ist.
Wählen Sie die benötigten Funktionen (z. B. Voice, Nachrichten, RTC usw.) und stellen Sie die erforderlichen Webhooks bereit (z. B. Ereignis-URLs, Antwort-URLs oder URLs für eingehende Nachrichten). Diese werden im Lernprogramm beschrieben.
Zum Speichern und Bereitstellen klicken Sie auf "Neue Anwendung generieren", um die Einrichtung abzuschließen. Ihre Anwendung ist nun bereit für die Verwendung mit Vonage-APIs.
Die öffentlichen und privaten Schlüssel und alle anderen Optionen sind hier nicht wirklich wichtig, da wir keine vollständige Integration vornehmen, sondern nur einige Daten erzeugen. Was ist Wichtig ist, dass Sie Ihre von Ngrok generierte URL in beide eingehenden Optionen einfügen, gefolgt von /webhook da dies die Route ist, die in Express erstellt wurde. Erstellen Sie nun die Anwendung. Die Nachrichtenfunktion sollte wie folgt aussehen:
Configuring your Vonage Application WebhooksAlle Antworten auf die an diese Anwendung angehängte Nummer werden nun über einen Webhook weitergeleitet. Webhook an die URL weitergeleitet, die Sie hier für die Inbound-URL angegeben haben.
Um eine virtuelle Rufnummer zu kaufen, gehen Sie zu Ihrem API-Dashboard und befolgen Sie die unten aufgeführten Schritte.
Purchase a phone number
Gehen Sie zu Ihrem API-Dashboard
Navigieren Sie zu BUILD & MANAGE > Numbers > Buy Numbers.
Wählen Sie die gewünschten Attribute und klicken Sie dann auf Suchen
Klicken Sie auf die Schaltfläche Kaufen neben der gewünschten Nummer und bestätigen Sie Ihren Kauf.
Um zu bestätigen, dass Sie die virtuelle Nummer erworben haben, gehen Sie im linken Navigationsmenü unter BUILD & MANAGE auf Numbers und dann auf Your Numbers
Unsere Konfiguration ist nun abgeschlossen: Senden Sie eine Nachricht an die von Ihnen erworbene Nummer, und die gesamte Verdrahtung wird erfolgen, um das Ereignis und die eingehende Nachricht direkt in Ihre neue SQLite-Datenbank zu schreiben. Hier habe ich ein Lieblingstool von mir verwendet, HTTPieverwendet, um das Senden des Webhooks zu testen:
Successful Persistence WinsÖffnen Sie über das PHPStorm-Datenbank-Panel die Webhook-Tabelle, und Sie sehen, dass der Datensatz korrekt persistiert worden ist:
Database Query View in WebStorm
Schlussfolgerung
Diese Demo zeigt die Leistungsfähigkeit von SQLite: Wir haben nicht eine ganze Menge getan um diesen Code dazu zu bringen, eingehende Daten zu persistieren. Kein Docker, keine Cloud-Spinups von relationalen Systemen. Diese Einführung dient als Hinweis darauf, wo SQLite nützlich sein könnte: kleinere Mengen von Protokolldateien auf Rotation, kleinere Stapel von menschlichen statt maschinell erzeugten Daten und Sitzungsdaten. Betrachten Sie es als eine schnelle Einrichtung ähnlich wie Redis, wenn Gleichzeitigkeit und Datenverkehr nicht so wichtig sind. Aber wie bei allen Dingen gilt auch hier das Motto der Ingenieure: Es kommt darauf an®.
Haben Sie eine Frage oder möchten Sie etwas mitteilen? Beteiligen Sie sich am Gespräch auf dem Vonage Community Slackund bleiben Sie auf dem Laufenden mit dem Entwickler-Newsletter, folgen Sie uns auf X (früher Twitter), abonnieren Sie unseren YouTube-Kanal für Video-Tutorials, und folgen Sie der Vonage Entwickler-Seite auf LinkedInein Raum für Entwickler, um zu lernen und sich mit der Community zu vernetzen. Bleiben Sie in Verbindung, teilen Sie Ihre Fortschritte und halten Sie sich über die neuesten Nachrichten, Tipps und Veranstaltungen für Entwickler auf dem Laufenden!
Teilen Sie:
Als ausgebildeter Schauspieler mit einer Dissertation in Standup-Comedy bin ich über die Meetup-Szene zur PHP-Entwicklung gekommen. Man findet mich, wenn ich über Technik spreche oder schreibe, oder wenn ich seltsame Platten aus meiner Vinylsammlung spiele oder kaufe.
