Facebook 架构学习

Facebook采用LAMP架构支撑大规模动态网站运营,强调使用开源软件并优化,遵循Unix哲学原则。其架构设计确保组件具备扩展性,最小化故障影响。利用MySQL进行Key-Value存储,避免JOIN操作以减少复杂度。同时大量应用Memcached提高数据访问效率。

在 QCon 2008 (旧金山站) 上Facebook 做的这个技术分享有不少值得借鉴的东西。所以,暂停对 QCon 北京的回顾,临时插播一贴。

设计原则

  • 尽可能的使用开源软件,并且在需要优化的时候进行优化
  • Unix 哲学。包括,模块化原则;整合化原则;清晰化原则等
  • 任何组件具备扩展性
  • 最小化故障影响
  • 简化,简化,简化!

架构概览

Facebook 是 LAMP 的坚定支持者,也差不多是用 LAMP (或许用 LAM2P 更适合) 实现的最大的动态站点。

Facebook Arch Overview.png

基础组件加上服务,中间用自己实现的一些工具进行粘合。其中关于运维细节的事情基本不会说出来的,这是很多公司的软实力所在。

PHP 经验

参见《Facebook 的 PHP 性能与扩展性》

MySQL 经验

  • 主要用于做 Key-Value 类型的存储操作,数据随机分布在多台逻辑实例上,访问多数基于全局 ID 。
  • 逻辑实例分散在多台物理主机上(超过1800台),负载均衡在物理层进行。
  • 不做读复制。
  • 尽量不做逻辑数据迁移(成本太高)。
  • 不做 JOIN 操作 (豆瓣在 QCon 上也阐述了这一点)。数据是随机分布的,关联操作反而带来了极大的复杂度。
  • 对于数据访问,主要的操作集中在最新的数据上,针对这部分做优化,旧的数据进行归档。
  • 在中心 DB 绝不存储非静态数据。
  • 使用服务或者 Memcached 进行全局查询。

 

Memcached 经验

参见我以前的笔记:Facebook 的 Memcached 扩展经验。Facebook 对 Memcached 做了不小的改进。另外,顺便说一下,前两天 Memcached 刚在 1.2.7 发布几天之后又发布了新版本 1.2.8,修正了一些问题。

一个比较有价值的是关于个人页面数据的获取的描述。这个就完全是需要做单页面 Benchmark 的细致活儿了,可能还需要产品经理能够理解工程师的"抵抗"。

  • 获取个人信息数据:通过Cache,隐性通过用户所在的 DB 获取(基于 User-ID 获知 DB)
  • 获取朋友连接信息:通过Cache,否则的话通过DB(基于 User-ID 获知 DB)
  • 并行抓取每个朋友的 10个照片相册 ID ,从Cache抓取,如果失效,再从 DB 抓取(基于相册 ID)
  • 并行抓取最近相册中的照片数据
  • 运行PHP 把整个业务逻辑跑出来
  • 返回数据给用户

然后是对 Facebook 非 LAMP 体系的东西做了一番介绍,基本上也开源了。最后参考两个架构图。

Facebook NewsFeed 的架构示意图

Facebook_NewsFeed_Arch.png

Facebook 搜索功能的架构示意图

Facebook_Search_Arch.png

管中窥豹,盲人摸象而已。

--EOF--

