From b9379d467bfb16b1c1dcf955641f0650503540ca Mon Sep 17 00:00:00 2001 From: Kailash Sethuraman Date: Fri, 19 Oct 2018 17:14:06 -0700 Subject: [PATCH 1/3] Adding the post for gRPC Web GA announcement. --- _posts/2018-10-23-grpc-web-ga.md | 122 +++++++++++++++++++++++++++++++ img/grpc-web-arch.png | Bin 0 -> 30387 bytes 2 files changed, 122 insertions(+) create mode 100644 _posts/2018-10-23-grpc-web-ga.md create mode 100644 img/grpc-web-arch.png diff --git a/_posts/2018-10-23-grpc-web-ga.md b/_posts/2018-10-23-grpc-web-ga.md new file mode 100644 index 00000000..e910b2e9 --- /dev/null +++ b/_posts/2018-10-23-grpc-web-ga.md @@ -0,0 +1,122 @@ +--- +layout: post +title: gRPC-Web is Generally Available +published: true +permalink: blog/grpc-web-ga +author: Luc Perkins - CNCF, Stanley Cheung - Google, Kailash Sethuraman - Google. +--- + +We are excited to announce the GA release of +[gRPC-Web](https://www.npmjs.com/package/grpc-web), a JavaScript client library +that enables web apps to communicate directly with gRPC backend services, +without requiring an HTTP server to act as an intermediary. + + + +With gRPC-Web, you can now easily build truly end-to-end gRPC application +architectures by defining your client *and* server-side data types and service +interfaces with Protocol Buffers. This has been a hotly requested feature for a +while, and we are finally happy to say that it is now ready for production use. +In addition, being able to access gRPC services opens up new an exciting +possibilities for [web based +tooling](https://github.com/grpc/grpc-experiments/tree/master/gdebug) around gRPC. + +## The Basics +gRPC-Web, just like gRPC, lets you define the service "contract" between client +(web) and backend gRPC services using Protocol Buffers. The client can then be +auto generated. To do this, you have a choice between the [Closure](https://developers.google.com/closure/compiler/) compiler +or the more widely used [CommonJS](https://requirejs.org/docs/commonjs.html). +This development process removes the need to manage concerns such as creating +custom JSOn seralization and deserialization logic, wrangling HTTP status codes +(which can vary across REST APIs), managing content type negotiation etc. + +From a broader architectural perspective, gRPC-Web enables end-to-end gRPC. The diagram below illustrates this: + + + + +

Figure 1. +gRPC with gRPC-Web (left) and gRPC with REST (right)

+ +In the gRPC-Web universe on the left, a client application speaks Protocol Buffers to a gRPC backend server that speaks Protocol Buffers to other gRPC backend services. In the REST universe on the right, the web app speaks HTTP to a backend REST API server that then speaks Protocol Buffers to backend services. + +## Advantages of using gRPC-Web +gRPC-Web will offer an ever-broader feature set over time, but here’s what’s in 1.0 today: + +* **End-to-end gRPC** — Enables you to craft your entire RPC pipeline using Protocol Buffers. Imagine a scenario in which a client request goes to an HTTP server, which then interacts with 5 backend gRPC services. There’s a good chance that you’ll spend as much time building the HTTP interaction layer as you will building the entire rest of the pipeline. +* **Tighter coordination between frontend and backend teams** — With the entire RPC pipeline defined using Protocol Buffers, you no longer need to have your “microservices teams” alongside your “client team.” The client-backend interaction is just one more gRPC layer amongst others. +* **Easily generate client libraries** — With gRPC-Web, the server that interacts with the “outside” world, i.e. the membrane connecting your backend stack to the internet, is now a gRPC server instead of an HTTP server, that means that all of your service’s client libraries can be gRPC libraries. Need client libraries for Ruby, Python, Java, and 4 other languages? You no longer need to write HTTP clients for all of them. + +## A gRPC-Web example +The previous section illustrated some of the high-level advantages of gRPC-Web for large-scale applications. Now let’s get closer to the metal with an example: a simple TODO app. In gRPC-Web you can start with a simple ``todos.proto`` definition like this: +```proto +syntax = "proto3"; + +package todos; + +message Todo { + string content = 1; + bool finished = 2; +} + +message GetTodoRequest { + int32 id = 1; +} + +service TodoService { + rpc GetTodoById (GetTodoRequest) returns (Todo); +} + +``` +CommonJS client-side code can be generated from this ``.proto`` definition with the following command: + +```proto +protoc echo.proto \ + --js_out=import_style=commonjs:./output \ + --grpc-web_out=import_style=commonjs:./output +``` + +Now, fetching a list of TODOs from a backend gRPC service is as simple as: + +```js +const {GetTodoRequest} = require('./todos_pb.js'); +const {TodoServiceClient} = require('./todos_grpc_web_pb.js'); + +const todoService = new proto.todos.TodoServiceClient('http://localhost:8080'); +const todoId = 1234; + +var getTodoRequest = new proto.todos.GetTodoRequest(); +getTodoRequest.setId(todoId); + +var metadata = {}; +var getTodo = todoService.getTodoById(getTodoRequest, metadata, (err, response) => { + if (err) { + console.log(err); + } else { + const todo = response.todo(); + if (todo == null) { + console.log(`A TODO with the ID ${todoId} wasn't found`); + } else { + console.log(`Fetched TODO with ID ${todoId}: ${todo.content()}`); + } + } +}); + +``` + +Once you declare the data types and a service interface, gRPC-Web abstracts away all the boilerplate, leaving you with a clean and human-friendly API (essentially the same API as the current [Node.js](https://grpc.io/docs/tutorials/basic/node.html) for gRPC API, just transferred to the client). + +On the backend, the gRPC server can be written in any language that supports gRPC, such as Go, Java, C++, Ruby, Node.js, and many others. The last piece of the puzzle is the service proxy. From the get-go, gRPC-Web will support [Envoy](https://envoyproxy.io) as the default service proxy, which has a built-in [envoy.grpc_web filter](https://www.envoyproxy.io/docs/envoy/latest/configuration/http_filters/grpc_web_filter#config-http-filters-grpc-web) that you can apply with just a few lines of copy-and-pastable configuration. + +## Next Steps +Going GA means that the core building blocks are firmly in place and ready for usage in production web applications. But there’s still much more to come for gRPC-Web. Check out the [official roadmap](https://github.com/grpc/grpc-web/blob/master/ROADMAP.md) to see what the core team envisions for the near future. + +If you’re interested in contributing to gRPC-Web, there are a few things we would love community help with: + +* **Front-end framework integration** — Commonly used front-end frameworks like [React](https://reactjs.org), [Vue](https://vuejs.org) and [Angular](https://angularjs.org) don't yet offer official support for gRPC-Web. But we would love to see these frameworks support it since the integration between these frontend frameworks and gRPC-Web can be a vehicle to deliver user-perceivable performance benefits to applications. If you are interested in building out support for these frontend frameworks, let us know on the [gRPC.io mailing list](https://groups.google.com/forum/#!forum/grpc-io), [filing a feature request on github](https://github.com/grpc/grpc-web/issues) or via the feature survey form below. + +* **Language-specific proxy support** — As of the GA release, [Envoy](https://envoyproxy.io) is the default proxy for gRPC-Web, offering support via a special module. NGNIX is also [supported](https://github.com/grpc/grpc-web/tree/master/net/grpc/gateway/nginx). But we’d also love to see development of in-process proxies for specific languages since they obviate the need for special proxies—such as Envoy and nginx—and would make using gRPC-Web even easier. + +We’d also love to get feature requests from the community. Currently the best way to make feature requests is to fill out the [gRPC-Web roadmap features survey](https://docs.google.com/forms/d/1NjWpyRviohn5jaPntosBHXRXZYkh_Ffi4GxJZFibylM/viewform?edit_requested=true). When filling up the form, list features you’d like to see and also let us know if you’d like to contribute to the development of those features in the **I’d like to contribute to** section. The gRPC-Web engineers will be sure to take that information to heart over the course of the project’s development. + +Most importantly, we want to thank all the Alpha and Beta users who have given us feedback, bug reports and pull requests contributions over the course of the past year. We would certainly hope to maintain this momentum and make sure this project brings tangible benefits to the developer community. \ No newline at end of file diff --git a/img/grpc-web-arch.png b/img/grpc-web-arch.png new file mode 100644 index 0000000000000000000000000000000000000000..7447d5d5bad364c1896d75beb0b7c12e7f0857cf GIT binary patch literal 30387 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 Date: Fri, 19 Oct 2018 17:17:43 -0700 Subject: [PATCH 2/3] Removed period at end of names in authors listing. --- _posts/2018-10-23-grpc-web-ga.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_posts/2018-10-23-grpc-web-ga.md b/_posts/2018-10-23-grpc-web-ga.md index e910b2e9..b06f51eb 100644 --- a/_posts/2018-10-23-grpc-web-ga.md +++ b/_posts/2018-10-23-grpc-web-ga.md @@ -3,7 +3,7 @@ layout: post title: gRPC-Web is Generally Available published: true permalink: blog/grpc-web-ga -author: Luc Perkins - CNCF, Stanley Cheung - Google, Kailash Sethuraman - Google. +author: Luc Perkins - CNCF, Stanley Cheung - Google, Kailash Sethuraman - Google --- We are excited to announce the GA release of @@ -119,4 +119,4 @@ If you’re interested in contributing to gRPC-Web, there are a few things we wo We’d also love to get feature requests from the community. Currently the best way to make feature requests is to fill out the [gRPC-Web roadmap features survey](https://docs.google.com/forms/d/1NjWpyRviohn5jaPntosBHXRXZYkh_Ffi4GxJZFibylM/viewform?edit_requested=true). When filling up the form, list features you’d like to see and also let us know if you’d like to contribute to the development of those features in the **I’d like to contribute to** section. The gRPC-Web engineers will be sure to take that information to heart over the course of the project’s development. -Most importantly, we want to thank all the Alpha and Beta users who have given us feedback, bug reports and pull requests contributions over the course of the past year. We would certainly hope to maintain this momentum and make sure this project brings tangible benefits to the developer community. \ No newline at end of file +Most importantly, we want to thank all the Alpha and Beta users who have given us feedback, bug reports and pull requests contributions over the course of the past year. We would certainly hope to maintain this momentum and make sure this project brings tangible benefits to the developer community. From a00925ffad6a7f39bbcb63b2a121573dc976bb54 Mon Sep 17 00:00:00 2001 From: Kailash Sethuraman Date: Tue, 23 Oct 2018 15:25:53 -0700 Subject: [PATCH 3/3] Fix typo with in "JSON" abbreviation. --- _posts/2018-10-23-grpc-web-ga.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_posts/2018-10-23-grpc-web-ga.md b/_posts/2018-10-23-grpc-web-ga.md index b06f51eb..524a66a8 100644 --- a/_posts/2018-10-23-grpc-web-ga.md +++ b/_posts/2018-10-23-grpc-web-ga.md @@ -27,7 +27,7 @@ gRPC-Web, just like gRPC, lets you define the service "contract" between client auto generated. To do this, you have a choice between the [Closure](https://developers.google.com/closure/compiler/) compiler or the more widely used [CommonJS](https://requirejs.org/docs/commonjs.html). This development process removes the need to manage concerns such as creating -custom JSOn seralization and deserialization logic, wrangling HTTP status codes +custom JSON seralization and deserialization logic, wrangling HTTP status codes (which can vary across REST APIs), managing content type negotiation etc. From a broader architectural perspective, gRPC-Web enables end-to-end gRPC. The diagram below illustrates this: