New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proxy route API discussion #796
Comments
I've used this configuration system to create... a simple configuration wrapper, which is what most end users will expect to use: https://github.com/dormando/memcached/blob/proxy_preview/proxy/simple.lua example configs:
with multiple "zones" per pool:
This is still lua syntax, but easily could be YAML. I'll be primarily working on this "simple" interface myself. The actual route functions the "simple" config uses might be ported to a higher level library, that people can use directly when the simple configuration doesn't work for them. IE: it should be possible to do tiering, collect specific stats counters, etc via customizing this library or writing your own. If "simple" doesn't do it for you, go nuts. |
One thing I use frequently is a local cache in front of memcached when I'm locally developing against a staging version of an application that's physically far away (100ms). Currently, I already solved this for the application itself - this is done manually in the application in an in-memory cache, but I can see that being useful elsewhere.
|
This proxy looks very interesting! Two questions:
[1] n2d machines on GCP |
Hey @goldfishy - thanks for expressing interest!
If you can spare any time the best thing towards getting it production ready faster is to give it a test; let me know what features are missing for you, what performance you get (and what the gap is between acceptable/top end), and any bugs/weirdness you run into while testing. Having someone actively testing will help a lot in motivating me to continue the production-ready bug scrub too :) I did a lot of the pre-production cleanup work last month. It should be much much easier to build and try than mcrouter, just see the extra steps in Productionizing work is tracked in #827 - discussions about the lua API's should be done here though. |
Going to close out this issue - Documentation is being created at https://github.com/memcached/memcached/wiki/Proxy work still being tracked at #827 and the code is out in released tarballs (though users recommended to use the @goldfishy - if you folks are still interested, development picked up again this year and it should be pretty usable now. |
This issue is for a discussion related to #716 - the embedded cache proxy.
Most of the proxy is C, two parts are handled in lua:
An example configuration file exists here: https://github.com/memcached/memcached/pull/716/files?file-filters%5B%5D=.lua&file-filters%5B%5D=No+extension#diff-1ab37d6d2cf900c8b5df02081cba299ebf0356af8a54f6111cedae0f527a81b0 - I'll explain the basics here as well.
To load the configuration, a dedicated thread first compiles the lua code. Then calls the function
mcp_config_pools
, which loads all backends, configures pools, and returns a table holding hash selectors. Once completed it will, for each worker thread, executemcp_config_routes
. This function is expected to set up route handling (code that matches requests to a pool), and sets the command hooks that memcached will call (ie; hooks on get, set, and so on).The proxy flow starts by parsing a request (ie:
get foo
) and looking for a function hook for this command. If a hook exists, it will call the supplied function. If no hook exists, it will handle the request as though it were a normal memcached.In lua, this looks like:
mcp.attach(mcp.CMD_GET, function)
- Functions are objects and can be passed as arguments. The function is called within a coroutine, which allows us to designs routes procedurally even if they have to make a network call in the middle of executing.The function is called with a prototype of:
The most basic example of a valid route would be:
mcp.attach(mcp.CMD_GET, function(r) return "SERVER_ERROR no route\r\n" end)
For any get command, we will return the above string to the client. This isn't very useful as-is. We want to test the key and send the command to a specific backend pool; but the function only takes a request object. How are routes actually built?
The way we recommend configuring routes are with function closures. In lua functions can be created capturing the environment they were created in. For example:
In this example,
new_route()
returns a function. This function has access to the environment (local res =
) of its parent. When proxy calls theCMD_GET
hook, it's calling the function that was returned bynew_route()
, notnew_route()
itself. This function uselessly returns a string.This should give you enough context to understand the example routes listed in the startfile.lua link above. To break it down a little more:
function(r) end
format, they match a request to a specific backend server, pause the lua function, executes the command, then resumes the original lua function.Since we have a real programming language for both configuration and the routes themselves, we can write loops around patterns and keep the configuration short.
My goal is to work through some main concepts:
r:key()
returns the request key to lua, andr:hit()
says if a response was a HIT or not). We should be able to modify or replace the key, make new requests, and examine a response in detail.Also of note: Custom hash selectors are possible, if you don't want to use one of the default ones. See
proxy/ketama
for an example.If you're using mcrouter or some similar memcached proxy, please take a look and let us know what's important to you!
The text was updated successfully, but these errors were encountered: