碗碗米线 發表於 2025-11-20 22:31:00

13. Spring AI 的观测性

<h1 id="13-spring-ai-的观测性">13. Spring AI 的观测性</h1>
<p>@</p><div class="toc"><div class="toc-container-header">目录</div><ul><li>13. Spring AI 的观测性<ul><li>观测性<ul><li>为什么Spring AI应用急需可观测性?<ul><li><font style="color: rgba(63, 63, 63, 1)">AI服务成本失控的痛点</font></li><li><font style="color: rgba(63, 63, 63, 1)">Spring AI可观测性的价值</font></li></ul></li><li>实战演练:构建可观测的Spring AI翻译应用<ul><li><font style="color: rgba(63, 63, 63, 1)">第一步:Spring AI项目初始化</font></li><li><font style="color: rgba(63, 63, 63, 1)">第二步:Spring AI客户端配置</font></li><li><font style="color: rgba(63, 63, 63, 1)">第三步:构建Spring AI翻译服务</font></li><li><font style="color: rgba(63, 63, 63, 1)">第四步:Spring AI翻译API测试</font></li></ul></li><li><font style="color: rgba(255, 255, 255, 1); background-color: rgba(15, 76, 129, 1)">Spring AI监控指标深度解析</font><ul><li><font style="color: rgba(63, 63, 63, 1)">核心指标1:Spring AI操作性能监控</font></li><li><font style="color: rgba(63, 63, 63, 1)">核心指标2:Spring AI Token使用量精准追踪</font></li></ul></li></ul></li></ul></li><li>最后:</li></ul></div><p></p>
<h2 id="观测性">观测性</h2>
<h3 id="为什么spring-ai应用急需可观测性">为什么Spring AI应用急需可观测性?</h3>
<h4 id="ai服务成本失控的痛点"><font style="color: rgba(63, 63, 63, 1)">AI服务成本失控的痛点</font></h4>
<p><font style="color: rgba(63, 63, 63, 1)">在企业级AI应用中,使用DeepSeek、OpenAI、Google Gemini或Azure OpenAI等服务时,成本控制是一个严峻挑战:</font></p>
<ul>
<li><strong>Token消耗不透明</strong><font style="color: rgba(63, 63, 63, 1)">:无法精确了解每次AI调用的成本</font></li>
<li><font style="color: rgba(63, 63, 63, 1)"> </font><strong>费用增长失控</strong><font style="color: rgba(63, 63, 63, 1)">:大规模应用中,AI服务费用可能呈指数级增长</font></li>
<li><font style="color: rgba(63, 63, 63, 1)"> </font><strong>性能瓶颈难定位</strong><font style="color: rgba(63, 63, 63, 1)">:AI调用链路复杂,问题排查困难</font></li>
<li><font style="color: rgba(63, 63, 63, 1)"> </font><strong>资源使用不合理</strong><font style="color: rgba(63, 63, 63, 1)">:缺乏数据支撑的优化决策</font></li>
</ul>
<h4 id="spring-ai可观测性的价值"><font style="color: rgba(63, 63, 63, 1)">Spring AI可观测性的价值</font></h4>
<p><font style="color: rgba(63, 63, 63, 1)">Spring AI的可观测性功能为这些痛点提供了完美解决方案:</font></p>
<ul>
<li><font style="color: rgba(63, 63, 63, 1)"></font><font style="color: rgba(63, 63, 63, 1)">✅</font><strong><font style="color: rgba(15, 76, 129, 1)">精准Token监控</font></strong><font style="color: rgba(63, 63, 63, 1)">:实时追踪输入/输出Token消耗,精确到每次调用</font></li>
<li><font style="color: rgba(63, 63, 63, 1)"></font><font style="color: rgba(63, 63, 63, 1)">✅</font><strong><font style="color: rgba(15, 76, 129, 1)">智能成本控制</font></strong><font style="color: rgba(63, 63, 63, 1)">:基于使用统计制定成本优化策略</font></li>
<li><font style="color: rgba(63, 63, 63, 1)"></font><font style="color: rgba(63, 63, 63, 1)">✅</font><strong><font style="color: rgba(15, 76, 129, 1)">深度性能分析</font></strong><font style="color: rgba(63, 63, 63, 1)">:识别AI调用瓶颈,优化响应时间</font></li>
<li><font style="color: rgba(63, 63, 63, 1)"></font><font style="color: rgba(63, 63, 63, 1)">✅</font><strong><font style="color: rgba(15, 76, 129, 1)">完整链路追踪</font></strong><font style="color: rgba(63, 63, 63, 1)">:端到端记录请求在Spring AI应用中的完整流转</font></li>
</ul>
<h3 id="实战演练构建可观测的spring-ai翻译应用">实战演练:构建可观测的Spring AI翻译应用</h3>
<h4 id="第一步spring-ai项目初始化"><font style="color: rgba(63, 63, 63, 1)">第一步:Spring AI项目初始化</font></h4>
<p><font style="color: rgba(63, 63, 63, 1)">在</font><font style="color: rgba(87, 107, 149, 1)">start.spring.io</font><sup><font style="color: rgba(87, 107, 149, 1)"></font></sup><font style="color: rgba(63, 63, 63, 1)">创建Spring Boot项目,集成Spring AI核心依赖:</font></p>
<p><strong><font style="color: rgba(15, 76, 129, 1)">Maven依赖配置(Spring AI BOM管理):</font></strong></p>
<pre><code class="language-xml">&lt;!--百炼--&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.alibaba.cloud.ai&lt;/groupId&gt;
&lt;artifactId&gt;spring-ai-alibaba-starter-dashscope&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;!-- Spring Boot Actuator 监控 --&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-actuator&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;!--web--&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
&lt;/dependency&gt;
</code></pre>
<h4 id="第二步spring-ai客户端配置"><font style="color: rgba(63, 63, 63, 1)">第二步:Spring AI客户端配置</font></h4>
<p><strong><font style="color: rgba(15, 76, 129, 1)">主应用类配置:</font></strong></p>
<pre><code class="language-java">@SpringBootApplication
publicclassSpringAiTranslationApplication {

    publicstaticvoidmain(String[] args) {
      SpringApplication.run(SpringAiTranslationApplication.class, args);
    }

    @Bean
    public ChatClient chatClient(ChatClient.Builder builder) {
      return builder.build();
    }
}
</code></pre>
<p><strong><font style="color: rgba(15, 76, 129, 1)">Spring AI配置文件:</font></strong></p>
<pre><code class="language-yaml"># Spring AI 可观测性配置
management:
endpoints:
    web:
      exposure:
      include:"*"
