envoyproxy / envoy

Cloud-native high-performance edge/middle/service proxy
https://www.envoyproxy.io
Apache License 2.0
24.97k stars 4.81k forks source link

async Redis client #36936

Open AcherTT opened 5 days ago

AcherTT commented 5 days ago

Title: Is there an async Redis client similar to httpAsyncClient ?

Description:

I want to write a custom HTTP filter and initiate an asynchronous Redis request in decodeHeaders. Is there an async Redis client similar to httpAsyncClient that allows me to easily make asynchronous Redis requests without needing external dependencies like hiredis or redis-plus-plus?

nezdolik commented 4 days ago

cc @weisisea @msukalski @henryyyang

spacewander commented 3 days ago

Maybe you can expose the redis proxy implemented in Envoy as the client. The Higress's fork of Envoy already did it: search "envoy/redis/async_client.h" in https://github.com/higress-group/envoy/commit/f4bdca54c7e6f351046a8f44c3fe05c714b122e3#diff-03c81bf3ce1c97ec44ea4982cd44b606973612f7070cc6fd5b48411b54f28cfe.

Another solution is using the Golang filter to interact with Redis. For example, you can take a look at: https://github.com/mosn/htnn/blob/8971f1420656889dd555059aa284f41d7f48259a/plugins/plugins/limitcountredis/filter.go#L110

ljluestc commented 1 day ago

#include <cpp_redis/cpp_redis>
#include <iostream>
#include <string>
#include <memory>
#include <functional>

// Custom HTTP filter class
class CustomHttpFilter {
public:
    CustomHttpFilter() {
        // Initialize the Redis client
        redisClient.connect("127.0.0.1", 6379);
    }

    void decodeHeaders(const std::string& key) {
        // Initiate asynchronous request to Redis
        redisClient.get(key, [this](cpp_redis::reply& reply) {
            if (reply.is_string()) {
                std::string value = reply.as_string();
                std::cout << "Value from Redis: " << value << std::endl;

                // Process the value or modify the HTTP headers here
                // Example: modify some headers based on the value
                modifyHttpHeaders(value);
            } else {
                std::cerr << "Failed to get value from Redis." << std::endl;
            }
        });

        // Commit the request to Redis
        redisClient.commit();
    }

    void modifyHttpHeaders(const std::string& value) {
        // Modify HTTP headers based on the Redis value
        // Implement your logic here
        std::cout << "Modifying HTTP headers with value: " << value << std::endl;
    }

    ~CustomHttpFilter() {
        // Disconnect the Redis client
        redisClient.disconnect();
    }

private:
    cpp_redis::client redisClient;
};

int main() {
    // Create an instance of the custom HTTP filter
    CustomHttpFilter filter;

    // Example usage: decode headers with a key
    filter.decodeHeaders("my_key");

    // Keep the main thread alive to allow async operations to complete
    std::this_thread::sleep_for(std::chrono::seconds(2));

    return 0;
}