Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
mikes zhang
001
提交
c1bc7de2
0
001
项目概览
mikes zhang
/
001
通知
6
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
0
001
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
未验证
提交
c1bc7de2
编写于
1月 22, 2021
作者:
J
Jacob Schmitt
提交者:
GitHub
1月 22, 2021
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #149 from d5h/microservices-with-grpc
Add materials for
https://github.com/realpython/tutorial-drafts/pull/602
上级
13c8992c
ce37b637
变更
20
隐藏空白更改
内联
并排
Showing
20 changed file
with
1117 addition
and
0 deletion
+1117
-0
python-microservices-with-grpc/README.md
python-microservices-with-grpc/README.md
+4
-0
python-microservices-with-grpc/build_and_run.sh
python-microservices-with-grpc/build_and_run.sh
+8
-0
python-microservices-with-grpc/docker-compose.yaml
python-microservices-with-grpc/docker-compose.yaml
+23
-0
python-microservices-with-grpc/gen_certs.sh
python-microservices-with-grpc/gen_certs.sh
+12
-0
python-microservices-with-grpc/integration_tests.sh
python-microservices-with-grpc/integration_tests.sh
+9
-0
python-microservices-with-grpc/kubernetes.yaml
python-microservices-with-grpc/kubernetes.yaml
+68
-0
python-microservices-with-grpc/marketplace/Dockerfile
python-microservices-with-grpc/marketplace/Dockerfile
+23
-0
python-microservices-with-grpc/marketplace/marketplace.py
python-microservices-with-grpc/marketplace/marketplace.py
+36
-0
python-microservices-with-grpc/marketplace/marketplace_integration_test.py
...ces-with-grpc/marketplace/marketplace_integration_test.py
+7
-0
python-microservices-with-grpc/marketplace/recommendations_pb2.py
...icroservices-with-grpc/marketplace/recommendations_pb2.py
+308
-0
python-microservices-with-grpc/marketplace/recommendations_pb2_grpc.py
...ervices-with-grpc/marketplace/recommendations_pb2_grpc.py
+77
-0
python-microservices-with-grpc/marketplace/requirements.txt
python-microservices-with-grpc/marketplace/requirements.txt
+4
-0
python-microservices-with-grpc/marketplace/templates/homepage.html
...croservices-with-grpc/marketplace/templates/homepage.html
+13
-0
python-microservices-with-grpc/protobufs/recommendations.proto
...n-microservices-with-grpc/protobufs/recommendations.proto
+26
-0
python-microservices-with-grpc/recommendations/Dockerfile
python-microservices-with-grpc/recommendations/Dockerfile
+22
-0
python-microservices-with-grpc/recommendations/recommendations.py
...icroservices-with-grpc/recommendations/recommendations.py
+77
-0
python-microservices-with-grpc/recommendations/recommendations_pb2.py
...services-with-grpc/recommendations/recommendations_pb2.py
+308
-0
python-microservices-with-grpc/recommendations/recommendations_pb2_grpc.py
...ces-with-grpc/recommendations/recommendations_pb2_grpc.py
+77
-0
python-microservices-with-grpc/recommendations/recommendations_test.py
...ervices-with-grpc/recommendations/recommendations_test.py
+12
-0
python-microservices-with-grpc/recommendations/requirements.txt
...-microservices-with-grpc/recommendations/requirements.txt
+3
-0
未找到文件。
python-microservices-with-grpc/README.md
0 → 100644
浏览文件 @
c1bc7de2
# Running the Example
1.
Install Docker if you haven't already.
2.
Run
`./build_and_run.sh`
.
python-microservices-with-grpc/build_and_run.sh
0 → 100755
浏览文件 @
c1bc7de2
#!/bin/bash
./gen_certs.sh
DOCKER_BUILDKIT
=
1 docker build
.
-f
marketplace/Dockerfile
-t
marketplace
--secret
id
=
ca.key,src
=
ca.key
DOCKER_BUILDKIT
=
1 docker build
.
-f
recommendations/Dockerfile
-t
recommendations
--secret
id
=
ca.key,src
=
ca.key
docker-compose up
python-microservices-with-grpc/docker-compose.yaml
0 → 100644
浏览文件 @
c1bc7de2
version
:
"
3.8"
services
:
marketplace
:
environment
:
RECOMMENDATIONS_HOST
:
recommendations
# DOCKER_BUILDKIT=1 docker build . -f marketplace/Dockerfile \
# -t marketplace --secret id=ca.key,src=ca.key
image
:
marketplace
networks
:
-
microservices
ports
:
-
5000:5000
recommendations
:
# DOCKER_BUILDKIT=1 docker build . -f recommendations/Dockerfile \
# -t recommendations --secret id=ca.key,src=ca.key
image
:
recommendations
networks
:
-
microservices
networks
:
microservices
:
python-microservices-with-grpc/gen_certs.sh
0 → 100755
浏览文件 @
c1bc7de2
#!/bin/bash
# Generate CA key and self-signed cert
openssl req
-x509
-nodes
-newkey
rsa:4096
-keyout
ca.key
-out
ca.pem
-subj
/O
=
me
# Generate a private key and certificate signing request for the client and server
openssl req
-nodes
-newkey
rsa:4096
-keyout
client.key
-out
client.csr
-subj
/CN
=
marketplace
openssl req
-nodes
-newkey
rsa:4096
-keyout
server.key
-out
server.csr
-subj
/CN
=
recommendations
# Sign the client and server certs with the CA cert
openssl x509
-req
-in
client.csr
-CA
ca.pem
-CAkey
ca.key
-set_serial
1
-out
client.pem
openssl x509
-req
-in
server.csr
-CA
ca.pem
-CAkey
ca.key
-set_serial
1
-out
server.pem
python-microservices-with-grpc/integration_tests.sh
0 → 100755
浏览文件 @
c1bc7de2
#!/bin/bash
set
-euo
pipefail
docker-compose up
-d
trap
"docker-compose down"
EXIT
sleep
5
# Give the services time to warm up
docker-compose
exec
marketplace pytest
python-microservices-with-grpc/kubernetes.yaml
0 → 100644
浏览文件 @
c1bc7de2
---
apiVersion
:
apps/v1
kind
:
Deployment
metadata
:
name
:
marketplace
labels
:
app
:
marketplace
spec
:
replicas
:
1
selector
:
matchLabels
:
app
:
marketplace
template
:
metadata
:
labels
:
app
:
marketplace
spec
:
containers
:
-
name
:
marketplace
image
:
hidan/python-microservices-article-marketplace:0.1
env
:
-
name
:
RECOMMENDATIONS_HOST
value
:
recommendations
---
apiVersion
:
apps/v1
kind
:
Deployment
metadata
:
name
:
recommendations
labels
:
app
:
recommendations
spec
:
replicas
:
1
selector
:
matchLabels
:
app
:
recommendations
template
:
metadata
:
labels
:
app
:
recommendations
spec
:
containers
:
-
name
:
recommendations
image
:
hidan/python-microservices-article-recommendations:0.1
---
apiVersion
:
v1
kind
:
Service
metadata
:
name
:
recommendations
spec
:
selector
:
app
:
recommendations
ports
:
-
protocol
:
TCP
port
:
50051
targetPort
:
50051
---
apiVersion
:
v1
kind
:
Service
metadata
:
name
:
marketplace
spec
:
type
:
LoadBalancer
selector
:
app
:
marketplace
ports
:
-
protocol
:
TCP
port
:
5000
targetPort
:
5000
python-microservices-with-grpc/marketplace/Dockerfile
0 → 100644
浏览文件 @
c1bc7de2
# syntax = docker/dockerfile:1.0-experimental
# DOCKER_BUILDKIT=1 docker build . -f marketplace/Dockerfile -t marketplace --secret id=ca.key,src=ca.key
FROM
python
RUN
mkdir
/service
COPY
protobufs/ /service/protobufs/
COPY
marketplace/ /service/marketplace/
COPY
ca.pem /service/marketplace/
WORKDIR
/service/marketplace
RUN
pip
install
-r
requirements.txt
RUN
python
-m
grpc_tools.protoc
-I
../protobufs
--python_out
=
.
\
--grpc_python_out
=
.
../protobufs/recommendations.proto
RUN
openssl req
-nodes
-newkey
rsa:4096
-subj
/CN
=
marketplace
\
-keyout
client.key
-out
client.csr
RUN
--mount
=
type
=
secret,id
=
ca.key
\
openssl x509
-req
-in
client.csr
-CA
ca.pem
-CAkey
/run/secrets/ca.key
\
-set_serial
1
-out
client.pem
EXPOSE
5000
ENV
FLASK_APP=marketplace.py
ENTRYPOINT
[ "flask", "run", "--host=0.0.0.0"]
python-microservices-with-grpc/marketplace/marketplace.py
0 → 100644
浏览文件 @
c1bc7de2
import
os
from
flask
import
Flask
,
render_template
import
grpc
from
recommendations_pb2
import
BookCategory
,
RecommendationRequest
from
recommendations_pb2_grpc
import
RecommendationsStub
app
=
Flask
(
__name__
)
recommendations_host
=
os
.
getenv
(
"RECOMMENDATIONS_HOST"
,
"localhost"
)
with
open
(
"client.key"
,
"rb"
)
as
fp
:
client_key
=
fp
.
read
()
with
open
(
"client.pem"
,
"rb"
)
as
fp
:
client_cert
=
fp
.
read
()
with
open
(
"ca.pem"
,
"rb"
)
as
fp
:
ca_cert
=
fp
.
read
()
creds
=
grpc
.
ssl_channel_credentials
(
ca_cert
,
client_key
,
client_cert
)
recommendations_channel
=
grpc
.
secure_channel
(
f
"
{
recommendations_host
}
:443"
,
creds
)
recommendations_client
=
RecommendationsStub
(
recommendations_channel
)
@
app
.
route
(
"/"
)
def
render_homepage
():
recommendations_request
=
RecommendationRequest
(
user_id
=
1
,
category
=
BookCategory
.
MYSTERY
,
max_results
=
3
)
recommendations_response
=
recommendations_client
.
Recommend
(
recommendations_request
)
return
render_template
(
"homepage.html"
,
recommendations
=
recommendations_response
.
recommendations
,
)
python-microservices-with-grpc/marketplace/marketplace_integration_test.py
0 → 100644
浏览文件 @
c1bc7de2
from
urllib.request
import
urlopen
def
test_render_homepage
():
homepage_html
=
urlopen
(
"http://localhost:5000"
).
read
().
decode
(
"utf-8"
)
assert
"<title>Online Books For You</title>"
in
homepage_html
assert
homepage_html
.
count
(
"<li>"
)
==
3
python-microservices-with-grpc/marketplace/recommendations_pb2.py
0 → 100644
浏览文件 @
c1bc7de2
# -*- coding: utf-8 -*-
# flake8: noqa
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: recommendations.proto
from
google.protobuf.internal
import
enum_type_wrapper
from
google.protobuf
import
descriptor
as
_descriptor
from
google.protobuf
import
message
as
_message
from
google.protobuf
import
reflection
as
_reflection
from
google.protobuf
import
symbol_database
as
_symbol_database
# @@protoc_insertion_point(imports)
_sym_db
=
_symbol_database
.
Default
()
DESCRIPTOR
=
_descriptor
.
FileDescriptor
(
name
=
"recommendations.proto"
,
package
=
""
,
syntax
=
"proto3"
,
serialized_options
=
None
,
serialized_pb
=
b
'
\n\x15
recommendations.proto"^
\n\x15
RecommendationRequest
\x12\x0f\n\x07
user_id
\x18\x01
\x01
(
\x05\x12\x1f\n\x08\x63\x61
tegory
\x18\x02
\x01
(
\x0e\x32\r
.BookCategory
\x12\x13\n\x0b
max_results
\x18\x03
\x01
(
\x05
"/
\n\x12\x42
ookRecommendation
\x12\n\n\x02
id
\x18\x01
\x01
(
\x05\x12\r\n\x05
title
\x18\x02
\x01
(
\t
"F
\n\x16
RecommendationResponse
\x12
,
\n\x0f
recommendations
\x18\x01
\x03
(
\x0b\x32\x13
.BookRecommendation*?
\n\x0c\x42
ookCategory
\x12\x0b\n\x07
MYSTERY
\x10\x00\x12\x13\n\x0f
SCIENCE_FICTION
\x10\x01\x12\r\n\t
SELF_HELP
\x10\x02\x32
O
\n\x0f
Recommendations
\x12
<
\n\t
Recommend
\x12\x16
.RecommendationRequest
\x1a\x17
.RecommendationResponseb
\x06
proto3'
,
)
_BOOKCATEGORY
=
_descriptor
.
EnumDescriptor
(
name
=
"BookCategory"
,
full_name
=
"BookCategory"
,
filename
=
None
,
file
=
DESCRIPTOR
,
values
=
[
_descriptor
.
EnumValueDescriptor
(
name
=
"MYSTERY"
,
index
=
0
,
number
=
0
,
serialized_options
=
None
,
type
=
None
,
),
_descriptor
.
EnumValueDescriptor
(
name
=
"SCIENCE_FICTION"
,
index
=
1
,
number
=
1
,
serialized_options
=
None
,
type
=
None
,
),
_descriptor
.
EnumValueDescriptor
(
name
=
"SELF_HELP"
,
index
=
2
,
number
=
2
,
serialized_options
=
None
,
type
=
None
,
),
],
containing_type
=
None
,
serialized_options
=
None
,
serialized_start
=
242
,
serialized_end
=
305
,
)
_sym_db
.
RegisterEnumDescriptor
(
_BOOKCATEGORY
)
BookCategory
=
enum_type_wrapper
.
EnumTypeWrapper
(
_BOOKCATEGORY
)
MYSTERY
=
0
SCIENCE_FICTION
=
1
SELF_HELP
=
2
_RECOMMENDATIONREQUEST
=
_descriptor
.
Descriptor
(
name
=
"RecommendationRequest"
,
full_name
=
"RecommendationRequest"
,
filename
=
None
,
file
=
DESCRIPTOR
,
containing_type
=
None
,
fields
=
[
_descriptor
.
FieldDescriptor
(
name
=
"user_id"
,
full_name
=
"RecommendationRequest.user_id"
,
index
=
0
,
number
=
1
,
type
=
5
,
cpp_type
=
1
,
label
=
1
,
has_default_value
=
False
,
default_value
=
0
,
message_type
=
None
,
enum_type
=
None
,
containing_type
=
None
,
is_extension
=
False
,
extension_scope
=
None
,
serialized_options
=
None
,
file
=
DESCRIPTOR
,
),
_descriptor
.
FieldDescriptor
(
name
=
"category"
,
full_name
=
"RecommendationRequest.category"
,
index
=
1
,
number
=
2
,
type
=
14
,
cpp_type
=
8
,
label
=
1
,
has_default_value
=
False
,
default_value
=
0
,
message_type
=
None
,
enum_type
=
None
,
containing_type
=
None
,
is_extension
=
False
,
extension_scope
=
None
,
serialized_options
=
None
,
file
=
DESCRIPTOR
,
),
_descriptor
.
FieldDescriptor
(
name
=
"max_results"
,
full_name
=
"RecommendationRequest.max_results"
,
index
=
2
,
number
=
3
,
type
=
5
,
cpp_type
=
1
,
label
=
1
,
has_default_value
=
False
,
default_value
=
0
,
message_type
=
None
,
enum_type
=
None
,
containing_type
=
None
,
is_extension
=
False
,
extension_scope
=
None
,
serialized_options
=
None
,
file
=
DESCRIPTOR
,
),
],
extensions
=
[],
nested_types
=
[],
enum_types
=
[],
serialized_options
=
None
,
is_extendable
=
False
,
syntax
=
"proto3"
,
extension_ranges
=
[],
oneofs
=
[],
serialized_start
=
25
,
serialized_end
=
119
,
)
_BOOKRECOMMENDATION
=
_descriptor
.
Descriptor
(
name
=
"BookRecommendation"
,
full_name
=
"BookRecommendation"
,
filename
=
None
,
file
=
DESCRIPTOR
,
containing_type
=
None
,
fields
=
[
_descriptor
.
FieldDescriptor
(
name
=
"id"
,
full_name
=
"BookRecommendation.id"
,
index
=
0
,
number
=
1
,
type
=
5
,
cpp_type
=
1
,
label
=
1
,
has_default_value
=
False
,
default_value
=
0
,
message_type
=
None
,
enum_type
=
None
,
containing_type
=
None
,
is_extension
=
False
,
extension_scope
=
None
,
serialized_options
=
None
,
file
=
DESCRIPTOR
,
),
_descriptor
.
FieldDescriptor
(
name
=
"title"
,
full_name
=
"BookRecommendation.title"
,
index
=
1
,
number
=
2
,
type
=
9
,
cpp_type
=
9
,
label
=
1
,
has_default_value
=
False
,
default_value
=
b
""
.
decode
(
"utf-8"
),
message_type
=
None
,
enum_type
=
None
,
containing_type
=
None
,
is_extension
=
False
,
extension_scope
=
None
,
serialized_options
=
None
,
file
=
DESCRIPTOR
,
),
],
extensions
=
[],
nested_types
=
[],
enum_types
=
[],
serialized_options
=
None
,
is_extendable
=
False
,
syntax
=
"proto3"
,
extension_ranges
=
[],
oneofs
=
[],
serialized_start
=
121
,
serialized_end
=
168
,
)
_RECOMMENDATIONRESPONSE
=
_descriptor
.
Descriptor
(
name
=
"RecommendationResponse"
,
full_name
=
"RecommendationResponse"
,
filename
=
None
,
file
=
DESCRIPTOR
,
containing_type
=
None
,
fields
=
[
_descriptor
.
FieldDescriptor
(
name
=
"recommendations"
,
full_name
=
"RecommendationResponse.recommendations"
,
index
=
0
,
number
=
1
,
type
=
11
,
cpp_type
=
10
,
label
=
3
,
has_default_value
=
False
,
default_value
=
[],
message_type
=
None
,
enum_type
=
None
,
containing_type
=
None
,
is_extension
=
False
,
extension_scope
=
None
,
serialized_options
=
None
,
file
=
DESCRIPTOR
,
),
],
extensions
=
[],
nested_types
=
[],
enum_types
=
[],
serialized_options
=
None
,
is_extendable
=
False
,
syntax
=
"proto3"
,
extension_ranges
=
[],
oneofs
=
[],
serialized_start
=
170
,
serialized_end
=
240
,
)
_RECOMMENDATIONREQUEST
.
fields_by_name
[
"category"
].
enum_type
=
_BOOKCATEGORY
_RECOMMENDATIONRESPONSE
.
fields_by_name
[
"recommendations"
].
message_type
=
_BOOKRECOMMENDATION
DESCRIPTOR
.
message_types_by_name
[
"RecommendationRequest"
]
=
_RECOMMENDATIONREQUEST
DESCRIPTOR
.
message_types_by_name
[
"BookRecommendation"
]
=
_BOOKRECOMMENDATION
DESCRIPTOR
.
message_types_by_name
[
"RecommendationResponse"
]
=
_RECOMMENDATIONRESPONSE
DESCRIPTOR
.
enum_types_by_name
[
"BookCategory"
]
=
_BOOKCATEGORY
_sym_db
.
RegisterFileDescriptor
(
DESCRIPTOR
)
RecommendationRequest
=
_reflection
.
GeneratedProtocolMessageType
(
"RecommendationRequest"
,
(
_message
.
Message
,),
{
"DESCRIPTOR"
:
_RECOMMENDATIONREQUEST
,
"__module__"
:
"recommendations_pb2"
# @@protoc_insertion_point(class_scope:RecommendationRequest)
},
)
_sym_db
.
RegisterMessage
(
RecommendationRequest
)
BookRecommendation
=
_reflection
.
GeneratedProtocolMessageType
(
"BookRecommendation"
,
(
_message
.
Message
,),
{
"DESCRIPTOR"
:
_BOOKRECOMMENDATION
,
"__module__"
:
"recommendations_pb2"
# @@protoc_insertion_point(class_scope:BookRecommendation)
},
)
_sym_db
.
RegisterMessage
(
BookRecommendation
)
RecommendationResponse
=
_reflection
.
GeneratedProtocolMessageType
(
"RecommendationResponse"
,
(
_message
.
Message
,),
{
"DESCRIPTOR"
:
_RECOMMENDATIONRESPONSE
,
"__module__"
:
"recommendations_pb2"
# @@protoc_insertion_point(class_scope:RecommendationResponse)
},
)
_sym_db
.
RegisterMessage
(
RecommendationResponse
)
_RECOMMENDATIONS
=
_descriptor
.
ServiceDescriptor
(
name
=
"Recommendations"
,
full_name
=
"Recommendations"
,
file
=
DESCRIPTOR
,
index
=
0
,
serialized_options
=
None
,
serialized_start
=
307
,
serialized_end
=
386
,
methods
=
[
_descriptor
.
MethodDescriptor
(
name
=
"Recommend"
,
full_name
=
"Recommendations.Recommend"
,
index
=
0
,
containing_service
=
None
,
input_type
=
_RECOMMENDATIONREQUEST
,
output_type
=
_RECOMMENDATIONRESPONSE
,
serialized_options
=
None
,
),
],
)
_sym_db
.
RegisterServiceDescriptor
(
_RECOMMENDATIONS
)
DESCRIPTOR
.
services_by_name
[
"Recommendations"
]
=
_RECOMMENDATIONS
# @@protoc_insertion_point(module_scope)
python-microservices-with-grpc/marketplace/recommendations_pb2_grpc.py
0 → 100644
浏览文件 @
c1bc7de2
# flake8: noqa
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
import
grpc
import
recommendations_pb2
as
recommendations__pb2
class
RecommendationsStub
(
object
):
"""Missing associated documentation comment in .proto file"""
def
__init__
(
self
,
channel
):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self
.
Recommend
=
channel
.
unary_unary
(
"/Recommendations/Recommend"
,
request_serializer
=
recommendations__pb2
.
RecommendationRequest
.
SerializeToString
,
response_deserializer
=
recommendations__pb2
.
RecommendationResponse
.
FromString
,
)
class
RecommendationsServicer
(
object
):
"""Missing associated documentation comment in .proto file"""
def
Recommend
(
self
,
request
,
context
):
"""Missing associated documentation comment in .proto file"""
context
.
set_code
(
grpc
.
StatusCode
.
UNIMPLEMENTED
)
context
.
set_details
(
"Method not implemented!"
)
raise
NotImplementedError
(
"Method not implemented!"
)
def
add_RecommendationsServicer_to_server
(
servicer
,
server
):
rpc_method_handlers
=
{
"Recommend"
:
grpc
.
unary_unary_rpc_method_handler
(
servicer
.
Recommend
,
request_deserializer
=
recommendations__pb2
.
RecommendationRequest
.
FromString
,
response_serializer
=
recommendations__pb2
.
RecommendationResponse
.
SerializeToString
,
),
}
generic_handler
=
grpc
.
method_handlers_generic_handler
(
"Recommendations"
,
rpc_method_handlers
)
server
.
add_generic_rpc_handlers
((
generic_handler
,))
# This class is part of an EXPERIMENTAL API.
class
Recommendations
(
object
):
"""Missing associated documentation comment in .proto file"""
@
staticmethod
def
Recommend
(
request
,
target
,
options
=
(),
channel_credentials
=
None
,
call_credentials
=
None
,
compression
=
None
,
wait_for_ready
=
None
,
timeout
=
None
,
metadata
=
None
,
):
return
grpc
.
experimental
.
unary_unary
(
request
,
target
,
"/Recommendations/Recommend"
,
recommendations__pb2
.
RecommendationRequest
.
SerializeToString
,
recommendations__pb2
.
RecommendationResponse
.
FromString
,
options
,
channel_credentials
,
call_credentials
,
compression
,
wait_for_ready
,
timeout
,
metadata
,
)
python-microservices-with-grpc/marketplace/requirements.txt
0 → 100644
浏览文件 @
c1bc7de2
flask ~= 1.1
grpcio-tools ~= 1.30
Jinja2 ~= 2.11
pytest ~= 5.4
python-microservices-with-grpc/marketplace/templates/homepage.html
0 → 100644
浏览文件 @
c1bc7de2
<!doctype html>
<html
lang=
"en"
>
<head>
<title>
Online Books For You
</title>
</head>
<body>
<h1>
Mystery books you may like
</h1>
<ul>
{% for book in recommendations %}
<li>
{{ book.title }}
</li>
{% endfor %}
</ul>
</body>
python-microservices-with-grpc/protobufs/recommendations.proto
0 → 100644
浏览文件 @
c1bc7de2
syntax
=
"proto3"
;
enum
BookCategory
{
MYSTERY
=
0
;
SCIENCE_FICTION
=
1
;
SELF_HELP
=
2
;
}
message
RecommendationRequest
{
int32
user_id
=
1
;
BookCategory
category
=
2
;
int32
max_results
=
3
;
}
message
BookRecommendation
{
int32
id
=
1
;
string
title
=
2
;
}
message
RecommendationResponse
{
repeated
BookRecommendation
recommendations
=
1
;
}
service
Recommendations
{
rpc
Recommend
(
RecommendationRequest
)
returns
(
RecommendationResponse
);
}
python-microservices-with-grpc/recommendations/Dockerfile
0 → 100644
浏览文件 @
c1bc7de2
# syntax = docker/dockerfile:1.0-experimental
# DOCKER_BUILDKIT=1 docker build . -f recommendations/Dockerfile -t recommendations --secret id=ca.key,src=ca.key
FROM
python
RUN
mkdir
/service
COPY
protobufs/ /service/protobufs/
COPY
recommendations/ /service/recommendations/
COPY
ca.pem /service/recommendations/
WORKDIR
/service/recommendations
RUN
pip
install
-r
requirements.txt
RUN
python
-m
grpc_tools.protoc
-I
../protobufs
--python_out
=
.
\
--grpc_python_out
=
.
../protobufs/recommendations.proto
RUN
openssl req
-nodes
-newkey
rsa:4096
-subj
/CN
=
recommendations
\
-keyout
server.key
-out
server.csr
RUN
--mount
=
type
=
secret,id
=
ca.key
\
openssl x509
-req
-in
server.csr
-CA
ca.pem
-CAkey
/run/secrets/ca.key
\
-set_serial
1
-out
server.pem
EXPOSE
50051
ENTRYPOINT
[ "python", "recommendations.py" ]
python-microservices-with-grpc/recommendations/recommendations.py
0 → 100644
浏览文件 @
c1bc7de2
from
concurrent
import
futures
import
random
import
grpc
from
grpc_interceptor
import
ExceptionToStatusInterceptor
from
grpc_interceptor.exceptions
import
NotFound
from
recommendations_pb2
import
(
BookCategory
,
BookRecommendation
,
RecommendationResponse
,
)
import
recommendations_pb2_grpc
books_by_category
=
{
BookCategory
.
MYSTERY
:
[
BookRecommendation
(
id
=
1
,
title
=
"The Maltese Falcon"
),
BookRecommendation
(
id
=
2
,
title
=
"Murder on the Orient Express"
),
BookRecommendation
(
id
=
3
,
title
=
"The Hound of the Baskervilles"
),
],
BookCategory
.
SCIENCE_FICTION
:
[
BookRecommendation
(
id
=
4
,
title
=
"The Hitchhiker's Guide To The Galaxy"
),
BookRecommendation
(
id
=
5
,
title
=
"Ender's Game"
),
BookRecommendation
(
id
=
6
,
title
=
"The Dune Chronicles"
),
],
BookCategory
.
SELF_HELP
:
[
BookRecommendation
(
id
=
7
,
title
=
"The 7 Habits of Highly Effective People"
),
BookRecommendation
(
id
=
8
,
title
=
"How to Win Friends and Influence People"
),
BookRecommendation
(
id
=
9
,
title
=
"Man’s Search for Meaning"
),
],
}
class
RecommendationService
(
recommendations_pb2_grpc
.
RecommendationsServicer
):
def
Recommend
(
self
,
request
,
context
):
if
request
.
category
not
in
books_by_category
:
raise
NotFound
(
"Category not found"
)
books_for_category
=
books_by_category
[
request
.
category
]
num_results
=
min
(
request
.
max_results
,
len
(
books_for_category
))
books_to_recommend
=
random
.
sample
(
books_for_category
,
num_results
)
return
RecommendationResponse
(
recommendations
=
books_to_recommend
)
def
serve
():
interceptors
=
[
ExceptionToStatusInterceptor
()]
server
=
grpc
.
server
(
futures
.
ThreadPoolExecutor
(
max_workers
=
10
),
interceptors
=
interceptors
)
recommendations_pb2_grpc
.
add_RecommendationsServicer_to_server
(
RecommendationService
(),
server
)
with
open
(
"server.key"
,
"rb"
)
as
fp
:
server_key
=
fp
.
read
()
with
open
(
"server.pem"
,
"rb"
)
as
fp
:
server_cert
=
fp
.
read
()
with
open
(
"ca.pem"
,
"rb"
)
as
fp
:
ca_cert
=
fp
.
read
()
creds
=
grpc
.
ssl_server_credentials
(
[(
server_key
,
server_cert
)],
root_certificates
=
ca_cert
,
require_client_auth
=
True
,
)
server
.
add_secure_port
(
"[::]:443"
,
creds
)
server
.
start
()
server
.
wait_for_termination
()
if
__name__
==
"__main__"
:
serve
()
python-microservices-with-grpc/recommendations/recommendations_pb2.py
0 → 100644
浏览文件 @
c1bc7de2
# -*- coding: utf-8 -*-
# flake8: noqa
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: recommendations.proto
from
google.protobuf.internal
import
enum_type_wrapper
from
google.protobuf
import
descriptor
as
_descriptor
from
google.protobuf
import
message
as
_message
from
google.protobuf
import
reflection
as
_reflection
from
google.protobuf
import
symbol_database
as
_symbol_database
# @@protoc_insertion_point(imports)
_sym_db
=
_symbol_database
.
Default
()
DESCRIPTOR
=
_descriptor
.
FileDescriptor
(
name
=
"recommendations.proto"
,
package
=
""
,
syntax
=
"proto3"
,
serialized_options
=
None
,
serialized_pb
=
b
'
\n\x15
recommendations.proto"^
\n\x15
RecommendationRequest
\x12\x0f\n\x07
user_id
\x18\x01
\x01
(
\x05\x12\x1f\n\x08\x63\x61
tegory
\x18\x02
\x01
(
\x0e\x32\r
.BookCategory
\x12\x13\n\x0b
max_results
\x18\x03
\x01
(
\x05
"/
\n\x12\x42
ookRecommendation
\x12\n\n\x02
id
\x18\x01
\x01
(
\x05\x12\r\n\x05
title
\x18\x02
\x01
(
\t
"F
\n\x16
RecommendationResponse
\x12
,
\n\x0f
recommendations
\x18\x01
\x03
(
\x0b\x32\x13
.BookRecommendation*?
\n\x0c\x42
ookCategory
\x12\x0b\n\x07
MYSTERY
\x10\x00\x12\x13\n\x0f
SCIENCE_FICTION
\x10\x01\x12\r\n\t
SELF_HELP
\x10\x02\x32
O
\n\x0f
Recommendations
\x12
<
\n\t
Recommend
\x12\x16
.RecommendationRequest
\x1a\x17
.RecommendationResponseb
\x06
proto3'
,
)
_BOOKCATEGORY
=
_descriptor
.
EnumDescriptor
(
name
=
"BookCategory"
,
full_name
=
"BookCategory"
,
filename
=
None
,
file
=
DESCRIPTOR
,
values
=
[
_descriptor
.
EnumValueDescriptor
(
name
=
"MYSTERY"
,
index
=
0
,
number
=
0
,
serialized_options
=
None
,
type
=
None
,
),
_descriptor
.
EnumValueDescriptor
(
name
=
"SCIENCE_FICTION"
,
index
=
1
,
number
=
1
,
serialized_options
=
None
,
type
=
None
,
),
_descriptor
.
EnumValueDescriptor
(
name
=
"SELF_HELP"
,
index
=
2
,
number
=
2
,
serialized_options
=
None
,
type
=
None
,
),
],
containing_type
=
None
,
serialized_options
=
None
,
serialized_start
=
242
,
serialized_end
=
305
,
)
_sym_db
.
RegisterEnumDescriptor
(
_BOOKCATEGORY
)
BookCategory
=
enum_type_wrapper
.
EnumTypeWrapper
(
_BOOKCATEGORY
)
MYSTERY
=
0
SCIENCE_FICTION
=
1
SELF_HELP
=
2
_RECOMMENDATIONREQUEST
=
_descriptor
.
Descriptor
(
name
=
"RecommendationRequest"
,
full_name
=
"RecommendationRequest"
,
filename
=
None
,
file
=
DESCRIPTOR
,
containing_type
=
None
,
fields
=
[
_descriptor
.
FieldDescriptor
(
name
=
"user_id"
,
full_name
=
"RecommendationRequest.user_id"
,
index
=
0
,
number
=
1
,
type
=
5
,
cpp_type
=
1
,
label
=
1
,
has_default_value
=
False
,
default_value
=
0
,
message_type
=
None
,
enum_type
=
None
,
containing_type
=
None
,
is_extension
=
False
,
extension_scope
=
None
,
serialized_options
=
None
,
file
=
DESCRIPTOR
,
),
_descriptor
.
FieldDescriptor
(
name
=
"category"
,
full_name
=
"RecommendationRequest.category"
,
index
=
1
,
number
=
2
,
type
=
14
,
cpp_type
=
8
,
label
=
1
,
has_default_value
=
False
,
default_value
=
0
,
message_type
=
None
,
enum_type
=
None
,
containing_type
=
None
,
is_extension
=
False
,
extension_scope
=
None
,
serialized_options
=
None
,
file
=
DESCRIPTOR
,
),
_descriptor
.
FieldDescriptor
(
name
=
"max_results"
,
full_name
=
"RecommendationRequest.max_results"
,
index
=
2
,
number
=
3
,
type
=
5
,
cpp_type
=
1
,
label
=
1
,
has_default_value
=
False
,
default_value
=
0
,
message_type
=
None
,
enum_type
=
None
,
containing_type
=
None
,
is_extension
=
False
,
extension_scope
=
None
,
serialized_options
=
None
,
file
=
DESCRIPTOR
,
),
],
extensions
=
[],
nested_types
=
[],
enum_types
=
[],
serialized_options
=
None
,
is_extendable
=
False
,
syntax
=
"proto3"
,
extension_ranges
=
[],
oneofs
=
[],
serialized_start
=
25
,
serialized_end
=
119
,
)
_BOOKRECOMMENDATION
=
_descriptor
.
Descriptor
(
name
=
"BookRecommendation"
,
full_name
=
"BookRecommendation"
,
filename
=
None
,
file
=
DESCRIPTOR
,
containing_type
=
None
,
fields
=
[
_descriptor
.
FieldDescriptor
(
name
=
"id"
,
full_name
=
"BookRecommendation.id"
,
index
=
0
,
number
=
1
,
type
=
5
,
cpp_type
=
1
,
label
=
1
,
has_default_value
=
False
,
default_value
=
0
,
message_type
=
None
,
enum_type
=
None
,
containing_type
=
None
,
is_extension
=
False
,
extension_scope
=
None
,
serialized_options
=
None
,
file
=
DESCRIPTOR
,
),
_descriptor
.
FieldDescriptor
(
name
=
"title"
,
full_name
=
"BookRecommendation.title"
,
index
=
1
,
number
=
2
,
type
=
9
,
cpp_type
=
9
,
label
=
1
,
has_default_value
=
False
,
default_value
=
b
""
.
decode
(
"utf-8"
),
message_type
=
None
,
enum_type
=
None
,
containing_type
=
None
,
is_extension
=
False
,
extension_scope
=
None
,
serialized_options
=
None
,
file
=
DESCRIPTOR
,
),
],
extensions
=
[],
nested_types
=
[],
enum_types
=
[],
serialized_options
=
None
,
is_extendable
=
False
,
syntax
=
"proto3"
,
extension_ranges
=
[],
oneofs
=
[],
serialized_start
=
121
,
serialized_end
=
168
,
)
_RECOMMENDATIONRESPONSE
=
_descriptor
.
Descriptor
(
name
=
"RecommendationResponse"
,
full_name
=
"RecommendationResponse"
,
filename
=
None
,
file
=
DESCRIPTOR
,
containing_type
=
None
,
fields
=
[
_descriptor
.
FieldDescriptor
(
name
=
"recommendations"
,
full_name
=
"RecommendationResponse.recommendations"
,
index
=
0
,
number
=
1
,
type
=
11
,
cpp_type
=
10
,
label
=
3
,
has_default_value
=
False
,
default_value
=
[],
message_type
=
None
,
enum_type
=
None
,
containing_type
=
None
,
is_extension
=
False
,
extension_scope
=
None
,
serialized_options
=
None
,
file
=
DESCRIPTOR
,
),
],
extensions
=
[],
nested_types
=
[],
enum_types
=
[],
serialized_options
=
None
,
is_extendable
=
False
,
syntax
=
"proto3"
,
extension_ranges
=
[],
oneofs
=
[],
serialized_start
=
170
,
serialized_end
=
240
,
)
_RECOMMENDATIONREQUEST
.
fields_by_name
[
"category"
].
enum_type
=
_BOOKCATEGORY
_RECOMMENDATIONRESPONSE
.
fields_by_name
[
"recommendations"
].
message_type
=
_BOOKRECOMMENDATION
DESCRIPTOR
.
message_types_by_name
[
"RecommendationRequest"
]
=
_RECOMMENDATIONREQUEST
DESCRIPTOR
.
message_types_by_name
[
"BookRecommendation"
]
=
_BOOKRECOMMENDATION
DESCRIPTOR
.
message_types_by_name
[
"RecommendationResponse"
]
=
_RECOMMENDATIONRESPONSE
DESCRIPTOR
.
enum_types_by_name
[
"BookCategory"
]
=
_BOOKCATEGORY
_sym_db
.
RegisterFileDescriptor
(
DESCRIPTOR
)
RecommendationRequest
=
_reflection
.
GeneratedProtocolMessageType
(
"RecommendationRequest"
,
(
_message
.
Message
,),
{
"DESCRIPTOR"
:
_RECOMMENDATIONREQUEST
,
"__module__"
:
"recommendations_pb2"
# @@protoc_insertion_point(class_scope:RecommendationRequest)
},
)
_sym_db
.
RegisterMessage
(
RecommendationRequest
)
BookRecommendation
=
_reflection
.
GeneratedProtocolMessageType
(
"BookRecommendation"
,
(
_message
.
Message
,),
{
"DESCRIPTOR"
:
_BOOKRECOMMENDATION
,
"__module__"
:
"recommendations_pb2"
# @@protoc_insertion_point(class_scope:BookRecommendation)
},
)
_sym_db
.
RegisterMessage
(
BookRecommendation
)
RecommendationResponse
=
_reflection
.
GeneratedProtocolMessageType
(
"RecommendationResponse"
,
(
_message
.
Message
,),
{
"DESCRIPTOR"
:
_RECOMMENDATIONRESPONSE
,
"__module__"
:
"recommendations_pb2"
# @@protoc_insertion_point(class_scope:RecommendationResponse)
},
)
_sym_db
.
RegisterMessage
(
RecommendationResponse
)
_RECOMMENDATIONS
=
_descriptor
.
ServiceDescriptor
(
name
=
"Recommendations"
,
full_name
=
"Recommendations"
,
file
=
DESCRIPTOR
,
index
=
0
,
serialized_options
=
None
,
serialized_start
=
307
,
serialized_end
=
386
,
methods
=
[
_descriptor
.
MethodDescriptor
(
name
=
"Recommend"
,
full_name
=
"Recommendations.Recommend"
,
index
=
0
,
containing_service
=
None
,
input_type
=
_RECOMMENDATIONREQUEST
,
output_type
=
_RECOMMENDATIONRESPONSE
,
serialized_options
=
None
,
),
],
)
_sym_db
.
RegisterServiceDescriptor
(
_RECOMMENDATIONS
)
DESCRIPTOR
.
services_by_name
[
"Recommendations"
]
=
_RECOMMENDATIONS
# @@protoc_insertion_point(module_scope)
python-microservices-with-grpc/recommendations/recommendations_pb2_grpc.py
0 → 100644
浏览文件 @
c1bc7de2
# flake8: noqa
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
import
grpc
import
recommendations_pb2
as
recommendations__pb2
class
RecommendationsStub
(
object
):
"""Missing associated documentation comment in .proto file"""
def
__init__
(
self
,
channel
):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self
.
Recommend
=
channel
.
unary_unary
(
"/Recommendations/Recommend"
,
request_serializer
=
recommendations__pb2
.
RecommendationRequest
.
SerializeToString
,
response_deserializer
=
recommendations__pb2
.
RecommendationResponse
.
FromString
,
)
class
RecommendationsServicer
(
object
):
"""Missing associated documentation comment in .proto file"""
def
Recommend
(
self
,
request
,
context
):
"""Missing associated documentation comment in .proto file"""
context
.
set_code
(
grpc
.
StatusCode
.
UNIMPLEMENTED
)
context
.
set_details
(
"Method not implemented!"
)
raise
NotImplementedError
(
"Method not implemented!"
)
def
add_RecommendationsServicer_to_server
(
servicer
,
server
):
rpc_method_handlers
=
{
"Recommend"
:
grpc
.
unary_unary_rpc_method_handler
(
servicer
.
Recommend
,
request_deserializer
=
recommendations__pb2
.
RecommendationRequest
.
FromString
,
response_serializer
=
recommendations__pb2
.
RecommendationResponse
.
SerializeToString
,
),
}
generic_handler
=
grpc
.
method_handlers_generic_handler
(
"Recommendations"
,
rpc_method_handlers
)
server
.
add_generic_rpc_handlers
((
generic_handler
,))
# This class is part of an EXPERIMENTAL API.
class
Recommendations
(
object
):
"""Missing associated documentation comment in .proto file"""
@
staticmethod
def
Recommend
(
request
,
target
,
options
=
(),
channel_credentials
=
None
,
call_credentials
=
None
,
compression
=
None
,
wait_for_ready
=
None
,
timeout
=
None
,
metadata
=
None
,
):
return
grpc
.
experimental
.
unary_unary
(
request
,
target
,
"/Recommendations/Recommend"
,
recommendations__pb2
.
RecommendationRequest
.
SerializeToString
,
recommendations__pb2
.
RecommendationResponse
.
FromString
,
options
,
channel_credentials
,
call_credentials
,
compression
,
wait_for_ready
,
timeout
,
metadata
,
)
python-microservices-with-grpc/recommendations/recommendations_test.py
0 → 100644
浏览文件 @
c1bc7de2
from
recommendations
import
RecommendationService
from
recommendations_pb2
import
BookCategory
,
RecommendationRequest
def
test_recommendations
():
service
=
RecommendationService
()
request
=
RecommendationRequest
(
user_id
=
1
,
category
=
BookCategory
.
MYSTERY
,
max_results
=
1
)
response
=
service
.
Recommend
(
request
,
None
)
assert
len
(
response
.
recommendations
)
==
1
python-microservices-with-grpc/recommendations/requirements.txt
0 → 100644
浏览文件 @
c1bc7de2
grpc-interceptor ~= 0.11.0
grpcio-tools ~= 1.30
pytest ~= 5.4
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录