Heim Backend-Entwicklung Golang CouchGO! – Erweitern von CouchDB mit einem in Go geschriebenen Abfrageserver

CouchGO! – Erweitern von CouchDB mit einem in Go geschriebenen Abfrageserver

Jul 19, 2024 pm 12:38 PM

CouchGO! — Enhancing CouchDB with Query Server Written in Go

Im letzten Monat habe ich aktiv an Proof-of-Concept-Projekten im Zusammenhang mit CouchDB gearbeitet, seine Funktionen erkundet und mich auf zukünftige Aufgaben vorbereitet. In dieser Zeit habe ich die CouchDB-Dokumentation mehrmals durchgesehen, um sicherzustellen, dass ich verstehe, wie alles funktioniert. Beim Durchlesen der Dokumentation stieß ich auf die Aussage, dass die Erstellung einer benutzerdefinierten Implementierung relativ einfach ist, obwohl CouchDB mit einem in JavaScript geschriebenen Standard-Abfrageserver ausgeliefert wird und es bereits benutzerdefinierte Lösungen gibt.

Ich habe schnell recherchiert und Implementierungen gefunden, die in Python, Ruby oder Clojure geschrieben sind. Da die gesamte Implementierung nicht allzu langwierig erschien, habe ich beschlossen, mit CouchDB zu experimentieren und zu versuchen, meinen eigenen benutzerdefinierten Abfrageserver zu schreiben. Dazu habe ich Go als Sprache gewählt. Ich hatte bisher nicht viel Erfahrung mit dieser Sprache, außer mit der Verwendung von Go-Vorlagen in Helms Diagrammen, aber ich wollte etwas Neues ausprobieren und dachte, dieses Projekt wäre eine großartige Gelegenheit dafür.

Den Abfrageserver verstehen

Bevor ich mit der Arbeit begann, habe ich mir die CouchDB-Dokumentation noch einmal angesehen, um zu verstehen, wie der Abfrageserver tatsächlich funktioniert. Der Dokumentation zufolge ist der allgemeine Überblick über den Abfrageserver recht einfach:

Der Abfrageserver ist ein externer Prozess, der über das JSON-Protokoll über eine stdio-Schnittstelle mit CouchDB kommuniziert und alle Design-Funktionsaufrufe abwickelt […].

Die Struktur der von CouchDB an den Abfrageserver gesendeten Befehle kann ausgedrückt werden als [, <*arguments>] oder ["ddoc", , [, < funcname>], [, , …]] im Fall von Designdokumenten.

Im Grunde musste ich also eine Anwendung schreiben, die in der Lage ist, diese Art von JSON von STDIO zu analysieren, die erwarteten Vorgänge auszuführen und Antworten wie in der Dokumentation angegeben zurückzugeben. Es war viel Typumwandlung erforderlich, um eine breite Palette von Befehlen im Go-Code zu verarbeiten. Spezifische Details zu jedem Befehl finden Sie im Abschnitt „Query Server Protocol“ der Dokumentation.

Ein Problem, mit dem ich hier konfrontiert war, war, dass der Abfrageserver in der Lage sein sollte, beliebigen in Designdokumenten bereitgestellten Code zu interpretieren und auszuführen. Da ich wusste, dass Go eine kompilierte Sprache ist, erwartete ich, an diesem Punkt stecken zu bleiben. Zum Glück habe ich schnell das Yeagi-Paket gefunden, das Go-Code problemlos interpretieren kann. Es ermöglicht die Erstellung einer Sandbox und die Steuerung des Zugriffs darauf, welche Pakete in den interpretierten Code importiert werden können. In meinem Fall habe ich beschlossen, nur mein Paket namens Couchgo verfügbar zu machen, aber auch andere Standardpakete können problemlos hinzugefügt werden.

Wir stellen vor: CouchGO!

Als Ergebnis meiner Arbeit ist eine Anwendung namens CouchGO! entstanden. Obwohl es dem Query Server Protocol folgt, handelt es sich nicht um eine Eins-zu-eins-Reimplementierung der JavaScript-Version, da es über eigene Ansätze für die Handhabung von Designdokumentfunktionen verfügt.

Zum Beispiel gibt es in CouchGO! keine Hilfsfunktion wie „emit“. Um Werte auszugeben, geben Sie sie einfach von der Kartenfunktion zurück. Darüber hinaus folgt jede Funktion im Designdokument demselben Muster: Sie verfügt nur über ein Argument, bei dem es sich um ein Objekt handelt, das funktionsspezifische Eigenschaften enthält, und soll als Ergebnis nur einen Wert zurückgeben. Dieser Wert muss kein Grundwert sein; Je nach Funktion kann es sich um ein Objekt, eine Karte oder sogar um einen Fehler handeln.

Um mit CouchGO! zu arbeiten, müssen Sie lediglich die ausführbare Binärdatei aus meinem GitHub-Repository herunterladen, sie irgendwo in der CouchDB-Instanz platzieren und eine Umgebungsvariable hinzufügen, die es CouchDB ermöglicht, CouchGO! zu starten. Prozess.

Wenn Sie beispielsweise die ausführbare Couchgo-Datei im Verzeichnis /opt/couchdb/bin ablegen, würden Sie die folgende Umgebungsvariable hinzufügen, damit sie funktioniert.

export COUCHDB_QUERY_SERVER_GO="/opt/couchdb/bin/couchgo"
Nach dem Login kopieren

Schreiben von Funktionen mit CouchGO!

Um schnell zu verstehen, wie man mit CouchGO! Funktionen schreibt, schauen wir uns die folgende Funktionsschnittstelle an:

func Func(args couchgo.FuncInput) couchgo.FuncOutput { ... }
Nach dem Login kopieren

Jede Funktion in CouchGO! folgt diesem Muster, wobei Func durch den entsprechenden Funktionsnamen ersetzt wird. Derzeit ist CouchGO! unterstützt die folgenden Funktionstypen:

  • Karte
  • Reduzieren
  • Filter
  • Update
  • Validieren (validate_doc_update)

Sehen wir uns ein Beispiel-Designdokument an, das eine Ansicht mit Karten- und Reduzierungsfunktionen sowie eine Funktion „validate_doc_update“ angibt. Zusätzlich müssen wir angeben, dass wir Go als Sprache verwenden.

{
  "_id": "_design/ddoc-go",
  "views": {
    "view": {
      "map": "func Map(args couchgo.MapInput) couchgo.MapOutput {\n\tout := couchgo.MapOutput{}\n\tout = append(out, [2]interface{}{args.Doc[\"_id\"], 1})\n\tout = append(out, [2]interface{}{args.Doc[\"_id\"], 2})\n\tout = append(out, [2]interface{}{args.Doc[\"_id\"], 3})\n\t\n\treturn out\n}",
      "reduce": "func Reduce(args couchgo.ReduceInput) couchgo.ReduceOutput {\n\tout := 0.0\n\n\tfor _, value := range args.Values {\n\t\tout += value.(float64)\n\t}\n\n\treturn out\n}"
    }
  },
  "validate_doc_update": "func Validate(args couchgo.ValidateInput) couchgo.ValidateOutput {\n\tif args.NewDoc[\"type\"] == \"post\" {\n\t\tif args.NewDoc[\"title\"] == nil || args.NewDoc[\"content\"] == nil {\n\t\t\treturn couchgo.ForbiddenError{Message: \"Title and content are required\"}\n\t\t}\n\n\t\treturn nil\n\t}\n\n\tif args.NewDoc[\"type\"] == \"comment\" {\n\t\tif args.NewDoc[\"post\"] == nil || args.NewDoc[\"author\"] == nil || args.NewDoc[\"content\"] == nil {\n\t\t\treturn couchgo.ForbiddenError{Message: \"Post, author, and content are required\"}\n\t\t}\n\n\t\treturn nil\n\t}\n\n\tif args.NewDoc[\"type\"] == \"user\" {\n\t\tif args.NewDoc[\"username\"] == nil || args.NewDoc[\"email\"] == nil {\n\t\t\treturn couchgo.ForbiddenError{Message: \"Username and email are required\"}\n\t\t}\n\n\t\treturn nil\n\t}\n\n\treturn couchgo.ForbiddenError{Message: \"Invalid document type\"}\n}",
  "language": "go"
}
Nach dem Login kopieren

Lassen Sie uns nun jede Funktion aufschlüsseln, beginnend mit der Kartenfunktion:

