go-kit / kit

A standard library for microservices.
https://gokit.io
MIT License
26.53k stars 2.43k forks source link

Implement server factories #913

Closed sagikazarmark closed 5 years ago

sagikazarmark commented 5 years ago

Preface

go-kit positions itself as a toolkit/library instead of being a framework. While I 100% agree with that mentality, there are scenarios where having a set of centrally configured components is useful, even at the cost of forcing modules to accept configuration from the outside.

The problem

Although go-kit is labeled as a microservice toolkit, it also mentions the "elegant monolith" model, which basically combines individual modules with strong boundaries into a single artifact. This way we can build large applications with a nice architecture and the possibility to factor out individual components if necessary.

When building large applications (for example a public REST/gRPC/GraphQL/NextBigThing API), there are certain responsibilities which we want to do the same way (or in a very similar style) in each module.

For example:

- Authentication
- Authorization (?)
- Metrics
- (Certain types of) logging

Frameworks usually provide (better or worse) tools for this in the form of globally registered middlewares (usually working within the transport layer).

In go-kit this is somewhat complicated at the moment. Although the transport layer can easily be extended with such middlewares from above (eg. in main.go wrapping returned HTTP handlers), many of the above listed responsibilities are in fact transport independent and should be added to the service or the endpoint level. Even the transport dependent (eg. HTTP auth) components should be handled at go-kit's level (eg. when the go-kit HTTP server is created).

Unfortunately (or not?), configuring these actions is completely manual at the moment. To give concrete examples:

In case of 50-100 endpoints this can be tedious, more importantly: error prone. Although with extensive testing we can make sure that no endpoint stays unprotected (eg. because the authentication middleware not added to the chain), I think it would be nice to have tools to make sure that it cannot happen in the first place.

The idea

The idea is to have a set of "factories" that can create transport handlers already populated with the necessary middlewares. For example, a HTTP server factory could add HTTPToContext to the HTTP server and the JWT auth middleware to the endpoint.

Alternatively, there could be a separate endpoint factory for endpoint related middlewares.

The important thing is that we can shift the responsibility to an external component....if we want.


It's probably trivial to implement a simple factory, so I could easily do it myself. There are two reasons for opening this issue:

What do you think?

mishudark commented 5 years ago

Authentication and Authorization can vary a lot depending on the company, Gokit as toolkit provides a lot of flexibility to integrate any tool that is great to your use case

sagikazarmark commented 5 years ago

Definitely, but I think there are common use cases that could be better supported by the above proposed solution. It's opt-in, so you don't have to use it, so the flexibility would still be there.

peterbourgon commented 5 years ago

Your organization should create an orgkit package which combines Go kit components with organinzation-specific policies and helper components for exactly this kind of thing. There is not enough commonality to provide meaningful default implementations, and providing scaffolding code in Go kit to help you set up this kind of thing would add a lot of LoC to the project without really carrying its weight.