我提供的gRPC服务不幸的是必须在BeginTransaction
和Commit
API调用之间具有节点亲缘关系。
消费者API调用顺序通常为:
BeginTransaction()
返回txnID
DoStuff(txnID, moreParams...)
DoStuff(txnID, moreParams...)
...
Commit(txnID)
消费者可以是同时调用我的API的多线程进程,因此他们可能在任何时间点使用数百个事务。
如果我使用Envoy代理作为服务入口点,则应将BeginTransaction
路由到群集中的任何运行正常的节点,但是必须确保将使用返回的txnID
的后续调用路由到同一节点。
在我的情况下,可以在http标头中或在消息的任何部分中传递任何上下文信息。
答案 0 :(得分:0)
使用Ring Hash平衡器取得了一些进步
在特使代理服务器中(查找“哈希”):
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 80
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: http2
stat_prefix: ingress_http #just for statistics
route_config:
name: local_route
virtual_hosts:
- name: samplefront_virtualhost
domains:
- "*"
routes:
- match:
prefix: "/mycompany.sample.v1"
grpc: {}
route:
cluster: sampleserver
hash_policy:
header:
header_name: "x-session-hash"
- match:
prefix: "/bbva.sample.admin"
grpc: {}
route:
cluster: sampleadmin
http_filters:
- name: envoy.router
config: {}
clusters:
- name: sampleserver
connect_timeout: 0.25s
type: strict_dns
lb_policy: ring_hash
http2_protocol_options: {}
hosts:
- socket_address:
address: sampleserver
port_value: 80 #Connect to the Sidecard Envoy
- name: sampleadmin
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
http2_protocol_options: {}
hosts:
- socket_address:
address: sampleadmin
port_value: 80 #Connect to the Sidecard Envoy
admin:
access_log_path: "/dev/null"
address:
socket_address:
address: 0.0.0.0
port_value: 8001
在我的消费者中,我在BeginTransaction()
之前创建了一个随机哈希,并确保每次都在x-session-hash
标头中发送一次,直到Commit(txnId)
它可以工作,但是有一些限制:
当我扩展服务,添加更多节点时,某些操作会失败,并显示错误upstream connect error or disconnect/reset before headers
。当一个节点丢失时,失败是绝对可以的,但是当添加一个节点时,它们几乎是不能接受的!好消息是两种情况下的负载都会重新平衡。
客户端必须在进行第一个调用(BeginTransaction
)之前生成哈希,因此客户端会无意中指示哪个节点将参加此事务的请求。
我将继续调查。