apache / trafficserver

Apache Traffic Server™ is a fast, scalable and extensible HTTP/1.1 and HTTP/2 compliant caching proxy server.
https://trafficserver.apache.org/
Apache License 2.0
1.81k stars 800 forks source link

Use JSON-RPC based interface for administrative API. #6633

Open SolidWallOfCode opened 4 years ago

SolidWallOfCode commented 4 years ago

(Original Document)

Administrative JSON RPC

To communicate between traffic_manager and traffic_server there is an RPC mechanism in mgmt/api. This is a simple serialization style RPC which runs over sockets. The goal of this project is to replace this with a JSON-RPC based implementation. The key benefits would be

The current logic is hand rolled and the messages and arguments are deeply embedded in the implementation, which makes changing them difficult and risky. This has an effect on most of these properties. A clean implementation that is generic would do much all by itself to ameloriate most of these issues, irrespective of it being JSON-RPC.

Standard RPC

Currently only Traffic Server specific implementations can access the external management API. This means interacting with any sort of standard managemet tools is very difficult, requiring custom code. Traffic Server ships with a Perl library to enable access via Perl, but this code is old, unmaintained, and painful to build.

In contrast, a JSON-RPC based API opens up a wide variety of libraries and tools in most (if not all) of the popular languages. There would be no need to provide any explicit support in the Traffic Server code base, as these existing tools are better than anything our community is likely to build.

One concern is performance, but in general the performance contraints for management APIs are much less severe than production traffic and in my view not a serious blocker for this application.

Internal extensibility

The functionality of the management API is limited primarily because it is so difficult. The new implementation must support a subsystem adding message types to the RPC without code changes in the RPC library. This will make adding additional functionality easy and make providing additional features much more feasible.

Argument handling

This is a mixed bag. On the one hand, using JSON-RPC will mean sending message arguments as JSON encoded data, effectively strings. This means converting to and from strings as the messages pass. Although it is a judgement call to say that will not be a problem. one can point to the large number of production web servers that use JSON-RPC (or just JSON encoded data) at production traffic levels.

On the other hand JSON encoded data is very easy to pass around and extend. If a new management API function needs a new type, it does not need any modification or additional support in the RPC library. The RPC library will be expected to handle only JSON encoded data. It may the case that an encoding framework is provided, but in general I have found it easier to directly print JSON encoded data than to use such a framework. Decoding is somewhat more challenging and we will need to look at what support can be provided by the RPC library. The RPC library will be responsible for parsing from text to JSON (or equivalent) data strutures. Other core components should need only to do direct type conversions. The RPC library must provide a set of basic converters for standard JSON types (integer, floats, booleans, possibly a few others).

Synchronicity

A key problem from the operators point of view is the “fire and forget” style of the current management API. The command line tools can verify the reciept of a message, but not any action done because of that message. The new implementation must be able to support synchronous messages for two reasons.

First so that the operators (or their tools) can know the message has been acted upon.

Enable message processing to pass back diagnostic information directly to the caller, rather than by spewing to a log file in the (frequently vain) hope an operator will notice.

It is acceptable for synchronicity to depend on the message, or on flags in the messages, but it must be possible.

In addition, there are multi-second delays built in to the current management API, for no particularly good reason I can see. A polling style is used, which seems unnecessary. Eliminating those delays would be worth while by itself, independent of using JSON-RPC.

Dynamic configuration

I dare to dream big - I want a Traffic Server which can start up with almost no (or literally no) configuration and then be fully configured via the management API. It has been a goal to minimize the required configuration need for a working Traffic Server for other reasons, but as the ability to configure via a management API is, in my opinion, critical for the long term success of Traffic Server.

As cloud based computing increases, operators will want ot embed Traffic Server in such systems (e.g. inside Kubernetes). Having to package configuration files is painful in such environments. What is wanted is the ability to deploy with a small amount of generic configuration (e.g. something that can be embeded in a RPM package) and bootstrap from that to the specific configuration needed.

Code Structure

As mentioned, the new implementation should be done in a library style, so that it depends on (at most) the already existing “tscore” library, but none of the proxy specific code. This is, in my view, the greatest single issue with the current code, its excessively complicated dependencies and linking. The new implementation must be a simple library with simple dependencies that don’t reach all over the code base.

Although not needed in the first phase, it should be kept in mind that the ability of plugins to register management API calls would be a very powerful feature. The design and implementation of this first phase should keep this in mind as a future feature.

ywkaras commented 4 years ago

I wouldn't disagree that we currently have a bad binary interface. But is that reason to conclude that a good binary interface (based on Unix or UDP sockets) is not the best option? Do we anticipate that the manager (or alternate managers) will be written in a language other than C++? After the Luapocalypse, can we feel confident that there is a healthy community associated with the JSON/RPC library we would rely on?

Do we want to allow the manager to be on a different host with different endiance than the host running traffic_server? I've got some code that can help with the byte-swapping that would be needed for a binary interface: https://github.com/wkaras/C-plus-plus-struct-component-wise-endiance-swap/blob/master/tst2.cpp .

SolidWallOfCode commented 4 years ago

For what reason do you think this wouldn't be based on UNIX sockets?

I certainly anticipate managers will be written in languages other than C++. See here for instance. As far as I know, there are two major administrative systems to manage ATS, and neither is written in C++.

One of the advantages of JSON-RPC is there isn't "a" library. There are many. Here is a partial list. Such things are also easy to write, given the number of JSON parsing libraries around (which, frankly, is most of the work).

Overall, I think the variety of support code and ease of implementation outweighs presumed performance gains from a binary API. What advantages, other than performance, are there for a binary API?

We don't really need to management to be a on different machine - in fact, there are security issues with that. I expect the local socket to be either a UNIX domain socket or bound to loopback and any off-box access proxied by some other mechanism.

ywkaras commented 4 years ago

A good general rule of thumb is, the less code the better. Even when the code is open source with a compatible license. If config data comes in binary format, saving it for efficient reading by per-transaction code might require little more than memory allocation and mem copies.

jpeach commented 4 years ago

What are the trade-offs between JSON-RPC and straight GRPC? My perspective would be that GRPC dominates the RPC space and has by far better tooling, libraries and access than anything else.

ywkaras commented 4 years ago

Since TS configuration has an SNMP "vibe" to it, should we consider using https://github.com/net-snmp/net-snmp/blob/master/README ?

ezelkow1 commented 4 years ago

might be nice, since we (and probably others) already use snmp for a variety of things, if we could more easily tie it into existing infrastructure that could be handy, but also something to be aware of that it shouldnt conflict with existing snmp agents

brbzull0 commented 4 years ago

What are the trade-offs between JSON-RPC and straight GRPC? My perspective would be that GRPC dominates the RPC space and has by far better tooling, libraries and access than anything else.

imo, to compare both solutions we should first put a scope on grpc, do we want to use the encoding they recommend by default which is proto buff? or just JSON as encoder? Transport, grpc uses h2, is this something we want/can? jsonrpc is transport agnostic so we can pick what we think is better. Performance, grpc seems super on this, will we be taking advantage of this?

Anyway, the plan is to have a 'lighting talk' during the Summit so we can keep talking about this.

I wasn't part of the first discussion on this topic, but I found this from 2018.

github-actions[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. Marking it stale to flag it for further consideration by the community.