func Map(args couchgo.MapInput) couchgo.MapOutput {
  out := couchgo.MapOutput{}
  out = append(out, [2]interface{}{args.Doc["_id"], 1})
  out = append(out, [2]interface{}{args.Doc["_id"], 2})
  out = append(out, [2]interface{}{args.Doc["_id"], 3})

  return out
}
Nach dem Login kopieren

In CouchGO!, there is no emit function; instead, you return a slice of key-value tuples where both key and value can be of any type. The document object isn't directly passed to the function as in JavaScript; rather, it's wrapped in an object. The document itself is simply a hashmap of various values.

Next, let’s examine the reduce function:

func Reduce(args couchgo.ReduceInput) couchgo.ReduceOutput {
  out := 0.0
  for _, value := range args.Values {
    out += value.(float64)
  }
  return out
}
Nach dem Login kopieren

Similar to JavaScript, the reduce function in CouchGO! takes keys, values, and a rereduce parameter, all wrapped into a single object. This function should return a single value of any type that represents the result of the reduction operation.

Finally, let’s look at the Validate function, which corresponds to the validate_doc_update property:

func Validate(args couchgo.ValidateInput) couchgo.ValidateOutput {
  if args.NewDoc["type"] == "post" {
    if args.NewDoc["title"] == nil || args.NewDoc["content"] == nil {
      return couchgo.ForbiddenError{Message: "Title and content are required"}
    }

    return nil
  }

  if args.NewDoc["type"] == "comment" {
    if args.NewDoc["post"] == nil || args.NewDoc["author"] == nil || args.NewDoc["content"] == nil {
      return couchgo.ForbiddenError{Message: "Post, author, and content are required"}
    }

    return nil
  }

  return nil
}
Nach dem Login kopieren

In this function, we receive parameters such as the new document, old document, user context, and security object, all wrapped into one object passed as a function argument. Here, we’re expected to validate if the document can be updated and return an error if not. Similar to the JavaScript version, we can return two types of errors: ForbiddenError or UnauthorizedError. If the document can be updated, we should return nil.

For more detailed examples, they can be found in my GitHub repository. One important thing to note is that the function names are not arbitrary; they should always match the type of function they represent, such as Map, Reduce, Filter, etc.

CouchGO! Performance

Even though writing my own Query Server was a really fun experience, it wouldn’t make much sense if I didn’t compare it with existing solutions. So, I prepared a few simple tests in a Docker container to check how much faster CouchGO! can:

  • Index 100k documents (indexing in CouchDB means executing map functions from views)
  • Execute reduce function for 100k documents
  • Filter change feed for 100k documents
  • Perform update function for 1k requests

I seeded the database with the expected number of documents and measured response times or differentiated timestamp logs from the Docker container using dedicated shell scripts. The details of the implementation can be found in my GitHub repository. The results are presented in the table below.

Test CouchGO! CouchJS Boost
Indexing 141.713s 421.529s 2.97x
Reducing 7672ms 15642ms 2.04x
Filtering 28.928s 80.594s 2.79x
Updating 7.742s 9.661s 1.25x

As you can see, the boost over the JavaScript implementation is significant: almost three times faster in the case of indexing, more than twice as fast for reduce and filter functions. The boost is relatively small for update functions, but still faster than JavaScript.

Conclusion

As the author of the documentation promised, writing a custom Query Server wasn’t that hard when following the Query Server Protocol. Even though CouchGO! lacks a few deprecated functions in general, it provides a significant boost over the JavaScript version even at this early stage of development. I believe there is still plenty of room for improvements.

If you need all the code from this article in one place, you can find it in my GitHub repository.

Thank you for reading this article. I would love to hear your thoughts about this solution. Would you use it with your CouchDB instance, or maybe you already use some custom-made Query Server? I would appreciate hearing about it in the comments.

Don’t forget to check out my other articles for more tips, insights, and other parts of this series as they are created. Happy hacking!

Das obige ist der detaillierte Inhalt vonCouchGO! – Erweitern von CouchDB mit einem in Go geschriebenen Abfrageserver. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

<🎜>: Bubble Gum Simulator Infinity - So erhalten und verwenden Sie Royal Keys
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Fusionssystem, erklärt
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Flüstern des Hexenbaum
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

Java-Tutorial
1671
14
PHP-Tutorial
1276
29
C#-Tutorial
1256
24
Golang gegen Python: Leistung und Skalierbarkeit Golang gegen Python: Leistung und Skalierbarkeit Apr 19, 2025 am 12:18 AM

