如何设计一个极快的pythonhttpapi和数据查找(>15K请求/秒)?

2024-04-20 11:45:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要建立一个restapi/服务器,在80ms内每秒响应超过15000个httpget请求,如果需要,我可以使用负载平衡器运行多个实例。在

服务器收到一个包含一系列条件(大约20个)的请求,需要对它们进行解析,并与一个规则集(大约2000个规则对所有20个条件都有不同的值,并有一个最终决定)进行比较,该规则集决定响应(是或否)。在

示例请求负载:

{"Country" : "DE",
 "ID" : "998423-423432-4234234-234234",
 "Criteria1": "8748r78",
 "Criteria2": "Some String",
  [...]
}

示例规则集(仍有待决定,但让我们从一个简单的设计开始):

^{pr2}$

每个标准可以包含1到大约400个不同的值,所有字符串(例如ISO代码中的GEOs)。有些可能是空的,并被视为通配符。理论上可能有20个标准都有相同值的条目,但这是一个有待编写的规则引擎要解决的问题。在

我做了一些研究如何做到这一点:

  1. 根据我的研究,使用sanic作为一个高吞吐量的web服务器 研究这是python中最快的,除了jafronto 在alpha;Edit:对于类似的用例,有没有人对基于python的webserver+webframework的性能有经验吗?我只阅读那些通常有一个非常简单的测试用例的基准测试(只对一个请求响应一个固定的字符串,因此在所有的基准测试中每秒可能的请求数量都很高)
  2. 使用sqlite3(内存中)进行规则查找;不确定带有20个约束的SQL语句是否足够快?也许还有另一个 将每个请求与超过20个条件的规则集进行比较的方法(每个 一种是字符串比较)。编辑:多亏了一个注释器,我可以将规则预先计算成散列并使用散列进行查找,因此不需要一个用于实时查找的数据库。在
  3. 使用redis或其他数据库来存储预先计算的规则(即 是另一个主题)让他们准备好在每一个 http服务器和sqlite3数据库的实例/工作线程。在
  4. 也许用pypy3来加速,但我没有经验 带着pypy

我会在Heroku主持这个节目。在

所以问题是:在python中,哪些库和体系结构允许这样的速度?在


Tags: 实例字符串服务器restapi数据库示例标准规则
1条回答
网友
1楼 · 发布于 2024-04-20 11:45:24

我会假设

  1. 所有字符串都是精确匹配的
  2. 所有未指定的条件匹配任何内容(通配符)
  3. 我们可以抛弃所有产生错误的规则
  4. 规则不能包含任何匹配项(通配符)
  5. 如果至少有一个规则与所有给定条件匹配,则结果为True,否则为False

我们可以建立一个快速查找,作为集合(匹配规则ID)的dict(列)的dict(列):

from collections import namedtuple

WILDCARD = None

Rule = namedtuple("Rule", ["Country", "Criteria1", "Criteria2"])

rules = [
    Rule("UK", "Somestring1", "Somestring3"),
    Rule("UK", "Somestring1", "Somestring2"),
    Rule("US", "Somestring4", WILDCARD)
]

def build_lookup(rules):
    columns = Rule._fields
    # create lookup table (special handling of wildcard entries)
    lookup = {column: {WILDCARD: set()} for column in columns}
    # index rules by criteria
    for id, rule in enumerate(rules):
        for column, value in zip(columns, rule):
            if value in lookup[column]:
                lookup[column][value].add(id)
            else:
                lookup[column][value] = {id}
    return lookup

rule_lookup = build_lookup(rules)

对于给定的示例数据,rule_lookup现在包含

^{pr2}$

然后我们可以快速地将标准与规则匹配,比如

def all_matching_rules(criteria):
    """
    criteria is a dict of {column: value} to match

    Return a set of all rule ids which match criteria
    """
    if criteria:
        result = empty = set()
        first = True
        for column, value in criteria.items():
            ids = rule_lookup[column].get(value, empty) | rule_lookup[column][WILDCARD]
            if first:
                result = ids
                first = False
            else:
                result &= ids   # find intersection of sets
            # short-circuit evaluation if result is null set
            if not result:
                break
        return result
    else:
        # no criteria, return everything
        return set(range(len(rules)))

def any_rule_matches(criteria):
    """
    criteria is a dict of {column: value} to match

    Return True if any rule matches criteria, else False
    """
    if criteria:
        return bool(all_matching_rules(criteria))
    else:
        return bool(len(rules))

它跑起来像

>>> all_matching_rules({"Country": "UK", "Criteria2": "Somestring8"})
set()

>>> all_matching_rules({"Country": "US", "Criteria2": "Somestring8"})
{2}

>>> any_rule_matches({"Country": "UK", "Criteria2": "Somestring8"})
False

>>> any_rule_matches({"Country": "US", "Criteria2": "Somestring8"})
True

Timeit报告说,这在我的机器上运行大约930ns-应该足够快了;-)

相关问题 更多 >