精选

民办的上限究竟在哪?——从小小小蓝厂到宇宙互联网终点站🛫🛫🛫

哈喽,大家好!我是 KingYen.

新的一期,小憨碎碎念~

又见面啦。又是一次人生的转折点。也希望这段经历能够帮助到正在求职或者正在迷茫的朋友们。

记得一个月前,在编程导航讲到自己上岸小小小蓝厂的 AI 安全实习,没想到现在马上又要开始新的一段旅途了。

23F88D0F-6C07-48CB-8A4F-BC5A2D474F0F.jpeg

转眼大三结束了,身边的朋友考研的考研、考公的考公、实习的实习。但是这其中,又有多少的不易和心酸。就几天前,应该是刚刚拿到新的offer,看到牛客上面几篇帖子在聊什么“不是211就不要投大厂了”、“不是985没有活路”。第一次感受到这个行业有如此多的🤡。我觉得我这个人还是慢性情的,做事情比较随心所欲。反正今天就写文章了,不妨就和大家一起来聊一聊,不过这部分内容由于是碎碎念,就放到最后的章节啦,我们先来谈论一点干货吧。

先放个 vivo 内推吧,欢迎大家投递~

image.png

走过的路比你读过的书更重要

在这里放一份面经,后续有时间会慢慢来聊一些相关的内容。项目背景是基于 Tiptap 做的协同编辑

一、WebSocket

  1. 单节点百万级WebSocket是如何实现的,有没有做过测试?怎么进行压测?Banchmark怎么做的?
  2. 业务后期如何进行水平扩展,如何确保同一房间下的用户都落在同一台服务器上?如果有的用户落到其他节点如何处理?
  3. Web端和移动端有哪些区别?考虑技术方案有哪些不同的侧重点?为什么考虑使用etcd来存储元数据而不是依赖现有的nacos?
  4. 断线重连如何处理,如何做的重连机制?(没考虑全面)

二、SSR/CSR水合问题

  1. 为什么要在SSR期间携带客户端元素?那当时为什么要考虑使用 Taptip?有没有其他的实现方案,为什么选择了这一套技术方案?
  2. 为什么要做内容同步优化,作用是什么?觉得还有什么可行的优化方案或者没有考虑到的地方?
  1. 单节点下百万级 Web Socket 连接支持
  • 技术背景
    • 读写频繁场景
      • 如果使用 sync.Mutex/sync.RWMutex 会带来频繁的锁竞争现象
      • 如果使用 sync.Map 由于写操作频繁,会带来高额的 gc 压力
  • 解决方案
    • 快照机制 + 分段拷贝 + 池化(最终采用)
    • 分段锁
  1. SSR/CSR 水合问题
    1. 问题分析
      • 错误症状:
        text
        复制代码
        Error: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties.
      • 根本原因:
        1. 协作编辑器的客户端特定功能:在服务器端渲染时无法访问 WebSocket、Y.js 等客户端特定功能
        2. 条件渲染不一致:isClient 状态变化导致服务器端和客户端第一次渲染不同的组件
        3. 浏览器扩展干扰:Grammarly 等扩展会在客户端添加属性,造成不匹配
    2. 修复方案
      1. 重构 SSR/CSR 切换策略
        • 修复前的问题:
          javascript
          复制代码
          // ❌ 问题:服务器端 isClient=false,客户端立即变为 true const [isClient, setIsClient] = React.useState(false) React.useEffect(() => { setIsClient(true) // 立即切换,造成不匹配 }, []) if (isClient) { return <CollaborationEditorComponent /> } else { return <BasicEditorComponent /> }
        • 修复后的方案:
          javascript
          复制代码
          // ✅ 解决:统一初始渲染,延迟升级 const [isHydrated, setIsHydrated] = React.useState(false) React.useEffect(() => { const timer = setTimeout(() => { setIsHydrated(true) // 延迟设置,确保 DOM 稳定 }, 50) return () => clearTimeout(timer) }, []) // 始终先渲染基础编辑器,确保一致性 if (!isHydrated) { return <BasicEditorComponent /> } // 水合完成后才升级到协作编辑器 return <CollaborationEditorComponent />
      2. 协作功能的客户端检测
        • Hook 中的客户端检测:
        javascript
        复制代码
        // ✅ 只在客户端创建协作提供者 const [isClient, setIsClient] = React.useState(false) React.useEffect(() => { setIsClient(true) }, []) const provider = React.useMemo(() => { // 只在客户端创建 provider if (!isClient) return null return new HocuspocusProvider({ // ... 配置 }) }, [doc, roomId, isClient])
      • 条件扩展加载:
        javascript
        复制代码
        // ✅ 基于客户端状态的扩展数组 const extensions = React.useMemo(() => { const baseExtensions = [ StarterKit, // ... 其他基础扩展 ] // 只在客户端且 provider 可用时添加协作扩展 if (isClient && provider) { baseExtensions.push( Collaboration.configure({ document: doc }), CollaborationCursor.configure({ provider, user: currentUser }) ) } return baseExtensions }, [isClient, provider, doc, currentUser])
      1. 浏览器扩展干扰防护
        • Layout 级别的防护:
        html
        复制代码
        // ✅ 在 body 元素上添加 suppressHydrationWarning <body className={`${fontSans.variable} ${fontMono.variable} font-sans antialiased`} suppressHydrationWarning // 抑制扩展引起的属性不匹配警告 >
      2. 内容同步优化
        • SSR 内容保护:
          javascript
          复制代码
          // ✅ 保护 SSR 期间的内容变化 const [ssrContent, setSsrContent] = React.useState<any | null>(null) React.useEffect(() => { if (!isHydrated && content) { setSsrContent(content) // 保存 SSR 期间的内容 } }, [content, isHydrated]) React.useEffect(() => { if (isHydrated && ssrContent) { setContent(ssrContent) // 恢复内容 setSsrContent(null) } }, [isHydrated, ssrContent, setContent])
    3. 修复效果
      1. 水合一致性:
        • 服务器端和客户端第一次渲染完全一致
        • 避免了组件类型突然切换
        • 延迟升级到协作功能,确保稳定性
      2. 协作功能健壮性:
        • 客户端特定功能只在客户端加载
        • 优雅的降级处理(协作失败时回退到基础编辑器)
        • 状态更新安全(在正确的生命周期中进行)
      3. 性能优化:
        • 减少不必要的重渲染
        • 条件扩展加载,降低初始包大小
        • 智能内容同步,避免丢失

