More blog post cleanup

Signed-off-by: lucperkins <lucperkins@gmail.com>
This commit is contained in:
lucperkins 2020-03-10 11:36:11 -07:00
parent 6ae6fc886f
commit 59fc928363
36 changed files with 314 additions and 410 deletions

View File

@ -1,6 +1,5 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
date: {{ dateFormat "2006-01-02" .Date }}
draft: true
---

View File

@ -1,35 +0,0 @@
---
attribution: Originally written by Dale Hopkins with additional content by Lisa Carey
and others at Google.
author: Dale Hopkins
company: Vendasta
company-link: https://vendasta.com
date: "2016-08-29T00:00:00Z"
published: true
thumbnail: ../img/vend-icon.png?raw=true
title: Why we have decided to move our APIs to gRPC
url: blog/vendastagrpc
---
Our guest post today comes from Dale Hopkins, CTO of [Vendasta](https://vendasta.com/).
Vendasta started out 8 years ago as a point solution provider of products for small business. From the beginning we partnered with media companies and agencies who have armies of salespeople and existing relationships with those businesses to sell our software. It is estimated that over 30 million small businesses exist in the United States alone, so scalability of our SaaS solution was considered one of our top concerns from the beginning and it was the reason we started with [Google App Engine](https://cloud.google.com/appengine/) and Datastore. This solution worked really well for us as our system scaled from hundreds to hundreds of thousands of end users. We also scaled our offering from a point solution to an entire platform with multiple products and the tools for partners to manage their sales of those products during this time.
All throughout this journey Python GAE served our needs well. We exposed a number of APIs via HTTP + JSON for our partners to automate tasks and integrate their other systems with our products and platform. However, in 2016 we introduced the Vendasta Marketplace. This marked a major change to our offering, which depended heavily on having 3rd party vendors use our APIs to deliver their own products in our platform. This was a major change because our public APIs provide an upper-bound on 3rd-party applications, and made us realize that we really needed to make APIs that were amazing, not just good.
The first optimization that we started with was to use the Go programming language to build endpoints that handled higher throughput with lower latency than we could get with Python. On some APIs this made an incredible difference: we saw 50th percentile response times to drop from 1200 ms to 4 ms, and even more spectacularly 99th percentile response times drop from 30,000 ms to 12 ms! On other APIs we saw a much smaller, but still significant difference.
The second optimization we used was to replicate large portions of our Datastore data into ElasticSearch. ElasticSearch is a fundamentally different storage technology to Datastore, and is not a managed service, so it was a big leap for us. But this change allowed us to migrate almost all of our overnight batch-processing APIs to real-time APIs. We had tried BigQuery, but it's query processing times meant that we couldn't display things in real time. We had tried cloudSQL, but there was too much data for it to easily scale. We had tried the appengine Search API, but it has limitations with result sets over 10,000. We instead scaled up our ElasticSearch cluster using [Google Container Engine](https://cloud.google.com/container-engine/) and with it's powerful aggregations and facet processing our needs were easily met. So with these first two solutions in place, we had made meaningful changes to the performance of our APIs.
The last optimization we made was to move our APIs to [gRPC](/). This change was much more extensive than the others as it affected our clients. Like ElasticSearch, it represents a fundamentally different model with differing performance characteristics, but unlike ElasticSearch we found it to be a true superset: all of our usage scenarios were impacted positively by it.
The first benefit we saw from gRPC was the ability to move from publishing APIs and asking developers to integrate with them, to releasing SDKs and asking developers to copy-paste example code written in their language. This represents a really big benefit for people looking to integrate with our products, while not requiring us to hand-roll entire SDKs in the 5+ languages our partners and vendors use. It is important to note that we still write light wrappers over the generated gRPC SDKs to make them package-manager friendly, and to provide wrappers over the generated protobuf structures.
The second benefit we saw from gRPC was the ability to break free from the call-and-response architecture necessitated by HTTP + JSON. gRPC is built on top of HTTP/2, which allows for client-side and/or server-side streaming. In our use cases, this means we can lower the time to first display by streaming results as they become ready on the server (server-side streaming). We have also been investigating the potential to offer very flexible create endpoints that easily support bulk ingestion with bi-directional streaming, this would mean we would allow the client to asynchronously stream results, while the server would stream back statuses allowing for easy checkpoint operations while not slowing upload speeds to wait for confirmations. We feel that we are just starting to see the benefits from this feature as it opens up a totally new model for client-server interactions that just wasn't possible with HTTP.
The third benefit was the switch from JSON to protocol buffers, which works very well with gRPC. This improves serialization and deserialization times; which is very significant to some of our APIs, but appreciated on all of them. The more important benefit comes from the explicit format specification of proto, meaning that clients receive typed objects rather than free-form JSON. Because of this, our clients can reap the benefits of auto-completion in their IDEs, type-safety if their language supports it, and enforced compatibility between clients and servers with differing versions.
The final benefit of gRPC was our ability to quickly spec endpoints. The proto format for both data and service definition greatly simplifies defining new endpoints and finally allows the succinct definition of endpoint contracts. This means we are much better able to communicate endpoint specifications between our development teams. gRPC means that for the first time at our company we are able to simultaneously develop the client and the server side of our APIs! This means our latency to produce new APIs with the accompanying SDKs has dropped dramatically. Combined with code generation, it allows us to truly develop clients and servers in parallel.
Our experience with gRPC has been positive, even though it does not eliminate the difficulty of providing endpoints to partners and vendors, and address all of our performance issues. However, it does make improvements to our endpoint performance, integration with those endpoints, and even in delivery of SDKs.

View File

@ -1,10 +1,8 @@
---
title: A short introduction to Channelz
author: Yuxuan Li
author-link: https://github.com/lyuxuan
date: "2018-09-05T00:00:00Z"
published: true
title: A short introduction to Channelz
url: blog/a_short_introduction_to_channelz
date: 2018-09-05
---
Channelz is a tool that provides comprehensive runtime info about connections at

View File

@ -1,13 +1,11 @@
---
title: Building gRPC services with bazel and rules_protobuf
attribution: Originally written by Paul Johnston.
author: Paul Cody Johnston
company: PubRef.org
company-link: https://pubref.org
date: "2016-10-13T00:00:00Z"
published: true
date: 2016-10-13
thumbnail: https://avatars3.githubusercontent.com/u/10408150?v=3&s=200
title: Building gRPC services with bazel and rules_protobuf
url: blog/bazel_rules_protobuf
---
[gRPC](/) makes it easier to build high-performance

View File

@ -1,7 +1,7 @@
---
title: gRPC releases Beta, opening door for use in production environments
attribution: Mugur Marculescu, gRPC
date: "2015-10-26"
date: 2015-10-26
aliases: ["blog/beta_release"]
---

View File

@ -1,10 +1,9 @@
---
title: 2017-08-17 Community Meeting Update
author: Jaye Pitzeruse
company: Indeed
company-link: https://www.indeed.com
date: "2017-08-17T00:00:00Z"
published: true
title: 2017-08-17 Community Meeting Update
date: 2017-08-17
---
**Next Community Meeting:** Thursday, August 31, 2017 11am Pacific Time (US and Canada)

View File

@ -1,12 +1,12 @@
---
title: gRPC with REST and Open APIs
attribution: Originally written by Brandon Phillips with additional content by Lisa
Carey and others at Google
author: Brandon Phillips
company: CoreOS
company-link: https://coreos.com
date: "2016-05-09"
date: 2016-05-09
thumbnail: https://avatars2.githubusercontent.com/u/3730757?v=3&s=200
title: gRPC with REST and Open APIs
---
Our guest post today comes from Brandon Phillips of [CoreOS](https://coreos.com/). CoreOS builds open source projects and products for Linux Containers. Their flagship product for consensus and discovery [etcd](https://coreos.com/etcd/) and their container engine [rkt](https://coreos.com/rkt/) are early adopters of gRPC.

View File

@ -1,14 +1,12 @@
---
title: gRPC and Deadlines
author: Gráinne Sheerin, Google SRE
company: Google
company-link: https://www.google.com
date: "2018-02-26T00:00:00Z"
published: true
title: gRPC and Deadlines
url: blog/deadlines
date: 2018-02-26
---
**TL;DR Always set a deadline**. This post explains why we recommend being deliberate about setting deadlines, with useful code snippets to show you how.
**TL;DR: Always set a deadline**. This post explains why we recommend being deliberate about setting deadlines, with useful code snippets to show you how.
<!--more-->

View File

@ -1,14 +1,13 @@
---
title: gRPC Project is now 1.0 and ready for production deployments
attribution: Originally written by Varun Talwar with additional content by Kailash
Sethuraman and others at Google.
author: Varun Talwar
company: Google
company-link: https://cloud.google.com
date: "2016-08-23T00:00:00Z"
published: true
date: 2016-08-23
thumbnail: ../img/gcp-icon.png?raw=true
title: gRPC Project is now 1.0 and ready for production deployments
url: blog/gablogpost
aliases: ["blog/gablogpost"]
---
Today, the gRPC project has reached a significant milestone with its [1.0 release](https://github.com/grpc/grpc/releases).

View File

@ -1,12 +1,10 @@
---
title: Gracefully clean up in gRPC JUnit tests
author: Dapeng Zhang
author-link: https://github.com/dapengzhang0
company: Google
company-link: https://www.google.com
date: "2018-06-26T00:00:00Z"
published: true
title: Gracefully clean up in gRPC JUnit tests
url: blog/gracefully_clean_up_in_grpc_junit_tests
date: 2018-06-26
---
It is best practice to always clean up gRPC resources such as client channels, servers, and previously attached Contexts whenever they are no longer needed.
@ -112,5 +110,5 @@ public class MyTest {
Now with [`GrpcCleanupRule`][GrpcCleanupRule] you don't need to worry about graceful shutdown of gRPC servers and channels in JUnit test. So try it out and clean up in your tests!
[GrpcServerRule]:https://github.com/grpc/grpc-java/blob/v1.1.x/testing/src/main/java/io/grpc/testing/GrpcServerRule.java
[GrpcCleanupRule]:https://github.com/grpc/grpc-java/blob/v1.13.x/testing/src/main/java/io/grpc/testing/GrpcCleanupRule.java
[GrpcServerRule]: https://github.com/grpc/grpc-java/blob/v1.1.x/testing/src/main/java/io/grpc/testing/GrpcServerRule.java
[GrpcCleanupRule]: https://github.com/grpc/grpc-java/blob/v1.13.x/testing/src/main/java/io/grpc/testing/GrpcCleanupRule.java

View File

@ -2,7 +2,7 @@
title: "gRPC Meets .NET SDK And Visual Studio: Automatic Codegen On Build"
author: Kirill 'kkm' Katsnelson
author-link: https://github.com/kkm000
date: "2018-12-18"
date: 2018-12-18
---
As part of Microsoft's move towards its cross-platform .NET offering, they have

View File

@ -1,12 +1,9 @@
---
title: Announcing out-of-the-box support for gRPC in the Flatbuffers serialization library
author: Wouter van Oortmerssen
company: Google
company-link: https://www.google.com
date: "2017-08-17T00:00:00Z"
published: true
title: Announcing out of the box support for gRPC in the Flatbuffers serialization
library.
url: blog/flatbuffers
date: 2017-08-17
---
The recent release of Flatbuffers [version 1.7](https://github.com/google/flatbuffers/releases) introduced truly zero-copy support for gRPC out of the box.
@ -22,9 +19,11 @@ This is currently, fully supported in the C++ implementation of FlatBuffers, wit
## Example Usage
Let's look at an example of how this works.
### Use Flatbuffers as an IDL
Start with an `.fbs` schema (similar to .proto, if you are familiar with protocol buffers) that declares an RPC service:
```proto

View File

@ -1,10 +1,9 @@
---
title: gRPC-Go Engineering Practices
author: Doug Fawley, gRPC-Go TL
company: Google
company-link: google.com
date: "2018-01-22T00:00:00Z"
published: true
title: 2018-01-19 gRPC-Go Engineering Practices
date: 2018-01-22
---
It's the start of the new year, and almost the end of my first full year on the

View File

@ -1,23 +1,20 @@
---
title: gRPC-Go performance Improvements
author: Mahak Mukhi
company: Google
company-link: google.com
date: "2017-08-22T00:00:00Z"
published: true
title: 2017-08-22 gRPC-Go performance Improvements
date: 2017-08-22
---
<p>
<span style="margin-bottom:5%">For past few months we've been working on improving gRPC-Go performance. This includes improving network utilization, optimizing CPU usage and memory allocations. Most of our recent effort has been focused around revamping gRPC-Go flow control. After several optimizations and new features we've been able to improve quite significantly, especially on high-latency networks. We expect users that are working with high-latency networks and large messages to see an order of magnitude performance gain.
For past few months we've been working on improving gRPC-Go performance. This includes improving network utilization, optimizing CPU usage and memory allocations. Most of our recent effort has been focused around revamping gRPC-Go flow control. After several optimizations and new features we've been able to improve quite significantly, especially on high-latency networks. We expect users that are working with high-latency networks and large messages to see an order of magnitude performance gain.
Benchmark results at the end.
This blog summarizes the work we have done so far (in chronological order) to improve performance and lays out our near-future plans.</style>
</p><br>
This blog summarizes the work we have done so far (in chronological order) to improve performance and lays out our near-future plans.
<!--more-->
### Recently Implemented Optimizations
## Recently Implemented Optimizations
###### Expanding stream window on receiving large messages
### Expanding stream window on receiving large messages
[Code link](https://github.com/grpc/grpc-go/pull/1248)
@ -26,7 +23,7 @@ This is an optimization used by gRPC-C to achieve performance benefits for large
This optimization alone provided a 10x improvement for large messages on high-latency networks.
###### Decoupling application reads from connection flow control
### Decoupling application reads from connection flow control
[Code link](https://github.com/grpc/grpc-go/pull/1265)
@ -45,14 +42,13 @@ The need for connection-level flow control:
It is true that stream-level flow control is sufficient to throttle a sender from sending too much data. But not having connection-level flow control (or using an unlimited connection-level window) makes it so that when things get slower on a stream, opening a new one will appear to make things faster. This will only take one so far since the number of streams are limited. However, having a connection-level flow control window set to the Bandwidth Delay Product (BDP) of the network puts an upper-bound on how much performance can realistically be squeezed out of the network.
###### Piggyback window updates
### Piggyback window updates
[Code link](https://github.com/grpc/grpc-go/pull/1273)
Sending a window update itself has a cost associated to it; a flush operation is necessary, which results in a syscall. Syscalls are blocking and slow. Therefore, when sending out a stream-level window update, it makes sense to also check if a connection-level window update can be sent using the same flush syscall.
###### BDP estimation and dynamic flow control window
### BDP estimation and dynamic flow control window
[Code link](https://github.com/grpc/grpc-go/pull/1310)
@ -72,13 +68,11 @@ Given that we're always bound by the flow control of TCP which for most cases is
BDP estimation and dynamically adjusting window sizes is turned-on by default and can be turned off by setting values manually for connection and/or stream window sizes.
###### Near-future efforts
### Near-future efforts
We are now looking into improving our throughput by better CPU utilization, the following efforts are in-line with that.
###### Reducing flush syscalls
### Reducing flush syscalls
We noticed a bug in our transport layer which causes us to make a flush syscall for every data frame we write, even if the same goroutine has more data to send. We can batch a lot of these writes to use only one flush. This in fact will not be a big change to the code itself.
@ -86,15 +80,11 @@ In our efforts to get rid of unnecessary flushes we recently combined the header
Another related idea proposed by one of our users @petermattic in [this](https://github.com/grpc/grpc-go/pull/1373) PR was to combine a server response to a unary RPC into one flush. We are currently looking into that as well.
###### Reducing memory allocation
### Reducing memory allocation
For every data frame read from the wire a new memory allocation takes place. The same holds true at the gRPC layer for every new message for decompressing and decoding. These allocations result in excessive garbage collection cycles, which are expensive. Reusing memory buffers can reduce this GC pressure, and we are prototyping approaches to do so. As requests need buffers of differing sizes, one approach would be to maintain individual memory pools of fixed sizes (powers of two). So now when reading x bytes from the wire we can find the nearest power of 2 greater than x and reuse a buffer from our cache if available or allocate a new one if need be. We will be using golang sync Pools so we don't have to worry about garbage collection. However, we will need to run sufficient tests before committing to this.
###### Results:
### Results
* Benchmark on a real network:
@ -104,18 +94,14 @@ For every data frame read from the wire a new memory allocation takes place. The
* [Code link](https://github.com/grpc/grpc-go/compare/master...MakMukhi:http_greeter)
<table>
<tr><th>Message Size </th><th>GRPC </th><th>HTTP 1.1</th></tr>
<tr><td>1 KB</td><td>~152 ms</td><td>~152 ms</td></tr>
<tr><td>10 KB</td><td>~152 ms</td><td>~152 ms</td></tr>
<tr><td>10 KB</td><td>~152 ms</td><td>~152 ms</td></tr>
<tr><td>1 MB</td><td>~152 ms</td><td>~152 ms</td></tr>
<tr><td>10 MB</td><td>~622 ms</td><td>~630 ms</td></tr>
<tr><td>100 MB</td><td>~5 sec</td><td>~5 sec</td></tr>
</table>
Message size | gRPC | HTTP 1.1
:------------|:-----|:--------
1 KB | ~152 ms | ~152 ms
10 KB | ~152 ms | ~152 ms
10 KB | ~152 ms | ~152 ms
1 MB | ~152 ms | ~152 ms
10 MB | ~622 ms | ~630 ms
100 MB | ~5 sec | ~5 sec
* Benchmark on simulated network:
* Server and client were launched on the same machine and different network latencies were simulated.
@ -124,9 +110,9 @@ For every data frame read from the wire a new memory allocation takes place. The
* Following tables show time taken by first 10 RPCs.
* [Code link](https://github.com/grpc/grpc-go/compare/master...MakMukhi:grpc_vs_http)
##### No Latency Network
##### No-latency Network
| GRPC | HTTP 2.0 | HTTP 1.1 |
| gRPC | HTTP 2.0 | HTTP 1.1 |
| --------------|:-------------:|-----------:|
|5.097809ms|16.107461ms|18.298959ms |
|4.46083ms|4.301808ms|7.715456ms
@ -141,7 +127,7 @@ For every data frame read from the wire a new memory allocation takes place. The
##### Network with RTT of 16ms
| GRPC | HTTP 2.0 | HTTP 1.1 |
| gRPC | HTTP 2.0 | HTTP 1.1 |
| --------------|:-------------:|-----------:|
|118.837625ms|84.453913ms|58.858109ms
|36.801006ms|22.476308ms|20.877585ms

View File

@ -1,11 +1,9 @@
---
title: gRPC Load Balancing
author: makdharma
company: Google
company-link: https://www.google.com
date: "2017-06-15T00:00:00Z"
published: true
title: gRPC Load Balancing
url: blog/loadbalancing
date: 2017-06-15
---
This post describes various load balancing scenarios seen when deploying gRPC. If you use [gRPC](/) with multiple backends, this document is for you.

View File

@ -2,7 +2,7 @@
title: .NET Core ❤ gRPC
author: Sourabh Shirhatti
author-link: https://twitter.com/sshirhatti
date: "2019-09-23"
date: 2019-09-23
---
_This is a guest post by [Sourabh Shirhatti](https://twitter.com/sshirhatti), a Program Manager on the .NET team at Microsoft._

View File

@ -1,24 +1,23 @@
---
author: Jean de Klerk
author-link: https://github.com/jadekler
date: "2018-08-20T00:00:00Z"
published: true
title: gRPC on HTTP/2 Engineering a Robust, High Performance Protocol
url: blog/grpc_on_http2
author: Jean de Klerk
author-link: https://github.com/jadekler
date: 2018-08-20
---
In a [previous article](/blog/http2_smarter_at_scale), we explored how HTTP/2 dramatically increases network efficiency and enables real-time communication by providing a framework for long-lived connections. In this article, well look at how gRPC builds on HTTP/2s long-lived connections to create a performant, robust platform for inter-service communication. We will explore the relationship between gRPC and HTTP/2, how gRPC manages HTTP/2 connections, and how gRPC uses HTTP/2 to keep connections alive, healthy, and utilized.
<!--more-->
## gRPC Semantics
To begin, lets dive into how gRPC concepts relate to HTTP/2 concepts. gRPC introduces three new concepts: *channels* [1], *remote procedure calls* (RPCs), and *messages*. The relationship between the three is simple: each channel may have many RPCs while each RPC may have many messages.
<img src="/img/channels_mapping_2.png" title="Channel Mapping" alt="Channel Mapping" style="max-width: 800px">
![Channel mapping](/img/channels_mapping_2.png)
Lets take a look at how gRPC semantics relate to HTTP/2:
<img src="/img/grpc_on_http2_mapping_2.png" title="gRPC on HTTP/2" alt="gRPC on HTTP/2" style="max-width: 800px">
![gRPC on HTTP/2](/img/grpc_on_http2_mapping_2.png)
Channels are a key concept in gRPC. Streams in HTTP/2 enable multiple concurrent conversations on a single connection; channels extend this concept by enabling multiple streams over multiple concurrent connections. On the surface, channels provide an easy interface for users to send messages into; underneath the hood, though, an incredible amount of engineering goes into keeping these connections alive, healthy, and utilized.
@ -28,9 +27,9 @@ Channels represent virtual connections to an endpoint, which in reality may be b
In order to keep connections alive, healthy, and utilized, gRPC utilizes a number of components, foremost among them *name resolvers* and *load balancers*. The resolver turns names into addresses and then hands these addresses to the load balancer. The load balancer is in charge of creating connections from these addresses and load balancing RPCs between connections.
<img src="/img/dns_to_load_balancer_mapping_3.png" title="Resolvers and Load Balancers" alt="Resolvers and Load Balancers" style="max-width: 800px">
![Resolvers and Load Balancers](/img/dns_to_load_balancer_mapping_3.png)
<img src="/img/load_balance_round_robins_2.png" alt="Round Robin Load Balancer" style="max-width: 800px">
![Round Robin Load Balancer](/img/load_balance_round_robins_2.png)
A DNS resolver, for example, might resolve some host name to 13 IP addresses, and then a RoundRobin balancer might create 13 connections - one to each address - and round robin RPCs across each connection. A simpler balancer might simply create a connection to the first address. Alternatively, a user who wants multiple connections but knows that the host name will only resolve to one address might have their balancer create connections against each address 10 times to ensure that multiple connections are used.

View File

@ -1,10 +1,8 @@
---
title: Visualizing gRPC Language Stacks
author: Carl Mastrangelo
author-link: https://carlmastrangelo.com/
date: "2018-12-11T00:00:00Z"
published: true
title: Visualizing gRPC Language Stacks
url: blog/grpc-stacks
date: 2018-12-11
---
Here is a high level overview of the gRPC Stacks. Each of the **10** default languages supported by gRPC has multiple layers, allowing you to customize what pieces you want in your application.

View File

@ -1,9 +1,7 @@
---
author: Luc Perkins - CNCF, Stanley Cheung - Google, Kailash Sethuraman - Google
date: "2018-10-23T00:00:00Z"
published: true
title: gRPC-Web is Generally Available
url: blog/grpc-web-ga
author: Luc Perkins - CNCF, Stanley Cheung - Google, Kailash Sethuraman - Google
date: 2018-10-23
---
We are excited to announce the GA release of
@ -35,7 +33,6 @@ From a broader architectural perspective, gRPC-Web enables end-to-end gRPC. The
<img src="/img/grpc-web-arch.png" style="max-width: 947px">
<p style="text-align: center"> Figure 1.
gRPC with gRPC-Web (left) and gRPC with REST (right)</p>

View File

@ -1,12 +1,10 @@
---
title: gRPC + JSON
author: Carl Mastrangelo
author-link: https://carlmastrangelo.com
company: Google
company-link: https://www.google.com
date: "2018-08-15T00:00:00Z"
published: true
title: gRPC + JSON
url: blog/grpc-with-json
date: 2018-08-15
---
So you've bought into this whole RPC thing and want to try it out, but aren't quite sure about Protocol Buffers. Your existing code encodes your own objects, or perhaps you have code that needs a particular encoding. What to do?
@ -227,4 +225,3 @@ Almost **10x** faster than before! We can still take advantage of gRPC's effici
gRPC lets you use encoders other than Protobuf. It has no dependency on Protobuf and was specially made to work with a wide variety of environments. We can see that with a little extra boilerplate, we can use any encoder we want. While this post only covered JSON, gRPC is compatible with Thrift, Avro, Flatbuffers, Capn Proto, and even raw bytes! gRPC lets you be in control of how your data is handled. (We still recommend Protobuf though due to strong backwards compatibility, type checking, and performance it gives you.)
All the code is avaialable on [GitHub](https://github.com/carl-mastrangelo/kvstore/tree/04-gson-marshaller) if you would like to see a fully working implementation.

View File

@ -1,10 +1,8 @@
---
title: Dear gRPC
author: April Nassi
author-link: https://www.thisisnotapril.com/
date: "2019-03-08T00:00:00Z"
published: true
title: Dear gRPC
url: blog/hello-pancakes
date: 2019-03-08
---
Dear gRPC,
@ -15,7 +13,7 @@ You're 4 now and that's a big milestone! You're part of so much amazing technolo
We're proud of you, gRPC, and we're going to make this up to you. For starters - we got you a puppy! He's an adorable **G**olden **R**etriever and his name is **P**an**C**akes. He loves to run back and forth with toys, packets, or messages. He's super active and no matter how much we train him, we just can't get him to REST. PanCakes is going to be your best friend, and ambassador.
<img src="https://raw.githubusercontent.com/grpc/grpc-community/master/PanCakes/Pancakes_Birthday.png" alt="gRPC Mascot PanCakes" style="max-width: 547px">
![gRPC Mascot PanCakes](https://raw.githubusercontent.com/grpc/grpc-community/master/PanCakes/Pancakes_Birthday.png)
Even though it's a bit late, we still want to throw you a party, gRPC. Our friends at CNCF have planned a [big event](https://events.linuxfoundation.org/events/grpconf-2019/) for you on March 21, and there's going to be lots of people there! They'll be sharing stories about the cool things they've built, and meeting new people. It's an entire day all about you, and everyone there is going to learn so much. There will be other puppies who can play with PanCakes! Some of the amazing dogs from [Canine Companions for Independence](http://www.cci.org/) will be there to greet conference attendees and share how they help their humans live a more independent life.
@ -23,4 +21,4 @@ We are so excited to see what this year holds for you, gRPC!
~ gRPC Maintainers
<img src="https://raw.githubusercontent.com/grpc/grpc-community/master/PanCakes/Pancakes_Birthday_4.png" alt="gRPC Mascot PanCakes" style="max-width: 547px">
![gRPC Mascot PanCakes](https://raw.githubusercontent.com/grpc/grpc-community/master/PanCakes/Pancakes_Birthday_4.png)

View File

@ -1,12 +1,10 @@
---
title: gRPC in Helm
author: Brian Hardock
company: DEIS
company-link: https://deis.com/
date: "2017-05-15T00:00:00Z"
published: true
date: 2017-05-15
thumbnail: https://gabrtv.github.io/deis-dockercon-2014/img/DeisLogo.png
title: gRPC in Helm
url: blog/helmgrpc
---
*Our guest post today comes from Brian Hardock, a software engineer from Deis working on the [Helm](https://helm.sh/) project.*

View File

@ -1,15 +1,14 @@
---
title: HTTP/2 Smarter At Scale
author: Jean de Klerk
author-link: https://github.com/jadekler
company: Google
company-link: https://www.google.com
date: "2018-07-13T00:00:00Z"
published: true
title: HTTP/2 Smarter At Scale
url: blog/http2_smarter_at_scale
date: 2018-07-13
---
Much of the web today runs on HTTP/1.1. The spec for HTTP/1.1 was published in June of 1999, just shy of 20 years ago. A lot has changed since then, which makes it all the more remarkable that HTTP/1.1 has persisted and flourished for so long. But in some areas its beginning to show its age; for the most part, in that the designers werent building for the scale at which HTTP/1.1 would be used and the astonishing amount of traffic that it would come to handle. A not-so-bad case is that subsequent tests can't pass because of a leaked resource from the previous test. The worst case is that some subsequent tests pass that wouldn't have passed at all if the previously passed test had not leaked a resource.
<!--more-->
HTTP/2, whose specification was published in May of 2015, seeks to address some of the scalability concerns of its predecessor while still providing a similar experience to users. HTTP/2 improves upon HTTP/1.1s design in a number of ways, perhaps most significantly in providing a semantic mapping over connections. In this post well explore the concept of streams and how they can be of substantial benefit to software engineers.
@ -20,7 +19,7 @@ Theres significant overhead to creating HTTP connections. You must establish
HTTP/2 takes the concept of persistent connections further by providing a semantic layer above connections: streams. Streams can be thought of as a series of semantically connected messages, called frames. A stream may be short-lived, such as a unary stream that requests the status of a user (in HTTP/1.1, this might equate to `GET /users/1234/status`). With increasing frequency its long-lived. To use the last example, instead of making individual requests to the /users/1234/status endpoint, a receiver might establish a long-lived stream and thereby continuously receive user status messages in real time.
<img src="/img/conn_stream_frame_mapping.png" alt="Kotlin Android app example" style="max-width: 800px">
![Kotlin Android app example](/img/conn_stream_frame_mapping.png)
## Streams Provide Concurrency
@ -30,13 +29,13 @@ To illustrate this point, consider the case of some service A sending HTTP/1.1 r
In some snapshot in time, service A has a single idle connection to service B and wants to use it to send some data. Service A wants to send a product order (request 1), a profile update (request 2), and two “new user” requests (requests 3 and 4). Since the product order arrives first, it dominates the single idle connection. The latter three smaller requests must either wait for the large product order to be sent, or some number of new HTTP/1.1 connection must be spun up for the small requests.
<img src="/img/http2_queue_3.png" alt="Kotlin Android app example" style="max-width: 800px">
![Kotlin Android app example](/img/http2_queue_3.png)
Meanwhile, with HTTP/2, streaming allows messages to be sent concurrently on the same connection. Lets imagine that service A creates a connection to service B with three streams: a “new users” stream, a “profile updates” stream, and a “product order” stream. Now, the latter requests dont have to wait for the first-to-arrive large product order request; all requests are sent concurrently.
Concurrency does not mean parallelism, though; we can only send one packet at a time on the connection. So, the sender might round robin sending packets between streams (see below). Alternatively, senders might prioritize certain streams over others; perhaps getting new users signed up is more important to the service!
<img src="/img/http2_round_robin.png" alt="Kotlin Android app example" style="max-width: 800px">
![Kotlin Android app example](/img/http2_round_robin.png)
## Flow Control

View File

@ -1,7 +1,7 @@
---
title: gRPC - now with easy installation
attribution: Originally written by Lisa Carey with help from others at Google.
date: "2016-04-04"
date: 2016-04-04
---
Today we are happy to provide an update that significantly simplifies the getting started experience for gRPC.

View File

@ -1,16 +1,16 @@
---
title: gRPC ❤ Kotlin
author: Spencer Fang
author-link: https://github.com/zpencer
company: Google
company-link: https://www.google.com
date: "2018-06-19T00:00:00Z"
published: true
title: gRPC ❤ Kotlin
url: blog/kotlin-gradle-projects
date: 2018-06-19
---
Did you know that gRPC Java now has out of box support for Kotlin projects built with Gradle? [Kotlin](https://kotlinlang.org/) is a modern, statically typed language developed by JetBrains that targets the JVM and Android. It is generally easy for Kotlin programs to interoperate with existing Java libraries. To improve this experience further, we have added support to the [protobuf-gradle-plugin](https://github.com/google/protobuf-gradle-plugin/releases) so that the generated Java libraries are automatically picked up by Kotlin. You can now add the protobuf-gradle-plugin to your Kotlin project, and use gRPC just like you would with a typical Java project.
<!--more-->
The following examples show you how to configure a project for a JVM application and an Android application using Kotlin.
### Kotlin gRPC client and server
@ -20,6 +20,7 @@ The full example can be found [here](https://github.com/grpc/grpc-java/tree/mast
Configuring gRPC for a Kotlin project is the same as configuring it for a Java project.
Below is a snippet of the example project's `build.gradle` highlighting some Kotlin related sections:
```groovy
apply plugin: 'kotlin'
apply plugin: 'com.google.protobuf'
@ -127,6 +128,6 @@ Just like the non-Android project, run `./gradlew generateProto generateProto` t
Finally, test out the Android app by opening the project in Android Studio and selecting `Run > Run 'app'`.
<img src="/img/kotlin-project-android-app.png" alt="Kotlin Android app example" style="max-width: 404px">
![Kotlin Android app example](/img/kotlin-project-android-app.png)
We are excited about improving the gRPC experience for Kotlin developers. Please add enhancement ideas or bugs to the [protobuf-gradle-plugin issue tracker](https://github.com/google/protobuf-gradle-plugin/issues) or the [grpc-java issue tracker](https://github.com/grpc/grpc-java/issues).

View File

@ -1,6 +1,6 @@
---
title: The gRPC Meetup Kit
date: "2017-09-14"
date: 2017-09-14
attribution: Mark Mandel, Sandeep Dinesh
---

View File

@ -1,28 +1,25 @@
---
title: Mobile Benchmarks
attribution: Originally written by David Cao with additional content by Makarand and
others at Google.
author: David Cao
company: Google
company-link: https://cloud.google.com
date: "2016-07-26T00:00:00Z"
published: false
date: 2016-07-26
thumbnail: ../img/gcp-icon.png?raw=true
title: Mobile Benchmarks
url: blog/mobile-benchmarks
---
As gRPC has become a better and faster RPC framework, we've consistently gotten the question, "How _much_ faster is gRPC?" We already have comprehensive server-side benchmarks, but we don't have mobile benchmarks. Benchmarking a client is a bit different than benchmarking a server. We care more about things such as latency and request size and less about things like queries per second (QPS) and number of concurrent threads. Thus we built an Android app in order to quantify these factors and provide solid numbers behind them.
Specifically what we want to benchmark is client side protobuf vs. JSON serialization/deserialization and gRPC vs. a RESTful HTTP JSON service. For the serialization benchmarks, we want to measure the size of messages and speed at which we serialize and deserialize. For the RPC benchmarks, we want to measure the latency of end-to-end requests and packet size.
Protobuf vs. JSON
## Protobuf vs. JSON
In order to benchmark protobuf and JSON, we ran serializations and deserializations over and over on randomly generated protos, which can be seen [here](https://github.com/david-cao/gRPCBenchmarks/tree/master/protolite_app/app/src/main/proto). These protos varied quite a bit in size and complexity, from just a few bytes to over 100kb. JSON equivalents were created and then also benchmarked. For the protobuf messages, we had three main methods of serializing and deserializing: simply using a byte array, `CodedOutputStream`/`CodedInputStream` which is protobuf's own implementation of input and output streams, and Java's `ByteArrayOutputStream` and `ByteArrayInputStream`. For JSON we used `org.json`'s [`JSONObject`](https://developer.android.com/reference/org/json/JSONObject.html). This only had one method to serialize and deserialize, `toString()` and `new JSONObject()`, respectively.
In order to keep benchmarks as accurate as possible, we wrapped the code to be benchmarked in an interface and simply looped it for a set number of iterations. This way we discounted any time spent checking the system time.
``` Java
```java
interface Action {
void execute();
}
@ -39,6 +36,7 @@ for (int i = 0; i < 100; ++i) {
a.execute();
}
```
Before running a benchmark, we ran a warmup in order to clean out any erratic behaviour by the JVM, and then calculated the number of iterations needed to run for a set time (10 seconds in the protobuf vs. JSON case). To do this, we started with 1 iteration, measured the time it took for that run, and compared it to a minimum sample time (2 seconds in our case). If the number of iterations took long enough, we estimated the number of iterations needed to run for 10 seconds by doing some math. Otherwise, we multiplied the number of iterations by 2 and repeated.
```Java
@ -54,22 +52,19 @@ while (elapsed < MIN_SAMPLE_TIME_MS) {
iterations = (int) ((TARGET_TIME_MS / (double) elapsed) * iterations);
```
Results
## Results
Benchmarks were run on protobuf, JSON, and gzipped JSON.
We found that regardless of the serialization/deserialization method used for protobuf, it was consistently about 3x faster for serializing than JSON. For deserialization, JSON is actually a bit faster for small messages (<1kb), around 1.5x, but for larger messages (>15kb) protobuf is 2x faster. For gzipped JSON, protobuf is well over 5x faster in serialization, regardless of size. For deserialization, both are about the same at small messages, but protobuf is about 3x faster for larger messages. Results can be explored in more depth and replicated [here](/github_readme).
gRPC vs. HTTP JSON
We found that regardless of the serialization/deserialization method used for protobuf, it was consistently about 3x faster for serializing than JSON. For deserialization, JSON is actually a bit faster for small messages (<1kb), around 1.5x, but for larger messages (>15kb) protobuf is 2x faster. For gzipped JSON, protobuf is well over 5x faster in serialization, regardless of size. For deserialization, both are about the same at small messages, but protobuf is about 3x faster for larger messages. Results can be explored in more depth and replicated [in the README](https://github.com/david-cao/gRPCBenchmarks).
## gRPC vs. HTTP JSON
To benchmark RPC calls, we want to measure end-to-end latency and bandwidth. To do this, we ping pong with a server for 60 seconds, using the same message each time, and measure the latency and message size. The message consists of some fields for the server to read, and a payload of bytes. We compared gRPC's unary call to a simple RESTful HTTP JSON service. The gRPC benchmark creates a channel, and starts a unary call that repeats when it recieves a response until 60 seconds have passed. The response contains a proto with the same payload sent.
Similarly for the HTTP JSON benchmarks, it sends a POST request to the server with an equivalent JSON object, and the server sends back a JSON object with the same payload.
```Java
```java
// This can be found in AsyncClient.java doUnaryCalls()
// Make stub to send unary call
final BenchmarkServiceStub stub = BenchmarkServiceGrpc.newStub(channel);
@ -109,11 +104,11 @@ stub.unaryCall(request, new StreamObserver<SimpleResponse>() {
}
});
```
Both `HttpUrlConnection` and the [OkHttp library](https://square.github.io/okhttp/) were used.
Only gRPC's unary calls were benchmarked against HTTP, since streaming calls were over 2x faster than the unary calls. Moreover, HTTP has no equivalent of streaming, which is an HTTP/2 specific feature.
## Results
Results
In terms of latency, gRPC is **5x-10x** faster up to the 95th percentile, with averages of around 2 milliseconds for an end-to-end request. For bandwidth, gRPC is about 3x faster for small requests (100-1000 byte payload), and consistently 2x faster for large requests (10kb-100kb payload). To replicate these results or explore in more depth, check out our [repository](/github_readme).
In terms of latency, gRPC is **5x-10x** faster up to the 95th percentile, with averages of around 2 milliseconds for an end-to-end request. For bandwidth, gRPC is about 3x faster for small requests (100-1000 byte payload), and consistently 2x faster for large requests (10kb-100kb payload). To replicate these results or explore in more depth, check out our [repository](https://github.com/david-cao/gRPCBenchmarks).

View File

@ -1,12 +1,10 @@
---
title: So You Want to Optimize gRPC - Part 1
author: Carl Mastrangelo
author-link: https://github.com/carl-mastrangelo
company: Google
company-link: https://www.google.com
date: "2018-03-06T00:00:00Z"
published: true
title: So You Want to Optimize gRPC - Part 1
url: blog/optimizing-grpc-part-1
date: 2018-03-06
---
A common question with gRPC is how to make it fast. The gRPC library offers users access to high
@ -61,26 +59,26 @@ As mentioned above, the client makes random RPCs. For example, here is the code
request:
```java
private void doCreate(KeyValueServiceBlockingStub stub) {
ByteString key = createRandomKey();
try {
CreateResponse res = stub.create(
CreateRequest.newBuilder()
.setKey(key)
.setValue(randomBytes(MEAN_VALUE_SIZE))
.build());
if (!res.equals(CreateResponse.getDefaultInstance())) {
throw new RuntimeException("Invalid response");
}
} catch (StatusRuntimeException e) {
if (e.getStatus().getCode() == Code.ALREADY_EXISTS) {
knownKeys.remove(key);
logger.log(Level.INFO, "Key already existed", e);
} else {
throw e;
}
private void doCreate(KeyValueServiceBlockingStub stub) {
ByteString key = createRandomKey();
try {
CreateResponse res = stub.create(
CreateRequest.newBuilder()
.setKey(key)
.setValue(randomBytes(MEAN_VALUE_SIZE))
.build());
if (!res.equals(CreateResponse.getDefaultInstance())) {
throw new RuntimeException("Invalid response");
}
} catch (StatusRuntimeException e) {
if (e.getStatus().getCode() == Code.ALREADY_EXISTS) {
knownKeys.remove(key);
logger.log(Level.INFO, "Key already existed", e);
} else {
throw e;
}
}
}
```
A random key is created, along with a random value. The request is sent to the server, and the
@ -101,21 +99,21 @@ On the server side, the request is received by the
[service handler](https://github.com/carl-mastrangelo/kvstore/blob/f422b1b6e7c69f8c07f96ed4ddba64757242352c/src/main/java/io/grpc/examples/KvService.java#L34):
```java
private final Map<ByteBuffer, ByteBuffer> store = new HashMap<>();
private final Map<ByteBuffer, ByteBuffer> store = new HashMap<>();
@Override
public synchronized void create(
CreateRequest request, StreamObserver<CreateResponse> responseObserver) {
ByteBuffer key = request.getKey().asReadOnlyByteBuffer();
ByteBuffer value = request.getValue().asReadOnlyByteBuffer();
simulateWork(WRITE_DELAY_MILLIS);
if (store.putIfAbsent(key, value) == null) {
responseObserver.onNext(CreateResponse.getDefaultInstance());
responseObserver.onCompleted();
return;
}
responseObserver.onError(Status.ALREADY_EXISTS.asRuntimeException());
@Override
public synchronized void create(
CreateRequest request, StreamObserver<CreateResponse> responseObserver) {
ByteBuffer key = request.getKey().asReadOnlyByteBuffer();
ByteBuffer value = request.getValue().asReadOnlyByteBuffer();
simulateWork(WRITE_DELAY_MILLIS);
if (store.putIfAbsent(key, value) == null) {
responseObserver.onNext(CreateResponse.getDefaultInstance());
responseObserver.onCompleted();
return;
}
responseObserver.onError(Status.ALREADY_EXISTS.asRuntimeException());
}
```
The service extracts the key and value as `ByteBuffer`s from the request. It acquires the lock
@ -164,21 +162,21 @@ decides](https://github.com/carl-mastrangelo/kvstore/blob/f422b1b6e7c69f8c07f96e
what operation to do:
```java
void doClientWork(AtomicBoolean done) {
Random random = new Random();
KeyValueServiceBlockingStub stub = KeyValueServiceGrpc.newBlockingStub(channel);
void doClientWork(AtomicBoolean done) {
Random random = new Random();
KeyValueServiceBlockingStub stub = KeyValueServiceGrpc.newBlockingStub(channel);
while (!done.get()) {
// Pick a random CRUD action to take.
int command = random.nextInt(4);
if (command == 0) {
doCreate(stub);
continue;
}
/* ... */
rpcCount++;
while (!done.get()) {
// Pick a random CRUD action to take.
int command = random.nextInt(4);
if (command == 0) {
doCreate(stub);
continue;
}
/* ... */
rpcCount++;
}
}
```
This means that **at most one RPC can be active at any time**. Each RPC has to wait for the
@ -192,7 +190,7 @@ Our code can do about 16 queries in a second, so that seems about right. We can
assumption by looking at the output of the `time` command used to run the code. The server goes
to sleep when running queries in the
[`simulateWork`](https://github.com/carl-mastrangelo/kvstore/blob/f422b1b6e7c69f8c07f96ed4ddba64757242352c/src/main/java/io/grpc/examples/KvService.java#L88)
method. This implies that the program should be mostly idle while waiting for the RPCs to
method. This implies that the program should be mostly idle while waiting for the RPCs to
complete.
We can confirm this is the case by looking at the `real` and `user` times of the command above.
@ -228,39 +226,39 @@ is still roughly from top to bottom in the function. Here is the
method revised:
```java
private void doCreate(KeyValueServiceFutureStub stub, AtomicReference<Throwable> error) {
ByteString key = createRandomKey();
ListenableFuture<CreateResponse> res = stub.create(
CreateRequest.newBuilder()
.setKey(key)
.setValue(randomBytes(MEAN_VALUE_SIZE))
.build());
res.addListener(() -> rpcCount.incrementAndGet(), MoreExecutors.directExecutor());
Futures.addCallback(res, new FutureCallback<CreateResponse>() {
@Override
public void onSuccess(CreateResponse result) {
if (!result.equals(CreateResponse.getDefaultInstance())) {
error.compareAndSet(null, new RuntimeException("Invalid response"));
}
synchronized (knownKeys) {
knownKeys.add(key);
}
private void doCreate(KeyValueServiceFutureStub stub, AtomicReference<Throwable> error) {
ByteString key = createRandomKey();
ListenableFuture<CreateResponse> res = stub.create(
CreateRequest.newBuilder()
.setKey(key)
.setValue(randomBytes(MEAN_VALUE_SIZE))
.build());
res.addListener(() -> rpcCount.incrementAndGet(), MoreExecutors.directExecutor());
Futures.addCallback(res, new FutureCallback<CreateResponse>() {
@Override
public void onSuccess(CreateResponse result) {
if (!result.equals(CreateResponse.getDefaultInstance())) {
error.compareAndSet(null, new RuntimeException("Invalid response"));
}
synchronized (knownKeys) {
knownKeys.add(key);
}
}
@Override
public void onFailure(Throwable t) {
Status status = Status.fromThrowable(t);
if (status.getCode() == Code.ALREADY_EXISTS) {
synchronized (knownKeys) {
knownKeys.remove(key);
}
logger.log(Level.INFO, "Key already existed", t);
} else {
error.compareAndSet(null, t);
@Override
public void onFailure(Throwable t) {
Status status = Status.fromThrowable(t);
if (status.getCode() == Code.ALREADY_EXISTS) {
synchronized (knownKeys) {
knownKeys.remove(key);
}
logger.log(Level.INFO, "Key already existed", t);
} else {
error.compareAndSet(null, t);
}
});
}
}
});
}
```
The stub has been modified to be a `KeyValueServiceFutureStub`, which produces a `Future` when
@ -323,23 +321,23 @@ permit. To [accomplish](https://github.com/carl-mastrangelo/kvstore/blob/02-fut
this, we will using a `Semaphore`:
```java
private final Semaphore limiter = new Semaphore(100);
private final Semaphore limiter = new Semaphore(100);
private void doCreate(KeyValueServiceFutureStub stub, AtomicReference<Throwable> error)
throws InterruptedException {
limiter.acquire();
ByteString key = createRandomKey();
ListenableFuture<CreateResponse> res = stub.create(
CreateRequest.newBuilder()
.setKey(key)
.setValue(randomBytes(MEAN_VALUE_SIZE))
.build());
res.addListener(() -> {
rpcCount.incrementAndGet();
limiter.release();
}, MoreExecutors.directExecutor());
/* ... */
}
private void doCreate(KeyValueServiceFutureStub stub, AtomicReference<Throwable> error)
throws InterruptedException {
limiter.acquire();
ByteString key = createRandomKey();
ListenableFuture<CreateResponse> res = stub.create(
CreateRequest.newBuilder()
.setKey(key)
.setValue(randomBytes(MEAN_VALUE_SIZE))
.build());
res.addListener(() -> {
rpcCount.incrementAndGet();
limiter.release();
}, MoreExecutors.directExecutor());
/* ... */
}
```
Now the code runs successfully, and doesn't run out of memory.
@ -396,4 +394,3 @@ the very basics of how to approach and think about optimization. Always make su
before and after your changes, and use these measurements to guide your optimizations.
In [Part 2](/blog/optimizing-grpc-part-2), we will continue optimizing the server part of the code.

View File

@ -1,12 +1,10 @@
---
title: So You Want to Optimize gRPC - Part 2
author: Carl Mastrangelo
author-link: https://carlmastrangelo.com/
company: Google
company-link: https://www.google.com
date: "2018-04-16T00:00:00Z"
published: true
title: So You Want to Optimize gRPC - Part 2
url: blog/optimizing-grpc-part-2
date: 2018-04-16
---
How fast is gRPC? Pretty fast if you understand how modern clients and servers are built. In
@ -32,21 +30,21 @@ accidentally corrupt the state of storage. To ensure this, the service uses the
keyword to ensure only one RPC is active at a time:
```java
private final Map<ByteBuffer, ByteBuffer> store = new HashMap<>();
private final Map<ByteBuffer, ByteBuffer> store = new HashMap<>();
@Override
public synchronized void create(
CreateRequest request, StreamObserver<CreateResponse> responseObserver) {
ByteBuffer key = request.getKey().asReadOnlyByteBuffer();
ByteBuffer value = request.getValue().asReadOnlyByteBuffer();
simulateWork(WRITE_DELAY_MILLIS);
if (store.putIfAbsent(key, value) == null) {
responseObserver.onNext(CreateResponse.getDefaultInstance());
responseObserver.onCompleted();
return;
}
responseObserver.onError(Status.ALREADY_EXISTS.asRuntimeException());
@Override
public synchronized void create(
CreateRequest request, StreamObserver<CreateResponse> responseObserver) {
ByteBuffer key = request.getKey().asReadOnlyByteBuffer();
ByteBuffer value = request.getValue().asReadOnlyByteBuffer();
simulateWork(WRITE_DELAY_MILLIS);
if (store.putIfAbsent(key, value) == null) {
responseObserver.onNext(CreateResponse.getDefaultInstance());
responseObserver.onCompleted();
return;
}
responseObserver.onError(Status.ALREADY_EXISTS.asRuntimeException());
}
```
While this code is thread safe, it comes at a high price: only one RPC can ever be active! We
@ -81,21 +79,21 @@ Concurrent maps provide stronger guarantees about the safety of `putIfAbsent`, s
`HashMap` to a `ConcurrentHashMap` and remove `synchronized`:
```java
private final ConcurrentMap<ByteBuffer, ByteBuffer> store = new ConcurrentHashMap<>();
@Override
public void create(
CreateRequest request, StreamObserver<CreateResponse> responseObserver) {
ByteBuffer key = request.getKey().asReadOnlyByteBuffer();
ByteBuffer value = request.getValue().asReadOnlyByteBuffer();
simulateWork(WRITE_DELAY_MILLIS);
if (store.putIfAbsent(key, value) == null) {
responseObserver.onNext(CreateResponse.getDefaultInstance());
responseObserver.onCompleted();
return;
}
responseObserver.onError(Status.ALREADY_EXISTS.asRuntimeException());
private final ConcurrentMap<ByteBuffer, ByteBuffer> store = new ConcurrentHashMap<>();
@Override
public void create(
CreateRequest request, StreamObserver<CreateResponse> responseObserver) {
ByteBuffer key = request.getKey().asReadOnlyByteBuffer();
ByteBuffer value = request.getValue().asReadOnlyByteBuffer();
simulateWork(WRITE_DELAY_MILLIS);
if (store.putIfAbsent(key, value) == null) {
responseObserver.onNext(CreateResponse.getDefaultInstance());
responseObserver.onCompleted();
return;
}
responseObserver.onError(Status.ALREADY_EXISTS.asRuntimeException());
}
```
### If at First You Don't Succeed
@ -104,21 +102,21 @@ Updating `create` was pretty easy. Doing the same for `retrieve` and `delete` i
However, the `update` method is a little trickier. Let's take a look at what it's doing:
```java
@Override
public synchronized void update(
UpdateRequest request, StreamObserver<UpdateResponse> responseObserver) {
ByteBuffer key = request.getKey().asReadOnlyByteBuffer();
ByteBuffer newValue = request.getValue().asReadOnlyByteBuffer();
simulateWork(WRITE_DELAY_MILLIS);
ByteBuffer oldValue = store.get(key);
if (oldValue == null) {
responseObserver.onError(Status.NOT_FOUND.asRuntimeException());
return;
}
store.replace(key, oldValue, newValue);
responseObserver.onNext(UpdateResponse.getDefaultInstance());
responseObserver.onCompleted();
@Override
public synchronized void update(
UpdateRequest request, StreamObserver<UpdateResponse> responseObserver) {
ByteBuffer key = request.getKey().asReadOnlyByteBuffer();
ByteBuffer newValue = request.getValue().asReadOnlyByteBuffer();
simulateWork(WRITE_DELAY_MILLIS);
ByteBuffer oldValue = store.get(key);
if (oldValue == null) {
responseObserver.onError(Status.NOT_FOUND.asRuntimeException());
return;
}
store.replace(key, oldValue, newValue);
responseObserver.onNext(UpdateResponse.getDefaultInstance());
responseObserver.onCompleted();
}
```
Updating a key to a new value needs two interactions with the `store`:
@ -135,21 +133,21 @@ was successful. (`ConcurrentMap` asserts that the operations will not corrupt t
structure, but doesn't say that they will succeed!) We will use a do-while loop:
```java
@Override
public void update(
UpdateRequest request, StreamObserver<UpdateResponse> responseObserver) {
// ...
ByteBuffer oldValue;
do {
oldValue = store.get(key);
if (oldValue == null) {
responseObserver.onError(Status.NOT_FOUND.asRuntimeException());
return;
}
} while (!store.replace(key, oldValue, newValue));
responseObserver.onNext(UpdateResponse.getDefaultInstance());
responseObserver.onCompleted();
}
@Override
public void update(
UpdateRequest request, StreamObserver<UpdateResponse> responseObserver) {
// ...
ByteBuffer oldValue;
do {
oldValue = store.get(key);
if (oldValue == null) {
responseObserver.onError(Status.NOT_FOUND.asRuntimeException());
return;
}
} while (!store.replace(key, oldValue, newValue));
responseObserver.onNext(UpdateResponse.getDefaultInstance());
responseObserver.onCompleted();
}
```
The code wants to fail if it ever sees null, but never if there is a non-null previous value. One
@ -229,4 +227,3 @@ need to understand what your code is doing. This post shows how to convert a lo
a low-contention, lock-free service. Always make sure to measure before and after your changes.
In Part 3, we will optimize the code even further. 2,400 RPC/s is just the beginning!

View File

@ -1,6 +1,6 @@
---
title: gRPC Motivation and Design Principles
date: "2015-09-08"
date: 2015-09-08
attribution: Originally written by Louis Ryan with help from others at Google
---

View File

@ -1,9 +1,7 @@
---
attribution: Originally written by Lisa Carey with help from others at Google.
date: "2016-03-24T00:00:00Z"
published: true
title: Google Cloud PubSub - with the power of gRPC!
url: blog/pubsub
attribution: Originally written by Lisa Carey with help from others at Google.
date: 2016-03-24
---
[Google Cloud PubSub](https://cloud.google.com/pubsub/) is Google's scalable real-time messaging service that lets users send and receive messages between independent applications. It's an important part of Google Cloud Platform's big data offering, and is used by customers worldwide to build their own robust, global services. However, until now, the only way to use the Cloud PubSub API was via JSON over HTTP. That's all changed with the release of [PubSub gRPC alpha](https://cloud.google.com/blog/big-data/2016/03/announcing-grpc-alpha-for-google-cloud-pubsub). Now **users can access PubSub via gRPC** and benefit from all the advantages it brings.

View File

@ -1,10 +1,8 @@
---
title: The state of gRPC in the browser
author: Johan Brandhorst
author-link: https://jbrandhorst.com/
date: "2019-01-08T00:00:00Z"
published: true
title: The state of gRPC in the browser
url: blog/state-of-grpc-web
date: 2019-01-08
---
_This is a guest post by_

View File

@ -1,20 +1,20 @@
---
title: Take the gRPC Survey!
author: Kailash Sethuraman
author-link: https://github.com/hsaliak
company: Google
company-link: https://www.google.com
date: "2018-08-14T00:00:00Z"
published: true
title: Take the gRPC Survey!
url: blog/take-the-grpc-survey
date: 2018-08-14
---
## The gRPC Project wants your feedback!
The gRPC project is looking for feedback to improve the gRPC experience. To do this, we are running a [gRPC user survey](http://bit.ly/gRPC18survey). We invite you to participate and provide input that will help us better plan and prioritize.
<!--more-->
## gRPC User Survey
**Who** : If you currently use gRPC, have used gRPC in the past, or have any interest in it, we would love to hear from you.
**Where**: Please take this 15 minute survey by Friday, 24th August.
@ -23,7 +23,7 @@ The gRPC project is looking for feedback to improve the gRPC experience. To do t
## Spread the word!
Please help us spread the word on this survey by posting it on your social networks and sharing with your friends. Every single feedback is precious, and we would like as much of it as possible!
Survey Short link: [http://bit.ly/gRPC18survey
](http://bit.ly/gRPC18survey)
Survey Short link: [http://bit.ly/gRPC18survey](http://bit.ly/gRPC18survey)

View File

@ -5,38 +5,30 @@ attribution: Originally written by Dale Hopkins with additional content by Lisa
author: Dale Hopkins
company: Vendasta
company-link: https://vendasta.com
date: "2016-07-25"
published: false
date: 2016-08-29
thumbnail: ../img/vend-icon.png?raw=true
aliases: ["blog/vendastagrpc"]
---
Our guest post today comes from Dale Hopkins, CTO of [Vendasta](https://vendasta.com/). Vendasta started out 8 years ago as a point solution provider of products for small business. From the beginning we partnered with media companies and agencies who have armies of salespeople and existing relationships with those businesses to sell our software. It is estimated that over 30 million small businesses exist in the United States alone, so scalability of our SaaS solution was considered one of our top concerns from the beginning and it was the reason we started with Google App Engine (Python GAE) and Datastore. This solution worked really well for us as our system scaled from hundreds to hundreds of thousands of end users. We also scaled our offering from a point solution to an entire platform with multiple products and the tools for partners to manage their sales of those products during this time.
Our guest post today comes from Dale Hopkins, CTO of [Vendasta](https://vendasta.com/).
Vendasta started out 8 years ago as a point solution provider of products for small business. From the beginning we partnered with media companies and agencies who have armies of salespeople and existing relationships with those businesses to sell our software. It is estimated that over 30 million small businesses exist in the United States alone, so scalability of our SaaS solution was considered one of our top concerns from the beginning and it was the reason we started with [Google App Engine](https://cloud.google.com/appengine/) and Datastore. This solution worked really well for us as our system scaled from hundreds to hundreds of thousands of end users. We also scaled our offering from a point solution to an entire platform with multiple products and the tools for partners to manage their sales of those products during this time.
<!--more-->
All throughout this journey Python GAE served our needs well. We exposed a number of APIs via HTTP + JSON for our partners to automate tasks and integrate their other systems with our products and platform. However, in 2016 we introduced the Vendasta Marketplace. This marked a major change to our offering, which depended heavily on having 3rd party vendors use our APIs to deliver their own products in our platform. This was a major change because our public APIs provide an upper-bound on 3rd-party applications, and made us realize that we really needed to make APIs that were amazing, not just good.
The first optimization that we started with was to use the Go programming language to build endpoints that handled higher throughput with lower latency than we could get with Python. On some APIs this made an incredible difference: we saw 50th percentile response times to drop from 1200 ms to 4 ms, and even more spectacularly 99th percentile response times drop from 30,000 ms to 12 ms! On other APIs we saw a much smaller, but still significant difference.
# Three Optimizations to our architecture
The second optimization we used was to replicate large portions of our Datastore data into ElasticSearch. ElasticSearch is a fundamentally different storage technology to Datastore, and is not a managed service, so it was a big leap for us. But this change allowed us to migrate almost all of our overnight batch-processing APIs to real-time APIs. We had tried BigQuery, but it's query processing times meant that we couldn't display things in real time. We had tried cloudSQL, but there was too much data for it to easily scale. We had tried the appengine Search API, but it has limitations with result sets over 10,000. We instead scaled up our ElasticSearch cluster using [Google Container Engine](https://cloud.google.com/container-engine/) and with it's powerful aggregations and facet processing our needs were easily met. So with these first two solutions in place, we had made meaningful changes to the performance of our APIs.
* The first optimization that we started with was to use the Go programming language to build endpoints that handled higher throughput with lower latency than we could get with Python. On some APIs this made an incredible difference: we saw 50th percentile response times to drop from 1200 ms to 4 ms, and even more spectacularly 99th percentile response times drop from 30,000 ms to 12 ms! On other APIs we saw a much smaller, but still significant difference.
The last optimization we made was to move our APIs to [gRPC](/). This change was much more extensive than the others as it affected our clients. Like ElasticSearch, it represents a fundamentally different model with differing performance characteristics, but unlike ElasticSearch we found it to be a true superset: all of our usage scenarios were impacted positively by it.
* The second optimization we used was to replicate large portions of our Datastore data into ElasticSearch. ElasticSearch is a fundamentally different storage technology to Datastore, and is not a managed service, so it was a big leap for us. But this change allowed us to migrate almost all of our overnight batch-processing APIs to real-time APIs. So with these first two solutions in place, we had made meaningful changes to the performance of our APIs.
* The last optimization we made was to move our APIs to gRPC. This change was much more extensive than the others as it affected our clients. Like ElasticSearch, it represents a fundamentally different model with differing performance characteristics, but unlike ElasticSearch we found it to be a true superset: all of our usage scenarios were impacted positively by it.
## Four Benefits from gRPC
The first benefit we saw from gRPC was the ability to move from publishing APIs and asking developers to integrate with them, to releasing SDKs and asking developers to copy-paste example code written in their language. This represents a really big benefit for people looking to integrate with our products, while not requiring us to hand-roll entire SDKs in the 5+ languages our partners and vendors use. It is important to note that we still write light wrappers over the generated gRPC SDKs to make them package-manager friendly, and to provide wrappers over the generated protobuf structures.
* The first benefit we saw from gRPC was the ability to move from publishing APIs and asking developers to integrate with them, to releasing SDKs and asking developers to copy-paste example code written in their language. This represents a really big benefit for people looking to integrate with our products, while not requiring us to hand-roll entire SDKs in the 5+ languages our partners and vendors use. It is important to note that we still write light wrappers over the generated gRPC SDKs to make them package-manager friendly, and to provide wrappers over the generated protobuf structures.
The second benefit we saw from gRPC was the ability to break free from the call-and-response architecture necessitated by HTTP + JSON. gRPC is built on top of HTTP/2, which allows for client-side and/or server-side streaming. In our use cases, this means we can lower the time to first display by streaming results as they become ready on the server (server-side streaming). We have also been investigating the potential to offer very flexible create endpoints that easily support bulk ingestion with bi-directional streaming, this would mean we would allow the client to asynchronously stream results, while the server would stream back statuses allowing for easy checkpoint operations while not slowing upload speeds to wait for confirmations. We feel that we are just starting to see the benefits from this feature as it opens up a totally new model for client-server interactions that just wasn't possible with HTTP.
* The second benefit we saw from gRPC was the ability to break free from the call-and-response architecture necessitated by HTTP + JSON. gRPC is built on top of HTTP/2, which allows for client-side and/or server-side streaming. In our use cases, this means we can lower the time to first display by streaming results as they become ready on the server (server-side streaming), and by providing very flexible create endpoints that easily support bulk ingestion (bi-directional streaming). We feel that we are just starting to see the benefits from this feature as it opens up a totally new model for client-server interactions that just wasn't possible with HTTP.
* The third benefit was the switch from JSON to protocol buffers, which works very well with gRPC. This improves serialization and deserialization times; which is very significant to some of our APIs, but appreciated on all of them. The more important benefit comes from the explicit format specification of proto, meaning that clients receive typed objects rather than free-form JSON. Because of this, our clients can reap the benefits of auto-completion in their IDEs, type-safety if their language supports it, and enforced compatibility between clients and servers with differing versions.
* The final benefit of gRPC was our ability to quickly spec endpoints. The proto format for both data and service definition greatly simplifies defining new endpoints and finally allows the succinct definition of endpoint contracts. Combined with code generation, it allows us to truly develop clients and servers in parallel.
Our experience with gRPC has been positive, even though it does not eliminate the difficulty of providing endpoints to partners and vendors, and address of our performance issues. However, it does make improvements to our endpoint performance, integration with those endpoints, and even in delivery of SDKs.
The third benefit was the switch from JSON to protocol buffers, which works very well with gRPC. This improves serialization and deserialization times; which is very significant to some of our APIs, but appreciated on all of them. The more important benefit comes from the explicit format specification of proto, meaning that clients receive typed objects rather than free-form JSON. Because of this, our clients can reap the benefits of auto-completion in their IDEs, type-safety if their language supports it, and enforced compatibility between clients and servers with differing versions.
The final benefit of gRPC was our ability to quickly spec endpoints. The proto format for both data and service definition greatly simplifies defining new endpoints and finally allows the succinct definition of endpoint contracts. This means we are much better able to communicate endpoint specifications between our development teams. gRPC means that for the first time at our company we are able to simultaneously develop the client and the server side of our APIs! This means our latency to produce new APIs with the accompanying SDKs has dropped dramatically. Combined with code generation, it allows us to truly develop clients and servers in parallel.
Our experience with gRPC has been positive, even though it does not eliminate the difficulty of providing endpoints to partners and vendors, and address all of our performance issues. However, it does make improvements to our endpoint performance, integration with those endpoints, and even in delivery of SDKs.

View File

@ -1,14 +1,13 @@
---
title: gRPC at VSCO
attribution: Thanks to the VSCO engineers that worked on this migration.Steven Tang,
Sam Bobra, Daniel Song, Lucas Kacher, and many others.
author: Robert Sayre and Melinda Lu
company: VSCO
company-link: https://vsco.co
date: "2016-09-06T00:00:00Z"
published: true
date: 2016-09-06
thumbnail: ../img/vsco-logo.png?raw=true
title: gRPC at VSCO
url: blog/vscogrpc
aliases: ["blog/vscogrpc"]
---
Our guest post today comes from Robert Sayre and Melinda Lu of VSCO.

View File

@ -1,12 +1,10 @@
---
title: Migration to Google Cloud PlatformgRPC & grpc-gateway
author: Miguel Mendez
company: Yik Yak
company-link: https://yikyakapp.com
date: "2017-04-12T00:00:00Z"
published: true
date: 2017-04-12
thumbnail: https://cdn-images-1.medium.com/max/1600/0*qYehJ2DvPgFcG_nX.
title: Migration to Google Cloud PlatformgRPC & grpc-gateway
url: blog/yygrpc
---
Our guest post today comes from [Miguel Mendez](https://www.linkedin.com/in/miguel-mendez-008231/) of Yik Yak.
@ -36,18 +34,17 @@ Third, it is great that I can use curl from the command line to hit an API, but
The fourth problem with a REST APIs is that, at least until [Swagger](https://swagger.io/) arrived on the scene, there was no declarative way to define a REST API and include type information. It may sound pedantic, but there are legitimate reasons to want a proper definition that includes type information in general. To reinforce the point, look at the lines of PHP server code below, which were extracted from various files, that set the “hidePin” field on “yak” which was then returned to the client. The actual line of code that executed on the server was a function of multiple parameters, so imagine that the one which was run was basically chosen at random:
```php
// Code omitted…
$yak->hidePin=false;
// Code omitted…
$yak->hidePin=true;
// Code omitted…
$yak->hidePin=0;
// Code omitted…
$yak->hidePin=1;
// Code omitted…
$yak->hidePin=false;
// Code omitted…
$yak->hidePin=true;
// Code omitted…
$yak->hidePin=0;
// Code omitted…
$yak->hidePin=1;
```
What is the type of the field hidePin? You cannot say for certain. It could be a boolean or an integer or whatever happens to have been written there by the server, but in any case now your clients have to be able to deal with these possibilities which makes them more complicated.
@ -55,51 +52,59 @@ What is the type of the field hidePin? You cannot say for certain. It could be a
Problems can also arise when the clients definition of a type varies from that which the server expects. Have a look at the server code below which processed a JSON payload sent up by a client:
```php
// Code omitted…
switch ($fieldName) {
// Code omitted…
case “recipientID”:
// This is being added because iOS is passing the recipientID
// incorrectly and we still want to capture these events
// … expected fall through …
case “Recipientid”:
$this->yakkerEvent->recipientID = $value;
break;
// Code omitted…
}
// Code omitted…
// Code omitted...
switch ($fieldName) {
// Code omitted...
case “recipientID”:
// This is being added because iOS is passing the recipientID
// incorrectly and we still want to capture these events
// … expected fall through …
case “Recipientid”:
$this->yakkerEvent->recipientID = $value;
break;
// Code omitted...
}
// Code omitted...
```
In this case, the server had to deal with an iOS client that sent a JSON object whose field name used unexpected casing. Again, not insurmountable but all of these little disconnects compound and work together to steal time away from the problems that really move the ball down the field.
## gRPC can address the issues with REST…
## gRPC can address the issues with REST
If youre not familiar with gRPC, its a “high performance, open-source universal remote procedure call (RPC) framework” that uses Google Protocol Buffers as the Interface Description Language (IDL) for describing a service interface as well as the structure of the messages exchanged. This IDL can then be compiled to produce language-specific client and server stubs. In case that seemed a little obtuse, Ill zoom into the aspects that are important.
### gRPC is Declarative, Strongly-Typed, and Language Independent
gRPC descriptions are written using an Interface Description Language that is independent of any specific programming language, yet its concepts map onto the supported languages. This means that you can describe your ideal service API, the messages that it supports, and then use “protoc”, the protocol compiler, to generate client and server stubs for your API. Out of the box, you can produce client and server stubs in C/C++, C#, Node.js, PHP, Ruby, Python, Go and Java. You can also get additional protoc plugins which can create stubs for Objective-C and Swift.
Those issues that we had with “hidePin” and “recipientID” vs.”Recipientid” fields above go away because we have a single, canonical declaration that establishes the types used, and the language-specific code generation ensures that we dont have typos in the client or server code regardless of their implementation language.
### gRPC Means No hand-rolling of RPC Code is Required
This is a very powerful aspect of the gRPC ecosystem. Often times developers will hand roll their RPC code because it just seems more straightforward. However, as the number of types of clients that you need to support increases, the carrying costs of this approach also increase non-linearly.
Imagine that you start off with a service that is called from a web browser. At some point down the road, the requirements are updated and now you have to support Android and iOS clients. Your server is likely fine, but the clients now need to be able to speak the same RPC dialect and often times there are differences that creep in. Things can get even worse if the server has to compensate for the differences amongst the clients.
On the other hand, using gRPC you just add the protocol compiler plugins and they generate the Android and iOS client stubs. This cuts out a whole class of problems. As a bonus, if you dont modify the generated codeand you should not have tothen any performance improvements in the generated code will be picked up.
### gRPC has Compact Serialization
gRPC uses Google protocol buffers to serialize messages. This serialization format is very compact because, among other things, field names are not included in the serialized form. Compare this to a JSON object where each instance of an object carries a full copy of its field names, includes extra curly braces, etc. For a low-volume application this may not be an issue, but it can add up quickly.
### gRPC Tooling is Extensible
Another very useful feature of the gRPC framework is that it is extensible. If you need support for a language that is not currently supported, there is a way to create plugins for the protocol compiler that allows you to add what you need.
### gRPC Supports Contract Updates
An often overlooked aspect of service APIs is how they may evolve over time. At best, this is often a secondary consideration. If you are using gRPC, and you adhered to a few basic rules, your messages can be forward and backward compatible.
## Grpc-gatewaybecause REST will be with us for a while…
Youre probably thinking: gRPC is great but I have a ton of REST clients to deal with. Well, there is another tool in this ecosystem and it is called grpc-gateway. Grpc-gateway “generates a reverse-proxy server which translates a RESTful JSON API into gRPC”. So if you want to support REST clients you can, and it doesnt cost you any real extra effort.
If your existing REST clients are pretty far from the normal REST APIs, you can use custom marshallers with grpc-gateway to compensate.
## Migration and gRPC + grpc-gateway
As mentioned previously, we had a lot of PHP code and REST endpoints which we wanted to rework as part of the migration. By using the combination of gRPC and grpc-gateway, we were able to define gRPC versions of the legacy REST APIs and then use grpc-gateway to expose the exact REST endpoints that clients were used to. With these alternative implementations in place we were able to move traffic between the old and new systems using combinations of DNS updates as well as our [Experimentation and Configuration System](https://medium.com/yik-yak-eng/yik-yak-configuration-and-experiment-system-16a5c15ee77c#.7s11d3kqh) without causing any disruption to the existing clients. We were even able to leverage the existing test suites to verify functionality and establish parity between the old and new systems.
Lets walk through the pieces and how they fit together.