Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何设计具有数据查找(>15K req/sec)的极快python HTTP API?_Python_Heroku_Sqlite_Webserver_Sanic - Fatal编程技术网

如何设计具有数据查找(>15K req/sec)的极快python HTTP API?

如何设计具有数据查找(>15K req/sec)的极快python HTTP API?,python,heroku,sqlite,webserver,sanic,Python,Heroku,Sqlite,Webserver,Sanic,我需要构建一个RESTAPI/服务器,它在80毫秒内响应超过每秒15000个HTTP GET请求。如果需要,我可以使用负载平衡器运行多个实例 服务器收到一个包含大约20个条件列表的请求,需要对它们进行解析,并将其与规则集(大约2000个规则)进行比较,这些规则对所有20个条件都有不同的值,最后的决定决定响应是或否 请求有效负载示例: {"Country" : "DE", "ID" : "998423-423432-4234234-234234", "Criteria1": "8748r78"

我需要构建一个RESTAPI/服务器,它在80毫秒内响应超过每秒15000个HTTP GET请求。如果需要,我可以使用负载平衡器运行多个实例

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

请求有效负载示例:

{"Country" : "DE",
 "ID" : "998423-423432-4234234-234234",
 "Criteria1": "8748r78",
 "Criteria2": "Some String",
  [...]
}
示例规则集仍有待确定,但让我们从一个简单的设计开始:

+--------+---------+-------------+--------------+
| RuleId | Country |  Criteria1  |  Criteria2   | etc...
+--------+---------+-------------+--------------+
|      1 | UK      | SomeString1 | SomeString3  |
|      2 | UK      | SomeString1 | SomeString2  |
|      3 | US      | SomeString4 | * (Wildcard) |
+--------+---------+-------------+--------------+
每个标准可以包含1到大约400个不同的值,所有字符串,例如ISO代码中的GEOs。有些可能为空,并被视为通配符。从理论上讲,可能存在所有20个标准都具有相同值的条目,但这是有待编写的规则引擎要解决的问题

我研究了如何实现这一点:

根据我的观点,使用sanic作为Web服务器可以获得高吞吐量 研究这是除japronto之外python最快的,japronto是 阿尔法;编辑:对于类似的用例,是否有人对基于python的webserver+webframework的性能有经验?我只阅读通常有一个非常简单的测试用例的基准测试,它只对一个请求响应一个固定的字符串,因此在所有基准测试中每秒可能有大量的请求 在内存中使用sqlite3进行规则查找;不确定具有20个约束的SQL语句是否足够快?也许还有另一个 将每个请求与规则集进行比较的方法,每个规则集超过20个标准 一个是字符串比较。编辑:多亏了一个注释,我可能会将规则预计算成散列并使用散列进行查找,因此不需要实时查找的数据库。 使用redis或其他数据库存储预先计算的规则 是另一个主题,让他们准备好在每个 http服务器和sqlite3数据库的实例/工作者。 也许可以使用Py3进行额外的加速,但我没有经验 和派比 我会在Heroku主持这个节目

所以问题是:哪些库和体系结构允许python具有这种速度?

我假设

所有给定的条件都是精确的字符串匹配 所有未指定的条件都匹配任何通配符 我们可以抛弃所有产生错误的规则 规则可能不包含任何与通配符匹配的内容 如果至少有一条规则与所有给定条件匹配,则结果为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)
对于给定的示例数据,规则查找现在包含

{
    'Country':   {WILDCARD: set(), 'UK': {0, 1}, 'US': {2}},
    'Criteria1': {WILDCARD: set(), 'Somestring1': {0, 1}, 'Somestring4': {2}},
    'Criteria2': {WILDCARD: {2}, 'Somestring2': {1}, 'Somestring3': {0}}
}
然后,我们可以快速将标准与规则匹配,如

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——应该足够快了-

你能给我们一个请求示例和规则示例吗?您如何确定应用哪个规则-最接近给定标准,即笛卡尔距离?规则集有多密集,即请求与其最接近的匹配规则之间的预期最大距离是多少?规则集多久更改一次?2000条规则很小。我会使用一些内存哈希表。。。。还要注意的是,Sanic在PyPi上被列为pre-alpha-我还不确定我是否希望在生产中信任它。@HughBothwell添加了示例—还没有代码,只是数据结构的原始开始。我最关心的是整个往返行程的80毫秒截止时间。@CL。非常好的主意,我可以散列所有规则,然后散列请求并获得极快的查找。。