endpoint:
    health:
      show-details:always
metrics:
    export:
      prometheus:
      enabled:true

spring:
threads:
    virtual:
      enabled:true
ai:
    deepseek:
      api-key:${DEEPSEEK_API_KEY}
      chat:
      options:
          model:deepseek-chat
          temperature: 0.8
</code></pre>
<p><strong><font style="color: rgba(15, 76, 129, 1)">环境变量设置:</font></strong></p>
<p>export DEEPSEEK_API_KEY=your-deepseek-api-key</p>
<h4 id="第三步构建spring-ai翻译服务"><font style="color: rgba(63, 63, 63, 1)">第三步:构建Spring AI翻译服务</font></h4>
<p><strong><font style="color: rgba(15, 76, 129, 1)">智能翻译控制器:</font></strong></p>
<pre><code class="language-java">@RestController
@RequestMapping("/api/v1")
@RequiredArgsConstructor
@Slf4j
public class SpringAiTranslationController {

    private final ChatModel chatModel;

    @PostMapping("/translate")
    public TranslationResponse translate(@RequestBody TranslationRequest request) {

      log.info("Spring AI翻译请求: {} -&gt; {}", request.getSourceLanguage(), request.getTargetLanguage());
      
      String prompt= String.format(
                "作为专业翻译助手,请将以下%s文本翻译成%s,保持原文的语气和风格:\n%s",
                request.getSourceLanguage(),
                request.getTargetLanguage(),
                request.getText()
      );

      String translatedText= chatModel.call(prompt);
      
      return TranslationResponse.builder()
                .originalText(request.getText())
                .translatedText(translatedText)
                .sourceLanguage(request.getSourceLanguage())
                .targetLanguage(request.getTargetLanguage())
                .timestamp(System.currentTimeMillis())
                .build();
    }
}

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
class TranslationRequest {
    private String text;
    private String sourceLanguage;
    private String targetLanguage;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
class TranslationResponse {
    private String originalText;
    private String translatedText;
    private String sourceLanguage;
    private String targetLanguage;
    private Long timestamp;
}
</code></pre>
<h4 id="第四步spring-ai翻译api测试"><font style="color: rgba(63, 63, 63, 1)">第四步:Spring AI翻译API测试</font></h4>
<pre><code class="language-json">curl -X POST http://localhost:8080/api/v1/translate
-H "Content-Type: application/json"
-d '{
"text": "Spring AI makes AI integration incredibly simple and powerful",
"sourceLanguage": "英语",
"targetLanguage": "中文"
}'

