#! /usr/bin/python# coding:utf-8# 此文件是 tls sig api 的 python 另一种实现# 使用了 python ecdsa 开发库__author__ = "tls@tencent.com"__date__ = "$Oct 2, 2016 11`17`43 PM"import OpenSSLimport base64import zlibimport jsonimport time# python ecdsa 开发库请到 https://github.com/warner/python-ecdsa# 或者 tls 技术支持分享的链接 http://share.weiyun.com/24b674bced4f84ecbbe6a7945738b9f4# 下载,下载完毕之后进入其根目录,运行下面的命令进行安装,# python **p.py install# ubuntu 用户可能需要添加 sudo# 由于 python ecdsa 这个开发库仅支持 ec 格式的私钥,从腾讯云下载的私钥格式是# pk #8 的格式,需要使用 openssl 命令进行转换,或者使用我们工具包中的 openssl 进行转换# 下面是转换命令# openssl ec -outform PEM -inform PEM -in private.pem -out private_ec.pem# -in 后面的传入下载的私钥 -out 后面是转换后的私钥文件from ecdsa import SigningKey,utilimport hashlib# 这里请填写应用自己的私钥ecdsa_pri_key = """请填上应用自己的私钥"""def base64_encode_url(data): base64_data = base64.b64encode(data) base64_data = base64_data.replace('+', '*') base64_data = base64_data.replace('/', '-') base64_data = base64_data.replace('=', '_') return base64_datadef base64_decode_url(base64_data): base64_data = base64_data.replace('*', '+') base64_data = base64_data.replace('-', '/') base64_data = base64_data.replace('_', '=') raw_data = base64.b64decode(base64_data) return raw_dataclass TLSSigAPI: """""" __acctype = 0 __identifier = "" __appid3rd = "" __sdkappid = 0 __version = 20151204 __expire = 3600*24*30 # 默认一个月,需要调整请自行修改 __pri_key = "" __pub_key = "" _err_msg = "ok" def __get_pri_key(self): return self.__pri_key_loaded def __init__(self, sdkappid, pri_key): self.__sdkappid = sdkappid self.__pri_key = pri_key self.__pri_key_loaded = SigningKey.from_pem(self.__pri_key) def __create_dict(self): m = {} m["TLS.account_type"] = "%d" % self.__acctype m["TLS.identifier"] = "%s" % self.__identifier m["TLS.appid_at_3rd"] = "%s" % self.__appid3rd m["TLS.sdk_appid"] = "%d" % self.__sdkappid m["TLS.expire_after"] = "%d" % self.__expire m["TLS.version"] = "%d" % self.__version m["TLS.time"] = "%d" % time.time() return m def __encode_to_fix_str(self, m): fix_str = "TLS.appid_at_3rd:"+m["TLS.appid_at_3rd"]+"\n" \ +"TLS.account_type:"+m["TLS.account_type"]+"\n" \ +"TLS.identifier:"+m["TLS.identifier"]+"\n" \ +"TLS.sdk_appid:"+m["TLS.sdk_appid"]+"\n" \ +"TLS.time:"+m["TLS.time"]+"\n" \ +"TLS.expire_after:"+m["TLS.expire_after"]+"\n" return fix_str def tls_gen_sig(self, identifier): self.__identifier = identifier m = self.__create_dict() fix_str = self.__encode_to_fix_str(m) pk_loaded = self.__get_pri_key() sig_field = pk_loaded.sign(fix_str, hashfunc=hashlib.sha256, sigencode=util.sigencode_der) sig_field_base64 = base64.b64encode(sig_field) m["TLS.sig"] = sig_field_base64 json_str = json.dumps(m) sig_cmpressed = zlib.compress(json_str) base64_sig = base64_encode_url(sig_cmpressed) return base64_sig def main(): api = TLSSigAPI(1400001052, ecdsa_pri_key) sig = api.tls_gen_sig("xiaojun") print sigif __name__ == "__main__": main()
啊,我的大脑刚刚起步,现在我有一个明智的建议。如果这是一次采访,可能太晚了,但不要介意:
机器1将被称为“控制机器”,并且为了争论起见它要么从所有数据开始,并且以相同的包裹将其发送到其他99台机器,否则数据开始在机器之间均匀分配,并且它将1/99的数据发送给其他每个人。分区不必相同,只需关闭即可。
每个其他机器对其数据进行排序,并且这样做有利于首先找到较低的值。因此,例如快速排序,总是首先对分区的下半部分进行排序[*]。它会尽快将其数据写回控制机器(使用异步IO以继续排序,并且可能使用Nagle:试验一下)。
控制机器在数据到达时对数据执行99路合并,但丢弃合并的数据,只保留所看到的数值的数量。它将中值计算为第二十亿分之十五十十亿以上的平均值。
这受到“牛群中最慢”问题的影响。直到分类机器发送的每个小于中值的值都不能完成该算法。有一个合理的机会,一个这样的数值在其数据包中会很高。因此,一旦数据的初始分区完成,估计的运行时间就是排序1/99数据的时间并将其发送回控制计算机,并且控制读取1/2数据的时间。“组合”介于最大值和这些时间之和之间,可能接近最大值。
我的直觉是,通过网络发送数据比排序更快(更不用说只是选择中位数),它需要成为一个相当糟糕的快速网络。如果可以假定网络是瞬时的,例如,如果您有100个内核可以访问包含数据的RAM,则可能会更好。
由于网络I / O很可能会受到限制,因此可能会出现一些技巧,至少可以将数据传回控制机器。例如,不是发送“1,2,3,... 100”,也许分拣机器可以发送一个消息,意思是“100个值小于101”。然后控制机器可以执行一个修改合并,在该合并中,它找到所有这些最高范围值中的最小值,然后告诉所有分拣机器它是什么,以便他们可以(a)告诉控制机器如何许多值“低于”该值,并且(b)从该点继续发送它们的排序数据。
更一般地说,控制机器可以使用99个分拣机器玩一个聪明的挑战 - 反应猜谜游戏。
这涉及到机器之间的往返,但是,我的简单的第一个版本避免了这种情况。我真的不知道如何盲目估计他们的相对表现,而且由于取舍是复杂的,所以我认为在那里有比我想象的更好的解决方案,假设这是一个真正的问题。
[*]可用堆栈许可 - 如果您没有O(N)额外空间,您首先要做的部分选择受到限制。但是如果你有足够的额外空间,你可以选择,如果你没有足够的空间,你至少可以使用你必须削减的一些角落,通过在前几个分区中首先做一小部分。
相似问题