OpenSearch

repository·main·Indexed 11 days ago

https://github.com/opensearch-project/OpenSearch

An open-source, enterprise-grade search and observability suite for managing unstructured data at scale. This documentation covers the OpenSearch microbenchmark suite built on JMH, client benchmarking with the client-benchmark-noop-api-plugin, distribution formats (Archives, Linux Packages, and Docker Images), and the implementation of search pipelines and processors.

Tokens
84.7K
Snippets
235
Records
353
Agent score
96%

What's inside OpenSearch

  1. Overview of analytics-backend-datafusion

    main

    The analytics-backend-datafusion plugin is a native execution engine for the OpenSearch analytics framework. It uses a Rust/DataFusion runtime via JNI to execute query plan fragments.

    It integrates with OpenSearch through two primary Service Provider Interfaces (SPIs):

    1. SearchBackEndPlugin: A server SPI used for shard-level reader management.
    2. AnalyticsSearchBackendPlugin: An analytics-framework SPI used for query execution.
  2. Overview of the analytics-engine plugin

    main
    The analytics-engine is a central hub plugin that implements ExtensiblePlugin. It does not contain its own query language or execution logic; instead, it acts as a discovery and wiring mechanism for analytics extensions. At startup, it discovers implementations of QueryPlanExecutorPlugin, AnalyticsBackEndPlugin, and AnalyticsFrontEndPlugin from other extending plugins and wires them into the system using Guice.
  3. Overview of the analytics-framework library

    main
    The analytics-framework is a shared library that defines the Service Provider Interface (SPI) and core types for the OpenSearch analytics engine. It acts as a contract layer: it defines the interfaces that all analytics-related plugins must implement, but it contains no implementation logic itself. Plugins use this library to ensure compatibility with the analytics hub and other engine components.
  4. Available OpenSearch Distributions

    main

    OpenSearch is distributed in several formats depending on your deployment needs. The primary distributions include:

    • Archives: .zip and .tar files. These serve as the foundational components for all other distribution types.
    • Linux Packages: .deb (Debian/Ubuntu) and .rpm (Red Hat/CentOS) formats for native Linux installation.
    • Docker Images: Containerized versions of OpenSearch for use in container orchestration environments.

    Note that certain build processes for these distributions are architecture-specific and do not support cross-compilation.

  5. Understand the OpenSearch REST API JSON specification

    main

    The OpenSearch REST API JSON specification is a collection of JSON files that formalize and standardize the OpenSearch HTTP API. This specification is intended to facilitate the development of client libraries and integrations by providing a machine-readable definition of the API surface.

    Each API definition in the specification typically includes:

    • API Name: The identifier (e.g., indices.create) which usually corresponds to client library calls.
    • Documentation Link: A live URL to the official documentation.
    • Stability Level: Indicates the API's lifecycle state.
    • Request URL: Defines the HTTP method, path, and path parameters (parts).
    • Request Parameters: Defines query or URL parameters.
    • Request Body: Defines the schema for the JSON body.

    If an API is stable but returns an arbitrary map of key-value pairs, it is noted using the treat_json_as_key_value flag in the response object.

    {
      "indices.create": {
        "documentation":{
          "url":"https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-create-index.html"
        },
        "stability": "stable",
        "url":{
          "paths":[
            {
              "path":"/{index}",
              "method":"PUT",
              "parts":{
                "index":{
                  "type":"string",
                  "description":"The name of the index"
                }
              }
            }
          ]
        },
        "params": {
          "timeout": {
            "type" : "time",
            "description" : "Explicit operation timeout"
          }
        },
        "body": {
          "description" : "The configuration for the index (`settings` and `mappings`)"
        }
      }
    }
  6. Use the ingestion-hive plugin for pull-based ingestion

    main

    The ingestion-hive plugin allows OpenSearch to pull data directly from Apache Hive tables into an index. It connects to a Hive Metastore via Thrift, discovers partitions, and reads Parquet data files from Hadoop-compatible filesystems. This eliminates the need for an intermediate streaming layer like Kafka.

    Key capabilities:

    • Connects to Hive Metastore using framed or unframed Thrift transport.
    • Distributes partitions across shards using consistent hashing.
    • Supports incremental partition discovery by monitoring for new partitions.
    • Supports Kerberos (SASL/GSSAPI) authentication for the Metastore connection.
    • Provides effectively exactly-once delivery guarantees by deriving document _ids from the partition, file, and row index, ensuring idempotent overwrites during recovery.
    PUT /my-hive-index
    {
      "settings": {
        "ingestion_source": {
          "type": "HIVE",
          "pointer": {
            "init": {
              "reset": "earliest"
            }
          },
          "param": {
            "metastore_uri": "thrift://hive-metastore:9083",
            "database": "my_database",
            "table": "my_table"
          }
        },
        "index.number_of_shards": 3,
        "index.number_of_replicas": 1,
        "index.replication.type": "SEGMENT"
      }
    }
  7. Understand Inbound Client communication flows

    main

    When a client receives a response from a server:

    • Netty4 Flow: The Netty4TcpChannel receives a BytesReference. The ClientInboundPipeline deserializes it to a TransportResponse (using StreamInput), and the ClientInboundHandler delivers the response to the ResponseHandler.
    • Flight Flow (Async Response Handling): The FlightClient uses handleInboundStream(Ticket, Listener) on a FlightClientChannel. This creates a FlightTransportResponse, retrieves the header and reqID, and then uses the reqID to find the correct TransportResponseHandler. The response is then processed asynchronously via handler.handleStreamResponse(streamResponse).
    sequenceDiagram
        participant CTC as Client TcpChannel<br/>(Netty4TcpChannel)
        participant CIP as Client InboundPipeline
        participant CIH as Client InboundHandler
        participant RH as ResponseHandler
    
        Note over CTC,RH: Netty4 Flow
        CTC->>CIP: Receive BytesReference
        CIP->>CIH: Deserialize to TransportResponse<br/>(StreamInput)
        CIH->>RH: Deliver Response
    
        participant FC as FlightClient
        participant FCC as FlightClientChannel
        participant FTR as FlightTransportResponse
        participant RH2 as ResponseHandler
    
        Note over FC,RH2: Flight Flow (Async Response Handling)
        FC->>FCC: handleInboundStream(Ticket, Listener)
        FCC->>FTR: Create FlightTransportResponse
        FCC->>FCC: Retrieve Header and reqID
        FCC->>RH2: Get TransportResponseHandler<br/>using reqID
        FCC->>RH2: handler.handleStreamResponse(streamResponse)<br/>(Async Processing)
  8. Optimize Park-Bound Producers with Virtual Threads

    main

    For workloads where the producer is frequently bottlenecked on awaitReadyOrThrow (high parking time, low compute per batch), you can optimize resource usage by dispatching the stream action handler on a virtual-thread executor owned by the registrant.

    Best Practices:

    • Parking: Use virtual threads so that 'parked' time does not consume a platform thread.
    • CPU-bound work: Perform heavy computation (like building batches) on a sized platform-thread pool to avoid pinning the virtual thread's carrier thread. You can achieve this by submitting the work to a separate executor and awaiting the result from the virtual thread.