Golang ist in Bezug auf Leistung und Skalierbarkeit besser als Python. 1) Golangs Kompilierungseigenschaften und effizientes Parallelitätsmodell machen es in hohen Parallelitätsszenarien gut ab. 2) Python wird als interpretierte Sprache langsam ausgeführt, kann aber die Leistung durch Tools wie Cython optimieren.

Golang und C: Parallelität gegen Rohgeschwindigkeit Golang und C: Parallelität gegen Rohgeschwindigkeit Apr 21, 2025 am 12:16 AM

Golang ist in Gleichzeitigkeit besser als C, während C bei Rohgeschwindigkeit besser als Golang ist. 1) Golang erreicht durch Goroutine und Kanal eine effiziente Parallelität, die zum Umgang mit einer großen Anzahl von gleichzeitigen Aufgaben geeignet ist. 2) C über Compiler -Optimierung und Standardbibliothek bietet es eine hohe Leistung in der Nähe der Hardware, die für Anwendungen geeignet ist, die eine extreme Optimierung erfordern.

Erste Schritte mit Go: Ein Anfängerführer Erste Schritte mit Go: Ein Anfängerführer Apr 26, 2025 am 12:21 AM

GoisidealforBeginersandSuitableforCloudandNetWorkServicesDuetoitsSimplicity, Effizienz und Konsumfeaturen.1) InstallgoFromTheofficialwebSiteAnDverifyWith'goversion'.2) CreateAneDrunyourFirstProgramwith'gorunhello.go.go.go.

Golang gegen C: Leistung und Geschwindigkeitsvergleich Golang gegen C: Leistung und Geschwindigkeitsvergleich Apr 21, 2025 am 12:13 AM

Golang ist für schnelle Entwicklung und gleichzeitige Szenarien geeignet, und C ist für Szenarien geeignet, in denen extreme Leistung und Kontrolle auf niedriger Ebene erforderlich sind. 1) Golang verbessert die Leistung durch Müllsammlung und Parallelitätsmechanismen und eignet sich für die Entwicklung von Webdiensten mit hoher Konsequenz. 2) C erreicht die endgültige Leistung durch das manuelle Speicherverwaltung und die Compiler -Optimierung und eignet sich für eingebettete Systementwicklung.

Golangs Auswirkungen: Geschwindigkeit, Effizienz und Einfachheit Golangs Auswirkungen: Geschwindigkeit, Effizienz und Einfachheit Apr 14, 2025 am 12:11 AM

GoimpactsDevelopmentPositivyThroughSpeed, Effizienz und DiasMlitication.1) Geschwindigkeit: Gocompilesquickandrunseffiction, idealforlargeProjects

Golang gegen Python: Schlüsselunterschiede und Ähnlichkeiten Golang gegen Python: Schlüsselunterschiede und Ähnlichkeiten Apr 17, 2025 am 12:15 AM

Golang und Python haben jeweils ihre eigenen Vorteile: Golang ist für hohe Leistung und gleichzeitige Programmierung geeignet, während Python für Datenwissenschaft und Webentwicklung geeignet ist. Golang ist bekannt für sein Parallelitätsmodell und seine effiziente Leistung, während Python für sein Ökosystem für die kurze Syntax und sein reiches Bibliothek bekannt ist.

Golang und C: Die Kompromisse bei der Leistung Golang und C: Die Kompromisse bei der Leistung Apr 17, 2025 am 12:18 AM

Die Leistungsunterschiede zwischen Golang und C spiegeln sich hauptsächlich in der Speicherverwaltung, der Kompilierungsoptimierung und der Laufzeiteffizienz wider. 1) Golangs Müllsammlung Mechanismus ist praktisch, kann jedoch die Leistung beeinflussen.

Das Performance -Rennen: Golang gegen C. Das Performance -Rennen: Golang gegen C. Apr 16, 2025 am 12:07 AM

Golang und C haben jeweils ihre eigenen Vorteile bei Leistungswettbewerben: 1) Golang ist für eine hohe Parallelität und schnelle Entwicklung geeignet, und 2) C bietet eine höhere Leistung und eine feinkörnige Kontrolle. Die Auswahl sollte auf Projektanforderungen und Teamtechnologie -Stack basieren.

See all articles