因此,场景是我的生产者和消费者的比例为 7:1,并且我希望在我的服务中对生产者和消费者进行一致且确定性的多重映射。消费者列表在配置中提供给每个生产者,这是通过 ansible 完成的。因此,我尝试在 ansible本身中实现映射逻辑,而不是传递整个消费者列表,并在生产者服务中进行。因此,我想到了使用自定义过滤器从消费者列表中过滤出来,并将其分配给生产者。下面是我写的自定义过滤器:
#!/usr/bin/python
class FilterModule(object):
def filters(self):
return { 'map_producer_to_consumer': self.map_producer_to_consumer }
# consumer_servers: complete list of consumers servers
# producer_id: provided to each producer for mapping purpose
# producer_count: total no. of producers
# map_consumer_count: no. of consumers need to be mapped to each producer
# consumer_count: total no. of consumers
def map_producer_to_consumer(self, consumer_servers, producer_id, producer_count, map_consumer_count):
consumer_count = len(consumer_servers)
index_offset = 0 if producer_count%consumer_count else 1
rotation_count = (producer_id/consumer_count) % (map_consumer_count-1) # used for left rotation of mapped servers
map_consumer_indexes = [ (producer_count*i + producer_id + index_offset*i) % consumer_count for i in xrange(map_consumer_count)]
mapped_consumer_servers = [consumer_servers[map_consumer_indexes[0]]]
for i in xrange(1, map_consumer_count):
index = (i + rotation_count) % map_consumer_count
if i + rotation_count >= map_consumer_count:
mapped_consumer_servers.append( consumer_servers[map_consumer_indexes[index] + 1] )
else:
mapped_consumer_servers.append( consumer_servers[map_consumer_indexes[index]] )
return (',').join(mapped_consumer_servers)
当与这样的静态争论一起使用时,此过滤器按预期工作:
"{{ tsdb_boxes | map_producer_to_consumer(2,3,3) }}"
但我想通过 jinja2 模板使其使用动态参数,例如:
"{{ groups['producers'] | map_producer_to_consumer ({{ consumer_servers }}, {{ producer_id }}, {{ producer_count }}, {{ map_consumer_count }}) }}"
但是由于变量嵌套而导致错误,这在 Jinja2 中是不允许的。如果我尝试这样的事情:
"{{ groups['producers'] }} | map_producer_to_consumer ({{ consumer_servers }}, {{ producer_id }}, {{ producer_count }}, {{ map_consumer_count }})"
它会打印出这样的字符串:
['ip-1', 'ip-2'...] | map_producer_to_consumer (1000, 10, 150, 3)
有人可以建议什么应该是实现这一目标的最佳方法。我应该使用脚本模块并在 bash 中转换逻辑,还是将其仅保留在服务中会更好。