<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Go on yafeiaa Blogs</title>
    <link>https://yafeiaa.github.io/tags/go/</link>
    <description>Recent content in Go on yafeiaa Blogs</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 14 Jan 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://yafeiaa.github.io/tags/go/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Agones SDK-Server 与 Allocator</title>
      <link>https://yafeiaa.github.io/posts/agones%E4%BD%93%E9%AA%8C/</link>
      <pubDate>Wed, 14 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://yafeiaa.github.io/posts/agones%E4%BD%93%E9%AA%8C/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;&#xA;&lt;p&gt;Agones 通过 SDK-Server 让 GameServer 自己管理生命周期状态。每个 GameServer 启动时会连接本地的 SDK Server，通过 gRPC API 同步状态。&lt;/p&gt;&#xA;&lt;p&gt;在实际部署时，sdk-server 会作为一个 sidecar 容器，和 gameserver 容器共享 network namespace，所以 gmaeserver 可以直接以 localhost 访问 sdk-server 的 api。&lt;/p&gt;&#xA;&lt;p&gt;sdk-server 作为 agones 和 gameserver 之间的状态同步器，负责将 gameserver 的状态同步给 agones，以及将 agones 的分配请求同步给 gameserver。&lt;/p&gt;&#xA;&lt;h2 id=&#34;allocator-service&#34;&gt;Allocator Service&lt;/h2&gt;&#xA;&lt;p&gt;Allocator 是 Agones 提供的 gRPC 服务，用于分配 GameServer。它监听集群中所有 Ready 状态的 GameServer，当收到分配请求时，选择一个合适的 GameServer 并将其状态改为 Allocated。&lt;/p&gt;&#xA;&lt;p&gt;Allocator 提供了两种分配方式：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;gRPC Service&lt;/strong&gt; - 直接调用 gRPC API（适合高性能、安全性要求高的场景，通过mtls认证）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Allocation API&lt;/strong&gt; - 通过 Kubernetes CRD &lt;code&gt;GameServerAllocation&lt;/code&gt;（更简单，通过k8s api调用）&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;核心-api&#34;&gt;核心 API&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ready()&lt;/strong&gt; - 标记就绪，可以被分配&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Health()&lt;/strong&gt; - 发送心跳，保持健康状态&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Shutdown()&lt;/strong&gt; - 通知关闭&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;SetAnnotation()&lt;/strong&gt; - 设置自定义信息（如 自定义的对外访问地址）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;WatchGameServer()&lt;/strong&gt; - 监听状态变化&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;状态流转&#34;&gt;状态流转&lt;/h2&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Port -&amp;gt; Ready -&amp;gt; Allocated -&amp;gt; Shutdown&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Port&lt;/strong&gt; - 刚启动，等待 Ready&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ready&lt;/strong&gt; - 调用 &lt;code&gt;Ready()&lt;/code&gt; 后进入，等待分配&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Allocated&lt;/strong&gt; - 被 match-maker 分配后进入，开始游戏逻辑&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Shutdown&lt;/strong&gt; - 调用 &lt;code&gt;Shutdown()&lt;/code&gt; 或收到关闭信号后进入&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;一个dedicate-server和-match-maker通过-sdk-server-和-allocator-交互的例子&#34;&gt;一个dedicate-server和 match-maker通过 sdk-server 和 allocator 交互的例子&lt;/h2&gt;&#xA;&lt;h3 id=&#34;dedicate-server&#34;&gt;dedicate-server&lt;/h3&gt;&#xA;&lt;p&gt;启动流程：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Minimatch 轻量级匹配服务使用体验</title>
      <link>https://yafeiaa.github.io/posts/minimatch%E5%AD%A6%E4%B9%A0/</link>
      <pubDate>Wed, 14 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://yafeiaa.github.io/posts/minimatch%E5%AD%A6%E4%B9%A0/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;&#xA;&lt;p&gt;最近在一个项目中，了解到了minimatch这个轻量级匹配服务，并借助minimatch实现了简单的match-maker服务，进行了学习。&lt;/p&gt;&#xA;&lt;p&gt;在游戏服务器匹配场景中，Open Match 是一个成熟的解决方案，但它的架构相对复杂，需要部署多个 Kubernetes 组件。在本地开发、或者不希望额外管理open-match的复杂性，只想实现 match 核心逻辑，minimatch 是一个很好的选择。&lt;/p&gt;&#xA;&lt;h2 id=&#34;核心概念&#34;&gt;核心概念&lt;/h2&gt;&#xA;&lt;h3 id=&#34;1-frontend-服务&#34;&gt;1. Frontend 服务&lt;/h3&gt;&#xA;&lt;p&gt;Frontend 负责接收玩家的匹配请求，创建和管理 Ticket。每个 Ticket 包含玩家的搜索条件，如地区、等级、角色等。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 创建 Ticket&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ticket&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;pb&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Ticket&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;SearchFields&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;pb&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SearchFields&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;Tags&lt;/span&gt;: []&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sprintf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;region:%s&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Region&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sprintf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;role:%s&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Role&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;DoubleArgs&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;map&lt;/span&gt;[&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;]&lt;span style=&#34;color:#66d9ef&#34;&gt;float64&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;level&amp;#34;&lt;/span&gt;: float64(&lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Level&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;2-backend-服务&#34;&gt;2. Backend 服务&lt;/h3&gt;&#xA;&lt;p&gt;Backend 是匹配的核心，它定期（每个 tick）从 Redis 获取活跃的 Tickets，执行匹配逻辑，并将匹配结果分配给 GameServer。&lt;/p&gt;&#xA;&lt;p&gt;Backend 包含三个关键组件：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;MatchProfile&lt;/strong&gt;：定义匹配规则，包括多个 Pool（匹配池），每个 Pool 可以设置过滤条件（如地区、等级范围）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;MatchFunction&lt;/strong&gt;：实现具体的匹配算法，根据 Pool 中的 Tickets 生成 Match&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Assigner&lt;/strong&gt;：将匹配结果分配给 GameServer&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;3-匹配流程&#34;&gt;3. 匹配流程&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;玩家请求 → Frontend 创建 Ticket → Redis 存储&#xA;                                    ↓&#xA;Backend 定时轮询（通过提前设置的tick） → 获取 Tickets → MatchFunction 匹配 → Assigner 分配 GameServer → 更新 Ticket 状态&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;实践与-agones-集成实现一个简单的match-maker&#34;&gt;实践：与 Agones 集成实现一个简单的match-maker&lt;/h2&gt;&#xA;&lt;h3 id=&#34;架构设计&#34;&gt;架构设计&lt;/h3&gt;&#xA;&lt;p&gt;我们将 minimatch 的 Frontend 和 Backend 集成到同一个服务中，通过 HTTP API 对外提供服务：&lt;/p&gt;</description>
    </item>
    <item>
      <title>protoc-gen-cloudevents-go：从 Protobuf 自动生成类型安全的事件驱动代码</title>
      <link>https://yafeiaa.github.io/posts/protoc-gen-cloudevents-go-introduction/</link>
      <pubDate>Tue, 25 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://yafeiaa.github.io/posts/protoc-gen-cloudevents-go-introduction/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;&#xA;&lt;p&gt;在微服务架构和事件驱动系统中，我们经常需要编写大量的事件发布和订阅代码。这些代码往往充斥着：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;❌ &lt;strong&gt;字符串魔法值&lt;/strong&gt;：事件类型容易拼写错误&lt;/li&gt;&#xA;&lt;li&gt;❌ &lt;strong&gt;类型不安全&lt;/strong&gt;：使用 &lt;code&gt;map[string]interface{}&lt;/code&gt; 传递数据&lt;/li&gt;&#xA;&lt;li&gt;❌ &lt;strong&gt;重复代码&lt;/strong&gt;：每个事件都要手写发布/订阅函数&lt;/li&gt;&#xA;&lt;li&gt;❌ &lt;strong&gt;难以维护&lt;/strong&gt;：事件定义分散在各处，缺乏统一管理&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;为了解决这些问题，我开发了 &lt;strong&gt;protoc-gen-cloudevents-go&lt;/strong&gt; —— 一个基于 &lt;a href=&#34;https://cloudevents.io/&#34;&gt;CloudEvents&lt;/a&gt; 标准的 Protobuf 代码生成器。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href=&#34;https://github.com/yafeiaa/protoc-gen-cloudevents-go&#34;&gt;https://github.com/yafeiaa/protoc-gen-cloudevents-go&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;核心理念&#34;&gt;核心理念&lt;/h2&gt;&#xA;&lt;h3 id=&#34;单一数据源single-source-of-truth&#34;&gt;单一数据源（Single Source of Truth）&lt;/h3&gt;&#xA;&lt;p&gt;使用 Protobuf 定义事件结构，自动生成类型安全的发布/订阅代码：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-protobuf&#34; data-lang=&#34;protobuf&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;syntax &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;proto3&amp;#34;&lt;/span&gt;;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; myapp&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;events;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cloudevents/event_meta.proto&amp;#34;&lt;/span&gt;;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 用户注册事件&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;message&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;UserRegisteredPayload&lt;/span&gt; {&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;option&lt;/span&gt; (cloudevents.event_meta) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    event_type&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;myapp.user.registered&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    description&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;用户注册成功&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  };&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; user_id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; email &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;int64&lt;/span&gt; registered_at &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一条命令生成所有代码：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;protoc &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;  -I . &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;  --go_out&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;. &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;  --cloudevents_out&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;. &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;  events.proto&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;类型安全--零样板代码&#34;&gt;类型安全 + 零样板代码&lt;/h3&gt;&#xA;&lt;p&gt;&lt;strong&gt;传统方式&lt;/strong&gt; vs &lt;strong&gt;使用 protoc-gen-cloudevents&lt;/strong&gt;：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Go 服务性能优化实战：从 pprof 分析到落地方案</title>
      <link>https://yafeiaa.github.io/posts/go-performance-optimization-from-pprof-to-practice/</link>
      <pubDate>Fri, 31 Oct 2025 00:00:00 +0000</pubDate>
      <guid>https://yafeiaa.github.io/posts/go-performance-optimization-from-pprof-to-practice/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;&#xA;&lt;p&gt;在生产环境中，Go 服务的性能问题往往不是单一原因造成的。本文基于真实的性能优化经验，通过 pprof 工具分析一个高并发 gRPC 服务的性能瓶颈，并给出具体的优化方案和代码实现。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;优化成果&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;CPU 使用率降低 30-50%&lt;/li&gt;&#xA;&lt;li&gt;内存对象数降低 65-95%&lt;/li&gt;&#xA;&lt;li&gt;P99 延迟降低 35-55%&lt;/li&gt;&#xA;&lt;li&gt;QPS 提升 50-80%&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;一性能分析的正确姿势&#34;&gt;一、性能分析的正确姿势&lt;/h2&gt;&#xA;&lt;h3 id=&#34;11-pprof-数据的类型&#34;&gt;1.1 pprof 数据的类型&lt;/h3&gt;&#xA;&lt;p&gt;Go 的 pprof 提供了多个维度的 profile 数据：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;┌─────────────────────────────────────────────────────┐&#xA;│                  pprof 数据类型                       │&#xA;├─────────────────────────────────────────────────────┤&#xA;│ CPU Profile      │ 程序运行时 CPU 占用情况            │&#xA;│ Heap (inuse)     │ 当前正在使用的内存                │&#xA;│ Heap (alloc)     │ 历史累计的内存分配                │&#xA;│ Goroutine        │ 当前 goroutine 的数量和状态       │&#xA;│ Block            │ 同步原语（锁）的阻塞情况           │&#xA;│ Mutex            │ 互斥锁的竞争情况                  │&#xA;└─────────────────────────────────────────────────────┘&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;关键洞察&lt;/strong&gt;：不同的 profile 数据能揭示不同的问题&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
