rest.li

repository·master·Indexed 25 days ago

https://github.com/linkedin/rest.li

An open-source REST framework for building scalable, type-safe RESTful architectures using asynchronous, non-blocking IO. The framework includes the D2 coordination layer for service discovery, load balancing, and routing via Zookeeper. Note: rest.li is currently deprecated as LinkedIn migrates to gRPC.

Tokens
5.8K
Snippets
13
Records
35
Agent score
82%

What's inside rest.li

  1. Overview of Rest.li features

    master

    Rest.li is an open source REST framework designed for building scalable RESTful architectures using type-safe bindings and asynchronous, non-blocking IO.

    Core Features:

    • End-to-end framework: Provides a complete development flow for building RESTful APIs.
    • Non-blocking IO: Uses ParSeq for approachable asynchronous client and server code.
    • Type-safety: Utilizes generated data and client bindings to ensure type-safe development.
    • Annotation-driven: Server-side resource development is inspired by JAX-RS annotations.
    • Scalability: Engineered for high availability and high scalability.
    • Dynamic Discovery: An optional subsystem that provides client-side load balancing and fault tolerance.
    • API Safety: Includes backward compatibility checking to ensure API changes are safe.
    • Advanced REST capabilities: Supports batch operations, partial updates, and projections.
    • API Catalog: Includes a Web UI for browsing and searching a catalog of Rest.li APIs.
  2. Use ConsistentHashRingSimulator for load distribution testing

    master

    ConsistentHashRingSimulator is a tool for testing, debugging, and tuning D2 consistent hash ring configurations. It simulates load distribution when multiple concurrent clients route requests to servers in a hash ring.

    Key Capabilities:

    • Comparison: Compares a test ring against a strict consistent hash ring.
    • Metrics: Reports request distribution (consistency) and average latency (load balancing).
    • Visualization: Automatically generates bar charts (request distribution) and line charts (CIR changes per server over time).
  3. Configure Client and Request parameters

    master

    Within the clients array, each client object requires number, arrival, and requests fields.

    Client Arrival Configuration

    Defined in the arrival object:

    • minInterval: Minimum interval between requests.
    • maxInterval: Maximum interval between requests.
    • randomStrategy: Enum [GAUSSIAN, UNIFORM]. Determines the distribution used to pick an integer between the min and max intervals.

    Request Configuration

    Defined in the requests array. Each request object supports:

    • id (Optional): If specified, requests in this group are considered the same kind. Use this to simulate hot spots.
    • number: Number of requests of this kind.
    • minLatency: Minimum latency.
    • maxLatency: Maximum latency.
    • randomStrategy: Enum [GAUSSIAN, UNIFORM]. Determines the distribution for latency.
  4. D2 Service-Driven Client Configuration

    master

    In the D2 model, the service dictates how the client should communicate with its servers. This ensures that service owners—who are most impacted by misbehaving clients—can enforce optimal interaction parameters.

    Typical service-dictated configurations include:

    • Timeouts
    • Connection pool sizes
    • SSL usage and SSL parameters

    Client Overrides: D2 provides the flexibility for a client to override these service-defined configurations, provided the service is configured to allow such overrides.

  5. Understand D2 Service and Cluster Coordination

    master

    In a D2 environment, services are organized into clusters. Coordination between clients and servers is achieved through Zookeeper.

    Key components in the D2 architecture include:

    • Clusters: Groups of service instances (e.g., RecommendationService, NewsService).
    • Services: Logical endpoints within a cluster (e.g., articleRecommendation).
    • d2Config.json: Defines the mapping of services to clusters. This is processed by the config-runner to populate Zookeeper.
    • server.json: Configures the physical server instances (e.g., EchoServer) and assigns them to specific clusters.
    • client.json: Configures the traffic proportions sent by the D2 client to various services.
    • D2 Announcers: Components that register server availability in Zookeeper so clients can discover them.

    Advanced D2 features include server weight adjustment, partition management, and routing stickiness.

  6. Understand D2 Routing and Load Balancing Capabilities

    master

    The D2 framework provides several mechanisms for managing how clients interact with service clusters:

    • Partitioning: Used to divide a service into distinct partitions (e.g., ProfileService). Each partition can contain specific servers, ensuring requests are routed to the correct subset of the cluster.
    • Weighted Routing: Allows assigning different weights to servers within a partition (e.g., EmailService). Traffic is distributed according to these weights (e.g., a 10:1 ratio between two servers).
    • Sticky Routing (Soft Affinity): Configures D2 to make an effort to route the same request to the same server to improve cache locality (e.g., CacheService). Note that this is not a strict guarantee; D2 may route to a different server if the primary target is in a bad state.
    • Client Overrides: While services typically dictate client configuration (timeouts, connection pools, SSL), D2 allows clients to override these settings if the service permits it (e.g., BigDataService).
  7. Build and run the Guice server example

    master

    This example demonstrates how to use Guice 3 dependency injection with rest.li. To set up the environment, you must first propagate the PDSC and IDL changes from the repository root before building the specific Guice server example.

    Prerequisites

    • Gradle 4.6 or greater.
    • If you prefer using a local wrapper, run ../../gradlew wrapper from the examples/guice-server directory to generate a ./gradlew script compatible with this sample.

    Build Steps

    1. Propagate IDL changes: From the repository root, run:
      gradle publishRestliIdl
    2. Build the project: From the repository root, run:
      gradle build
      (Note: Subsequent builds only require gradle build after the initial IDL propagation).

    Running the Server and Client

    Navigate to the examples/guice-server folder to execute the following:

    • Start the Jetty server:
      gradle JettyRunWar
    • Test with a GET request (once the server is running):
      curl -v http://localhost:8080/fortunes/1
    • Run the built-in client:
      gradle startFortunesClient
    gradle publishRestliIdl
    gradle build
    gradle JettyRunWar
    curl -v http://localhost:8080/fortunes/1
    gradle startFortunesClient
  8. Run the D2 Client-Server Quickstart Example

    master

    This standalone example demonstrates a simple D2 client-server architecture using two clusters (RecommendationService and NewsService) and three services (articleRecommendation, jobRecommendation, and newsArticle). The mapping between services and clusters is managed via Zookeeper using a config-runner and a d2Config.json file.

    To run the demonstration, follow these steps:

    1. Start Zookeeper: Ensure Zookeeper is running (default is localhost:2181).
    2. Populate Configuration: Run the config-runner to populate Zookeeper with the service-to-cluster mappings defined in d2Config.json.
    3. Start Servers: Run the server command to instantiate EchoServer instances and D2 announcers based on server.json.
    4. Start Client: In a separate terminal, run the client command to begin sending traffic to the services based on the proportions defined in client.json.
  9. Run the D2 Advanced Example

    master

    This example demonstrates advanced D2 client-server capabilities including partitioning, load balancing, weighted routing, client overrides, and sticky routing.

    Prerequisites

    • Ensure Zookeeper is running (default is localhost:2181).

    Execution Steps

    1. Populate Configuration: Run the config-runner to populate Zookeeper with the mappings defined in d2Config.json:
      ../../gradlew runConfigRunner
    2. Start Servers: Create the echo servers and D2 announcers based on server.json:
      ../../gradlew runServer
      (Press Enter to stop the server)
    3. Run Client Scenarios: You can run specific clients to observe different D2 behaviors:
      • ProfileService (Partitioning/Load Balancing): ../../gradlew runProfileClient
      • EmailService (Weighted Routing): ../../gradlew runEmailClient
      • BigDataService (Client Overrides): ../../gradlew runBigDataClient
      • CacheService (Sticky/Soft Affinity Routing): ../../gradlew runCacheClient
    ../../gradlew runConfigRunner
    ../../gradlew runServer
    ../../gradlew runProfileClient
    ../../gradlew runEmailClient
    ../../gradlew runBigDataClient
    ../../gradlew runCacheClient