.proto offers me little over a decent development environment around JSON, and it seems to be pretty Google-specific.
I'm also wary of adopting standards that come out of Google.
.proto offers me little over a decent development environment around JSON, and it seems to be pretty Google-specific.
I'm also wary of adopting standards that come out of Google.
gRPC lets you use other data exchange formats or IDLs as well, such as flatbuffers. However, the protobuf codegen experience we have spent most of the time and energy on.
I see two sides to this - on one hand, there are folks who want a 'contract first' development experience, in which the service contracts are defined first, and the business logic is implemented later. gRPC lends itself to this model very well. Admittedly, this is also the way services are developed in Google.
On the other hand, there are folks who want a model whereby you evolve a service and generate the specs from that service. Currently, this is not the experience that gRPC is optimized for. Time and effort are the main barriers to making this work well alongside a contract-first experience. FWIW: I believe both models have merit and it really depends on what you want to adopt as the source of truth for how your services interact. Ideally, gRPC would be good at both.
In contrast, I have been using NSwag [1] to generate C# client code with far greater comfort, and it seems to support multiple Typescript clients already.
[0] https://github.com/swagger-api/swagger-codegen [1] https://github.com/RSuter/NSwag
Myself and 40+ top contributors have decided to fork Swagger Codegen so as to maintain a community-driven version called OpenAPI Generator [1] with a better governance structure to move the project forward. Now there are 10+ core team members and contributors with proper rights to merge PRs so I think we've better PR management in OpenAPI Generator. Please refer to the Q&A [2] for the reasons behind the fork.
For TypeScript generators, we've recently added the TypeScript Axios client generator [3] and there's an ongoing project to consolidate the TypeScript generators into one [4]. Please check these out and let us know if you've any feedback.
We hope you will find OpenAPI Generator useful in your projects.
[1] https://openapi-generator.tech [2] https://github.com/OpenAPITools/openapi-generator/blob/maste... [3] https://twitter.com/oas_generator/status/1041939441109983232 [4] https://github.com/OpenAPITools/openapi-generator/projects/4
also i think i'm missing something:
>which you don’t really need with json+REST anyways
why don't you need server stubs for json+REST?
Checkout the main router, it's open source and handles a decent 6k msg/sec on a raspi: https://crossbar.io/
The best things about it is that you don't have to write the message schemas in advance, only the function signatures.
However, you have a low number of requests, or big requests, REST is going to be faster.
But as usual, it depends of your implementation and your constraint. After all, facebook is using polling if I recall.
All it all, if your configuration allows it, it's way, way easier and more flexible than MQTT to use.
Combared to RabbitMQ, it's not as fast. You can't beat years of optimized Erlang and field testing by fortune 500. Yet, Rabbit MQ is very low level: you need to setup queues, and consumers, and if you need RPC with returned value you will add manual logic on top of it. Don't get me started if you want to load balance consummers. Real life AMQP is hard.
Comparatively crossbar offers a great out of the box experience.
All in all, I'd say the sweet spot for the tech is between the arduino/raspi and an average website/company micro service archi. If you have very small hardware, MQTT could fit in the tiny space, and if you have a 100 message highways interconnecting your data centers around the world, you may want AMQP. Between those, crossbar.io is great.
If your development environment includes Swagger, programmatically generated HTTP clients and servers in multiple languages, built-in intelligent error handling, client-side and server-side type-checking of API requests and responses, gzipping your JSON over the wire, and if you exclusively write in languages like Python and JavaScript where protobuf doesn't serialize and deserialize any faster than JSON, then your development environment is honestly rather exceptional.
When using Protobuf on a non-compressed environment, the requests took 78% less time than the JSON requests. This shows that the binary format performed almost 5 times faster than the text format. And, when issuing these requests on a compressed environment, the difference was even bigger. Protobuf performed 6 times faster, taking only 25ms to handle requests that took 150ms on a JSON format.
"""
https://auth0.com/blog/beating-json-performance-with-protobu...
If your data to be transported is heterogeneous, or one of your endpoints is JavaScript, or if your requests are gates by something else, e.g. bandwidth, transport latency, endpoint raw compute, or human interaction, this dramatic difference may not necessarily apply.
50K records in a single request is a highly abnormal situation, and we're still talking about only shaving 125ms off of the sum total time of that request. In most apps where something that crazy is happening, this is not a problem, as it's clearly in async batch territory.
In a realistic architecture where you need request/response, there's going to be a lot of network calls and database calls. In my experience, it's those DB calls where the largest opportunity to optimize is. The other opportunity is removing N+1 request patterns. A lot of these "Proto is faster than JSON" benchmarks are showing a throughput bottlenecked app, when most apps that need a fast response are concerned with latency, and serialization is often only a few percent of that.
A few percent is a huge performance win. For example shaving 5% off the latency of twitter / facebook's apis is huge. Thing about the compute, energy and bottom line impacts.
I do agree for many protobuf is overkill, there's way lower hanging fruit that will give a greater latency reduction.
I've watched quite a few companies waste a lot of time with static IDL systems for performance reasons (going back to CORBA in the 90s) and have had the exact opposite effect.
Facebook has Thrift internally but ultimately ended up building GraphQL because orchestration and parallelism was the limiting factor (they also need a giant amount of coordination glue code to map from Thrift to JSON anyways). Netflix had similar problems which resulted in them building Falcor.
gRPC-web, as well, needs this serialization hop step, so depending on your use case, it may actually be slower. The last two companies I've worked at were in the 50-300 services range with 50K+ business customers and in the 10M+ B2C consumer usage range, and in both cases the IDL translation case (gRPC in one and Thrift in the other) was slower than JSON for many of their applications. Not all cases mind you, but it was definitely hit or miss.
In regards to utilization as well, will the reduced overhead of server CPU utilization for protobuf return a higher ROI than the added engineering time of the solution vs something like Swagger codegen? Will the engineers' extra energy expenditure for their work ever make up for the (potentially) reduced servers? These are serious questions and I think a lot of companies waste a lot of effort and resources by not answering those questions honestly.
You can get much of the same benefit with swagger codegen, though. It’s just that by the time you’re doing that, gRPC wouldn’t be that much more work anyway.
Incidentally, the dividing line between where programming languages are faster at handling protobuf than JSON, namely the dividing line between interpreted and compiled languages, is also the same one where you start to care about performance in the first place. And in Java or Golang, I’m not sure that gRPC is any more difficult.
Admittedly, gRPC doesn't support asyncio either (https://github.com/grpc/grpc/issues/6046), but gRPC has its own server frameworks already, and is not as well suited for the kinds of applications where you'd want a Python server anyway. But Swagger Codegen is.
(OpenAPI Generator is a fork of Swagger Codegen. For the reasons behind the fork, please refer to the Q&A [2])
[1] https://github.com/OpenAPITools/openapi-generator/pulls?q=is...
[2] https://github.com/OpenAPITools/openapi-generator/blob/maste...
Frontend
|
| GraphQL
|
V
Backend
|
| gRPC
|
V
Microservice
The situation with gRPC in the browser right now isn't ideal. Moreover, the client-side story -- interaction with React/Redux, client-side catching and prefetching, relationships and so on -- is nearly non-existent.GraphQL is better suited to how JS web apps work. In particular, GraphQL is designed to work with arbitrarily nested graphs of objects at dynamic levels of detail, in a way that makes caching, prefetching and so on fairly simple. And it speaks JSON fluently. gRPC's payloads are fixed, and if you want levels of detail ("fetch posts with creator"; "fetch posts without creator") you have to invent your own scheme for expressing this.
gRPC also isn't particularly developer-friendly when it comes to implementing the client or the server. As with any language-agnostic RPC layer, the interfaces tend to be quite sharp-edged: For example, it's relatively awkward to write services that deal with heterogenous collections of objects ("oneof" fields are limited), and arbitrary structured — as opposed to schema-based that can be expressed with the Proto IDL — data (while there's the "well-known" type Value that can effectively express JSON data, it's easier just to wrap JSON in a proto string).
GraphQL is much smoother to implement the client. Less so for the server, but it's all about graphs of objects, so it has the benefit that every server is essentially implemented the same way (the "verbs" are the same).
GraphQL's introspection story is also better. gRPC has facilities for probing an API without having the schema at hand, but GraphQL arguably has better tools here for now.
If the server side is also JS, because it is just a pain in anything else.
I am yet to see a good reason to move away from the flexibility, and most relevant, the tooling of REST.
Lacinia tries to be feature complete (as defined by Apollo Server and GraphQL spec), but obviously does not support everything Apollo does (remote schemas and graphql endpoints for example).
I have not tried any GraphQL server libraries in other languages, so I can't speak for people using C#, Java, or some other language.
I think the tooling around GraphQL is quickly approaching a point where it is better to use GraphQL then REST for client facing services. The fact that you can more precisely define your data needs and don't have to fetch the world, or make multiple round trips, is a big win. The contract a GraphQL schema provides both during development and runtime is also nice.
In my experience it's also faster to develop GRPC microservices as you spend less time dealing with Serialization and Deserialization. The only main downsides are the quirks of Protobuf but they are pretty easy to get used to.
Combining with GraphQL you can get a pretty high performance microservice stack, especially if you develop your microservices in Go and use a GraphQL Gateway like Apollo to stitch the whole thing together.
Imagine writing JSON/Rest, you have to define end point/router, convert/encode data into JSON/text.
With gRPC, all are done for you, the data is ready and pass to your function handler directly without you writing any glue code.