import React, { useEffect, useMemo, useState } from 'react'; import { ReactDOM } from 'react'; import style from '@/styles/index.less'; import { message, Tabs } from 'choerodon-ui'; import { DataSet,Table,Button,TextArea } from 'choerodon-ui/pro'; import { grpcFormDS, requestDs } from '../../stores/index'; import { getPurchaseList } from '../../services/index'; import { getCurrentOrganizationId } from 'utils/utils'; const TabPane = Tabs.TabPane const { Column } = Table const organizationId = getCurrentOrganizationId(); const callback = (key) => { console.log(key); } const Hello = () => { const [ isLoading, setIsLoading ] = useState(false); //New Request const requestDs = useMemo(() => new DataSet({ // autoQuery:true, //实例化后自动发送查询请求 autoQuery:false, fields:[ { name:'PO No.', type:'Number', label:'编号', required:true, }, { name:'Company Code', type:'string', label:'公司编码', }, { name:'App Type', type:'string', label:'应用类型', }, { name:'Vendor', type:'string', label:'供应商', required:true, lookupCode:'HR.EMPLOYE_GENDER', }, { name:'Delivery Date', type:'string', label:'日期', }, ], // transport:{ // read:({ params }) => { // console.log('organizationId',organizationId) // return { // url:`http://10.216.118.161:8080/lcdp/v1/${organizationId}/xmc-po-masts`, // method:'GET', // params // } // } // } }),[]) //mock数据 const requestMockData = [ { PO No.:111111,Company Code:'WH01',App Type:'DP',Vendor:'Fujitsu Limited',Delivery Date:'2017-11-10' }, ] //模拟数据加载 const loadRequestMockData = () => { setIsLoading(true); //模拟异步请求 setTimeout(() => { //将mock数据加载到dataset中 requestDs.loadData(requestMockData); setIsLoading(false); message.success('数据加载成功'); },1000) } //组件挂载时自动加载数据 useEffect(() => { loadRequestMockData(); },[requestDs]) const requestColumns = [ {name:'PO No.'}, {name:'Company Code'}, {name:'App Type'}, {name:'Vendor'}, {name:'Delivery Date'}, ] return ( <> <h1>XMC DownPay Requisition System</h1> <div className={style.downPay}> <Tabs defaultActiveKey="1" onChange={callback}> <TabPane tab="New Request" key="1"> <Table style={{ width:'auto' }} dataSet={requestDs} columns={requestColumns} pristine /> </TabPane> <TabPane tab="New Request(accept)" key="2">second</TabPane> <TabPane tab="Accept Report" key="3">third</TabPane> <TabPane tab="Lcdp Report" key="4">forth</TabPane> </Tabs> </div> </> ); }; export default Hello;运行代码报错Module build failed (from ../../node_modules/@umijs/deps/compiled/babel-loader/index.js): SyntaxError: C:\item\h0-front-master\packages\front-module\src\pages\blank2\index.tsx: Unexpected token, expected "," (68:9)
最新发布
09-04
<think> 我们正在处理一个SyntaxError,具体位置在index.tsx文件的第68行第9个字符处。错误信息是“Unexpected token, expected ','”,这意味着在第68行第9列附近,解析器遇到了一个它不认识的符号,而它原本期望那里是一个逗号。 根据错误提示,我们需要检查该位置的代码,看看是否有以下情况: 1. 在对象字面量中,属性之间缺少逗号。 2. 在函数参数列表中,参数之间缺少逗号。 3. 在数组字面量中,元素之间缺少逗号。 4. 在接口或类型别名定义中,属性之间缺少逗号。 5. 在JSX属性中,错误地使用了逗号(实际上JSX属性之间应该用空格分隔,而不是逗号)或者缺少必要的分隔符。 由于错误发生在第68行第9列,我们应当打开该文件并定位到第68行附近(通常需要查看前后几行)的代码。 假设我们无法直接看到用户的代码,但根据常见错误模式,我们可以给出一些典型的例子和修复方法。 典型错误示例1:对象属性缺少逗号 ```typescript const user = { name: "John" // 第67行,末尾没有逗号 age: 30 // 第68行,解析器在这里会报错,因为它期望一个逗号(在name和age之间) } ``` 修复:在name属性后面加上逗号。 典型错误示例2:函数调用参数缺少逗号 ```typescript someFunction( arg1 // 第67行 arg2 // 第68行:这里缺少逗号 ) ``` 修复:在arg1后面加上逗号。 典型错误示例3:数组中对象元素缺少逗号 ```typescript const items = [ { id: 1, name: 'Item 1' } // 第67行 { id: 2, name: 'Item 2' } // 第68行:这里缺少逗号 ]; ``` 修复:在第一个对象元素后面加上逗号。 典型错误示例4:接口定义中属性缺少逗号 ```typescript interface Person { name: string // 第67行 age: number // 第68行:这里缺少逗号 } ``` 修复:在name属性后面加上逗号。 由于错误位置在第68行第9列,我们应重点检查第68行第9列附近的代码。注意,错误可能出现在第68行的开始部分(即第9列之前),因此第67行的末尾也可能是问题所在。 另外,在React的JSX中,我们需要注意: - 在JSX标签中传递多个属性时,属性之间不需要逗号,而是用空格分开。例如: ```jsx <Component prop1={value1} prop2={value2} /> ``` 如果在JSX属性中错误地加了逗号,也会导致语法错误。 但是,根据错误信息期望的是逗号,所以更可能是上述非JSX上下文中的逗号缺失问题。 由于用户之前提供了一个引用(引用[1])中的代码,但那是一个虚拟列表的示例,与当前错误没有直接关系。用户当前的错误是在blank2/index.tsx文件中,所以我们需要关注那个文件。 用户现在需要解决的是第68行第9列的错误。因此,我们建议用户: 步骤1:打开`packages/front-module/src/pages/blank2/index.tsx`文件,定位到第68行。 步骤2:检查第68行第9列附近的代码,以及第67行末尾。 步骤3:重点检查是否有上面提到的几种情况(对象、数组、函数参数、接口等缺少逗号)。 步骤4:如果发现确实缺少逗号,则添加逗号。 步骤5:保存文件并重新运行,看错误是否消失。 如果用户无法自行确定,可以提供第67行到68行附近的代码片段,我们可以帮助进一步分析。 注意:有时错误可能是由于前一行缺少结束符号(比如括号、花括号)导致,但当前错误信息明确提示期望逗号,所以首先考虑逗号缺失。 下面是一个修复后的例子: 错误代码(第67行和第68行): ```typescript 67 | const state = { 68 | count: 0 69 | total: 100 | ^ 错误位置(68行第9列附近,因为解析器在count属性后没有看到逗号,所以在解析total时遇到意外标记) ``` 修复代码(在count属性后添加逗号): ```typescript const state = { count: 0, total: 100 }; ``` 这样错误就会消失。 如果用户提供的代码中,第68行第9列的位置是一个JSX标签,那么我们需要检查JSX的语法是否正确。例如: 错误示例(在JSX标签中错误使用逗号): ```jsx return ( <div> <h1>标题</h1> <p>内容,</p> {/* 这里正常 */} <ChildComponent prop1={value1}, {/* 错误:这里不应该有逗号 */} prop2={value2} /> </div> ); ``` 但在这种情况下,错误信息可能会不同,不过如果逗号出现在JSX属性之间,则确实会报错。如果错误发生在JSX内部,那么删除多余的逗号即可。 总之,根据错误信息,我们优先考虑在非JSX上下文中遗漏逗号的情况。 最后,建议用户如果问题仍然存在,可以粘贴出错误位置附近的代码(67-69行),以便更精确地诊断问题。 </think> 针对您的 `SyntaxError: Unexpected token, expected "," (68:9)` 错误,以下是逐步解决方案: ### 错误分析与解决步骤 根据错误位置(第 68 行第 9 列),最常见的原因是: 1. **对象属性间缺少逗号** 2. **JSX 属性语法错误** 3. **数组元素分隔符缺失** #### 步骤 1:检查对象语法 在 67-68 行附近的代码中,查找对象声明: ```typescript // ✘ 错误示例(缺少逗号) const data = { id: 1, // 67行 name: "Test" // 68行:此处报错 (68:9) value: 100 // 应为属性 } // ✓ 修复:添加逗号 const data = { id: 1, name: "Test", // 68行添加逗号 value: 100 } ``` #### 步骤 2:检查 JSX 属性 如果是 React 组件: ```tsx // ✘ 错误示例(属性间误用逗号) <Component prop1={value1} // 67prop2={value2} // 68行:JSX属性间不应有逗号 /> // ✓ 修复:移除逗号 <Component prop1={value1} // 67prop2={value2} // 68行 /> ``` #### 步骤 3:检查数组语法 ```typescript // ✘ 错误示例(元素间缺少逗号) const items = [ { id: 1 }, // 67行 { id: 2 } // 68行:缺少逗号 { id: 3 } ] // ✓ 修复:添加逗号 const items = [ { id: 1 }, { id: 2 }, // 68行添加逗号 { id: 3 } ] ``` ### 实际修复案例 参考您提供的虚拟列表示例: ```typescript const testData = useMemo(() => { return Array.from({ length: 100 }, (_, index) => ({ id: index, // 属性间必须有逗号 title: `测试项目 ${index + 1}`, // ← 检查此行结尾逗号 thumbnail: index % 3 === 0 ? 'img1;img2;img3' : 'img1', // ← 68行附近 description: `描述...` // 确认此行逗号 })); }, []); ``` **重点检查:** 1. `thumbnail` 属性结尾是否有逗号(第 68 行附近) 2. 最后一个属性是否**没有**逗号 ### 验证方法 1. 使用 VS Code 的 **Error Lens** 扩展实时显示错误 2. 命令行检查: ```bash cd C:\item\h0-front-master\packages\front-module npx tsc --noEmit src/pages/blank2/index.tsx ``` ### 预防措施 1. 配置 ESLint 规则: ```json // .eslintrc { "rules": { "comma-dangle": ["error", "always-multiline"], "object-curly-spacing": ["error", "always"] } } ``` 2. 使用 Prettier 自动格式化: ```json // .prettierrc { "trailingComma": "all", "bracketSpacing": true } ``` > **提示**:68:9 表示错误在第 68 行第 9 列字符处,请优先检查该位置是否为属性分隔位置[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值