#API串接服务
Explore tagged Tumblr posts
sinsason · 2 months ago
Text
2016世界杯加密投注风暴:esball+ 与 E世博全方位实战指南
2016 年全球体育博彩市场规模超 1,000 亿美元,线上渠道年增近 20% 。同期,区块链和加密货币开始渗透博彩行业,提高了支付效率与隐私保护 。本��结合esball+与E世博网站两大平台特色,剖析赛事亮点、加密支付流程、数据驱动投注策略、实时滚球玩法、套利对冲,以及风控合规实践,助力加密玩家抢占 2016 世界杯投注先机。
一、全球博彩市场与加密浪潮
1.1 市场规模与增长
2016 年全球体育博彩市场规模超过 1,000 亿美元,其中线上投注同比增长近 20% 。 研究机构 Statista 报告指出,2016 年线上体育博彩收入占总市场的 35% 以上,预计未来五年将持续上升 。
1.2 加密货币的切入
比特币与以太坊等加密货币,为博彩行业带来跨境支付便利与交易匿名性,2016 年加密博彩交易量同比增长 30% 。 Blockchain.info 数据显示,2016 年全球比特币交易所交易额突破 300 亿美元,体现出加密支付的快速普及 。
二、2016 世界杯赛事亮点与投注热点
2.1 赛事概况
2016 年虽无国家队世界杯,但 FIFA 俱乐部世界杯等国际赛事同样吸引大量投注,单赛事投注额达数十亿美元 。 全球观众超过 30 亿,实时滚球与组合投注成为主流玩法,占比超过 40% 。
2.2 盘口与玩法偏好
胜平负(1X2)、亚洲让球和大小球盘为最受欢迎的三大传统盘口,合计占投注总量的 65% 。 移动端实时滚球投注在世界杯期间占比 62%,明显高于传统桌面端的 38% 。
三、平台对比:esball+ 与 E世博网站
维度esball+E世博网站牌照监管去中心化模式,无传统博彩牌照持有马耳他博彩管理局(MGA)等国际正规牌照 赔率更新AI+大数据引擎,赔率刷新延迟≤150ms 高频撮合系统,刷新延迟≤200ms多币种支持BTC、ETH、USDT (ERC-20/TRC-20)同上,另支持少量山寨币特色玩法分段投注、冠军安放、实时滚球花式串关、精确比分+角球数等组合玩法优惠与活动首存 100% BTC/ETH 返利;VIP 专属赛事预测赛首存 200% BTC/ETH/USDT 返利;世界杯限时抽奖与免费注
四、加密支付全流程:充值与提现实操
4.1 充值示范(USDT-TRC20)
进入平台“资产管理”→选择 USDT-TRC20→添加���保存钱包地址。
在个人钱包粘贴地址→输入金额→确认转账→等待 1–2 次网络确认;到账通常≤1 分钟 。
4.2 提现优化
优选 TRC-20 协议:网络费低、确认快,适合频繁套利及小额提现。
批量提现:多笔合并到固定时段一起发起,显著节省手续费。
五、数据驱动的投注策略
5.1 黑马与价值下注
历史数据表明,俱乐部世界杯中的“冷门球队”在赔率超过 6.00 时,往往具备高价值下注机会 。 结合 FIFA 官方排名与近期战绩,可通过 AI 模型提前捕捉潜在黑马 。
5.2 半场反转与分段投注
若上半场控球领先却未得分的强攻队,常在下半场首 10–15 分钟爆发,可在此时段重点下注“大球” 。 分段投注将整场拆分为若干 10–15 分钟小盘,可更精准地利用比赛节奏波动。
六、实时滚球玩法揭秘
实时滚球(Live Betting)在 2016 年世界杯期间占比近 40%,是加密玩家首选 。 esball+ 的高频数据撮合引擎,可在比分、角球、黄牌等关键事件时瞬息调整赔率,并通过“自动跟单”功能帮助玩家锁定红利 。
七、套利与对冲实战
7.1 Surebet 套利构建
利用 API 同步抓取 esball+ 与主流平台(Bet365、Pinnacle)赔率,当对立盘口满足无风险套利条件时,即可分配资金进行对冲下注 。
7.2 操作要点
必须预留 2–5 分钟的区块确认窗口,防止错失套利机会;
提现成本应优先考虑 TRC-20 协议,减少手续费对冲收益损耗。
八、风控合规与反欺诈
E世博网站已对接 Chainalysis 与 Civic 等第三方 KYC/AML 服务,实现三重身份与资金源验证,确保合规运营 。 平台引入 Sportradar Fraud Detection System,实时监测大额异常注单并自动触发风控审核,有效打击操盘与假赛 。 此外,日充值/提现限额与 72 小时冷热钱包冷却期策略,有助于防范洗钱风险。
���、行动号召(CTA)
立即访问并注册 esball+ 或 E世博网站,开启您的 2016 世界杯加密投注之旅:
esball+:https://www.bed3539.com/?aff=3242 → 注册即享首存 100% BTC/ETH 返利
E世博网站: https://www.bed3539.com/?aff=3242 → 完成 KYC → 领取 200% BTC/ETH/USDT 返利
24/7 在线客服全天候待命,扫码或点击官网链接,立刻参与,加密时代的世界杯投注风暴正等待您的加入!
0 notes
wingedmiraclesublime · 3 months ago
Text
蜘蛛池搭建需要哪些认证技术?TG@yuantou2048
在互联网时代,网站的优化和搜索引擎排名对于企业和个人来说至关重要。为了提高网站的收录率和排名,许多站长会选择使用蜘蛛池来吸引搜索引擎蜘蛛进行抓取。然而,在搭建蜘蛛池的过程中,选择合适的认证技术是确保其安全性和有效性的关键。本文将详细介绍蜘蛛池搭建过程中常用的几种认证技术。
1. 基本认证(Basic Authentication)
基本认证是最简单的一种认证方式,通过HTTP协议中的Authorization头字段传递用户名和密码。虽然这种方式易于实现,但安全性较低,容易被破解。因此,它通常用于内部测试或非敏感信息的访问控制。
2. 摘要认证(Digest Authentication)
摘要认证是一种基于挑战-响应机制的身份验证方法。服务器会向客户端发送一个随机字符串(称为“挑战”),客户端根据这个挑战生成一个哈希值,并将其返回给服务器进行验证。相比基本认证,摘要认证的安全性更高,因为它不会直接传输明文密码。
3. OAuth认证
OAuth是一种开放标准授权协议,允许第三方应用获取用户资源而无需暴露用户的凭证。这种认证方式广泛应用于社交网络、云服务等场景中。在蜘蛛池的搭建过程中,可以利用OAuth进行身份验证,以保护数据的安全性。
4. API密钥认证
API密钥认证是一种常见的认证方式,适用于API接口的调用。通过为每个用户分配唯一的密钥,可以有效地防止未授权访问。这种方式适合于需要频繁交互的应用场景,如API接口的调用。
5. JWT认证
JSON Web Token (JWT) 是一种无状态的认证机制,适用于分布式系统中的用户认证。JWT认证能够提供更高级别的安全保障,尤其适用于需要跨域请求的场景。
6. SSL/TLS证书认证
SSL/TLS证书认证通过数字证书来验证客户端的身份。这种方式不仅提高了安全性,还简化了开发流程。当用户访问特定资源时,服务器会检查请求头中的令牌是否有效,从而决定是否允许访问。这种方式特别适用于需要频繁访问的场景,如爬虫程序与服务器之间的通信。
7. 双因素认证(Two-Factor Authentication, 2FA)
双因素认证要求用户提供两种不同的认证因素,例如密码和短信验证码。这种方式增加了额外的安全层,使得攻击者难以伪造请求。在蜘蛛池的搭建过程中,采用SSL/TLS加密技术,确保数据传输过程中的信息安全。
8. 自定义认证方案
除了上述标准认证方式外,还可以根据具体需求设计自定义的认证方案。开发者可以根据业务需求定制一套自己的认证逻辑,增强系统的安全性。
结论
综上所述,选择合适的认证技术对于蜘蛛池的搭建至关重要。根据实际需求选择合适的技术方案,可以显著提升系统的安全性。
加飞机@yuantou2048
Tumblr media
EPS Machine
谷歌留痕
0 notes
ctkqiang · 1 year ago
Text
SQL injection | SQL注入
SQLi是一种网络安全漏洞,它允许攻击者干扰应用程序对其数据库进行的查询。这可能允许攻击者查看他们通常无法检索的数据。这可能包括属于其他用户的数据,或者应用程序可以访问的任何其他数据。在许多情况下,攻击者可以修改或删除这些数据,导致应用程序的内容或行为发生持久变化。
在某些情况下,攻击者可以升级SQL注入攻击,以破坏底层服务器或其他后端基础设施。它还可以使他们能够执行拒绝服务攻击。
[图片]
假设有一个网站URL https://someurl.com/someroute?param=some_value,它返回一组公共数据。当请求此URL时,服务器的中间件会生成一个SQL查询来检索数据:
SELECT * FROM SOMEROUTE WHERE SOME_CONDITION = 'some_value' AND RELEASED = 1
这个查询旨在返回SOME_CONDITION与URL参数中提供的值匹配且RELEASED标志设置为1的数据,表示公共数据。
然而,如果黑客在GET请求的param值后附加'--,它有效地注释掉了SQL查询的其余部分,导致中间件返回所有数据,包括公共和私有数据。修改后, https://someurl.com/someroute?param=some_value'-- 将导致以下SQL查询:
SELECT * FROM SOMEROUTE WHERE SOME_CONDITION = 'some_value' --' AND RELEASED = 1
`--` 之后的内容被视为注释,因此忽略了AND RELEASED = 1条件。
此外,如果黑客将URL更改为https://someurl.com/someroute?param=some_value'+OR+1=1--,他们利用了OR 1=1 始终为真的事实。这导致以下SQL查询:
SELECT * FROM SOMEROUTE WHERE SOME_CONDITION = 'some_value' OR 1 = 1 --' AND RELEASED = 1;
同样,`--` 注释掉了AND RELEASED = 1条件,由于1=1始终为真 (TRUE),查询返回SOMEROUTE的所有行,忽略任何条件。
应用程序逻辑的颠覆:
想象一下这样的情景, 一个网站要求用户输入用户名和密码进行登录。然后,应用程序使用类似以下查询的方式检查这些凭据:SELECT * FROM USERS WHERE USERNAME = 'username' AND PASSWORD = 'password' 。如果提供的凭据与数据库中存储的匹配,则应用程序会继续进行其他阶段,例如转到主页面。然而,攻击者或黑客可以利用应用程序逻辑中的漏洞来获取未经授权的访问权限。
一种常见的方法涉及操纵查询以完全绕过密码检查。通过输入一个特制的用户名,比如administrator'--,攻击者可以有效地注释掉查询中的密码检查部分。这导致应用程序执行类似于SELECT * FROM USERS WHERE USERNAME = 'administrator' -- AND PASSWORD = ''" 的查询,从而允许攻击者无需有效密码即可登录。
此外,攻击者还可以利用UNION关键字执行SQL注入攻击,并从数据库中的其他表中检索敏感数据。例如,如果应用程序通常查询SELECT NAME, DESCRIPTION FROM PRODUCTS WHERE CATEGORY = 'GIFTS'来显示可用产品,则攻击者可以注入一个UNION SELECT USERNAME, PASSWORD FROM USERS 的语句,将结果与用户凭据合并。这将允许攻击者从数据库中提取用户名和密码。
SELECT NAME, DESCRIPTION FROM PRODUCTS WHERE CATEGORY = ' GIFTS ' UNION SELECT USERNAME , PASSWORD FROM USERS
对于开发人员来说,实施强大的输入验证和参数化查询至关重要,以防止此类攻击,并保护敏感数据免受未经授权的访问。定期进行安全审计和测试可以帮助识别和解决应用程序逻辑中的潜在漏洞。
成功的SQL注入攻击会有什么影响?
成功的SQL注入攻击可能导致未经授权的访问敏感数据,例如: 
• 密码。
• 信用卡详细信息。
• 个人用户信息。
多年来,SQL注入攻击已被用于许多高调的数据泄露事件。这些事件造成了声誉损害和监管罚款。在某些情况下,攻击者可以获得组织系统的持久后门,导致长期妥协,可能长时间不被发现。
���何检测SQL注入漏洞?
您可以使用一套系统的测试手动检测每个应用程序入口点的SQL注入。为此,您通常会提交:
• 单引号字符'并查找错误或其他异常。
• 一些SQL特定语法,评估入口点的基本(原始)值和不同的值,并寻找应用程序响应中的系统差异。
• 布尔条件,如OR 1=1和OR 1=2,并寻找应用程序响应中的差异。
• 设计用于在SQL查询中执行时触发时间延迟的有效载荷,并寻找响应时间的差异。
• 设计用于在SQL查询中执行时触发出站网络交互的OAST有效载荷,并监视任何结果交互。
或者,您可以使用Burp Scanner快速可靠地找到大多数SQL注入漏洞。
查询中不同部分的SQL注入
大多数SQL注入漏洞发生在SELECT查询的WHERE子句中。大多数有经验的测试人员都熟悉这种类型的SQL注入。
然而,SQL注入漏洞可以发生在查询的任何位置,以及在不同的查询类型中。SQL注入出现的一些其他常见位置包括:
• 在UPDATE语句中,在更新的值或WHERE子句中。
• 在INSERT语句中,在插入的值中。
• 在SELECT语句中,在表名或列名中。
• 在SELECT语句中,在ORDER BY子句中。
SQL注入示例
有许多不同情况下发生的SQL注入漏洞、攻击和技术。一些常见的SQL注入示例包括:
• 检索隐藏的数据,您可以修改SQL查询以返回额外的结果。
• 颠覆应用程序逻辑,您可以更改查询以干扰应用程序的逻辑。
• UNION攻击,您可以从不同的数据库表中检索数据。
• 盲SQL注入,您控制的查询结果不会在应用程序的响应中返回。
SQL注入示例
存在许多不同情况下的SQL注入漏洞、攻击和技术。一些常见的SQL注入示例包括:
• 检索隐藏数据,您可以修改SQL查询以返回额外的结果。
• 颠覆应用程序逻辑,您可以更改查询以干扰应用程序的逻辑。
• UNION攻击,您可以从不同的数据库表中检索数据。
• 盲SQL注入,您控制的查询结果不会在应用程序的响应中返回。
二阶SQL注入
一阶SQL注入发生在应用程序处理来自HTTP请求的用户输入,并以不安全的方式将输入纳入SQL查询中。二阶SQL注入发生在应用程序接收来自HTTP请求的用户输入并将其存储以供将来使用时。这通常是通过将输入放入数据库来完成的,但在存储数据时不会出现漏洞。稍后,在处理不同的HTTP请求时,应用程序会检索存储的数据,并以不安全的方式将其纳入SQL查询。因此,二阶SQL注入也被称为存储型SQL注入。
[图片]
二阶SQL注入通常发生在开发者意识到SQL注入漏洞,并因此安全地处理输入数据至数据库的情况。当数据稍后被处理时,由于之前已安全地存放在数据库中,它被认为是安全的。此时,数据以不安全的方式被处理,因为开发者错误地认为它是可信的。
检查数据库
SQL语言的一些核心特性在流行的数据库平台中以相同的方式实现,因此许多检测和利用SQL注入漏洞的方法在不同类型的数据库上工作方式相同。
然而,常见数据库之间也存在许多差异。这意味着一些检测和利用SQL注入的技术在不同平台上的工作方式不同。例如:
• 字符串连接的语法。
• 注释。
• 批处理(或堆叠)查询。
• 特定平台的API。
• 错误信息。
在你识别出SQL注入漏洞后,获取有关数据库的信息通常很有用。这些信息可以帮助你利用漏洞。
你可以查询数据库的版本详细信息。不同的方法适用于不同类型的数据库。这意味着如果你找到一个特定的方法有效,你可以推断出数据库类型。例如,在Oracle上,你可以执行:
SELECT * FROM v$version
你还可以识别存在哪些数据库表,以及它们包含哪些列。例如,在大多数数据库上,你可以执行以下查询来列出表格:
SELECT * FROM information_schema.tables
不同上下文中的SQL注入
在之前的实验室中,你使用查询字符串来注入恶意SQL有效载荷。然而,你可以使用任何可控输入来执行SQL注入攻击,只要应用程序将其作为SQL查询处理。例如,一些网站接受JSON或XML格式的输入,并使用这些输入来查询数据库。
这些不同的格式可能提供了不同的方法来混淆攻击,这些攻击由于WAFs和其他防御机制而被阻止。弱实现通常会在请求中查找常见的SQL注入关键字,因此你可能能够通过编码或转义禁止关键字中的字符来绕过这些过滤器。例如,以下基于XML的SQL注入使用XML转义序列来编码SELECT中的S字符:
<stockCheck>
    <productId>123</productId>
    <storeId>999 &#x53;SELECT * FROM information_schema.tables</storeId>
