Video and slides synchronized, mp3 and slide download available at URL http://bit.ly/2k1eZ00.
Chris Roche and Christopher Burnett discuss how they extended the Protocol Buffer (PB) IDL to create unified APIs and data models. From validation logic to automatic logging and statistics, PBs allows them to speed up development across Go, Python, and PHP stacks. They also show how they leverage the Envoy proxy to transparently upgrade HTTP/1.1 services to speak gRPC on the wire. Filmed at qconnewyork.com.
Chris Roche is a Core Libraries Engineer at Lyft focused on enriching the tools to create distributed systems. Christopher Burnett is Lead Core Libraries Engineer at Lyft, where he designs software for distributed systems.
Generating Unified APIs with Protocol Buffers and gRPC
1. TYPES ALL THE WAY DOWN
GENERATING APIS WITH PROTOBUFS AND GRPC
2. InfoQ.com: News & Community Site
• 750,000 unique visitors/month
• Published in 4 languages (English, Chinese, Japanese and Brazilian
Portuguese)
• Post content from our QCon conferences
• News 15-20 / week
• Articles 3-4 / week
• Presentations (videos) 12-15 / week
• Interviews 2-3 / week
• Books 1 / month
Watch the video with slide
synchronization on InfoQ.com!
https://www.infoq.com/presentations/
api-pb-grpc
3. Presented at QCon New York
www.qconnewyork.com
Purpose of QCon
- to empower software development by facilitating the spread of
knowledge and innovation
Strategy
- practitioner-driven conference designed for YOU: influencers of
change and innovation in your teams
- speakers and topics driving the evolution and innovation
- connecting and catalyzing the influencers and innovators
Highlights
- attended by more than 12,000 delegates since 2007
- held in 9 cities worldwide
4. HI!
Christopher Burnett - Lead Core Libraries
Formerly Twitter, VSCO
@twoism
Chris Roche - Core Libraries
Formerly VSCO
@rodaine
5. CORE LIBRARIES
A little about us…
• HTTP & gRPC Frameworks
• Tooling for Go, Python, and PHP
• Rolling out gRPC within Lyft
6. AGENDA
• Why choose RPC in the first place?
• Working with legacy systems
• Disrupting workflows, nicely :)
• What we’ve built
7. EVERY TEN YEARS…
A furious bout of language and protocol design takes place and a new
distributed computing paradigm is announced that is compliant with the
latest programming model.
- A Note On Distributed Computing, Waldo 1994
10. A LITTLE HISTORY
Like any good story we begin with a PHP
monolith…
• Active decomp efforts
• 100s of Python Microservices
- Flask HTTP/REST
And to keep things interesting…
• gRPC Core and Compositional Services
11. DEFINING A CORE SERVICE
• Organizational Primitives
- User, Rides, Vehicles
• Zero (Service) Dependencies
- Databases, caches, etc
• Highly Performant
21. IDLS ARE PRETTY GREAT
• Single Source of Truth
-Primitive definitions
• Code Generation
-APIs, Clients, Servers, Data Models, Docs, Observability
• Extensibility
-Plugins for everything else
22. IDL SERVICE DEFINITION
package lyft.service.users.v1
service Users {
rpc Update(UpdateRequest) UpdateResponse;
}
message UpdateRequest {
uint64 id = 1;
string name = 2;
}
34. WHAT CAN MAKE THIS BETTER?
• Incremental Adoption
-Allow teams to opt-in to the new shiny things
• Familiarity
-Tooling that feels welcoming
-Standardized framework patterns
• Roll Forward
-Wire format first, then the protocol and frameworks
35. How can we make protocol and
infra changes flexible and
transparent?
46. ODIE: MODELS AS PROTOCOL BUFFERS
message User {
option (odie.mongo).enabled = true;
string id = 1 [(odie.mongo).primary = true,
(odie.type).object_id = true];
string name = 2 [(odie.mongo).name = "username"];
int64 date = 3 [(odie.type).datetime = true];
uint32 vers = 4 [(odie.locking).revision = true];
}
47. ODIE: MODELS AS PROTOCOL BUFFERS
type UserModel struct {
Id bson.ObjectId `bson:"_id"`
Name string `bson:"username"`
Date time.Time
Vers uint32
}
func (pb *User) ToModel() *UserModel
func (m *UserModel) ToProto() *User
48. ODIE: TYPE-SAFE REPOSITORIES
type UserRepo interface {
Events() *Events
Get(ctx context.Context, id bson.ObjectId) *GetBuilder
Put(ctx context.Context, m *UserModel) *PutBuilder
Delete(ctx context.Context) *DeleteBuilder
Update(ctx context.Context) *UpdateBuilder
Query(ctx context.Context) *QueryBuilder
}
49. ODIE: THE PLATONIC IDEAL
• Zero/Empty value ≅ Nil value
- False is semantically the same as null
• Fields are not polymorphic
- All attributes are singularly typed
• Models are rigidly typed
- Legacy data is already mappable
50. ODIE: THE REALITY
• Zero/Empty value ≅ Nil value
- False is semantically the same as null
• Fields are not polymorphic
- All attributes are singularly typed
• Models are rigidly typed
- Legacy data is already mappable
• true and false …and nil
- Allow proto2 syntax models
• Need to decomp from existing
PHP Doctrine models
- Move source of truth without breaking
legacy code.
• Covariant polymorphic
repeated discriminator maps
- Enough said.
51. “How do you change the
wheels of a moving train?”
52. MOVE THE SOURCE OF TRUTH
Entity
UserModel
Schema
Computed
Properties
Behavior
Entity
UserModel
Computed
Properties
Behavior
UserFields
Schema
Codegen
from
the IDL
53. MOVE THE SOURCE OF TRUTH
Users Service
Envoy
Legacy PHP
Envoy
m.ToProto()
pb.ToModel()
OdieDoctrine
Adapter
Odie
Repo
Legacy
ModelPB / gRPC
Fields
Class
62. PROTOC-GEN-STAR (PG*)
Code generation framework
• AST of Lyft primitives
• Simplifies code generation
• Highly testable
Package
File
Service
Method Enum
EnumValue
Message
OneOf
Field
63. PG*: WALK THE AST
type Visitor interface {
VisitPackage(Package) (v Visitor, err error)
VisitFile(File) (v Visitor, err error)
VisitMessage(Message) (v Visitor, err error)
VisitEnum(Enum) (v Visitor, err error)
VisitEnumValue(EnumValue) (v Visitor, err error)
VisitField(Field) (v Visitor, err error)
VisitOneOf(OneOf) (v Visitor, err error)
VisitService(Service) (v Visitor, err error)
VisitMethod(Method) (v Visitor, err error)
}
65. SERVICE GENERATION
Srv Framework
HTTP Server gRPC Server
Debug API
App-Level Config
Users Odie Gizmo Odie
HTTP Service
Config
Users Service ConfigModel Repositories
HTTP Handlers Users Handlers
66. FUTURE TOOLS
Linting & Static Analysis
• Enforce best practices
• Protect production code
• Core Libraries ≠ IDL Police
Mocks & Test Fixtures
• Scenarios of valid state
• Reduce reliance on integration tests
• Developer confidence
gRPC on Mobile
• Reduced payload size
• Leverage streaming APIs
• Global consistency