mirror of https://github.com/grpc/grpc.io.git
Merge remote-tracking branch 'upstream/master' into lperkins/markdown-community-page
This commit is contained in:
commit
073eec3f10
|
|
@ -0,0 +1,14 @@
|
|||
# Hugo default output directory
|
||||
/public
|
||||
/resources
|
||||
|
||||
## OS Files
|
||||
# Windows
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
*~
|
||||
9
Makefile
9
Makefile
|
|
@ -1,9 +1,16 @@
|
|||
HUGO_VERSION = 0.53
|
||||
DOCKER_IMG := klakegg/hugo:$(HUGO_VERSION)
|
||||
SERVE_CMD = server --buildDrafts --buildFuture --disableFastRender --ignoreCache
|
||||
|
||||
serve:
|
||||
hugo server \
|
||||
--buildDrafts \
|
||||
--buildFuture \
|
||||
--disableFastRender
|
||||
|
||||
docker-serve:
|
||||
docker run --rm -it -v $(CURDIR):/src -p 1313:1313 $(DOCKER_IMG) $(SERVE_CMD)
|
||||
|
||||
production-build:
|
||||
hugo \
|
||||
--minify
|
||||
|
|
@ -13,4 +20,4 @@ preview-build:
|
|||
--baseURL $(DEPLOY_PRIME_URL) \
|
||||
--buildDrafts \
|
||||
--buildFuture \
|
||||
--minify
|
||||
--minify
|
||||
29
README.md
29
README.md
|
|
@ -1,4 +1,25 @@
|
|||
# gRPC
|
||||
This is the new [gRPC](https://grpc.io/) website, written on [Hugo](https://gohugo.io/). Here are a few key things to know about the site:
|
||||
* Key variables are stored in `/config.toml`, for example `grpc_release_tag` which is used in various places throughout the site.
|
||||
* If you're not familiar with Hugo, all content is stored in the `/content` directory. Go there to edit anything on the site. Images are stored in `/static/img`. Check out the [Hugo Quick Start](https://gohugo.io/getting-started/quick-start/) for a quick intro to Hugo.
|
||||
# The gRPC website and documentation
|
||||
|
||||
This repository houses the assets used to build and deploy the gRPC website, available at https://grpc.io. The site is built using the [Hugo](https://gohugo.io) static site generator. Check out the [Hugo Quick Start](https://gohugo.io/getting-started/quick-start/) for a quick intro.
|
||||
|
||||
## Running the site locally
|
||||
|
||||
To run the site locally, you need to [install Hugo](https://gohugo.io/getting-started/installing). Once Hugo is installed:
|
||||
|
||||
```bash
|
||||
make serve
|
||||
```
|
||||
|
||||
Alternatively, you can run the site using a [Docker](https://docker.com) container:
|
||||
|
||||
```bash
|
||||
make docker-serve
|
||||
```
|
||||
|
||||
## Publishing the site
|
||||
|
||||
The gRPC website is automatically published by [Netlify](https://netlify.com). Any time changes are pushed to the `master` branch, the site is re-built and re-deployed. This process does not require manual management.
|
||||
|
||||
## Site content
|
||||
|
||||
All of the [Markdown](https://www.markdownguide.org/) content used to build the site's documentation, blog, etc. is in the [`content`](./content) directory.
|
||||
|
|
@ -9,6 +9,7 @@ grpc_release_tag_no_v = "1.20.0"
|
|||
grpc_java_release_tag = "v1.20.0"
|
||||
milestones_link = "https://github.com/grpc/grpc/milestones"
|
||||
|
||||
# Configuration required for auto-generating the Netlify _redirects file
|
||||
[mediaTypes."text/netlify"]
|
||||
delimiter = ""
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
layout: guides
|
||||
title: Authentication
|
||||
aliases: [/docs/guides/auth.html]
|
||||
---
|
||||
<p class="lead">This document provides an overview of gRPC authentication,
|
||||
including our built-in supported auth mechanisms, how to plug in your own
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
layout: guides
|
||||
title: Benchmarking
|
||||
aliases: [/docs/guides/benchmarking.html]
|
||||
---
|
||||
<p class="lead">gRPC is designed to support high-performance
|
||||
open-source RPCs in many languages. This document describes the
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
layout: guides
|
||||
title: gRPC Concepts
|
||||
aliases: [/docs/guides/concepts.html]
|
||||
---
|
||||
<p class="lead">This document introduces some key gRPC concepts with an overview
|
||||
of gRPC's architecture and RPC life cycle.</p>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
layout: guides
|
||||
title: Error Handling
|
||||
aliases: [/docs/guides/error.html]
|
||||
---
|
||||
<p class="lead"> This page describes how gRPC deals with errors, including gRPC's built-in error codes. Example code in different languages can be found <a href="https://github.com/avinassh/grpc-errors">here</a>.</p>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
layout: quickstart
|
||||
title: Android Java Quickstart
|
||||
aliases: [/docs/quickstart/android.html]
|
||||
short: Android
|
||||
---
|
||||
<p class="lead">This guide gets you started with gRPC in Android Java with a simple
|
||||
working example.</p>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
layout: quickstart
|
||||
title: C++ Quickstart
|
||||
aliases: [/docs/quickstart/cpp.html]
|
||||
title: C++ Quick Start
|
||||
short: C++
|
||||
---
|
||||
<p class="lead">This guide gets you started with gRPC in C++ with a simple
|
||||
working example.</p>
|
||||
|
|
@ -225,28 +225,30 @@ int main(int argc, char** argv) {
|
|||
Just like we did before, from the `examples/cpp/helloworld` directory:
|
||||
|
||||
1. Build the client and server after having made changes:
|
||||
```sh
|
||||
$ make
|
||||
```
|
||||
|
||||
```sh
|
||||
$ make
|
||||
```
|
||||
|
||||
2. Run the server
|
||||
|
||||
```sh
|
||||
$ ./greeter_server
|
||||
```
|
||||
```sh
|
||||
$ ./greeter_server
|
||||
```
|
||||
|
||||
3. On a different terminal, run the client
|
||||
|
||||
```sh
|
||||
$ ./greeter_client
|
||||
```
|
||||
```sh
|
||||
$ ./greeter_client
|
||||
```
|
||||
|
||||
You should see the updated output:
|
||||
```sh
|
||||
$ ./greeter_client
|
||||
Greeter received: Hello world
|
||||
Greeter received: Hello again world
|
||||
```
|
||||
You should see the updated output:
|
||||
|
||||
```sh
|
||||
$ ./greeter_client
|
||||
Greeter received: Hello world
|
||||
Greeter received: Hello again world
|
||||
```
|
||||
|
||||
### What's next
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: C# Quick Start
|
||||
layout: quickstart
|
||||
aliases: [/docs/quickstart/csharp.html]
|
||||
short: C#
|
||||
---
|
||||
|
||||
<p class="lead">This guide gets you started with gRPC in C# with a simple
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
layout: quickstart
|
||||
title: Dart Quickstart
|
||||
aliases: [/docs/quickstart/dart.html]
|
||||
short: Dart
|
||||
---
|
||||
<p class="lead">This guide gets you started with gRPC in Dart with a simple
|
||||
working example.</p>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: Go Quick Start
|
||||
layout: quickstart
|
||||
aliases: [/docs/quickstart/go.html]
|
||||
short: Go
|
||||
---
|
||||
<p class="lead">This guide gets you started with gRPC in Go with a simple
|
||||
working example.</p>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
layout: quickstart
|
||||
title: Java Quickstart
|
||||
aliases: [/docs/quickstart/java.html]
|
||||
title: Java Quick Start
|
||||
short: Java
|
||||
---
|
||||
<p class="lead">This guide gets you started with gRPC in Java with a simple
|
||||
working example.</p>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: Node Quick Start
|
||||
layout: quickstart
|
||||
aliases: [/docs/quickstart/node.html]
|
||||
short: Node
|
||||
---
|
||||
<p class="lead">This guide gets you started with gRPC in Node with a simple
|
||||
working example.</p>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
layout: quickstart
|
||||
title: Objective-C Quickstart
|
||||
aliases: [/docs/quickstart/objective-c.html]
|
||||
title: Objective-C Quick Start
|
||||
short: Objective-C
|
||||
---
|
||||
<p class="lead">This guide gets you started with gRPC on the iOS platform in
|
||||
Objective-C with a simple working example.</p>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
layout: quickstart
|
||||
title: PHP Quickstart
|
||||
aliases: [/docs/quickstart/php.html]
|
||||
title: PHP Quick Start
|
||||
short: PHP
|
||||
---
|
||||
<p class="lead">This guide gets you started with gRPC in PHP with a simple
|
||||
working example.</p>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
layout: quickstart
|
||||
title: Python Quickstart
|
||||
aliases: [/docs/quickstart/python.html]
|
||||
title: Python Quick Start
|
||||
short: Python
|
||||
---
|
||||
<p class="lead">This guide gets you started with gRPC in Python with a simple
|
||||
working example.</p>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: Ruby Quick Start
|
||||
layout: quickstart
|
||||
aliases: [/docs/quickstart/ruby.html]
|
||||
short: Ruby
|
||||
---
|
||||
|
||||
<p class="lead">This guide gets you started with gRPC in Ruby with a simple
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: Web Quick Start
|
||||
layout: quickstart
|
||||
aliases: [/docs/quickstart/web.html]
|
||||
short: Web
|
||||
---
|
||||
<p class="lead">This guide gets you started with gRPC-Web with a simple
|
||||
working example from the browser.</p>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
bodyclass: docs
|
||||
headline: Go Generated Code Reference
|
||||
layout: docs
|
||||
aliases: [/docs/reference/go/generated-code.html]
|
||||
---
|
||||
# Go Generated Code Reference
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
bodyclass: docs
|
||||
title: Java Generated Code Reference
|
||||
layout: docs
|
||||
aliases: [/docs/reference/java/generated-code.html]
|
||||
---
|
||||
# Java Generated Code Reference
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
bodyclass: docs
|
||||
layout: docs
|
||||
headline: Python Generated Code Reference
|
||||
aliases: [/docs/reference/python/generated-code.html]
|
||||
---
|
||||
|
||||
# Python Generated Code Reference
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: Asynchronous Basics - C++
|
||||
aliases: [docs/tutorials/async/helloasync-cpp.html]
|
||||
short: Async - C++
|
||||
group: async
|
||||
---
|
||||
|
||||
This tutorial shows you how to write a simple server and client in C++ using
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: OAuth2 on gRPC - Objective-C
|
||||
aliases: [/docs/tutorials/auth/oauth2-objective-c.html]
|
||||
short: Auth - Objective-C
|
||||
group: auth
|
||||
---
|
||||
|
||||
This example demonstrates how to use OAuth2 on gRPC to make
|
||||
authenticated API calls on behalf of a user.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: gRPC Basics - Android Java
|
||||
aliases: [/docs/tutorials/basic/android.html]
|
||||
short: Android
|
||||
group: basic
|
||||
---
|
||||
|
||||
This tutorial provides a basic Android Java programmer's introduction to working with gRPC.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: gRPC Basics - C++
|
||||
aliases: [/docs/tutorials/basic/c.html]
|
||||
title: gRPC Basics - C++
|
||||
group: basic
|
||||
short: C
|
||||
---
|
||||
|
||||
This tutorial provides a basic C++ programmer's introduction to working with gRPC.
|
||||
|
||||
By walking through this example you'll learn how to:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: gRPC Basics - C#
|
||||
aliases: [/docs/tutorials/basic/csharp.html]
|
||||
group: basic
|
||||
short: C#
|
||||
---
|
||||
This tutorial provides a basic C# programmer's introduction to working with gRPC.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: gRPC Basics - Dart
|
||||
aliases: [/docs/tutorials/basic/dart.html]
|
||||
group: basic
|
||||
short: Dart
|
||||
---
|
||||
This tutorial provides a basic Dart programmer's introduction to
|
||||
working with gRPC.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: gRPC Basics - Go
|
||||
aliases: [/docs/tutorials/basic/go.html]
|
||||
group: basic
|
||||
short: Go
|
||||
---
|
||||
This tutorial provides a basic Go programmer's introduction to
|
||||
working with gRPC.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: gRPC Basics - Java
|
||||
aliases: [/docs/tutorials/basic/java.html]
|
||||
group: basic
|
||||
short: Java
|
||||
---
|
||||
This tutorial provides a basic Java programmer's introduction to
|
||||
working with gRPC.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: gRPC Basics - Node.js
|
||||
aliases: [/docs/tutorials/basic/node.html]
|
||||
group: basic
|
||||
short: Node
|
||||
---
|
||||
This tutorial provides a basic Node.js programmer's introduction
|
||||
to working with gRPC.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: gRPC Basics - Objective-C
|
||||
aliases: [/docs/tutorials/basic/objective-c.html]
|
||||
group: basic
|
||||
---
|
||||
This tutorial provides a basic Objective-C programmer's
|
||||
introduction to working with gRPC.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: gRPC Basics - PHP
|
||||
aliases: [/docs/tutorials/basic/php.html]
|
||||
group: basic
|
||||
short: PHP
|
||||
---
|
||||
This tutorial provides a basic PHP programmer's introduction to
|
||||
working with gRPC.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: gRPC Basics - Python
|
||||
aliases: [/docs/tutorials/basic/python.html]
|
||||
group: basic
|
||||
short: Python
|
||||
---
|
||||
This tutorial provides a basic Python programmer's introduction
|
||||
to working with gRPC.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: gRPC Basics - Ruby
|
||||
aliases: [/docs/tutorials/basic/ruby.html]
|
||||
group: basic
|
||||
short: Ruby
|
||||
---
|
||||
This tutorial provides a basic Ruby programmer's introduction to working with gRPC.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
layout: tutorials
|
||||
title: gRPC Basics - Web
|
||||
aliases: [/docs/tutorials/basic/web.html]
|
||||
group: basic
|
||||
short: Web
|
||||
---
|
||||
|
||||
This tutorial provides a basic introduction on how to use
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
splat:
|
||||
- go
|
||||
- java
|
||||
- python
|
||||
|
|
|
|||
|
|
@ -11,14 +11,13 @@
|
|||
<title>{{ block "title" . }}{{ .Site.Title }}{{ end }}</title>
|
||||
|
||||
<!-- Favicons -->
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png">
|
||||
<link rel="shortcut icon" href="/favicons/favicon.ico">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-512x512.png" sizes="512x512" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
<link rel="manifest" href="/favicons/site.webmanifest">
|
||||
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
|
||||
{{ define "title" }}
|
||||
{{ .Title }} – {{ .Site.Title }}
|
||||
{{ .Title }} – {{ .Site.Title }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
{{ $currentUrl := .RelPermalink }}
|
||||
{{ $quickstartDocs := where site.Pages ".Layout" "quickstart" }}
|
||||
|
||||
<div class="headertext">Documentation</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -14,19 +18,19 @@
|
|||
|
||||
<div class="quickstartcol1">
|
||||
|
||||
<h8>Quick Start</h8>
|
||||
<a href="{{ .Site.BaseURL }}docs/quickstart/cpp/" {{ if in .RelPermalink "cpp" }} class="active"{{ end }}>C++</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/quickstart/csharp/" {{ if in .RelPermalink "csharp" }} class="active"{{ end }}>C#</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/quickstart/dart/" {{ if in .RelPermalink "dart" }} class="active"{{ end }}>Dart</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/quickstart/go/" {{ if in .RelPermalink "go" }} class="active"{{ end }}>Go</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/quickstart/java/" {{ if in .RelPermalink "java" }} class="active"{{ end }}>Java</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/quickstart/android/" {{ if in .RelPermalink "android" }} class="active"{{ end }}>Android Java</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/quickstart/node/" {{ if in .RelPermalink "node" }} class="active"{{ end }}>Node.js</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/quickstart/objective-c/" {{ if in .RelPermalink "objective-c" }} class="active"{{ end }}>Objective-C</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/quickstart/php/" {{ if in .RelPermalink "php" }} class="active"{{ end }}>PHP</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/quickstart/python/" {{ if in .RelPermalink "python" }} class="active"{{ end }}>Python</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/quickstart/ruby/" {{ if in .RelPermalink "ruby" }} class="active"{{ end }}>Ruby</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/quickstart/web/" {{ if in .RelPermalink "web" }} class="active"{{ end }}>Web</a>
|
||||
<h8>Quick Start</h8>
|
||||
|
||||
<a href="/docs/quickstart">
|
||||
Quick Start Home
|
||||
</a>
|
||||
|
||||
{{ range $quickstartDocs }}
|
||||
{{ $isCurrentPage := eq $currentUrl .RelPermalink }}
|
||||
{{ $title := .Params.short }}
|
||||
<a href="{{ .RelPermalink }}"{{ if $isCurrentPage }} class="active"{{ end }}>
|
||||
{{ $title }}
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<div class="quickstartcol2" style="margin-top:4%">
|
||||
|
|
|
|||
|
|
@ -3,6 +3,12 @@
|
|||
{{ .Title }} – {{ .Site.Title }}
|
||||
{{ end }}
|
||||
{{ define "main" }}
|
||||
{{ $currentUrl := .RelPermalink }}
|
||||
{{ $tutorials := where site.Pages ".Layout" "tutorials" }}
|
||||
{{ $async := where $tutorials ".Params.group" "eq" "async" }}
|
||||
{{ $auth := where $tutorials ".Params.group" "eq" "auth" }}
|
||||
{{ $basic := where $tutorials ".Params.group" "eq" "basic" }}
|
||||
|
||||
<div class="headertext">Documentation</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -15,21 +21,32 @@
|
|||
<div class="quickstartcol1">
|
||||
|
||||
<h8>Tutorials</h8>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/async/helloasync-cpp/" {{ if in .RelPermalink "helloasync-cpp" }}class="active"{{ end }}>Async - C++</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/auth/oauth2-objective-c/" {{ if in .RelPermalink "oauth2-objective-c" }}class="active"{{ end }}>Auth - Objective C</a>
|
||||
|
||||
{{ range $auth }}
|
||||
{{ $isCurrentPage := eq $currentUrl .RelPermalink }}
|
||||
{{ $title := .Params.short }}
|
||||
<a href="{{ .RelPermalink }}"{{ if $isCurrentPage }} class="active"{{ end }}>
|
||||
{{ $title }}
|
||||
</a>
|
||||
{{ end }}
|
||||
|
||||
{{ range $async }}
|
||||
{{ $isCurrentPage := eq $currentUrl .RelPermalink }}
|
||||
{{ $title := .Params.short }}
|
||||
<a href="{{ .RelPermalink }}">
|
||||
{{ $title }}
|
||||
</a>
|
||||
{{ end }}
|
||||
|
||||
<h8>Basic</h8>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/basic/c/" {{ if in .RelPermalink "basic/c/" }}class="active"{{ end }}>C++</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/basic/csharp/" {{ if in .RelPermalink "csharp" }}class="active"{{ end }}>C#</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/basic/dart/" {{ if in .RelPermalink "dart" }}class="active"{{ end }}>Dart</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/basic/go/" {{ if in .RelPermalink "go" }}class="active"{{ end }}>Go</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/basic/java/" {{ if in .RelPermalink "java" }}class="active"{{ end }}>Java</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/basic/android/" {{ if in .RelPermalink "android" }}class="active"{{ end }}>Android Java</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/basic/node/" {{ if in .RelPermalink "node" }}class="active"{{ end }}>Node</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/basic/objective-c/" {{ if in .RelPermalink "objective-c" }}class="active"{{ end }}>Objective-C</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/basic/php/" {{ if in .RelPermalink "php" }}class="active"{{ end }}>PHP</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/basic/python/" {{ if in .RelPermalink "python" }}class="active"{{ end }}>Python</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/basic/ruby/" {{ if in .RelPermalink "ruby" }}class="active"{{ end }}>Ruby</a>
|
||||
<a href="{{ .Site.BaseURL }}docs/tutorials/basic/web/" {{ if in .RelPermalink "web" }}class="active"{{ end }}>Web</a>
|
||||
|
||||
{{ range $basic }}
|
||||
{{ $isCurrentPage := eq $currentUrl .RelPermalink }}
|
||||
{{ $title := .Params.short }}
|
||||
<a href="{{ .RelPermalink }}">
|
||||
{{ $title }}
|
||||
</a>
|
||||
{{ end }}
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{{- $redirects := site.Data.redirects -}}
|
||||
{{- range $redirects -}}
|
||||
/grpc-{{ . }}/* https://github.com/grpc/grpc-{{ . }}/:splat
|
||||
{{- $splatRedirects := site.Data.redirects.splat -}}
|
||||
{{- range $splatRedirects -}}
|
||||
/grpc-{{ . }}/* https://grpc.github.io/grpc-{{ . }}/:splat
|
||||
{{ end -}}
|
||||
/grpc/* https://grpc.github.io/grpc/:splat
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
/grpc-go/* https://github.com/grpc/grpc-go/:splat
|
||||
/grpc-java/* https://github.com/grpc/grpc-java/:splat
|
||||
/grpc-python/* https://github.com/grpc/grpc-python/:splat
|
||||
/grpc-dotnet/* https://github.com/grpc/grpc-dotnet/:splat
|
||||
/grpc-swift/* https://github.com/grpc/grpc-swift/:splat
|
||||
/grpc-proto/* https://github.com/grpc/grpc-proto/:splat
|
||||
/grpc-web/* https://github.com/grpc/grpc-web/:splat
|
||||
/grpc-dart/* https://github.com/grpc/grpc-dart/:splat
|
||||
/grpc-community/* https://github.com/grpc/grpc-community/:splat
|
||||
/grpc-node/* https://github.com/grpc/grpc-node/:splat
|
||||
/grpc-swift/* https://github.com/grpc/grpc-swift/:splat
|
||||
/grpc-php/* https://github.com/grpc/grpc-php/:splat
|
||||
/grpc-java-api-checker/* https://github.com/grpc/grpc-java-api-checker/:splat
|
||||
/grpc-docker-library/* https://github.com/grpc/grpc-docker-library/:splat
|
||||
/grpc-experiments/* https://github.com/grpc/grpc-experiments/:splat
|
||||
/grpc-haskell/* https://github.com/grpc/grpc-haskell/:splat
|
||||
|
|
@ -1,324 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
About gRPC – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">About gRPC</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section2" style="text-align:left;margin-bottom:5%">
|
||||
|
||||
|
||||
<p>gRPC is a modern open source high performance RPC framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication. It is also applicable in last mile of distributed computing to connect devices, mobile applications and browsers to backend services.</p>
|
||||
|
||||
<p><b>The main usage scenarios:</b></p>
|
||||
|
||||
<ul>
|
||||
<li>Efficiently connecting polyglot services in microservices style architecture</li>
|
||||
<li>Connecting mobile devices, browser clients to backend services</li>
|
||||
<li>Generating efficient client libraries</li>
|
||||
</ul>
|
||||
|
||||
<p><b>Core Features that make it awesome:</b></p>
|
||||
|
||||
<ul>
|
||||
<li>Idiomatic client libraries in 10 languages</li>
|
||||
<li>Highly efficient on wire and with a simple service definition framework</li>
|
||||
<li>Bi-directional streaming with http/2 based transport</li>
|
||||
<li>Pluggable auth, tracing, load balancing and health checking</li>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2 id="cases-who-s-using-it-and-why">Cases: Who’s using it and why?</h2>
|
||||
|
||||
<p>Many companies are already using gRPC for connecting multiple services in their environments. The use case varies from connecting a handful of services to hundreds of services across various languages in on-prem or cloud environments. Below are details and quotes from some of our early adopters.</p>
|
||||
|
||||
<p>Check out what people are saying below:</p>
|
||||
|
||||
<div class="testimonialrow">
|
||||
<div class="testimonialsection">
|
||||
<div>
|
||||
<a href="https://www.youtube.com/watch?v=-2sWDr3Z0Wo">
|
||||
<div class="testimonialimage"> <img src="../img/square-icon.png" style="width:45%"/></a></div>
|
||||
<div>
|
||||
<div class="testimonialquote">“ </div>
|
||||
At Square, we have been collaborating with Google so that we can replace all uses of our custom RPC solution to use gRPC. We decided to move to gRPC because of its open support for multiple platforms, the demonstrated performance of the protocol, and the ability to customize and adapt it to our network. Developers at Square are looking forward to being able to take advantage of writing streaming APIs and in the future, push gRPC to the edges of the network for integration with mobile clients and third party APIs.
|
||||
</div>
|
||||
|
||||
<p></div>
|
||||
</div></p>
|
||||
|
||||
<div class="testimonialsection">
|
||||
<div class="testimonialimage"><a href="https://github.com/Netflix/ribbon">
|
||||
<img src="../img/netflix-logo.png" /> </a></div>
|
||||
<div>
|
||||
<div class="testimonialquote"> “ </div>
|
||||
In our initial use of gRPC we've been able to extend it easily to live within our opinionated ecosystem. Further, we've had great success making improvements directly to gRPC through pull requests and interactions with Google's team that manages the project. We expect to see many improvements to developer productivity, and the ability to allow development in non-JVM languages as a result of adopting gRPC.
|
||||
</div>
|
||||
|
||||
<p></div>
|
||||
<div class="testimonialsection">
|
||||
<div class="testimonialimage"><a href="https://blog.gopheracademy.com/advent-2015/etcd-distributed-key-value-store-with-grpc-http2/">
|
||||
<img src="../img/coreos-1.png" style="width:30%"/></a></div>
|
||||
<div>
|
||||
<div class="testimonialquote">“ </div>
|
||||
At CoreOS we are excited by the gRPC v1.0 release and the opportunities it opens up for people consuming and building what we like to call Google Infrastructure for Everyone Else. Today gRPC is in use in a number of our critical open source projects such as the etcd consensus database and the rkt container engine.
|
||||
</div></p>
|
||||
|
||||
<p></div>
|
||||
</div>
|
||||
<div class="testimonialsection">
|
||||
<div class="testimonialimage"> <a href="https://github.com/cockroachdb/cockroach">
|
||||
<img src="../img/cockroach-1.png" /> </a></div>
|
||||
<div>
|
||||
<div class="testimonialquote">“ </div>
|
||||
Our switch from a home-grown RPC system to gRPC was seamless. We quickly took advantage of the per-stream flow control to provide better scheduling of large RPCs over the same connection as small ones.
|
||||
</div></p>
|
||||
|
||||
<p></div></p>
|
||||
|
||||
<div class="testimonialsection">
|
||||
<div class="testimonialimage"><a href="https://github.com/CiscoDevNet/grpc-getting-started">
|
||||
<img src="../img/cisco.svg" /></a></div>
|
||||
<div>
|
||||
<div class="testimonialquote">“ </div>
|
||||
With support for high performance bi-directional streaming, TLS based security, and a wide variety of programming languages, gRPC is an ideal unified transport protocol for model driven configuration and telemetry.
|
||||
</div>
|
||||
|
||||
<p></div></p>
|
||||
|
||||
<div class="testimonialsection">
|
||||
<div class="testimonialimage"><a href="http://www.carbon3d.com">
|
||||
<img src="../img/carbon3d.svg" /></a></div>
|
||||
<div>
|
||||
<div class="testimonialquote">“ </div>
|
||||
Carbon3D uses gRPC to implement distributed processes both within and outside our 3D printers. We actually switched from using Thrift early on for a number of reasons including but not limited to robust support for multiple languages like C++, Nodejs and Python. Features like bi-directional streaming are a huge win in keeping our systems implementations simpler and correct. Lastly the gRPC team/community is very active and responsive which is also a key factor for us in selecting an open source technology for mission critical projects.
|
||||
</div>
|
||||
|
||||
<p></div></p>
|
||||
|
||||
<div class="testimonialsection">
|
||||
<div class="testimonialimage"><img src="../img/wisc-mad.jpg" /></a></div>
|
||||
<div>
|
||||
<div class="testimonialquote">“ </div>
|
||||
We've been using gRPC for both classes and research at University of Wisconsin. Students in our distributed systems class (CS 739) utilized many of its powerful features when building their own distributed systems. In addition, gRPC is a key component of our OpenLambda research project (https://www.open-lambda.org/) which aims to provide an open-source, low-latency, serverless computational framework.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="testimonialsection">
|
||||
<div class="testimonialimage"><a href="https://github.com/Juniper/open-nti">
|
||||
<img src="../img/juniperlogo.png" /> </a></div>
|
||||
<div>
|
||||
<div class="testimonialquote">“ </div>
|
||||
The fact that gRPC is built on HTTP/2 transport brings us native bi-directional streaming capabilities and flexible custom-metadata in request headers. The first point is important for large payloadexchange and network telemetry scenarios while the latter enables us to expand and include capabilities including but not limited to various network element authentication mechanisms.
|
||||
|
||||
In addition, the wide language binding support that gRPC/proto3 bringsenables us to provide a flexible and rapid development environment for both internal and external consumers.
|
||||
|
||||
Last but not least, while there are a number of network communicationprotocols for configuration, operational state retrieval and network telemetry, gRPC provides us with a unified flexible protocol and transport to ease client/server interaction.
|
||||
</div>
|
||||
|
||||
<p></div></p>
|
||||
|
||||
<div class="aboutsection2">
|
||||
<h2>Officially Supported Platforms</h2>
|
||||
|
||||
|
||||
<table style="width:80%;margin-top:5%;margin-bottom:5%">
|
||||
<tr style="width:100%">
|
||||
<th style="width:20%">Language </th><th> Platform </th><th>Compiler</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>C/C++</td><td>Linux</td><td>GCC 4.4 <br/> GCC 4.6 <br> GCC 5.3 <br> Clang 3.5 <br> Clang 3.6 <br> Clang 3.7|</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>C/C++</td><td>Windows 7+</td><td>Visual Studio 2013+</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td>C#</td><td>Windows 7+ </td><td> Linux <br> .NET Core, .NET 4.5+ <br> .NET Core, Mono 4+ <br> .NET Core, Mono 4+</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Dart</td><td>Windows/Linux/Mac</td><td> Dart 2.0+</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td>Go</td><td>Windows/Linux/Mac</td><td> Go 1.6+</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Java</td><td>Windows/Linux/Mac</td><td> JDK 8 recommended. Gingerbread+ for Android</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Node.js</td><td>Windows/Linux/Mac</td><td> Node v4+</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>PHP * </td><td>Linux/Mac</td><td> PHP 5.5+ and PHP 7.0+</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Python </td><td>Windows/Linux/Mac</td><td> Python 2.7 and Python 3.4+</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Ruby </td><td>Windows/Linux/Mac</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<!--
|
||||
|
||||
| Language | Platform | Compiler |
|
||||
| -------- | -------- | -------- |
|
||||
| C/C++ | Linux | GCC 4.4 <br/> GCC 4.6 <br> GCC 5.3 <br> Clang 3.5 <br> Clang 3.6 <br> Clang 3.7|
|
||||
| C/C++ | Windows 7+ | Visual Studio 2013+ |
|
||||
| C# | Windows 7+ <br> Linux <br> Mac | .NET Core, .NET 4.5+ <br> .NET Core, Mono 4+ <br> .NET Core, Mono 4+ |
|
||||
| Dart | Windows/Linux/Mac | Dart 2.0+ |
|
||||
| Go | Windows/Linux/Mac | Go 1.6+ |
|
||||
| Java | Windows/Linux/Mac | JDK 8 recommended. Gingerbread+ for Android |
|
||||
| Node.js | Windows/Linux/Mac | Node v4+ |
|
||||
| PHP * | Linux/Mac | PHP 5.5+ and PHP 7.0+ |
|
||||
| Python | Windows/Linux/Mac | Python 2.7 and Python 3.4+ |
|
||||
| Ruby | Windows/Linux/Mac | |
|
||||
_* still in beta_
|
||||
-->
|
||||
|
||||
<h2>The story behind gRPC</h2>
|
||||
Google has been using a single general-purpose RPC infrastructure called Stubby to connect the large number of microservices running within and across our data centers for over a decade. Our internal systems have long embraced the microservice architecture gaining popularity today. Stubby has powered all of Google’s microservices interconnect for over a decade and is the RPC backbone behind every Google service that you use today. In March 2015, we decided to build the next version of Stubby in the open so we can share our learnings with the industry and collaborate with them to build the next version of Stubby both for microservices inside and outside Google but also for last mile of computing (mobile, web and IOT).
|
||||
<br>
|
||||
For more background on why we created gRPC, read the <a href="/blog/principles">gRPC Motivation and Design Principles blog</a>.
|
||||
<br><br>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
2017-08-17 Community Meeting Update – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>2017-08-17 Community Meeting Update</h1>
|
||||
<h5>Posted on Thursday, August 17, 2017
|
||||
by
|
||||
|
||||
Jaye Pitzeruse
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p><strong>Next Community Meeting:</strong> Thursday, August 31, 2017 11am Pacific Time (US and Canada)</p>
|
||||
|
||||
<h2 id="general-announcements">General Announcements</h2>
|
||||
|
||||
<p>Call for Papers: CloudNativeCon</p>
|
||||
|
||||
<p>CloudNativeCon gathers all CNCF (Cloud Native Computing Foundation) projects under a single roof.
|
||||
Presenters will be talking about their experiences with Kubernetes, Prometheus, OpenTracing, Fluentd, Linkerd, gRPC, CoreDNS, containerd, rkt and CNI.
|
||||
The call for papers period will be ending on Monday, August 21, 2017.
|
||||
The conference will be taking place on the 6th and 7th of December, 2017.
|
||||
If you submit a talk, please add an entry to the spreadsheet linked in the <a href="https://docs.google.com/document/d/1DTMEbBNmzNbZBh8nOivsnnw3CwUr1Q7WGRe7rNxyHOU/edit#bookmark=id.7qk9qf3ri75m">gRPC Community Meeting Working Doc</a>.</p>
|
||||
|
||||
<p>Register for <a href="https://events.linuxfoundation.org/events/cloudnativecon-and-kubecon-north-america/attend/register">CloudNativeCon</a></p>
|
||||
|
||||
<h2 id="release-updates">Release Updates</h2>
|
||||
|
||||
<p>1.6 will be available soon.
|
||||
The required changes have already been merged and published in the protocol buffer libraries.
|
||||
Keep your eyes peeled for the upcoming release.</p>
|
||||
|
||||
<h2 id="platform-updates">Platform Updates</h2>
|
||||
|
||||
<p>No platform updates.</p>
|
||||
|
||||
<h2 id="language-updates">Language Updates</h2>
|
||||
|
||||
<p>No language specific updates.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,484 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
2017-08-22 gRPC-Go performance Improvements – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>2017-08-22 gRPC-Go performance Improvements</h1>
|
||||
<h5>Posted on Tuesday, August 22, 2017
|
||||
by
|
||||
|
||||
Mahak Mukhi
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p><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.
|
||||
Benchmark results at the end.</p>
|
||||
|
||||
<p>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></p>
|
||||
|
||||
<h3 id="recently-implemented-optimizations">Recently Implemented Optimizations</h3>
|
||||
|
||||
<h6 id="expanding-stream-window-on-receiving-large-messages">Expanding stream window on receiving large messages</h6>
|
||||
|
||||
<p><a href="https://github.com/grpc/grpc-go/pull/1248">Code link</a></p>
|
||||
|
||||
<p>This is an optimization used by gRPC-C to achieve performance benefits for large messages. The idea is that when there’s an active read by the application on the receive side, we can effectively bypass stream-level flow control to request the whole message. This proves to be very helpful with large messages. Since the application is already committed to reading and has allocated enough memory for it, it makes sense that we send a proactive large window update (if necessary) to get the whole message rather than receiving it in chunks and sending window updates when we run low on window.</p>
|
||||
|
||||
<p>This optimization alone provided a 10x improvement for large messages on high-latency networks.</p>
|
||||
|
||||
<h6 id="decoupling-application-reads-from-connection-flow-control">Decoupling application reads from connection flow control</h6>
|
||||
|
||||
<p><a href="https://github.com/grpc/grpc-go/pull/1265">Code link</a></p>
|
||||
|
||||
<p>After having several discussions with gRPC-Java and gRPC-C core team we realized that gRPC-Go’s connection-level flow control was overly restrictive in the sense that window updates on the connection depended upon if the application had read data from it or not. It must be noted that it makes perfect sense to have stream-level flow control depended on application read but not so much for connection-level flow control. The rationale is as follows: A connection is shared by several streams (RPCs). If there were at least one stream that read slowly or didn’t read at all, it would hamper the performance or completely stall other streams on that connection. This happens because we won’t send out window updates on the connection until that slow or inactive stream read data. Therefore, it makes sense to decouple the connection’s flow control from application reads.</p>
|
||||
|
||||
<p>However, this begs at least two questions:</p>
|
||||
|
||||
<ol>
|
||||
<li><p>Won’t a client be able to send as much data as it wants to the server by creating new streams when one runs out?</p></li>
|
||||
|
||||
<li><p>Why even have connection-level flow control if the stream-level flow control is enough?</p></li>
|
||||
</ol>
|
||||
|
||||
<p>The answer to the first question is short and simple: no. A server has an option to limit the number of streams that it intends to serve concurrently. Therefore, although at first it may seem like a problem, it really is not.</p>
|
||||
|
||||
<p>The need for connection-level flow control:</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h6 id="piggyback-window-updates">Piggyback window updates</h6>
|
||||
|
||||
<p><a href="https://github.com/grpc/grpc-go/pull/1273">Code link</a></p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h6 id="bdp-estimation-and-dynamic-flow-control-window">BDP estimation and dynamic flow control window</h6>
|
||||
|
||||
<p><a href="https://github.com/grpc/grpc-go/pull/1310">Code link</a></p>
|
||||
|
||||
<p>This feature is the latest and in some ways the most awaited optimization feature that has helped us close the final gap between gRPC and HTTP/1.1 performance on high latency networks.</p>
|
||||
|
||||
<p>Bandwidth Delay Product (BDP) is the bandwidth of a network connection times its round-trip latency. This effectively tells us how many bytes can be “on the wire” at a given moment, if full utilization is achieved.</p>
|
||||
|
||||
<p>The <a href="https://docs.google.com/document/d/1Eq4eBEbNt1rc8EYuwqsduQd1ZfcBOCYt9HVSBa--m-E/pub">algorithm</a> to compute BDP and adapt accordingly was first proposed by @ejona and later implemented by both gRPC-C core and gRPC-Java (note that it isn’t enabled in Java yet). The idea is simple and powerful: every time a receiver gets a data frame it sends out a BDP ping (a ping with unique data only used by BDP estimator). After this, the receiver starts counting the number of bytes it receives (including the ones that triggered the BDP ping) until it receives the ack for that ping. This total sum of all bytes received in about 1.5 RTT (Round-Trip Time) is an approximation of the effective BDP * 1.5. If this is close to our current window size (say, more than 2/3rd of it) we must increase the window size. We put our window sizes (both streaming and connection) to be twice the BDP we sampled(total sum of all bytes received).</p>
|
||||
|
||||
<p>This algorithm by itself could cause the BDP estimation to increase indefinitely; an increase in window will result in sampling more bytes which in turn will cause the window to be increased further. This phenomenon is called <a href="https://en.wikipedia.org/wiki/Bufferbloat">buffer-bloat</a> and was discovered by earlier implementations in gRPC-C core and gRPC-Java. The solution to this is to calculate the bandwidth for every sample and check if it is greater than the maximum bandwidth noted so far. If so, only then increase our window sizes. The bandwidth, as we know, can be calculated by dividing the sample by RTT * 1.5 (remember the sample was for one and a half round trips). If the bandwidth doesn’t increase with an increase in sampled bytes that’s indicative that this change is because of an increased window size and doesn’t really reflect the nature of the network itself.</p>
|
||||
|
||||
<p>While running experiments on VMs in different continents we realized that every once in awhile a rogue, unnaturally fast ping-ack at the right time (really the wrong time) would cause our window sizes to go up. This happens because such a ping-ack would cause us to notice a decreased RTT and calculate a high bandwidth value. Now if that sample of bytes was greater than 2/3rd of our window then we would increase the window sizes. However, this ping ack was an aberration and shouldn’t have changed our perception of the network RTT al together. Therefore, we keep a running average of the RTTs we note weighted by a constant rather than the total number of samples to heed more to recent RTTs and less to the ones in past. It is important because networks might change over time.</p>
|
||||
|
||||
<p>During implementation, we experimented with several tuning parameters, such as the multiplier to compute the window size from the sample size to select the best settings, that balanced between growth and accuracy.</p>
|
||||
|
||||
<p>Given that we’re always bound by the flow control of TCP which for most cases is upper bounded at 4MB, we bound the growth of our window sizes by the same number: 4MB.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h6 id="near-future-efforts">Near-future efforts</h6>
|
||||
|
||||
<p>We are now looking into improving our throughput by better CPU utilization, the following efforts are in-line with that.</p>
|
||||
|
||||
<h6 id="reducing-flush-syscalls">Reducing flush syscalls</h6>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>In our efforts to get rid of unnecessary flushes we recently combined the headers and data write for unary and server streaming RPCs to one flush on the client-side. Link to <a href="https://github.com/grpc/grpc-go/pull/1343">code</a></p>
|
||||
|
||||
<p>Another related idea proposed by one of our users @petermattic in <a href="https://github.com/grpc/grpc-go/pull/1373">this</a> PR was to combine a server response to a unary RPC into one flush. We are currently looking into that as well.</p>
|
||||
|
||||
<h6 id="reducing-memory-allocation">Reducing memory allocation</h6>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h6 id="results">Results:</h6>
|
||||
|
||||
<ul>
|
||||
<li><p>Benchmark on a real network:</p>
|
||||
|
||||
<ul>
|
||||
<li>Server and client were launched on two VMs in different continents. RTT of ~152ms.</li>
|
||||
<li>Client made an RPC with a payload and server responded back with an empty message.</li>
|
||||
<li>The time taken for each RPC was measured.</li>
|
||||
<li><a href="https://github.com/grpc/grpc-go/compare/master...MakMukhi:http_greeter">Code link</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<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>
|
||||
|
||||
<ul>
|
||||
<li>Benchmark on simulated network:
|
||||
|
||||
<ul>
|
||||
<li>Server and client were launched on the same machine and different network latencies were simulated.</li>
|
||||
<li>Client made an RPC with 1MB of payload and server responded back with an empty message.</li>
|
||||
<li>The time taken for each RPC was measured.</li>
|
||||
<li>Following tables show time taken by first 10 RPCs.</li>
|
||||
<li><a href="https://github.com/grpc/grpc-go/compare/master...MakMukhi:grpc_vs_http">Code link</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h5 id="no-latency-network">No Latency Network</h5>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>GRPC</th>
|
||||
<th align="center">HTTP 2.0</th>
|
||||
<th align="right">HTTP 1.1</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>5.097809ms</td>
|
||||
<td align="center">16.107461ms</td>
|
||||
<td align="right">18.298959ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>4.46083ms</td>
|
||||
<td align="center">4.301808ms</td>
|
||||
<td align="right">7.715456ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>5.081421ms</td>
|
||||
<td align="center">4.076645ms</td>
|
||||
<td align="right">8.118601ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>4.338013ms</td>
|
||||
<td align="center">4.232606ms</td>
|
||||
<td align="right">6.621028ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>5.013544ms</td>
|
||||
<td align="center">4.693488ms</td>
|
||||
<td align="right">5.83375ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>3.963463ms</td>
|
||||
<td align="center">4.558047ms</td>
|
||||
<td align="right">5.571579ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>3.509808ms</td>
|
||||
<td align="center">4.855556ms</td>
|
||||
<td align="right">4.966938ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>4.864618ms</td>
|
||||
<td align="center">4.324159ms</td>
|
||||
<td align="right">6.576279ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>3.545933ms</td>
|
||||
<td align="center">4.61375ms</td>
|
||||
<td align="right">6.105608ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>3.481094ms</td>
|
||||
<td align="center">4.621215ms</td>
|
||||
<td align="right">7.001607ms</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h5 id="network-with-rtt-of-16ms">Network with RTT of 16ms</h5>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>GRPC</th>
|
||||
<th align="center">HTTP 2.0</th>
|
||||
<th align="right">HTTP 1.1</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>118.837625ms</td>
|
||||
<td align="center">84.453913ms</td>
|
||||
<td align="right">58.858109ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>36.801006ms</td>
|
||||
<td align="center">22.476308ms</td>
|
||||
<td align="right">20.877585ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>35.008349ms</td>
|
||||
<td align="center">21.206222ms</td>
|
||||
<td align="right">19.793881ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>21.153461ms</td>
|
||||
<td align="center">20.940937ms</td>
|
||||
<td align="right">22.18179ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>20.640364ms</td>
|
||||
<td align="center">21.888247ms</td>
|
||||
<td align="right">21.4666ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>21.410346ms</td>
|
||||
<td align="center">21.186008ms</td>
|
||||
<td align="right">20.925514ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>19.755766ms</td>
|
||||
<td align="center">21.818027ms</td>
|
||||
<td align="right">20.553768ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>20.388882ms</td>
|
||||
<td align="center">21.366796ms</td>
|
||||
<td align="right">21.460029ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>20.623342ms</td>
|
||||
<td align="center">20.681414ms</td>
|
||||
<td align="right">20.586908ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>20.452023ms</td>
|
||||
<td align="center">20.781208ms</td>
|
||||
<td align="right">20.278481ms</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h5 id="network-with-rtt-of-64ms">Network with RTT of 64ms</h5>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>GRPC</th>
|
||||
<th align="center">HTTP 2.0</th>
|
||||
<th align="right">HTTP 1.1</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>455.072669ms</td>
|
||||
<td align="center">275.290241ms</td>
|
||||
<td align="right">208.826314ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>195.43357ms</td>
|
||||
<td align="center">70.386788ms</td>
|
||||
<td align="right">70.042513ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>132.215978ms</td>
|
||||
<td align="center">70.01131ms</td>
|
||||
<td align="right">71.19429ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>69.239273ms</td>
|
||||
<td align="center">70.032237ms</td>
|
||||
<td align="right">69.479335ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>68.669903ms</td>
|
||||
<td align="center">70.192272ms</td>
|
||||
<td align="right">70.858937ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>70.458108ms</td>
|
||||
<td align="center">69.395154ms</td>
|
||||
<td align="right">71.161921ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>68.488057ms</td>
|
||||
<td align="center">69.252731ms</td>
|
||||
<td align="right">71.374758ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>68.816031ms</td>
|
||||
<td align="center">69.628744ms</td>
|
||||
<td align="right">70.141381ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>69.170105ms</td>
|
||||
<td align="center">68.935813ms</td>
|
||||
<td align="right">70.685521ms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>68.831608ms</td>
|
||||
<td align="center">69.728349ms</td>
|
||||
<td align="right">69.45605ms</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,276 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
2018-01-19 gRPC-Go Engineering Practices – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>2018-01-19 gRPC-Go Engineering Practices</h1>
|
||||
<h5>Posted on Monday, January 22, 2018
|
||||
by
|
||||
|
||||
Doug Fawley, gRPC-Go TL
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>It’s the start of the new year, and almost the end of my first full year on the
|
||||
gRPC-Go project, so I’d like to take this opportunity to provide an update on
|
||||
the state of gRPC-Go development and give some visibility into how we manage the
|
||||
project. For me, personally, this is the first open source project to which
|
||||
I’ve meaningfully contributed, so this year has been a learning experience for
|
||||
me. Over this year, the team has made constant improvements to our work habits
|
||||
and communication. I still see room for improvement, but I believe we are in a
|
||||
considerably better place than we were a year ago.</p>
|
||||
|
||||
<h2 id="repo-health">Repo Health</h2>
|
||||
|
||||
<p>When I first joined the gRPC-Go team, they had been without their previous
|
||||
technical lead for a few months. At that time, we had 45 open PRs, the oldest
|
||||
of which was over a year old at the time. As a new team member and maintainer,
|
||||
the accumulation of stale PRs made it difficult to assess priorities and
|
||||
understand the state of things. For our contributors, neglecting PRs was both
|
||||
disrespectful and an inconvenience when we started asking for rebases due to
|
||||
other commits. To resolve this, we made a concerted effort to either merge or
|
||||
close all of those PRs, and we now hold weekly meetings to review the status of
|
||||
every active PR to prevent the situation from reoccurring.</p>
|
||||
|
||||
<p>At the same time, we had 103 open issues, many of which were already fixed or
|
||||
outdated or untriaged. Since then, we fixed or closed 85 of those and put in
|
||||
place a process to ensure we triage and prioritize new issues on a weekly
|
||||
rotation. Similarly to our PRs, we also review our assigned and high-priority
|
||||
issues in a weekly meeting.</p>
|
||||
|
||||
<p>Our ongoing SLO for new issues and PRs is 1 week to triage and first response.</p>
|
||||
|
||||
<p>We also revamped our <a href="https://github.com/grpc/grpc-go/labels">labels</a> for issues
|
||||
and PRs to help with organization. We typically apply a priority (P0-P3) and a
|
||||
type (e.g. Bug, Feature, or Performance) to every issue. We also have a
|
||||
collection of status labels we apply in various situations. The type labels are
|
||||
also applied to PRs to aid in generating our release notes.</p>
|
||||
|
||||
<h2 id="versioning-and-backward-compatibility">Versioning and Backward Compatibility</h2>
|
||||
|
||||
<p>We have recently documented our <a href="https://github.com/grpc/grpc-go/blob/master/Documentation/versioning.md">versioning
|
||||
policy</a>.
|
||||
Our goal is to maintain full backward compatibility except in limited
|
||||
circumstances, including experimental APIs and mitigating security risks (most
|
||||
notably <a href="https://github.com/grpc/grpc-go/pull/1392">#1392</a>). If you notice a
|
||||
behavior regression, please don’t hesitate to <a href="https://github.com/grpc/grpc-go/issues/new">open an
|
||||
issue</a> in our repo (please <a href="https://xkcd.com/1172/">be
|
||||
reasonable</a>).</p>
|
||||
|
||||
<h2 id="grfc">gRFC</h2>
|
||||
|
||||
<p>The <a href="https://github.com/grpc/proposal">gRPC proposal repo</a> contains proposals
|
||||
for substantial feature changes for gRPC that need to be designed upfront,
|
||||
called gRFCs. The purpose of this process is to provide visibility and solicit
|
||||
feedback from the community. Each change is discussed on our <a href="https://groups.google.com/forum/#!forum/grpc-io">mailing
|
||||
list</a> and debated before the
|
||||
change is made. We leveraged this before making the
|
||||
backward-compatibility-breaking metadata change (<a href="https://github.com/grpc/proposal/blob/master/L7-go-metadata-api.md">gRFC
|
||||
L7</a>), and
|
||||
also for designing the new resolver/balancer API (<a href="https://github.com/grpc/proposal/pull/30">gRFC
|
||||
L9</a>).</p>
|
||||
|
||||
<h2 id="regression-testing">Regression Testing</h2>
|
||||
|
||||
<p>Every PR in our repo must pass our unit and end-to-end tests. Our current test
|
||||
coverage is 85%. Anytime a regression is identified, we add a test that covers
|
||||
the failing scenario, both to prove to ourselves that the problem is resolved by
|
||||
the fix, and to prevent it from reoccurring in the future. This helps us
|
||||
improve our overall coverage numbers as well. We also intend to re-enable
|
||||
coverage reporting for all PRs, but in a non-blocking fashion (<a href="https://github.com/grpc/grpc-go/issues/1676">related
|
||||
issue</a>).</p>
|
||||
|
||||
<p>In addition to testing for correctness, any PR that we suspect will impact
|
||||
performance is run though our benchmarks. We have a set of benchmarks both in
|
||||
our <a href="https://github.com/grpc/grpc-go/tree/master/benchmark">open source repo</a>
|
||||
and also within Google. These comprise a variety of workloads that we believe
|
||||
are most important for our users, both streaming and unary, and some are
|
||||
specifically designed to measure our optimal QPS, throughput, or latency.</p>
|
||||
|
||||
<h2 id="releases">Releases</h2>
|
||||
|
||||
<p>The GA release of gRPC-Go was made in conjunction with the other languages in
|
||||
July of 2016. The team performed several patch releases between then and the
|
||||
end of 2016, but none included release notes. Our subsequent releases have
|
||||
improved in regularity (a minor release is performed every six weeks) and
|
||||
in the quality of the release notes. We also are responsive with patch
|
||||
releases, back-porting bug fixes to older releases either on demand or for more
|
||||
serious issues within a week.</p>
|
||||
|
||||
<p>When performing a release, in addition to the tests in our repo, we also run a
|
||||
full suite of inter-op tests with other gRPC language implementations. This
|
||||
process has been working well for us, and we will cover more about this in a
|
||||
future blog post.</p>
|
||||
|
||||
<h2 id="non-open-source-work">Non-Open Source Work</h2>
|
||||
|
||||
<p>We have taken an “open source first” approach to developing gRPC. This means
|
||||
that, wherever possible, gRPC functionality is added directly into the open
|
||||
source project. However, to work within Google’s infrastructure, our team
|
||||
sometimes needs to provide additional functionality on top of gRPC. This is
|
||||
typically done through hooks like the <a href="https://godoc.org/google.golang.org/grpc/stats#Handler">stats
|
||||
API</a> or
|
||||
<a href="https://godoc.org/google.golang.org/grpc#UnaryClientInterceptor">interceptors</a>
|
||||
or <a href="https://godoc.org/google.golang.org/grpc/resolver">custom resolvers</a>.</p>
|
||||
|
||||
<p>To keep Google’s internal version of gRPC up-to-date with the open source
|
||||
version, we do weekly or on-demand imports. Before an import, we run every test
|
||||
within Google that depends upon gRPC. This gives us another way in which we can
|
||||
catch problems before performing releases in Open Source.</p>
|
||||
|
||||
<h2 id="looking-forward">Looking Forward</h2>
|
||||
|
||||
<p>In 2018, we intend to do more of the same, and maintain our SLOs around
|
||||
addressing issues and accepting contributions to the project. We also would
|
||||
like to more aggressively tag issues with the <a href="https://github.com/grpc/grpc-go/labels/Status%3A%20Help%20Wanted">“Help
|
||||
Wanted”</a> label
|
||||
for anyone looking to contribute to have a bigger selection of issues to choose
|
||||
from.</p>
|
||||
|
||||
<p>For gRPC itself, one of our main focuses right now is performance, which we hope
|
||||
will transparently benefit many of our users. In the near-term, we have some
|
||||
exciting changes we’re wrapping up that should provide a 30+% reduction in
|
||||
latency with high concurrency, resulting in a QPS improvement of ~25%. Once
|
||||
that work is done, we have a list of other <a href="https://github.com/grpc/grpc-go/issues?q=is%3Aissue+is%3Aopen+label%3A%22Type%3A+Performance%22">performance
|
||||
issues</a>
|
||||
that we’ll be tackling next.</p>
|
||||
|
||||
<p>On user experience, we want to provide better documentation, and are starting to
|
||||
improve our godoc with better comments and more examples. We want to improve
|
||||
the overall experience of using gRPC, so we will be working closely on projects
|
||||
around distributed tracing, monitoring, and testing to make gRPC services easier
|
||||
to manage in production. We want to do more, and we are hoping that starting
|
||||
with these and listening to feedback will help us ship improvements steadily.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,431 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
A short introduction to Channelz – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>A short introduction to Channelz</h1>
|
||||
<h5>Posted on Wednesday, September 05, 2018
|
||||
by
|
||||
|
||||
<a href="https://github.com/lyuxuan">Yuxuan Li</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>Channelz is a tool that provides comprehensive runtime info about connections at
|
||||
different levels in gRPC. It is designed to help debug live programs, which may
|
||||
be suffering from network, performance, configuration issues, etc. The
|
||||
<a href="https://github.com/grpc/proposal/blob/master/A14-channelz.md">gRFC</a> provides a
|
||||
detailed explanation of channelz design and is the canonical reference for all
|
||||
channelz implementations across languages. The purpose of this blog is to
|
||||
familiarize readers with channelz service and how to use it for debugging
|
||||
issues. The context of this post is set in
|
||||
<a href="https://github.com/grpc/grpc-go">gRPC-Go</a>, but the overall idea should be
|
||||
applicable across languages. At the time of writing, channelz is available for
|
||||
<a href="https://github.com/grpc/grpc-go">gRPC-Go</a> and
|
||||
<a href="https://github.com/grpc/grpc-java">gRPC-Java</a>. Support for
|
||||
<a href="https://github.com/grpc/grpc">C++</a> and wrapped languages is coming soon.</p>
|
||||
|
||||
<p>Let’s learn channelz through a simple example which uses channelz to help debug
|
||||
an issue. The
|
||||
<a href="https://github.com/grpc/grpc-go/tree/master/examples/helloworld">helloworld</a>
|
||||
example from our repo is slightly modified to set up a buggy scenario. You can
|
||||
find the full source code here:
|
||||
<a href="https://gist.github.com/lyuxuan/515fa6da7e0924b030e29b8be56fd90a">client</a>,
|
||||
<a href="https://gist.github.com/lyuxuan/81dd08ca649a6c78a61acc7ab05e0fef">server</a>.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<blockquote>
|
||||
<p><strong>Client setup:</strong></p>
|
||||
|
||||
<p>The client will make 100 SayHello RPCs to a specified target and load balance
|
||||
the workload with the round robin policy. Each call has a 150ms timeout. RPC
|
||||
responses and errors are logged for debugging purposes.</p>
|
||||
</blockquote>
|
||||
|
||||
<hr />
|
||||
|
||||
<p>Running the program, we notice in the log that there are intermittent errors
|
||||
with error code <strong>DeadlineExceeded</strong> (as shown in Figure 1).</p>
|
||||
|
||||
<p>However, there’s no clue about what is causing the deadline exceeded error and
|
||||
there are many possibilities:</p>
|
||||
|
||||
<ul>
|
||||
<li>network issue, e.g. connection lost</li>
|
||||
<li>proxy issue, e.g. dropped requests/responses in the middle</li>
|
||||
<li>server issue, e.g. lost requests or just slow to respond</li>
|
||||
</ul>
|
||||
|
||||
<p><img src="/img/log.png" style="max-width: 947px"></p>
|
||||
|
||||
<p style="text-align: center"> Figure 1. Program log
|
||||
screenshort</p>
|
||||
|
||||
<p>Let’s turn on grpc INFO logging for more debug info and see if we can find
|
||||
something helpful.</p>
|
||||
|
||||
<p><img src="/img/logWithInfo.png" style="max-width: 997px"></p>
|
||||
|
||||
<p style="text-align: center"> Figure 2.
|
||||
gRPC INFO log</p>
|
||||
|
||||
<p>As shown in Figure 2, the info log indicates that all three connections to the
|
||||
server are connected and ready for transmitting RPCs. No suspicious event shows
|
||||
up in the log. One thing that can be inferred from the info log is that all
|
||||
connections are up all the time, therefore the lost connection hypothesis can be
|
||||
ruled out.</p>
|
||||
|
||||
<p>To further narrow down the root cause of the issue, we will ask channelz for
|
||||
help.</p>
|
||||
|
||||
<p>Channelz provides gRPC internal networking machinery stats through a gRPC
|
||||
service. To enable channelz, users just need to register the channelz service to
|
||||
a gRPC server in their program and start the server. The code snippet below
|
||||
shows the API for registering channelz service to a
|
||||
<a href="https://godoc.org/google.golang.org/grpc#Server">grpc.Server</a>. Note that this
|
||||
has already been done for our example client.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#f92672">import</span> <span style="color:#e6db74">"google.golang.org/grpc/channelz/service"</span>
|
||||
|
||||
<span style="color:#75715e">// s is a *grpc.Server
|
||||
</span><span style="color:#75715e"></span><span style="color:#a6e22e">service</span>.<span style="color:#a6e22e">RegisterChannelzServiceToServer</span>(<span style="color:#a6e22e">s</span>)
|
||||
|
||||
<span style="color:#f92672">//</span> <span style="color:#a6e22e">call</span> <span style="color:#a6e22e">s</span>.<span style="color:#a6e22e">Serve</span>() <span style="color:#a6e22e">to</span> <span style="color:#a6e22e">serve</span> <span style="color:#a6e22e">channelz</span> <span style="color:#a6e22e">service</span></code></pre></div>
|
||||
<p>A web tool called
|
||||
<a href="https://github.com/grpc/grpc-experiments/tree/master/gdebug">grpc-zpages</a>
|
||||
has been developed to conveniently serve channelz data through a web page.
|
||||
First, configure the web app to connect to the gRPC port that’s serving the
|
||||
channelz service (see instructions from the previous link). Then, open the
|
||||
channelz web page in the browser. You should see a web page like Figure 3. Now
|
||||
we can start querying channelz!</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="/img/mainpage.png" style="max-width: 935px">
|
||||
</p>
|
||||
|
||||
<p style="text-align: center"> Figure 3.
|
||||
Channelz main page</p>
|
||||
|
||||
<p>As the error is on the client side, let’s first click on
|
||||
<a href="https://github.com/grpc/proposal/blob/master/A14-channelz.md#gettopchannels">TopChannels</a>.
|
||||
TopChannels is a collection of root channels which don’t have parents. In
|
||||
gRPC-Go, a top channel is a
|
||||
<a href="https://godoc.org/google.golang.org/grpc#ClientConn">ClientConn</a> created by the
|
||||
user through <a href="https://godoc.org/google.golang.org/grpc#Dial">Dial</a> or
|
||||
<a href="https://godoc.org/google.golang.org/grpc#DialContext">DialContext</a>, and used
|
||||
for making RPC calls. Top channels are of
|
||||
<a href="https://github.com/grpc/grpc-proto/blob/9b13d199cc0d4703c7ea26c9c330ba695866eb23/grpc/channelz/v1/channelz.proto#L37">Channel</a>
|
||||
type in channelz, which is an abstraction of a connection that an RPC can be
|
||||
issued to.</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="/img/topChan1.png" style="max-width: 815px">
|
||||
</p>
|
||||
|
||||
<p style="text-align: center"> Figure 4.
|
||||
TopChannels result</p>
|
||||
|
||||
<p>So we click on the TopChannels, and a page like Figure 4 appears, which lists
|
||||
all the live top channel(s) with related info.</p>
|
||||
|
||||
<p>As shown in Figure 5, there is only one top channel with id = 2 (Note that text
|
||||
in square brackets is the reference name of the in memory channel object, which
|
||||
may vary across languages).</p>
|
||||
|
||||
<p>Looking at the <strong>Data</strong> section, we can see there are 15 calls failed out of 100
|
||||
on this channel.</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="/img/topChan2.png" style="max-width: 815px">
|
||||
</p>
|
||||
|
||||
<p style="text-align: center"> Figure 5.
|
||||
Top Channel (id = 2)</p>
|
||||
|
||||
<p>On the right hand side, it shows the channel has no child <strong>Channels</strong>, 3
|
||||
<strong>Subchannels</strong> (as highlighted in Figure 6), and 0 <strong>Sockets</strong>.</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="/img/topChan3.png" style="max-width: 815px">
|
||||
</p>
|
||||
|
||||
<p style="text-align: center"> Figure 6.
|
||||
Subchannels owned by the Channel (id = 2)</p>
|
||||
|
||||
<p>A
|
||||
<a href="https://github.com/grpc/grpc-proto/blob/9b13d199cc0d4703c7ea26c9c330ba695866eb23/grpc/channelz/v1/channelz.proto#L61">Subchannel</a>
|
||||
is an abstraction over a connection and used for load balancing. For example,
|
||||
you want to send requests to “google.com”. The resolver resolves “google.com” to
|
||||
multiple backend addresses that serve “google.com”. In this example, the client
|
||||
is set up with the round robin load balancer, so all live backends are sent
|
||||
equal traffic. Then the (logical) connection to each backend is represented as a
|
||||
Subchannel. In gRPC-Go, a
|
||||
<a href="https://godoc.org/google.golang.org/grpc/balancer#SubConn">SubConn</a> can be seen
|
||||
as a Subchannel.</p>
|
||||
|
||||
<p>The three Subchannels owned by the parent Channel means there are three
|
||||
connections to three different backends for sending the RPCs to. Let’s look
|
||||
inside each of them for more info.</p>
|
||||
|
||||
<p>So we click on the first Subchannel ID (i.e. “4[]”) listed, and a page like
|
||||
Figure 7 renders. We can see that all calls on this Subchannel have succeeded.
|
||||
Thus it’s unlikely this Subchannel is related to the issue we are having.</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="/img/subChan4.png" style="max-width: 815px">
|
||||
</p>
|
||||
|
||||
<p style="text-align: center"> Figure 7.
|
||||
Subchannel (id = 4)</p>
|
||||
|
||||
<p>So we go back, and click on Subchannel 5 (i.e. “5[]”). Again, the web page
|
||||
indicates that Subchannel 5 also never had any failed calls.</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="/img/subChan6_1.png" style="max-width: 815px">
|
||||
</p>
|
||||
|
||||
<p style="text-align: center"> Figure 8.
|
||||
Subchannel (id = 6)</p>
|
||||
|
||||
<p>And finally, we click on Subchannel 6. This time, there’s something different.
|
||||
As we can see in Figure 8, there are 15 out of 34 RPC calls failed on this
|
||||
Subchannel. And remember that the parent Channel also has exactly 15 failed
|
||||
calls. Therefore, Subchannel 6 is where the issue comes from. The state of the
|
||||
Subchannel is <strong>READY</strong>, which means it is connected and is ready to transmit
|
||||
RPCs. That rules out network connection problems. To dig up more info, let’s
|
||||
look at the Socket owned by this Subchannel.</p>
|
||||
|
||||
<p>A
|
||||
<a href="https://github.com/grpc/grpc-proto/blob/9b13d199cc0d4703c7ea26c9c330ba695866eb23/grpc/channelz/v1/channelz.proto#L227">Socket</a>
|
||||
is roughly equivalent to a file descriptor, and can be generally regarded as the
|
||||
TCP connection between two endpoints. In grpc-go,
|
||||
<a href="https://github.com/grpc/grpc-go/blob/ce4f3c8a89229d9db3e0c30d28a9f905435ad365/internal/transport/http2_client.go#L46">http2Client</a>
|
||||
and
|
||||
<a href="https://github.com/grpc/grpc-go/blob/ce4f3c8a89229d9db3e0c30d28a9f905435ad365/internal/transport/http2_server.go#L61">http2Server</a>
|
||||
correspond to Socket. Note that a network listener is also considered a Socket,
|
||||
and will show up in the channelz Server info.</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="/img/subChan6_2.png" style="max-width: 815px">
|
||||
</p>
|
||||
|
||||
<p style="text-align: center"> Figure 9.
|
||||
Subchannel (id = 6) owns Socket (id = 8)</p>
|
||||
|
||||
<p>We click on Socket 8, which is at the bottom of the page (see Figure 9). And we
|
||||
now see a page like Figure 10.</p>
|
||||
|
||||
<p>The page provides comprehensive info about the socket like the security
|
||||
mechanism in use, stream count, message count, keepalives, flow control numbers,
|
||||
etc. The socket options info is not shown in the screenshot, as there are a lot
|
||||
of them and not related to the issue we are investigating.</p>
|
||||
|
||||
<p>The <strong>Remote Address</strong> field suggests that the backend we are having a problem
|
||||
with is <strong>“127.0.0.1:10003”</strong>. The stream counts here correspond perfectly to
|
||||
the call counts of the parent Subchannel. From this, we can know that the server
|
||||
is not actively sending DeadlineExceeded errors. This is because if the
|
||||
DeadlineExceeded error is returned by the server, then the streams would all be
|
||||
successful. A client side stream’s success is independent of whether the call
|
||||
succeeds. It is determined by whether a HTTP2 frame with EOS bit set has been
|
||||
received (refer to the
|
||||
<a href="https://github.com/grpc/proposal/blob/master/A14-channelz.md#socket-data">gRFC</a>
|
||||
for more info). Also, we can see that the number of messages sent is 34, which
|
||||
equals the number of calls, and it rules out the possibility of the client being
|
||||
stuck somehow and results in deadline exceeded. In summary, we can narrow down
|
||||
the issue to the server which serves on 127.0.0.1:10003. It may be that the
|
||||
server is slow to respond, or some proxy in front of it is dropping requests.</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="/img/socket8.png" style="max-width: 815px">
|
||||
</p>
|
||||
|
||||
<p style="text-align: center"> Figure 10. Socket
|
||||
(id = 8)</p>
|
||||
|
||||
<p>As you see, channelz has helped us pinpoint the potential root cause of the
|
||||
issue with just a few clicks. You can now concentrate on what’s happening with
|
||||
the pinpointed server. And again, channelz may help expedite the debugging at
|
||||
the server side too.</p>
|
||||
|
||||
<p>We will stop here and let readers explore the server side channelz, which is
|
||||
simpler than the client side. In channelz, a
|
||||
<a href="https://github.com/grpc/grpc-proto/blob/9b13d199cc0d4703c7ea26c9c330ba695866eb23/grpc/channelz/v1/channelz.proto#L199">Server</a>
|
||||
is also an RPC entry point like a Channel, where incoming RPCs arrive and get
|
||||
processed. In grpc-go, a
|
||||
<a href="https://godoc.org/google.golang.org/grpc#Server">grpc.Server</a> corresponds to a
|
||||
channelz Server. Unlike Channel, Server only has Sockets (both listen socket(s)
|
||||
and normal connected socket(s)) as its children.</p>
|
||||
|
||||
<p>Here are some hints for the readers:</p>
|
||||
|
||||
<ul>
|
||||
<li>Look for the server with the address (127.0.0.1:10003).</li>
|
||||
<li>Look at the call counts.</li>
|
||||
<li>Go to the Socket(s) owned by the server.</li>
|
||||
<li>Look at the Socket stream counts and message counts.</li>
|
||||
</ul>
|
||||
|
||||
<p>You should notice that the number of messages received by the server socket is
|
||||
the same as sent by the client socket (Socket 8), which rules out the case of
|
||||
having a misbehaving proxy (dropping request) in the middle. And the number of
|
||||
messages sent by the server socket is equal to the messages received at client
|
||||
side, which means the server was not able to send back the response before
|
||||
deadline. You may now look at the
|
||||
<a href="https://gist.github.com/lyuxuan/81dd08ca649a6c78a61acc7ab05e0fef">server</a> code
|
||||
to verify whether it is indeed the cause.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<blockquote>
|
||||
<p><strong>Server setup:</strong></p>
|
||||
|
||||
<p>The server side program starts up three GreeterServers, with two of them using
|
||||
an implementation
|
||||
(<a href="https://gist.github.com/lyuxuan/81dd08ca649a6c78a61acc7ab05e0fef#file-main-go-L42">server{}</a>)
|
||||
that imposes no delay when responding to the client, and one using an
|
||||
implementation
|
||||
(<a href="https://gist.github.com/lyuxuan/81dd08ca649a6c78a61acc7ab05e0fef#file-main-go-L50">slowServer{}</a>)
|
||||
which injects a variable delay of 100ms - 200ms before sending the response.</p>
|
||||
</blockquote>
|
||||
|
||||
<hr />
|
||||
|
||||
<p>As you can see through this demo, channelz helped us quickly narrow down the
|
||||
possible causes of an issue and is easy to use. For more resources, see the
|
||||
detailed channelz
|
||||
<a href="https://github.com/grpc/proposal/blob/master/A14-channelz.md">gRFC</a>. Find us on
|
||||
github at <a href="https://github.com/grpc/grpc-go">https://github.com/grpc/grpc-go</a>.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,162 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC releases Beta, opening door for use in production environments. – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC releases Beta, opening door for use in production environments.</h1>
|
||||
<h5>Posted on Monday, October 26, 2015
|
||||
|
||||
|
||||
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>
|
||||
We’re also taking a big step forward in improving the installation process. Over the past few weeks we’ve rolled out gRPC packages to <a href="https://packages.debian.org/jessie-backports/libgrpc0">Debian Stable/Backports</a>. Installation in most cases is now a two line install using the Debian package and available language specific package managers (<a href="https://search.maven.org/#artifactdetails%7Cio.grpc%7Cgrpc-core%7C0.9.0%7Cjar">maven</a>, <a href="https://pypi.python.org/pypi/grpcio">pip</a>, <a href="https://rubygems.org/gems/grpc">gem</a>, <a href="https://packagist.org/packages/grpc/grpc">composer</a>, <a href="https://pecl.php.net/package/gRPC">pecl</a>, <a href="https://www.npmjs.com/package/grpc">npm</a>, <a href="https://www.nuget.org/packages/Grpc/">nuget</a>, <a href="https://cocoapods.org/pods/gRPC">pod</a>). In addition <a href="https://hub.docker.com/r/grpc/">gRPC docker images</a> are now available on Docker Hub.
|
||||
</p>
|
||||
<p>
|
||||
We’ve updated the <a href="/docs/">documentation</a> on grpc.io to reflect the latest changes and released additional language-specific <a href="/docs/reference/">reference docs</a>. See what’s changed with the Beta release in the release notes on GitHub for <a href="https://github.com/grpc/grpc-java/releases/tag/v0.9.0">Java</a>, <a href="https://godoc.org/google.golang.org/grpc">Go</a> and <a href="https://github.com/grpc/grpc/releases/tag/release-0_11_0">all other</a> languages.
|
||||
</p>
|
||||
<p>
|
||||
In keeping in line with our <a href="/blog/principles">principles</a> and goal to enable highly performant and scalable APIs and microservices on top of HTTP/2, in the coming months, the focus of the gRPC project will be to keep improving performance and stability and adding carefully chosen features for production use cases. Documentation will also be clarified and will continue to improve with new examples and guides.
|
||||
</p>
|
||||
<p>
|
||||
We’ve been very excited to see the community response to gRPC and the various projects starting to use it (<a href="https://coreos.com/blog/etcd-2.2/">etcd v3 experimental api</a>, <a href="https://github.com/gengo/grpc-gateway">grpc-gateway</a> for RESTful APIs and others).
|
||||
</p>
|
||||
<p>
|
||||
We really want to thank everyone who contributed code, gave presentations, adopted the technology and engaged in the community. With your help support we look forward to the 1.0!
|
||||
</p>
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,201 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC with REST and Open APIs – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC with REST and Open APIs</h1>
|
||||
<h5>Posted on Monday, May 09, 2016
|
||||
by
|
||||
|
||||
Brandon Phillips
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>Our guest post today comes from Brandon Phillips of <a href="https://coreos.com/">CoreOS</a>. CoreOS builds open source projects and products for Linux Containers. Their flagship product for consensus and discovery <a href="https://coreos.com/etcd/">etcd</a> and their container engine <a href="https://coreos.com/rkt/">rkt</a> are early adopters of gRPC.</p>
|
||||
|
||||
<p>One of the key reasons CoreOS chose gRPC is because it uses HTTP/2, enabling applications to present both a HTTP 1.1 REST/JSON API and an efficient gRPC interface on a single TCP port (available for Go). This provides developers with compatibility with the REST web ecosystem, while advancing a new, high-efficiency RPC protocol. With the recent release of Go 1.6, Go ships with a stable <code>net/http2</code> package by default.</p>
|
||||
|
||||
<p>Since many CoreOS clients speak HTTP 1.1 with JSON, gRPC’s easy interoperability with JSON and the <a href="https://github.com/OAI/OpenAPI-Specification">Open API Specification</a> (formerly Swagger) was extremely valuable. For their users who are more comfortable with HTTP/1.1+JSON-based and Open API Spec APIs they used a combination of open source libraries to make their gRPC services available in both gRPC and HTTP REST flavors, using API multiplexers to give users the best of both worlds. Let’s dive into the details and find out how they did it!</p>
|
||||
|
||||
<p><em>This post was originally published at the <a href="https://coreos.com/blog/gRPC-protobufs-swagger.html">CoreOS blog</a>. We are reproducing it here with some edits.</em></p>
|
||||
|
||||
<h2 id="a-grpc-application-called-echoservice">A gRPC application called EchoService</h2>
|
||||
|
||||
<p>In this post we will build a small proof-of-concept gRPC application from a gRPC API definition, add a REST service gateway, and finally serve it all on a single TLS port. The application is called EchoService, and is the web equivalent of the shell command echo: the service returns, or “echoes”, whatever text is sent to it.</p>
|
||||
|
||||
<p>First, let’s define the arguments to EchoService in a protobuf message called EchoMessage, which includes a single field called value. We will define this message in a protobuf “.proto” file called <code>service.proto</code>. Here is our EchoMessage:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto"><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">EchoMessage</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">string</span> value <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
||||
<p>In this same .proto file, we define a gRPC service that takes this data structure and returns it:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto"><span style="color:#66d9ef">service</span> EchoService {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">rpc</span> Echo(EchoMessage) <span style="color:#66d9ef">returns</span> (EchoMessage) {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> }<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
||||
<p>Running this <code>service.proto</code> file “as is” through the Protocol Buffer compiler <code>protoc</code> generates a stub gRPC service in Go, along with clients in various languages. But gRPC alone isn’t as useful as a service that also exposes a REST interface, so we won’t stop with the gRPC service stub.</p>
|
||||
|
||||
<p>Next, we add the gRPC REST Gateway. This library will build a RESTful proxy on top of the gRPC EchoService. To build this gateway, we add metadata to the EchoService .proto to indicate that the Echo RPC maps to a RESTful POST method with all RPC parameters mapped to a JSON body. The gateway can map RPC parameters to URL paths and query parameters, but we omit those complications here for brevity.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto"><span style="color:#66d9ef">service</span> EchoService {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">rpc</span> Echo(EchoMessage) <span style="color:#66d9ef">returns</span> (EchoMessage) {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">option</span> (google.api.http) <span style="color:#f92672">=</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> post<span style="color:#f92672">:</span> <span style="color:#e6db74">"/v1/echo"</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> body<span style="color:#f92672">:</span> <span style="color:#e6db74">"*"</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> };<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> }<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
||||
<p>This means the gateway, once generated by <code>protoc</code>, can now accept a HTTP request from <code>curl</code> like this:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">curl -X POST -k https://localhost:10000/v1/echo -d <span style="color:#e6db74">'{"value": "CoreOS is hiring!"}'</span></code></pre></div>
|
||||
<p>The whole system so far looks like this, with a single <code>service.proto</code> file generating both a gRPC server and a REST proxy:</p>
|
||||
|
||||
<p><img src="/img/grpc-rest-gateway.png" class="img-responsive" alt="gRPC API with REST gateway"></p>
|
||||
|
||||
<p>To bring this all together, the echo service creates a Go <code>http.Handler</code> to detect if the protocol is HTTP/2 and the Content-Type is “application/grpc”, and sends such requests to the gRPC server. Everything else is routed to the REST gateway. The code looks something like this:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">r</span>.<span style="color:#a6e22e">ProtoMajor</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">&&</span> <span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">Contains</span>(<span style="color:#a6e22e">r</span>.<span style="color:#a6e22e">Header</span>.<span style="color:#a6e22e">Get</span>(<span style="color:#e6db74">"Content-Type"</span>), <span style="color:#e6db74">"application/grpc"</span>) {
|
||||
<span style="color:#a6e22e">grpcServer</span>.<span style="color:#a6e22e">ServeHTTP</span>(<span style="color:#a6e22e">w</span>, <span style="color:#a6e22e">r</span>)
|
||||
} <span style="color:#66d9ef">else</span> {
|
||||
<span style="color:#a6e22e">otherHandler</span>.<span style="color:#a6e22e">ServeHTTP</span>(<span style="color:#a6e22e">w</span>, <span style="color:#a6e22e">r</span>)
|
||||
}</code></pre></div>
|
||||
<p>To try it out, all you need is a working Go 1.6 development environment and the following simple commands:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ go get -u github.com/philips/grpc-gateway-example
|
||||
$ grpc-gateway-example serve</code></pre></div>
|
||||
<p>With the server running you can try requests on both HTTP 1.1 and gRPC interfaces:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">grpc-gateway-example echo Take a REST from REST with gRPC
|
||||
curl -X POST -k https://localhost:10000/v1/echo -d <span style="color:#e6db74">'{"value": "CoreOS is hiring!"}'</span></code></pre></div>
|
||||
<p>One last bonus: because we have an Open API specification, you can browse the Open API UI running at <code>https://localhost:10000/swagger-ui/#!/EchoService/Echo</code> if you have the server above running on your laptop.</p>
|
||||
|
||||
<p><img src="/img/grpc-swaggerscreen.png" class="img-responsive" alt="gRPC/REST Open API document"></p>
|
||||
|
||||
<p>We’ve taken a look at how to use gRPC to bridge to the world of REST. If you want to take a look at the complete project, check out the <a href="https://github.com/philips/grpc-gateway-example">repo on GitHub</a>. We think this pattern of using a single protobuf to describe an API leads to an easy to consume, flexible API framework, and we’re excited to leverage it in more of our projects.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,220 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC and Deadlines – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC and Deadlines</h1>
|
||||
<h5>Posted on Monday, February 26, 2018
|
||||
by
|
||||
|
||||
Gráinne Sheerin, Google SRE
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p><strong>TL;DR Always set a deadline</strong>. This post explains why we recommend being deliberate about setting deadlines, with useful code snippets to show you how.</p>
|
||||
|
||||
<p>When you use gRPC, the gRPC library takes care of communication, marshalling, unmarshalling, and deadline enforcement. Deadlines allow gRPC clients to specify how long they are willing to wait for an RPC to complete before the RPC is terminated with the error <code>DEADLINE_EXCEEDED</code>. By default this deadline is a very large number, dependent on the language implementation. How deadlines are specified is also language-dependent. Some language APIs work in terms of a <strong>deadline</strong>, a fixed point in time by which the RPC should complete. Others use a <strong>timeout</strong>, a duration of time after which the RPC times out.</p>
|
||||
|
||||
<p>In general, when you don’t set a deadline, resources will be held for all in-flight requests, and all requests can potentially reach the maximum timeout. This puts the service at risk of running out of resources, like memory, which would increase the latency of the service, or could crash the entire process in the worst case.</p>
|
||||
|
||||
<p>To avoid this, services should specify the longest default deadline they technically support, and clients should wait until the response is no longer useful to them. For the service this can be as simple as providing a comment in the .proto file. For the client this involves setting useful deadlines.</p>
|
||||
|
||||
<p>There is no single answer to “What is a good deadline/timeout value?”. Your service might be as simple as the <a href="https://github.com/grpc/grpc/blob/master/examples/protos/helloworld.proto">Greeter</a> in our quick start guides, in which case 100 ms would be fine. Your service might be as complex as a globally-distributed and strongly consistent database. The deadline for a client query will be different from how long they should wait for you to drop their table.</p>
|
||||
|
||||
<p>So what do you need to consider to make an informed choice of deadline? Factors to take into account include the end to end latency of the whole system, which RPCs are serial, and which can be made in parallel. You should to be able to put numbers on it, even if it’s a rough calculation. Engineers need to understand the service and then set a deliberate deadline for the RPCs between clients and servers.</p>
|
||||
|
||||
<p>In gRPC, both the client and server make their own independent and local determination about whether the remote procedure call (RPC) was successful. This means their conclusions may not match! An RPC that finished successfully on the server side can fail on the client side. For example, the server can send the response, but the reply can arrive at the client after their deadline has expired. The client will already have terminated with the status error <code>DEADLINE_EXCEEDED</code>. This should be checked for and managed at the application level.</p>
|
||||
|
||||
<h2 id="setting-a-deadline">Setting a deadline</h2>
|
||||
|
||||
<p>As a client you should always set a deadline for how long you are willing to wait for a reply from the server. Here’s an example using the greeting service from our <a href="/docs/quickstart/">Quick Start Guides</a>:</p>
|
||||
|
||||
<h3 id="c">C++</h3>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp">ClientContext context;
|
||||
time_point deadline <span style="color:#f92672">=</span> std<span style="color:#f92672">::</span>chrono<span style="color:#f92672">::</span>system_clock<span style="color:#f92672">::</span>now() <span style="color:#f92672">+</span>
|
||||
std<span style="color:#f92672">::</span>chrono<span style="color:#f92672">::</span>milliseconds(<span style="color:#ae81ff">100</span>);
|
||||
context.set_deadline(deadline);
|
||||
</code></pre></div>
|
||||
<h3 id="go">Go</h3>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#a6e22e">clientDeadline</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Now</span>().<span style="color:#a6e22e">Add</span>(<span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Duration</span>(<span style="color:#f92672">*</span><span style="color:#a6e22e">deadlineMs</span>) <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Millisecond</span>)
|
||||
<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">cancel</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">WithDeadline</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">clientDeadline</span>)</code></pre></div>
|
||||
<h3 id="java">Java</h3>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">response <span style="color:#f92672">=</span> blockingStub<span style="color:#f92672">.</span><span style="color:#a6e22e">withDeadlineAfter</span><span style="color:#f92672">(</span>deadlineMs<span style="color:#f92672">,</span> TimeUnit<span style="color:#f92672">.</span><span style="color:#a6e22e">MILLISECONDS</span><span style="color:#f92672">).</span><span style="color:#a6e22e">sayHello</span><span style="color:#f92672">(</span>request<span style="color:#f92672">);</span></code></pre></div>
|
||||
<p>This sets the deadline to 100ms from when the client RPC is set to when the response is picked up by the client.</p>
|
||||
|
||||
<h2 id="checking-deadlines">Checking deadlines</h2>
|
||||
|
||||
<p>On the server side, the server can query to see if a particular RPC is no longer wanted. Before a server starts work on a response it is very important to check if there is still a client waiting for it. This is especially important to do before starting expensive processing.</p>
|
||||
|
||||
<h3 id="c-1">C++</h3>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#66d9ef">if</span> (context<span style="color:#f92672">-></span>IsCancelled()) {
|
||||
<span style="color:#66d9ef">return</span> Status(StatusCode<span style="color:#f92672">::</span>CANCELLED, <span style="color:#e6db74">"Deadline exceeded or Client cancelled, abandoning."</span>);
|
||||
}
|
||||
</code></pre></div>
|
||||
<h3 id="go-1">Go</h3>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">Err</span>() <span style="color:#f92672">==</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Canceled</span> {
|
||||
<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">status</span>.<span style="color:#a6e22e">New</span>(<span style="color:#a6e22e">codes</span>.<span style="color:#a6e22e">Canceled</span>, <span style="color:#e6db74">"Client cancelled, abandoning."</span>)
|
||||
}</code></pre></div>
|
||||
<h3 id="java-1">Java</h3>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>Context<span style="color:#f92672">.</span><span style="color:#a6e22e">current</span><span style="color:#f92672">().</span><span style="color:#a6e22e">isCancelled</span><span style="color:#f92672">())</span> <span style="color:#f92672">{</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onError</span><span style="color:#f92672">(</span>Status<span style="color:#f92672">.</span><span style="color:#a6e22e">CANCELLED</span><span style="color:#f92672">.</span><span style="color:#a6e22e">withDescription</span><span style="color:#f92672">(</span><span style="color:#e6db74">"Cancelled by client"</span><span style="color:#f92672">).</span><span style="color:#a6e22e">asRuntimeException</span><span style="color:#f92672">());</span>
|
||||
<span style="color:#66d9ef">return</span><span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>Is it useful for a server to continue with the request, when you know your client has reached their deadline? It depends. If the response can be cached in the server, it can be worth processing and caching it; particularly if it’s resource heavy, and costs you money for each request. This will make future requests faster as the result will already be available.</p>
|
||||
|
||||
<h2 id="adjusting-deadlines">Adjusting deadlines</h2>
|
||||
|
||||
<p>What if you set a deadline but a new release or server version causes a bad regression? The deadline could be too small, resulting in all your requests timing out with <code>DEADLINE_EXCEEDED</code>, or too large and your user tail latency is now massive. You can use a flag to set and adjust the deadline.</p>
|
||||
|
||||
<h3 id="c-2">C++</h3>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#75715e">#include</span> <span style="color:#75715e"><gflags/gflags.h></span><span style="color:#75715e">
|
||||
</span><span style="color:#75715e"></span>DEFINE_int32(deadline_ms, <span style="color:#ae81ff">20</span><span style="color:#f92672">*</span><span style="color:#ae81ff">1000</span>, <span style="color:#e6db74">"Deadline in milliseconds."</span>);
|
||||
|
||||
ClientContext context;
|
||||
time_point deadline <span style="color:#f92672">=</span> std<span style="color:#f92672">::</span>chrono<span style="color:#f92672">::</span>system_clock<span style="color:#f92672">::</span>now() <span style="color:#f92672">+</span>
|
||||
std<span style="color:#f92672">::</span>chrono<span style="color:#f92672">::</span>milliseconds(FLAGS_deadline_ms);
|
||||
context.set_deadline(deadline);
|
||||
</code></pre></div>
|
||||
<h3 id="go-2">Go</h3>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">deadlineMs</span> = <span style="color:#a6e22e">flag</span>.<span style="color:#a6e22e">Int</span>(<span style="color:#e6db74">"deadline_ms"</span>, <span style="color:#ae81ff">20</span><span style="color:#f92672">*</span><span style="color:#ae81ff">1000</span>, <span style="color:#e6db74">"Default deadline in milliseconds."</span>)
|
||||
|
||||
<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">cancel</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">WithTimeout</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Duration</span>(<span style="color:#f92672">*</span><span style="color:#a6e22e">deadlineMs</span>) <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Millisecond</span>)</code></pre></div>
|
||||
<h3 id="java-2">Java</h3>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#a6e22e">@Option</span><span style="color:#f92672">(</span>name<span style="color:#f92672">=</span><span style="color:#e6db74">"--deadline_ms"</span><span style="color:#f92672">,</span> usage<span style="color:#f92672">=</span><span style="color:#e6db74">"Deadline in milliseconds."</span><span style="color:#f92672">)</span>
|
||||
<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">int</span> deadlineMs <span style="color:#f92672">=</span> 20<span style="color:#f92672">*</span>1000<span style="color:#f92672">;</span>
|
||||
|
||||
response <span style="color:#f92672">=</span> blockingStub<span style="color:#f92672">.</span><span style="color:#a6e22e">withDeadlineAfter</span><span style="color:#f92672">(</span>deadlineMs<span style="color:#f92672">,</span> TimeUnit<span style="color:#f92672">.</span><span style="color:#a6e22e">MILLISECONDS</span><span style="color:#f92672">).</span><span style="color:#a6e22e">sayHello</span><span style="color:#f92672">(</span>request<span style="color:#f92672">);</span></code></pre></div>
|
||||
<p>Now the deadline can be adjusted to wait longer to avoid failing, without the need to cherry-pick a release with a different hard coded deadline. This lets you mitigate the issue for users until the regression can be debugged and resolved.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,200 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Announcing out of the box support for gRPC in the Flatbuffers serialization library. – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>Announcing out of the box support for gRPC in the Flatbuffers serialization library.</h1>
|
||||
<h5>Posted on Thursday, August 17, 2017
|
||||
by
|
||||
|
||||
Wouter van Oortmerssen
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>The recent release of Flatbuffers <a href="https://github.com/google/flatbuffers/releases">version 1.7</a> introduced truly zero-copy support for gRPC out of the box.</p>
|
||||
|
||||
<p><a href="https://google.github.io/flatbuffers/">Flatbuffers</a> is a serialization library that allows you to access serialized data without first unpacking it or allocating any
|
||||
additional data structures. It was originally designed for games and other resource constrained applications, but is now finding more general use, both by teams within Google and in other companies such as Netflix and Facebook.</p>
|
||||
|
||||
<p>Flatbuffers enables maximum throughput by directly using gRPC’s slice buffers with zero-copy for common use cases. An incoming rpc can be processed directly from gRPCs internal buffers, and constructing a new message will write directly to these buffers without intermediate steps.</p>
|
||||
|
||||
<p>This is currently, fully supported in the C++ implementation of FlatBuffers, with more languages to come. There is also an implementation in Go, which is not entirely zero copy, but still very low on allocation cost (see below).</p>
|
||||
|
||||
<h2 id="example-usage">Example Usage</h2>
|
||||
|
||||
<p>Let’s look at an example of how this works.</p>
|
||||
|
||||
<h3 id="use-flatbuffers-as-an-idl">Use Flatbuffers as an IDL</h3>
|
||||
|
||||
<p>Start with an <code>.fbs</code> schema (similar to .proto, if you are familiar with protocol buffers) that declares an RPC service:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto">table HelloReply {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> message<span style="color:#f92672">:</span><span style="color:#66d9ef">string</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>table HelloRequest {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> name<span style="color:#f92672">:</span><span style="color:#66d9ef">string</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>table ManyHellosRequest {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> name<span style="color:#f92672">:</span><span style="color:#66d9ef">string</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> num_greetings<span style="color:#f92672">:</span>int;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>rpc_service Greeter {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> SayHello(HelloRequest)<span style="color:#f92672">:</span>HelloReply;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> SayManyHellos(ManyHellosRequest)<span style="color:#f92672">:</span>HelloReply (streaming<span style="color:#f92672">:</span> <span style="color:#e6db74">"server"</span>);<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
||||
<p>To generate C++ code from this, run: <code>flatc --cpp --grpc example.fbs</code>, much like in protocol buffers.</p>
|
||||
|
||||
<h4 id="generated-server-implementation">Generated Server Implementation</h4>
|
||||
|
||||
<p>The server implementation is very similar to protocol buffers, except now the request and response messages are of type <code>flatbuffers::grpc::Message<HelloRequest> *</code>.
|
||||
Unlike protocol buffers, where these types represent a tree of C++ objects, here they are merely handles to a flat object in the underlying gRPC slice. You can access the data directly:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#66d9ef">auto</span> request <span style="color:#f92672">=</span> request_msg<span style="color:#f92672">-></span>GetRoot();
|
||||
<span style="color:#66d9ef">auto</span> name <span style="color:#f92672">=</span> request<span style="color:#f92672">-></span>name()<span style="color:#f92672">-></span>str();
|
||||
</code></pre></div>
|
||||
<p>Building a response is equally simple</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#66d9ef">auto</span> msg_offset <span style="color:#f92672">=</span> mb_.CreateString(<span style="color:#e6db74">"Hello, "</span> <span style="color:#f92672">+</span> name);
|
||||
<span style="color:#66d9ef">auto</span> hello_offset <span style="color:#f92672">=</span> CreateHelloReply(mb_, msg_offset);
|
||||
mb_.Finish(hello_offset);
|
||||
<span style="color:#f92672">*</span>response_msg <span style="color:#f92672">=</span> mb_.ReleaseMessage<span style="color:#f92672"><</span>HelloReply<span style="color:#f92672">></span>();
|
||||
</code></pre></div>
|
||||
<p>The client code is the same as that generated by protocol buffers, except for the FlatBuffer access and construction code.</p>
|
||||
|
||||
<p>See the full example <a href="https://github.com/google/flatbuffers/tree/master/grpc/samples/greeter">here</a>. To compile it, you need gRPC.
|
||||
The same repo has a <a href="https://github.com/google/flatbuffers/blob/master/grpc/tests/go_test.go">similar example</a> for Go.</p>
|
||||
|
||||
<p>Read more about using and building FlatBuffers for your platform <a href="https://google.github.io/flatbuffers/">on the flatbuffers site</a>.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC Project is now 1.0 and ready for production deployments – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC Project is now 1.0 and ready for production deployments</h1>
|
||||
<h5>Posted on Tuesday, August 23, 2016
|
||||
by
|
||||
|
||||
Varun Talwar
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>Today, the gRPC project has reached a significant milestone with its <a href="https://github.com/grpc/grpc/releases">1.0 release</a>.
|
||||
Languages moving to 1.0 include C++, Java, Go, Node, Ruby, Python and C# across Linux, Windows, and Mac. Objective-C and Android Java support on iOS and Android is also moving to 1.0. The 1.0 release means that the core protocol and API surface are now stable with measured performance, stress tested and developers can rely on these APIs and deploy in production, they will follow semantic versioning from here.</p>
|
||||
|
||||
<p>We are very excited about the progress we have made so far and would like to thank all our users and contributors. First announced in March 2015 with <a href="https://corner.squareup.com/2015/02/grpc.html">Square</a>, gRPC is already being used in many open source projects like <a href="https://github.com/coreos/etcd">etcd</a> from CoreOS, <a href="https://github.com/docker/containerd">containerd</a> from Docker, <a href="https://github.com/cockroachdb/cockroach">cockroachdb</a> from Cockroach Labs, and by many other companies like <a href="https://vendasta.com">Vendasta</a>, <a href="https://github.com/Netflix/ribbon">Netflix</a>, <a href="http://yikyakapp.com">YikYak</a> and <a href="http://carbon3d.com">Carbon 3d</a>. Outside of microservices, telecom giants like <a href="https://github.com/CiscoDevNet/grpc-getting-started">Cisco</a>, <a href="https://github.com/Juniper/open-nti">Juniper</a>, <a href="https://github.com/aristanetworks/goarista">Arista</a>, and Ciena, are building support for streaming telemetry and network configuration from their network devices using gRPC, as part of <a href="http://www.openconfig.net/">OpenConfig</a> effort.</p>
|
||||
|
||||
<p>From the beta release, we have made significant strides in the areas of usability, interoperability, and performance measurement on the <a href="https://www.youtube.com/watch?v=_vfbVJ_u5mE">road to 1.0</a>. In most of the languages, the <a href="/blog/installation">installation of the gRPC runtime</a> as well as setup of a development environment is a single command. Beyond installation, we have set up automated tests for gRPC across languages and RPC types in order to stress test our APIs and ensure interoperability. There is now a <a href="https://goo.gl/tHPEfD">performance dashboard</a> available in the open to see latency and throughput for unary and streaming ping pong for various languages. Other measurements have shown significant gains from using gRPC/Protobuf instead of HTTP/JSON such as in <a href="https://blog.gopheracademy.com/advent-2015/etcd-distributed-key-value-store-with-grpc-http2/">CoreOS blogpost</a> and in <a href="https://cloud.google.com/blog/big-data/2016/03/announcing-grpc-alpha-for-google-cloud-pubsub">Google Cloud PubSub testing</a>. In the coming months, we will invest a lot more in performance tuning.</p>
|
||||
|
||||
<p>Even within Google, we have seen Google cloud APIs like <a href="https://cloudplatform.googleblog.com/2015/07/A-Go-client-for-Google-Cloud-Bigtable.html">BigTable</a>, PubSub, <a href="https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/speech/grpc">Speech</a>, launch of a gRPC-based API surface leading to ease of use and performance benefits. Products like <a href="https://research.googleblog.com/2016/02/running-your-models-in-production-with.html">Tensorflow</a> have effectively used gRPC for inter-process communication as well.
|
||||
Beyond usage, we are keen to see the contributor community grow with gRPC. We are already starting to see contributions around gRPC in meaningful ways in the <a href="https://github.com/grpc-ecosystem">grpc-ecosystem</a> organization. We are very happy to see projects like <a href="https://github.com/grpc-ecosystem/grpc-gateway">grpc-gateway</a> to enable users to serve REST clients with gRPC based services, <a href="https://github.com/grpc-ecosystem/polyglot">Polyglot</a> to have a CLI for gRPC, <a href="https://github.com/grpc-ecosystem/go-grpc-prometheus">Prometheus monitoring</a> of gRPC Services and work with <a href="https://github.com/grpc-ecosystem/grpc-opentracing">OpenTracing</a>. You can suggest and contribute projects to this organization <a href="https://docs.google.com/a/google.com/forms/d/119zb79XRovQYafE9XKjz9sstwynCWcMpoJwHgZJvK74/edit">here</a>. We look forward to working with the community to take the gRPC project to new heights.</p>
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,230 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Gracefully clean up in gRPC JUnit tests – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>Gracefully clean up in gRPC JUnit tests</h1>
|
||||
<h5>Posted on Tuesday, June 26, 2018
|
||||
by
|
||||
|
||||
<a href="https://github.com/dapengzhang0">Dapeng Zhang</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>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.</p>
|
||||
|
||||
<p>This is even true for JUnit tests, because otherwise leaked resources may not only linger in your machine forever, but also interfere with subsequent tests. 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.</p>
|
||||
|
||||
<p>So cleanup, cleanup, cleanup… and fail the test if any cleanup is not successful.</p>
|
||||
|
||||
<p>A typical example is</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyTest</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">private</span> Server server<span style="color:#f92672">;</span>
|
||||
<span style="color:#66d9ef">private</span> ManagedChannel channel<span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">...</span>
|
||||
<span style="color:#a6e22e">@After</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">tearDown</span><span style="color:#f92672">()</span> <span style="color:#66d9ef">throws</span> InterruptedException <span style="color:#f92672">{</span>
|
||||
<span style="color:#75715e">// assume channel and server are not null
|
||||
</span><span style="color:#75715e"></span> channel<span style="color:#f92672">.</span><span style="color:#a6e22e">shutdownNow</span><span style="color:#f92672">();</span>
|
||||
server<span style="color:#f92672">.</span><span style="color:#a6e22e">shutdownNow</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#75715e">// fail the test if cleanup is not successful
|
||||
</span><span style="color:#75715e"></span> <span style="color:#66d9ef">assert</span> channel<span style="color:#f92672">.</span><span style="color:#a6e22e">awaitTermination</span><span style="color:#f92672">(</span>5<span style="color:#f92672">,</span> TimeUnit<span style="color:#f92672">.</span><span style="color:#a6e22e">SECONDS</span><span style="color:#f92672">)</span> <span style="color:#f92672">:</span> <span style="color:#e6db74">"channel failed to shutdown"</span><span style="color:#f92672">;</span>
|
||||
<span style="color:#66d9ef">assert</span> server<span style="color:#f92672">.</span><span style="color:#a6e22e">awaitTermination</span><span style="color:#f92672">(</span>5<span style="color:#f92672">,</span> TimeUnit<span style="color:#f92672">.</span><span style="color:#a6e22e">SECONDS</span><span style="color:#f92672">)</span> <span style="color:#f92672">:</span> <span style="color:#e6db74">"server failed to shutdown"</span><span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">...</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>or to be more graceful</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyTest</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">private</span> Server server<span style="color:#f92672">;</span>
|
||||
<span style="color:#66d9ef">private</span> ManagedChannel channel<span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">...</span>
|
||||
<span style="color:#a6e22e">@After</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">tearDown</span><span style="color:#f92672">()</span> <span style="color:#66d9ef">throws</span> InterruptedException <span style="color:#f92672">{</span>
|
||||
<span style="color:#75715e">// assume channel and server are not null
|
||||
</span><span style="color:#75715e"></span> channel<span style="color:#f92672">.</span><span style="color:#a6e22e">shutdown</span><span style="color:#f92672">();</span>
|
||||
server<span style="color:#f92672">.</span><span style="color:#a6e22e">shutdown</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#75715e">// fail the test if cannot gracefully shutdown
|
||||
</span><span style="color:#75715e"></span> <span style="color:#66d9ef">try</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">assert</span> channel<span style="color:#f92672">.</span><span style="color:#a6e22e">awaitTermination</span><span style="color:#f92672">(</span>5<span style="color:#f92672">,</span> TimeUnit<span style="color:#f92672">.</span><span style="color:#a6e22e">SECONDS</span><span style="color:#f92672">)</span> <span style="color:#f92672">:</span> <span style="color:#e6db74">"channel cannot be gracefully shutdown"</span><span style="color:#f92672">;</span>
|
||||
<span style="color:#66d9ef">assert</span> server<span style="color:#f92672">.</span><span style="color:#a6e22e">awaitTermination</span><span style="color:#f92672">(</span>5<span style="color:#f92672">,</span> TimeUnit<span style="color:#f92672">.</span><span style="color:#a6e22e">SECONDS</span><span style="color:#f92672">)</span> <span style="color:#f92672">:</span> <span style="color:#e6db74">"server cannot be gracefully shutdown"</span><span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span> <span style="color:#66d9ef">finally</span> <span style="color:#f92672">{</span>
|
||||
channel<span style="color:#f92672">.</span><span style="color:#a6e22e">shutdownNow</span><span style="color:#f92672">();</span>
|
||||
server<span style="color:#f92672">.</span><span style="color:#a6e22e">shutdownNow</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">...</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>However, having to add all this to every test so it shuts down gracefully gives you more work to do, as you need to write the shutdown boilerplate by yourself. Because of this, the gRPC testing library has helper rules to make this job less tedious.</p>
|
||||
|
||||
<p>Initially, a JUnit rule <a href="https://github.com/grpc/grpc-java/blob/v1.1.x/testing/src/main/java/io/grpc/testing/GrpcServerRule.java"><code>GrpcServerRule</code></a> was introduced to eliminate the shutdown boilerplate. This rule creates an In-Process server and channel at the beginning of the test, and shuts them down at the end of test automatically. However, users found this rule too restrictive in that it does not support transports other than In-Process transports, multiple channels to the server, custom channel or server builder options, and configuration inside individual test methods.</p>
|
||||
|
||||
<p>A more flexible JUnit rule <a href="https://github.com/grpc/grpc-java/blob/v1.13.x/testing/src/main/java/io/grpc/testing/GrpcCleanupRule.java"><code>GrpcCleanupRule</code></a> was introduced in gRPC release v1.13, which also eliminates the shutdown boilerplate. However unlike <code>GrpcServerRule</code>, <code>GrpcCleanupRule</code> does not create any server or channel automatically at all. Users create and start the server by themselves, and create channels by themselves, just as in plain tests. With this rule, users just need to register every resource (channel or server) that needs to be shut down at the end of test, and the rule will then shut them down gracefully automatically.</p>
|
||||
|
||||
<p>You can register resources either before running test methods</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyTest</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#a6e22e">@Rule</span>
|
||||
<span style="color:#66d9ef">public</span> GrpcCleanupRule grpcCleanup <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> GrpcCleanupRule<span style="color:#f92672">();</span>
|
||||
<span style="color:#f92672">...</span>
|
||||
<span style="color:#66d9ef">private</span> String serverName <span style="color:#f92672">=</span> InProcessServerBuilder<span style="color:#f92672">.</span><span style="color:#a6e22e">generateName</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#66d9ef">private</span> Server server <span style="color:#f92672">=</span> grpcCleanup<span style="color:#f92672">.</span><span style="color:#a6e22e">register</span><span style="color:#f92672">(</span>InProcessServerBuilder
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">forName</span><span style="color:#f92672">(</span>serverName<span style="color:#f92672">).</span><span style="color:#a6e22e">directExecutor</span><span style="color:#f92672">().</span><span style="color:#a6e22e">addService</span><span style="color:#f92672">(</span>myServiceImpl<span style="color:#f92672">).</span><span style="color:#a6e22e">build</span><span style="color:#f92672">().</span><span style="color:#a6e22e">start</span><span style="color:#f92672">());</span>
|
||||
<span style="color:#66d9ef">private</span> ManagedChannel channel <span style="color:#f92672">=</span> grpcCleanup<span style="color:#f92672">.</span><span style="color:#a6e22e">register</span><span style="color:#f92672">(</span>InProcessChannelBuilder
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">forName</span><span style="color:#f92672">(</span>serverName<span style="color:#f92672">).</span><span style="color:#a6e22e">directExecutor</span><span style="color:#f92672">().</span><span style="color:#a6e22e">build</span><span style="color:#f92672">());</span>
|
||||
<span style="color:#f92672">...</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>or inside each individual test method</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyTest</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#a6e22e">@Rule</span>
|
||||
<span style="color:#66d9ef">public</span> GrpcCleanupRule grpcCleanup <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> GrpcCleanupRule<span style="color:#f92672">();</span>
|
||||
<span style="color:#f92672">...</span>
|
||||
<span style="color:#66d9ef">private</span> String serverName <span style="color:#f92672">=</span> InProcessServerBuilder<span style="color:#f92672">.</span><span style="color:#a6e22e">generateName</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#66d9ef">private</span> InProcessServerBuilder serverBuilder <span style="color:#f92672">=</span> InProcessServerBuilder
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">forName</span><span style="color:#f92672">(</span>serverName<span style="color:#f92672">).</span><span style="color:#a6e22e">directExecutor</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#66d9ef">private</span> InProcessChannelBuilder channelBuilder <span style="color:#f92672">=</span> InProcessChannelBuilder
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">forName</span><span style="color:#f92672">(</span>serverName<span style="color:#f92672">).</span><span style="color:#a6e22e">directExecutor</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#f92672">...</span>
|
||||
|
||||
<span style="color:#a6e22e">@Test</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">testFooBar</span><span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#f92672">...</span>
|
||||
grpcCleanup<span style="color:#f92672">.</span><span style="color:#a6e22e">register</span><span style="color:#f92672">(</span>
|
||||
serverBuilder<span style="color:#f92672">.</span><span style="color:#a6e22e">addService</span><span style="color:#f92672">(</span>myServiceImpl<span style="color:#f92672">).</span><span style="color:#a6e22e">build</span><span style="color:#f92672">().</span><span style="color:#a6e22e">start</span><span style="color:#f92672">());</span>
|
||||
ManagedChannel channel <span style="color:#f92672">=</span> grpcCleanup<span style="color:#f92672">.</span><span style="color:#a6e22e">register</span><span style="color:#f92672">(</span>
|
||||
channelBuilder<span style="color:#f92672">.</span><span style="color:#a6e22e">maxInboundMessageSize</span><span style="color:#f92672">(</span>1024<span style="color:#f92672">).</span><span style="color:#a6e22e">build</span><span style="color:#f92672">());</span>
|
||||
<span style="color:#f92672">...</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>Now with <a href="https://github.com/grpc/grpc-java/blob/v1.13.x/testing/src/main/java/io/grpc/testing/GrpcCleanupRule.java"><code>GrpcCleanupRule</code></a> 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!</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,317 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC Meets .NET SDK And Visual Studio: Automatic Codegen On Build – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC Meets .NET SDK And Visual Studio: Automatic Codegen On Build</h1>
|
||||
<h5>Posted on Tuesday, December 18, 2018
|
||||
by
|
||||
|
||||
<a href="https://github.com/kkm000">Kirill 'kkm' Katsnelson</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>As part of Microsoft’s move towards its cross-platform .NET offering, they have
|
||||
greatly simplified the project file format, and allowed a tight integration of
|
||||
third-party code generators with .NET projects. We are listening, and now proud
|
||||
to introduce integrated compilation of Protocol Buffer and gRPC service
|
||||
<code>.proto</code> files in .NET C# projects starting with the version 1.17 of the
|
||||
Grpc.Tools NuGet package, now available from Nuget.org.</p>
|
||||
|
||||
<p>You no longer need to use hand-written scripts to generate code from <code>.proto</code>
|
||||
files: The .NET build magic handles this for you. The integrated tools locate
|
||||
the proto compiler and gRPC plugin, standard Protocol Buffer imports, and track
|
||||
dependencies before invoking the code generators, so that the generated C#
|
||||
source files are never out of date, at the same time keeping regeneration to
|
||||
the minimum required. In essence, <code>.proto</code> files are treated as first-class
|
||||
sources in a .NET C# project.</p>
|
||||
|
||||
<h2 id="a-walkthrough">A Walkthrough</h2>
|
||||
|
||||
<p>In this blog post, we’ll walk through the simplest and probably the most common
|
||||
scenario of creating a library from <code>.proto</code> files using the cross-platform
|
||||
<code>dotnet</code> command. We will implement essentially a clone of the <code>Greeter</code>
|
||||
library, shared by client and server projects in the <a href="https://github.com/grpc/grpc/tree/master/examples/csharp/Helloworld/Greeter">C# <code>Helloworld</code> example
|
||||
directory
|
||||
</a>.</p>
|
||||
|
||||
<h3 id="create-a-new-project">Create a new project</h3>
|
||||
|
||||
<p>Let’s start by creating a new library project.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">~/work$ dotnet new classlib -o MyGreeter
|
||||
The template <span style="color:#e6db74">"Class library"</span> was created successfully.
|
||||
|
||||
~/work$ cd MyGreeter
|
||||
~/work/MyGreeter$ ls -lF
|
||||
total <span style="color:#ae81ff">12</span>
|
||||
-rw-rw-r-- <span style="color:#ae81ff">1</span> kkm kkm <span style="color:#ae81ff">86</span> Nov <span style="color:#ae81ff">9</span> <span style="color:#ae81ff">16</span>:10 Class1.cs
|
||||
-rw-rw-r-- <span style="color:#ae81ff">1</span> kkm kkm <span style="color:#ae81ff">145</span> Nov <span style="color:#ae81ff">9</span> <span style="color:#ae81ff">16</span>:10 MyGreeter.csproj
|
||||
drwxrwxr-x <span style="color:#ae81ff">2</span> kkm kkm <span style="color:#ae81ff">4096</span> Nov <span style="color:#ae81ff">9</span> <span style="color:#ae81ff">16</span>:10 obj/</code></pre></div>
|
||||
<p>Observe that the <code>dotnet new</code> command has created the file <code>Class1.cs</code> that
|
||||
we won’t need, so remove it. Also, we need some <code>.proto</code> files to compile. For
|
||||
this exercise, we’ll copy an example file <a href="https://github.com/grpc/grpc/blob/master/examples/protos/helloworld.proto"><code>examples/protos/helloworld.proto</code>
|
||||
</a>
|
||||
from the gRPC distribution.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">~/work/MyGreeter$ rm Class1.cs
|
||||
~/work/MyGreeter$ wget -q https://raw.githubusercontent.com/grpc/grpc/master/examples/protos/helloworld.proto</code></pre></div>
|
||||
<p>(on Windows, use <code>del Class1.cs</code>, and, if you do not have the wget command,
|
||||
just <a href="https://raw.githubusercontent.com/grpc/grpc/master/examples/protos/helloworld.proto">open the above URL
|
||||
</a>
|
||||
and use a <em>Save As…</em> command from your Web browser).</p>
|
||||
|
||||
<p>Next, add required NuGet packages to the project:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">~/work/MyGreeter$ dotnet add package Grpc
|
||||
info : PackageReference <span style="color:#66d9ef">for</span> package <span style="color:#e6db74">'Grpc'</span> version <span style="color:#e6db74">'1.17.0'</span> added to file <span style="color:#e6db74">'/home/kkm/work/MyGreeter/MyGreeter.csproj'</span>.
|
||||
~/work/MyGreeter$ dotnet add package Grpc.Tools
|
||||
info : PackageReference <span style="color:#66d9ef">for</span> package <span style="color:#e6db74">'Grpc.Tools'</span> version <span style="color:#e6db74">'1.17.0'</span> added to file <span style="color:#e6db74">'/home/kkm/work/MyGreeter/MyGreeter.csproj'</span>.
|
||||
~/work/MyGreeter$ dotnet add package Google.Protobuf
|
||||
info : PackageReference <span style="color:#66d9ef">for</span> package <span style="color:#e6db74">'Google.Protobuf'</span> version <span style="color:#e6db74">'3.6.1'</span> added to file <span style="color:#e6db74">'/home/kkm/work/MyGreeter/MyGreeter.csproj'</span>.</code></pre></div>
|
||||
<h3 id="add-proto-files-to-the-project">Add <code>.proto</code> files to the project</h3>
|
||||
|
||||
<p><strong>Next comes an important part.</strong> First of all, by default, a <code>.csproj</code> project
|
||||
file automatically finds all <code>.cs</code> files in its directory, although
|
||||
<a href="https://docs.microsoft.com/dotnet/core/tools/csproj#recommendation">Microsoft now recommends suppressing this globbing
|
||||
behavior</a>,
|
||||
so we too decided against globbing <code>.proto</code> files. Thus the <code>.proto</code>
|
||||
files must be added to the project explicitly.</p>
|
||||
|
||||
<p>Second of all, it is important to add a property <code>PrivateAssets="All"</code> to the
|
||||
Grpc.Tools package reference, so that it will not be needlessly fetched by the
|
||||
consumers of your new library. This makes sense, as the package only contains
|
||||
compilers, code generators and import files, which are not needed outside of
|
||||
the project where the <code>.proto</code> files have been compiled. While not strictly
|
||||
required in this simple walkthrough, it must be your standard practice to do
|
||||
that always.</p>
|
||||
|
||||
<p>So edit the file <code>MyGreeter.csproj</code> to add the <code>helloworld.proto</code> so that it
|
||||
will be compiled, and the <code>PrivateAssets</code> property to the Grpc.Tools package
|
||||
reference. Your resulting project file should now look like this:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml"><span style="color:#f92672"><Project</span> <span style="color:#a6e22e">Sdk=</span><span style="color:#e6db74">"Microsoft.NET.Sdk"</span><span style="color:#f92672">></span>
|
||||
|
||||
<span style="color:#f92672"><PropertyGroup></span>
|
||||
<span style="color:#f92672"><TargetFramework></span>netstandard2.0<span style="color:#f92672"></TargetFramework></span>
|
||||
<span style="color:#f92672"></PropertyGroup></span>
|
||||
|
||||
<span style="color:#f92672"><ItemGroup></span>
|
||||
<span style="color:#f92672"><PackageReference</span> <span style="color:#a6e22e">Include=</span><span style="color:#e6db74">"Google.Protobuf"</span> <span style="color:#a6e22e">Version=</span><span style="color:#e6db74">"3.6.1"</span> <span style="color:#f92672">/></span>
|
||||
<span style="color:#f92672"><PackageReference</span> <span style="color:#a6e22e">Include=</span><span style="color:#e6db74">"Grpc"</span> <span style="color:#a6e22e">Version=</span><span style="color:#e6db74">"1.17.0"</span> <span style="color:#f92672">/></span>
|
||||
|
||||
<span style="color:#75715e"><!-- The Grpc.Tools package generates C# sources from .proto files during
|
||||
</span><span style="color:#75715e"> project build, but is not needed by projects using the built library.
|
||||
</span><span style="color:#75715e"> It's IMPORTANT to add the 'PrivateAssets="All"' to this reference: --></span>
|
||||
<span style="color:#f92672"><PackageReference</span> <span style="color:#a6e22e">Include=</span><span style="color:#e6db74">"Grpc.Tools"</span> <span style="color:#a6e22e">Version=</span><span style="color:#e6db74">"1.17.0"</span> <span style="color:#a6e22e">PrivateAssets=</span><span style="color:#e6db74">"All"</span> <span style="color:#f92672">/></span>
|
||||
|
||||
<span style="color:#75715e"><!-- Explicitly include our helloworld.proto file by adding this line: --></span>
|
||||
<span style="color:#f92672"><Protobuf</span> <span style="color:#a6e22e">Include=</span><span style="color:#e6db74">"helloworld.proto"</span> <span style="color:#f92672">/></span>
|
||||
<span style="color:#f92672"></ItemGroup></span>
|
||||
|
||||
<span style="color:#f92672"></Project></span></code></pre></div>
|
||||
<h3 id="build-it">Build it!</h3>
|
||||
|
||||
<p>At this point you can build the project with the <code>dotnet build</code> command to
|
||||
compile the <code>.proto</code> file and the library assembly. For this walkthrough, we’ll
|
||||
add a logging switch <code>-v:n</code> to the command, so we can see that the command to
|
||||
compile the <code>helloworld.proto</code> file was in fact run. You may find it a good
|
||||
idea to always do that the very first time you compile a project!</p>
|
||||
|
||||
<p>Note that many output lines are omitted below, as the build output is quite
|
||||
verbose.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">~/work/MyGreeter$ dotnet build -v:n
|
||||
|
||||
Build started <span style="color:#ae81ff">11</span>/9/18 <span style="color:#ae81ff">5</span>:33:44 PM.
|
||||
<span style="color:#ae81ff">1</span>:7>Project <span style="color:#e6db74">"/home/kkm/work/MyGreeter/MyGreeter.csproj"</span> on node <span style="color:#ae81ff">1</span> <span style="color:#f92672">(</span>Build target<span style="color:#f92672">(</span>s<span style="color:#f92672">))</span>.
|
||||
<span style="color:#ae81ff">1</span>>_Protobuf_CoreCompile:
|
||||
/home/kkm/.nuget/packages/grpc.tools/1.17.0/tools/linux_x64/protoc
|
||||
--csharp_out<span style="color:#f92672">=</span>obj/Debug/netstandard2.0
|
||||
--plugin<span style="color:#f92672">=</span>protoc-gen-grpc<span style="color:#f92672">=</span>/home/kkm/.nuget/packages/grpc.tools/1.17.0/tools/linux_x64/grpc_csharp_plugin
|
||||
--grpc_out<span style="color:#f92672">=</span>obj/Debug/netstandard2.0 --proto_path<span style="color:#f92672">=</span>/home/kkm/.nuget/packages/grpc.tools/1.17.0/build/native/include
|
||||
--proto_path<span style="color:#f92672">=</span>. --dependency_out<span style="color:#f92672">=</span>obj/Debug/netstandard2.0/da39a3ee5e6b4b0d_helloworld.protodep helloworld.proto
|
||||
CoreCompile:
|
||||
|
||||
<span style="color:#f92672">[</span> ... skipping long output ... <span style="color:#f92672">]</span>
|
||||
|
||||
MyGreeter -> /home/kkm/work/MyGreeter/bin/Debug/netstandard2.0/MyGreeter.dll
|
||||
|
||||
Build succeeded.</code></pre></div>
|
||||
<p>If at this point you invoke the <code>dotnet build -v:n</code> command again, <code>protoc</code>
|
||||
would not be invoked, and no C# sources would be compiled. But if you change
|
||||
the <code>helloworld.proto</code> source, then its outputs will be regenerated and then
|
||||
recompiled by the C# compiler during the build. This is a regular dependency
|
||||
tracking behavior that you expect from modifying any source file.</p>
|
||||
|
||||
<p>Of course, you can also add <code>.cs</code> files to the same project: It is a regular C#
|
||||
project building a .NET library, after all. This is done in our <a href="https://github.com/grpc/grpc/tree/master/examples/csharp/RouteGuide/RouteGuide">RouteGuide
|
||||
</a>
|
||||
example.</p>
|
||||
|
||||
<h3 id="where-are-the-generated-files">Where are the generated files?</h3>
|
||||
|
||||
<p>You may wonder where the proto compiler and gRPC plugin output C# files are. By
|
||||
default, they are placed in the same directory as other generated files, such
|
||||
as objects (termed the “intermediate output” directory in the .NET build
|
||||
parlance), under the <code>obj/</code> directory. This is a regular practice of .NET
|
||||
builds, so that autogenerated files do not clutter the working directory or
|
||||
accidentally placed under source control. Otherwise, they are accessible to the
|
||||
tools like the debugger. You can see other autogenerated sources in that
|
||||
directory, too:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">~/work/MyGreeter$ find obj -name <span style="color:#e6db74">'*.cs'</span>
|
||||
obj/Debug/netstandard2.0/MyGreeter.AssemblyInfo.cs
|
||||
obj/Debug/netstandard2.0/Helloworld.cs
|
||||
obj/Debug/netstandard2.0/HelloworldGrpc.cs</code></pre></div>
|
||||
<p>(use <code>dir /s obj\*.cs</code> if you are following this walkthrough from a Windows
|
||||
command prompt).</p>
|
||||
|
||||
<h2 id="there-is-more-to-it">There Is More To It</h2>
|
||||
|
||||
<p>While the simplest default behavior is adequate in many cases, there are many
|
||||
ways to fine-tune your <code>.proto</code> compilation process in a large project. We
|
||||
encourage you to read the <a href="https://github.com/grpc/grpc/blob/master/src/csharp/BUILD-INTEGRATION.md">documentation file BUILD-INTEGRATION.md
|
||||
</a>
|
||||
for available options if you find that the default arrangement does not suit
|
||||
your workflow. The package also extends the Visual Studio’s Properties window,
|
||||
so you may set some options per file in the Visual Studio interface.</p>
|
||||
|
||||
<p>“Classic” <code>.csproj</code> projects and Mono are also supported.</p>
|
||||
|
||||
<h2 id="share-your-experience">Share Your Experience</h2>
|
||||
|
||||
<p>As with any initial release of a complex feature, we are thrilled to receive
|
||||
your feedback. Did something not work as expected? Do you have a scenario that
|
||||
is not easy to cover with the new tools? Do you have an idea how to improve the
|
||||
workflow in general? Please read the documentation carefully, and then <a href="https://github.com/grpc/grpc/issues">open an
|
||||
issue</a> in the gRPC code repository on
|
||||
GitHub. Your feedback is important to determine the future direction for our
|
||||
build integration work!</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Visualizing gRPC Language Stacks – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>Visualizing gRPC Language Stacks</h1>
|
||||
<h5>Posted on Tuesday, December 11, 2018
|
||||
by
|
||||
|
||||
<a href="https://carlmastrangelo.com/">Carl Mastrangelo</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>Here is a high level overview of the gRPC Stacks. Each of the <strong>10</strong> default languages supported by gRPC has multiple layers, allowing you to customize what pieces you want in your application.</p>
|
||||
|
||||
<p>There are three main stacks in gRPC: C-core, Go, and Java. Most of the languages are thin wrappers on top of the <a href="https://github.com/grpc/grpc/tree/master/src/core">C-based</a> gRPC core library:</p>
|
||||
|
||||
<h3 id="wrapped-languages">Wrapped Languages:</h3>
|
||||
|
||||
<p><img src="/img/grpc-core-stack.svg" alt="gRPC Core Stack" style="max-width: 800px" /></p>
|
||||
|
||||
<p>For example, a Python application calls into the generated Python stubs. These calls pass through interceptors, and into the wrapping library where the calls are translated into C calls. The gRPC C-core will encode the RPC as HTTP/2, optionally encrypt the data with TLS, and then write it to the network.</p>
|
||||
|
||||
<p>One of the cool things about gRPC is that you can swap these pieces out. For example, you could use C# instead, and use an In-Process transport. This would save you from having to go all the way down to the OS network layer. Another example is trying out the QUIC protocol, which allows you to open new connections quickly. Being able to run over a variety of transports based on the environment makes gRPC really flexible.</p>
|
||||
|
||||
<p>For each of the wrapped languages, the default HTTP/2 implementation is built into the C-core library, so there is no need to include an outside one. However, as you can see, it is possible to bring your own (such as with Cronet, the Chrome networking library).</p>
|
||||
|
||||
<h3 id="go">Go</h3>
|
||||
|
||||
<p>In <a href="https://github.com/grpc/grpc-go">gRPC-Go</a>, the stack is much simpler, due to not having to support so many configurations. Here is a high level overview of the Go stack:</p>
|
||||
|
||||
<p><img src="/img/grpc-go-stack.svg" alt="gRPC Go Stack" style="max-width: 800px" /></p>
|
||||
|
||||
<p>The structure is a little different here. Since there is only one language, the flow from the top of the stack to the bottom is more linear. Unlike wrapped languages, gRPC Go can use either its own HTTP/2 implementation, or the Go <code>net/http</code> package.</p>
|
||||
|
||||
<h3 id="java">Java</h3>
|
||||
|
||||
<p>Here is a high level overview of the <a href="https://github.com/grpc/grpc-java">gRPC-Java</a> stack:</p>
|
||||
|
||||
<p><img src="/img/grpc-java-stack.svg" alt="gRPC Java Stack" style="max-width: 800px" /></p>
|
||||
|
||||
<p>Again, the structure is a little different. Java supports HTTP/2, QUIC, and In Process like the C-core. Unlike the C-Core though, applications commonly can bypass the generated stubs and interceptors, and speak directly to the Java Core library. Each structure is slightly different based on the needs of each language implementation of gRPC. Also unlike wrapped languages, gRPC Java separates the HTTP/2 implementation into pluggable libraries (such as Netty, OkHttp, or Cronet).</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,255 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC-Web is Generally Available – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC-Web is Generally Available</h1>
|
||||
<h5>Posted on Tuesday, October 23, 2018
|
||||
by
|
||||
|
||||
Luc Perkins - CNCF, Stanley Cheung - Google, Kailash Sethuraman - Google
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>We are excited to announce the GA release of
|
||||
<a href="https://www.npmjs.com/package/grpc-web">gRPC-Web</a>, 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. “GA” means that
|
||||
gRPC-Web is now Generally Available and stable and qualified for production use.</p>
|
||||
|
||||
<p>With gRPC-Web, you can now easily build truly end-to-end gRPC application
|
||||
architectures by defining your client <em>and</em> 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 <a href="https://github.com/grpc/grpc-experiments/tree/master/gdebug">web based
|
||||
tooling</a> around gRPC.</p>
|
||||
|
||||
<h2 id="the-basics">The Basics</h2>
|
||||
|
||||
<p>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 <a href="https://developers.google.com/closure/compiler/">Closure</a> compiler
|
||||
or the more widely used <a href="https://requirejs.org/docs/commonjs.html">CommonJS</a>.
|
||||
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.</p>
|
||||
|
||||
<p>From a broader architectural perspective, gRPC-Web enables end-to-end gRPC. The diagram below illustrates this:</p>
|
||||
|
||||
<p><img src="/img/grpc-web-arch.png" style="max-width: 947px"></p>
|
||||
|
||||
<p style="text-align: center"> Figure 1.
|
||||
gRPC with gRPC-Web (left) and gRPC with REST (right)</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h2 id="advantages-of-using-grpc-web">Advantages of using gRPC-Web</h2>
|
||||
|
||||
<p>gRPC-Web will offer an ever-broader feature set over time, but here’s what’s in 1.0 today:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong>End-to-end gRPC</strong> — 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.</li>
|
||||
<li><strong>Tighter coordination between frontend and backend teams</strong> — 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.</li>
|
||||
<li><strong>Easily generate client libraries</strong> — 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.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="a-grpc-web-example">A gRPC-Web example</h2>
|
||||
|
||||
<p>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 <code>todos.proto</code> definition like this:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto">syntax <span style="color:#f92672">=</span> <span style="color:#e6db74">"proto3"</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#f92672">package</span> todos;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">Todo</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">string</span> content <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">bool</span> finished <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">GetTodoRequest</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">int32</span> id <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">service</span> TodoService {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">rpc</span> GetTodoById (GetTodoRequest) <span style="color:#66d9ef">returns</span> (Todo);<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>} </code></pre></div>
|
||||
<p>CommonJS client-side code can be generated from this <code>.proto</code> definition with the following command:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto">protoc echo.proto <span style="color:#960050;background-color:#1e0010">\
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#f92672">--</span>js_out<span style="color:#f92672">=</span>import_style<span style="color:#f92672">=</span>commonjs<span style="color:#f92672">:./</span>output <span style="color:#960050;background-color:#1e0010">\
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#f92672">--</span>grpc<span style="color:#f92672">-</span>web_out<span style="color:#f92672">=</span>import_style<span style="color:#f92672">=</span>commonjs<span style="color:#f92672">:./</span>output</code></pre></div>
|
||||
<p>Now, fetching a list of TODOs from a backend gRPC service is as simple as:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">const</span> {<span style="color:#a6e22e">GetTodoRequest</span>} <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">'./todos_pb.js'</span>);
|
||||
<span style="color:#66d9ef">const</span> {<span style="color:#a6e22e">TodoServiceClient</span>} <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">'./todos_grpc_web_pb.js'</span>);
|
||||
|
||||
<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">todoService</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">proto</span>.<span style="color:#a6e22e">todos</span>.<span style="color:#a6e22e">TodoServiceClient</span>(<span style="color:#e6db74">'http://localhost:8080'</span>);
|
||||
<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">todoId</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1234</span>;
|
||||
|
||||
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">getTodoRequest</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">proto</span>.<span style="color:#a6e22e">todos</span>.<span style="color:#a6e22e">GetTodoRequest</span>();
|
||||
<span style="color:#a6e22e">getTodoRequest</span>.<span style="color:#a6e22e">setId</span>(<span style="color:#a6e22e">todoId</span>);
|
||||
|
||||
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">metadata</span> <span style="color:#f92672">=</span> {};
|
||||
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">getTodo</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">todoService</span>.<span style="color:#a6e22e">getTodoById</span>(<span style="color:#a6e22e">getTodoRequest</span>, <span style="color:#a6e22e">metadata</span>, (<span style="color:#a6e22e">err</span>, <span style="color:#a6e22e">response</span>) => {
|
||||
<span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">err</span>) {
|
||||
<span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">err</span>);
|
||||
} <span style="color:#66d9ef">else</span> {
|
||||
<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">todo</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">response</span>.<span style="color:#a6e22e">todo</span>();
|
||||
<span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">todo</span> <span style="color:#f92672">==</span> <span style="color:#66d9ef">null</span>) {
|
||||
<span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">`A TODO with the ID </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">todoId</span><span style="color:#e6db74">}</span><span style="color:#e6db74"> wasn't found`</span>);
|
||||
} <span style="color:#66d9ef">else</span> {
|
||||
<span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">`Fetched TODO with ID </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">todoId</span><span style="color:#e6db74">}</span><span style="color:#e6db74">: </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">todo</span>.<span style="color:#a6e22e">content</span>()<span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>);
|
||||
}
|
||||
}
|
||||
});
|
||||
</code></pre></div>
|
||||
<p>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 <a href="/docs/tutorials/basic/node/">Node.js</a> for gRPC API, just transferred to the client).</p>
|
||||
|
||||
<p>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 <a href="https://envoyproxy.io">Envoy</a> as the default service proxy, which has a built-in <a href="https://www.envoyproxy.io/docs/envoy/latest/configuration/http_filters/grpc_web_filter#config-http-filters-grpc-web">envoy.grpc_web filter</a> that you can apply with just a few lines of copy-and-pastable configuration.</p>
|
||||
|
||||
<h2 id="next-steps">Next Steps</h2>
|
||||
|
||||
<p>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 <a href="https://github.com/grpc/grpc-web/blob/master/ROADMAP.md">official roadmap</a> to see what the core team envisions for the near future.</p>
|
||||
|
||||
<p>If you’re interested in contributing to gRPC-Web, there are a few things we would love community help with:</p>
|
||||
|
||||
<ul>
|
||||
<li><p><strong>Front-end framework integration</strong> — Commonly used front-end frameworks like <a href="https://reactjs.org">React</a>, <a href="https://vuejs.org">Vue</a> and <a href="https://angularjs.org">Angular</a> 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 <a href="https://groups.google.com/forum/#!forum/grpc-io">gRPC.io mailing list</a>, <a href="https://github.com/grpc/grpc-web/issues">filing a feature request on github</a> or via the feature survey form below.</p></li>
|
||||
|
||||
<li><p><strong>Language-specific proxy support</strong> — As of the GA release, <a href="https://envoyproxy.io">Envoy</a> is the default proxy for gRPC-Web, offering support via a special module. NGNIX is also <a href="https://github.com/grpc/grpc-web/tree/master/net/grpc/gateway/nginx">supported</a>. 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.</p></li>
|
||||
</ul>
|
||||
|
||||
<p>We’d also love to get feature requests from the community. Currently the best way to make feature requests is to fill out the <a href="https://docs.google.com/forms/d/1NjWpyRviohn5jaPntosBHXRXZYkh_Ffi4GxJZFibylM/viewform?edit_requested=true">gRPC-Web roadmap features survey</a>. 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 <strong>I’d like to contribute to</strong> section. The gRPC-Web engineers will be sure to take that information to heart over the course of the project’s development.</p>
|
||||
|
||||
<p>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.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,315 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC + JSON – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC + JSON</h1>
|
||||
<h5>Posted on Wednesday, August 15, 2018
|
||||
by
|
||||
|
||||
<a href="https://carlmastrangelo.com">Carl Mastrangelo</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>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?</p>
|
||||
|
||||
<p>Fortunately, gRPC is encoding agnostic! You can still get a lot of the benefits of gRPC without using Protobuf. In this post we’ll go through how to make gRPC work with other encodings and types. Let’s try using JSON.</p>
|
||||
|
||||
<p>gRPC is actually a collection of technologies that have high cohesion, rather than a singular, monolithic framework. This means its possible to swap out parts of gRPC and still take advantage of gRPC’s benefits. <a href="https://github.com/google/gson">Gson</a> is a popular library for Java for doing JSON encoding. Let’s remove all the protobuf related things and replace them with Gson:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-diff" data-lang="diff"><span style="color:#f92672">- Protobuf wire encoding
|
||||
</span><span style="color:#f92672">- Protobuf generated message types
|
||||
</span><span style="color:#f92672">- gPRC generated stub types
|
||||
</span><span style="color:#f92672"></span><span style="color:#a6e22e">+ JSON wire encoding
|
||||
</span><span style="color:#a6e22e">+ Gson message types
|
||||
</span></code></pre></div>
|
||||
<p>Previously, Protobuf and gRPC were generating code for us, but we would like to use our own types. Additionally, we are going to be using our own encoding too. Gson allows us to bring our own types in our code, but provides a way of serializing those types into bytes.</p>
|
||||
|
||||
<p>Let’s continue with the <a href="https://github.com/carl-mastrangelo/kvstore/tree/04-gson-marshaller">Key-Value</a> store service. We will be modifying the code used my previous <a href="/blog/optimizing-grpc-part-2">So You Want to Optimize gRPC</a> post.</p>
|
||||
|
||||
<h2 id="what-is-a-service-anyways">What is a Service Anyways?</h2>
|
||||
|
||||
<p>From the point of view of gRPC, a <em>Service</em> is a collection of <em>Methods</em>. In Java, a method is represented as a <a href="https://grpc.io/grpc-java/javadoc/io/grpc/MethodDescriptor.html"><code>MethodDescriptor</code></a>. Each <code>MethodDescriptor</code> includes the name of the method, a <code>Marshaller</code> for encoding requests, and a <code>Marshaller</code> for encoding responses. They also include additional detail, such as if the call is streaming or not. For simplicity, we’ll stick with unary RPCs which have a single request and single response.</p>
|
||||
|
||||
<p>Since we won’t be generating any code, we’ll need to write the message classes ourselves. There are four methods, each which have a request and a response type. This means we need to make eight messages:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">CreateRequest</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">byte</span><span style="color:#f92672">[]</span> key<span style="color:#f92672">;</span>
|
||||
<span style="color:#66d9ef">byte</span><span style="color:#f92672">[]</span> value<span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
<span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">CreateResponse</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
<span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">RetrieveRequest</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">byte</span><span style="color:#f92672">[]</span> key<span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
<span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">RetrieveResponse</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">byte</span><span style="color:#f92672">[]</span> value<span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
<span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UpdateRequest</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">byte</span><span style="color:#f92672">[]</span> key<span style="color:#f92672">;</span>
|
||||
<span style="color:#66d9ef">byte</span><span style="color:#f92672">[]</span> value<span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
<span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UpdateResponse</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
<span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DeleteRequest</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">byte</span><span style="color:#f92672">[]</span> key<span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
<span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DeleteResponse</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>Because GSON uses reflection to determine how the fields in our classes map to the serialized JSON, we don’t need to annotate the messages.</p>
|
||||
|
||||
<p>Our client and server logic will use the request and response types, but gRPC needs to know how to produce and consume these messages. To do this, we need to implement a <a href="https://grpc.io/grpc-java/javadoc/io/grpc/MethodDescriptor.Marshaller.html"><code>Marshaller</code></a>. A marshaller knows how to convert from an arbitrary type to an <code>InputStream</code>, which is then passed down into the gRPC core library. It is also capable of doing the reverse transformation when decoding data from the network. For GSON, here is what the marshaller looks like:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#66d9ef">static</span> <span style="color:#f92672"><</span>T<span style="color:#f92672">></span> Marshaller<span style="color:#f92672"><</span>T<span style="color:#f92672">></span> <span style="color:#a6e22e">marshallerFor</span><span style="color:#f92672">(</span>Class<span style="color:#f92672"><</span>T<span style="color:#f92672">></span> clz<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
Gson gson <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Gson<span style="color:#f92672">();</span>
|
||||
<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> Marshaller<span style="color:#f92672"><</span>T<span style="color:#f92672">>()</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> InputStream <span style="color:#a6e22e">stream</span><span style="color:#f92672">(</span>T value<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> ByteArrayInputStream<span style="color:#f92672">(</span>gson<span style="color:#f92672">.</span><span style="color:#a6e22e">toJson</span><span style="color:#f92672">(</span>value<span style="color:#f92672">,</span> clz<span style="color:#f92672">).</span><span style="color:#a6e22e">getBytes</span><span style="color:#f92672">(</span>StandardCharsets<span style="color:#f92672">.</span><span style="color:#a6e22e">UTF_8</span><span style="color:#f92672">));</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
<span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> T <span style="color:#a6e22e">parse</span><span style="color:#f92672">(</span>InputStream stream<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">return</span> gson<span style="color:#f92672">.</span><span style="color:#a6e22e">fromJson</span><span style="color:#f92672">(</span><span style="color:#66d9ef">new</span> InputStreamReader<span style="color:#f92672">(</span>stream<span style="color:#f92672">,</span> StandardCharsets<span style="color:#f92672">.</span><span style="color:#a6e22e">UTF_8</span><span style="color:#f92672">),</span> clz<span style="color:#f92672">);</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">};</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>Given a <code>Class</code> object for a some request or response, this function will produce a marshaller. Using the marshallers, we can compose a full <code>MethodDescriptor</code> for each of the four CRUD methods. Here is an example of the Method descriptor for <em>Create</em>:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> MethodDescriptor<span style="color:#f92672"><</span>CreateRequest<span style="color:#f92672">,</span> CreateResponse<span style="color:#f92672">></span> CREATE_METHOD <span style="color:#f92672">=</span>
|
||||
MethodDescriptor<span style="color:#f92672">.</span><span style="color:#a6e22e">newBuilder</span><span style="color:#f92672">(</span>
|
||||
marshallerFor<span style="color:#f92672">(</span>CreateRequest<span style="color:#f92672">.</span><span style="color:#a6e22e">class</span><span style="color:#f92672">),</span>
|
||||
marshallerFor<span style="color:#f92672">(</span>CreateResponse<span style="color:#f92672">.</span><span style="color:#a6e22e">class</span><span style="color:#f92672">))</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">setFullMethodName</span><span style="color:#f92672">(</span>
|
||||
MethodDescriptor<span style="color:#f92672">.</span><span style="color:#a6e22e">generateFullMethodName</span><span style="color:#f92672">(</span>SERVICE_NAME<span style="color:#f92672">,</span> <span style="color:#e6db74">"Create"</span><span style="color:#f92672">))</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">setType</span><span style="color:#f92672">(</span>MethodType<span style="color:#f92672">.</span><span style="color:#a6e22e">UNARY</span><span style="color:#f92672">)</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">build</span><span style="color:#f92672">();</span></code></pre></div>
|
||||
<p>Note that if we were using Protobuf, we would use the existing Protobuf marshaller, and the
|
||||
<a href="https://github.com/carl-mastrangelo/kvstore/blob/03-nonblocking-server/build/generated/source/proto/main/grpc/io/grpc/examples/proto/KeyValueServiceGrpc.java#L44">method descriptors</a>
|
||||
would be generated automatically.</p>
|
||||
|
||||
<h2 id="sending-rpcs">Sending RPCs</h2>
|
||||
|
||||
<p>Now that we can marshal JSON requests and responses, we need to update our
|
||||
<a href="https://github.com/carl-mastrangelo/kvstore/blob/b225d28c7c2f3c356b0f3753384b3329f2ab5911/src/main/java/io/grpc/examples/KvClient.java#L98"><code>KvClient</code></a>,
|
||||
the gRPC client used in the previous post, to use our MethodDescriptors. Additionally, since we won’t be using any Protobuf types, the code needs to use <code>ByteBuffer</code> rather than <code>ByteString</code>. That said, we can still use the <code>grpc-stub</code> package on Maven to issue the RPC. Using the <em>Create</em> method again as an example, here’s how to make an RPC:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> ByteBuffer key <span style="color:#f92672">=</span> createRandomKey<span style="color:#f92672">();</span>
|
||||
ClientCall<span style="color:#f92672"><</span>CreateRequest<span style="color:#f92672">,</span> CreateResponse<span style="color:#f92672">></span> call <span style="color:#f92672">=</span>
|
||||
chan<span style="color:#f92672">.</span><span style="color:#a6e22e">newCall</span><span style="color:#f92672">(</span>KvGson<span style="color:#f92672">.</span><span style="color:#a6e22e">CREATE_METHOD</span><span style="color:#f92672">,</span> CallOptions<span style="color:#f92672">.</span><span style="color:#a6e22e">DEFAULT</span><span style="color:#f92672">);</span>
|
||||
KvGson<span style="color:#f92672">.</span><span style="color:#a6e22e">CreateRequest</span> req <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> KvGson<span style="color:#f92672">.</span><span style="color:#a6e22e">CreateRequest</span><span style="color:#f92672">();</span>
|
||||
req<span style="color:#f92672">.</span><span style="color:#a6e22e">key</span> <span style="color:#f92672">=</span> key<span style="color:#f92672">.</span><span style="color:#a6e22e">array</span><span style="color:#f92672">();</span>
|
||||
req<span style="color:#f92672">.</span><span style="color:#a6e22e">value</span> <span style="color:#f92672">=</span> randomBytes<span style="color:#f92672">(</span>MEAN_VALUE_SIZE<span style="color:#f92672">).</span><span style="color:#a6e22e">array</span><span style="color:#f92672">();</span>
|
||||
|
||||
ListenableFuture<span style="color:#f92672"><</span>CreateResponse<span style="color:#f92672">></span> res <span style="color:#f92672">=</span> ClientCalls<span style="color:#f92672">.</span><span style="color:#a6e22e">futureUnaryCall</span><span style="color:#f92672">(</span>call<span style="color:#f92672">,</span> req<span style="color:#f92672">);</span>
|
||||
<span style="color:#f92672">//</span> <span style="color:#f92672">...</span></code></pre></div>
|
||||
<p>As you can see, we create a new <code>ClientCall</code> object from the <code>MethodDescriptor</code>, create the request, and then send it using <code>ClientCalls.futureUnaryCall</code> in the stub library. gRPC takes care of the rest for us. You can also make blocking stubs or async stubs instead of future stubs.</p>
|
||||
|
||||
<h2 id="receiving-rpcs">Receiving RPCs</h2>
|
||||
|
||||
<p>To update the server, we need to create a key-value service and implementation. Recall that in gRPC, a <em>Server</em> can handle one or more <em>Services</em>. Again, what Protobuf would normally have generated for us we need to write ourselves. Here is what the base service looks like:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">KeyValueServiceImplBase</span> <span style="color:#66d9ef">implements</span> BindableService <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">create</span><span style="color:#f92672">(</span>
|
||||
KvGson<span style="color:#f92672">.</span><span style="color:#a6e22e">CreateRequest</span> request<span style="color:#f92672">,</span> StreamObserver<span style="color:#f92672"><</span>CreateResponse<span style="color:#f92672">></span> responseObserver<span style="color:#f92672">);</span>
|
||||
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">retrieve</span><span style="color:#f92672">(</span><span style="color:#75715e">/*...*/</span><span style="color:#f92672">);</span>
|
||||
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">update</span><span style="color:#f92672">(</span><span style="color:#75715e">/*...*/</span><span style="color:#f92672">);</span>
|
||||
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">delete</span><span style="color:#f92672">(</span><span style="color:#75715e">/*...*/</span><span style="color:#f92672">);</span>
|
||||
|
||||
<span style="color:#75715e">/* Called by the Server to wire up methods to the handlers */</span>
|
||||
<span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">final</span> ServerServiceDefinition <span style="color:#a6e22e">bindService</span><span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
|
||||
ServerServiceDefinition<span style="color:#f92672">.</span><span style="color:#a6e22e">Builder</span> ssd <span style="color:#f92672">=</span> ServerServiceDefinition<span style="color:#f92672">.</span><span style="color:#a6e22e">builder</span><span style="color:#f92672">(</span>SERVICE_NAME<span style="color:#f92672">);</span>
|
||||
ssd<span style="color:#f92672">.</span><span style="color:#a6e22e">addMethod</span><span style="color:#f92672">(</span>CREATE_METHOD<span style="color:#f92672">,</span> ServerCalls<span style="color:#f92672">.</span><span style="color:#a6e22e">asyncUnaryCall</span><span style="color:#f92672">(</span>
|
||||
<span style="color:#f92672">(</span>request<span style="color:#f92672">,</span> responseObserver<span style="color:#f92672">)</span> <span style="color:#f92672">-></span> create<span style="color:#f92672">(</span>request<span style="color:#f92672">,</span> responseObserver<span style="color:#f92672">)));</span>
|
||||
|
||||
ssd<span style="color:#f92672">.</span><span style="color:#a6e22e">addMethod</span><span style="color:#f92672">(</span>RETRIEVE_METHOD<span style="color:#f92672">,</span> <span style="color:#75715e">/*...*/</span><span style="color:#f92672">);</span>
|
||||
ssd<span style="color:#f92672">.</span><span style="color:#a6e22e">addMethod</span><span style="color:#f92672">(</span>UPDATE_METHOD<span style="color:#f92672">,</span> <span style="color:#75715e">/*...*/</span><span style="color:#f92672">);</span>
|
||||
ssd<span style="color:#f92672">.</span><span style="color:#a6e22e">addMethod</span><span style="color:#f92672">(</span>DELETE_METHOD<span style="color:#f92672">,</span> <span style="color:#75715e">/*...*/</span><span style="color:#f92672">);</span>
|
||||
<span style="color:#66d9ef">return</span> ssd<span style="color:#f92672">.</span><span style="color:#a6e22e">build</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p><code>KeyValueServiceImplBase</code> will serve as both the service definition (which describes which methods the server can handle) and as the implementation (which describes what to do for each method). It serves as the glue between gRPC and our application logic. Practically no changes are needed to swap from Proto to GSON in the server code:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">KvService</span> <span style="color:#66d9ef">extends</span> KvGson<span style="color:#f92672">.</span><span style="color:#a6e22e">KeyValueServiceImplBase</span> <span style="color:#f92672">{</span>
|
||||
|
||||
<span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">create</span><span style="color:#f92672">(</span>
|
||||
KvGson<span style="color:#f92672">.</span><span style="color:#a6e22e">CreateRequest</span> request<span style="color:#f92672">,</span> StreamObserver<span style="color:#f92672"><</span>KvGson<span style="color:#f92672">.</span><span style="color:#a6e22e">CreateResponse</span><span style="color:#f92672">></span> responseObserver<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
ByteBuffer key <span style="color:#f92672">=</span> ByteBuffer<span style="color:#f92672">.</span><span style="color:#a6e22e">wrap</span><span style="color:#f92672">(</span>request<span style="color:#f92672">.</span><span style="color:#a6e22e">key</span><span style="color:#f92672">);</span>
|
||||
ByteBuffer value <span style="color:#f92672">=</span> ByteBuffer<span style="color:#f92672">.</span><span style="color:#a6e22e">wrap</span><span style="color:#f92672">(</span>request<span style="color:#f92672">.</span><span style="color:#a6e22e">value</span><span style="color:#f92672">);</span>
|
||||
<span style="color:#75715e">// ...
|
||||
</span><span style="color:#75715e"></span> <span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>After implementing all the methods on the server, we now have a fully functioning gRPC Java, JSON encoding RPC system. And to show you there is nothing up my sleeve:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ ./gradlew :dependencies | grep -i proto
|
||||
$ <span style="color:#75715e"># no proto deps!</span></code></pre></div>
|
||||
<h2 id="optimizing-the-code">Optimizing the Code</h2>
|
||||
|
||||
<p>While Gson is not as fast as Protobuf, there’s no sense in not picking the low hanging fruit. Running the code we see the performance is pretty slow:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">./gradlew installDist
|
||||
time ./build/install/kvstore/bin/kvstore
|
||||
|
||||
INFO: Did <span style="color:#ae81ff">215</span>.883 RPCs/s</code></pre></div>
|
||||
<p>What happened? In the previous <a href="/blog/optimizing-grpc-part-2">optimization</a> post, we saw the Protobuf version do nearly <em>2,500 RPCs/s</em>. JSON is slow, but not <em>that</em> slow. We can see what the problem is by printing out the JSON data as it goes through the marshaller:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">{<span style="color:#f92672">"key"</span>:[<span style="color:#ae81ff">4</span>,<span style="color:#ae81ff">-100</span>,<span style="color:#ae81ff">-48</span>,<span style="color:#ae81ff">22</span>,<span style="color:#ae81ff">-128</span>,<span style="color:#ae81ff">85</span>,<span style="color:#ae81ff">115</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">56</span>,<span style="color:#ae81ff">34</span>,<span style="color:#ae81ff">-48</span>,<span style="color:#ae81ff">-1</span>,<span style="color:#ae81ff">-119</span>,<span style="color:#ae81ff">60</span>,<span style="color:#ae81ff">17</span>,<span style="color:#ae81ff">-13</span>,<span style="color:#ae81ff">-118</span>]}</code></pre></div>
|
||||
<p>That’s not right! Looking at a <code>RetrieveRequest</code>, we see that the key bytes are being encoded as an array, rather than as a byte string. The wire size is much larger than it needs to be, and may not be compatible with other JSON code. To fix this, let’s tell GSON to encode and decode this data as base64 encoded bytes:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> Gson gson <span style="color:#f92672">=</span>
|
||||
<span style="color:#66d9ef">new</span> GsonBuilder<span style="color:#f92672">().</span><span style="color:#a6e22e">registerTypeAdapter</span><span style="color:#f92672">(</span><span style="color:#66d9ef">byte</span><span style="color:#f92672">[].</span><span style="color:#a6e22e">class</span><span style="color:#f92672">,</span> <span style="color:#66d9ef">new</span> TypeAdapter<span style="color:#f92672"><</span><span style="color:#66d9ef">byte</span><span style="color:#f92672">[]>()</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">write</span><span style="color:#f92672">(</span>JsonWriter out<span style="color:#f92672">,</span> <span style="color:#66d9ef">byte</span><span style="color:#f92672">[]</span> value<span style="color:#f92672">)</span> <span style="color:#66d9ef">throws</span> IOException <span style="color:#f92672">{</span>
|
||||
out<span style="color:#f92672">.</span><span style="color:#a6e22e">value</span><span style="color:#f92672">(</span>Base64<span style="color:#f92672">.</span><span style="color:#a6e22e">getEncoder</span><span style="color:#f92672">().</span><span style="color:#a6e22e">encodeToString</span><span style="color:#f92672">(</span>value<span style="color:#f92672">));</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
<span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">byte</span><span style="color:#f92672">[]</span> <span style="color:#a6e22e">read</span><span style="color:#f92672">(</span>JsonReader in<span style="color:#f92672">)</span> <span style="color:#66d9ef">throws</span> IOException <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">return</span> Base64<span style="color:#f92672">.</span><span style="color:#a6e22e">getDecoder</span><span style="color:#f92672">().</span><span style="color:#a6e22e">decode</span><span style="color:#f92672">(</span>in<span style="color:#f92672">.</span><span style="color:#a6e22e">nextString</span><span style="color:#f92672">());</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}).</span><span style="color:#a6e22e">create</span><span style="color:#f92672">();</span></code></pre></div>
|
||||
<p>Using this in our marshallers, we can see a dramatic performance difference:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">./gradlew installDist
|
||||
time ./build/install/kvstore/bin/kvstore
|
||||
|
||||
INFO: Did <span style="color:#ae81ff">2</span>,202.2 RPCs/s</code></pre></div>
|
||||
<p>Almost <strong>10x</strong> faster than before! We can still take advantage of gRPC’s efficiency while bringing our own encoders and messages.</p>
|
||||
|
||||
<h2 id="conclusion">Conclusion</h2>
|
||||
|
||||
<p>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, Cap’n 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.)</p>
|
||||
|
||||
<p>All the code is avaialable on <a href="https://github.com/carl-mastrangelo/kvstore/tree/04-gson-marshaller">GitHub</a> if you would like to see a fully working implementation.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,213 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC on HTTP/2 Engineering a Robust, High Performance Protocol – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC on HTTP/2 Engineering a Robust, High Performance Protocol</h1>
|
||||
<h5>Posted on Monday, August 20, 2018
|
||||
by
|
||||
|
||||
<a href="https://github.com/jadekler">Jean de Klerk</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>In a <a href="/blog/http2_smarter_at_scale">previous article</a>, 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, we’ll look at how gRPC builds on HTTP/2’s 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.</p>
|
||||
|
||||
<h2 id="grpc-semantics">gRPC Semantics</h2>
|
||||
|
||||
<p>To begin, let’s dive into how gRPC concepts relate to HTTP/2 concepts. gRPC introduces three new concepts: <em>channels</em> [1], <em>remote procedure calls</em> (RPCs), and <em>messages</em>. The relationship between the three is simple: each channel may have many RPCs while each RPC may have many messages.</p>
|
||||
|
||||
<p><img src="/img/channels_mapping_2.png" title="Channel Mapping" alt="Channel Mapping" style="max-width: 800px"></p>
|
||||
|
||||
<p>Let’s take a look at how gRPC semantics relate to HTTP/2:</p>
|
||||
|
||||
<p><img src="/img/grpc_on_http2_mapping_2.png" title="gRPC on HTTP/2" alt="gRPC on HTTP/2" style="max-width: 800px"></p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>Channels represent virtual connections to an endpoint, which in reality may be backed by many HTTP/2 connections. RPCs are associated with a connection (this association is described further on). RPCs are in practice plain HTTP/2 streams. Messages are associated with RPCs and get sent as HTTP/2 data frames. To be more specific, messages are <em>layered</em> on top of data frames. A data frame may have many gRPC messages, or if a gRPC message is quite large [2] it might span multiple data frames.</p>
|
||||
|
||||
<h2 id="resolvers-and-load-balancers">Resolvers and Load Balancers</h2>
|
||||
|
||||
<p>In order to keep connections alive, healthy, and utilized, gRPC utilizes a number of components, foremost among them <em>name resolvers</em> and <em>load balancers</em>. 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.</p>
|
||||
|
||||
<p><img src="/img/dns_to_load_balancer_mapping_3.png" title="Resolvers and Load Balancers" alt="Resolvers and Load Balancers" style="max-width: 800px"></p>
|
||||
|
||||
<p><img src="/img/load_balance_round_robins_2.png" alt="Round Robin Load Balancer" style="max-width: 800px"></p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>Resolvers and load balancers solve small but crucial problems in a gRPC system. This design is intentional: reducing the problem space to a few small, discrete problems helps users build custom components. These components can be used to fine-tune gRPC to fit each system’s individual needs.</p>
|
||||
|
||||
<h2 id="connection-management">Connection Management</h2>
|
||||
|
||||
<p>Once configured, gRPC will keep the pool of connections - as defined by the resolver and balancer - healthy, alive, and utilized.</p>
|
||||
|
||||
<p>When a connection fails, the load balancer will begin to reconnect using the last known list of addresses [3]. Meanwhile, the resolver will begin attempting to re-resolve the list of host names. This is useful in a number of scenarios. If the proxy is no longer reachable, for example, we’d want the resolver to update the list of addresses to not include that proxy’s address. To take another example: DNS entries might change over time, and so the list of addresses might need to be periodically updated. In this manner and others, gRPC is designed for long-term resiliency.</p>
|
||||
|
||||
<p>Once resolution is finished, the load balancer is informed of the new addresses. If addresses have changed, the load balancer may spin down connections to addresses not present in the new list or create connections to addresses that weren’t previously there.</p>
|
||||
|
||||
<h2 id="identifying-failed-connections">Identifying Failed Connections</h2>
|
||||
|
||||
<p>The effectiveness of gRPC’s connection management hinges upon its ability to identify failed connections. There are generally two types of connection failures: clean failures, in which the failure is communicated, and the less-clean failure, in which the failure is not communicated.</p>
|
||||
|
||||
<p>Let’s consider a clean, easy-to-observe failure. Clean failures can occur when an endpoint intentionally kills the connection. For example, the endpoint may have gracefully shut down, or a timer may have been exceeded, prompting the endpoint to close the connection. When connections close cleanly, TCP semantics suffice: closing a connection causes the <a href="https://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm">FIN handshake</a> to occur. This ends the HTTP/2 connection, which ends the gRPC connection. gRPC will immediately begin reconnecting (as described above). This is quite clean and requires no additional HTTP/2 or gRPC semantics.</p>
|
||||
|
||||
<p>The less clean version is where the endpoint dies or hangs without informing the client. In this case, TCP might undergo retry for as long as 10 minutes before the connection is considered failed. Of course, failing to recognize that the connection is dead for 10 minutes is unacceptable. gRPC solves this problem using HTTP/2 semantics: when configured using KeepAlive, gRPC will periodically send <a href="https://http2.github.io/http2-spec/#PING">HTTP/2 PING frames</a>. These frames bypass flow control and are used to establish whether the connection is alive. If a PING response does not return within a timely fashion, gRPC will consider the connection failed, close the connection, and begin reconnecting (as described above).</p>
|
||||
|
||||
<p>In this way, gRPC keeps a pool of connections healthy and uses HTTP/2 to ascertain the health of connections periodically. All of this behavior is opaque to the user, and message redirecting happens automatically and on the fly. Users simply send messages on a seemingly always-healthy pool of connections.</p>
|
||||
|
||||
<h2 id="keeping-connections-alive">Keeping Connections Alive</h2>
|
||||
|
||||
<p>As mentioned above, KeepAlive provides a valuable benefit: periodically checking the health of the connection by sending an HTTP/2 PING to determine whether the connection is still alive. However, it has another equally useful benefit: signaling liveness to proxies.</p>
|
||||
|
||||
<p>Consider a client sending data to a server through a proxy. The client and server may be happy to keep a connection alive indefinitely, sending data as necessary. Proxies, on the other hand, are often quite resource constrained and may kill idle connections to save resources. Google Cloud Platform (GCP) load balancers disconnect apparently-idle connections after <a href="https://cloud.google.com/compute/docs/troubleshooting#communicatewithinternet">10 minutes</a>, and Amazon Web Services Elastic Load Balancers (AWS ELBs) disconnect them after <a href="https://aws.amazon.com/articles/1636185810492479">60 seconds</a>.</p>
|
||||
|
||||
<p>With gRPC periodically sending HTTP/2 PING frames on connections, the perception of a non-idle connection is created. Endpoints using the aforementioned idle kill rule would pass over killing these connections.</p>
|
||||
|
||||
<h2 id="a-robust-high-performance-protocol">A Robust, High Performance Protocol</h2>
|
||||
|
||||
<p>HTTP/2 provides a foundation for long-lived, real-time communication streams. gRPC builds on top of this foundation with connection pooling, health semantics, efficient use of data frames and multiplexing, and KeepAlive.</p>
|
||||
|
||||
<p>Developers choosing protocols must choose those that meet today’s demands as well as tomorrow’s. They are well served by choosing gRPC, whether it be for resiliency, performance, long-lived or short-lived communication, customizability, or simply knowing that their protocol will scale to extraordinarily massive traffic while remaining efficient all the way. To get going with gRPC and HTTP/2 right away, check out <a href="https://grpc.io/docs/">gRPC’s Getting Started guides</a>.</p>
|
||||
|
||||
<h2 id="footnotes">Footnotes</h2>
|
||||
|
||||
<ol>
|
||||
<li>In Go, a gRPC channel is called ClientConn because the word “channel” has a language-specific meaning.</li>
|
||||
<li>gRPC uses the HTTP/2 default max size for a data frame of 16kb. A message over 16kb may span multiple data frames, whereas a message below that size may share a data frame with some number of other messages.</li>
|
||||
<li>This is the behavior of the RoundRobin balancer, but not every load balancer does or must behave this way.</li>
|
||||
</ol>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,164 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Dear gRPC – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>Dear gRPC</h1>
|
||||
<h5>Posted on Friday, March 08, 2019
|
||||
by
|
||||
|
||||
<a href="https://www.thisisnotapril.com/">April Nassi</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>Dear gRPC,</p>
|
||||
|
||||
<p>We messed up. We are so sorry that we missed your birthday this year. Last year we celebrated <a href="https://twitter.com/grpcio/status/968618209803931648">with cake</a> and fanfare, but this year we dropped the ball. Please don’t think that we love you any less.</p>
|
||||
|
||||
<p>You’re 4 now and that’s a big milestone! You’re part of so much amazing technology at companies like Salesforce, Netflix, Spotify, Fanatics, and of course, Google. In fact just this week the <a href="https://ads-developers.googleblog.com/2019/03/upgrade-to-new-google-ads-api-to-get.html">biggest API Google has</a> went production-ready with gRPC.</p>
|
||||
|
||||
<p>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 <strong>G</strong>olden <strong>R</strong>etriever and his name is <strong>P</strong>an<strong>C</strong>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.</p>
|
||||
|
||||
<p><img src="https://raw.githubusercontent.com/grpc/grpc-community/master/PanCakes/Pancakes_Birthday.png" alt="gRPC Mascot PanCakes" style="max-width: 547px"></p>
|
||||
|
||||
<p>Even though it’s a bit late, we still want to throw you a party, gRPC. Our friends at CNCF have planned a <a href="https://events.linuxfoundation.org/events/grpconf-2019/">big event</a> 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 <a href="http://www.cci.org/">Canine Companions for Independence</a> will be there to greet conference attendees and share how they help their humans live a more independent life.</p>
|
||||
|
||||
<p>We are so excited to see what this year holds for you, gRPC!</p>
|
||||
|
||||
<p>~ gRPC Maintainers</p>
|
||||
|
||||
<p><img src="https://raw.githubusercontent.com/grpc/grpc-community/master/PanCakes/Pancakes_Birthday_4.png" alt="gRPC Mascot PanCakes" style="max-width: 547px"></p>
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC in Helm – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC in Helm</h1>
|
||||
<h5>Posted on Monday, May 15, 2017
|
||||
by
|
||||
|
||||
Brian Hardock
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p><em>Our guest post today comes from Brian Hardock, a software engineer from Deis working on the <a href="https://helm.sh/">Helm</a> project.</em></p>
|
||||
|
||||
<p>Helm is the package manager for Kubernetes. Helm provides its users with a customizable mechanism for
|
||||
managing distributed applications and controlling their deployment.</p>
|
||||
|
||||
<p>I have the good fortune to be a member of the phenomenal open-source Kubernetes Helm community serving as
|
||||
a core contributor. My first day working with the Helm team was spent prototyping the architecture for
|
||||
the next generation of Helm. By the end of that day, we had procured the preliminary RPC protocol data model
|
||||
used to enable communication between Helm and its in-cluster server component, Tiller.</p>
|
||||
|
||||
<p>We chose to use protocol buffers - the default framework gRPC uses for serialization and over-the-air
|
||||
transmission - as our data definition language. By the end of that first day hacking with the Helm team,
|
||||
gRPC and protocol buffers proved to be a powerful combination. We had successfully had acheived communication
|
||||
between the Helm client and Tiller server using code generated from the protobuf and gRPC service definitions.
|
||||
As a personal preference, we found that the protobuf files and resulting generated gRPC
|
||||
code provided an aesthetic, nearly self-documenting developer experience compared to something like Swagger.</p>
|
||||
|
||||
<p>Within a few days, the Helm team was scoping and implementing features for our users. By choosing gRPC/Proto
|
||||
we had reduced the typical time spent bikeshedding that, in general, inevitably evolves from API modeling and
|
||||
churning out boilerplate server code. If we had not reaped the benefits of gRPC/protobuf from day 1, we would
|
||||
have spent significantly more time pivoting up and down the stack, as opposed to honing our focus on what
|
||||
matters: the users and the features they requested.</p>
|
||||
|
||||
<p>In addition to serving as the Helm/Tiller communication protocol, one of our more interesting applications
|
||||
of protocol buffers is that we use it to model what’s referred to in Kubernetes parlance as a “Chart”. Charts
|
||||
are an encapsulation of Kubernetes manifests that enable you to define, install, and upgrade Kubernetes applications.
|
||||
For more complex Kubernetes applications, the set of manifests may be large. By virtue of its inherent compression
|
||||
capabilities, protocol buffers and gRPC allowed us to mitigate the nuisance of transmitting bulky and
|
||||
sprawling Kubernetes manifests.</p>
|
||||
|
||||
<p>For a deeper dive into:</p>
|
||||
|
||||
<ul>
|
||||
<li>The Helm proto, see: <a href="https://github.com/kubernetes/helm/tree/master/_proto/hapi">https://github.com/kubernetes/helm/tree/master/_proto/hapi</a></li>
|
||||
<li>Its generated counterpart, see: <a href="https://github.com/kubernetes/helm/tree/master/pkg/proto/hapi">https://github.com/kubernetes/helm/tree/master/pkg/proto/hapi</a></li>
|
||||
<li>The interface to our Helm client, see: <a href="https://github.com/kubernetes/helm/tree/master/pkg/helm">https://github.com/kubernetes/helm/tree/master/pkg/helm</a></li>
|
||||
</ul>
|
||||
|
||||
<p>In summary, protobuf and gRPC provided Helm with:</p>
|
||||
|
||||
<ul>
|
||||
<li>Clearly defined message and protocol semantics for client and server communications.</li>
|
||||
<li>Increased feature development via a reduction in time spent on boilerplate server code / API modeling.</li>
|
||||
<li>High performance transmission of data through generated code and compression.</li>
|
||||
<li>Minimized cognitive cycles spent going from 0 to client/server communications.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
HTTP/2 Smarter At Scale – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>HTTP/2 Smarter At Scale</h1>
|
||||
<h5>Posted on Friday, July 13, 2018
|
||||
by
|
||||
|
||||
<a href="https://github.com/jadekler">Jean de Klerk</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>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 it’s beginning to show its age; for the most part, in that the designers weren’t 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.</p>
|
||||
|
||||
<p>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.1’s design in a number of ways, perhaps most significantly in providing a semantic mapping over connections. In this post we’ll explore the concept of streams and how they can be of substantial benefit to software engineers.</p>
|
||||
|
||||
<h2 id="semantic-mapping-over-connections">Semantic Mapping over Connections</h2>
|
||||
|
||||
<p>There’s significant overhead to creating HTTP connections. You must establish a TCP connection, secure that connection using TLS, exchange headers and settings, and so on. HTTP/1.1 simplified this process by treating connections as long-lived, reusable objects. HTTP/1.1 connections are kept idle so that new requests to the same destination can be sent over an existing, idle connection. Though connection reuse mitigates the problem, a connection can only handle one request at a time - they are coupled 1:1. If there is one large message being sent, new requests must either wait for its completion (resulting in head-of-line blocking) or, more frequently, pay the price of spinning up another connection.</p>
|
||||
|
||||
<p>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 <code>GET /users/1234/status</code>). With increasing frequency it’s 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.</p>
|
||||
|
||||
<p><img src="/img/conn_stream_frame_mapping.png" alt="Kotlin Android app example" style="max-width: 800px"></p>
|
||||
|
||||
<h2 id="streams-provide-concurrency">Streams Provide Concurrency</h2>
|
||||
|
||||
<p>The primary advantage of streams is connection concurrency, i.e. the ability to interleave messages on a single connection.</p>
|
||||
|
||||
<p>To illustrate this point, consider the case of some service A sending HTTP/1.1 requests to some service B about new users, profile updates, and product orders. Product orders tend to be large, and each product order ends up being broken up and sent as 5 TCP packets (to illustrate its size). Profile updates are very small and fit into one packet; new user requests are also small and fit into two packets.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p><img src="/img/http2_queue_3.png" alt="Kotlin Android app example" style="max-width: 800px"></p>
|
||||
|
||||
<p>Meanwhile, with HTTP/2, streaming allows messages to be sent concurrently on the same connection. Let’s 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 don’t have to wait for the first-to-arrive large product order request; all requests are sent concurrently.</p>
|
||||
|
||||
<p>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!</p>
|
||||
|
||||
<p><img src="/img/http2_round_robin.png" alt="Kotlin Android app example" style="max-width: 800px"></p>
|
||||
|
||||
<h2 id="flow-control">Flow Control</h2>
|
||||
|
||||
<p>Concurrent streams, however, harbor some subtle gotchas. Consider the following situation: two streams A and B on the same connection. Stream A receives a massive amount of data, far more than it can process in a short amount of time. Eventually the receiver’s buffer fills up and the TCP receive window limits the sender. This is all fairly standard behavior for TCP, but this situation is bad for streams as neither streams would receive any more data. Ideally stream B should be unaffected by stream A’s slow processing.</p>
|
||||
|
||||
<p>HTTP/2 solves this problem by providing a flow control mechanism as part of the stream specification. Flow control is used to limit the amount of outstanding data on a per-stream (and per-connection) basis. It operates as a credit system in which the receiver allocates a certain “budget” and the sender “spends” that budget. More specifically, the receiver allocates some buffer size (the “budget”) and the sender fills (“spends”) the buffer by sending data. The receiver advertises to the sender additional buffer as it is made available, using special-purpose WINDOW_UPDATE frames. When the receiver stops advertising additional buffer, the sender must stop sending messages when the buffer (its “budget”) is exhausted.</p>
|
||||
|
||||
<p>Using flow control, concurrent streams are guaranteed independent buffer allocation. Coupled with round robin request sending, streams of all sizes, processing speeds, and duration may be multiplexed on a single connection without having to care about cross-stream problems.</p>
|
||||
|
||||
<h2 id="smarter-proxies">Smarter Proxies</h2>
|
||||
|
||||
<p>The concurrency properties of HTTP/2 allow proxies to be more performant. As an example, consider an HTTP/1.1 load balancer that accepts and forwards spiky traffic: when a spike occurs, the proxy spins up more connections to handle the load or queues the requests. The former - new connections - are typically preferred (to a point); the downside to these new connections is paid not just in time waiting for syscalls and sockets, but also in time spent underutilizing the connection whilst TCP slow-start occurs.</p>
|
||||
|
||||
<p>In contrast, consider an HTTP/2 proxy that is configured to multiplex 100 streams per connection. A spike of some amount of requests will still cause new connections to be spun up, but only <sup>1</sup>⁄<sub>100</sub> connections as compared to its HTTP/1.1 counterpart. More generally speaking: If n HTTP/1.1 requests are sent to a proxy, n HTTP/1.1 requests must go out; each request is a single, meaningful request/payload of data, and requests are 1:1 with connections. In contrast, with HTTP/2 n requests sent to a proxy require n streams, but there is no requirement of n connections!</p>
|
||||
|
||||
<p>The proxy has room to make a wide variety of smart interventions. It may, for example:</p>
|
||||
|
||||
<ul>
|
||||
<li>Measure the bandwidth delay product (BDP) between itself and the service and then transparently create the minimum number of connections necessary to support the incoming streams.</li>
|
||||
<li>Kill idle streams without affecting the underlying connection.</li>
|
||||
<li>Load balance streams across connections to evenly spread traffic across those connections, ensuring maximum connection utilization.</li>
|
||||
<li>Measure processing speed based on WINDOW_UPDATE frames and use weighted load balancing to prioritize sending messages from streams on which messages are processed faster.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="http-2-is-smarter-at-scale">HTTP/2 Is Smarter At Scale</h2>
|
||||
|
||||
<p>HTTP/2 has many advantages over HTTP/1.1 that dramatically reduce the network cost of large-scale, real-time systems. Streams present one of the biggest flexibility and performance improvements that users will see, but HTTP/2 also provides semantics around graceful close (see: GOAWAY), header compression, server push, pinging, stream priority, and more. Check out the HTTP/2 spec if you’re interested in digging in more - it is long but rather easy reading.</p>
|
||||
|
||||
<p>To get going with HTTP/2 right away, check out gRPC, a high-performance, open-source universal RPC framework that uses HTTP/2. In a future post we’ll dive into gRPC and explore how it makes use of the mechanics provided by HTTP/2 to provide incredibly performant communication at scale.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,428 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Blogs – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="blogcols">
|
||||
<div class="blogcol1" style="margin-top:4%">
|
||||
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/hello-pancakes/">Dear gRPC</a></h3>
|
||||
<h5>March 08, 2019</h5>
|
||||
<p>
|
||||
Dear gRPC,
|
||||
We messed up. We are so sorry that we missed your birthday this year. Last year we celebrated with cake and fanfare, but this year we dropped the ball. Please don’t think that we love you any less.
|
||||
You’re 4 now and that’s a big milestone! You’re part of so much amazing technology at companies like Salesforce, Netflix, Spotify, Fanatics, and of course, Google. In fact just this week the biggest API Google has went production-ready with gRPC.
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/hello-pancakes/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/state-of-grpc-web/">The state of gRPC in the browser</a></h3>
|
||||
<h5>January 08, 2019</h5>
|
||||
<p>
|
||||
<p><em>This is a guest post by</em>
|
||||
<em><a href="https://jbrandhorst.com">Johan Brandhorst</a>, Software Engineer at</em>
|
||||
<em><a href="https://www.infosum.com">InfoSum</a>.</em></p>
|
||||
|
||||
<p>gRPC 1.0 was released in August 2016 and has since grown to become one of the
|
||||
premier technical solutions for application communications. It has been adopted
|
||||
by startups, enterprise companies, and open source projects worldwide.
|
||||
Its support for polyglot environments, focus on performance, type safety, and
|
||||
developer productivity has transformed the way developers design their
|
||||
architectures.</p>
|
||||
|
||||
<p>So far the benefits have largely only been available to mobile
|
||||
app and backend developers, whilst frontend developers have had to continue to
|
||||
rely on JSON REST interfaces as their primary means of information exchange.
|
||||
However, with the release of gRPC-Web, gRPC is poised to become a valuable
|
||||
addition in the toolbox of frontend developers.</p>
|
||||
|
||||
<p>In this post, I’ll describe some of the history of gRPC in the browser, explore
|
||||
the state of the world today, and share some thoughts on the future.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/state-of-grpc-web/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/grpc-dotnet-build/">gRPC Meets .NET SDK And Visual Studio: Automatic Codegen On Build</a></h3>
|
||||
<h5>December 18, 2018</h5>
|
||||
<p>
|
||||
<p>As part of Microsoft’s move towards its cross-platform .NET offering, they have
|
||||
greatly simplified the project file format, and allowed a tight integration of
|
||||
third-party code generators with .NET projects. We are listening, and now proud
|
||||
to introduce integrated compilation of Protocol Buffer and gRPC service
|
||||
<code>.proto</code> files in .NET C# projects starting with the version 1.17 of the
|
||||
Grpc.Tools NuGet package, now available from Nuget.org.</p>
|
||||
|
||||
<p>You no longer need to use hand-written scripts to generate code from <code>.proto</code>
|
||||
files: The .NET build magic handles this for you. The integrated tools locate
|
||||
the proto compiler and gRPC plugin, standard Protocol Buffer imports, and track
|
||||
dependencies before invoking the code generators, so that the generated C#
|
||||
source files are never out of date, at the same time keeping regeneration to
|
||||
the minimum required. In essence, <code>.proto</code> files are treated as first-class
|
||||
sources in a .NET C# project.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-dotnet-build/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/grpc-stacks/">Visualizing gRPC Language Stacks</a></h3>
|
||||
<h5>December 11, 2018</h5>
|
||||
<p>
|
||||
<p>Here is a high level overview of the gRPC Stacks. Each of the <strong>10</strong> default languages supported by gRPC has multiple layers, allowing you to customize what pieces you want in your application.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-stacks/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/grpc-web-ga/">gRPC-Web is Generally Available</a></h3>
|
||||
<h5>October 23, 2018</h5>
|
||||
<p>
|
||||
<p>We are excited to announce the GA release of
|
||||
<a href="https://www.npmjs.com/package/grpc-web">gRPC-Web</a>, 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. “GA” means that
|
||||
gRPC-Web is now Generally Available and stable and qualified for production use.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-web-ga/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/a_short_introduction_to_channelz/">A short introduction to Channelz</a></h3>
|
||||
<h5>September 05, 2018</h5>
|
||||
<p>
|
||||
<p>Channelz is a tool that provides comprehensive runtime info about connections at
|
||||
different levels in gRPC. It is designed to help debug live programs, which may
|
||||
be suffering from network, performance, configuration issues, etc. The
|
||||
<a href="https://github.com/grpc/proposal/blob/master/A14-channelz.md">gRFC</a> provides a
|
||||
detailed explanation of channelz design and is the canonical reference for all
|
||||
channelz implementations across languages. The purpose of this blog is to
|
||||
familiarize readers with channelz service and how to use it for debugging
|
||||
issues. The context of this post is set in
|
||||
<a href="https://github.com/grpc/grpc-go">gRPC-Go</a>, but the overall idea should be
|
||||
applicable across languages. At the time of writing, channelz is available for
|
||||
<a href="https://github.com/grpc/grpc-go">gRPC-Go</a> and
|
||||
<a href="https://github.com/grpc/grpc-java">gRPC-Java</a>. Support for
|
||||
<a href="https://github.com/grpc/grpc">C++</a> and wrapped languages is coming soon.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/a_short_introduction_to_channelz/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/grpc_on_http2/">gRPC on HTTP/2 Engineering a Robust, High Performance Protocol</a></h3>
|
||||
<h5>August 20, 2018</h5>
|
||||
<p>
|
||||
<p>In a <a href="/blog/http2_smarter_at_scale">previous article</a>, 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, we’ll look at how gRPC builds on HTTP/2’s 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.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc_on_http2/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/grpc-with-json/">gRPC + JSON</a></h3>
|
||||
<h5>August 15, 2018</h5>
|
||||
<p>
|
||||
<p>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?</p>
|
||||
|
||||
<p>Fortunately, gRPC is encoding agnostic! You can still get a lot of the benefits of gRPC without using Protobuf. In this post we’ll go through how to make gRPC work with other encodings and types. Let’s try using JSON.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-with-json/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/take-the-grpc-survey/">Take the gRPC Survey!</a></h3>
|
||||
<h5>August 14, 2018</h5>
|
||||
<p>
|
||||
<h2 id="the-grpc-project-wants-your-feedback">The gRPC Project wants your feedback!</h2>
|
||||
|
||||
<p>The gRPC project is looking for feedback to improve the gRPC experience. To do this, we are running a <a href="http://bit.ly/gRPC18survey">gRPC user survey</a>. We invite you to participate and provide input that will help us better plan and prioritize.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/take-the-grpc-survey/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/http2_smarter_at_scale/">HTTP/2 Smarter At Scale</a></h3>
|
||||
<h5>July 13, 2018</h5>
|
||||
<p>
|
||||
<p>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 it’s beginning to show its age; for the most part, in that the designers weren’t 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.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/http2_smarter_at_scale/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
|
||||
|
||||
<ul class="pagination">
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/" class="page-link" aria-label="First"><span aria-hidden="true">««</span></a>
|
||||
</li>
|
||||
|
||||
<li class="page-item disabled">
|
||||
<a href="" class="page-link" aria-label="Previous"><span aria-hidden="true">«</span></a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item active"><a class="page-link" href="/blog/">1</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item"><a class="page-link" href="/blog/page/2/">2</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item"><a class="page-link" href="/blog/page/3/">3</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item"><a class="page-link" href="/blog/page/4/">4</a></li>
|
||||
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/page/2/" class="page-link" aria-label="Next"><span aria-hidden="true">»</span></a>
|
||||
</li>
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/page/4/" class="page-link" aria-label="Last"><span aria-hidden="true">»»</span></a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="blogcol2">
|
||||
|
||||
<h5 style="font-size:12pt;margin-bottom:20px">All blog posts</h5>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/hello-pancakes/">Dear gRPC</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/state-of-grpc-web/">The state of gRPC in the browser</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-dotnet-build/">gRPC Meets .NET SDK And Visual Studio: Automatic Codegen On Build</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-stacks/">Visualizing gRPC Language Stacks</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-web-ga/">gRPC-Web is Generally Available</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/a_short_introduction_to_channelz/">A short introduction to Channelz</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc_on_http2/">gRPC on HTTP/2 Engineering a Robust, High Performance Protocol</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-with-json/">gRPC + JSON</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/take-the-grpc-survey/">Take the gRPC Survey!</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/http2_smarter_at_scale/">HTTP/2 Smarter At Scale</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/gracefully_clean_up_in_grpc_junit_tests/">Gracefully clean up in gRPC JUnit tests</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/kotlin-gradle-projects/">gRPC ❤ Kotlin</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-2/">So You Want to Optimize gRPC - Part 2</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-1/">So You Want to Optimize gRPC - Part 1</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/deadlines/">gRPC and Deadlines</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2018-01-22-grpc-go-engineering-practices/">2018-01-19 gRPC-Go Engineering Practices</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/meetup-kit/">The gRPC Meetup Kit</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2017-08-22-grpc-go-perf-improvements/">2017-08-22 gRPC-Go performance Improvements</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2017-08-17-community-meeting-update/">2017-08-17 Community Meeting Update</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/flatbuffers/">Announcing out of the box support for gRPC in the Flatbuffers serialization library.</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/loadbalancing/">gRPC Load Balancing</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/helmgrpc/">gRPC in Helm</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/yygrpc/">Migration to Google Cloud Platform — gRPC & grpc-gateway</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/bazel_rules_protobuf/">Building gRPC services with bazel and rules_protobuf</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/vscogrpc/">gRPC at VSCO</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/vendastagrpc/">Why we have decided to move our APIs to gRPC</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/gablogpost/">gRPC Project is now 1.0 and ready for production deployments</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/coreos/">gRPC with REST and Open APIs</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/installation/">gRPC - now with easy installation.</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/pubsub/">Google Cloud PubSub - with the power of gRPC!</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/beta_release/">gRPC releases Beta, opening door for use in production environments.</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/principles/">gRPC Motivation and Design Principles.</a><br><br>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,424 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>Blogs on gRPC</title>
|
||||
<link>https://cjyabraham.github.io/blog/</link>
|
||||
<description>Recent content in Blogs on gRPC</description>
|
||||
<generator>Hugo -- gohugo.io</generator>
|
||||
<language>en-us</language>
|
||||
<lastBuildDate>Fri, 08 Mar 2019 00:00:00 +0000</lastBuildDate>
|
||||
|
||||
<atom:link href="https://cjyabraham.github.io/blog/index.xml" rel="self" type="application/rss+xml" />
|
||||
|
||||
|
||||
<item>
|
||||
<title>Dear gRPC</title>
|
||||
<link>https://cjyabraham.github.io/blog/hello-pancakes/</link>
|
||||
<pubDate>Fri, 08 Mar 2019 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/hello-pancakes/</guid>
|
||||
<description>Dear gRPC,
|
||||
We messed up. We are so sorry that we missed your birthday this year. Last year we celebrated with cake and fanfare, but this year we dropped the ball. Please don&rsquo;t think that we love you any less.
|
||||
You&rsquo;re 4 now and that&rsquo;s a big milestone! You&rsquo;re part of so much amazing technology at companies like Salesforce, Netflix, Spotify, Fanatics, and of course, Google. In fact just this week the biggest API Google has went production-ready with gRPC.</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>The state of gRPC in the browser</title>
|
||||
<link>https://cjyabraham.github.io/blog/state-of-grpc-web/</link>
|
||||
<pubDate>Tue, 08 Jan 2019 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/state-of-grpc-web/</guid>
|
||||
<description><p><em>This is a guest post by</em>
|
||||
<em><a href="https://jbrandhorst.com">Johan Brandhorst</a>, Software Engineer at</em>
|
||||
<em><a href="https://www.infosum.com">InfoSum</a>.</em></p>
|
||||
|
||||
<p>gRPC 1.0 was released in August 2016 and has since grown to become one of the
|
||||
premier technical solutions for application communications. It has been adopted
|
||||
by startups, enterprise companies, and open source projects worldwide.
|
||||
Its support for polyglot environments, focus on performance, type safety, and
|
||||
developer productivity has transformed the way developers design their
|
||||
architectures.</p>
|
||||
|
||||
<p>So far the benefits have largely only been available to mobile
|
||||
app and backend developers, whilst frontend developers have had to continue to
|
||||
rely on JSON REST interfaces as their primary means of information exchange.
|
||||
However, with the release of gRPC-Web, gRPC is poised to become a valuable
|
||||
addition in the toolbox of frontend developers.</p>
|
||||
|
||||
<p>In this post, I&rsquo;ll describe some of the history of gRPC in the browser, explore
|
||||
the state of the world today, and share some thoughts on the future.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC Meets .NET SDK And Visual Studio: Automatic Codegen On Build</title>
|
||||
<link>https://cjyabraham.github.io/blog/grpc-dotnet-build/</link>
|
||||
<pubDate>Tue, 18 Dec 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/grpc-dotnet-build/</guid>
|
||||
<description><p>As part of Microsoft&rsquo;s move towards its cross-platform .NET offering, they have
|
||||
greatly simplified the project file format, and allowed a tight integration of
|
||||
third-party code generators with .NET projects. We are listening, and now proud
|
||||
to introduce integrated compilation of Protocol Buffer and gRPC service
|
||||
<code>.proto</code> files in .NET C# projects starting with the version 1.17 of the
|
||||
Grpc.Tools NuGet package, now available from Nuget.org.</p>
|
||||
|
||||
<p>You no longer need to use hand-written scripts to generate code from <code>.proto</code>
|
||||
files: The .NET build magic handles this for you. The integrated tools locate
|
||||
the proto compiler and gRPC plugin, standard Protocol Buffer imports, and track
|
||||
dependencies before invoking the code generators, so that the generated C#
|
||||
source files are never out of date, at the same time keeping regeneration to
|
||||
the minimum required. In essence, <code>.proto</code> files are treated as first-class
|
||||
sources in a .NET C# project.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>Visualizing gRPC Language Stacks</title>
|
||||
<link>https://cjyabraham.github.io/blog/grpc-stacks/</link>
|
||||
<pubDate>Tue, 11 Dec 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/grpc-stacks/</guid>
|
||||
<description><p>Here is a high level overview of the gRPC Stacks. Each of the <strong>10</strong> default languages supported by gRPC has multiple layers, allowing you to customize what pieces you want in your application.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC-Web is Generally Available</title>
|
||||
<link>https://cjyabraham.github.io/blog/grpc-web-ga/</link>
|
||||
<pubDate>Tue, 23 Oct 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/grpc-web-ga/</guid>
|
||||
<description><p>We are excited to announce the GA release of
|
||||
<a href="https://www.npmjs.com/package/grpc-web">gRPC-Web</a>, 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. &ldquo;GA&rdquo; means that
|
||||
gRPC-Web is now Generally Available and stable and qualified for production use.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>A short introduction to Channelz</title>
|
||||
<link>https://cjyabraham.github.io/blog/a_short_introduction_to_channelz/</link>
|
||||
<pubDate>Wed, 05 Sep 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/a_short_introduction_to_channelz/</guid>
|
||||
<description><p>Channelz is a tool that provides comprehensive runtime info about connections at
|
||||
different levels in gRPC. It is designed to help debug live programs, which may
|
||||
be suffering from network, performance, configuration issues, etc. The
|
||||
<a href="https://github.com/grpc/proposal/blob/master/A14-channelz.md">gRFC</a> provides a
|
||||
detailed explanation of channelz design and is the canonical reference for all
|
||||
channelz implementations across languages. The purpose of this blog is to
|
||||
familiarize readers with channelz service and how to use it for debugging
|
||||
issues. The context of this post is set in
|
||||
<a href="https://github.com/grpc/grpc-go">gRPC-Go</a>, but the overall idea should be
|
||||
applicable across languages. At the time of writing, channelz is available for
|
||||
<a href="https://github.com/grpc/grpc-go">gRPC-Go</a> and
|
||||
<a href="https://github.com/grpc/grpc-java">gRPC-Java</a>. Support for
|
||||
<a href="https://github.com/grpc/grpc">C++</a> and wrapped languages is coming soon.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC on HTTP/2 Engineering a Robust, High Performance Protocol</title>
|
||||
<link>https://cjyabraham.github.io/blog/grpc_on_http2/</link>
|
||||
<pubDate>Mon, 20 Aug 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/grpc_on_http2/</guid>
|
||||
<description><p>In a <a href="https://cjyabraham.github.io/blog/http2_smarter_at_scale">previous article</a>, 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, we’ll look at how gRPC builds on HTTP/2’s 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.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC + JSON</title>
|
||||
<link>https://cjyabraham.github.io/blog/grpc-with-json/</link>
|
||||
<pubDate>Wed, 15 Aug 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/grpc-with-json/</guid>
|
||||
<description><p>So you&rsquo;ve bought into this whole RPC thing and want to try it out, but aren&rsquo;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?</p>
|
||||
|
||||
<p>Fortunately, gRPC is encoding agnostic! You can still get a lot of the benefits of gRPC without using Protobuf. In this post we&rsquo;ll go through how to make gRPC work with other encodings and types. Let&rsquo;s try using JSON.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>Take the gRPC Survey!</title>
|
||||
<link>https://cjyabraham.github.io/blog/take-the-grpc-survey/</link>
|
||||
<pubDate>Tue, 14 Aug 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/take-the-grpc-survey/</guid>
|
||||
<description><h2 id="the-grpc-project-wants-your-feedback">The gRPC Project wants your feedback!</h2>
|
||||
|
||||
<p>The gRPC project is looking for feedback to improve the gRPC experience. To do this, we are running a <a href="http://bit.ly/gRPC18survey">gRPC user survey</a>. We invite you to participate and provide input that will help us better plan and prioritize.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>HTTP/2 Smarter At Scale</title>
|
||||
<link>https://cjyabraham.github.io/blog/http2_smarter_at_scale/</link>
|
||||
<pubDate>Fri, 13 Jul 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/http2_smarter_at_scale/</guid>
|
||||
<description><p>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 it’s beginning to show its age; for the most part, in that the designers weren’t 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&rsquo;t pass because of a leaked resource from the previous test. The worst case is that some subsequent tests pass that wouldn&rsquo;t have passed at all if the previously passed test had not leaked a resource.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>Gracefully clean up in gRPC JUnit tests</title>
|
||||
<link>https://cjyabraham.github.io/blog/gracefully_clean_up_in_grpc_junit_tests/</link>
|
||||
<pubDate>Tue, 26 Jun 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/gracefully_clean_up_in_grpc_junit_tests/</guid>
|
||||
<description><p>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.</p>
|
||||
|
||||
<p>This is even true for JUnit tests, because otherwise leaked resources may not only linger in your machine forever, but also interfere with subsequent tests. A not-so-bad case is that subsequent tests can&rsquo;t pass because of a leaked resource from the previous test. The worst case is that some subsequent tests pass that wouldn&rsquo;t have passed at all if the previously passed test had not leaked a resource.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC ❤ Kotlin</title>
|
||||
<link>https://cjyabraham.github.io/blog/kotlin-gradle-projects/</link>
|
||||
<pubDate>Tue, 19 Jun 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/kotlin-gradle-projects/</guid>
|
||||
<description><p>Did you know that gRPC Java now has out of box support for Kotlin projects built with Gradle? <a href="https://kotlinlang.org/">Kotlin</a> 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 <a href="https://github.com/google/protobuf-gradle-plugin/releases">protobuf-gradle-plugin</a> 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.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>So You Want to Optimize gRPC - Part 2</title>
|
||||
<link>https://cjyabraham.github.io/blog/optimizing-grpc-part-2/</link>
|
||||
<pubDate>Mon, 16 Apr 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/optimizing-grpc-part-2/</guid>
|
||||
<description><p>How fast is gRPC? Pretty fast if you understand how modern clients and servers are built. In
|
||||
<a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-1">part 1</a>, I showed how to get an easy <strong>60%</strong> improvement. In this
|
||||
post I show how to get a <strong>10000%</strong> improvement.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>So You Want to Optimize gRPC - Part 1</title>
|
||||
<link>https://cjyabraham.github.io/blog/optimizing-grpc-part-1/</link>
|
||||
<pubDate>Tue, 06 Mar 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/optimizing-grpc-part-1/</guid>
|
||||
<description><p>A common question with gRPC is how to make it fast. The gRPC library offers users access to high
|
||||
performance RPCs, but it isn&rsquo;t always clear how to achieve this. Because this question is common
|
||||
enough I thought I would try to show my thought process when tuning programs.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC and Deadlines</title>
|
||||
<link>https://cjyabraham.github.io/blog/deadlines/</link>
|
||||
<pubDate>Mon, 26 Feb 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/deadlines/</guid>
|
||||
<description><p><strong>TL;DR Always set a deadline</strong>. This post explains why we recommend being deliberate about setting deadlines, with useful code snippets to show you how.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>2018-01-19 gRPC-Go Engineering Practices</title>
|
||||
<link>https://cjyabraham.github.io/blog/2018-01-22-grpc-go-engineering-practices/</link>
|
||||
<pubDate>Mon, 22 Jan 2018 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/2018-01-22-grpc-go-engineering-practices/</guid>
|
||||
<description><p>It&rsquo;s the start of the new year, and almost the end of my first full year on the
|
||||
gRPC-Go project, so I&rsquo;d like to take this opportunity to provide an update on
|
||||
the state of gRPC-Go development and give some visibility into how we manage the
|
||||
project. For me, personally, this is the first open source project to which
|
||||
I&rsquo;ve meaningfully contributed, so this year has been a learning experience for
|
||||
me. Over this year, the team has made constant improvements to our work habits
|
||||
and communication. I still see room for improvement, but I believe we are in a
|
||||
considerably better place than we were a year ago.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>The gRPC Meetup Kit</title>
|
||||
<link>https://cjyabraham.github.io/blog/meetup-kit/</link>
|
||||
<pubDate>Thu, 14 Sep 2017 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/meetup-kit/</guid>
|
||||
<description>
|
||||
<p>If you have ever wanted to run an event around <a href="http://grpc.io">gRPC</a>, but didn&rsquo;t know where to start, or wasn&rsquo;t sure what content is available - we have released the <a href="https://github.com/grpc-ecosystem/meetup-kit">gRPC Meetup Kit</a>!</p>
|
||||
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>2017-08-22 gRPC-Go performance Improvements</title>
|
||||
<link>https://cjyabraham.github.io/blog/2017-08-22-grpc-go-perf-improvements/</link>
|
||||
<pubDate>Tue, 22 Aug 2017 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/2017-08-22-grpc-go-perf-improvements/</guid>
|
||||
<description><p><p>
|
||||
<span style="margin-bottom:5%">For past few months we&rsquo;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&rsquo;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.</p>
|
||||
|
||||
<p>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></p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>2017-08-17 Community Meeting Update</title>
|
||||
<link>https://cjyabraham.github.io/blog/2017-08-17-community-meeting-update/</link>
|
||||
<pubDate>Thu, 17 Aug 2017 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/2017-08-17-community-meeting-update/</guid>
|
||||
<description><p><strong>Next Community Meeting:</strong> Thursday, August 31, 2017 11am Pacific Time (US and Canada)</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>Announcing out of the box support for gRPC in the Flatbuffers serialization library.</title>
|
||||
<link>https://cjyabraham.github.io/blog/flatbuffers/</link>
|
||||
<pubDate>Thu, 17 Aug 2017 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/flatbuffers/</guid>
|
||||
<description><p>The recent release of Flatbuffers <a href="https://github.com/google/flatbuffers/releases">version 1.7</a> introduced truly zero-copy support for gRPC out of the box.</p>
|
||||
|
||||
<p><a href="https://google.github.io/flatbuffers/">Flatbuffers</a> is a serialization library that allows you to access serialized data without first unpacking it or allocating any
|
||||
additional data structures. It was originally designed for games and other resource constrained applications, but is now finding more general use, both by teams within Google and in other companies such as Netflix and Facebook.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC Load Balancing</title>
|
||||
<link>https://cjyabraham.github.io/blog/loadbalancing/</link>
|
||||
<pubDate>Thu, 15 Jun 2017 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/loadbalancing/</guid>
|
||||
<description><p>This post describes various load balancing scenarios seen when deploying gRPC. If you use <a href="https://cjyabraham.github.io/">gRPC</a> with multiple backends, this document is for you.</p>
|
||||
|
||||
<p>A large scale gRPC deployment typically has a number of identical back-end instances, and a number of clients. Each server has a certain capacity. Load balancing is used for distributing the load from clients optimally across available servers.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC in Helm</title>
|
||||
<link>https://cjyabraham.github.io/blog/helmgrpc/</link>
|
||||
<pubDate>Mon, 15 May 2017 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/helmgrpc/</guid>
|
||||
<description><p><em>Our guest post today comes from Brian Hardock, a software engineer from Deis working on the <a href="https://helm.sh/">Helm</a> project.</em></p>
|
||||
|
||||
<p>Helm is the package manager for Kubernetes. Helm provides its users with a customizable mechanism for
|
||||
managing distributed applications and controlling their deployment.</p>
|
||||
|
||||
<p>I have the good fortune to be a member of the phenomenal open-source Kubernetes Helm community serving as
|
||||
a core contributor. My first day working with the Helm team was spent prototyping the architecture for
|
||||
the next generation of Helm. By the end of that day, we had procured the preliminary RPC protocol data model
|
||||
used to enable communication between Helm and its in-cluster server component, Tiller.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>Migration to Google Cloud Platform — gRPC & grpc-gateway</title>
|
||||
<link>https://cjyabraham.github.io/blog/yygrpc/</link>
|
||||
<pubDate>Wed, 12 Apr 2017 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/yygrpc/</guid>
|
||||
<description><p>Our guest post today comes from <a href="https://www.linkedin.com/in/miguel-mendez-008231/">Miguel Mendez</a> of Yik Yak.</p>
|
||||
|
||||
<p><em>This post was originally a part of the <a href="https://medium.com/yik-yak-eng">Yik Yak Engineering Blog</a> which focused on sharing the lessons learned as we evolved Yik Yak from early-stage startup code running in Amazon Web Services to an eventual incremental rewrite, re-architecture, and live-migration to Google Cloud Platform.</em></p>
|
||||
|
||||
<p>In our previous blog <a href="https://medium.com/yik-yak-eng/migration-to-google-cloud-platform-overview-9b5e5c17c368">post</a> we gave an overview of our migration to Google Cloud Platform from Amazon Web Services. In this post we will drill down into the role that <a href="https://cjyabraham.github.io/">gRPC</a> and <a href="https://github.com/grpc-ecosystem/grpc-gateway">grpc-gateway</a> played in that migration and share some lessons which we picked up along the way.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>Building gRPC services with bazel and rules_protobuf</title>
|
||||
<link>https://cjyabraham.github.io/blog/bazel_rules_protobuf/</link>
|
||||
<pubDate>Thu, 13 Oct 2016 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/bazel_rules_protobuf/</guid>
|
||||
<description><p><a href="https://cjyabraham.github.io/">gRPC</a> makes it easier to build high-performance
|
||||
microservices by providing generated service entrypoints in a variety
|
||||
of different languages. <a href="https://bazel.io">Bazel</a> complements these
|
||||
efforts with a capable and fast polyglot build environment.</p>
|
||||
|
||||
<p><a href="https://github.com/pubref/rules_protobuf">rules_protobuf</a> extends
|
||||
bazel and makes it easier develop gRPC services.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC at VSCO</title>
|
||||
<link>https://cjyabraham.github.io/blog/vscogrpc/</link>
|
||||
<pubDate>Tue, 06 Sep 2016 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/vscogrpc/</guid>
|
||||
<description><p>Our guest post today comes from Robert Sayre and Melinda Lu of VSCO.</p>
|
||||
|
||||
<p>Founded in 2011, <a href="https://vsco.co">VSCO</a> is a community for expression—empowering people to create, discover and connect through images and words. VSCO is in the process of migrating their stack to gRPC.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>Why we have decided to move our APIs to gRPC</title>
|
||||
<link>https://cjyabraham.github.io/blog/vendastagrpc/</link>
|
||||
<pubDate>Mon, 29 Aug 2016 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/vendastagrpc/</guid>
|
||||
<description>Our guest post today comes from Dale Hopkins, CTO of Vendasta.
|
||||
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 and Datastore.</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC Project is now 1.0 and ready for production deployments</title>
|
||||
<link>https://cjyabraham.github.io/blog/gablogpost/</link>
|
||||
<pubDate>Tue, 23 Aug 2016 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/gablogpost/</guid>
|
||||
<description>Today, the gRPC project has reached a significant milestone with its 1.0 release. Languages moving to 1.0 include C++, Java, Go, Node, Ruby, Python and C# across Linux, Windows, and Mac. Objective-C and Android Java support on iOS and Android is also moving to 1.0. The 1.0 release means that the core protocol and API surface are now stable with measured performance, stress tested and developers can rely on these APIs and deploy in production, they will follow semantic versioning from here.</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC with REST and Open APIs</title>
|
||||
<link>https://cjyabraham.github.io/blog/coreos/</link>
|
||||
<pubDate>Mon, 09 May 2016 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/coreos/</guid>
|
||||
<description><p>Our guest post today comes from Brandon Phillips of <a href="https://coreos.com/">CoreOS</a>. CoreOS builds open source projects and products for Linux Containers. Their flagship product for consensus and discovery <a href="https://coreos.com/etcd/">etcd</a> and their container engine <a href="https://coreos.com/rkt/">rkt</a> are early adopters of gRPC.</p>
|
||||
|
||||
<p>One of the key reasons CoreOS chose gRPC is because it uses HTTP/2, enabling applications to present both a HTTP 1.1 REST/JSON API and an efficient gRPC interface on a single TCP port (available for Go). This provides developers with compatibility with the REST web ecosystem, while advancing a new, high-efficiency RPC protocol. With the recent release of Go 1.6, Go ships with a stable <code>net/http2</code> package by default.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC - now with easy installation.</title>
|
||||
<link>https://cjyabraham.github.io/blog/installation/</link>
|
||||
<pubDate>Mon, 04 Apr 2016 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/installation/</guid>
|
||||
<description><p>Today we are happy to provide an update that significantly simplifies the getting started experience for gRPC.</p>
|
||||
|
||||
<ul>
|
||||
<li><p>For most languages, <strong>the gRPC runtime can now be installed in a single step via native package managers</strong> such as <code>npm</code> for Node.js, <code>gem</code> for Ruby and <code>pip</code> for Python. Even though our Node, Ruby and Python runtimes are wrapped on gRPC&rsquo;s C core, users now don&rsquo;t need to explicitly pre-install the C core library as a package in most Linux distributions. We autofetch it for you :-).</p></li>
|
||||
|
||||
<li><p><strong>For Java, we have simplified the steps needed to add gRPC support to your build tools</strong> by providing plugins for Maven and Gradle. These let you easily depend on the core runtime to deploy or ship generated libraries into production environments.</p></li>
|
||||
|
||||
<li><p>You can also use our Dockerfiles to use these updated packages - deploying microservices built on gRPC should now be a very simple experience.</p></li>
|
||||
</ul></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>Google Cloud PubSub - with the power of gRPC!</title>
|
||||
<link>https://cjyabraham.github.io/blog/pubsub/</link>
|
||||
<pubDate>Thu, 24 Mar 2016 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/pubsub/</guid>
|
||||
<description><p><a href="https://cloud.google.com/pubsub/">Google Cloud PubSub</a> is Google&rsquo;s scalable real-time messaging service that lets users send and receive messages between independent applications. It&rsquo;s an important part of Google Cloud Platform&rsquo;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&rsquo;s all changed with the release of <a href="https://cloud.google.com/blog/big-data/2016/03/announcing-grpc-alpha-for-google-cloud-pubsub">PubSub gRPC alpha</a>. Now <strong>users can access PubSub via gRPC</strong> and benefit from all the advantages it brings.</p></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC releases Beta, opening door for use in production environments.</title>
|
||||
<link>https://cjyabraham.github.io/blog/beta_release/</link>
|
||||
<pubDate>Mon, 26 Oct 2015 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/beta_release/</guid>
|
||||
<description>
|
||||
<p>
|
||||
The gRPC team is excited to announce the immediate availability of gRPC Beta. This release marks an important point in API stability and going forward most API changes are expected to be additive in nature. This milestone opens the door for gRPC use in production environments.
|
||||
</p>
|
||||
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC Motivation and Design Principles.</title>
|
||||
<link>https://cjyabraham.github.io/blog/principles/</link>
|
||||
<pubDate>Tue, 08 Sep 2015 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/blog/principles/</guid>
|
||||
<description>
|
||||
<h2>Motivation</h2>
|
||||
|
||||
<p>Google has been using a single general-purpose RPC infrastructure called Stubby to connect the large number of microservices running within and across our data centers for over a decade. Our internal systems have long embraced the microservice architecture gaining popularity today. Having a uniform, cross-platform RPC infrastructure has allowed for the rollout of fleet-wide improvements in efficiency, security, reliability and behavioral analysis critical to supporting the incredible growth seen in that period.
|
||||
</p>
|
||||
|
||||
</description>
|
||||
</item>
|
||||
|
||||
</channel>
|
||||
</rss>
|
||||
|
|
@ -1,229 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC - now with easy installation. – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC - now with easy installation.</h1>
|
||||
<h5>Posted on Monday, April 04, 2016
|
||||
|
||||
|
||||
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>Today we are happy to provide an update that significantly simplifies the getting started experience for gRPC.</p>
|
||||
|
||||
<ul>
|
||||
<li><p>For most languages, <strong>the gRPC runtime can now be installed in a single step via native package managers</strong> such as <code>npm</code> for Node.js, <code>gem</code> for Ruby and <code>pip</code> for Python. Even though our Node, Ruby and Python runtimes are wrapped on gRPC’s C core, users now don’t need to explicitly pre-install the C core library as a package in most Linux distributions. We autofetch it for you :-).</p></li>
|
||||
|
||||
<li><p><strong>For Java, we have simplified the steps needed to add gRPC support to your build tools</strong> by providing plugins for Maven and Gradle. These let you easily depend on the core runtime to deploy or ship generated libraries into production environments.</p></li>
|
||||
|
||||
<li><p>You can also use our Dockerfiles to use these updated packages - deploying microservices built on gRPC should now be a very simple experience.</p></li>
|
||||
</ul>
|
||||
|
||||
<p>The installation story is not yet complete: we are now focused on improving your development experience by packaging our protocol buffer plugins in the same way as the gRPC runtime. This will simplify code generation and setting up your development environment.</p>
|
||||
|
||||
<h3 id="want-to-try-it">Want to try it?</h3>
|
||||
|
||||
<p>Here’s how to install the gRPC runtime today in all our supported languages:</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Language</th>
|
||||
<th>Platform</th>
|
||||
<th>Command</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Node.js</td>
|
||||
<td>Linux, Mac, Windows</td>
|
||||
<td><code>npm install grpc</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Python</td>
|
||||
<td>Linux, Mac, Windows</td>
|
||||
<td><code>pip install grpcio</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Ruby</td>
|
||||
<td>Linux, Mac, Windows</td>
|
||||
<td><code>gem install grpc</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>PHP</td>
|
||||
<td>Linux, Mac, Windows</td>
|
||||
<td><code>pecl install grpc-beta</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Go</td>
|
||||
<td>Linux, Mac, Windows</td>
|
||||
<td><code>go get google.golang.org/grpc</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Objective-C</td>
|
||||
<td>Mac</td>
|
||||
<td>Runtime source fetched automatically from GitHub by Cocoapods</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>C#</td>
|
||||
<td>Windows</td>
|
||||
<td>Install <a href="https://www.nuget.org/packages/Grpc/">gRPC NuGet package</a> from your IDE (Visual Studio, Monodevelop, Xamarin Studio)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Java</td>
|
||||
<td>Linux, Mac, Windows</td>
|
||||
<td>Use our <a href="https://github.com/grpc/grpc-java/blob/master/README.md">Maven and Gradle plugins</a> that provide gRPC with <a href="https://github.com/grpc/grpc-java/blob/master/SECURITY.md#openssl-statically-linked-netty-tcnative-boringssl-static">statically linked <code>boringssl</code></a></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>C++</td>
|
||||
<td>Linux, Mac, Windows</td>
|
||||
<td>Currently requires <a href="https://github.com/grpc/grpc/blob/v1.20.0/src/cpp/README.md">manual build and install</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>You can find out more about installation in our <a href="/docs/#install-grpc">Getting Started guide</a> and GitHub repositories. Do send us your feedback on our <a href="https://groups.google.com/forum/#!forum/grpc-io">mailing list</a> or file issues on our issue tracker if you run into any problems.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC ❤ Kotlin – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC ❤ Kotlin</h1>
|
||||
<h5>Posted on Tuesday, June 19, 2018
|
||||
by
|
||||
|
||||
<a href="https://github.com/zpencer">Spencer Fang</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>Did you know that gRPC Java now has out of box support for Kotlin projects built with Gradle? <a href="https://kotlinlang.org/">Kotlin</a> 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 <a href="https://github.com/google/protobuf-gradle-plugin/releases">protobuf-gradle-plugin</a> 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.</p>
|
||||
|
||||
<p>The following examples show you how to configure a project for a JVM application and an Android application using Kotlin.</p>
|
||||
|
||||
<h3 id="kotlin-grpc-client-and-server">Kotlin gRPC client and server</h3>
|
||||
|
||||
<p>The full example can be found <a href="https://github.com/grpc/grpc-java/tree/master/examples/example-kotlin">here</a>.</p>
|
||||
|
||||
<p>Configuring gRPC for a Kotlin project is the same as configuring it for a Java project.</p>
|
||||
|
||||
<p>Below is a snippet of the example project’s <code>build.gradle</code> highlighting some Kotlin related sections:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-groovy" data-lang="groovy">apply plugin: <span style="color:#e6db74">'kotlin'</span>
|
||||
apply plugin: <span style="color:#e6db74">'com.google.protobuf'</span>
|
||||
|
||||
<span style="color:#75715e">// Generate IntelliJ IDEA's .idea & .iml project files.
|
||||
</span><span style="color:#75715e">// protobuf-gradle-plugin automatically registers *.proto and the gen output files
|
||||
</span><span style="color:#75715e">// to IntelliJ as sources.
|
||||
</span><span style="color:#75715e">// For best results, install the Protobuf and Kotlin plugins for IntelliJ.
|
||||
</span><span style="color:#75715e"></span>apply plugin: <span style="color:#e6db74">'idea'</span>
|
||||
|
||||
buildscript <span style="color:#f92672">{</span>
|
||||
ext<span style="color:#f92672">.</span><span style="color:#a6e22e">kotlin_version</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">'1.2.21'</span>
|
||||
|
||||
repositories <span style="color:#f92672">{</span>
|
||||
mavenCentral<span style="color:#f92672">()</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
dependencies <span style="color:#f92672">{</span>
|
||||
classpath <span style="color:#e6db74">'com.google.protobuf:protobuf-gradle-plugin:0.8.5'</span>
|
||||
classpath <span style="color:#e6db74">"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
dependencies <span style="color:#f92672">{</span>
|
||||
compile <span style="color:#e6db74">"org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"</span>
|
||||
<span style="color:#75715e">// The rest of the projects dep are added below, refer to example URL
|
||||
</span><span style="color:#75715e"></span><span style="color:#f92672">}</span>
|
||||
|
||||
<span style="color:#75715e">// The standard protobuf block, same as normal gRPC Java projects
|
||||
</span><span style="color:#75715e"></span>protobuf <span style="color:#f92672">{</span>
|
||||
protoc <span style="color:#f92672">{</span> artifact <span style="color:#f92672">=</span> <span style="color:#e6db74">'com.google.protobuf:protoc:3.5.1-1'</span> <span style="color:#f92672">}</span>
|
||||
plugins <span style="color:#f92672">{</span>
|
||||
grpc <span style="color:#f92672">{</span> artifact <span style="color:#f92672">=</span> <span style="color:#e6db74">"io.grpc:protoc-gen-grpc-java:${grpcVersion}"</span> <span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
generateProtoTasks <span style="color:#f92672">{</span>
|
||||
all<span style="color:#f92672">()*.</span><span style="color:#a6e22e">plugins</span> <span style="color:#f92672">{</span> grpc <span style="color:#f92672">{}</span> <span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>Now Kotlin source files can use the proto generated messages and gRPC stubs. By default, Kotlin sources should be placed in <code>src/main/kotlin</code> and <code>src/test/kotlin</code>. If needed, run <code>./gradlew generateProto generateTestProto</code> and refresh IntelliJ for the generated sources to appear in the IDE. Finally, run <code>./gradlew installDist</code> to build the project, and use <code>./build/install/examples/bin/hello-world-client</code> or <code>./build/install/examples/bin/hello-world-server</code> to run the example.</p>
|
||||
|
||||
<p>You can read more about configuring Kotlin <a href="https://kotlinlang.org/docs/reference/using-gradle.html">here</a>.</p>
|
||||
|
||||
<h3 id="kotlin-android-grpc-application">Kotlin Android gRPC application</h3>
|
||||
|
||||
<p>The full example can be found <a href="https://github.com/grpc/grpc-java/tree/master/examples/example-kotlin/android/helloworld">here</a>.</p>
|
||||
|
||||
<p>Configuring gRPC for a Kotlin Android project is the same as configuring it for a normal Android project.</p>
|
||||
|
||||
<p>In the top level <code>build.gradle</code> file:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-groovy" data-lang="groovy">buildscript <span style="color:#f92672">{</span>
|
||||
ext<span style="color:#f92672">.</span><span style="color:#a6e22e">kotlin_version</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">'1.2.21'</span>
|
||||
|
||||
repositories <span style="color:#f92672">{</span>
|
||||
google<span style="color:#f92672">()</span>
|
||||
jcenter<span style="color:#f92672">()</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
dependencies <span style="color:#f92672">{</span>
|
||||
classpath <span style="color:#e6db74">'com.android.tools.build:gradle:3.0.1'</span>
|
||||
classpath <span style="color:#e6db74">"com.google.protobuf:protobuf-gradle-plugin:0.8.5"</span>
|
||||
classpath <span style="color:#e6db74">"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
allprojects <span style="color:#f92672">{</span>
|
||||
repositories <span style="color:#f92672">{</span>
|
||||
google<span style="color:#f92672">()</span>
|
||||
jcenter<span style="color:#f92672">()</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>And in the app module’s <code>build.gradle</code> file:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-groovy" data-lang="groovy">apply plugin: <span style="color:#e6db74">'com.android.application'</span>
|
||||
apply plugin: <span style="color:#e6db74">'kotlin-android'</span>
|
||||
apply plugin: <span style="color:#e6db74">'kotlin-android-extensions'</span>
|
||||
apply plugin: <span style="color:#e6db74">'com.google.protobuf'</span>
|
||||
|
||||
repositories <span style="color:#f92672">{</span>
|
||||
mavenCentral<span style="color:#f92672">()</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
dependencies <span style="color:#f92672">{</span>
|
||||
compile <span style="color:#e6db74">"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"</span>
|
||||
<span style="color:#75715e">// refer to full example for remaining deps
|
||||
</span><span style="color:#75715e"></span><span style="color:#f92672">}</span>
|
||||
|
||||
protobuf <span style="color:#f92672">{</span>
|
||||
<span style="color:#75715e">// The normal gRPC configuration for Android goes here
|
||||
</span><span style="color:#75715e"></span><span style="color:#f92672">}</span>
|
||||
|
||||
android <span style="color:#f92672">{</span>
|
||||
<span style="color:#75715e">// Android Studio 3.1 does not automatically pick up 'src/main/kotlin' as source files
|
||||
</span><span style="color:#75715e"></span> sourceSets <span style="color:#f92672">{</span>
|
||||
main<span style="color:#f92672">.</span><span style="color:#a6e22e">java</span><span style="color:#f92672">.</span><span style="color:#a6e22e">srcDirs</span> <span style="color:#f92672">+=</span> <span style="color:#e6db74">'src/main/kotlin'</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>Just like the non-Android project, run <code>./gradlew generateProto generateProto</code> to run the proto code generator and <code>./gradlew build</code> to build the project.</p>
|
||||
|
||||
<p>Finally, test out the Android app by opening the project in Android Studio and selecting <code>Run > Run 'app'</code>.</p>
|
||||
|
||||
<p><img src="/img/kotlin-project-android-app.png" alt="Kotlin Android app example" style="max-width: 404px"></p>
|
||||
|
||||
<p>We are excited about improving the gRPC experience for Kotlin developers. Please add enhancement ideas or bugs to the <a href="https://github.com/google/protobuf-gradle-plugin/issues">protobuf-gradle-plugin issue tracker</a> or the <a href="https://github.com/grpc/grpc-java/issues">grpc-java issue tracker</a>.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,335 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC Load Balancing – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC Load Balancing</h1>
|
||||
<h5>Posted on Thursday, June 15, 2017
|
||||
by
|
||||
|
||||
makdharma
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>This post describes various load balancing scenarios seen when deploying gRPC. If you use <a href="/">gRPC</a> with multiple backends, this document is for you.</p>
|
||||
|
||||
<p>A large scale gRPC deployment typically has a number of identical back-end instances, and a number of clients. Each server has a certain capacity. Load balancing is used for distributing the load from clients optimally across available servers.</p>
|
||||
|
||||
<h3 id="why-grpc">Why gRPC?</h3>
|
||||
|
||||
<p>gRPC is a modern RPC protocol implemented on top of HTTP/2. HTTP/2 is a Layer 7 (Application layer) protocol, that runs on top of a TCP (Layer 4 - Transport layer) protocol, which runs on top of IP (Layer 3 - Network layer) protocol. gRPC has many <a href="https://http2.github.io/faq/#why-is-http2-binary">advantages</a> over traditional HTTP/REST/JSON mechanism such as</p>
|
||||
|
||||
<ol>
|
||||
<li><p>Binary protocol (HTTP/2),</p></li>
|
||||
|
||||
<li><p>Multiplexing many requests on one connection (HTTP/2)</p></li>
|
||||
|
||||
<li><p>Header compression (HTTP/2)</p></li>
|
||||
|
||||
<li><p>Strongly typed service and message definition (Protobuf)</p></li>
|
||||
|
||||
<li><p>Idiomatic client/server library implementations in many languages</p></li>
|
||||
</ol>
|
||||
|
||||
<p>In addition, gRPC integrates seamlessly with ecosystem components like service discovery, name resolver, load balancer, tracing and monitoring, among others.</p>
|
||||
|
||||
<h2 id="load-balancing-options">Load balancing options</h2>
|
||||
|
||||
<h3 id="proxy-or-client-side">Proxy or Client side?</h3>
|
||||
|
||||
<p><em>Note: Proxy load balancing is also known as server-side load balancing in some literature.</em></p>
|
||||
|
||||
<p>Deciding between proxy versus client-side load balancing is a primary architectural choice. In Proxy load balancing, the client issues RPCs to the a Load Balancer (LB) proxy. The LB distributes the RPC call to one of the available backend servers that implement the actual logic for serving the call. The LB keeps track of load on each backend and implements algorithms for distributing load fairly. The clients themselves do not know about the backend servers. Clients can be untrusted. This architecture is typically used for user facing services where clients from open internet can connect to servers in a data center, as shown in the picture below. In this scenario, clients make requests to LB (#1). The LB passes on the request to one of the backends (#2), and the backends report load to LB (#3).</p>
|
||||
|
||||
<p><img src="/img/image_0.png" alt="image alt text" /></p>
|
||||
|
||||
<p>In Client side load balancing, the client is aware of multiple backend servers and chooses one to use for each RPC. The client gets load reports from backend servers and the client implements the load balancing algorithms. In simpler configurations server load is not considered and client can just round-robin between available servers. This is shown in the picture below. As you can see, the client makes request to a specific backend (#1). The backends respond with load information (#2), typically on the same connection on which client RPC is executed. The client then updates its internal state.</p>
|
||||
|
||||
<p><img src="/img/image_1.png" alt="image alt text" /></p>
|
||||
|
||||
<p>The following table outlines the pros and cons of each model.</p>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Proxy</td>
|
||||
<td>Client Side</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:10% !important">Pros</td>
|
||||
<td>
|
||||
le client
|
||||
* No client-side awareness of backend
|
||||
* Works with untrusted clients
|
||||
</td>
|
||||
<td>
|
||||
|
||||
* High performance because elimination of extra hop
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Cons</td>
|
||||
<td>
|
||||
|
||||
* LB is in the data path
|
||||
* Higher latency
|
||||
* LB throughput may limit scalability
|
||||
</td>
|
||||
<td>
|
||||
|
||||
* Complex client
|
||||
* Client keeps track of server load and health
|
||||
* Client implements load balancing algorithm
|
||||
* Per-language implementation and maintenance burden
|
||||
* Client needs to be trusted, or the trust boundary needs to be handled by a lookaside LB.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3 id="proxy-load-balancer-options">Proxy Load Balancer options</h3>
|
||||
|
||||
<p>Proxy load balancing can be L3/L4 (transport level) or L7 (application level). In transport level load balancing, the server terminates the TCP connection and opens another connection to the backend of choice. The application data (HTTP/2 and gRPC frames) are simply copied between the client connection to the backend connection. L3/L4 LB by design does very little processing, adds less latency compared with L7 LB, and is cheaper because it consumes fewer resources.</p>
|
||||
|
||||
<p>In L7 (application level) load balancing, the LB terminates and parses the HTTP/2 protocol. The LB can inspect each request and assign a backend based on the request contents. For example, a session cookie sent as part of HTTP header can be used to associate with a specific backend, so all requests for that session are served by the same backend. Once the LB has chosen an appropriate backend, it creates a new HTTP/2 connection to that backend. It then forwards the HTTP/2 streams received from the client to the backend(s) of choice. With HTTP/2, LB can distribute the streams from one client among multiple backends.</p>
|
||||
|
||||
<h4 id="l3-l4-transport-vs-l7-application">L3/L4 (Transport) vs L7 (Application)</h4>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
Use case
|
||||
</td>
|
||||
<td>
|
||||
Recommendation
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>RPC load varies a lot among connections</td>
|
||||
<td>Use Application level LB</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Storage or compute affinity is important</td>
|
||||
<td>Use Application level LB and use cookies or similar for routing requests to correct backend</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Minimizing resource utilization in proxy is more important than features</td>
|
||||
<td>Use L3/L4 LB</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Latency is paramount</td>
|
||||
<td>Use L3/L4 LB</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3 id="client-side-lb-options">Client side LB options</h3>
|
||||
|
||||
<h4 id="thick-client">Thick client</h4>
|
||||
|
||||
<p>A thick client approach means the load balancing smarts are implemented in the client. The client is responsible for keeping track of available servers, their workload, and the algorithms used for choosing servers. The client typically integrates libraries that communicate with other infrastructures such as service discovery, name resolution, quota management, etc.</p>
|
||||
|
||||
<h4 id="lookaside-load-balancing">Lookaside Load Balancing</h4>
|
||||
|
||||
<p><em>Note: A lookaside load balancer is also known as an external load balancer or one-arm load balancer</em></p>
|
||||
|
||||
<p>With lookaside load balancing, the load balancing smarts are implemented in a special LB server. Clients query the lookaside LB and the LB responds with best server(s) to use. The heavy lifting of keeping server state and implementation of LB algorithm is consolidated in the lookaside LB. Note that client might choose to implement simple algorithms on top of the sophisticated ones implemented in the LB. gRPC defines a protocol for communication between client and LB using this model. See Load Balancing in gRPC <a href="https://github.com/grpc/grpc/blob/master/doc/load-balancing.md">doc</a> for details.</p>
|
||||
|
||||
<p>The picture below illustrates this approach. The client gets at least one address from lookaside LB (#1). Then the client uses this address to make a RPC (#2), and server sends load report to the LB (#3). The lookaside LB communicates with other infrastructure such as name resolution, service discovery, and so on (#4).</p>
|
||||
|
||||
<p><img src="/img/image_2.png" alt="image alt text" /></p>
|
||||
|
||||
<h2 id="recommendations-and-best-practices">Recommendations and best practices</h2>
|
||||
|
||||
<p>Depending upon the particular deployment and constraints, we suggest the following.</p>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>Setup</td>
|
||||
<td>Recommendation</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td markdown="1">
|
||||
|
||||
* Very high traffic between clients and servers
|
||||
* Clients can be trusted
|
||||
</td>
|
||||
<td markdown="1">
|
||||
|
||||
* Thick client-side load balancing
|
||||
* Client side LB with ZooKeeper/Etcd/Consul/Eureka. [ZooKeeper Example](https://github.com/makdharma/grpc-zookeeper-lb).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td markdown="1">
|
||||
|
||||
* Traditional setup - Many clients connecting to services behind a proxy
|
||||
* Need trust boundary between servers and clients
|
||||
</td>
|
||||
<td markdown="1">
|
||||
|
||||
* Proxy Load Balancing
|
||||
* L3/L4 LB with GCLB (if using GCP)
|
||||
* L3/L4 LB with haproxy - [Config file](https://gist.github.com/thpham/114d20de8472b2cef966)
|
||||
* Nginx coming soon
|
||||
* If need session stickiness - L7 LB with Envoy as proxy
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td markdown="1">
|
||||
|
||||
* Microservices - N clients, M servers in the data center
|
||||
* Very high performance requirements (low latency, high traffic)
|
||||
* Client can be untrusted
|
||||
</td>
|
||||
<td markdown="1">
|
||||
|
||||
* Look-aside Load Balancing
|
||||
* Client-side LB using [gRPC-LB protocol](https://github.com/grpc/grpc/blob/master/doc/load-balancing.md). Roll your own implementation (Q2’17), hosted gRPC-LB in the works.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td markdown="1">
|
||||
|
||||
* Existing Service-mesh like setup using Linkerd or Istio
|
||||
</td>
|
||||
<td markdown="1">
|
||||
|
||||
* Service Mesh
|
||||
* Use built-in LB with [Istio](https://istio.io/), or [Envoy](https://github.com/lyft/envoy).
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
The gRPC Meetup Kit – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>The gRPC Meetup Kit</h1>
|
||||
<h5>Posted on Thursday, September 14, 2017
|
||||
|
||||
|
||||
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>The meetup kit includes a 15 minute presentation on the basic concepts of gRPC, with accompanying <a href="https://docs.google.com/presentation/d/1dgI09a-_4dwBMLyqfwchvS6iXtbcISQPLAXL6gSYOcc/edit?usp=sharing">slides</a> and <a href="https://www.youtube.com/watch?v=UVsIfSfS6I4">video</a> for either reference or playback, as well as a <a href="https://codelabs.developers.google.com/codelabs/cloud-grpc/index.html">45 minute codelab</a> that takes you through the basics of gRPC in <a href="https://nodejs.org">Node.js</a> and <a href="https://golang.org/">Go</a>. At the end of the codelab participants will have a solid understanding of the fundamentals of gRPC.</p>
|
||||
<p>If you are thinking about running a gRPC event, make sure to contact us to receive <a href="https://goo.gl/forms/C3TCtFdobz4ippty2">gRPC stickers</a> and/or organise <a href="https://goo.gl/forms/pvxNwWExr5ApbNst2">office hours over Hangouts with the gRPC team</a>! </p>
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,500 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
So You Want to Optimize gRPC - Part 1 – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>So You Want to Optimize gRPC - Part 1</h1>
|
||||
<h5>Posted on Tuesday, March 06, 2018
|
||||
by
|
||||
|
||||
<a href="https://github.com/carl-mastrangelo">Carl Mastrangelo</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>A common question with gRPC is how to make it fast. The gRPC library offers users access to high
|
||||
performance RPCs, but it isn’t always clear how to achieve this. Because this question is common
|
||||
enough I thought I would try to show my thought process when tuning programs.</p>
|
||||
|
||||
<h2 id="setup">Setup</h2>
|
||||
|
||||
<p>Consider a basic key-value service that is used by multiple other programs. The service needs to
|
||||
be safe for concurrent access in case multiple updates happen at the same time. It needs to be
|
||||
able to scale up to use the available hardware. Lastly, it needs to be fast. gRPC is a perfect
|
||||
fit for this type of service; let’s look at the best way to implement it.</p>
|
||||
|
||||
<p>For this blog post, I have written an example
|
||||
<a href="https://github.com/carl-mastrangelo/kvstore">client and server</a> using gRPC Java. The program is
|
||||
split into three main classes, and a protobuf file describing the API:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://github.com/carl-mastrangelo/kvstore/blob/01-start/src/main/java/io/grpc/examples/KvClient.java">KvClient</a>
|
||||
is a simulated user of the key value system. It randomly creates, retrieves, updates,
|
||||
and deletes keys and values. The size of keys and values it uses is also randomly decided
|
||||
using an <a href="https://en.wikipedia.org/wiki/Exponential_distribution">exponential distribution</a>.</li>
|
||||
<li><a href="https://github.com/carl-mastrangelo/kvstore/blob/01-start/src/main/java/io/grpc/examples/KvService.java">KvService</a>
|
||||
is an implementation of the key value service. It is installed by the gRPC Server to handle
|
||||
the requests issued by the client. To simulate storing the keys and values on disk, it adds
|
||||
short sleeps while handling the request. Reads and writes will experience a 10 and 50
|
||||
millisecond delay to make the example act more like a persistent database.</li>
|
||||
<li><a href="https://github.com/carl-mastrangelo/kvstore/blob/01-start/src/main/java/io/grpc/examples/KvRunner.java">KvRunner</a>
|
||||
orchestrates the interaction between the client and the server. It is the main entry point,
|
||||
starting both the client and server in process, and waiting for the the client to execute its
|
||||
work. The runner does work for 60 seconds and then records how many RPCs were completed.</li>
|
||||
<li><a href="https://github.com/carl-mastrangelo/kvstore/blob/01-start/src/main/proto/kvstore.proto">kvstore.proto</a>
|
||||
is the protocol buffer definition of our service. It describes exactly what clients can expect
|
||||
from the service. For the sake of simplicity, we will use Create, Retrieve, Update, and Delete
|
||||
as the operations (commonly known as CRUD). These operations work with keys and values made up
|
||||
of arbitrary bytes. While they are somewhat REST like, we reserve the right to diverge and
|
||||
add more complex operations in the future.</li>
|
||||
</ul>
|
||||
|
||||
<p><a href="https://developers.google.com/protocol-buffers/">Protocol buffers(protos)</a> aren’t required to use
|
||||
gRPC, they are a very convenient way to define service interfaces and generate client and server
|
||||
code. The generated code acts as glue code between the application logic and the core gRPC
|
||||
library. We refer to the code called by a gRPC client the <em>stub</em>.</p>
|
||||
|
||||
<h2 id="starting-point">Starting Point</h2>
|
||||
|
||||
<h3 id="client">Client</h3>
|
||||
|
||||
<p>Now that we know what the program <em>should</em> do, we can start looking at how the program performs.
|
||||
As mentioned above, the client makes random RPCs. For example, here is the code that makes the
|
||||
<a href="https://github.com/carl-mastrangelo/kvstore/blob/f422b1b6e7c69f8c07f96ed4ddba64757242352c/src/main/java/io/grpc/examples/KvClient.java#L80">creation</a>
|
||||
request:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">doCreate</span><span style="color:#f92672">(</span>KeyValueServiceBlockingStub stub<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
ByteString key <span style="color:#f92672">=</span> createRandomKey<span style="color:#f92672">();</span>
|
||||
<span style="color:#66d9ef">try</span> <span style="color:#f92672">{</span>
|
||||
CreateResponse res <span style="color:#f92672">=</span> stub<span style="color:#f92672">.</span><span style="color:#a6e22e">create</span><span style="color:#f92672">(</span>
|
||||
CreateRequest<span style="color:#f92672">.</span><span style="color:#a6e22e">newBuilder</span><span style="color:#f92672">()</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">setKey</span><span style="color:#f92672">(</span>key<span style="color:#f92672">)</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">setValue</span><span style="color:#f92672">(</span>randomBytes<span style="color:#f92672">(</span>MEAN_VALUE_SIZE<span style="color:#f92672">))</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">build</span><span style="color:#f92672">());</span>
|
||||
<span style="color:#66d9ef">if</span> <span style="color:#f92672">(!</span>res<span style="color:#f92672">.</span><span style="color:#a6e22e">equals</span><span style="color:#f92672">(</span>CreateResponse<span style="color:#f92672">.</span><span style="color:#a6e22e">getDefaultInstance</span><span style="color:#f92672">()))</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> RuntimeException<span style="color:#f92672">(</span><span style="color:#e6db74">"Invalid response"</span><span style="color:#f92672">);</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span> <span style="color:#66d9ef">catch</span> <span style="color:#f92672">(</span>StatusRuntimeException e<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>e<span style="color:#f92672">.</span><span style="color:#a6e22e">getStatus</span><span style="color:#f92672">().</span><span style="color:#a6e22e">getCode</span><span style="color:#f92672">()</span> <span style="color:#f92672">==</span> Code<span style="color:#f92672">.</span><span style="color:#a6e22e">ALREADY_EXISTS</span><span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
knownKeys<span style="color:#f92672">.</span><span style="color:#a6e22e">remove</span><span style="color:#f92672">(</span>key<span style="color:#f92672">);</span>
|
||||
logger<span style="color:#f92672">.</span><span style="color:#a6e22e">log</span><span style="color:#f92672">(</span>Level<span style="color:#f92672">.</span><span style="color:#a6e22e">INFO</span><span style="color:#f92672">,</span> <span style="color:#e6db74">"Key already existed"</span><span style="color:#f92672">,</span> e<span style="color:#f92672">);</span>
|
||||
<span style="color:#f92672">}</span> <span style="color:#66d9ef">else</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">throw</span> e<span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>A random key is created, along with a random value. The request is sent to the server, and the
|
||||
client waits for the response. When the response is returned, the code checks that it is as
|
||||
expected, and if not, throws an exception. While the keys are chosen randomly, they need to be
|
||||
unique, so we need to make sure that each key isn’t already in use. To address this, the code
|
||||
keeps track of keys it has created, so as not to create the same key twice. However, it’s
|
||||
possible that another client already created a particular key, so we log it and move on.
|
||||
Otherwise, an exception is thrown.</p>
|
||||
|
||||
<p>We use the <strong>blocking</strong> gRPC API here, which issues a requests and waits for a response.
|
||||
This is the simplest gRPC stub, but it blocks the thread while running. This means that at most
|
||||
<strong>one</strong> RPC can be in progress at a time from the client’s point of view.</p>
|
||||
|
||||
<h3 id="server">Server</h3>
|
||||
|
||||
<p>On the server side, the request is received by the
|
||||
<a href="https://github.com/carl-mastrangelo/kvstore/blob/f422b1b6e7c69f8c07f96ed4ddba64757242352c/src/main/java/io/grpc/examples/KvService.java#L34">service handler</a>:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">final</span> Map<span style="color:#f92672"><</span>ByteBuffer<span style="color:#f92672">,</span> ByteBuffer<span style="color:#f92672">></span> store <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> HashMap<span style="color:#f92672"><>();</span>
|
||||
|
||||
<span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">synchronized</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">create</span><span style="color:#f92672">(</span>
|
||||
CreateRequest request<span style="color:#f92672">,</span> StreamObserver<span style="color:#f92672"><</span>CreateResponse<span style="color:#f92672">></span> responseObserver<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
ByteBuffer key <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getKey</span><span style="color:#f92672">().</span><span style="color:#a6e22e">asReadOnlyByteBuffer</span><span style="color:#f92672">();</span>
|
||||
ByteBuffer value <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getValue</span><span style="color:#f92672">().</span><span style="color:#a6e22e">asReadOnlyByteBuffer</span><span style="color:#f92672">();</span>
|
||||
simulateWork<span style="color:#f92672">(</span>WRITE_DELAY_MILLIS<span style="color:#f92672">);</span>
|
||||
<span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>store<span style="color:#f92672">.</span><span style="color:#a6e22e">putIfAbsent</span><span style="color:#f92672">(</span>key<span style="color:#f92672">,</span> value<span style="color:#f92672">)</span> <span style="color:#f92672">==</span> <span style="color:#66d9ef">null</span><span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onNext</span><span style="color:#f92672">(</span>CreateResponse<span style="color:#f92672">.</span><span style="color:#a6e22e">getDefaultInstance</span><span style="color:#f92672">());</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onCompleted</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#66d9ef">return</span><span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onError</span><span style="color:#f92672">(</span>Status<span style="color:#f92672">.</span><span style="color:#a6e22e">ALREADY_EXISTS</span><span style="color:#f92672">.</span><span style="color:#a6e22e">asRuntimeException</span><span style="color:#f92672">());</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>The service extracts the key and value as <code>ByteBuffer</code>s from the request. It acquires the lock
|
||||
on the service itself to make sure concurrent requests don’t corrupt the storage. After
|
||||
simulating the disk access of a write, it stores it in the <code>Map</code> of keys to values.</p>
|
||||
|
||||
<p>Unlike the client code, the service handler is <strong>non-blocking</strong>, meaning it doesn’t return a
|
||||
value like a function call would. Instead, it invokes <code>onNext()</code> on the <code>responseObserver</code> to
|
||||
send the response back to the client. Note that this call is also non-blocking, meaning that
|
||||
the message may not yet have been sent. To indicate we are done with the message, <code>onCompleted()</code>
|
||||
is called.</p>
|
||||
|
||||
<h3 id="performance">Performance</h3>
|
||||
|
||||
<p>Since the code is safe and correct, let’s see how it performs. For my measurement I’m using my
|
||||
Ubuntu system with a 12 core processor and 32 GB of memory. Let’s build and run the code:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ ./gradlew installDist
|
||||
$ time ./build/install/kvstore/bin/kvstore
|
||||
Feb <span style="color:#ae81ff">26</span>, <span style="color:#ae81ff">2018</span> <span style="color:#ae81ff">1</span>:10:07 PM io.grpc.examples.KvRunner runClient
|
||||
INFO: Starting
|
||||
Feb <span style="color:#ae81ff">26</span>, <span style="color:#ae81ff">2018</span> <span style="color:#ae81ff">1</span>:11:07 PM io.grpc.examples.KvRunner runClient
|
||||
INFO: Did <span style="color:#ae81ff">16</span>.55 RPCs/s
|
||||
|
||||
real 1m0.927s
|
||||
user 0m10.688s
|
||||
sys 0m1.456s</code></pre></div>
|
||||
<p>Yikes! For such a powerful machine, it can only do about 16 RPCs per second. It hardly used any
|
||||
of our CPU, and we don’t know how much memory it was using. We need to figure out why it’s so
|
||||
slow.</p>
|
||||
|
||||
<h2 id="optimization">Optimization</h2>
|
||||
|
||||
<h3 id="analysis">Analysis</h3>
|
||||
|
||||
<p>Let’s understand what the program is doing before we make any changes. When optimizing, we need
|
||||
to know where the code is spending its time in order to know what we can optimize. At this early
|
||||
stage, we don’t need profiling tools yet, we can just reason about the program.</p>
|
||||
|
||||
<p>The client is started and serially issues RPCs for about a minute. Each iteration, it <a href="https://github.com/carl-mastrangelo/kvstore/blob/f422b1b6e7c69f8c07f96ed4ddba64757242352c/src/main/java/io/grpc/examples/KvClient.java#L49">randomly
|
||||
decides</a>
|
||||
what operation to do:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">doClientWork</span><span style="color:#f92672">(</span>AtomicBoolean done<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
Random random <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Random<span style="color:#f92672">();</span>
|
||||
KeyValueServiceBlockingStub stub <span style="color:#f92672">=</span> KeyValueServiceGrpc<span style="color:#f92672">.</span><span style="color:#a6e22e">newBlockingStub</span><span style="color:#f92672">(</span>channel<span style="color:#f92672">);</span>
|
||||
|
||||
<span style="color:#66d9ef">while</span> <span style="color:#f92672">(!</span>done<span style="color:#f92672">.</span><span style="color:#a6e22e">get</span><span style="color:#f92672">())</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#75715e">// Pick a random CRUD action to take.
|
||||
</span><span style="color:#75715e"></span> <span style="color:#66d9ef">int</span> command <span style="color:#f92672">=</span> random<span style="color:#f92672">.</span><span style="color:#a6e22e">nextInt</span><span style="color:#f92672">(</span>4<span style="color:#f92672">);</span>
|
||||
<span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>command <span style="color:#f92672">==</span> 0<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
doCreate<span style="color:#f92672">(</span>stub<span style="color:#f92672">);</span>
|
||||
<span style="color:#66d9ef">continue</span><span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#75715e">/* ... */</span>
|
||||
rpcCount<span style="color:#f92672">++;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>This means that <strong>at most one RPC can be active at any time</strong>. Each RPC has to wait for the
|
||||
previous one to complete. And how long does each RPC take to complete? From reading the server
|
||||
code, most of the operations are doing a write which takes about 50 milliseconds. At top
|
||||
efficiency, the most operations this code can do per second is about 20:</p>
|
||||
|
||||
<p>20 queries = 1000ms / (50 ms / query)</p>
|
||||
|
||||
<p>Our code can do about 16 queries in a second, so that seems about right. We can spot check this
|
||||
assumption by looking at the output of the <code>time</code> command used to run the code. The server goes
|
||||
to sleep when running queries in the
|
||||
<a href="https://github.com/carl-mastrangelo/kvstore/blob/f422b1b6e7c69f8c07f96ed4ddba64757242352c/src/main/java/io/grpc/examples/KvService.java#L88"><code>simulateWork</code></a>
|
||||
method. This implies that the program should be mostly idle while waiting for the RPCs to
|
||||
complete.</p>
|
||||
|
||||
<p>We can confirm this is the case by looking at the <code>real</code> and <code>user</code> times of the command above.
|
||||
They say that the amount of <em>wall clock</em> time was 1 minute, while the amount of <em>cpu</em> time
|
||||
was 10 seconds. My powerful, multicore CPU was only busy 16% of the time. Thus, if we could
|
||||
get the program to do more work during that time, it seems like we could get more RPCs complete.</p>
|
||||
|
||||
<h3 id="hypothesis">Hypothesis</h3>
|
||||
|
||||
<p>Now we can state clearly what we think is the problem, and propose a solution. One way to speed
|
||||
up programs is to make sure the CPU is not idling. To do this, we issue work concurrently.</p>
|
||||
|
||||
<p>In gRPC Java, there are three types of stubs: blocking, non-blocking, and listenable future. We
|
||||
have already seen the blocking stub in the client, and the non-blocking stub in the server. The
|
||||
listenable future API is a compromise between the two, offering both blocking and non-blocking
|
||||
like behavior. As long as we don’t block a thread waiting for work to complete, we can start
|
||||
new RPCs without waiting for the old ones to complete.</p>
|
||||
|
||||
<h3 id="experiment">Experiment</h3>
|
||||
|
||||
<p>To test our hypothesis, let’s modify the client code to use the listenable future API. This
|
||||
means that we need to think more about concurrency in our code. For example, when keeping track
|
||||
of known keys client-side, we need to safely read, modify, and write the keys. We also need to
|
||||
make sure that in case of an error, we stop making new RPCs (proper error handling will be covered
|
||||
in a future post). Lastly, we need to update the number of RPCs made concurrently, since the
|
||||
update could happen in another thread.</p>
|
||||
|
||||
<p>Making all these changes increases the complexity of the code. This is a trade off you will need
|
||||
to consider when optimizing your code. In general, code simplicity is at odds with optimization.
|
||||
Java is not known for being terse. That said, the code below is still readable, and program flow
|
||||
is still roughly from top to bottom in the function. Here is the
|
||||
<a href="https://github.com/carl-mastrangelo/kvstore/blob/f0113912c01ac4ea48a80bb7a4736ddcb3f21e24/src/main/java/io/grpc/examples/KvClient.java#L92"><code>doCreate()</code></a>
|
||||
method revised:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">doCreate</span><span style="color:#f92672">(</span>KeyValueServiceFutureStub stub<span style="color:#f92672">,</span> AtomicReference<span style="color:#f92672"><</span>Throwable<span style="color:#f92672">></span> error<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
ByteString key <span style="color:#f92672">=</span> createRandomKey<span style="color:#f92672">();</span>
|
||||
ListenableFuture<span style="color:#f92672"><</span>CreateResponse<span style="color:#f92672">></span> res <span style="color:#f92672">=</span> stub<span style="color:#f92672">.</span><span style="color:#a6e22e">create</span><span style="color:#f92672">(</span>
|
||||
CreateRequest<span style="color:#f92672">.</span><span style="color:#a6e22e">newBuilder</span><span style="color:#f92672">()</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">setKey</span><span style="color:#f92672">(</span>key<span style="color:#f92672">)</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">setValue</span><span style="color:#f92672">(</span>randomBytes<span style="color:#f92672">(</span>MEAN_VALUE_SIZE<span style="color:#f92672">))</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">build</span><span style="color:#f92672">());</span>
|
||||
res<span style="color:#f92672">.</span><span style="color:#a6e22e">addListener</span><span style="color:#f92672">(()</span> <span style="color:#f92672">-></span> rpcCount<span style="color:#f92672">.</span><span style="color:#a6e22e">incrementAndGet</span><span style="color:#f92672">(),</span> MoreExecutors<span style="color:#f92672">.</span><span style="color:#a6e22e">directExecutor</span><span style="color:#f92672">());</span>
|
||||
Futures<span style="color:#f92672">.</span><span style="color:#a6e22e">addCallback</span><span style="color:#f92672">(</span>res<span style="color:#f92672">,</span> <span style="color:#66d9ef">new</span> FutureCallback<span style="color:#f92672"><</span>CreateResponse<span style="color:#f92672">>()</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">onSuccess</span><span style="color:#f92672">(</span>CreateResponse result<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">if</span> <span style="color:#f92672">(!</span>result<span style="color:#f92672">.</span><span style="color:#a6e22e">equals</span><span style="color:#f92672">(</span>CreateResponse<span style="color:#f92672">.</span><span style="color:#a6e22e">getDefaultInstance</span><span style="color:#f92672">()))</span> <span style="color:#f92672">{</span>
|
||||
error<span style="color:#f92672">.</span><span style="color:#a6e22e">compareAndSet</span><span style="color:#f92672">(</span><span style="color:#66d9ef">null</span><span style="color:#f92672">,</span> <span style="color:#66d9ef">new</span> RuntimeException<span style="color:#f92672">(</span><span style="color:#e6db74">"Invalid response"</span><span style="color:#f92672">));</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#66d9ef">synchronized</span> <span style="color:#f92672">(</span>knownKeys<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
knownKeys<span style="color:#f92672">.</span><span style="color:#a6e22e">add</span><span style="color:#f92672">(</span>key<span style="color:#f92672">);</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
|
||||
<span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">onFailure</span><span style="color:#f92672">(</span>Throwable t<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
Status status <span style="color:#f92672">=</span> Status<span style="color:#f92672">.</span><span style="color:#a6e22e">fromThrowable</span><span style="color:#f92672">(</span>t<span style="color:#f92672">);</span>
|
||||
<span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>status<span style="color:#f92672">.</span><span style="color:#a6e22e">getCode</span><span style="color:#f92672">()</span> <span style="color:#f92672">==</span> Code<span style="color:#f92672">.</span><span style="color:#a6e22e">ALREADY_EXISTS</span><span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#66d9ef">synchronized</span> <span style="color:#f92672">(</span>knownKeys<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
knownKeys<span style="color:#f92672">.</span><span style="color:#a6e22e">remove</span><span style="color:#f92672">(</span>key<span style="color:#f92672">);</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
logger<span style="color:#f92672">.</span><span style="color:#a6e22e">log</span><span style="color:#f92672">(</span>Level<span style="color:#f92672">.</span><span style="color:#a6e22e">INFO</span><span style="color:#f92672">,</span> <span style="color:#e6db74">"Key already existed"</span><span style="color:#f92672">,</span> t<span style="color:#f92672">);</span>
|
||||
<span style="color:#f92672">}</span> <span style="color:#66d9ef">else</span> <span style="color:#f92672">{</span>
|
||||
error<span style="color:#f92672">.</span><span style="color:#a6e22e">compareAndSet</span><span style="color:#f92672">(</span><span style="color:#66d9ef">null</span><span style="color:#f92672">,</span> t<span style="color:#f92672">);</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">});</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>The stub has been modified to be a <code>KeyValueServiceFutureStub</code>, which produces a <code>Future</code> when
|
||||
called instead of the response itself. gRPC Java uses an extension of this called <code>ListenableFuture</code>,
|
||||
which allows adding a callback when the future completes. For the sake of this program, we are
|
||||
not as concerned with getting the response. Instead we care more if the RPC succeeded or not.
|
||||
With that in mind, the code mainly checks for errors rather than processing the response.</p>
|
||||
|
||||
<p>The first change made is how the number of RPCs is recorded. Instead of incrementing the counter
|
||||
outside of the main loop, we increment it when the RPC completes.</p>
|
||||
|
||||
<p>Next, we create a new object
|
||||
for each RPC which handles both the success and failure cases. Because <code>doCreate()</code> will already
|
||||
be completed by the time RPC callback is invoked, we need a way to propagate errors other than
|
||||
by throwing. Instead, we try to update an reference atomically. The main loop will occasionally
|
||||
check if an error has occurred and stop if there is a problem.</p>
|
||||
|
||||
<p>Lastly, the code is careful to only add a key to <code>knownKeys</code> when the RPC is actually complete,
|
||||
and only remove it when known to have failed. We synchronize on the variable to make sure two
|
||||
threads don’t conflict. Note: although the access to <code>knownKeys</code> is threadsafe, there are still
|
||||
<a href="https://en.wikipedia.org/wiki/Race_condition">race conditions</a>. It is possible that one thread
|
||||
could read from <code>knownKeys</code>, a second thread delete from <code>knownKeys</code>, and then the first thread
|
||||
issue an RPC using the first key. Synchronizing on the keys only ensures that it is consistent,
|
||||
not that it is correct. Fixing this properly is outside of the scope of this post, so instead we
|
||||
just log the event and move on. You will see a few such log statements if you run this program.</p>
|
||||
|
||||
<h3 id="running-the-code">Running the Code</h3>
|
||||
|
||||
<p>If you start up this program and run it, you’ll notice that it doesn’t work:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">WARNING: An exception was thrown by io.grpc.netty.NettyClientStream$Sink$1.operationComplete<span style="color:#f92672">()</span>
|
||||
java.lang.OutOfMemoryError: unable to create new native thread
|
||||
at java.lang.Thread.start0<span style="color:#f92672">(</span>Native Method<span style="color:#f92672">)</span>
|
||||
at java.lang.Thread.start<span style="color:#f92672">(</span>Thread.java:714<span style="color:#f92672">)</span>
|
||||
...</code></pre></div>
|
||||
<p>What?! Why would I show you code that fails? The reason is that in real life making a change often
|
||||
doesn’t work on the first try. In this case, the program ran out of memory. Odd things begin to
|
||||
happen when a program runs out of memory. Often, the root cause is hard to find, and red herrings
|
||||
abound. A confusing error message says</p>
|
||||
|
||||
<blockquote>
|
||||
<p>unable to create new native thread</p>
|
||||
</blockquote>
|
||||
|
||||
<p>even though we didn’t create any new threads in our code. Experience is very helpful in fixing
|
||||
these problems rather than debugging. Since I have debugged many OOMs, I happen to know Java tells
|
||||
us about the straw that broke the camel’s back. Our program started using way more memory, but the
|
||||
final allocation that failed happened, by chance, to be in thread creation.</p>
|
||||
|
||||
<p>So what happened? <em>There was no pushback to starting new RPCs.</em> In the blocking version, a new
|
||||
RPC couldn’t start until the last one completed. While slow, it also prevented us from creating
|
||||
tons of RPCs that we didn’t have memory for. We need to account for this in the listenable
|
||||
future version.</p>
|
||||
|
||||
<p>To solve this, we can apply a self-imposed limit on the number of active RPCs. Before starting a
|
||||
new RPC, we will try to acquire a permit. If we get one, the RPC can start. If not, we will wait
|
||||
until one is available. When an RPC completes (either in success or failure), we return the
|
||||
permit. To <a href="https://github.com/carl-mastrangelo/kvstore/blob/02-future-client/src/main/java/io/grpc/examples/KvClient.java#L94">accomplish</a>
|
||||
this, we will using a <code>Semaphore</code>:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">final</span> Semaphore limiter <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Semaphore<span style="color:#f92672">(</span>100<span style="color:#f92672">);</span>
|
||||
|
||||
<span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">doCreate</span><span style="color:#f92672">(</span>KeyValueServiceFutureStub stub<span style="color:#f92672">,</span> AtomicReference<span style="color:#f92672"><</span>Throwable<span style="color:#f92672">></span> error<span style="color:#f92672">)</span>
|
||||
<span style="color:#66d9ef">throws</span> InterruptedException <span style="color:#f92672">{</span>
|
||||
limiter<span style="color:#f92672">.</span><span style="color:#a6e22e">acquire</span><span style="color:#f92672">();</span>
|
||||
ByteString key <span style="color:#f92672">=</span> createRandomKey<span style="color:#f92672">();</span>
|
||||
ListenableFuture<span style="color:#f92672"><</span>CreateResponse<span style="color:#f92672">></span> res <span style="color:#f92672">=</span> stub<span style="color:#f92672">.</span><span style="color:#a6e22e">create</span><span style="color:#f92672">(</span>
|
||||
CreateRequest<span style="color:#f92672">.</span><span style="color:#a6e22e">newBuilder</span><span style="color:#f92672">()</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">setKey</span><span style="color:#f92672">(</span>key<span style="color:#f92672">)</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">setValue</span><span style="color:#f92672">(</span>randomBytes<span style="color:#f92672">(</span>MEAN_VALUE_SIZE<span style="color:#f92672">))</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">build</span><span style="color:#f92672">());</span>
|
||||
res<span style="color:#f92672">.</span><span style="color:#a6e22e">addListener</span><span style="color:#f92672">(()</span> <span style="color:#f92672">-></span> <span style="color:#f92672">{</span>
|
||||
rpcCount<span style="color:#f92672">.</span><span style="color:#a6e22e">incrementAndGet</span><span style="color:#f92672">();</span>
|
||||
limiter<span style="color:#f92672">.</span><span style="color:#a6e22e">release</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#f92672">},</span> MoreExecutors<span style="color:#f92672">.</span><span style="color:#a6e22e">directExecutor</span><span style="color:#f92672">());</span>
|
||||
<span style="color:#75715e">/* ... */</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>Now the code runs successfully, and doesn’t run out of memory.</p>
|
||||
|
||||
<h3 id="results">Results</h3>
|
||||
|
||||
<p>Building and running the code again looks a lot better:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ ./gradlew installDist
|
||||
$ time ./build/install/kvstore/bin/kvstore
|
||||
Feb <span style="color:#ae81ff">26</span>, <span style="color:#ae81ff">2018</span> <span style="color:#ae81ff">2</span>:40:47 PM io.grpc.examples.KvRunner runClient
|
||||
INFO: Starting
|
||||
Feb <span style="color:#ae81ff">26</span>, <span style="color:#ae81ff">2018</span> <span style="color:#ae81ff">2</span>:41:47 PM io.grpc.examples.KvRunner runClient
|
||||
INFO: Did <span style="color:#ae81ff">24</span>.283 RPCs/s
|
||||
|
||||
real 1m0.923s
|
||||
user 0m12.772s
|
||||
sys 0m1.572s</code></pre></div>
|
||||
<p>Our code does <strong>46%</strong> more RPCs per second than previously. We can also see that we used about 20%
|
||||
more CPU than previously. As we can see our hypothesis turned out to be correct and the fix
|
||||
worked. All this happened without making any changes to the server. Also, we were able to
|
||||
measure without using any special profilers or tracers.</p>
|
||||
|
||||
<p>Do the numbers make sense? We expect to issue mutation (create, update, and delete) RPCs each
|
||||
about with <sup>1</sup>⁄<sub>4</sub> probability. Reads are also issue <sup>1</sup>⁄<sub>4</sub> of the time, but don’t take as long. The
|
||||
mean RPC time should be about the weighted average RPC time:</p>
|
||||
|
||||
<pre><code> .25 * 50ms (create)
|
||||
.25 * 10ms (retrieve)
|
||||
.25 * 50ms (update)
|
||||
+.25 * 50ms (delete)
|
||||
------------
|
||||
40ms
|
||||
</code></pre>
|
||||
|
||||
<p>At 40ms on average per RPC, we would expect the number of RPCs per second to be:</p>
|
||||
|
||||
<p>25 queries = 1000ms / (40 ms / query)</p>
|
||||
|
||||
<p>That’s approximately what we see with the new code. The server is still serially handling
|
||||
requests, so it seems like we have more work to do in the future. But for now, our optimizations
|
||||
seem to have worked.</p>
|
||||
|
||||
<h2 id="conclusion">Conclusion</h2>
|
||||
|
||||
<p>There are a lot of opportunities to optimize your gRPC code. To take advantage of these, you
|
||||
need to understand what your code is doing, and what your code is supposed to do. This post shows
|
||||
the very basics of how to approach and think about optimization. Always make sure to measure
|
||||
before and after your changes, and use these measurements to guide your optimizations.</p>
|
||||
|
||||
<p>In <a href="/blog/optimizing-grpc-part-2">Part 2</a>, we will continue optimizing the server part of the code.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,337 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
So You Want to Optimize gRPC - Part 2 – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>So You Want to Optimize gRPC - Part 2</h1>
|
||||
<h5>Posted on Monday, April 16, 2018
|
||||
by
|
||||
|
||||
<a href="https://carlmastrangelo.com/">Carl Mastrangelo</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>How fast is gRPC? Pretty fast if you understand how modern clients and servers are built. In
|
||||
<a href="/blog/optimizing-grpc-part-1">part 1</a>, I showed how to get an easy <strong>60%</strong> improvement. In this
|
||||
post I show how to get a <strong>10000%</strong> improvement.</p>
|
||||
|
||||
<h2 id="setup">Setup</h2>
|
||||
|
||||
<p>As in <a href="/blog/optimizing-grpc-part-1">part 1</a>, we will start with an existing, Java based,
|
||||
key-value service. The service will offer concurrent access for creating, reading, updating,
|
||||
and deleting keys and values. All the code can be seen
|
||||
<a href="https://github.com/carl-mastrangelo/kvstore/tree/03-nonblocking-server">here</a> if you want to try
|
||||
it out.</p>
|
||||
|
||||
<h2 id="server-concurrency">Server Concurrency</h2>
|
||||
|
||||
<p>Let’s look at the <a href="https://github.com/carl-mastrangelo/kvstore/blob/f422b1b6e7c69f8c07f96ed4ddba64757242352c/src/main/java/io/grpc/examples/KvService.java">KvService</a>
|
||||
class. This service handles the RPCs sent by the client, making sure that none of them
|
||||
accidentally corrupt the state of storage. To ensure this, the service uses the <code>synchronized</code>
|
||||
keyword to ensure only one RPC is active at a time:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">final</span> Map<span style="color:#f92672"><</span>ByteBuffer<span style="color:#f92672">,</span> ByteBuffer<span style="color:#f92672">></span> store <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> HashMap<span style="color:#f92672"><>();</span>
|
||||
|
||||
<span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">synchronized</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">create</span><span style="color:#f92672">(</span>
|
||||
CreateRequest request<span style="color:#f92672">,</span> StreamObserver<span style="color:#f92672"><</span>CreateResponse<span style="color:#f92672">></span> responseObserver<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
ByteBuffer key <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getKey</span><span style="color:#f92672">().</span><span style="color:#a6e22e">asReadOnlyByteBuffer</span><span style="color:#f92672">();</span>
|
||||
ByteBuffer value <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getValue</span><span style="color:#f92672">().</span><span style="color:#a6e22e">asReadOnlyByteBuffer</span><span style="color:#f92672">();</span>
|
||||
simulateWork<span style="color:#f92672">(</span>WRITE_DELAY_MILLIS<span style="color:#f92672">);</span>
|
||||
<span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>store<span style="color:#f92672">.</span><span style="color:#a6e22e">putIfAbsent</span><span style="color:#f92672">(</span>key<span style="color:#f92672">,</span> value<span style="color:#f92672">)</span> <span style="color:#f92672">==</span> <span style="color:#66d9ef">null</span><span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onNext</span><span style="color:#f92672">(</span>CreateResponse<span style="color:#f92672">.</span><span style="color:#a6e22e">getDefaultInstance</span><span style="color:#f92672">());</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onCompleted</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#66d9ef">return</span><span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onError</span><span style="color:#f92672">(</span>Status<span style="color:#f92672">.</span><span style="color:#a6e22e">ALREADY_EXISTS</span><span style="color:#f92672">.</span><span style="color:#a6e22e">asRuntimeException</span><span style="color:#f92672">());</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>While this code is thread safe, it comes at a high price: only one RPC can ever be active! We
|
||||
need some way of allowing multiple operations to happen safely at the same time. Otherwise,
|
||||
the program can’t take advantage of all the available processors.</p>
|
||||
|
||||
<h3 id="breaking-the-lock">Breaking the Lock</h3>
|
||||
|
||||
<p>To solve this, we need to know a little more about the <em>semantics</em> of our RPCs. The more we know
|
||||
about how the RPCs are supposed to work, the more optimizations we can make. For a key-value
|
||||
service, we notice that <em>operations to different keys don’t interfere with each other</em>. When
|
||||
we update key ‘foo’, it has no bearing on the value stored for key ‘bar’. But, our server is
|
||||
written such that operations to any key must be synchronized with respect to each other. If we
|
||||
could make operations to different keys happen concurrently, our server could handle a lot more
|
||||
load.</p>
|
||||
|
||||
<p>With the idea in place, we need to figure out how to modify the server. The
|
||||
<code>synchronized</code> keyword causes Java to acquire a lock on <code>this</code>, which is the instance of
|
||||
<code>KvService</code>. The lock is acquired when the <code>create</code> method is entered, and released on return.
|
||||
The reason we need synchronization is to protect the <code>store</code> Map. Since it is implemented as a
|
||||
<a href="https://en.wikipedia.org/wiki/Hash_table"><code>HashMap</code></a>, modifications to it change the internal
|
||||
arrays. Because the internal state of the <code>HashMap</code> will be corrupted if not properly
|
||||
synchronized, we can’t just remove the synchronization on the method.</p>
|
||||
|
||||
<p>However, Java offers a solution here: <code>ConcurrentHashMap</code>. This class offers the ability to
|
||||
safely access the contents of the map concurrently. For example, in our usage we want to check
|
||||
if a key is present. If not present, we want to add it, else we want to return an error. The
|
||||
<code>putIfAbsent</code> method atomically checks if a value is present, adds it if not, and tells us if
|
||||
it succeeded.</p>
|
||||
|
||||
<p>Concurrent maps provide stronger guarantees about the safety of <code>putIfAbsent</code>, so we can swap the
|
||||
<code>HashMap</code> to a <code>ConcurrentHashMap</code> and remove <code>synchronized</code>:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">final</span> ConcurrentMap<span style="color:#f92672"><</span>ByteBuffer<span style="color:#f92672">,</span> ByteBuffer<span style="color:#f92672">></span> store <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ConcurrentHashMap<span style="color:#f92672"><>();</span>
|
||||
|
||||
<span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">create</span><span style="color:#f92672">(</span>
|
||||
CreateRequest request<span style="color:#f92672">,</span> StreamObserver<span style="color:#f92672"><</span>CreateResponse<span style="color:#f92672">></span> responseObserver<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
ByteBuffer key <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getKey</span><span style="color:#f92672">().</span><span style="color:#a6e22e">asReadOnlyByteBuffer</span><span style="color:#f92672">();</span>
|
||||
ByteBuffer value <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getValue</span><span style="color:#f92672">().</span><span style="color:#a6e22e">asReadOnlyByteBuffer</span><span style="color:#f92672">();</span>
|
||||
simulateWork<span style="color:#f92672">(</span>WRITE_DELAY_MILLIS<span style="color:#f92672">);</span>
|
||||
<span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>store<span style="color:#f92672">.</span><span style="color:#a6e22e">putIfAbsent</span><span style="color:#f92672">(</span>key<span style="color:#f92672">,</span> value<span style="color:#f92672">)</span> <span style="color:#f92672">==</span> <span style="color:#66d9ef">null</span><span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onNext</span><span style="color:#f92672">(</span>CreateResponse<span style="color:#f92672">.</span><span style="color:#a6e22e">getDefaultInstance</span><span style="color:#f92672">());</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onCompleted</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#66d9ef">return</span><span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onError</span><span style="color:#f92672">(</span>Status<span style="color:#f92672">.</span><span style="color:#a6e22e">ALREADY_EXISTS</span><span style="color:#f92672">.</span><span style="color:#a6e22e">asRuntimeException</span><span style="color:#f92672">());</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<h3 id="if-at-first-you-don-t-succeed">If at First You Don’t Succeed</h3>
|
||||
|
||||
<p>Updating <code>create</code> was pretty easy. Doing the same for <code>retrieve</code> and <code>delete</code> is easy too.
|
||||
However, the <code>update</code> method is a little trickier. Let’s take a look at what it’s doing:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">synchronized</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">update</span><span style="color:#f92672">(</span>
|
||||
UpdateRequest request<span style="color:#f92672">,</span> StreamObserver<span style="color:#f92672"><</span>UpdateResponse<span style="color:#f92672">></span> responseObserver<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
ByteBuffer key <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getKey</span><span style="color:#f92672">().</span><span style="color:#a6e22e">asReadOnlyByteBuffer</span><span style="color:#f92672">();</span>
|
||||
ByteBuffer newValue <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getValue</span><span style="color:#f92672">().</span><span style="color:#a6e22e">asReadOnlyByteBuffer</span><span style="color:#f92672">();</span>
|
||||
simulateWork<span style="color:#f92672">(</span>WRITE_DELAY_MILLIS<span style="color:#f92672">);</span>
|
||||
ByteBuffer oldValue <span style="color:#f92672">=</span> store<span style="color:#f92672">.</span><span style="color:#a6e22e">get</span><span style="color:#f92672">(</span>key<span style="color:#f92672">);</span>
|
||||
<span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>oldValue <span style="color:#f92672">==</span> <span style="color:#66d9ef">null</span><span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onError</span><span style="color:#f92672">(</span>Status<span style="color:#f92672">.</span><span style="color:#a6e22e">NOT_FOUND</span><span style="color:#f92672">.</span><span style="color:#a6e22e">asRuntimeException</span><span style="color:#f92672">());</span>
|
||||
<span style="color:#66d9ef">return</span><span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
store<span style="color:#f92672">.</span><span style="color:#a6e22e">replace</span><span style="color:#f92672">(</span>key<span style="color:#f92672">,</span> oldValue<span style="color:#f92672">,</span> newValue<span style="color:#f92672">);</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onNext</span><span style="color:#f92672">(</span>UpdateResponse<span style="color:#f92672">.</span><span style="color:#a6e22e">getDefaultInstance</span><span style="color:#f92672">());</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onCompleted</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>Updating a key to a new value needs two interactions with the <code>store</code>:</p>
|
||||
|
||||
<ol>
|
||||
<li>Check to see if the key exists at all.</li>
|
||||
<li>Update the previous value to the new value.</li>
|
||||
</ol>
|
||||
|
||||
<p>Unfortunately <code>ConcurrentMap</code> doesn’t have a straightforward method to do this. Since we may not
|
||||
be the only ones modifying the map, we need to handle the possibility that our assumptions
|
||||
have changed. We read the old value out, but by the time we replace it, it may have been deleted.</p>
|
||||
|
||||
<p>To reconcile this, let’s retry if <code>replace</code> fails. It returns true if the replace
|
||||
was successful. (<code>ConcurrentMap</code> asserts that the operations will not corrupt the internal
|
||||
structure, but doesn’t say that they will succeed!) We will use a do-while loop:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"> <span style="color:#a6e22e">@Override</span>
|
||||
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">update</span><span style="color:#f92672">(</span>
|
||||
UpdateRequest request<span style="color:#f92672">,</span> StreamObserver<span style="color:#f92672"><</span>UpdateResponse<span style="color:#f92672">></span> responseObserver<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
<span style="color:#75715e">// ...
|
||||
</span><span style="color:#75715e"></span> ByteBuffer oldValue<span style="color:#f92672">;</span>
|
||||
<span style="color:#66d9ef">do</span> <span style="color:#f92672">{</span>
|
||||
oldValue <span style="color:#f92672">=</span> store<span style="color:#f92672">.</span><span style="color:#a6e22e">get</span><span style="color:#f92672">(</span>key<span style="color:#f92672">);</span>
|
||||
<span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>oldValue <span style="color:#f92672">==</span> <span style="color:#66d9ef">null</span><span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onError</span><span style="color:#f92672">(</span>Status<span style="color:#f92672">.</span><span style="color:#a6e22e">NOT_FOUND</span><span style="color:#f92672">.</span><span style="color:#a6e22e">asRuntimeException</span><span style="color:#f92672">());</span>
|
||||
<span style="color:#66d9ef">return</span><span style="color:#f92672">;</span>
|
||||
<span style="color:#f92672">}</span>
|
||||
<span style="color:#f92672">}</span> <span style="color:#66d9ef">while</span> <span style="color:#f92672">(!</span>store<span style="color:#f92672">.</span><span style="color:#a6e22e">replace</span><span style="color:#f92672">(</span>key<span style="color:#f92672">,</span> oldValue<span style="color:#f92672">,</span> newValue<span style="color:#f92672">));</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onNext</span><span style="color:#f92672">(</span>UpdateResponse<span style="color:#f92672">.</span><span style="color:#a6e22e">getDefaultInstance</span><span style="color:#f92672">());</span>
|
||||
responseObserver<span style="color:#f92672">.</span><span style="color:#a6e22e">onCompleted</span><span style="color:#f92672">();</span>
|
||||
<span style="color:#f92672">}</span></code></pre></div>
|
||||
<p>The code wants to fail if it ever sees null, but never if there is a non-null previous value. One
|
||||
thing to note is that if <em>another</em> RPC modifies the value between the <code>store.get()</code> call and the
|
||||
<code>store.replace()</code> call, it will fail. This is a non-fatal error for us, so we will just try again.
|
||||
Once it has successfully put the new value in, the service can respond back to the user.</p>
|
||||
|
||||
<p>There is one other possibility that could happen: two RPCs could update the same value and
|
||||
overwrite each other’s work. While this may be okay for some applications, it would not be
|
||||
suitable for APIs that provide transactionality. It is out of scope for this post to show how to
|
||||
fix this, but be aware it can happen.</p>
|
||||
|
||||
<h2 id="measuring-the-performance">Measuring the Performance</h2>
|
||||
|
||||
<p>In the last post, we modified the client to be asynchronous and use the gRPC ListenableFuture API.
|
||||
To avoid running out of memory, the client was modified to have at most <strong>100</strong> active RPCs at a
|
||||
time. As we now see from the server code, performance was bottlenecked on acquiring locks.
|
||||
Since we have removed those, we expect to see a 100x improvement. The same amount of work is done
|
||||
per RPC, but a lot more are happening at the same time. Let’s see if our hypothesis holds:</p>
|
||||
|
||||
<p>Before:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ ./gradlew installDist
|
||||
$ time ./build/install/kvstore/bin/kvstore
|
||||
Apr <span style="color:#ae81ff">16</span>, <span style="color:#ae81ff">2018</span> <span style="color:#ae81ff">10</span>:38:42 AM io.grpc.examples.KvRunner runClient
|
||||
INFO: Did <span style="color:#ae81ff">24</span>.067 RPCs/s
|
||||
|
||||
real 1m0.886s
|
||||
user 0m9.340s
|
||||
sys 0m1.660s</code></pre></div>
|
||||
<p>After:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">Apr <span style="color:#ae81ff">16</span>, <span style="color:#ae81ff">2018</span> <span style="color:#ae81ff">10</span>:36:48 AM io.grpc.examples.KvRunner runClient
|
||||
INFO: Did <span style="color:#ae81ff">2</span>,449.8 RPCs/s
|
||||
|
||||
real 1m0.968s
|
||||
user 0m52.184s
|
||||
sys 0m20.692s</code></pre></div>
|
||||
<p>Wow! From 24 RPCs per second to 2,400 RPCs per second. And we didn’t have to change our API or
|
||||
our client. This is why understanding your code and API semantics is important. By exploiting the
|
||||
properties of the key-value API, namely the independence of operations on different keys, the code
|
||||
is now much faster.</p>
|
||||
|
||||
<p>One noteworthy artifact of this code is the <code>user</code> timing in the results. Previously the user time
|
||||
was only 9 seconds, meaning that the CPU was active only 9 of the 60 seconds the code was running.
|
||||
Afterwards, the usage went up by more than 5x to 52 seconds. The reason is that more CPU cores are
|
||||
active. The <code>KvServer</code> is simulating work by sleeping for a few milliseconds. In a real
|
||||
application, it would be doing useful work and not have such a dramatic change. Rather than
|
||||
scaling per the number of RPCs, it would scale per the number of cores. Thus, if your machine had
|
||||
12 cores, you would expect to see a 12x improvement. Still not bad though!</p>
|
||||
|
||||
<h3 id="more-errors">More Errors</h3>
|
||||
|
||||
<p>If you run this code yourself, you will see a lot more log spam in the form:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">Apr <span style="color:#ae81ff">16</span>, <span style="color:#ae81ff">2018</span> <span style="color:#ae81ff">10</span>:38:40 AM io.grpc.examples.KvClient$3 onFailure
|
||||
INFO: Key not found
|
||||
io.grpc.StatusRuntimeException: NOT_FOUND</code></pre></div>
|
||||
<p>The reason is that the new version of the code makes API level race conditions more apparent.
|
||||
With 100 times as many RPCs happening, the chance of updates and deletes colliding with each other
|
||||
is more likely. To solve this we will need to modify the API definition. Stay tuned for the next
|
||||
post showing how to fix this.</p>
|
||||
|
||||
<h2 id="conclusion">Conclusion</h2>
|
||||
|
||||
<p>There are a lot of opportunities to optimize your gRPC code. To take advantage of these, you
|
||||
need to understand what your code is doing. This post shows how to convert a lock-based service into
|
||||
a low-contention, lock-free service. Always make sure to measure before and after your changes.</p>
|
||||
|
||||
<p>In Part 3, we will optimize the code even further. 2,400 RPC/s is just the beginning!</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1 +0,0 @@
|
|||
<!DOCTYPE html><html><head><title>https://cjyabraham.github.io/blog/</title><link rel="canonical" href="https://cjyabraham.github.io/blog/"/><meta name="robots" content="noindex"><meta charset="utf-8" /><meta http-equiv="refresh" content="0; url=https://cjyabraham.github.io/blog/" /></head></html>
|
||||
|
|
@ -1,399 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Blogs – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="blogcols">
|
||||
<div class="blogcol1" style="margin-top:4%">
|
||||
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/gracefully_clean_up_in_grpc_junit_tests/">Gracefully clean up in gRPC JUnit tests</a></h3>
|
||||
<h5>June 26, 2018</h5>
|
||||
<p>
|
||||
<p>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.</p>
|
||||
|
||||
<p>This is even true for JUnit tests, because otherwise leaked resources may not only linger in your machine forever, but also interfere with subsequent tests. 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.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/gracefully_clean_up_in_grpc_junit_tests/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/kotlin-gradle-projects/">gRPC ❤ Kotlin</a></h3>
|
||||
<h5>June 19, 2018</h5>
|
||||
<p>
|
||||
<p>Did you know that gRPC Java now has out of box support for Kotlin projects built with Gradle? <a href="https://kotlinlang.org/">Kotlin</a> 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 <a href="https://github.com/google/protobuf-gradle-plugin/releases">protobuf-gradle-plugin</a> 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.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/kotlin-gradle-projects/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-2/">So You Want to Optimize gRPC - Part 2</a></h3>
|
||||
<h5>April 16, 2018</h5>
|
||||
<p>
|
||||
<p>How fast is gRPC? Pretty fast if you understand how modern clients and servers are built. In
|
||||
<a href="/blog/optimizing-grpc-part-1">part 1</a>, I showed how to get an easy <strong>60%</strong> improvement. In this
|
||||
post I show how to get a <strong>10000%</strong> improvement.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-2/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-1/">So You Want to Optimize gRPC - Part 1</a></h3>
|
||||
<h5>March 06, 2018</h5>
|
||||
<p>
|
||||
<p>A common question with gRPC is how to make it fast. The gRPC library offers users access to high
|
||||
performance RPCs, but it isn’t always clear how to achieve this. Because this question is common
|
||||
enough I thought I would try to show my thought process when tuning programs.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-1/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/deadlines/">gRPC and Deadlines</a></h3>
|
||||
<h5>February 26, 2018</h5>
|
||||
<p>
|
||||
<p><strong>TL;DR Always set a deadline</strong>. This post explains why we recommend being deliberate about setting deadlines, with useful code snippets to show you how.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/deadlines/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/2018-01-22-grpc-go-engineering-practices/">2018-01-19 gRPC-Go Engineering Practices</a></h3>
|
||||
<h5>January 22, 2018</h5>
|
||||
<p>
|
||||
<p>It’s the start of the new year, and almost the end of my first full year on the
|
||||
gRPC-Go project, so I’d like to take this opportunity to provide an update on
|
||||
the state of gRPC-Go development and give some visibility into how we manage the
|
||||
project. For me, personally, this is the first open source project to which
|
||||
I’ve meaningfully contributed, so this year has been a learning experience for
|
||||
me. Over this year, the team has made constant improvements to our work habits
|
||||
and communication. I still see room for improvement, but I believe we are in a
|
||||
considerably better place than we were a year ago.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2018-01-22-grpc-go-engineering-practices/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/meetup-kit/">The gRPC Meetup Kit</a></h3>
|
||||
<h5>September 14, 2017</h5>
|
||||
<p>
|
||||
|
||||
<p>If you have ever wanted to run an event around <a href="http://grpc.io">gRPC</a>, but didn’t know where to start, or wasn’t sure what content is available - we have released the <a href="https://github.com/grpc-ecosystem/meetup-kit">gRPC Meetup Kit</a>!</p>
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/meetup-kit/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/2017-08-22-grpc-go-perf-improvements/">2017-08-22 gRPC-Go performance Improvements</a></h3>
|
||||
<h5>August 22, 2017</h5>
|
||||
<p>
|
||||
<p><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.
|
||||
Benchmark results at the end.</p>
|
||||
|
||||
<p>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></p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2017-08-22-grpc-go-perf-improvements/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/2017-08-17-community-meeting-update/">2017-08-17 Community Meeting Update</a></h3>
|
||||
<h5>August 17, 2017</h5>
|
||||
<p>
|
||||
<p><strong>Next Community Meeting:</strong> Thursday, August 31, 2017 11am Pacific Time (US and Canada)</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2017-08-17-community-meeting-update/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/flatbuffers/">Announcing out of the box support for gRPC in the Flatbuffers serialization library.</a></h3>
|
||||
<h5>August 17, 2017</h5>
|
||||
<p>
|
||||
<p>The recent release of Flatbuffers <a href="https://github.com/google/flatbuffers/releases">version 1.7</a> introduced truly zero-copy support for gRPC out of the box.</p>
|
||||
|
||||
<p><a href="https://google.github.io/flatbuffers/">Flatbuffers</a> is a serialization library that allows you to access serialized data without first unpacking it or allocating any
|
||||
additional data structures. It was originally designed for games and other resource constrained applications, but is now finding more general use, both by teams within Google and in other companies such as Netflix and Facebook.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/flatbuffers/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
|
||||
|
||||
<ul class="pagination">
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/" class="page-link" aria-label="First"><span aria-hidden="true">««</span></a>
|
||||
</li>
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/" class="page-link" aria-label="Previous"><span aria-hidden="true">«</span></a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item"><a class="page-link" href="/blog/">1</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item active"><a class="page-link" href="/blog/page/2/">2</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item"><a class="page-link" href="/blog/page/3/">3</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item"><a class="page-link" href="/blog/page/4/">4</a></li>
|
||||
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/page/3/" class="page-link" aria-label="Next"><span aria-hidden="true">»</span></a>
|
||||
</li>
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/page/4/" class="page-link" aria-label="Last"><span aria-hidden="true">»»</span></a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="blogcol2">
|
||||
|
||||
<h5 style="font-size:12pt;margin-bottom:20px">All blog posts</h5>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/hello-pancakes/">Dear gRPC</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/state-of-grpc-web/">The state of gRPC in the browser</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-dotnet-build/">gRPC Meets .NET SDK And Visual Studio: Automatic Codegen On Build</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-stacks/">Visualizing gRPC Language Stacks</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-web-ga/">gRPC-Web is Generally Available</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/a_short_introduction_to_channelz/">A short introduction to Channelz</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc_on_http2/">gRPC on HTTP/2 Engineering a Robust, High Performance Protocol</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-with-json/">gRPC + JSON</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/take-the-grpc-survey/">Take the gRPC Survey!</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/http2_smarter_at_scale/">HTTP/2 Smarter At Scale</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/gracefully_clean_up_in_grpc_junit_tests/">Gracefully clean up in gRPC JUnit tests</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/kotlin-gradle-projects/">gRPC ❤ Kotlin</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-2/">So You Want to Optimize gRPC - Part 2</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-1/">So You Want to Optimize gRPC - Part 1</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/deadlines/">gRPC and Deadlines</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2018-01-22-grpc-go-engineering-practices/">2018-01-19 gRPC-Go Engineering Practices</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/meetup-kit/">The gRPC Meetup Kit</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2017-08-22-grpc-go-perf-improvements/">2017-08-22 gRPC-Go performance Improvements</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2017-08-17-community-meeting-update/">2017-08-17 Community Meeting Update</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/flatbuffers/">Announcing out of the box support for gRPC in the Flatbuffers serialization library.</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/loadbalancing/">gRPC Load Balancing</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/helmgrpc/">gRPC in Helm</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/yygrpc/">Migration to Google Cloud Platform — gRPC & grpc-gateway</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/bazel_rules_protobuf/">Building gRPC services with bazel and rules_protobuf</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/vscogrpc/">gRPC at VSCO</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/vendastagrpc/">Why we have decided to move our APIs to gRPC</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/gablogpost/">gRPC Project is now 1.0 and ready for production deployments</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/coreos/">gRPC with REST and Open APIs</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/installation/">gRPC - now with easy installation.</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/pubsub/">Google Cloud PubSub - with the power of gRPC!</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/beta_release/">gRPC releases Beta, opening door for use in production environments.</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/principles/">gRPC Motivation and Design Principles.</a><br><br>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,408 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Blogs – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="blogcols">
|
||||
<div class="blogcol1" style="margin-top:4%">
|
||||
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/loadbalancing/">gRPC Load Balancing</a></h3>
|
||||
<h5>June 15, 2017</h5>
|
||||
<p>
|
||||
<p>This post describes various load balancing scenarios seen when deploying gRPC. If you use <a href="/">gRPC</a> with multiple backends, this document is for you.</p>
|
||||
|
||||
<p>A large scale gRPC deployment typically has a number of identical back-end instances, and a number of clients. Each server has a certain capacity. Load balancing is used for distributing the load from clients optimally across available servers.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/loadbalancing/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/helmgrpc/">gRPC in Helm</a></h3>
|
||||
<h5>May 15, 2017</h5>
|
||||
<p>
|
||||
<p><em>Our guest post today comes from Brian Hardock, a software engineer from Deis working on the <a href="https://helm.sh/">Helm</a> project.</em></p>
|
||||
|
||||
<p>Helm is the package manager for Kubernetes. Helm provides its users with a customizable mechanism for
|
||||
managing distributed applications and controlling their deployment.</p>
|
||||
|
||||
<p>I have the good fortune to be a member of the phenomenal open-source Kubernetes Helm community serving as
|
||||
a core contributor. My first day working with the Helm team was spent prototyping the architecture for
|
||||
the next generation of Helm. By the end of that day, we had procured the preliminary RPC protocol data model
|
||||
used to enable communication between Helm and its in-cluster server component, Tiller.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/helmgrpc/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/yygrpc/">Migration to Google Cloud Platform — gRPC & grpc-gateway</a></h3>
|
||||
<h5>April 12, 2017</h5>
|
||||
<p>
|
||||
<p>Our guest post today comes from <a href="https://www.linkedin.com/in/miguel-mendez-008231/">Miguel Mendez</a> of Yik Yak.</p>
|
||||
|
||||
<p><em>This post was originally a part of the <a href="https://medium.com/yik-yak-eng">Yik Yak Engineering Blog</a> which focused on sharing the lessons learned as we evolved Yik Yak from early-stage startup code running in Amazon Web Services to an eventual incremental rewrite, re-architecture, and live-migration to Google Cloud Platform.</em></p>
|
||||
|
||||
<p>In our previous blog <a href="https://medium.com/yik-yak-eng/migration-to-google-cloud-platform-overview-9b5e5c17c368">post</a> we gave an overview of our migration to Google Cloud Platform from Amazon Web Services. In this post we will drill down into the role that <a href="/">gRPC</a> and <a href="https://github.com/grpc-ecosystem/grpc-gateway">grpc-gateway</a> played in that migration and share some lessons which we picked up along the way.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/yygrpc/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/bazel_rules_protobuf/">Building gRPC services with bazel and rules_protobuf</a></h3>
|
||||
<h5>October 13, 2016</h5>
|
||||
<p>
|
||||
<p><a href="/">gRPC</a> makes it easier to build high-performance
|
||||
microservices by providing generated service entrypoints in a variety
|
||||
of different languages. <a href="https://bazel.io">Bazel</a> complements these
|
||||
efforts with a capable and fast polyglot build environment.</p>
|
||||
|
||||
<p><a href="https://github.com/pubref/rules_protobuf">rules_protobuf</a> extends
|
||||
bazel and makes it easier develop gRPC services.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/bazel_rules_protobuf/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/vscogrpc/">gRPC at VSCO</a></h3>
|
||||
<h5>September 06, 2016</h5>
|
||||
<p>
|
||||
<p>Our guest post today comes from Robert Sayre and Melinda Lu of VSCO.</p>
|
||||
|
||||
<p>Founded in 2011, <a href="https://vsco.co">VSCO</a> is a community for expression—empowering people to create, discover and connect through images and words. VSCO is in the process of migrating their stack to gRPC.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/vscogrpc/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/vendastagrpc/">Why we have decided to move our APIs to gRPC</a></h3>
|
||||
<h5>August 29, 2016</h5>
|
||||
<p>
|
||||
Our guest post today comes from Dale Hopkins, CTO of Vendasta.
|
||||
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 and Datastore.
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/vendastagrpc/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/gablogpost/">gRPC Project is now 1.0 and ready for production deployments</a></h3>
|
||||
<h5>August 23, 2016</h5>
|
||||
<p>
|
||||
Today, the gRPC project has reached a significant milestone with its 1.0 release. Languages moving to 1.0 include C++, Java, Go, Node, Ruby, Python and C# across Linux, Windows, and Mac. Objective-C and Android Java support on iOS and Android is also moving to 1.0. The 1.0 release means that the core protocol and API surface are now stable with measured performance, stress tested and developers can rely on these APIs and deploy in production, they will follow semantic versioning from here.
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/gablogpost/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/coreos/">gRPC with REST and Open APIs</a></h3>
|
||||
<h5>May 09, 2016</h5>
|
||||
<p>
|
||||
<p>Our guest post today comes from Brandon Phillips of <a href="https://coreos.com/">CoreOS</a>. CoreOS builds open source projects and products for Linux Containers. Their flagship product for consensus and discovery <a href="https://coreos.com/etcd/">etcd</a> and their container engine <a href="https://coreos.com/rkt/">rkt</a> are early adopters of gRPC.</p>
|
||||
|
||||
<p>One of the key reasons CoreOS chose gRPC is because it uses HTTP/2, enabling applications to present both a HTTP 1.1 REST/JSON API and an efficient gRPC interface on a single TCP port (available for Go). This provides developers with compatibility with the REST web ecosystem, while advancing a new, high-efficiency RPC protocol. With the recent release of Go 1.6, Go ships with a stable <code>net/http2</code> package by default.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/coreos/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/installation/">gRPC - now with easy installation.</a></h3>
|
||||
<h5>April 04, 2016</h5>
|
||||
<p>
|
||||
<p>Today we are happy to provide an update that significantly simplifies the getting started experience for gRPC.</p>
|
||||
|
||||
<ul>
|
||||
<li><p>For most languages, <strong>the gRPC runtime can now be installed in a single step via native package managers</strong> such as <code>npm</code> for Node.js, <code>gem</code> for Ruby and <code>pip</code> for Python. Even though our Node, Ruby and Python runtimes are wrapped on gRPC’s C core, users now don’t need to explicitly pre-install the C core library as a package in most Linux distributions. We autofetch it for you :-).</p></li>
|
||||
|
||||
<li><p><strong>For Java, we have simplified the steps needed to add gRPC support to your build tools</strong> by providing plugins for Maven and Gradle. These let you easily depend on the core runtime to deploy or ship generated libraries into production environments.</p></li>
|
||||
|
||||
<li><p>You can also use our Dockerfiles to use these updated packages - deploying microservices built on gRPC should now be a very simple experience.</p></li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/installation/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/pubsub/">Google Cloud PubSub - with the power of gRPC!</a></h3>
|
||||
<h5>March 24, 2016</h5>
|
||||
<p>
|
||||
<p><a href="https://cloud.google.com/pubsub/">Google Cloud PubSub</a> 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 <a href="https://cloud.google.com/blog/big-data/2016/03/announcing-grpc-alpha-for-google-cloud-pubsub">PubSub gRPC alpha</a>. Now <strong>users can access PubSub via gRPC</strong> and benefit from all the advantages it brings.</p>
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/pubsub/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
|
||||
|
||||
<ul class="pagination">
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/" class="page-link" aria-label="First"><span aria-hidden="true">««</span></a>
|
||||
</li>
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/page/2/" class="page-link" aria-label="Previous"><span aria-hidden="true">«</span></a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item"><a class="page-link" href="/blog/">1</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item"><a class="page-link" href="/blog/page/2/">2</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item active"><a class="page-link" href="/blog/page/3/">3</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item"><a class="page-link" href="/blog/page/4/">4</a></li>
|
||||
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/page/4/" class="page-link" aria-label="Next"><span aria-hidden="true">»</span></a>
|
||||
</li>
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/page/4/" class="page-link" aria-label="Last"><span aria-hidden="true">»»</span></a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="blogcol2">
|
||||
|
||||
<h5 style="font-size:12pt;margin-bottom:20px">All blog posts</h5>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/hello-pancakes/">Dear gRPC</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/state-of-grpc-web/">The state of gRPC in the browser</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-dotnet-build/">gRPC Meets .NET SDK And Visual Studio: Automatic Codegen On Build</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-stacks/">Visualizing gRPC Language Stacks</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-web-ga/">gRPC-Web is Generally Available</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/a_short_introduction_to_channelz/">A short introduction to Channelz</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc_on_http2/">gRPC on HTTP/2 Engineering a Robust, High Performance Protocol</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-with-json/">gRPC + JSON</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/take-the-grpc-survey/">Take the gRPC Survey!</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/http2_smarter_at_scale/">HTTP/2 Smarter At Scale</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/gracefully_clean_up_in_grpc_junit_tests/">Gracefully clean up in gRPC JUnit tests</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/kotlin-gradle-projects/">gRPC ❤ Kotlin</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-2/">So You Want to Optimize gRPC - Part 2</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-1/">So You Want to Optimize gRPC - Part 1</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/deadlines/">gRPC and Deadlines</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2018-01-22-grpc-go-engineering-practices/">2018-01-19 gRPC-Go Engineering Practices</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/meetup-kit/">The gRPC Meetup Kit</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2017-08-22-grpc-go-perf-improvements/">2017-08-22 gRPC-Go performance Improvements</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2017-08-17-community-meeting-update/">2017-08-17 Community Meeting Update</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/flatbuffers/">Announcing out of the box support for gRPC in the Flatbuffers serialization library.</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/loadbalancing/">gRPC Load Balancing</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/helmgrpc/">gRPC in Helm</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/yygrpc/">Migration to Google Cloud Platform — gRPC & grpc-gateway</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/bazel_rules_protobuf/">Building gRPC services with bazel and rules_protobuf</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/vscogrpc/">gRPC at VSCO</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/vendastagrpc/">Why we have decided to move our APIs to gRPC</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/gablogpost/">gRPC Project is now 1.0 and ready for production deployments</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/coreos/">gRPC with REST and Open APIs</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/installation/">gRPC - now with easy installation.</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/pubsub/">Google Cloud PubSub - with the power of gRPC!</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/beta_release/">gRPC releases Beta, opening door for use in production environments.</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/principles/">gRPC Motivation and Design Principles.</a><br><br>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,314 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Blogs – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="blogcols">
|
||||
<div class="blogcol1" style="margin-top:4%">
|
||||
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/beta_release/">gRPC releases Beta, opening door for use in production environments.</a></h3>
|
||||
<h5>October 26, 2015</h5>
|
||||
<p>
|
||||
|
||||
<p>
|
||||
The gRPC team is excited to announce the immediate availability of gRPC Beta. This release marks an important point in API stability and going forward most API changes are expected to be additive in nature. This milestone opens the door for gRPC use in production environments.
|
||||
</p>
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/beta_release/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
<h3 style="margin-top:0px;"><a href="https://cjyabraham.github.io/blog/principles/">gRPC Motivation and Design Principles.</a></h3>
|
||||
<h5>September 08, 2015</h5>
|
||||
<p>
|
||||
|
||||
<h2>Motivation</h2>
|
||||
|
||||
<p>Google has been using a single general-purpose RPC infrastructure called Stubby to connect the large number of microservices running within and across our data centers for over a decade. Our internal systems have long embraced the microservice architecture gaining popularity today. Having a uniform, cross-platform RPC infrastructure has allowed for the rollout of fleet-wide improvements in efficiency, security, reliability and behavioral analysis critical to supporting the incredible growth seen in that period.
|
||||
</p>
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/principles/">Read More</a>
|
||||
<br><br><br>
|
||||
|
||||
|
||||
|
||||
<ul class="pagination">
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/" class="page-link" aria-label="First"><span aria-hidden="true">««</span></a>
|
||||
</li>
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/page/3/" class="page-link" aria-label="Previous"><span aria-hidden="true">«</span></a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item"><a class="page-link" href="/blog/">1</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item"><a class="page-link" href="/blog/page/2/">2</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item"><a class="page-link" href="/blog/page/3/">3</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="page-item active"><a class="page-link" href="/blog/page/4/">4</a></li>
|
||||
|
||||
|
||||
<li class="page-item disabled">
|
||||
<a href="" class="page-link" aria-label="Next"><span aria-hidden="true">»</span></a>
|
||||
</li>
|
||||
|
||||
<li class="page-item">
|
||||
<a href="/blog/page/4/" class="page-link" aria-label="Last"><span aria-hidden="true">»»</span></a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="blogcol2">
|
||||
|
||||
<h5 style="font-size:12pt;margin-bottom:20px">All blog posts</h5>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/hello-pancakes/">Dear gRPC</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/state-of-grpc-web/">The state of gRPC in the browser</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-dotnet-build/">gRPC Meets .NET SDK And Visual Studio: Automatic Codegen On Build</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-stacks/">Visualizing gRPC Language Stacks</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-web-ga/">gRPC-Web is Generally Available</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/a_short_introduction_to_channelz/">A short introduction to Channelz</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc_on_http2/">gRPC on HTTP/2 Engineering a Robust, High Performance Protocol</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/grpc-with-json/">gRPC + JSON</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/take-the-grpc-survey/">Take the gRPC Survey!</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/http2_smarter_at_scale/">HTTP/2 Smarter At Scale</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/gracefully_clean_up_in_grpc_junit_tests/">Gracefully clean up in gRPC JUnit tests</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/kotlin-gradle-projects/">gRPC ❤ Kotlin</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-2/">So You Want to Optimize gRPC - Part 2</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/optimizing-grpc-part-1/">So You Want to Optimize gRPC - Part 1</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/deadlines/">gRPC and Deadlines</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2018-01-22-grpc-go-engineering-practices/">2018-01-19 gRPC-Go Engineering Practices</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/meetup-kit/">The gRPC Meetup Kit</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2017-08-22-grpc-go-perf-improvements/">2017-08-22 gRPC-Go performance Improvements</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/2017-08-17-community-meeting-update/">2017-08-17 Community Meeting Update</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/flatbuffers/">Announcing out of the box support for gRPC in the Flatbuffers serialization library.</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/loadbalancing/">gRPC Load Balancing</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/helmgrpc/">gRPC in Helm</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/yygrpc/">Migration to Google Cloud Platform — gRPC & grpc-gateway</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/bazel_rules_protobuf/">Building gRPC services with bazel and rules_protobuf</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/vscogrpc/">gRPC at VSCO</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/vendastagrpc/">Why we have decided to move our APIs to gRPC</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/gablogpost/">gRPC Project is now 1.0 and ready for production deployments</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/coreos/">gRPC with REST and Open APIs</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/installation/">gRPC - now with easy installation.</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/pubsub/">Google Cloud PubSub - with the power of gRPC!</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/beta_release/">gRPC releases Beta, opening door for use in production environments.</a><br><br>
|
||||
|
||||
<a href="https://cjyabraham.github.io/blog/principles/">gRPC Motivation and Design Principles.</a><br><br>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC Motivation and Design Principles. – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC Motivation and Design Principles.</h1>
|
||||
<h5>Posted on Tuesday, September 08, 2015
|
||||
|
||||
|
||||
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>Stubby has many great features - however, it's not based on any standard and is too tightly coupled to our internal infrastructure to be considered suitable for public release. With the advent of SPDY, HTTP/2, and QUIC, many of these same features have appeared in public standards, together with other features that Stubby does not provide. It became clear that it was time to rework Stubby to take advantage of this standardization, and to extend its applicability to mobile, IoT, and Cloud use-cases.</p>
|
||||
|
||||
<h2>Principles & Requirements</h2>
|
||||
|
||||
<p><strong>Services not Objects, Messages not References</strong> - Promote the microservices design philosophy of coarse-grained message exchange between systems while avoiding the <a href="https://martinfowler.com/articles/distributed-objects-microservices.html">pitfalls of distributed objects</a> and the <a href="https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing">fallacies of ignoring the network</a>.</p>
|
||||
|
||||
<p><strong>Coverage & Simplicity</strong> - The stack should be available on every popular development platform and easy for someone to build for their platform of choice. It should be viable on CPU & memory limited devices. </p>
|
||||
|
||||
<p><strong>Free & Open</strong> - Make the fundamental features free for all to use. Release all artifacts as open-source efforts with licensing that should facilitate and not impede adoption.</p>
|
||||
|
||||
<p><strong>Interoperability & Reach</strong> - The wire-protocol must be capable of surviving traversal over common internet infrastructure.</p>
|
||||
|
||||
<p><strong>General Purpose & Performant</strong> - The stack should be applicable to a broad class of use-cases while sacrificing little in performance when compared to a use-case specific stack.</p>
|
||||
|
||||
<p><strong>Layered</strong> - Key facets of the stack must be able to evolve independently. A revision to the wire-format should not disrupt application layer bindings.</p>
|
||||
|
||||
<p><strong>Payload Agnostic</strong> - Different services need to use different message types and encodings such as protocol buffers, JSON, XML, and Thrift; the protocol and implementations must allow for this. Similarly the need for payload compression varies by use-case and payload type: the protocol should allow for pluggable compression mechanisms.</p>
|
||||
|
||||
<p><strong>Streaming</strong> - Storage systems rely on streaming and flow-control to express large data-sets. Other services, like voice-to-text or stock-tickers, rely on streaming to represent temporally related message sequences.</p>
|
||||
|
||||
<p><strong>Blocking & Non-Blocking</strong> - Support both asynchronous and synchronous processing of the sequence of messages exchanged by a client and server. This is critical for scaling and handling streams on certain platforms.</p>
|
||||
|
||||
<p><strong>Cancellation & Timeout</strong> - Operations can be expensive and long-lived - cancellation allows servers to reclaim resources when clients are well-behaved. When a causal-chain of work is tracked, cancellation can cascade. A client may indicate a timeout for a call, which allows services to tune their behavior to the needs of the client.</p>
|
||||
|
||||
<p><strong>Lameducking</strong> - Servers must be allowed to gracefully shut-down by rejecting new requests while continuing to process in-flight ones.</p>
|
||||
|
||||
<p><strong>Flow-Control</strong> - Computing power and network capacity are often unbalanced between client & server. Flow control allows for better buffer management as well as providing protection from DOS by an overly active peer.</p>
|
||||
|
||||
<p><strong>Pluggable</strong> - A wire protocol is only part of a functioning API infrastructure. Large distributed systems need security, health-checking, load-balancing and failover, monitoring, tracing, logging, and so on. Implementations should provide extensions points to allow for plugging in these features and, where useful, default implementations.</p>
|
||||
|
||||
<p><strong>Extensions as APIs</strong> - Extensions that require collaboration among services should favor using APIs rather than protocol extensions where possible. Extensions of this type could include health-checking, service introspection, load monitoring, and load-balancing assignment.</p>
|
||||
|
||||
<p><strong>Metadata Exchange</strong> - Common cross-cutting concerns like authentication or tracing rely on the exchange of data that is not part of the declared interface of a service. Deployments rely on their ability to evolve these features at a different rate to the individual APIs exposed by services.</p>
|
||||
|
||||
<p><strong>Standardized Status Codes</strong> - Clients typically respond to errors returned by API calls in a limited number of ways. The status code namespace should be constrained to make these error handling decisions clearer. If richer domain-specific status is needed the metadata exchange mechanism can be used to provide that.</p>
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Google Cloud PubSub - with the power of gRPC! – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>Google Cloud PubSub - with the power of gRPC!</h1>
|
||||
<h5>Posted on Thursday, March 24, 2016
|
||||
|
||||
|
||||
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p><a href="https://cloud.google.com/pubsub/">Google Cloud PubSub</a> 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 <a href="https://cloud.google.com/blog/big-data/2016/03/announcing-grpc-alpha-for-google-cloud-pubsub">PubSub gRPC alpha</a>. Now <strong>users can access PubSub via gRPC</strong> and benefit from all the advantages it brings.</p>
|
||||
|
||||
<p><a href="https://cloud.google.com/pubsub/grpc-overview">Alpha instructions and gRPC code</a> are now available for gRPC PubSub in Python and Java.</p>
|
||||
|
||||
<p>But what if you want to use this service now with gRPC in another language - C#, say, or Ruby? Once you have a Google account, with a little bit of extra work you can do that too! You can use the tools and the instructions on <a href="/docs/">our site</a> to generate and use your own gRPC client code from the PubSub service’s <code>.proto</code> file, available from <a href="https://github.com/googleapis/googleapis/blob/master/google/pubsub/v1/pubsub.proto">GitHub</a>.</p>
|
||||
|
||||
<p><a href="https://cloud.google.com/blog/big-data/2016/03/announcing-grpc-alpha-for-google-cloud-pubsub">Read the full Google Cloud PubSub announcement</a></p>
|
||||
|
||||
<p><a href="https://cloud.google.com/pubsub/docs">Find out more about using Google Cloud PubSub</a></p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,372 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
The state of gRPC in the browser – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>The state of gRPC in the browser</h1>
|
||||
<h5>Posted on Tuesday, January 08, 2019
|
||||
by
|
||||
|
||||
<a href="https://jbrandhorst.com/">Johan Brandhorst</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p><em>This is a guest post by</em>
|
||||
<em><a href="https://jbrandhorst.com">Johan Brandhorst</a>, Software Engineer at</em>
|
||||
<em><a href="https://www.infosum.com">InfoSum</a>.</em></p>
|
||||
|
||||
<p>gRPC 1.0 was released in August 2016 and has since grown to become one of the
|
||||
premier technical solutions for application communications. It has been adopted
|
||||
by startups, enterprise companies, and open source projects worldwide.
|
||||
Its support for polyglot environments, focus on performance, type safety, and
|
||||
developer productivity has transformed the way developers design their
|
||||
architectures.</p>
|
||||
|
||||
<p>So far the benefits have largely only been available to mobile
|
||||
app and backend developers, whilst frontend developers have had to continue to
|
||||
rely on JSON REST interfaces as their primary means of information exchange.
|
||||
However, with the release of gRPC-Web, gRPC is poised to become a valuable
|
||||
addition in the toolbox of frontend developers.</p>
|
||||
|
||||
<p>In this post, I’ll describe some of the history of gRPC in the browser, explore
|
||||
the state of the world today, and share some thoughts on the future.</p>
|
||||
|
||||
<h1 id="beginnings">Beginnings</h1>
|
||||
|
||||
<p>In the summer of 2016, both a team at Google and
|
||||
Improbable<sup id="a1"><a href="#f1">1</a></sup> independently started working on
|
||||
implementing something that could be called “gRPC for the browser”. They soon
|
||||
discovered each other’s existence and got together to define a
|
||||
spec<sup id="a2"><a href="#f2">2</a></sup> for the new protocol.</p>
|
||||
|
||||
<h2 id="the-grpc-web-spec">The gRPC-Web Spec</h2>
|
||||
|
||||
<p>It is currently impossible to implement the HTTP/2 gRPC
|
||||
spec<sup id="a3"><a href="#f3">3</a></sup> in the browser, as there is simply no browser
|
||||
API with enough fine-grained control over the requests. For example: there is
|
||||
no way to force the use of HTTP/2, and even if there was, raw HTTP/2 frames are
|
||||
inaccessible in browsers. The gRPC-Web spec starts from the point of view of the
|
||||
HTTP/2 spec, and then defines the differences. These notably include:</p>
|
||||
|
||||
<ul>
|
||||
<li>Supporting both HTTP/1.1 and HTTP/2.</li>
|
||||
<li>Sending of gRPC trailers at the very end of request/response bodies as
|
||||
indicated by a new bit in the gRPC message header<sup id="a4"><a href="#f4">4</a></sup>.</li>
|
||||
<li>A mandatory proxy for translating between gRPC-Web requests and gRPC HTTP/2
|
||||
responses.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="the-tech">The Tech</h2>
|
||||
|
||||
<p>The basic idea is to have the browser send normal HTTP requests (with Fetch or
|
||||
XHR) and have a small proxy in front of the gRPC server to translate the
|
||||
requests and responses to something the browser can use.</p>
|
||||
|
||||
<p><img src="/img/grpc-web-proxy.png"
|
||||
alt="The role of the gRPC-Web proxy" style="max-width: 800px" /></p>
|
||||
|
||||
<h1 id="the-two-implementations">The Two Implementations</h1>
|
||||
|
||||
<p>The teams at Google and Improbable both went on to implement the spec in two
|
||||
different repositories<sup id="a5"><a href="#f5">5</a>,</sup><sup id="a6"><a href="#f6">6</a></sup>,
|
||||
and with slightly different implementations, such that neither was entirely
|
||||
conformant to the spec, and for a long time neither was compatible with the
|
||||
other’s proxy<sup id="a7"><a href="#f7">7</a>,</sup><sup id="a8"><a href="#f8">8</a></sup>.</p>
|
||||
|
||||
<p>The Improbable gRPC-Web client<sup id="a9"><a href="#f9">9</a></sup> is implemented in
|
||||
TypeScript and available on npm as <code>@improbable-eng/grpc-web</code><sup id="a10"><a href="#f10">10</a></sup>.
|
||||
There is also a Go proxy available, both as a package that can be imported into
|
||||
existing Go gRPC servers<sup id="a11"><a href="#f11">11</a></sup>, and as a standalone
|
||||
proxy that can be used to expose an arbitrary gRPC server to a gRPC-Web
|
||||
frontend<sup id="a12"><a href="#f12">12</a></sup>.</p>
|
||||
|
||||
<p>The Google gRPC-Web client<sup id="a13"><a href="#f13">13</a></sup> is implemented in
|
||||
JavaScript using the Google Closure library<sup id="a14"><a href="#f14">14</a></sup> base.
|
||||
It is available on npm as <code>grpc-web</code><sup id="a15"><a href="#f15">15</a></sup>. It originally
|
||||
shipped with a proxy implemented as an NGINX
|
||||
extension<sup id="a16"><a href="#f16">16</a></sup>, but has since doubled down on an Envoy
|
||||
proxy HTTP filter<sup id="a17"><a href="#f17">17</a></sup>, which is available in all
|
||||
versions since v1.4.0.</p>
|
||||
|
||||
<h2 id="feature-sets">Feature Sets</h2>
|
||||
|
||||
<p>The gRPC HTTP/2 implementations all support the four method types: unary,
|
||||
server-side, client-side, and bi-directional streaming. However, the gRPC-Web
|
||||
spec does not mandate any client-side or bi-directional streaming support
|
||||
specifically, only that it will be implemented once WHATWG
|
||||
Streams<sup id="a18"><a href="#f18">18</a></sup> are implemented in browsers.</p>
|
||||
|
||||
<p>The Google client supports unary and server-side streaming, but only when used
|
||||
with the <code>grpcwebtext</code> mode. Only unary requests are fully supported in the
|
||||
<code>grpcweb</code> mode. These two modes specify different ways to encode the protobuf
|
||||
payload in the requests and responses.</p>
|
||||
|
||||
<p>The Improbable client supports both unary and server-side streaming, and has an
|
||||
implementation that automatically chooses between XHR and Fetch based on the
|
||||
browser capabilities.</p>
|
||||
|
||||
<p>Here’s a table that summarizes the different features supported:</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client / Feature</th>
|
||||
<th>Transport</th>
|
||||
<th>Unary</th>
|
||||
<th>Server-side streams</th>
|
||||
<th>Client-side & bi-directional streaming</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Improbable</td>
|
||||
<td>Fetc️h/XHR ️</td>
|
||||
<td>✔️</td>
|
||||
<td>✔️</td>
|
||||
<td>❌<sup id="a19"><a href="#f19">19</a></sup></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Google (<code>grpcwebtext</code>)</td>
|
||||
<td>XHR ️</td>
|
||||
<td>✔️</td>
|
||||
<td>✔️</td>
|
||||
<td>❌</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Google (<code>grpcweb</code>)</td>
|
||||
<td>XHR ️</td>
|
||||
<td>✔️</td>
|
||||
<td>❌<sup id="a20"><a href="#f20">20</a></sup></td>
|
||||
<td>❌</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>For more information on this table, please see
|
||||
<a href="https://github.com/johanbrandhorst/grpc-web-compatibility-test">my compatibility test repo on github</a>.</p>
|
||||
|
||||
<p>The compatibility tests may evolve into some automated test framework to enforce
|
||||
and document the various compatibilities in the future.</p>
|
||||
|
||||
<h2 id="compatibility-issues">Compatibility Issues</h2>
|
||||
|
||||
<p>Of course, with two different proxies also come compatibility issues.
|
||||
Fortunately, these have recently been ironed out, so you can expect to use
|
||||
either client with either proxy.</p>
|
||||
|
||||
<h1 id="the-future">The Future</h1>
|
||||
|
||||
<p>The Google implementation announced version 1.0 and general availability in
|
||||
October 2018<sup id="a21"><a href="#f21">21</a></sup> and has published a roadmap of future
|
||||
goals<sup id="a22"><a href="#f22">22</a></sup>, including:</p>
|
||||
|
||||
<ul>
|
||||
<li>An efficient JSON-like message encoding</li>
|
||||
<li>In-process proxies for Node, Python, Java and more</li>
|
||||
<li>Integration with popular frameworks (React, Angular, Vue)</li>
|
||||
<li>Fetch API transport for memory efficient streaming</li>
|
||||
<li>Bi-directional steaming support</li>
|
||||
</ul>
|
||||
|
||||
<p>Google is looking for feedback on what features are important to the community,
|
||||
so if you think any of these are particularly valuable to you, then please fill
|
||||
in their survey<sup id="a23"><a href="#f23">23</a></sup>.</p>
|
||||
|
||||
<p>Recent talks between the two projects have agreed on promoting the Google client
|
||||
and Envoy proxy as preferred solutions for new users. The Improbable client and
|
||||
proxy will remain as alternative implementations of the spec without the
|
||||
Google Closure dependency, but should be considered experimental. A migration
|
||||
guide will be produced for existing users to move to the Google client, and the
|
||||
teams are working together to converge the generated APIs.</p>
|
||||
|
||||
<h1 id="conclusion">Conclusion</h1>
|
||||
|
||||
<p>The Google client will continue to have new features and fixes implemented at a
|
||||
steady pace, with a team dedicated to its success, and it being the official
|
||||
gRPC client. It doesn’t have Fetch API support like the Improbable client, but
|
||||
if this is an important feature for the community, it will be added. The Google
|
||||
team and the greater community are collaborating on the official client to the
|
||||
benefit of the gRPC community at large. Since the GA announcement the community
|
||||
contributions to the Google gRPC-Web repo has increased dramatically.</p>
|
||||
|
||||
<p>When choosing between the two proxies, there’s no difference in capability, so
|
||||
it becomes a matter of your deployment model. Envoy will suit some
|
||||
scenarios, while an in-process Go proxy has its own advantages.</p>
|
||||
|
||||
<p>If you’re getting started with gRPC-Web today, first try the Google client. It
|
||||
has strict API compatibility guarantees and is built on the rock-solid Google
|
||||
Closure library base used by Gmail and Google Maps. If you <em>need</em> Fetch API
|
||||
memory efficiency or experimental websocket client-side and bi-directional
|
||||
streaming, the Improbable client is a good choice, and it will continue to be
|
||||
used and maintained by Improbable for the foreseeable future.</p>
|
||||
|
||||
<p>Either way, gRPC-Web is an excellent choice for web developers. It brings the
|
||||
portability, performance, and engineering of a sophisticated protocol into the
|
||||
browser, and marks an exciting time for frontend developers!</p>
|
||||
|
||||
<h2 id="references">References</h2>
|
||||
|
||||
<ol>
|
||||
<li><div id="f1"></div> <a href="https://improbable.io/games/blog/grpc-web-moving-past-restjson-towards-type-safe-web-apis">https://improbable.io/games/blog/grpc-web-moving-past-restjson-towards-type-safe-web-apis</a> <a href="#a1">↩</a></li>
|
||||
<li><div id="f2"></div> <a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md">https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md</a> <a href="#a2">↩</a></li>
|
||||
<li><div id="f3"></div> <a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md">https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md</a> <a href="#a3">↩</a></li>
|
||||
<li><div id="f4"></div> <a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md#protocol-differences-vs-grpc-over-http2">https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md#protocol-differences-vs-grpc-over-http2</a> <a href="#a4">↩</a></li>
|
||||
<li><div id="f5"></div> <a href="https://github.com/improbable-eng/grpc-web">https://github.com/improbable-eng/grpc-web</a> <a href="#a5">↩</a></li>
|
||||
<li><div id="f6"></div> <a href="https://github.com/grpc/grpc-web">https://github.com/grpc/grpc-web</a> <a href="#a6">↩</a></li>
|
||||
<li><div id="f7"></div> <a href="https://github.com/improbable-eng/grpc-web/issues/162">https://github.com/improbable-eng/grpc-web/issues/162</a> <a href="#a7">↩</a></li>
|
||||
<li><div id="f8"></div> <a href="https://github.com/grpc/grpc-web/issues/91">https://github.com/grpc/grpc-web/issues/91</a> <a href="#a8">↩</a></li>
|
||||
<li><div id="f9"></div> <a href="https://github.com/improbable-eng/grpc-web/tree/master/ts">https://github.com/improbable-eng/grpc-web/tree/master/ts</a> <a href="#a9">↩</a></li>
|
||||
<li><div id="f10"></div> <a href="https://www.npmjs.com/package/@improbable-eng/grpc-web">https://www.npmjs.com/package/@improbable-eng/grpc-web</a> <a href="#a10">↩</a></li>
|
||||
<li><div id="f11"></div> <a href="https://github.com/improbable-eng/grpc-web/tree/master/go/grpcweb">https://github.com/improbable-eng/grpc-web/tree/master/go/grpcweb</a> <a href="#a11">↩</a></li>
|
||||
<li><div id="f12"></div> <a href="https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy">https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy</a> <a href="#a12">↩</a></li>
|
||||
<li><div id="f13"></div> <a href="https://github.com/grpc/grpc-web/tree/master/javascript/net/grpc/web">https://github.com/grpc/grpc-web/tree/master/javascript/net/grpc/web</a> <a href="#a13">↩</a></li>
|
||||
<li><div id="f14"></div> <a href="https://developers.google.com/closure/">https://developers.google.com/closure/</a> <a href="#a14">↩</a></li>
|
||||
<li><div id="f15"></div> <a href="https://www.npmjs.com/package/grpc-web">https://www.npmjs.com/package/grpc-web</a> <a href="#a15">↩</a></li>
|
||||
<li><div id="f16"></div> <a href="https://github.com/grpc/grpc-web/tree/master/net/grpc/gateway">https://github.com/grpc/grpc-web/tree/master/net/grpc/gateway</a> <a href="#a16">↩</a></li>
|
||||
<li><div id="f17"></div> <a href="https://www.envoyproxy.io/docs/envoy/latest/configuration/http_filters/grpc_web_filter">https://www.envoyproxy.io/docs/envoy/latest/configuration/http_filters/grpc_web_filter</a> <a href="#a17">↩</a></li>
|
||||
<li><div id="f18"></div> <a href="https://streams.spec.whatwg.org/">https://streams.spec.whatwg.org/</a> <a href="#a18">↩</a></li>
|
||||
<li><div id="f19"></div>The Improbable client supports client-side and
|
||||
bi-directional streaming with an experimental websocket transport. This is
|
||||
not part of the gRPC-Web spec, and is not recommended for production use. <a href="#a19">↩</a></li>
|
||||
<li><div id="f20"></div><code>grpcweb</code> allows server streaming methods to be called, but
|
||||
it doesn’t return data until the stream has closed. <a href="#a20">↩</a></li>
|
||||
<li><div id="f21"></div> <a href="https://grpc.io/blog/grpc-web-ga">https://grpc.io/blog/grpc-web-ga</a> <a href="#a21">↩</a></li>
|
||||
<li><div id="f22"></div> <a href="https://github.com/grpc/grpc-web/blob/master/ROADMAP.md">https://github.com/grpc/grpc-web/blob/master/ROADMAP.md</a> <a href="#a22">↩</a></li>
|
||||
<li><div id="f23"></div> <a href="https://docs.google.com/forms/d/1NjWpyRviohn5jaPntosBHXRXZYkh_Ffi4GxJZFibylM">https://docs.google.com/forms/d/1NjWpyRviohn5jaPntosBHXRXZYkh_Ffi4GxJZFibylM</a> <a href="#a23">↩</a></li>
|
||||
</ol>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,164 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Take the gRPC Survey! – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>Take the gRPC Survey!</h1>
|
||||
<h5>Posted on Tuesday, August 14, 2018
|
||||
by
|
||||
|
||||
<a href="https://github.com/hsaliak">Kailash Sethuraman</a>
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<h2 id="the-grpc-project-wants-your-feedback">The gRPC Project wants your feedback!</h2>
|
||||
|
||||
<p>The gRPC project is looking for feedback to improve the gRPC experience. To do this, we are running a <a href="http://bit.ly/gRPC18survey">gRPC user survey</a>. We invite you to participate and provide input that will help us better plan and prioritize.</p>
|
||||
|
||||
<h2 id="grpc-user-survey">gRPC User Survey</h2>
|
||||
|
||||
<p><strong>Who</strong> : If you currently use gRPC, have used gRPC in the past, or have any interest in it, we would love to hear from you.</p>
|
||||
|
||||
<p><strong>Where</strong>: Please take this 15 minute survey by Friday, 24th August.</p>
|
||||
|
||||
<p><strong>Why</strong>: gRPC is a broadly applicable project with a variety of use cases. We want to use <a href="http://bit.ly/gRPC18survey">this survey</a> to help us understand what works well, and what needs to be fixed.</p>
|
||||
|
||||
<h2 id="spread-the-word">Spread the word!</h2>
|
||||
|
||||
<p>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!</p>
|
||||
|
||||
<p>Survey Short link: <a href="http://bit.ly/gRPC18survey">http://bit.ly/gRPC18survey
|
||||
</a></p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Why we have decided to move our APIs to gRPC – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>Why we have decided to move our APIs to gRPC</h1>
|
||||
<h5>Posted on Monday, August 29, 2016
|
||||
by
|
||||
|
||||
Dale Hopkins
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>Our guest post today comes from Dale Hopkins, CTO of <a href="https://vendasta.com/">Vendasta</a>.</p>
|
||||
|
||||
<p>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 <a href="https://cloud.google.com/appengine/">Google App Engine</a> 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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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 <a href="https://cloud.google.com/container-engine/">Google Container Engine</a> 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.</p>
|
||||
|
||||
<p>The last optimization we made was to move our APIs to <a href="/">gRPC</a>. 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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC at VSCO – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>gRPC at VSCO</h1>
|
||||
<h5>Posted on Tuesday, September 06, 2016
|
||||
by
|
||||
|
||||
Robert Sayre and Melinda Lu
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>Our guest post today comes from Robert Sayre and Melinda Lu of VSCO.</p>
|
||||
|
||||
<p>Founded in 2011, <a href="https://vsco.co">VSCO</a> is a community for expression—empowering people to create, discover and connect through images and words. VSCO is in the process of migrating their stack to gRPC.</p>
|
||||
|
||||
<p>In 2015, user growth forced VSCO down a familiar path. A monolithic PHP application in existence since the early days of the company was exhibiting performance problems and becoming difficult to maintain. We experimented with some smaller services in node.js, Go, and Java. At the same time, a larger messaging service for email, push messages, and in-app notifications was built in Go. Taking a first step away from JSON, we chose <a href="https://developers.google.com/protocol-buffers/">Protocol Buffers</a> as the serialization format for this system.</p>
|
||||
|
||||
<p>Today, VSCO has largely settled on Go for new services. There are exceptions, particularly where a mature JVM solution is available for a given problem. Additionally, VSCO uses node.js for web applications, often with server-side <a href="https://facebook.github.io/react/">React</a>. Given that mix of languages, services, and some future data pipeline work detailed below, VSCO settled on gRPC and Protocol Buffers as the most practical solution for interprocess communication. A gradual migration from JSON over HTTP/1.1 APIs to gRPC over HTTP/2 is underway and going well. That said, there have been issues with the maturity of the PHP implementation relative to other languages.</p>
|
||||
|
||||
<p>Protocol buffers have been particularly valuable in building out our data ecosystem, where we rely on them to standardize and allow safe evolution of our data schemas in a language-agnostic way. As one example, we’ve built a Go service that feeds off our MySQL and MongoDB database replication logs and transforms backend database changes into a stream of immutable events in Kafka, with each row- or document-change event encoded as a protocol buffer. This database event stream allows us to add real-time data consumers as desired, without impacting production traffic and without having to coordinate with other systems. By processing all database events into protocol buffers en-route to Kafka, we can ensure that data is encoded in a uniform way that makes it easy to consume and use from multiple languages. Our implementation of <a href="https://github.com/vsco/autobahn-binlog">MySQL-binary-log</a> and <a href="https://github.com/vsco/autobahn-oplog">Mongo-oplog</a> tailers are available on GitHub.</p>
|
||||
|
||||
<p>Elsewhere in our data pipeline, we’ve begun using gRPC and protocol buffers to deliver behavioral events from our iOS and Android clients to a Go ingestion service, which then publishes these events to Kafka. To support this high-volume use case, we needed (1) a performant, fault-tolerant, language-agnostic RPC framework, (2) a way to ensure data compatibility as our product evolves, and (3) horizontally-scalable infrastructure. We’ve found gRPC, protocol buffers, and Go services running in Kubernetes a good fit for all three. As this was our first client-facing Go gRPC service, we did experience some new points of friction — in particular, load-balancer support and amenities like curl-like debugging have been lagging due to the youth of the HTTP/2 ecosystem. However, the ease of defining services with the gRPC IDL, using built-in architecture like interceptors, and scaling with Go have made the tradeoffs worthwhile.</p>
|
||||
|
||||
<p>As a first step in bringing gRPC to our mobile clients, we’ve shipped telemetry code in our iOS and Android apps. As of gRPC 1.0, this process is relatively straightforward. They only post events to our servers so far, and don’t do much with gRPC responses. The previous implementation was based on JSON, and our move to a single protocol buffer definition of our events uncovered a bunch of subtle bugs and differences between the clients.</p>
|
||||
|
||||
<p>One slight roadblock we ran into was the need for our clients to maintain compatibility with our JSON implementation as we ramp up, and for integration with vendor SDKs. This required a little bit of key-value coding on iOS, but it got more difficult on Android. We ended up having to write a protobuf compiler plugin to get the reflection features we needed while maintaining adequate performance. Drawing from that experience, we’ve made a concise <a href="https://github.com/vsco/protoc-demo">example protoc plugin</a> built with <a href="https://bazel.io/">Bazel</a> available on GitHub.</p>
|
||||
|
||||
<p>As more and more of our data becomes available in protocol buffer form, we plan to build upon this unified schema to expand our machine-learning and analytics systems. For example, we write our Kafka database replication streams to Amazon S3 as <a href="https://parquet.apache.org/">Apache Parquet</a>, an efficient columnar disk-storage format. Parquet has low-level support for protocol buffers, so we can use our existing data definitions to write optimized tables and do partial deserializations where desired.</p>
|
||||
|
||||
<p>From S3, we run computations on our data using Apache Spark, which can use our protocol buffer definitions to define types. We’re also building new machine-learning applications with <a href="https://www.tensorflow.org/">TensorFlow</a>. It uses protocol buffers natively and allows us to serve our models as gRPC services with <a href="https://tensorflow.github.io/serving/">TensorFlow Serving</a>.</p>
|
||||
|
||||
<p>So far, we’ve had good luck with gRPC and Protocol Buffers. They don’t eliminate every integration headache. However it’s easy to see how they help our engineers avoid writing a lot of boilerplate RPC code, while side-stepping the endless data-quality papercuts that come with looser serialization formats.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,348 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Migration to Google Cloud Platform — gRPC & grpc-gateway – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Blog</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="singleblog">
|
||||
<h1>Migration to Google Cloud Platform — gRPC & grpc-gateway</h1>
|
||||
<h5>Posted on Wednesday, April 12, 2017
|
||||
by
|
||||
|
||||
Miguel Mendez
|
||||
|
||||
</h5>
|
||||
<p>
|
||||
<p>Our guest post today comes from <a href="https://www.linkedin.com/in/miguel-mendez-008231/">Miguel Mendez</a> of Yik Yak.</p>
|
||||
|
||||
<p><em>This post was originally a part of the <a href="https://medium.com/yik-yak-eng">Yik Yak Engineering Blog</a> which focused on sharing the lessons learned as we evolved Yik Yak from early-stage startup code running in Amazon Web Services to an eventual incremental rewrite, re-architecture, and live-migration to Google Cloud Platform.</em></p>
|
||||
|
||||
<p>In our previous blog <a href="https://medium.com/yik-yak-eng/migration-to-google-cloud-platform-overview-9b5e5c17c368">post</a> we gave an overview of our migration to Google Cloud Platform from Amazon Web Services. In this post we will drill down into the role that <a href="/">gRPC</a> and <a href="https://github.com/grpc-ecosystem/grpc-gateway">grpc-gateway</a> played in that migration and share some lessons which we picked up along the way.</p>
|
||||
|
||||
<h2 id="most-people-have-rest-apis-don-t-you-what-s-the-problem">Most people have REST APIs, don’t you? What’s the problem?</h2>
|
||||
|
||||
<p>Yes, we actually still have REST APIs that clients use because migrating the client APIs was out of scope. To be fair, you can make REST APIs work and there are a lot of useful REST APIs out there. Having said that, the issues that we had with REST lie in the details.</p>
|
||||
|
||||
<h3 id="no-canonical-rest-specification">No Canonical REST Specification</h3>
|
||||
|
||||
<p>There is no single REST specification that is canonical. There are best practices, but no true canon. For that reason, there isn’t unanimous agreement on when to use specific HTTP methods and response codes. Beyond that, not all of the possible HTTP methods and response codes are supported across all platforms… This forces REST API implementers to compensate for these deficiencies using techniques that work for them but create more variance in REST APIs across the board. At best, REST APIs are really REST-ish dialects.</p>
|
||||
|
||||
<h3 id="harder-on-developers">Harder on Developers</h3>
|
||||
|
||||
<p>REST APIs aren’t exactly great from a developer’s standpoint either.
|
||||
First, because REST is tied to HTTP there is no simple mapping to an API in my language of choice. If I’m using Go or Java there is no “interface” that I can use in my code to stub it out. I can create one, but it is extra-linguistic to the REST API definition.</p>
|
||||
|
||||
<p>Second, REST APIs spread information that is necessary to interpreting the intent of the request across various components of the request. You have the HTTP method, the request URI, the request payload, and it can get even more complicated if request headers are involved in the semantics.</p>
|
||||
|
||||
<p>Third, it is great that I can use curl from the command line to hit an API, but it comes at the cost of having to shoehorn the API into that ecosystem. Normally that use case only matters for letting people quickly try out an API — and if that is high on your list of requirements then by all means feel free to use REST… Just keep it simple.</p>
|
||||
|
||||
<h3 id="no-declarative-rest-api-description">No Declarative REST API Description</h3>
|
||||
|
||||
<p>The fourth problem with a REST APIs is that, at least until <a href="https://swagger.io/">Swagger</a> 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:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"> // Code omitted…
|
||||
$yak->hidePin=false;
|
||||
|
||||
// Code omitted…
|
||||
$yak->hidePin=true;
|
||||
|
||||
// Code omitted…
|
||||
$yak->hidePin=0;
|
||||
|
||||
// Code omitted…
|
||||
$yak->hidePin=1;</code></pre></div>
|
||||
<p>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.</p>
|
||||
|
||||
<p>Problems can also arise when the client’s 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:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="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></pre></div>
|
||||
<p>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.</p>
|
||||
|
||||
<h2 id="grpc-can-address-the-issues-with-rest">gRPC can address the issues with REST…</h2>
|
||||
|
||||
<p>If you’re not familiar with gRPC, it’s 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, I’ll zoom into the aspects that are important.</p>
|
||||
|
||||
<h3 id="grpc-is-declarative-strongly-typed-and-language-independent">gRPC is Declarative, Strongly-Typed, and Language Independent</h3>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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 don’t have typos in the client or server code regardless of their implementation language.</p>
|
||||
|
||||
<h3 id="grpc-means-no-hand-rolling-of-rpc-code-is-required">gRPC Means No hand-rolling of RPC Code is Required</h3>
|
||||
|
||||
<p>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 don’t modify the generated code — and you should not have to — then any performance improvements in the generated code will be picked up.</p>
|
||||
|
||||
<h3 id="grpc-has-compact-serialization">gRPC has Compact Serialization</h3>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h3 id="grpc-tooling-is-extensible">gRPC Tooling is Extensible</h3>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h3 id="grpc-supports-contract-updates">gRPC Supports Contract Updates</h3>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h2 id="grpc-gateway-because-rest-will-be-with-us-for-a-while">Grpc-gateway — because REST will be with us for a while…</h2>
|
||||
|
||||
<p>You’re 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 doesn’t 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.</p>
|
||||
|
||||
<h2 id="migration-and-grpc-grpc-gateway">Migration and gRPC + grpc-gateway</h2>
|
||||
|
||||
<p>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 <a href="https://medium.com/yik-yak-eng/yik-yak-configuration-and-experiment-system-16a5c15ee77c#.7s11d3kqh">Experimentation and Configuration System</a> 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.</p>
|
||||
|
||||
<h3 id="grpc-idl-for-api-getmessages">gRPC IDL for “/api/getMessages”</h3>
|
||||
|
||||
<p>Below is the gRPC IDL that we defined to mimic the legacy Yik Yak API in GCP. We’ve simplified the example to only contain the “/api/getMessages” endpoint which clients use to get the set of messages centered around their current location.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto"><span style="color:#75715e">// APIRequest Message — sent by clients
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">APIRequest</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#75715e">// userID is the ID of the user making the request
|
||||
</span><span style="color:#75715e"></span> <span style="color:#66d9ef">string</span> userID <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#75715e">// Other fields omitted for clarity…
|
||||
</span><span style="color:#75715e"></span>}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#75715e">// APIFeedResponse contains the set of messages that clients should
|
||||
</span><span style="color:#75715e">// display.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">APIFeedResponse</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">repeated</span> APIPost messages <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#75715e">// Other fields omitted for clarity…
|
||||
</span><span style="color:#75715e"></span>}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#75715e">// APIPost defines the set of post fields returned to the clients.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">APIPost</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">string</span> messageID <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">string</span> <span style="color:#66d9ef">message</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#75715e">// Other fields omitted for clarity…
|
||||
</span><span style="color:#75715e"></span>}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#75715e">// YYAPI service accessed by Android, iOS and Web clients.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">service</span> YYAPI {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#75715e">// Other endpoints omitted…
|
||||
</span><span style="color:#75715e"></span> <span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#75715e">// APIGetMessages returns the list of messages within a radius of
|
||||
</span><span style="color:#75715e"></span> <span style="color:#75715e">// the user’s current location.
|
||||
</span><span style="color:#75715e"></span> <span style="color:#66d9ef">rpc</span> APIGetMessages (APIRequest) <span style="color:#66d9ef">returns</span> (APIFeedResponse) {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">option</span> (google.api.http) <span style="color:#f92672">=</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> get<span style="color:#f92672">:</span> <span style="color:#960050;background-color:#1e0010">“</span><span style="color:#f92672">/</span>api<span style="color:#f92672">/</span>getMessages<span style="color:#960050;background-color:#1e0010">”</span> <span style="color:#75715e">// Option tells grpc-gateway that an HTTP
|
||||
</span><span style="color:#75715e"></span> <span style="color:#75715e">// GET to /api/getMessages should be
|
||||
</span><span style="color:#75715e"></span> <span style="color:#75715e">// routed to the APIGetMessages gRPC
|
||||
</span><span style="color:#75715e"></span> <span style="color:#75715e">// endpoint.
|
||||
</span><span style="color:#75715e"></span> };<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> }<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#75715e">// Other endpoints omitted…
|
||||
</span><span style="color:#75715e"></span>}</code></pre></div>
|
||||
<h3 id="protoc-generated-go-interfaces-for-yyapi-service">Protoc Generated Go Interfaces for YYAPI Service</h3>
|
||||
|
||||
<p>The IDL above is then compiled to Go files by the protoc compiler to produce client proxies and server stubs as below.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#75715e">// Client API for YYAPI service
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">YYAPIClient</span> <span style="color:#66d9ef">interface</span> {
|
||||
<span style="color:#a6e22e">APIGetMessages</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">in</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">APIRequest</span>, <span style="color:#a6e22e">opts</span> <span style="color:#f92672">...</span><span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">CallOption</span>) (<span style="color:#f92672">*</span><span style="color:#a6e22e">APIFeedResponse</span>, <span style="color:#66d9ef">error</span>)
|
||||
}
|
||||
|
||||
<span style="color:#75715e">// NewYYAPIClient returns an implementation of the YYAPIClient interface which
|
||||
</span><span style="color:#75715e">// clients can use to call the gRPC service.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">NewYYAPIClient</span>(<span style="color:#a6e22e">cc</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">ClientConn</span>) <span style="color:#a6e22e">YYAPIClient</span> {
|
||||
<span style="color:#75715e">// Code omitted for clarity..
|
||||
</span><span style="color:#75715e"></span>}
|
||||
|
||||
<span style="color:#75715e">// Server API for YYAPI service
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">YYAPIServer</span> <span style="color:#66d9ef">interface</span> {
|
||||
<span style="color:#a6e22e">APIGetMessages</span>(<span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#f92672">*</span><span style="color:#a6e22e">APIRequest</span>) (<span style="color:#f92672">*</span><span style="color:#a6e22e">APIFeedResponse</span>, <span style="color:#66d9ef">error</span>)
|
||||
}
|
||||
|
||||
<span style="color:#75715e">// RegisterYYAPIServer registers an implementation of the YYAPIServer with an
|
||||
</span><span style="color:#75715e">// existing gRPC server instance.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">RegisterYYAPIServer</span>(<span style="color:#a6e22e">s</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">Server</span>, <span style="color:#a6e22e">srv</span> <span style="color:#a6e22e">YYAPIServer</span>) {
|
||||
<span style="color:#75715e">// Code omitted for clarity..
|
||||
</span><span style="color:#75715e"></span>}</code></pre></div>
|
||||
<h3 id="grpc-gateway-generated-go-code-for-rest-reverse-proxy-of-yyapi-service">Grpc-gateway Generated Go-code for REST Reverse Proxy of YYAPI Service</h3>
|
||||
|
||||
<p>By using the google.api.http option in our IDL above, we tell the grpc-gateway system that it should route HTTP GETs for “/api/getMessages” to the APIGetMessages gRPC endpoint. In turn, it creates the HTTP to gRPC reverse proxy and allows you to set it up by calling the generated function below.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#75715e">// RegisterYYAPIHandler registers the http handlers for service YYAPI to “mux”.
|
||||
</span><span style="color:#75715e">// The handlers forward requests to the grpc endpoint over “conn”.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">RegisterYYAPIHandler</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">mux</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">runtime</span>.<span style="color:#a6e22e">ServeMux</span>, <span style="color:#a6e22e">conn</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">ClientConn</span>) <span style="color:#66d9ef">error</span> {
|
||||
<span style="color:#75715e">// Code omitted for clarity
|
||||
</span><span style="color:#75715e"></span>}</code></pre></div>
|
||||
<p>So again, from a single gRPC IDL description you can obtain client and server interfaces and implementation stubs in your language of choice as well as REST reverse proxies for free.</p>
|
||||
|
||||
<h2 id="grpc-i-heard-there-were-some-rough-edges">gRPC — I heard there were some rough edges?</h2>
|
||||
|
||||
<p>We started working with gRPC for Go late in Q1 of 2016 and there were definitely some rough edges at the time.</p>
|
||||
|
||||
<h3 id="early-adopter-issues">Early Adopter Issues</h3>
|
||||
|
||||
<p>We ran into <a href="https://github.com/grpc/grpc-go/issues/674">Issue 674</a>, a resource leak inside of the Go gRPC client code which could cause gRPC transports to hang when under heavy load. The gRPC team was very responsive and the fix was merged into the master branch within days.</p>
|
||||
|
||||
<p>We ran into a resource leak in the generated code for grpc-gateway. However, by the time we found that issue, it had already been fixed by that team and merged into master.</p>
|
||||
|
||||
<p>The last early-adopter type issue that we ran into was around the Go’s gRPC client not supporting the GOAWAY packet that was part of the gRPC protocol spec. Fortunately, this one did not impact us in production. It only manifested during the repo case we had put together for Issue 674.</p>
|
||||
|
||||
<p>All in all this was fairly reasonable given how early we were.</p>
|
||||
|
||||
<h3 id="load-balancing">Load Balancing</h3>
|
||||
|
||||
<p>Now, if you are going to use gRPC this is definitely one area that you need to think through carefully. By default, gRPC uses HTTP2 instead of HTTP1. HTTP2 is able to open a connection to a server and reuse it for multiple requests among other things. If you use it in that mode, you won’t distribute requests amongst all of the servers in your load balancing pool. At the time that we executing the migration, existing load balancers didn’t handle HTTP2 traffic very well if at all.</p>
|
||||
|
||||
<p>At the time the gRPC team didn’t have a <a href="https://github.com/grpc/grpc/blob/master/doc/load-balancing.md">Load Balancing Proposal</a>, so we burned a lot of cycles trying to force our system to do some type of client-side load balancing. In the end, since most of our raw gRPC communications took place within the data center, and everything was deployed using Kubernetes, it was simpler to dial the remote server every time thereby forcing the system to spread the load out amongst the servers in the Kubernetes Service. Given our setup it only added about 1 ms to the overall response time, so it was a simple work around.</p>
|
||||
|
||||
<p>So was that the end of the load balancing issues? Not exactly. Once we had our basic gRPC-based system up and running we started running load tests against it, and noticed some interesting behaviors. Below is the per gRPC server CPU load graph over time, do you notice anything curious about it?</p>
|
||||
|
||||
<p><img src="/img/yy-cpu-imbalance.png" alt="" /></p>
|
||||
|
||||
<p>The server with the heaviest load was running at around 50% CPU, while the most lightly loaded server was running at around 20% CPU even after several minutes of warmup. It turned out that even though we were dialing every time, we had an <a href="https://nghttp2.org/">nghttp2</a> ingress as part of our network topology which would tend to send inbound requests to servers to whom it had already connected and thereby causing uneven distribution. After removing the nghttp2 ingress, our CPU graphs showed much less variance in the load distribution.</p>
|
||||
|
||||
<p><img src="/img/yy-cpu-balanced.png" alt="" /></p>
|
||||
|
||||
<h2 id="conclusion">Conclusion</h2>
|
||||
|
||||
<p>REST APIs have their issues, but they are not going away anytime soon. If you are up for trying something a little cleaner, then definitely consider using gRPC (along with grpc-gateway if you still need to expose a REST API). Even though we hit some issues early on, gRPC was a net gain for us. It gave us a path forward to more tightly defined APIs. It also allowed us to stand up new implementations of the legacy REST APIs in GCP which teed us up to seamlessly migrate traffic from the AWS implementations to the new GCP ones in a controlled manner.</p>
|
||||
|
||||
<p>Having discussed our use of Go, gRPC and Google Cloud Platform, we are ready to discuss how we built a new geo store on top of Google Bigtable and the Google S2 Library — the subject of our next post.</p>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>gRPC</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<main>
|
||||
<article>
|
||||
<header>
|
||||
<h1>Categories</h1>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
<ul>
|
||||
|
||||
|
||||
</ul>
|
||||
</main>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>Categories on gRPC</title>
|
||||
<link>https://cjyabraham.github.io/categories/</link>
|
||||
<description>Recent content in Categories on gRPC</description>
|
||||
<generator>Hugo -- gohugo.io</generator>
|
||||
<language>en-us</language>
|
||||
|
||||
<atom:link href="https://cjyabraham.github.io/categories/index.xml" rel="self" type="application/rss+xml" />
|
||||
|
||||
|
||||
</channel>
|
||||
</rss>
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Community – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Community</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section2" style="text-align:left;margin-bottom:5%">
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<p class="lead" style="margin-top:2%">gRPC has an active community of developers who are using, enhancing and building valuable integrations with other software projects. We’d love your help to improve and extend the project. You can reach us via <a href="https://groups.google.com/forum/#!forum/grpc-io">Mailing list</a>, <a href="https://gitter.im/grpc/grpc"> Gitter channel</a>, <a href="https://twitter.com/grpcio">Twitter</a> to start engaging with the project and its members.
|
||||
</p>
|
||||
|
||||
<section class="community-section">
|
||||
<h4 class="community-contribute community-title">Contribute on Github</h4>
|
||||
<p>gRPC has an active community of developers who are using, enhancing and building valuable integrations with other software projects. We are always looking for active contributors in gRPC and gRPC Ecosystem. Here are a few areas where we would love community contribution in grpc project. Be sure to follow our <a href="/contribute/">community addition guidelines</a>.</p>
|
||||
|
||||
<div class="contribute-wrapper">
|
||||
<div class="contribute-item">
|
||||
<div class="item-content">
|
||||
<a class="item-box" href="https://github.com/grpc/grpc/labels/disposition%2Fhelp%20wanted">
|
||||
<p class="item-link">gRPC C-based</p>
|
||||
</a>
|
||||
<p class="item-desc">Or shortcut to: <a href="https://github.com/grpc/grpc/issues?q=is%3Aopen+is%3Aissue+label%3Aarea%2Fcore+label%3A%22disposition%2Fhelp+wanted%22">C</a>, <a href="https://github.com/grpc/grpc/issues?q=is%3Aopen+is%3Aissue+label%3A%22disposition%2Fhelp+wanted%22+label%3Alang%2Fc%2B%2B">C++</a>, <a href="https://github.com/grpc/grpc/issues?q=is%3Aopen+is%3Aissue+label%3A%22disposition%2Fhelp+wanted%22+label%3Alang%2Fnode">Node.js</a>, <a href="https://github.com/grpc/grpc/issues?q=is%3Aopen+is%3Aissue+label%3A%22disposition%2Fhelp+wanted%22+label%3Alang%2FPython">Python</a>, <a href="https://github.com/grpc/grpc/issues?q=is%3Aopen+is%3Aissue+label%3A%22disposition%2Fhelp+wanted%22+label%3Alang%2Fruby">Ruby</a>, <a href="https://github.com/grpc/grpc/issues?q=is%3Aopen+is%3Aissue+label%3A%22disposition%2Fhelp+wanted%22+label%3Alang%2FObjC">Objective-C</a>, <a href="https://github.com/grpc/grpc/issues?q=is%3Aopen+is%3Aissue+label%3A%22disposition%2Fhelp+wanted%22+label%3Alang%2Fphp">PHP</a>, and <a href="https://github.com/grpc/grpc/issues?utf8=%E2%9C%93&q=is%3Aopen+is%3Aissue+label%3A%22disposition%2Fhelp+wanted%22+label%3Alang%2Fc%23+">C#</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contribute-item">
|
||||
<div class="item-content">
|
||||
<a class="item-box" href="https://github.com/grpc/grpc-java/labels/help%20wanted">
|
||||
<p class="item-link">gRPC Java</p>
|
||||
</a>
|
||||
<p class="item-desc">For Android Java and Java.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contribute-item">
|
||||
<div class="item-content">
|
||||
<a class="item-box" href="https://github.com/grpc/grpc-go/labels/Status:%20help%20wanted">
|
||||
<p class="item-link">gRPC Go</p>
|
||||
</a>
|
||||
<p class="item-desc">For the Go implementation</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="/contribute/"><span>More on how to contribute to gRPC Documentation ></span></a>
|
||||
</section>
|
||||
|
||||
<section class="community-section">
|
||||
<h4 class="community-mailing community-title">Mailing List</h4>
|
||||
<p>Any questions or suggestions? Just want to be in the loop of what is going on with the project? Join the <a href="https://groups.google.com/forum/#!forum/grpc-io">mailing list</a>
|
||||
</section>
|
||||
|
||||
<section class="community-section">
|
||||
<h4 class="community-irc community-title">Join gRPC Ecosystem</h4>
|
||||
<p>We have an organization for all valuable projects around gRPC in the <a href="https://github.com/grpc-ecosystem">gRPC Ecosystem</a>. The goal is to have all projects around gRPC (showing integrations with other projects or building utilities on top of gRPC) to be showcased here. If you have a new project you would like to add to gRPC Ecosystem, please fill up the <a href="https://docs.google.com/a/google.com/forms/d/119zb79XRovQYafE9XKjz9sstwynCWcMpoJwHgZJvK74/edit">gRPC Ecosystem Project Request</a> form. Please read the <a href="https://github.com/grpc/grpc-contrib/blob/master/CONTRIBUTING.md">contribution guidelines</a> for gRPC Ecosystem before submitting.
|
||||
</section>
|
||||
|
||||
<section class="community-section" style="width:100%;margin-bottom:5%;">
|
||||
<h4 class="community-irc community-title">Gitter Channel</h4>
|
||||
<p>Join other developers and users on the <a href="https://gitter.im/grpc/grpc">gRPC Gitter channel</a></p>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="community-section">
|
||||
<h4 style="margin-bottom:15%" class="community-reddit community-title">Reddit</h4>
|
||||
<p style="margin-top:5%">Join the <a href="https://www.reddit.com/r/grpc/">subreddit</a></p>
|
||||
</section>
|
||||
|
||||
<section class="community-section">
|
||||
<h4 class="community-meetings community-title">Community Meetings</h4>
|
||||
<p class="community-text">We hold a community video conference every other week. It's a way to discuss the status of work and show off things the community is working on. Meeting information and notes can be found at <a href="https://bit.ly/grpcmeetings">bit.ly/grpcmeetings</a>.</p>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,179 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Contribute – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown ">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Contribute</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section2" style="text-align:left;margin-bottom:5%">
|
||||
<div class="container markdown">
|
||||
<div class="row">
|
||||
|
||||
To contribute to gRPC documentation, please fork the <a href="https://github.com/grpc/grpc.github.io">GitHub gRPC repository</a> and start submitting pull requests.
|
||||
|
||||
<div id="MainRepoInstructions">
|
||||
<h2>Contribution guidelines for gRPC</h2>
|
||||
|
||||
<p>We welcome contributions to either of our three core repositories. <a href="https://github.com/grpc/grpc">gRPC</a>, <a href="https://github.com/grpc/grpc-java">gRPC Java</a> and <a href="https://github.com/grpc/grpc-go">gRPC Go</a>. </p>
|
||||
|
||||
<button class="btn btn-grpc waves-effect waves-light"><a href="https://github.com/grpc/grpc/blob/master/CONTRIBUTING.md">View Guidelines</a></button>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="EcosystemInstructions">
|
||||
<h2>Contribution guidelines for gRPC Ecosystem</h2>
|
||||
|
||||
<p><a href="https://github.com/grpc-ecosystem/">gRPC Ecosystem</a> is a different organization where we collect and curate valuable integrations of other projects with gRPC. You can propose a new project for it by filling up the <a hre="https://docs.google.com/a/google.com/forms/d/119zb79XRovQYafE9XKjz9sstwynCWcMpoJwHgZJvK74/edit">Propose new project form</a>.</p>
|
||||
|
||||
<button class="btn btn-grpc waves-effect waves-light"><a href="https://github.com/grpc/grpc-contrib/blob/master/CONTRIBUTING.md">View Guidelines</a></button>
|
||||
|
||||
|
||||
<div id="generalInstructions">
|
||||
<h2>Edit our site on github</h2>
|
||||
|
||||
<p>Click the below button to visit the repo for our site. You can then click the "Fork" button in the upper-right area of the screen to create a copy of our site on your GitHub account called a "fork." Make any changes you want in your fork, and when you are ready to send those changes to us, go to the index page for your fork and click "New Pull Request" to let us know about it.</p>
|
||||
|
||||
<button class="btn btn-grpc waves-effect waves-light"><a href="https://github.com/grpc/grpc.github.io">Browse this site's source code</a></button>
|
||||
</div>
|
||||
|
||||
<div id="githubOrganization">
|
||||
<h2>Being a member of the gRPC organization on github</h2>
|
||||
|
||||
<p>Being an organization member is not required for the vast majority of the contributions. Membership is required for certain administrative tasks such as accepting a pull request, or closing issues. If you wish to be part of the gRPC organization on github, please <a href="https://grpc.io/community/">get in touch with us</a>. Please note that in order to be part of the organization, your github account needs to have <a href="https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/">two factor security enabled</a>.</p>
|
||||
|
||||
</div>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
1224
public/css/style.css
1224
public/css/style.css
File diff suppressed because it is too large
Load Diff
|
|
@ -1 +0,0 @@
|
|||
<!DOCTYPE html><html><head><title>https://cjyabraham.github.io/docs/guides/auth/</title><link rel="canonical" href="https://cjyabraham.github.io/docs/guides/auth/"/><meta name="robots" content="noindex"><meta charset="utf-8" /><meta http-equiv="refresh" content="0; url=https://cjyabraham.github.io/docs/guides/auth/" /></head></html>
|
||||
|
|
@ -1,689 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Authentication – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown active">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="headertext">Documentation</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="subnav d-none d-md-block">
|
||||
<a href="https://cjyabraham.github.io/docs/" >Overview</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/quickstart/" >Quick Start</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/guides/" class="active">Guides</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/tutorials/" >Tutorials</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/reference/" >Reference</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/samples/" >Samples</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/talks/" >Presentations</a>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="quickstartcols">
|
||||
|
||||
<div class="quickstartcol1">
|
||||
|
||||
<h8>Guides</h8>
|
||||
|
||||
|
||||
<a href="/docs/guides/">
|
||||
What is gRPC?
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/concepts/">
|
||||
gRPC Concepts
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/auth/" class="active">
|
||||
Authentication
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/error/">
|
||||
Error handling and debugging
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/benchmarking/">
|
||||
Benchmarking
|
||||
</a>
|
||||
|
||||
|
||||
<a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md">
|
||||
gRPC Wire Format
|
||||
</a>
|
||||
|
||||
|
||||
<h8 style="margin-top:25%">Related Guides</h8>
|
||||
<a href="https://developers.google.com/protocol-buffers/docs/overview">Protocol Buffers</a>
|
||||
</div>
|
||||
|
||||
<div class="quickstartcol2" style="margin-top:4%">
|
||||
<h3 style="margin-top:0px;">
|
||||
Authentication
|
||||
</h3>
|
||||
|
||||
|
||||
|
||||
<p class="lead">This document provides an overview of gRPC authentication,
|
||||
including our built-in supported auth mechanisms, how to plug in your own
|
||||
authentication systems, and examples of how to use gRPC auth in our supported
|
||||
languages.</p>
|
||||
|
||||
<div id="toc" class="toc mobile-toc"></div>
|
||||
|
||||
<h3 id="overview">Overview</h3>
|
||||
|
||||
<p>gRPC is designed to work with a variety of authentication mechanisms, making it
|
||||
easy to safely use gRPC to talk to other systems. You can use our supported
|
||||
mechanisms - SSL/TLS with or without Google token-based authentication - or you
|
||||
can plug in your own authentication system by extending our provided code.</p>
|
||||
|
||||
<p>gRPC also provides a simple authentication API that lets you provide all the
|
||||
necessary authentication information as <code>Credentials</code> when creating a channel or
|
||||
making a call.</p>
|
||||
|
||||
<h3 id="supported-auth-mechanisms">Supported auth mechanisms</h3>
|
||||
|
||||
<p>The following authentication mechanisms are built-in to gRPC:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong>SSL/TLS</strong>: gRPC has SSL/TLS integration and promotes the use of SSL/TLS
|
||||
to authenticate the server, and to encrypt all the data exchanged between
|
||||
the client and the server. Optional mechanisms are available for clients to
|
||||
provide certificates for mutual authentication.</li>
|
||||
<li><strong>Token-based authentication with Google</strong>: gRPC provides a generic
|
||||
mechanism (described below) to attach metadata based credentials to requests
|
||||
and responses. Additional support for acquiring access tokens
|
||||
(typically OAuth2 tokens) while accessing Google APIs through gRPC is
|
||||
provided for certain auth flows: you can see how this works in our code
|
||||
examples below. In general this mechanism must be used <em>as well as</em> SSL/TLS
|
||||
on the channel - Google will not allow connections without SSL/TLS, and
|
||||
most gRPC language implementations will not let you send credentials on an
|
||||
unencrypted channel.</li>
|
||||
</ul>
|
||||
|
||||
<p class="note"> <strong>WARNING</strong>: Google credentials should only
|
||||
be used to connect to Google services. Sending a Google issued OAuth2 token
|
||||
to a non-Google service could result in this token being stolen and used to
|
||||
impersonate the client to Google services.</p>
|
||||
|
||||
<h3 id="authentication-api">Authentication API</h3>
|
||||
|
||||
<p>gRPC provides a simple authentication API based around the unified concept of
|
||||
Credentials objects, which can be used when creating an entire gRPC channel or
|
||||
an individual call.</p>
|
||||
|
||||
<h4 id="credential-types">Credential types</h4>
|
||||
|
||||
<p>Credentials can be of two types:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong>Channel credentials</strong>, which are attached to a <code>Channel</code>, such as SSL
|
||||
credentials.</li>
|
||||
<li><strong>Call credentials</strong>, which are attached to a call (or <code>ClientContext</code> in
|
||||
C++).</li>
|
||||
</ul>
|
||||
|
||||
<p>You can also combine these in a<code>CompositeChannelCredentials</code>, allowing you to
|
||||
specify, for example, SSL details for the channel along with call credentials
|
||||
for each call made on the channel. A <code>CompositeChannelCredentials</code> associates a
|
||||
<code>ChannelCredentials</code> and a <code>CallCredentials</code> to create a new
|
||||
<code>ChannelCredentials</code>. The result will send the authentication data associated
|
||||
with the composed <code>CallCredentials</code>with every call made on the channel.</p>
|
||||
|
||||
<p>For example, you could create a <code>ChannelCredentials</code> from an <code>SslCredentials</code>
|
||||
and an <code>AccessTokenCredentials</code>. The result when applied to a <code>Channel</code> would
|
||||
send the appropriate access token for each call on this channel.</p>
|
||||
|
||||
<p>Individual <code>CallCredentials</code> can also be composed using
|
||||
<code>CompositeCallCredentials</code>. The resulting <code>CallCredentials</code> when used in a call
|
||||
will trigger the sending of the authentication data associated with the two
|
||||
<code>CallCredentials</code>.</p>
|
||||
|
||||
<h4 id="using-client-side-ssl-tls">Using client-side SSL/TLS</h4>
|
||||
|
||||
<p>Now let’s look at how <code>Credentials</code> work with one of our supported auth
|
||||
mechanisms. This is the simplest authentication scenario, where a client just
|
||||
wants to authenticate the server and encrypt all data. The example is in C++,
|
||||
but the API is similar for all languages: you can see how to enable SSL/TLS in
|
||||
more languages in our Examples section below.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#75715e">// Create a default SSL ChannelCredentials object.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">auto</span> channel_creds <span style="color:#f92672">=</span> grpc<span style="color:#f92672">::</span>SslCredentials(grpc<span style="color:#f92672">::</span>SslCredentialsOptions());
|
||||
<span style="color:#75715e">// Create a channel using the credentials created in the previous step.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">auto</span> channel <span style="color:#f92672">=</span> grpc<span style="color:#f92672">::</span>CreateChannel(server_name, channel_creds);
|
||||
<span style="color:#75715e">// Create a stub on the channel.
|
||||
</span><span style="color:#75715e"></span>std<span style="color:#f92672">::</span>unique_ptr<span style="color:#f92672"><</span>Greeter<span style="color:#f92672">::</span>Stub<span style="color:#f92672">></span> stub(Greeter<span style="color:#f92672">::</span>NewStub(channel));
|
||||
<span style="color:#75715e">// Make actual RPC calls on the stub.
|
||||
</span><span style="color:#75715e"></span>grpc<span style="color:#f92672">::</span>Status s <span style="color:#f92672">=</span> stub<span style="color:#f92672">-></span>sayHello(<span style="color:#f92672">&</span>context, <span style="color:#f92672">*</span>request, response);
|
||||
</code></pre></div>
|
||||
<p>For advanced use cases such as modifying the root CA or using client certs,
|
||||
the corresponding options can be set in the <code>SslCredentialsOptions</code> parameter
|
||||
passed to the factory method.</p>
|
||||
|
||||
<h4 id="using-google-token-based-authentication">Using Google token-based authentication</h4>
|
||||
|
||||
<p>gRPC applications can use a simple API to create a credential that works for
|
||||
authentication with Google in various deployment scenarios. Again, our example
|
||||
is in C++ but you can find examples in other languages in our Examples section.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#66d9ef">auto</span> creds <span style="color:#f92672">=</span> grpc<span style="color:#f92672">::</span>GoogleDefaultCredentials();
|
||||
<span style="color:#75715e">// Create a channel, stub and make RPC calls (same as in the previous example)
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">auto</span> channel <span style="color:#f92672">=</span> grpc<span style="color:#f92672">::</span>CreateChannel(server_name, creds);
|
||||
std<span style="color:#f92672">::</span>unique_ptr<span style="color:#f92672"><</span>Greeter<span style="color:#f92672">::</span>Stub<span style="color:#f92672">></span> stub(Greeter<span style="color:#f92672">::</span>NewStub(channel));
|
||||
grpc<span style="color:#f92672">::</span>Status s <span style="color:#f92672">=</span> stub<span style="color:#f92672">-></span>sayHello(<span style="color:#f92672">&</span>context, <span style="color:#f92672">*</span>request, response);
|
||||
</code></pre></div>
|
||||
<p>This channel credentials object works for applications using Service Accounts as
|
||||
well as for applications running in <a href="https://cloud.google.com/compute/">Google Compute Engine
|
||||
(GCE)</a>. In the former case, the service
|
||||
account’s private keys are loaded from the file named in the environment
|
||||
variable <code>GOOGLE_APPLICATION_CREDENTIALS</code>. The keys are used to generate bearer
|
||||
tokens that are attached to each outgoing RPC on the corresponding channel.</p>
|
||||
|
||||
<p>For applications running in GCE, a default service account and corresponding
|
||||
OAuth2 scopes can be configured during VM setup. At run-time, this credential
|
||||
handles communication with the authentication systems to obtain OAuth2 access
|
||||
tokens and attaches them to each outgoing RPC on the corresponding channel.</p>
|
||||
|
||||
<h4 id="extending-grpc-to-support-other-authentication-mechanisms">Extending gRPC to support other authentication mechanisms</h4>
|
||||
|
||||
<p>The Credentials plugin API allows developers to plug in their own type of
|
||||
credentials. This consists of:</p>
|
||||
|
||||
<ul>
|
||||
<li>The <code>MetadataCredentialsPlugin</code> abstract class, which contains the pure virtual
|
||||
<code>GetMetadata</code> method that needs to be implemented by a sub-class created by
|
||||
the developer.</li>
|
||||
<li>The <code>MetadataCredentialsFromPlugin</code> function, which creates a <code>CallCredentials</code>
|
||||
from the <code>MetadataCredentialsPlugin</code>.</li>
|
||||
</ul>
|
||||
|
||||
<p>Here is example of a simple credentials plugin which sets an authentication
|
||||
ticket in a custom header.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#66d9ef">class</span><span style="color:#960050;background-color:#1e0010"> </span><span style="color:#a6e22e">MyCustomAuthenticator</span> <span style="color:#f92672">:</span> <span style="color:#66d9ef">public</span> grpc<span style="color:#f92672">::</span>MetadataCredentialsPlugin {
|
||||
<span style="color:#66d9ef">public</span><span style="color:#f92672">:</span>
|
||||
MyCustomAuthenticator(<span style="color:#66d9ef">const</span> grpc<span style="color:#f92672">::</span>string<span style="color:#f92672">&</span> ticket) <span style="color:#f92672">:</span> ticket_(ticket) {}
|
||||
|
||||
grpc<span style="color:#f92672">::</span>Status GetMetadata(
|
||||
grpc<span style="color:#f92672">::</span>string_ref service_url, grpc<span style="color:#f92672">::</span>string_ref method_name,
|
||||
<span style="color:#66d9ef">const</span> grpc<span style="color:#f92672">::</span>AuthContext<span style="color:#f92672">&</span> channel_auth_context,
|
||||
std<span style="color:#f92672">::</span>multimap<span style="color:#f92672"><</span>grpc<span style="color:#f92672">::</span>string, grpc<span style="color:#f92672">::</span>string<span style="color:#f92672">>*</span> metadata) <span style="color:#66d9ef">override</span> {
|
||||
metadata<span style="color:#f92672">-></span>insert(std<span style="color:#f92672">::</span>make_pair(<span style="color:#e6db74">"x-custom-auth-ticket"</span>, ticket_));
|
||||
<span style="color:#66d9ef">return</span> grpc<span style="color:#f92672">::</span>Status<span style="color:#f92672">::</span>OK;
|
||||
}
|
||||
|
||||
<span style="color:#66d9ef">private</span><span style="color:#f92672">:</span>
|
||||
grpc<span style="color:#f92672">::</span>string ticket_;
|
||||
};
|
||||
|
||||
<span style="color:#66d9ef">auto</span> call_creds <span style="color:#f92672">=</span> grpc<span style="color:#f92672">::</span>MetadataCredentialsFromPlugin(
|
||||
std<span style="color:#f92672">::</span>unique_ptr<span style="color:#f92672"><</span>grpc<span style="color:#f92672">::</span>MetadataCredentialsPlugin<span style="color:#f92672">></span>(
|
||||
<span style="color:#66d9ef">new</span> MyCustomAuthenticator(<span style="color:#e6db74">"super-secret-ticket"</span>)));
|
||||
</code></pre></div>
|
||||
<p>A deeper integration can be achieved by plugging in a gRPC credentials
|
||||
implementation at the core level. gRPC internals also allow switching out
|
||||
SSL/TLS with other encryption mechanisms.</p>
|
||||
|
||||
<h3 id="examples">Examples</h3>
|
||||
|
||||
<p>These authentication mechanisms will be available in all gRPC’s supported
|
||||
languages. The following sections demonstrate how authentication and
|
||||
authorization features described above appear in each language: more languages
|
||||
are coming soon.</p>
|
||||
|
||||
<h4 id="go">Go</h4>
|
||||
|
||||
<h5 id="base-case-no-encryption-or-authentication">Base case - no encryption or authentication</h5>
|
||||
|
||||
<p>Client:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#a6e22e">conn</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">Dial</span>(<span style="color:#e6db74">"localhost:50051"</span>, <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">WithInsecure</span>())
|
||||
<span style="color:#75715e">// error handling omitted
|
||||
</span><span style="color:#75715e"></span><span style="color:#a6e22e">client</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">pb</span>.<span style="color:#a6e22e">NewGreeterClient</span>(<span style="color:#a6e22e">conn</span>)
|
||||
<span style="color:#f92672">//</span> <span style="color:#f92672">...</span></code></pre></div>
|
||||
<p>Server:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#a6e22e">s</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">NewServer</span>()
|
||||
<span style="color:#a6e22e">lis</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">net</span>.<span style="color:#a6e22e">Listen</span>(<span style="color:#e6db74">"tcp"</span>, <span style="color:#e6db74">"localhost:50051"</span>)
|
||||
<span style="color:#75715e">// error handling omitted
|
||||
</span><span style="color:#75715e"></span><span style="color:#a6e22e">s</span>.<span style="color:#a6e22e">Serve</span>(<span style="color:#a6e22e">lis</span>)</code></pre></div>
|
||||
<h5 id="with-server-authentication-ssl-tls">With server authentication SSL/TLS</h5>
|
||||
|
||||
<p>Client:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#a6e22e">creds</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">credentials</span>.<span style="color:#a6e22e">NewClientTLSFromFile</span>(<span style="color:#a6e22e">certFile</span>, <span style="color:#e6db74">""</span>)
|
||||
<span style="color:#a6e22e">conn</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">Dial</span>(<span style="color:#e6db74">"localhost:50051"</span>, <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">WithTransportCredentials</span>(<span style="color:#a6e22e">creds</span>))
|
||||
<span style="color:#75715e">// error handling omitted
|
||||
</span><span style="color:#75715e"></span><span style="color:#a6e22e">client</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">pb</span>.<span style="color:#a6e22e">NewGreeterClient</span>(<span style="color:#a6e22e">conn</span>)
|
||||
<span style="color:#f92672">//</span> <span style="color:#f92672">...</span></code></pre></div>
|
||||
<p>Server:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#a6e22e">creds</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">credentials</span>.<span style="color:#a6e22e">NewServerTLSFromFile</span>(<span style="color:#a6e22e">certFile</span>, <span style="color:#a6e22e">keyFile</span>)
|
||||
<span style="color:#a6e22e">s</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">NewServer</span>(<span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">Creds</span>(<span style="color:#a6e22e">creds</span>))
|
||||
<span style="color:#a6e22e">lis</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">net</span>.<span style="color:#a6e22e">Listen</span>(<span style="color:#e6db74">"tcp"</span>, <span style="color:#e6db74">"localhost:50051"</span>)
|
||||
<span style="color:#75715e">// error handling omitted
|
||||
</span><span style="color:#75715e"></span><span style="color:#a6e22e">s</span>.<span style="color:#a6e22e">Serve</span>(<span style="color:#a6e22e">lis</span>)</code></pre></div>
|
||||
<h5 id="authenticate-with-google">Authenticate with Google</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#a6e22e">pool</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">x509</span>.<span style="color:#a6e22e">SystemCertPool</span>()
|
||||
<span style="color:#75715e">// error handling omitted
|
||||
</span><span style="color:#75715e"></span><span style="color:#a6e22e">creds</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">credentials</span>.<span style="color:#a6e22e">NewClientTLSFromCert</span>(<span style="color:#a6e22e">pool</span>, <span style="color:#e6db74">""</span>)
|
||||
<span style="color:#a6e22e">perRPC</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">oauth</span>.<span style="color:#a6e22e">NewServiceAccountFromFile</span>(<span style="color:#e6db74">"service-account.json"</span>, <span style="color:#a6e22e">scope</span>)
|
||||
<span style="color:#a6e22e">conn</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">Dial</span>(
|
||||
<span style="color:#e6db74">"greeter.googleapis.com"</span>,
|
||||
<span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">WithTransportCredentials</span>(<span style="color:#a6e22e">creds</span>),
|
||||
<span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">WithPerRPCCredentials</span>(<span style="color:#a6e22e">perRPC</span>),
|
||||
)
|
||||
<span style="color:#75715e">// error handling omitted
|
||||
</span><span style="color:#75715e"></span><span style="color:#a6e22e">client</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">pb</span>.<span style="color:#a6e22e">NewGreeterClient</span>(<span style="color:#a6e22e">conn</span>)
|
||||
<span style="color:#f92672">//</span> <span style="color:#f92672">...</span></code></pre></div>
|
||||
<h4 id="ruby">Ruby</h4>
|
||||
|
||||
<h5 id="base-case-no-encryption-or-authentication-1">Base case - no encryption or authentication</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby">stub <span style="color:#f92672">=</span> <span style="color:#66d9ef">Helloworld</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Greeter</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Stub</span><span style="color:#f92672">.</span>new(<span style="color:#e6db74">'localhost:50051'</span>, <span style="color:#e6db74">:this_channel_is_insecure</span>)
|
||||
<span style="color:#f92672">...</span></code></pre></div>
|
||||
<h5 id="with-server-authentication-ssl-tls-1">With server authentication SSL/TLS</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby">creds <span style="color:#f92672">=</span> <span style="color:#66d9ef">GRPC</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Core</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Credentials</span><span style="color:#f92672">.</span>new(load_certs) <span style="color:#75715e"># load_certs typically loads a CA roots file</span>
|
||||
stub <span style="color:#f92672">=</span> <span style="color:#66d9ef">Helloworld</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Greeter</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Stub</span><span style="color:#f92672">.</span>new(<span style="color:#e6db74">'myservice.example.com'</span>, creds)</code></pre></div>
|
||||
<h5 id="authenticate-with-google-1">Authenticate with Google</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby">require <span style="color:#e6db74">'googleauth'</span> <span style="color:#75715e"># from http://www.rubydoc.info/gems/googleauth/0.1.0</span>
|
||||
<span style="color:#f92672">...</span>
|
||||
ssl_creds <span style="color:#f92672">=</span> <span style="color:#66d9ef">GRPC</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Core</span><span style="color:#f92672">::</span><span style="color:#66d9ef">ChannelCredentials</span><span style="color:#f92672">.</span>new(load_certs) <span style="color:#75715e"># load_certs typically loads a CA roots file</span>
|
||||
authentication <span style="color:#f92672">=</span> <span style="color:#66d9ef">Google</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Auth</span><span style="color:#f92672">.</span>get_application_default()
|
||||
call_creds <span style="color:#f92672">=</span> <span style="color:#66d9ef">GRPC</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Core</span><span style="color:#f92672">::</span><span style="color:#66d9ef">CallCredentials</span><span style="color:#f92672">.</span>new(authentication<span style="color:#f92672">.</span>updater_proc)
|
||||
combined_creds <span style="color:#f92672">=</span> ssl_creds<span style="color:#f92672">.</span>compose(call_creds)
|
||||
stub <span style="color:#f92672">=</span> <span style="color:#66d9ef">Helloworld</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Greeter</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Stub</span><span style="color:#f92672">.</span>new(<span style="color:#e6db74">'greeter.googleapis.com'</span>, combined_creds)</code></pre></div>
|
||||
<h4 id="c">C++</h4>
|
||||
|
||||
<h5 id="base-case-no-encryption-or-authentication-2">Base case - no encryption or authentication</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#66d9ef">auto</span> channel <span style="color:#f92672">=</span> grpc<span style="color:#f92672">::</span>CreateChannel(<span style="color:#e6db74">"localhost:50051"</span>, InsecureChannelCredentials());
|
||||
std<span style="color:#f92672">::</span>unique_ptr<span style="color:#f92672"><</span>Greeter<span style="color:#f92672">::</span>Stub<span style="color:#f92672">></span> stub(Greeter<span style="color:#f92672">::</span>NewStub(channel));
|
||||
...
|
||||
</code></pre></div>
|
||||
<h5 id="with-server-authentication-ssl-tls-2">With server authentication SSL/TLS</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#66d9ef">auto</span> channel_creds <span style="color:#f92672">=</span> grpc<span style="color:#f92672">::</span>SslCredentials(grpc<span style="color:#f92672">::</span>SslCredentialsOptions());
|
||||
<span style="color:#66d9ef">auto</span> channel <span style="color:#f92672">=</span> grpc<span style="color:#f92672">::</span>CreateChannel(<span style="color:#e6db74">"myservice.example.com"</span>, channel_creds);
|
||||
std<span style="color:#f92672">::</span>unique_ptr<span style="color:#f92672"><</span>Greeter<span style="color:#f92672">::</span>Stub<span style="color:#f92672">></span> stub(Greeter<span style="color:#f92672">::</span>NewStub(channel));
|
||||
...
|
||||
</code></pre></div>
|
||||
<h5 id="authenticate-with-google-2">Authenticate with Google</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#66d9ef">auto</span> creds <span style="color:#f92672">=</span> grpc<span style="color:#f92672">::</span>GoogleDefaultCredentials();
|
||||
<span style="color:#66d9ef">auto</span> channel <span style="color:#f92672">=</span> grpc<span style="color:#f92672">::</span>CreateChannel(<span style="color:#e6db74">"greeter.googleapis.com"</span>, creds);
|
||||
std<span style="color:#f92672">::</span>unique_ptr<span style="color:#f92672"><</span>Greeter<span style="color:#f92672">::</span>Stub<span style="color:#f92672">></span> stub(Greeter<span style="color:#f92672">::</span>NewStub(channel));
|
||||
...
|
||||
</code></pre></div>
|
||||
<h4 id="c-35">C#</h4>
|
||||
|
||||
<h5 id="base-case-no-encryption-or-authentication-3">Base case - no encryption or authentication</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-csharp" data-lang="csharp"><span style="color:#66d9ef">var</span> channel = <span style="color:#66d9ef">new</span> Channel(<span style="color:#e6db74">"localhost:50051"</span>, ChannelCredentials.Insecure);
|
||||
<span style="color:#66d9ef">var</span> client = <span style="color:#66d9ef">new</span> Greeter.GreeterClient(channel);
|
||||
...
|
||||
</code></pre></div>
|
||||
<h5 id="with-server-authentication-ssl-tls-3">With server authentication SSL/TLS</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-csharp" data-lang="csharp"><span style="color:#66d9ef">var</span> channelCredentials = <span style="color:#66d9ef">new</span> SslCredentials(File.ReadAllText(<span style="color:#e6db74">"roots.pem"</span>)); <span style="color:#75715e">// Load a custom roots file.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">var</span> channel = <span style="color:#66d9ef">new</span> Channel(<span style="color:#e6db74">"myservice.example.com"</span>, channelCredentials);
|
||||
<span style="color:#66d9ef">var</span> client = <span style="color:#66d9ef">new</span> Greeter.GreeterClient(channel);
|
||||
</code></pre></div>
|
||||
<h5 id="authenticate-with-google-3">Authenticate with Google</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-csharp" data-lang="csharp"><span style="color:#66d9ef">using</span> Grpc.Auth; <span style="color:#75715e">// from Grpc.Auth NuGet package
|
||||
</span><span style="color:#75715e"></span>...
|
||||
<span style="color:#75715e">// Loads Google Application Default Credentials with publicly trusted roots.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">var</span> channelCredentials = <span style="color:#66d9ef">await</span> GoogleGrpcCredentials.GetApplicationDefaultAsync();
|
||||
|
||||
<span style="color:#66d9ef">var</span> channel = <span style="color:#66d9ef">new</span> Channel(<span style="color:#e6db74">"greeter.googleapis.com"</span>, channelCredentials);
|
||||
<span style="color:#66d9ef">var</span> client = <span style="color:#66d9ef">new</span> Greeter.GreeterClient(channel);
|
||||
...
|
||||
</code></pre></div>
|
||||
<h5 id="authenticate-a-single-rpc-call">Authenticate a single RPC call</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-csharp" data-lang="csharp"><span style="color:#66d9ef">var</span> channel = <span style="color:#66d9ef">new</span> Channel(<span style="color:#e6db74">"greeter.googleapis.com"</span>, <span style="color:#66d9ef">new</span> SslCredentials()); <span style="color:#75715e">// Use publicly trusted roots.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">var</span> client = <span style="color:#66d9ef">new</span> Greeter.GreeterClient(channel);
|
||||
...
|
||||
<span style="color:#66d9ef">var</span> googleCredential = <span style="color:#66d9ef">await</span> GoogleCredential.GetApplicationDefaultAsync();
|
||||
<span style="color:#66d9ef">var</span> result = client.SayHello(request, <span style="color:#66d9ef">new</span> CallOptions(credentials: googleCredential.ToCallCredentials()));
|
||||
...
|
||||
</code></pre></div>
|
||||
<h4 id="python">Python</h4>
|
||||
|
||||
<h5 id="base-case-no-encryption-or-authentication-4">Base case - No encryption or authentication</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> grpc
|
||||
<span style="color:#f92672">import</span> helloworld_pb2
|
||||
|
||||
channel <span style="color:#f92672">=</span> grpc<span style="color:#f92672">.</span>insecure_channel(<span style="color:#e6db74">'localhost:50051'</span>)
|
||||
stub <span style="color:#f92672">=</span> helloworld_pb2<span style="color:#f92672">.</span>GreeterStub(channel)</code></pre></div>
|
||||
<h5 id="with-server-authentication-ssl-tls-4">With server authentication SSL/TLS</h5>
|
||||
|
||||
<p>Client:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> grpc
|
||||
<span style="color:#f92672">import</span> helloworld_pb2
|
||||
|
||||
<span style="color:#66d9ef">with</span> open(<span style="color:#e6db74">'roots.pem'</span>, <span style="color:#e6db74">'rb'</span>) <span style="color:#66d9ef">as</span> f:
|
||||
creds <span style="color:#f92672">=</span> grpc<span style="color:#f92672">.</span>ssl_channel_credentials(f<span style="color:#f92672">.</span>read())
|
||||
channel <span style="color:#f92672">=</span> grpc<span style="color:#f92672">.</span>secure_channel(<span style="color:#e6db74">'myservice.example.com:443'</span>, creds)
|
||||
stub <span style="color:#f92672">=</span> helloworld_pb2<span style="color:#f92672">.</span>GreeterStub(channel)</code></pre></div>
|
||||
<p>Server:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> grpc
|
||||
<span style="color:#f92672">import</span> helloworld_pb2
|
||||
<span style="color:#f92672">from</span> concurrent <span style="color:#f92672">import</span> futures
|
||||
|
||||
server <span style="color:#f92672">=</span> grpc<span style="color:#f92672">.</span>server(futures<span style="color:#f92672">.</span>ThreadPoolExecutor(max_workers<span style="color:#f92672">=</span><span style="color:#ae81ff">10</span>))
|
||||
<span style="color:#66d9ef">with</span> open(<span style="color:#e6db74">'key.pem'</span>, <span style="color:#e6db74">'rb'</span>) <span style="color:#66d9ef">as</span> f:
|
||||
private_key <span style="color:#f92672">=</span> f<span style="color:#f92672">.</span>read()
|
||||
<span style="color:#66d9ef">with</span> open(<span style="color:#e6db74">'chain.pem'</span>, <span style="color:#e6db74">'rb'</span>) <span style="color:#66d9ef">as</span> f:
|
||||
certificate_chain <span style="color:#f92672">=</span> f<span style="color:#f92672">.</span>read()
|
||||
server_credentials <span style="color:#f92672">=</span> grpc<span style="color:#f92672">.</span>ssl_server_credentials( ( (private_key, certificate_chain), ) )
|
||||
<span style="color:#75715e"># Adding GreeterServicer to server omitted</span>
|
||||
server<span style="color:#f92672">.</span>add_secure_port(<span style="color:#e6db74">'myservice.example.com:443'</span>, server_credentials)
|
||||
server<span style="color:#f92672">.</span>start()
|
||||
<span style="color:#75715e"># Server sleep omitted</span></code></pre></div>
|
||||
<h5 id="authenticate-with-google-using-a-jwt">Authenticate with Google using a JWT</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> grpc
|
||||
<span style="color:#f92672">import</span> helloworld_pb2
|
||||
|
||||
<span style="color:#f92672">from</span> google <span style="color:#f92672">import</span> auth <span style="color:#66d9ef">as</span> google_auth
|
||||
<span style="color:#f92672">from</span> google.auth <span style="color:#f92672">import</span> jwt <span style="color:#66d9ef">as</span> google_auth_jwt
|
||||
<span style="color:#f92672">from</span> google.auth.transport <span style="color:#f92672">import</span> grpc <span style="color:#66d9ef">as</span> google_auth_transport_grpc
|
||||
|
||||
credentials, _ <span style="color:#f92672">=</span> google_auth<span style="color:#f92672">.</span>default()
|
||||
jwt_creds <span style="color:#f92672">=</span> google_auth_jwt<span style="color:#f92672">.</span>OnDemandCredentials<span style="color:#f92672">.</span>from_signing_credentials(
|
||||
credentials)
|
||||
channel <span style="color:#f92672">=</span> google_auth_transport_grpc<span style="color:#f92672">.</span>secure_authorized_channel(
|
||||
jwt_creds, None, <span style="color:#e6db74">'greeter.googleapis.com:443'</span>)
|
||||
stub <span style="color:#f92672">=</span> helloworld_pb2<span style="color:#f92672">.</span>GreeterStub(channel)</code></pre></div>
|
||||
<h5 id="authenticate-with-google-using-an-oauth2-token">Authenticate with Google using an Oauth2 token</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> grpc
|
||||
<span style="color:#f92672">import</span> helloworld_pb2
|
||||
|
||||
<span style="color:#f92672">from</span> google <span style="color:#f92672">import</span> auth <span style="color:#66d9ef">as</span> google_auth
|
||||
<span style="color:#f92672">from</span> google.auth.transport <span style="color:#f92672">import</span> grpc <span style="color:#66d9ef">as</span> google_auth_transport_grpc
|
||||
<span style="color:#f92672">from</span> google.auth.transport <span style="color:#f92672">import</span> requests <span style="color:#66d9ef">as</span> google_auth_transport_requests
|
||||
|
||||
credentials, _ <span style="color:#f92672">=</span> google_auth<span style="color:#f92672">.</span>default(scopes<span style="color:#f92672">=</span>(scope,))
|
||||
request <span style="color:#f92672">=</span> google_auth_transport_requests<span style="color:#f92672">.</span>Request()
|
||||
channel <span style="color:#f92672">=</span> google_auth_transport_grpc<span style="color:#f92672">.</span>secure_authorized_channel(
|
||||
credentials, request, <span style="color:#e6db74">'greeter.googleapis.com:443'</span>)
|
||||
stub <span style="color:#f92672">=</span> helloworld_pb2<span style="color:#f92672">.</span>GreeterStub(channel)</code></pre></div>
|
||||
<h4 id="java">Java</h4>
|
||||
|
||||
<h5 id="base-case-no-encryption-or-authentication-5">Base case - no encryption or authentication</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">ManagedChannel channel <span style="color:#f92672">=</span> ManagedChannelBuilder<span style="color:#f92672">.</span><span style="color:#a6e22e">forAddress</span><span style="color:#f92672">(</span><span style="color:#e6db74">"localhost"</span><span style="color:#f92672">,</span> 50051<span style="color:#f92672">)</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">usePlaintext</span><span style="color:#f92672">(</span><span style="color:#66d9ef">true</span><span style="color:#f92672">)</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">build</span><span style="color:#f92672">();</span>
|
||||
GreeterGrpc<span style="color:#f92672">.</span><span style="color:#a6e22e">GreeterStub</span> stub <span style="color:#f92672">=</span> GreeterGrpc<span style="color:#f92672">.</span><span style="color:#a6e22e">newStub</span><span style="color:#f92672">(</span>channel<span style="color:#f92672">);</span></code></pre></div>
|
||||
<h5 id="with-server-authentication-ssl-tls-5">With server authentication SSL/TLS</h5>
|
||||
|
||||
<p>In Java we recommend that you use OpenSSL when using gRPC over TLS. You can find
|
||||
details about installing and using OpenSSL and other required libraries for both
|
||||
Android and non-Android Java in the gRPC Java
|
||||
<a href="https://github.com/grpc/grpc-java/blob/master/SECURITY.md#transport-security-tls">Security</a>
|
||||
documentation.</p>
|
||||
|
||||
<p>To enable TLS on a server, a certificate chain and private key need to be
|
||||
specified in PEM format. Such private key should not be using a password.
|
||||
The order of certificates in the chain matters: more specifically, the certificate
|
||||
at the top has to be the host CA, while the one at the very bottom
|
||||
has to be the root CA. The standard TLS port is 443, but we use 8443 below to
|
||||
avoid needing extra permissions from the OS.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">Server server <span style="color:#f92672">=</span> ServerBuilder<span style="color:#f92672">.</span><span style="color:#a6e22e">forPort</span><span style="color:#f92672">(</span>8443<span style="color:#f92672">)</span>
|
||||
<span style="color:#75715e">// Enable TLS
|
||||
</span><span style="color:#75715e"></span> <span style="color:#f92672">.</span><span style="color:#a6e22e">useTransportSecurity</span><span style="color:#f92672">(</span>certChainFile<span style="color:#f92672">,</span> privateKeyFile<span style="color:#f92672">)</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">addService</span><span style="color:#f92672">(</span>TestServiceGrpc<span style="color:#f92672">.</span><span style="color:#a6e22e">bindService</span><span style="color:#f92672">(</span>serviceImplementation<span style="color:#f92672">))</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">build</span><span style="color:#f92672">();</span>
|
||||
server<span style="color:#f92672">.</span><span style="color:#a6e22e">start</span><span style="color:#f92672">();</span></code></pre></div>
|
||||
<p>If the issuing certificate authority is not known to the client then a properly
|
||||
configured <code>SslContext</code> or <code>SSLSocketFactory</code> should be provided to the
|
||||
<code>NettyChannelBuilder</code> or <code>OkHttpChannelBuilder</code>, respectively.</p>
|
||||
|
||||
<p>On the client side, server authentication with SSL/TLS looks like this:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#75715e">// With server authentication SSL/TLS
|
||||
</span><span style="color:#75715e"></span>ManagedChannel channel <span style="color:#f92672">=</span> ManagedChannelBuilder<span style="color:#f92672">.</span><span style="color:#a6e22e">forAddress</span><span style="color:#f92672">(</span><span style="color:#e6db74">"myservice.example.com"</span><span style="color:#f92672">,</span> 443<span style="color:#f92672">)</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">build</span><span style="color:#f92672">();</span>
|
||||
GreeterGrpc<span style="color:#f92672">.</span><span style="color:#a6e22e">GreeterStub</span> stub <span style="color:#f92672">=</span> GreeterGrpc<span style="color:#f92672">.</span><span style="color:#a6e22e">newStub</span><span style="color:#f92672">(</span>channel<span style="color:#f92672">);</span>
|
||||
|
||||
<span style="color:#75715e">// With server authentication SSL/TLS; custom CA root certificates; not on Android
|
||||
</span><span style="color:#75715e"></span>ManagedChannel channel <span style="color:#f92672">=</span> NettyChannelBuilder<span style="color:#f92672">.</span><span style="color:#a6e22e">forAddress</span><span style="color:#f92672">(</span><span style="color:#e6db74">"myservice.example.com"</span><span style="color:#f92672">,</span> 443<span style="color:#f92672">)</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">sslContext</span><span style="color:#f92672">(</span>GrpcSslContexts<span style="color:#f92672">.</span><span style="color:#a6e22e">forClient</span><span style="color:#f92672">().</span><span style="color:#a6e22e">trustManager</span><span style="color:#f92672">(</span><span style="color:#66d9ef">new</span> File<span style="color:#f92672">(</span><span style="color:#e6db74">"roots.pem"</span><span style="color:#f92672">)).</span><span style="color:#a6e22e">build</span><span style="color:#f92672">())</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">build</span><span style="color:#f92672">();</span>
|
||||
GreeterGrpc<span style="color:#f92672">.</span><span style="color:#a6e22e">GreeterStub</span> stub <span style="color:#f92672">=</span> GreeterGrpc<span style="color:#f92672">.</span><span style="color:#a6e22e">newStub</span><span style="color:#f92672">(</span>channel<span style="color:#f92672">);</span></code></pre></div>
|
||||
<h5 id="authenticate-with-google-4">Authenticate with Google</h5>
|
||||
|
||||
<p>The following code snippet shows how you can call the <a href="https://cloud.google.com/pubsub/overview">Google Cloud PubSub
|
||||
API</a> using gRPC with a service
|
||||
account. The credentials are loaded from a key stored in a well-known location
|
||||
or by detecting that the application is running in an environment that can
|
||||
provide one automatically, e.g. Google Compute Engine. While this example is
|
||||
specific to Google and its services, similar patterns can be followed for other
|
||||
service providers.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">GoogleCredentials creds <span style="color:#f92672">=</span> GoogleCredentials<span style="color:#f92672">.</span><span style="color:#a6e22e">getApplicationDefault</span><span style="color:#f92672">();</span>
|
||||
ManagedChannel channel <span style="color:#f92672">=</span> ManagedChannelBuilder<span style="color:#f92672">.</span><span style="color:#a6e22e">forTarget</span><span style="color:#f92672">(</span><span style="color:#e6db74">"greeter.googleapis.com"</span><span style="color:#f92672">)</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">build</span><span style="color:#f92672">();</span>
|
||||
GreeterGrpc<span style="color:#f92672">.</span><span style="color:#a6e22e">GreeterStub</span> stub <span style="color:#f92672">=</span> GreeterGrpc<span style="color:#f92672">.</span><span style="color:#a6e22e">newStub</span><span style="color:#f92672">(</span>channel<span style="color:#f92672">)</span>
|
||||
<span style="color:#f92672">.</span><span style="color:#a6e22e">withCallCredentials</span><span style="color:#f92672">(</span>MoreCallCredentials<span style="color:#f92672">.</span><span style="color:#a6e22e">from</span><span style="color:#f92672">(</span>creds<span style="color:#f92672">));</span></code></pre></div>
|
||||
<h4 id="node-js">Node.js</h4>
|
||||
|
||||
<h5 id="base-case-no-encryption-authentication">Base case - No encryption/authentication</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">stub</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">helloworld</span>.<span style="color:#a6e22e">Greeter</span>(<span style="color:#e6db74">'localhost:50051'</span>, <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">credentials</span>.<span style="color:#a6e22e">createInsecure</span>());
|
||||
</code></pre></div>
|
||||
<h5 id="with-server-authentication-ssl-tls-6">With server authentication SSL/TLS</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">ssl_creds</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">credentials</span>.<span style="color:#a6e22e">createSsl</span>(<span style="color:#a6e22e">root_certs</span>);
|
||||
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">stub</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">helloworld</span>.<span style="color:#a6e22e">Greeter</span>(<span style="color:#e6db74">'myservice.example.com'</span>, <span style="color:#a6e22e">ssl_creds</span>);
|
||||
</code></pre></div>
|
||||
<h5 id="authenticate-with-google-5">Authenticate with Google</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#75715e">// Authenticating with Google
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">GoogleAuth</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">'google-auth-library'</span>); <span style="color:#75715e">// from https://www.npmjs.com/package/google-auth-library
|
||||
</span><span style="color:#75715e"></span>...
|
||||
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">ssl_creds</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">credentials</span>.<span style="color:#a6e22e">createSsl</span>(<span style="color:#a6e22e">root_certs</span>);
|
||||
(<span style="color:#66d9ef">new</span> <span style="color:#a6e22e">GoogleAuth</span>()).<span style="color:#a6e22e">getApplicationDefault</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">err</span>, <span style="color:#a6e22e">auth</span>) {
|
||||
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">call_creds</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">credentials</span>.<span style="color:#a6e22e">createFromGoogleCredential</span>(<span style="color:#a6e22e">auth</span>);
|
||||
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">combined_creds</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">credentials</span>.<span style="color:#a6e22e">combineChannelCredentials</span>(<span style="color:#a6e22e">ssl_creds</span>, <span style="color:#a6e22e">call_creds</span>);
|
||||
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">stub</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">helloworld</span>.<span style="color:#a6e22e">Greeter</span>(<span style="color:#e6db74">'greeter.googleapis.com'</span>, <span style="color:#a6e22e">combined_credentials</span>);
|
||||
});
|
||||
</code></pre></div>
|
||||
<h5 id="authenticate-with-google-using-oauth2-token-legacy-approach">Authenticate with Google using Oauth2 token (legacy approach)</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">GoogleAuth</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">'google-auth-library'</span>); <span style="color:#75715e">// from https://www.npmjs.com/package/google-auth-library
|
||||
</span><span style="color:#75715e"></span>...
|
||||
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">ssl_creds</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">Credentials</span>.<span style="color:#a6e22e">createSsl</span>(<span style="color:#a6e22e">root_certs</span>); <span style="color:#75715e">// load_certs typically loads a CA roots file
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">scope</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">'https://www.googleapis.com/auth/grpc-testing'</span>;
|
||||
(<span style="color:#66d9ef">new</span> <span style="color:#a6e22e">GoogleAuth</span>()).<span style="color:#a6e22e">getApplicationDefault</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">err</span>, <span style="color:#a6e22e">auth</span>) {
|
||||
<span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">auth</span>.<span style="color:#a6e22e">createScopeRequired</span>()) {
|
||||
<span style="color:#a6e22e">auth</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">auth</span>.<span style="color:#a6e22e">createScoped</span>(<span style="color:#a6e22e">scope</span>);
|
||||
}
|
||||
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">call_creds</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">credentials</span>.<span style="color:#a6e22e">createFromGoogleCredential</span>(<span style="color:#a6e22e">auth</span>);
|
||||
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">combined_creds</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">grpc</span>.<span style="color:#a6e22e">credentials</span>.<span style="color:#a6e22e">combineChannelCredentials</span>(<span style="color:#a6e22e">ssl_creds</span>, <span style="color:#a6e22e">call_creds</span>);
|
||||
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">stub</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">helloworld</span>.<span style="color:#a6e22e">Greeter</span>(<span style="color:#e6db74">'greeter.googleapis.com'</span>, <span style="color:#a6e22e">combined_credentials</span>);
|
||||
});
|
||||
</code></pre></div>
|
||||
<h4 id="php">PHP</h4>
|
||||
|
||||
<h5 id="base-case-no-encryption-authorization">Base case - No encryption/authorization</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">$client = new helloworld\GreeterClient('localhost:50051', [
|
||||
'credentials' => Grpc\ChannelCredentials::createInsecure(),
|
||||
]);
|
||||
...</code></pre></div>
|
||||
<h5 id="authenticate-with-google-6">Authenticate with Google</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">function updateAuthMetadataCallback($context)
|
||||
{
|
||||
$auth_credentials = ApplicationDefaultCredentials::getCredentials();
|
||||
return $auth_credentials->updateMetadata($metadata = [], $context->service_url);
|
||||
}
|
||||
$channel_credentials = Grpc\ChannelCredentials::createComposite(
|
||||
Grpc\ChannelCredentials::createSsl(file_get_contents('roots.pem')),
|
||||
Grpc\CallCredentials::createFromPlugin('updateAuthMetadataCallback')
|
||||
);
|
||||
$opts = [
|
||||
'credentials' => $channel_credentials
|
||||
];
|
||||
$client = new helloworld\GreeterClient('greeter.googleapis.com', $opts);
|
||||
````
|
||||
|
||||
##### Authenticate with Google using Oauth2 token (legacy approach)
|
||||
|
||||
```php
|
||||
// the environment variable "GOOGLE_APPLICATION_CREDENTIALS" needs to be set
|
||||
$scope = "https://www.googleapis.com/auth/grpc-testing";
|
||||
$auth = Google\Auth\ApplicationDefaultCredentials::getCredentials($scope);
|
||||
$opts = [
|
||||
'credentials' => Grpc\Credentials::createSsl(file_get_contents('roots.pem'));
|
||||
'update_metadata' => $auth->getUpdateMetadataFunc(),
|
||||
];
|
||||
$client = new helloworld\GreeterClient('greeter.googleapis.com', $opts);</code></pre></div>
|
||||
<h4 id="dart">Dart</h4>
|
||||
|
||||
<h5 id="base-case-no-encryption-or-authentication-6">Base case - no encryption or authentication</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">final</span> channel <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ClientChannel(<span style="color:#e6db74">'localhost'</span>,
|
||||
port: <span style="color:#ae81ff">50051</span>,
|
||||
options: <span style="color:#66d9ef">const</span> ChannelOptions(
|
||||
credentials: <span style="color:#66d9ef">const</span> ChannelCredentials.insecure()));
|
||||
<span style="color:#66d9ef">final</span> stub <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> GreeterClient(channel);</code></pre></div>
|
||||
<h5 id="with-server-authentication-ssl-tls-7">With server authentication SSL/TLS</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// Load a custom roots file.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">final</span> trustedRoot <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> File(<span style="color:#e6db74">'roots.pem'</span>).readAsBytesSync();
|
||||
<span style="color:#66d9ef">final</span> channelCredentials <span style="color:#f92672">=</span>
|
||||
<span style="color:#66d9ef">new</span> ChannelCredentials.secure(certificates: trustedRoot);
|
||||
<span style="color:#66d9ef">final</span> channelOptions <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ChannelOptions(credentials: channelCredentials);
|
||||
<span style="color:#66d9ef">final</span> channel <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ClientChannel(<span style="color:#e6db74">'myservice.example.com'</span>,
|
||||
options: channelOptions);
|
||||
<span style="color:#66d9ef">final</span> client <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> GreeterClient(channel);</code></pre></div>
|
||||
<h5 id="authenticate-with-google-7">Authenticate with Google</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// Uses publicly trusted roots by default.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">final</span> channel <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ClientChannel(<span style="color:#e6db74">'greeter.googleapis.com'</span>);
|
||||
<span style="color:#66d9ef">final</span> serviceAccountJson <span style="color:#f92672">=</span>
|
||||
<span style="color:#66d9ef">new</span> File(<span style="color:#e6db74">'service-account.json'</span>).readAsStringSync();
|
||||
<span style="color:#66d9ef">final</span> credentials <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> JwtServiceAccountAuthenticator(serviceAccountJson);
|
||||
<span style="color:#66d9ef">final</span> client <span style="color:#f92672">=</span>
|
||||
<span style="color:#66d9ef">new</span> GreeterClient(channel, options: credentials.toCallOptions);</code></pre></div>
|
||||
<h5 id="authenticate-a-single-rpc-call-1">Authenticate a single RPC call</h5>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// Uses publicly trusted roots by default.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">final</span> channel <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ClientChannel(<span style="color:#e6db74">'greeter.googleapis.com'</span>);
|
||||
<span style="color:#66d9ef">final</span> client <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> GreeterClient(channel);
|
||||
...
|
||||
<span style="color:#66d9ef">final</span> serviceAccountJson <span style="color:#f92672">=</span>
|
||||
<span style="color:#66d9ef">new</span> File(<span style="color:#e6db74">'service-account.json'</span>).readAsStringSync();
|
||||
<span style="color:#66d9ef">final</span> credentials <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> JwtServiceAccountAuthenticator(serviceAccountJson);
|
||||
<span style="color:#66d9ef">final</span> response <span style="color:#f92672">=</span>
|
||||
<span style="color:#66d9ef">await</span> client.sayHello(request, options: credentials.toCallOptions);</code></pre></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1 +0,0 @@
|
|||
<!DOCTYPE html><html><head><title>https://cjyabraham.github.io/docs/guides/benchmarking/</title><link rel="canonical" href="https://cjyabraham.github.io/docs/guides/benchmarking/"/><meta name="robots" content="noindex"><meta charset="utf-8" /><meta http-equiv="refresh" content="0; url=https://cjyabraham.github.io/docs/guides/benchmarking/" /></head></html>
|
||||
|
|
@ -1,322 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Benchmarking – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown active">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="headertext">Documentation</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="subnav d-none d-md-block">
|
||||
<a href="https://cjyabraham.github.io/docs/" >Overview</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/quickstart/" >Quick Start</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/guides/" class="active">Guides</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/tutorials/" >Tutorials</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/reference/" >Reference</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/samples/" >Samples</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/talks/" >Presentations</a>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="quickstartcols">
|
||||
|
||||
<div class="quickstartcol1">
|
||||
|
||||
<h8>Guides</h8>
|
||||
|
||||
|
||||
<a href="/docs/guides/">
|
||||
What is gRPC?
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/concepts/">
|
||||
gRPC Concepts
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/auth/">
|
||||
Authentication
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/error/">
|
||||
Error handling and debugging
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/benchmarking/" class="active">
|
||||
Benchmarking
|
||||
</a>
|
||||
|
||||
|
||||
<a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md">
|
||||
gRPC Wire Format
|
||||
</a>
|
||||
|
||||
|
||||
<h8 style="margin-top:25%">Related Guides</h8>
|
||||
<a href="https://developers.google.com/protocol-buffers/docs/overview">Protocol Buffers</a>
|
||||
</div>
|
||||
|
||||
<div class="quickstartcol2" style="margin-top:4%">
|
||||
<h3 style="margin-top:0px;">
|
||||
Benchmarking
|
||||
</h3>
|
||||
|
||||
|
||||
|
||||
<p class="lead">gRPC is designed to support high-performance
|
||||
open-source RPCs in many languages. This document describes the
|
||||
performance benchmarking tools, the scenarios considered by the tests,
|
||||
and the testing infrastructure.</p>
|
||||
|
||||
<div id="toc"></div>
|
||||
|
||||
<p><a name="Overview"></a></p>
|
||||
|
||||
<h3 id="overview">Overview</h3>
|
||||
|
||||
<p>gRPC is designed for both high-performance and high-productivity
|
||||
design of distributed applications. Continuous performance
|
||||
benchmarking is a critical part of the gRPC development
|
||||
workflow. Multi-language performance tests run hourly against
|
||||
the master branch, and these numbers are reported to a dashboard for
|
||||
visualization.</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://performance-dot-grpc-testing.appspot.com/explore?dashboard=5636470266134528">Multi-language performance dashboard @latest_release (lastest available stable release)</a></li>
|
||||
<li><a href="https://performance-dot-grpc-testing.appspot.com/explore?dashboard=5652536396611584">Multi-language performance dashboard @master (latest dev version)</a></li>
|
||||
<li><a href="https://performance-dot-grpc-testing.appspot.com/explore?dashboard=5685265389584384">C++ detailed performance dashboard @master (latest dev version)</a></li>
|
||||
</ul>
|
||||
|
||||
<p>Additional benchmarking provides fine grained insights into where
|
||||
CPU is spent.</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://performance-dot-grpc-testing.appspot.com/explore?dashboard=5684961520648192">C++ full-stack microbenchmarks</a></li>
|
||||
<li><a href="https://performance-dot-grpc-testing.appspot.com/explore?dashboard=5740240702537728">C Core filter benchmarks</a></li>
|
||||
<li><a href="https://performance-dot-grpc-testing.appspot.com/explore?dashboard=5641826627223552&container=789696829&widget=512792852">C Core shared component benchmarks</a></li>
|
||||
<li><a href="https://performance-dot-grpc-testing.appspot.com/explore?dashboard=5732910535540736">C Core HTTP/2 microbenchmarks</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="performance-testing-design">Performance testing design</h3>
|
||||
|
||||
<p>Each language implements a performance testing worker that implements
|
||||
a gRPC
|
||||
<a href="https://github.com/grpc/grpc/blob/master/src/proto/grpc/testing/worker_service.proto">WorkerService</a>. This
|
||||
service directs the worker to act as either a client or a server for
|
||||
the actual benchmark test, represented as
|
||||
<a href="https://github.com/grpc/grpc/blob/master/src/proto/grpc/testing/benchmark_service.proto">BenchmarkService</a>. That
|
||||
service has two methods:</p>
|
||||
|
||||
<ul>
|
||||
<li>UnaryCall - a unary RPC of a simple request that specifies the number of bytes to return in the response</li>
|
||||
<li>StreamingCall - a streaming RPC that allows repeated ping-pongs of request and response messages akin to the UnaryCall</li>
|
||||
</ul>
|
||||
|
||||
<p><img src="/img/testing_framework.png" alt="gRPC performance testing worker diagram" /></p>
|
||||
|
||||
<p>These workers are controlled by a
|
||||
<a href="https://github.com/grpc/grpc/blob/master/test/cpp/qps/qps_json_driver.cc">driver</a>
|
||||
that takes as input a scenario description (in JSON format) and an
|
||||
environment variable specifying the host:port of each worker process.</p>
|
||||
|
||||
<p><a name="Languages under test"></a></p>
|
||||
|
||||
<h3 id="languages-under-test">Languages under test</h3>
|
||||
|
||||
<p>The following languages have continuous performance testing as both
|
||||
clients and servers at master:</p>
|
||||
|
||||
<ul>
|
||||
<li>C++</li>
|
||||
<li>Java</li>
|
||||
<li>Go</li>
|
||||
<li>C#</li>
|
||||
<li>node.js</li>
|
||||
<li>Python</li>
|
||||
<li>Ruby</li>
|
||||
</ul>
|
||||
|
||||
<p>Additionally, all languages derived from C core have limited
|
||||
performance testing (smoke testing) conducted at every pull request.</p>
|
||||
|
||||
<p>In addition to running as both the client-side and server-side of
|
||||
performance tests, all languages are tested as clients against a C++
|
||||
server, and as servers against a C++ client. This test aims to provide
|
||||
the current upper bound of performance for a given language’s client or
|
||||
server implementation without testing the other side.</p>
|
||||
|
||||
<p>Although PHP or mobile environments do not support a gRPC server
|
||||
(which is needed for our performance tests), their client-side
|
||||
performance can be benchmarked using a proxy WorkerService written in
|
||||
another language. This code is implemented for PHP but is not yet in
|
||||
continuous testing mode.</p>
|
||||
|
||||
<p><a name="Scenarios under test"></a></p>
|
||||
|
||||
<h3 id="scenarios-under-test">Scenarios under test</h3>
|
||||
|
||||
<p>There are several important scenarios under test and displayed in the dashboards
|
||||
above, including the following:</p>
|
||||
|
||||
<ul>
|
||||
<li>Contentionless latency - the median and tail response latencies seen with only 1 client sending a single message at a time using StreamingCall</li>
|
||||
<li>QPS - the messages/second rate when there are 2 clients and a total of 64 channels, each of which has 100 outstanding messages at a time sent using StreamingCall</li>
|
||||
<li>Scalability (for selected languages) - the number of messages/second per server core</li>
|
||||
</ul>
|
||||
|
||||
<p>Most performance testing is using secure communication and
|
||||
protobufs. Some C++ tests additionally use insecure communication and
|
||||
the generic (non-protobuf) API to display peak performance. Additional
|
||||
scenarios may be added in the future.</p>
|
||||
|
||||
<p><a name="Testing infrastructure"></a></p>
|
||||
|
||||
<h3 id="testing-infrastructure">Testing infrastructure</h3>
|
||||
|
||||
<p>All performance benchmarks are run as instances in GCE through our
|
||||
Jenkins testing infrastructure. In addition to the gRPC performance
|
||||
scenarios described above, we also run baseline <a href="http://www.netperf.org">netperf
|
||||
TCP_RR</a> latency numbers in order to understand
|
||||
the underlying network characteristics. These numbers are present on
|
||||
our dashboard and sometimes vary depending on where our instances
|
||||
happen to be allocated within GCE.</p>
|
||||
|
||||
<p>Most test instances are 8-core systems, and these are used for both
|
||||
latency and QPS measurement. For C++ and Java, we additionally support
|
||||
QPS testing on 32-core systems. All QPS tests use 2 identical client machines
|
||||
for each server, to make sure that QPS measurement is not client-limited.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1 +0,0 @@
|
|||
<!DOCTYPE html><html><head><title>https://cjyabraham.github.io/docs/guides/concepts/</title><link rel="canonical" href="https://cjyabraham.github.io/docs/guides/concepts/"/><meta name="robots" content="noindex"><meta charset="utf-8" /><meta http-equiv="refresh" content="0; url=https://cjyabraham.github.io/docs/guides/concepts/" /></head></html>
|
||||
|
|
@ -1,409 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
gRPC Concepts – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown active">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="headertext">Documentation</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="subnav d-none d-md-block">
|
||||
<a href="https://cjyabraham.github.io/docs/" >Overview</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/quickstart/" >Quick Start</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/guides/" class="active">Guides</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/tutorials/" >Tutorials</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/reference/" >Reference</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/samples/" >Samples</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/talks/" >Presentations</a>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="quickstartcols">
|
||||
|
||||
<div class="quickstartcol1">
|
||||
|
||||
<h8>Guides</h8>
|
||||
|
||||
|
||||
<a href="/docs/guides/">
|
||||
What is gRPC?
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/concepts/" class="active">
|
||||
gRPC Concepts
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/auth/">
|
||||
Authentication
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/error/">
|
||||
Error handling and debugging
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/benchmarking/">
|
||||
Benchmarking
|
||||
</a>
|
||||
|
||||
|
||||
<a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md">
|
||||
gRPC Wire Format
|
||||
</a>
|
||||
|
||||
|
||||
<h8 style="margin-top:25%">Related Guides</h8>
|
||||
<a href="https://developers.google.com/protocol-buffers/docs/overview">Protocol Buffers</a>
|
||||
</div>
|
||||
|
||||
<div class="quickstartcol2" style="margin-top:4%">
|
||||
<h3 style="margin-top:0px;">
|
||||
gRPC Concepts
|
||||
</h3>
|
||||
|
||||
|
||||
|
||||
<p class="lead">This document introduces some key gRPC concepts with an overview
|
||||
of gRPC's architecture and RPC life cycle.</p>
|
||||
|
||||
<p>It assumes that you’ve read <a href="/docs/guides">What is gRPC?</a>. For
|
||||
language-specific details, see the Quick Start, tutorial, and reference
|
||||
documentation for your chosen language(s), where available (complete reference
|
||||
docs are coming soon).</p>
|
||||
|
||||
<div id="toc" class="toc mobile-toc"></div>
|
||||
|
||||
<h3 id="overview">Overview</h3>
|
||||
|
||||
<h4 id="service-definition">Service definition</h4>
|
||||
|
||||
<p>Like many RPC systems, gRPC is based around the idea of defining a service,
|
||||
specifying the methods that can be called remotely with their parameters and
|
||||
return types. By default, gRPC uses <a href="https://developers.google.com/protocol-buffers/">protocol
|
||||
buffers</a> as the Interface
|
||||
Definition Language (IDL) for describing both the service interface and the
|
||||
structure of the payload messages. It is possible to use other alternatives if
|
||||
desired.</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto"><span style="color:#66d9ef">service</span> HelloService {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">rpc</span> SayHello (HelloRequest) <span style="color:#66d9ef">returns</span> (HelloResponse);<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">HelloRequest</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">string</span> greeting <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">HelloResponse</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">string</span> reply <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
||||
<p>gRPC lets you define four kinds of service method:</p>
|
||||
|
||||
<ul>
|
||||
<li>Unary RPCs where the client sends a single request to the server and gets a
|
||||
single response back, just like a normal function call.</li>
|
||||
</ul>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto"><span style="color:#66d9ef">rpc</span> SayHello(HelloRequest) <span style="color:#66d9ef">returns</span> (HelloResponse){<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
||||
<ul>
|
||||
<li>Server streaming RPCs where the client sends a request to the server and gets
|
||||
a stream to read a sequence of messages back. The client reads from the
|
||||
returned stream until there are no more messages. gRPC guarantees message
|
||||
ordering within an individual RPC call.</li>
|
||||
</ul>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto"><span style="color:#66d9ef">rpc</span> LotsOfReplies(HelloRequest) <span style="color:#66d9ef">returns</span> (stream HelloResponse){<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
||||
<ul>
|
||||
<li>Client streaming RPCs where the client writes a sequence of messages and sends
|
||||
them to the server, again using a provided stream. Once the client has
|
||||
finished writing the messages, it waits for the server to read them and return
|
||||
its response. Again gRPC guarantees message ordering within an individual RPC
|
||||
call.</li>
|
||||
</ul>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto"><span style="color:#66d9ef">rpc</span> LotsOfGreetings(stream HelloRequest) <span style="color:#66d9ef">returns</span> (HelloResponse) {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
||||
<ul>
|
||||
<li>Bidirectional streaming RPCs where both sides send a sequence of messages
|
||||
using a read-write stream. The two streams operate independently, so clients
|
||||
and servers can read and write in whatever order they like: for example, the
|
||||
server could wait to receive all the client messages before writing its
|
||||
responses, or it could alternately read a message then write a message, or
|
||||
some other combination of reads and writes. The order of messages in each
|
||||
stream is preserved.</li>
|
||||
</ul>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto"><span style="color:#66d9ef">rpc</span> BidiHello(stream HelloRequest) <span style="color:#66d9ef">returns</span> (stream HelloResponse){<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
||||
<p>We’ll look at the different types of RPC in more detail in the RPC life cycle section below.</p>
|
||||
|
||||
<h4 id="using-the-api-surface">Using the API surface</h4>
|
||||
|
||||
<p>Starting from a service definition in a .proto file, gRPC provides protocol
|
||||
buffer compiler plugins that generate client- and server-side code. gRPC users
|
||||
typically call these APIs on the client side and implement the corresponding API
|
||||
on the server side.</p>
|
||||
|
||||
<ul>
|
||||
<li>On the server side, the server implements the methods declared by the service
|
||||
and runs a gRPC server to handle client calls. The gRPC infrastructure decodes
|
||||
incoming requests, executes service methods, and encodes service responses.</li>
|
||||
<li>On the client side, the client has a local object known as <em>stub</em> (for some
|
||||
languages, the preferred term is <em>client</em>) that implements the same methods as
|
||||
the service. The client can then just call those methods on the local object,
|
||||
wrapping the parameters for the call in the appropriate protocol buffer
|
||||
message type - gRPC looks after sending the request(s) to the server and
|
||||
returning the server’s protocol buffer response(s).</li>
|
||||
</ul>
|
||||
|
||||
<h4 id="synchronous-vs-asynchronous">Synchronous vs. asynchronous</h4>
|
||||
|
||||
<p>Synchronous RPC calls that block until a response arrives from the server are
|
||||
the closest approximation to the abstraction of a procedure call that RPC
|
||||
aspires to. On the other hand, networks are inherently asynchronous and in many
|
||||
scenarios it’s useful to be able to start RPCs without blocking the current
|
||||
thread.</p>
|
||||
|
||||
<p>The gRPC programming surface in most languages comes in both synchronous and
|
||||
asynchronous flavors. You can find out more in each language’s tutorial and
|
||||
reference documentation (complete reference docs are coming soon).</p>
|
||||
|
||||
<h3 id="rpc-life-cycle">RPC life cycle</h3>
|
||||
|
||||
<p>Now let’s take a closer look at what happens when a gRPC client calls a gRPC
|
||||
server method. We won’t look at implementation details, you can find out more
|
||||
about these in our language-specific pages.</p>
|
||||
|
||||
<h4 id="unary-rpc">Unary RPC</h4>
|
||||
|
||||
<p>First let’s look at the simplest type of RPC, where the client sends a single request and gets back a single response.</p>
|
||||
|
||||
<ul>
|
||||
<li>Once the client calls the method on the stub/client object, the server is
|
||||
notified that the RPC has been invoked with the client’s <a href="#metadata">metadata</a>
|
||||
for this call, the method name, and the specified <a href="#deadlines">deadline</a> if
|
||||
applicable.</li>
|
||||
<li>The server can then either send back its own initial metadata (which must be
|
||||
sent before any response) straight away, or wait for the client’s request
|
||||
message - which happens first is application-specific.</li>
|
||||
<li>Once the server has the client’s request message, it does whatever work is
|
||||
necessary to create and populate its response. The response is then returned
|
||||
(if successful) to the client together with status details (status code and
|
||||
optional status message) and optional trailing metadata.</li>
|
||||
<li>If the status is OK, the client then gets the response, which completes the
|
||||
call on the client side.</li>
|
||||
</ul>
|
||||
|
||||
<h4 id="server-streaming-rpc">Server streaming RPC</h4>
|
||||
|
||||
<p>A server-streaming RPC is similar to our simple example, except the server sends
|
||||
back a stream of responses after getting the client’s request message. After
|
||||
sending back all its responses, the server’s status details (status code and
|
||||
optional status message) and optional trailing metadata are sent back to
|
||||
complete on the server side. The client completes once it has all the server’s
|
||||
responses.</p>
|
||||
|
||||
<h4 id="client-streaming-rpc">Client streaming RPC</h4>
|
||||
|
||||
<p>A client-streaming RPC is also similar to our simple example, except the client
|
||||
sends a stream of requests to the server instead of a single request. The server
|
||||
sends back a single response, typically but not necessarily after it has
|
||||
received all the client’s requests, along with its status details and optional
|
||||
trailing metadata.</p>
|
||||
|
||||
<h4 id="bidirectional-streaming-rpc">Bidirectional streaming RPC</h4>
|
||||
|
||||
<p>In a bidirectional streaming RPC, again the call is initiated by the client
|
||||
calling the method and the server receiving the client metadata, method name,
|
||||
and deadline. Again the server can choose to send back its initial metadata or
|
||||
wait for the client to start sending requests.</p>
|
||||
|
||||
<p>What happens next depends on the application, as the client and server can read
|
||||
and write in any order - the streams operate completely independently. So, for
|
||||
example, the server could wait until it has received all the client’s messages
|
||||
before writing its responses, or the server and client could “ping-pong”: the
|
||||
server gets a request, then sends back a response, then the client sends another
|
||||
request based on the response, and so on.</p>
|
||||
|
||||
<p><a name="deadlines"></a></p>
|
||||
|
||||
<h4 id="deadlines-timeouts">Deadlines/Timeouts</h4>
|
||||
|
||||
<p>gRPC allows clients to specify how long they are willing to wait for an RPC to
|
||||
complete before the RPC is terminated with the error <code>DEADLINE_EXCEEDED</code>. On
|
||||
the server side, the server can query to see if a particular RPC has timed out,
|
||||
or how much time is left to complete the RPC.</p>
|
||||
|
||||
<p>How the deadline or timeout is specified varies from language to language - for
|
||||
example, not all languages have a default deadline, some language APIs work in
|
||||
terms of a deadline (a fixed point in time), and some language APIs work in
|
||||
terms of timeouts (durations of time).</p>
|
||||
|
||||
<h4 id="rpc-termination">RPC termination</h4>
|
||||
|
||||
<p>In gRPC, both the client and server make independent and local determinations of
|
||||
the success of the call, and their conclusions may not match. This means that,
|
||||
for example, you could have an RPC that finishes successfully on the server side
|
||||
(“I have sent all my responses!”) but fails on the client side (“The responses
|
||||
arrived after my deadline!“). It’s also possible for a server to decide to
|
||||
complete before a client has sent all its requests.</p>
|
||||
|
||||
<h4 id="cancelling-rpcs">Cancelling RPCs</h4>
|
||||
|
||||
<p>Either the client or the server can cancel an RPC at any time. A cancellation
|
||||
terminates the RPC immediately so that no further work is done. It is <em>not</em> an
|
||||
“undo”: changes made before the cancellation will not be rolled back.</p>
|
||||
|
||||
<p><a name="metadata"></a></p>
|
||||
|
||||
<h4 id="metadata">Metadata</h4>
|
||||
|
||||
<p>Metadata is information about a particular RPC call (such as <a href="/docs/guides/auth/">authentication details</a>) in the
|
||||
form of a list of key-value pairs, where the keys are strings and the values are
|
||||
typically strings (but can be binary data). Metadata is opaque to gRPC itself -
|
||||
it lets the client provide information associated with the call to the server
|
||||
and vice versa.</p>
|
||||
|
||||
<p>Access to metadata is language-dependent.</p>
|
||||
|
||||
<h4 id="channels">Channels</h4>
|
||||
|
||||
<p>A gRPC channel provides a connection to a gRPC server on a specified host and
|
||||
port and is used when creating a client stub (or just “client” in some
|
||||
languages). Clients can specify channel arguments to modify gRPC’s default
|
||||
behaviour, such as switching on and off message compression. A channel has
|
||||
state, including <code>connected</code> and <code>idle</code>.</p>
|
||||
|
||||
<p>How gRPC deals with closing down channels is language-dependent. Some languages
|
||||
also permit querying channel state.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,203 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Contribution Guidelines – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown active">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="headertext">Documentation</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="subnav d-none d-md-block">
|
||||
<a href="https://cjyabraham.github.io/docs/" >Overview</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/quickstart/" >Quick Start</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/guides/" class="active">Guides</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/tutorials/" >Tutorials</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/reference/" >Reference</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/samples/" >Samples</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/talks/" >Presentations</a>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="quickstartcols">
|
||||
|
||||
<div class="quickstartcol1">
|
||||
|
||||
<h8>Guides</h8>
|
||||
|
||||
|
||||
<a href="/docs/guides/">
|
||||
What is gRPC?
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/concepts/">
|
||||
gRPC Concepts
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/auth/">
|
||||
Authentication
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/error/">
|
||||
Error handling and debugging
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/benchmarking/">
|
||||
Benchmarking
|
||||
</a>
|
||||
|
||||
|
||||
<a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md">
|
||||
gRPC Wire Format
|
||||
</a>
|
||||
|
||||
|
||||
<h8 style="margin-top:25%">Related Guides</h8>
|
||||
<a href="https://developers.google.com/protocol-buffers/docs/overview">Protocol Buffers</a>
|
||||
</div>
|
||||
|
||||
<div class="quickstartcol2" style="margin-top:4%">
|
||||
<h3 style="margin-top:0px;">
|
||||
Contribution Guidelines
|
||||
</h3>
|
||||
|
||||
|
||||
|
||||
<h1 id="contribution-guidelines">Contribution Guidelines</h1>
|
||||
|
||||
<p>Coming soon!</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1 +0,0 @@
|
|||
<!DOCTYPE html><html><head><title>https://cjyabraham.github.io/docs/guides/error/</title><link rel="canonical" href="https://cjyabraham.github.io/docs/guides/error/"/><meta name="robots" content="noindex"><meta charset="utf-8" /><meta http-equiv="refresh" content="0; url=https://cjyabraham.github.io/docs/guides/error/" /></head></html>
|
||||
|
|
@ -1,344 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Error Handling – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown active">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="headertext">Documentation</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="subnav d-none d-md-block">
|
||||
<a href="https://cjyabraham.github.io/docs/" >Overview</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/quickstart/" >Quick Start</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/guides/" class="active">Guides</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/tutorials/" >Tutorials</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/reference/" >Reference</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/samples/" >Samples</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/talks/" >Presentations</a>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="quickstartcols">
|
||||
|
||||
<div class="quickstartcol1">
|
||||
|
||||
<h8>Guides</h8>
|
||||
|
||||
|
||||
<a href="/docs/guides/">
|
||||
What is gRPC?
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/concepts/">
|
||||
gRPC Concepts
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/auth/">
|
||||
Authentication
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/error/" class="active">
|
||||
Error handling and debugging
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/benchmarking/">
|
||||
Benchmarking
|
||||
</a>
|
||||
|
||||
|
||||
<a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md">
|
||||
gRPC Wire Format
|
||||
</a>
|
||||
|
||||
|
||||
<h8 style="margin-top:25%">Related Guides</h8>
|
||||
<a href="https://developers.google.com/protocol-buffers/docs/overview">Protocol Buffers</a>
|
||||
</div>
|
||||
|
||||
<div class="quickstartcol2" style="margin-top:4%">
|
||||
<h3 style="margin-top:0px;">
|
||||
Error Handling
|
||||
</h3>
|
||||
|
||||
|
||||
|
||||
<p class="lead"> This page describes how gRPC deals with errors, including gRPC's built-in error codes. Example code in different languages can be found <a href="https://github.com/avinassh/grpc-errors">here</a>.</p>
|
||||
|
||||
<div id="toc" class="toc mobile-toc"></div>
|
||||
|
||||
<h3 id="error-model">Error model</h3>
|
||||
|
||||
<p>As you’ll have seen in our concepts document and examples, when a gRPC call
|
||||
completes successfully the server returns an <code>OK</code> status to the client
|
||||
(depending on the language the <code>OK</code> status may or may not be directly used in
|
||||
your code). But what happens if the call isn’t successful?</p>
|
||||
|
||||
<p>If an error occurs, gRPC returns one of its error status codes instead, with an
|
||||
optional string error message that provides further details about what happened.
|
||||
Error information is available to gRPC clients in all supported languages.</p>
|
||||
|
||||
<h3 id="error-status-codes">Error status codes</h3>
|
||||
|
||||
<p>Errors are raised by gRPC under various circumstances, from network failures to
|
||||
unauthenticated connections, each of which is associated with a particular
|
||||
status code. The following error status codes are supported in all gRPC
|
||||
languages.</p>
|
||||
|
||||
<h4 id="general-errors">General errors</h4>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Case</th>
|
||||
<th>Status code</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Client application cancelled the request</td>
|
||||
<td>GRPC_STATUS_CANCELLED</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Deadline expired before server returned status</td>
|
||||
<td>GRPC_STATUS_DEADLINE_EXCEEDED</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Method not found on server</td>
|
||||
<td>GRPC_STATUS_UNIMPLEMENTED</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Server shutting down</td>
|
||||
<td>GRPC_STATUS_UNAVAILABLE</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Server threw an exception (or did something other than returning a status code to terminate the RPC)</td>
|
||||
<td>GRPC_STATUS_UNKNOWN</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p><br></p>
|
||||
|
||||
<h4 id="network-failures">Network failures</h4>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Case</th>
|
||||
<th>Status code</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>No data transmitted before deadline expires. Also applies to cases where some data is transmitted and no other failures are detected before the deadline expires</td>
|
||||
<td>GRPC_STATUS_DEADLINE_EXCEEDED</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Some data transmitted (for example, the request metadata has been written to the TCP connection) before the connection breaks</td>
|
||||
<td>GRPC_STATUS_UNAVAILABLE</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p><br></p>
|
||||
|
||||
<h4 id="protocol-errors">Protocol errors</h4>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Case</th>
|
||||
<th>Status code</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Could not decompress but compression algorithm supported</td>
|
||||
<td>GRPC_STATUS_INTERNAL</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Compression mechanism used by client not supported by the server</td>
|
||||
<td>GRPC_STATUS_UNIMPLEMENTED</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Flow-control resource limits reached</td>
|
||||
<td>GRPC_STATUS_RESOURCE_EXHAUSTED</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Flow-control protocol violation</td>
|
||||
<td>GRPC_STATUS_INTERNAL</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Error parsing returned status</td>
|
||||
<td>GRPC_STATUS_UNKNOWN</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Unauthenticated: credentials failed to get metadata</td>
|
||||
<td>GRPC_STATUS_UNAUTHENTICATED</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Invalid host set in authority metadata</td>
|
||||
<td>GRPC_STATUS_UNAUTHENTICATED</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Error parsing response protocol buffer</td>
|
||||
<td>GRPC_STATUS_INTERNAL</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Error parsing request protocol buffer</td>
|
||||
<td>GRPC_STATUS_INTERNAL</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,294 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Guides – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown active">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="headertext">Documentation</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="subnav d-none d-md-block">
|
||||
<a href="https://cjyabraham.github.io/docs/" >Overview</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/quickstart/" >Quick Start</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/guides/" class="active">Guides</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/tutorials/" >Tutorials</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/reference/" >Reference</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/samples/" >Samples</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/talks/" >Presentations</a>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="quickstartcols">
|
||||
|
||||
<div class="quickstartcol1">
|
||||
|
||||
<h8>Guides</h8>
|
||||
|
||||
|
||||
<a href="/docs/guides/" class="active">
|
||||
What is gRPC?
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/concepts/">
|
||||
gRPC Concepts
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/auth/">
|
||||
Authentication
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/error/">
|
||||
Error handling and debugging
|
||||
</a>
|
||||
|
||||
|
||||
<a href="/docs/guides/benchmarking/">
|
||||
Benchmarking
|
||||
</a>
|
||||
|
||||
|
||||
<a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md">
|
||||
gRPC Wire Format
|
||||
</a>
|
||||
|
||||
|
||||
<h8 style="margin-top:25%">Related Guides</h8>
|
||||
<a href="https://developers.google.com/protocol-buffers/docs/overview">Protocol Buffers</a>
|
||||
</div>
|
||||
|
||||
<div class="quickstartcol2" style="margin-top:4%">
|
||||
<h3 style="margin-top:0px;">
|
||||
Guides
|
||||
</h3>
|
||||
|
||||
|
||||
|
||||
<p>This document introduces you to gRPC and protocol buffers. gRPC can use
|
||||
protocol buffers as both its Interface Definition Language (IDL) and as its underlying message
|
||||
interchange format. If you’re new to gRPC and/or protocol buffers, read this!
|
||||
If you just want to dive in and see gRPC in action first,
|
||||
see our <a href="../quickstart">Quick Starts</a>.</p>
|
||||
|
||||
<div id="toc" class="toc mobile-toc"></div>
|
||||
|
||||
<h3 id="overview">Overview</h3>
|
||||
|
||||
<p>In gRPC a client application can directly call methods on a server application on a different machine as if it was a local object, making it easier for you to create distributed applications and services. As in many RPC systems, gRPC is based around the idea of defining a service, specifying the methods that can be called remotely with their parameters and return types. On the server side, the server implements this interface and runs a gRPC server to handle client calls. On the client side, the client has a stub (referred to as just a client in some languages) that provides the same methods as the server.</p>
|
||||
|
||||
<p><img src="../../img/landing-2.svg" alt="Concept Diagram" /></p>
|
||||
|
||||
<p>gRPC clients and servers can run and talk to each other in a variety of environments - from servers inside Google to your own desktop - and can be written in any of gRPC’s supported languages. So, for example, you can easily create a gRPC server in Java with clients in Go, Python, or Ruby. In addition, the latest Google APIs will have gRPC versions of their interfaces, letting you easily build Google functionality into your applications.</p>
|
||||
|
||||
<h3 id="working-with-protocol-buffers">Working with Protocol Buffers</h3>
|
||||
|
||||
<p>By default gRPC uses <a href="https://developers.google.com/protocol-buffers/docs/overview">protocol buffers</a>, Google’s
|
||||
mature open source mechanism for serializing structured data (although it
|
||||
can be used with other data formats such as JSON). Here’s a quick intro to how
|
||||
it works. If you’re already familiar with protocol buffers, feel free to skip
|
||||
ahead to the next section.</p>
|
||||
|
||||
<p>The first step when working with protocol buffers is to define the structure
|
||||
for the data you want to serialize in a <em>proto file</em>: this is an ordinary text
|
||||
file with a <code>.proto</code> extension. Protocol buffer data is structured as
|
||||
<em>messages</em>, where each message is a small logical record of information
|
||||
containing a series of name-value pairs called <em>fields</em>. Here’s a simple
|
||||
example:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto"><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">Person</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">string</span> name <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">int32</span> id <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">bool</span> has_ponycopter <span style="color:#f92672">=</span> <span style="color:#ae81ff">3</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
||||
<p>Then, once you’ve specified your data structures, you use the protocol buffer
|
||||
compiler <code>protoc</code> to generate data access classes in your preferred language(s)
|
||||
from your proto definition. These provide simple accessors for each field
|
||||
(like <code>name()</code> and <code>set_name()</code>) as well as methods to serialize/parse
|
||||
the whole structure to/from raw bytes – so, for instance, if your chosen
|
||||
language is C++, running the compiler on the above example will generate a
|
||||
class called <code>Person</code>. You can then use this class in your application to
|
||||
populate, serialize, and retrieve Person protocol buffer messages.</p>
|
||||
|
||||
<p>As you’ll see in more detail in our examples, you define gRPC services
|
||||
in ordinary proto files, with RPC method parameters and return types specified as
|
||||
protocol buffer messages:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-proto" data-lang="proto"><span style="color:#75715e">// The greeter service definition.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">service</span> Greeter {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#75715e">// Sends a greeting
|
||||
</span><span style="color:#75715e"></span> <span style="color:#66d9ef">rpc</span> SayHello (HelloRequest) <span style="color:#66d9ef">returns</span> (HelloReply) {}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#75715e">// The request message containing the user's name.
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">HelloRequest</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">string</span> name <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#75715e">// The response message containing the greetings
|
||||
</span><span style="color:#75715e"></span><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">HelloReply</span> {<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">string</span> <span style="color:#66d9ef">message</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
||||
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
||||
<p>gRPC also uses <code>protoc</code> with a special gRPC plugin to
|
||||
generate code from your proto file. However, with the gRPC plugin, you get
|
||||
generated gRPC client and server code, as well as the regular protocol buffer
|
||||
code for populating, serializing, and retrieving your message types. We’ll
|
||||
look at this example in more detail below.</p>
|
||||
|
||||
<p>You can find out lots more about protocol buffers in the <a href="https://developers.google.com/protocol-buffers/docs/overview">Protocol Buffers
|
||||
documentation</a>,
|
||||
and find out how to get and install <code>protoc</code> with gRPC plugins in your chosen
|
||||
language’s Quickstart.</p>
|
||||
|
||||
<h4 id="protocol-buffer-versions">Protocol buffer versions</h4>
|
||||
|
||||
<p>While protocol buffers have been available for open source users for some
|
||||
time, our examples use a new flavor of protocol buffers called proto3, which
|
||||
has a slightly simplified syntax, some useful new features, and supports
|
||||
lots more languages. This is currently available in Java, C++, Python,
|
||||
Objective-C, C#, a lite-runtime (Android Java), Ruby, and JavaScript from the
|
||||
<a href="https://github.com/google/protobuf/releases">protocol buffers GitHub repo</a>,
|
||||
as well as a Go language generator from the <a href="https://github.com/golang/protobuf">golang/protobuf GitHub
|
||||
repo</a>, with more languages
|
||||
in development. You can find out more in the <a href="https://developers.google.com/protocol-buffers/docs/proto3">proto3 language
|
||||
guide</a> and the
|
||||
<a href="https://developers.google.com/protocol-buffers/docs/reference/overview">reference documentation</a>
|
||||
available for each language. The reference documentation also includes a
|
||||
<a href="https://developers.google.com/protocol-buffers/docs/reference/proto3-spec">formal specification</a>
|
||||
for the <code>.proto</code> file format.</p>
|
||||
|
||||
<p>In general, while you can use proto2 (the current default protocol buffers
|
||||
version), we recommend that you use proto3 with gRPC as it lets you use the
|
||||
full range of gRPC-supported languages, as well as avoiding compatibility
|
||||
issues with proto2 clients talking to proto3 servers and vice versa.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>Guides on gRPC</title>
|
||||
<link>https://cjyabraham.github.io/docs/guides/</link>
|
||||
<description>Recent content in Guides on gRPC</description>
|
||||
<generator>Hugo -- gohugo.io</generator>
|
||||
<language>en-us</language>
|
||||
|
||||
<atom:link href="https://cjyabraham.github.io/docs/guides/index.xml" rel="self" type="application/rss+xml" />
|
||||
|
||||
|
||||
<item>
|
||||
<title>Authentication</title>
|
||||
<link>https://cjyabraham.github.io/docs/guides/auth/</link>
|
||||
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/docs/guides/auth/</guid>
|
||||
<description>This document provides an overview of gRPC authentication, including our built-in supported auth mechanisms, how to plug in your own authentication systems, and examples of how to use gRPC auth in our supported languages.
|
||||
Overview gRPC is designed to work with a variety of authentication mechanisms, making it easy to safely use gRPC to talk to other systems. You can use our supported mechanisms - SSL/TLS with or without Google token-based authentication - or you can plug in your own authentication system by extending our provided code.</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>Benchmarking</title>
|
||||
<link>https://cjyabraham.github.io/docs/guides/benchmarking/</link>
|
||||
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/docs/guides/benchmarking/</guid>
|
||||
<description>gRPC is designed to support high-performance open-source RPCs in many languages. This document describes the performance benchmarking tools, the scenarios considered by the tests, and the testing infrastructure.
|
||||
|
||||
Overview gRPC is designed for both high-performance and high-productivity design of distributed applications. Continuous performance benchmarking is a critical part of the gRPC development workflow. Multi-language performance tests run hourly against the master branch, and these numbers are reported to a dashboard for visualization.</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>Contribution Guidelines</title>
|
||||
<link>https://cjyabraham.github.io/docs/guides/contributing/</link>
|
||||
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/docs/guides/contributing/</guid>
|
||||
<description>Contribution Guidelines Coming soon!</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>Error Handling</title>
|
||||
<link>https://cjyabraham.github.io/docs/guides/error/</link>
|
||||
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/docs/guides/error/</guid>
|
||||
<description>This page describes how gRPC deals with errors, including gRPC's built-in error codes. Example code in different languages can be found here.
|
||||
Error model As you&rsquo;ll have seen in our concepts document and examples, when a gRPC call completes successfully the server returns an OK status to the client (depending on the language the OK status may or may not be directly used in your code). But what happens if the call isn&rsquo;t successful?</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>gRPC Concepts</title>
|
||||
<link>https://cjyabraham.github.io/docs/guides/concepts/</link>
|
||||
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
|
||||
|
||||
<guid>https://cjyabraham.github.io/docs/guides/concepts/</guid>
|
||||
<description>This document introduces some key gRPC concepts with an overview of gRPC's architecture and RPC life cycle.
|
||||
It assumes that you&rsquo;ve read What is gRPC?. For language-specific details, see the Quick Start, tutorial, and reference documentation for your chosen language(s), where available (complete reference docs are coming soon).
|
||||
Overview Service definition Like many RPC systems, gRPC is based around the idea of defining a service, specifying the methods that can be called remotely with their parameters and return types.</description>
|
||||
</item>
|
||||
|
||||
</channel>
|
||||
</rss>
|
||||
|
|
@ -1,309 +0,0 @@
|
|||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<title>
|
||||
Documentation – gRPC
|
||||
</title>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
||||
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="/favicons/manifest.json">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-60127042-1');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landing-content">
|
||||
<div class="row">
|
||||
<div class="topbannersub">
|
||||
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
||||
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
||||
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown active">
|
||||
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Docs
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs">
|
||||
Overview
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/quickstart/">
|
||||
Quick Start
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/guides/">
|
||||
Guides
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/tutorials/">
|
||||
Tutorials
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/reference/">
|
||||
Reference
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/samples/">
|
||||
Samples
|
||||
</a>
|
||||
|
||||
|
||||
<a class="dropdown-item" href="/docs/talks">
|
||||
Presentations
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="/community">Community</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://packages.grpc.io/">
|
||||
Packages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="headertext">Documentation</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="subnav d-none d-md-block">
|
||||
<a href="https://cjyabraham.github.io/docs/" class="active">Overview</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/quickstart/" >Quick Start</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/guides/" >Guides</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/tutorials/" >Tutorials</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/reference/" >Reference</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/samples/" >Samples</a>
|
||||
| <a href="https://cjyabraham.github.io/docs/talks/" >Presentations</a>
|
||||
</div>
|
||||
|
||||
<div class="refsection">
|
||||
|
||||
<div class="docssection2">
|
||||
Welcome to the developer documentation for gRPC.
|
||||
Here you can learn about key gRPC concepts, find quick starts, reference
|
||||
material, and tutorials for all our supported languages, and more. If you’re new to gRPC we recommend that you read <a href="guides/"><b>What is
|
||||
gRPC?</b></a> to find out more about our system and how it works. Or, if you want to see gRPC in action first, visit the <a href="quickstart/">QuickStart</a> for your favourite language.
|
||||
</div>
|
||||
|
||||
|
||||
<div class="doclangsection">
|
||||
<h4 style="text-align:center;"> gRPC by Language</h4>
|
||||
<div class="doccols">
|
||||
<div class="docscol1">
|
||||
|
||||
<h3>C++</h3>
|
||||
<a href="/docs/quickstart/cpp/">Quick Start Guide</a><br>
|
||||
<a href="/docs/tutorials/basic/c/">gRPC Basics Tutorial</a><br>
|
||||
<a href="https://grpc.io/grpc/cpp/index.html">API Reference</a>
|
||||
<br>
|
||||
<h3 style="margin-top:3%;">Go</h3>
|
||||
|
||||
<a href="/docs/quickstart/go/">Quick Start Guide</a><br>
|
||||
<a href="/docs/tutorials/basic/go/">gRPC Basics Tutorial</a><br>
|
||||
<a href="https://godoc.org/google.golang.org/grpc">API Reference</a><br>
|
||||
<a href="/docs/reference/go/generated-code/">Generated Code Reference</a>
|
||||
<br>
|
||||
<h3 style="margin-top:3%;">Node.js</h3>
|
||||
|
||||
<a href="/docs/quickstart/node/">Quick Start Guide</a><br>
|
||||
<a href="/docs/tutorials/basic/node/">gRPC Basics Tutorial</a><br>
|
||||
<a href="https://grpc.io/grpc/node/">API Reference</a>
|
||||
<br>
|
||||
<h3 style="margin-top:3%;">PHP</h3>
|
||||
|
||||
<a href="/docs/quickstart/php/">Quick Start Guide</a><br>
|
||||
<a href="/docs/tutorials/basic/php/">gRPC Basics Tutorial</a><br>
|
||||
<a href="https://grpc.io/grpc/php/namespace-Grpc.html">API Reference</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="docscol2">
|
||||
|
||||
<h3>Java</h3>
|
||||
|
||||
<a href="/docs/quickstart/java/">Quick Start Guide</a><br>
|
||||
<a href="/docs/tutorials/basic/java/">gRPC Basics Tutorial</a><br>
|
||||
<a href="https://grpc.io/grpc-java/javadoc/index.html">API Reference</a><br>
|
||||
<a href="/docs/reference/java/generated-code/">Generated Code Reference</a>
|
||||
<br>
|
||||
<h3 style="margin-top:3%;">Ruby</h3>
|
||||
|
||||
<a href="/docs/quickstart/ruby/">Quick Start Guide</a><br>
|
||||
<a href="/docs/tutorials/basic/ruby/">gRPC Basics Tutorial</a><br>
|
||||
<a href="https://godoc.org/google.golang.org/grpc">API Reference</a>
|
||||
<br>
|
||||
<h3 style="margin-top:3%;">Android Java</h3>
|
||||
|
||||
<a href="/docs/quickstart/android/">Quick Start Guide</a><br>
|
||||
<a href="/docs/tutorials/basic/android/">gRPC Basics Tutorial</a><br>
|
||||
<a href="https://grpc.io/grpc-java/javadoc/index.html">API Reference</a><br>
|
||||
<a href="/docs/reference/java/generated-code/">Generated Code Reference</a>
|
||||
<br>
|
||||
<h3 style="margin-top:3%;">Dart</h3>
|
||||
|
||||
<a href="/docs/quickstart/dart/">Quick Start Guide</a><br>
|
||||
<a href="/docs/tutorials/basic/dart/">gRPC Basics Tutorial</a><br>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="docscol3">
|
||||
|
||||
<h3>Python</h3>
|
||||
|
||||
<a href="/docs/quickstart/python/">Quick Start Guide</a><br>
|
||||
<a href="/docs/tutorials/basic/python/">gRPC Basics Tutorial</a><br>
|
||||
<a href="https://grpc.io/grpc/python/">API Reference</a><br>
|
||||
<a href="/docs/reference/python/generated-code/">Generated Code Reference</a>
|
||||
|
||||
<br>
|
||||
<h3 style="margin-top:3%;">C#</h3>
|
||||
|
||||
<a href="/docs/quickstart/csharp/">Quick Start Guide</a><br>
|
||||
<a href="/docs/tutorials/basic/csharp/">gRPC Basics Tutorial</a><br>
|
||||
<a href="https://grpc.io/grpc/csharp/api/Grpc.Core.html">API Reference</a>
|
||||
<br>
|
||||
<h3 style="margin-top:3%;">Objective-C</h3>
|
||||
|
||||
<a href="/docs/quickstart/objective-c/">Quick Start Guide</a><br>
|
||||
<a href="/docs/tutorials/basic/objective-c/">gRPC Basics Tutorial</a><br>
|
||||
<a href="http://cocoadocs.org/docsets/gRPC/">API Reference</a>
|
||||
<br>
|
||||
<h3 style="margin-top:3%;">Web</h3>
|
||||
|
||||
<a href="/docs/quickstart/web/">Quick Start Guide</a><br>
|
||||
<a href="/docs/tutorials/basic/web/">gRPC Basics Tutorial</a><br>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="docusecasesection">
|
||||
<h4 style="text-align:center;">gRPC by Use Cases</h4>
|
||||
<div class="doccols" style="background-color:white;margin-top:0px"">
|
||||
<div class="docstext">
|
||||
gRPC is used in last mile of computing in mobile and web client since it can generate libraries for iOS and Android and uses standards based HTTP/2 as transport allowing it to easily traverse proxies and firewalls. There is also work underway to develop a JS library for use in browsers. Beyond that, it is ideal as a microservices interconnect, not just because the core protocol is very efficient but also because the framework has pluggable authentication, load balancing etc. Google itself is also transitioning to use it to connect microservices.
|
||||
</div>
|
||||
<div class="docscol1">
|
||||
|
||||
<h3 style="padding-bottom:5%;">Last Mile of Computing</h3>
|
||||
|
||||
<p><a href="/docs/tutorials/basic/android/">Mobile: Example RouteGuide Client on Android</a></p>
|
||||
<p><a href="https://github.com/grpc/grpc-web">Web: Browser Client</a></p>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
<div class="docscol2" >
|
||||
|
||||
<h3 style="padding-bottom:5%;">APIs</h3>
|
||||
<p>
|
||||
<a href="https://github.com/GoogleCloudPlatform/cloud-bigtable-client">Google Cloud BigTable Client APIs</a></p>
|
||||
<p><a href="https://cloud.google.com/blog/big-data/2016/03/announcing-grpc-alpha-for-google-cloud-pubsub">Google Cloud PubSub APIs</a></p>
|
||||
<p><a href="https://cloud.google.com/speech/reference/rpc/">Google Cloud Speech APIs</a></p>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
<div class="docscol3">
|
||||
|
||||
<h3 style="padding-bottom:5%;">Microservices</h3>
|
||||
|
||||
<p><a href="https://github.com/dinowernli/java-grpc-prometheus">Monitoring gRPC services using Prometheus in Java</a></p>
|
||||
<p><a href="https://github.com/mwitkow/go-grpc-prometheus">Tracing gRPC services using Zipkin in Java</a></p>
|
||||
<p><a href="https://github.com/grpc/grpc/blob/master/doc/load-balancing.md">Load Balancing in gRPC</a></p>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="docprojectsection">
|
||||
<h4 style="text-align:center;">gRPC in Other Projects</h4>
|
||||
<div class="doccols">
|
||||
<div class="docstext">
|
||||
gRPC now has a vibrant community of companies, projects, developers who are extending and building around it. Here are some popular projects.
|
||||
</div>
|
||||
<div class="docscol1">
|
||||
|
||||
<h3 style="padding-bottom:5%;">Popular Projects</h3>
|
||||
|
||||
<a href="https://github.com/grpc-ecosystem/grpc-gateway" style="display:block">gRPC Gateway</a>
|
||||
<a href="https://github.com/grpc-ecosystem/polyglot" style="display:block">Polyglot: gRPC command line client</a>
|
||||
<a href="https://github.com/google/flatbuffers/tree/master/grpc" style="display:block">FlatBuffer for gRPC</a>
|
||||
<a href="https://github.com/go-kit/kit/tree/master/transport/grpc" style="display:block">Go kit with gRPC transport</a>
|
||||
<a href="https://github.com/etcd-io/etcd" style="display:block">etcd</a>
|
||||
<a href="https://github.com/cockroachdb/cockroach" style="display:block">cockroachdb</a>
|
||||
<a href="https://github.com/openzipkin/brave/tree/master/archive/brave-grpc" style="display:block">Zipkin for gRPC</a>
|
||||
<a href="https://github.com/pingcap/tidb" style="display:block">TiDB</a>
|
||||
<a href="https://github.com/apache/bookkeeper" style="display:block">Apache BookKeeper</a>
|
||||
<br>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>Documentation on gRPC</title>
|
||||
<link>https://cjyabraham.github.io/docs/</link>
|
||||
<description>Recent content in Documentation on gRPC</description>
|
||||
<generator>Hugo -- gohugo.io</generator>
|
||||
<language>en-us</language>
|
||||
|
||||
<atom:link href="https://cjyabraham.github.io/docs/index.xml" rel="self" type="application/rss+xml" />
|
||||
|
||||
|
||||
</channel>
|
||||
</rss>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue