书写拦截器
调用链路、身份验证
- init code、detail
- 错误函数 grpc_code、abort
-
intercept_service(self, continuation, header_call_details)
def _abort(code, details): # unary, stream def terminate(ignored_request, context): context.abort(code, details) return grpc.unary_unary_rpc_method_handler(terminate)
class TestInterceptor(grpc.ServerInterceptor):
def init(self, key, value, code, detail):
self.key = key
self.value = value
self.code = code
self._abort = _abort(code, detail)
def intercept_service(self, continuation, handler_call_details):
"""
:param continuation: 函数执行器
:param handler_call_details: header
:return:
"""
headers = dict(handler_call_details.invocation_metadata)
if self.key not in headers:
return self._abort
# if (self.key, self.value) not in handler_call_details.invocation_metadata:
# return self._abort
if headers.get(self.key) != self.value:
return self._abort
return continuation(handler_call_details)
grpc_server = grpc.server(
futures.ThreadPoolExecutor(max_workers=1),
interceptors=(validator, ),
)
# 因为cPython 有全局解释器锁,所以如何改造成多进程呢?
```python
@contextlib.contextmanager
def _reserve_port():
# with _reserve_port() as xx:
"""
find and reserve a port for all subprocesses to use
sudo pop3 install --no-binary grpcio
由于很多linux系统不支持so_reuseport,所以安装grpcio的时候需要按照上面的这种模式
安装,时间比较长(多进程监听函数)
:return:
"""
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT) == 0:
raise RuntimeError("Fail to set SO_REUSEPORT")
sock.bind(("", 6000))
try:
yield sock.getsockname()[1] # 返回的就是端口号
finally:
sock.close()
# 启动进程数量
_PROCESS_COUNT = multiprocessing.cpu_count()
# 线程数量
_THREAD_CONCURRENCY = _PROCESS_COUNT
def serve(port=6000):
grpc_server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), compression=grpc.Compression.Gzip)
pb2_grpc.add_SayHelloServicer_to_server(SayHello(), grpc_server)
grpc_server.add_insecure_port('localhost:{}'.format(port))
print("----in serve 子进程 pid=%d ,父进程的pid=%d---" % (os.getpid(), os.getppid()))
grpc_server.start()
grpc_server.wait_for_termination()
def main():
print("----in main 子进程 pid=%d ,父进程的pid=%d---" % (os.getpid(), os.getppid()))
with _reserve_port() as port:
# sys.stdout.flush() # 刷新缓存区
workers = []
for _ in range(_PROCESS_COUNT):
worker = multiprocessing.Process(target=serve, args=(port, ))
worker.start()
workers.append(worker)
for worker in workers:
worker.join()