</stockCheck>
这将在服务器端解码,然后传递给SQL解释器。
SQL注入速查表
1. 字符串连接: 不同的数据库有不同的字符串连接语法。例如,Oracle使用’foo’||‘bar’,而Microsoft SQL Server使用’foo’+‘bar’。
2. 子字符串:您可以从指定的偏移量提取字符串的一部分,具有指定的长度。在所有数据库中,偏移索引都是基于1的。
3. 注释:注释可用于截断查询并删除跟随您输入的部分。不同数据库的注释语法不同,如Oracle和Microsoft使用–comment,MySQL使用#comment。
4. 数据库版本:您可以查询数据库以确定其类型和版本,这对于制定更复杂的攻击非常有用。
5. 数据库内容:您可以列出数据库中存在的表及其包含的列。这通常使用information_schema.tables和information_schema.columns来完成。
6. 条件错误:您可以测试单个布尔条件,并在条件为真时触发数据库错误。这对于盲SQL注入非常有用,其中结果不直接可见。
7. 不同上下文中的SQL注入:SQL注入可以使用应用程序作为SQL查询处理的任何可控输入来执行,不仅仅是通过查询字符串。
0 notes
kmaimi079 · 1 year ago
Text
如何选择包网及游戏API?
在过去的十年里,包网公司在线上博彩行业崛起迅速,为该行业的发展提供了强大的支持。以下是包网公司在线上博彩市场中盛行的原因,以及与自行搭建线上博彩平台串接游戏API的区别: 1.降低市场进入门槛: 包网公司的出现使得进入在线博彩市场变得更加容易。它们提供了一揽子的解决方案,包括平台搭建、游戏API对接、运营服务等,省去了业者自行建立团队的时间和成本。
2.多样化的服务: 包网公司提供各种类型的包网服务,包括彩票、棋牌、体育和真人视讯等,使得线上博彩业者能够根据自己的需求选择适合的游戏类型,而不必从零开始搭建。
3.快速且方便: 包网公司提供一站式服务,从平台搭建到游戏API对接再到运营服务,都能迅速完成。这使得业者能够更专注于业务发展,而不用花费大量时间和资源在技术层面上。
4.网站安全性: 包网公司通常具备高水平的安全防御系统,确保线上博彩平台的安全性。这对于保护用户信息和防范潜在的网络攻击是至关重要的。
5.专业团队支持: 包网公司拥有专业的团队,处理游戏API对接等技术问题。在平台运营出现问题时,业者可以迅速联系包网公司获得支持��减少运营中断的风险。
选择自行搭建平台和串接游戏API的优劣:
•优势: 自行搭建平台允许业者根据自己的需求和喜好构建平台,选择特定的游戏API进行对接。平台运营时出现问题时,业者可以直接解决,而不依赖于包网公司。
•劣势: 自行搭建需要大量的人力、资源、时间和金钱投入,前期投入费用不能立即获得回报。对于技术支持、游戏API对接等方面,业者需要建立专业团队,增加了运营的复杂性。
为何选择包网公司:
•快速和方便: 包网公司提供了一揽子服务,快速搭建平台,业者无需为建设团队和处理技术问题而烦恼。
•专业支持: 包网公司有专业的团队支持,解决技术和运营问题。业者只需集中精力在业务发展上,而不必担心技术层面的挑战。
•安全性: 包网公司通常拥有高水平的安全防御系统,保障线上博彩平台的安全性。
•成本可控: 尽管需要支付一些费用,但相较于自行搭建,业者可以更好地控制成本,并且能够更早地获得回报。
在选择自行搭建还是选择包网公司时,业者需要权衡投入和回报,根据自身情况做出明智的决策。
KM包网在博彩市场拥有多年深耕经验,对在线博彩包网市场有着深入的了解和分析。KM包网拥有专业的24小时资安团队和技术维护团队,时刻监控系统,确保平台运营不受任何阻碍。KM包网全面考虑在线博彩平台常遇到的问题,轻松实现各种游戏API的对接。KM包网提供在线博彩平台专属模板,贴近在线博彩玩家的喜好选择。KM包网提供多语言服务,满足所有包网需求。KM包网为所有包网客户提供全方位技术和服务,从平台架构到开站运营都有1对1的专人服务,让您轻松进入在线博彩市场,无负担地开展业务!
✈️招商经理TG:https://t.me/kmaimi001 ✈️官方招商频道: https://t.me/kmaimi78 ✈️官方招商中心:https://www.skggf.com/aimi
1 note · View note
skggroup · 3 years ago
Text
Tumblr media Tumblr media
0 notes
shawnzeng · 2 years ago
Text
LangChain:快速构建自然语言处理应用程序的工具
(封面图由文心一格生成)
LangChain:快速构建自然语言处理应用程序的工具
LangChain 是一个用于构建端到端语言模型应用的Python框架。它提供了一系列模块,这些模块可以组合在一起,用于创建复杂的应用程序,也可以单独用于简单的应用程序。在本篇博客中,我们将重点介绍以下几个方面:
安装和环境设置
构建语言模型应用
Prompt Templates:管理LLMs的提示
Chains:组合LLMs和Prompt Templates以进行多步骤工作流
Agents:根据用户输入动态调用Chains
Memory:为Chains和Agents添加状态
1. 安装和环境设置
首先,我们需要使用以下命令安装LangChain:pip install langchain
使用LangChain通常需要与一个或多个模型提供程序、数据存储、API等集成。在本例中,我们将使用OpenAI的API,因此我们首先需要安装他们的SDK:pip install openai
然后,在终端中设置环境变量:export OPENAI_API_KEY="..."
或者,可以从Jupyter notebook(或Python脚本)中执行此操作:import os os.environ["OPENAI_API_KEY"] = "..."
2. 构建语言模型应用
有了安装的LangChain和设置的环境变量,我们现在可以开始构建语言模型应用了。LangChain提供了许多模块,用于构建语言模型应用。这些模块可以组合在一起,用于创建复杂的应用程序,也可以单独用于简单的应用程序。
LLMs:从语言模型获取预测 LangChain的最基本的构建块是在一些输入上调用LLM。让我们通过一个简单的例子来演示如何实现这一点。为此,让我们假装我们正在构建一个服务,根据公司的产品生成公司名称。
首先,我们需要导入LLM包装器:from langchain.llms import OpenAI
然后,我们可以使用任何参数初始化包装器。在这个例子中,我们可能希望输出更随机,因此我们将使用高temperature进行初始化:llm = OpenAI(temperature=0.9)
现在我们可以在一些输入上调用它!text = "What would be a good company name for a company that makes colorful socks?" print(llm(text))
3. Prompt Templates:管理LLMs的提示
调用LLM是一个很好的第一步,但这只是个开始。通常,在应用程序中使用LLM时,不会直接将用户输入直接发送到LLM。相反,你可能会获取用户输入并构造一个提示,然后将提示发送到LLM中。 例如,在上一个例子中,我们传递的文本是硬编码的,要求为制造彩色袜子的公司取一个名称。在这个想象的服务中,我们想要做的是仅取用户描述公司所做的事情,然后使用该信息格式化提示。
使用LangChain可以轻松实现这一点!
首先定义提示模板:from langchain.prompts import PromptTemplateprompt = PromptTemplate(input_variables=["product"],template="What is a good name for a company that makes {product}?", )
现在我们来看看它是如何工作的!我们可以调用.format方法进行格式化。print(prompt.format(product="colorful socks"))
4. Chains:将LLMs和Prompts结合在多步骤工作流中
到目前为止,我们已经单独使用Prompt Template和LLM基元。但是,一个真正的应用程序不仅仅是一个原语,而是由它们的组合构成的。
在LangChain中,一个链由链接组成,这些链接可以是LLM、Prompt Template或其他链。
LLMChain是最核心的链类型,它由Prompt Template和LLM组成。
扩展上一个例子,我们可以构建一个LLMChain,该链接受用户输入,使用Prompt Template格式化它,然后将格式化的响应传递给LLM。from langchain.prompts import PromptTemplate from langchain.llms import OpenAIllm = OpenAI(temperature=0.9) prompt = PromptTemplate(input_variables=["product"],template="What is a good name for a company that makes {product}?", )
我们现在可以创建一个非常简单的链,该链将获取用户输入,使用Prompt Template对其进行格式化,然后将其发送到LLM:from langchain.chains import LLMChain chain = LLMChain(llm=llm, prompt=prompt)
现在我们可以运行该链,只需指定产品即可!chain.run("colorful socks") # -> '\n\nSocktastic!'
5. Agents:根据用户输入动态调用Chains
到目前为止,我们已经看到的链都是按照预定顺序运行的。Agents不再如此:它们使用LLM确定要采取的动作及其顺序。一个动作可以是使用工具并观察其输出,或者返回给用户。
如果正确使用Agents,它们可以非常强大。在本教程中,我们通过最简单、最高级别的API向你展示如何轻松使用代理。
为了加载代理,你应该了解以下概念:
Tool: 执行特定任务的功能。这可以是类似Google搜索、数据库查找、Python REPL、其他链的东西。工具的接口目前是期望有一个字符串作为输入,输出一个字符串的函数。 LLM: ���动代理的语言模型。
Agent: 要使用的代理。这应该是引用支持代理类的字符串。因为本笔记本专注于最简单、最高级别的API,所以仅涵盖使用标准支持的代理。如果要实现自定义代理,请参见自定义代理的文档(即将推出)。 代理: 支持的代理及其规格的列表,请参见此处。
工具: 预定义工具及其规格的列表,请参见此处。
对于此示例,你还需要安装SerpAPI Python包。pip install google-search-results
并设置适当的环境变量。import os os.environ["SERPAPI_API_KEY"] = "..."
现在我们可以开始!from langchain.agents import load_tools from langchain.agents import initialize_agent from langchain.llms import OpenAI# 首先,让我们加载我们要用来控制代理的语言模型。 llm = OpenAI(temperature=0)# 接下来,让我们加载一些要使用的工具。请注意,`llm-math`工具使用LLM,因此我们需要将其传递给它。 tools = load_tools(["serpapi", "llm-math"], llm=llm)# 最后,让我们使用工具、语言模型和我们想要使用的代理类型来初始化一个代理。 agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)# 现在让我们测试一下! agent.run("Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?") Entering new AgentExecutor chain...I need to find out who Olivia Wilde's boyfriend is and then calculate his age raised to the 0.23 power. Action: Search Action Input: "Olivia Wilde boyfriend" Observation: Jason Sudeikis Thought: I need to find out Jason Sudeikis' age Action: Search Action Input: "Jason Sudeikis age" Observation: 47 years Thought: I need to calculate 47 raised to the 0.23 power Action: Calculator Action Input: 47^0.23 Observation: Answer: 2.4242784855673896Thought: I now know the final answer Final Answer: Jason Sudeikis, Olivia Wilde's boyfriend, is 47 years old and his age raised to the 0.23 power is 2.4242784855673896. > Finished AgentExecutor chain. "Jason Sudeikis, Olivia Wilde's boyfriend, is 47 years old and his age raised to the 0.23 power is 2.4242784855673896."
6. Memory:向链和代理添加状态
到目前为止,我们所讨论的所有链和代理都是无状态的。但通常,你可能希望链或代理具有一些“记忆”概念,以便它们可以记住有关其先前交互的信息。 这是在设计聊天机器人时最明显和简单的例子-你希望它记住以前的消息,以便它可以使用上下文来进行更好的对话。这将是一种“短期记忆”。在更复杂的一面,你可以想象链/代理随时间记住关键信息-这将是一种“长期记忆”。关于后者的更具体想法,请参见此出色的论文。
LangChain提供了几个专门为此目的创建的链。本笔记本介绍了使用其中一个链(ConversationChain)的两种不同类型的内存。
默认情况下,ConversationChain具有一种简单类型的内存,该内存记住所有先前的输入/输出并将它们添加到传递的上下文中。让我们看看如何使用此链(将verbose=True设置为我们可以看到提示)。from langchain import OpenAI, ConversationChainllm = OpenAI(temperature=0) conversation = ConversationChain(llm=llm, verbose=True)conversation.predict(input="Hi there!") > Entering new chain... Prompt after formatting: The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.Current conversation:Human: Hi there! AI:> Finished chain. ' Hello! How are you today?' conversation.predict(input="I'm doing well! Just having a conversation with an AI.") > Entering new chain... Prompt after formatting: The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.Current conversation:Human: Hi there! AI: Hello! How are you today? Human: I'm doing well! Just having a conversation with an AI. AI:> Finished chain. " That's great! What would you like to talk about?"
1 note · View note
fx999blog · 5 years ago
Photo
Tumblr media
欧市盘前:美大法官提名获通过,国内黄金两大需求均强劲,油市聚焦API库存与飓风 © Reuters. 欧市盘前:美大法官提名获通过,国内黄金两大需求均强劲,油市聚焦API库存与飓风 周二(10月27日)亚洲时段,美元避险需求减弱,美国参议院表决通过巴雷特出任最高法院大法官的提名。现货黄金走高至1910附近,隔夜美股暴跌,恐慌指数(VIX)大幅走高,黄金获得一定支撑。同时,在美国大选选情胶着背景下,市场避险资金近期也会更多向黄金资产转移,短线而言金价仍有上行空间,中国三季度黄金实物消费量实现环比增长28.71%,且投资需求旺盛,国内黄金ETF市场规模进一步扩大,黄金ETF产品已增至11支。尽管此前疫情和利比亚增产令油价重挫,但OPEC+各方整体依旧对需求表示乐观。市场正在等待周二日内美国API原油库存数据的进一步指引,虽然气象消息显示有新的飓风生成逼近美国墨西哥湾地区,但是其对油气产能的影响尚未全面显现。 本交易日主要关注美国耐用品订单数据。 亚洲时段行情回顾 亚盘时段,美元兑日元承压于105大关,汇价现报104.74,跌幅0.1%;牛津/阿斯利康疫苗证明在高龄人群中效果良好,以及英国一家大型医院的人员被告知最快下个月准备打疫苗,但这些消息不足以提振市场信心。目前没有什么具体迹象显示接近达成协议。投资者也对民主党在美国国会选举中完胜的预期表示怀疑,外汇咨询公司Klarity FX执行董事Amo Sahota表示,“随着标普500指数下跌,市场变得紧张起来。危险显然在于,如果病例数继续像之前那样上升,北美不得不开始实施进一步限制措施,日元获得一定避险支撑”。 亚盘时段,欧元兑美元走高,汇价现报1.1833,涨幅0.19%;美元避险需求减弱,美国参议院表决通过巴雷特出任最高法院大法官的提名。但欧元自身基本面依旧偏弱,近日来,欧洲疫情反弹来势汹汹,多个国家单日确诊人数呈爆发式增长,数倍于今年4月份第一波疫情时的高峰水平。面对严峻的形势,多国管控措施再次升级。专家认为,封锁措施升级或将延迟欧元区经济复苏,欧洲经济面临“二次衰退”风险。 亚盘时段,现货黄金走高至1910附近,现货黄金现报1908.3美元/盎司,涨幅0.33%;美元指数在美国国会参院通过新任大法官巴雷特的提名表决后回落,带动美元计价的商品价格走高;完成大法官提名扫除了美国政治领域的一重不确定性,不过隔夜美股暴跌,恐慌指数(VIX)大幅走高,黄金获得一定支撑。同时,在美国大选选情胶着背景下,市场避险资金近期也会更多向黄金资产转移,短线而言金价仍有上行空间。另外,中国三季度黄金消费量实现环比增长28.71%。国内黄金ETF市场规模进一步扩大,黄金ETF产品已增至11支。 亚盘时段,国际油价止跌企稳,美油现报38.86美元/桶,涨幅0.78%;布伦特原油现报41.15美元/桶,涨幅0.83%;尽管此前疫情和利比亚增产令油价重挫,但OPEC+各方整体依旧对需求表示乐观。市场正在等待周二日内美国API原油库存数据的进一步指引,虽然气象消息显示有新的飓风生成逼近美国墨西哥湾地区,但是其对油气产能的影响尚未全面显现。因而,OPEC+在进一步限产前景上遭遇的阻力仍受到格外瞩目,同时,市若美元指数受美国政局冲击承压,也将有助于美元计价的油价反弹。 亚洲股市行情一览 财经数据 欧洲从10月25日开始至2021年3月28日进入冬令时: 英国、德国和法国的交易时间延后一个小时,英国伦敦证券交易所:北京时间16:00-00:30,之前为15:00-23:30;德国法兰克福证券交易所:北京时间16:00-00:30,之前为15:00-23:30;法国巴黎证券交易所:北京时间16:00-00:30,之前为15:00-23:30  财经大事 17:00  欧洲央行管委森特诺在一场银行会议上发表讲话。 18:00  德国经济部长阿尔特迈尔发表讲话。 22:45  英国央行首席经济学家及货币政策委员会委员霍尔丹出席一场线上活动。 亚洲时段消息回顾 美国参议院表决通过巴雷特出任最高法院大法官的提名; 三季度我国黄金消费量环比增长28.71%;据中国黄金协会最新统计数据显示,2020年前三季度,全国黄金实际消费量548.09吨,与2019年同期相比下降28.66%。随着国内经济持续稳定恢复,以及婚庆市场的快速复苏,黄金消费明显回暖,三季度黄金消费量实现环比增长28.71%。国内黄金ETF市场规模进一步扩大,黄金ETF产品已增至11支,截至9月末,国内黄金ETF持仓量约69.5吨,较年初增长约55%。 疫情急剧反弹 欧洲经济或临“二次衰退”风险;近日来,欧洲疫情反弹来势汹汹,多个国家单日确诊人数呈爆发式增长,数倍于今年4月份第一波疫情时的高峰水平。面对严峻的形势,多国管控措施再次升级。专家认为,封锁措施升级或将延迟欧元区经济复苏,欧洲经济面临“二次衰退”风险。 特朗普和拜登均造访大选关键州宾州,民调显示拜登仅小幅领先;① 在距离美国大选还有八天之际,美国总统特朗普在宾夕法尼亚州喧闹的集会上发表了讲话,而民主党总统候选人拜登则在该州低调露面。宾夕法尼亚州被认为对两人的胜算都至关重要。② 这位共和党籍总统在艾伦镇对欢呼的支持者说,“我们赢得宾州,我们就赢得整个大选,”特朗普预测自己将拿下宾州,尽管他在很多民调中的支持率落后于拜登。艾伦镇是特朗普在宾州三场竞选活动的第一站。③ 拜登则在费城附近的切斯特市举行了小规模的见面会,会见了十几名竞选志愿者,并接受了记者采访。拜登说,他“对任何事情都不过分自信”,“凭藉着上帝的恩典”,他将赢得他出生的宾夕法尼亚州。④ 拜登在提到其他竞选关键州时说,“我想我们会赢得密西根,我想我们会赢得威斯康辛。我想我们会赢得明尼苏达。我认为在俄亥俄有获胜的机会。我认为我们在北卡罗来纳有获胜的机会。我们在乔治亚有获胜的机会”⑤ 尽管拜登在全国民调中稳稳领先,但在可能决定大选结果的战场州差距似乎更小。路透/益普索于10月20-26日进行的调查显示,拜登在宾夕法尼亚州仅小幅领先特朗普 新一波疫情导致美股周一大跌,疫苗普及仍面临障碍;① 美国、俄罗斯、法国和许多其他国家的新冠感染人数皆创下纪录,新一波疫情横扫北半球部分地区,迫使一些国家实施新限制措施。② 感染人数激增令经济前景蒙上阴影,加剧了周一金融市场压力。美股大幅收低,是七周多���来表现最糟糕的一天,道指跌超2%,标普和纳指跌超1.5%以上,因新增病例数飙升,且华盛顿财政援助议案的不确定性令美国经济复苏前景变得黯淡。③ 英国制药公司阿斯利康周一(10月26日)表示,牛津大学研发的新冠疫苗在老年人和年轻人身上均产生了免疫反应,这带来了一些正面消息。目前北方国家正从秋季步入冬季,人们更多地在室内进行社交活动。④ 但英国卫生大臣汉考克提醒称,在明年以前疫苗恐怕无法普遍施打,并称“我们还没有做到那个程度。”⑤ 任何疫苗皆面临科学与公关方面的障碍。调查显示,出于对安全性、有效性与审批流程的疑虑,仅有约半数美国民众愿意接种疫苗。在美国,新冠住院病患人数达到两个月高点,一些州的卫生医疗体系紧绷。  欧洲新冠疫情病例激增,多国实施宵禁措施;① 欧洲的情况异常残酷,以法国为首的一连串国家报告新增病例创纪录,法国周日新增病例首次超过5万例。欧洲疫情死亡人数已经超过25万人。② 政府顾问委员会负责人Jean-Francois Delfraisnsy教授表示,法国单日新增病例甚至可能达到10万例。③ 新增病例稳步增加促使欧洲很多地区收紧防控举措。④ 德国画报报导,德国总理默克尔在党内会议上表示:“未来几个月,我们将面临非常、非常艰难的局面。”报导称,默克尔计划采取“轻度封闭”,聚焦于关闭酒吧、餐厅和公共活动。⑤ 西班牙政府计划在该国实施为期六个月的紧急状态,这一计划遭到了强烈反对。反对党说六个月太长了,流行病学家则表示,这一举措或许力度不够也太迟了,一些民众反对宵禁。⑥ 俄罗斯周一新增新冠感染病例升至创纪录的17,347例,该国政府警告称,疫情开始在莫斯科以外地区造成更大的损失。该国感染病例已达到150万例,在全球仅次于美国、印度和巴西。⑦ 意大利实施新的疫情限制,下令餐馆和酒吧从下午六点起停业,关闭电影院和健身房,并在多个地区实施宵禁。  特朗普在德克萨斯州、蒙大拿州领先,佐治亚州胶着;① 特朗普在德克萨斯州微弱领先,打破僵局。特朗普在周一(10月26日)发布的纽约时报/锡耶纳学院民意测验中领先拜登4个百分点,此前一周其他三项民调发现两位候选人在这个共和党大本营旗鼓相��。特朗普在此次民调中以47%比43%领先拜登,误差幅度为3.8个百分点。② 特朗普自夸在蒙大拿州的民调中遥遥领先。自1992年以来,民主党总统候选人从未在该州获胜。特朗普周一(10月26日)在宾夕法尼亚州阿伦敦的竞选活动中说,他在三个传统的共和党州的民意调查中表现良好。纽约时报/锡耶纳学院最近进行的一项民意调查显示,他在蒙大拿领先拜登6个百分点。③ 特朗普和拜登在佐治亚州旗鼓相当。由于一项新的民调显示佐治亚州选情胶着,拜登将于周二(10月27日)访问亚特兰大。在佐治亚大学公共与国际事务学院周一(10月26日)发布的一项调查结果中,47%的可能投票选民支持拜登,46%支持特朗普,二者差距在误差范围之内。自1992年以来,民主党总统候选人从未在佐治亚州获胜。  OPEC秘书长称疫情反弹恐拖慢油市复苏,平衡市场努力将“坚持到底”;① 石油输出国组织(OPEC)秘书长巴尔金都周一表示,石油市场复苏的时间可能比预期的要长,因为全球范围内的新冠病毒感染上升,OPEC及其盟友平衡市场的努力将“坚持到底”。② OPEC和包括俄罗斯在内的盟友在4月创纪录地削减了石油产量,因新冠大流行打击了需求。他们计划在明年1月份增加产量,作为逐步放���供应限制的一部分。③ 在剑桥能源周(CERAWeek)举行的线上印度能源论坛上,当被问及第二波疫情是否需要OPEC+改变策略时,巴尔金都表示,今年早些时候对需求反弹的希望已经落空。④ 巴尔金都说,“我们希望2020年下半年开始看到复苏。不幸的是,目前经济增长和需求复苏仍然乏力,主要是因为疫情。我们对经济复苏将会继续保持谨慎乐观态度。复苏可能需要更长的时间,或许在较低的水平,但我们决心坚持到底”。⑤ 巴尔金都表示,生产商预计油价不会像第二季那样再度崩跌,当时油价触及历史低点,美国原油期货一度跌至负值区间。⑥ 巴尔金都称,OPEC+产油国的平均减产执行率已达到100%,并将继续实施减产措施,以使库存进一步下降。“我们决心通过确保库存继续减少来帮助市场恢复稳定”  日本首相菅义伟:严防疫情暴发基础上重启经济;日本首相菅义伟在26日召开的第203届临时国会上发表施政演说,强调在防止出现暴发性感染新冠病毒的基础上重启社会经济活动,促进经济早日复苏。 这是菅义伟9月当选日本首相以来的首次施政演说。他在谈到新冠肺炎疫情对策时说,政府计划明年上半年在优先确认新冠病毒疫苗的安全性和有效性之后,保证可供全民接种的疫苗数量,并优先为高龄者、基础病患者以及医务工作者免费接种。(央视新闻)  美国又一投票箱遭纵火焚烧 ,FBI介入调查;当地时间10月26日��美国一名男子被控纵火焚烧波士顿的投票箱,里面装有120余张选票。据报道,这是本月美国发生的第二起投票箱火灾事件。有关部门上周表示,洛杉矶县一个投票箱起火也正在以纵火罪进行调查。警方称,赶到现场的警察看到投票箱在冒烟,消防人员立即向盒子里注水灭火。选举官员称,此前投票箱里面有122张选票,其中87张仍清晰可见,35张损毁的选票大部分完好无损,应该可以辨认。其中5到10张损严重,无法辨认。(海外网)  澳洲联储副主席:疫情拖累对澳洲经济影响或不及预期;① 澳洲联储副主席德贝尔(Guy Debelle)周二对议会小组委员会表示,澳大利亚其他地区的经济增长,足以抵消维多利亚州的拖累而有余。他表示,来自维多利亚州的拖累可能没有澳洲联储8月份预测的那么大。德贝尔同时拒绝评论量化宽松意图② 澳大利亚央行理事会将于下周二(11月3日)开会,市场预期该行将放宽政策,并可能宣布扩大债券购买计划。下周五(11月6日),该行将发布最新季度经济预测。 机构观点 摩根大通(JP Morgan)表示,比特币有不少长期上行的空间,并且是黄金的有力竞争;① 比特币自出现以来就一直被用来和黄金做比较。全球实物黄金市场总计价值2.6万亿美元左右,包括黄金ETF。比特币目前市值则大约2400亿美元;今年以来黄金价格大涨了近25%,而比特币价格则上涨近80%;② 摩根大通在报告中表示,哪怕只是黄金市场中一小部分人选择替代品,那么有望意味着比特币价格翻两倍甚至三倍。数字货币的价值不仅仅在其保值的功能,也在于它们是支付工具。越来越多机构接受数字货币,它们的价值就越高;③ 该行表示,由于千禧一代投资者会成为这一领域越来越重要的组成部分,长期而言,比特币是能成为黄金的有力竞争的;④ CME的比特币期货未平仓可以在三季度日均大跌1.05万手,比二季度环比增长32%,比去年三季度同比大增127%。  摩根大通前瞻本周四20:45公布的欧洲央行利率决议;本次会议将给欧洲央行一个机会来评估近期的数据以及疫情,并可能为12月的利率决议提供一些指引。随着欧洲新冠肺炎确诊病例急剧上升,欧洲央行本次会议将比此前“有趣很多”,但这并不表明我们预计其将采取实际决策,事实上我们仍认为欧央行周四可能仅只会对第三轮定向长期再融资操作(TLTRO)的模式以及分层利率体系的倍数作出部分调整。此外,仍预计欧洲央行将在12月宣布将紧急抗疫购债计划(PEPP)规模扩大5000亿欧元,并将不得不在2021年年中继续将规模扩大2500亿欧元。  分析师:美国大选结果出炉后,美股有望开启反弹;①市场分析师Patti Domm撰文称,美股在大选前恐持续波动,随后在大选结果确定后出现反弹;②从历史上看,美股通常会在选举日和年底前这段时间上涨;③他同时指出,如果选举后计票时间很长,没有明确的获胜者,或者出现争议性结果,则将出现一段波动期  美国大选临近,贝莱德做空美元兑亚洲货币汇率;世界头号资产管理公司贝莱德正在做空美元,认为此番大选无论是谁最终获胜,美国史无前例的财政和货币刺激措施都会使美元的颓势旷日持久。该公司驻新加坡亚洲信贷主管Neeraj Seth表示,贝莱德持有“适度”的美元兑人民币、印度卢比和印尼盾等亚洲货币的空头头寸。当投资者四处寻求高收益、高增长资产之际,这三种亚洲货币最有可能从美元的颓势中获益。“我的基线预期是,较为温和的美元弱势至少还会持续一到三年时间,这种趋势不会变,”Seth周四接受电话采访时说。“无论美国大选结果如何,一些政策行动毕竟已经发生了。”当此距离美国大选只剩一周之际,管理着7.3万亿美元巨量资产的贝莱德也加入了高盛和瑞银资产管理等全球同行看跌美元的行列。 周一,贝莱德策略师调降了对美国国债的预期,理由是在立场统一的民主党政府领导下,大规模财政扩张的可能性会日益加大。随着拜登进一步扩大民调中对特朗普的领先优势,彭博美元即期汇率指数本月迄今已下跌逾1%。Seth说,取决于大选的最终结果,美元的跌势或许会“暂时停顿”,但从长远来看,其颓势会根深蒂固。“从基本面看,美元估值依然偏高”。  摩根士丹利:是时候“All in”新兴市场货币了;① 随着10月进入尾声和11月美国大选的迫近,摩根士丹利分析师表示,投资者们是时候为年底新兴市场货币的上涨做好准备了;② 摩根士丹利分析师James Lord团队在上周五的一份报告中认为,市场似乎低估了民主党横扫的可能性,即民主党赢得白宫、参议院和众议院;③ 尽管选举结果仍然存在不确定性,但是对于那些希望民主党赢得大选的人来说,新兴市场的风险/回报看起来令人信服,尤其是在一个团结的政府的情况下,可能会出现大规模的刺激措施和一套更加一致的经济政策;④ 货币方面,这家大行表示,看好巴西雷亚尔、墨西哥比索、和哥伦比亚比索,并已建了南非兰特和俄罗斯卢比的多头头寸;⑤ 理由是,除了近期的政治风险较少之外,新兴市场今年部分时间季节性表现强劲,意味着“All in 新兴市场”的时机已经到来;⑥ 另外,如果能分发到有效的新冠疫苗,那么新兴市场可能会更充分地参与全球增长复苏中去。 产油国利比亚政局企稳,原本恢复艰难的原油市场,将要面临新的供给冲击了;① 利比亚国家石油公司宣布,Es Sider以及Ras Lanuf这两个主要港口的出口不可抗力解除,两周内其产量将从当前的50万桶/日增加到80万桶/日,四周内将进一步增加到100万桶/日,高于市场预期。② 迪拜银行Emirates NBD分析师Edward Bell在近期报告中表示,在油价走低的背后,最直接的驱动因素可能在于,市场预期利比亚的产量将在接下来数周内恢复到内战之前100万桶/日的水平。③ 这也并不难理解,对于饱受战乱之苦的利比亚来说,停火之后亟需发展经济,而原油出口又是其经济命脉。OPEC数据显示,原油出口占到利比亚出口总收入的95%,以及GDP的60%。④ 石油经纪商PVM Oil Associates分析师Tamas Varga周一表示,政治稳定以及随之而来的原油产出增加,对于经历多年战乱的利比亚来说是好消息,不过对于OPEC以及其他产油国来说,也意味着原油市场整体前景面临新的风险。⑤ Varga认为,OPEC+对此必须要认真看待,及时解决油市面临的供给冲击,否则油价相对稳定的日子就屈指可数了。
0 notes
it-observer · 8 years ago
Text
举全网之力 电信云堤守护网络安全
Tumblr media
最近的武林不消停。 在练家子眼里,这是一个草根的自由搏击选手“滋事”,不自量力地挑战中国传统武术,从而达到炒作的目的。 姑且不去说背后的是是非非,不过这种情形却让我不由联想起安全圈里令人谈之色变的分布式拒绝服务攻击。 怎么说呢?分布式拒绝服务攻击,即我们通常所说的DDoS(发音:滴到死)。听着就够坏的,本身没有多少技术含量,成本还非常低廉,但是却能够轻松瘫痪一个网站。 毫不夸张地说,只要量足够大,DDoS攻击甚至可以让一座城市断网。 好消息是,魔高一尺道高一丈。目前市场上已经有很多公司在做防护攻击的工作,而其中尤其值得关注的,则是运营商级别的某些产品和服务,譬如来自中国电信的“云堤”。 5月3日,第五届中国国际云计算技术和应用展览会暨论坛在北京召开,中国电信网络安全产品运营中心市场总���刘长波在云安全论坛上发表了演讲。会后,我有幸与他就云堤进行了一番交流。
Tumblr media
面对网络攻击的第四种选择
云堤是中国电信集团公司旗下,面向政府和企业客户推出的运营商级网络安全产品。 基于中国电信全网海量带宽、高性能设备、覆盖全国的运维体系和技术团队,云堤为政���客户提供DDoS攻击防护、域名安全防护、反钓鱼、网站安全等专业服务。 其实这个产品问世并不久。 最初的团队2014年10月成立,骨干均来自于中国电信集团公司的生产和科研一线。2015年1月,云堤正式发布和推出,当时主打DDoS攻击防护。 云堤的发展很快,不到一年的时间就服务了近1000家客户。在当年12月的第二届乌镇世界互联网大会上,鉴于云堤助力我国网络强国所取得的成绩,国家领导人对之给予了高度评价和肯定。 云堤的功力暴增,并不是因为有什么大还丹或者武林秘笈之类的奇遇,而是它与生俱来的能力,并且不断磨砺自我所致。 早在2008年,中国电信就为北京奥运预先部署了DDoS清洗设备,重点保障政府重要系统和信息平台。可以这样说,历来重要的国家级大型活动和事件,背后都有中国电信的默默支持和保驾护航。 而今,中国电信将这种能力开放出来,为更多政企客户提供专业的安全防护。据刘长波介绍,目前云堤DDoS攻击防护的客户已经超过3000家,网站安全防护的客户超过1000家。
Tumblr media
很多人可能不知道,目前几乎所有的著名大型互联网公司以及大型云服务提供商,均通过云堤提供的API调用DDoS防护能力抵挡超大规模的流量型攻击。 尽管如此,最近几年来DDoS攻击仍是有增无减。刘长波列举了一串数据,以今年2月为例,尽管当月只有28天,但是DDoS攻击总量却超过了过去任何一个月。原因很简单——充当攻击任务的“肉鸡”越来越多,攻击者的成本愈发低廉。 现实的网络环境如同充满雾霾,刘长波表示。面对网络攻击存在三种人,第一种人是正在被攻击,第���种人是不知道被攻击,第三种人是不承认被攻击。 刘长波希望大家做第四种,即:知道网络存在安全风险,一起去面对,同时清楚地知道如何去解决。他表示,针对不同的安全风险,云堤拥有不同的、针对性的解决方案。
运营商级别的终极防护
与其他同类的产品和服务不同,云堤的DDoS攻击防护是运营商级别。 首先,这意味着云堤的攻击防护位置在运营商的上游网络,而不是在客户层面。DDoS的防护动作离客户越远,客户就越安全。 其次,攻击防护的关键之一在于带宽,没有足够的带宽,大流量的DDoS攻击就没有办法被吃下去,电信在带宽方面的优势自不待言。 再次,攻击流量被带宽吃下来之后,需要专业的顶级设备做处置,将一些攻击流量破解掉,确保误杀率低。 最后,云堤有比较成熟的运维体系。得益于中国电信的运维体系,云堤可以做到从集团到省、市甚至县级层面,具有强大的现场支援能力。 云堤的优势可以总结为三步,即看得见、防得住、说得清。在防护攻击上,云堤可以做到知己知彼,这也是其他同类产品服务难以企及的巨大优势。
Tumblr media
                             DDoS攻击流量统计实时截屏 刘长波表示,对于DDoS攻击,电信云堤有7×24的值班人员。这些值班人员并不只是起到预警作用,他们实际上就是处置专家。这样做的好处是,整个链条非常短,响应时间及时,根本不需要转接二线,对DDoS攻击防护可以做到第一时间处置。 现在的各种安全防护,在本质上均属于智能化。毕竟面对海量的攻击,根本没有办法通过手动的方式进行排除。云堤也是智能化的产品,但与其他同类产品不同的是,它拥有海量的历史数据积累,对于各种攻击,云堤通过大数据“知道”如何识别正常流量,应该采取何种防护策略。 云堤的另一个优势在于DDoS攻击近源防护。其工作原理基于分布式近源防护架构的DDoS攻击防护,云堤的清洗动作靠近攻击源,将流量分布式牵引到部署在全国的26个清洗中心,完成清洗后将正常流量回送到客户服务器。 这样做的好处是可以避免单个防护节点能力不足的问题,又可以避免攻击流量过大,导致骨干网、城域网或者IDC其中任何一个环节出现网络拥塞,引起客户的业务访问质量劣化。 前面我们曾经提到过,现在的网络环境愈发严峻,各种攻击有增无减。刘长波认为,在互联网时代,只要有竞争,就必然有攻击,这种黑色产业链比过去有了更加广泛和隐蔽的存在。 互联网基础设施的不断演进,不仅给创业创新带来机遇,从另外一个角度来看,同时也给黑色产业链带来了“能力增长”。举例而言,带宽的快速增长,意味着单点的攻击能力也被迅速提升。目前,100G的24小时DDoS攻击只需要几百块钱,这在以前是不可想象的。 可以想见,DDoS攻击和防护仍将长期鏖战,运营商级别的终极防护能力不可或缺。
众志成城守护网络安全
当然,网络攻击的形式并不是只有DDoS。目前,某些攻击行为可能并不是很常见,但是造成的危害却是触目惊心。 譬如两年前苹果公司发布Apple Watch后不久,其网站便惨遭全球性宕机。结果是11个小时内,客户无法访问和购买苹果相关的产品服务,造成直接经济损失至少2500万美元,苹果的市值更是瞬间蒸发了130亿美元。 最终,苹果给出的缘由是“一个内部DNS错误”。 DNS是域名和IP地址相互映射的分布式数据库,能够使人更方便地访问互联网。简而言之,DNS就像一个自动的电话号码簿,用户可以通过直接输入网站名字,来代替复杂的IP地址,从而完成对网站的访问。 由此可见,作为网络应用的基础设施,DNS服务的安全性和稳定性,对于互联网的健康有序运转,有着举足轻重的影响。相比DDoS攻击,DNS被篡改的频率相对较低,但是各方仍务必对此加以关注。 尤其值得关注的是,一旦出现DNS被篡改的情况,客户方面基本没有任何办法,即便修正回来,倘若运营商的缓存DNS没有同步,那也无法解决。刘长波表示,云堤负责中国电信全网local DNS的维护工作,可以通过统一的调度平台实现秒级同步。 当然,并不是所有的流量都会通过中国电信,做好DNS防护需要几家运营商的统一行动。好消息是中国电信本地DNS解析流量占比多达70%到80%,因此云堤实质上守护了DNS安全的大半壁江山。 据悉,云堤目前还在跟多个大型互联网公司讨论合作事宜,争取将云堤域名无忧做成云的标配,全方位地守护客户的云安全。刘长波表示,中国电信一直在与互联网公司进行技术交流,不断对自身的产品进行迭代开发,同时与互联网公司协同处理攻击问题。
Tumblr media
每到年中年底,有一种攻击行为会变得越发活跃,这就是钓鱼网站。我们每个人都曾经收到过积分商城之类的信息,一旦点击其中的链接地址,就会被导入到一个假冒网站。倘若用户在这里输入了真实的登录信息和密码,损失就不可避免了。 目前,但凡涉及现��、虚拟货币、充值卡甚至网络游戏,都有被钓鱼的可能。由于管控力度不足,这些钓鱼网站80%以上位于香港。 云堤反钓鱼的策略除了利用大网优势——譬如DNS解析记录被动查询、秒级关停等之外,也在主动跟业内相关部门、组织和公司积极互动,共同探讨新的防护方式,为客户提供先进的防护技术,造福社会。 刘长波希望澄清外界对于云堤的一个认识误区。他表示,尽管与同类产品服务相比,云堤的价格略微高一点,但这并不意味着它是大型企业和政府机构的专享。事实上,围绕着不同客户的特点,云堤定制了不同的套餐,中小企业同样负担得起。 作为基础运营商,中国电信愿意跟各种合作伙伴一起,让网络环境更加美好,云堤也将全力守护中国互联网的安全。
2 notes · View notes
lupbiy · 8 years ago
Text
分布式系统设计的求生之路
WeTest导读
分布式系统理念渐渐成为了后台架构技术的重要选择,本文介绍了作者在手游领域对分布式系统进行的种种尝试,并在尝试中制定了对服务的定义、整体框架的构建以及服务内部拆分的流程。
前言
业务规模不断扩大,对稳定性、扩展性的要求不断提高,推动了后台架构技术的不断革新。面对日益复杂的需求,分布式系统的理念也逐渐深入到后台开发者的骨髓。2013年,借着手游热潮我对分布式系统开始尝试。在近三年的摸爬滚打中,踩过不少坑,也从业界技术发展中吸取一些经验,逐渐形成了目前的设计思路。这里和大家分��点心得,不敢奢谈有多大参考价值,权当抛砖引玉吧。
1. 失败的首次尝试
最初考虑使用分布式的出发点很简单:解决端游开发时单点结构导致容灾、扩容困难的问题。一种朴素的想法就是将相同功能的进程作为一个整体对外提供服务。这里简要描述下基本框架:
这种架构提供了三个基本组件:
Client API, 服务请求者API:
从 Cluster Center Server 获取服务提供者地址
向Server集群内所有实例注册,注册成功则认为可用
通过负载均衡算法,选择一个Server实例通信
检测Server集群内各实例的运行状态
Server API, 服务提供者API:
向 Cluster Center Server 上报自己的状态、访问地址等
接收 Client API 的注册,并提供服务
向已经注册成功的Client定时汇报状态
Cluster Center Server, 集群中心进程:
接收 Server Cluster 上报,确定服务集群的结构,以及各实例的状态
接收 Client Cluster 的请求,返回可用服务集群列表
这种架构具备了集群的基本雏形,可以满足容灾扩容的基本需求,大家应该也发现不少问题,我这里总结几点:
1. 服务发现的蹩脚实现 Cluster Center Server 的实现是单点,出现故障时Client请求会异常;没有提供监控机制,Client只能通过定时请求来获取服务的最新状况。
2. CS采用Request/Response的通信方式不灵活 现实应用中,服务往往存在相互请求,一应一答远远不够,全双工 是必须要支持的。
3. 有瑕疵的保活机制 Server对Client定期单边心跳,有两个问题:不同Client对保活要求可能不同,有些5s,有些可能1s,如果心跳发起全部在Server,无法满足差异化要求;服务端作为被动方,承担监控请求者存活的责任不明智。
4. 架构设计的层次不清晰 对架构的层次、模块划分没有作出很好的规划,比如通信底层、服务发现、集群探测与保活等等没有清晰定义接口,导致相互耦合,替换、维护较为困难。
2. 看看外面的世界
上述问题,归根结底还是眼界狭窄,自己闷头造轮子没跟上业界技术发展的步伐。近几年微服务架构发展迅速,相比传统面向服务架构不再过分强调企业服务总线,而是深入到单个业务系统内部的组件化。这里我介绍下自己的调研结果。
2.1 服务协同
服务协同是分布式系统一个核心组成部分,概述为:多个进程节点作为整体对外提供服务,服务可以相互发现,服务关注者可以及时获取被关注者的变化以完成协作。具体运行过程包括:服务注册 和 服务发现。在实现上涉及以下方面:
统一命名 对服务以及其中的节点,进行集中式、统一命名,便于相互区分和访问。
监控 确定服务的可用性和状态,当服务状态变化时,关注者要有途径获知。
访问策略 服务通常包含多个节点,以集群形式存在,Client在每次请求时需要策略确定通信节点,策略目标可能是多样的,比如 负载均衡 ,稳定映射 等等。
可用性 容灾处理,动态扩容。
业界中较为成熟的实现如下表所示:
2.2 消息中间件
亦称消息队列,在分布式系统广泛使用,在需要进行网络通信的节点间建立通道,高效可靠地进行平台无关的数据交流。架构上主要分为两种:Broker-Based(代理),和 Brokerless(无代理)。前者需要部署一个消息转发的中间层,提供二次处理和可靠性保证。后者轻量级,直接在内嵌在通信节点上。业界较为成熟的实现如下表所示:
2.3 通信协议数据格式
服务间通信,需要将数据结构/对象和传输过程中的二进制流做相互转化,一般称为 序列化/反序列化 。不同编程语言或应用场景,对数据结构/对象的定义和实现是不同的。在选择时需要考虑以下方面:
通用性 是否支持跨平台、跨语言;业界是否广泛流行或者支持
可读性 文本流有天然优势,纯粹二进制流如果没有便捷可视化工具,调试将会异常痛苦
性能 空间开销——存储空间的占用;时间开销——序列化/反序列化的快慢
可扩展性 业务的不变之道就是——一直在变,必须具有处理新旧数据之间的兼容性的能力
实现 序列化/反序列化 的组件一般包含:IDL(Interface Description Language), IDL Compiler, Stub/Skeleton。业界目前比较流行的序列化协议有:XML, JSON, ProtoBuf, Thrift, Avro等。关于这几种协议的实现以及比较,可以参考文章 《序列化和反序列化》。这里将原文中的选型结论摘录给大家:
允许高延迟比如100ms以上,内容变更频繁,且复杂的业务,可以考虑基于XML的SOAP协议。
基于Web browser的Ajax,以及Mobile app与服务端之间的通讯;对于性能要求不太高,或者以动态类型语言为主的场景,JSON可以考虑。
对性能和简洁性有极高要求的场景,Protobuf,Thrift,Avro都差不多。
对于Terabyte级别数据持久化应用场景,Protobuf和Avro是首要选择。持久化后的数据若存储在Hadoop子项目里,或以动态类型语言为主,Avro会是更好的选择;非Hadoop项目,以静态类型语言为主,首选Protobuf。
不想造 RPC 的轮子,Thrift可以考虑。
如果序列化之后需要支持不同的传输层协议,或者需要跨防火墙访问的高性能场景,Protobuf可以优先考虑。
3. 重整旗鼓
调研周边后,2015年开搞第二款手游,吸取之前的教训,这次设计的基本原则是:
系统拆分、解耦,清晰定义系统间接口,隐藏系统内部实现
大框架尽可能通用,子系统可在不同场景替换
下面首先对服务定义,然后介绍整体框架和服务内部拆分。
3.1 服务定义
举个手游的例子,看图说话:
Service Cluster 服务集群,由功能相同的实例组成,作为整体对外服务,是一个集合。比如 Lobby 提供大厅服务,Battle 提供战斗服务,Club 提供工会服务,Trade 提供交易服务。
Service Instance 服务实例,提供某种服务功能的最细粒度,以进程形式存在。比如Club 集群中有两个实例 3.2.6.1 和 3.2.6.2 ,功能一致。
Service Node 服务节点,是服务发现组件管理的基本单元,可以是集群、实例、层次关系或者业务关心的含义。
Service Key 服务节点的Key,全局唯一的身份标记。key的设计需要能够体现出层级关系,至少要能够体现出 Cluster 和 Instance 的包含关系。etcd和zookeeper均支持key层次化的组织关系,类似文件系统的树形结构。etcd有mkdir直接建立目录,zookeeper则通过路径描述父子关系。但不管怎么都可以在概念层次使用路径结构 。
上图中,Service Instance 完整路径可描述为:/AppID/Area/Platform/WorldID/GroupID/ClusterName/InstanceName。有以下特点:
集群路径一定是其中各个实例的父路径
从功能完整性而言,集群是服务的基本粒度
相同功能的集群在不同前缀路径下含义不同,服务目标也可以不同,比如: /Example/wechat/android/w_1/g_1/Lobby 和/Example/wechat/android/w_3/g_2/Lobby 功能上均表示大厅服务,但一个为大区1分组1服务,一个为大区3分组2服务
3.2 服务发现基本流程
先抽象几个基本操作,不同服务发现组件的API可能略有差异,但应该有对应功能:
Create 在服务发现组件中创建 Key 对应的 Service Node,指定全局唯一的标记。
Delete 在服务发现组件中删除 Key 对应的节点。
Set 设置 Key 对应的 Value, 安全访问策略或者节点基础属性等。
Get 根据 Key 获取对应节点的数据,如果是父节点可以获取其子节点列表。
Watch 对节点设置监视器,当该节点自身,以及嵌套子节点数据发生变更时,服务发现组件将变更事件主动通知给监视者。
Service Instance 每次在启动时,按照下面的流程处理:
生成自己的 Service Path,注意这是服务实例的路径。
以 Service Path 为key,通过 Create 方法生成节点,Set 数据:对外开放的地址、安全访问策略等。
生成需要访问的服务集群的 Service Path,通过 Get 方法获取集群数据,如果找不到说明该服务不存在;如果可以找到分两种情况:
该路径下没有子节点。说明当前不存在可用的服务实例,对集群路径设置watcher,等待新的可用实例。
该路径下有子节点。那么 Get 所有子节点列表,并进一步 Get 子节点访问方式和其它数据。同时设置 watcher 到集群路径,检测集群是否存在变化,比如新增或减少实例等。
Service Instance 在关闭时,按照下面的流程处理:
通过 Delete 方法删除自己对应的节点。有些服务发现组件可以在实例生命周期结束时自行删除,比如zookeeper的临时节点。对于etcd的目录,或者zookeeper的父路径,如果非空,是无法删除的。
根据上面的抽象可以定义 服务发现 的基本接口,接口的具体实现可以针对不同的组件开发不同的wrapper,但可以和业务解耦。
3.3 服务架构
所有的架构归根结底还是需要具体到进程层次实现的。目前我们项目开发的分布式架构组件称之为 DMS(Distributed Messaging System),以 DMS Library 的形式提供,集成该库即可实现面向服务的分布式通信。下面是 DMS 设计的总体结构:
关于Serialize/DeSerialize, APP业务的选择自由度较高,下面介绍其它Layer的具体实现:
3.3.1 Message Middleware
消息中间件前面介绍有很多选择。DMS 使用的是 ZeroMQ,出发点是:轻量级、性能强大、偏底层所以灵活而且可控性较高。由此带来的成本是,高级应用场景需要做不少二次开发,而且长达80多页的资料也需要不少时间。介绍ZeroMQ的文章太多,这里不打算科普,所以直接给出设计方案。
通信模式的选择
ZeroMQ的Socket有多种类型,不同组合可以形成不同的通信模式,列举几种常见的:
REQ/REP 一应一答,有请求必须等待回应
PUB/SUB 发布订阅
PUSH/PULL 流水线式处理,上游推数据,下游拉数据
DEALER/ROUTER 全双工异��通信
看到这里,大家可能会觉得选择PUB/SUB和DEALER/ROUTER应该可以满足绝大部分应用场景吧。实际上DMS只使用了一种socket类型,那就是ROUTER,通信模式只有一种ROUTER/ROUTER。一种socket,一种通信模式,听起来很简单,但真可以满足要求吗?
DEALER/ROUTER 是传统异步模式,一方connect,一方bind。前端如果要连接多个后端就得建立多个socket。在前面描述的集群服务模式下,一个节点既会作为Client也会作为Server,会有多条入边(被动接收连接)和出边(主动发起连接)。这正好就是路由的概念,一个ROUTER socket可以建立多条通路,并对每条通路发送或者接收消息。
PUB/SUB 注重的是扩展性和规模,按照ZeroMQ作者的意思当每秒钟需要向上千的节点广播百万条消息时,你应该考虑使用 PUB/SUB 。好吧,可预见的将来业务规模恐怕还到达不到这种程度,现在先把简单放在第一位吧。
3.3.2 DMS Protocol
消息结构
DMS的协议实现集群管理,消息转发等基本功能。ZeroMQ的消息可以由 Frame 组成,一个Frame可以为空也可以是一段字节流,一个完整的消息可以包含多个Frame,称为Multipart Message。基于这种特点,在DMS定义协议,可以将内容拆分为不同的基本单元,每个单元用一个Frame描述,通过单元组合表示不同的含义。这与传统方式:一条协议就是一个结构体,不同单元组合需要定义为一个结构体的方式相比更加灵活。
下面来看看DMS Protocol的基本组成。首帧一定是对端ID。对端接收后也一定会获取信息发送端的ID。第二帧包含DMS控制信息。第三、第四帧等全部是业务自定义的传输信息,仅对REQ-REP有效:
PIDF有两层含义:所在服务集群的标记,自身的实例标记。这些标记与Service Discovery关于节点key的定义保持一致,有两种形式 字符串 与 整型,前者可读方便理解,后者是前者的Hash,提高传输效率。使用伪代码来描述PIDF,大概是下面的样子:
PIDF中的 ClusterID 和 InstanceID 各种取值,会有不同的通信行为:
在连接首次建立时,还需要将可读的服务路径传输给对端:
协议命令字
DMS协议全部在每个消息的第二帧即Control Frame中实现。命令字定义为:
通信流程——建立连接
通过 Service Discovery 找到server后不要立即连接,而是发送探测包。原因有以下几点:
服务发现虽然可以反映节点是否存活,但一般有延迟,所以从服务发现获取的节点仅仅是候选节点。
网络底层机制差异较大,有些基于连接,比如raw socket,有些没有连接,比如shared memory。最好在高层协议中解决连接是否成功。这就好比声纳,投石问路,有回应说明可以连接,没有回应说明目前连接不可用。
通信流程——业务消息发送
普通消息 若 PIDF 表示对端实例和当前进程直接连接,那么发送消息
路由消息 若 PIDF 表示对端实例和当前进程没有直接连接,那么可以通过直连的实例转发。路由机制 后文会介绍
广播消息 若 PIDF InstanceID为负数,则向指定集群内所有实例广播
路由 和 广播 是可以混合使用的。上述过程 DMS 自动完成,业务不必参与,但可以截获干预。
通信流程——保活机制
建立连接后,请求者会持续按照自己的间隔向服务者发送探测包。如果请求者连续若干次没有收到服务者的PONG回包,则请求者认为与服务者的连接已经断开。 如果服务者收到请求者的任何数据包,认为请求者存活,如果超出一定时间没有收到(含PING),则认为请求者掉线。这个超时时间包含在READY协议中,由请求者告知服务者。
通信流程——连接断开
任何一方收到 DISCONNECT 后,即认为对方主动断开连接,不要再主动向对方进行任何形式的通信。
3.3.3 DMS Kernel
下面介绍 DMS Kernel 如何根据 DMS Protocol 实现相关逻辑,并如何与业务交互。
SERVICE MANAGER
self 确定自身 服务路径,实现服务注册,以及与目标通信链路的注册,供路由表使用
targets 获取并监控目标服务的数据以及运行状态
ACL 访问控制管理
对服务发现层接口进行封装,不同的 SERVICE DISCOVERY 功能可能有所不同
ROUTER MANAGER
每个服务实例在主动成功连接对端服务后,通过 SERVICE MANAGER 将连接以边的形式写入到 SERVICE DISCOVERY 中,这样就会以 邻接边 的形式生成一张完整的图结构,也就是routing table。比如: Service 1 和 Service 2,Service 3,Service 4 均有连接,那么将边(1,2),(1,3),(1,4) 记录下来。SERVICE DISCOVERY 关于路由邻接链表的记录可以使用公共的key,比如: /AppID/Area/Platform/routing_table 。然后所有的服务实例都可以更新、访问该路径以便获得一致的路由表。基础功能有两个:
Updater 用于向路由表中添加边,删除边,设置边的属性(比如权重),并对边的变化进行监控
Calculator 根据邻接边形成的 图结构 计算路由,出发点是当前实例,给定目标点判断目标是否可达,如果可达确定路径并传输给下一个节点转发。默认选择 Dijkstra 算法,业务可以定制。
CONNECTION MANAGER
管理 Frontends 即前端请求进入的连接,和 Backends 即向后端主动发起的连接。Backends的目标来源于 Service Manager。
Sentinel 对前端发起的连接,通过 READY 协议,可以获取该连接的失活标准,并通过前端主动包来判断进入连接是否存活。如果失活,将该连接���为断开状态,不再向对应前端主动发包。
Prober 对后端服务进行连接建立和连接保活。
Dispatcher 消息发送时用于确定通信对端实例。连接是基于实例的,但是业务一般都是面向服务集群的,所以Dispathcer 需要实现一定的分配机制,将消息转发给 服务集群中的某个 具体实例 。注意这里仅只存在直接连接的单播。分配时应考虑 负载均衡 默认使用一致性哈希算法,业务完全可以根据具体应用场景自定义。
3.3.4 DMS Interface
DMS API 是DMS对业务提供的服务接口,可以管理服务、通信等基本功能;
DMS APP Interface 是DMS要求业务必须实现的接口比如:Dispatcher 的负载均衡策略,对端服务状态变化通知,以及业务自定义 路由算法 等等。
3.4 应用场景
下面罗列DMS三大类典型应用场景,其它场景应该可以通过这三个例子组合实现:
无Broker通信
最基础的通信方式——两个集群之间的 Instance 全连接,适合服务数量不多、逻辑不复杂的简单业务。
Broker通信
对于一个内部聚合的子系统,可能包含N个服务,这些服务之间相互存在较强的交互行为。如果使用无Broker模式可能有两个问题:链路过多:通信层的内存占用较大;运维维护困难;服务没有解耦,直接依赖于对端的存在; 这时Broker集群可以承担消息中转的作用,而且可以完成一些集中式逻辑处理。注意这里Broker只是一个名字,通过 DMS Library 可以直接实现。
Broker级联通信
多个子系统相互通信,估计没有设计者愿意把内部细节完全暴露给对方,这时两个Broker集群就相当于门户:首先可以实现内部子系统相互通信,以及集中逻辑;其次,可以作为所处子系统的对外接口,屏蔽细节。这样不同子系统只需通过各自的Broker集群对外提供服务即可。
总结
本文主要介绍了 DMS 的几个基础结构:服务发现、消息中间件以及通信架构。基本思想是:框架分层、层级之间接口清晰定义,以便在不同场景下使用不同的具体实现进行替换。其中 zookeeper,ZeroMQ 只是举例说明当前的一种实现方式,在不同场景下可以选择不同组件,只要满足接口即可。
分布式系统设计的求生之路,首发于文章 - 伯乐在线。
1 note · View note
gozealouscloudcollection · 5 years ago
Text
我在GitHub找Bug:如何轻松赚到10000美元
Bug赏金猎人,不用流血牺牲,只需轻敲键盘就可完成赏金任务。这些人通过发现企业的安全漏洞以获得赏金,企业也非常欢迎这样的赏金猎人“找茬”。今天这篇文章主要送给Bug赏金猎人以及企业信息安全团队,我们将探讨用户意外发布至公开GitHub库内的常见敏感信息(即“秘密”)类型,以及查找这些秘密的启发性方法。
每一天,都有API密钥、密码以及客户数据被意外发布到GitHub之上。恶意人士当然可以利用这些密钥登录服务器、窃取个人信息,或者给用户带来数额高到不可思议的AWS服务成本。GitHub泄露事故可能令企业蒙受数百甚至数千万美元的损失,而从GitHub上收集开源情报也已经成为每一位安全研究者都不能错过的重要信息来源。来自北卡罗来纳大学的研究人员,甚至专门就此撰写了学术论文。
今天这篇文章主要送给Bug赏金猎人以及企业信息安全团队,我们将探讨用户意外发布至公开GitHub库内的常见敏感信息(即“秘密”)类型,以及查找这些秘密的启发性方法。当然,本文中提到的技术手段也��用于GitHub Gist片段。
就在去年,我凭借着这些技巧从HackerOne(一个对接白帽黑客和企业的平台)上的几个Bug赏金计划中轻松拿到了接近1万美元的奖励。我还发布了GitHound——这是一款开源dork,能够自动在GitHub上查找不慎外泄的密钥。GitHound所针对的可不仅仅是单一用户或组织:它能够遍历整个GitHub,使用代码搜索查询作为项目库的入口点中,而后利用上下文、正则表达式及其他一些巧妙的“歪脑筋”快速批量查找秘密。
GitHub代码搜索
GitHub提供丰富的代码搜索功能,可用于扫描公开GitHub库(这里忽略fork及非默认分支等因素)。查询方式可以简单如uberinternal.com,也可以包含类似 “Authorization: Bearer”这样的多单词字符串。搜索操作甚至可以指向特定文件(filename: vim_settings.xml)或者特定语言(language:SQL)。另外,搜索也能包含某些布尔限定符,例如NOT …
from 我在GitHub找Bug:如何轻松赚到10000美元 via KKNEWS
0 notes
wingedmiraclesublime · 3 months ago
Text
好的,以下是根据您的需求生成的文章:
```
蜘蛛池需要哪些注释?TG@yuantou2048
在进行爬虫开发时,使用“蜘蛛池”是一种常见的策略,它可以帮助我们更高效地管理和运行多个爬虫任务。为了确保代码的可读性和维护性,添加适当的注释是非常重要的。下面是一些在蜘蛛池中常用的注释类型:
1. 模块注释:在每个模块或文件的开头,可以添加模块注释来描述该模块的功能、用途以及依赖关系等信息。例如:
```python
"""
模块名称: spider_pool
功能描述: 用于管理多个爬虫任务的调度和执行
作者: YourName
创建日期: YYYY-MM-DD
"""
```
2. 函数注释:对于每个自定义函数,都应该有详细的注释说明其功能、参数、返回值等信息。
```python
def start_spiders():
"""
启动所有爬虫任务
:return: None
"""
```
3. 变量注释:对关键变量进行解释,特别是那些具有特定含义或者复杂逻辑的变量。
```python
爬虫任务队列
task_queue = Queue()
```
4. 类注释:当定义一个类时,可以在类定义之前添加文档字符串(docstring),以清晰地表达该类的作用及使用方法。
```python
class SpiderManager:
"""
管理爬虫任务的类
"""
5. 方法/函数注释:为每个方法或函数提供简短但明确的描述。
```python
def add_task(self, url):
"""
将新的URL添加到任务队列中
:param url: 需要爬取的网页链接
```
6. 流程注释:在实现具体业务逻辑的地方添加必要的注释,帮助其他开发者理解这段代码的目的和工作原理。
```python
def process_response(self, response):
"""
处理HTTP响应数据
:param response: 请求返回的结果对象
:return: None
"""
```
7. 异常处理注释:当遇到可能引发错误的情况时,应该注明可能出现的异常情况及其处理方式。
```python
try:
...
except Exception as e:
print(f"Error occurred: {e}")
```
8. 算法逻辑注释:如果某个部分涉及到复杂的算法或逻辑判断,则需要详细解释这些步骤背后的思路和设计意图。
```python
def parse_item(self, item):
"""
解析提取出的数据项
:param item: 抓取到的具体内容
```
9. 重要步骤注释:在关键步骤前后加上注释,指出此段代码做了什么以及为什么这么做。
```python
try:
...
finally:
pass
```
10. 调试信息注释:在调试过程中记录下每一步操作的原因和预期结果。
```python
if condition:
do_something()
else:
raise ValueError("Invalid input")
```
11. TODO注释:标记待完成的任务或需要注意的地方。
```python
TODO: 实现具体的解析规则
```
12. 日志记录:利用logging模块记录关键点的日志信息,方便后期维护和排查问题。
```
13. 版本控制相关注释:如果项目中有版本控制机制(如Git),则应在相应位置添加注释来指示下一步该如何做。
```
14. 优化建议:如果某些地方有待改进之处,请务必留下提示以便于后续优化。
```python
logger.info('Processing...')
```
15. 性能优化建议:如果某段代码是为了提高性能而编写,则应给出相应的注释,指明这样做的原因是什么样的场景下会触发这个分支条件。
```
16. 配置文件注释:对于一些配置项做出合理安排,并且保持一致性。
17. 遗留问题注释:如果当前实现存在缺陷或者未来可能需要修改的地方也请做好标注。
```
18. 外部接口调用注释:当调用了第三方库或其他模块的功能时,最好能够指出这部分代码的意义所在。
```
19. 测试用例注释:编写单元测试时,可以考虑加入关于如何改进现有实现的注释,这将有助于团队成员快速定位问题所在区域。
```
20. 数据库操作注释:针对数据库交互的部分给予适当提醒。
```
21. API接口注释:当调用外部服务或API时,记得写清楚调用过程中的注意事项。
```
22. 环境变量注释:如果程序依赖于特定环境变量,则需特别强调它们之间的联系。
```
23. 安全相关注释:任何与安全性有关的操作都需要详细说明其作用范围内的上下文环境要求等信息。
```
24. 遗留代码注释:有时候我们会遇到一些暂时无法解决的问题,此时可以通过这种方式告知他人此处存在的风险点在哪里。
```
25. 资源清理注释:比如关闭连接等操作前后的状态变化情况。
```
26. 遗留代码注释:有时因为历史原因保留下来的冗余代码块,通常包括但不限于以下几点:
```
27. 遗留代码注释:如果有一些未完成的功能点,可以用特殊符号``标识出来。
```
28. 遗留代码注释:如果有些地方采用了临时解决方案,则必须详细记录下来。
```
29. 遗留代码注释:当引入了新特性后,别忘了更新文档以反映最新改动。
```
30. 遗留代码注释:如果遗留了一些没有被充分利用的功能点,也应该给出原因以及预期效果。
```
31. 遗留代码注释:如果遗留了旧版遗留代码,请尽量减少重复劳动并保持良好的编程习惯总是优于直接删除不适用的代码块,而不是简单地删除掉它们。
```
32. 遗留代码注释:如果系统架构发生变化,则需要特别注意的地方。
```
加飞机@yuantou2048
Tumblr media
Google外链购买
谷歌留痕
0 notes
inmatts-blog-blog · 6 years ago
Text
氪星晚报 |腾讯公布游戏主播认证计划;蔚来汽车9月将裁员1200人;雷军:第二款5G手机将在国内首发
大公司 腾讯公布游戏主播认证计划公告 36氪获悉,腾讯游戏主播站在微博发文公布游戏主播认证计划公告,公告中指出,认证计划是由腾讯游戏发起,针对游戏直播内容创作者的首个腾讯官方主播扶持计划。对有意愿长期基于腾讯游戏创作内容的优秀创作者,腾讯游戏主播认证计划将给予官方身份认证和曝光特权、产品特权、活动特权、内容特权。 美媒测试:部分iPhone辐射超出安全极限,iPhone 7最差 美国《芝加哥论坛报》近期对热门智能手机的射频辐射水平进行调查,发现某些型号iPhone射频辐射超过安全极限。多款iPhone的辐射水平超过法定安全极限,表现最差的是iPhone 7。这款手机的射频辐射暴露超过法定极限,是苹果向美国联邦监管机构报告数字的两倍多。对此,苹果发表声明称测试不准确,因为“测试设置不符合正确评测iPhone所需的程序”。(新浪科技) 蔚来继续裁员1200人,1号员工被调整待命 36氪获得的蔚来全员邮件显示,这家公司仍在推进裁员计划,将在全球范围内继续减少1200个工作岗位,9月底保留7500人。而在8月初,蔚来总裁秦力洪告诉36氪未来汽车日报,蔚来员工总数为8800多人,相比蔚来员工数最高时的9800人,已经减员1000人。 京东方年底有望列入苹果供应商名单,取决于iPhone能卖多少台 针对有消息称苹果正在对京东方的智能手机屏进行最后阶段测试一事,苹果方面回应称,公司不予置评。不过IHS分析师郭子骄表示,如果进展顺利,京东方预计将于明年起向苹果供货,“京东方何时能真正量产出货,以及具体的产量计划目前还很难预测,因为这取决于多个因素,包括苹果明年的销量以及京东方自身产品的稳定性。目前这两者都还是未知数。”(第一财经) 改变世界的52家公司:比亚迪、阿里、百度上榜 近日,财富中文网发布2019改变世界的52家公司榜单,其中高通、万事达卡、比亚迪排名前三。今年共有3家中国公司上榜,除比亚迪之外,阿里巴巴排名37,百度排名39。(中新网) 支付宝官方宣布小程序与蜻蜓Iot支付已经实现打通 36氪获悉,支付宝官方宣布小程序与蜻蜓Iot支付已经实现打通,即刷脸支付、电子会员、小程序串联为一条完整链路。支付宝相关人士表示,这项能力在帮助商家做会员拉新和粘性培养上效果显著,是传统移动端开卡规模的6倍。(站长之家) 特斯拉Autopilot软件负责人离职 据外媒报道,在特斯拉对其自动驾驶团队进行重组后,该公司自动驾驶系统Autopilot负责人Stuart Bowers已离职,跳槽至风险投资公司Greylock工作。在特斯拉任职时,Stuart负责领导Autopilot团队,管理一百多名工程师。在此之前,其曾是Snap的一名软件高管。(盖世汽车资讯) 科技企业联手保护云数据,阿里巴巴、腾讯和百度加入 据美国科技媒体GeekWire报道,微软、谷歌、阿里巴巴、Red Hat、IBM、英特尔等大型科技企业联合起来,希望增强云安全,以保护数据。Linux基金会宣布说,大型科技企业将会组建Confidential Computing Consortium(简称CCC),它的目标是设立标准和框架,开发工具,给数据加密。目前的技术主要用来保护静止数据,不是传输中的数据。(新浪科技) 苹果投入60亿美元,Apple TV+或定价每月9.99美元 据知名苹果博客Macrumors报道,苹果已为其即将于今年晚些时候推出的Apple TV+流媒体服务花费60多亿美元用于原创电视节目和电影。此外,据彭博社报道,苹果正在考虑为Apple TV+定价每月9.99美元,其中包括免费试用。苹果的目标是在11月正式推出Apple TV+,具体排播计划目前仍未确定,但计划一次发布三集原创电视节目,每周发行一次。(界面) 传三星代工致高通5G芯片报废,高通回应:假新闻 据中国半导体论坛消息,三星代工的高通5G芯片Snapdragon SDM7250,因良率出问题,导致全部产品报废,三星自身的处理器也发生同样问题。据《每日经济新闻》最新报道,高通方面相关人士称,5G芯片报废是假新闻,正式的回应正在协同沟通中。   联想启动"酷公司30"计划,帮助中小科创企业转型 联想集团启动“酷公司30”计划,称招募并筛选最具代表性的科创企业Top 30,帮助中小企业成长并实现数字化转型升级。该计划由联想和极客公园共同发起。入选企业将成为超级企业会员,联想将提供硬件、开放兼容的IT服务、定制咨询及企业整合解决方案等。此外,联想还正式发起“企业会员招募”,邀请更多企业加入。(新浪科技) 喜马拉雅回应“安排规模至多10亿美元IPO”:尚未有明确计划 据IFRAsia援引知情人士消息称,中国在线音频平台喜马拉雅已选择高盛、摩根大通和摩根士丹利安排5亿美元至10亿美元的IPO。随后,喜马拉雅回复36氪称:现阶段尚未有明确的IPO计划,目前喜马拉雅的重心还是聚焦整个音频生态的建设,专心为用户和主播做好服务。 投融资 上海人工智能相关行业融资额创新高,正推进一批重大创新项目 从上海市经信委获悉,据全口径企业信息统计,上海人工智能核心企业超过1000家,泛人工智能企业超过3000家,人工智能企业从业人员约10万人。2018年全市人工智能相关行业融资额超过600亿,达历史新高。此外,一批重大创新项目正在持续推进。包括商汤人工智能重大算力平台、联影人工智能医疗创新平台、复旦微电子异构智能芯片、武纪云端推理芯片、达闼柔性机器人等。(澎湃) “爱宠医生”获1.3亿元新一轮融资 36氪获悉,“爱宠医生”近日完成了1.3亿元人民币新一轮融资,本轮融资来自复星旗下上市公司豫园股份。在此之前,爱宠医生已经获得过多轮融资,投资方包括中金资本、普华资本、探针基金等。 在线少儿音乐教育品牌“优贝甜”获得千万元Pre-A轮融资 36氪获悉,在线少儿音乐教育品牌“优贝甜”近日完成了千万元Pre-A轮融资,由荟聚资本领投,北塔资本、定安得科技跟投的千万级Pre-A轮投资,融资将主要用于课程研发、市场推广、运营团队扩招。此前,优贝甜曾于 2017 年 8 月获得北塔资本和蓝象资本的数百万元天使轮投资。 新产品 亚马逊全球开店向欧洲站提供线上发货服务 近日,亚马逊全球开店正式向欧洲站的自配送卖家们推出 “购买配送”服务。“购买配送”是亚马逊网站上针对卖家自配送订单的线上发货服务。卖家可以在卖家平台,直接向合作的配送商购买配送服务并打印标签,也可以使用“购买配送”服务API对接ERP使用该服务。(亿邦动力网) 外媒:诺基亚5G手机明年发布,价格最低约500美元 据Digitaltrends报道,生产诺基亚手机的HMD Global公司称,他们正在制造一款旗舰级的5G智能手机,发布日期定在2020年。关于价格,HMD的首席产品官Juho Sarvikas称,诺基亚5G手机的成本将是目前5G手机的一半左右。(IT之家) 雷军:第二款5G手机即将在国内首发 小米集团创始人雷军时表示,小米第一款5G手机是今年5月在欧洲首发,第二款准备即将在国内首发。雷军认为,5G对智能手机企业来说是一次重大的机遇,3年前小米就开始准备各种5G技术的预研,他表示,现在5G才刚刚开始拉开序幕,明年第二季度开始5G网络的铺设和5G终端普及将大规模到来。(新华网)  西安:年底前将推广应用6000余辆纯电动出租汽车 2019年年底前,西安市将推广应用6000余辆纯电动出租汽车。届时,西安市老旧的双燃料出租汽车将退出历史舞台,全部更换为更加环保的甲醇出租汽车和纯电动出租汽车。本次更新的纯电动出租汽车选用比亚迪e5车型。(陕西日报) Facebook发布新工具:用户可清除外部网站浏览历史 Facebook发布了一款工具,让用户可以看到Facebook在其平台之外收集的在��活动相关信息。这个新工具将会显示有那些第三方网站与Facebook分享了用户访问信息,并允许用户将自己的历史浏览记录与其Facebook账号断开联系。用户还可以选择不让Facebook追踪他们以后在其他网站上的在线活动。(腾讯证券) 今日观点 新加坡:特斯拉是生活方式不是环保 我们没兴趣 新加坡环境和水资源部长马善高(Masagos Zulkifli)周三接受采访时说,新加坡已将更多依靠地铁和公交出行放在优先位置。马斯克此前曾批评新加坡在接纳和部署电动汽车方面行动迟缓,马善高被问及马斯克的评论时说:“马斯克想要的是一种生活方式,我们对生活方式不感兴趣。我们感兴趣的是解决气候问题的合适方案。”(新浪财经) 其他重要资讯 中国人民银行印发《金融科技(FinTech) 发展规划(2019—2021年)》 36氪获悉,近日,中国人民银行印发《金融科技(FinTech)发展规划(2019-2021年)》,明确提出未来三年金融科技工作的指导思想、基本原则、发展目标、重点任务和保障措施。《规划》指出,金融科技是技术驱动的金融创新。 电子邮箱地址、行踪信息拟被纳入法定个人信息范围 民法典人格权编草案22日提请十三届全国人大常委会三审。鉴于个人的电子邮箱地址、行踪信息同样具有识别特定自然人的功能,草案三审稿将其纳入个人信息范围,规定:个人信息是以电子或者其他方式记录的能够单独或者与其他信息结合识别特定自然人的各种信息,包括自然人的姓名、出生日期、身份证件号码、电子邮箱地址、行踪信息等。自然人的个人信息受法律保护。(中新网) 36氪每日商业精选 商业精选是36氪的一个日更专栏,每天从海量信息中精选8条要闻,帮你省时间,主编条条做点评,帮你做判断。以下是专栏的一个小栏目——小数据,查看完整内容,请戳链接订阅哦~ http://dlvr.it/RBgnmF
0 notes
einverne · 8 years ago
Link
本文原载于 theVerge,作者 Sarah Jeong,由 ONES Piece 翻译计划 翻译。ONES Piece 是一个由 ONES Ventures 发起的非营利翻译计划,聚焦科技、创投和商业。
译者按:Waymo 和 Uber 的知识产权纠纷还在发酵,引发行业持续关注。但或许少有人知的是,审理该案的法官本人也是一位「技术宅」,写了几十年的程序,其对技术细节的熟悉程度甚至让很多科技公司的律师汗颜。在法律与科技越发紧密结合的今天,这位「极客法官」的经历不仅极富趣味,更是对两个行业从业者的一种鞭策:闭门专攻一门学科已经不够,唯有两者兼修,才能在未来的市场上立足。
2012 年 5 月 18 日,在加州北区的 William H. Alsup 法官主持的一次庭审中,甲骨文和 Google 的律师围绕着九行代码争论不休。甲骨文诉 Google 案(Oracle v. Google),一场关于 Google 是否抄袭了甲骨文的代码来开发 Android 系统的争议,正要结束第一次陪审团审理。
争议焦点集中在一个名为 rangeCheck 的函数上。在甲骨文测试的共计 1500 万行代码中,只有这一部分是「逐字逐句」抄袭的,每个字符都分毫不差。越是尽可能鼓吹 rangeCheck 的重要性,对甲骨文就越有利。甲骨文的律师 David Boies 于是开始主张 Google 抄袭了 rangeCheck,目的是更快将 Android 推向市场。但 Alsup 法官对这个说法并不买账。
「判这个案子之前,我对 Java 一无所知,」这位法官说。「但是,我自己用很多其他语言编过程序,现在也还在编程。我写过一百多段 rangeCheck 这样的代码。这我都能做到。你也能。这太容易了。」
(甲骨文的律师试图继续发言,但只是让法官变得越来越不满)
这段不经意的评论像雪球一样,影响力越滚越大,以至失控。这让 Alsup 大为懊恼。它先是在律师和法律专业人士间被反复引述,然后又传到了科技媒体那里。每经过一次转述,Alsup 的技能就增长一分,直到最后他变成了「会 Java 的法官」——程序员 Alsup、黑袍加身的技术宅英雄、十倍速法官、「法庭和 Java 双料大师」。
Alsup 法官想让人们知道的是,他不懂 Java。
至少,他懂得不多。不过他确实会写代码。实际上,他已经用 BASIC 自娱自乐地写了几十年代码,包括一个写出来送给妻子的玩桥牌的程序,和一个自动给出桌游《珠机妙算》(Mastermind)解法的程序。
最花心思的,要数一个带图形界面的复杂多功能程序,用来方便他广泛爱好中的另一项——火腿电台(译注:指供业余无线电爱好者进行信息交换、技术实验、自我训练、个人娱乐、运动竞赛以及应急通信的一项使用无线电频率频谱的无线电业务)。
他的兴趣对法官工作大有帮助。是这份兴趣,使他形成了对面前这桩价值数十亿美元的知识产权案件的看法。科技公司的财富增减,全凭他的判决。甲骨文诉 Google 案对大公司和类似的小开发商将产生深远的间接影响,更遑论其九亿美元的争议标的。在正在审理的 Waymo 诉 Uber 案中,Alphabet 公司也是请求判决 Uber 赔偿数十亿美元,总额尚未确定。这笔钱的归属攸关 Uber 在新兴的自动驾驶汽车市场的存亡。
巧得很,这些要案都归到了可能是全美唯一能理解它们技术细节的法官——一位会写代码的法官的案头。Alsup 长年的兴趣给解决甲骨文诉 Google 案的核心问题带来了启发,而他在业余时间捣���摄影、镜头、光线学问的经历也为他审理 Waymo 诉 Uber 案提供了信息——该案涉及到一种名为 LIDAR 的基于激光为自动驾驶汽车提供导航的技术。
科技行业长期以来都对法律无法理解自己感到沮丧,而大多数司法系统正因如此难以跟上高速发展的步伐。那种认为法律永远不能「追上」科技的观念,一部分来自技术优越论(tech exceptionalism),即一种自由倾向的精英主义,嘲讽一切采用法律或规制形式介入技术发展的行为,将其比作纺织工人对织布机的抵制(Luddism)。但这种观念也来自对法律现状真实存在的不满。专利局被看作橡皮图章,为那些显而易见的技术颁发专利;最高法院的大法官似乎对编程的基本流程都感到困惑;还有律师让技术盲组成陪审团,他们做出了侵犯网上购物车专利的巨额赔偿判决。
在这样的背景下,Alsup 是一个异类——在「法律无法理解快速变化的科技行业」这一广为流传的经验面前,他成了一个谜一样的例外。但 Alsup 的秘诀也很简单:他当了一辈子的极客。
Alsup 在旧金山的律师中因为总是赶早而「臭名昭著」(而且还强迫出庭律师一起赶早)。早上九点,联邦法院大多数法官的房间还是一片漆黑、大门紧闭。但当我走到 Alsup 的房间时,发现大门敞开,忙碌的景象说明里边的人已经忙活几个钟头了。
Alsup 一头白发,戴矩形边框眼镜,操着一口温和的南方口音。虽然身型与常人无异,但他那强烈的存在感却给人居高临下的印象。
Alsup 的房间体现出很多法律从业者的传统审美:整架整架的皮面书、深色木墙板、一张大得吓人的桌子上挂着亚伯拉罕 · 林肯的小幅黑白像。另一头是一张沙发,上面扔了几个给狗玩的玩具。他经常带着上班的那只杰克罗素梗今天没在办公室。
法官请我在沙发上坐下,给我展示了他存在一台法院发的 2011 年款戴尔笔记本上的程序。他的台式机运行不了这些程序,他颇为恼火地告诉我,所以得留着这台戴尔。「这是最后一台支持 QuickBASIC 的机器,非常遗憾,我只懂这种语言。」
这位法官对硬件并不感冒。法院给他发什么电脑和手机,他就用什么。他用的是法院发的 iPhone,但他说,如果加州北区法院给他发一台 Android 手机,那他就会用 Android。
我问他能不能把他的代码发在 GitHub 上,结果他问我什么是 GitHub。作为替代,他递给了我打印版的程序代码,整整三叠纸,边角处装订整齐。他道歉说,最上面那叠有一些依赖程序没空打印出来。在成为审理硅谷案件的法官之前,Alsup 就是个特立独行的业余爱好者;他是个极客,不过是来自另一个时代的极客。
Alsup 于 1945 年出生在密西西比州的杰克逊市,父母都是德州乡下人——母亲是护士,父亲是土木工程师,从罗斯福时代的公共事业振兴署开始参加工作。
孩童时起,Alsup 就体现出他日后标志性的无拘无束的好奇心和技术天赋。他童年的大部分时间是和如今的奥本大学教授 Hubert Feild 一起度过的。两人从六岁起就成了朋友,一起堆过沙垒,埋过时间胶囊,放过用洗衣袋做的热气球,用晾衣夹发射过点燃的火柴(Alsup 的发明),还「用土块打过仗」(Feild 说,「不推荐这么玩」)。
「Bill 是个超级聪明的小孩,」Feild 说。Alsup 自从学了钢琴,因为不满意钢琴的声音,便把图钉摁进敲击琴弦的弦槌里。这番改动让琴声听起来好像是从消失已久的牛仔酒馆里传出来的。「我还留着 Bill 在他的『全新改进』版钢琴上弹经典歌曲(比如雷 · 查尔斯的作品)的录音,」Feild 说。
但最激发这两个男孩想象力的玩意儿还要数火腿电台。两人整小时地收听短波广播,还把一台天顶电子「跨洋」收音机(Zenith Transoceanic)的频段接到一个七寸的远距离接收天线上。他们调到遥远的电台,像莫斯科电台、基多电台、哈瓦那电台,但最多的时间还是花在收听业余操作员,也就是所谓「火腿」们的对话上。
「当我们听到来自美国各州和外国的『火腿』们的对话时,那感觉就像是在密西西比的边界外发现了『新世界』,」Feild 说。他曾亲耳听到高中就领到业余操作员执照的 Alsup 在自家卧室里和遥远的爱好者交流,有时用的还是摩斯电码。
(这是大约 1963 年,年轻的 Alsup 在火腿电台前)
「Bill 对我的人生影响很大,到现在还是,」Feild 说。「在过去的二十多年里,我每周六早上都用火腿电台和 Bill 聊天。」
高中毕业后,Alsup 进入了密西西比州立大学学习工程专业,立志像父亲一样成为土木工程师。但那是六十年代,民权运动正如日中天:他入校第一年就爆发了华盛顿大游行;大二那年,1964 人权法案又获得通过。
随着 Alsup 对更广泛的法律问题产生兴趣,他的目标明确起来。「我想成为另一个阿提克斯 · 芬奇(译注:《杀死一只知更鸟》中的律师父亲),」Alsup 告诉我。大学毕业后,他进入了哈佛法学院,随后成为最高法院大法官道格拉斯(William O. Douglas)的书记员。
他曾在密西西比州开业从事民权工作,但发现难以维持生计。最终,他和妻子在 1973 年迁到旧金山,多年间从事私人法律业务,同时在司法部工作。1999 年,他被比尔 · 克林顿总统任命为联邦法院法官。
Alsup 在加州北区律师圈中有着令人生畏的名声。他赶早的习惯是律师们的噩梦,要他们最早七点就开始提出动议;有时候,如果看到人都到齐,开庭时间可能更早。诉讼律师的时间被精确到分钟;他说什么时间,陪审团就得在那个点准时出去。
在甲骨文诉 Google 案的第二次开庭中,他拒绝律师在下午一点以后继续对施密特(Eric Schmidt)提问,即便这意味着这位 Alphabet 董事长第二天又得回到法庭。市值 5700 亿美元的大公司的生意要给陪审员让路,因为他们得去幼儿园接孩子,把晚饭端上桌,或者赶一趟回家的远途列车。「我知道证人很忙,」Alsup 说,「但陪审员们的时间现在更重要。」
他把自己法庭的温度维持得比法院别处冷得多;据传他把空调开大是为了让陪审员保持清醒。如果旁听席里有人咳嗽,Alsup 就会停下审理,找出是谁在咳嗽。人找出来以后,法官就掏出一颗止咳糖——这是他摆在椅子边为这种场合准备的,然后这颗让人难堪的止咳糖就从律师那一排一直传到旁听席上。如果那人还接着咳嗽,他就得离开法庭,越快、越安静,越好。
在陪审员关在合议室里听不见的时候,他对律师会很尖刻。但陪审员眼中的法官是一位爷爷般关切备至的南方绅士,他会花时间单独问候陪审员,感谢他们投入时间。
一次,甲骨文诉 Google 案中的一位陪审员在庭审中被蜜蜂蛰了,Alsup 就问她还能不能跟上庭审。听到她哼哼唧唧,法官说,「那我换种问法。你还能不能像被蜜蜂蛰之前那样清楚地理解现在的进程?」
「能,」她赶紧回答。
美国法律制度赋予律师很大程度上选择陪审员的权力。正因如此,即使是一桩发生在加州旧金山,这座科技之都的软件版权案件,陪审团里竟没有一个人有计算机行业从业经验。然而,律师决定不了自己会碰上什么法官。在科技业主导的加州北区,诉讼律师们已经明白,在 Alsup 法官面前,他们可占不到便宜。
(Alsup 法官 2012 年在甲骨文诉 Google 案意见中的代码样例)
甲骨文诉 Google 案是有关 Android 平台的一桩涉及面宽、影响力广的诉讼;对于本案,几十亿美元的标的只是诉讼可能带来的后果中最不重要的一个。
70 位著名程序员并不是无缘无故联名以「法庭之友」(译注:amicus curiae,指特殊案件中为法院提供中立建议之人)身份向联邦巡回法庭,后来又向最高法院提交《计算机科学概要》的。他们都是在担心甲骨文诉 Google 案对他们的职业可能造成的影响。
甲骨文在 2010 年就以多项专利权和版权主张起诉了 Google ,这些诉讼 2012 年在 Alsup 法官的审理下全部落败。但甲骨文上诉了,联邦巡回法庭改判其胜诉。当 Google 试图再次上诉时,最高法院拒绝审理这些案件,并将其发回地区法院,由 Alsup 法官重审。
本案是于 2016 年重新开庭审理的。和上一次一样,陪审团判决 Google 胜诉,而上诉案也又一次有待联邦巡回法庭作出判决。在七年的官司之后,本案此时已经归结为一个问题: Google 使用 37 行 Java API 的行为是否侵犯甲骨文的版权?
软件版权是个棘手的问题。如果争议的对象是音乐、电影、文学作品、绘画,甚至是印度瑜伽,判断是否抄袭都很容易。相反,软件版权却到很晚才以「文字作品」的形式被硬塞进原 1976 年《版权法》的 102(a) 节。
版权本意只保护独创性作品,其用途和功能则在所不问。因此,任何事物的功能性部分——人体模型、会计账簿、电脑程序菜单——都被排除在版权保护之外。
代码到底是有用的工具,还是一种独创性表达呢?从代码「表达含义」的层面看,它确实如艺术作品一样可以主张版权保护。想想那些嘴边挂着「优雅的代码」「差劲的代码」的程序员就能明白。但当代码被执行起来,用于操作机器人手臂拾起并拧紧螺丝时,似乎又完全是功能性的,这种东西因此也就不能以版权处理。
你没法给一个小便器申请版权,但小便器的塑像或许就可以申请。而代码,正如杜尚的著名作品一样,身兼两种属性。
「你会发现法院已经在这个问题上纠结了几十年,」康奈尔技术学院法学教授 James Grimmelmann 说,他曾经在微软当过程序员。「事实证明,要把软件切分成功能性或非功能性的部分是很难的,」他说,「这需要对软件内部的功能和含义有非常细致的理解。」
甲骨文诉 Google 案涉及的是软件的一个特定组成部分:程序编程界面(Application Programming Interface, API)。
API 是一组定义完整的交互,一种快速访问服务、库和其他功能的捷径。API 一直被比作包含了单词及其定义的词典,但 Public Knowledge(译注:华盛顿一家致力于知识产权、开放互联网等问题的非盈利公益组织)的一位高级律师 John Bergmayer 说,它们更类似于代词或习语。要说出语法正确的英语,你没必要懂得习语;但正如许多以英语为第二语言的学生所知,如果不懂习语,交流就会太花时间。
习语有时是一种俏皮的表达方式;但在特定的一群人中,习语用得越多,就越是完全成为一种简略的说话方式,用于省去详述所需的更多时间。类似地,API 也经常是常用或繁杂代码的凝练。
这正是甲骨文诉 Google 案的核心问题。《版权法》的 102(b) 段将「一切操作的概念、过程、程序、机制和方法」排除于版权保护之外。API 是操作的过程、机制或方法吗?或者,它是版权所保护的独创性表达吗?
Google 最初创造 Android 时,决定让它兼容 Java 这门流行的编程语言。用上了 Java, Android 就能利用现有的开发者社区,甚至可能利用他们现成的代码。任何人都可以用 Java 写程序,但 Java 语言的开发者 Sun 微系统公司牢牢把控着 Java 标准版(Java Standard Edition)和移动版(Java Mobile Edition),它们分别用来将 Java 代码部署在桌面电脑和手机上。
在与 Java 的授权谈判破裂后, Google 的一群工程师另起炉灶实现了 Java SE——这意味着一个拿不到源代码的团队以逆向工程的方式获取了代码。甲骨文在 2010 年收购了 Sun,几个月后,就以 Android 侵权为由起诉了 Google 。
Google 对 Java API 的重新实现几乎完全是从头来过的。但它与 Java SE 的 API 在声明代码——用来指明代码其余组成部分名称的代码——上是相同的。不仅如此,Google 实现方案的结构、排序和组织也与 Java SE 很类似。
这就要说到那著名的九行代码 rangeCheck 了。这段代码是被 Joshua Bloch 写进 Android 的;令人生疑的是,他之前在 Sun 微系统公司工作过,并且写出了 Java API 的很多部分。(Alsup 法官后来裁判称这只是个不幸的巧合。Bloch 在离开 Sun 加入 Google 后又继续为 Java 的开源实现 OpenJDK 贡献过代码,他的代码同时出现在 Android 和 Java SE 中是无意之举。)
为了和 Java 兼容,对特定 API 的特定调用必须在外观上相同。例如,在一组数中找出最大值的方法被命名为一目了然的 java.lang.Math.max。甲骨文主张 Google 本可以把名字换成 java.lang.Arith.larger。
Google 则主张,Java API 就好比是 QWERTY 的键盘布局,键盘确实可以换一种布局方式,但制造商必须生产 QWERTY 布局的键盘,因为人们已经习惯了。
编程语言是建立在其他语言的基础之上的,这就意味着其 API 看起来也很类似。Java 的正则表达式 API 是对 Perl 5 语言的重新实现,其字符串格式 API 则是对 C 语言的重新实现。
这正是程序员们对甲骨文诉 Google 案感到气愤的原因之一:阻止 Google 做一件别人都在做的事,是毫无道理的。
软件开发者的共识是,甲骨文错了,API 的本意就是拿来用的,阻止它们用途的行为违背了其本意。
的确,连甲骨文也很难坚持自己的立场。2015 年,甲骨文的一名公司证人在证词中说 Java API 和免费使用的 Java 语言是「不可分割」的。一顿午饭过后,他汗流浃背地收回了这段话。
2012 年,当甲骨文诉 Google 第一次开庭时,陪审团支持了 Google 的所有专利权主张,但版权问题则被分为两个部分。首先,甲骨文所主张的 API 部分能否被授予版权?如果能,Google 的行为是否构成合理使用?前一个问题取决于 Alsup 法官,后一个问题则由陪审团判断。
对于 Google 使用 Java API 的行为是不是合理使用,陪审团犹豫不决。但这似乎并不重要,因为 Alsup 法官判定甲骨文对其宣称的代码及其实现方法的结构、排序和组织并无版权。Google 没有侵权,因为它无权可侵。理由是,Alsup 法官总结道,API 实现代码的结构、排序和组织在本质上是功能性而不是独创性的。
在这样一个证人和律师费力解释 API,将其比作文件柜、电插座等一系列事物的案件中,Alsup 法官意见之细致和专业独树一帜。这份意见整页整页地描述了代码的运作方式,从源代码和目标代码的区别说起,再说到类、声明、头部、子程序、方法、接口、数据包,甚至还包括了代码实例。
很难想象一个没有 Alsup 这样长年编程经验的法官能给出这样一份意见。显然,在对 rangeCheck 这著名的九段代码做出判决的过程中,Alsup 的背景帮了他的忙。
「这种东西我用 QuickBASIC 写过好多遍了,」离那次庭审五年后,他说。(Alsup 法官用的是微软的 QuickBASIC,这是用于写 BASIC 语言的一个集成开发环境和编译器。)「如果你要我用 QuickBASIC 解决这个问题,我保证可以一个小时后带着一个能用的 QuickBASIC 模型来见你。」
交流过程中,Alsup 法官谈起甲骨文诉 Google 案很谨慎,因为联邦巡回法庭尚未作出第二次上诉的判决。但他似乎仍对甲骨文把抄袭 rangeCheck 代码称作「重大问题」感到恼火。他作为程序员的那一面或许多少对 rangeCheck 作者遇上的麻烦有些同情。Alsup 对此事感到十分困扰,以至于在法官意见中花了整整一节来阐述。「甲骨文过度强调了这段同时在 Android 和 Java 中出现的代码。该情形完全事出无心,却被甲骨文夸大了,故本庭将在下文阐述认定的事实,以便上诉庭参考。」(这九行代码再也没有在本案中被提起。)
如 Grimmelmann 所说,Alsup 在 2013 年对甲骨文诉 Google 案的意见,是司法机关有关软件版权问题「最详尽、最困难、最细致入微的一次参与」。他在自己的知产课堂上讲解甲骨文诉 Google 案。「这是对 Java 运行方式、源代码中不同部分的框架阐述。这已经不仅仅是就案判案了。这是一篇有教学意义的文章。」
多亏 Alsup 的意见之细致,他对 Java 和软件开发的理解有很大一部分被保留在了判例法中,将被传给年轻的未来法律人。这或许是这位程序员法官所做标志性判决最深远的印记——因为判决本身已经被彻底推翻了。
Alsup 在 2013 年对甲骨文诉 Google 案的判决几乎立刻被上诉。2014 年,联邦巡回上诉法庭作出了令人震惊的相反判决,该判决引发恼火的版权法学者写出了连篇累牍的法律评论文章。上诉法庭在判决中写道,甲骨文「对 Google 抄袭的 7000 行代码有无限多种选择和排列方式。」甲骨文不一定要把那个函数称作 java.lang.Math.max。它的名字「想有多少就能有多少」,比如 Math.maximum 或者 Arith.larger。
这说法听起来像是对代码一无所知。(在意见的另一部分中,法庭称,「 Google 完全可以开发自己的 API 包,然后『游说』程序员接纳它们。」)
Google 将联邦巡回法庭的判决上诉到最高法院,但最高法院拒绝审理本案。案件被发回到最初审理的地方:由旧金山的 Alsup 法官再次进行陪审团审理。2016 年 5 月 26 日,陪审团判决 Google 构成合理使用。
Google 或许胜诉了,但案件不但仍然悬而未决——甲骨文再次上诉到联邦巡回法院——其长期现实影响也尚不可知。何时可以、何时又不可以照搬声明代码,或是 API 的结构、序列、组织?陪审团的合理使用判决并未给出任何指导方针。
无论 Alsup 基于自己长年的 BASIC 编程经验,写出了多么有洞见、清晰的意见,它们都被上诉法庭彻底推翻、消失不见了。
(Sarah Jeong 摄 / The Verge)
Alsup 毫不羞于谈论自己的编程技能:「我确实觉得自己是个好程序员,你看我写的程序就知道了——因为我全都是自学的——这些 QuickBASIC 程序里有些很巧思的编程手法。」他补充说,「只可惜不是 Java。」
这位法官从 1985 年得到第一台电脑起就开始编程:那是一台旧型 IBM,后来被打发到他在优胜美地的牧场里的牛棚,一个黑乎乎、灰蒙蒙的角落里。这机器用的是 5.25 英寸软盘,没有硬盘。你可以买到带一个软驱的版本,也可以买到有两个软驱的版本。他和妻子买了豪华双驱动器版。
这台电脑随附了两本书,一本讲的是 DOS 操作系统,另一本讲的是 BASIC 语言。「有一次,我看到了那本 BASIC 书,决定学习一下。」他完全靠这本书自学,在他的回忆中,这本书「相当开门见山」。
他最开始写的程序是演示性的,用来做简单的算术。接着,他越写越复杂:一个可以算 21 点,一个用来玩七张牌扑克。这些程序都存在一张 5.25 寸软盘上,但 1988 年被他两岁的儿子用订书机弄坏了。
「他可自豪了,」Alsup 伤感地说。
(Alsup 的短波电台传送预测程序。Sarah Jeong 摄 / The Verge)
在写过的所有程序中,他最自豪的是一个短波传送预测器。他有理由为此自豪:这是一个相当复杂的软件,有多个依赖程序和复古的图形界面,显示着一幅根据你选择的起始位置显示的等距方位投影地图,辅之以展示太阳移动轨迹的彩色线条,以及 Alsup 从地图册上人工采编的详尽数据库。(他对自己在业余时间输入这些数据所花的大量时间十分自豪,这横跨他被美国总统任命为终身法官前后。)
通过计算给定两点的方位,这个程序能预测将他的火腿电台信号对准世界各地传送的最佳时刻,甚至能为他从全球选择的几个关键位置生成数据表格。
即使在他刚开始编程的 1995 年,市场上已经发售了类似的程序。但他说,「我就是想看看自己能不能做到,从中获得乐趣。」
他用自己的程序校准 Yaesu Mk V Field 收音机,和世界各地的朋友聊天,包括他的朋友「小」Feild,以及结交的远在日本和新西兰的操作员朋友。他至今还每个月花两小时操作电台,大多数都是在 Sierra 山脚下。他的呼号是 N6XMW,或者按他的说法,「November Six X-Ray Mike Whiskey」。
法官花了差不多一个小时向我解释这个程序,讲到了每一种可能改变短波传送的不同输入,以及背后的原理。随着他耐心解释起太阳波动、K 指标、电离层,这次采访变成了一次即兴物理讲座。
预测电台传送除了要考虑日期和时间,还要考虑大量持续波动、根据你的位置和目的地而变的变量。
当他输入这些变量后,敲击回车,电脑就开始了运算。「看,」他说。「它在思考呢。」
的确,电脑屏幕现在几乎一片空白,上面只有几个字,「正在思考……」
在这段长长的演示中,程序的确出过一次故障:一个依赖程序出错了,不知为何不让我在位置中输入纽约。「差劲,」他对自己嘟囔着。「好吧…… 是我弄糟了,」他对我承认。我们决定试试另外的位置,结果程序此后运行得都很流畅。
几十年间,Alsup 几乎是完全独自在编程,用书本自学、人工采编数据库。这与当代软件开发者的典型做法截然不同,后者的工作流程和习惯往往涉及一个更大的社区。Alsup 不用 Google 搜答案,不逛 StackExchange,也不用现成的库。他的每行代码都是从头写起的。
实际上,Alsup 和当代开发者的文化和社区最近的一次接触,似乎就是因甲骨文诉 Google 案引发的。
在第二次审理的一段著名对话中,前 Sun 公司 CEO Jonathan Schwartz 试图向陪审团解释免费软件和开源软件。他先讲了 GNU,一个整合在 Linux 中的项目,可以粗略描述为一个操作系统加上相关的软件套件。
「GNU 指的是什么?」Alsup 打断他的话问道。
「GNU is Not Unix,」Schwartz 说。
「G 指的是 GNU?」
Schwartz 说是的。
「这根本说不通,」法官说。法庭中响起一些笑声。但这远比不上事后 Twitter 上的骚动——全世界成百上千的技术宅都忍俊不禁。(我后来甚至看到一幅描绘这番对话的网络漫画。)
GNU 是一个递归式缩写,意思是它自己在全称中提到自己,无限循环——这在电脑程序中是常见的做法。程序中有大把的递归缩写,包括 PHP(PHP: Hypertext Processor)、cURL(cURL URL Request Library),以及民间戏传的 Bing 搜索引擎(Bing Is Not Google)。这都是些不怀好意的笑话,是一种封闭文化戏弄外行的标志,它根本没想过得跟法庭解释自己的含义。
而即便 Alsup 写了这么多年程序,他也直到那时才知道 GNU 指的是什么。我问起这件事时,他显得有些懊恼。显然,他的一个工程师朋友(他的远足野��伙伴之一)拿他对 GNU 的评论寻开心了。「我以前不知道这个定义是递归的,」Alsup 说。「当别人解释给我听的时候,我想的是,『好吧,挺可爱的。』」
电脑编程近年来的变动让 Alsup 不那么容易坚持自己的爱好了。几年前,他试图学习 Python,但最终搁置一边,因为他「太忙了」,或许是因为身为联邦法官的日常工作。微软后来不再在 Windows 中同捆 QuickBASIC,这让 Alsup 没法在新电脑上跑自己写的程序。
这件事本身就很有诗意:一位法官审理着有关兼容性的要案,现在自己成为了兼容性问题的受害者。
(Sarah Jeong 摄 / The Verge)
十二月,Alsup 将审理 Waymo 诉 Uber 案,该案涉及数十亿美元,Uber 被诉盗窃 Alphabet 子公司的汽车自动驾驶技术知识产权。与甲骨文诉 Google 案不同,Waymo 案并不触及知识产权法的核心原则,但其结果将永远改变这个行业的面貌。
在我们的对话中,Alsup 非常小心地回避了还在进行中的 Waymo 案。但他对围绕着这个案子的科学原理兴趣浓厚。这一回,跟 Waymo 诉 Uber 案最相关的大概是他对摄影和光学的兴趣。三月份,Alsup 要求原被告各列举关于 LIDAR 这一本案争议的自动驾驶车激光检测系统的一本书或一篇论文,这样他就可以找来看。但他也在一则法庭命令中严厉告诫双方不要看轻他。
请注意本庭已经熟知有关透镜的基本光线和光学原理,如焦距,焦点(即物体在透镜后光屏上聚焦的位置)与物距呈非线性函数关系,以及镜片在聚焦和投影上的用途。
  因此,最有用的材料应是关于在自动驾驶汽车上适用 LIDAR 的论文,包括在透镜后如何放置发光二极管以获取最佳整体效果,以及如何用单镜头同时向外投射光线并将传入的反射光线聚焦。(当然,也包括本案的专利。)
Alsup 还要求双方律师就 LIDAR 进行讲解。他在很多案件中都如此要求。他很享受这些讲解,他告诉我,而且听得很认真。然而,他还是怀疑在很多案件中,他对技术的理解比律师还要深入。
他记得有很多次怀���律师试图压制他,结果都栽在他的工程师背景和毒舌上。跟所有极客一样,他对任何有混淆技术之虞的行为都心怀不满。
在大约十年前的一个涉及 FastTrak(湾区一种过桥收费自动追踪设备)专利的案子中,双方就如何解释该专利的技术方面达成了一个有法律约束力的协议。但 Alsup 法官没有盲目认同这番约定,而是自己钻研了专利,得出的结论是它们的约定毫无意义。
「我知道那个技术是什么,也告诉了它们。然后我写了一道命令,说明我拒绝接受这个约定,以及真正含义应该是什么。他们后来都认同了我的观点。」
没过多久,双方和解结案。
「我猜他们会觉得法官疯了。」
在 Waymo 案中,Alsup 对律师的不留情面展现得淋漓尽致。这或许是源于他对 Alphabet 和 Uber 烧了数百万美元雇佣业内最好的律师的行为极不赞同。过去,他从不掩饰对公司在法庭上烧钱行为的厌恶。在甲骨文诉 Google 案的一场预审中,他打断说,「你知道你们争论一个账单会耽误我处理多少社保请求吗?」
他还特别在 Waymo 案中动用媒体来审查两家公司在法庭上的行为,要求记者留意哪一方在陪审团决策过程中试图用技术障碍摆脱陪审员。与此同时,Alphabet 甚至 Lyft 都要求部分审理过程不向媒体开放,称这可能将值钱的交易机密公之于众。
此后,一群媒体(包括 The Verge 的母公司 Vox Media)介入本案,要求保持庭审开放。虽然案件的部分环节——确实涉及一定数量交易机密的部分——将维持保密,Alsup 仍坚持媒体有尽可能大的知情权。
一次庭审中,Uber 的律师要求闭门开庭,让审理情况对公众封闭。但庭审一开始,Alsup 法官就认定这是越权行为,是出于难堪而拿秘密当借口,而不是出于合法的理由。
「听着,别再跟我玩这套了,」他说。「这样你们双方都会上负面报道,我可阻止不了。公众有知情权,」随后就是 Alsup 招牌的转折,「实际上,这不是有全程笔录吗?我会把它公开。」
(2017 年 3 月 26 日 Waymo 诉 Uber 案笔录节选)
1999 年起,Alsup 就开始将他的案件分给两个书记员,他分别称作刑事部和知产部。放不进这两类的案件,工作就平均分配。
这些日子,他往往为知产部寻找一些有理工科(STEM)背景的书记员。这么做不是必要的,但能帮上忙。审理甲骨文诉 Google 案期间的知产部书记员 Bill Toth 没有理工科背景,但他告诉我,法官特地要求他在准备上岗时修一门计算机科学课程。
当我向 Alsup 求证此事时,他微微一笑——他不记得「强迫」Toth 选修任何课程——但他承认有时会提前告诉书记员会碰上什么类型的案子,以及提前上什么课会派得上用场。
Bill Toth 现在在为联邦巡回法庭的 Sharon Prost 首席法官做书记员。当然,他不能再处理甲骨文诉 Google 案的工作;这会构成利益冲突。
但 Toth 属于新生代法律人的一份子,他们将逐渐代表法律职业中的更大比重。尽管 Toth 在法律之前主修宗教,他却是个彻头彻尾的程序员。「我写些代码来自娱自乐,」Toth 告诉我。
「过去三四年我都参加了 Google Code Jam 竞赛(不是特别当真),写的是 Java。我记得除了一次都过了资质轮,而且每次参加肯定都学到很多。」除了 Alsup 让他上的计算机科学课,在给 Alsup 当书记员之前,他已经学了 HTML、Javascript、CSS、BASIC,以及「一点点」Python 和 Perl。Toth 不愿意说自己的编程技能是否在甲骨文诉 Google 案的工作中发挥了作用,但我很难想象这会没有用。
科技社群固执地相信,法律永远不会理解自己在做什么。显然,上级法院对甲骨文诉 Google 案的判决无助于驱散这种观念。然而,Alsup 的存在本身就是对这种观念的挑战:一位 72 岁的前工科生,几十年来一直独自兴高采烈地玩转 BASIC,摆弄电台和相机,将自己所知所学教给书记员和各路记者。
在甲骨文案意见中,Alsup 向联邦巡回法庭解释软件概念时的耐心和细致,一如向我解释电离层时那样。他的解释是如此精准、专业,巡回法庭因而不得不对软件开发投入更多关注。无论巡回法庭最终判决如何,Alsup 对软件理解的很大部分在上诉判例法中得以保留。
他的观点如今在法学院的知识产权课堂上被教授。随着科技领域吸引到越来越多的资金,专攻于此的法律人不断涌现,以填补需求。他们中的很多人将会在培养过程中接触到 Alsup 的细致教导——大多数是通过书本,少数的幸运者还能亲耳聆教。
在我结束采访、离开法院的几个小时后,Alsup 发给我一封题为《找到 bug 了》的邮件,告诉我他找出了演示短波电台传送程序时的故障所在。「我之前不记得为什么把一行关键代码注释掉了。现在我让它重新生效就没问题了,」他写道。
我回想起在他办公室里的最后一段时间。那时我正把录音笔和笔记本收进包里,喊了他一声「极客法官」。结果,他看起来很困惑,问我,「那是件好事儿吗?」
听到我肯定地说是,他报之以咧嘴一笑。「在我那会儿,极客可不是什么你会想当的角色。」
ONES Piece 翻译计划
星辰大海之下有太多被埋没的宝藏,让我们好好擦亮了给你看……ONES Piece 是一个由 ONES Ventures 发起的非营利翻译计划,聚焦科技、创投和商业。如有优质内容推荐或想要加入计划,请发邮件至 [email protected]
邮箱
#欢迎关注爱范儿官方微信公众号:爱范儿(微信号:ifanr),更多精彩内容第一时间为您奉上。
爱范儿 | 原文链接 · 查看评论 · 新浪微博
以上内容由IFTTT自动发布,原文地址:http://www.ifanr.com/935880?utm_source=rss&utm_medium=rss&utm_campaign=
0 notes
ixtech · 8 years ago
Text
想进Google?这里有一份Google面试流程和攻略
作者 |  Ting Fan
专栏 | 九章算法,高阶IT求职教育平台,官网www.jiuzhang.com
Google的招聘流程涉及两种面试。在每一轮面试中,Google都会从面试官那里收集反馈,然后确定后续步骤。
Part 1 面试流程
1、第一阶段:电面(Phone Screen)
电面的面试官很有可能是你以后的同事或经理。
如果你申请的是软件工程相关职位,电面将持续 30 到 60 分钟。回答编码相关问题时,你需要一边在与面试官共享的 Google Doc 上编写代码,一边清晰地阐述你的思路。建议你使用耳机或扬声器,以便你能够自由输入相关内容。
电面会问到数据结构和算法。使用你最擅长的编程语言写 20-30 行代码。根据如下步骤做编码练习(注意你的代码风格,参考文章:《Google 官方代码风格指南》):
你会被问到一个开放式的问题。面试官会据此问一些问题,然后制定一些要求。
用一个算法解释这个问题。
将其转换为可行的代码。 (提示:因为有时间限制,不要想着一下子写出完美的代码,写下你所想到的,稍后再进行修改,还要确保考虑了边界情况和运行问题。)
优化代码,测试用例并发现错误。
对于所有其他职位,电面将持续 30 到 45 分钟。请准备好回答涵盖职位相关知识的行为问题、假设问题或案例式问题。
2、第二阶段:现场面试(Onsite)
一般情况下,会有 4 位 Google 员工(一些可能成为你以后的同事,还有一些是跨职能部门的员工)面试你,每个人的面试时间大约为 30-45 分钟。
对于软件工程职位的应聘者,面试官希望了解你的编码技能和技术领域的专业知识(其中包括工具或编程语言,以及有关数据结构和算法等主题的一般知识)。面试官通常会在这种讨论中反复提及与此相关的问题,就像讨论实际工作中遇到的问题一样,因为他们喜欢激发彼此的思想碰撞火花,进而了解不同的方法。因此,请准备好深入探讨你的解决方案。超越自我界限,找到最佳答案,这很可能就代表了您的工作方式。
工程职位以外的应聘者将有机会从 4 个不同的方面突出展示自己的优势:
一般认知能力:
面试官会提出一些开放式问题,以便了解你如何着手处理问题和解决问题。这些问题没有标准答案,因此,他们最看重的是,你是否具备一定的能力,可以清晰地阐明你的思路以及你如何利用数据做出明智决策。
领导能力:
准备好谈一谈你曾如何利用自己的沟通和决策能力调动他人积极性。这种案例可以是你在工作期间或单位的领导岗位晋升经历,也可以是你带领团队取得成功(即便在你并未正式成为领导者的情况下)的经历。
职位相关知识:
面试官希望可以了解你如何将自己的个人优势与经验相结合以带来积极的影响。面试官不仅想知道你目前能做出的贡献,还要了解你打算如何提升自身能力以便挑战不同的职位,甚至包括目前尚不存在的职位。
Google 精神:
分享你如何独立工作以及如何与团队协作,如何帮助他人,如何在迷茫中找到方向,以及如何激励自己居安思危、不断进步。
在整个面试过程中,你可以放心大胆地请面试官明确说明面试问题,以确保你完全理解所问的问题。你也可以畅所欲言,面试面试官们,询问有关工作、团队和文化的问题,这样做可以帮助你确定相应职位是否适合你。
Part 2 如何准备
1、适用于所有职位的面试
预测可能遇到的面试问题:
你可以预测到面试官会向您提出的 90% 的面试问题。例如“为什么想要这份工作?”、“你曾解决过什么棘手的问题?”等等。如果你实在想不出来,可以阅读《硅谷程序员面试宝典》,将你认为最有可能被问到的前 20 个问题写下来。
计划:
针对你列表上的每个问题写下答案。这有助于你牢记相关问题及答案,以便在需要时能够不假思索地说出来,这一点至关重要。
制定备用方案:
实际上,对于每个问题,建议你写下 3 个答案。为什么要写 3 个呢?对于每个问题,你都需要另外准备一个同样可行的不同答案,因为第一个面试官有可能不喜欢你讲述的案例,这时,你就得寄希望于下一位面试官听听你的另一个案例,或许他/她能因此成为你的支持者。
说出想法:
面试官想了解你的想法,在面试中说出你的思考过程和决策。 请记住,面试过程中,不仅评估你的技术能力,更是要评估你如何处理问题并尝试解决问题。 和面试官明确地说明和检查他给出的假设,确保它们是合理。
用数据说话:
在回答每个问题时,你都需要通过具体案例来说明自己具备问题中所要求的能力。例如,如果你被问到“你是如何履行领导职责的?”这样的问题,你应该回答:“我是一个具有协作能力/决策能力/诸如此类任何能力的领导,我来给你讲一下当我在…”
遇到问题询问:
面试题可能是有问题的,面试官故意不提,来深入了解你在技术难题中所看重的范畴和信息。 他们是想看看你是如何参与解决问题的。 一定要谈谈你的思考过程,如果遇到疑问,随时提问。
优化:
想想如何改进你提供的解决方案。在许多情况下,你一开始的解决方案可能需要一些细化和进一步的解释。 如果有必要,从暴力解决方案开始,改进它 - 要让面试官知道你在做什么以及为什么。
练习:
每个人都可以通过不断练习获得进步。大声复述你的面试答案,直到你可以简明扼要地讲述每个案例。
2、适用于软件工程和技术职位的面试
编码实践:
你可以在 LintCode、CodeLab、Quora 和 Stack Overflow 等网站上找到一些编码问题示例。美国大公司面试真题训练和 Google Mock Interview 也值得一做。面试会要求手写,所以请在纸张或白板上练习编写代码。一定要测试你的代码,并确保它易读而且没有错误。不要纠结于小的语法错误,比如对于给定的方法用哪个子串,直接选择一个,让面试官知道就可以了。
编码:
至少擅长一种编程语言,最好是C ++,Java,Python,Go或C。如果你擅长API、面向对象设计和编程,知道如何测试代码,以及知道如何处理边界情况更好。请注意:面试注重的是概念理解而不是记忆。
算法:
掌握用自下而上和自顶向下的算法解决问题。知道算法的复杂性,以及如何优化/改变算法。熟悉解决Google问题的算法:排序,分治法,动态规划,贪心,递归或有关数据结构的算法。知道Big-O符号(例如运行时间),并准备好像Dijkstra和A *这样的复杂算法。在编写代码之前,建议你讨论或阐述你所想到的算法。
排序:
熟悉常见的排序类型以及它们有效的输入数据类型。考虑运行时间和空间。例如,在特殊情况下,插入排序���基数排序比通用的快速排序、归并排序、堆排序答案要好得多。
数据结构:
研究尽可能多的数据结构。最常使用的数据结构是数组,链表,堆栈,队列,哈希集合,哈希图,哈希表,字典树,树和二叉树,堆和图。了解内部的数据结构,以及哪些算法倾向于和哪个数据结构一起使用。
数学:
一些面试官会提一些基本的离散数学问题。尤其在Google,因为Google的工作经常会接触计数问题、概率问题和其他离散Math 101情况。在面试之前花上一些时间,记住基本概率理论和组合的基本要素。熟悉n选择问题和类似的问题。
图:
考虑一个问题是否可以应用于距离、搜索、连接、循环检测等图形算法中。有三种图形表示方法:对象和指针、矩阵、邻接列表,你需要熟悉每个方法及其利弊。掌握基本图遍历算法、广度优先搜索和深度优先搜索。了解它们的复杂度,了解什么情况该用哪个,以及如何在实际代码中实现它们。
递归:
许多编码问题涉及递归的思想和用递归编码给出解决方案。对于可以用迭代的方法解决的问题,用递归找到更优的解决方案。
Part 3 其他问题
着装:
大部分面试对着装都没有特定的要求,但招聘人员会告知你如何着装最得体。如果你不确定哪种风格适合自己,那就做你自己,穿你认为舒适的衣服就好。
如何组织面试答案:
回答问题时,请务必说明你是如何得出解决方案的,因此,你可以想到什么就说什么。
做准备工作时要考虑的有帮助的问题:
独立工作以及参与团队协作时,你如何让自己的能力得到充分发挥?你在求学时和职场中遇到过哪些挑战?你是如何战胜这些挑战的?你有哪些技能和经验可作为你申请本职位的优势,为什么?
如果你没有理解面试问题:
可以请面试官明确说明,且回答问题时可视需要从容作答。
via36氪
0 notes
lupbiy · 8 years ago
Text
高性能服务器架构思路,不仅是思路
在服务器端程序开发领域,性能问题一直是备受关注的重点。业界有大量的框架、组件、类库都是以性能为卖点而广为人知。然而,服务器端程序在性能问题上应该有何种基本思路,这个却很少被这些项目的文档提及。本文正式希望介绍服务器端解决性能问题的基本策略和经典实践,并分为几个部分来说明:
1. 缓存策略的概念和实例
2.缓存策略的难点:不同特点的缓存数据的清理机制
3.分布策略的概念和实例
4.分布策略的难点:共享数据安全性与代码复杂度的平衡
缓存
缓存策略的概念
我们提到服务器端性能问题的时候,往往会混淆不清。因为当我们访问一个服务器时,出现服务卡住不能得到数据,就会认为是“性能问题”。但是实际上这个性能问题可能是有不同的原因,表现出来都是针对客户请求的延迟很长甚至中断。我们来看看这些原因有哪些:第一个是所谓并发数不足,也就是同时请求的客户过多,导致超过容纳能力的客户被拒绝服务,这种情况往往会因为服务器内存耗尽而导致的;第二个是处理延迟过长,也就是有一些客户的请求处理时间已经超过用户可以忍受的长度,这种情况常常表现为CPU占用满额100%。
我们在服务器开发的时候,最常用到的有下面这几种硬件:CPU、内存、磁盘、网卡。其中CPU是代表计算机处理时间的,硬盘的空间一般很大,主要是读写磁盘会带来比较大的处理延迟,而内存、网卡则是受存储、带宽的容量限制的。所以当我们的服务器出现性能问题的时候,就是这几个硬件某一个甚至几个都出现负荷占满的情况。这四个硬件的资源一般可以抽象成两类:一类是时间资源,比如CPU和磁盘读写;一类是空间资源,比如内存和网卡带宽。所以当我们的服务器出现性能问题,有一个最基本的思路,就是——时间空间转换。我们可以举几个例子来说明这个问题。
[水坝就是用水库空间来换流量时间的例子]
当我们访问一个WEB的网站的时候,输入的URL地址会被服务器变成对磁盘上某个文件的读取。如果有大量的用户访问这个网站,每次的请求都会造成对磁盘的读操作,可能会让磁盘不堪重负,导致无法即时读取到文件内容。但是如果我们写的程序,会把读取过一次的文件内容,长时间的保存在内存中,当有另外一个对同样文件的读取时,就直接从内存中把数据返回给客户端,就无需去让磁盘读取了。由于用户访问的文件往往很集中,所以大量的请求可能都能从内存中找到保存的副本,这样就能大大提高服务器能承载的访问量了。这种做法,就是用内存的空间,换取了磁盘的读写时间,属于用空间换时间的策略。
[方便面预先缓存了大量的烹饪操作]
举另外一个例子:我们写一个网络游戏的服务器端程序,通过读写数据库来提供玩家资料存档。如果有大量玩家进入这个服务器,必定有很多玩家的数据资料变化,比如升级、获得武器等等,这些通过读写数据库来实现的操作,可能会让数据库进程负荷过重,导致玩家无法即时完成游戏操作。我们会发现游戏中的读操作,大部分都是针是对一些静态数据的,比如游戏中的关卡数据、武器道具的具体信息;而很多写操作,实际上是会覆盖的,比如我的经验值,可能每打一个怪都会增加几十点,但是最后记录的只是最终的一个经验值,而不会记录下打怪的每个过程。所以我们也可以使用时空转换的策略来提供性能:我们可以用内存,把那些游戏中的静态数据,都一次性读取并保存起来,这样每次读这些数据,都和数据库无关了;而玩家的资料数据,则不是每次变化都去写数据库,而是先在内存中保持一个玩家数据的副本,所有的写操作都先去写内存中的结构,然后定期再由服务器主动写回到数据库中,这样可以把多次的写数据库操作变成一次写操作,也能节省很多写数据库的消耗。这种做法也是用空间换时间的策略。
[拼装家具很省运输空间,但是安装很费时]
最后说说用时间换空间的例子:假设我们要开发一个企业通讯录的数据存储系统,客户要求我们能保存下通讯录的每次新增、修改、删除操作,也就是这个数据的所有变更历史,以便可以让数据回退到任何一个过去的时间点。那么我们最简单的做法,就是这个数据在任何变化的时候,都拷贝一份副本。但是这样会非常的浪费磁盘空间,因为这个数据本身变化的部分可能只有很小一部分,但是要拷贝的副本可能很大。这种情况下,我们就可以在每次数据变化的时候,都记下一条记录,内容就是数据变化的情况:插入了一条内容是某某的联系方法、删除了一条某某的联系方法……,这样我们记录的数据,仅仅就是变化的部分,而不需要拷贝很多份副本。当我们需要恢复到任何一个时间点的时候,只需要按这些记录依次对数据修改一遍,直到指定的时间点的记录即可。这个恢复的时间可能会有点长,但是却可以大大节省存储空间。这就是用CPU的时间来换磁盘的存储空间的策略。我们现在常见的MySQL InnoDB日志型数据表,以及SVN源代码存储,都是使用这种策略的。
另外,我们的Web服务器,在发送HTML文件内容的时候,往往也会先用ZIP压缩,然后发送给浏览器,浏览器收到后要先解压,然后才能显示,这个也是用服务器和客户端的CPU时间,来换取网络带宽的空间。
在我们的计算机体系中,缓存的思路几乎无处不在,比如我们的CPU里面就有1级缓存、2级缓存,他们就是为了用这些快速的存储空间,换取对内存这种相对比较慢的存储空间的等待时间。我们的显示卡里面也带有大容量的缓存,他们是用来存储显示图形的运算结果的。
[通往大空间的郊区路上容易交通堵塞]
缓存的本质,除了让“已经处理过的数据,不需要重复处理”以外,还有“以快速的数据存储读写,代替较慢速的存储读写”的策略。我们在选择缓存策略进行时空转换的时候,必须明确我们要转换的时间和空间���否合理,是否能达到效果。比如早期有一些人会把WEB文件缓存在分布式磁盘上(例如NFS),但是由于通过网络访问磁盘本身就是一个比较慢的操作,而且还会占用可能就不充裕的网络带宽空间,导致性能可能变得更慢。
在设计缓存机制的时候,我们还容易碰到另外一个风险,就是对缓存数据的编程处理问题。如果我们要缓存的数据,并不是完全无需处理直接读写的,而是需要读入内存后,以某种语言的结构体或者对象来处理的,这就需要涉及到“序列化”和“反序列化”的问题。如果我们采用直接拷贝内存的方式来缓存数据,当我们的这些数据需要跨进程、甚至跨语言访问的时候,会出现那些指针、ID、句柄数据的失效。因为在另外一个进程空间里,这些“标记型”的数据都是不存在的。因此我们需要更深入的对数据缓存的方法,我们可能会使用所谓深拷贝的方案,也就是跟着那些指针去找出目标内存的数据,一并拷贝。一些更现代的做法,则是使用所谓序列化方案来解决这个问题,也就是用一些明确定义了的“拷贝方法”来定义一个结构体,然后用户就能明确的知道这个数据会被拷贝,直接取消了指针之类的内存地址数据的存在。比如著名的Protocol Buffer就能很方便的进行内存、磁盘、网络位置的缓存;现在我们常见的JSON,也被一些系统用来作为缓存的数据格式。
但是我们需要注意的是,缓存的数据和我们程序真正要操作的数据,往往是需要进行一些拷贝和运算的,这就是序列化和反序列化的过程,这个过程很快,也有可能很慢。所以我们在选择数据缓存结构的时候,必须要注意其转换时间,否则你缓存的效果可能被这些数据拷贝、转换消耗去很多,严重的甚至比不缓存更差。一般来说,缓存的数据越解决使用时的内存结构,其转换速度就越快,在这点上,Protocol Buffer采用TLV编码,就比不上直接memcpy的一个C结构体,但是比编码成纯文本的XML或者JSON要来的更快。因为编解码的过程往往要进行复杂的查表映射,列表结构等操作。
缓存策略的难点
虽然使用缓存思想似乎是一个很简单的事情,但是缓存机制却有一个核心的难点,就是——缓存清理。我们所说的缓存,都是保存一些数据,但是这些数据往往是会变化的,我们要针对这些变化,清理掉保存的“脏”数据,却可能不是那么容易。
首先我们来看看最简单的缓存数据——静态数据。这种数据往往在程序的运行时是不会变化的,比如Web服务器内存中缓存的HTML文件数据,就是这种。事实上,所有的不是由外部用户上传的数据,都属于这种“运行时静态数据”。一般来说,我们对这种数据,可以采用两种建立缓存的方法:一是程序一启动,就一股脑把所有的静态数据从文件或者数据库读入内存;二就是程序启动的时候并不加载静态数据,而是等有用户访问相关数据的时候,才去加载,这也就是所谓lazy load的做法。第一种方法编程比较简单,程序的内存启动后就稳定了,不太容易出现内存漏洞(如果加载的缓存太多,程序在启动后立刻会因内存不足而退出,比较容易发现问题);第二种方法程序启动很快,但要对缓存占用的空间有所限制或者规划,否则如果要缓存的数据太多,可能会耗尽内存,导致在线服务中断。
一般来说,静态数据是不会“脏”的,因为没有用户会去写缓存中的数据。但是在实际工作中,我们的在线服务往往会需要“立刻”变更一些缓存数据。比如在门户网站上发布了一条新闻,我们会希望立刻让所有访问的用户都看到。按最简单的做法,我们一般只要重启一下服务器进程,内存中的缓存就会消失了。对于静态缓存的变化频率非常低的业务,这样是可以的,但是如果是新闻网站,就不能每隔几分钟就重启一下WEB服务器进程,这样会影响大量在线用户的访问。常见的解决这类问题有两种处理策略:
第一种是使用控制命令。简单来说,就是在服务器进程上,开通一个实时的命令端口,我们可以通过网络数据包(如UDP包),或者Linux系统信号(如kill SIGUSR2进程号)之类的手段,发送一个命令消息给服务器进程,让进程开始清理缓存。这种清理可能执行的是最简单的“全部清理”,也有的可以细致一点的,让命令消息中带有“想清理的数据ID”这样的信息,比如我们发送给WEB服务器的清理消息网络包中会带一个字符串URL,表示要清理哪一个HTML文件的缓存。这种做法的好处是清理的操作很精准,可以明确的控制清理的时间和数据。但是缺点就是比较繁琐,手工去编写发送这种命令很烦人,所以一般我们会把清理缓存命令的工作,编写到上传静态数据的工具当中,比如结合到网站的内容发布系统中,一旦编辑提交了一篇新的新闻,发布系统的程序就自动的发送一个清理消息给WEB服务器。
第二种是使用字段判断逻辑。也就是服务器进程,会在每次读取缓存前,根据一些特征数据,快速的判断内存中的缓存和源数据内容,是否有不一致(是否脏)的地方,如果有不一致的地方,就自动清理这条数据的缓存。这种做法会消耗一部分CPU,但是就不需要人工去处理清理缓存的事情,自动化程度很高。现在我们的浏览器和WEB服务器之间,就有用这种机制:检查文件MD5;或者检查文件最后更新时间。具体的做法,就是每次浏览器发起对WEB服务器的请求时,除了发送URL给服务器外,还会发送一个缓存了此URL对应的文件内容的MD5校验串、或者是此文件在服务器上的“最后更新时间”(这个校验串和“最后更新时间”是第一次获的文件时一并从服务器获得的);服务器收到之后,就会把MD5校验串或者最后更新时间,和磁盘上的目标文件进行对比,如果是一致的,说明这个文件没有被修改过(缓存不是“脏”的),可以直接使用缓存。否则就会读取目标文件返回新的内容给浏览器。这种做法对于服务器性能是有一定消耗的,所以如果往往我们还会搭配其他的缓存清理机制来用,比如我们会在设置一个“超时检查”的机制:就是对于所有的缓存清理检查,我们都简单的看看缓存存在的时间是否“超时”了,如果超过了,才进行下一步的检查,这样就不用每次请求都去算MD5或者看最后更新时间了。但是这样就存在“超时”时间内缓存变脏的可能性。
[WEB服务器静态缓存例子]
  上面说了运行时静态的缓存清理,现在说说运行时变化的缓存数据。在服务器程序运行期间,如果用户和服务器之间的交互,导致了缓存的数据产生了变化,就是所谓“运行时变化缓存”。比如我们玩网络游戏,登录之后的角色数据就会从数据库里读出来,进入服务器的缓存(可能是堆内存或者memcached、共享内存),在我们不断进行游戏操作的时候,对应的角色数据就会产生修改的操作,这种缓存数据就是“运行时变化的缓存”。这种运行时变化的数据,有读和写两个方面的清理问题:由于缓存的数据会变化,如果另外一个进程从数据库读你的角色数据,就会发现和当前游戏里的数据不一致;如果服务器进程突然结束了,你在游戏里升级,或者捡道具的数据可能会从内存缓存中消失,导致你白忙活了半天,这就是没有回写(缓存写操作的清理)导致的问题。这种情况在电子商务领域也很常见,最典型的就是火车票网上购买的系统,火车票数据缓存在内存必须有合适的清理机制,否则让两个买了同一张票就麻烦了,但如果不缓存,大量用户同时抢票,服务器也应对不过来。因此在运行时变化的数据缓存,应该有一些特别的缓存清理策略。
在实际运行业务中,运行变化的数据往往是根据使用用户的增多而增多的,因此首先要考虑的问题,就是缓存空间不够的可能性。我们不太可能把全部数据都放到缓存的空间里,也不可能清理缓存的时候就全部数据一起清理,所以我们一般要对数据进行分割,这种分割的策略常见的有两种:一种是按重要级来分割,一种是按使用部分分割。
先举例说说“按重要级分割”,在网络游戏中,同样是角色的数据,有些数据的变化可能会每次修改都立刻回写到数据库(清理写缓存),其他一些数据的变化会延迟一段时间,甚至有些数据直到角色退出游戏才回写,如玩家的等级变化(升级了),武器装备的获得和消耗,这些玩家非常看重的数据,基本上会立刻回写,这些就是所谓最重要的缓存数据。而玩家的经验值变化、当前HP、MP的变化,就会延迟一段时间才写,因为就算丢失了缓存,玩家也不会太过关注。最后有些比如玩家在房间(地区)里的X/Y坐标,对话聊天的记录,可能会退出时回写,甚至不回写。这个例子说的是“写缓存”的清理,下面说说“读缓存”的按重要级分割清理。
假如我们写一个网店系统,里面容纳了很多产品,这些产品有一些会被用户频繁检索到,比较热销,而另外一些商品则��那么热销。热销的商品的余额、销量、评价都会比较频繁的变化,而滞销的商品则变化很少。所以我们在设计的时候,就应该按照不同商品的访问频繁程度,来决定缓存哪些商品的数据。我们在设计缓存的结构时,就应该构建一个可以统计缓存读写次数的指标,如果有些数据的读写频率过低,或者空闲(没有人读、写缓存)时间超长,缓存应该主动清理掉这些数据,以便其他新的数据能进入缓存。这种策略也叫做“冷热交换”策略。实现“冷热交换”的策略时,关键是要定义一个合理的冷热统计算法。一些固定的指标和算法,往往并不能很好的应对不同硬件、不同网络情况下的变化,所以现在人们普遍会用一些动态的算法,如Redis就采用了5种,他们是:
1.根据过期时间,清理最长时间没用过的
2.根据过期时间,清理即将过期的
3.根据过期时间,任意清理一个
4.无论是否过期,随机清理
5.无论是否过期,根据LRU原则清理:所谓LRU,就是Least Recently Used,最近最久未使用过。这个原则的思想是:如果一个数据在最近一段时间没有被访问到,那么在将来他被访问的可能性也很小。LRU是在操作系统中很常见的一种原则,比如内存的页面置换算法(也包括FIFO,LFU等),对于LRU的实现,还是非常有技巧的,但是本文就不详细去说明如何实现,留待大家上网搜索“LRU”关键字学习。
数据缓存的清理策略其实远不止上面所说的这些,要用好缓存这个武器,就要仔细研究需要缓存的数据特征,他们的读写分布,数据之中的差别。然后最大化的利用业务领域的知识,来设计最合理的缓存清理策略。这个世界上不存在万能的优化缓存清理策略,只存在针对业务领域最优化的策略,这需要我们程序员深入理解业务领域,去发现数据背后的规律。
分布
分布策略的概念
任何的服务器的性能都是有极限的,面对海量的互联网访问需求,是不可能单靠一台服务器或者一个CPU来承担的。所以我们一般都会在运行时架构设计之初,就考虑如何能利用多个CPU、多台服务器来分担负载,这就是所谓分布的策略。分布式的服务器概念很简单,但是实现起来却比较复杂。因为我们写的程序,往往都是以一个CPU,一块内存为基础来设计的,所以要让多个程序同时运行,并且协调运作,这需要更多的底层工作。
首先出现能支持分布式概念的技术是多进程。在DOS时代,计算机在一个时间内只能运行一个程序,如果你想一边写程序,同时一边听mp3,都是不可能的。但是,在WIN95操作系统下,你就可以同时开多个窗口,背后就是同时在运行多个程序。在Unix和后来的Linux操作系统里面,都普遍支持了多进程的技术。所谓的多进程,就是操作系统可以同时运行我们编写的多个程序,每个程序运行的时候,都好像自己独占着CPU和内存一样。在计算机只有一个CPU的时候,实际上计算机会分时复用的运行多个进程,CPU在多个进程之间切换。但是如果这个计算机有多个CPU或者多个CPU核,则会真正的有几个进程同时运行。所以进程就好像一个操作系统提供的运行时“程序盒子”,可以用来在运行时,容纳任何我们想运行的程序。当我们掌握了操作系统的多进程技术后,我们就可以把服务器上的运行任务,分为多个部分,然后分别写到不同的程序里,利用上多CPU或者多核,甚至是多个服务器的CPU一起来承担负载。
[多进程利用多CPU]
  这种划分多个进程的架构,一般会有两种策略:一种是按功能来划分,比如负责网络处理的一个进程,负责数据库处理的一个进程,负责计算某个业务逻辑的一个进程。另外一种策略是每个进程都是同样的功能,只是分担不同的运算任务而已。使用第一种策略的系统,运行的时候,直接根据操作系统提供的诊断工具,就能直观的监测到每个功能模块的性能消耗,因为操作系统提供进程盒子的同时,也能提供对进程的全方位的监测,比如CPU占用、内存消耗、磁盘和网络I/O等等。但是这种策略的运维部署会稍微复杂一点,因为任何一个进程没有启动,或者和其他进程的通信地址没配置好,都可能导致整个系统无法运作;而第二种分布策略,由于每个进程都是一样的,这样的安装部署就非常简单,性能不够就多找几个机器,多启动几个进程就完成了,这就是所谓的平行扩展。
现在比较复杂的分布式系统,会结合这两种策略,也就是说系统既按一些功能划分出不同的具体功能进程,而这些进程又是可以平行扩展的。当然这样的系统在开发和运维上的复杂度,都是比单独使用“按功能划分”和“平行划分”要更高的。由于要管理大量的进程,传统的依靠配置文件来配置整个集群的做法,会显得越来越不实用:这些运行中的进程,可能和其他很多进程产生通信关系,当其中一个进程变更通信地址时,势必影响所有其他进程的配置。所以我们需要集中的管理所有进程的通信地址,当有变化的时候,只需要修改一个地方。在大量进程构建的集群中,我们还会碰到容灾和扩容的问题:当集群中某个服务器出现故障,可能会有一些进程消失;而当我们需要增加集群的承载能力时,我们又需要增加新的服务器以及进程。这些工作在长期运行的服务器系统中,会是比较常见的任务,如果整个分布系统有一个运行中的中心进程,能自动化的监测所有的进程状态,一旦有进程加入或者退出集群,都能即时的修改所有其他进程的配置,这就形成了一套动态的多进程管理系统。开源的ZooKeeper给我们提供了一个可以充当这种动态集群中心的实现方案。由于ZooKeeper本身是可以平行扩展的,所以它自己也是具备一定容灾能力的。现在越来越多的分布式系统都开始使用以ZooKeeper为集群中心的动态进程管理策略了。
[动态进程集群]
  在调用多进程服务的策略上,我们也会有一定的策略选择,其中最著名的策略有三个:一个是动态负载均衡策略;一个是读写分离策略;一个是一致性哈希策略。动态负载均衡策略,一般会搜集多个进程的服务状态,然后挑选一个负载最轻的进程来分发服务,这种策略对于比较同质化的进程是比较合适的。读写分离策略则是关注对持久化数据的性能,比如对数据库的操作,我们会提供一批进程专门用于提供读数据的服务,而另外一个(或多个)进程用于写数据的服务,这些写数据的进程都会每次写多份拷贝到“读服务进程”的数据区(可能就是单独的数据库),这样在对外提供服务的时候,就可以提供更多的硬件资源。一致性哈希策略是针对任何一个任务,看看这个任务所涉及读写的数据,是属于哪一片的,是否有某种可以缓存的特征,然后按这个数据的ID或者特征值,进行“一致性哈希”的计算,分担给对应的处理进程。这种进程调用策略,能非常的利用上进程内的缓存(如果存在),比如我们的一个在线游戏,由100个进程承担服务,那么我们就可以把游戏玩家的ID,作为一致性哈希的数据ID,作为进程调用的KEY,如果目标服务进程有缓存游戏玩家的数据,那么所有这个玩家的操作请求,都会被转到这个目标服务进程上,缓存的命中率大大提高。而使用“一致性哈希”,而不是其他哈希算法,或者取模算法,主要是考虑到,如果服务进程有一部分因故障消失,剩下的服务进程的缓存依然可以有效,而不会整个集群所有进程的缓存都失效。具体有兴趣的读者可以搜索“一致性哈希”一探究竟。
以多进程利用大量的服务器,以及服务器上的多个CPU核心,是一个非常有效的手段。但是使用多进程带来的额外的编程复杂度的问题。一般来说我们认为最好是每个CPU核心一个进程,这样能最好的利用硬件。如果同时运行的进程过多,操作系统会消耗很多CPU时间在不同进程的切换过程上。但是,我们早期所获得的很多API都是阻塞的,比如文件I/O,网络读写,数据库操作等。如果我们只用有限的进程来执行带这些阻塞操作的程序,那么CPU会大量被浪费,因为阻塞的API会让有限的这些进程停着等待结果。那么,如果我们希望能处理更多的任务,就必须要启动更多的进程,以便充分利用那些阻塞的时间,但是由于进程是操作系统提供的“盒子”,这个盒子比较大,切换耗费的时间也比较多,所以大量并行的进程反而会无谓的消耗服务器资源。加上进程之间的内存一般是隔离的,进程间如果要交换一些数据,往往需要使用一些操作系统提供的工具,比如网络socket,这些都会额外消耗服务器性能。因此,我们需要一种切换代价更少,通信方式更便捷,编程方法更简单的并行技术,这个时候,多线程技术出现了。
[在进程盒子里面的线程盒子]
  多线程的特点是切换代价少,可以同时访问内存。我们可以在编程的时候,任意让某个函数放入新的线程去执行,这个函数的参数可以是任何的变量或指针。如果我们希望和这些运行时的线程通信,只要读、写这些指针指向的变量即可。在需要大量阻塞操作的时候,我们可以启动大量的线程,这样就能较好的利用CPU的空闲时间;线程的切换代价比进程低得多,所以我们能利用的CPU也会多很多。线程是一个比进程更小的“程序盒子”,他可以放入某一个函数调用,而不是一个完整的程序。一般来说,如果多个线程只是在一个进程里面运行,那其实是没有利用到多核CPU的并行好处的,仅仅是利用了单个空闲的CPU核心。但是,在JAVA和C#这类带虚拟机的语言中,多线程的实现底层,会根据具体的操作系统的任务调度单位(比如进程),尽量让线程也成为操作系统可以调度的单位,从而利用上多个CPU核心。比如Linux2.6之后,提供了NPTL的内核线程模型,JVM就提供了JAVA线程到NPTL内核线程的映射,从而利用上多核CPU。而Windows系统中,据说本身线程就是系统的最小调度单位,所以多线程也是利用上多核CPU的。所以我们在使用JAVA\C#编程的时候,多线程往往已经同时具备了多进程利用多核CPU、以及切换开销低的两个好处。
早期的一些网���聊天室服务,结合了多线程和多进程使用的例子。一开始程序会启动多个广播聊天的进程,每个进程都代表一个房间;每个用户连接到聊天室,就为他启动一个线程,这个线程会阻塞的读取用户的输入流。这种模型在使用阻塞API的环境下,非常简单,但也非常有效。
当我们在广泛使用多线程的时候,我们发现,尽管多线程有很多优点,但是依然会有明显的两个缺点:一个内存占用比较大且不太可控;第二个是多个线程对于用一个数据使用时,需要考虑复杂的“锁”问题。由于多线程是基于对一个函数调用的并行运行,这个函数里面可能会调用很多个子函数,每调用一层子函数,就会要在栈上占用新的内存,大量线程同时在运行的时候,就会同时存在大量的栈,这些栈加在一起,可能会形成很大的内存占用。并且,我们编写服务器端程序,往往希望资源占用尽量可控,而不是动态变化太大,因为你不知道什么时候会因为内存用完而当机,在多线程的程序中,由于程序运行的内容导致栈的伸缩幅度可能很大,有可能超出我们预期的内存占用,导致服务的故障。而对于内存的“锁”问题,一直是多线程中复杂的课题,很多多线程工具库,都推出了大量的“无锁”容器,或者“线程安全”的容器,并且还大量设计了很多协调线程运作的类库。但是这些复杂的工具,无疑都是证明了多线程对于内存使用上的问题。
[同时排多条队就是并行]
  由于多线程还是有一定的缺点,所以很多程序员想到了一个釜底抽薪的方法:使用多线程往往是因为阻塞式API的存在,比如一个read()操作会一直停止当前线程,那么我们能不能让这些操作变成不阻塞呢?——selector/epoll就是Linux退出的非阻塞式API。如果我们使用了非阻塞的操作函数,那么我们也无需用多线程来并发的等待阻塞结果。我们只需要用一个线程,循环的检查操作的状态,如果有结果就处理,无结果就继续循环。这种程序的结果往往会有一个大的死循环,称为主循环。在主循环体内,程序员可以安排每个操作事件、每个逻辑状态的处理逻辑。这样CPU既无需在多线程间切换,也无需处理复杂的并行数据锁的问题——因为只有一个线程在运行。这种就是被称为“并发”的方案。
[服务员兼了点菜、上菜就是并发]
实际上计算机底层早就有使用并发的策略,我们知道计算机对于外部设备(比如磁盘、网卡、显卡、声卡、键盘、鼠标),都使用了一种叫“中断”的技术,早期的电脑使用者可能还被要求配置IRQ号。这个中断技术的特点,就是CPU不会阻塞的一直停在等待外部设备数据的状态,而是外部数据准备好后,给CPU发一个“中断信号”,让CPU转去处理这些数据。非阻塞的编程实际上也是类似这种行为,CPU不会一直阻塞的等待某些I/O的API调用,而是先处理其他逻辑,然后每次主循环去主动检查一下这些I/O操作的状态。
多线程和异步的例子,最著名就是Web服务器领域的Apache和Nginx的模型。Apache是多进程/多线程模型的,它会在启动的时候启动一批进程,作为进程池,当用户请求到来的时候,从进程池中分配处理进程给具体的用户请求,这样可以节省多进程/线程的创建和销毁开销,但是如果同时有大量的请求过来,还是需要消耗比较高的进程/线程切换。而Nginx则是采用epoll技术,这种非阻塞的做法,可以让一个进程同时处理大量的并发请求,而无需反复切换。对于大量的用户访问场景下,apache会存在大量的进程,而nginx则可以仅用有限的进程(比如按CPU核心数来启动),这样就会比apache节省了不少“进程切换”的消耗,所以其并发性能会更好。
[Nginx的固定多进程,一个进程异步处理多个客户端]
  [Apache的多态多进程,一个进程处理一个客户]
在现代服务器端软件中,nginx这种模型的运维管理会更简单,性能消耗也会稍微更小一点,所以成为最流行的进程架构。但是这种好处,会付出一些另外的代价:非阻塞代码在编程的复杂度变大。
分布式编程复杂度
以前我们的代码,从上往下执行,每一行都会占用一定的CPU时间,这些代码的直接顺序,也是和编写的顺序基本一致,任何一行代码,都是唯一时刻的执行任务。当我们在编写分布式程序的时候,我们的代码将不再好像那些单进程、单线程的程序一样简单。我们要把同时运行的不同代码,在同一段代码中编写。就好像我们要把整个交响乐团的每个乐器的乐谱,全部写到一张纸上。为了解决这种编程的复杂度,业界发展出了多种编码形式。
在多进程的编码模型上,fork()函数可以说一个非常典型的代表。在一段代码中,fork()调用之后的部分,可能会被新的进程中执行。要区分当前代码的所在进程,要靠fork()的返回值变量。这种做法,等于把多个进程的代码都合并到一块,然后通过某些变量作为标志来划分。这样的写法,对于不同进程代码大部份相同的“同质进程”来说,还是比较方便的,最怕就是有大量的不同逻辑要用不同的进程来处理,这种情况下,我们就只能自己通过规范fork()附近的代码,来控制混乱的局面。比较典型的是把fork()附近的代码弄成一个类似分发器(dispatcher)的形式,把不同功能的代码放到不同的函数中,以fork之前的标记变量来决定如何调用。
[动态多进程的代码模式]
  在我们使用多线程的API时,情况就会好很多,我们可以用一个函数指针,或者一个带回调方法的对象,作为线程执行的主体,并且以句柄或者对象的形式来控制这些线程。作为开发人员,我们只要掌握了对线程的启动、停止等有限的几个API,就能很好的对并行的多线程进行控制。这对比多进程的fork()来说,从代码上看会更直观,只是我们必须要分清楚调用一个函数,和新建一个线程去调用一个函数,之间的差别:新建线程去调用函数,这个操作会很快的结束,并不会依序去执行那个函数,而是代表着,那个函数中的代码,可能和线程调用之后的代码,交替的执行。
由于多线程把“并行的任务”作为一个明确的编程概念定义了出来,以句柄、对象的形式封装好,那么我们自然会希望对多线程能更多复杂而细致的控制。因此出现了很多多线程相关的工具。比较典型的编程工具有线程池、线程安全容器、锁这三类。线程池提供给我们以“池”的形态,自动管理线程的能力:我们不需要自己去考虑怎么建立线程、回收线程,而是给线程池一个策略,然后输入需要执行的任务函数,线程池就会自动操作,比如它会维持一个同时运行线程数量,或者保持一定的空闲线程以节省创建、销毁线程的消耗。在多线程操作中,不像多进程在内存上完全是区分开的,所以可以访问同一份内存,也就是对堆里面的同一个变量进行读写,这就可能产生程序员所预计不到的情况(因为我们写程序只考虑代码是顺序执行的)。还有一些对象容器,比如哈希表和队列,如果被多个线程同时操作,可能还会因为内部数据对不上,造成严重的错误,所以很多人开发了一些可以被多个线程同时操作的容器,以及所谓“原子”操作的工具,以解决这样的问题。有些语言如Java,在语法层面,就提供了关键字来对某个变量进行“上锁”,以保障只有一个线程能操作它。多线程的编程中,很多并行任务,是有一定的阻塞顺序的,所以有各种各样的锁被发明出来,比如倒数锁、排队锁等等。java.concurrent库就是多线程工具的一个大集合,非常值得学习。然而,多线程的这些五花八门的武器,其实也是证明了多线程本身,是一种不太容易使用的顺手的技术,但是我们一下子还没有更好的替代方案罢了。
[多线程的对象模型]
  在多线程的代码下,除了启动线程的地方,是和正常的执行顺序不同以外,其他的基本都还是比较近似单线程代码的。但是如果在异步并发的代码下,你会发现,代码一定要装入一个个“回调函数”里。这些回调函数,从代码的组织形态上,几乎完全无法看出来其预期的执行顺序,一般只能在运行的时候通过断点或者日志来分析。这就对代码阅读带来了极大的障碍。因此现在有越来越多的程序员关注“协程”这种技术:可以用类似同步的方法来写异步程序,而无需把代码塞到不同的回调函数里面。协程技术最大的特点,就是加入了一个叫yield的概念,这个关键字所在的代码行,是一个类似return的作用,但是又代表着后续某个时刻,程序会从yield的地方继续往下执行。这样就把那些需要回调的代码,从函数中得以解放出来,放到yield的后面了。在很多客户端游戏引擎中,我们写的代码都是由一个框架,以每秒30帧的速度在反复执行,为了让一些任务,可以分别放在各帧中运行,而不是一直阻塞导致“卡帧”,使用协程就是最自然和方便的了——Unity3D就自带了协程的支持。
在多线程同步程序中,我们的函数调用栈就代表了一系列同属一个线程的处理。但是在单线程的异步回调的编程模式下,我们的一个回调函数是无法简单的知道��是在处理哪一个请求的序列中。所以我们往往需要自己写代码去维持这样的状态,最常见的做法是,每个并发任务启动的时候,就产生一个序列号(seqid),然后在所有的对这个并发任务处理的回调函数中,都传入这个seqid参数,这样每个回调函数,都可以通过这个参数,知道自己在处理哪个任务。如果有些不同的回调函数,希望交换数据,比如A函数的处理结果希望B函数能得到,还可以用seqid作为key把结果存放到一个公共的哈希表容器中,这样B函数根据传入的seqid就能去哈希表中获得A函数存入的结果了,这样的一份数据我们往往叫做“会话”。如果我们使用协程,那么这些会话可能都不需要自己来维持了,因为协程中的栈代表了会话容器,当执行序列切换到某个协程中的时候,栈上的局部变量正是之前的处理过程的内容结果。
[协程的代码特征]
  为了解决异步编程的回调这种复杂的操作,业界还发明了很多其他的手段,比如lamda表达式、闭包、promise模型等等,这些都是希望我们,能从代码的表面组织上,把在多个不同时间段上运行的代码,以业务逻辑的形式组织到一起。
最后我想说说函数式编程,在多线程的模型下,并行代码带来最大的复杂性,就是对堆内存的同时操作。所以我们才弄出来锁的机制,以及一大批对付死锁的策略。而函数式编程,由于根本不使用堆内存,所以就无需处理什么锁,反而让整个事情变得非常简单。唯一需要改变的,就是我们习惯于把状态放到堆里面的编程思路。函数式编程的语言,比如LISP或者Erlang,其核心数据结果是链表——一种可以表示任何数据结构的结构。我们可以把所有的状态,都放到链表这个数据列车中,然后让一个个函数去处理这串数据,这样同样也可以传递程序的状态。这是一种用栈来代替堆的编程思路,在多线程并发的环境下,非常的有价值。
分布式程序的编写,一直都伴随着大量的复杂性,影响我们对代码的阅读和维护,所以我们才有各种各样的技术和概念,试图简化这种复杂性。也许我们无法找到任何一个通用的解决方案,但是我们可以通过理解各种方案的目标,来选择最适合我们的场景:
l  动态多进程fork——同质的并行任务
l  多线程——能明确划的逻辑复杂的并行任务
l  异步并发回调——对性能要求高,但中间会被阻塞的处理较少的并行任务
l  协程——以同步的写法编写并发的任务,但是不合适发起复杂的动态并行操作。
l  函数式编程——以数据流为模型的并行处理任务
分布式数据通信
分布式的编程中,对于CPU时间片的切分本身不是难点,最困难的地方在于并行的多个代码片段,如何进行通信。因为任何一个代码段,都不可能完全单独的运作,都需要和其他代码产生一定的依赖。在动态多进程中,我们往往只能通过父进程的内存提供共享的初始数据,运行中则只能通过操作系统间的通讯方式了:Socket、信号、共享内存、管道等等。无论那种做法,这些都带来了一堆复杂的编码。这些方式大部分都类似于文件操作:一个进程写入、另外一个进程读出。所以很多人设计了一种叫“消息队列”的模型,提供“放入”消息和“取出”消息的接口,底层则是可以用Socket、共享内存、甚至是文件来实现。这种做法几乎能够处理任何状况下的数据通讯,而且有些还能保存消息。但是缺点是每个通信消息,都必须经过编码、解码、收包、发包这些过程,对处理延迟有一定的消耗。
如果我们在多线程中进行通信,那么我们可以直接对某个堆里面的变量直接进行读写,这样的性能是最高的,使用也非常方便。但是缺点是可能出现几个线程同时使用变量,产生了不可预期的结果,为了对付这个问题,我们设计了对变量的“锁”机制,而如何使用锁又成为另外一个问题,因为可能出现所谓的“死锁”问题。所以我们一般会用一些“线程安全”的容器,用来作为多线程间通讯的方案。为了协调多个线程之间的执行顺序,还可以使用很多种类型的“工具锁”。
在单线程异步并发的情况下,多个会话间的通信,也是可以通过直接对变量进行读写操作,而且不会出现“锁”的问题,因为本质上每个时刻都只有一个段代码会操作这个变量。然而,我们还是需要对这些变量进行一定规划和整理,否则各种指针或全局变量在代码中散布,也是很出现BUG的。所以我们一般会把“会话”的概念变成一个数据容器,每段代码都可以把这个会话容器作为一个“收件箱”,其他的并发任务如果需要在这个任务中通讯,就把数据放入这个“收件箱”即可。在WEB开发领域,和cookie对应的服务器端Session机制,就是这种概念的典型实现。
分布式缓存策略
在分布式程序架构中,如果我们需要整个体系有更高的稳定性,能够对进程容灾或者动态扩容提供支持,那么最难解决的问题,就是每个进程中的内存状态。因为进程一旦毁灭,内存中的状态会消失,这就很难不影响提供的服务。所以我们需要一种方法,让进程的内存状态,不太影响整体服务,甚至最好能变成“无状态”的服务。当然“状态”如果不写入磁盘,始终还是需要某些进程来承载的。在现在流行的WEB开发模式中,很多人会使用PHP+Memcached+MySQL这种模型,在这里,PHP就是无状态的,因为状态都是放在Memcached里面。这种做法对于PHP来说,是可以随时动态的毁灭或者新建,但是Memcached进程就要保证稳定才行;而且Memcached作为一个额外的进程,和它通信本身也会消耗更多的延迟时间。因此我们需要一种更灵活和通用的进程状态保存方案,我们把这种任务叫做“分布式缓存”的策略。我们希望进程在读取数据的时候,能有最高的性能,最好能和在堆内存中读写类似,又希望这些缓存数据,能被放在多个进程内,以分布式的形态提供高吞吐的服务,其中最关键的问题,就是缓存数据的同步。
[PHP常用Memached做缓存]
  为了解决这个问题,我们需要先一步步来分解这个问题:
首先,我们的缓存应该是某种特定形式的对象,而不应该是任意类型的变量。因为我们需要对这些缓存进行标准化的管理,尽管C++语言提供了运算重载,我们可以对“=”号的写变量操作进行重新定义,但是现在基本已经没有人推荐去做这样的事。而我们手头就有最常见的一种模型,适合缓存这种概念的使用,它就是——哈希表。所有的哈希表(或者是Map接口),都是把数据的存放,分为key和value两个部分,我们可以把想要缓存的数据,作为value存放到“表”当中,同时我们也可以用key把对应的数据取出来,而“表”对象就代表了缓存。
其次我们需要让这个“表”能在多个进程中都存在。如果每个进程中的数据都毫无关联,那问题其实就非常简单,但是如果我们可能从A进程把数据写入缓存,然后在B进程把数据读取出来,那么就比较复杂了。我们的“表”要有能把数据在A、B两个进程间同步的能力。因此我们一般会用三种策略:租约清理、租约转发、修改广播
l  租约清理,一般是指,我们把存放某个key的缓存的进程,称为持有这个key的数据的“租约”,这个租约要登记到一个所有进程都能访问到的地方,比如是ZooKeeper集群进程。那么在读、写发生的时候,如果本进程没有对应的缓存,就先去查询一下对应的租约,如果被其他进程持有,则通知对方“清理”,所谓“清理”,往往是指删除用来读的数据,回写用来写的数据到数据库等持久化设备,等清理完成后,在进行正常的读写操作,这些操作可能会重新在新的进程上建立缓存。这种策略在缓存命中率比较高的情况下,性能是最好的,因为一般无需查询租约情况,就可以直接操作;但如果缓存命中率低,那么就会出现缓存反复在不同进程间“移动”,会严重降低系统的处理性能。
  l  租约转发。同样,我们把存放某个KEY的缓存的进程,称为持有这个KEY数据的“租约”,同时也要登记到集群的共享数据进程中。和上面租约清理不同的地方在于,如果发现持有租约的进程不是本次操作的进程,就会把整个数据的读、写请求,都通过网络“转发”个持有租约的进程,然后等待他的操作结果返回。这种做法由于每次操作都需要查询租约,所以性能会稍微低一些;但如果缓存命中率不高,这种做法能把缓存的操作分担到多个进程上,而且也无需清理缓存,这比租约清理的策略适应性更好。
  l  修改广播。上面两种策略,都需要维护一份缓存数据的租约,但是本身对于租约的操作,就是一种比较耗费性能的事情。所以有时候可以采用一些更简单,但可能承受一些不一致性的策略:对于读操作,每个节点的读都建立缓存,每次读都判断是否超过预设的读冷却时间x,超过则清理缓存从持久化重建;对于写操作,么个节点上都判断是否超过预设的写冷却时间y,超过则展开清理操作。清理操作也分两种,如果数据量小就广播修改数据;如果数据量大就广播清理通知回写到持久化中。这样虽然可能会有一定的不一致风险,但是如果数据不是那种要求太高的,而且缓存命中率又能比较有保障的话(比如根据KEY来进行一致性哈希访问缓存进程),那么真正因为写操作广播不及时,导致数据不一致的情况还是会比较少的。这种策略实现起来非常简单,无需一个中心节点进程维护数据租约,也无需复杂的判断逻辑进行同步,只要有广播的能力,加上对于写操作的一些配置,就能实现高效的缓存服务。所以“修改广播”策略是在大多数需要实时同步,但数据一致性要求不高的领域最常见的手段。著名的DNS系统的缓存就是接近这种策略:我们要修改某个域名对应的IP,并不是立刻在全球所有的DNS服务器上生效,而是需要一定时间广播修改给其他服务区。而我们每个DSN服务器,都具备了大量的其他域名的缓存数据。
  总结
在高性能的服务器架构中,常用的缓存和分布两种策略,往往是结合到一起使用的。虽然这两种策略,都有无数种不同的表现形式,成为各种各样的技术流派,但是只有清楚的理解这些技术的原理,并且和实际的业务场景结合起来,才能真正的做出满足应用要求的高性能架构。
高性能服务器架构思路,不仅是思路,首发于文章 - 伯乐在线。
1 note · View note
inmatts-blog-blog · 6 years ago
Text
氪星晚报 | 腾讯将联合任天堂完善各项本地化服务;蔚来与雷蛇推出限量版车型;网易云音乐朱一闻:IPO和盈利已有内部时间表
大公司 腾讯首次介绍国行Switch进展:将完善本地化服务,代理发行任天堂游戏 36氪获悉,腾讯游戏任天堂合作部总经理钱赓表示,腾讯将会联合任天堂完善各项本地化服务,游戏本地化上,腾讯会与任天堂一起完善知名游戏的本地化翻译,未来会有更多简体中文版游戏在中国大陆陆续上市。钱赓称,腾讯作为发行方,将会代理引进合适的任天堂游戏和其他非任天堂出品的精品游戏。此外,腾讯也在计划辅助任天堂设立线下购买渠道和玩家交流中心。 荣耀赵明:鸿蒙系统首发设备欲屏蔽开机广告 从华为官方给出的最新公告显示,8月9日的开发者大会上,将会公布鸿蒙系统,而首款搭载该系统的设备(8月10日发布),会是荣耀的智慧屏,华为自有品牌产品会在9月份推出。荣耀掌门人赵明在微博上跟网友互动时暗示,搭载鸿蒙系统的智慧屏设备将改变现有互联网电视的模式,屏蔽烦人的开机广告。(硅谷分析狮) 腾讯云发布“腾讯云·云游戏解决方案” 36氪获悉,腾讯云今日在2019年China Joy上发布“腾讯云·��游戏解决方案”,在现场,基于该方案,腾讯云联合WeGame提供了《天涯明月刀》《中国式家长》《三国杀》等云游戏模式的试玩。此外,腾讯云正与GPU厂商共同定制和开发企业级显卡,并将其“虚拟化”,开发者能像云服务一样按需采买云GPU资源。 网易宣布与Creative Assembly战略合作,将《全面战争》系列游戏引入中国 8月2日,网易宣布与世嘉欧洲旗下子公司Creative Assembly建立长期战略合作伙伴关系,网易将作为独家游戏发行商,将《全面战争》(Total War)系列游戏引入中国,其中包括《全面战争》系列历史策略游戏,以及最新推出的《全面战争:三国》 。(游民星空) 特斯拉再次因致命Autopilot事故遭起诉 据外媒The Verge报道,近日一名50岁的男子使用Autopilot驾驶一辆特斯拉Model 3电动汽车时发生致命车祸而丧生。Jeremy Beren Banner的家人对特斯拉提起诉讼,同时要求支付超过15000美元的赔偿金。Banner是第四个在使用Autopilot时死亡的人,这是特斯拉Autopilot系统涉及致命车祸的第二起诉讼。(cnBeta) 哈啰顺风车启动安全专项行动 哈啰顺风车近日发布声明宣布,基于用户评分、异常接单行为等数据,启动了全国范围内对违规行为的集中打击和管理,对查实违规车主进行了集中的警告,封禁处理。截至到8月2日,已封禁2677个违规账户,警告1811个违规账户。(腾讯科技) 三星今年将完成6纳米量产 三星官方最近给出时间表,6nm 6LPP将在今年下半年如期投入量产,5nm 5LPE今年内完成流片、明年上半年量产,4nm 4LPE也会在年内设计完毕。(TechWeb) 亚马逊卷入Capital One数据泄露,美国会要求解释 美国众议院和参议院的委员会领导者希望Capital One和亚马逊向国会解释,黑客如何从超过1亿的Capital One信用卡客户和申请人那里获取个人信息。这是大公司遭遇的最新一起大规模数据泄露事件。(新浪科技) 网易云音乐CEO朱一闻:IPO和盈利已有内部时间表 对于外界关注的资本进程,网易云音乐CEO朱一闻在今日举行的小型媒体交流会上表示,“音乐平台最核心的商业机制是会员模式。网易云音乐到现在为止,占比最高的,也是会员收入,有其他抓手,包括广告、直播等,但会员一定是核心的。融资的话,战略投资方为主,资金为辅。IPO和盈利,内部有时间表。社区和帮助用户发现好音乐,是网易云音乐最核心模式。”(21世纪经济报道) 快手:核心二次元用户超过4000万人,已有接近400个动漫IP入驻 36氪获悉,在2019中国国际数字娱乐产业大会上,快手高级副总裁马宏彬表示,2019年上半年快手站内游戏内容发布数达5亿多,游戏直播移动端日活3500万。快手平台有核心二次元活跃用户超4000万人,已有近400个动漫IP入驻,单个动漫作品最高播放量超2000万。 大搜车与优酷达成合作 36氪获悉,大搜车宣布与优酷达成合作,弹个车和大搜车家选将与优酷综艺《一起乐队吧》、《演技派》、《江湖食令》、《当红不让》展开品牌内容定制。合作方式包括:品牌时刻定制、特色串烧歌曲创作、选手深度绑定等。 光大证券:公司首席风险官王勇申请辞职 36氪获悉,光大证券发布公告称,公司首席风险官王勇因职业发展原因,申请辞去公司首席风险官职务,确认与公司董事会并无意见分歧,亦无其他因辞职而需知会股东的事宜。据21世纪经济报道此前消息,王勇即将离职或与MPS事件有关。2016年,暴风集团与光大资本共同发起收购英国体育版权公司MPS,MPS公司已经破产。 英特尔与百度将继续在AI、自动驾驶和5G领域开展合作 近日英特尔和百度相关负责人于英特尔总部加利福尼亚州圣克拉拉讨论人工智能、自动驾驶和5G领域合作事宜。英特尔与百度领导人签署新的合作备忘录,旨在通过英特尔丰富的技术产品组合和支持资源,以及英特尔在软硬件方面的专长,深化双方未来三年在百度核心业务领域的合作。(新浪科技) 通用汽车自动驾驶子公司Cruise上半年亏损5.03亿美元 36氪获悉,8月1日,通用汽车向美国证券交易委员会递交2019年第二季度财报文件。财报显示,今年上半年,其自动驾驶子公司Cruise收入总额5000万美元,开销为5.53亿美元,总营业收入为亏损5.03亿美元。 索尼互动娱乐年内将发售PS4游戏《西游记之大圣归来》 36氪获悉,PlayStation中国在官方微博宣布,索尼互动娱乐与十月文化、绿洲游戏联合制作的PS4游戏《西游记之大圣归来》计划于2019年内发售。这是PlayStation平台上首款基于中国原创IP、由中日双方团队联手打造、将于全球发行的游戏大作。 投融资 “大地量子”完成数百万美金Pre-A轮融资 36氪获悉,空间大数据平台“大地量子”今日宣布完成由SIG投资的数百万美金的Pre-A轮融资。公司创始人王驰表示,本轮资金将主要应用于新技术的研发以及市场推广。大地量子成立于2017年,通过对海量卫星遥感数据进行整合,并结合人工智能技术对数据进行加工处理,目前已开发落地了基于API的空间数据平台,其中包括了作物识别、污染监控等一系列空间数据产品。 零售自动化解决方案公司“Caper”完成A轮近千万美元融资 36氪获悉,美国初创零售自动化公司“Caper”于近期完成了千万元美元的A轮融资,由Lux Capital领投,Y Combinator, First Round Capital, Funders Club以及各大美国商超参投。此轮融资后,Caper将扩大团队,进入更多国家和地区。Caper主要利用AI,物联网技术,大数据技术加快购物流程,提升购物体验。 跨境电商平台“Wish” 获H轮融资 36氪获悉,跨境电商平台“Wish”获General Atlantic领投的H轮融资,估值112亿美元。 2017年Wish完成了G轮融资,估值87亿美元。投资方包括光际资本、Founders Fund、纪源资本、GST Global、淡马锡等。General Atlantic董事总经理Tanzeen Syed通过这次投资加入了Wish的董事会。 新产品 蔚来与雷蛇联合推出ES6暗夜探索者限量版,限量88台 36氪获悉,8月2日,蔚来与雷蛇正式宣布启动跨界合作,推出限量版车型蔚来ES6暗夜探索者限量版,该款定制车型限量88台,售价467800元,即日起开启线上预订。据蔚来介绍,ES6暗夜探索者限量版以ES6性能版为基础,搭载NIO Pilot,NOMI Mate等科技配置,并配备雷蛇专属后装套件,包括经典的雷蛇标志图案和饰条、碳纤维贴膜包围、绿色卡钳及定制尾标和设计套装。 苹果9月将发3款A13芯的新iPhone11 搭配Taptic引擎 报道称,与去年推出的iPhone XS、iPhone XS Max和iPhone XR类似,苹果今年秋天将推出三款新的“iPhone 11”机型。新款iPhone将搭载苹果A13芯片,其平台代号为Cebu,型号为T8030。报道还称,今年的新“iPhone 11”还将采用一种新型的Taptic引擎模型,代号为leap-heptics。(新浪科技) 其他重要新闻 《哪吒之魔童降世》票房超过《疯狂动物城》,位列中国影史动画电影票房第一 36氪获悉,截至发稿,猫眼数据显示,电影《哪吒之魔童降世》上映8天票房达到15.28亿元,超过《疯狂动物城》(累计综合票房15.27705亿元)位列中国影史动画电影票房第一。 央行开通微信公众号,易纲:提升政策透明度和公信力 36氪获悉,今日,央行微信公众号“中国人民银行”开通,央行将通过这一公众号发布官方信息、解读金融政策、介绍金融知识。央行行长易纲表示,央行将继续丰富完善与公众沟通的方式,不断提升各项政策的透明度和公信力。 奥维睿沃:2019年上半年全球电视品牌出货9816万台,同比下降0.7% 36氪获悉,奥维睿沃(AVC Revo)《全球TV品牌出货月度数据报告》显示,2019年上半年全球电视品牌出货9816万台,同比下降0.7%,其中OLED电视出货120万台,同比增长21%。从全球TV品牌出货情况来看,三星、LGE、TCL、海信、小米排名前五。 每日商业精选 商业精选是36氪的一个日更专栏,每天从海量信息中精选8条要闻,帮你省时间,主编条条做点评,帮你做判断。以下是专栏的一个小栏目——小数据,查看完整内容,请戳链接订阅哦 http://dlvr.it/R9XfXQ
0 notes