利用gRPC构建Python微服务(五)微服务可观测性
在上一篇中,主要讲解了如何将开发好的微服务模块部署到Kubernetes中,本篇将介绍拦截器的使用方法。 全文导航
为了方便大家阅读,这里将全部目录进行一下索引,方便大家在老孙正经胡说(https://sunqi.site)中查看相关文章: 利用gRPC构建Python微服务(一)——关于微服务(https://sunqi.site/posts/python-microservices-grpc-1/) 利用gRPC构建Python微服务(二)——gRPC基础(https://sunqi.site/posts/python-microservices-grpc-2/) 利用gRPC构建Python微服务(三)——实战Python gRPC(https://sunqi.site/posts/python-microservices-grpc-3/) 利用gRPC构建Python微服务(四)——在Kubernetes中部署(https://sunqi.site/posts/python-microservices-grpc-4/) 利用gRPC构建Python微服务(五)——微服务可观测性(https://sunqi.site/posts/python-microservices-grpc-5/) 利用gRPC构建Python微服务(六)——Python gRPC最佳实践(https://sunqi.site/posts/python-microservices-grpc-6/) 利用gRPC构建Python微服务(七)——AsyncIO和gRPC(https://sunqi.site/posts/python-microservices-grpc-7/) 使用拦截器(Interceptors)对微服务进行监控
一旦你在云中使用了微服务,你需要具备可观测性。你需要监控的项目包括: 每个微服务收到的请求 错误请求,以及错误内容 请求延时 异常堆栈帮助后续调查
下面就介绍一些方法。 为什么不用装饰器(Decorators)
对于Python开发人员自然想到在每个微服务端点使用装饰器(Decorator)。这种情况下,使用装饰器有以下缺点: 新的微服务开发时,开发人员需要记住在每个方法前添加装饰器 如果你有很多监控,你可能在各种装饰器的堆栈中结束 如果你有几个装饰器,开发人员可能顺序排错了 你可能想把所有的监控写入单一装饰器中,但是这只能让一切变得更加混乱
这个装饰器堆栈是你想避免的: class RecommendationService(recommendations_pb2_grpc.RecommendationsServicer):
@catch_and_log_exceptions
@log_request_counts
@log_latency
def Recommend(self, request, context):
...
以上实现非常丑陋并且重复,违反了DRY programming原则:不要重复制造轮子。装饰器开发中也具有挑战,特别是接受了很多参数。 拦截器(Interceptors)
这里面介绍一下gRPC中提供的类似装饰器的方式——拦截器,比装饰器的实现更加干净。 实现拦截器
很不幸,Python实现gRPC拦截器API非常复杂,因为过于灵活。但grpc-inteceptor包对此进行了简化。
将他们添加到 recommendations/requirements.txt grpc-interceptor ~= 0.12.0
grpcio-tools ~= 1.30
pytest ~= 5.4
更新你的virtualenv环境
$ python -m pip install recommendations/requirements.txt
以下是一个拦截器的示例 from grpc_interceptor import ServerInterceptor
class ErrorLogger(ServerInterceptor):
def intercept(self, method, request, context, method_name):
try:
return method(request, context)
except Exception as e:
self.log_error(e)
raise
def log_error(self, e: Exception) -> None:
# ...
当发生未捕获异常时,会调用log_error,你可以尝试实现,将异常发送至APM系统等。
使用这个拦截器,你只需要传给grpc.server() interceptors = [ErrorLogger()]
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10),
interceptors=interceptors)
使用这段代码,所有微服务的请求和返回都经过你的拦截器,这样你就可以统计有多少请求是错误的。
grpc-interceptor也为每个gRPC状态码提供了异常拦截器 ExceptionToStatusInterceptor 。如果微服务抛出异常,然后ExceptionToStatusInterceptor 将设置了gRPC状态码。这可以让你轻松的简化你的代码,如下面的高亮部分:from grpc_interceptor import ExceptionToStatusInterceptor
from grpc_interceptor.exceptions import NotFound
# ...
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
)
# ...
代码的可读性更高,你能从很多函数中抛出异常,无须传给context,通过调用context.abort()实现。拦截器将为你捕获抛出的异常,无须自行实现。 测试拦截器
如果你想开发自己的拦截器,你应该测试他们。但是使用mock方式测试拦截器很危险。举个例子,你可以在测试中调用.intercept(),确保返回你预期内容,但是不会测试真实的输入甚至不会被调用。
为了优化测试,可以运行带拦截器的gRPC微服务。grpc-interceptor提供一个框架去实现。下面,为ErrorLogger拦截器写一个测试。这仅仅是一个测试,不需要在代码中实现,如果需要加入项目中,则需要添加到单独的测试文件中。 from grpc_interceptor.testing import dummy_client, DummyRequest, raises
class MockErrorLogger(ErrorLogger):
def __init__(self):
self.logged_exception = None
def log_error(self, e: Exception) -> None:
self.logged_exception = e
def test_log_error():
mock = MockErrorLogger()
ex = Exception()
special_cases = {"error": raises(ex)}
with dummy_client(special_cases=special_cases, interceptors=[mock]) as client:
# Test no exception
assert client.Execute(DummyRequest(input="foo")).output == "foo"
assert mock.logged_exception is None
# Test exception
with pytest.raises(grpc.RpcError) as e:
client.Execute(DummyRequest(input="error"))
assert mock.logged_exception is ex
在某些场景下,可以使用service mesh实现拦截器。所有微服务的请求和返回都会经过代理,从代理层面可以自动处理日志或者记录错误次数。为了获取更精确地错误输出,你的微服务需要正确设置状态码。在某些场景下,你的拦截器能实现server mesh。一种流行的server mesh是lstio。
你的iPhone上安装了哪些优秀的App?这11个iPhone上超级出色的良心APP,好几个iPhone自带的优秀软件,原来iPhone自带的软件竟然可以这么好用!以前真的是没发掘到!用完直呼相见恨晚!1微手帐(iOSAn
c入门教程(十三)委托委托是一个方法的签名,它规定了方法的返回类型,参数的个数和类型。委托的作用是可以把方法当成参数一样进行传递。定义publicdelegatevoidToDo()委托由访问级别关键词
电商之利弊电商优化了生产要素,提高了生产效率,相当于提高了生产力,比如原来全国的人民一年需1亿台电视机,从材料,到组装到分销渠道共需一百万工人,电视机一台一万。现在电商从分销渠道上少用五十万
电脑一直嘟嘟嘟响是什么问题相信也有不少用户遇到过笔记本出现嘟嘟的声音的情况,出现这样的问题会对我们使用电脑造成一定的影响和困扰。那么我们应该如何解决出现嘟嘟声的问题呢?接下来就为大家来介绍一个小妙招,教教大
英特尔订购全球最先进芯片制造机,为追赶台积电财经网科技1月19日讯,据新浪科技报道,为了从台积电手中夺回全球最先进芯片制造商的地位,英特尔今日向荷兰光刻机制造商阿斯麦(ASML)订购了一款最先进的芯片制造机(光刻机)。这款光
邓丽君现场清唱甜蜜蜜!微软奈飞等巨头纷纷入局,又一风口来了?(央视财经经济信息联播)近来,元宇宙概念可谓是火爆网络。虚拟的世界个性化的人物和沉浸式的场景,都吸引了不少的关注。在元宇宙里可以有怎样的体验?生活方式会有哪些改变呢?记者走入元宇宙
微软收购暴雪索尼股价暴跌市值一日蒸发200亿美元!丨一只热股微软宣布以687亿美元的价格收购游戏开发商动视暴雪后,市场出现了剧烈震动。微软在游戏界的主要竞争对手索尼尤其受挫。1月19日,索尼股价暴跌13,市值一天之内减少约200亿美元。微软
Oracle不同数据库之间同步处理方案背景项目中遇到的问题,需要二区两台数据库之间同步一些表,以及导出sql文件同步至三区数据库。1SQL文件目录新建SQL文件生成的目录DmptmsudataDNLTBDIR。二区数据
想换电动车,新日和雅迪哪个更好?选新日是必须的,好品质选新日,新日是电动车制造的黄浦军校,试问爱玛,雅迪等前十位电车制造商,哪家没有从新日高薪挖宝,亚运会,奥运会,世博会,指定用车是新日,还是上海主板上市公司,我
全球最大比特币基金较比特币折价近30创出纪录Grayscale比特币信托基金成为了加密货币遭遇抛售的最大受害者之一。这个规模达到270亿美元的基金(代码GBTC)2022年迄今下跌了近27,大于比特币近9的跌幅。根据彭博的数
中信证券新能源汽车换电行业销量五年有望提升十倍以上3060大背景下,换电成为推动新能源汽车全场景普及的必然形式,是充电的有效补充。我们预计,在政策资本自身产品力提升下,2022年有望成为换电行业高速发展的元年,全年有望新增换电站超