# 响应示例
{
"originalText": "Spring AI makes AI integration incredibly simple and powerful",
"translatedText": "Spring AI让AI集成变得极其简单而强大",
"sourceLanguage": "英语",
"targetLanguage": "中文",
"timestamp": 1704067200000
}
</code></pre>
<h3 id="spring-ai监控指标深度解析"><font style="color: rgba(255, 255, 255, 1); background-color: rgba(15, 76, 129, 1)">Spring AI监控指标深度解析</font></h3>
<h4 id="核心指标1spring-ai操作性能监控"><font style="color: rgba(63, 63, 63, 1)">核心指标1:Spring AI操作性能监控</font></h4>
<p><strong>指标端点</strong>:/actuator/metrics/spring.ai.chat.client</p>
<pre><code class="language-json">{
"name":"spring.ai.chat.client.operation",
"description":"Spring AI ChatClient操作性能指标",
"baseUnit":"seconds",
"measurements":[
    {
      "statistic":"COUNT",
      "value":15
    },
    {
      "statistic":"TOTAL_TIME",
      "value":8.456780293
    },
    {
      "statistic":"MAX",
      "value":2.123904083
    }
],
"availableTags":[
    {
      "tag":"gen_ai.operation.name",
      "values":["framework"]
    },
    {
      "tag":"spring.ai.kind",
      "values":["chat_client"]
    }
]
}
</code></pre>
<p><strong><font style="color: rgba(15, 76, 129, 1)">业务价值</font></strong><font style="color: rgba(63, 63, 63, 1)">:</font></p>
<ul>
<li><font style="color: rgba(63, 63, 63, 1)">监控Spring AI翻译服务调用频次</font></li>
<li><font style="color: rgba(63, 63, 63, 1)">分析Spring AI响应时间分布</font></li>
<li><font style="color: rgba(63, 63, 63, 1)">识别Spring AI性能瓶颈</font></li>
</ul>
<h4 id="核心指标2spring-ai-token使用量精准追踪"><font style="color: rgba(63, 63, 63, 1)">核心指标2:Spring AI Token使用量精准追踪</font></h4>
<p><strong>指标端点</strong> /actuator/metrics/gen_ai.client.token.usage</p>
<pre><code class="language-json">{
"name":"gen_ai.client.token.usage",
"description":"Spring AI Token使用量统计",
"measurements":[
    {
      "statistic":"COUNT",
      "value":1250
    }
],
"availableTags":[
    {
      "tag":"gen_ai.response.model",
      "values":["deepseek-chat"]
    },
    {
      "tag":"gen_ai.request.model",
      "values":["deepseek-chat"]
    },
    {
      "tag":"gen_ai.token.type",
      "values":[
      "output",
      "input",
      "total"
      ]
    }
]
}
</code></pre>
<p><strong>成本控制价值</strong><font style="color: rgba(63, 63, 63, 1)">:</font></p>
<ul>
<li>精确计算Spring AI服务成本</li>
<li>优化Prompt设计降低Token消耗</li>
<li>制定基于使用量的预算策略</li>
</ul>
<h1 id="最后">最后:</h1>
<blockquote>
<p>“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”</p>
<p><img alt="在这里插入图片描述" loading="lazy" src="https://img2024.cnblogs.com/blog/3084824/202511/3084824-20251120223111932-583195925.gif" class="lazyload"></p>
</blockquote><br><br>
来源:https://www.cnblogs.com/TheMagicalRainbowSea/p/19249786
頁: [1]
查看完整版本: 13. Spring AI 的观测性