有人在埋头赶路,有人在贩卖焦虑

当一群人去 talk 学历问题的时候,我时常就在想,当你去谈论学历问题的时候,你有没有回头想过你为此付出了多少呢?我也承认,我学历不好,求职期间也经历了很多迷茫的时间,也经历过不少迷途、走过不少弯路。自我质疑过、甚至几经想要放弃,就在今年四五月份吧,我甚至连自己的退路都找好了。也不怕大家笑话,现在多多少少也是众多大厂牛马中的一员了,想不到曾经也有转行的想法吧。我觉得不可笑,因为当时也挺多人,劝我认命。没学历,没背景、没实习,在现在这个行业啥都不是。

但是无论在各行各业,最重要的就是抓住机遇。埋头赶路,莫问前途。其实这句话是各行各业成功的前提。我记得四月左右吧。有朋友找实习,运营和活动策划岗位,其实也拿到了几家不错的offer,甚至还给她内推过字节 Dev AI 的产品运营。可是短短的几个月的时间,她已经放弃去卷实习了,选择回家去休息一下。我上周还劝过我一个朋友,和她说实在不行就回家好好放松一下,秋招再战。不过很幸运的是,就在上周,我和她一块拿到了字节的 offer。马上又可以并肩作战了,蛮期待的~

最近圈子里话题度特别高的一个好像是牛客上的“小浪学长”,另一个就是 Vibe Coding 吧。其实我个人也不太玩牛客,也不熟悉。不过就事论事的来谈一谈。我也一直在帮朋友改简历、挖亮点、指导面试,不过我只是觉得力所能及的帮一帮。大家有问题的时候,我也会力所能及的提供一些帮助。(p.s.在这里道个歉,可能有时候在工作或者比较忙,消息可能看一眼点了之后就没有消息提醒了,后面忙完可能就忘了或者回复不及时,也希望大家能谅解)。关于买课这种事情,其实我也不反对,我也经常去购置一些课程,真的是有很多高质量的内容。但是如果质量平平的话,我觉得就emmm。可能本身就是一个理科直男,做内容也好、工作也好,对质量有着一些强迫症。不想将就,其实之前 MCP 之类的其实都写过文章,后来觉得把,网上同质的内容太多了,也就没有发了。因为觉得带不给大家新的认知、有用的认知,那其实就是在给大家获取有效知识造成困扰。在我这里,也一定是内容大于流量了。不过关于买课这种事情,真的不歧视、不鼓吹,这种事情只能说是“周瑜打黄盖——一个愿打,一个愿挨”。

最近也听到挺多学弟学妹想去考研,其实本身也不是什么坏事情吧。人嘛,有目标总是好的,自己做出的所有的选择也会由自己买单。其实,无论说考研也好、考公也好抑或是就业,只有自身能力足够了,才能在这个社会上立足。“打铁还需自身硬”这句话其实也还没有过时。最近 AI 蛮火的嘛,对各行各业的影响也在逐渐变大。有人觉得 AI 能力都这么强了,那还努力去学这么多东西干嘛,反正再卷也卷不过 AI 嘛。其实,任何一个工具都有利有弊,运用得好,那它将是你去提升自己效率最大的法宝,如果用不好,那只是淹死骆驼的最后一根稻草。最简单的例子,就单纯写 prompt 这件事情,现在绝大多数还是傻瓜式的提问,有一部分花过心思的,知道去通过CoT等方式去写 prompt,但是今天绝大多数的 LLM 编写 prompt 的能力基本上都非常强大了。技术是在与时俱进的,也需要大家持续去学习的。

大概就唠这么多吧。也希望大家能够找到自己的路,坚持着走下去。相信总有一天,会上岸的! 送给大家我高中时期特别喜欢的一句话,“山积而高,则积而长”

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
KingYen
下载 APP