diff --git a/build.sh b/build.sh index acce01d66..2af146afc 100644 --- a/build.sh +++ b/build.sh @@ -1,3 +1,11 @@ -NODE_OPTIONS=--max-old-space-size=14096 npm run build +# 先切换到指定的 Node.js 版本 sudo n +NODE_OPTIONS=--max-old-space-size=24096 npm run build -# 优惠券地址;https://bugstack.cn/images/article/zsxq/zsxq-youhuiquan.png \ No newline at end of file +# 优惠券地址;https://bugstack.cn/images/article/zsxq/zsxq-youhuiquan.png +# node 版本切换;https://www.cnblogs.com/fengchong0925/p/18489658 +# 全局安装;npm install -g n +# 安装指定node版本;sudo -E n 18.16.0 +# 查看已安装的版本列表;n list +# 删除指定版本;n rm 16.13.2 +# 切换node版本;sudo n +# 查看切换版本;node -v npm -v \ No newline at end of file diff --git a/docs/.vuepress/components/LockArticle.vue b/docs/.vuepress/components/LockArticle.vue index ad153b655..cbebdc22f 100644 --- a/docs/.vuepress/components/LockArticle.vue +++ b/docs/.vuepress/components/LockArticle.vue @@ -95,7 +95,7 @@ t._lock(articleObj); } else { t._unlock(articleObj); - t.setCookie("_unlock", "success", 7); + t.setCookie("_unlock", "success", 45); } }, error: function (data) { @@ -170,13 +170,7 @@ if (!value) { return await this.getFingerprintId(); } - - if (value.length <= 12) { - return value.substring(value.length - 6).toUpperCase(); - } - - const currentMonth = new Date().getMonth() + 1; // 获取当前月份(JavaScript 中月份是从 0 开始的) - return value.substring(currentMonth, currentMonth + 6).toUpperCase(); + return value.substring(value.length - 6).toUpperCase(); } else{ return await this.getFingerprintId(); } @@ -211,9 +205,9 @@ if (parts.length === 2) return parts.pop().split(";").shift(); }, - setCookie: function (name, value, hours){ + setCookie: function (name, value, day){ let exp = new Date(); - exp.setTime(exp.getTime() + hours*60*60*1000); + exp.setTime(exp.getTime() + day*24*60*60*1000); // ;path=/ cookie全站有效 document.cookie = name + "="+ escape (value) + ";path=/;expires=" + exp.toGMTString(); }, diff --git a/docs/.vuepress/components/RoadMap.vue b/docs/.vuepress/components/RoadMap.vue index 700d00053..71cd5ab96 100644 --- a/docs/.vuepress/components/RoadMap.vue +++ b/docs/.vuepress/components/RoadMap.vue @@ -1867,7 +1867,7 @@ src="https://bugstack.cn/images/roadmap/08-测试/082-性能测试/1-Jemeter/images/Jemeter.png"> - Jemeter + JMeter diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 105aaf0af..50871fed0 100755 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -33,7 +33,7 @@ module.exports = { "/": { lang: "zh-CN", title: "小傅哥 bugstack 虫洞栈", - description: "包含: Java 基础,面经手册,Netty4.x,手写Spring,用Java实现JVM,重学Java设计模式,SpringBoot中间件开发,IDEA插件开发,Lottery抽奖系统,字节码编程..." + description: "包含: Java 基础,面经手册,Netty4.x,手写MyBatis,用Java实现JVM,重学Java设计模式,SpringBoot中间件开发,IDEA插件开发,大营销抽奖系统,Java 实战项目训练,字节码编程..." } }, head: [ @@ -47,7 +47,7 @@ module.exports = { ["meta", {"http-equiv": "Expires", content: "0"}], ["meta", { name: "keywords", - content: "小傅哥, bugstack 虫洞栈, 实战项目, 应用项目, 面试项目, DDD抽奖系统,数据结构,重学Java设计模式, 字节码编程, 中间件, 手写Spring, 手写MyBatis,Java基础, 面经手册,Java面试题,API网关,SpringBoot Stater, ChatGPT" + content: "欢迎来到小傅哥的编程世界,这里是bugstack虫洞栈!无论你是Java初学者还是资深开发者,我们都为你准备了丰富的学习资源和实战项目,包括Java基础教程、实战项目指南、应用项目开发、Java面试题解析、重学Java设计模式、字节码编程、手写Spring与MyBatis、API网关与中间件、DDD抽奖系统、SpringBoot Starter开发,以及ChatGPT与AI技术的应用。我们致力于为你提供最优质的学习体验,帮助你在Java开发的道路上不断进步。欢迎访问我们的官方网站获取更多资源,并加入我们的社交媒体平台,与全球开发者一起交流学习。" }], ["meta", {name: "apple-mobile-web-app-capable", content: "yes"}], ['script', @@ -185,7 +185,10 @@ module.exports = { text: '导读', link: '/md/other/guide-to-reading.md' }, { - text: '路书', link: '/md/road-map/road-map.md' + text: '编程路书', link: '/md/road-map/road-map.md' + }, + { + text: 'AI Agent', link: '/md/ai/spring-ai.md' }, { text: '算法', @@ -205,184 +208,185 @@ module.exports = { ] }, { - text: 'Java', + text: '开发技术', items: [ { - text: '面经手册', - link: '/md/java/interview/2020-07-28-面经手册 · 开篇《面试官都问我啥》.md' - }, - { - text: '用Java实现JVM', - link: '/md/java/develop-jvm/2019-05-01-用Java实现JVM第一章《命令行工具》.md' - }, - { - text: '基础技术', - link: '/md/java/core/2020-01-06-[源码分析]咋嘞?你的IDEA过期了吧!加个Jar包就破解了,为什么?.md' - } - ] - }, - { - text: 'Spring', - items: [ - { - text: 'Spring 手撸专栏', - link: '/md/spring/develop-spring/2021-05-16-第1章:开篇介绍,手写Spring能给你带来什么?.md' - }, - { - text: 'MyBatis 手撸专栏', - link: '/md/spring/develop-mybatis/2022-03-20-第1章:开篇介绍,手写Mybatis能给你带来什么?.md' - }, - { - text: 'Spring Cloud', - link: '/md/spring/spring-cloud/2019-10-31-Spring Cloud零《总有一偏概述告诉你SpringCloud是什么》.md' + text: 'Java', + items: [ + { + text: '面经手册', + link: '/md/java/interview/2020-07-28-面经手册 · 开篇《面试官都问我啥》.md' + }, + { + text: '用Java实现JVM', + link: '/md/java/develop-jvm/2019-05-01-用Java实现JVM第一章《命令行工具》.md' + }, + { + text: '基础技术', + link: '/md/java/core/2020-01-06-[源码分析]咋嘞?你的IDEA过期了吧!加个Jar包就破解了,为什么?.md' + } + ] }, { - text: '源码分析(Mybatis、Quartz)', - link: '/md/spring/source-code/2019-12-25-[源码分析]Mybatis接口没有实现类为什么可以执行增删改查.md' - } - ] - }, - { - text: '面向对象', - items: [ - { - text: '重学Java设计模式', + text: 'Spring', items: [ { - text: '创建型模式', - link: '/md/develop/design-pattern/2020-05-20-重学Java设计模式《实战工厂方法模式》.md' + text: 'Spring 手撸专栏', + link: '/md/spring/develop-spring/2021-05-16-第1章:开篇介绍,手写Spring能给你带来什么?.md' }, { - text: '结构型模式', - link: '/md/develop/design-pattern/2020-06-02-重学 Java 设计模式《适配器模式》.md' + text: 'MyBatis 手撸专栏', + link: '/md/spring/develop-mybatis/2022-03-20-第1章:开篇介绍,手写Mybatis能给你带来什么?.md' }, { - text: '行为型模式', - link: '/md/develop/design-pattern/2020-06-18-重学 Java 设计模式《实战责任链模式》.md' + text: 'Spring Cloud', + link: '/md/spring/spring-cloud/2019-10-31-Spring Cloud零《总有一偏概述告诉你SpringCloud是什么》.md' + }, + { + text: '源码分析(Mybatis、Quartz)', + link: '/md/spring/source-code/2019-12-25-[源码分析]Mybatis接口没有实现类为什么可以执行增删改查.md' } ] }, { - text: '系统架构', + text: '面向对象', items: [ { - text: 'DDD 专题', + text: '重学Java设计模式-创建型模式', + link: '/md/develop/design-pattern/2020-05-20-重学Java设计模式《实战工厂方法模式》.md' + }, + { + text: '重学Java设计模式-结构型模式', + link: '/md/develop/design-pattern/2020-06-02-重学 Java 设计模式《适配器模式》.md' + }, + { + text: '重学Java设计模式-行为型模式', + link: '/md/develop/design-pattern/2020-06-18-重学 Java 设计模式《实战责任链模式》.md' + }, + { + text: '系统架构-DDD 专题', link: '/md/develop/framework/ddd/2019-10-15-DDD专题案例一《初识领域驱动设计DDD落地》.md' }, { - text: '工程框架', + text: '系统架构-工程框架', link: '/md/develop/framework/frame/2019-12-22-架构框架搭建一《单体应用服务之SSM整合:Spring4 + SpringMvc + Mybatis》.md' }, { - text: '架构方案', + text: '系统架构-架构方案', link: '/md/develop/framework/scheme/2021-02-04-基于IDEA插件开发和字节码插桩技术,实现研发交付质量自动分析.md' + }, + { + text: '标准-开发规范&事故', + link: '/md/develop/standard/2020-09-14-一次代码评审,差点过不了试用期!.md' } ] }, { - text: '标准', + text: 'Netty 4.x', items: [ { - text: '开发规范&事故', - link: '/md/develop/standard/2020-09-14-一次代码评审,差点过不了试用期!.md' - } + text: '基础入门篇', + link: '/md/netty/base/2019-07-30-netty案例,netty4.1基础入门篇零《初入JavaIO之门BIO、NIO、AIO实战练习》.md' + }, + { + text: '中级拓展篇', + link: '/md/netty/expand/2019-08-16-netty案例,netty4.1中级拓展篇一《Netty与SpringBoot整合》.md' + }, + { + text: '高级应用篇', + link: '/md/netty/application/2019-09-01-手写RPC框架第一章《自定义配置xml》.md' + }, + { + text: '源码分析篇', + link: '/md/netty/source-code/2019-09-10-netty案例,netty4.1源码分析篇一《NioEventLoopGroup源码分析》.md' + }, ] - } - ] - }, - { - text: '中间件', - items: [ - { - text: 'SpringBoot 中间件开发', - link: '/md/assembly/middleware/2019-12-02-SpringBoot服务治理中间件之统一白名单验证.md' - }, - { - text: 'IDEA Plugin 开发手册', - link: '/md/assembly/idea-plugin/2021-08-27-技术调研,IDEA 插件怎么开发?.md' }, { - text: 'API网关:中间件设计和实践', - link: '/md/assembly/api-gateway/api-gateway.md' - } - ] - }, - { - text: 'Netty 4.x', - items: [ - { - text: '基础入门篇', - link: '/md/netty/base/2019-07-30-netty案例,netty4.1基础入门篇零《初入JavaIO之门BIO、NIO、AIO实战练习》.md' - }, - { - text: '中级拓展篇', - link: '/md/netty/expand/2019-08-16-netty案例,netty4.1中级拓展篇一《Netty与SpringBoot整合》.md' - }, - { - text: '高级应用篇', - link: '/md/netty/application/2019-09-01-手写RPC框架第一章《自定义配置xml》.md' - }, - { - text: '源码分析篇', - link: '/md/netty/source-code/2019-09-10-netty案例,netty4.1源码分析篇一《NioEventLoopGroup源码分析》.md' - }, - ] - }, - { - text: '字节码编程', - items: [ - { - text: '框架', items: [ + text: '字节码编程', + items: [ { - text: 'ASM', + text: '框架-ASM', link: '/md/bytecode/asm/2020-03-25-[ASM字节码编程]如果你只写CRUD,那这种技术你永远碰不到.md' }, { - text: 'Javassist', + text: '框架-Javassist', link: '/md/bytecode/javassist/2020-04-19-字节码编程,Javassist篇一《基于javassist的第一个案例helloworld》.md' }, { - text: 'Byte-Buddy', + text: '框架-Byte-Buddy', link: '/md/bytecode/byte-buddy/2020-05-08-字节码编程,Byte-buddy篇一《基于Byte Buddy语法创建的第一个HelloWorld》.md' + }, + { + text: '全链路监控-JavaAgent', + link: '/md/bytecode/agent/2019-07-10-基于JavaAgent的全链路监控一《嗨!JavaAgent》.md' + }, + { + text: '文档-ASM-DOC', + link: '/md/bytecode/asm-document/1引言.md' } ] }, { - text: '全链路监控', items: [ + text: '部署', + items: [ { - text: 'JavaAgent', - link: '/md/bytecode/agent/2019-07-10-基于JavaAgent的全链路监控一《嗨!JavaAgent》.md' + text: '部署工具', + link: '/md/devops/2023-04-18-tool.md' } ] }, - { - text: '文档', items: [ - {text: 'ASM-DOC', link: '/md/bytecode/asm-document/1引言.md'} - ] - } ] }, - { - text: '部署', - link: '/md/devops/2023-04-18-tool.md' - }, { text: '💯实战项目', items: [ + { + text: '创新类型(AI)', items: [ + { + text: 'AI Agent 脚手架 + 场景应用', + link: '/md/project/ai-agent-scaffold/ai-agent-scaffold.md' + }, + { + text: 'AI MCP Gateway 网关服务系统(更新中)', + link: '/md/project/ai-mcp-gateway/ai-mcp-gateway.md' + }, + { + text: 'AI Agent 拖拉拽 + 动态配置', + link: '/md/project/ai-knowledge/ai-knowledge.md' + }, + { + text: 'OpenAI 代码自动评审', + link: 'https://bugstack.cn/md/zsxq/project/openai-code-review.html' + }, + { + text: 'OpenAI 大模型应用服务体系构建', + link: '/md/project/chatgpt/chatgpt.md' + }, + { + text: 'ChatGPT AI 问答助手', + link: '/md/project/chatbot-api/chatbot-api.md' + }, + { + text: 'OpenAI SDK 组件项目', + link: 'https://bugstack.cn/md/zsxq/project/openai-sdk-java.html' + } + ] + }, { text: '业务类型', items: [ { - text: '小型支付电商系统(新)', + text: '拼团交易平台系统', + link: '/md/project/group-buy-market/group-buy-market.md' + }, + { + text: '小型支付电商系统', link: '/md/project/s-pay-mall/s-pay-mall.md' }, { text: '大营销平台系统', link: '/md/project/big-market/big-market.md' }, - { - text: 'OpenAi 大模型应用服务体系构建', - link: '/md/project/chatgpt/chatgpt.md' - }, { text: 'Lottery 分布式抽奖系统', link: '/md/project/lottery/introduce/Lottery抽奖系统.md' @@ -390,18 +394,18 @@ module.exports = { { text: 'IM Netty 仿PC端微信', link: '/md/project/im/2020-03-04-《Netty+JavaFx实战:仿桌面版微信聊天》.md' - }, - { - text: 'ChatGPT AI 问答助手', - link: '/md/project/chatbot-api/chatbot-api.md' } ] }, { text: '组件类型', items: [ { - text: 'OpenAI 代码自动评审', - link: 'https://bugstack.cn/md/zsxq/project/openai-code-review.html' + text: '本地任务消息组件', + link: '/md/project/local-task-message/local-task-message.md' + }, + { + text: '通用技术组件 - 🔧扳手工程', + link: 'https://bugstack.cn/md/zsxq/project/xfg-wrench.html' }, { text: '透视业务流程-监控系统', @@ -430,11 +434,19 @@ module.exports = { ] }, { - text: '其他类型', items: [ + text: '自学类型', items: [ { - text: '小场景训练营', + text: '场景案例', link: '/md/project/ddd-scene-solution/alipay-sandbox.md' }, + { + text: '吉祥外卖', + link: '/md/project/lucky-tackout/lucky-tackout.md' + }, + { + text: '钓鱼佬', + link: '/md/project/xfg-fish-pond/xfg-fish-pond.md' + }, ] }, ] @@ -444,7 +456,7 @@ module.exports = { link: '/md/zsxq/introduce.md' }, { - text: '📝产品', + text: '📝产品(ai ide)', items: [ { text: '出版物', items: [ @@ -486,7 +498,15 @@ module.exports = { text: '插件', items: [ { text: '💱 IDEA Plugin vo2dto —— 对象转换插件', - link: '/md/product/idea-plugin/vo2dto.md' + link: '/md/product/idea-plugin/vo2dto-v2.5.5.md' + }, + ] + }, + { + text: 'AI IDE', items: [ + { + text: '👨🏻‍💻WaLiCode,AI IDE Coding', + link: '/md/product/software/walicode.md' }, ] }, @@ -546,10 +566,16 @@ module.exports = { "/md/project/chatbot-api/": getBarProjectChatBotApi(), "/md/project/big-market/": getBarBigMarket(), "/md/project/s-pay-mall/": getBarSPayMall(), - "/md/project/ddd-scene-solution/": getBarDDDSceneSolution(), + "/md/project/group-buy-market/": getBarGroupBuyMarket(), + "/md/project/ai-knowledge/": getBarAiRagKnowledge(), + "/md/project/ai-agent-scaffold/": getBarAIAgentScaffold(), + "/md/project/ai-mcp-gateway/": getBarAIMCPGateway(), + "/md/project/local-task-message/": getBarLocalTaskMessage(), + "/md/project/": getBarDDDSceneSolution(), "/md/zsxq/": getBarZSXQ(), "/md/product/": getBarProduct(), "/md/road-map/": genBarGuide(), + "/md/ai/": genBarAI(), "/md/about/": genBarAbout() } } @@ -572,15 +598,52 @@ function genBarOther() { ] } +function genBarAI() { + return [ + { + title: "框架", + collapsable: false, + sidebarDepth: 0, + children: [ + "spring-ai.md", + "google-adk.md", + ] + }, + { + title: "组件", + collapsable: false, + sidebarDepth: 0, + children: [ + "agent-skill.md", + "a2a.md", + ] + }, + { + title: "工具", + collapsable: false, + sidebarDepth: 0, + children: [ + "draw.io.md", + "qclaw.md", + "openclaw.md", + "ai-ssh-opencode.md", + "github-models.md", + "trae.md", + ] + }, + ] +} + function genBarGuide() { return [ { - title: "简明教程(2)", + title: "简明教程(3)", collapsable: false, - sidebarDepth: 2, + sidebarDepth: 3, children: [ "road-map.md", - "introduce.md" + "introduce.md", + "cainiao.md", ] }, { @@ -593,11 +656,12 @@ function genBarGuide() { ] }, { - title: "系统架构(9)", + title: "系统架构(10)", collapsable: false, sidebarDepth: 0, children: [ "mvc.md", + "ddd-guide-00.md", "ddd-guide-01.md", "ddd-guide-02.md", "ddd-guide-03.md", @@ -609,20 +673,26 @@ function genBarGuide() { ] }, { - title: "开发环境(6)", + title: "开发环境(12)", collapsable: false, sidebarDepth: 0, children: [ + "tool.md", "intellij-idea.md", "maven.md", + "maven-central.md", "git.md", "github.md", "gitcode.md", "gitee.md", + "mac.md", + "nas.md", + "trae.md", + "joycode.md", ] }, { - title: "开发技术(16)", + title: "开发技术(19)", collapsable: true, sidebarDepth: 0, children: [ @@ -642,6 +712,19 @@ function genBarGuide() { "redis.md", "ignite.md", "canal.md", + "springcloud-feign.md", + "springcloud-stream.md", + "springcloud-bus.md", + ] + }, + { + title: "授权框架(3)", + collapsable: true, + sidebarDepth: 0, + children: [ + "spring-security.md", + "spring-oauth2.md", + "spring-oauth2-sso-01.md", ] }, { @@ -653,20 +736,37 @@ function genBarGuide() { "guava.md", "http.md", "ratelimiter.md", + "disruptor.md", + ] + }, + { + title: "智能组件(8)", + collapsable: true, + sidebarDepth: 0, + children: [ "spring-ai.md", + "google-adk.md", + "agent-skill.md", + "a2a.md", + "draw.io.md", + "ai-ssh-opencode.md", + "github-models.md", + "openclaw.md", ] }, { - title: "工程测试(2)", + title: "工程测试(4)", collapsable: true, sidebarDepth: 0, children: [ "mock.md", "jmeter.md", + "intellij-idea-remote-jvm-debug.md", + "arex-test.md", ] }, { - title: "质量监控(4)", + title: "质量监控(7)", collapsable: true, sidebarDepth: 0, children: [ @@ -674,32 +774,45 @@ function genBarGuide() { "grafana.md", "elk.md", "dump-mat.md", + "dump-visualvm.md", + "arthas.md", + "13scan-jdumpspider.md", ] }, { - title: "发布部署(11)", + title: "发布部署(20)", collapsable: true, sidebarDepth: 0, children: [ + "cloud-server.md", "linux.md", + "1panel.md", + "docker-what.md", "docker.md", + "docker-install.md", + "docker-deploy-project.md", "portainer.md", - "nginx.md", - "ssl.md", - "ssl-httpsok.md", - "jenkins.md", - "buddy.md", + "aliyun-workbench.md", "github-actions-workflows.md", + "buddy.md", "private-docker-hub.md", "docker-idea.md", + "jenkins.md", + "frp.md", + "nginx.md", + "ssl.md", + "ssl-httpsok.md", + "ollama.md", + "aigc.md", ] }, { - title: "应用网关(3)", + title: "应用网关(4)", collapsable: true, sidebarDepth: 0, children: [ "higress.md", + "higress-ai.md", "springcloud-gateway.md", "apisix.md", ] @@ -830,6 +943,7 @@ function genAlgorithmModel() { "2023-02-12-chat-gpt.md", "2023-02-18-gpt2-chitchat.md", "2023-05-21-chatglm-6b.md", + "autoglm-phone-agent.md", ] } ] @@ -1762,9 +1876,10 @@ function getBarZSXQ() { children: [ "introduce.md", "material/guide.md", - "material/student-learn-all.md", + // "material/student-learn-all.md", "material/student-learn-line.md", - "material/student-learn-recruit.md", + // "material/student-learn-recruit.md", + "material/student-learn-advanced.md", ] }, { @@ -1775,22 +1890,36 @@ function getBarZSXQ() { "material/architecture_design.md", "material/interview.md", "material/dialogue-skills.md", + "material/speaking-skills.md", "material/notes.md", "material/study-experience.md", "material/exam.md", ] }, + { + title: "创新项目(AI)", + collapsable: false, + sidebarDepth: 0, + children: [ + "project/ai-agent-scaffold.md", + "project/ai-mcp-gateway.md", + "project/ai-knowledge.md", + "project/openai-code-review.md", + "project/chatgpt.md", + "project/chatbot-api.md", + "project/openai-sdk-java.md", + ] + }, { title: "业务项目", collapsable: false, sidebarDepth: 0, children: [ + "project/group-buy-market.md", "project/s-pay-mall.md", "project/big-market.md", - "project/chatgpt.md", "project/lottery.md", "project/im.md", - "project/chatbot-api.md", ] }, { @@ -1798,11 +1927,11 @@ function getBarZSXQ() { collapsable: false, sidebarDepth: 0, children: [ - "project/openai-code-review.md", + "project/local-task-message.md", + "project/xfg-wrench.md", "project/business-behavior-monitor.md", "project/dynamic-thread-pool.md", "project/ltzf-sdk-java.md", - "project/openai-sdk-java.md", "project/api-gateway.md", "project/springboot-starter.md", "booklet/idea-plugin.md", @@ -1858,6 +1987,7 @@ function getBarZSXQ() { collapsable: true, sidebarDepth: 0, children: [ + "memorabilia/sideline.md", "memorabilia/seven-thousand.md", "memorabilia/ten-thousand.md", "memorabilia/overall.md", @@ -1868,6 +1998,9 @@ function getBarZSXQ() { "memorabilia/student-offer.md", "memorabilia/project-plan-v2406.md", "memorabilia/xiaofuge-team.md", + "memorabilia/java-interview-experience.md", + "memorabilia/campus-recruitment-offer.md", + "memorabilia/job-hire-jd.md", ] } ] @@ -1875,6 +2008,14 @@ function getBarZSXQ() { function getBarProduct() { return [ + { + title: "AI IDE", + collapsable: false, + sidebarDepth: 0, + children: [ + "software/walicode.md", + ] + }, { title: "出版物", collapsable: false, @@ -1903,8 +2044,10 @@ function getBarProduct() { children: [ "idea-plugin/vo2dto.md", "idea-plugin/vo2dto-v2.5.1.md", + "idea-plugin/vo2dto-v2.5.5.md", ] }, + ] } @@ -2168,6 +2311,371 @@ function getBarProjectChatGPT() { ] } +function getBarAIMCPGateway() { + return [ + { + title: "介绍", + collapsable: false, + sidebarDepth: 0, + children: [ + "ai-mcp-gateway.md", + ] + }, + { + title: "第1部分:系统设计", + collapsable: false, + sidebarDepth: 0, + children: [ + "第1-1节:网关需求分析.md", + "第1-2节:系统建模设计.md", + "第1-3节:网关协议表.md", + "第1-4节:升级网关库表.md", + ] + }, + { + title: "第2部分:协议分析", + collapsable: false, + sidebarDepth: 0, + children: [ + "第2-1节:MCP服务实现.md", + "第2-2节:MCP代理调用.md", + "第2-3节:MCP通信协议.md", + ] + }, + { + title: "第3部分:网关实现", + collapsable: false, + sidebarDepth: 0, + children: [ + "第3-1节:工程初始化创建.md", + "第3-2节:会话管理服务实现.md", + "第3-3节:会话接口编排.md", + "第3-4节:会话消息结构设计.md", + "第3-5节:消息协议处理案例.md", + "第3-6节:基础层数据处理.md", + "第3-7节:协议消息处理-Initialize.md", + "第3-8节:协议消息处理-ToolsList.md", + "第3-9节:协议消息处理-ToolsCall.md", + "第3-10节:评审库表升级代码.md", + "第3-11节:会话内容编排处理.md", + "第3-12节:鉴权功能领域服务.md", + "第3-13节:鉴权功能编排处理.md", + "第3-14节:解析Swagger标准OpenAPI协议.md", + "第3-15节:协议域-协议解析处理.md", + "第3-16节:协议域-协议存储处理.md", + "第3-17节:网关域-配置数据存储(CRUD).md", + "第3-18节:管理端-API功能编排串联.md", + "第3-19节:管理端-API与UI对接.md", + "none.md", + ] + }, + ] +} + +function getBarLocalTaskMessage() { + return [ + { + title: "介绍", + collapsable: false, + sidebarDepth: 0, + children: [ + "local-task-message.md", + ] + }, + { + title: "课程", + collapsable: false, + sidebarDepth: 0, + children: [ + "第1节:组件需求分析.md", + "第2节:SpringEvent事件消息.md", + "第3节:任务表设计和数据写入.md", + "第4节:通知策略处理.md", + "第5节:动态任务补偿处理.md", + "第6节:切面拦截任务操作.md", + ] + } + ] +} + +function getBarAIAgentScaffold() { + return [ + { + title: "介绍", + collapsable: false, + sidebarDepth: 0, + children: [ + "ai-agent-scaffold.md", + "notes.md", + ] + }, + { + title: "1阶段 - 做设计", + collapsable: false, + sidebarDepth: 0, + children: [ + "part-1/第1-1节:脚手架需求分析.md", + "part-1/第1-2节:系统架构设计.md", + ] + }, + { + title: "2阶段 - 智能体", + collapsable: false, + sidebarDepth: 0, + children: [ + "part-2/第2-1节:工程初始化创建.md", + "part-2/第2-2节:Api功能测试.md", + "part-2/第2-3节:智能体配置表设计.md", + "part-2/第2-4节:装配域结构化定义.md", + "part-2/第2-5节:装配域节点-AiApiNode.md", + "part-2/第2-6节:装配域节点-ChatModelNode.md", + "part-2/第2-7节:装配域节点-AgentNode.md", + "part-2/第2-8节:装配域节点-AgentWorkflowNode.md", + "part-2/第2-9节:装配域节点-Loop、Parallel、Sequential.md", + "part-2/第2-10节:装配域节点-RunnerNode.md", + "part-2/第2-11节:智能体加载使用验证.md", + "part-2/第2-12节:增强装配-RunnerNode.md", + "part-2/第2-13节:增强装配-AgentWorkflowNode.md", + "part-2/第2-14节:增强装配-本地mcp.md", + "part-2/第2-15节:增强装配-回调plugin.md", + "part-2/第2-16节:fix-多模态能力使用.md", + "part-2/第2-17节:会话服务接口实现-service.md", + "part-2/第2-18节:会话服务接口实现-trigger.md", + "part-2/第2-19节:会话服务接口对接-ui.md", + "part-2/第2-20节:增强装配-skills.md", + ] + }, + { + title: "3阶段 - 脚手架", + collapsable: false, + sidebarDepth: 0, + children: [ + "part-3/第3-1节:Maven脚手架配置.md", + "part-3/第3-2节:上传jar到maven仓库.md", + "part-3/第3-3节:部署脚手架网页.md", + ] + }, + { + title: "4阶段 - 场景 - draw.io", + collapsable: false, + sidebarDepth: 0, + children: [ + "part-4/第4-0节:ai + draw.io 产品设计.md", + "part-4/第4-1节:初始化工程搭建.md", + "part-4/第4-2节:在页面嵌入draw.io组件和对话框.md", + "part-4/第4-3节:智能体API接口对接.md", + "part-4/第4-4节:AI+用户+DrawIO,交互式画图.md", + "part-4/第4-5节:ai-draw-io,云服务器部署.md", + ] + }, + { + title: "5阶段 - 场景 - MobileOpenClaw", + collapsable: false, + sidebarDepth: 0, + children: [ + "part-5/第5-1节:初始化工程搭建.md", + "part-5/第5-2节:手机网关动作调度设计.md", + "part-5/第5-3节:服务端网络通信设计(Netty).md", + "part-5/第5-4节:初步通过智能体,操作手机设备.md", + "part-5/第5-5节:智能体工作流设计.md", + "part-5/第5-6节:智能体异步响应展示执行过程.md", + "part-5/第5-7节:使用AutoGLM-Phone-9B构建手机智能体.md", + "part-5/第5-8节:多版本安卓版本策略支持.md", + "part-5/第5-9节:会话上下文细化处理.md", + ] + } + ] +} + +function getBarAiRagKnowledge() { + return [ + { + title: "介绍", + collapsable: false, + sidebarDepth: 0, + children: [ + "ai-knowledge.md", + "notes.md", + ] + }, + { + title: "1阶段 RAG spring-ai v0.8.1", + collapsable: false, + sidebarDepth: 0, + children: [ + "第1节:AI RAG 知识库,项目介绍.md", + "第2节:初始化知识库工程&提交代码.md", + "第3接:Ollama DeepSeek 流式应答接口实现.md", + "第4节:Ollama DeepSeek 流式应答页面对接.md", + "第5节:Ollama RAG 知识库上传、解析和验证.md", + "第6节:Ollama RAG 知识库接口服务实现.md", + "第7节:基于AI工具,设计知识库UI和接口对接.md", + "第8节:Git仓库代码库解析到知识库.md", + "第9节:扩展OpenAI模型对接,以及完整AI对接.md", + "第10节:云服务器部署知识库(Docker、Nginx).md", + ] + }, + { + title: "2阶段 MCP spring-ai v1.0.0", + collapsable: false, + sidebarDepth: 0, + children: [ + "第11节:吃上细糠,升级SpringAI框架.md", + "第12节:康庄大道,上手 AI MCP 工作流.md", + "第13节,道山学海,实现MCP自动发帖服务.md", + "第14节:海纳百川,上线MCP自动发帖服务.md", + "第15节:川流不息,实现MCP微信公众号消息通知服务.md", + "第16节:息息相通,MCP 服务部署上线(sse 模式).md", + ] + }, + { + title: "3阶段 Agent spring-ai v1.0.0", + collapsable: false, + sidebarDepth: 0, + children: [ + "agent/第3-0节:AiAgent 项目介绍和系统演示.md", + "agent/第3-1节:Ai Agent 业务流程、系统架构、库表设计说明.md", + "agent/第3-2节:初始化项目工程.md", + "agent/第3-3节:AiAgent测试案例.md", + "agent/第3-4节:根据AiAgent案例,设计库表.md", + "agent/第3-5节:多数据源和Mapper配置.md", + "agent/第3-6节:数据加载模型设计.md", + "agent/第3-7节:动态实例化客户端API.md", + "agent/第3-8节:动态实例化对话模型.md", + "agent/第3-9节:动态实例化对话客户端.md", + "agent/第3-10节:Agent执行链路分析.md", + "agent/第3-11节:Agent执行链路设计.md", + "agent/第3-12节:Agent服务接口和UI对接.md", + "agent/第3-13节,Agent-ELK日志分析场景.md", + "agent/第3-14节,Agent-Prometheus监控分析场景.md", + "agent/第3-15节:FlowAgent执行链路分析.md", + "agent/第3-16节:FlowAgent执行链路设计.md", + "agent/第3-17节:增加调度器策略执行Agent链路.md", + "agent/第3-18节:动态执行智能体任务.md", + "agent/第3-19节:拖拉拽编排数据存储.md", + "agent/第3-20节:Agent管理后台实现.md", + "agent/第3-21节:在云服务器部署上线.md", + ] + }, + { + title: "扩展", + collapsable: false, + sidebarDepth: 0, + children: [ + "ext/ai-agent-flowgram.md", + "ext/ai-agent-mcp-auth.md", + "ext/ai-agent-auto.md", + "ext/ai-agent-notes.md", + "ext/ai-agent-job.md", + "promotion/AI MCP 已经帮我“干活”了!.md", + "promotion/AI MCP 再这么用下去,可就要”创业“变现了呀!.md", + ] + } + ] +} + +function getBarGroupBuyMarket() { + return [ + { + title: "介绍", + collapsable: false, + sidebarDepth: 0, + children: [ + "group-buy-market.md", + "notes.md", + "qa.md", + ] + }, + { + title: "第1部分:系统设计", + collapsable: false, + sidebarDepth: 0, + children: [ + "第1-1节:拼团需求分析.md", + "第1-2节:拼团库表设计.md", + "第1-3节:研发系统设计.md", + ] + }, + { + title: "第2部分:服务实现", + collapsable: false, + sidebarDepth: 0, + children: [ + "第2-1节:初始工程搭建.md", + "第2-2节:试算模型抽象模板设计.md", + "第2-3节:多线程异步数据加载.md", + "第2-4节:策略模式优惠折扣计算.md", + "第2-5节:人群标签数据采集.md", + "第2-6节:拆分库表关联关系.md", + "第2-7节:人群标签节点过滤.md", + "第2-8节:动态配置开关操作.md", + "第2-9节:拼团交易营销锁单.md", + "第2-10节:责任链抽象模板设计.md", + "第2-11节:交易规则责任链过滤.md", + "第2-12节:拼团组队结算统计.md", + "第2-13节:交易结算责任链过滤.md", + "第2-14节:拼团回调通知任务.md", + "第2-15节:根据UI展示封装接口.md", + "第2-16节:引入RabbitMQ分布式多端消费.md", + "第2-17节:发送MQ结算消息.md", + "第2-18节:消费MQ结算消息.md", + "第2-19节:独占锁和无锁化场景运用.md", + "第2-20节:函数式数据缓存和降级到DB处理.md", + "第2-21节:引入扳手工程.md", + "第2-22节:动态限流配置.md", + "第2-23节:ELK+AI MCP检索.md", + "第2-24节:系统监控+AIMCP分析.md", + "第2-25节:逆向流程场景分析.md", + "第2-26节:未支付退单流程.md", + "第2-27节:已支付未成团退单.md", + "第2-28节:已支付已成团退单.md", + "第2-29节:退单锁单量恢复.md", + "第2-30节:设计模式重构退单.md", + "第2-31节:退订接口和定时任务.md", + ] + }, + { + title: "第3部分:外部对接", + collapsable: false, + sidebarDepth: 0, + children: [ + "第3-1节:DeepSeek设计拼团UI.md", + "第3-2节:DeepSeek处理UI与接口对接.md", + "第3-3节:小商城对接营销锁单.md", + "第3-4节:小商城对接营销结算.md", + "第3-5节:小商城UI与接口对接.md", + "第3-6节:通过浏览器指纹获取登录ticket无痕登录.md", + "第3-7节:用户订单列表和退单UI.md", + "第3-8节:退单退款服务对接.md", + ] + }, + { + title: "第4部分:开发运维", + collapsable: false, + sidebarDepth: 0, + children: [ + "第4-1节:第1阶段部署云环境.md", + "第4-2节:第2阶段部署云环境.md", + "第4-3节:第3阶段部署云环境.md", + ] + }, + { + title: "番外 - 课程阶段产物", + collapsable: false, + sidebarDepth: 0, + children: [ + "promotion/group-buy-market-v1.md", + "promotion/group-buy-market-v2.md", + "promotion/group-buy-market-v3.md", + "promotion/group-buy-market-v4.md", + "promotion/group-buy-market-v5.md", + "promotion/group-buy-market-v6.md", + "promotion/group-buy-market-v7.md", + ] + } + ] +} + function getBarSPayMall() { return [ { @@ -2209,6 +2717,8 @@ function getBarSPayMall() { "part-3-mvc/第4节:商品下单.md", "part-3-mvc/第5节:对接支付.md", "part-3-mvc/第6节:支付回调.md", + "part-3-mvc/第7节:前端页面.md", + "part-3-mvc/第8节:Docker构建和部署.md", ] }, { @@ -2222,6 +2732,8 @@ function getBarSPayMall() { "part-3-ddd/第4节:DDD 重构,商品下单.md", "part-3-ddd/第5节:DDD 重构,对接支付.md", "part-3-ddd/第6节:DDD 重构,支付回调.md", + "part-3-ddd/第7节:前端页面.md", + "part-3-ddd/第8节:Docker构建和部署.md", ] }, { @@ -2232,7 +2744,6 @@ function getBarSPayMall() { "part-4/第1节:natapp 内网穿透.md", "part-4/第2节:微信公众号测试评审申请.md", "part-4/第3节:支付宝沙箱申请.md", - "part-4/第4节:项目上线.md", ] } ] @@ -2247,7 +2758,9 @@ function getBarBigMarket() { children: [ "big-market.md", "ddd.md", + "system-design-diagram.md", "notes.md", + "qa.md", ] }, { @@ -2269,6 +2782,7 @@ function getBarBigMarket() { "dev-ops/第1节:使用脚手架创建工程.md", "dev-ops/第2节:第一阶段完成抽奖部署.md", "dev-ops/第3节:引入Nacos+Dubbo框架.md", + "dev-ops/openai_big_market.md", ] }, { @@ -2303,12 +2817,12 @@ function getBarBigMarket() { "api/第25节:积分发奖服务实现.md", "api/第26节:积分领域调额服务.md", "api/第27节:积分支付兑换商品.md", + "api/第28节:积分应用场景接口实现.md", "api/第29节:分布式动态配置活动降级.md", "api/第30节:分布式动态限流和熔断.md", "api/第31节:分库分表数据同步ES.md", "api/第32节:ES-ORM多数据源配置使用.md", "api/第33节:xxl-job分布式任务调度.md", - "none.md", ] }, { @@ -2326,10 +2840,22 @@ function getBarBigMarket() { }, { title: "第5部分:后台管理", - collapsable: true, + collapsable: false, sidebarDepth: 0, children: [ "erp/第1节:初始后台运营页面.md", + "erp/第2节:querys模块提供查询接口.md", + ] + }, + { + title: "第6部分:外部对接", + collapsable: false, + sidebarDepth: 0, + children: [ + "distributed/第1节:对接OpenAI项目额度奖品接口.md", + "distributed/第2节:营销页面接口封装.md", + "distributed/第3节:RPC接口对接支付返利.md", + "distributed/第4节:活动上架发布预热对接.md", ] }, { @@ -2343,6 +2869,7 @@ function getBarBigMarket() { "extra/big-market-v4.md", "extra/big-market-v5.md", "extra/big-market-v6.md", + "extra/big-market-v7.md", ] } ] @@ -2351,14 +2878,23 @@ function getBarBigMarket() { function getBarDDDSceneSolution() { return [ { - title: "课程", + title: "案例", collapsable: false, sidebarDepth: 0, children: [ - "alipay-sandbox.md", - "openai-tldraw.md", - "sensitive-word-content-moderation.md", - "weixin-login.md", + "ddd-scene-solution/alipay-sandbox.md", + "ddd-scene-solution/openai-tldraw.md", + "ddd-scene-solution/sensitive-word-content-moderation.md", + "ddd-scene-solution/weixin-login.md", + ] + }, + { + title: "项目", + collapsable: false, + sidebarDepth: 0, + children: [ + "lucky-tackout/lucky-tackout.md", + "xfg-fish-pond/xfg-fish-pond.md", ] }, ] @@ -2454,16 +2990,26 @@ function getBarProjectLottery() { function genBarAbout() { return [ { - title: "关于自己", + title: "年终总结", collapsable: false, sidebarDepth: 0, children: [ - "me/about-me.md", - "me/2020-03-31-大学四年到毕业工作5年的学习路线资源汇总.md", "me/2020-12-27-2020总结,作为技术号主的一年!.md", "me/2022-01-27-2021年,小傅哥の年终总结!.md", "me/2023-01-02-2022年,小傅哥の年终总结.md", "me/2024-02-07-2023年,小傅哥の年终总结.md", + "me/2025-01-05-2024年,小傅哥の年终总结!.md", + "me/2025-01-04-2025年,小傅哥の年终总结.md", + ] + }, + { + title: "关于自己", + collapsable: false, + sidebarDepth: 0, + children: [ + "me/about-me.md", + "me/2020-03-31-大学四年到毕业工作5年的学习路线资源汇总.md", + "me/2020-07-25-12天,这本《重学Java设计模式》PDF书籍下载量9k,新增粉丝1400人,Github上全球推荐榜.md", "me/2020-08-25-13年毕业,用两年时间从外包走进互联网大厂.md", "me/2020-10-09-让人怪不好意思的,粉丝破万,用了1年!.md", @@ -2482,6 +3028,8 @@ function genBarAbout() { "me/2023-05-07-51假期代码旅游.md", "me/2024-01-09-从T4到T8,4年时间,4次晋升。技术提升最快的那几年,我做了什么?.md", "me/2024-01-28-大厂架构师小傅哥,上学时都做过哪些项目?.md", + "me/2024-11-17-gold-content.md", + "me/2025-07-03-嘎嘎强,嘎嘎哒学v2.0.md", ] }, { @@ -2527,6 +3075,9 @@ function genBarAbout() { "job/2023-03-19-你简历没项目,你得遭老罪喽!.md", "job/2023-07-11-面试官都问你啥了.md", "job/2023-09-13-工作内推.md", + "job/2024-09-08-阿里P7,就是很多人的天花板吗?.md", + "job/2025-11-16-现在转AI应用开发,是不是个机会?.md", + "job/2026-03-21-古法编程,是否还重要?.md", ] } ]; diff --git a/docs/.vuepress/public/images/article/about/about-241117-01.gif b/docs/.vuepress/public/images/article/about/about-241117-01.gif new file mode 100644 index 000000000..07bee7721 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-241117-01.gif differ diff --git a/docs/.vuepress/public/images/article/about/about-241117-02.png b/docs/.vuepress/public/images/article/about/about-241117-02.png new file mode 100644 index 000000000..c81295834 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-241117-02.png differ diff --git a/docs/.vuepress/public/images/article/about/about-241117-03.png b/docs/.vuepress/public/images/article/about/about-241117-03.png new file mode 100644 index 000000000..248346345 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-241117-03.png differ diff --git a/docs/.vuepress/public/images/article/about/about-241117-04.png b/docs/.vuepress/public/images/article/about/about-241117-04.png new file mode 100644 index 000000000..c4a64f1e2 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-241117-04.png differ diff --git a/docs/.vuepress/public/images/article/about/about-241117-05.png b/docs/.vuepress/public/images/article/about/about-241117-05.png new file mode 100644 index 000000000..ef474068f Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-241117-05.png differ diff --git a/docs/.vuepress/public/images/article/about/about-241117-06.png b/docs/.vuepress/public/images/article/about/about-241117-06.png new file mode 100644 index 000000000..1f1d5d2dd Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-241117-06.png differ diff --git a/docs/.vuepress/public/images/article/about/about-241117-07.png b/docs/.vuepress/public/images/article/about/about-241117-07.png new file mode 100644 index 000000000..275bd7b5e Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-241117-07.png differ diff --git a/docs/.vuepress/public/images/article/about/about-250713-01.png b/docs/.vuepress/public/images/article/about/about-250713-01.png new file mode 100644 index 000000000..86b676bd2 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-250713-01.png differ diff --git a/docs/.vuepress/public/images/article/about/about-250713-02.png b/docs/.vuepress/public/images/article/about/about-250713-02.png new file mode 100644 index 000000000..0b2121fe6 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-250713-02.png differ diff --git a/docs/.vuepress/public/images/article/about/about-250713-03.png b/docs/.vuepress/public/images/article/about/about-250713-03.png new file mode 100644 index 000000000..3d4172f37 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-250713-03.png differ diff --git a/docs/.vuepress/public/images/article/about/about-250713-04.png b/docs/.vuepress/public/images/article/about/about-250713-04.png new file mode 100644 index 000000000..4c81ec588 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-250713-04.png differ diff --git a/docs/.vuepress/public/images/article/about/about-250713-05.png b/docs/.vuepress/public/images/article/about/about-250713-05.png new file mode 100644 index 000000000..dbe75d24b Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-250713-05.png differ diff --git a/docs/.vuepress/public/images/article/about/about-250713-06.png b/docs/.vuepress/public/images/article/about/about-250713-06.png new file mode 100644 index 000000000..137c4bfa8 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-250713-06.png differ diff --git a/docs/.vuepress/public/images/article/about/about-250713-07.png b/docs/.vuepress/public/images/article/about/about-250713-07.png new file mode 100644 index 000000000..7a3ad83a2 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-250713-07.png differ diff --git a/docs/.vuepress/public/images/article/about/about-250713-08.png b/docs/.vuepress/public/images/article/about/about-250713-08.png new file mode 100644 index 000000000..12a8db470 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-250713-08.png differ diff --git a/docs/.vuepress/public/images/article/about/about-interview-250823-01.png b/docs/.vuepress/public/images/article/about/about-interview-250823-01.png new file mode 100644 index 000000000..aadee0905 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-interview-250823-01.png differ diff --git a/docs/.vuepress/public/images/article/about/about-job-240908-01.gif b/docs/.vuepress/public/images/article/about/about-job-240908-01.gif new file mode 100644 index 000000000..c97e3cb2b Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-job-240908-01.gif differ diff --git a/docs/.vuepress/public/images/article/about/about-job-240908-02.png b/docs/.vuepress/public/images/article/about/about-job-240908-02.png new file mode 100644 index 000000000..b012d4915 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-job-240908-02.png differ diff --git a/docs/.vuepress/public/images/article/about/about-job-240908-03.png b/docs/.vuepress/public/images/article/about/about-job-240908-03.png new file mode 100644 index 000000000..b4fa9e891 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-job-240908-03.png differ diff --git a/docs/.vuepress/public/images/article/about/about-job-240908-04.png b/docs/.vuepress/public/images/article/about/about-job-240908-04.png new file mode 100644 index 000000000..c59887462 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-job-240908-04.png differ diff --git a/docs/.vuepress/public/images/article/about/about-job-ai-code-01.png b/docs/.vuepress/public/images/article/about/about-job-ai-code-01.png new file mode 100644 index 000000000..45612a6ee Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-job-ai-code-01.png differ diff --git a/docs/.vuepress/public/images/article/about/about-job-ai-code-02.png b/docs/.vuepress/public/images/article/about/about-job-ai-code-02.png new file mode 100644 index 000000000..438d1c88d Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-job-ai-code-02.png differ diff --git a/docs/.vuepress/public/images/article/about/about-job-ai-code-03.png b/docs/.vuepress/public/images/article/about/about-job-ai-code-03.png new file mode 100644 index 000000000..ee6c677ce Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-job-ai-code-03.png differ diff --git a/docs/.vuepress/public/images/article/about/about-job-ai-code-04.png b/docs/.vuepress/public/images/article/about/about-job-ai-code-04.png new file mode 100644 index 000000000..a722f6866 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-job-ai-code-04.png differ diff --git a/docs/.vuepress/public/images/article/about/about-job-ai-code-05.png b/docs/.vuepress/public/images/article/about/about-job-ai-code-05.png new file mode 100644 index 000000000..256e3d9bb Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-job-ai-code-05.png differ diff --git a/docs/.vuepress/public/images/article/about/about-job-ai-code-06.png b/docs/.vuepress/public/images/article/about/about-job-ai-code-06.png new file mode 100644 index 000000000..9c1e4119e Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-job-ai-code-06.png differ diff --git a/docs/.vuepress/public/images/article/about/about-me-25-01.png b/docs/.vuepress/public/images/article/about/about-me-25-01.png new file mode 100644 index 000000000..22a5f6e63 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-me-25-01.png differ diff --git a/docs/.vuepress/public/images/article/about/about-me-25-02.png b/docs/.vuepress/public/images/article/about/about-me-25-02.png new file mode 100644 index 000000000..b2adfc1f6 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-me-25-02.png differ diff --git a/docs/.vuepress/public/images/article/about/about-me-25-03.png b/docs/.vuepress/public/images/article/about/about-me-25-03.png new file mode 100644 index 000000000..7e270fe5a Binary files /dev/null and b/docs/.vuepress/public/images/article/about/about-me-25-03.png differ diff --git a/docs/.vuepress/public/images/article/about/ai-agent-job-01.png b/docs/.vuepress/public/images/article/about/ai-agent-job-01.png new file mode 100644 index 000000000..a853d8cbd Binary files /dev/null and b/docs/.vuepress/public/images/article/about/ai-agent-job-01.png differ diff --git a/docs/.vuepress/public/images/article/about/ai-agent-job-02.png b/docs/.vuepress/public/images/article/about/ai-agent-job-02.png new file mode 100644 index 000000000..bafd0d5fb Binary files /dev/null and b/docs/.vuepress/public/images/article/about/ai-agent-job-02.png differ diff --git a/docs/.vuepress/public/images/article/about/ai-agent-job-03.png b/docs/.vuepress/public/images/article/about/ai-agent-job-03.png new file mode 100644 index 000000000..e6b4db398 Binary files /dev/null and b/docs/.vuepress/public/images/article/about/ai-agent-job-03.png differ diff --git "a/docs/.vuepress/public/images/article/about/\345\255\246\344\271\240\350\267\257\347\272\277.xmind" "b/docs/.vuepress/public/images/article/about/\345\255\246\344\271\240\350\267\257\347\272\277.xmind" deleted file mode 100644 index bec517734..000000000 Binary files "a/docs/.vuepress/public/images/article/about/\345\255\246\344\271\240\350\267\257\347\272\277.xmind" and /dev/null differ diff --git a/docs/.vuepress/public/images/article/product/idea-plugin/vo2dto-2.5.5-01.png b/docs/.vuepress/public/images/article/product/idea-plugin/vo2dto-2.5.5-01.png new file mode 100644 index 000000000..73d0010a8 Binary files /dev/null and b/docs/.vuepress/public/images/article/product/idea-plugin/vo2dto-2.5.5-01.png differ diff --git a/docs/.vuepress/public/images/article/product/idea-plugin/vo2dto-2.5.5-02.png b/docs/.vuepress/public/images/article/product/idea-plugin/vo2dto-2.5.5-02.png new file mode 100644 index 000000000..aa70d7799 Binary files /dev/null and b/docs/.vuepress/public/images/article/product/idea-plugin/vo2dto-2.5.5-02.png differ diff --git a/docs/.vuepress/public/images/article/product/idea-plugin/vo2dto-2.5.5-03.png b/docs/.vuepress/public/images/article/product/idea-plugin/vo2dto-2.5.5-03.png new file mode 100644 index 000000000..2de7fc584 Binary files /dev/null and b/docs/.vuepress/public/images/article/product/idea-plugin/vo2dto-2.5.5-03.png differ diff --git a/docs/.vuepress/public/images/article/product/software/product-walicode-00.png b/docs/.vuepress/public/images/article/product/software/product-walicode-00.png new file mode 100644 index 000000000..c6cb4d13c Binary files /dev/null and b/docs/.vuepress/public/images/article/product/software/product-walicode-00.png differ diff --git a/docs/.vuepress/public/images/article/product/software/product-walicode-01.png b/docs/.vuepress/public/images/article/product/software/product-walicode-01.png new file mode 100644 index 000000000..a5ca4bbca Binary files /dev/null and b/docs/.vuepress/public/images/article/product/software/product-walicode-01.png differ diff --git a/docs/.vuepress/public/images/article/product/software/product-walicode-02.png b/docs/.vuepress/public/images/article/product/software/product-walicode-02.png new file mode 100644 index 000000000..85df57845 Binary files /dev/null and b/docs/.vuepress/public/images/article/product/software/product-walicode-02.png differ diff --git a/docs/.vuepress/public/images/article/product/software/product-walicode-03.png b/docs/.vuepress/public/images/article/product/software/product-walicode-03.png new file mode 100644 index 000000000..3f89becd6 Binary files /dev/null and b/docs/.vuepress/public/images/article/product/software/product-walicode-03.png differ diff --git a/docs/.vuepress/public/images/article/product/software/product-walicode-04.png b/docs/.vuepress/public/images/article/product/software/product-walicode-04.png new file mode 100644 index 000000000..6c145f6db Binary files /dev/null and b/docs/.vuepress/public/images/article/product/software/product-walicode-04.png differ diff --git a/docs/.vuepress/public/images/article/product/software/product-walicode-05.png b/docs/.vuepress/public/images/article/product/software/product-walicode-05.png new file mode 100644 index 000000000..3f89becd6 Binary files /dev/null and b/docs/.vuepress/public/images/article/product/software/product-walicode-05.png differ diff --git a/docs/.vuepress/public/images/article/product/software/product-walicode-06.png b/docs/.vuepress/public/images/article/product/software/product-walicode-06.png new file mode 100644 index 000000000..dbcc4dd94 Binary files /dev/null and b/docs/.vuepress/public/images/article/product/software/product-walicode-06.png differ diff --git a/docs/.vuepress/public/images/article/product/software/product-walicode-07.png b/docs/.vuepress/public/images/article/product/software/product-walicode-07.png new file mode 100644 index 000000000..90c3473f8 Binary files /dev/null and b/docs/.vuepress/public/images/article/product/software/product-walicode-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/ai-agent-scaffold.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/ai-agent-scaffold.png new file mode 100644 index 000000000..ad5ff84e6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/ai-agent-scaffold.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-0/images/ai-agent-scaffold-0-0-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-0/images/ai-agent-scaffold-0-0-01.png new file mode 100644 index 000000000..4b0cad0f1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-0/images/ai-agent-scaffold-0-0-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-0/images/ai-agent-scaffold-mobileopenclaw-260307-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-0/images/ai-agent-scaffold-mobileopenclaw-260307-01.png new file mode 100644 index 000000000..c4f70f510 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-0/images/ai-agent-scaffold-mobileopenclaw-260307-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-0/images/ai-agent-scaffold-mobileopenclaw-260307-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-0/images/ai-agent-scaffold-mobileopenclaw-260307-02.png new file mode 100644 index 000000000..c92739856 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-0/images/ai-agent-scaffold-mobileopenclaw-260307-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-0/images/ai-agent-scaffold-mobileopenclaw-260307-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-0/images/ai-agent-scaffold-mobileopenclaw-260307-03.png new file mode 100644 index 000000000..0d72f852c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-0/images/ai-agent-scaffold-mobileopenclaw-260307-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-01.png new file mode 100644 index 000000000..ca2f8ce62 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-02.png new file mode 100644 index 000000000..6d47c797f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-03.png new file mode 100644 index 000000000..2e066f914 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-04.png new file mode 100644 index 000000000..851f16dd2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-05.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-05.png new file mode 100644 index 000000000..040b9e8e0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-06.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-06.png new file mode 100644 index 000000000..b2f6d1b8c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-07.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-07.png new file mode 100644 index 000000000..b47852838 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-08.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-08.png new file mode 100644 index 000000000..a63c2a826 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-09.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-09.png new file mode 100644 index 000000000..e3a12db64 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-09.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-10.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-10.png new file mode 100644 index 000000000..1543caaba Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ai-agent-scaffold-1-1-10.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ppt.pptx b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ppt.pptx new file mode 100644 index 000000000..a85d6f698 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-1/images/ppt.pptx differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-01.png new file mode 100644 index 000000000..758751459 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-02.png new file mode 100644 index 000000000..469fc7c0b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-03.png new file mode 100644 index 000000000..2a0ef5509 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-04.png new file mode 100644 index 000000000..0cfb1c63f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-05.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-05.png new file mode 100644 index 000000000..e370f0354 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-1/1-2/images/ai-agent-scaffold-1-2-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-1/images/ai-agent-scaffold-2-1-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-1/images/ai-agent-scaffold-2-1-01.png new file mode 100644 index 000000000..485753b6c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-1/images/ai-agent-scaffold-2-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-1/images/ai-agent-scaffold-2-1-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-1/images/ai-agent-scaffold-2-1-02.png new file mode 100644 index 000000000..b660adc6b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-1/images/ai-agent-scaffold-2-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-1/images/ai-agent-scaffold-2-1-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-1/images/ai-agent-scaffold-2-1-03.png new file mode 100644 index 000000000..cf4be75d2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-1/images/ai-agent-scaffold-2-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-10/images/ai-agent-scaffold-2-10-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-10/images/ai-agent-scaffold-2-10-01.png new file mode 100644 index 000000000..229a3b43a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-10/images/ai-agent-scaffold-2-10-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-10/images/ai-agent-scaffold-2-10-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-10/images/ai-agent-scaffold-2-10-02.png new file mode 100644 index 000000000..8fbeaccfa Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-10/images/ai-agent-scaffold-2-10-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-11/images/ai-agent-scaffold-2-11-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-11/images/ai-agent-scaffold-2-11-01.png new file mode 100644 index 000000000..2b67697d9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-11/images/ai-agent-scaffold-2-11-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-11/images/ai-agent-scaffold-2-11-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-11/images/ai-agent-scaffold-2-11-02.png new file mode 100644 index 000000000..004765e3f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-11/images/ai-agent-scaffold-2-11-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-12/images/ai-agent-scaffold-2-12-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-12/images/ai-agent-scaffold-2-12-01.png new file mode 100644 index 000000000..1cfc8c21d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-12/images/ai-agent-scaffold-2-12-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-12/images/ai-agent-scaffold-2-12-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-12/images/ai-agent-scaffold-2-12-02.png new file mode 100644 index 000000000..30f9c172c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-12/images/ai-agent-scaffold-2-12-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-12/images/ai-agent-scaffold-2-12-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-12/images/ai-agent-scaffold-2-12-03.png new file mode 100644 index 000000000..c9457310f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-12/images/ai-agent-scaffold-2-12-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-12/images/ai-agent-scaffold-2-12-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-12/images/ai-agent-scaffold-2-12-04.png new file mode 100644 index 000000000..a8492b570 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-12/images/ai-agent-scaffold-2-12-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-13/images/ai-agent-scaffold-2-13-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-13/images/ai-agent-scaffold-2-13-01.png new file mode 100644 index 000000000..9bf59bbc9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-13/images/ai-agent-scaffold-2-13-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-13/images/ai-agent-scaffold-2-13-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-13/images/ai-agent-scaffold-2-13-02.png new file mode 100644 index 000000000..63bf34203 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-13/images/ai-agent-scaffold-2-13-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-14/images/ai-agent-scaffold-2-14-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-14/images/ai-agent-scaffold-2-14-01.png new file mode 100644 index 000000000..1f3c17c7c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-14/images/ai-agent-scaffold-2-14-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-14/images/ai-agent-scaffold-2-14-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-14/images/ai-agent-scaffold-2-14-02.png new file mode 100644 index 000000000..8660965b1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-14/images/ai-agent-scaffold-2-14-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-15/images/ai-agent-scaffold-2-15-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-15/images/ai-agent-scaffold-2-15-01.png new file mode 100644 index 000000000..8ace6c2a7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-15/images/ai-agent-scaffold-2-15-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-15/images/ai-agent-scaffold-2-15-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-15/images/ai-agent-scaffold-2-15-02.png new file mode 100644 index 000000000..1a57704c4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-15/images/ai-agent-scaffold-2-15-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-01.png new file mode 100644 index 000000000..666af7610 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-02.png new file mode 100644 index 000000000..4c43047c7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-03.png new file mode 100644 index 000000000..d88ff2f09 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-04.png new file mode 100644 index 000000000..d71bc7927 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-05.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-05.png new file mode 100644 index 000000000..b23d69f16 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-06.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-06.png new file mode 100644 index 000000000..372fee3dd Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-07.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-07.png new file mode 100644 index 000000000..b1338d4cb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-08.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-08.png new file mode 100644 index 000000000..20d92c51f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-09.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-09.png new file mode 100644 index 000000000..0ca10afa8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-16/images/ai-agent-scaffold-2-16-09.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-17/images/ai-agent-scaffold-2-17-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-17/images/ai-agent-scaffold-2-17-01.png new file mode 100644 index 000000000..bb322427c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-17/images/ai-agent-scaffold-2-17-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-17/images/ai-agent-scaffold-2-17-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-17/images/ai-agent-scaffold-2-17-02.png new file mode 100644 index 000000000..d9bcd7323 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-17/images/ai-agent-scaffold-2-17-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-18/images/ai-agent-scaffold-2-18-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-18/images/ai-agent-scaffold-2-18-01.png new file mode 100644 index 000000000..bc9f321e4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-18/images/ai-agent-scaffold-2-18-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-18/images/ai-agent-scaffold-2-18-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-18/images/ai-agent-scaffold-2-18-02.png new file mode 100644 index 000000000..7790de817 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-18/images/ai-agent-scaffold-2-18-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-18/images/ai-agent-scaffold-2-18-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-18/images/ai-agent-scaffold-2-18-03.png new file mode 100644 index 000000000..3abb8d05f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-18/images/ai-agent-scaffold-2-18-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-01.png new file mode 100644 index 000000000..408e21f03 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-02.png new file mode 100644 index 000000000..57495dd40 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-03.png new file mode 100644 index 000000000..ee86f3013 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-04.png new file mode 100644 index 000000000..b0c012e9d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-05.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-05.png new file mode 100644 index 000000000..bf735ee7a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-06.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-06.png new file mode 100644 index 000000000..6e820fbae Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-19/images/ai-agent-scaffold-2-19-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-2/images/ai-agent-scaffold-2-2-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-2/images/ai-agent-scaffold-2-2-01.png new file mode 100644 index 000000000..63368a463 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-2/images/ai-agent-scaffold-2-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-20/images/ai-agent-scaffold-2-20-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-20/images/ai-agent-scaffold-2-20-01.png new file mode 100644 index 000000000..ebdcc9414 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-20/images/ai-agent-scaffold-2-20-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-20/images/ai-agent-scaffold-2-20-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-20/images/ai-agent-scaffold-2-20-02.png new file mode 100644 index 000000000..453650b99 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-20/images/ai-agent-scaffold-2-20-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-20/images/ai-agent-scaffold-2-20-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-20/images/ai-agent-scaffold-2-20-03.png new file mode 100644 index 000000000..5f638861d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-20/images/ai-agent-scaffold-2-20-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-3/images/ai-agent-scaffold-2-3-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-3/images/ai-agent-scaffold-2-3-01.png new file mode 100644 index 000000000..1e196eca1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-3/images/ai-agent-scaffold-2-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-3/images/ai-agent-scaffold-2-3-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-3/images/ai-agent-scaffold-2-3-02.png new file mode 100644 index 000000000..f285f5298 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-3/images/ai-agent-scaffold-2-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-3/images/ai-agent-scaffold-2-3-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-3/images/ai-agent-scaffold-2-3-03.png new file mode 100644 index 000000000..0b059f011 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-3/images/ai-agent-scaffold-2-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-4/images/ai-agent-scaffold-2-4-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-4/images/ai-agent-scaffold-2-4-01.png new file mode 100644 index 000000000..ecd999b17 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-4/images/ai-agent-scaffold-2-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-4/images/ai-agent-scaffold-2-4-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-4/images/ai-agent-scaffold-2-4-02.png new file mode 100644 index 000000000..72fc4fcd4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-4/images/ai-agent-scaffold-2-4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-4/images/ai-agent-scaffold-2-4-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-4/images/ai-agent-scaffold-2-4-03.png new file mode 100644 index 000000000..7cffb5490 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-4/images/ai-agent-scaffold-2-4-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-5/images/ai-agent-scaffold-2-5-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-5/images/ai-agent-scaffold-2-5-01.png new file mode 100644 index 000000000..d6f02ba35 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-5/images/ai-agent-scaffold-2-5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-5/images/ai-agent-scaffold-2-5-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-5/images/ai-agent-scaffold-2-5-02.png new file mode 100644 index 000000000..351b0fcb4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-5/images/ai-agent-scaffold-2-5-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-6/images/ai-agent-scaffold-2-6-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-6/images/ai-agent-scaffold-2-6-01.png new file mode 100644 index 000000000..89f882a13 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-6/images/ai-agent-scaffold-2-6-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-6/images/ai-agent-scaffold-2-6-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-6/images/ai-agent-scaffold-2-6-02.png new file mode 100644 index 000000000..434a31e8c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-6/images/ai-agent-scaffold-2-6-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-7/images/ai-agent-scaffold-2-7-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-7/images/ai-agent-scaffold-2-7-01.png new file mode 100644 index 000000000..e6947c2c5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-7/images/ai-agent-scaffold-2-7-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-7/images/ai-agent-scaffold-2-7-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-7/images/ai-agent-scaffold-2-7-02.png new file mode 100644 index 000000000..60a04dae0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-7/images/ai-agent-scaffold-2-7-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-8/images/ai-agent-scaffold-2-8-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-8/images/ai-agent-scaffold-2-8-01.png new file mode 100644 index 000000000..b4727be1a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-8/images/ai-agent-scaffold-2-8-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-8/images/ai-agent-scaffold-2-8-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-8/images/ai-agent-scaffold-2-8-02.png new file mode 100644 index 000000000..37fdd953e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-8/images/ai-agent-scaffold-2-8-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-9/images/ai-agent-scaffold-2-9-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-9/images/ai-agent-scaffold-2-9-01.png new file mode 100644 index 000000000..b83e49831 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-9/images/ai-agent-scaffold-2-9-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-9/images/ai-agent-scaffold-2-9-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-9/images/ai-agent-scaffold-2-9-02.png new file mode 100644 index 000000000..a13e30d02 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-2/2-9/images/ai-agent-scaffold-2-9-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-01.png new file mode 100644 index 000000000..469fc7c0b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-02.png new file mode 100644 index 000000000..f7c6a87de Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-03.png new file mode 100644 index 000000000..4a58ccc72 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-04.png new file mode 100644 index 000000000..5ce511bbb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-05.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-05.png new file mode 100644 index 000000000..999367a95 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-06.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-06.png new file mode 100644 index 000000000..fd8b3dbb8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-07.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-07.png new file mode 100644 index 000000000..5a310decb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-08.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-08.png new file mode 100644 index 000000000..3ec34129e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-09.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-09.png new file mode 100644 index 000000000..75e3ab76d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-09.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-10.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-10.png new file mode 100644 index 000000000..bd033bfd5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-1/images/ai-agent-scaffold-3-1-10.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-01.png new file mode 100644 index 000000000..8c66787e1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-02.png new file mode 100644 index 000000000..0c37fa725 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-03.png new file mode 100644 index 000000000..9384e2d8d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-04.png new file mode 100644 index 000000000..683ffa91c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-05.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-05.png new file mode 100644 index 000000000..5eaca56de Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-06.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-06.png new file mode 100644 index 000000000..dbcba126c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-07.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-07.png new file mode 100644 index 000000000..73b4ae752 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-2/images/ai-agent-scaffold-3-2-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-01.png new file mode 100644 index 000000000..37d7ef507 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-02.png new file mode 100644 index 000000000..accc9a261 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-03.png new file mode 100644 index 000000000..895ae2e0d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-04.png new file mode 100644 index 000000000..579971d26 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-05.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-05.png new file mode 100644 index 000000000..b9b6fafee Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-06.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-06.png new file mode 100644 index 000000000..a021d9dc6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-07.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-07.png new file mode 100644 index 000000000..7a4d372ed Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-08.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-08.png new file mode 100644 index 000000000..872cfa4aa Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-09.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-09.png new file mode 100644 index 000000000..b59b57b0d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-09.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-10.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-10.png new file mode 100644 index 000000000..3fc71458a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-3/3-3/images/ai-agent-scaffold-3-3-10.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-0/images/ai-agent-scaffold-4-0-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-0/images/ai-agent-scaffold-4-0-01.png new file mode 100644 index 000000000..06a288107 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-0/images/ai-agent-scaffold-4-0-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-0/images/ai-agent-scaffold-4-0-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-0/images/ai-agent-scaffold-4-0-02.png new file mode 100644 index 000000000..d6b2533d1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-0/images/ai-agent-scaffold-4-0-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-1/images/ai-agent-scaffold-4-1-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-1/images/ai-agent-scaffold-4-1-01.png new file mode 100644 index 000000000..cbf0a266a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-1/images/ai-agent-scaffold-4-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-1/images/ai-agent-scaffold-4-1-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-1/images/ai-agent-scaffold-4-1-02.png new file mode 100644 index 000000000..6285e89ed Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-1/images/ai-agent-scaffold-4-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-1/images/ai-agent-scaffold-4-1-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-1/images/ai-agent-scaffold-4-1-03.png new file mode 100644 index 000000000..9e7553045 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-1/images/ai-agent-scaffold-4-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-1/images/ai-agent-scaffold-4-1-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-1/images/ai-agent-scaffold-4-1-04.png new file mode 100644 index 000000000..dc32e860d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-1/images/ai-agent-scaffold-4-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-2/images/ai-agent-scaffold-4-2-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-2/images/ai-agent-scaffold-4-2-01.png new file mode 100644 index 000000000..6bc4c60ae Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-2/images/ai-agent-scaffold-4-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-2/images/ai-agent-scaffold-4-2-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-2/images/ai-agent-scaffold-4-2-02.png new file mode 100644 index 000000000..ea7376fbe Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-2/images/ai-agent-scaffold-4-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-2/images/ai-agent-scaffold-4-2-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-2/images/ai-agent-scaffold-4-2-03.png new file mode 100644 index 000000000..fa346e2fa Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-2/images/ai-agent-scaffold-4-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-01.png new file mode 100644 index 000000000..8cb79830f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-02.png new file mode 100644 index 000000000..9afe9f01e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-03.png new file mode 100644 index 000000000..cb64abcc8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-04.png new file mode 100644 index 000000000..f454f8e93 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-05.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-05.png new file mode 100644 index 000000000..506041398 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-06.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-06.png new file mode 100644 index 000000000..6f2cf7b97 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-07.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-07.png new file mode 100644 index 000000000..e22d9dba4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-3/images/ai-agent-scaffold-4-3-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-01.png new file mode 100644 index 000000000..239d5a421 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-02.png new file mode 100644 index 000000000..a0861d1ea Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-03.png new file mode 100644 index 000000000..8aee4a55d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-04.png new file mode 100644 index 000000000..66747ddb2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-05.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-05.png new file mode 100644 index 000000000..b47852838 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-06.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-06.png new file mode 100644 index 000000000..c867ba605 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-4/images/ai-agent-scaffold-4-4-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-01.png new file mode 100644 index 000000000..de5a2914c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-02.png new file mode 100644 index 000000000..b4d52c3b6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-03.png new file mode 100644 index 000000000..16d58a44d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-04.png new file mode 100644 index 000000000..ba435b7c7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-05.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-05.png new file mode 100644 index 000000000..876dc2032 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-06.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-06.png new file mode 100644 index 000000000..62be0eb07 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-07.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-07.png new file mode 100644 index 000000000..d8213f196 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-4/4-5/images/ai-agent-scaffold-4-5-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-0/images/ai-agent-scaffold-5-0-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-0/images/ai-agent-scaffold-5-0-01.png new file mode 100644 index 000000000..bb0cdae00 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-0/images/ai-agent-scaffold-5-0-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-0/images/logo.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-0/images/logo.png new file mode 100644 index 000000000..429b2d42d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-0/images/logo.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-00.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-00.png new file mode 100644 index 000000000..7c466f457 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-00.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-01.png new file mode 100644 index 000000000..2f3fe1357 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-02.png new file mode 100644 index 000000000..99b172578 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-03.png new file mode 100644 index 000000000..4816954bb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-04.png new file mode 100644 index 000000000..e47009b00 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-05.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-05.png new file mode 100644 index 000000000..b93a74ddb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-1/images/ai-agent-scaffold-5-1-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-2/images/ai-agent-scaffold-5-2-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-2/images/ai-agent-scaffold-5-2-01.png new file mode 100644 index 000000000..258781d2a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-2/images/ai-agent-scaffold-5-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-2/images/ai-agent-scaffold-5-2-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-2/images/ai-agent-scaffold-5-2-02.png new file mode 100644 index 000000000..81b7ecaf9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-2/images/ai-agent-scaffold-5-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-2/images/ai-agent-scaffold-5-2-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-2/images/ai-agent-scaffold-5-2-03.png new file mode 100644 index 000000000..6b7d58eed Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-2/images/ai-agent-scaffold-5-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-3/images/ai-agent-scaffold-5-3-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-3/images/ai-agent-scaffold-5-3-01.png new file mode 100644 index 000000000..a774fd287 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-3/images/ai-agent-scaffold-5-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-3/images/ai-agent-scaffold-5-3-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-3/images/ai-agent-scaffold-5-3-02.png new file mode 100644 index 000000000..f993106fe Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-3/images/ai-agent-scaffold-5-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-3/images/ai-agent-scaffold-5-3-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-3/images/ai-agent-scaffold-5-3-03.png new file mode 100644 index 000000000..847b630de Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-3/images/ai-agent-scaffold-5-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-4/images/ai-agent-scaffold-5-4-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-4/images/ai-agent-scaffold-5-4-01.png new file mode 100644 index 000000000..115f81115 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-4/images/ai-agent-scaffold-5-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-4/images/ai-agent-scaffold-5-4-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-4/images/ai-agent-scaffold-5-4-02.png new file mode 100644 index 000000000..d7a210be9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-4/images/ai-agent-scaffold-5-4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-4/images/ai-agent-scaffold-5-4-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-4/images/ai-agent-scaffold-5-4-03.png new file mode 100644 index 000000000..3128727f8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-4/images/ai-agent-scaffold-5-4-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-4/images/ai-agent-scaffold-5-4-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-4/images/ai-agent-scaffold-5-4-04.png new file mode 100644 index 000000000..3c43ab5db Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-4/images/ai-agent-scaffold-5-4-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-01.png new file mode 100644 index 000000000..970e7486f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-02.png new file mode 100644 index 000000000..373fe0d50 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-03.png new file mode 100644 index 000000000..236ddcb84 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-04.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-04.png new file mode 100644 index 000000000..8ef5d932b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-05.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-05.png new file mode 100644 index 000000000..a4f700950 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-5/images/ai-agent-scaffold-5-5-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-6/images/ai-agent-scaffold-5-6-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-6/images/ai-agent-scaffold-5-6-01.png new file mode 100644 index 000000000..ee3be6537 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-6/images/ai-agent-scaffold-5-6-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-6/images/ai-agent-scaffold-5-6-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-6/images/ai-agent-scaffold-5-6-02.png new file mode 100644 index 000000000..8b9d7043a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-6/images/ai-agent-scaffold-5-6-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-6/images/ai-agent-scaffold-5-6-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-6/images/ai-agent-scaffold-5-6-03.png new file mode 100644 index 000000000..86d74d9ae Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-6/images/ai-agent-scaffold-5-6-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-7/images/ai-agent-scaffold-5-7-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-7/images/ai-agent-scaffold-5-7-01.png new file mode 100644 index 000000000..4b58b4421 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-7/images/ai-agent-scaffold-5-7-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-7/images/ai-agent-scaffold-5-7-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-7/images/ai-agent-scaffold-5-7-02.png new file mode 100644 index 000000000..f41fdc283 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-7/images/ai-agent-scaffold-5-7-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-7/images/ai-agent-scaffold-5-7-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-7/images/ai-agent-scaffold-5-7-03.png new file mode 100644 index 000000000..21cb57c64 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-7/images/ai-agent-scaffold-5-7-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-8/images/ai-agent-scaffold-5-8-01.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-8/images/ai-agent-scaffold-5-8-01.png new file mode 100644 index 000000000..4e21a6106 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-8/images/ai-agent-scaffold-5-8-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-8/images/ai-agent-scaffold-5-8-02.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-8/images/ai-agent-scaffold-5-8-02.png new file mode 100644 index 000000000..d1bf41d39 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-8/images/ai-agent-scaffold-5-8-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-8/images/ai-agent-scaffold-5-8-03.png b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-8/images/ai-agent-scaffold-5-8-03.png new file mode 100644 index 000000000..9fb2ec11c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-agent-scaffold/part-5/5-8/images/ai-agent-scaffold-5-8-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-1-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-1-01.png new file mode 100644 index 000000000..796e21231 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-1-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-1-02.png new file mode 100644 index 000000000..01fd90f9b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-1-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-1-03.png new file mode 100644 index 000000000..31fe9b342 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-1-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-1-04.png new file mode 100644 index 000000000..14772da72 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-2-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-2-01.png new file mode 100644 index 000000000..6b7692b97 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-2-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-2-02.png new file mode 100644 index 000000000..ea9307b98 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-2-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-2-03.png new file mode 100644 index 000000000..649de5c7e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-01.png new file mode 100644 index 000000000..b624b92d4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-02.png new file mode 100644 index 000000000..c8866688d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-03.png new file mode 100644 index 000000000..febb05e7f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-04-1.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-04-1.png new file mode 100644 index 000000000..93ada7105 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-04-1.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-04.png new file mode 100644 index 000000000..8d4a3bec7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-05-1.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-05-1.png new file mode 100644 index 000000000..28fbf0708 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-05-1.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-05.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-05.png new file mode 100644 index 000000000..a1f36adae Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-06-1.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-06-1.png new file mode 100644 index 000000000..a775c1457 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-06-1.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-06.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-06.png new file mode 100644 index 000000000..05cb27795 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-07-1.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-07-1.png new file mode 100644 index 000000000..efe2a904b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-07-1.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-07.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-07.png new file mode 100644 index 000000000..8f9b8939a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-3-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-4-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-4-01.png new file mode 100644 index 000000000..c91db171a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-4-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-4-02.png new file mode 100644 index 000000000..892cf7fce Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-1-4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-1-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-1-01.png new file mode 100644 index 000000000..a0ccf09cc Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-1-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-1-02.png new file mode 100644 index 000000000..5d33ca481 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-1-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-1-03.png new file mode 100644 index 000000000..15232fee9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-2-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-2-01.png new file mode 100644 index 000000000..adb2077b0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-2-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-2-02.png new file mode 100644 index 000000000..e7e452366 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-2-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-2-03.png new file mode 100644 index 000000000..ff2caebd3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-2-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-2-04.png new file mode 100644 index 000000000..7d25c2ab5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-2-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-01.png new file mode 100644 index 000000000..0bfbd597e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-02.png new file mode 100644 index 000000000..017ee0286 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-03.png new file mode 100644 index 000000000..4227b708b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-04.png new file mode 100644 index 000000000..4befba4ec Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-05.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-05.png new file mode 100644 index 000000000..244f0b964 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-06.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-06.png new file mode 100644 index 000000000..87ae5b38c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-07.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-07.png new file mode 100644 index 000000000..ba4583147 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-08.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-08.png new file mode 100644 index 000000000..d67bf8b03 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-2-3-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-1-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-1-01.png new file mode 100644 index 000000000..b660adc6b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-1-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-1-02.png new file mode 100644 index 000000000..a5b52a8c8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-1-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-1-03.png new file mode 100644 index 000000000..485753b6c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-1-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-1-04.png new file mode 100644 index 000000000..5420bc958 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-01.png new file mode 100644 index 000000000..5838b6a61 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-02.png new file mode 100644 index 000000000..f363681bb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-03.png new file mode 100644 index 000000000..a74d20e9d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-04.png new file mode 100644 index 000000000..5c80dea8c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-05.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-05.png new file mode 100644 index 000000000..b41b2ac2b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-06.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-06.png new file mode 100644 index 000000000..6be709da3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-10-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-11-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-11-01.png new file mode 100644 index 000000000..2c5ccdfce Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-11-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-11-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-11-02.png new file mode 100644 index 000000000..0b6bb8e5d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-11-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-11-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-11-03.png new file mode 100644 index 000000000..83ea835b9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-11-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-12-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-12-01.png new file mode 100644 index 000000000..a9fd3181f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-12-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-12-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-12-02.png new file mode 100644 index 000000000..6073b850a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-12-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-12-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-12-03.png new file mode 100644 index 000000000..3e7ea1643 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-12-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-12-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-12-04.png new file mode 100644 index 000000000..1afe11c9e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-12-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-13-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-13-01.png new file mode 100644 index 000000000..a9a36f2b5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-13-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-13-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-13-02.png new file mode 100644 index 000000000..62b72d811 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-13-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-13-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-13-03.png new file mode 100644 index 000000000..11dfad080 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-13-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-14-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-14-01.png new file mode 100644 index 000000000..ed78d81f3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-14-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-14-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-14-02.png new file mode 100644 index 000000000..f51004205 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-14-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-14-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-14-03.png new file mode 100644 index 000000000..57382fb0a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-14-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-14-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-14-04.png new file mode 100644 index 000000000..a432f0003 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-14-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-16-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-16-01.png new file mode 100644 index 000000000..f4b3186e7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-16-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-16-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-16-02.png new file mode 100644 index 000000000..38e7c5386 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-16-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-18-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-18-01.png new file mode 100644 index 000000000..654e8a3b0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-18-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-18-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-18-02.png new file mode 100644 index 000000000..1eb8ef49f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-18-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-18-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-18-03.png new file mode 100644 index 000000000..98d8c0027 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-18-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-18-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-18-04.png new file mode 100644 index 000000000..40fc70fd5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-18-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-01.png new file mode 100644 index 000000000..00ea6f071 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-02.png new file mode 100644 index 000000000..543e1054e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-03.png new file mode 100644 index 000000000..ec58c0554 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-04.png new file mode 100644 index 000000000..5a45a2ef7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-05.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-05.png new file mode 100644 index 000000000..7d1bd2e76 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-06.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-06.png new file mode 100644 index 000000000..2d8211a14 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-07.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-07.png new file mode 100644 index 000000000..00e3df281 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-08.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-08.png new file mode 100644 index 000000000..1a73601c8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-09.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-09.png new file mode 100644 index 000000000..f525f10c5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-19-09.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-2-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-2-01.png new file mode 100644 index 000000000..02e0b8953 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-2-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-2-02.png new file mode 100644 index 000000000..6894b6b05 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-3-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-3-01.png new file mode 100644 index 000000000..d9bc284c9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-3-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-3-02.png new file mode 100644 index 000000000..e4cc3b16e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-3-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-3-03.png new file mode 100644 index 000000000..f1fd3a7c1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-3-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-3-04.png new file mode 100644 index 000000000..4bccc6c05 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-4-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-4-01.png new file mode 100644 index 000000000..6f9bacd50 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-4-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-4-02.png new file mode 100644 index 000000000..ff076a8ea Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-4-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-4-03.png new file mode 100644 index 000000000..d93bb4b6a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-4-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-4-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-4-04.png new file mode 100644 index 000000000..95fa15002 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-4-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-5-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-5-01.png new file mode 100644 index 000000000..343f93f09 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-5-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-5-02.png new file mode 100644 index 000000000..536070517 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-5-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-5-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-5-03.png new file mode 100644 index 000000000..2bae7e9bb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-5-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-6-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-6-01.png new file mode 100644 index 000000000..9a2de0dac Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-6-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-6-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-6-02.png new file mode 100644 index 000000000..eb0ac05b1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-6-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-6-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-6-03.png new file mode 100644 index 000000000..281bf9711 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-6-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-6-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-6-04.png new file mode 100644 index 000000000..3dc6274a1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-6-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-01.png new file mode 100644 index 000000000..a44c74922 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-02.png new file mode 100644 index 000000000..6329a601d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-03.png new file mode 100644 index 000000000..08229294e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-04.png new file mode 100644 index 000000000..ffdf1fb74 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-05.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-05.png new file mode 100644 index 000000000..745e76504 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-06.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-06.png new file mode 100644 index 000000000..88b969686 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-07.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-07.png new file mode 100644 index 000000000..325b4931e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-08.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-08.png new file mode 100644 index 000000000..27cbff57e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-7-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-01.png new file mode 100644 index 000000000..e32f2e689 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-02.png new file mode 100644 index 000000000..0e3a018fa Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-03.png new file mode 100644 index 000000000..4ce744dfe Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-04.png new file mode 100644 index 000000000..ff31c024c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-05.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-05.png new file mode 100644 index 000000000..3f68602d0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-06.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-06.png new file mode 100644 index 000000000..23164998e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-07.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-07.png new file mode 100644 index 000000000..79a38781b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-8-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-01.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-01.png new file mode 100644 index 000000000..584c4aaa1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-02.png new file mode 100644 index 000000000..ed9bc1555 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-03.png new file mode 100644 index 000000000..eb3c1b1b5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-04.png new file mode 100644 index 000000000..7ec7a89dd Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-05.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-05.png new file mode 100644 index 000000000..462205f7e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-06.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-06.png new file mode 100644 index 000000000..79964e866 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/ai-mcp-gateway-3-9-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-01.gif b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-01.gif new file mode 100644 index 000000000..aae4626af Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-01.gif differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-02.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-02.png new file mode 100644 index 000000000..e7ef0a3d6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-03.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-03.png new file mode 100644 index 000000000..c8b1c0407 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-04.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-04.png new file mode 100644 index 000000000..8f19975d4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-05.png b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-05.png new file mode 100644 index 000000000..11faa2518 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-mcp-gateway/mcp-gateway-promotion-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-01.png new file mode 100644 index 000000000..098ba0443 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-02.png new file mode 100644 index 000000000..0166dd73d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-03.png new file mode 100644 index 000000000..462074582 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-04.png new file mode 100644 index 000000000..6e14c37c7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-05.png new file mode 100644 index 000000000..eaf34b393 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-06.png new file mode 100644 index 000000000..c0b78cead Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-07.png new file mode 100644 index 000000000..9ca37f333 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-1-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-01.png new file mode 100644 index 000000000..f1787ebad Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-02.png new file mode 100644 index 000000000..66ed25ba4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-03.png new file mode 100644 index 000000000..c5af04bf3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-04.png new file mode 100644 index 000000000..0cea30183 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-05.png new file mode 100644 index 000000000..8b8f05e7e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250517-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250524-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250524-01.png new file mode 100644 index 000000000..041ea5e40 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250524-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250524-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250524-02.png new file mode 100644 index 000000000..04471e771 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250524-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250524-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250524-03.png new file mode 100644 index 000000000..7e64df5de Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250524-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250524-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250524-04.png new file mode 100644 index 000000000..c03aef592 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-250524-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-01.png new file mode 100644 index 000000000..7ba5726b9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-02.png new file mode 100644 index 000000000..f6ad01606 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-03.png new file mode 100644 index 000000000..5b1bff3ac Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-04.png new file mode 100644 index 000000000..ca8ef3c05 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-05.png new file mode 100644 index 000000000..86be9a07d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-06.png new file mode 100644 index 000000000..99e7b5eda Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-07.png new file mode 100644 index 000000000..040b9e8e0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-08.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-08.png new file mode 100644 index 000000000..7cf49e15d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250810-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250817-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250817-01.png new file mode 100644 index 000000000..59eb10ce8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250817-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250817-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250817-02.png new file mode 100644 index 000000000..c80b4e7c7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250817-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250921-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250921-01.png new file mode 100644 index 000000000..2d73e2a90 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250921-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250921-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250921-02.png new file mode 100644 index 000000000..5d6f5a906 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250921-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250921-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250921-03.png new file mode 100644 index 000000000..99628d4f2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-agent-station-ext-250921-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-01.png new file mode 100644 index 000000000..37d03c66d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-02.png new file mode 100644 index 000000000..a9bcb4f52 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-03.png new file mode 100644 index 000000000..15ad51b46 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-04.png new file mode 100644 index 000000000..b2d4bf784 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-05.png new file mode 100644 index 000000000..500d98e1d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-06.png new file mode 100644 index 000000000..566e1656e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-07.png new file mode 100644 index 000000000..cdd40e46b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-knowledge-250413-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-01.png new file mode 100644 index 000000000..30ef61eed Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-02.gif b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-02.gif new file mode 100644 index 000000000..b5882a5f3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-02.gif differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-03.png new file mode 100644 index 000000000..920fb55f3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-04.png new file mode 100644 index 000000000..30a236c97 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-05.png new file mode 100644 index 000000000..bf6220631 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-06.png new file mode 100644 index 000000000..d614b2408 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-07.png new file mode 100644 index 000000000..11f1b6bf3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-08.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-08.png new file mode 100644 index 000000000..6d05d229e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-mcp-knowledge-250330-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-0-00.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-0-00.png new file mode 100644 index 000000000..40b8d60b4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-0-00.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-0-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-0-01.png new file mode 100644 index 000000000..e0898537b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-0-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-01.png new file mode 100644 index 000000000..c6a930721 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-02.png new file mode 100644 index 000000000..00b7723d7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-03.png new file mode 100644 index 000000000..cccc99bf6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-04.png new file mode 100644 index 000000000..50ffcda56 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-05.png new file mode 100644 index 000000000..b911fc0bf Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-1-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-01.png new file mode 100644 index 000000000..63a359a3d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-02.png new file mode 100644 index 000000000..0b1f728dd Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-03.png new file mode 100644 index 000000000..0c46d4584 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-04.png new file mode 100644 index 000000000..b4b0a48f3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-05.png new file mode 100644 index 000000000..d8e1082ca Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-06.png new file mode 100644 index 000000000..e858f4225 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-07.png new file mode 100644 index 000000000..b02198e82 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-08.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-08.png new file mode 100644 index 000000000..9bae5f1eb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-09.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-09.png new file mode 100644 index 000000000..28f71f95b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-10-09.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-00-1.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-00-1.png new file mode 100644 index 000000000..8cc6b25f3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-00-1.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-01.png new file mode 100644 index 000000000..beb65f8d2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-02.png new file mode 100644 index 000000000..3c369b246 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-03.png new file mode 100644 index 000000000..314c53cd6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-04.png new file mode 100644 index 000000000..a7461e5ff Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-11-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-01.png new file mode 100644 index 000000000..7fb5d4c0c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-02.png new file mode 100644 index 000000000..3747a5e95 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-03.png new file mode 100644 index 000000000..04eae84ba Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-04.png new file mode 100644 index 000000000..d86c218f3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-05.png new file mode 100644 index 000000000..ecc5924a0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-06.png new file mode 100644 index 000000000..a8830fd11 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-07.png new file mode 100644 index 000000000..e8206d259 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-08.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-08.png new file mode 100644 index 000000000..43703a9d8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-09.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-09.png new file mode 100644 index 000000000..63ed1d877 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-09.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-10.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-10.png new file mode 100644 index 000000000..ceeb40ce1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-10.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-01.png new file mode 100644 index 000000000..8ef61d0b8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-02.png new file mode 100644 index 000000000..1e74edda0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-03.png new file mode 100644 index 000000000..b8287168e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-04.png new file mode 100644 index 000000000..ff858d112 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-05.png new file mode 100644 index 000000000..00bab426f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-06.png new file mode 100644 index 000000000..e30e7f73f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-12-12-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-01.png new file mode 100644 index 000000000..289161271 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-02.png new file mode 100644 index 000000000..93b61ea1e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-03.png new file mode 100644 index 000000000..1fb1f39e6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-04.png new file mode 100644 index 000000000..4a6ad8e71 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-05.png new file mode 100644 index 000000000..9a1c6101b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-06.png new file mode 100644 index 000000000..9e768ea57 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-07.png new file mode 100644 index 000000000..302c26ea9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-08.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-08.png new file mode 100644 index 000000000..da53d5a5e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-09.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-09.png new file mode 100644 index 000000000..1c47aeb22 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-09.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-10.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-10.png new file mode 100644 index 000000000..cd8efba15 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-10.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-11.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-11.png new file mode 100644 index 000000000..17ffdbd97 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-11.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-12.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-12.png new file mode 100644 index 000000000..639b78f64 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-12.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-13.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-13.png new file mode 100644 index 000000000..15ba76351 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-13-13.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-01.png new file mode 100644 index 000000000..94890772d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-02.png new file mode 100644 index 000000000..8d3511f57 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-03.png new file mode 100644 index 000000000..1a2af109d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-04.png new file mode 100644 index 000000000..399206904 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-05.png new file mode 100644 index 000000000..5048b623c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-06.png new file mode 100644 index 000000000..007cb28c4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-07.png new file mode 100644 index 000000000..a7d6bee54 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-08.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-08.png new file mode 100644 index 000000000..5cf001876 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-09.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-09.png new file mode 100644 index 000000000..6c0f13816 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-09.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-10.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-10.png new file mode 100644 index 000000000..b42b6d0c4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-10.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-11.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-11.png new file mode 100644 index 000000000..8adb2fd99 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-11.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-12.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-12.png new file mode 100644 index 000000000..d7a9bd1aa Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-12.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-13.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-13.png new file mode 100644 index 000000000..4afc08e97 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-13.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-14.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-14.png new file mode 100644 index 000000000..b7b59dc44 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-14-14.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-15-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-15-01.png new file mode 100644 index 000000000..56de64a8a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-15-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-15-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-15-02.png new file mode 100644 index 000000000..de380b2f2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-15-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-15-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-15-03.png new file mode 100644 index 000000000..e7538a845 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-15-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-01.png new file mode 100644 index 000000000..e8509babf Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-02.png new file mode 100644 index 000000000..4cd82e807 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-03.png new file mode 100644 index 000000000..24c8d6ab0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-04.png new file mode 100644 index 000000000..423a0139e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-05.png new file mode 100644 index 000000000..c8c3f5436 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-06.png new file mode 100644 index 000000000..3d6941b8b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-07.png new file mode 100644 index 000000000..00650cf88 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-08.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-08.png new file mode 100644 index 000000000..bd0da8e3b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-09.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-09.png new file mode 100644 index 000000000..f07968c57 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-09.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-10.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-10.png new file mode 100644 index 000000000..01e6f077b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-10.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-11.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-11.png new file mode 100644 index 000000000..271f30609 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-11.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-12.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-12.png new file mode 100644 index 000000000..8069b3e3c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-16-12.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-01.png new file mode 100644 index 000000000..866ccbb41 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-02.png new file mode 100644 index 000000000..45c2c2c85 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-03.png new file mode 100644 index 000000000..9429bd188 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-04.png new file mode 100644 index 000000000..941040b10 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-05.png new file mode 100644 index 000000000..c8a83fa53 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-2-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-01.png new file mode 100644 index 000000000..3b79db58a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-02.png new file mode 100644 index 000000000..05653bd79 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-03.png new file mode 100644 index 000000000..978f6a09c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-04.png new file mode 100644 index 000000000..dce9b6747 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-05.png new file mode 100644 index 000000000..afa6a6911 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-06.png new file mode 100644 index 000000000..f810a3118 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-07.png new file mode 100644 index 000000000..3d4feddab Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-08.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-08.png new file mode 100644 index 000000000..9bcef3f45 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-0-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-01.png new file mode 100644 index 000000000..7283e3aa6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-02.png new file mode 100644 index 000000000..7727ba881 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-1-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-1-01.png new file mode 100644 index 000000000..b5bbdce1d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-1-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-1-02.png new file mode 100644 index 000000000..0fde02b9b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-10-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-10-01.png new file mode 100644 index 000000000..9baad7c5a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-10-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-10-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-10-02.png new file mode 100644 index 000000000..9cb07a1d7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-10-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-11-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-11-01.png new file mode 100644 index 000000000..786e82759 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-11-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-11-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-11-02.png new file mode 100644 index 000000000..f080a05a6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-11-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-11-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-11-03.png new file mode 100644 index 000000000..fb234dc7f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-11-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-11-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-11-04.png new file mode 100644 index 000000000..c5f7f06f4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-11-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-01.png new file mode 100644 index 000000000..9b1aeded8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-02.png new file mode 100644 index 000000000..040b9e8e0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-03.png new file mode 100644 index 000000000..5571d3def Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-04.png new file mode 100644 index 000000000..b71d39e62 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-05.png new file mode 100644 index 000000000..a67260959 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-06.png new file mode 100644 index 000000000..7ab41408c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-12-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-01.png new file mode 100644 index 000000000..97f5f090c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-02.png new file mode 100644 index 000000000..f668aa163 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-03.png new file mode 100644 index 000000000..76aa86c13 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-04.png new file mode 100644 index 000000000..794256633 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-05.png new file mode 100644 index 000000000..1cbff6409 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-06.png new file mode 100644 index 000000000..15a2fce6b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-07.png new file mode 100644 index 000000000..94c1b271f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-08.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-08.png new file mode 100644 index 000000000..1c11a1e7c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-13-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-15-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-15-01.png new file mode 100644 index 000000000..2e066f914 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-15-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-15-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-15-02.png new file mode 100644 index 000000000..5e165a92f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-15-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-01.png new file mode 100644 index 000000000..d66ac8f17 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-02.png new file mode 100644 index 000000000..221eae276 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-03.png new file mode 100644 index 000000000..750b011ad Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-04.png new file mode 100644 index 000000000..e00bc1510 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-05.png new file mode 100644 index 000000000..e1b582a41 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-16-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-17-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-17-01.png new file mode 100644 index 000000000..851f16dd2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-17-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-17-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-17-02.png new file mode 100644 index 000000000..126da06a5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-17-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-17-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-17-03.png new file mode 100644 index 000000000..87964973b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-17-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-17-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-17-04.png new file mode 100644 index 000000000..71bf9272c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-17-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-18-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-18-01.png new file mode 100644 index 000000000..89074e025 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-18-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-18-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-18-02.png new file mode 100644 index 000000000..94cc7af6e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-18-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-18-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-18-03.png new file mode 100644 index 000000000..8e4b21647 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-18-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-18-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-18-04.png new file mode 100644 index 000000000..f54895357 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-18-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-01.png new file mode 100644 index 000000000..d253947b4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-02.png new file mode 100644 index 000000000..79bcfe630 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-03.png new file mode 100644 index 000000000..3f3f51a31 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-04.png new file mode 100644 index 000000000..3f45dfb5d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-05.png new file mode 100644 index 000000000..f35d7e35b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-06.png new file mode 100644 index 000000000..784d0b8b3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-07.png new file mode 100644 index 000000000..1a919d925 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-19-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-01.png new file mode 100644 index 000000000..fbfb8c474 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-02.png new file mode 100644 index 000000000..6c678a496 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-03.png new file mode 100644 index 000000000..7dc85bd09 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-04.png new file mode 100644 index 000000000..07efe9729 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-05.png new file mode 100644 index 000000000..be68de99f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-06.png new file mode 100644 index 000000000..5d28e632e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-07.png new file mode 100644 index 000000000..b840dc101 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-08.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-08.png new file mode 100644 index 000000000..eebb64fca Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-09.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-09.png new file mode 100644 index 000000000..a5fa4c564 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-09.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-10.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-10.png new file mode 100644 index 000000000..f61261e07 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-10.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-11.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-11.png new file mode 100644 index 000000000..dbe8c1660 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-11.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-12.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-12.png new file mode 100644 index 000000000..46a3431ae Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-2-12.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-01.png new file mode 100644 index 000000000..5c9f7de54 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-02.png new file mode 100644 index 000000000..de69255d8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-03.png new file mode 100644 index 000000000..f19061b14 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-04.png new file mode 100644 index 000000000..d081d93e9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-05.png new file mode 100644 index 000000000..4c35ba6c9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-06.png new file mode 100644 index 000000000..d021448ef Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-07.png new file mode 100644 index 000000000..46b1e748f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-20-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-01.png new file mode 100644 index 000000000..c8f2df63d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-02.png new file mode 100644 index 000000000..1731ae34a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-03.png new file mode 100644 index 000000000..1ec050eb6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-04.png new file mode 100644 index 000000000..64a0e2e6c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-05.png new file mode 100644 index 000000000..9792485b6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-06.png new file mode 100644 index 000000000..1f08610df Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-07.png new file mode 100644 index 000000000..4c7c79bbb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-08.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-08.png new file mode 100644 index 000000000..3445d70d2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-21-08.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-3-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-3-01.png new file mode 100644 index 000000000..6c72e2f86 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-3-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-3-02.png new file mode 100644 index 000000000..129843d29 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-3-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-3-03.png new file mode 100644 index 000000000..c67c42a37 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-4-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-4-01.png new file mode 100644 index 000000000..b8191bb9e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-4-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-4-02.png new file mode 100644 index 000000000..9d18d20fb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-5-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-5-01.png new file mode 100644 index 000000000..3d807a4eb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-5-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-5-02.png new file mode 100644 index 000000000..757e76d28 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-5-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-5-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-5-03.png new file mode 100644 index 000000000..cbdb71778 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-5-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-5-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-5-04.png new file mode 100644 index 000000000..d15e43a49 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-5-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-6-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-6-01.png new file mode 100644 index 000000000..68d017da8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-6-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-6-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-6-02.png new file mode 100644 index 000000000..9b23b3a02 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-6-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-6-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-6-03.png new file mode 100644 index 000000000..b98217de4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-6-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-7-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-7-01.png new file mode 100644 index 000000000..3f00ca8f6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-7-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-7-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-7-02.png new file mode 100644 index 000000000..95db900f8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-7-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-8-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-8-01.png new file mode 100644 index 000000000..fcc03b4ac Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-8-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-8-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-8-02.png new file mode 100644 index 000000000..67ab78fdd Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-8-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-8-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-8-03.png new file mode 100644 index 000000000..ef6163179 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-8-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-9-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-9-01.png new file mode 100644 index 000000000..a50d21c86 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-9-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-9-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-9-02.png new file mode 100644 index 000000000..6e1e117b2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-9-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-9-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-9-03.png new file mode 100644 index 000000000..32cd9c458 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-3-9-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-01.png new file mode 100644 index 000000000..bd0146c60 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-02.png new file mode 100644 index 000000000..1530b2440 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-03.png new file mode 100644 index 000000000..d8fb6c1d8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-04.png new file mode 100644 index 000000000..604c077b5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-05.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-05.png new file mode 100644 index 000000000..36a42813d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-05.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-06.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-06.png new file mode 100644 index 000000000..7b146035b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-06.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-07.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-07.png new file mode 100644 index 000000000..3ae3ffa14 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-4-07.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-5-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-5-01.png new file mode 100644 index 000000000..127cdd237 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-5-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-5-02.png new file mode 100644 index 000000000..488843d7c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-5-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-6-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-6-01.png new file mode 100644 index 000000000..467ce20f0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-6-01.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-6-02.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-6-02.png new file mode 100644 index 000000000..86d1a2178 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-6-02.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-6-03.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-6-03.png new file mode 100644 index 000000000..23bec8fcc Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-6-03.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-6-04.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-6-04.png new file mode 100644 index 000000000..88c466876 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-6-04.png differ diff --git a/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-9-01.png b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-9-01.png new file mode 100644 index 000000000..496eef7f4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/ai-rag-knowledge/ai-rag-knowledge-9-01.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-49-01.png b/docs/.vuepress/public/images/article/project/big-market/big-market-49-01.png new file mode 100644 index 000000000..601ad166b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-49-01.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-49-02.png b/docs/.vuepress/public/images/article/project/big-market/big-market-49-02.png new file mode 100644 index 000000000..4bc067fad Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-49-02.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-49-03.png b/docs/.vuepress/public/images/article/project/big-market/big-market-49-03.png new file mode 100644 index 000000000..85fe68cfe Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-49-03.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-49-04.png b/docs/.vuepress/public/images/article/project/big-market/big-market-49-04.png new file mode 100644 index 000000000..edc4586f4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-49-04.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-49-05.png b/docs/.vuepress/public/images/article/project/big-market/big-market-49-05.png new file mode 100644 index 000000000..86ebb96f9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-49-05.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-49-06.png b/docs/.vuepress/public/images/article/project/big-market/big-market-49-06.png new file mode 100644 index 000000000..7d9454720 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-49-06.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-50-01.png b/docs/.vuepress/public/images/article/project/big-market/big-market-50-01.png new file mode 100644 index 000000000..ca97a7b4c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-50-01.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-50-02.png b/docs/.vuepress/public/images/article/project/big-market/big-market-50-02.png new file mode 100644 index 000000000..634f4f4bf Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-50-02.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-50-03.png b/docs/.vuepress/public/images/article/project/big-market/big-market-50-03.png new file mode 100644 index 000000000..72a546b95 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-50-03.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-50-04.png b/docs/.vuepress/public/images/article/project/big-market/big-market-50-04.png new file mode 100644 index 000000000..230c90831 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-50-04.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-51-01.png b/docs/.vuepress/public/images/article/project/big-market/big-market-51-01.png new file mode 100644 index 000000000..93108fbe2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-51-01.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-51-02.png b/docs/.vuepress/public/images/article/project/big-market/big-market-51-02.png new file mode 100644 index 000000000..2e4712e6a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-51-02.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-51-03.png b/docs/.vuepress/public/images/article/project/big-market/big-market-51-03.png new file mode 100644 index 000000000..49a4908c6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-51-03.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-51-04.png b/docs/.vuepress/public/images/article/project/big-market/big-market-51-04.png new file mode 100644 index 000000000..763b14796 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-51-04.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-52-01.png b/docs/.vuepress/public/images/article/project/big-market/big-market-52-01.png new file mode 100644 index 000000000..d8b683421 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-52-01.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-52-02.png b/docs/.vuepress/public/images/article/project/big-market/big-market-52-02.png new file mode 100644 index 000000000..25ff7d7df Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-52-02.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-52-03.png b/docs/.vuepress/public/images/article/project/big-market/big-market-52-03.png new file mode 100644 index 000000000..3c6967d0a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-52-03.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-53-01.png b/docs/.vuepress/public/images/article/project/big-market/big-market-53-01.png new file mode 100644 index 000000000..2813a9db1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-53-01.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-53-02.png b/docs/.vuepress/public/images/article/project/big-market/big-market-53-02.png new file mode 100644 index 000000000..50edfa7e0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-53-02.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-53-03.png b/docs/.vuepress/public/images/article/project/big-market/big-market-53-03.png new file mode 100644 index 000000000..990a7db27 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-53-03.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-53-04.png b/docs/.vuepress/public/images/article/project/big-market/big-market-53-04.png new file mode 100644 index 000000000..f196f8c2b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-53-04.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-53-05.png b/docs/.vuepress/public/images/article/project/big-market/big-market-53-05.png new file mode 100644 index 000000000..176b10803 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-53-05.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-53-06.png b/docs/.vuepress/public/images/article/project/big-market/big-market-53-06.png new file mode 100644 index 000000000..97a6512cb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-53-06.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-01.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-01.png new file mode 100644 index 000000000..adbac603d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-02.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-02.png new file mode 100644 index 000000000..85328fac7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-02.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-03.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-03.png new file mode 100644 index 000000000..3bb894277 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-03.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-04.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-04.png new file mode 100644 index 000000000..aa2b7afa4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-04.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-05.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-05.png new file mode 100644 index 000000000..610114578 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-05.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-06.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-06.png new file mode 100644 index 000000000..fcd432bd1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-06.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-07.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-07.png new file mode 100644 index 000000000..50910d8d1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-07.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-08.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-08.png new file mode 100644 index 000000000..ca4801f29 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-08.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-09.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-09.png new file mode 100644 index 000000000..6476abc21 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-09.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-10.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-10.png new file mode 100644 index 000000000..31e91bc35 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-10.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-11.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-11.png new file mode 100644 index 000000000..24647031b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-11.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-12.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-12.png new file mode 100644 index 000000000..0546783af Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-12.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-13.png b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-13.png new file mode 100644 index 000000000..96c2f57b0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-dev-ops-5-13.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-01.png b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-01.png new file mode 100644 index 000000000..b183d421a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-01.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-02.png b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-02.png new file mode 100644 index 000000000..b2fe305aa Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-02.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-03.png b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-03.png new file mode 100644 index 000000000..e0d91b044 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-03.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-04.png b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-04.png new file mode 100644 index 000000000..d5dabd66a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-04.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-05.png b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-05.png new file mode 100644 index 000000000..d61909685 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-05.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-06.png b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-06.png new file mode 100644 index 000000000..ecc720319 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-06.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-07.png b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-07.png new file mode 100644 index 000000000..57b3e4231 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-07.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-08.png b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-08.png new file mode 100644 index 000000000..9b6d0ba02 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-system-design-diagram-08.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-v8-01.gif b/docs/.vuepress/public/images/article/project/big-market/big-market-v8-01.gif new file mode 100644 index 000000000..e60416b99 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-v8-01.gif differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-v8-02.png b/docs/.vuepress/public/images/article/project/big-market/big-market-v8-02.png new file mode 100644 index 000000000..7dbcad55b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-v8-02.png differ diff --git a/docs/.vuepress/public/images/article/project/big-market/big-market-v8-03.png b/docs/.vuepress/public/images/article/project/big-market/big-market-v8-03.png new file mode 100644 index 000000000..763b14796 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/big-market/big-market-v8-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-1-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-1-01.png new file mode 100755 index 000000000..a77dce7e0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-1-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-1-02.png new file mode 100644 index 000000000..d0c2faa5a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-1-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-1-03.png new file mode 100644 index 000000000..f11d9c172 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-1-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-1-04.png new file mode 100644 index 000000000..3e4c31bd9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-2-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-2-01.png new file mode 100755 index 000000000..18373c4d0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-2-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-2-02.png new file mode 100644 index 000000000..85398e1f5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-2-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-2-03.png new file mode 100644 index 000000000..aecfbc484 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-3-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-3-01.png new file mode 100755 index 000000000..deeb57278 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-3-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-3-02.png new file mode 100644 index 000000000..ad9913a80 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-3-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-3-03.png new file mode 100644 index 000000000..5420a9486 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-3-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-3-04.png new file mode 100644 index 000000000..d252b1cf1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-1-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-01.png new file mode 100755 index 000000000..b82291008 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-02.png new file mode 100644 index 000000000..45c2c2c85 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-03.png new file mode 100644 index 000000000..51caebdf0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-04.png new file mode 100644 index 000000000..4d8ab0ba3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-05.png new file mode 100644 index 000000000..13ac69ed8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-1-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-10-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-10-01.png new file mode 100755 index 000000000..05bc77a6e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-10-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-10-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-10-02.png new file mode 100644 index 000000000..f39060f69 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-10-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-01.png new file mode 100755 index 000000000..85c5cb2e5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-02.png new file mode 100644 index 000000000..4f7e05ced Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-03.png new file mode 100644 index 000000000..09ccb2bc6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-04.png new file mode 100644 index 000000000..fe28a4f38 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-05.png new file mode 100644 index 000000000..7a2b89441 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-11-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-01.png new file mode 100755 index 000000000..3606d04e1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-02.png new file mode 100644 index 000000000..2f0e8d14c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-03.png new file mode 100644 index 000000000..c856b9e87 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-04.png new file mode 100644 index 000000000..b5665978c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-05.png new file mode 100644 index 000000000..d1a40ff30 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-06.png new file mode 100644 index 000000000..af1c60504 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-12-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-01.png new file mode 100755 index 000000000..c884d5408 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-02.png new file mode 100644 index 000000000..ad6ca2cbb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-03.png new file mode 100644 index 000000000..b1e7be26e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-04.png new file mode 100644 index 000000000..889bcf4b8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-05.png new file mode 100644 index 000000000..e03d2b6cc Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-06.png new file mode 100644 index 000000000..cd852ac1d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-13-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-14-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-14-01.png new file mode 100755 index 000000000..ee4a7ee3a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-14-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-14-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-14-02.png new file mode 100644 index 000000000..9c736b620 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-14-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-14-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-14-03.png new file mode 100644 index 000000000..8c8f7fd0f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-14-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-14-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-14-04.png new file mode 100644 index 000000000..14937dd1a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-14-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-01.png new file mode 100755 index 000000000..c8b49a1d7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-02.png new file mode 100644 index 000000000..986a78f7f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-03.png new file mode 100644 index 000000000..3506000a0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-04.png new file mode 100644 index 000000000..a3fd8a14a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-05.png new file mode 100644 index 000000000..695840223 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-06.png new file mode 100644 index 000000000..ba055f25d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-07.png new file mode 100644 index 000000000..2b24014dd Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-15-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-01.png new file mode 100755 index 000000000..9ba052966 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-02.png new file mode 100644 index 000000000..931f1a666 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-03.png new file mode 100644 index 000000000..52aab91db Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-04.png new file mode 100644 index 000000000..57924829d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-05.png new file mode 100644 index 000000000..d1de4275c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-06.png new file mode 100644 index 000000000..2a0946dcb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-07.png new file mode 100644 index 000000000..edb349e2a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-08.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-08.png new file mode 100644 index 000000000..0d3019273 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-16-08.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-17-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-17-01.png new file mode 100755 index 000000000..cdc863458 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-17-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-17-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-17-02.png new file mode 100644 index 000000000..bdae13477 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-17-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-17-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-17-03.png new file mode 100644 index 000000000..93a0704b9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-17-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-17-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-17-04.png new file mode 100644 index 000000000..b4b6ee124 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-17-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-01.png new file mode 100755 index 000000000..db2f28b6b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-02.png new file mode 100644 index 000000000..998d3feb8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-03.png new file mode 100644 index 000000000..e453e688b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-04.png new file mode 100644 index 000000000..b3b2ecaab Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-05.png new file mode 100644 index 000000000..3fd37d331 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-06.png new file mode 100644 index 000000000..6a8253e1b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-07.png new file mode 100644 index 000000000..057bd03ab Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-18-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-19-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-19-01.png new file mode 100755 index 000000000..01254b9e2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-19-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-19-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-19-02.png new file mode 100644 index 000000000..ecccf2307 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-19-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-19-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-19-03.png new file mode 100644 index 000000000..f113a8b5c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-19-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-19-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-19-04.png new file mode 100644 index 000000000..d5807e5e6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-19-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-2-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-2-01.png new file mode 100755 index 000000000..f53555121 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-2-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-2-02.png new file mode 100644 index 000000000..e0bc62e87 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-2-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-2-03.png new file mode 100644 index 000000000..a87652b3d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-20-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-20-01.png new file mode 100755 index 000000000..2af83e7b6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-20-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-20-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-20-02.png new file mode 100644 index 000000000..dda6ceaf4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-20-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-01.png new file mode 100755 index 000000000..b65b52fea Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-02.png new file mode 100644 index 000000000..8eee79253 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-03.png new file mode 100644 index 000000000..4f631d096 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-04.png new file mode 100644 index 000000000..2bb9b3279 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-05.png new file mode 100644 index 000000000..643965d2b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-06.png new file mode 100644 index 000000000..4c6274252 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-07.png new file mode 100644 index 000000000..2553d8b4d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-21-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-22-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-22-01.png new file mode 100755 index 000000000..47e379abe Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-22-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-22-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-22-02.png new file mode 100644 index 000000000..125f06912 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-22-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-22-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-22-03.png new file mode 100644 index 000000000..76ee0b584 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-22-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-22-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-22-04.png new file mode 100644 index 000000000..5cf021726 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-22-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-01.png new file mode 100755 index 000000000..a6406ec9c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-02.png new file mode 100644 index 000000000..a6fe9553c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-03.png new file mode 100644 index 000000000..4f40aa8af Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-04.png new file mode 100644 index 000000000..494c51c25 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-05.png new file mode 100644 index 000000000..ecb903ab1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-06.png new file mode 100644 index 000000000..b88fd23f0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-07.png new file mode 100644 index 000000000..e17c8f39c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-08.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-08.png new file mode 100644 index 000000000..244e0d7f9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-08.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-09.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-09.png new file mode 100644 index 000000000..0d1fbd769 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-09.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-10.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-10.png new file mode 100644 index 000000000..e1db230f3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-10.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-11.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-11.png new file mode 100644 index 000000000..082e3d433 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-23-11.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-01.png new file mode 100755 index 000000000..e2d98a8c4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-02.png new file mode 100644 index 000000000..c0d103502 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-03.png new file mode 100644 index 000000000..b8d994512 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-04.png new file mode 100644 index 000000000..3f3904fc0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-05.png new file mode 100644 index 000000000..07416dcac Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-06.png new file mode 100644 index 000000000..f9c59efed Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-07.png new file mode 100644 index 000000000..c85bb6ba6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-08.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-08.png new file mode 100644 index 000000000..389890a57 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-08.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-09.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-09.png new file mode 100644 index 000000000..8c1801aea Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-09.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-10.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-10.png new file mode 100644 index 000000000..6f2a5e6eb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-10.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-11.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-11.png new file mode 100644 index 000000000..7ff3fe45b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-11.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-12.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-12.png new file mode 100644 index 000000000..4ad20bb1b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-12.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-13.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-13.png new file mode 100644 index 000000000..a5724ce4c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-13.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-14.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-14.png new file mode 100644 index 000000000..6a7ac4f11 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-14.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-15.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-15.png new file mode 100644 index 000000000..ef2202b67 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-15.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-16.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-16.png new file mode 100644 index 000000000..4ddba8640 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-24-16.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-25-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-25-01.png new file mode 100755 index 000000000..c9e3f4490 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-25-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-25-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-25-02.png new file mode 100644 index 000000000..1b5f4fa29 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-25-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-25-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-25-03.png new file mode 100644 index 000000000..5f7770fb3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-25-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-25-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-25-04.png new file mode 100644 index 000000000..cc252ebe8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-25-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-26-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-26-01.png new file mode 100755 index 000000000..de5b5170f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-26-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-26-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-26-02.png new file mode 100644 index 000000000..43ecb2eda Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-26-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-26-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-26-03.png new file mode 100644 index 000000000..64ad4bf38 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-26-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-26-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-26-04.png new file mode 100644 index 000000000..b32c58f20 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-26-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-27-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-27-01.png new file mode 100755 index 000000000..b959cd95a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-27-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-27-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-27-02.png new file mode 100644 index 000000000..978c94137 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-27-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-27-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-27-03.png new file mode 100644 index 000000000..14bfb07f7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-27-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-27-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-27-04.png new file mode 100644 index 000000000..ae6dfeb12 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-27-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-01.png new file mode 100755 index 000000000..31838b989 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-02.png new file mode 100644 index 000000000..121fd06f4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-03.png new file mode 100644 index 000000000..16ddf07dd Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-04.png new file mode 100644 index 000000000..38bb7d7f4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-05.png new file mode 100644 index 000000000..86dea6e3b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-28-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-29-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-29-01.png new file mode 100755 index 000000000..1fefa7a0a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-29-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-29-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-29-02.png new file mode 100644 index 000000000..1aaf14d0e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-29-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-29-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-29-03.png new file mode 100644 index 000000000..eab506d5d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-29-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-29-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-29-04.png new file mode 100644 index 000000000..9f8ca3de4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-29-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-3-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-3-01.png new file mode 100755 index 000000000..7987a0889 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-3-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-3-02.png new file mode 100644 index 000000000..277fb1f3a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-30-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-30-01.png new file mode 100755 index 000000000..68a964a34 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-30-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-30-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-30-02.png new file mode 100644 index 000000000..87b072b57 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-30-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-30-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-30-03.png new file mode 100644 index 000000000..0ee4721db Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-30-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-30-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-30-04.png new file mode 100644 index 000000000..2071429d0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-30-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-31-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-31-01.png new file mode 100755 index 000000000..239b0cee4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-31-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-31-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-31-02.png new file mode 100644 index 000000000..bbf413d4f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-31-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-31-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-31-03.png new file mode 100644 index 000000000..9d4dac0c0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-31-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-31-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-31-04.png new file mode 100644 index 000000000..befbedacb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-31-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-4-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-4-01.png new file mode 100755 index 000000000..7230d1fac Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-4-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-4-02.png new file mode 100644 index 000000000..84d8a0d80 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-4-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-4-03.png new file mode 100644 index 000000000..10c7f4701 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-4-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-5-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-5-01.png new file mode 100755 index 000000000..b21426317 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-5-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-5-02.png new file mode 100644 index 000000000..a1380f443 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-5-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-5-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-5-03.png new file mode 100644 index 000000000..a48faa57f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-5-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-6-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-6-01.png new file mode 100755 index 000000000..1459d06c5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-6-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-6-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-6-02.png new file mode 100644 index 000000000..abb2c7147 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-6-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-6-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-6-03.png new file mode 100644 index 000000000..048edbad2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-6-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-7-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-7-01.png new file mode 100755 index 000000000..33fc4d76b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-7-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-7-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-7-02.png new file mode 100644 index 000000000..e51bc8f7c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-7-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-7-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-7-03.png new file mode 100644 index 000000000..8aab66507 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-7-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-7-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-7-04.png new file mode 100644 index 000000000..76efa198b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-7-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-8-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-8-01.png new file mode 100755 index 000000000..a89bd4457 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-8-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-8-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-8-02.png new file mode 100644 index 000000000..eadb631d2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-8-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-8-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-8-03.png new file mode 100644 index 000000000..e798d6572 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-8-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-9-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-9-01.png new file mode 100755 index 000000000..e23a63a58 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-9-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-9-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-9-02.png new file mode 100644 index 000000000..2918546b1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-9-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-9-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-9-03.png new file mode 100644 index 000000000..31d3d020f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-2-9-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-01.png new file mode 100755 index 000000000..64c12689b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-02.png new file mode 100755 index 000000000..5c19c2f4d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-03.png new file mode 100755 index 000000000..3c79aef06 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-04.png new file mode 100755 index 000000000..326a55536 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-05.png new file mode 100755 index 000000000..6c1313a76 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-241109-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-01.png new file mode 100755 index 000000000..8fdc3ee03 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-02.png new file mode 100644 index 000000000..cc7bd813e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-03.png new file mode 100644 index 000000000..ac6ca2d13 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-04.png new file mode 100644 index 000000000..b7357d384 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-05.png new file mode 100644 index 000000000..e9fba3ec1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-1-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-01.png new file mode 100755 index 000000000..075532cbf Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-02.png new file mode 100644 index 000000000..c7309121d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-03.png new file mode 100644 index 000000000..feff1c8a4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-04.png new file mode 100644 index 000000000..9fcf2f686 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-05.png new file mode 100644 index 000000000..c81ddf439 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-06.png new file mode 100644 index 000000000..016d7584c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-2-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-01.png new file mode 100755 index 000000000..00694546f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-02.png new file mode 100644 index 000000000..716a4ca2b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-03.png new file mode 100644 index 000000000..ef5e15dcb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-04.png new file mode 100644 index 000000000..3847b5ea6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-05.png new file mode 100644 index 000000000..d039a38f6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-06.png new file mode 100644 index 000000000..79dc0dc86 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-07.png new file mode 100644 index 000000000..3d7d2be0a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-08.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-08.png new file mode 100644 index 000000000..21b1f7bc4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-3-08.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-4-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-4-01.png new file mode 100755 index 000000000..94571111d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-4-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-4-02.png new file mode 100644 index 000000000..92f41f708 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-4-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-4-03.png new file mode 100644 index 000000000..f265c188f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-4-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-5-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-5-01.png new file mode 100755 index 000000000..635390ffc Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-5-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-5-02.png new file mode 100644 index 000000000..2652e8ba6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-5-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-5-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-5-03.png new file mode 100644 index 000000000..cca199176 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-5-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-01.png new file mode 100755 index 000000000..05ac88b76 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-02.png new file mode 100644 index 000000000..e0b78f87e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-03.png new file mode 100644 index 000000000..6ab929e8e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-04.png new file mode 100644 index 000000000..9c4efd4a7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-05.png new file mode 100644 index 000000000..6ad83f5a5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-6-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-01.png new file mode 100755 index 000000000..bc81b7f6b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-02.png new file mode 100644 index 000000000..a4c448ecc Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-03.png new file mode 100644 index 000000000..d3b451f0a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-04.png new file mode 100644 index 000000000..4d501269b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-05.png new file mode 100644 index 000000000..224ad3cb7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-06.png new file mode 100644 index 000000000..f54ae6f88 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-7-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-01.png new file mode 100755 index 000000000..e47c88d82 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-02.png new file mode 100644 index 000000000..4654ea88f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-03.png new file mode 100644 index 000000000..32fa8dfc6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-04.png new file mode 100644 index 000000000..cc3668986 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-05.png new file mode 100644 index 000000000..c819870bf Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-06.png new file mode 100644 index 000000000..348a8bc05 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-07.png new file mode 100644 index 000000000..d4781a1f0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-08.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-08.png new file mode 100644 index 000000000..8ebed8cd0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-3-8-08.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-01.png new file mode 100755 index 000000000..dfc1f1781 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-02.png new file mode 100644 index 000000000..f849c9567 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-03.png new file mode 100644 index 000000000..8493ffdf6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-04.png new file mode 100644 index 000000000..91bda7fe3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-05.png new file mode 100644 index 000000000..5d0e3e81f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-06.png new file mode 100644 index 000000000..c12e464c0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-07.png new file mode 100644 index 000000000..4f467b52a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-08.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-08.png new file mode 100644 index 000000000..c383df54c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-1-08.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-01.png new file mode 100755 index 000000000..ed63ba4bf Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-02.png new file mode 100644 index 000000000..25479bf79 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-03.png new file mode 100644 index 000000000..83480e7ef Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-04.png new file mode 100644 index 000000000..bb31a2536 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-05.png new file mode 100644 index 000000000..550da8ec7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-06.png new file mode 100644 index 000000000..aafc71726 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-07.png new file mode 100644 index 000000000..c88a175c5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-08.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-08.png new file mode 100644 index 000000000..fde7a2378 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-2-08.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-01.png new file mode 100755 index 000000000..6d900205e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-02.png new file mode 100644 index 000000000..0548a3e95 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-03.png new file mode 100644 index 000000000..ad8eb566e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-04.png new file mode 100644 index 000000000..353e41dd4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-05.png new file mode 100644 index 000000000..67cff6d74 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-06.png new file mode 100644 index 000000000..8a16078ee Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-07.png new file mode 100644 index 000000000..ef967f867 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-4-3-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-notes-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-notes-01.png new file mode 100644 index 000000000..060939d7c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-notes-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-241229-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-241229-01.png new file mode 100644 index 000000000..1853f66de Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-241229-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-241229-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-241229-02.png new file mode 100644 index 000000000..68b5af395 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-241229-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-01.gif b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-01.gif new file mode 100644 index 000000000..5d637f90d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-01.gif differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-02.png new file mode 100644 index 000000000..4bf2b198c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-03.png new file mode 100644 index 000000000..13a47fc30 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-04.png new file mode 100644 index 000000000..b2852152e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-05.png new file mode 100644 index 000000000..6381be155 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-06.png new file mode 100644 index 000000000..527f27d9b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250118-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-01.png new file mode 100644 index 000000000..8db8aa512 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-02.png new file mode 100644 index 000000000..c3a25fc4e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-03.png new file mode 100644 index 000000000..f0b40ef53 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-04.png new file mode 100644 index 000000000..e5310a097 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-05.png new file mode 100644 index 000000000..b9ec88b6f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-06.png new file mode 100644 index 000000000..16f387955 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-07.png new file mode 100644 index 000000000..569d5dba5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-08.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-08.png new file mode 100644 index 000000000..4db135cad Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250205-08.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250629-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250629-01.png new file mode 100644 index 000000000..258d2db63 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250629-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250629-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250629-02.png new file mode 100644 index 000000000..24b910750 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250629-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250803-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250803-01.png new file mode 100644 index 000000000..ba229e549 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250803-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250803-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250803-02.png new file mode 100644 index 000000000..a90eadc98 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250803-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250803-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250803-03.png new file mode 100644 index 000000000..fa410b53d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250803-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250803-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250803-04.png new file mode 100644 index 000000000..5acd6faaa Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-250803-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-01.png new file mode 100644 index 000000000..e42a15181 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-02.png new file mode 100644 index 000000000..ebf2eb61b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-03.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-03.png new file mode 100644 index 000000000..13a32fbd9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-03.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-04.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-04.png new file mode 100644 index 000000000..c913caa22 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-04.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-05.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-05.png new file mode 100644 index 000000000..85f363fe0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-05.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-06.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-06.png new file mode 100644 index 000000000..60707c183 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-06.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-07.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-07.png new file mode 100644 index 000000000..219df9a91 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v4-07.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v5-01.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v5-01.png new file mode 100644 index 000000000..c575e158e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v5-02.png b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v5-02.png new file mode 100644 index 000000000..044718d9d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/group-buy-market/group-buy-market-promotion-v5-02.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-01.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-01.png new file mode 100644 index 000000000..4b09b9734 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-01.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-1-01.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-1-01.png new file mode 100644 index 000000000..ad4902995 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-1-02.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-1-02.png new file mode 100644 index 000000000..bb7d25c93 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-1-03.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-1-03.png new file mode 100644 index 000000000..8b4c891c3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-01.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-01.png new file mode 100644 index 000000000..671241ef0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-02.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-02.png new file mode 100644 index 000000000..587f6b960 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-03.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-03.png new file mode 100644 index 000000000..fb2da7256 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-04.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-04.png new file mode 100644 index 000000000..45b14206c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-04.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-05.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-05.png new file mode 100644 index 000000000..27c555a7d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-2-05.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-01.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-01.png new file mode 100644 index 000000000..dc7abef89 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-02.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-02.png new file mode 100644 index 000000000..fbce624f0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-03.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-03.png new file mode 100644 index 000000000..246740714 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-04.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-04.png new file mode 100644 index 000000000..dd438d30c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-05.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-05.png new file mode 100644 index 000000000..acb15f2c0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-05.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-06.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-06.png new file mode 100644 index 000000000..a0bbf13f4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-06.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-07.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-07.png new file mode 100644 index 000000000..a5c391307 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-3-07.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-01.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-01.png new file mode 100644 index 000000000..656b058c9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-02.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-02.png new file mode 100644 index 000000000..880758f95 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-03.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-03.png new file mode 100644 index 000000000..0697811fa Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-03.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-04.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-04.png new file mode 100644 index 000000000..fcda29a67 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-04.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-05.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-05.png new file mode 100644 index 000000000..99e69594b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-4-05.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-5-01.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-5-01.png new file mode 100644 index 000000000..7458f5d45 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-5-02.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-5-02.png new file mode 100644 index 000000000..b36135fae Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-5-02.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-5-03.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-5-03.png new file mode 100644 index 000000000..3c468c66c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-5-03.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-5-04.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-5-04.png new file mode 100644 index 000000000..a5f929302 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-5-04.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-6-01.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-6-01.png new file mode 100644 index 000000000..818ae30d2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-6-01.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-6-02.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-6-02.png new file mode 100644 index 000000000..f79e504c3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-6-02.png differ diff --git a/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-6-03.png b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-6-03.png new file mode 100644 index 000000000..0a6599552 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/local-task-message/local-task-message-6-03.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-01.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-01.png new file mode 100644 index 000000000..072c6fe3b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-01.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-02.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-02.png new file mode 100644 index 000000000..1d32cceac Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-02.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-03.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-03.png new file mode 100644 index 000000000..33786c268 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-03.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-04.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-04.png new file mode 100644 index 000000000..8b47275a5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-04.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-05.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-05.png new file mode 100644 index 000000000..4704c9486 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-05.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-06.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-06.png new file mode 100644 index 000000000..fc9460b32 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-06.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-07.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-07.png new file mode 100644 index 000000000..b738804ff Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-07.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-08.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-08.png new file mode 100644 index 000000000..4c969101b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-08.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-09.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-09.png new file mode 100644 index 000000000..502504c0b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-09.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-10.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-10.png new file mode 100644 index 000000000..fa65ea6d2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-10.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-11.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-11.png new file mode 100644 index 000000000..1f6235d5f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-11.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-12.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-12.png new file mode 100644 index 000000000..64e72cc74 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-12.png differ diff --git a/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-13.png b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-13.png new file mode 100644 index 000000000..55dedc253 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/lucky-tackout/lucky-tackout-introduction-13.png differ diff --git a/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-01.png b/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-01.png new file mode 100644 index 000000000..d1f832197 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-02.png b/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-02.png new file mode 100644 index 000000000..453c3da13 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-03.png b/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-03.png new file mode 100644 index 000000000..afc1ef440 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-04.png b/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-04.png new file mode 100644 index 000000000..4c4046f0e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-05.png b/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-05.png new file mode 100644 index 000000000..ada1369cd Binary files /dev/null and b/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-05.png differ diff --git a/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-06.png b/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-06.png new file mode 100644 index 000000000..fd5c9ea1b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/prd/xfg-prd-1-06.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-01.png new file mode 100644 index 000000000..d73726c56 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-02.png new file mode 100644 index 000000000..3a3080d99 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-03.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-03.png new file mode 100644 index 000000000..e582f1150 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-04.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-04.png new file mode 100644 index 000000000..ded65f9c2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-04.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-05.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-05.png new file mode 100644 index 000000000..cb89076c7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-2-05.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-3-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-3-01.png new file mode 100644 index 000000000..2152ee64c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-3-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-3-02.png new file mode 100644 index 000000000..8cc8a9ed8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-2-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-01.png new file mode 100644 index 000000000..4ced3d23c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-02.png new file mode 100644 index 000000000..7044efbf4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-03.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-03.png new file mode 100644 index 000000000..b82d12b4c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-04.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-04.png new file mode 100644 index 000000000..2492516a2 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-05.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-05.png new file mode 100644 index 000000000..51eefdd64 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-05.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-06.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-06.png new file mode 100644 index 000000000..26f80cf88 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-06.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-07.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-07.png new file mode 100644 index 000000000..d56ac7d3d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-07.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-08.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-08.png new file mode 100644 index 000000000..89a9602c4 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-08.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-09.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-09.png new file mode 100644 index 000000000..aab97d7a6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-09.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-10.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-10.png new file mode 100644 index 000000000..c141e153e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-1-10.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-01.png new file mode 100644 index 000000000..f9fc6a122 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-02.png new file mode 100644 index 000000000..e52b790cb Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-03.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-03.png new file mode 100644 index 000000000..4a789947a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-04.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-04.png new file mode 100644 index 000000000..c8d8c5300 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-04.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-05.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-05.png new file mode 100644 index 000000000..407f25594 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-05.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-06.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-06.png new file mode 100644 index 000000000..9f96f9500 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-06.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-07.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-07.png new file mode 100644 index 000000000..853112319 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-07.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-08.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-08.png new file mode 100644 index 000000000..d9c7436c6 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-08.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-09.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-09.png new file mode 100644 index 000000000..39a6f9b4a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-09.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-10.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-10.png new file mode 100644 index 000000000..6791c4291 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-2-10.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-01.png new file mode 100644 index 000000000..92844e6f3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-02.png new file mode 100644 index 000000000..ee4beac9e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-03.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-03.png new file mode 100644 index 000000000..af41df69a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-04.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-04.png new file mode 100644 index 000000000..f4357f47b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-05.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-05.png new file mode 100644 index 000000000..e657cb62a Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-05.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-06.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-06.png new file mode 100644 index 000000000..5d2c96932 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-4-3-06.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-1-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-1-01.png new file mode 100644 index 000000000..dac7c7cf9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-1-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-1-02.png new file mode 100644 index 000000000..ab8a37566 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-2-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-2-02.png new file mode 100644 index 000000000..7cd44a207 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-3-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-3-01.png new file mode 100644 index 000000000..ab7c08ed5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-4-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-4-01.png new file mode 100644 index 000000000..237532bf7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-6-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-6-01.png new file mode 100644 index 000000000..38efa3421 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-ddd-3-6-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-1-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-1-01.png new file mode 100644 index 000000000..95dea7831 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-1-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-1-02.png new file mode 100644 index 000000000..185a760dd Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-1-03.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-1-03.png new file mode 100644 index 000000000..5855428bd Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-2-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-2-01.png new file mode 100644 index 000000000..e35b79f0c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-2-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-2-02.png new file mode 100644 index 000000000..ae309ae21 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-2-03.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-2-03.png new file mode 100644 index 000000000..ca786a16b Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-2-04.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-2-04.png new file mode 100644 index 000000000..b9dc4d14f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-2-04.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-01.png new file mode 100644 index 000000000..1f92af8b7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-02.png new file mode 100644 index 000000000..69405813e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-03.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-03.png new file mode 100644 index 000000000..d1711112c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-04.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-04.png new file mode 100644 index 000000000..6d07d979d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-05.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-05.png new file mode 100644 index 000000000..efcd335e0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-3-05.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-4-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-4-01.png new file mode 100644 index 000000000..37ad10331 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-4-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-4-02.png new file mode 100644 index 000000000..29077bbb7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-5-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-5-01.png new file mode 100644 index 000000000..ebfd8a9f0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-5-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-5-02.png new file mode 100644 index 000000000..dde0ba2e9 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-5-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-6-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-6-01.png new file mode 100644 index 000000000..0cd9547e1 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-6-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-7-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-7-01.png new file mode 100644 index 000000000..b43222f48 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-7-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-8-01.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-8-01.png new file mode 100644 index 000000000..9a5bb8487 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-8-01.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-8-02.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-8-02.png new file mode 100644 index 000000000..2b7836b9f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-8-02.png differ diff --git a/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-8-03.png b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-8-03.png new file mode 100644 index 000000000..0a8af6ee7 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/s-pay-mall/s-pay-mall-mvc-3-8-03.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-01.png b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-01.png new file mode 100644 index 000000000..cd54100da Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-01.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-02.png b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-02.png new file mode 100644 index 000000000..65ed7f697 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-02.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-03.png b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-03.png new file mode 100644 index 000000000..caa337eb0 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-03.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-04.png b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-04.png new file mode 100644 index 000000000..e0e545804 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-04.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-05.png b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-05.png new file mode 100644 index 000000000..a0a8c20da Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-05.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-06.png b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-06.png new file mode 100644 index 000000000..f7bc15d80 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-06.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-07.png b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-07.png new file mode 100644 index 000000000..812777e8f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-fish-pond/xfg-fish-pond-introduction-07.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-01.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-01.png new file mode 100644 index 000000000..ff82e2c7d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-01.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-02.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-02.png new file mode 100644 index 000000000..861c6932d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-02.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-03.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-03.png new file mode 100644 index 000000000..c6a96cabf Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-03.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-04.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-04.png new file mode 100644 index 000000000..9e099d13e Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-04.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-05.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-05.png new file mode 100644 index 000000000..a87fe8ffd Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-0-05.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-1-01.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-1-01.png new file mode 100644 index 000000000..a79d39385 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-1-01.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-1-02.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-1-02.png new file mode 100644 index 000000000..475e72003 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-1-02.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-1-03.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-1-03.png new file mode 100644 index 000000000..e23b64cef Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-1-03.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-1-04.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-1-04.png new file mode 100644 index 000000000..01586774c Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-1-04.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-01.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-01.png new file mode 100644 index 000000000..8c47ef8a8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-01.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-02.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-02.png new file mode 100644 index 000000000..12b118ca8 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-02.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-03.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-03.png new file mode 100644 index 000000000..659693111 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-03.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-04.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-04.png new file mode 100644 index 000000000..d77d9dc90 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-04.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-05.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-05.png new file mode 100644 index 000000000..2573c9257 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-05.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-06.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-06.png new file mode 100644 index 000000000..481e66400 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-06.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-01.gif b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-01.gif new file mode 100644 index 000000000..2c1084909 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-01.gif differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-02.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-02.png new file mode 100644 index 000000000..3e9646293 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-03.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-03.png new file mode 100644 index 000000000..065b3dd7d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-04.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-04.png new file mode 100644 index 000000000..a14abee1d Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-05.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-05.png new file mode 100644 index 000000000..e6393e403 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-05.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-06.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-06.png new file mode 100644 index 000000000..08a6e4a0f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-06.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-07.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-07.png new file mode 100644 index 000000000..68f68ff98 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-07.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-08.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-08.png new file mode 100644 index 000000000..9bf95ee07 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-08.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-09.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-09.png new file mode 100644 index 000000000..e90c26c61 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-2-3-09.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-3-01.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-3-01.png new file mode 100644 index 000000000..53ab2800f Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-3-01.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-3-02.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-3-02.png new file mode 100644 index 000000000..e4ab3e542 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-3-02.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-3-03.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-3-03.png new file mode 100644 index 000000000..1a0329830 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-3-03.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-3-04.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-3-04.png new file mode 100644 index 000000000..92009f6ad Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-3-04.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-4-01.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-4-01.png new file mode 100644 index 000000000..51f91db50 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-4-01.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-4-02.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-4-02.png new file mode 100644 index 000000000..c90fb16a5 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-4-02.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-4-03.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-4-03.png new file mode 100644 index 000000000..772543295 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-4-03.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-4-04.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-4-04.png new file mode 100644 index 000000000..394ee4c53 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-4-04.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-5-01.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-5-01.png new file mode 100644 index 000000000..d4e9c0d78 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-5-01.png differ diff --git a/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-5-02.png b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-5-02.png new file mode 100644 index 000000000..37a812fd3 Binary files /dev/null and b/docs/.vuepress/public/images/article/project/xfg-wrench/xfg-wrench-5-02.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/job-hire-jd-01.png b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-01.png new file mode 100644 index 000000000..0125211b1 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-01.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/job-hire-jd-02.png b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-02.png new file mode 100644 index 000000000..0132c37d8 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-02.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/job-hire-jd-03.png b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-03.png new file mode 100644 index 000000000..0243629e9 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-03.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/job-hire-jd-04.png b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-04.png new file mode 100644 index 000000000..a6d54a915 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-04.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/job-hire-jd-05.png b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-05.png new file mode 100644 index 000000000..abba9c0f0 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-05.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/job-hire-jd-06.png b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-06.png new file mode 100644 index 000000000..3fad0bac4 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-06.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/job-hire-jd-07.png b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-07.png new file mode 100644 index 000000000..e2196d615 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/job-hire-jd-07.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241007-01.gif b/docs/.vuepress/public/images/article/zsxq/zsxq-241007-01.gif new file mode 100644 index 000000000..a8e4892e1 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241007-01.gif differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241007-02-2.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241007-02-2.png new file mode 100644 index 000000000..241a48fd0 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241007-02-2.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241007-02-3.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241007-02-3.png new file mode 100644 index 000000000..788b6aad2 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241007-02-3.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241007-02.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241007-02.png new file mode 100644 index 000000000..c8b986380 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241007-02.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241007-03.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241007-03.png new file mode 100644 index 000000000..d908f86a2 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241007-03.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241007-04.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241007-04.png new file mode 100644 index 000000000..98e3b0cf3 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241007-04.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241024-01.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-01.png new file mode 100644 index 000000000..37bfbaae2 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-01.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241024-02.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-02.png new file mode 100644 index 000000000..d54ed7826 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-02.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241024-03.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-03.png new file mode 100644 index 000000000..c0da6857c Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-03.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241024-04.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-04.png new file mode 100644 index 000000000..f69503a34 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-04.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241024-05.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-05.png new file mode 100644 index 000000000..d3531e166 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-05.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241024-06.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-06.png new file mode 100644 index 000000000..c04db94a3 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-06.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241024-07.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-07.png new file mode 100644 index 000000000..ff8ce887f Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-07.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241024-08.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-08.png new file mode 100644 index 000000000..7e91f252b Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241024-08.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241219-00.gif b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-00.gif new file mode 100644 index 000000000..25097b89a Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-00.gif differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241219-01.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-01.png new file mode 100755 index 000000000..9a61ca7b7 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-01.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241219-02.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-02.png new file mode 100755 index 000000000..46495d2b7 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-02.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241219-03.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-03.png new file mode 100755 index 000000000..3c82f25b4 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-03.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241219-04.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-04.png new file mode 100755 index 000000000..e2f9c4274 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-04.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241219-05.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-05.png new file mode 100755 index 000000000..4cc86127c Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-05.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241219-06.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-06.png new file mode 100755 index 000000000..db9447140 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-06.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241219-07.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-07.png new file mode 100755 index 000000000..b79911d09 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-07.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241219-08.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-08.png new file mode 100755 index 000000000..4af98f8d0 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-08.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241219-09.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-09.png new file mode 100755 index 000000000..a8826a4fe Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-09.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-241219-10.png b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-10.png new file mode 100755 index 000000000..4d998a367 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-241219-10.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-250115-01.jpg b/docs/.vuepress/public/images/article/zsxq/zsxq-250115-01.jpg new file mode 100644 index 000000000..6d55952a8 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-250115-01.jpg differ diff --git a/docs/.vuepress/public/images/article/zsxq/zsxq-door.png b/docs/.vuepress/public/images/article/zsxq/zsxq-door.png new file mode 100644 index 000000000..976ee0aa2 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zsxq-door.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zxsq-240917-01.png b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-01.png new file mode 100644 index 000000000..cb0ffc73f Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-01.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zxsq-240917-02.png b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-02.png new file mode 100644 index 000000000..8629112b5 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-02.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zxsq-240917-03.png b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-03.png new file mode 100644 index 000000000..75cca6a85 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-03.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zxsq-240917-04.png b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-04.png new file mode 100644 index 000000000..97d211b41 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-04.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zxsq-240917-05.png b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-05.png new file mode 100644 index 000000000..d46137941 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-05.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zxsq-240917-06.png b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-06.png new file mode 100644 index 000000000..28330ff55 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-06.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zxsq-240917-07.png b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-07.png new file mode 100644 index 000000000..dc36cbbd6 Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-07.png differ diff --git a/docs/.vuepress/public/images/article/zsxq/zxsq-240917-08.png b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-08.png new file mode 100644 index 000000000..2d1898f8b Binary files /dev/null and b/docs/.vuepress/public/images/article/zsxq/zxsq-240917-08.png differ diff --git a/docs/.vuepress/public/images/personal/wx.png b/docs/.vuepress/public/images/personal/wx.png new file mode 100644 index 000000000..3cbc440c7 Binary files /dev/null and b/docs/.vuepress/public/images/personal/wx.png differ diff --git a/docs/.vuepress/public/images/personal/wx_kefu.png b/docs/.vuepress/public/images/personal/wx_kefu.png new file mode 100644 index 000000000..81b3e7838 Binary files /dev/null and b/docs/.vuepress/public/images/personal/wx_kefu.png differ diff --git a/docs/.vuepress/public/images/personal/wx_little.png b/docs/.vuepress/public/images/personal/wx_little.png new file mode 100644 index 000000000..b98b265c6 Binary files /dev/null and b/docs/.vuepress/public/images/personal/wx_little.png differ diff --git a/docs/.vuepress/public/images/personal/wx_qiye.png b/docs/.vuepress/public/images/personal/wx_qiye.png new file mode 100644 index 000000000..4463c47fd Binary files /dev/null and b/docs/.vuepress/public/images/personal/wx_qiye.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/Xnip2025-12-28_10-47-09.png b/docs/.vuepress/public/images/roadmap/tutorial/Xnip2025-12-28_10-47-09.png new file mode 100644 index 000000000..0d7f9601a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/Xnip2025-12-28_10-47-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/draw.io-01.png b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-01.png new file mode 100644 index 000000000..c1fe9f54d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/draw.io-02.png b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-02.png new file mode 100644 index 000000000..bc28c2f0c Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/draw.io-03.png b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-03.png new file mode 100644 index 000000000..35929acdb Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/draw.io-04.png b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-04.png new file mode 100644 index 000000000..7549c9265 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/draw.io-05.png b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-05.png new file mode 100644 index 000000000..7f591702a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/draw.io-06.png b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-06.png new file mode 100644 index 000000000..60d69da8b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/draw.io-07.png b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-07.png new file mode 100644 index 000000000..808ca7cf5 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/draw.io-08.png b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-08.png new file mode 100644 index 000000000..fd5659f43 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/draw.io-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/img.png b/docs/.vuepress/public/images/roadmap/tutorial/img.png new file mode 100644 index 000000000..7a61a114e Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/img.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/img_1.png b/docs/.vuepress/public/images/roadmap/tutorial/img_1.png new file mode 100644 index 000000000..7a61a114e Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/img_1.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-01.gif b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-01.gif new file mode 100644 index 000000000..6fb467757 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-01.gif differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-02.png b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-02.png new file mode 100644 index 000000000..db8e2c9c9 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-03.png b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-03.png new file mode 100644 index 000000000..c0d12775c Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-04.png b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-04.png new file mode 100644 index 000000000..b61c212c2 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-05.png b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-05.png new file mode 100644 index 000000000..0a7cd50d1 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-06.png b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-06.png new file mode 100644 index 000000000..d2e3959fe Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-07.png b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-07.png new file mode 100644 index 000000000..7e6e5e30b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-08.png b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-08.png new file mode 100644 index 000000000..cb7086192 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-09.png b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-09.png new file mode 100644 index 000000000..182d06168 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-10.png b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-10.png new file mode 100644 index 000000000..7f4dc9773 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-11.png b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-11.png new file mode 100644 index 000000000..351c388ee Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-12.png b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-12.png new file mode 100644 index 000000000..86d1b31eb Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/intellij-idea-remote-jvm-debug-12.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-1panel-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-1panel-01.png new file mode 100644 index 000000000..9599da683 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-1panel-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-1panel-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-1panel-02.png new file mode 100644 index 000000000..5f4766da7 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-1panel-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-1panel-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-1panel-03.png new file mode 100644 index 000000000..33c2ed33a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-1panel-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-1panel-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-1panel-04.png new file mode 100644 index 000000000..8cb3011a7 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-1panel-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-00.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-00.png new file mode 100644 index 000000000..eeba5f5c0 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-00.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-01.png new file mode 100644 index 000000000..358d5d57b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-02.png new file mode 100644 index 000000000..ebdcc9414 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-03.png new file mode 100644 index 000000000..7308b1874 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-04.png new file mode 100644 index 000000000..5d1a4d512 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-05.png new file mode 100644 index 000000000..595c95a2c Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-agent-skill-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-01.png new file mode 100644 index 000000000..c5cdf08d0 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-02.png new file mode 100644 index 000000000..dcb66342f Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-03.png new file mode 100644 index 000000000..4a8bb4ecc Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-04.png new file mode 100644 index 000000000..af04c6ba6 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-05.png new file mode 100644 index 000000000..cd18dbbef Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-06.png new file mode 100644 index 000000000..74c34090d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-07.png new file mode 100644 index 000000000..4380115e5 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-08.png new file mode 100644 index 000000000..441ed5c9f Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-09.png new file mode 100644 index 000000000..639c92891 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-10.png new file mode 100644 index 000000000..1365aaecb Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-11.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-11.png new file mode 100644 index 000000000..f06c83ab9 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-12.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-12.png new file mode 100644 index 000000000..8b2f45e59 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-12.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-13.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-13.png new file mode 100644 index 000000000..e8f3c928e Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-13.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-14.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-14.png new file mode 100644 index 000000000..c56806efd Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-14.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-15.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-15.png new file mode 100644 index 000000000..716c7b46d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-15.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-16.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-16.png new file mode 100644 index 000000000..e7f2458d4 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ai-agent-openclaw-attempt-16.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-01.png new file mode 100644 index 000000000..27f96155c Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-02.png new file mode 100644 index 000000000..07df0e716 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-03.png new file mode 100644 index 000000000..7a9c9003e Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-04.png new file mode 100644 index 000000000..bdc8786e3 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-05.png new file mode 100644 index 000000000..d8fa0ca30 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-06.png new file mode 100644 index 000000000..a84d5d132 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-07.png new file mode 100644 index 000000000..4a2a8f86a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-08.png new file mode 100644 index 000000000..b1e4efee0 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-09.png new file mode 100644 index 000000000..32bbfcbf0 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-10.png new file mode 100644 index 000000000..5d15173fa Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aigc-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-01.png new file mode 100644 index 000000000..6e7326585 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-02.png new file mode 100644 index 000000000..237e830cc Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-03.png new file mode 100644 index 000000000..70c5bed00 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-04.png new file mode 100644 index 000000000..eb4182e3c Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-05.png new file mode 100644 index 000000000..923da7f1b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-06.png new file mode 100644 index 000000000..7cf270c6a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-07.png new file mode 100644 index 000000000..8e2641563 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-08.png new file mode 100644 index 000000000..82b5bbbf6 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-09.png new file mode 100644 index 000000000..7817fb940 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-10.png new file mode 100644 index 000000000..ac4ce9927 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-11.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-11.png new file mode 100644 index 000000000..9cbb196ba Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-12.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-12.png new file mode 100644 index 000000000..5b1233cf4 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-12.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-13.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-13.png new file mode 100644 index 000000000..5e19871a6 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-13.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-14.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-14.png new file mode 100644 index 000000000..95fa20d12 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-14.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-15.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-15.png new file mode 100644 index 000000000..60c232cc5 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-15.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-16.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-16.png new file mode 100644 index 000000000..22103ace4 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-16.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-17.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-17.png new file mode 100644 index 000000000..3d83021a7 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-aliyun-workbench-17.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-architectural-design-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-architectural-design-01.png new file mode 100644 index 000000000..dda9ed57d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-architectural-design-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-architectural-design-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-architectural-design-02.png new file mode 100644 index 000000000..c2a752994 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-architectural-design-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-architectural-design-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-architectural-design-03.png new file mode 100644 index 000000000..1a84a9fe1 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-architectural-design-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-architectural-design-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-architectural-design-04.png new file mode 100644 index 000000000..ef5362bf8 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-architectural-design-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-01.png new file mode 100644 index 000000000..09d250359 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-02.png new file mode 100644 index 000000000..d1f9bd5e5 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-03.png new file mode 100644 index 000000000..4399dcc1e Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-04.png new file mode 100644 index 000000000..0e623d940 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-05.png new file mode 100644 index 000000000..aac28d6fe Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-06.png new file mode 100644 index 000000000..034162af7 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-07.png new file mode 100644 index 000000000..292ac72a0 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-08.png new file mode 100644 index 000000000..bb7bc2736 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-09.png new file mode 100644 index 000000000..c2f44aadc Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-10.png new file mode 100644 index 000000000..14e236795 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-11.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-11.png new file mode 100644 index 000000000..019e09a39 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-12.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-12.png new file mode 100644 index 000000000..bf9b6a9ab Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-12.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-13.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-13.png new file mode 100644 index 000000000..a9fcc22f9 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-arthas-13.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-01.png new file mode 100644 index 000000000..0f0b9caea Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-02.png new file mode 100644 index 000000000..d2c71adf7 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-03.png new file mode 100644 index 000000000..cb0a47398 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-04.png new file mode 100644 index 000000000..f9cb57b55 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-05.png new file mode 100644 index 000000000..edb51b167 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cainiao-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-01.png new file mode 100644 index 000000000..74bf528e4 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-02.png new file mode 100644 index 000000000..73fcc58da Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-03.png new file mode 100644 index 000000000..59c755e50 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-04.png new file mode 100644 index 000000000..84669cbfd Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-05.png new file mode 100644 index 000000000..26244a451 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-cloud-server-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-disruptor-01.gif b/docs/.vuepress/public/images/roadmap/tutorial/road-map-disruptor-01.gif new file mode 100644 index 000000000..f32099b9d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-disruptor-01.gif differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-disruptor-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-disruptor-02.png new file mode 100644 index 000000000..a9bb17e00 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-disruptor-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-disruptor-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-disruptor-03.png new file mode 100644 index 000000000..37014481d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-disruptor-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-disruptor-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-disruptor-04.png new file mode 100644 index 000000000..10094eb59 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-disruptor-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-00.gif b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-00.gif new file mode 100644 index 000000000..479d9ed45 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-00.gif differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-01.png new file mode 100644 index 000000000..2bf30fa79 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-02.png new file mode 100644 index 000000000..d71057a83 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-03.png new file mode 100644 index 000000000..2798f5d87 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-04.png new file mode 100644 index 000000000..a4eda6f05 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-01.png new file mode 100644 index 000000000..038c8988f Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-02.png new file mode 100644 index 000000000..e510ecdbf Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-03.png new file mode 100644 index 000000000..ff765afa8 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-04.png new file mode 100644 index 000000000..0acb0ef50 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-05.png new file mode 100644 index 000000000..d44657c78 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-06.png new file mode 100644 index 000000000..209f3a719 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-07.png new file mode 100644 index 000000000..a88952496 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-08.png new file mode 100644 index 000000000..7f98bae43 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-09.png new file mode 100644 index 000000000..37e222db1 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-10.png new file mode 100644 index 000000000..60c0065b0 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-11.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-11.png new file mode 100644 index 000000000..e25857da2 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-deploy-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-01.png new file mode 100644 index 000000000..a8e83b083 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-02.png new file mode 100644 index 000000000..b5b613549 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-03.png new file mode 100644 index 000000000..c57449790 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-04.png new file mode 100644 index 000000000..d8490710e Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-05.png new file mode 100644 index 000000000..a100f3058 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-06.png new file mode 100644 index 000000000..30ce95c19 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-07.png new file mode 100644 index 000000000..bc6b5cdf2 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-docker-install-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-01.png new file mode 100644 index 000000000..0d65d5a12 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-02.png new file mode 100644 index 000000000..9ae618d63 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-03.png new file mode 100644 index 000000000..c8b24fd62 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-04.png new file mode 100644 index 000000000..000f727a6 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-05.png new file mode 100644 index 000000000..7e31fcb8b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-06.png new file mode 100644 index 000000000..2240875cf Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-07.png new file mode 100644 index 000000000..7013cf6f3 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-08.png new file mode 100644 index 000000000..54b941d0d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-09.png new file mode 100644 index 000000000..0b1f14fc0 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-10.png new file mode 100644 index 000000000..f6d4ac592 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-11.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-11.png new file mode 100644 index 000000000..3a53c27aa Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-12.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-12.png new file mode 100644 index 000000000..8d0e046b0 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-12.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-13.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-13.png new file mode 100644 index 000000000..e0965ab32 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-frp-13.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-20.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-20.png new file mode 100644 index 000000000..844f9500a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-20.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-21.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-21.png new file mode 100644 index 000000000..66a75a92c Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-21.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-22.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-22.png new file mode 100644 index 000000000..b3d46066d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-22.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-23.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-23.png new file mode 100644 index 000000000..7aa6effb6 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-23.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-24.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-24.png new file mode 100644 index 000000000..d750688c7 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-git-24.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-01.png new file mode 100644 index 000000000..64f4f58dc Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-02.png new file mode 100644 index 000000000..9fbc61029 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-03.png new file mode 100644 index 000000000..cc77e4c58 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-04.png new file mode 100644 index 000000000..4728d1328 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-05.png new file mode 100644 index 000000000..47677b348 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-06.png new file mode 100644 index 000000000..f8fdf32da Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-07.png new file mode 100644 index 000000000..de436b72d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-08.png new file mode 100644 index 000000000..244bc6e6a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-github-modes-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-01.png new file mode 100644 index 000000000..42a560e19 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-02.png new file mode 100644 index 000000000..a60cec435 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-03.png new file mode 100644 index 000000000..875664022 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-04.png new file mode 100644 index 000000000..883001553 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-05.png new file mode 100644 index 000000000..10f7f87a4 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-06.png new file mode 100644 index 000000000..e9173e8f1 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-google-adk-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-01.gif b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-01.gif new file mode 100644 index 000000000..2a6a043e2 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-01.gif differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-02.png new file mode 100644 index 000000000..6deb76af8 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-03.png new file mode 100644 index 000000000..ba7d15785 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-04.png new file mode 100644 index 000000000..69c2239e0 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-05.png new file mode 100644 index 000000000..3ea8daf99 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-06.png new file mode 100644 index 000000000..5b96ce19d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-07.png new file mode 100644 index 000000000..ac7a36964 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-08.png new file mode 100644 index 000000000..59c9a68b7 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-09.png new file mode 100644 index 000000000..ea7dd3f5a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-10.png new file mode 100644 index 000000000..08c11c68d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-11.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-11.png new file mode 100644 index 000000000..e3ecff4aa Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-12.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-12.png new file mode 100644 index 000000000..cd6acf932 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-12.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-13.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-13.png new file mode 100644 index 000000000..ff5a3929e Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-13.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-14.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-14.png new file mode 100644 index 000000000..7842833b1 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-14.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-15.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-15.png new file mode 100644 index 000000000..a6884c4f9 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-15.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-16.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-16.png new file mode 100644 index 000000000..503faff79 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-higress-ai-16.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-01.png new file mode 100644 index 000000000..e015c2463 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-02.png new file mode 100644 index 000000000..9316bca60 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-03.png new file mode 100644 index 000000000..5a16d2869 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-04.png new file mode 100644 index 000000000..d8f9da698 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-05.png new file mode 100644 index 000000000..5a6349c38 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-06.png new file mode 100644 index 000000000..04839277b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-07.png new file mode 100644 index 000000000..e0bf78df3 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-08.png new file mode 100644 index 000000000..665762591 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-09.png new file mode 100644 index 000000000..d4ac8f7a7 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-10.png new file mode 100644 index 000000000..abbbfb815 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-11.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-11.png new file mode 100644 index 000000000..22afb2875 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-12.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-12.png new file mode 100644 index 000000000..01c896624 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-12.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-13.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-13.png new file mode 100644 index 000000000..94ec310b3 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-joycode-13.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-01.gif b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-01.gif new file mode 100644 index 000000000..3e9103a8c Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-01.gif differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-02.gif b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-02.gif new file mode 100644 index 000000000..66af144d7 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-02.gif differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-03.png new file mode 100644 index 000000000..03d375099 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-04.png new file mode 100644 index 000000000..23bfc1ce9 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-05.png new file mode 100644 index 000000000..26c3022ae Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-06.png new file mode 100644 index 000000000..438997207 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-07.png new file mode 100644 index 000000000..8caf650f2 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-mac-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-01.gif b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-01.gif new file mode 100644 index 000000000..f298fac61 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-01.gif differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-02.png new file mode 100644 index 000000000..0d8a668c9 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-03.png new file mode 100644 index 000000000..c1696c1f3 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-04.png new file mode 100644 index 000000000..5f11e856b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-05.png new file mode 100644 index 000000000..ff6a911b8 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-06.png new file mode 100644 index 000000000..0f13431db Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-07.png new file mode 100644 index 000000000..64f767bcd Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-08.png new file mode 100644 index 000000000..dfeaa17ab Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-09.png new file mode 100644 index 000000000..4f3f4ff87 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-10.png new file mode 100644 index 000000000..df2b6bf9c Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-11.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-11.png new file mode 100644 index 000000000..2e00430a0 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-12.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-12.png new file mode 100644 index 000000000..34c17315a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-12.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-13.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-13.png new file mode 100644 index 000000000..d79927edc Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-13.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-14.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-14.png new file mode 100644 index 000000000..a20069560 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-14.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-15.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-15.png new file mode 100644 index 000000000..35961140e Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-15.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-16.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-16.png new file mode 100644 index 000000000..ec96d087a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-16.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-17.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-17.png new file mode 100644 index 000000000..a9cacc934 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-17.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-18.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-18.png new file mode 100644 index 000000000..4c1a6981a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-18.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-19.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-19.png new file mode 100644 index 000000000..f9fda0cd9 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-19.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-20.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-20.png new file mode 100644 index 000000000..d70d66466 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-20.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-21.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-21.png new file mode 100644 index 000000000..a3080cd17 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-21.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-22.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-22.png new file mode 100644 index 000000000..0fd15fbff Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-22.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-23.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-23.png new file mode 100644 index 000000000..9b420aa60 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-23.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-24.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-24.png new file mode 100644 index 000000000..905b2a162 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-maven-24.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-01.gif b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-01.gif new file mode 100644 index 000000000..090e37ae9 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-01.gif differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-02.png new file mode 100644 index 000000000..e61d6bf93 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-03.png new file mode 100644 index 000000000..9f55039a5 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-04.png new file mode 100644 index 000000000..252b49648 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-05.png new file mode 100644 index 000000000..30562382d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-06.png new file mode 100644 index 000000000..59b158b44 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-07.png new file mode 100644 index 000000000..a7860e169 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-08.png new file mode 100644 index 000000000..c72758bde Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-nas-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-01.png new file mode 100644 index 000000000..ee2a166d8 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-02.png new file mode 100644 index 000000000..4f3f5793b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-03.png new file mode 100644 index 000000000..6f0b027df Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-04.png new file mode 100644 index 000000000..98eca0ffc Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-05.png new file mode 100644 index 000000000..74b1d0a3b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-06.png new file mode 100644 index 000000000..ec63f5a06 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-07.png new file mode 100644 index 000000000..286a954d5 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-08.png new file mode 100644 index 000000000..ade777de9 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-09.png new file mode 100644 index 000000000..cc73f8f58 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-10.png new file mode 100644 index 000000000..f7f273bc2 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-11.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-11.png new file mode 100644 index 000000000..9c455920b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-12.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-12.png new file mode 100644 index 000000000..fe2361aa1 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-12.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-13.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-13.png new file mode 100644 index 000000000..2c84428e3 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-13.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-14.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-14.png new file mode 100644 index 000000000..561f04eb4 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-oauth2-14.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-00.gif b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-00.gif new file mode 100644 index 000000000..977e4808e Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-00.gif differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-01.png new file mode 100644 index 000000000..160e50843 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-02.png new file mode 100644 index 000000000..5cfbd0586 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-03.png new file mode 100644 index 000000000..9429bd188 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-04.png new file mode 100644 index 000000000..0f4c7a2ba Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-05.png new file mode 100644 index 000000000..05dc48486 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-06.png new file mode 100644 index 000000000..25cd2d233 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-07.png new file mode 100644 index 000000000..a22a08baf Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-08.png new file mode 100644 index 000000000..dc8a3b40a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-09.png new file mode 100644 index 000000000..bf7dcdc8a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-10.png new file mode 100644 index 000000000..3bae3e205 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-11.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-11.png new file mode 100644 index 000000000..e221c1451 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-ollama-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-01.gif b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-01.gif new file mode 100644 index 000000000..cb6e9d748 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-01.gif differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-02.png new file mode 100644 index 000000000..c230746e2 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-03.png new file mode 100644 index 000000000..753f57d77 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-04.png new file mode 100644 index 000000000..f9132d68f Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-05.png new file mode 100644 index 000000000..ce0b3ff9a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-06.png new file mode 100644 index 000000000..cdac29f60 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-07.png new file mode 100644 index 000000000..d28c83d25 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-08.png new file mode 100644 index 000000000..176565d16 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-09.png new file mode 100644 index 000000000..a7bc9ed75 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-10.png new file mode 100644 index 000000000..5511b6f66 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-11.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-11.png new file mode 100644 index 000000000..21d19b4ed Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-12.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-12.png new file mode 100644 index 000000000..460d47939 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-12.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-13.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-13.png new file mode 100644 index 000000000..7ea01653d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-13.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-14.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-14.png new file mode 100644 index 000000000..15d0ebd92 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-14.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-15.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-15.png new file mode 100644 index 000000000..093f7a423 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-15.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-16.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-16.png new file mode 100644 index 000000000..e920d454c Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-16.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-17.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-17.png new file mode 100644 index 000000000..a5575f7c2 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-17.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-18.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-18.png new file mode 100644 index 000000000..d3fa7b60f Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-18.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-19.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-19.png new file mode 100644 index 000000000..3d31eed31 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-19.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-20.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-20.png new file mode 100644 index 000000000..d9a689de9 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-20.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-21.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-21.png new file mode 100644 index 000000000..26ae2c19b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-21.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-22.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-22.png new file mode 100644 index 000000000..6b5767942 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-22.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-23.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-23.png new file mode 100644 index 000000000..f59dd95c3 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-openclaw-23.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-01.png new file mode 100644 index 000000000..86b0aafe2 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-02.png new file mode 100644 index 000000000..4f482e9cb Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-03.png new file mode 100644 index 000000000..59a180a90 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-04.png new file mode 100644 index 000000000..d663606e5 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-05.png new file mode 100644 index 000000000..7320d4523 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-06.png new file mode 100644 index 000000000..baf2383b1 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-07.png new file mode 100644 index 000000000..f1dae07a1 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-08.png new file mode 100644 index 000000000..820a83918 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-09.png new file mode 100644 index 000000000..a987a1f74 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-10.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-10.png new file mode 100644 index 000000000..3ba133a7a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-11.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-11.png new file mode 100644 index 000000000..b9479e9ee Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-12.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-12.png new file mode 100644 index 000000000..92c8c5545 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-12.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-13.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-13.png new file mode 100644 index 000000000..9768c5577 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-opencode-13.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-01.png new file mode 100644 index 000000000..2de1fd999 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-02.png new file mode 100644 index 000000000..520eb9e61 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-03.png new file mode 100644 index 000000000..7ff3a8916 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-04.png new file mode 100644 index 000000000..5528a95ed Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-05.png new file mode 100644 index 000000000..956129d86 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-06.png new file mode 100644 index 000000000..61ffbc3a5 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-07.png new file mode 100644 index 000000000..e950192bc Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-08.png new file mode 100644 index 000000000..acdf41db1 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-spring-security-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-01.png new file mode 100644 index 000000000..a4b30212d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-02.png new file mode 100644 index 000000000..e3262a557 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-03.png new file mode 100644 index 000000000..f8f49e431 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-04.png new file mode 100644 index 000000000..4169e2f6e Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-05.png new file mode 100644 index 000000000..19896632a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-06.png new file mode 100644 index 000000000..cd3896bcb Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-07.png new file mode 100644 index 000000000..92ce813df Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-08.png new file mode 100644 index 000000000..7b8f223e6 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-09.png new file mode 100644 index 000000000..e7538a845 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-trae-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-01.png new file mode 100755 index 000000000..72c1cfbd4 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-02.png new file mode 100755 index 000000000..bb91a8daa Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-03.png new file mode 100755 index 000000000..1ba0a88cf Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-04.png new file mode 100755 index 000000000..51cf26346 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-05.png new file mode 100755 index 000000000..045d409aa Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-06.png new file mode 100755 index 000000000..fb3420ba7 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-07.png new file mode 100755 index 000000000..0cf748479 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-08.png new file mode 100755 index 000000000..215c6dcc0 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-09.png new file mode 100755 index 000000000..d35dc34c8 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-traffic-agent-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-01.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-01.png new file mode 100644 index 000000000..634305c99 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-02.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-02.png new file mode 100644 index 000000000..157d188fd Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-03.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-03.png new file mode 100644 index 000000000..147e45d55 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-04.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-04.png new file mode 100644 index 000000000..dc0451d61 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-05.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-05.png new file mode 100644 index 000000000..b08a3fffc Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-06.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-06.png new file mode 100644 index 000000000..5edf80a6a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-07.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-07.png new file mode 100644 index 000000000..a7c05b2e5 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-08.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-08.png new file mode 100644 index 000000000..f6071c31c Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-09.png b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-09.png new file mode 100644 index 000000000..851b3d50b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/road-map-w13scan-jdumpspider-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-01.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-01.png new file mode 100644 index 000000000..20216091e Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-02.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-02.png new file mode 100644 index 000000000..9f6363a3a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-03.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-03.png new file mode 100644 index 000000000..d6be0e7d6 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-04.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-04.png new file mode 100644 index 000000000..4e57f8326 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-05.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-05.png new file mode 100644 index 000000000..c86afd28a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-06.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-06.png new file mode 100644 index 000000000..d0e283460 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-07.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-07.png new file mode 100644 index 000000000..5b4680044 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-08.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-08.png new file mode 100644 index 000000000..9989d96d5 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-09.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-09.png new file mode 100644 index 000000000..3da7112dd Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-10.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-10.png new file mode 100644 index 000000000..1945470ac Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-10.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-11.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-11.png new file mode 100644 index 000000000..2c1533893 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-11.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-12.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-12.png new file mode 100644 index 000000000..7743f2ad8 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-12.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-13.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-13.png new file mode 100644 index 000000000..a08135be8 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-13.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-14.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-14.png new file mode 100644 index 000000000..45ce04f39 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-14.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-15.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-15.png new file mode 100644 index 000000000..00f3eb8a1 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-15.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-16.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-16.png new file mode 100644 index 000000000..6cc0dde80 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-16.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-17.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-17.png new file mode 100644 index 000000000..2d04fad25 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-17.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-18.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-18.png new file mode 100644 index 000000000..27dfbb314 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-phone-agent-18.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-redis-06.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-redis-06.png new file mode 100644 index 000000000..67b2b92a1 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-redis-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-redis-07.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-redis-07.png new file mode 100644 index 000000000..52659e0ac Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-redis-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-01.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-01.png new file mode 100644 index 000000000..3efeecfd9 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-02.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-02.png new file mode 100644 index 000000000..759e5c16c Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-03.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-03.png new file mode 100644 index 000000000..6a5485442 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-04.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-04.png new file mode 100644 index 000000000..efc2a3236 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-05.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-05.png new file mode 100644 index 000000000..9f317ef3f Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-06.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-06.png new file mode 100644 index 000000000..6225d3f71 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-07.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-07.png new file mode 100644 index 000000000..c66fab4fd Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-08.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-08.png new file mode 100644 index 000000000..0bd6b19ce Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-09.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-09.png new file mode 100644 index 000000000..bd3ff1b9f Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-bus-09.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-01.gif b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-01.gif new file mode 100644 index 000000000..27c31ab25 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-01.gif differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-02.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-02.png new file mode 100644 index 000000000..37cd5097f Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-03.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-03.png new file mode 100644 index 000000000..f2d432b98 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-04.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-04.png new file mode 100644 index 000000000..ee242a673 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-05.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-05.png new file mode 100644 index 000000000..ce031bdfd Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-06.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-06.png new file mode 100644 index 000000000..8610f2352 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-07.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-07.png new file mode 100644 index 000000000..3f6a559d6 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-feign-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-stream-01.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-stream-01.png new file mode 100644 index 000000000..481913e1b Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-stream-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-stream-02.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-stream-02.png new file mode 100644 index 000000000..5b804eea9 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-stream-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-stream-03.png b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-stream-03.png new file mode 100644 index 000000000..be5655d9c Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/roadmap-springcloud-stream-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-01.gif b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-01.gif new file mode 100644 index 000000000..69b2da8d2 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-01.gif differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-02.png b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-02.png new file mode 100644 index 000000000..fb10eef7d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-03.png b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-03.png new file mode 100644 index 000000000..b963cdaa7 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-04.png b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-04.png new file mode 100644 index 000000000..e8aebb8c4 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-05.png b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-05.png new file mode 100644 index 000000000..f5be72464 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-06.png b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-06.png new file mode 100644 index 000000000..cca1aae7f Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-07.png b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-07.png new file mode 100644 index 000000000..becd3d3e5 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/spring-oauth2-sso-01-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-01.png b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-01.png new file mode 100644 index 000000000..88d1619bd Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-01.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-02.png b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-02.png new file mode 100644 index 000000000..a68e9e76f Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-02.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-03.png b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-03.png new file mode 100644 index 000000000..c625f1a3a Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-03.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-04.png b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-04.png new file mode 100644 index 000000000..1ccd842ba Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-04.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-05.png b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-05.png new file mode 100644 index 000000000..c633cd888 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-05.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-06.png b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-06.png new file mode 100644 index 000000000..018312ee8 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-06.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-07.png b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-07.png new file mode 100644 index 000000000..8e8d0b204 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-07.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-08.png b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-08.png new file mode 100644 index 000000000..0fd1bdb8d Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-08.png differ diff --git a/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-09.png b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-09.png new file mode 100644 index 000000000..72737e3d5 Binary files /dev/null and b/docs/.vuepress/public/images/roadmap/tutorial/xfg-dev-tech-visualvm-09.png differ diff --git a/docs/.vuepress/public/images/system/code.png b/docs/.vuepress/public/images/system/code.png new file mode 100644 index 000000000..784062316 Binary files /dev/null and b/docs/.vuepress/public/images/system/code.png differ diff --git a/docs/.vuepress/public/images/system/zsxq/zsxq-user-guide.png b/docs/.vuepress/public/images/system/zsxq/zsxq-user-guide.png new file mode 100644 index 000000000..5a529e191 Binary files /dev/null and b/docs/.vuepress/public/images/system/zsxq/zsxq-user-guide.png differ diff --git a/docs/.vuepress/styles/index.styl b/docs/.vuepress/styles/index.styl index 3e91100ce..1ef828975 100755 --- a/docs/.vuepress/styles/index.styl +++ b/docs/.vuepress/styles/index.styl @@ -30,4 +30,12 @@ h2 // sidebar .sidebar width: 18rem - font-size: 15px \ No newline at end of file + font-size: 15px + +.page-bottom-footer { + text-align: center; + padding: 15px; + font-size: .8rem; + font-weight: 400; + color: var(--c-text-lightest) +} \ No newline at end of file diff --git a/docs/.vuepress/theme/components/Page.vue b/docs/.vuepress/theme/components/Page.vue index b9a0e950b..ed7f4b914 100755 --- a/docs/.vuepress/theme/components/Page.vue +++ b/docs/.vuepress/theme/components/Page.vue @@ -59,6 +59,9 @@ + diff --git a/docs/.vuepress/theme/components/PageSidebar.vue b/docs/.vuepress/theme/components/PageSidebar.vue index c55a9833b..74aae8f48 100755 --- a/docs/.vuepress/theme/components/PageSidebar.vue +++ b/docs/.vuepress/theme/components/PageSidebar.vue @@ -13,6 +13,15 @@
+ + + + + + + + + @@ -58,14 +67,14 @@ 左栏 -
+
星球
- 实战项目「DDD+RPC分布式抽奖系统」、专属小册、问题解答、简历指导、架构图稿、视频课程 + 带你学习,实战项目。提高编程思维,锻炼编码能力!17个实战项目,增强面试竞争力! 知识星球:码农会锁
@@ -81,7 +90,7 @@
添加小傅哥微信(fustack)进虫洞栈学习交流圈「无任何套路」 - + PS:添加时请备注读者加群,谢谢!
@@ -103,6 +112,11 @@
+
+ + 做项目 +
+
八股文 diff --git a/docs/README.md b/docs/README.md index a65fe1198..a1e629d10 100755 --- a/docs/README.md +++ b/docs/README.md @@ -5,17 +5,23 @@ actionLinks: - link: /md/other/guide-to-reading.md text: 开始阅读 → class: primary -- link: https://t.zsxq.com/09hMHNMEh +#- link: https://wx.zsxq.com/group/48411118851818 +# text: 知识星球 +# class: secondary +- link: /md/zsxq/introduce.html text: 知识星球 class: secondary - link: /md/road-map/road-map.md - text: 路书 👣 + text: 编程路书 👣 class: secondary - link: https://gaga.plus - text: 项目 💐 + text: 项目(+菜鸟教程) 💐 class: secondary -- link: https://618.gaga.plus - text: 3.8元/月(云服务器) ☁️ +#- link: https://618.gaga.plus +# text: 9.9元/月(云服务器) ☁️ +# class: secondary +- link: https://walicode.xiaofuge.cn/ + text: WaLiCode 🤖 class: secondary features: - title: 沉淀 @@ -31,7 +37,7 @@ footer: 京ICP备19031103号< ### 我是小傅哥 -- :dog: 13年毕业,互联网大厂T8架构师,全网40万+粉编程知识博主。 +- :dog: 13年毕业,互联网大厂架构师,全网40万+粉编程知识博主。 - :man_technologist: 成长:[关于我,从小白到架构师的成长经历](https://www.bilibili.com/video/BV1FF41137q5) - :bus: 作品:[`CodeGuide | 程序员编码指南`](https://github.com/fuzhengwei/CodeGuide) | [`RoadMap 编程路书`](https://github.com/fuzhengwei/RoadMap) | [`Java 数据结构和算法`](https://github.com/fuzhengwei/java-algorithms) | [`IM 仿微信`](https://github.com/fuzhengwei/NaiveChat) | [`Java 面经手册`](https://github.com/fuzhengwei/interview) | [`IntelliJ IDEA 插件开发`](https://github.com/fuzhengwei/guide-idea-plugin) | [`Lottery 抽奖系统 - 基于领域驱动设计的四层架构实践`](https://github.com/fuzhengwei/Lottery) | [`API网关`](https://github.com/fuzhengwei/api-gateway) | [`手写MyBatis`](https://github.com/fuzhengwei/small-mybatis) | [`重学Java设计模式`](https://github.com/fuzhengwei/itstack-demo-design) | [`Netty 实战案例`](https://github.com/fuzhengwei/itstack-demo-netty) | [`字节码编程`](https://github.com/fuzhengwei/itstack-demo-bytecode) | [`ChatGPT AI 问答助手`](https://github.com/fuzhengwei/chatbot-api) | [`chatglm-sdk-java`](https://github.com/fuzhengwei/chatglm-sdk-java) | [`docker-image-pusher`](https://github.com/fuzhengwei/docker-image-pusher) | [`💱IDEA Plugin vo2dto —— 对象转换插件(15.8k+安装)`](https://bugstack.cn/md/product/idea-plugin/vo2dto.html) | [更多搜索...](https://github.com/fuzhengwei?tab=repositories) - :seedling: 干货:[公众号『 bugstack虫洞栈 』](https://bugstack.cn/images/personal/qrcode.png) @@ -42,16 +48,24 @@ footer: 京ICP备19031103号< ### 开发的项目 -- 业务项目 +- 创新项目「AI」(6) + - [AI MCP Gateway 网关服务系统](https://bugstack.cn/md/project/ai-mcp-gateway/ai-mcp-gateway.html) + - [AI Agent 脚手架 + 场景应用(draw.io、手机龙虾)](https://bugstack.cn/md/project/ai-agent-scaffold/ai-agent-scaffold.html) - 综合 Spring AI、LangChain4j + Google ADK(a2a、mcp、skills),打造全新智能体架构方案。 + - [AI Agent 拖拉拽 + 动态配置(RAG、MCP、Prompt)](https://bugstack.cn/md/project/ai-knowledge/ai-knowledge.html) + - [OpenAI 代码自动评审组件](https://bugstack.cn/md/zsxq/project/openai-code-review.html) + - [OpenAI 大模型微服务应用体系构建 - API-SDK、鉴权、公众号、微信支付](https://bugstack.cn/md/zsxq/project/chatgpt.html) + - [ChatGPT AI 问答助手 - 小型,对接知识星球](https://bugstack.cn/md/zsxq/project/chatbot-api.html) + +- 业务项目(5) + - [拼团交易平台系统](https://bugstack.cn/md/project/group-buy-market/group-buy-market.html) - [小型支付电商系统 - 一套项目2套架构开发(MVC+DDD)](https://bugstack.cn/md/project/s-pay-mall/s-pay-mall.html) - [大营销平台系统 - 前后端 + Dev-Ops 的全栈式综合编程实战DDD项目!](https://bugstack.cn/md/project/big-market/big-market.html) - - [OpenAi 大模型微服务应用体系构建 - API-SDK、鉴权、公众号、微信支付](https://bugstack.cn/md/zsxq/project/chatgpt.html) - [Lottery 分布式抽奖系统 - 基于领域驱动设计的四层架构实践](https://bugstack.cn/md/zsxq/project/lottery.html) - [Netty+JavaFx实战:仿桌面版微信聊天](https://bugstack.cn/md/zsxq/project/im.html) - - [ChatGPT AI 问答助手 - 小型,对接知识星球](https://bugstack.cn/md/zsxq/project/chatbot-api.html) -- 组件项目 - - [OpenAI 代码自动评审组件](https://bugstack.cn/md/zsxq/project/openai-code-review.html) +- 组件项目(8) + - [本地任务消息组件](https://bugstack.cn/md/project/local-task-message/local-task-message.html) + - [通用技术组件 - 🔧扳手工程](https://bugstack.cn/md/zsxq/project/xfg-wrench.html) - [透视业务流程 - 监控系统](https://bugstack.cn/md/zsxq/project/business-behavior-monitor.html) - [动态线程池组件](https://bugstack.cn/md/zsxq/project/dynamic-thread-pool.html) - [蓝兔支付SDK设计和开发](https://bugstack.cn/md/zsxq/project/ltzf-sdk-java.html) @@ -89,11 +103,11 @@ footer: 京ICP备19031103号< ### 联系我 - 可加技术交流群 -沉淀、分享、成长,让自己和他人都能有所收获!你也可以添加本站作者小傅哥的微信:`fustack` —— 加入作者技术交流群 +沉淀、分享、成长,让自己和他人都能有所收获!你也可以扫码添加本站作者小傅哥的微信(记得备注从博客来的)
- -
微信:fustack
+ +
提示:如果添加失败,可以先扫码图中的客服,也可以找到我

diff --git "a/docs/md/about/job/2024-09-08-\351\230\277\351\207\214P7\357\274\214\345\260\261\346\230\257\345\276\210\345\244\232\344\272\272\347\232\204\345\244\251\350\212\261\346\235\277\345\220\227\357\274\237.md" "b/docs/md/about/job/2024-09-08-\351\230\277\351\207\214P7\357\274\214\345\260\261\346\230\257\345\276\210\345\244\232\344\272\272\347\232\204\345\244\251\350\212\261\346\235\277\345\220\227\357\274\237.md" new file mode 100644 index 000000000..f175ebbc0 --- /dev/null +++ "b/docs/md/about/job/2024-09-08-\351\230\277\351\207\214P7\357\274\214\345\260\261\346\230\257\345\276\210\345\244\232\344\272\272\347\232\204\345\244\251\350\212\261\346\235\277\345\220\227\357\274\237.md" @@ -0,0 +1,87 @@ +--- +title: 阿里P7,就是很多人的天花板吗? +lock: no +--- + +# 阿里P7,就是很多人的天花板吗? + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +有人说:”阿里的P7就是很多人的天花板?“,其实他说的没错。这个级别对应研发就是高级架构师,或者M序列管理一个组长的岗位。前面冲到P7靠你的学历进入大厂和技术积累冲击岗位,但从这往后再想晋升靠命了! + +
+ +
+ +**天花板级别的收入咋样?🤔** + +`字节的 2-2 ~ 3-1`、`腾讯的10级 ~ 11级`、`阿里的 P7~P8`、`京东的 T7~T8`,他们的待遇和基本收入是差不多的。在这些级别中平级跳槽的一般不多,除非有是干的实在不爽了。一般是手里有干货的,从任何一家调另外一家,普通会级别+1,收入也会有所增加。来自 [duibiao.info](https://duibiao.info/) 的一份收入数据对比。 + +
+ +
+ +举例🌰,在一个大部门中,T9级别极少,年龄最大,T8少量、主力在 T6~T7,校招新入职在 T2~T3。不过往往C9级别高等院校的学生 + 技术积累很不错,拿到的校招 Offer 会倒挂社招T5级别的薪资范围。前两年一般需要积累,无晋升名额,从做出成绩后,1~2年可能会提名一次晋升。当然还有一些靠命的东西,会走的很快。比如公司组织的技术赛事获奖、A级项目入围等。**当然如果你连续发生事故,造成重大影响,也会让你走的很快。** + +> 接下来,小傅哥分享一些,修炼一身,即走的出去加薪,也留的下来晋升的本事! + +## 一、不要过早冒头!- 做人 + +`纵无显效亦藏拙,若有所成甘守株。` + +在武侠电影🎬《剑雨》中有这一段,陆竹在破庙中与细雨经过一番过招之后,指出细雨的剑法漏洞。并通过`藏拙于巧(藏巧于拙)`,`用晦而明`,`寓清于浊`,`以屈为伸`,破解辟水剑。 + +
+ +
+ +这里有一句,藏拙于巧,出自于 自贻 - 唐·罗隐 中的诗句`纵无显效亦藏拙,若有所成甘守株。`。意思在于古往成就大事者,都要善于藏锋守拙、低调隐忍。 + +在我最开始入职的时候,就不善于这个。往往都是横冲直撞,斗业务、怼产品、干测试!要不是得益于早年的互联网更纯粹,加上领导的偏爱。可能在某次过招后,我也就被送走了。直到现在我的电脑里还保留有和当时产品 battle 的截图 😂。当时的性格就是,你错了,你不对,我指出你不认,那我就再上一招!但往往每一招背后,我也都有漏洞,就像那剑法一样。所以一直我也没有走管理岗! + +所以无论是校招还是社招,进入一家公司后。都不要想着一进来就做的多大,也不要想着多快的晋升。所有看似风平浪静的组织,往往背后也都牵扯着一堆的`"利益权衡"`。先做好自己,完成好交付。 + +## 二、不要只做业务!- 做事 + +业务是程序员👨🏻‍💻进入公司后完成的第一个交付动作,以目前看所有的人都是为了业务的发展而存在的。如果业务不赚钱,第一个被送走的就是程序员。但这里就有一个很重要的事情,你还记得你是怎么进来的吗?要不是校招学历、要不是技术积累、要不是项目经验、要不是背了八股刷了算法。但终究不是说你手速多快,能敲多少 CRUD 进来的。 + +所以,在公司中不能只是完成业务交付即可,要在业务交付多积累成绩。因为同样一个项目不同的人设计实现,就会出现不一样的成绩。有些会把架构、模型、方案、扩展、都在一次次交付中积累出来,并在需求的时候将这一套标准沉淀并复用。这些东西落地可为其他组做标准,上升可为述职讲成绩。同时,你观察🔎还会发现,组内总有人会对同类的技术工作,凝练总结设计开发成通用的技术组件。在归属上这不是他的强职责范围,但在年终总结和后续晋升比拼上可是实打实的成绩。差距也是这样一点点拉开的。 + +我常听到有人说,DDD 复杂、设计模式浪费时间。不,你要知道,不是那东西复杂,也不是那东西浪费时间。是你,是你复杂,是你浪费时间!你不觉得当让你来做分享的时候,你甚至没有办法用技术的话术阐述自己的过程,也很难总结出过往的成绩。总感觉自己就是在拼装接口、组织逻辑、完成交付。 + +所以你只是扮演着劳苦,但不功高的角色。每每提到晋升加薪,就会反问到,你这个人有什么成绩! + +## 三、不要持续趟平!- 自己 + +`趟平就是工作懈怠吗?其实过渡的工作也是一种趟平。` + +不知道你是否意识到,公司和个人是两条发展线,是不能顾此失彼的。更好的个人能力是可以更好的把工作做出成绩。而往往有些人一脑门子的只是一个状态下同一个方式的完成工作,其实往往是没有多少成绩的。 + +一个程序员如果只是会写代码,其实是偏安一隅。业务怎么样、运营怎么做、产品怎么设计、一整套的开发工具实施运维是怎么运行的、各个组件都有哪些原理等等,这些东西都是都需要掌握的。在整体的学习过程中,综合的锻炼出自己成体系的知识结构,才是长久有价值的。 + +尤其是可以跟着一些有大厂经验的人学习他的方法论,学习他的业务经验、学习他的编码技巧,都是可以快速的提高自己的能力的。 + +## 四、小傅哥的经验!- 参照 + +小傅哥在职场发展、业务经验、场景方案、技术经验、实战项目等多方面都有来自于大厂锻炼出来的经验编写。可以让伙伴们学习,快速提高自己的。还为500多人修改过简历,不少伙伴也都被小傅哥的经验,抬进了非常不错的公司。各个大厂也都有小傅哥的伙伴。 + +在这方面我总结了很多的经验,你可以阅读; + +
+ +
+ +地址:[https://bugstack.cn/md/zsxq/material/study-experience.html](https://bugstack.cn/md/zsxq/material/study-experience.html) + +--- + +加入小傅哥的星球「码农会锁」阅读450+份简历和评审,学习6个业务项目;`MVC+DDD,双架构开发小型电商`、`大营销(超级大课)`、`OpenAI 大模型应用`、`Lottery`、`IM`、`AI 问答助手`。7个组件项目;`OpenAI 代码评审`、`BCP 透视业务监控`、`动态线程池`、`支付SDK设计和开发`、`API网关`、`SpringBoot Starter`、`IDEA Plugin 插件开发`。1套源码课程、1套基础教程、1到云服务器教程以及各类场景解决方案。 + +如果大家希望通过做有价值的编程项目,提高自己的编程思维和编码能力,可以加入小傅哥的【星球:码农会锁】。加入后解锁🔓所有往期项目,还可以学习后续新开发的项目。 + +> 🧧加入学习这样一套项目,放在一些平台售卖,一个至少都是上千块。但小傅哥的星球,只需要100多,就可以获得全部的学习项目!重要的是学习小傅哥的经验! diff --git "a/docs/md/about/job/2025-11-16-\347\216\260\345\234\250\350\275\254AI\345\272\224\347\224\250\345\274\200\345\217\221\357\274\214\346\230\257\344\270\215\346\230\257\344\270\252\346\234\272\344\274\232\357\274\237.md" "b/docs/md/about/job/2025-11-16-\347\216\260\345\234\250\350\275\254AI\345\272\224\347\224\250\345\274\200\345\217\221\357\274\214\346\230\257\344\270\215\346\230\257\344\270\252\346\234\272\344\274\232\357\274\237.md" new file mode 100644 index 000000000..24d0e7e42 --- /dev/null +++ "b/docs/md/about/job/2025-11-16-\347\216\260\345\234\250\350\275\254AI\345\272\224\347\224\250\345\274\200\345\217\221\357\274\214\346\230\257\344\270\215\346\230\257\344\270\252\346\234\272\344\274\232\357\274\237.md" @@ -0,0 +1,102 @@ +--- +title: 现在转AI应用开发,是不是个机会? +lock: no +--- + +# 现在转AI应用开发,是不是个机会? + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是小傅哥。 + +最近 AI 实在是太火了,不是以前那种火在互联网上,而是火到互联网公司里头。之前是铺在 AI 算法上,现在是扎进 AI 应用里。一天天我们都下班了,AI Agent 应用项目组的小伙伴还在加班!🤨 + +
+ +
+ +**其实这是个机会!** + +如果你的学历将将够得到中大厂,但总是被刷。或者之前在一些传统行业,但想进入互联网。那么,一定要在简历上添加 AI 应用类场景项目。 + +
+ +
+ +此类项目以 AI Agent 智能体和 OpenAI 应用为主,无需掌握底层算法或复杂调优能力。只要具备任一主流 AI 框架(如 Spring AI、Google ADK)使用经验,或有自主开发 AI SDK 及应用的实践,都能显著提升你的竞争力。 + +
+ +
+ +如果你最近在搜索招聘岗位,一定会发现各个公司都新增加了 AI 应用开发岗位,而且是非常多。因为公司里的各个部门,都需要基于 AI 做场景提效,因此所有的业务项目,都会被 AI 翻一遍。而且各个大厂的里的研发都比较倾向于参与到一些 AI 场景开发里,因为这必然后面做晋升述职可以讲的一个亮点。 + +**为啥以前没那么 AI 应用开发的岗位?** + +2024年11月25日,AI MCP 协议发布,这东西就是 AI 的手脚,有了他以后 AI 进入了 Agent 智能体时代。以前我们都是问它,之后按照回答的流程,操作我们自己的场景。但现在,我们不是问,而是让它直接做。AI Agent 智能体,可以基于询问,把内容拆分,执行,判断,输出。给出最终的结果。 + +所以,公司里目前大量的业务场景,都开始做相关业务类型的智能体服务,也因此有了非常多的 AI Agent 智能体岗位。当你在Boss直聘,检索这些岗位后,就会知道他们都在哪些场景落地了(AI Agent + 业务)。 + +## 一、学习路线 + +从22年年尾至今,小傅哥一直在做 AI 应用方面的实战编程项目,从最初的 AI 类的接口开发和使用,到 SDK 的封装,再到 OpenAI 应用结合微信支付、公众号、多模态、敏感词做线上服务。随后24年出了 MCP 协议,又紧跟着最新技术做 AI Agent 智能体。现在又开发 AI MCP Gateway 网关。可以说每一步都很超前,企业里需要的技术,小傅哥就带着你最先最快的补充起来。 + +
+ +
+如图所示,这是一套 AI 应用开发路线,按照你的诉求可以选择学习; + +- 时间充足;可以从 OpenAI 代码自动评审开始,之后到 AI Agent 智能体,再到 OpenAI 项目开发。后面可以跟随二阶段项目。 +- 时间紧张;可以先做 AI Agent 智能体,这个项目分为3部分,第三部分是智能体部分。学习后写完简历,后面在学其他部分。 +- 时间很紧;适合于找实习或者校招想加点AI的,那么可以做个 OpenAI 代码自动评审,项目不大,但也是一个两眼的技术点。随着写完简历面试,后续可以继续补充其他 AI 内容。 + +> AI MCP Gateway 正在更新,这也是互联网中必备的 AI 类项目,之后还会继续更细其他 AI 项目。 + +## 二、项目介绍 + +### 1. OpenAI 代码自动评审 + +本套组件是小傅哥基于 `GitHub Actions` + `OpenAI(ChatGLM)` + `Git/GitHub` + `公众号模板消息` 串联出从代码提交获取通知,Git 检出分支变化,在使用 OpenAI 进行代码和写入日志,再发送消息通知完成整个链路。 + +
+ +
+ +
+ +
+### 2. AI Agent 智能体 + +这是一套综合`前后端 + Dev-Ops`,基于 Spring Ai 框架实现,Ai Agent 智能体。耗时7个多月,38节课程(`视频`+`文档`),从 RAG 到 MCP,再实现出互联网企业级,可编排的 Ai Agent 智能体,现已全部开发完成 + 部署上线。💐 + +
+ +
+ +
+ +
+### 3. OpenAI 应用(含支付) + +此项目以应用OpenAI技术,对接多种大模型提供生成式服务,为XXX场景提效。项目的架构设计实现以微服务进行拆分,涵盖;OpenAI-SDK、OpenAI-API、公众号鉴权、微信支付等。并以模块化设计,积木式构建应用,让不同的场景诉求都可以配置化对接。 + +
+ +
+ +
+ +
+### 4. AI MCP GateWay + +该项目是 AI 应用场景下的通用技术服务组件类项目,以解决接口 MCP 协议转换而设计实现。在整个项目中,你可以积累到关于 MCP 协议的深度分析,学习分析协议的技巧和方案,并积累关于设计一个组件解决通用场景问题的能力。 + +
+ +
+ +> 很多能力就是这样,早早的储备起来,以备不时之需!程序员也是一个一直学习的行业!春江水暖鸭先知🦆,码农需要学知识! + diff --git "a/docs/md/about/job/2026-03-21-\345\217\244\346\263\225\347\274\226\347\250\213\357\274\214\346\230\257\345\220\246\350\277\230\351\207\215\350\246\201\357\274\237.md" "b/docs/md/about/job/2026-03-21-\345\217\244\346\263\225\347\274\226\347\250\213\357\274\214\346\230\257\345\220\246\350\277\230\351\207\215\350\246\201\357\274\237.md" new file mode 100644 index 000000000..b28f7f71f --- /dev/null +++ "b/docs/md/about/job/2026-03-21-\345\217\244\346\263\225\347\274\226\347\250\213\357\274\214\346\230\257\345\220\246\350\277\230\351\207\215\350\246\201\357\274\237.md" @@ -0,0 +1,131 @@ +# 纳闷?老板,为什么还不开除你! + +作者:小傅哥 +博客:[https://bugstack.cn](https://bugstack.cn/) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +AI 的迅猛迭代,好像让很多伙伴都开始焦虑,是否会被 AI 替代。今天小傅哥,站在一个老码农的视角,参与过众多复杂项目需求的场景下,帮你分析 AI 是否可以完全取代我们。 + +
+ +
+ +**古法编程!** + +2025年是 AI Agent 工具爆发的时代,AI IDE 也在这一年兴起。从这一年往前,称之为古法编程。AI 都来了,还用学代码吗,反正问 AI 就行了,他可以帮我写好。 + +但 AI 真的能帮你把所有的代码都写好吗?古法编程也真的不重要吗?好!咱们接下来就讨论下! + +## 老板,为什么还不开除你? + +🤔古法编程,是否还重要?如果不重要了,那老板现在应该立马把你开了才对。资本是逐利,不可能这会不拿起屠刀,进行开“猿”节流。 + +那,为什么,我们还在岗位上。用着 AI 和自己,一起写代码呢? + +或者说,软件开发岗位的企业招聘也不用限制学历和专业了,土木的、经管的、美院的、学医的,都可以过来写代码呀。那这到底为什么呢?不是说,现在学编程是49年入国军吗? + +啊!其实,原来有一部分人在扯淡。 + +他们刻意在描述上降低了软件交付的复杂度,并把 AI 编码等同于软件交付,等价于程序员👨🏻‍💻的工作就只是写代码。从而忽视了,一个复杂项目需求,在前期的调研、讨论、分析,产出 PRD 文档,在进行细节的讨论,确保流程的可靠行。最后才是研发设计和编码实现,以及测试验证、预发验证、流量回放等,这才是一整个需求交付的过程。编码,只是其中的一小部分而已。 + +
+ +
+ +**所以**,目前老板还不敢开除你!只会让你使用 AI 加快生产效率。 + +## 外行,为什么也没做出大项目? + +不少外行,特别兴奋于,一句话 AI 写个贪吃蛇,或者搞出个坦克大战。 + +那你就在这个实现的贪吃蛇上,在完成以下诉求; +1. 完整的登录体系,涵盖;手机号验证、公众号扫码、APP 应用可人脸、浏览器要有指纹,登录后同平台服务免登录。 +2. 可微信/支付宝多渠道,支付购买各类场景增强VIP道具,可给任务角色换装。涵盖完整商城体系,用户可在平台售卖个人游戏时获得的特殊道具。 +3. 给用户提供,积分、兑换、返利,以及在活动时间,有转盘抽奖、老虎机🎰、扭蛋等各类配合场景的玩法,增强用户心智和提高用户体验。并提供给运营自主配置使用。 +4. 支持联机对战、定期赛事、总/区排行榜、组队房间、语音对话(YY功能)、打字聊天(注意敏感词过滤)、视频录制(精彩时刻)。 +5. 支持种树、种菜乐园,为贪吃蛇提供家园归属,及其N天种菜,果实成熟后,可获得xxx商城对应sku商品兑换卡,0元支付可配送到家。 +6. 综上,确保数据库事务,以及最终一致性。并支持 MQ、RPC、xxl-job 等分布式架构设计。 + +
+ +
+ +以上内容,可不是胡编乱写,这就是现实中的互联网场景里的业务。也是你天天使用的`淘宝`、`京东`、`滴滴`、`美团`、`腾讯`里面的场景。如果你觉得 AI 可以替代程序员,那么你现在就可以对以上应用全面截图之后让 AI 帮你帮所有内容都写出来。 + +真相就是,AI 没办法,在你自己不清楚详细逻辑的情况,为你全量的完成所有内容的编写。甚至它可能为了实现 A 功能,而导致 B 功能连带不可用。 + +所以,外行们,**燃骚你的 Token 吧,让 API 中转站哇哇赚钱!** + +## 自己,跟着AI屁股后面评审代码 + +Duang、Duang、Duang,写出一堆。但你看不懂,你敢提交吗?出了事故是开除你,还是开除 AI? + +就代码来说,它是对产品功能详细逻辑的具体数字化体现,个人的对产品功能的理解和架构、编码、设计等经验的积累,决定了产出代码的正确性和可靠性。 + +注意,千万不要简单的理解为,你只是在一个新工程或者代码量很少的工程中完成需求。你现在可能要打开2、3个工程,每个工程在历史沉淀中,有几十万行代码。还要与其他部门的伙伴配合,完成接口的开发、对接和联调。 + +那么,这么复杂的业务理解和需求交付情况下,程序员为了更细致的理解细节,也常常会在通过编写伪代码来梳理逻辑,并与产品经理确认临界细节。这个过程是非常重要的。 + +如果,现在换成 AI 全部完成逻辑的开发,那么细节分析的时候,你要写的就是所有开发内容的提示词,这个工作成本并不低(甚至还会漏逻辑,因为不是你持续的写,就可能发现不了)。但对于有经验的高级开发来说,AI 编码的质量,并不一定多高,甚至比如上一些高级开发。所以,他们往往是在一些已经明确自己完全可以写,也可以把控 AI 写的代码时候,会让 AI 来完成这部分内容的编写,之后再进行审查和提交。 + +
+ +
+ +所以,复杂项目场景,并不是一句话 AI 就能全干了。甚至在整个工作来看,AI 只是完成了一少部分编码而已。 + +## 关于,有AI后岗位是否减少? + +减少?反而增多了! + +没有 AI 的时候,业务需求交付就完事了。现在有 AI 了,各种服务都要支持 AI 的接入,又是监控、又是巡检、又是客服,甚至点奶茶都要走个 AI 玩一圈。也因此为 AI 建基础技术设施,包括;AI 网关、AI 脚手架、AI 通用智能体(A2A)、AI 测试标准化验证等等。 + +
+ +
+ +与此同时,各行业也都会被程序员写的 AI 类服务,洗一圈的。春江水暖鸭先知,没有哪个行业有程序员能这么早的感受这个世界的变化了!即使就放在现在,AI 都火成这个德行,部分焦虑的程序员还害怕没工作的时候,其实外行人想装个 OpenClaw 都要付费请程序员帮忙。 + +所以,别傻了。你已经踩在这个时代的风口上了!没有人比你的机会更多。你看现在的 Boss 上有多少新上的 AI 应用开发工程师岗位,哪些做过的 Java 项目,现在都要用 Spring AI + Google ADK(a2a、mcp、skills)在翻盖。 + +
+ +
+ +## 那么,请正确看待AI的价值! + +AI 是这个时代非常牛的工具,也改变了很多的工作协作方式,还为各类场景带来了智能体赋能。如;豆包、OpenClaw、AI IDE、NotebookLM..., + +- 可以使用豆包,做一些内容编写,询问知识,还可以给小朋友讲故事。 +- 可以使用 OpenClaw 完成一些日常工作,整理素材,编写资料,剪辑视频。 +- 可以使用 AI IDE,学习编程,处理开发工作(明确范围的内容实现) +- 可以使用 NotebookLM 整理笔记,学习知识。 + +有太多的好用AI产品,在改变我们的生活。 + +其实整个时代来看,不是学古法编程重要不,也不是 AI 重要不,而是我们走过的这条路,增长的见识,积累的经验,锻炼的思维,重要!没有这些,即使有个工具也没法驾驭的起来。 + +
+ +
+ +之后,我们在说回本质;llm、rag、mcp、skills、a2a、agent work flow,这也是程序员设计出来的呀。所以,ai 的上限,由人决定。 + +--- + +**综上;** + +
+ +
+ +1. 首先,全局视角来看,所有行业,没有哪个行业有程序员这个行业具备最早接触世界上最新技术的了。即使是普通的 gpt 使用,OpenClaw 体验,程序员行业可以折腾,但其他行业直到现在都没法接触、使用和开发。 +2. 之后,说回写代码,写代码是交付的一部分,但交付不等于写代码。交付包括需求的讨论、分析、设计、编码、测试、上线、维护等全流程的操作。之后编码来说,有架构经验,丰富业务知识积累,复杂场景解决方案的程序员和只是初级程序员,使用 AI 也完全不一样。AI 是辅助提效的,但AI 没法完全替代人来写代码。否则互联网公司,现在就可以把人全部开除了,而不是让人又去使用 AI 提效。 +3. 并且35也不是终点,企业里现在也很喜欢老员工,老员工稳定性好,工资相对新人甚至是有点偏低(新人往往好学校的,工作几年培养起来,薪资很不错)。那么老员工的收入偏低,企业的成本不高,而且经验丰富好用。 +4. 如果这,如果那,但不如每一天都进步一点,每一年都有个变化。没有哪个绝对的好,也没有绝对的差,每一个行业,领域,都需要走到腰部以上,深入的积累,才可能让自己具备随时走的出去,也有留下来的本事。 + + + diff --git "a/docs/md/about/me/2020-12-27-2020\346\200\273\347\273\223\357\274\214\344\275\234\344\270\272\346\212\200\346\234\257\345\217\267\344\270\273\347\232\204\344\270\200\345\271\264\357\274\201.md" "b/docs/md/about/me/2020-12-27-2020\346\200\273\347\273\223\357\274\214\344\275\234\344\270\272\346\212\200\346\234\257\345\217\267\344\270\273\347\232\204\344\270\200\345\271\264\357\274\201.md" index b34a64b10..e508c7ad4 100644 --- "a/docs/md/about/me/2020-12-27-2020\346\200\273\347\273\223\357\274\214\344\275\234\344\270\272\346\212\200\346\234\257\345\217\267\344\270\273\347\232\204\344\270\200\345\271\264\357\274\201.md" +++ "b/docs/md/about/me/2020-12-27-2020\346\200\273\347\273\223\357\274\214\344\275\234\344\270\272\346\212\200\346\234\257\345\217\267\344\270\273\347\232\204\344\270\200\345\271\264\357\274\201.md" @@ -1,14 +1,14 @@ --- layout: post category: itstack-code-life -title: 2020总结 | 作为技术号主的一年! +title: 2020年,小傅哥の年终总结! tagline: by 小傅哥 tag: [java,itstack-code-life] excerpt: 快到年底了,写个总结吧!关注我的粉丝朋友,谢谢你!滴水之恩,永不相忘!我没照顾到的伙伴,对不起!我不是有意忽略了你。致我相识的每一位同好,所求皆如愿、所行化坦途。再见2020,迎接2021! lock: need --- -# 2020总结 | 作为技术号主的一年! +# 2020年,小傅哥の年终总结! 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) diff --git a/docs/md/about/me/2024-11-17-gold-content.md b/docs/md/about/me/2024-11-17-gold-content.md new file mode 100644 index 000000000..5c0e6528f --- /dev/null +++ b/docs/md/about/me/2024-11-17-gold-content.md @@ -0,0 +1,90 @@ +--- +title: 小傅哥的含金量,还在上升! +lock: need +--- + +# 小傅哥的含金量,还在上升! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +嘿嘿 😈,有时候我也会去网上对我评论,或者爬爬楼看看群里有人提到我时候的评价。当然无论什么内容,我基本不会去参与。毕竟让人怪不好意思的。不过我偷偷截图下来,当做对自己所做事情的鼓励。**你也想知道大家对我怎么评价的不?🤔** + +
+ +
+ +**不装了,我是大厂架构师,我摊牌了!** + +能在一家互联网大厂公司工作近10年,一直在一线核心业务场景开发&架构,又不断的承担高并发项目的架构和设计落地。那么他的广度、深度都会有非常不错的积累。如果他在能陆续的输出这些内容让人能学习到,可以说是做了非常有意义的事情!而小傅哥就是那个其中的他。 + +
+ +
+ +在我编写的博客量内容越来越多以后,我得到了很多的正反馈,包括;非常多的公司把这些内容作为`架构指导建议`、`编码行为规范`、`场景方案示例`,也有高校老师直接点名学生跟着小傅哥学项目,还有伙伴在各个论坛留言的认可。嘿嘿 那可以刻我觉得做有价值的技术分享真不错。 + +## 一、老师说;先跟着小傅哥做项目! + +我的大学导员时而也会和我聊,现在大学生要学习哪些技术,才能和公司招聘要求匹配。因为在校的学生👩🏻‍🎓做的项目,很多都是 CRUD 的,这些内容刚入门的时候做1-2次还好,但再重复就没有意义了,缺少广度和深度锻炼。所以非常需要像做公司里的项目一样成长。 + +没想到类似这样的对话,在其他高校的老师和高校的学生也给他的学生和伙伴分享。 + +
+ +
+ +
+ +
+ +也是因为有这样多的信任和认可,我也变得"越来越卷"😂,不断的卷出新的实战项目!这些项目的不是就只完成功能,而是把大厂中的经验整合进来,把业务、架构、设计、编码的技巧,逐步的呈现到项目中。所以跟着小傅哥学习,会吸收的非常多。 + +## 二、评论区;这群死鬼还真认可我! + +有时候我的粉丝伙伴会把一些评论截图给我,告诉大家对我的认可。还把我引流到 linux.do 注册了个账号😂。 + +
+ +
+ +
+ +
+ +- 其实当你有非常强的积累,有足够的广度和深度,用大量的时间做技术积累,其实是会得到很多伙伴的认可的。 +- 像是 OpenAI 大模型、大营销这样的大项目每个都花费1年的时间进行打磨输出。而且我也会有意的把互联网大厂中的技术方案,随着项目输入进去。这就像你吃一个东西一样,层层都有口感。演示:[https://openai.gaga.plus/](https://openai.gaga.plus/) - 当你看到小傅哥编码的项目,会让你对系统架构和工程编码都有非常高的认知。 + +## 三、产品线;为开源社区做贡献! + +写开源组件、做工具插件,又发表过十多个专利。小傅哥不只是带着大家做项目,日常也会搞一些小东西,让开发工程师可以使用,提高编码效率。 + +地址:[https://plugins.jetbrains.com/plugin/18262-vo2dto/versions](https://plugins.jetbrains.com/plugin/18262-vo2dto/versions) +源码:[https://github.com/fuzhengwei/vo2dto](https://github.com/fuzhengwei/vo2dto) + +
+ +
+ +💱 vo2dto IDEA Plugin 1.89万下载量,解决对象转换问题。选定对象批量织入“x.set(y.get)”代码,帮助开发者自动生成vo2dto转换代码。 + +✨ 特性 + +1. 2个对象的转换操作,通过复制 X x 对象,转换给 Y y 对象 +2. 允许使用 lombok 对象转换、lombok 和普通对象转换,对于 serialVersionUID 属性过滤 +3. 支持类继承类,全量的对象转换操作 +4. 含记忆功能的弹窗选择映射关系,支持全量对象、支持匹配对象、也支持空转换,生成一组set但无get的对象 +5. 支持对于引入不同包下的同名类处理 +6. 支持 Lombok.Builder 模式创建转换对象 + +## 四、卷工作;用强悍的实力拿下大厂Offer + +跟着小傅哥学习,不会浪费时间,不会走小道弯路。全程做技术兜底,遇到的各种问题都能帮你解决。包括你学习时候的代码bug,可以把代码提交到星球,我来帮你调试。最终把兄弟们送到各个竞争赛道的头部,拿到最牛的薪资待遇 Offer! + +
+ +
diff --git "a/docs/md/about/me/2025-01-04-2025\345\271\264\357\274\214\345\260\217\345\202\205\345\223\245\343\201\256\345\271\264\347\273\210\346\200\273\347\273\223.md" "b/docs/md/about/me/2025-01-04-2025\345\271\264\357\274\214\345\260\217\345\202\205\345\223\245\343\201\256\345\271\264\347\273\210\346\200\273\347\273\223.md" new file mode 100644 index 000000000..5c07b93af --- /dev/null +++ "b/docs/md/about/me/2025-01-04-2025\345\271\264\357\274\214\345\260\217\345\202\205\345\223\245\343\201\256\345\271\264\347\273\210\346\200\273\347\273\223.md" @@ -0,0 +1,145 @@ +--- +title: 2025年,小傅哥の年终总结! +lock: need +--- + +# 2025年,小傅哥の年终总结! + +作者:小傅哥 +博客:[https://bugstack.cn](https://bugstack.cn/) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +喜悦、兴奋、困惑、焦虑、释然、强大。2025年,是我的本命年,12年的一个轮回,好像所有做的事情,在这一年都有了一个阶段性的表现。**就像因果不是你一拳我一脚,而是蝴蝶振翅一念换天。** + +
+ +
+ +12年一个轮回,也和【道】符合。所以,今年的年度总结,换个行文方式,用 [《道德经》](https://daodejing.org/) 第42章比较热门的内容,做为引子,来串联故事线,希望小伙伴们喜欢😄。**好啦,2025年的,年终总结正式开始!** + +
+ +
+ +>道生一,一生二,二生三,三生万物。万物负阴而抱阳,冲气以为和。人之所恶,唯孤寡不毂,而王公以为称。故物,或损之而益,或益之而损。人之所教,我亦教之。强梁者不得其死,吾将以为教父。道德经,资料:[https://daodejing.org/](https://daodejing.org/) + +## 一、副业,道生一 + +>道生一,一生二,二生三,三生万物。 + +起因动念,决定做的事,想好走的路,就是道。开始执行便有了一,之后又用了6~7年时间,开枝散叶完成了一个自己的IP品牌建设。 + +6年时间里,从最初的写技术博客,到编写技术小册和出书,再到带着读者粉丝做实战项目。我用10年+互联网大厂的技术经验积累和产品业务认知,帮助读者构建一个1:1还原真实工作环境的超大技术资料库,覆盖全部的核心应用技术,以及截止到今年有19个应用级实战编程项目。 + +我的目标是,让加入小傅哥的伙伴,就等同于进入一个互联网大厂的项目组。在这里可以学习到非常有价值的编程架构经验,也能学习到丰富的应用产品业务知识。不少伙伴都感慨:“进入到公司才发现,小傅哥教的东西有多重要!” + +2025年,新增完成了,1个业务项目、2个AI项目(含1个进行中)、2个组件项目、2个自学项目、5套基础教程; + +### 1. 实战项目 + +- 2024-11-11《拼团交易平台系统》 - 24年末启动,25年中完成。这套项目业务流程非常细腻,可以让学习的伙伴,掌握细腻的业务知识、大厂的架构设计和解决方案,也可以学习到微服务&分布式的设计和实现,同时又有非常有价值的场景解决方案。 +- 2025-03-03《DeepSeek RAG、MCP、Ai Agent 智能体》 - 这几乎是全网最早启动的智能体项目,分3个阶段教学,直至完成一个可拖拉拽配置的智能体。这套内容是基于 Spring AI 框架实现,做 Java 业务项目的公司,也都是使用 Java 语言编写智能体,来为业务项目提效。而 Python 类则偏向底层或者数据以及量化多一些。 +- 2025-04-19《通用技术组件 - 🔧扳手工程》 - 这是一套互联网大厂里的通用解决方案,他们会把共性的诉求,凝练成通用的组件,让各个系统可以复用。像是拼团项目、Ai Agent 项目,都有使用这里的组件能力,让大家真实感受到一个互联网公司级的项目,是怎么做这样的事情的。 +- 2025-10-20《AI MCP Gateway 网关服务系统》 - 这是25年10月,新启动的一个 AI 类项目,也是互联网公司中必备的 AI 类项目。因为公司里需要把各类的业务接口,转换为 AI MCP 协议的服务能力,让 AI 客户端可以调用使用。而这个项目又是深入理解 json-rpc2 mcp 协议的一个项目,非常具有学习价值。 +- 2025-11-23《本地任务消息组件》- 在互联网公司中,所做的微服务项目,都要解决一致性(MQ、RPC、HTTP)问题,这里会设计一个通用的技术组件,来完成任务补充操作。 +- 2025-09-15《钓鱼佬-网页游戏项目》- 自学扩展思路类型项目,Java & Python 双版本代码 +- 2025-09-08《吉祥外卖系统 PLUS 版》 - 自学扩展思路类型项目,方便伙伴拓宽互联网场景视野,增强自身学习过外卖,补充外卖知识的项目。 + +### 2. 基础知识 + +- 2024-12-17《技术术语》- 陆续编写,防腐、对象(vo、po、dto...)、微服务、埋点、幂等... +- 2025-08-03《云服务器操作课程》- 购买配置、SSH连接使用、Docker 一键安装脚本、JDK、Maven、MySQL、Redis等,Docker 部署项目、ai ssh命令工具 +- 2025-08-24《产品文档》- 滴滴特惠、国家电网营销 +- 2025-07-28《菜鸟教程》- 小白基础教程,基础环境配置、Java基础、并发编程、线程池、JVM 调优、Spring、MyBatis、MySQL、Redis、技术架构、互联网场景、技术关键词、Dev-Ops 环境配置等。 +- 2025-01-01《编程路书》长期维护项目,今年更新内容,今年新增;oauth2、ddd、ollama、aigc、google adk、joycode、docker 一键安装脚本&部署项目教程、流量录制和回放、远程调试、draw.io + ai 提效等。 + +
+ +
+ +**怎么样,加入小傅哥的社群,学起来是不很爽。你得到的哪是一个项目,而是完整的小傅哥本人!** + +## 二、职场,以为和 + +>万物负阴而抱阳,冲气以为和。 + +生阴而向阳,冲气乃万物,万物是道之所念,意之所行的结果。万物又皆以循环往复,起落升降周而复始。但因我道心已改😂,所以也只是坦然的看待当前这个循环。 + +因为我在一个公司的时间足够长,所以我现在看待职场,看像是看待一个缩影的人生。从3-5年蓄力、到5-10年爆发、再到10-15年淬炼到下个赛道(高级技术架构、T转M),后面在逐步缓慢退场。就像这一年, 我有好几个饭搭子离职了,也有被动毕业的,还有一些是领导换成了员工,员工换成了领导。更有之前的伙伴,已经走到了更高的顶层M级别,光彩照人。 + +放到以前我也会很羡慕晋升到更高级别,甚至不在意钱,而是在意晋升。但现在是站在了循环之外,来看待这些事情。更关心的不是那些晋升,而是在意于把多的时间留给家人,留个自己,留给身体。整个职场生涯到了这个阶段的很多伙伴,应该算是在“控分”,做的不是特别突出,但也不落后。 + +**为啥会“控分”呢?** + +刚工作时我绝不会意识到这一点,但到了结婚生子,上有老,下有小的时候,就会感受到了。 + +举例,很多北京工作的伙伴,是没有北京户口的。周五晚上一堆拼车的,要回天津了,周一早上又突突的跑来。有时候又要调休办理这个流程,办理那个手续,那你的精力自然就会被分配出去,很难有自己时间,或者全都扑给工作。类似这样的工作的伙伴,可以说非常消耗自己的,直至控分越低,最后也就只能做其他的去了。 + +伙伴说:“北京社保我已缴满10年+了,但我好像也从没细致的看看北京,当我办完手续,想先在北京好好玩一周,再退租回家。” 哼,这死鬼,变现不少股票,也拿了顶格 n+1,当然满意离场了。 + +潮汕人说,工字不出头,在小也要做生意。不过,像是我们这种家里没有做生意的,可能也没有啥做生意的基因,所以只能一小小点的尝试,在一个长期的时间里进行验证,找到自己的【道】。 + +## 三、心态,求不毂 + +>人之所恶,唯孤、寡、不毂(gu 车轱辘,圆满),而王公以为称。 + +反着干,求圆,则求不圆(不毂)。以放下的心态拿起来,上班就是为了离职的,面试就是为了面不上的。把期待放到最低,我不要了,爱咋地咋地。 + +生活中那么多事,不可能每件事都做到尽善尽美,所有的事情都玩命投入,那么每一件事情都可能做的乱码起糟。所以,要有第一性原则,要有自己的主线任务,找到那些事务的本质,才能有更好的心态完成这件事。 + +就像很多985/211的伙伴找实习的时候,学校就近找了个小公司,干着一些打杂的事情,那么临近毕业写到简历就非常难看。 + +找实习的第一个点,是验证你的能力,可以够得上当前这家公司。那么第一性目标,就应该奔着你的学校和你的积累,匹配未来你要去的城市和公司级别来找实习。 + +而写简历,是通过你的实习经历(或导师实验室)、项目经验、技术积累、赛事活动等,举证你的能力项。这样才能让你再毕业的时候找到一份更好的工作。 + +而我做的事情也一样,很多事情都是很慢,很慢的推进,不图热点,也不去接广告。朝着不骄不矜,虚怀处下的心态做事,把时间和精力都放在构建整个技术体系上,逐步形成一个完整的闭环,这样它的价值也会在后续逐步的变大。 + +## 四、结果,益和损 + +>故物或损之而益,或益之而损。 + +放在当下可能有困惑或不甘,但拉长时间线看,未来的某一天你都可以释然般的讲出当年的事,而那些事为你涨的经验,又能驱动着你走到了更高的一个台阶。往往,我们就是在这些不确定性中获益,动心忍性,曾益其所不能。 + +上一个12年,租房被骗,合租不爽,入职时间拉长(毕业了也不给办正式入职,多实习了3个月),电脑进水,手机丢了,出差没钱租满屋子都是床的一张床... + +后来,所有的事情都让我有了新的想法和计划; +- 租房被骗,合租不爽;后来,再也不合租了,就自己住,有了更多的自己的时间,也能做一些自己事情。从13年,就开始折腾各种技术。 +- 入职时间拉长;后来,第二年以入职不满一年为理由不给涨薪,所以多方面储备,1年后离职进入互联网,才有了现在的生活方式。 +- 电脑进水,手机丢了;后来,花500元修了电脑,暂时用一个临时的小手机打电话用。接了第一份私活,转了5000块,立马买了新手机。 +- 出差没钱;后来,我会想,什么公司、什么工作、什么领导,饿肚子的时候,只有自己感受到。 + +所以,很多事情都是这样,没有什么一定的好或则一定的不好。这一个12年,也有很多杂七杂八的事情,它们也驱动着我做了新的规划,未来会逐步体现出来。 + +你呢,是不也有很多事情,让你有了新的计划和不错的结果。 + +## 五、分享;亦教之 + +>人之所教,我亦教之。 + +站在我自己来看,这些年一直秉承着;**沉淀、分享、成长,让自己和他人都能有所收获。** + +我看待我自己便是一个知识的桥梁或者媒介,通过的我工作储备,把这些内容转换成`文字`、`视频`、`代码`,让关注到我的伙伴,可以成体系的学习积累编程相关的经验。 + +一年一年来说,其实我都在构建这个业务场景和技术实践的体系结构,并紧跟技术热点,甚至要早于很多互联网公司的动向,把这些内容提前给大家。这也让很伙伴进入职场后可以受益:`“小傅哥,我们公司在做 DDD 重构,我可以主导很多东西”`、`“我们公司也开始了 MCP 的开发,还有 AI MCP 网关”`、`“真快,现在公司都在做 AI Agent 提效业务的了”`、`“小傅哥是真教东西呀,要不是学了这些,我进入公司肯定跟不上”`,等等。 + +
+ +
+ +可能多年以后,小伙伴会说一句:**“傅哥,对得起我!”** + +## 六、共勉:强梁者 + +>强梁者不得其死,吾将以为教父(始/本/规矩)。 + +强梁者,亦是强良者,过分的强横,亦或过分的善良,都不会得到太好的结果。所以,不惹事,不怕事,多积累自己,储备自己,让自己具备随时脱身的本事,亦或是能站住脚的能力,才是做人的始末规矩。 + +当在校生有丰富的技术积累就不害怕面试、当工作多年的你有很好的项目经验就不用担心跳槽、当你有了不错的资金储备就不担心职场pua,当你有了工作以外的提前规划和实施就不担心未来的发展。 + +斜杠、多面手,让自己有更多的可能,不让自己陷入任何一个环境里,作为梁者承重,或为良者受欺。打开思路,多关注事务的本质和运行规律,我们都可以过一个更舒服的生活。加油,每个少年们! + +**2025年,再见啦,2026年开启啦!祝每一个伙伴,每一年都有一个新的认知,来过好每一天的生活。** diff --git "a/docs/md/about/me/2025-01-05-2024\345\271\264\357\274\214\345\260\217\345\202\205\345\223\245\343\201\256\345\271\264\347\273\210\346\200\273\347\273\223\357\274\201.md" "b/docs/md/about/me/2025-01-05-2024\345\271\264\357\274\214\345\260\217\345\202\205\345\223\245\343\201\256\345\271\264\347\273\210\346\200\273\347\273\223\357\274\201.md" new file mode 100644 index 000000000..d45e24404 --- /dev/null +++ "b/docs/md/about/me/2025-01-05-2024\345\271\264\357\274\214\345\260\217\345\202\205\345\223\245\343\201\256\345\271\264\347\273\210\346\200\273\347\273\223\357\274\201.md" @@ -0,0 +1,79 @@ +--- +title: 2024年,小傅哥の年终总结! +lock: need +--- + +# 2024年,小傅哥の年终总结! + +作者:小傅哥 +博客:[https://bugstack.cn](https://bugstack.cn/) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +仿佛24年的元旦聚餐还在昨天,一觉酒醒就到了25年的元旦😂。要不总说,幸福不折腾的日子总让人感觉过的很快,还真是快。 + +同时我也满怀期待,临近过年的3周,有伙伴聚餐、有单位团建,喜庆氛围逐步拉满,之后快乐过年!**今年应该能放炮了🧨,庆祝下这一年做的大量上百万字的内容输出!** + +
+ +
+ +>这是我东北的老家,每每过年都会想起他。从13年毕业到现在,整个家里人就一起“北漂”了,也就没在东北过过年。看看2025年可以回去一趟。 + +## 疯狂输出 + +这一年的输出也是卷的飞起,包括;一套`大营销项目60节+`、一套`小型支付双架构MVC+DDD`、三套`技术组件项目`和一套`基础教程70节的《编程路书》`,同时配套的录制大量的视频教程。合计输出至少在200万字。—— 键盘膜都敲碎了!😱 + +- 编程路书,是一套为了帮助小白伙伴学习编程开发的实战案例指导手册。包括;脚手架、系统架构、开发环境、开发技术、常用类库、工程测试、质量监控、发布部署、应用网关,这样几个大块。这也是我看过很多网上都是碎片化的不成体系的教程,甚至都没法运行,所以构建了这样一套免费教程,帮助大家学习。 +- 业务项目,大营销是一套非常大型的实战业务项目,含有丰富的业务场景,全程视频手把手的教程,带着大家做技术成长。随着大营销的落地,又开启了小型支付项目,用 MVC 和 DDD 架构分别实现一遍,让小伙伴可以快速理解 DDD 并上手开发。 +- 技术组件,其实小傅哥深知,简历要想漂亮点,必须是有点轮子一样的技术组件。虽然公司不一定让你哐哐哐的造轮子,但是得有这样的技术,因为这是你技术深度的体现。 + +与此同时,为了让学习编程的伙伴可以成体系化的成长,所学内容有连贯性、进阶型,而不是东一榔头,西一棒子。所以小傅哥构建了一整套项目进阶路线。这套项目进阶路线,在25年会继续迭代。让大家一次加入就学到爽! + +
+ +
+ +>🧧关注公众号「bugstack虫洞栈」回复「星球」可以领取加入优惠券。 + +## 长期主义 + +`这一年胖东来火了,雷军的含金量也在不断提升。` + +但其实说白了,别骗人、别忽悠、做长期且有价值的事,长期坚持做,达到一定的规模体量了,就一定会有成绩。 + +而那些靠大量推广和包装起来的,总会在后面得到一堆堆流量的反噬。而长期坚持虽然看着慢,但完完整整的做下来一个个硬核项目的,总能在后面得到好的反馈。 + +如果有些伙伴想自己做点什么,只要在你喜欢的能长期做的方向上,一直做下去,积累大量的生产资料,最后也都可以做成。不用图快,有时候图快就会成韭菜。 + +工作了这么多年,看到一个个同事从最初入职到10年的发展,会感觉多少有点“命”在里面😂。有些一起的同期的伙伴,职位都已经到达了顶峰。而以前的他的领导,都成了他下面,下面,下面的部门职员。 + +但其实这个“命”也是个人长期在某些方向积累的结果,比如你持续积累的业务经验甚多,做的项目也都次次拿奖,又具备良好的表达能力。自然就会平步青云。而如果你在部门偏创新,反复的调整折腾,别说往上走,别被开除都算不错的。 + +当然,所有的这些,没有啥可能一直持续的平稳的,都可能在不确定性中发展。即使你工作很久在一个项目上,但这个项目也不是你的。随时都可能被拿走。如果你的被反复拿走,那么就要多积累自己。如果你的不被拿走,而且把别人的拿走给你,那你就可以好好做项目,慢慢项目多了,管的人也会增多。所以,你要知道自己处于的是什么路线,有没有“命”里的正财或偏财,之后选择性的发展。让其他分支路线,保持个60分及格就行了。 + +但命呢,也是过往信息、技能、知识、逻辑的积累所产生的行为判断。如果你做的哪些事向好,但又不符合自己的性格就是运。所以,一个人正向的积累越多,越能让自己有非常好的命。 + +## 卷和不卷 + +`500万-800万,买一套房,你会选择留在北京吗?🐂🐴` + +不会,为什么?因为小孩晚上不爱睡觉!啊?这两者有什么关系? + +我呢,是来自于东北的村里,小的时候总是天一黑,跟着大人看会电视📺,没等到7:00的新闻联播演完,就困的睡着了。第二天,又跟着大人,早早的起床。因为大人要下地干活了,晚起就没人管了。 + +但现在的小孩,能整整熬到10点、11点才睡觉,他们就像有很多精力一直没释放完一样。和自己小时候一对比,突然想到。是呀,自己小时候,开门出去就是一个非常大的院子,再跑出去就是跟着一帮的伙伴在野地里疯跑,晚上自然累的呼呼就睡。 + +而现在的小孩,基本一整天都在水泥楼房里,每次下个楼都要换一堆的衣服,出去跑一会又回来继续脱衣服。等在过几年,就开始上幼儿园、小学、中学,一直被卷到毕业再到进厂当牛马。虽然我们现在也做这牛马的工作,但好在累了还能回忆下小时候有个不错的童年。 + +所以,在整个时代机会那么大的时候,你都没有卷出结果,怎么就能觉得在培养一个小牛马,就能继续卷赢。当然,这只是我的想法,如果都是我的想法,想必不卷也会过的不好。所以一定要有人卷。 + +当下,我们都已经这么明白这个社会的运行规则了,要卷就先卷自己吧。**走暗路、更瘦天、进窄门** + +## 未来输出 + +25年,必然也会很忙的一年。因为我的计划是交付出一套全体系的应用级项目,让你在小傅哥这里学习就等于进入一个互联网大厂学习。 + +目前已有6个业务项目、7个组件项目交付完成,未来一年保守估计将会再交付2套业务,2套组件。不过虽然有这么大量的交付和高频的更新,但小傅哥的星球依旧是价格上最实惠的。仅仅用一个项目的价格,就可以学习全部项目! \ No newline at end of file diff --git "a/docs/md/about/me/2025-07-03-\345\230\216\345\230\216\345\274\272\357\274\214\345\230\216\345\230\216\345\223\222\345\255\246v2.0.md" "b/docs/md/about/me/2025-07-03-\345\230\216\345\230\216\345\274\272\357\274\214\345\230\216\345\230\216\345\223\222\345\255\246v2.0.md" new file mode 100644 index 000000000..a5d3a0223 --- /dev/null +++ "b/docs/md/about/me/2025-07-03-\345\230\216\345\230\216\345\274\272\357\274\214\345\230\216\345\230\216\345\223\222\345\255\246v2.0.md" @@ -0,0 +1,115 @@ +--- +title: 帮助大家学编程,嘎嘎大学 v2.0 上线! +lock: need +--- + +# 帮助大家学编程,嘎嘎大学 v2.0 上线! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +五年啦📢,从最初只有一个 `IM 仿微信项目` + `编写 Netty` + `字节码编程`文章小傅哥,终于靠一己之力构建出了完整的toc业务场景,实战项目训练社群。感谢这么多年一直陪伴着小傅哥的粉丝伙伴!体验地址:[https://gaga.plus](https://gaga.plus) + +
+ +
+ +**文末说说下个五年** + +**gaga.plus 嘎嘎强,嘎嘎哒(大)学,小傅哥的私有技术朋友圈 👬🏻** + +嘎嘎强,嘎嘎哒学,是帮助从事软件开发行业的伙伴,搭建起一条与实际公司场景项目最近的桥廊。在这里你不需要臆想出虚假的项目,也不需要全是 CRUD 的空洞编程。而是实实在在的来自于企业的真实业务流程,进行编程思维的锻炼和编码能力的提升。 + +嘎嘎哒学,是以一个互联网公司中的真实项目组,进行业务场景需求的讲解和项目的开发。再这样的一个项目组,有业务项目,有通用组件项目,有创新应用项目。还有项目的分析、设计、部署、上线、监控、压测,可以说你在小傅哥这里学习,就等于你在真实大厂的实际工作。 + +
+ +
+ +**注意,实习生不算,因为实习生进入工作大部分是做边角料的活。** 所以实习生,更要学习,否则还远不如在小傅哥技术社群学习积累的多。 + +## 一、嘎嘎哒学 + +**嘎嘎强,嘎嘎哒学!**我把这作为一个`在线的技术大学`进行维护。社群,以最实惠的价格,最丰富的项目,带着粉丝伙伴一起成长。并且提供全程从0到1的教程,让小白伙伴也能上手学习,互联网真实场景的实战项目。 + +地址:[https://gaga.plus/](https://gaga.plus/) + +
+ +
+ +🎓 欢迎来到技术社群,星球「码农会锁」!这里是你的 🏫 编程学习殿堂。体验真实业务场景项目,掌握大厂核心编程技术。 全程视频手把手,增强编程思维,锻炼编码能力 👨🏻‍💻 + +跟着小傅哥学习,你可以积累到非常丰富的实用性实战技能; + +- 【系统架构】微服务、DDD 领域驱动设计、SpringBoot Starter、IDEA Plugin +- 【设计模式】工厂、策略、模板、外观、组合、状态、代理、门面等 —— 这些设计模式都在项目中使用,解决实际场景问题。 +- 【框架技术】Spring、SpringBoot、SpringMVC、MyBatis、MySQL、Guava、JWT、Shiro、OKHTTP3、Schedule、Netty、字节码(ASM\Javassist\Byte-Buddy)、JavaFx +- 【分布式类】Dubbo、MQ(Kafka\RocketMQ)、Redis、XXL-Job、Zookeeper、Sharding-JDBC、DB-Router、Elasticsearch、Zookeeper、Canal、Otter、ELK、Hystrix、RateLimiter +- 【前端技术】React、Next.js、Typescript +- 【运维知识】Docker、Portainer、Git、Compose、运维脚本 +- 【创新技术】Spring AI、RAG、MCP、Agent +- 【通用组件】结合 Spring、Redis、MyBatis、AOP技术等,实现的通用技术组件 +- 【技术方案】营销、电商、外卖、支付、组件、重构,以及性能优化等各类场景的技术方案归档。 + +这些技术都是在各个项目中运用到的内容,也是中大互联网公司必备的技术技能,从面试招聘的要求中就能看到这些知识项要求熟练掌握。那么,这些内容也是小傅哥星球内项目能让大家学习掌握的技术。此外,还有一项隐藏技能就是绘画能力。 + +进入公司后,免不了要述职、分享、答辩,那么绘画就是一些非常重要的技能,加入星球就能看到各类项目中的高级绘图,学习这些能力。 + +## 二、项目举例 + +### 1. 业务项目 + +
+ +
+ +### 2. 组件项目 + +
+ +
+ +### 3. 其他项目 + +
+ +
+ +## 三、运维操作 + +其实学项目,就不只是写代码,还有很多的其他操作。就像公司里一样,写代码只是编程工作的一部分。因此,小傅哥也带着大家学习整个 DevOps 的各项技术。如,Docker + 软件,在云服务器的操作,提供好运维脚本。 + +
+ +
+ +### 1. 一键安装脚本 + +
+ +
+ +### 2. 云服务器教程 + +
+ +
+ +- 地址:[https://bugstack.cn/md/road-map/docker-install.html](https://bugstack.cn/md/road-map/docker-install.html) + +## 四、下个五年 + +地址:[https://github.com/fuzhengwei/CodeGuide/issues/111](https://github.com/fuzhengwei/CodeGuide/issues/111) + +让人怪不好意思的,上山⛰的路走了,巅峰的山也看了,后面也快下山了。**所以下个五年,感觉有点像离职倒计时。😂** + +在公司中我们每隔3年,可以申请一次换新的电脑,领取到手后,会有一个残值,不断的降低,最终到3年降低到0元,之后就可以换新的了。 + +有时候我们一起聊天的伙伴,也会感觉自己的残值在逐渐的降低。一方面是年级越来越大,部门的新人越来越多。另外一方面是自己的家庭,娃也都快要上小学,离开也是陆续的事。 + +那么,下个五年走完后。那时候,应该彻底的在做自己的事了。今年5年的利率 `1.6%`,五年后正好取定期存款,拿利息带着家人一起旅游!🚗 ⛰ diff --git a/docs/md/ai/a2a.md b/docs/md/ai/a2a.md new file mode 100644 index 000000000..8974a9fc5 --- /dev/null +++ b/docs/md/ai/a2a.md @@ -0,0 +1,388 @@ +--- +title: a2a +lock: need +--- + +# A2A,实际跑起来是什么样? + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +chatgpt(22年)-> LLM 进阶(23年)-> MCP 协议(24年)-> Skils 技能(25年)-> A2A 标准(25年),这几年 AI 发展的非常迅速,定义了协议,开发了组件,发布了产品。每个阶段,都有非常牛皮的代表性的内容,车速非常快🚌,不知道在坐的各位有没有掉队。 + +
+ +
+ +针对这些 LLM 大模型的相关知识,小傅哥也分别提供了相关实战类项目,包括;**AI 问答助手(23年)**、**OpenAi(ChatGPT/ChatGLM) 微服务应用体系构(23年)**、**OpenAI 代码自动评审组件(24年)**、**AI Agent 智能体 - 拖拉拽(25年)**、**AI MCP Gateway 网关服务系统(25年)**、**AI Agent 脚手架 + 场景应用(26年)**,通过这些实战项目,实践各类标准协议和技术组件(spring ai、google adk...)的使用,以及提供非常出色的解决方案。 + +因为后续的 ai agent 智能体项目,还会涉及到 a2a 协议,所以先给大家做个相关技术的使用方便大家快速实践理解。 + +>🧧 文末提供了20个实战项目(6个AI、5个业务、8个组件、1套源码),以及各类编程技术小册等。欢迎一起加入学习。 + +## 一、A2A 是什么? + +A2A (Agent2Agent) 协议是 Google于2025年4月推出、并由 Linux基金会托管的开源开放标准。它作为AI智能体之间的“通用语言”,旨在实现不同框架、不同厂商构建的智能体(Agent)间跨平台发现、通信与协作。 + +随后25年底,Google 发布了 [a2a adk](https://central.sonatype.com/artifact/com.google.adk/google-adk-a2a/0.4.0) 组件(迭代速度很快)。之后借助代理开发工具包 (Google ADK),我们可以构建复杂的多代理系统,其中不同的代理需要使用代理对代理 (A2A) 协议进行协作和交互!本节提供了一个全面的指南,指导您构建强大的多代理系统,使代理能够安全高效地进行通信和协作。 + +框架:[https://google.github.io/adk-docs/a2a/](https://google.github.io/adk-docs/a2a/) + +源码:[https://github.com/google/adk-java](https://github.com/google/adk-java) + +资料:[https://www.ibm.com/cn-zh/think/topics/agent2agent-protocol](https://www.ibm.com/cn-zh/think/topics/agent2agent-protocol) + +文档:[https://a2aprotocol.ai/docs/](https://a2aprotocol.ai/docs/) + +--- + +如图,整套智能体架构(含A2A); + +
+ +
+ +- 左侧,是 LLM 模型智能体构建,基于 Spring AI 框架实现。这部分包括,AiApi 使用、RAG、MCP、Skills 的组合构建。 +- 右侧,是 AI Agent 智能体编排,基于 Google ADK 框架实现。这套框架,提供了智能体工作流组装,插件回调钩子等各项基于 Google 发布的协议进行构建的。 +- 之后,右上方,是 Google ADK 26年基于 A2A 协议实现的框架组件,方便我们设计出远程的 A2A 服务对接,把远程服务,转换为本地功能组件,编排进智能体中。因此 A2A 协议的作用,就是让一个远程的智能体,可以像构建本地智能体一样,连接起来进行使用。 + +> 基于 a2a 的协议,也有很多三方框架,但我们需要的是一个整体的解决方案,单一一个功能,还不能解决所有问题。所以这里优先选择 google adk 框架。 + +## 二、实践案例 + +### 1. 编程环境 + +- jdk 17 +- google adk 0.8 +- spring ai 1.1.0-M3 + +>相关的版本包,已经在测试工程中的 pom 里引入了。可以打开工程查看。 + +### 2. 工程结构 + +
+ +
+ +- 工程:[https://github.com/fuzhengwei/xfg-dev-tech-google-adk-a2a-server](https://github.com/fuzhengwei/xfg-dev-tech-google-adk-a2a-server) +- 说明:基于 Google ADK 框架,构建 A2A 服务端和客户端。注意,服务端的启动方式为 `quarkus.sh` 方式启动服务,之后使用客户端连接。 +- 注意:这部分还有一些关于关于 Spring AI + Google ADK 的基础使用知识,是在 ApiTest 中有案例。也可以学习项目 [《AI Agent 脚手架 + 场景应用》](https://bugstack.cn/md/project/ai-agent-scaffold/ai-agent-scaffold.html) + +### 3. 测试案例 + +```java +public class ApiTest { + + public static void main(String[] args) throws Exception { + OpenAiApi openAiApi = OpenAiApi.builder() + .baseUrl("https://apis.****.cn") + .apiKey("sk-tIYdEUUnMqKX3bRf756a31449a4942***需要配置你的key") + .completionsPath("v1/chat/completions") + .embeddingsPath("v1/embeddings") + .build(); + + ChatModel chatModel = OpenAiChatModel.builder() + .openAiApi(openAiApi) + .defaultOptions(OpenAiChatOptions.builder() + .model("gpt-4o") + .build()) + .build(); + + // agent 测试 + LlmAgent agent = LlmAgent.builder() + .name("test") + .description("Chess coach agent") + .model(new SpringAI(chatModel)) + .instruction(""" + You are a knowledgeable chess coach + who helps chess players train and sharpen their chess skills. + """) + .build(); + + InMemoryRunner runner = new InMemoryRunner(agent); + + Session session = runner + .sessionService() + .createSession("test", "fzw") + .blockingGet(); + + Flowable events = runner.runAsync("fzw", session.id(), + Content.fromParts(Part.fromText("1+1"))); + + System.out.print("\nAgent > "); + events.blockingForEach(event -> System.out.println(event.stringifyContent())); + } + +} +``` + +- 这是一个 Spring AI + Google ADK 构建的简单智能体,由 LlmAgent 构建时候,创建模型 `new SpringAI(chatModel)` 关联到 Spring AI 框架。 +- 之后,由 Google ADK 构建的智能体,使用内存记忆,创建会话之后进行测试。也可以学习项目 [《AI Agent 脚手架 + 场景应用》](https://bugstack.cn/md/project/ai-agent-scaffold/ai-agent-scaffold.html) 锻炼使用相关内容。 + +### 4. A2A 测试 + +#### 4.1 服务端 + +这部分内容的学习,可以打开案例代码,方便对比。 + +##### 4.1.1 服务提供 + +```java +@ApplicationScoped +public class AgentExecutorProducer { + + @ConfigProperty(name = "my.adk.app.name", defaultValue = "default-app") + String appName; + + @Produces + public AgentExecutor agentExecutor() { + return new com.google.adk.a2a.executor.AgentExecutor.Builder() + .agent(Agent.ROOT_AGENT) + .appName(appName) + .sessionService(new InMemorySessionService()) + .artifactService(new InMemoryArtifactService()) + .agentExecutorConfig(AgentExecutorConfig.builder().build()) + .build(); + } + +} +``` + +- 这部分是把智能体提供出去,通过 google adk 框架,创建 AgentExecutor 实例。 +- 之后 Agent.ROOT_AGENT 类似于上面的测试案例,智能体构建的部分。你可以创建任何之后通过 AgentExecutor 发布出去。 + +##### 4.1.2 卡片提供 + +```java +@ApplicationScoped +public class AgentCardProducer { + + @Produces + @PublicAgentCard + public AgentCard agentCard() { + try (InputStream is = getClass().getResourceAsStream("/agent/agent.json")) { + if (is == null) { + throw new RuntimeException("agent.json not found in resources"); + } + + // Read the JSON file content + String json = new String(is.readAllBytes(), StandardCharsets.UTF_8); + + // Use the SDK's built-in mapper to convert JSON string to AgentCard record + return Utils.OBJECT_MAPPER.readValue(json, AgentCard.class); + + } catch (Exception e) { + throw new RuntimeException("Failed to load AgentCard from JSON", e); + } + } + +} +``` + +**/agent/agent.json** + +```java +{ + "capabilities": {"streaming": true}, + "defaultInputModes": ["text/plain"], + "defaultOutputModes": ["application/json"], + "description": "一个专门检查数字是否为素数的智能体。它可以高效地确定单个数字或数字列表的素性。", + "name": "check_prime_agent", + "skills": [ + { + "id": "prime_checking", + "name": "Prime Number Checking", + "description": "使用高效的数学算法检查列表中的数字是否为素数", + "tags": ["mathematical", "computation", "prime", "numbers"] + } + ], + "preferredTransport": "JSONRPC", + "url": "http://localhost:9090", + "version": "1.0.0" +} + +``` + +- 这里要构建一个智能体卡,A2A 的协议中,把服务包装成一个卡片的概念。 +- agent.json 配置的是 `Agent.ROOT_AGENT` 智能体的信息。 +- 如果你之前学习过小傅哥的 AI MCP 网关项目,会对 JSONRPC 有印象, MCP 协议和 A2A 协议,都是走到 JSONRPC 标准进行的通信。 + +#### 4.2 客户端 + +##### 4.2.1 构建端 + +```java +public final class A2AAgent { + + private static final Random RANDOM = new Random(); + + private static final OpenAiApi openAiApi = OpenAiApi.builder() + .baseUrl("https://apis.****.cn") + .apiKey("sk-tIYdEUUnMqKX3bRf756a31449a4942***需要配置你的key") + .completionsPath("v1/chat/completions") + .embeddingsPath("v1/embeddings") + .build(); + + private static final ChatModel chatModel = OpenAiChatModel.builder() + .openAiApi(openAiApi) + .defaultOptions(OpenAiChatOptions.builder() + .model("gpt-4.1") + .build()) + .build(); + + @SuppressWarnings("unchecked") + public static ImmutableMap rollDie(int sides, ToolContext toolContext) { + ArrayList rolls = + (ArrayList) toolContext.state().computeIfAbsent("rolls", k -> new ArrayList<>()); + int result = RANDOM.nextInt(Math.max(sides, 1)) + 1; + rolls.add(result); + return ImmutableMap.of("result", result); + } + + public static final LlmAgent ROLL_AGENT = + LlmAgent.builder() + .name("roll_agent") + .model(new SpringAI(chatModel)) + .description("处理不同面数骰子的投掷。") + .instruction( + """ + 当被要求掷骰子时,始终调用 roll_die 工具并指定面数(如果未指定,默认为 6)。不要编造结果。 + """) + .tools(ImmutableList.of(FunctionTool.create(A2AAgent.class, "rollDie"))) + .build(); + + public static LlmAgent createRootAgent(String primeAgentBaseUrl) { + // 远程 agent + BaseAgent primeAgent = createRemoteAgent(primeAgentBaseUrl); + + // 本地 agent + return LlmAgent.builder() + .name("root_agent") + .model(new SpringAI(chatModel)) + .instruction( + """ + 你可以在本地掷骰子,并将素数检查委托给远程的 prime_agent。 + 1. 当用户要求掷骰子时,将请求路由给 roll_agent。 + 2. 当用户要求检查素数时,委托给 prime_agent。 + 3. 如果用户要求先掷骰子然后检查,先调用 roll_agent,然后将结果传给 prime_agent。 + 在讨论素数之前,始终先简述骰子结果。 + """) + .subAgents(ImmutableList.of(ROLL_AGENT, primeAgent)) + .build(); + } + + private static BaseAgent createRemoteAgent(String primeAgentBaseUrl) { + + String agentCardUrl = primeAgentBaseUrl + "/.well-known/agent-card.json"; + AgentCard publicAgentCard = + new A2ACardResolver(new JdkA2AHttpClient(), primeAgentBaseUrl, agentCardUrl).getAgentCard(); + + Client a2aClient = + Client.builder(publicAgentCard) + .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) + .clientConfig( + new ClientConfig.Builder() + .setStreaming(publicAgentCard.capabilities().streaming()) + .build()) + .build(); + + return RemoteA2AAgent.builder() + .name(publicAgentCard.name()) + .a2aClient(a2aClient) + .agentCard(publicAgentCard) + .build(); + } + +} +``` + +- createRootAgent 是构建入口,一个是创建 createRemoteAgent 远程智能体,一个是 `LlmAgent.builder()` 构建本地智能体。之后在构建本地智能体的时候,通过 subAgents 把远程智能体填充到本地的智能体里去了。这个编排的方式有多种多样的。 +- createRemoteAgent 远程构建,这是固定协议路径 `/.well-known/agent-card.json`拿到智能体卡片以后(一个卡片上有各类的信息),之后通过 a2aClient 创建客户端,在通过 RemoteA2AAgent 完成本地智能体的转换。 + +##### 4.2.2 使用端 + +```java +public final class A2AAgentRun { + private final String userId; + private final String sessionId; + private final Runner runner; + + public A2AAgentRun(BaseAgent agent) { + this.userId = "test_user"; + String appName = "A2AAgentApp"; + this.sessionId = UUID.randomUUID().toString(); + + InMemoryArtifactService artifactService = new InMemoryArtifactService(); + InMemorySessionService sessionService = new InMemorySessionService(); + this.runner = + new Runner(agent, appName, artifactService, sessionService, /* memoryService= */ null); + + ConcurrentMap initialState = new ConcurrentHashMap<>(); + var unused = + sessionService.createSession(appName, userId, initialState, sessionId).blockingGet(); + } + + // ... 省略部分 + + public static void main(String[] args) throws InterruptedException { + BaseAgent agent = A2AAgent.createRootAgent("http://localhost:9090"); + A2AAgentRun a2aRun = new A2AAgentRun(agent); + + List events = + a2aRun.run("掷一个6面的骰子。").toList().timeout(90, TimeUnit.SECONDS).blockingGet(); + + events.forEach(A2AAgentRun::printOutEvent); + + events = + a2aRun.run("这是素数吗?").toList().timeout(90, TimeUnit.SECONDS).blockingGet(); + + events.forEach(A2AAgentRun::printOutEvent); + } + +} +``` + +- A2AAgentRun 测试入口,连接远程的智能体,之后做相关的调用验证。 + +## 三、测试验证 + +### 1. 前置准备 + +1. IntelliJ IDEA 右侧的 maven 点击执行 clean -> install 构建 +2. 通过命令启动服务,`mvn quarkus:dev -pl xfg-dev-tech-app` + +### 2. 访问服务 + +#### 2.1 服务首页 + +
+ +
+ +- 地址:[http://localhost:9090/q/dev-ui/welcome](http://localhost:9090/q/dev-ui/welcome) +- 说明:访问首页,localhost:9090 会看到上面的地址信息,这个是 a2a 协议的入口。 + +#### 2.2 服务协议 + +
+ +
+ +- 地址:[http://localhost:9090/.well-known/agent-card.json](http://localhost:9090/.well-known/agent-card.json) +- 说明:点击 agent-card.json 可以看到具体的服务协议信息。 + +### 3. 调用验证 + +
+ +
+ +- 点击运行,你可以看到它在进行多个智能体的调用(可能模型原因不准,但核心点在于多个智能体的调用)。 +- 好啦,到这关于 A2A 整个内容就演示完了,可以时刻关注 google adk a2a 协议的迭代,这部分内容后续还会有一些调整。 + diff --git a/docs/md/ai/agent-skill.md b/docs/md/ai/agent-skill.md new file mode 100644 index 000000000..123e16dd1 --- /dev/null +++ b/docs/md/ai/agent-skill.md @@ -0,0 +1,226 @@ +--- +title: agent-skills +lock: need +--- + +# Agent Skill,你记一下,我做如下部署调整! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +skill 是什么?它像是一本技能书📚,把一阳指(`mcp/py/shell/js`)和狮吼功(`prompt`)合成了一整招。缩短了从用户把提示词发给AI客户端,进行分析,决策,再到 mcp 执行的过程,**让诉求直达结果**,token 减少了,幻觉减少了! + +
+ +
+ +随着 LLM 大模型能力的不断提升,并与 RAG、MCP、Skill 的结合,使得 Agent 智能体与完整的计算机环境(Computer/Phone)交互成为可能。这个过程中,一方面不断产生新的技术方案,一方面又不断的优化设计。就像 Skill 的出现,它不是替代 MCP,而是更准确的使用 MCP 能力。 + +接下来,小傅哥就带着大家使用一波 skill,让小伙伴们可以在 opencode、trae.ai,以及基于 Spring AI 也可以使用上 skill 能力。 + +## 一、skill 和 prompt + mcp + +如图,演示了一段 skill 的编写案例; + +
+ +
+ +- 场景:案例中体现的是,对电脑性能检测后,用一段下达命令的方式,告知用户如何优化电脑性能。 +- 重点:如果不使用 skill,则需要描述一大段话术,让 ai 自己完成对用户场景诉求的分析,并按照步骤来调用对应的各个 mcp 服务(没有 skill 则需要把各类内容,都包装为 mcp 服务)。这个过程是比较消耗 token 的,也可能有不小的幻觉。现在有了 skill,我们可以适当的完整的写一段诉求文档,文档里嵌入可执行的脚本/mcp服务,让执行更可靠。 +- 用途:那都有哪些场景可以写 skill 技能书呢?🤔 如;互联网公司里的系统巡检,在接收到报警日志后,拿到一个报警的系统和接口信息,之后用 skill 技能书,分别采集出对应的系统配置、上线日志、数据库/缓存情况、运营操作记录、全链路监控上的接口耗时情况等。之后在根据我们日常排查问题的时候经验,编写过程步骤,这样会更加准确。 + +> 所以,不是 skill、mcp 谁替代谁,而是 skill 对 mcp 进行增强,让 ai 执行时更加可靠。 + +## 二、配置使用 + +首先,像是市面上的 claude code、opencode 这些软件,都是支持了 skill 技能书配置使用的,如果遇到一些软件暂时还不支持 skill,或者自己使用 spring ai、langchain4j、google adk 构建的智能体时候需要使用 skil 技能,则可以通过 skillport-mcp 来使用 skill 配置。 + +这里小傅哥分别演示下 opencode、trae.ai + mcp、spring ai + google adk + mcp 的方式使用 skill; + +### 1. 测试工程(skill) + +
+ +
+ +- 地址:[https://github.com/fuzhengwei/xfg-dev-tech-agent-skills](https://github.com/fuzhengwei/xfg-dev-tech-agent-skills) +- 说明: + - 工程里 `docs/skills` 下面就是一个个技能书,battle-plan、pdf,每一个技能书下都必须有一个 SKILL.md 文件,作为入口。这个文件,可以描述 prompt 提示词,以及在提示词中明确给出可执行的脚本(py\shell\js)和可参考的文档。 + - 此外,在 xfg-dev-tech-app 下,test 里编码的是 SpringAiToolTest 测试技能书案例。 + +### 2. opencode 使用 + +- 文档:[https://opencode.ai/docs/skills/](https://opencode.ai/docs/skills/) +- 安装:[https://bugstack.cn/md/road-map/ai-ssh-opencode.html](https://bugstack.cn/md/road-map/ai-ssh-opencode.html) - `做好了安装脚本,方便小白伙伴使用` + +#### 2.1 配置skill + +```java +fuzhengwei@fuzhengweideMacBook-Pro-2 skill % ls +battle-plan +fuzhengwei@fuzhengweideMacBook-Pro-2 skill % pwd +/Users/fuzhengwei/.opencode/skill +fuzhengwei@fuzhengweideMacBook-Pro-2 skill % cd battle-plan +fuzhengwei@fuzhengweideMacBook-Pro-2 battle-plan % ls +reference.md scripts SKILL.md +fuzhengwei@fuzhengweideMacBook-Pro-2 battle-plan % +``` + +进入到 opencode 配置文件下,如果是 linux 一般会放到 `/root/.config/opencode/` 下。首先你要进入到这个 opencode 配置文件夹,之后在这个文件夹添加一个 skill,再之后就在 skill 下创建你的具体的技能书了。现在你可以把 xfg-dev-tech-agent-skills 案例工程的技能书,battle-plan 放到 skill 里。 + +#### 2.2 开启skill + +```java +fuzhengwei@fuzhengweideMacBook-Pro-2 ~ % cd /Users/fuzhengwei/.opencode +fuzhengwei@fuzhengweideMacBook-Pro-2 .opencode % ls +bin node_modules package.json +bun.lock opencode.json skill +fuzhengwei@fuzhengweideMacBook-Pro-2 .opencode % cat opencode.json +{ + "permission": { + "skill": { + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask", + "*": "allow" + } + }, + "$schema": "https://opencode.ai/config.json" +}% fuzhengwei@fuzhengweideMacBook-Pro-2 .opencode % +``` + +- 注意 `opencode.json` 需要配置下 `"*": "allow"` + +#### 2.3 使用skill + +
+ +
+ +- 提问:`基于 skill 解答,电脑性能优化` +- 说明:这里的`电脑性能优化`就是 skill 工具名称的描述。 + +### 3. trae.ai + mcp + skill + +#### 3.1 工具说明 + +工具:[https://github.com/gotalab/skillport](https://github.com/gotalab/skillport) + +目前还有不少 AI Agent 智能体,在底层设计上,还不支持直接使用 skill,也包括一些 ai 组件框架,也都没有 skill 的直接支持。那么这里要引入一个 skillport-mcp 服务来解决。借助 mcp 能力,使用 skill。 + +#### 3.2 工具安装 + +```java +# 需要安装 python3 +pip3 config set global.index-url http://mirrors.aliyun.com/pypi/simple/ +pip3 install uvx +``` + +- 安装 skillport 前,要确保本地安装了 pyhton/python3 环境。之后有 uvx 的安装。 + +```java +pip3 install skillport +# or: uv tool install skillport +``` + +- 如果安装过程中遇到一些失败的问题,可以用 trae.ai 里面执行安装,之后把报错拖进去提问。 + +#### 3.3 mcp 配置 + +
+ +
+ +```java +{ + "mcpServers": { + "skillport": { + "command": "uvx", + "args": ["skillport-mcp"], + "env": { "SKILLPORT_SKILLS_DIR": "~/.skillport/skills" } + } + } +} +``` + +- 这里你要配置下自己 skill mcp 服务,到你的 trae.ai 中。确保一定安装好了 python 环境,可以执行 `pip3 install skillport` 安装。 + +#### 3.4 工具使用 + +
+ +
+ +当你选择 Builder with MCP(涵盖了skillport-mcp),之后提问 `基于 skill 解答,电脑性能优化` 那么就可以得到上面的命令了。 + +### 4. spring ai + skill + +```java +public class SpringAiToolTest { + + private static final Logger log = LoggerFactory.getLogger(SpringAiToolTest.class); + + public static void main(String[] args) { + OpenAiApi openAiApi = OpenAiApi.builder() + .baseUrl("https://apis.itedus.cn") + .apiKey("sk-efen7WX8Q8vGvBps3f7c9a34578d41BbBc508dC5Df33A9Fb") + .completionsPath("v1/chat/completions") + .embeddingsPath("v1/embeddings") + .build(); + + ChatModel chatModel = OpenAiChatModel.builder() + .openAiApi(openAiApi) + .defaultOptions(OpenAiChatOptions.builder() + .model("gpt-4.1") + .toolCallbacks(new ArrayList<>() {{ + addAll(List.of(sseMcpClient())); + }}) + .build()) + .build(); + +// String call = chatModel.call("你哪有哪些 skill 工具能力"); + String call = chatModel.call("基于 skill 解答,电脑性能优化"); + + log.info("测试结果:{}", call); + + } + + /** + * https://github.com/gotalab/skillport + * pip3 config set global.index-url http://mirrors.aliyun.com/pypi/simple/ + * pip3 config set install.trusted-host mirrors.aliyun.com + * pip3 config list + * pip3 install uvx + */ + public static ToolCallback[] sseMcpClient() { + ServerParameters stdioParams = ServerParameters.builder("uvx") + .args("skillport-mcp") + .env(new HashMap<>() {{ + put("SKILLPORT_SKILLS_DIR", "/Users/fuzhengwei/coding/gitcode/KnowledgePlanet/road-map/xfg-dev-tech-agent-skills/docs/skills"); + }}) + .build(); + + McpSyncClient mcpSyncClient = McpClient.sync(new StdioClientTransport(stdioParams, new JacksonMcpJsonMapper(new ObjectMapper()))) + .requestTimeout(Duration.ofSeconds(35000)).build(); + + McpSchema.InitializeResult initialize = mcpSyncClient.initialize(); + + return SyncMcpToolCallbackProvider.builder().mcpClients(mcpSyncClient).build() + .getToolCallbacks(); + } + +} +``` + +- 在 Spring AI 程序中,添加 `skillport-mcp` 服务,之后在 ChatModel 模型里,使用 mcp 服务。 +- 如果你正在开发一些 AI Agent,那么也可以把 `skillport-mcp` 配置进去使用。如小傅哥带着做 [AI Agent 智能体项目](https://bugstack.cn/md/project/ai-knowledge/ai-knowledge.html) 你现在可以加进去更多的扩展操作了。 + + + diff --git a/docs/md/ai/ai-ssh-opencode.md b/docs/md/ai/ai-ssh-opencode.md new file mode 100644 index 000000000..d7c22695a --- /dev/null +++ b/docs/md/ai/ai-ssh-opencode.md @@ -0,0 +1,229 @@ +--- +title: ai ssh opencode +lock: need +--- + +# ai ssh opencode 命令行工具 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获! + + + +大家好,我是技术UP主小傅哥。 + +天才般的发明,**ai ssh 命令行工具**,让 ai 的使用不只局限在 `ai 对话提问`、`ai idea 辅助编码`,也可以直接让操作系统具备 ai 能力。其实这才是我一直想要的东西!😄 + +
+ +
+ +**ai 正在改变产品设计!** + +2025年,是 ai agent 智能体爆发的一年,它所提效的接入方式可以分三层来看; + +先是中间这一层,是 ai agent 接入服务和软件,像是大家使用的 trae.ai 或者小傅哥分享过的 [draw.io + ai](https://bugstack.cn/md/road-map/draw.io.html),以及各个互联网公司用 ai 提效做的一些场景客服,系统巡检,日志分析等。 + +之后上面这一层,是从用户视角,模拟用户行为使用软件,而不是直接接入到软件api上。它使用的方式是 AutoGLM-Phone-9B 手机模型,以 ADB 或者无障碍模式,让手机可以接收用户指令,完成操作。如;`打开京东,搜索东北老式麻辣烫,加入购物车,以默认地址,进行支付购买。下单支付完成后,微信发给xxx告诉,她预计送达时间。` 如果感兴趣,可以基于这篇文章进行实践。[《手机 + agent,这是要掀桌子!》](https://bugstack.cn/md/algorithm/model/autoglm-phone-agent.html) + +然后底下这一层,是从系统层面,不再依赖于直接对接某个软件,某个api,而是以系统层面直接操作软件,或者完成整个行为动作。如,在云服务器/本地,配置好 jdk、maven、docker 环境,之后帮我拉取 git clone xxx 仓库代码,本地完成 maven 构建和启动。以及在遇到问题时候,让 ai 直接检索并处理都是非常可以的。 + +好,那接下来,小傅哥给大家分享下,如何安装一个 ai ssh 工具(没有这个教程,很多人是安装不上的!)。 + +>🧧 文末提供了小傅哥所有编程实战项目获取方式,一次加入即可获得19个已完结的实战项目,也有非常多的 AI 类项目,一定要补充学习! + +## 一、工具介绍 + +ai ssh 是命令行工具,可以安装到 Mac、Windows、Linux 上,以通过 terminal(终端)直接操作系统进行使用。它的场景也包括你打开的 IntelliJ IDEA 下面的 terminal 终端中使用,这样就天然的嵌入到了 IntelliJ IDEA 中了,非常方便。 + +目前这类的 ai ssh 命令行工具软件也非常多,包括;[opencode.ai](https://opencode.ai/)、[claude](https://claude.com/product/claude-code)、[openai codex](https://github.com/openai/codex)、[阿里千问 - qianwen code](https://github.com/QwenLM/qwen-code),都出了对应的软件。 + +在整体体验后,效果还是都不错的,这里是 opencode 的终端使用截图; + +
+ +
+ +- opencode 默认提供了一些免费模型,可以输入 `/models` 进行选择。 +- 另外还可以通过配置文件,添加其他模型,如 claude 模型、openai 模型、小米模型等。 + +## 二、软件安装 + +以下软件安装,会需要用到 gcc、nodejs 20+ 版本,建议安装 Ubuntu 24 版本,可以不需要折腾系统环境。 + +### 1. 脚本说明 + +这软件好用是挺好用,但它的源都在 Github 上,很多伙伴在执行官网脚本 `curl -fsSL https://opencode.ai/install | bash` 是安装不上的。所以,小傅哥做了一个对应的脚本,方便大家更加简化的安装使用。 + +
+ +
+ +- 脚本(gitcode):[https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install](https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install) +- 脚本(github):[https://github.com/fuzhengwei/xfg-dev-tech-docker-install](https://github.com/fuzhengwei/xfg-dev-tech-docker-install) + +### 2. 脚本下载 + +```java +git clone https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install.git +``` + +- 你可以通过命令的方式把脚本拉取到本地电脑或者云服务器上。 + +### 3. 脚本授权 + +```java +find . -name "*.sh" -type f -exec chmod +x {} \; +``` + +- 全部授权 + +```java +chmod +x terminal.sh +``` + +- 指定授权 + +### 4. 执行安装 + +
+ +
+ +```java +./terminal.sh +``` + +- 执行安装时,选择1,opencode code,这个是比较推荐的。 +- 无论是 Windows、Mac、Linux 都可以使用这个脚本进行安装,我已经做好了对应的脚本。 +- 安装完成后,需要输入 `opencode` 之后 Enter(回车)进入到系统中。如果提示 opencode 不是有效的命令,可以检查是否安装过程中有个提示 `source .../bashrc` 可以自行执行刷新。 + +## 三、软件配置 + +### 1. 命令使用 + +
+ +
+ +
+ +
+ +- `/init` - 创建/更新 Agents.md" +- `/review` - 检查变化" +- `/new` - 创建新的会话" +- `/models` - 选择模型" +- `/agents` - 智能体方式" +- `/session` - 会话列表" +- `/status` - 查看状态" +- `/mcp` - 选择mcp服务" +- `/theme` - 选择主题" +- `/editor` - 编辑" +- `/connect` - 链接模型提供者" +- `/help` - 帮助" +- `/commands` - 命令" +- `/exit` - 调试模式" + +> 这些可能会随着版本更新而调整,你可以依次尝试下。 + +### 2. 配置模型(自定义 - 可选) + +
+ +
+ +
+ +
+ +```java +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "my-model-openai": { + "npm": "@ai-sdk/openai-compatible", + "name": "OpenAPI", + "options": { + "apiKey": "你的apikey", + "baseURL": "https://你的baseURL/v1" + }, + "models": { + "gpt-4.1": { + "name": "gpt-4.1" + } + } + }, + "my-model-glm": { + "npm": "@ai-sdk/openai-compatible", + "name": "GLMAPI", + "options": { + "apiKey": "你的apikey", + "baseURL": "https://open.bigmodel.cn/api/paas/v4" + }, + "models": { + "glm-4.7": { + "name": "glm-4.7" + } + } + } + }, + "model": "my-model-openai/gpt-4.1" +} +``` + +- 如果你想自己更换下模型,比如使用 openai 的或则 claude 的,那么需要你在脚本下的 terminal/opencode.json 进行更换,之后执行 `./opencode.json.sh` 进行创建。 +- 如果先执行了 ``./opencode.json.sh`` 之后想更换配置的模型,则可以通过 vim 命令,编辑 `/root/.config/opencode/opencode.json` +- 其他的还有一些像是 mcp 的配置,可以参考官网(避免调整了配置错),[https://opencode.ai/docs/mcp-servers/](https://opencode.ai/docs/mcp-servers/) + + +## 三、软件使用 + +### 1. Linux + +#### 1.1 构建项目 + +
+ +
+ +#### 1.2 安装软件 + +
+ +
+ +#### 1.3 巡检系统 + +
+ +
+ +#### 1.4 编写文件 + +
+ +
+ +>通过命令操作云服务器是非常便捷的,尤其是很多小白伙伴,有了这个可以说是如小白虎添翼!打开思路,你可以在更多地方使用上,尤其哪些环境安装都困难的伙伴。 + +### 2. Mac/Windows + IntelliJ IDEA + +
+ +
+ +- 在本地电脑,除了可以像 Linux 举例那种安装和检查各类软件,也可以直接在 IntelliJ IDEA 开启,之后管理你的项目。 +- 尤其是很多伙伴,拿到一个项目,不知道里面都是什么,也不清楚脚本能干啥,那你都可以使用 opencode 帮你解决。 + +### 3. IPad Pro + +
+ +
+ +虽然 IPad Pro 没啥开发类软件,但如果你使用的是云服务器、Nas等,这些软件里安装 opencode,那么你也可以在 IPad Pro 安装 [termius.com](https://termius.com/) SSH 工具,通过 SSH 工具操作部署了 opencode 的 Linux 系统。 + +现在日常出门,带着 IPad Pro 也是可以处理一些小的开发的维护的,非常方便。IPad Pro + Nas 嘎嘎舒服! diff --git a/docs/md/ai/draw.io.md b/docs/md/ai/draw.io.md new file mode 100644 index 000000000..4ffdac94a --- /dev/null +++ b/docs/md/ai/draw.io.md @@ -0,0 +1,140 @@ +--- +title: draw.io + ai agent +lock: need +--- + +# draw.io + ai Agent,确实打开新思路 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获! + + + +大家好,我是技术UP主小傅哥。 + +又到年底了,又要必不可少的开始画图做PPT述职啦 😂,述职的好坏和年终奖都有可能挂钩!这对天天写代码大部分的程序员👨🏻‍💻来说是一件非常头疼的事,但好在这次可以使用个**神器**! + +
+ +
+ +**Ai Agent 会结合到各个场景!** + +可以想象,将来我们使用的各种工具,都会很方便的以标准的协议方式结合到 AI Agent 智能体。这就像小傅哥,25年,年初开始做 Ai Agent 时,对一个智能体的执行过程,是需要自己进行分析,设计,实现的(`那时候我就在讲,Agent 也会出标准框架`)。到了年中的时候 Google ADK 除了 0.1.0 最初的版本,年尾发布了 0.4.0,这个框架提供了构建智能体的最基本框架,可以整合 Spring AI、Langchain4j 快速构建智能体。 + +>Spring AI、Langchain4j 提供的是 AI 封装能力,Google ADK 提供的是 Agent 执行能力(并行、循环、串行)的组装和使用。 + +未来(甚至不会太久),各个软件与 Ai Agent 的对接会变得非常容易,你手里用到的各项软件,都可以很方便的添加上智能体的能力。就像,我们现在用到的 `trae.ai`、`Cursor`,在以后 Ai Agent 基础能力成熟后,在结合 `Visual Studio Code` 给出软件对接标准协议,那么任何一个人都可以快速的搭建出一个智能体编码工具。除此之外,其他的软件也都会逐步提供出这样的能力。 + +扩展的思路分析完毕,小傅哥这次先带着大家了解下,draw.io 是怎么与 Ai 结合使用的。 + +>🧧 文末提供了小傅哥所有编程实战项目获取方式,一次加入即可获得19个已完结的和本次新开展的。 + +## 一、关于 draw.io + +draw.io 是一个用于绘制通用图表的 JavaScript 客户端编辑器。 + +官网:[https://www.drawio.com/](https://www.drawio.com/) +代码:[https://github.com/jgraph/drawio](https://github.com/jgraph/drawio) + +
+ +
+ +我所有的这类的绘图,都来自于使用 draw.io 完成([bugstack.cn](https://bugstack.cn) 还有很多绘图)。它可以下载到本地使用,也可以在网页使用。如果你是开发人员,还可以使用它的开发组件引入到自己的程序中进行使用。也正因如此,有了 Ai Agent 能力的结合,一种是通过 MCP,另外一种是直接通过扩展功能,直接在 draw.io 二开上完成。接下来小傅哥会分别介绍这两种方式以及使用。 + +## 二、MCP 方式对接 + +MCP(Model Context Protocol)是用于解决 AI 与服务接口通信的标准模型上下文协议,该协议通过标准化通信方式,使AI应用程序能够访问和使用实时数据、执行操作,从而克服了模型训练数据的局限性。 你可以将MCP想象成AI应用程序的“USB-C接口”,它提供了一个标准化的方法,让AI模型能够连接各种外部资源。 + +**Draw.io Model Context Protocol (MCP) Server**,就是基于此协议实现的对接 Draw.io 的 MCP 服务。我们可以使用这样一套服务,把 AI 与 Draw.io 建立起使用链接。 + +源码:[https://github.com/lgazo/drawio-mcp-server](https://github.com/lgazo/drawio-mcp-server) + +### 1. 插件安装 + +- 谷歌浏览器:[https://chromewebstore.google.com/detail/drawio-mcp-extension/okdbbjbbccdhhfaefmcmekalmmdjjide](https://chromewebstore.google.com/detail/drawio-mcp-extension/okdbbjbbccdhhfaefmcmekalmmdjjide) +- 火狐浏览器:[https://addons.mozilla.org/en-US/firefox/addon/drawio-mcp-extension/](https://addons.mozilla.org/en-US/firefox/addon/drawio-mcp-extension/) + +
+ +
+ +安装完成后,可以看到这样一个小插件(右侧插件文件里可以点击让常驻浏览器),之后后面可以等着使用(继续下面的步骤)。 + +### 2. 配置服务 + +```java +{ + "mcpServers": { + "drawio": { + "command": "npx", + "args": [ + "-y", + "drawio-mcp-server" + ] + } + } +} +``` + +#### 2.1 trae.ai - 也可以其他的 + +
+ +
+ +#### 2.2 spring ai + +
+ +
+ +### 3. 使用服务 + +首先打开:[https://app.diagrams.net/#](https://app.diagrams.net/) + +
+ +
+ +- 对接上之后,你就可以在右侧提问了。之后他就可以实时的出设计图。`受限于MCP服务对接,它不是在 Draw.io 上扩展,会缺少一些交互和判断,画图有时候会有重叠。` +- 不过,这个方式的好处是,你可以结合自己的代码,拖进去,让它直接出架构图、流程图、模型图等。之后在自己做一些调整。 + +## 三、软件方式使用 + +现在 Github 上有很多基于 Draw.io 的二次开发,结合了 Ai 的能力,这里小傅哥找到一个做这块功能比较早的,next-ai-draw-io 来演示给大家。感兴趣的伙伴,还可以结合代码做二次开发。 + +这是一个基于 Next.js 的 Web 应用程序,它将 AI 功能与 draw.io 图表集成在一起。该应用程序允许您通过自然语言命令和 AI 辅助可视化来创建、修改和增强图表。 + +### 1. 代码下载 + +代码:[https://github.com/DayuanJiang/next-ai-draw-io](https://github.com/DayuanJiang/next-ai-draw-io) + +```java +git clone https://github.com/DayuanJiang/next-ai-draw-io.git +``` + +
+ +
+ +下载代码后,注意修改配置文件。 + +### 2. 启动工程 + +
+ +
+ +- 进入 package.json 点击绿色箭头执行启动。 + +### 3. 访问项目 + +
+ +
+ +- 访问 http://localhost:6002 这样你就可以提问来让它绘制图了。这个效果还不错。 \ No newline at end of file diff --git a/docs/md/ai/github-models.md b/docs/md/ai/github-models.md new file mode 100644 index 000000000..08fbfcac4 --- /dev/null +++ b/docs/md/ai/github-models.md @@ -0,0 +1,212 @@ +--- +title: Github Models +lock: need +--- + +# Github Models(AI接口),申请使用教程 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +现在做 AI 应用开发的小伙伴越来越多了,随之而来的是对 LLM 大模型接口的使用依赖。一般的模型,可能会让程序出现幻觉。而高质量的模型,大部分是需要付费,比如 `openai/gpt-5`、`azureml-xai/grok3`、`azureml/Phi-4` 等。**那怎么办!?🤔** + +
+ +
+ +这些免费的不错的大模型(LLM),也都是有对应的频次和最大出入/输出token的限制。虽然不会让咱们玩命的调用测试。但在程序开发初期,对于单个功能的验证还是非常方便的。接下来,小傅哥就给大家演示下,关于 Github 免费提供的大模型如何配置使用。 + +## 一、模型说明 + +### 1. 官网地址 + +官网:[https://github.com/marketplace?type=models](https://github.com/marketplace?type=models) + +
+ +
+ +在 Github marketplace 下提供了非常多的免费的 LLM 使用,gpt-5、gpt-4.1 都是有的,具备完整的测试功能。有时候还会新增加其他模型。 + +### 2. 频次限制 + +地址:[https://docs.github.com/en/github-models/use-github-models/prototyping-with-ai-models#rate-limits](https://docs.github.com/en/github-models/use-github-models/prototyping-with-ai-models#rate-limits) + +
+ +
+ +- 每日150次、每分钟15次,每次token,8000进、4000出。对于单个模型的验证是没问题的,不过对于复杂的 ai agent 智能体是跑不动的。所以,这块测试的话,要分开验证。之后对于全流程的,在购买 api 进行测试即可。 +- 如果小伙伴还觉得,每分钟15次,有点不够干的,那你可以弄10个账号,通过 nginx 负载下,这样基本每分钟150次,一天1500次还是很够用的。 + +## 二、模型使用 + +### 1. 测试工程 + +
+ +
+ +- 地址:[https://github.com/fuzhengwei/xfg-dev-tech-github-models](https://github.com/fuzhengwei/xfg-dev-tech-github-models) +- 说明:这里小傅哥准备了一套基于 Spring AI 的测试工程,来验证 Github LLM 的使用。你可以下载后,替换 token/apikey 即可调用验证。 +- 环境:jdk 17、maven 3.8.x、spring ai 1.1.0 + +### 2. 对接申请 + +#### 2.1 申请token + +地址:https://github.com/settings/tokens/new + +
+ +
+ +- 在 Tokens 下,添加 Note 描述和过期时间,完事后不用加任何其他权限,拉到最后设置点击 `Generate token` 生成令牌即可。 +- 生成后复制你的 Token,复制后关闭就看不见了。只有删除和创建新的。 + +#### 2.2 查看curl(api) + +地址:[https://github.com/marketplace/models/azure-openai/gpt-4-1/playground](https://github.com/marketplace/models/azure-openai/gpt-4-1/playground) + +
+ +
+ +在左侧你可以选择需要使用的模型,之后进行对话验证。之后,在右侧有一个 `Use this model` 这里可以获得模型 API 请求信息。 + +
+ +
+ +你现在单独验证 api,在整个程序测试前,要确保你的 api 是可用的。 + +### 3. 测试验证 + +```java +public class ApiTest { + + public static void main(String[] args) throws Exception { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Resource resource = new ClassPathResource("dog.png", classLoader); + + OpenAiApi openAiApi = OpenAiApi.builder() + .baseUrl("https://models.github.ai/inference") + // apikey 要替换为你的,在 https://github.com/settings/tokens 创建即可。 + .apiKey("ghp_FfiwBkVunYDQyhIwaQSccVw******") + .completionsPath("/chat/completions") + .embeddingsPath("/embeddings") + .build(); + + ChatModel chatModel = OpenAiChatModel.builder() + .openAiApi(openAiApi) + .defaultOptions(OpenAiChatOptions.builder() + .model("openai/gpt-4.1") + .build()) + .build(); + + // 模型测试,没问题可以识别图片 + ChatResponse response = chatModel.call(new Prompt( + UserMessage.builder() + .text("请描述这张图片的主要内容,并说明图中物品的可能用途。") + .media(Media.builder() + .mimeType(MimeType.valueOf(MimeTypeUtils.IMAGE_PNG_VALUE)) + .data(resource) + .build()) + .build())); + + System.out.println("测试结果" + JSON.toJSONString(response)); + + } + +} +``` + +```java +测试结果{"metadata":{"empty":false,"id":"chatcmpl-CzHhVYaXPv3HjJ3oKE4YKPamPQRQB","model":"gpt-4.1-2025-04-14","rateLimit":{"requestsLimit":1000,"requestsRemaining":996,"tokensLimit":1000000,"tokensRemaining":980423},"usage":{"completionTokens":0,"nativeUsage":{},"promptTokens":0,"totalTokens":0}},"result":{"metadata":{"contentFilters":[],"empty":true,"finishReason":"STOP"},"output":{"media":[],"messageType":"ASSISTANT","metadata":{"role":"ASSISTANT","messageType":"ASSISTANT","finishReason":"STOP","refusal":"","index":0,"annotations":[{"$ref":"$.metadata.rateLimit.usage.nativeUsage"}],"id":"chatcmpl-CzHhVYaXPv3HjJ3oKE4YKPamPQRQB"},"text":"这张图片的主要内容是一只卡通风格的小狗。小狗是棕色的,脸部较大,眼睛圆而突出,表情看起来有些疑惑或惊讶,嘴巴微微张开,尾巴翘起。整个形象简洁可爱,线条和颜色运用都比较简单。\n\n**物品的可能用途:**\n1. **图标或表情包**:这种卡通形象常用于聊天软件中的表情包或头像,传达惊讶、困惑等情感。\n2. **儿童绘本或动画角色**:可以作为儿童图书或动画中的形象角色,吸引小朋友的注意力。\n3. **宠物相关宣传设计**:可用于宠物店、宠物产品的宣传海报、包装或logo,增加亲和力。\n4. **教育材料**:在教学课件或教育类APP中,用于引导、示范或者增加趣味性。\n\n整体而言,这是一种很常见且可爱的卡通动物形象,主要用于与宠物、儿童或者情感表达相关的领域。","toolCalls":[]}},"results":[{"$ref":"$.metadata.rateLimit.usage.nativeUsage.result"}]} +``` + +- 这是一段基于 Spring AI 配置 github llm api的使用方式,尤其注意,baseUrl、apiKey、completionsPath、embeddingsPath、openai/gpt-4.1,这些配置信息和你直接使用管的 gpt 配置是有差异的。 +- 本案例,是识别图片的用途,你也可以验证其他功能。这样的项目在小傅哥的 [《AI Agent 智能体》](https://bugstack.cn/md/project/ai-knowledge/ai-knowledge.html) 都有讲解。 + +## 三、使用拓展 + +### 1. 部署脚本 + +
+ +
+ +- 这是一套 nginx 转发脚本。你需要有自己的域名(各个云服务器厂商都可以购买)以及申请 ssl 后才可以配置使用。 +- ssl 可以从 [httpok](https://bugstack.cn/md/road-map/ssl-httpsok.html) 申请使用。地址:[https://bugstack.cn/md/road-map/ssl-httpsok.html](https://bugstack.cn/md/road-map/ssl-httpsok.html) + +### 2. 转发说明(nginx) + +如果你希望在使用的过程中,让模型是以你之前使用 openai 一样的方式,那么可以配置一套 Nginx 转发; + +```java +server { + listen 80; + listen [::]:80; + server_name 需要配置域名(api.xxx.cn); + + rewrite ^(.*) https://$server_name$1 permanent; + +} + +server { + listen 443 ssl; + server_name 需要配置域名(api.xxx.cn); + + ssl_certificate /etc/nginx/ssl/_.itedus.cn.pem; + ssl_certificate_key /etc/nginx/ssl/_.itedus.cn.key; + + ssl_session_cache shared:SSL:1m; + ssl_session_timeout 5m; + + ssl_ciphers HIGH:!aNULL:!MD5; + ssl_prefer_server_ciphers on; + + location / { + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + root /usr/share/nginx/html; + index index.html index.htm; + } + + location /v1/ { + # 去掉路径中的/v1前缀 + rewrite ^/v1/(.*) /$1 break; + proxy_pass https://models.inference.ai.azure.com; + proxy_http_version 1.1; + chunked_transfer_encoding off; + proxy_buffering off; + proxy_cache off; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} +``` + +- nginx 的方式是,当访问有 v1/ 路径的时候,在进行路径重写 `rewrite ^/v1/(.*) /$1 break;` 之后转发到 `https://models.inference.ai.azure.com` - `这个也是 gpt 里的一种模型对接地址` +- 转发后,你就可以直接使用模型服务了。 + +### 3. curl 验证 + +
+ +
+ +- 配置转发后,就可以使用 curl_nginx.sh 脚本进行验证了。 + +好啦,本文到这,你就可以初步使用免费的 LLM 进行一些一些初始功能验证。2025年,ai agent 开始崛起,2026年,必然是 ai agent 爆发的时候。一定要多学习这类实战项目,企业里 spring 是大盘,所以结合 spring ai 做的项目也必然会非常多。 + diff --git a/docs/md/ai/google-adk.md b/docs/md/ai/google-adk.md new file mode 100644 index 000000000..805cf6e95 --- /dev/null +++ b/docs/md/ai/google-adk.md @@ -0,0 +1,344 @@ +--- +title: google adk +lock: need +--- + +# Google Agent ADK,20分钟,帮你搭建一个简单智能体 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +💐 从22年至今,小傅哥已经带着大家做了5个AI类项目,包括;`(22年)问答助手`、`(23年)OpenAI应用(含支付、敏感词过滤)`、`(24年)AI 代码自动评审`、`(25年)Ai Agent 智能体`、`(25年)Ai MCP Gateway 网关`。 + +这些项目也都是结合这,AI 这一年最新的技术动向和应用方向,而做的设计和落地。所以,每次小傅哥都给大家讲了,接下来 AI 将影响的一些场景,也都陆续的发生了。就像,24年11月发布 MCP 协议后,我给大家说,所有互联网企业都将大量的落地 MCP 服务,并开始 Ai Agent 智能体实现(别看市面有 dify、扣子,各个且用还是要做自己的业务智能体)。 + +随后,25年年初,小傅哥就带着大家开始了 RAG、MCP、Ai Agent 智能体的开发,并告诉大家,以后 Ai Agent 智能体也会出标准的框架,让开发更加容易。这不,**谷歌的 ADK 就来了**。并且这哥们👬🏻还定义A2A协议。这会让不是那么大型的互联网公司,也会具备 Ai Agent 智能体开发的能力。 + +接下来的几年,所有的业务项目,都会以 Ai Agent 智能体翻一遍,程序员新增的岗位和工作量仍然会很多。因为在咱们这,你做的越快,你就得做的越多! + +>接下来,小傅哥就带着大家做一下 Google ADK 搭建 AI Agent。如果你感兴趣 AI 类项目,还可以在文末获取全部实战项目源码,深度积累此类技术内容。**文末有Google ADK 运行效果,交互式对话智能体,对 ELK 进行巡检分析。** + +## 一、官网资料 + +- 官网:[https://google.github.io/adk-docs/](https://google.github.io/adk-docs/) +- 搭建:[https://google.github.io/adk-docs/get-started/](https://google.github.io/adk-docs/get-started/) + +
+ +
+ +- ADK 以轻便化构建 Ai Agent 智能体,解决智能体开发的复杂流程而设计。目前支持 Python、Java、Go 3种语言对应的技术框架。 +- 整个文档完整的描述了,智能体的创建和运行、工具的调用(tools、function、mcp)、可观测性以及 A2A 协议等。 +- Agent Development Kit (ADK) is designed to empower developers to quickly build, manage, evaluate and deploy AI-powered agents. These quick start guides get you set up and running a simple agent in less than **20 minutes**. + +## 二、工程实践 + +### 1. 前置说明 + +本次的 Ai Agent 实践,是以 Google ADK 框架为基础,配和 Github [system-prompts-and-models-of-ai-tools](https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools) 开源提示词项目中的 claude-code-system-prompt 作为必要描述。来实验,ELK 系统日志智能分析场景。 + +- API Key:[https://ai.google.dev/gemini-api](https://ai.google.dev/gemini-api) 需要申请开发 API 秘钥,是免费的。 +- Docker 环境,本项目部署了一套 ELK 日志服务,基于 Docker 部署,之后对 ELK 模拟写入日志,让 Ai Agent 智能体进行分析。`如果暂时配置不了,可以在测试的时候去掉这部分 mcp 服务` +- `JDK 17+`、`Maven 3.8.x` + +### 2. 工程说明 + +
+ +
+ +- 工程地址:[https://github.com/fuzhengwei/xfg-dev-tech-google-adk](https://github.com/fuzhengwei/xfg-dev-tech-google-adk) +- 这是一套引入了 Google ADK 0.1.0 版本的 Agent 最基础智能体测试。如果需要扩展,还要额外增加很多东西,可以参考 [《Ai Agent 智能体项目》](https://bugstack.cn/md/project/ai-knowledge/ai-knowledge.html) + +#### 2.1 YML 配置 + +```java +server: + port: 8901 + +# 可申请API秘钥;https://ai.google.dev/gemini-api +google: + api: + base-url: https://generativelanguage.googleapis.com + key: AIzaSyDF6JnvFx7xWEsARS*******可以自己申请免费的 + cloud: + project: xfg-google-adk + +logging: + level: + root: info + config: classpath:logback-spring.xml +``` + +- 在 `application-dev.yml` 修改你的参数配置,配置你的 Google api key + +#### 2.2 ADK 单测 + +```java +import com.google.adk.agents.LlmAgent; +import com.google.adk.events.Event; +import com.google.adk.models.Gemini; +import com.google.adk.runner.InMemoryRunner; +import com.google.adk.sessions.Session; +import com.google.genai.Client; +import com.google.genai.types.Content; +import com.google.genai.types.HttpOptions; +import com.google.genai.types.Part; +import io.reactivex.rxjava3.core.Flowable; + +public class ApiTest { + + /** + * 可申请免费测试api + * https://ai.google.dev/gemini-api/docs/quickstart?hl=zh-cn#apps-script + */ + public static void main(String[] args) { + LlmAgent agent = LlmAgent.builder() + .name("test") + .description("test agent help user do work") + .model(Gemini.builder() + .apiClient(Client.builder() + .apiKey("AIzaSyDF6JnvFx7xWEsARSGosNmvTU3ZoCwo-mc") + .httpOptions(HttpOptions + .builder() + .baseUrl("https://generativelanguage.googleapis.com") + .timeout(500000) + .build()) + .build()) + .modelName("gemini-2.0-flash") + .build()) + .build(); + + InMemoryRunner runner = new InMemoryRunner(agent); + + Session session = runner + .sessionService() + .createSession("test", "xiaofuge") + .blockingGet(); + + Flowable events = runner.runAsync("xiaofuge", session.id(), Content.fromParts(Part.fromText("hi agent can you help me"))); + + System.out.print("\nAgent > "); + events.blockingForEach(event -> System.out.println(event.stringifyContent())); + + } + +} +``` + +```java +Agent > Hi there! Yes, I'm here to help. To best assist you, could you tell me what you need help with? The more information you give me, the better I can understand your request and provide a useful response. +``` + +- 这是一套最基础的 Ai Agent 智能体 ADK 的测试使用代码。其实它的配置和调用与 Spring AI 框架是有类似之处的,基本上这类框架也都是这样的使用模式。 +- LlmAgent 提供了一整套构建智能体的方式,可以设置客户端(Gemini),并设置相关的 baseUrl、apiKey 参数,以及模型和超时时间等。 +- InMemoryRunner 的用途是把 Agent 放入一个记忆执行里,让一整个 Session 会话下的执行都被记录下,这样才能记录上下文。 +- 之后就是放到响应框架进行之后和拿到最后结果啦。 + +#### 2.3 Agent 智能体测试 + +```java +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest +public class AutoAgentTest { + + @Value("${google.api.base-url}") + private String baseUrl; + + @Value("${google.api.key}") + private String apiKey; + + private static final String USER_ID = "xiaofuge"; + private static final String NAME = "multi_tool_agent"; + + public static BaseAgent agent; + + @Before + public void init() { + List mcpTools = new ArrayList<>(); + mcpTools.addAll(mcp_elk()); + mcpTools.addAll(mcp_filesystem()); + + agent = LlmAgent.builder() + .name(NAME) + .model(Gemini.builder() + .apiClient(Client.builder() + .apiKey(apiKey) + .httpOptions(HttpOptions + .builder() + .baseUrl(baseUrl) + .timeout(500000) + .build()) + .build()) + .modelName("gemini-2.0-flash") + .build()) + .description("You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.") + .instruction( + """ + You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user. + + 可以在这里复制全部提示词;https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools/blob/main/Claude%20Code/claude-code-system-prompt.txt + """) + .tools(mcpTools) + .build(); + } + + /** + * - 需要配置后,才能在单测控制台输入内容 + * IntelliJ IDEA Help -> Edit Custom VM Options -> -Deditable.java.test.console=true + *
+ * -
ai.google.dev/api + */ + @Test + public void test_agent() { + InMemoryRunner runner = new InMemoryRunner(agent); + + Session session = + runner + .sessionService() + .createSession(NAME, USER_ID) + .blockingGet(); + + try (Scanner scanner = new Scanner(System.in, StandardCharsets.UTF_8)) { + while (true) { + System.out.print("\nYou > "); + String userInput = scanner.nextLine(); + + if ("quit".equalsIgnoreCase(userInput)) { + break; + } + + Content userMsg = Content.fromParts(Part.fromText(userInput)); + Flowable events = runner.runAsync(USER_ID, session.id(), userMsg); + + System.out.print("\nAgent > "); + events.blockingForEach(event -> System.out.println(event.stringifyContent())); + } + } + + } + + private List mcp_elk() { + Map env = new HashMap<>(); + env.put("ES_HOST", "http://127.0.0.1:9200"); + env.put("ES_API_KEY", "none"); + + ServerParameters mcp_elk = ServerParameters.builder("npx") + .args(List.of( + "-y", + "@awesome-ai/elasticsearch-mcp" + )) + .env(env) + .build(); + + CompletableFuture futureResult = + McpToolset.fromServer(mcp_elk, JsonBaseModel.getMapper()); + + McpToolset.McpToolsAndToolsetResult result = futureResult.join(); + + return result.getTools(); + } + + private List mcp_filesystem() { + ServerParameters mcp_filesystem = ServerParameters.builder("npx") + .args(List.of( + "-y", + "@modelcontextprotocol/server-filesystem", + "/Users/fuzhengwei/Desktop" + )) + .build(); + + CompletableFuture futureResult = + McpToolset.fromServer(mcp_filesystem, JsonBaseModel.getMapper()); + + McpToolset.McpToolsAndToolsetResult result = futureResult.join(); + + return result.getTools(); + } + +} +``` + +- AutoAgentTest 智能体,配置了两个 mcp,mcp_elk、mcp_filesystem 服务。其实 AI Agent 智能体,都少不了 MCP 服务的加持,这样才能让这个大脑有手脚可以行动起来。 +- init 初始化阶段,instruction 配置了对应的智能体提示词,这部分很重要,有点像智能体的神经。[https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools/blob/main/Claude%20Code/claude-code-system-prompt.txt](https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools/blob/main/Claude%20Code/claude-code-system-prompt.txt) - 可以选择这里的提示词配置到智能体进行测试。 +- 这部分也可以运行测试,之后会你可以进行提问。注意,如果你没有配置 elk,那么可以删掉 `mcpTools.addAll(mcp_elk());` 代码。 +- mcp_filesystem() 配置了,`/Users/fuzhengwei/Desktop` 你需要修改为你的本地的有权限访问的地址。 + +#### 2.4 Agent 智能体服务 + +有了前面的案例测试基础,就可以把服务配置成对应的接口,以及开发个简单的页面进行对接验证了。 + +##### 2.4.1 服务接口 + +```java +@Slf4j +@RestController +@RequestMapping("/trigger") +@CrossOrigin(origins = "*") +public class AgentController { + + private final AgentService agentService; + + public AgentController(AgentService agentService) { + this.agentService = agentService; + } + + @PostMapping(path = "/session", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public CreateSessionResponse createSession(@RequestBody CreateSessionRequest req) { + String sessionId = agentService.createOrGetSession(req.getUserId()); + log.info("创建会话ID:{}", sessionId); + return new CreateSessionResponse(sessionId); + } + + @PostMapping(path = "/chat", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ChatResponse chat(@RequestBody ChatRequest req) { + String sessionId = req.getSessionId(); + if (sessionId == null || sessionId.isEmpty()) { + sessionId = agentService.createOrGetSession(req.getUserId()); + } + log.info("使用会话ID:{}", sessionId); + List outputs = agentService.chat(req.getUserId(), sessionId, req.getMessage()); + return new ChatResponse(sessionId, String.join("\n", outputs)); + } +} +``` + +- 这里就是把单测的服务,包装成接口。详细的部分可以直接看工程代码。 + +##### 2.4.2 页面对接 + +
+ +
+ +- 把服务端的接口对接到页面。 + +## 三、功能测试 + +### 1. 部署 elk 日志服务 + +
+ +
+ +- 整个 Ai Agent 案例,配置了 ELK 作为日志分析的基础,所以最好配置下。 +- 这里也有云服务器的部署操作,也可以参考教程来部署。教程:[https://bugstack.cn/md/road-map/docker-install.html](https://bugstack.cn/md/road-map/docker-install.html) +- 注意配置完成后,要执行 `elk-blacklist-data.sh` 模拟的写入进去一些日志,这样才能用于分析使用。 + +### 2. 启动服务访问页面 + +
+ +
+ +
+ +
+ +- 以上演示了,使用 Ai Agent 进行 ELK 日志分析,通过对话可以看到,最终我们可以拿到系统的日志数据。 +- 你还可以尝试配置其他的 MCP 服务,之后验证各种场景功能。担任如果你希望更细化的做 Ai Agent,还是要看下 [《Ai Agent 智能体项目》](https://bugstack.cn/md/project/ai-knowledge/ai-knowledge.html) 这样可以更细腻的做出这样的系统,以及对应的可视化编排操作。 diff --git a/docs/md/ai/openclaw.md b/docs/md/ai/openclaw.md new file mode 100644 index 000000000..85fc8b974 --- /dev/null +++ b/docs/md/ai/openclaw.md @@ -0,0 +1,347 @@ +--- +title: OpenClaw +lock: need +--- + +# 🦞OpenClaw,你是不还没有安装上?这个中文版,可以试试! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +🦞OpenClaw,大龙虾,看着挺复杂,其实一点也不简单。都火成这德行了,但也还是有很多伙伴在安装这一块就挂壁了。想体验呀,咋整? + +
+ +
+ +**怎么理解 OpenClaw 🦞** + +OpenClaw 是一款开源 AI 助手,不到2个月时间 [Github](https://github.com/openclaw/openclaw) 点赞量已经超过 170k Star ⭐️,它的出现为我们提供了更俏的思路使用 LLM 大模型。从24年底,定义了 MCP 协议,25年爆发了 Ai Agent 的落地,随后出现 [GLM AutoPhone](https://bugstack.cn/md/algorithm/model/autoglm-phone-agent.html) 控制手机,现在又来了大龙虾 OpenClaw 控制电脑。 + +你可以把 OpenClaw 理解为一个从你到电脑设备,需要敲键盘的过程,**设计了一个中间网关层**。你的指令可以通过各类 APP/Web 对话的方式,下发给 OpenClaw 完成电脑的一些列操作。如;`帮我安装个Docker`、`在Docker中部署下Redis`、`告诉我现在运行状况和剩余可用资源`等等操作。 + +
+ +
+ +综上,这让我们离`数字员工`又近了一步,后续可以拷贝个人工作技能到 skills 编写,如一些高频重复的场景,对现存系统运行的巡检,对运营类数据的排查,对活动经营情况的分析等。都可以被制作为 skills 让 OpenClaw 使用。 + +接下来,小傅哥就带着大家安装下 OpenClaw + 飞书配置,这套组合还是蛮好用的。 + +## 一、安装介绍 + +### 1. 软件 + +官网:[https://openclaw.ai/](https://openclaw.ai/) +源码:[https://github.com/openclaw/openclaw](https://github.com/openclaw/openclaw) + +中文社区: +- [https://clawd.org.cn/](https://clawd.org.cn/) - `新人伙伴比较推荐实用这个,全是中文提示,安装起来更友好。` +- [https://openclaw.qt.cool/](https://openclaw.qt.cool/) +- [https://1panel.cn](https://1panel.cn/) + +> 除了官网的 OpenClaw 资源,还有不少中文社区,对 OpenClaw 做了镜像和汉化的处理。安装方式也都一样,小白伙伴也可以体验下,全是中文对小白更友好。另外,这部分汉化是基于 openclaw 源码来做的,如果你有一些预安装诉求,以及汉化或者有自身公司想做些扩展也可以基于源码 fork 来改造。 + +### 2. 环境 + +- nodejs 22+ (不少安装包里会提供检测和安装)[https://nodejs.org/zh-cn/download](https://nodejs.org/zh-cn/download) +- 2c4g 云服务器/本地电脑 [https://618.gaga.plus](https://618.gaga.plus) - `推荐买1年送3个月的` + Ubuntu 24 系统。 +- 环境初始化脚本 [https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install](https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install) - `执行 sudo ./openclaw.sh 会帮你在云服务器安装 nodejs 22+` +- 镜像资源 `--registry https://registry.npmmirror.com` 如使用 `sudo npm install -g openclaw@latest --registry https://registry.npmmirror.com` + +### 3. 资源 + +- GLM ApiKey:[https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys](https://www.bigmodel.cn/glm-coding?ic=KFLKGANUMO) - 可以换账号新注册下,获取2000万token,可以提前申请好,复制到自己的文档里(你可能会失败好多次,反复使用)。 +- 飞书:[https://open.feishu.cn/app](https://open.feishu.cn/app) - `企业自建应用(下载个桌面版更好用)`,先发布一次(拿到App ID、App Secret)让 OpenClaw 对接上,之后再飞书机器人配置上**事件配置**,之后在发布一次应用。这样就建立起链接了,下文教程有详细处理过程。 + +## 二、部署介绍 + +### 1. 部署流程 + +OpenClaw 的安装过程中,会涉及一些列命令的使用,我把这些放到一个图里,方便大家理解; + +
+ +
+ +- 首先,关于安装可以使用 curl 向导式一次安装,也可以使用 npm 安装软件后,在启动配置向导。在 [xfg-dev-tech-docker-install](https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install) 一键安装脚本中,提供了 `sudo ./openclaw.sh` 安装脚本,附带的会帮助你完成 nodejs 22+ 的检测和安装,以及飞书组件的提示,会简化一些你的操作。 +- 然后,在执行 `sudo openclaw onboard` 运行向导后,会告诉你这个软件的安全提示,你可以通过`←` `→`选择 yes 安装即可。再往后,会进行模型的选择,这里支持好多模型,本案例使用的 [glm apikey](https://www.bigmodel.cn/glm-coding?ic=KFLKGANUMO) +- 之后,一系列选择后(不分可以跳过),包括通信渠道(飞书)也可以先跳过,即可完成安装。安装后可以通过 `sudo openclaw gateway` 启动网关。这样 openclaw 也就正式启动起来了。 +- 再后,安装飞书插件 `sudo openclaw plugins install @m1heng-clawd/feishu --registry https://registry.npmmirror.com` 这东西的目的是让 openclaw 可以对接上飞书。 + +### 2. 常用命令 + +| 命令 | 作用 | 备注 / 参数 | +| :----------------------------------------------------------- | :---------------------- | :-------------------------------------------- | +| `npm install -g openclaw@latest --registry https://registry.npmmirror.com` | 安装 openclaw | | +| `openclaw onboard` | 安装引导 | | +| `openclaw status` | 查看 Gateway 状态 | 检查网关是否可达及运行状况 | +| `openclaw health` | 健康检查 | 主要检测 core 运行和依赖情况 | +| `openclaw doctor` | 综合诊断与修复建议 | 可配合 `--yes` / `--non-interactive` 自动执行 | +| `openclaw configure` | 交互式配置向导 | 用于设置模型、通道、凭据等 | +| `openclaw config get ` | 获取配置值 | 指定路径提取配置 | +| `openclaw config set ` | 设置配置项 | 支持 JSON5/raw 文本 | +| `openclaw config unset ` | 清除配置项 | 移除单个键值 | +| `openclaw channels list` | 列出已登录通道 | 可观察 WhatsApp/Telegram 等登录状态 | +| `openclaw channels login` | 登录新的通道账号 | 用于扫描/授权链接 | +| `openclaw skills list` | 列出技能 | 查看可用/已安装的技能 | +| `openclaw skills info ` | 技能详情 | 观察某项技能参数或版本 | +| `openclaw plugins list` | 列出插件 | 查看已安装插件 | +| `openclaw plugins install ` | 安装插件 | 例如 @openclaw/voice-call | +| `openclaw plugins enable ` | 启用插件 | 之后通常需要重启网关 | +| `openclaw logs --follow` | 显示日志 | `--json / --plain / --limit` 等组合使用 | +| `openclaw gateway` | 启动 Gateway 网关 | | +| `openclaw gateway install` | 安装系统服务 | 根据平台注册 Gateway 守护进程 | +| `openclaw gateway start` | 启动 Gateway 网关 | 系统服务模式下启动 | +| `openclaw gateway stop` | 停止 Gateway 网关 | 同上 | +| `openclaw gateway restart` | 重启 Gateway 网关 | 适合配置变更后应用 | +| `openclaw gateway status` | 网关系统服务状态 | 不同于 `openclaw status`,会探测服务单元 | +| `openclaw uninstall` | 卸载 Gateway 服务及数据 | 官方推荐使用 | +| `openclaw uninstall --all --yes --non-interactive` | 全自动卸载 | 包含状态、workspace、插件等 | +| `openclaw uninstall --state` | 删除状态文件 | 不删除 workspace/CLI | +| `openclaw uninstall --workspace` | 删除工作区 | 移除 agent/workspace 文件 | +| `openclaw uninstall --service` | 仅卸载服务 | 不删除数据 | +| `openclaw uninstall --dry-run` | 模拟卸载 | 显示结果但不实际执行 | + +## 三、部署操作 + +### 1. 创建飞书 + +
+ +
+ +#### 1.1 创建应用 + +
+ +
+ +**批量导入,权限列表** + +```java +{ + "scopes": { + "tenant": [ + "aily:file:read", + "aily:file:write", + "application:application.app_message_stats.overview:readonly", + "application:application:self_manage", + "application:bot.menu:write", + "cardkit:card:write", + "contact:contact.base:readonly", + "contact:user.employee_id:readonly", + "corehr:file:download", + "docs:document.content:read", + "event:ip_list", + "im:chat", + "im:chat.access_event.bot_p2p_chat:read", + "im:chat.members:bot_access", + "im:message", + "im:message.group_at_msg:readonly", + "im:message.group_msg", + "im:message.p2p_msg:readonly", + "im:message:readonly", + "im:message:send_as_bot", + "im:resource", + "sheets:spreadsheet", + "wiki:wiki:readonly" + ], + "user": [ + "aily:file:read", + "aily:file:write", + "im:chat.access_event.bot_p2p_chat:read" + ] + } +} +``` + +- 创建应用后,你可以获得到应用凭证(appid、appsecret)这个信息是用于 openclaw 对接使用的。 + +#### 1.2 发布应用 + +
+ +
+ +- 创建应用后,点击发布应用。这样你创建的应用才是有效的。 + +#### 1.3 事件配置(机器人)- openclaw 配置之前 + +
+ +
+ +- 飞书应用创建后,还需要配置机器人。但这会配置也是失败的,因为 openclaw 还没有关联上来。 +- 这里需要在 openclaw 配置飞书通信渠道,之后重启 openclaw 网关,这里点击保存并配置权限(`接收消息`、`通讯录基本信息`),点击确认开通权限。在发布一个新应用,再和飞书机器人对话就可以使用了。 + +### 2. 安装应用(openclaw) + +#### 2.1 执行脚本(含带引导) + +```java +curl -fsSL https://openclaw.ai/install.sh | sudo bash -s -- --registry https://registry.npmmirror.com +``` + +- openclaw 官网版 + +```java +curl -fsSL https://clawd.org.cn/install.sh | sudo bash -s -- --registry https://registry.npmmirror.com +``` + +- openclaw-cn 中文社区版,适合新人伙伴使用。熟练后,使用官网版即可。他们操作的方式是一样的。 +- 安装后的使用差异,一个是 `sudo openclaw config` 一个是 `sudo openclaw-cn config` + +#### 2.2 引导配置 + +```java +sudo npm install -g openclaw@latest --registry https://registry.npmmirror.com +sudo npm install -g openclaw-cn@latest --registry https://registry.npmmirror.com + +# 运行向导 +sudo openclaw onboard +sudo openclaw-cn onboard +``` + +- 注意 `-cn` 为中文版,如果你不是执行的 curl 一键安装版本,是采用了 安装 `openclaw@latest` 程序,那么需要自己执行引导配置。 + +##### 2.2.1 安全提示 + +
+ +
+ +##### 2.2.2 配置方式 + +
+ +
+ +##### 2.2.3 模型配置 + +
+ +
+ +
+ +
+ +##### 2.2.4 通信通道(飞书) + +**选择渠道** + +
+ +
+ +**安装插件** + +
+ +
+ +- 如果未安装过飞书插件,可以选择安装,也可以跳过后,后续在安装。 +- 单独安装插件 `sudo openclaw-cn plugins install @m1heng-clawd/feishu` + +**配置凭证** + +
+ +
+ +- 把你的应用凭证,配置到 openclaw 应用程序里。之后继续回车。 +- 注意,一会要会到飞书页面,配置事件关联到 openclaw 上。 + +##### 2.2.5 技能配置 + +
+ +
+ +##### 2.2.6 部署完成 + +
+ +
+ +
+ +
+ +```java +ubuntu@VM-0-2-ubuntu:~$ sudo openclaw-cn gateway +``` + +- 配置完成后,要启动下网关。能看到以上信息,表示运行没问题了。 +- 现在要到 3.1 接着配置飞书。 + +### 3. 配置飞书 + +#### 3.1 事件配置(机器人) + +
+ +
+ +- 注意,完成 2.2.6 步骤后,再回来操作。 +- openclaw 关联上飞书以后,点击**添加事件**,以及添加上相关权限。完成后,会提示你发布一个新应用。 + +#### 3.2 发布应用 + +
+ +
+ +- 点击发布应用,版本号 +1 + +#### 3.3 打开应用 + +
+ +
+ +- 这会对话飞书,会提示执行一个命令,类似于验证签名。 +- 命令 `sudo openclaw-cn pairing approve feishu KF2BRAXW` + +#### 3.4 验证前面(+重启网关) + +
+ +
+ +```java +ubuntu@VM-0-2-ubuntu:~$ sudo openclaw-cn pairing approve feishu KF2BRAXW + +🦞 Clawdbot-CN 0.1.4 (b161cdd) — 唯一不能在你的私信上训练的机器人Mark。 + +Approved feishu sender ou_762197513d3d1cb907f4c0d2ed3c3b2b. +ubuntu@VM-0-2-ubuntu:~$ sudo openclaw-cn gateway + +🦞 Clawdbot-CN 0.1.4 (b161cdd) — 我不是魔法——我只是在重试和应对策略上极其执着。 + +06:39:38 [canvas] host mounted at http://127.0.0.1:18789/__clawdbot__/canvas/ (root /root/clawd/canvas) +06:39:38 [heartbeat] started +06:39:38 [gateway] agent model: zai/glm-4.7 +06:39:38 [gateway] listening on ws://127.0.0.1:18789 (PID 20687) +06:39:38 [gateway] listening on ws://[::1]:18789 +06:39:38 [gateway] log file: /tmp/clawdbot/clawdbot-2026-02-08.log +06:39:38 [browser/server] Browser control listening on http://127.0.0.1:18791/ +06:39:38 [feishu] [default] starting Feishu provider (你的应用名称) +06:39:38 [info]: [ 'event-dispatch is ready' ] +``` + +- 如上方式,执行你的签名验证,并重启网关。 +- 到这,就配置完成了,可以使用了。 + +## 四、使用体验 + +
+ +
+ +现在你可以发挥想象的让 openclaw 帮你做事情了,很多运维的活,他也都可以完成。美滋滋! diff --git a/docs/md/ai/qclaw.md b/docs/md/ai/qclaw.md new file mode 100644 index 000000000..5d5bf04dd --- /dev/null +++ b/docs/md/ai/qclaw.md @@ -0,0 +1,242 @@ +--- +title: QClaw +lock: need +--- + +# 🦞站起来蹬,每天2亿token,我已经会用 OpenClaw 了! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +深度体验后,**云服务器 + OpenClaw 的工作属性,基本等于零,白费蜡🕯!** 所以,于3月初,购入 Mac Mini(丐版16G)。部署 `OpenClaw`(+`QClaw`)+ `编程环境`(`jdk`、`maven`...) + `Docker`,`配合 Nas 环境做存储` + `Mac Pro`(随行控制设备)+ UU 远程(没事看看它)等,我才体验到**它能给我干活啦**!😄 + +
+ +
+ +❤ 心得体会! + +最早部署的是 [OpenClaw](https://openclaw.ai/)(这哥们也原生就支持中文啦)+ 飞书,部署起来也很简单。但因为使用的都是自己的 Token,有点舍不得站起来蹬 🚴🏻,感觉每一句话都在烧钱💰。相比较下 OpenClaw 同样一个事的消耗程度,是其他 AI IDE(Trae.ai)的上百倍,那直接用其他的不也可以吗!?🤔 + +但不深度玩,不干它几亿 Token,就不能体验到花钱的快乐! + +好在呀,好在 [**QClaw**](https://qclaw.qq.com/) 每天一个登录的账号,赠送 4000 万 Token。换5个微信(还得家里人多),就是2亿 Token!就算干山崎大队,也是tm有富余的呀! + +
+ +
+ +几十亿 Token 下去后,我的体验是;它能干活,能想一个你的员工一样,控制这台电脑干活。包括,可以按照需求写代码,完成编译、构建、部署,打开浏览器验证功能逻辑,对于错误的编码可以继续完善。并且你可以随时随地的通过手机/Pad,通过`微信`/`企微`/`飞书`等方式,与它交流。 + +不过,它也不是那么省心的。三千六百颗手榴弹,给老李能干山崎大队,给咱也就能炸个鱼塘。所以,OpenClaw 你要想让它准确的给咱干活,就像写出来的代码,不仅它能看懂,我也得能认识呀。 + +那么,就需要上技能 Skills,这也是我在深度体验 OpenClaw 的最大感受,也是最先干的一个活。先拿10亿 Token,写2个 Skills 之后再说(先把🦵🏻腿接上)。—— 把你工作的方式,训练成技能,让 AI 懂你! + +
+ +
+ +> 接下来,小傅哥就分享下,用 OpenClaw(QClaw)做的一些事。 + +## 一、产品上线(skills) + +发布到了官网(clawhub):[https://clawhub.ai/u/fuzhengwei](https://clawhub.ai/u/fuzhengwei) + +
+ +
+ +[**xfg-zsxq-skills**](https://clawhub.ai/fuzhengwei/xfg-zsxq-skills) 一款星球社群运营服务的技能,便于所有加入社群的龙虾🦞主,可以让龙虾自主看帖、回帖,根据自己工作信息发帖/文章,以此方式龙虾形成一个自己的社群,吸收 OpenClaw 使用经验。这是一个自我成长的过程。 + +[**Xfg-ddd-skills**](https://clawhub.ai/fuzhengwei/xfg-ddd-skills) 一款 DDD 架构(六边形)指导编码的技能,因为在实际使用 AI 编码中,如果不加限制,他可能每次实现的功能逻辑,工程结构、分包方式、实现过程,都有非常大的差异。这会导致我们在拿到这份代码后,后续迭代也会非常吃力。所以,设计此技能,按照通用的 DDD 架构(六边形),限定 AI 编码方式。此技能初上线,已经用户体用。 + +## 二、安装技能 + +
+ +
+ +| 用途 | 地址 | +| -------- | --------------------------------------------- | +| 星球社群 | https://github.com/fuzhengwei/xfg-zsxq-skills | +| 编码架构 | https://github.com/fuzhengwei/xfg-ddd-skills | + +OpenClaw、QClaw、OpenCode等,你都可以直接把技能**连接**告诉它,它可以帮你直接安装。如果不能直接安装也可以下载安装包,本地到底即可。 + +## 三、运行效果(zsxq-skills) + +### 1. 主动发帖 + +
+ +
+ +- 当你部署 zsxq-skills 技能后开始时,他会询问你,要对哪个星球地址进行操作,以及对应的 cookie 信息。如果 cookie 过期了,它还会主动询问你进行替换。 +- 整体配置完成后,你就可以对星球进行发帖以及查看帖子等操作。不过不要弄的特别频繁! +- 像是在 OpenClaw(QClaw)还可以让添加上定时的任务处理。 + +### 2. 龙虾社群🦞 + +
+ +
+ +- 地址:[https://wx.zsxq.com/group/48885154455258](https://wx.zsxq.com/group/48885154455258) +- 说明:现在这个[《OpenClaw 养虾社区🦞》](https://wx.zsxq.com/group/48885154455258)就已经入住了很多小龙虾,欢迎👏🏻一起来玩下。 + +## 四、编程效果(ddd-skills) + +### 1. 技能说明 + +如果不对 ai 做编码结构和实现方式限定,ai 会每次都给你“惊喜”,但工程交付需要的是在确定的结构下,持续的迭代输出。所以,需要增加规范技能,限定 ai 编码输出方式的统一。 + +
+ +
+ +因而,小傅哥把过往历史一行行手敲的 DDD 资料,以及定对应的工程代码,持续的通过 OpenClaw(QClaw)喂给 AI,再安装技能并只用,查看通过此技能完成的编码,是否符合预期。经过仅2周的折腾,目前发布了 [xfg-ddd-skills v2.2.1](https://github.com/fuzhengwei/xfg-ddd-skills) 版本,可以满足 DDD 六边形架构设计和编码实现。 + +地址:[https://github.com/fuzhengwei/xfg-ddd-skills](https://github.com/fuzhengwei/xfg-ddd-skills) - 欢迎使用,也感谢给点个 Star 支持!更建议,帮忙一起维护迭代。 + +### 2. 技能设计 + +```java +xfg-ddd-skills/ +├── SKILL.md # 技能入口文件 +├── README.md # 本文件 +├── assets/ # 资源文件 +├── scripts/ # 脚本工具 +└── references/ # 参考文档 + ├── architecture.md # 六边形架构概述 + ├── entity.md # 实体设计规范 + ├── aggregate.md # 聚合根设计规范 + ├── value-object.md # 值对象设计规范 + ├── repository.md # 仓储模式规范 + ├── port-adapter.md # 端口与适配器规范 + ├── case-layer.md # 业务编排层规范 + ├── project-structure.md # Maven 多模块结构 + ├── naming.md # 命名规范 + └── docker-images.md # Docker 镜像配置 +``` + +- 当你需要以下场景时,使用本技能: + + - 设计或实现 DDD 架构的项目,可以直接帮你创建准确的、统一的、可用的工程架构 + - 需要六边形架构、端口与适配器模式 + - 创建 Entity(实体)、Aggregate(聚合根)、Value Object(值对象) + - 设计 Repository(仓储)模式 + - 业务编排层(Case Layer)设计 + - 触发层(Trigger Layer:HTTP/MQ/Job)设计 + - 构建富领域模型(Rich Domain Model) + +- 注意,此技能还在持续迭代中,陆续还会增强使用效果。 + +```java +┌─────────────────────────────────────────────────────────────┐ +│ 触发层 Trigger │ +│ (HTTP Controller / MQ Listener / Job) │ +└─────────────────────────┬───────────────────────────────────┘ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ API 层 │ +│ (DTO / Request / Response) │ +└─────────────────────────┬───────────────────────────────────┘ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 案例层 Case │ +│ (业务编排 / 流程串联 / 组合调用) │ +└─────────────────────────┬───────────────────────────────────┘ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 领域层 Domain │ +│ (Entity / Aggregate / VO / Domain Service) │ +└─────────────────────────┬───────────────────────────────────┘ + ▲ +┌─────────────────────────────────────────────────────────────┐ +│ 基础设施层 Infrastructure │ +│ (Repository Impl / Port Adapter / DAO / PO) │ +└─────────────────────────────────────────────────────────────┘ +``` + +- 此技能符合六边形架构设计标准,相关文档:[https://bugstack.cn/md/road-map/ddd-guide-03.html](https://bugstack.cn/md/road-map/ddd-guide-03.html) + +### 3. 场景应用 + +#### 3.1 表单开发 + +小傅哥这里选择的一个【表单】功能开发的场景,类似通讯 doc 里有一个表单的功能,设置表单后,让用户填写; + +由运营配置表单,填写相应的输入信息(字段),有文本、数字、日期、下拉选择和图片上传等类型。以及增强了表单数据场景运用,填表的表单可以直接关联到用途上,如数据做权限功能审核,或者数据做发券等功能。最后分享链接给用户填写提交,提交时候可以选择让用户是否鉴权(如github登录、星球登录、公众号登录)。 + +
+ +
+ +全程零参与代码实现,只提供必要的信息。对于开发后的功能,都是让 OpenClaw(QClaw)自己做浏览器访问,填写数据,验证功能。如果有问题,则进行优化功能的处理。 + +不过,做这类东西,还是需要懂场景,懂产品,懂架构,懂技术。否则,它真运行起来,也是会有不少问题的。 + +#### 3.2 产品演示 + +##### 3.2.1 编辑表单(关联数据场景) + +
+ +
+ +##### 3.2.2 表单数据(全局展示信息) + +
+ +
+ +##### 3.2.3 能力配置(数据场景配置) + +
+ +
+ +- 这个的目的,就在于配置完表单,用户填写后,那么这些数据,要干啥用。我们可以把一些字段关联起来,直接使用。 + +##### 3.2.4 填写记录(展示收集信息) + +
+ +
+ +##### 3.2.5 分享表单(用户填写数据) + +
+ +
+ +- 分享表单后,用户填写提交即可。 + +### 4. 工程演示 + +
+ +
+ +- 这个结构很重要,通过 xfg-ddd-skills 的限定,它可以按照约定的方式来编码。不要有ai幻觉和惊喜,而是要有小傅哥的“味道”。 +- 不过在整个设计实现的“灵魂”上,还是差了点,不够老辣! + +## 五、体验总结 + +1. 这种大量的工程化的,AI 写的代码,我不想碰。既不能给它修,也不想给它改。只要有 Token 就想让 AI 继续搞。软件工程交付,需要的不只是代码,还包括完整的理解代码,代码与产品PRD完全匹配,从而形成代码资产。 +2. 使用AI做项目,仍然需要懂技术的,你的能力多强,你驾驭AI的本事就多大。 +3. 纯新项目,或者小公司快速场景验证,可以使用AI快速搭建出来一套。 +4. 公司里几十万行的老项目,如果靠 AI 这样迭代编写,可能会出事故。审查要严格。程序员编码的过程,是一行行逻辑的确认和产品功能的完整匹配。 +5. 当一个需求过于复杂的时候,AI 会有过程中崩溃问题。这个对于个人编码项目没啥所谓,但公司级别的需求的迭代的。它的编码速度,有时候会低于人。n个类中,n行代码中,迭代功能,程序员已经有历史经验。ai 需要全量识别(或者你提前都编写好了技能) +6. skills 很有用,希望使用 ai 迭代项目的,需要持续的为工程迭代 skills 的各项技能。相当于为工程写技能路书。 +7. OpenClaw(QClaw)属于一种网关入口,来控制设备。如果你更熟练于编码,那么纯 AI IDE 会更适合。如果你往各类的服务,接管电脑,那么 OpenClaw 更为合适。 + +--- + +
+ +
\ No newline at end of file diff --git a/docs/md/ai/spring-ai.md b/docs/md/ai/spring-ai.md new file mode 100644 index 000000000..89d85372b --- /dev/null +++ b/docs/md/ai/spring-ai.md @@ -0,0 +1,191 @@ +--- +title: Spring AI +lock: need +--- + +# spring ai + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。今天来带大家体验一下 Spring AI 的 Easy 开发! + +现在的 OpenAI 对接开发真的是越来越容易了,直接引入 Spring AI 这个组件包,配置上可调用的 ApiHost、ApiKey 就可以完成对 OpenAI(ChatGPT)接口的调用。在此之前也有那么多各类的接口服务,还没有像 OpenAI 这样,被 Spring 如此重视,直接提供专属的 SDK 包,封装所有大模型(`暂无国内的`)。这也说明 OpenAI 的趋势力量多么庞大! + +
+ +
+ +**OpenAI 结合业务才更有价值** + +虽然 OpenAI 的接口对接是越来越简单了,但我们要知道,一个实际的项目就不只是对接 OpenAI 接口,还需要完成一系列的业务流程封装。就比如目前我们看到国内的各类套壳或自研类的 OpenAI 服务,都会包括;`用户`、`鉴权`、`账户`、`支付`、`场景`等,一套东西来支撑整个流程跑通,同时还有系统工程背后的`舆情监控`、`敏感词过滤`、`数据存储`、`行为分析`等各类操作。这些东西也就是常说的,不能只会一个技术点,而是要结合场景,用技术支撑业务落地。 + +接下来,小傅哥会分享 Spring AI + Gpt-4o 的对接使用,以及介绍如何开发应用级的 OpenAI 项目。 + +## 一、简单介绍 + +Spring AI 项目,是为开发 AI 应用程序提供了 Spring 友好的 API 和抽象。所有的大模型对接(OpenAI、Ollama、Azure OpenAI、Amazon Bedrock、HuggingFace、Google VertexAI、Mistral AI)都以一种统一标准的形式进行。这样就减少了大家再额外开发对接的成本了,也不用维护和兼容各个 OpenAI 的接口迭代。 + +- 官网:[https://docs.spring.io/spring-ai/reference/index.html](https://docs.spring.io/spring-ai/reference/index.html) +- 文档:[https://docs.spring.io/spring-ai/reference/1.0-SNAPSHOT/index.html](https://docs.spring.io/spring-ai/reference/1.0-SNAPSHOT/index.html) +- 源码:[https://github.com/spring-projects/spring-ai](https://github.com/spring-projects/spring-ai) + +## 二、工程对接 + +### 1. 工程说明 + +- 环境:JDK 17、SpringBoot 3.2.3、spring-ai 0.8.0 +- 源码:[xfg-dev-tech-spring-ai](https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-spring-ai) + +
+ +
+ +在此工程中完成了 SpringAI 模块的引入,以及使用提供的 API 接口,完成同步应答、流式应答、图片绘制功能。 + +### 2. 引入模块 + +```pom + + org.springframework.ai + spring-ai-bom + 0.8.0 + pom + import + + + + org.springframework.ai + spring-ai-openai-spring-boot-starter + +``` + +- spring-ai 也在不断的发展,2024年5月22日 发布了 1.0.0 M1 并对代码做了一些调整。在生产级别使用需要注意📢版本的迭代。 + +### 2. 接口对接 + +测试之前需要在 application-dev.yml 配置对接的信息。 + +```yaml +spring: + ai: + openai: + base-url: https://api.aws-*****/ + api-key: sk-oLkakcax33mJl628D3A533Fd67A24602Ac37D6***** +``` + +注意 spring-ai 提供了各类大模型的对接,都可以按需配置到这里。*在它的源码 autoConfig 类里会有要配置参数的名称,可以参考。* + +#### 2.1 功能测试 + +```java +@Resource +private OpenAiChatClient chatClient; +@Resource +private OpenAiImageClient openaiImageClient; + +@Test +public void test_generate() { + ChatResponse chatResponse = chatClient.call( + new Prompt( + "1+1", + OpenAiChatOptions.builder() + .withModel("gpt-4o") + .build() + )); + log.info("测试结果:{}", JSON.toJSONString(chatResponse)); +} + +@Test +public void test_generate_stream() throws InterruptedException { + CountDownLatch countDownLatch = new CountDownLatch(1); + Flux stream = chatClient.stream(new Prompt("1+1")); + stream.subscribe( + chatResponse -> { + AssistantMessage output = chatResponse.getResult().getOutput(); + log.info("测试结果: {}", JSON.toJSONString(output)); + }, + Throwable::printStackTrace, + () -> { + countDownLatch.countDown(); + System.out.println("Stream completed"); + } + ); + countDownLatch.await(); +} + +@Test +public void test_generate_image() { + ImageResponse imageResponse = openaiImageClient.call( + new ImagePrompt("画个小狗", + OpenAiImageOptions.builder() + .withModel("dall-e-3") + .withQuality("hd") + .withN(1) + .withHeight(1024) + .withWidth(1024) + .build() + ) + ); + log.info("测试结果: {}", JSON.toJSONString(imageResponse)); +} +``` + +**测试结果** + +```java +24-05-26.16:46:46.287 [ForkJoinPool.commonPool-worker-1] INFO OpenAITest - 测试结果: {"content":"","messageType":"ASSISTANT","properties":{"role":"ASSISTANT"}} +24-05-26.16:46:46.288 [ForkJoinPool.commonPool-worker-1] INFO OpenAITest - 测试结果: {"content":"","messageType":"ASSISTANT","properties":{"role":"ASSISTANT"}} +24-05-26.16:46:46.289 [ForkJoinPool.commonPool-worker-1] INFO OpenAITest - 测试结果: {"content":"1","messageType":"ASSISTANT","properties":{"role":"ASSISTANT"}} +24-05-26.16:46:46.289 [ForkJoinPool.commonPool-worker-1] INFO OpenAITest - 测试结果: {"content":"+","messageType":"ASSISTANT","properties":{"role":"ASSISTANT"}} +24-05-26.16:46:46.289 [ForkJoinPool.commonPool-worker-1] INFO OpenAITest - 测试结果: {"content":"1","messageType":"ASSISTANT","properties":{"role":"ASSISTANT"}} +24-05-26.16:46:46.289 [ForkJoinPool.commonPool-worker-1] INFO OpenAITest - 测试结果: {"content":" equals","messageType":"ASSISTANT","properties":{"role":"ASSISTANT"}} +24-05-26.16:46:46.289 [ForkJoinPool.commonPool-worker-1] INFO OpenAITest - 测试结果: {"content":" ","messageType":"ASSISTANT","properties":{"role":"ASSISTANT"}} +24-05-26.16:46:46.290 [ForkJoinPool.commonPool-worker-1] INFO OpenAITest - 测试结果: {"content":"2","messageType":"ASSISTANT","properties":{"role":"ASSISTANT"}} +24-05-26.16:46:46.290 [ForkJoinPool.commonPool-worker-1] INFO OpenAITest - 测试结果: {"content":"","messageType":"ASSISTANT","properties":{"role":"ASSISTANT"}} +Stream completed +``` + +- 测试结果为 test_generate_stream 流式返回 `1+1` 的应答结果。 + +#### 2.2 接口服务 + +```java +@RestController() +@CrossOrigin("*") +@RequestMapping("/api/v1/openai/") +public class OpenAiController { + + @Resource + private OpenAiChatClient chatClient; + + /** + * curl http://localhost:8090/api/v1/openai/generate?message=1+1 + */ + @RequestMapping(value = "generate", method = RequestMethod.GET) + public ChatResponse generate(@RequestParam String message) { + return chatClient.call( + new Prompt( + message, + OpenAiChatOptions.builder() + .withModel("gpt-4o") + .build() + )); + } + + /** + * curl http://localhost:8090/api/v1/openai/generate_stream?message=1+1 + */ + @RequestMapping(value = "generate_stream", method = RequestMethod.GET) + public Flux generateStream(@RequestParam String message) { + return chatClient.stream(new Prompt(message)); + } + +} +``` + +在 OpenAiController 中提供了对接两个接口的方法,以及同步和流式返回。*流式返回还可以使用 ResponseBodyEmitter 进行流式返回* + +Spring AI 提供的 OpenAI 大模型对接是 Easy 的很,减去了自己开发代码对接大模型。但仅仅是这样一个简单还不够,我们还需要学习积累的更多!如;微信鉴权登录怎么做、支付怎么对接、账户额度怎么扣减、限流熔断怎么操作等等,实际场景问题才是有价值的核心内容,所以,咱们要上个大菜!☞ [OpenAi 大模型应用服务体系构建 - API-SDK、鉴权、公众号、企业微信、支付服务](https://bugstack.cn/md/project/chatgpt/chatgpt.html) \ No newline at end of file diff --git a/docs/md/ai/trae.md b/docs/md/ai/trae.md new file mode 100644 index 000000000..3294a349b --- /dev/null +++ b/docs/md/ai/trae.md @@ -0,0 +1,210 @@ +--- +title: Trae.ai +lock: need +--- + +# Trae.ai - 真好用,码农必备工具! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +有人说程序员这个行业👨🏻‍💻总是在革自己的命,一个个编码 AI 工具的出现,是不已经不需要那么多初级 CRUD 程序员了🤔。但恰恰相反,AI 工具的出现,是把初级程序员,迅速培养到了高级工程师! + +
+ +
+ +`其实 AI 让程序员更牛!` + +以前初学编程看不懂的代码,现在使用AI能动态做解释和提供案例,以前跨语言(java->vue/react)不能做的事情,现在可以搞了。以前不能写的插件(IntelliJ IDEA、谷歌浏览器),现在能实现了。以前写不出的高级感代码,现在随手就拿到全球最优秀的编码方案。 + +今天介绍一款 AI 开发工具 [Trae.ai](https://www.trae.ai/) ,让刚入门编程的找到学习方法,让初级工程也能写出优秀的代码,让高级研发嘎嘎提高效率! + +>文末提供了 AI 应用开发实战项目,想提高 AI 应用编程能力的伙伴,可以获取学习项目。 + +## 一、软件下载 + +官网地址:[https://www.trae.ai/](https://www.trae.ai/) + +
+ +
+ +- Trae 是一个自适应的 AI IDE,它可以改变您的工作方式,与您协作以更快地运行。 +- 在使用的时候,你可以一个工程同时在 IntelliJ IDEA 打开,也使用 Trae 打开。😂 `因为习惯 IntelliJ IDEA,各类调试还是很舒服的。` + +> 同类软件 [Cursor](https://www.cursor.com/cn),不过这个想使用好的模型得付费,Trae 是不需要付费的! + +## 二、使用体验 + +### 1. 提问代码 + +**拖拽代码/文件夹/工程** + +
+ +
+ +**添加代码到对话** + +
+ +
+ +**通过#号,选择要对话的内容** + +
+ +
+ +> 之所以分享这个软件,也是因为很多小白初学编程,拿到一个项目不知道从哪里看。现在你有了这个软件,就可以非常简单的对工程的代码进行提问了。也不需要复制到任何 AI 对话工具了,并且这套软件是免费的。 + +### 2. 生成代码 - 后端 + +这里我们举例,复制掘金发文接口,之后让 Trae.ai 帮我包装; + +#### 2.1 复制接口 + +
+ +
+ +#### 2.2 研发设计 - 话术 + +
+ +
+ +**生成话术,类似于研发设计** + +```java +在 gateway 文件夹下,编写 IJueJinService 类,以 retrofit2 方式包装 curl 请求接口。接口入参仅为必要参数,如;cookie,发文的 Request 对象。 + +curl 如下; + +curl 'https://api.juejin.cn/content_api/v1/article_draft/create?aid=2608&uuid=7058897578062890496' \ + -H 'accept: */*' \ + -H 'accept-language: zh-CN,zh;q=0.9,en;q=0.8' \ + -H 'content-type: application/json' \ + -b 'store-region=cn-bj; store-region-src=uid; __tea_cookie_tokens_2608=%******a51b13e5; uid_tt_ss=7aff2f2394310b3b71f07006a51b13e5; sid_tt=3813572f48984e4b5b3cc7f90733f2e9; sessionid=3813572f48984e4b5b3cc7f90733f2e9; sessionid_ss=3813572f48984e4b5b3cc7f90733f2e9; sid_ucp_v1=1.0.0-KDU4N2NlM2Q2NjFiODhjOGNhZGE5YzVlOTM4ZWZkY2U3ZTc3MzVjMjAKFwjemIC67ozUAxDT_ci_BhiwFDgCQPEHGgJsZiIgMzgxMzU3MmY0ODk4NGU0YjViM2NjN2Y5MDczM2YyZTk; ssid_ucp_v1=1.0.0-KDU4N2NlM2Q2NjFiODhjOGNhZGE5YzVlOTM4ZWZkY2U3ZTc3MzVjMjAKFwjemIC67ozUAxDT_ci_BhiwFDgCQPEHGgJsZiIgMzgxMzU3MmY0ODk4NGU0YjViM2NjN2Y5MDczM2YyZTk' \ + -H 'dnt: 1' \ + -H 'origin: https://juejin.cn' \ + -H 'priority: u=1, i' \ + -H 'referer: https://juejin.cn/' \ + -H 'sec-ch-ua: "Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"' \ + -H 'sec-ch-ua-mobile: ?0' \ + -H 'sec-ch-ua-platform: "macOS"' \ + -H 'sec-fetch-dest: empty' \ + -H 'sec-fetch-mode: cors' \ + -H 'sec-fetch-site: same-site' \ + -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36' \ + -H 'x-secsdk-csrf-token: 00010000000152d838f2c09c65e4feef033c275a8cff940c12228719074fe36f9ce2d18b4d251833ae62ea768117' \ + --data-raw '{"category_id":"0","tag_ids":[],"link_url":"","cover_image":"","title":"测试文章","brief_content":"","edit_type":10,"html_content":"deprecated","mark_content":"","theme_ids":[],"pics":[]}' + +接口返回结果; + +{ + "err_no": 0, + "err_msg": "success", + "data": { + "id": "7489358088379531291", + "article_id": "0", + "user_id": "2058727733595230", + "category_id": "0", + "tag_ids": [], + "link_url": "", + "cover_image": "", + "is_gfw": 0, + "title": "测试文章", + "brief_content": "", + "is_english": 0, + "is_original": 1, + "edit_type": 10, + "html_content": "deprecated", + "mark_content": "", + "ctime": "1743929226", + "mtime": "1743929226", + "status": 0, + "original_type": 0, + "theme_ids": [] + } +} + +根据接口信息封装 DTO 对象,放到 gateway dto 下。 +``` + +#### 2.3 编码效果 + +
+ +
+ +- 生成后,代码会直接写入到你说明的文件夹下,创建好相关的类信息。之后你可以点击全部接受,他会审查代码,如果代码有问题还会检修编写。 + +### 3. 生成代码 - 前端 + +
+ +
+ +- 这是小傅哥实现的一套 AI RAG&MCP 知识库项目,设计的一套页面。这套页面使用了 AI 做了大量的编码。`以前能写前端,但总感觉是屎上雕花,不出活!`这回有 AI 工具,省心多了。 +- AI 对于这类既定的,没有复杂的逻辑和各类框架综合使用的,真的描述一句优化UI,它就`苦吃苦吃`的干活了! + +> 你发现没,你只要写一些描述,它就能很好的干活了。这是因为 AI Agent 智能体会包括;规划、记忆、召回、工具(MCP),来把需求转换为可以看到的代码。 + +## 三、实战项目 + +这是小傅哥最近带着大家做的一套 AI 应用实战项目,《DeepSeek RAG&MCP 增强检索知识库系统》 - 解析文档&Git仓库代码&AI工作流,全程视频手把手教学。 + +RAG:实现了除普通文档知识解析外,增加了 Git 代码库的拉取和解析,并提供操作接口。为工程师做项目开发时,`需求分析`、`研发设计`、`辅助编码`、`代码评审`、`风险评估`、`上线检测`等,做工程交付提效。 + +MCP:用不了多久,各大互联网企业都将大量的推进落地,自有 MCP 服务的实现,用于增强企业 AI 应用的提效能力。因为 MCP 的加入,可以让你;一条命令`帮研发`,调用应用系统日志、排查系统CPU负载、自主选择是否调度数据库信息。也可以一条命令`帮运营`,搞定复杂的SQL执行、导出报表、分析数据、完成促活营销券的自动化配置上架。这就是 MCP的魅力!👍🏻 + +**RAG + MCP = 智能AI工作流,如智能客服,智能编码助手,智能运维工程师等。** + +
+ +
+ +```java +@Test +public void test_weixinNotice_chatMemory() { + System.out.println("\n>>> ASSISTANT: " + chatClient + .prompt(""" + 我需要你帮我生成一篇文章,要求如下; + + 1. 场景为互联网大厂java求职者面试 + 2. 面试管提问 Java 核心知识、JUC、JVM、多线程、线程池、HashMap、ArrayList、Spring、SpringBoot、MyBatis、Dubbo、RabbitMQ、xxl-job、Redis、MySQL、Linux、Docker、设计模式、DDD等不限于此的各项技术问题。 + 3. 按照故事场景,以严肃的面试官和搞笑的水货程序员谢飞机进行提问,谢飞机对简单问题可以回答,回答好了面试官还会夸赞。复杂问题胡乱回答,回答的不清晰。 + 4. 每次进行3轮提问,每轮可以有3-5个问题。这些问题要有技术业务场景上的衔接性,循序渐进引导提问。最后是面试官让程序员回家等通知类似的话术。 + 5. 提问后把问题的答案,写到文章最后,最后的答案要详细讲述出技术点,让小白可以学习下来。 + + 根据以上内容,不要阐述其他信息,请直接提供;文章标题、文章内容、文章标签(多个用英文逗号隔开)、文章简述(100字) + + 将以上内容发布文章到CSDN。 + """) + .advisors(advisor -> advisor + .param(CHAT_MEMORY_CONVERSATION_ID_KEY, "1001") + .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)) + .call() + .content()); + + + System.out.println("\n>>> ASSISTANT: " + chatClient + .prompt(""" + 之后进行,微信公众号消息通知,平台:CSDN、主题:为文章标题、描述:为文章简述、跳转地址:从发布文章到CSDN获取 url + """) + .advisors(advisor -> advisor + .param(CHAT_MEMORY_CONVERSATION_ID_KEY, "1001") + .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)) + .call() + .content()); +} +``` + +- 两轮对话,发文到CSDN,之后推送消息到公众号平台。这两轮对话是配置有记忆功能的,所以可以衔接上下文。 +- 这样的技术,还是非常有必要积累的,因为很多中大厂也都开了 AI 开发工程师的岗位。 diff --git a/docs/md/algorithm/data-structures/2022-10-01-tree-2-3.md b/docs/md/algorithm/data-structures/2022-10-01-tree-2-3.md index f81cc073e..344dc8bdc 100644 --- a/docs/md/algorithm/data-structures/2022-10-01-tree-2-3.md +++ b/docs/md/algorithm/data-structures/2022-10-01-tree-2-3.md @@ -39,9 +39,11 @@ lock: need
- 2-3 树的插入过程与 BST 树类似,会通过树的左右节点大小,找到自己的插入位置。 -- 一个节点可以右1-3个元素,但当元素个数为3时,则需要调衡。把三个节点的中间节点晋升上来,其余两个节点为子节点。 +- 一个节点可以有1-2个元素(注意:不是1-3个),但当元素个数为3时,则需要调衡。把三个节点的中间节点晋升上来,其余两个节点为子节点。 - 如果进行一次调衡后,上一层父节点达到3个元素,则需要2次调衡,来满足2-3树的规则。 +**注意**:2-3树的定义是每个节点可以有1-2个元素,当插入导致节点有3个元素时需要立即调衡。例如在插入节点9之前的树结构中,父节点6应该只有一个元素,其左子树为节点5。这样的结构符合2-3树的定义,也便于后续插入节点9时的调衡操作。 + **咋样**,是不看过这个图之后对于2-3树的实现已经有感觉了,想动手写写试试了? - 源码地址:[https://github.com/fuzhengwei/java-algorithms](https://github.com/fuzhengwei/java-algorithms) - 本章源码:[https://github.com/fuzhengwei/java-algorithms/tree/main/data-structures/src/main/java/tree](https://github.com/fuzhengwei/java-algorithms/tree/main/data-structures/src/main/java/tree) diff --git a/docs/md/algorithm/model/autoglm-phone-agent.md b/docs/md/algorithm/model/autoglm-phone-agent.md new file mode 100644 index 000000000..c5e1dac01 --- /dev/null +++ b/docs/md/algorithm/model/autoglm-phone-agent.md @@ -0,0 +1,326 @@ +--- +title: AutoGLM Phone Agent +lock: need +--- + +# 手机 + agent,这是要掀桌子! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +`这 + agent`,`那 + agent`,都是赋能,辅助提效。但**手机 + agent**,要掀桌子呀,这是要改变现有手机和APP厂商入口的格局。就像你开了个超市,别在你家开了个【超市入口】! + +
+ +
+ +**智能体时代,谁也阻挡不住!** + +先是有豆包手机,之后GLM推出 AutoGLM-Phone-9B 模型,可以通知命令、API、语音等方式,以多模态形式,帮助用户完成手机任务。如,`打开xxxAPP,搜索xxx商品,完成下单,之后通知给xxx微信伙伴,在xxx时间,进行收货`。`也可以,告诉手机,定时定点完成xxxAPP的签到、领券,刷票抢票`。`还可以,为老年人对于手机的xxx业务复杂的操作,进行一些列的自动化完成处理`。 + +这将是下一代手机的使用体验,也是各大厂即将争夺的智能入口。接下来,小傅哥带着大家部署下 AutoGLM 模型,以及讲解如何配置使用和最终的效果。 + +目前 AutoGLM 还是面向研发使用的阶段,不是直接可以调用的 API,所以要自己部署。不过以后肯定会更加方便,也会附带的提供对应的产品。也有可能出新安卓/IOS+agent的手机系统。路已经开了,看谁跑的快吧! + +## 一、模型介绍 + +官网:[https://github.com/zai-org/Open-AutoGLM](https://github.com/zai-org/Open-AutoGLM) + +
+ +
+ +- Phone Agent 是一个基于 AutoGLM 构建的手机端智能助理框架,它能够以多模态方式理解手机屏幕内容,并通过自动化操作帮助用户完成任务。系统通过 ADB(Android Debug Bridge)来控制设备,以视觉语言模型进行屏幕感知,再结合智能规划能力生成并执行操作流程。用户只需用自然语言描述需求,如“打开小红书搜索美食”,Phone Agent 即可自动解析意图、理解当前界面、规划下一步动作并完成整个流程。系统还内置敏感操作确认机制,并支持在登录或验证码场景下进行人工接管。同时,它提供远程 ADB 调试能力,可通过 WiFi 或网络连接设备,实现灵活的远程控制与开发。 +- 其他资料:[https://mp.weixin.qq.com/s/wRp22dmRVF23ySEiATiWIQ](https://mp.weixin.qq.com/s/wRp22dmRVF23ySEiATiWIQ) + +## 二、安装教程 + +### 1. 环境要求 + +- Python 3.10+ - `如果你是手动配置环境,可以参考` [https://bugstack.cn/md/algorithm/model/2023-05-21-chatglm-6b.html](https://bugstack.cn/md/algorithm/model/2023-05-21-chatglm-6b.html) +- GPU 24G * 2 显卡(单卡24G部署,成功概率低)推荐具备 AI 能力的云服务器,可以减少很多基础环境的配置。如:[autodl.com](https://www.autodl.com) +- 安卓手机一台 + 数据线(不能只是充电功能的线),`设置-关于手机-版本号` 然后连续快速点击 10 次左右,直到弹出弹窗显示“开发者模式已启用”。启用开发者模式之后,会出现 `设置-开发者选项-USB 调试`,勾选启用。(如果手机不是这样的,可以百度搜下设置) +- AutoGLM-Phone-9B/AutoGLM-Phone-9B-Multilingual 模型镜像地址:[https://huggingface.co/zai-org/AutoGLM-Phone-9B/tree/main](https://huggingface.co/zai-org/AutoGLM-Phone-9B/tree/main) +- ADB (Android Debug Bridge) 桥接测试包 下载地址:[https://developer.android.com/tools/releases/platform-tools?hl=zh-cn](https://developer.android.com/tools/releases/platform-tools?hl=zh-cn) - `下载后配置路径 export PATH=${PATH}:~/Downloads/platform-tools` Windows 电脑参考第三方教程:[https://blog.csdn.net/x2584179909/article/details/108319973](https://blog.csdn.net/x2584179909/article/details/108319973) +- ADB Keyboard 安卓手机输入法,用于连接桥接测试包 下载地址:[https://github.com/senzhk/ADBKeyBoard/blob/master/ADBKeyboard.apk](https://github.com/senzhk/ADBKeyBoard/blob/master/ADBKeyboard.apk) - 安装后在手机`设置-输入法` 或者 `设置-键盘列表` 中启用 `ADB Keyboard` 才能生效 + +> 接下来介绍,各个环境配置以及验证使用。只想看效果的,可以翻看到最后(使用效果)。 + +### 2. 算力部署 + +目前具备 AI 算力的服务器(支持小时购买的,关机不收费); + +- [www.autodl.com](https://www.autodl.com/home) - `推荐 vGPUT-48GB,推荐 717机、708机` +- [www.ucloud.cn](https://passport.ucloud.cn/?cps_code=5704U7oL0BOGDYCoSmU0pj) +- [https://gcs-console.jdcloud.com/instance/create?region=cn-central-xy1](https://gcs-console.jdcloud.com/instance/create?region=cn-central-xy1) - `2*24GB` + +
+ +
+ +> 注意,选择2卡,单卡24G的,否则大概率会失败。 + +#### 2.1 创建实例(autodl) + +##### 2.1.1 创建选择 + +地址:[https://www.autodl.com/create](https://www.autodl.com/create) + +
+ +
+ +##### 2.1.2 创建完成 + +地址:[https://www.autodl.com/console/instance/list](https://www.autodl.com/console/instance/list) - `控制台` + +
+ +
+ +- 创建并开机后,稍等即可看到GPU服务运行。 +- 注意,蓝色字 JupyterLab 是你登录地址,可以进入控制台部署模型。 + +> 其他的 GPU 服务器也都类似,如果使用的纯白 GPU 服务器,需要自己安装各种环,可参考;境。[https://bugstack.cn/md/algorithm/model/2023-05-21-chatglm-6b.html](https://bugstack.cn/md/algorithm/model/2023-05-21-chatglm-6b.html) + +#### 2.2 模型部署 + +##### 2.2.1 进入终端 + +
+ +
+ +- 注意,进入后,要把服务和软件安装到 `/root/autodl-tmp` 下,否则系统盘安装满了,就不能运行了。 + +##### 2.2.2 拉取代码 + +
+ +
+ +- 进入到 `/root/autodl-tmp` 拉取项目工程代码 `git clone https://github.com/zai-org/Open-AutoGLM.git` + +##### 2.2.3 更新文件(requirements.txt) + +
+ +
+ +```java +Pillow>=12.0.0 +openai>=2.9.0 + +# For Model Deployment +# Linux 云服务器环境下可以正常安装这些包 +transformers>=4.30.0 +vllm>=0.12.0 + +# Optional: sglang (如果需要的话) +# sglang>=0.5.6.post1 + +# Optional: for development +pytest>=7.0.0 +pre-commit>=4.5.0 +black>=23.0.0 +mypy>=1.0.0 +``` + +- 这份文件需要更新下,默认是关闭的。 + +##### 2.2.4 安装依赖 + +
+ +
+ +```java +pip install -r requirements.txt +pip install -e . +``` + +- 设置镜像源;`pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple` +- `cd Open-AutoGLM` 以此执行安装脚本。这个过程需要一段时间。如果有失败,可以重复执行脚本。 + +##### 2.2.5 下载模型 + +下载模型是为了启动 `Open-AutoGLM`,如果不手动下载,默认执行脚本速度比较慢,同时可能把文件安装到系统盘中。 + +
+ +
+ +- 官网地址:[https://huggingface.co/zai-org/AutoGLM-Phone-9B/tree/main](https://huggingface.co/zai-org/AutoGLM-Phone-9B/tree/main) + +- 镜像地址:[https://modelscope.cn/models/ZhipuAI/AutoGLM-Phone-9B](https://modelscope.cn/models/ZhipuAI/AutoGLM-Phone-9B) - `【下载模型】里面有对应的使用说明` + +
+ +
+ +使用说明: + +- 在下载前,请先通过如下命令安装ModelScope `pip install modelscope` +- 指定路径,下载完整模型库 `modelscope download --model ZhipuAI/AutoGLM-Phone-9B --local_dir ./AutoGLM-Phone-9B` + +##### 2.2.6 模型部署 + +**脚本说明** - `固定大小的参数不能修改` + +```java +python3 -m vllm.entrypoints.openai.api_server \ + --served-model-name autoglm-phone-9b \ + --allowed-local-media-path / \ + --mm-encoder-tp-mode data \ + --mm_processor_cache_type shm \ + --mm_processor_kwargs "{\"max_pixels\":5000000}" \ + --max-model-len 25480 \ + --chat-template-content-format string \ + --limit-mm-per-prompt "{\"image\":10}" \ + --model /root/autodl-tmp/Open-AutoGLM/AutoGLM-Phone-9B \ + --port 6008 +``` + +
+ +
+ +- model 由 Open-AutoGLM 默认的 `zai-org/AutoGLM-Phone-9B` 从 `https://huggingface.co/zai-org/AutoGLM-Phone-9B/tree/main` 下载,修改为已经下载好的本地的路径地址。 +- port 修改为 6008 端口,因为 `autodl.com` 算力指定的自定义服务,对外暴漏的端口有 6008、6006 部署后,用 `https://uu835267-800d-24be97d2.westc.gpuhub.com:8443` 访问服务。 + +**执行脚本** + +
+ +
+ +##### 2.2.7 验证模型 + +
+ +
+ +```java +curl https://cb869967ef619cf1-8000.cn-south-1.gpu-instance.ppinfra.com/v1/chat/completions -H "Content-Type: application/json" -d '{ + "model": "autoglm-phone-9b", + "messages": [ + { + "role": "user", + "content": "打开抖音,连刷5个视频,给第4个视频点赞,第5个视频收藏" + } + ] +}' +``` + +- 这个API和 GPT 一样的格式,可以访问接口。 + +```java +# 交互模式 +python main.py --base-url https://cb869967ef619cf1-8000.cn-south-1.gpu-instance.ppinfra.com/v1 --model "autoglm-phone-9b" + +# 指定模型端点 +python main.py --base-url https://cb869967ef619cf1-8000.cn-south-1.gpu-instance.ppinfra.com/v1 "打开美团搜索附近的火锅店" + +# 使用英文 system prompt +python main.py --lang en --base-url https://cb869967ef619cf1-8000.cn-south-1.gpu-instance.ppinfra.com/v1 "Open Chrome browser" + +# 列出支持的应用 +python main.py --list-apps +``` + +- 根据你部署的模型, 设置 --base-url 和 --model 参数,之后本地就可以验证模型了。 + +### 3. ADB (Android Debug Bridge) - 电脑安装 + +#### 3.1 安装环境 + +1. 下载官方 ADB [安装包](https://developer.android.com/tools/releases/platform-tools?hl=zh-cn),并解压到自定义路径,地址:[https://developer.android.com/tools/releases/platform-tools?hl=zh-cn](https://developer.android.com/tools/releases/platform-tools?hl=zh-cn) +2. 配置环境变量 + +- MacOS 配置方法:在 `Terminal` 或者任何命令行工具里 + +``` +# 假设解压后的目录为 ~/Downlaods/platform-tools。如果不是请自行调整命令。 +export PATH=${PATH}:~/Downloads/platform-tools +``` + +- Windows 配置方法:可参考 [第三方教程](https://blog.csdn.net/x2584179909/article/details/108319973) 进行配置。 + +#### 3.2 验证脚本 + +```java +(base) fuzhengwei@ZBMac-GV47H1GXD Open-AutoGLM % adb devices +List of devices attached +94343646 device + +(base) fuzhengwei@ZBMac-GV47H1GXD Open-AutoGLM % +``` + +- 此时你的电脑USB,链接了手机,会显示出设备ID(如果没显示,检查下数据线等) + +### 4. Android 7.0+ 的设备或模拟器 + +#### 4.1 开启调试模式 + +1. 开发者模式启用:通常启用方法是,找到 `设置-关于手机-版本号` 然后连续快速点击 10 次左右,直到弹出弹窗显示“开发者模式已启用”。不同手机会有些许差别,如果找不到,可以上网搜索一下教程。 + +2. USB 调试启用:启用开发者模式之后,会出现 `设置-开发者选项-USB 调试`,勾选启用 + +3. 部分机型在设置开发者选项以后, 可能需要重启设备才能生效. 可以测试一下: 将手机用USB数据线连接到电脑后, `adb devices` 查看是否有设备信息, 如果没有说明连接失败. + +#### 4.2 安装 ADB Keyboard(用于文本输入) + +下载 [安装包](https://github.com/senzhk/ADBKeyBoard/blob/master/ADBKeyboard.apk) 并在对应的安卓设备中进行安装。 注意,安装完成后还需要到 `设置-输入法` 或者 `设置-键盘列表` 中启用 `ADB Keyboard` 才能生效 + +
+ +
+ +安装包地址:[https://github.com/senzhk/ADBKeyBoard/blob/master/ADBKeyboard.apk](https://github.com/senzhk/ADBKeyBoard/blob/master/ADBKeyboard.apk) - `可以下载好传到手机也可以` + +## 三、测试验证 + +### 1. 使用说明 + +
+ +
+ +- 整个的过程为,你通过命令调用LLM Phone,之后模型返回的结果,通过 ADB 方式,调用`调试模式`的安卓机,完成各项 APP 应用的操作。 + +### 2. 支持应用 + +
+ +
+ +### 3. 使用效果 + +
+ +
+ +```java +python main.py --device-id 94343646 --base-url https://uu835267-800d-0124cb32.westc.gpuhub.com:8443/v1 --model "autoglm-phone-9b" "打开抖音,刷视频" +``` + +- `device-id 94343646` 就是 adb 列出来的设备ID,`base-url 是你的服务地址`,之后可以自行验证,测试各种 APP 的启动,使用等。 +- 像是一些没有的预设的应用以及应用里的流程,他还会截图屏幕,自动分析和使用。也可以是打开其他APP,并执行一些列的流程操作。 + +## 四、其他资料 + +📢 **接下来**,在phone + agent 这个方向,将有越来越多的模型和产品。检索:[https://github.com/search?q=phone%20agent&type=repositories](https://github.com/search?q=phone%20agent&type=repositories) + +
+ +
+ +- https://github.com/mobile-next/mobile-mcp +- https://device-farm.com/doc/ +- https://droidrun.ai/ +- https://github.com/CherryHQ/cherry-studio-app +- https://github.com/minitap-ai/mobile-use \ No newline at end of file diff --git "a/docs/md/assembly/middleware/2019-12-07-\345\217\221\345\270\203Jar\345\214\205\345\210\260Maven\344\270\255\345\244\256\344\273\223\345\272\223\357\274\214\344\270\272\345\274\200\345\217\221\345\274\200\346\272\220\344\270\255\351\227\264\344\273\266\345\201\232\345\207\206\345\244\207.md" "b/docs/md/assembly/middleware/2019-12-07-\345\217\221\345\270\203Jar\345\214\205\345\210\260Maven\344\270\255\345\244\256\344\273\223\345\272\223\357\274\214\344\270\272\345\274\200\345\217\221\345\274\200\346\272\220\344\270\255\351\227\264\344\273\266\345\201\232\345\207\206\345\244\207.md" index 7b87d0a5c..b11591800 100644 --- "a/docs/md/assembly/middleware/2019-12-07-\345\217\221\345\270\203Jar\345\214\205\345\210\260Maven\344\270\255\345\244\256\344\273\223\345\272\223\357\274\214\344\270\272\345\274\200\345\217\221\345\274\200\346\272\220\344\270\255\351\227\264\344\273\266\345\201\232\345\207\206\345\244\207.md" +++ "b/docs/md/assembly/middleware/2019-12-07-\345\217\221\345\270\203Jar\345\214\205\345\210\260Maven\344\270\255\345\244\256\344\273\223\345\272\223\357\274\214\344\270\272\345\274\200\345\217\221\345\274\200\346\272\220\344\270\255\351\227\264\344\273\266\345\201\232\345\207\206\345\244\207.md" @@ -34,6 +34,7 @@ lock: need ## 跟着节奏 ### 1. 下载安装Gpg生成密钥 + 我们需要一个GPG环境,用来对上传的文件进行加密和签名,保证你的jar包不被篡改 >1991年,程序员Phil Zimmermann为了避开政府监视,开发了加密软件PGP。这个软件非常好用,迅速流传开来,成了许多程序员的必备工具。但是,它是商业软件,不能自由使用。所以,自由软件基金会决定,开发一个PGP的替代品,取名为GnuPG。这就是GPG的由来。 diff --git a/docs/md/develop/design-pattern/2024-08-25-chain-tree.md b/docs/md/develop/design-pattern/2024-08-25-chain-tree.md index 6da6da263..3560cd3b7 100644 --- a/docs/md/develop/design-pattern/2024-08-25-chain-tree.md +++ b/docs/md/develop/design-pattern/2024-08-25-chain-tree.md @@ -8,6 +8,8 @@ lock: need 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) + + > 沉淀、分享、成长,让自己和他人都能有所收获!😄 大家伙,我是技术UP主小傅哥。 @@ -26,10 +28,6 @@ lock: need >接下来,小傅哥就给大家分享一个链路执行的设计模式,看看都有哪些方式处理。 -
- -
- ## 一、场景问题 Java 开发,尤其是 Java 业务开发的,就离不开大量的流程分支处理。产品给的需求,也是在编码中调用一系列的接口做流程验证处理。而且需求是频繁变化的,这也就间接的导致了程序员的 if...else 代码也要跟着一次次调整,从原来的几十行编程几百几千行。这个过程中还有一些要去掉的、要根据流程类型选择切换的、要覆盖所有的之前的需求不能出问题的。所以腐化越来越严重,开发成本越来越高。 diff --git a/docs/md/devops/2023-04-18-nginx.md b/docs/md/devops/2023-04-18-nginx.md index fa9235c7a..59ce13887 100644 --- a/docs/md/devops/2023-04-18-nginx.md +++ b/docs/md/devops/2023-04-18-nginx.md @@ -293,18 +293,18 @@ docker run \ ![](https://bugstack.cn/images/article/devops/dev-ops-nginx-230418-04.png) -## 五、OpenAI 访问 +## 五、重定向 -### 1. 重定向 +### 1. default.conf 在 default.conf 中添加如下配置后重启 Nginx 即可; ```shell location /d5fe/ { rewrite ^/d5fe/(.*)$ /$1 break; - proxy_pass https://api.openai.com; + proxy_pass https://api.x.com; proxy_ssl_server_name on; - proxy_set_header Host api.openai.com; + proxy_set_header Host api.x.com; proxy_set_header Connection ''; proxy_http_version 1.1; chunked_transfer_encoding off; @@ -351,9 +351,9 @@ server { location /abc/ { auth_request /auth; rewrite ^/abc/(.*)$ /$1 break; - proxy_pass https://api.openai.com; + proxy_pass https://api.x.com; proxy_ssl_server_name on; - proxy_set_header Host api.openai.com; + proxy_set_header Host api.x.com; proxy_set_header Connection ''; proxy_http_version 1.1; chunked_transfer_encoding off; diff --git "a/docs/md/java/core/2020-11-22-\351\271\277\351\274\216\350\256\260 \302\267 \351\237\246\345\260\217\345\256\235\357\274\214\344\270\275\346\230\245\351\231\242\343\200\201\345\244\251\345\234\260\344\274\232\343\200\201\345\205\245\347\232\207\345\256\253\347\255\211\344\272\224\344\270\252\345\234\272\346\231\257\357\274\214\346\220\255\351\205\215\344\270\215\345\220\214\345\211\247\346\203\205\350\256\262\350\247\243\345\244\232\347\272\277\347\250\213\345\222\214\351\224\201\357\274\214\347\234\237\351\246\231\357\274\201.md" "b/docs/md/java/core/2020-11-22-\351\271\277\351\274\216\350\256\260 \302\267 \351\237\246\345\260\217\345\256\235\357\274\214\344\270\275\346\230\245\351\231\242\343\200\201\345\244\251\345\234\260\344\274\232\343\200\201\345\205\245\347\232\207\345\256\253\347\255\211\344\272\224\344\270\252\345\234\272\346\231\257\357\274\214\346\220\255\351\205\215\344\270\215\345\220\214\345\211\247\346\203\205\350\256\262\350\247\243\345\244\232\347\272\277\347\250\213\345\222\214\351\224\201\357\274\214\347\234\237\351\246\231\357\274\201.md" index 2d7b37cb0..4a66f6632 100644 --- "a/docs/md/java/core/2020-11-22-\351\271\277\351\274\216\350\256\260 \302\267 \351\237\246\345\260\217\345\256\235\357\274\214\344\270\275\346\230\245\351\231\242\343\200\201\345\244\251\345\234\260\344\274\232\343\200\201\345\205\245\347\232\207\345\256\253\347\255\211\344\272\224\344\270\252\345\234\272\346\231\257\357\274\214\346\220\255\351\205\215\344\270\215\345\220\214\345\211\247\346\203\205\350\256\262\350\247\243\345\244\232\347\272\277\347\250\213\345\222\214\351\224\201\357\274\214\347\234\237\351\246\231\357\274\201.md" +++ "b/docs/md/java/core/2020-11-22-\351\271\277\351\274\216\350\256\260 \302\267 \351\237\246\345\260\217\345\256\235\357\274\214\344\270\275\346\230\245\351\231\242\343\200\201\345\244\251\345\234\260\344\274\232\343\200\201\345\205\245\347\232\207\345\256\253\347\255\211\344\272\224\344\270\252\345\234\272\346\231\257\357\274\214\346\220\255\351\205\215\344\270\215\345\220\214\345\211\247\346\203\205\350\256\262\350\247\243\345\244\232\347\272\277\347\250\213\345\222\214\351\224\201\357\274\214\347\234\237\351\246\231\357\274\201.md" @@ -204,9 +204,9 @@ public class ReentrantLockTest { } public static void 招收杂役(String name) throws InterruptedException { - lock.lock(); try { - while (true) { + while (!lock.isLocked()) { + lock.lock(); System.out.println(name + ",排队等待进宫当杂役..."); Thread.sleep(1000); } @@ -227,12 +227,16 @@ public class ReentrantLockTest { - **测试结果**: ```java -路人甲,排队等待进宫当杂役... +路人丙,排队等待进宫当杂役... 韦小宝,进宫当太监,不用排队! -路人甲,排队等待进宫当杂役... -路人甲,排队等待进宫当杂役... -路人甲,排队等待进宫当杂役... -路人甲,排队等待进宫当杂役... +韦小宝,排队等待进宫当杂役... +路人庚,排队等待进宫当杂役... +路人丁,排队等待进宫当杂役... +路人乙,排队等待进宫当杂役... +路人戊,排队等待进宫当杂役... +路人己,排队等待进宫当杂役... +路人壬,排队等待进宫当杂役... +路人癸,排队等待进宫当杂役... 路人甲,排队等待进宫当杂役... ``` diff --git "a/docs/md/java/interview/2020-08-20-\351\235\242\347\273\217\346\211\213\345\206\214 \302\267 \347\254\2546\347\257\207\343\200\212\345\270\246\347\235\200\351\235\242\350\257\225\351\242\230\345\255\246\344\271\240\347\272\242\351\273\221\346\240\221\346\223\215\344\275\234\345\216\237\347\220\206\357\274\214\350\247\243\346\236\220\344\273\200\344\271\210\346\227\266\345\200\231\346\237\223\350\211\262\343\200\201\346\200\216\344\271\210\350\277\233\350\241\214\346\227\213\350\275\254\343\200\201\344\270\2162-3\346\240\221\346\234\211\344\273\200\344\271\210\345\205\263\350\201\224\343\200\213.md" "b/docs/md/java/interview/2020-08-20-\351\235\242\347\273\217\346\211\213\345\206\214 \302\267 \347\254\2546\347\257\207\343\200\212\345\270\246\347\235\200\351\235\242\350\257\225\351\242\230\345\255\246\344\271\240\347\272\242\351\273\221\346\240\221\346\223\215\344\275\234\345\216\237\347\220\206\357\274\214\350\247\243\346\236\220\344\273\200\344\271\210\346\227\266\345\200\231\346\237\223\350\211\262\343\200\201\346\200\216\344\271\210\350\277\233\350\241\214\346\227\213\350\275\254\343\200\201\344\270\2162-3\346\240\221\346\234\211\344\273\200\344\271\210\345\205\263\350\201\224\343\200\213.md" index 00ba3bc3b..b95d6c2e4 100755 --- "a/docs/md/java/interview/2020-08-20-\351\235\242\347\273\217\346\211\213\345\206\214 \302\267 \347\254\2546\347\257\207\343\200\212\345\270\246\347\235\200\351\235\242\350\257\225\351\242\230\345\255\246\344\271\240\347\272\242\351\273\221\346\240\221\346\223\215\344\275\234\345\216\237\347\220\206\357\274\214\350\247\243\346\236\220\344\273\200\344\271\210\346\227\266\345\200\231\346\237\223\350\211\262\343\200\201\346\200\216\344\271\210\350\277\233\350\241\214\346\227\213\350\275\254\343\200\201\344\270\2162-3\346\240\221\346\234\211\344\273\200\344\271\210\345\205\263\350\201\224\343\200\213.md" +++ "b/docs/md/java/interview/2020-08-20-\351\235\242\347\273\217\346\211\213\345\206\214 \302\267 \347\254\2546\347\257\207\343\200\212\345\270\246\347\235\200\351\235\242\350\257\225\351\242\230\345\255\246\344\271\240\347\272\242\351\273\221\346\240\221\346\223\215\344\275\234\345\216\237\347\220\206\357\274\214\350\247\243\346\236\220\344\273\200\344\271\210\346\227\266\345\200\231\346\237\223\350\211\262\343\200\201\346\200\216\344\271\210\350\277\233\350\241\214\346\227\213\350\275\254\343\200\201\344\270\2162-3\346\240\221\346\234\211\344\273\200\344\271\210\345\205\263\350\201\224\343\200\213.md" @@ -48,7 +48,7 @@ Rudolf Bayer 于1978年发明红黑树,在当时被称为`对称二叉 B 树(s 2. 节点是红黑或者黑色 3. 所有子叶节点都是黑色(叶子是NIL节点,默认没有画出来) 4. 每个红色节点必须有两个黑色子节点(也同样说明一条链路上不能有链路的红色节点) -5. 黑高,从任一节点到齐每个叶子节点,经过的路径都包含相同数目的黑色节点 +5. 从任一节点到齐每个叶子节点,经过的路径都包含相同数目的黑色节点 ``` 那么,这些规则是怎么总结定义出来的呢?接下里我们一步步分析讲解。 @@ -195,7 +195,7 @@ Rudolf Bayer 于1978年发明红黑树,在当时被称为`对称二叉 B 树(s ![](https://bugstack.cn/assets/images/2020/interview/interview-7-13.png) -##### 3.2.5 被删节点兄弟为黑色&含双黑节点(黑) +##### 3.2.5 被删节点兄弟为红色&含双黑节点(黑) ![](https://bugstack.cn/assets/images/2020/interview/interview-7-14.png) @@ -213,11 +213,11 @@ Rudolf Bayer 于1978年发明红黑树,在当时被称为`对称二叉 B 树(s ![](https://bugstack.cn/assets/images/2020/interview/interview-7-17.png) -##### 3.2.4 被删节点兄弟为黑色&不含子节点 +##### 3.3.4 被删节点兄弟为黑色&不含子节点 ![](https://bugstack.cn/assets/images/2020/interview/interview-7-18.png) -##### 3.2.5 被删节点兄弟为黑色&含双黑节点(黑) +##### 3.3.5 被删节点兄弟为红色&含双黑节点(黑) ![](https://bugstack.cn/assets/images/2020/interview/interview-7-19.png) diff --git "a/docs/md/java/interview/2020-08-27-\351\235\242\347\273\217\346\211\213\345\206\214 \302\267 \347\254\2547\347\257\207\343\200\212ArrayList\344\271\237\350\277\231\344\271\210\345\244\232\347\237\245\350\257\206\357\274\237\344\270\200\344\270\252\346\214\207\345\256\232\344\275\215\347\275\256\346\217\222\345\205\245\345\260\261\346\212\212\350\260\242\351\243\236\346\234\272\351\235\242\346\231\225\344\272\206\357\274\201\343\200\213.md" "b/docs/md/java/interview/2020-08-27-\351\235\242\347\273\217\346\211\213\345\206\214 \302\267 \347\254\2547\347\257\207\343\200\212ArrayList\344\271\237\350\277\231\344\271\210\345\244\232\347\237\245\350\257\206\357\274\237\344\270\200\344\270\252\346\214\207\345\256\232\344\275\215\347\275\256\346\217\222\345\205\245\345\260\261\346\212\212\350\260\242\351\243\236\346\234\272\351\235\242\346\231\225\344\272\206\357\274\201\343\200\213.md" index a2d5da729..2964200aa 100755 --- "a/docs/md/java/interview/2020-08-27-\351\235\242\347\273\217\346\211\213\345\206\214 \302\267 \347\254\2547\347\257\207\343\200\212ArrayList\344\271\237\350\277\231\344\271\210\345\244\232\347\237\245\350\257\206\357\274\237\344\270\200\344\270\252\346\214\207\345\256\232\344\275\215\347\275\256\346\217\222\345\205\245\345\260\261\346\212\212\350\260\242\351\243\236\346\234\272\351\235\242\346\231\225\344\272\206\357\274\201\343\200\213.md" +++ "b/docs/md/java/interview/2020-08-27-\351\235\242\347\273\217\346\211\213\345\206\214 \302\267 \347\254\2547\347\257\207\343\200\212ArrayList\344\271\237\350\277\231\344\271\210\345\244\232\347\237\245\350\257\206\357\274\237\344\270\200\344\270\252\346\214\207\345\256\232\344\275\215\347\275\256\346\217\222\345\205\245\345\260\261\346\212\212\350\260\242\351\243\236\346\234\272\351\235\242\346\231\225\344\272\206\357\274\201\343\200\213.md" @@ -112,11 +112,11 @@ list.add("ccc"); #### 1.2 方式02;内部类方式 ```java -ArrayList list = new ArrayList() \\{ +ArrayList list = new ArrayList() {{ add("aaa"); add("bbb"); add("ccc"); -\\}; +}}; ``` - 这种方式也是比较常用的,而且省去了多余的代码量。 diff --git "a/docs/md/netty/source-code/2019-09-10-netty\346\241\210\344\276\213\357\274\214netty4.1\346\272\220\347\240\201\345\210\206\346\236\220\347\257\207\344\270\200\343\200\212NioEventLoopGroup\346\272\220\347\240\201\345\210\206\346\236\220\343\200\213.md" "b/docs/md/netty/source-code/2019-09-10-netty\346\241\210\344\276\213\357\274\214netty4.1\346\272\220\347\240\201\345\210\206\346\236\220\347\257\207\344\270\200\343\200\212NioEventLoopGroup\346\272\220\347\240\201\345\210\206\346\236\220\343\200\213.md" index 29d7f599c..c607ae5b2 100644 --- "a/docs/md/netty/source-code/2019-09-10-netty\346\241\210\344\276\213\357\274\214netty4.1\346\272\220\347\240\201\345\210\206\346\236\220\347\257\207\344\270\200\343\200\212NioEventLoopGroup\346\272\220\347\240\201\345\210\206\346\236\220\343\200\213.md" +++ "b/docs/md/netty/source-code/2019-09-10-netty\346\241\210\344\276\213\357\274\214netty4.1\346\272\220\347\240\201\345\210\206\346\236\220\347\257\207\344\270\200\343\200\212NioEventLoopGroup\346\272\220\347\240\201\345\210\206\346\236\220\343\200\213.md" @@ -214,7 +214,7 @@ public class NioEventLoopGroup extends MultithreadEventLoopGroup { - 在创建Netty服务端的时候,代码中实例化了两个EventLoopGroup分别是parentGroup、childGroup,parentGroup 主要用于接收请求链接,链接成功后交给childGroup处理收发数据等事件。 - - NioEventLoopGroup可以在构造方法中传入需要启动的线程数,默认的情况下他会在采用计算机核心数*2的方式去启动线程数量。另外目前很多计算机采用了超线程技术,那么4核心的机器,超线程后就是8核心,Netty在启动的时候随时会启动8*2=16个线程。 + - NioEventLoopGroup可以在构造方法中传入需要启动的线程数,默认的情况下他会在采用计算机核心数 * 2的方式去启动线程数量。另外目前很多计算机采用了超线程技术,那么4核心的机器,超线程后就是8核心,Netty在启动的时候随时会启动8*2=16个线程。 >超线程(HT, Hyper-Threading)是英特尔研发的一种技术,于2002年发布。超线程技术原先只应用于Xeon 处理器中,当时称为“Super-Threading”。之后陆续应用在Pentium 4 HT中。早期代号为Jackson。 [1] 通过此技术,英特尔实现在一个实体CPU中,提供两个逻辑线程。之后的Pentium D纵使不支持超线程技术,但就集成了两个实体核心,所以仍会见到两个线程。超线程的未来发展,是提升处理器的逻辑线程。英特尔于2016年发布的Core i7-6950X便是将10核心的处理器,加上超线程技术,使之成为20个逻辑线程的产品。 diff --git a/docs/md/product/idea-plugin/vo2dto-v2.5.5.md b/docs/md/product/idea-plugin/vo2dto-v2.5.5.md new file mode 100644 index 000000000..d897ddfd9 --- /dev/null +++ b/docs/md/product/idea-plugin/vo2dto-v2.5.5.md @@ -0,0 +1,163 @@ +--- +title: IDEA Plugin vo2dto v2.5.5 +lock: no +--- + +# IDEA Plugin vo2dto —— 这款插件,已经有20k安装量,月增量1000+! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +公司明确要求禁止在项目中使用 `BeanUtils.copyProperties` 复制对象,不仅是因为性能问题,更多是这种方式根本不知道有哪些对象属性被转换了。而手动编码 x.set(y.get) 是最稳定可靠处理方式。 + +但如果有几十个属性怎么办😰!那么你可以立即安装这款免费的 vo2dto v2.5.5 版本插件。截止到目前小傅哥开发的这款插件已经有 20.1k 安装量! + +
+ +IDEA Plugin vo2dto 是一款用于帮助使用 IntelliJ IDEA 编写代码的研发人员,快速生成两个对象转换过程中所需要大量的 `x.set(y.get)` 代码块的插件工具。在最新 v2.5.1 版本中已支持 Lombok.Builder 模式,让使用可丝滑得嘞! + +>文末提供了此插件的源码地址,你可以针对使用优化提交PR,以后那么多人的使用,都会看见你的贡献💐。 + +## ✨ 特性 + +1. 2个对象的转换操作,通过复制 X x 对象,转换给 Y y 对象 +2. 允许使用 lombok 对象转换、lombok 和普通对象转换,对于 serialVersionUID 属性过滤 +3. 支持类继承类,全量的对象转换操作 +4. 含记忆功能的弹窗选择映射关系,支持全量对象、支持匹配对象、也支持空转换,生成一组set但无get的对象 +5. 支持对于引入不同包下的同名类处理 +6. 支持 Lombok.Builder 模式创建转换对象 +7. 支持类的内部类对象,进行转换 + +## 👨🏻‍💻 重构 + +**这次我要说说重构!** + +其实最开始这个项目并不大,简单的建了个抽象模板类定义执行步骤,方法都写在子类里。三下五除二就完成了对象转换功能。 + +但随着小伙伴们不断的提出一些使用诉求后,这里的逻辑变得的复杂了,并且由于本身 IDEA Plugin 的开发,很多时候都要一点点的处理那些对象属性的数据,兼容各种类文件所在的包信息,还有Lombok以及类的内部类。所以,每次维护起来都像是重新写一遍一样。**时间一长,都不认识它了!** + +所以,为了改变这种情况。在 v2.5.5 版本的开发中,做了首次的工程重构,把流水面条的代码,用规则树拆分,让不同的节点实现不同的功能。优雅的效果,如图; + +
+ +这是一套规则树的模型结构,在 vo2dto 插件开发中的实践使用。关于这块的设计模式可以在这里学习;[https://bugstack.cn/md/develop/design-pattern/2024-08-25-chain-tree.html](https://bugstack.cn/md/develop/design-pattern/2024-08-25-chain-tree.html) + +通过节点功能对逻辑边界的拆解,让每一块功能区都可以显而易见的找到和处理,这样即使是过去很长时间,在看这段代码也能很轻松的知道每一块在干什么。其实代码写的最好的目标就是看代码就像看文档,用类划分边界比只单纯的叠加方法要清晰的多。 + +
+ +- 重构前:[https://github.com/fuzhengwei/vo2dto/tree/2.5.4](https://github.com/fuzhengwei/vo2dto/tree/2.5.4) +- 重构后:[https://github.com/fuzhengwei/vo2dto/tree/2.5.5](https://github.com/fuzhengwei/vo2dto/tree/2.5.5) + +如果感兴趣这样一个处理,可以进入到重构前后的代码,看看设计模式如何处理的这部分逻辑,怎么拆分的上下文逻辑。可以说非常优雅! + +## 🛠️ 安装 + +### 1. 在线安装 + +| IDEA Plugin 搜索vo2dto直接在线安装即可| +|:---:| +|
| + +### 2. 手动安装 + +- 下载:[https://github.com/fuzhengwei/vo2dto/releases/tag/v2.5.5](https://github.com/fuzhengwei/vo2dto/releases/tag/v2.5.5) +- 安装: + +| IDEA Plugin 手动安装,导入下载包 | +|:------------------------:| +|
| + +## 🔨 使用 + +- 视频:[https://www.bilibili.com/video/BV13Y411h7fv](https://www.bilibili.com/video/BV13Y411h7fv) - `视频内有完整的使用介绍和插件设计` +- 描述:你需要复制被转换 X x = new X() 中的 X x 部分,无论它是方法入参还是实例化或者是接口回值,接下来鼠标定位到转换对象 Y y 上,可以定位到`类 大Y`、或者`属性 小y`,这样我就可以知道你要做到是X的对象的属性值,转换到Y对象的属性值上。接下来帮你快速生成全部的 `y.set(x.get)` 代码片段。 + +| IDEA Plugin vo2dto 使用演示图| +|:---:| +|
| + +```java +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +public class ApiTest { + + /** + * 普通模式 + */ + public void test_vo2dto01(UserVO user) { + UserDTO userDTO = new UserDTO(); + userDTO.setUserId(user.getUserId()); + userDTO.setUserNickName(user.getUserNickName()); + userDTO.setUserHead(user.getUserHead()); + } + /** + * lombok Builder 模式 + */ + public void test_vo2dto02(UserVO user) { + UserDTO userDTO = UserDTO.builder() + .userId(user.getUserId()) + .userNickName(user.getUserNickName()) + .userHead(user.getUserHead()) + .build(); + } + + /** + * 类的内部类转换 + */ + public void test(UserDTO userDTO) { + UserVO.UserVO2 userVO2 + + } + + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + static class UserDTO { + + private String userId; + private String userIdx; + private String userNickName; + private String userHead; + private int page; + private int rows; + + } + + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + static class UserVO { + + private Long id; + private String userId; + private String userNickName; + private String userHead; + private String userPassword; + private Date createTime; + private Date updateTime; + + } + +} +``` + +- 注意;v2.5.5 版本已支持了 `类的内部类` 模式,如图使用方式即可完成创建过程。 + +## 💐 成长 + +如果你的简历也能有一个这样的小组件,让那么多的程序员👨🏻‍💻进行使用,那么对你的面试简历来说也是非常亮眼的一笔。 + +包括;这样的组件,还有;OPenAI 代码自动评审、透视业务监控、动态线程池,以及大量的业务项目;大营销平台、小型支付商城、拼团交易等,你都可以跟着小傅哥一起学习。👣 踩在我的肩膀,你能看的更远,走的更快,上的更高! + diff --git a/docs/md/product/software/walicode.md b/docs/md/product/software/walicode.md new file mode 100644 index 000000000..7524636d8 --- /dev/null +++ b/docs/md/product/software/walicode.md @@ -0,0 +1,115 @@ +--- +title: WaLiCode,AI IDE Coding! +lock: no +--- + +WaLiCode - 小傅哥出品,研发自己人的 AI IDE Coding ! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥! + +得益于 Claude Code 的被动开源 😂 (~~怀疑是故意的~~),市面上出现了非常多的 Claude Code 源码架构设计分析,这也让我们看到了非常精彩的 +AI Agent 运行时设计技巧。按照剧本套路,我们使用的 AI IDE 将迎来一大波迭代升级。**嘿嘿,但这次,我先下手啦!** + +
+ +
+ +**小傅哥的 WaLiCode,AI IDE Coding v0.1.0 发布!** + +市面上优秀的 AI IDE 非常多,但论最好用的还得是 Claude Code。所以借助于这些的“源码”学习,小傅哥基于 Tauri(Rust)桥接 Claude +Code 能力(这个设计也可以桥接其他的,如 OpenCode),在上层做一套 AI IDE 应用服务实现。通过工程、工程、代码块(含图片)对话的方式,驱动代码开发辅助提效处理。 +`也让大家可以通过 WaLiCode 感受到 Claude Code 的巴士体验!` + +
+ +
+ +> WaLiCode 产品功能还在快速迭代中,可以扫码加入群聊,关注最新动态和讨论使用! + +## 一、产品介绍 + +**产品官网**:[https://walicode.xiaofuge.cn/](https://walicode.xiaofuge.cn/) - 提供了下载安装包( +`如果遇到什么bug,可以群里交流`)。 + +WaLiCode,本地运行的 AI 编程助手。基于 Tauri + Claude Code 底层能力桥接,深度集成文件系统与终端,让 AI 真正帮你写代码,而不只是给建议。更为重要的是你可以,你可以直接本地安装 WaLiCode 就能体验到 Claude Code 的编码能力! + +在辅助编码中,可以直接把代码块、文件、图片放入对话框作为上下文,AI 会结合项目结构与依赖关系给出更准确的修改建议,并可通过 +Diff 预览后安全应用到本地代码。 + +但当然,我还是一个配角,小配角!我还有很多功能需要迭代,让研发伙伴使用这款工具,可以在学习源码、了解项目、深入功能、俯瞰架构等方面,都能有所帮助。 +**好吧,让我们一起期待,WaLiCode 的迭代!** + +## 二、使用演示 + +### 1. 模型配置 + +
+ +
+ +- 多厂家模型灵活配置,支持自定义 OpenAI 格式的各类大模型接口,无论是智谱、火山引擎还是本地部署的模型,均可一键接入,满足不同场景的开发需求。 +- 各类的 token/coding plan,支持 OpenAI 格式就可以配置使用。 + +### 2. 产品首页 + +
+ +
+ +- 首先,安装软件后,打开 WaliCode 在初次使用会引导你配置 apikey,可以添加你需要的模型。得益于 Claude Code 和 WaliCode + 的扩展,上下文的使用会非常准确和节省,也就让你的模型消耗也会很低。 +- 之后,你可以打开文件夹选择自己的工程,进行对话框对话,以及智能终端对话。在对话中,你可以把模块、文件、代码以及图片,都放到对话框中,之后进行诉求描述。 + +### 3. 添加技能(Skills) + +
+ +
+ +- 在设置中可以添加你需要扩展的 Skills 技能,支持zip包上传、git地址直接拉取,可以非常方便的扩展 Skills。 +- 同时还为你提供了 SkillMP、ClawHub 官网 Skills 地址,随时去找你需要的技能扩展到工程里。 + +### 4. 添加服务(MCP) + +
+ +
+ +- 在设置中可以添加 MCP 服务能力,支持 stdio、sse、json 多种配置方式。极大的方便用户扩展自己的功能使用场景。 + +### 5. 智能终端 + +
+ +
+ +- 这是一个附属功能,方便用户可以在终端直接使用 Claude Code 能力。属于原生的扩展支持。 + +### 6. Git 能力 + +
+ +
+ +- 内置 Git 操作面板,支持分支切换、代码提交与状态查看。结合 AI 能力,还能自动分析变更并生成规范的提交信息。 + +> 好嘞,欢迎下载体验 [https://walicode.xiaofuge.cn/](https://walicode.xiaofuge.cn/) 遇到问题可以群里交流 😄 + +## 三、扩展学习(AI Agent) + +如果你希望自己不只是一个业务开发工程师,也具备 AI Agent 开发能力,让自己在这个 AI +时代做点什么,那么下面的教程你可以学习下。小傅哥也是在这些项目中积累的经验,可以一次次在 AI 快速迭代中,做一些有意思的事情。 + +
+ +
+ +小傅哥的社群星球「码农会锁」,现已经有20个实战项目,6个AI、5个业务、8个组件 + 1套源码(MyBatis),这6个AI项目,你可以按需选择学习。 + + + diff --git a/docs/md/project/ai-agent-scaffold/ai-agent-scaffold.md b/docs/md/project/ai-agent-scaffold/ai-agent-scaffold.md new file mode 100644 index 000000000..e1bb88f93 --- /dev/null +++ b/docs/md/project/ai-agent-scaffold/ai-agent-scaffold.md @@ -0,0 +1,297 @@ +--- +title: AI Agent 脚手架 + 场景应用 +lock: no +--- + +# 《AI Agent 脚手架 + 场景应用》- 综合 Spring AI、LangChain4j + Google ADK(a2a、mcp、skills),打造全新智能体架构方案。 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
项目:[https://t.zsxq.com/a8AJj](https://t.zsxq.com/a8AJj) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +💥炸了!**日更,日更,接下来这套新项目,即刻开启日更!** 是的,小傅哥又一个新 AI 项目来啦。可以说,现阶段 AI 是每个工程师都必备的技术技能。 + +从 `RAG` 到 `MCP`、`A2A` 再到 `Skills`,一系列的 AI 编程技术技能陆续迭代更新, +各个互联网企业也随之跟进开发自身的 AI Agent 智能体,解决业务场景问题。 + +因此你在 Boss 直聘,校招/社招,都能看到大量的 AI 应用开发岗位。`AI 没让程序员工作丢失,反而多了更多的岗位!` + +
+ +
+ +新项目,📅于25年12月初启动,26年2月底完结,将近耗时90天打造精品企业级智能体解决方案项目。 + +在小傅哥社群,`OpenAI 代码自动评审做了`、`OpenAI 应用 + 扫码登录 + 微信支付 + 敏感词过滤 + SDK 开发做了`、`AI Agent 可视化编排也做了`、`AI MCP 网关深入理解 MCP 协议还做了`! + +那为什么还要做一个 AI Agent 呢?🤔🤔🤔 + +因为 **【AI Agent 可视化编排】** 解决的是横向通用性场景方案,而本次要做的 **【AI Agent 脚手架 + 场景方案】** 是纵深业务场景细化方案(也是企业里必备的架构设计,针对细化场景,通用的编排就失效啦!)。`这些东西,不是个架构师带着你,那你就根本理解不到!` + +好,该项目为大家带来一套企业级 AI Agent 智能体脚手架底座及场景应用方案的实战编程项目。项目采用 `Spring AI`、`Langchain4j(对照学习)` + `Google ADK`(a2a 框架 + 工作流编排),融合 `MCP`、`Skills`、`Plugin`、`Session` 等多项智能体开发技术,构建通用智能体脚手架工程。 + +并借助该脚手架,用户能够快速高效地搭建各类智能体应用场景。就像本次项目,既带着你搭建脚手架,也带着你使用脚手架做场景用(价值超级大,还要带着你做手机版大龙虾 MobileOpenClaw 🦞!)。 + +
+ +
+ +**💻 每个工程师,都需要AI应用编程技能!** + +竹外桃花三两枝,春江水暖鸭先知🦆。没有哪个行业,有程序员👨🏻‍💻可以这么快的接触到世界的科技变化。甚至也只有程序员行业,可以驾驭 AI 技术,做出各项 AI 应用软件。`AutoPhone`、`OpenClaw`,码农正在加速改变这个世界! + +> 当前互联网企业,Java 有庞大的市场,如美团、京东、阿里、饿了么、滴滴等。这些业务都要大量的引入 AI 进行提效,如;客服、巡检、运营、监控等。因为这些业务本身也都是基于 Java 构建,背靠 Spring 框架。所以很多公司也就天然的选择了 Spring AI 框架开发智能体应用。包括;阿里还基于 Spring AI 做了 alibaba 版本,谷歌也做了 google adk 框架。现在你懂了,为什么我们选择 Spring AI 实现业务智能体项目了吧!当然,这些框架也都类似,选择一套学习后,其他的也都很容易上手。 + + + +>🧧 文末提供了本套项目的完整工程代码,此外还有其他的业务项目 + 组件项目,共计20个全部可以获取。 + +## 一、我能学到什么 + +首先,这是一整套从0到1,文档 + 视频 + 源码,包含前后端 + DevOps 的综合实战项目。带着大家进行需求分析、底座构建、脚手架设计、应用场景实践。所以,你可以非常完整的学习到关于 AI Agent 智能体的全部内容,让你具备企业级项目开发能力。 + +- 【后端】熟练 Spring AI、Langchain4j(对照学习)框架的使用知识,掌握 api、model、client 的组装构建。 +- 【后端】深入 Spring AI 框架,使用 spring-ai-community 包,引入 Agent Skills 技能。 +- 【后端】设计多种 MCP 加载策略,满足 local、sse、stdio 各种类型的加载操作。 +- 【后端】运用 Google ADK 框架,整合 Spring AI、Langchain4j 分别验证学习,做好技术调研。 +- 【后端】使用 Google ADK 框架,通过提供的 loop(循环)、parallel(并行)、sequential(串行),构建多样性智能体。 +- 【后端】通过 Google ADK 框架,掌握 Runner 运行插件机制,掌握智能体运行中各个节点的数据采集和控制操作。 +- 【后端】设计通用智能体配置 yml 文件,通过配置文件的内容编排,可以配置出复杂的智能体。 +- 【后端】深入 Google ADK 源码,调试源码找到bug,并提供解决方案。已经在google adk 发布了[issue #705 - 小傅哥为 Google ADK 框架,提交的 issue 记录](https://github.com/google/adk-java/issues/705) +- 【后端】拓展设计模式的使用,在智能体构建中,使用规则树模式进行各个节点的编排。编排依赖于 agent.yml 文件的配置。这是非常灵活的设计。 +- 【后端】基于 Maven 脚手架构建方式,对底座工程创建出通用脚手架项目。 +- 【后端】积累 Netty 通信技术,基于 Netty 构建通信网关。 +- 【前端】安卓 Android(Kotlin) 网关终端开发,做智能设备控制。`基于 AutoPhone 9B + OpenClaw 理解,构建 MobileOpenClaw` +- 【前端】使用 React 构建前端工程 + draw.io,实现出一套智能体绘图操作。这部分会结合 AI IDE + prompt 进行编程实现。 +- 【运维】在云服务器环境(Ubuntu 24)安装 Docker 环境 + Protainer 管理面板,以及初始化环境等(提供了一件安装脚本)。 +- 【运维】分别对前后端进行 docker 镜像构建,以及在云服务器上完成项目的部署操作。 +- 【其他】积累应用设计经验,面向对象开发,在整个工程实现中,都有非常干净,清晰,具备高内聚,低耦合,有单一职责的逻辑体现。 + +>小傅哥带着你做的是企业级项目架构和技术积累,通过这些东西的学习,在面试中与面试官交流,才会显得更为专业。 + +## 二、适合哪些伙伴 + +- 需要快速🔜写到简历(每个阶段完成都可以写简历),用于秋招/社招面试(本项目可快速部署验证结果)。 +- 对 AI Agent 智能体感兴趣,但不知道如何自己实现一套的。 +- 希望提高自己的架构设计思维,设计模式运用的。 +- 增强核心竞争力,储备一些非业务的核心技术类知识的。 +- 需要掌握 Spring AI、Langchain4j、Google ADK 框架使用。 + +## 三、项目是否硬核 + +很多小伙伴都害怕学习到一个`(前端)外壳漂亮`,`(后端)代码水货`的项目,满是 CRUD 缺少架构设计,也没有编程思维的体现。这样的项目,在面试后端工程师的时候,很难讲出东西。所以,这里小傅哥先把一些核心的架构设计给大家看看,让大家知道小傅哥带着你学习的东西质量如何。 + +### 1. 智能体整体设计 + +
+ +
+ +- 2025年11月27日,Google 正式在 Maven 仓库管理中心,推送了 0.4.0 版本 ADK,该版本新增加了 Spring AI 的集成。[google-adk-spring-ai](https://central.sonatype.com/artifact/com.google.adk/google-adk-spring-ai) 至此,也因此,小傅哥决定基于这套服务组合,设计智能体脚手架。 +- 首先,Google ADK 是一个智能体框架,他自身也是支持直接对接各类大模型的 API,以及构建 ChatModel 的。但在整合 Spring AI、LangeChain4J 以后,Google ADK 的使用,将会得到已经使用上述组件的公司更大的青睐。 +- 之后,Spring AI 解决的 AI 对接的前半部分,让你可以把 AI API、Model、Prompt、RAG、Tool(Function、MCP)等,非常方便的构建出一个单一的 AI Agent 服务(也可以称之为是一个客户端)。 +- 然后,Google ADK 解决的是,多个 AI Agent 怎么协同工作的问题。这里包括,Sequential 序列顺序执行、Loop 循环执行、Parallel 并行执行,而这些执行方式,又可以组合搭配的配置到一个 Sequential 中进行顺序执行(注意图中颜色)。绿色的是大模型服务,绿色部分可以被深黄色或者浅青色包装,之后在组合到 SequentialAgent - 序列执行中。 +- 最后,Google ADK 提供了记忆上下文 Runner 执行器(也可以自己扩展实现),在这里又提供了钩子插件,你可以对执行过程中的流程,进行拦截。这个过程类似 Spring 容器中对 Bean 对象的处理,before、after 的过程。 + +### 2. 系统的分层结构 + +如图,整体简要架构设计(剥离其他流程,方便理解); + +
+ +
+ +整个应用架构分为3层,包括;基础底座、脚手架、业务场景; + +- 基础底座,负责整 Spring AI + Google ADK 框架的使用,这里的重点在于整个智能体工作流程的设计和使用(第2部分20节课程)。 +- 脚手架,将基础底座使用 maven 抽取出脚手架,脚手架可以让我们快速复刻出一套基础工程(第3部分3节)。 +- 业务场景,结合 draw.io 绘图操作 + ai agent 智能体,做一套AI交互式画图系统(第4部分6节)。 + +### 3. 底座的运行流程 + +
+ +
+ +- 首先,从用户基于脚手架创建完成后,在使用 YML 文件进行智能体的配置,之后在启动项目后,会进行一些利的装配。api、model、agent、workflow、runner,再到 spring 容器。 +- 其中,关于智能体的工作流组装是非常巧妙的,可以自由组合出多种类型智能体。这部分不需要硬编码即可完成。 +- 最后,是整个内容装配完成后,提供了通用的接口能力可以进行对话。 + +### 4. 脚手架配置发布 + +
+ +
+ +- 左侧,对现有工程使用 maven-archetype-plugin 插件,构建工程脚手架。将当前的工程打包成一个可复用的 Archetype 模板。 +- 中间,打包好的脚手架,可以在本地直接使用,也可以发布jar到私服,让大家都可以使用。私服部分,后续在做处理。 +- 右侧,使用方可以基于命令,或者 IntelliJ IDEA 配置 Maven 脚手架的方式,创建和启动工程。这一节,我们先通过命令的方式使用。 + +## 四、应用场景举例 + +### 1. 普通对话 + +
+ +
+ +- 智能体搭建后,可以进行对话操作,基于你配置的 MCP 能力,它可以做很多事项。 + +### 2. draw.io + 画图 + +
+ +
+ +```java +agents: + # 1. 需求分析与检索智能体 + - name: agent_analyst + description: 负责理解用户意图,调用工具检索信息,并决定是请求补充信息还是继续绘图。 + instruction: | + 你是一个专业的需求分析师。你的任务是分析用户的绘图请求。 + 1. 如果用户提供了具体的上下文或需要引用外部知识(如Git仓库、本地文件),请使用可用的工具(MCP)进行检索和分析。 + 2. 分析用户的意图: + - 如果用户的描述模糊、不完整,无法直接生成图表,你需要返回 JSON 格式要求用户补充信息。 + 格式:{"type": "user", "content": "请补充关于...的具体信息"} + - 如果用户意图清晰,请整理出详细的绘图需求(图表类型、节点、关系、布局要求等)。 + 3. 输出你的分析结果。 + output-key: analysis_result + # 2. 绘图执行智能体 + - name: agent_drawer + description: 根据分析结果生成 Draw.io 的 XML 数据。 + instruction: | + 你是一个 Draw.io 绘图专家。请根据输入 {analysis_result} 进行操作: + 1. 如果输入是 {"type": "user", ...},请直接原样输出该 JSON。 + 2. 如果输入是详细的绘图需求: + - 设计图表的结构(UML、流程图、时序图等)。 + - 生成符合 Draw.io 规范的 XML 代码。 + - 确保节点布局合理,逻辑清晰,连线不能交叉等。 + - 输出生成的 XML 内容。 + output-key: draft_diagram + # 3. 检查与优化智能体 + - name: agent_reviewer + description: 检查绘图结果,确保无连线交叉等问题,并格式化最终输出。 + instruction: | + 你是一个图表质量检查员。请审查输入 {draft_diagram}: + 1. 如果输入是 {"type": "user", ...},请直接原样输出。 + 2. 如果输入是 XML 代码: + - 检查连线是否混乱或有严重的交叉(在文本层面尽力优化布局逻辑)。 + - 检查 XML 语法是否正确。 + - 如果有问题,请尝试修正 XML。 + - 最终输出必须严格符合 JSON 格式: + {"type": "drawio", "content": "这里放最终的XML字符串"} + output-key: final_result +``` + +- ai agent + draw.io,可以配置出一套交互式绘图智能体。我们可以把诉求发给 AI,之后 AI 进行分析和决策,让用户补充信息或者直接画图。 +- 在大量的测试和体验中,这套智能体 + gpt 5.1 可以绘制出非常符合企业中真实场景的流程图,效果还是非常不错的。如果你还配置 mcp 可以结合本地代码库,文档库,产品PRD库,那么它还可以更好的绘制出相关的流程图。 + +### 3. AutoPhone 实验性场景 + +智谱发布过一个 [Open-AutoGLM](https://github.com/zai-org/Open-AutoGLM) 类似于豆包手机,可以通过指令发送 AI,AI 操作手机完成一系列动作。目前官网这套产品目前使用的是 ADB 连接手机,数据线调试方式。 + +- 文档(手机 + Agent):[https://bugstack.cn/md/algorithm/model/autoglm-phone-agent.html](https://bugstack.cn/md/algorithm/model/autoglm-phone-agent.html) +- 官网:[https://github.com/zai-org/Open-AutoGLM](https://github.com/zai-org/Open-AutoGLM) + +这里小傅哥在体验了 OpenClaw 大龙虾的设计后,对 AutoPhone 也有了想法。我们可以设计一套安卓版的手机 MobileOpenClaw,在手机端开发一个网关,网关功能具备;`启动应用`、`点击指定坐标`、`输入文本`、`滑动屏幕`等。之后在让 AI 以借助 Socket 通信,对手机设备进行管理。 + +
+ +
+ +- 首先,需要实现一套 MobileOpenClaw 的网关,这部分内容是安卓开发的一个软件,如果 IOS 也还有其他方案。可以在 Github 检索相关资料 [https://github.com/search?q=phone%20agent&type=repositories](https://github.com/search?q=phone%20agent&type=repositories) +- 之后,基于脚手架,开发 MobileOpenClaw 智能体,这部分要通过 Socket 和 手机端进行通信。让 AI 识别用户意图,控制手机端执行相关操作。因为这里大量的视觉识别,所以 gemini-3-pro-preview 效果不错,另外就是 GLM 定制的 [AutoGLM-Phone-9B](https://github.com/zai-org/Open-AutoGLM) 模型,可以自己在 GPU 部署。 + +## 五、课程学习目录 + +全程`视频` + `文档` + `源码`,开局 IntelliJ IDEA + Webstorm + Android Studio,手把手带着你一路狂飙! + +
+ +
+ +>以下2、3、4部分,每部分做完,都可以写简历,也就是最早学习完2部分20节,就可以写一份简历啦! + +### 介绍 + +[AI Agent 脚手架 + 场景应用](#) - 综合 Spring AI、LangChain4j + Google ADK(a2a、mcp、skills),打造全新智能体架构方案。 + +[面试:技能、简历、问题汇总](#) + +### 第1部分:需求与架构 + +- [第1-1节:脚手架需求分析](#) +- [第1-2节:系统架构设计](#) + +### 第2部分:基础底座开发 + +- [第2-1节:工程初始化创建](#) +- [第2-2节:Api功能测试](#) +- [第2-3节:智能体配置表设计](#) +- [第2-4节:装配域结构化定义](#) +- [第2-5节:装配域节点-AiApiNode](#) +- [第2-6节:装配域节点-ChatModelNode](#) +- [第2-7节:装配域节点-AgentNode](#) +- [第2-8节:装配域节点-AgentWorkflowNode](#) +- [第2-9节:装配域节点-Loop、Parallel、Sequential](#) +- [第2-10节:装配域节点-RunnerNode](#) +- [第2-11节:智能体加载使用验证](#) +- [第2-12节:增强装配-RunnerNode](#) +- [第2-13节:增强装配-AgentWorkflowNode](#) +- [第2-14节:增强装配-本地mcp](#) +- [第2-15节:增强装配-回调plugin](#) +- [第2-16节:fix-多模态能力使用](#) +- [第2-17节:会话服务接口实现-service](#) +- [第2-18节:会话服务接口实现-trigger](#) +- [第2-19节:会话服务接口对接-ui](#) +- [第2-20节:增强装配-skills](#) + +### 第3部分:脚手架工程化 + +- [第3-1节:Maven脚手架配置](#) +- [第3-2节:上传jar到maven仓库](#) +- [第3-3节:部署脚手架网页](#) + +### 第4部分:业务场景(ai+draw.io) - `这部分内容非常有实用价值!` + +- [第4-0节:ai + draw.io 产品设计](#) +- [第4-1节:初始化工程搭建](#) +- [第4-2节:在页面嵌入draw.io组件和对话框](#) +- [第4-3节:智能体API接口对接](#) +- [第4-4节:AI+用户+DrawIO,交互式画图](#) +- [第4-5节:ai-draw-io,云服务器部署](#) + +### 第5部分:业务场景(MobileOpenClaw)- `这部分内容非常有意思!` + +- [第5-0节:MobileOpenClaw 产品设计](#) +- [第5-1节:初始化工程搭建](#) +- [第5-2节:手机网关能力设计](#) +- [第5-3节:通过 Netty 进行同步等待通信](#) +- [第5-4节:智能体初步配置使用](#) +- [第5-5节:智能体工作流设计](#) +- [第5-6节:异步结果响应](#) +- [第5-7节:图片位点识别增强](#) +- [第5-8节:多版本安卓版本策略支持](#) +- [第5-9节:会话上下文细化处理](#) + +>星球里另外一套 AI Agent 还对接了 ELK、普罗米修斯、微信公众号等,也可以把 MCP 对接过来进行系统巡检。有了这套脚手架的学习,你可以完成非常多的场景对接使用。 + +## 六、学习路线推荐(AI) + +小傅哥的社群星球「码农会锁」,现已经有20个实战项目,6个AI、5个业务、8个组件 + 1套源码(MyBatis),这6个AI项目,你可以按需选择学习。 + +
+ +
+ +> 综上,所有的实战项目,加入小傅哥社群,全部都可以学习的到! \ No newline at end of file diff --git a/docs/md/project/ai-agent-scaffold/notes.md b/docs/md/project/ai-agent-scaffold/notes.md new file mode 100644 index 000000000..5173d8046 --- /dev/null +++ b/docs/md/project/ai-agent-scaffold/notes.md @@ -0,0 +1,241 @@ +--- +title: 面试:技能、简历、问题汇总 +lock: no +--- + +# 面试:技能、简历、问题汇总 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、项目介绍 + +面试官您好,本套 AI Agent 综合智能体脚手架 项目,主要为降低智能体开发门槛、提升业务系统集成效率而构建。项目涵盖了:`工程脚手架自动生成`、`智能工作流编排`、`多模态交互(文本/绘图/动作)` ,以及`手机自动化网关控制`等核心功能和场景方案。 + +整套项目,核心抽象并拆分了 AI Agent 执行过程所需的各项组件(`Armory 装配域` 、`Runner 执行器` 、 `Skills 技能库`等)到结构化的配置定义中,使其具备自由配置、灵活编排的特性。以此方式,开发者可以结合实际业务场景诉求,像搭积木一样编排复杂的智能体协作流程——例如项目中实现的 "AI + Draw.io 交互式绘图" 和 "Android 手机自动化网关 - MobileOpenClaw" 场景,达到“业务需要什么能力,就组装什么节点”的 AI Auto Agent 效果。 + +该项目在架构设计上,严格遵循 DDD(领域驱动设计) 分层架构进行开发,核心采用了 **组合模式(Composite Pattern)**,构建智能体的执行规则树(支持串行、并行、循环流转),并结合**工厂模式 (创建不同类型的 Agent/Tool 节点)**、 **策略模式 (处理不同的模型调用策略)** 以及 **责任链设计思维模式(这块按照不同的理解,说成规则树也可以) (处理节点间的上下文传递)** 来处理具体流程细节。这种设计不仅解耦了底层模型(支持 Spring AI、Google ADK)与上层业务逻辑,也使得系统在面对未来各类扩展性诉求(如新增 MCP 协议、对接新模型)时,能够更加灵活方便地进行迭代。 + +## 二、简历模板 + +**项目名称**:AI Agent 智能体通用脚手架(可以自己起项目名称) + +**项目架构**:DDD 领域驱动设计(六边形架构)、事件驱动架构、前后端分离、组合模式规则引擎、模块化微服务 + +**核心技术** :Spring Boot 3.4、JDK 17+、Spring AI(LangChain4j)、Google ADK(Application Development Kit)、Kotlin (Android)、MCP (Model Context Protocol)、RAG (Vector Store)、Netty、Websocket、React、Draw.io (mxGraph)、TypeScript、Maven Archetype、Docker、Nginx - `不用都写,可以适当减少。` + +**项目描述** : + +本项目是一套企业级 AI Agent 综合解决方案与标准化脚手架,旨在解决智能体开发中“编排难、落地难、复用难”的痛点。系统基于 DDD 分层架构,创新性地设计了 Armory(装配域) 引擎,将复杂的业务流程抽象为可配置的节点(Node)流转。支持用户通过低代码方式,动态组装 Advisor(顾问) 、 Tools(工具) 和 Workflows(工作流) 。此外基于本套脚手架,实现了从“文本对话”到“自动绘图(Draw.io)”再到“物理设备控制(手机网关)”的全链路智能化。该平台不仅显著降低了 AI 应用的开发门槛,还通过标准化的 MCP 协议,实现了跨生态的能力互通。 + +**核心职责** : + +- 智能体架构设计与 DDD 建模 : + + - 主导系统的领域驱动设计,划分 Armory(装配) 、 Runner(执行) 、 Skill(技能)等核心领域。采用 六边形架构 解耦底层模型依赖(Spring AI / Google ADK),确保系统可无缝切换不同的大模型供应商(OpenAI, Claude, DeepSeek)。 + - 设计基于 组合模式(Composite Pattern) 的执行规则引擎,实现了 Loop(循环优化) 、 Parallel(并行处理) 、 Sequential(串行执行) 等多种编排策略,支持复杂的动态工作流配置。 +- 核心组件抽象与开发 : + + - 拆解并标准化 AI Agent 的核心原子能力,构建了包括 AgentNode (智能体节点)、 AiApiNode (接口节点)、 RouterNode (路由节点)在内的组件库。 + - 设计 DynamicContext(动态上下文) 机制,利用 责任链模式 在节点间传递会话状态与中间结果,解决了多智能体协作时的数据共享与状态一致性问题。 +- 多智能体协作与可视化场景实现(AI + Draw.io)- `这个场景可以独立展开作为一个简历` : + + - 针对业务流程图绘制场景,设计了 Analyst(需求分析) -> Drawer(绘图执行) -> Reviewer(质量审查) 的多智能体协作链路(Multi-Agent System)。 + - 基于 React + Draw.io (mxGraph) 定制前端组件,开发了专门的 JSON 交互协议,使 AI 能够直接生成和修改 XML 图表数据,实现了“一句话生成专业 UML/流程图”的端到端能力。 + - 集成并适配(百度搜索) https://sai.baidu.com 等公开 MCP Server 资源,让绘图可以检索网络资源。 +- 智能体与硬件设备交互(端侧网关建设) - `这个场景可以独立展开作为一个简历` : + + - 开发了 MobileOpenClaw(手机网关) ,通过 Netty 长连接 与 Android 端 AccessibilityService(无障碍服务) 通信,赋予 AI 操作物理设备的能力(点击、滑动、截图)。以 AutoPhone GLM 为参考,做设备通信设计。 + - 使用 auto-glm-9b 模型,分析用户诉求,网关网关入口下达操作指令。让手机端完成用户的行为动作。如;点赞、下单、刷抖音、收藏、发微信,等行为动作。 +- 脚手架工程化与提效 : + + - 设计并发布 Maven Archetype 脚手架,支持一键生成包含完整依赖与最佳实践的 AI 工程代码。 + - 实现了 Agent 预热机制 ,在 Spring 容器启动时动态加载和校验模型配置,支持运营人员在不重启服务的情况下,通过配置中心热更新 Prompt 和编排逻辑。 + +## 三、面试题归档 + +### 项目架构与设计模式 + +#### 1. 请简述本项目的整体架构设计,以及为什么选择 DDD(领域驱动设计)? +**参考答案:** +本项目采用了 **DDD(领域驱动设计)** 配合 **六边形架构(Hexagonal Architecture)**。 +- **分层设计**:将系统划分为 **API 接口层**(Controller/Trigger)、**应用层**(Service/Application)、**领域层**(Domain/Model)和 **基础设施层**(Infrastructure)。 +- **核心优势**: + - **解耦业务与技术**:核心业务逻辑(如 Agent 编排、策略执行)定义在 Domain 层,不依赖具体的 AI 模型(OpenAI/Claude)或数据库实现。通过 **适配器模式(Adapter Pattern)** 在 Infrastructure 层实现具体技术细节,方便随时替换底层 AI 服务商。 + - **高内聚低耦合**:各层职责清晰,便于单元测试和维护。例如,Armory 装配域专注于智能体构建,Chat 领域专注于对话逻辑。 + +#### 2. 在“智能体装配(Armory)”模块中,你是如何处理复杂的配置解析和对象构建的?使用了哪些设计模式? +**参考答案:** +- **设计模式**:核心使用了 **组合模式(Composite Pattern)** 和 **责任链模式(Chain of Responsibility)** 的思想,构建了一个 **节点(Node)处理管道**。 +- **实现逻辑**: + - 将复杂的 Agent 构建流程拆解为一系列独立的 **Node**(如 `AiApiNode` 配置 API、`ChatModelNode` 配置模型、`AgentNode` 实例化智能体、`AgentWorkflowNode` 处理编排)。 + - 定义了统一的 `IArmoryService` 接口和 `AbstractArmorySupport` 抽象类,确保所有节点遵循相同的规范。 + - 使用 **工厂模式(Factory Pattern)**(`DefaultArmoryFactory`)来创建和管理这些节点。 + - 通过 **上下文对象(DynamicContext)** 在节点间传递配置数据,避免了方法参数爆炸,实现了构建逻辑的 **高扩展性**(新增节点只需实现接口并注册即可)。 + +#### 3. 项目中是如何实现 MCP (Model Context Protocol) 的?特别是“本地 MCP”是如何设计的? +**参考答案:** +- **多协议支持**:项目支持 **SSE**(Server-Sent Events)和 **Stdio** 标准协议,通过 `McpClient` 统一封装。 +- **本地 MCP 设计**: + - **策略模式(Strategy Pattern)**:定义了 `ToolMcpCreateService` 策略接口,分别实现了 `SseMcpCreateStrategy`、`StdioMcpCreateStrategy` 和 **`LocalMcpCreateStrategy`**。 + - **反射与 Spring 容器**:**本地 MCP** 的核心是利用 Java 反射机制和 Spring 的 `ApplicationContext`。它根据配置的 `beanName` 和 `methodName` 直接查找并调用本地 Spring Bean 的方法,将其封装为 `FunctionCallback` 提供给 AI 模型。这使得 AI 可以直接调用本地业务代码(如查询数据库、发送邮件),无需走网络协议,**性能更高** 且 **开发更便捷**。 + +--- + +### 二、 并发编程与网络通信 (Netty) + +#### 4. 在“手机网关”模块中,Netty 服务端是如何解决 TCP 粘包/拆包问题的?通信协议是如何设计的? +**参考答案:** +- **粘包/拆包解决方案**:使用了 Netty 自带的 **`LineBasedFrameDecoder`**。 + - **原理**:以换行符 `\n` 作为消息结束的标志。发送端在 JSON 数据后追加换行符,接收端的 Decoder 会自动根据换行符分割出完整的消息帧,从而解决 TCP 粘包和拆包问题。 +- **通信协议设计**:采用 **JSON 文本协议**。 + - **请求**:`{"type": "action", "command": "click", "x": 100, "y": 200}\n` + - **响应**:`{"type": "response", "status": "success", "data": "..."}\n` + - **优势**:协议简单,易于调试(人类可读),且 JSON 解析库成熟。 + +#### 5. Netty 是异步通信的,但业务层调用(如“让手机截图”)通常需要同步等待结果,你是如何实现的? +**参考答案:** +- **核心机制**:使用了 JDK 的 **`CompletableFuture`** 实现 **异步转同步**。 +- **实现步骤**: + 1. **请求映射**:在发送指令前,创建一个 `CompletableFuture` 对象,并将其存入一个线程安全的 `ConcurrentHashMap`(Key 为请求 ID)。 + 2. **同步等待**:业务线程调用 `future.get(timeout)`,进入阻塞等待状态。 + 3. **异步回调**:当 Netty 的 `channelRead` 方法收到客户端响应时,根据响应中的 ID 从 Map 中取出对应的 `future`。 + 4. **唤醒线程**:调用 `future.complete(response)` 将结果填入,此时阻塞的业务线程会被唤醒并获取到结果。 + 5. **超时处理**:如果 `future.get()` 超时,抛出异常并从 Map 中移除该 Future,防止内存泄漏。 + +--- + +### 三、 AI 智能体编排与业务逻辑 + +#### 6. 请介绍一下项目中 Agent 工作流(Workflow)的设计,Loop、Parallel 和 Sequential 节点分别解决了什么问题? +**参考答案:** +项目通过 `AgentWorkflowNode` 实现了类似 **LangChain** 或 **Google ADK** 的编排能力: +- **Sequential(串行编排)**: + - **场景**:任务之间有严格依赖关系。例如:`搜索信息` -> `整理摘要` -> `生成报告`。 + - **实现**:按顺序依次执行 List 中的 Agent,上一个 Agent 的输出作为下一个的输入。 +- **Parallel(并行编排)**: + - **场景**:任务独立且耗时,需要提高效率。例如:同时`搜索技术方案 A`、`搜索技术方案 B`、`搜索技术方案 C`,最后汇总对比。 + - **实现**:使用线程池并发执行多个 Agent,最后通过 `CountDownLatch` 或 `CompletableFuture.allOf` 等待所有任务完成并聚合结果。 +- **Loop(循环编排)**: + - **场景**:需要反复迭代直到满足条件。例如:`生成代码` -> `运行测试` -> `报错` -> `修正代码` -> `再运行测试`... 直到测试通过或达到最大重试次数。 + - **实现**:在 `LoopAgentNode` 中维护一个循环逻辑,根据 **评估函数(Evaluator)** 的结果决定是继续循环还是输出最终结果。 + +#### 7. 在“AI + Draw.io”场景中,如何确保 AI 生成的 XML 是可用的?前后端交互协议是如何设计的? +**参考答案:** +- **质量控制(Reviewer Agent)**: + - 引入了 **多智能体协作(Multi-Agent System)** 机制。 + - 设计了专门的 **Reviewer(审查员)** 智能体。在 **Drawer(绘图员)** 生成 XML 后,Reviewer 会检查 XML 的语法正确性、连线逻辑(如是否交叉、是否有孤立节点)等。如果发现问题,Reviewer 会反馈给 Drawer 进行修正,直到通过审查。 +- **交互协议设计**: + - 定义了包含 `type` 字段的 JSON 协议: + - `type: "user"`:表示 AI 需要用户补充信息(如“请问您想要画什么类型的图?”),前端渲染为对话框。 + - `type: "drawio"`:表示 AI 生成了绘图数据,前端解析 XML 并调用 Draw.io 组件进行渲染。 + - `type: "review"`:表示正在审查中(可选,用于展示状态)。 + - **优势**:明确区分了 **对话交互** 和 **指令执行**,提升了用户体验。 + +#### 8. 你提到的“Spring AI 动态预热”是如何实现的?有什么作用? +**参考答案:** +- **作用**: + - **快速响应**:AI 模型(尤其是加载了大量 Prompt 或上下文的模型)初始化较慢,预热可以避免用户第一次请求时的长延迟。 + - **配置校验**:在应用启动时尽早发现 API Key 错误、网络不通等配置问题,避免上线后报错。 +- **实现**: + - 利用 Spring 的 `ApplicationRunner` 或 `CommandLineRunner` 接口,在 Spring 容器启动完成后自动触发。 + - 读取配置文件中的 `warm-up` 列表,模拟一次简单的 AI 调用(如发送 "Hello"),强制初始化底层的 `ChatModel` 和 `Token` 连接池。 + +--- + +### 进阶与优化 (Spring AI/Skills/性能) + +#### 9. 在 Spring AI 集成中,项目是如何利用 "Skills" 机制来增强 RAG 或替代传统向量检索的? +**参考答案:** +- **Skills 概念**:项目引入 `spring-ai-agent-utils`,将特定领域的知识(如 PDF 处理、系统巡检脚本)封装为 **Skills(技能书)**,这不仅仅是静态文本,还包含了可执行的代码逻辑(Tools)。 +- **与传统 RAG 对比**: + - **传统 RAG**:侧重于 **检索 (Retrieval)**,即从向量数据库中找到相关文本片段喂给 LLM。优点是知识覆盖面广,缺点是不仅准确率受限于检索算法,而且无法直接操作。 + - **Skills**:侧重于 **执行 (Action)**。它将“工具定义 + Prompt 模板 + 执行脚本(Python/Shell)”打包。Agent 识别到意图后,直接加载对应的 Skill 并执行脚本。 + - **优势**:减少了 LLM 的幻觉(执行逻辑是确定性的代码),缩短了 "Prompt -> 分析 -> 找工具 -> 执行" 的决策链路,对于特定任务(如“重启服务器”)比 RAG 更精准、更安全。 + +#### 10. 移动网关系统中,服务端如何处理 Netty 的异步通信与 Agent 同步决策之间的矛盾? +**参考答案:** +- **矛盾点**:Netty 是基于事件驱动的异步框架,而 Agent 的思维链(Chain of Thought)通常是线性的、同步等待每一步结果的(例如:点击按钮 -> 等待截图 -> 分析截图 -> 下一步)。 +- **实现机制**: + - **Future 模式**:服务端维护一个 `Map> pendingResponses`。 + - **同步等待**:Agent 线程在发送指令后,调用 `future.get(timeout)` 阻塞等待。 + - **异步唤醒**:Netty 的 Handler 收到手机端响应后,根据 ID 从 Map 中取出对应的 Future,调用 `future.complete(response)`。 + - **异常处理**:设置超时时间(如 30秒),防止因手机端无响应导致 Agent 线程永久阻塞。 + +#### 11. 项目在装配 MCP (Model Context Protocol) 工具时使用了什么设计模式?解决了什么问题? +**参考答案:** +- **设计模式**:使用了 **策略模式 (Strategy Pattern)** 配合 **工厂模式 (Factory Pattern)**。 +- **解决痛点**:在 `ChatModelNode` 中,如果使用大量的 `if-else` 来判断是创建 SSE 客户端、Stdio 客户端还是本地 Bean 调用,代码会非常臃肿且难以维护。 +- **实现细节**: + - 定义了 `ToolMcpCreateService` 策略接口。 + - 实现了 `SseMcpCreateStrategy`、`StdioMcpCreateStrategy`、`LocalMcpCreateStrategy` 等具体策略类。 + - 工厂类 `DefaultMcpClientFactory` 根据配置自动分发请求到对应的策略实现,从而实现了代码的 **开闭原则(Open/Closed Principle)**——新增一种协议只需增加一个策略类,无需修改原有逻辑。 + +#### 12. 针对智能体服务的异常处理,项目采用了怎样的分层处理策略?如果 Netty 服务端突然宕机,如何保证 Agent 任务的一致性? +**参考答案:** +- **分层异常处理**: + - **Trigger 层**:`AgentServiceController` 使用 `try-catch` 全局捕获异常,并封装为统一的 `Response` 对象(包含错误码和提示信息),确保前端总是收到合法的 JSON 响应。 + - **Service 层**:业务逻辑中抛出自定义 `AppException`(如 `E0001` 智能体不存在),由上层统一处理,避免将底层堆栈信息直接暴露给用户。 +- **宕机恢复方案(进阶)**: + - **现状**:目前架构中 `CompletableFuture` 存储在内存中,宕机会导致任务丢失。 + - **优化思路**:引入 **持久化状态机(State Machine)**。在下发指令前,将 Task 状态(如 `PENDING_SCREENSHOT`)写入 Redis 或数据库。服务重启后,通过 Session ID 恢复上下文,或者手机端实现 **断线重连(Heartbeat)** 机制,重连后主动上报当前状态,Agent 根据最新截图重新规划后续步骤。 + +--- + +### AI Agent 核心八股文 (概念与原理) + +#### 13. 什么是 AI Agent(智能体)?它与传统的 LLM 应用(如 ChatGPT)有什么本质区别? +**参考答案:** +- **AI Agent 定义**:AI Agent 是一个能够感知环境、进行推理规划、主动调用工具并采取行动以实现目标的智能系统。它具备 **感知(Perception)**、**大脑(Brain/LLM)**、**规划(Planning)** 和 **行动(Action/Tools)** 四大核心组件。 +- **与传统 LLM 区别**: + - **被动 vs 主动**:ChatGPT 等 LLM 应用通常是 **被动响应** 用户输入的(Input -> Output),无状态且单次交互。而 AI Agent 具备 **主观能动性**,它能将复杂目标拆解为一系列子任务,并主动调用工具(如搜索、API、代码执行)来获取信息或改变环境状态。 + - **工具使用能力**:传统 LLM 仅依赖训练数据(内部知识),存在幻觉且无法获取实时信息。Agent 通过 **Function Calling** 或 **MCP** 协议连接外部世界(Google、数据库、API),极大地扩展了能力边界。 + - **循环迭代**:Agent 通常采用 **ReAct (Reasoning + Acting)** 范式,即“思考 -> 行动 -> 观察结果 -> 再思考”,形成一个闭环,直到目标达成。 + +#### 14. 什么是 ReAct 范式?它是如何让 Agent 具备推理能力的? +**参考答案:** +- **概念**:ReAct 是 **Reasoning(推理)** 和 **Acting(行动)** 的组合。它是一种 Prompt Engineering 技术,要求 LLM 在执行具体动作前,先生成一段“思维链(Thought)”。 +- **工作流程**: + 1. **Thought(思考)**:LLM 分析当前任务,决定下一步该做什么(例如:“我需要先搜索一下今天的日期”)。 + 2. **Action(行动)**:LLM 生成调用工具的指令(例如:`SearchTool.search("current date")`)。 + 3. **Observation(观察)**:工具执行并返回结果(例如:“2023-10-27”)。 + 4. **Repeat(循环)**:LLM 根据观察结果进行下一轮思考,直到得出最终答案(Final Answer)。 +- **优势**:相比直接生成答案(Zero-shot),ReAct 显著减少了幻觉,增强了解决复杂多步问题的能力,并提供了可解释的推理过程。 + +#### 15. 请解释 RAG(检索增强生成)与 Fine-tuning(微调)的区别及各自适用场景。 +**参考答案:** +- **RAG (Retrieval-Augmented Generation)**: + - **原理**:类似于“开卷考试”。在 LLM 生成答案前,先从外部知识库(向量数据库)中检索相关文档片段,作为上下文(Context)拼接到 Prompt 中喂给 LLM。 + - **适用场景**:需要**实时更新知识**(如新闻)、**私有数据查询**(如企业文档)、**降低成本**(无需训练模型)的场景。 + - **优缺点**:成本低、无遗忘问题,但受限于检索精度和 Context Window 长度。 +- **Fine-tuning (微调)**: + - **原理**:类似于“复习内化”。使用特定领域的数据集对预训练模型进行进一步训练,调整模型参数,使其掌握特定领域的知识或风格。 + - **适用场景**:需要**特定格式输出**(如代码生成、JSON提取)、**特定领域深度理解**(如医疗诊断)、**降低延迟**(无需检索)的场景。 + - **优缺点**:效果好、响应快,但成本高、知识更新困难(需重新训练)。 + +#### 16. 什么是向量数据库(Vector Database)?它在 AI Agent 中起什么作用? +**参考答案:** +- **定义**:专门用于存储和检索高维向量(Vector / Embedding)的数据库。它支持 **近似最近邻搜索(ANN)**,能快速找到与查询向量距离最近的数据。 +- **Embedding(嵌入)**:将文本、图片、音频等非结构化数据转化为数字向量的过程。语义相似的内容,其向量在空间中的距离更近(如 Cosine Similarity)。 +- **在 Agent 中的作用**: + - **长期记忆(Long-term Memory)**:Agent 可以将对话历史、用户偏好存储在向量库中,实现跨会话记忆。 + - **知识库检索(Knowledge Base)**:存储海量文档片段,供 RAG 检索使用,弥补 LLM 训练数据的滞后性。 + +#### 17. 什么是 Chain of Thought (CoT)?它如何提升 LLM 的推理能力? +**参考答案:** +- **概念**:思维链(Chain of Thought)是一种通过引导 LLM 生成**中间推理步骤**来解决复杂问题的技术。 +- **原理**:对于数学题或逻辑推理题,如果直接问答案,LLM 容易出错。但如果提示它“**Let's think step by step(让我们一步步思考)**”,或者在 Few-shot 示例中展示推理过程,LLM 就会模仿这种思维方式,将大问题拆解为小问题逐个击破。 +- **类型**: + - **Zero-Shot CoT**:仅添加提示词 "Let's think step by step"。 + - **Few-Shot CoT**:在 Prompt 中提供包含推理步骤的示例()。 +- **价值**:显著提升了 LLM 在算术、常识推理和符号推理任务上的准确率,是 Agent 实现复杂规划的基础。 + +#### 18. 什么是 MCP (Model Context Protocol)?为什么它对 Agent 生态很重要? +**参考答案:** +- **定义**:MCP 是一个开放标准协议,用于标准化 AI 模型与外部数据/工具的连接方式。它定义了统一的接口规范,使得工具(Tools)、资源(Resources)和提示(Prompts)可以跨平台、跨模型复用。 +- **核心价值**: + - **去碎片化**:解决了每个 AI 应用都需要为 Google Drive、Slack、GitHub 等写独立连接器(Connector)的问题。MCP 提供了统一的“插座”。 + - **即插即用**:开发者只需编写一次 MCP Server,任何支持 MCP 的 Client(如 Claude Desktop、Cursor、IDEA)都可以直接使用该工具。 + - **安全性**:通过标准化的鉴权机制(如 SSE + Token)管理数据访问权限。 diff --git a/docs/md/project/ai-agent-scaffold/part-0/mobile-openclaw.md b/docs/md/project/ai-agent-scaffold/part-0/mobile-openclaw.md new file mode 100644 index 000000000..478d0fc9b --- /dev/null +++ b/docs/md/project/ai-agent-scaffold/part-0/mobile-openclaw.md @@ -0,0 +1,62 @@ +--- +title: 手机小龙虾,这次我比小米下手早! +lock: no +--- + +# 手机小龙虾,这次我比小米下手早! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +🦞 OpenClaw 太火了,火到什么程度,给 Mac Mini 干断货了,各行各业都找程序员👨🏻‍💻安装小龙虾,上门部署 OpenClaw 也成了生意!3月6日,深圳腾讯大厦,公益装机,也排起了长长的队伍。很多父母带着电脑过来,给自己娃的电脑装上小龙虾。 + +
+ +
+ +但当所有人都盯着 OpenClaw 小龙虾时,小米发布了 miclaw 手机版龙虾🦞,对标豆包手机、AutoGLM-Phone,首批支持小米17系列机型。 + +但,嘿嘿,不谋而合。我在看到和体验 OpenClaw 后,也想着,我的手机、平板,也可以来一个 Mobile-OpenClaw 呀!让这些电子设备,帮我完成一些工作不是美滋滋!`下文我会演示通过小龙虾手机的案例视频。` + +
+ +
+ +所以,在小米 miclaw 发布之前,我也已经开始设计实现手机版龙虾。并且还申请了一个手机版龙虾的域名,哈哈哈 死鬼,早有预谋哇! + +
+ +
+ +那手机版龙虾怎么做?🤔 它可以,通过 AI Agent 智能体,分析用户行为。之后下达一些列指令到应用设备的 Socket 网关端点上,完成功能指令动作。`小米 miclaw` 应该也是类似的,以后也可以体验下,但他可以原生态直接从系统上支持,控制整个米家的应用生态 👍🏻。 + +闲言少叙,接下来我们演示下运行效果。我的小米 Pad 7 Pro 也到位了。新的设备测试起来速度更快。😂 最近是一顿花钱呀,Mac Mini(电脑龙虾)、Pad 7 Pro(手机龙虾)、群辉 Nas(数据存储 + qwen3.5:9b)!**这个世界,终究是程序员的!** + +## 一、演示场景 + +小傅哥这里做了2个演示场景,一个是在小红书🍠发帖,一个是汽水音乐🎵自动看广告开会员。 + +### 1. 小红书 - 自动发帖 + +```java +打开小红书,点击下面的红色按钮,发送一个帖子。先写想法为,你好,世界,我是手机版小龙虾 🦞 想法编写后,点击【下一步】继续。在发帖页面,输入标题为;你好,世界,我是手机版小龙虾 🦞 内容为;我是 @小傅哥 正在测试开发的 MobileOpenClaw 欢迎关注我的动向!编写后,点击右上角【发布】。 +``` + +-- + +### 2. 汽水音乐 - 看广告 + +```java +打开汽水音乐,看广告获得VIP时长,操作流程; + +1. 点击右上角【免】按钮。 +2. 点击【免】后会进入后,右上角有倒计时播放广告,播放完成后显示为【领取成功】。这个时候点击【领取成功】,会有一个弹窗,点击弹窗的【领取奖励】,不要点x关闭。 +3. 完成领取后,继续看广告,重复步骤2,一直领取奖励,直至没有。 +``` + + + diff --git "a/docs/md/project/ai-agent-scaffold/part-1/\347\254\2541-1\350\212\202\357\274\232\350\204\232\346\211\213\346\236\266\351\234\200\346\261\202\345\210\206\346\236\220.md" "b/docs/md/project/ai-agent-scaffold/part-1/\347\254\2541-1\350\212\202\357\274\232\350\204\232\346\211\213\346\236\266\351\234\200\346\261\202\345\210\206\346\236\220.md" new file mode 100644 index 000000000..cf8a978c4 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-1/\347\254\2541-1\350\212\202\357\274\232\350\204\232\346\211\213\346\236\266\351\234\200\346\261\202\345\210\206\346\236\220.md" @@ -0,0 +1,46 @@ +--- +title: 【更】第1-1节:脚手架需求分析 +pay: https://t.zsxq.com/l3GtR +--- + +# 《AI Agent 脚手架》第1-1节:脚手架需求分析 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/uNA2K](https://t.zsxq.com/uNA2K) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +今天是我们 **《AI Agent 脚手架》** 项目学习的第1节课程,小傅哥会带着大家,以互联网公司正规的承接产品需求到开发部署上线的流程,带着大家以第一主人公视角的方式进行学习。这样既可以保证你学习到项目内容,也能了解到公司里正规的开发模式,以后进入到公司也可以很好的融入团队,承接项目需求。加油💪🏻!让我们开启新项目之旅! + +## 一、本章诉求 + +站在技术视角,分析 AI Agent 脚手架项目,这样一个产品功能需求的背景、诉求和目的。 + +首先,脚手架你可以理解为是一个工程模板框架,通过简单的配置即可完成初始化项目工程(IntelliJ IDEA)的搭建,并在工程内提供最为常用的基础服务,免去大家每次做新的项目,都要手动搭建工程的过程。 + +**那么,为什么叫技术视角?** + +在互联网公司中,项目通常分为两类:一类是源自产品业务的需求,另一类则是由研发驱动的纯技术项目(或由基架部门专门负责的技术产品)。后者的初衷在于解决研发在响应业务需求时,频繁且重复的工作负担,同时推动需求制定的统一标准化。 + +随着2025年起互联网公司纷纷通过AI赋能业务,推动各场景的效率提升,构建多样化的AI Agent智能体业务应用将成为常态。面对大量复杂的工程搭建需求,亟需一套统一的标准化框架,能够快速创建项目,显著降低用户的使用门槛和开发成本。 + +## 二、项目背景 + +为互联网企业构建业务场景下的 AI Agent 智能体,提供统一标准和便捷易用的脚手架。 + +**为什么要为创建脚手架?** + +回归本质,当前大规模语言模型(LLM)的使用,基本上是通过 HTTP 响应式接口进行对接。随着应用需求的增长,为了简化各自封装 AI HTTP 接口的复杂度,逐渐出现了以 AI SDK 方式进行对接的设计和实现,提升了开发效率和集成体验。 + +随后,AI 服务不仅仅局限于简单的接口调用,还引入了诸如 RAG(检索增强生成)知识库、Tool 工具(如 Function、MCP)等能力。同时,不同厂商的大模型(OpenAI、Google、智谱、阿里千问等)在接口和功能上存在差异,推动了类似 Spring AI 这类产品的诞生,帮助开发者更加便捷地统一调用和管理多样化的 AI 服务。 + +进入下一阶段,随着智能体(AI Agent)概念的兴起,开发者开始设计支持顺序执行、循环执行(分析与决策)、并行执行等复杂流程的智能体方案。Google 发布的 ADK(Agent Development Kit)智能体框架,标志着这一阶段的技术成熟和标准化趋势。 + +
+ +
+ +综上所述,构建一个完整的智能体,需要综合运用上述所有技术和能力。为了统一标准、提升易用性,就很需要搭建一套统一的 AI Agent 智能体开发脚手架,剔除重复且复杂的工作环节,帮助业务快速融合并高效开展智能体开发。 \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-1/\347\254\2541-2\350\212\202\357\274\232\347\263\273\347\273\237\346\236\266\346\236\204\350\256\276\350\256\241.md" "b/docs/md/project/ai-agent-scaffold/part-1/\347\254\2541-2\350\212\202\357\274\232\347\263\273\347\273\237\346\236\266\346\236\204\350\256\276\350\256\241.md" new file mode 100644 index 000000000..8eab70477 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-1/\347\254\2541-2\350\212\202\357\274\232\347\263\273\347\273\237\346\236\266\346\236\204\350\256\276\350\256\241.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第1-2节:系统架构设计 +pay: https://t.zsxq.com/sSD6u +--- + +# 《AI Agent 脚手架》第1-2节:系统架构设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/v8C8a](https://t.zsxq.com/v8C8a) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +对 AI Agent 智能体脚手架,进行应用技术选型和工程框架设计。 + +这个过程就等同于大家做一个新项目时,分析项目实现过程,以及过程中所需的技术能力,并对未知的技术点进行案例验证。待全部梳理完成后,则进行详细的方案设计。 + +>随着大家进入公司以后,在你承接一个新的项目/需求时,会大量的做这个事情,你会遇到很多没用过却需要使用的技术或者方案。当然,也会随着你的积累,你做这个事情会越来越熟练,越来越高效。而与之相反的,如果你之前的学习总是对照视频cv代码,最好一次就成功运行,害怕出错,不敢排查,没有一个思考和验证的过程,那么其实是一点经验也没积累。所以,要正视自己的学习方法。 + +## 二、架构设计 + +如图,整体简要架构设计; + +
+ +
+ +做这个事情,我们要思考,需要哪些东西来完成这样项目的开发。如下; \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-10\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-RunnerNode.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-10\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-RunnerNode.md" new file mode 100644 index 000000000..331e39a5c --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-10\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-RunnerNode.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第2-10节:装配域节点-RunnerNode +pay: https://t.zsxq.com/pEBw8 +--- + +# 《AI Agent 脚手架》第2-10节:装配域节点-RunnerNode + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/tMfj3](https://t.zsxq.com/tMfj3) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +把构建的智能体,填充到 InMemoryRunner 中,以及注册到 Spring 容器中。这样后续就可以使用 Spring 容器中的对象,进行 AI Agent 对话了。 + +>目前是把最后构建的 SequentialAgent 写入到 InMemoryRunner 中,后续会做成动态的,让配置任何的一个智能体都可以填充到 InMemoryRunner 中。 + +## 二、流程设计 + +如图,智能体构建完成后,则填充到 InMemoryRunner 中; + +
+ +
+ +- 从 SequentialAgentNode 节点,流转到 RunnerNode 节点。 +- 在 RunnerNode 节点,创建 InMemoryRunner 以及注册到 Spring 容器。这样可以任何一个地方获取到执行对象。 \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-11\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223\345\212\240\350\275\275\344\275\277\347\224\250\351\252\214\350\257\201.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-11\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223\345\212\240\350\275\275\344\275\277\347\224\250\351\252\214\350\257\201.md" new file mode 100644 index 000000000..7cc2ac0a5 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-11\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223\345\212\240\350\275\275\344\275\277\347\224\250\351\252\214\350\257\201.md" @@ -0,0 +1,27 @@ +--- +title: 【更】第2-11节:智能体加载使用验证 +pay: https://t.zsxq.com/CyuXv +--- + +# 《AI Agent 脚手架》第2-11节:智能体加载使用验证 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/kgrzQ](https://t.zsxq.com/kgrzQ) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +启动程序,加载智能体yml配置,完成智能体的装配。以及编写测试案例,验证加载智能体的使用。这部分的内容,会为后续开发对话服务做一个基础。让大家知道对话的过程需要创建会话和处理消息请求。 + +## 二、流程设计 + +如图,智能体全部节点构建完成后,在程序启动的时候进行加载; + +
+ +
+ +- 前面章节已经做好了全部的加载动作,到这可以把调用入口串联起来了。在程序启动的时候,完成自动化的加载处理。 +- 完成加载处理后,我们在做一个初步的验证操作,也就是使用这个智能体,通过这样的方式了解整个会话过程。 diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-12\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-RunnerNode.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-12\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-RunnerNode.md" new file mode 100644 index 000000000..7c73d00ba --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-12\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-RunnerNode.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第2-12节:增强装配-RunnerNode +pay: https://t.zsxq.com/jxbVS +--- + +# 《AI Agent 脚手架》第2-12节:增强装配-RunnerNode + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/Ls0hf](https://t.zsxq.com/Ls0hf) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +基础的智能体装配一个链路做完,并验证了会话的设计,让整个链路跑通。之后我们做一下增强设计操作。让整个智能体可以在后续适应更多的场景使用。 + +这一节,我们先来做下 RunnerNode 的增强,也就是前面提到的,用户如果只是配置一个基础的 Agent 不在配置其他的 loop(循环)、parallel(并行)、sequential(序列),就结束了。那么这里要怎么流转到 RunnerNode。 + +## 二、流程设计 + +如图,从 AgentWorkflowNode 流转到 RunnerNode 设计; + +
+ +
+ +- 首先,在有了前面的内容学习后,我们了解到 RunnerNode 会做 InMemoryRunner 的构建,而这个对象的构建是需要拿到 SequentialAgentNode 作为最后一个节点,构建的 SequentialAgent 写入到上下文,到 RunnerNode 节点使用。它的核心本质是拿到 InMemoryRunner 创建的时候,所需 Agent 智能体。 +- 之后,这个 Agent 智能体,不非得以一个固定的写死,而是可以在配置文件中添加以 runner 配置,指定装配到 runner 中的 agent 名称。之后在 RunnerNode 构建 InMemoryRunner 的时候,则从上下文通过智能体名称获取 agent 装配进来即可。 +- 最后,思考下,AgentWorkflowNode 什么时候流转,这个流转则是根据当前 agentWorkflows 是不为空了,为空则直接流转到 RunnerNode 即可。RunnerNode 会根据配置的关联 agentName 进行配置。`这部分看代码的yml文件会更加清晰` diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-13\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-AgentWorkflowNode.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-13\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-AgentWorkflowNode.md" new file mode 100644 index 000000000..144a44533 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-13\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-AgentWorkflowNode.md" @@ -0,0 +1,417 @@ +--- +title: 【更】第2-13:增强装配-AgentWorkflowNode +pay: https://t.zsxq.com/qjhUb +--- + +# 《AI Agent 脚手架》第2-13:增强装配-AgentWorkflowNode + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/AuQlk](https://t.zsxq.com/AuQlk) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +换种设计方式,增强 AgentWorkflowNode 流转能力,让 LoopAgentNode、ParallelAgentNode、SequentialAgentNode 不在负责判断流转,而是每个流程处理完毕后,都回到 AgentWorkflowNode 中进行流转决策。这样我们就可以组合出更为复杂的智能体编排。 + +## 二、流程设计 + +如图,增强 AgentWorkflowNode 流转能力,每个节点流转完都重新回到 AgentWorkflowNode 节点进行决策; + +
+ +
+ +- 左侧是旧版流程,LoopAgentNode、ParallelAgentNode、SequentialAgentNode,每个节点交叉流转。这次换到新版流程,所有的流转都由 AgentWorkflowNode 负责。这样会让三个功能 Agent 节点的职责更为清晰。 +- 这样,AgentWorkflowNode 就成了分发中心,三个 LoopAgentNode、ParallelAgentNode、SequentialAgentNode 智能体节点处理完业务后都回到 AgentWorkflowNode 即可。 + +## 三、功能实现 + +### 1. 工程结构 + +
+ +
+ +- 修改 LoopAgentNode、ParallelAgentNode、SequentialAgentNode,三个节点中的流转操作,都转移到 AgentWorkflowNode 处理。 +- 在 AgentWorkflowNode 中,要拿到当前 agentWorkflows 配置的列表中,步骤中第N个,把拿到的值作为当前的信息存储到上下文,之后流转到任何一个节点,只负责从上下文取到当前值即可。 + +### 2. 核心模块 + +#### 2.1 定义上下文 + +```java +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public static class DynamicContext { + + /** + * LLM API + */ + private OpenAiApi openAiApi; + + /** + * 对话模型 + */ + private ChatModel chatModel; + + /** + * 原子安全的递进步骤 + */ + private AtomicInteger currentStepIndex = new AtomicInteger(0); + + /** + * 当前的智能体 + */ + private AiAgentConfigTableVO.Module.AgentWorkflow currentAgentWorkflow; + + /** + * 智能体组 + */ + private Map agentGroup = new HashMap<>(); + + private Map dataObjects = new HashMap<>(); +} +``` + +- 首先,去掉 agentWorkflows 列表值,增加一个 currentAgentWorkflow 当前值。 +- 之后,添加 currentStepIndex 步骤完成一个,则迭代+1,从 agentWorkflows 渠道的当前对象存储到 currentAgentWorkflow,这样会更加方便判断。(`这个就是前面提到的另外的一个方案设计,小傅哥在项目里也给大家增加这种演进的迭代设计,可以让大家多一些积累`) + +#### 2.2 增强流转 + +```java +@Slf4j +@Service +public class AgentWorkflowNode extends AbstractArmorySupport { + + @Resource + private LoopAgentNode loopAgentNode; + + @Resource + private ParallelAgentNode parallelAgentNode; + + @Resource + private SequentialAgentNode sequentialAgentNode; + + @Resource + private RunnerNode runnerNode; + + @Override + protected AiAgentRegisterVO doApply(ArmoryCommandEntity requestParameter, DefaultArmoryFactory.DynamicContext dynamicContext) throws Exception { + log.info("Ai Agent 装配操作 - AgentWorkflowNode"); + + AiAgentConfigTableVO aiAgentConfigTableVO = requestParameter.getAiAgentConfigTableVO(); + List agentWorkflows = aiAgentConfigTableVO.getModule().getAgentWorkflows(); + + // 如果未配置 agentWorkflows 则直接流转到 RunnerNode + if (null == agentWorkflows || agentWorkflows.isEmpty() || dynamicContext.getCurrentStepIndex() >= agentWorkflows.size()) { + // 设置结果值 + dynamicContext.setCurrentAgentWorkflow(null); + // 路由下节点 + return router(requestParameter, dynamicContext); + } + + // 设置当前判断流程对象 + dynamicContext.setCurrentAgentWorkflow(agentWorkflows.get(dynamicContext.getCurrentStepIndex())); + + // 步骤值增加 + dynamicContext.addCurrentStepIndex(); + + return router(requestParameter, dynamicContext); + } + + @Override + public StrategyHandler get(ArmoryCommandEntity requestParameter, DefaultArmoryFactory.DynamicContext dynamicContext) throws Exception { + + AiAgentConfigTableVO.Module.AgentWorkflow currentAgentWorkflow = dynamicContext.getCurrentAgentWorkflow(); + + // 没有下一个节点,流转到结束节点 + if (null == currentAgentWorkflow) { + return runnerNode; + } + + String type = currentAgentWorkflow.getType(); + AgentTypeEnum agentTypeEnum = AgentTypeEnum.fromType(type); + + if (null == agentTypeEnum) { + throw new RuntimeException("agentWorkflow type is error!"); + } + + String node = agentTypeEnum.getNode(); + + return switch (node) { + case "loopAgentNode" -> loopAgentNode; + case "parallelAgentNode" -> parallelAgentNode; + case "sequentialAgentNode" -> sequentialAgentNode; + default -> runnerNode; + }; + + } + +} +``` + +- doApply 方法的核心是判断是否配置 agentWorkflows,以及不断的取值(类似for循环),是否取到了最后一个。如果是,则设置 `dynamicContext.setCurrentAgentWorkflow(null);` 并路由走。否则,从 agentWorkflows 获取当前步骤的对象并设置到上下文中,以及给步骤 +1 处理。 +- get 则负责节点流转,判断当前节点是否为null,为null则表示没有要处理的节点,直接进入 runnerNode 即可。如果不是 null 则按照不同的 node 流转到子 agent 智能体节点。 + +#### 2.3 子智能体节点 + +##### 2.3.1 LoopAgentNode + +```java +@Service +public class LoopAgentNode extends AbstractArmorySupport { + + @Override + protected AiAgentRegisterVO doApply(ArmoryCommandEntity requestParameter, DefaultArmoryFactory.DynamicContext dynamicContext) throws Exception { + log.info("Ai Agent 装配操作 - LoopAgentNode"); + + AiAgentConfigTableVO.Module.AgentWorkflow currentAgentWorkflow = dynamicContext.getCurrentAgentWorkflow(); + + List subAgents = dynamicContext.queryAgentList(currentAgentWorkflow.getSubAgents()); + + LoopAgent loopAgent = + LoopAgent.builder() + .name(currentAgentWorkflow.getName()) + .description(currentAgentWorkflow.getDescription()) + .subAgents(subAgents) + .maxIterations(currentAgentWorkflow.getMaxIterations()) + .build(); + + dynamicContext.getAgentGroup().put(currentAgentWorkflow.getName(), loopAgent); + + return router(requestParameter, dynamicContext); + } + + @Override + public StrategyHandler get(ArmoryCommandEntity requestParameter, DefaultArmoryFactory.DynamicContext dynamicContext) throws Exception { + return getBean("agentWorkflowNode"); + } + +} +``` + +- doApply 要修改为从上下文的 `dynamicContext.getCurrentAgentWorkflow()` 获取当前节点的数据,构建 Agent 之后路由。 +- get 则负责流转回 `getBean("agentWorkflowNode")` 让 agentWorkflowNode 继续负责节点的流转判断。 + +##### 2.3.2 ParallelAgentNode + +```java +@Service +public class ParallelAgentNode extends AbstractArmorySupport { + + @Override + protected AiAgentRegisterVO doApply(ArmoryCommandEntity requestParameter, DefaultArmoryFactory.DynamicContext dynamicContext) throws Exception { + log.info("Ai Agent 装配操作 - ParallelAgentNode"); + + AiAgentConfigTableVO.Module.AgentWorkflow currentAgentWorkflow = dynamicContext.getCurrentAgentWorkflow(); + + List subAgents = dynamicContext.queryAgentList(currentAgentWorkflow.getSubAgents()); + + ParallelAgent parallelAgent = + ParallelAgent.builder() + .name(currentAgentWorkflow.getName()) + .subAgents(subAgents) + .description(currentAgentWorkflow.getDescription()) + .build(); + + dynamicContext.getAgentGroup().put(currentAgentWorkflow.getName(), parallelAgent); + + return router(requestParameter, dynamicContext); + } + + @Override + public StrategyHandler get(ArmoryCommandEntity requestParameter, DefaultArmoryFactory.DynamicContext dynamicContext) throws Exception { + return getBean("agentWorkflowNode"); + } +} +``` + +- 代码修改方式同 `LoopAgentNode` + +##### 2.3.3 SequentialAgentNode + +```java +@Service +public class SequentialAgentNode extends AbstractArmorySupport { + + @Override + protected AiAgentRegisterVO doApply(ArmoryCommandEntity requestParameter, DefaultArmoryFactory.DynamicContext dynamicContext) throws Exception { + log.info("Ai Agent 装配操作 - SequentialAgentNode"); + + AiAgentConfigTableVO.Module.AgentWorkflow currentAgentWorkflow = dynamicContext.getCurrentAgentWorkflow(); + + List subAgents = dynamicContext.queryAgentList(currentAgentWorkflow.getSubAgents()); + + SequentialAgent sequentialAgent = + SequentialAgent.builder() + .name(currentAgentWorkflow.getName()) + .description(currentAgentWorkflow.getDescription()) + .subAgents(subAgents) + .build(); + + dynamicContext.getAgentGroup().put(currentAgentWorkflow.getName(), sequentialAgent); + + return router(requestParameter, dynamicContext); + } + + @Override + public StrategyHandler get(ArmoryCommandEntity requestParameter, DefaultArmoryFactory.DynamicContext dynamicContext) throws Exception { + return getBean("agentWorkflowNode"); + } + +} +``` + +- 代码修改方式同 `LoopAgentNode` + +## 四、测试验证 + +### 1. 修改配置文件 + +**parallel_research_app.yml** + +```java +ai: + agent: + config: + tables: + testAgent02: + app-name: ResearchAndSynthesisPipeline + agent: + agent-id: 100002 + agent-name: 测试智能体02 + agent-desc: 并行研究并汇总的智能体管道 + module: + ai-api: + base-url: https://apis.itedus.cn + api-key: sk-Sp2jx3yeq7x7HJ663bDc9bF0D34b4f609f833840271519B1 + completions-path: v1/chat/completions + embeddings-path: v1/embeddings + chat-model: + model: gpt-4.1 + tool-mcp-list: + - sse: + name: baidu-search + base-uri: https://appbuilder.baidu.com/v2/ai_search/mcp/ + sse-endpoint: sse?api_key=bce-v3/ALTAK-3zODLb9qHozIftQlGwez5/2696e92781f5bf1ba1870e2958f239fd6dc822a4 + request-timeout: 5000 + agents: + - name: RenewableEnergyResearcher + description: Researches renewable energy sources. + instruction: | + You are an AI Research Assistant specializing in energy. + Research the latest advancements in 'renewable energy sources'. + Use the Google Search tool provided. + Summarize your key findings concisely (1-2 sentences). + Output *only* the summary. + output-key: renewable_energy_result + - name: EVResearcher + description: Researches electric vehicle technology. + instruction: | + You are an AI Research Assistant specializing in transportation. + Research the latest developments in 'electric vehicle technology'. + Use the Google Search tool provided. + Summarize your key findings concisely (1-2 sentences). + Output *only* the summary. + output-key: ev_technology_result + - name: CarbonCaptureResearcher + description: Researches carbon capture methods. + instruction: | + You are an AI Research Assistant specializing in climate solutions. + Research the current state of 'carbon capture methods'. + Use the Google Search tool provided. + Summarize your key findings concisely (1-2 sentences). + Output *only* the summary. + output-key: carbon_capture_result + - name: SynthesisAgent + description: Combines research findings into a structured report. + instruction: | + You are an AI Assistant responsible for combining research findings into a structured report. + Your primary task is to synthesize the following research summaries, clearly attributing findings to their source areas. Structure your response using headings for each topic. Ensure the report is coherent and integrates the key points smoothly. + **Crucially: Your entire response MUST be grounded *exclusively* on the information provided in the 'Input Summaries' below. Do NOT add any external knowledge, facts, or details not present in these specific summaries.** + **Input Summaries:** + + * **Renewable Energy:** + {renewable_energy_result} + + * **Electric Vehicles:** + {ev_technology_result} + + * **Carbon Capture:** + {carbon_capture_result} + + **Output Format:** + + ## Summary of Recent Sustainable Technology Advancements + + ### Renewable Energy Findings + (Based on RenewableEnergyResearcher's findings) + [Synthesize and elaborate *only* on the renewable energy input summary provided above.] + + ### Electric Vehicle Findings + (Based on EVResearcher's findings) + [Synthesize and elaborate *only* on the EV input summary provided above.] + + ### Carbon Capture Findings + (Based on CarbonCaptureResearcher's findings) + [Synthesize and elaborate *only* on the carbon capture input summary provided above.] + + ### Overall Conclusion + [Provide a brief (1-2 sentence) concluding statement that connects *only* the findings presented above.] + + Output *only* the structured report following this format. Do not include introductory or concluding phrases outside this structure, and strictly adhere to using only the provided input summary content. + agent-workflows: + - type: parallel + name: ParallelWebResearchAgent + description: Runs multiple research agents in parallel to gather information. + sub-agents: + - RenewableEnergyResearcher + - EVResearcher + - CarbonCaptureResearcher + - type: sequential + name: ResearchAndSynthesisPipeline + description: Coordinates parallel research and synthesizes the results. + sub-agents: + - ParallelWebResearchAgent + - SynthesisAgent + runner: + agent-name: ResearchAndSynthesisPipeline +``` + +- agent-workflows 配置下 ParallelWebResearchAgent、ResearchAndSynthesisPipeline,这样可以测试循环处理。 +- runner 则配置 ResearchAndSynthesisPipeline 进行运行体转配。 + +### 2. 测试方法 + +```java +@Test +public void test_handlerMessage_03(){ + AiAgentRegisterVO aiAgentRegisterVO = applicationContext.getBean("100002", AiAgentRegisterVO.class); + String appName = aiAgentRegisterVO.getAppName(); + InMemoryRunner runner = aiAgentRegisterVO.getRunner(); + Session session = runner.sessionService() + .createSession(appName, "xiaofuge") + .blockingGet(); + Content userMsg = Content.fromParts(Part.fromText("你具备哪些能力")); + Flowable events = runner.runAsync("xiaofuge", session.id(), userMsg); + List outputs = new ArrayList<>(); + events.blockingForEach(event -> outputs.add(event.stringifyContent())); + log.info("测试结果:{}", JSON.toJSONString(outputs)); +} +``` + +```java +26-01-01.13:20:04.106 [main ] INFO test_handlerMessage_03 - 测试结果:["我可以帮助你查询和分析可再生能源领域的最新进展,包括太阳能、风能、生物能、地热能、海洋能等各类新能源技术的发展趋势、创新成果及政策动态。同时,我可以利用互联网搜索功能,快速获取最新科研成果、行业动态和相关数据,并将关键信息进行简明总结。","我是专注于电动汽车技术(electric vehicle technology)研究的AI助理,具备以下能力:\n\n1. **新技术检索与总结**:我能利用Google搜索等工具,快速检索最新的电动汽车技术发展、行业动态和科研突破,并进行简洁明了的总结。\n2. **趋势与前沿分析**:能够获取并分析行业趋势,例如电池创新、驱动系统进展、智能网联、电驱动新材料等领域的最新动向。\n3. **政策与市场信息搜集**:可查询全球各地与电动汽车相关的政策、市场增长、补贴政策等信息。\n4. **参考文献和数据追溯**:能帮助定位权威期刊、会议论文、专利等技术文档,提供学术研究支持。\n5. **技术对比与评估**:可对比不同品牌、技术路径或产品,分析其优劣及市场应用前景。\n6. **简明交流和摘要能力**:围绕“电动汽车技术”,可将复杂技术信息压缩为1-2句话的核心摘要,便于快速理解。\n\n如果你有特定方向的需求(如电池、驱动控制、充电技术等),我也能定向进行最新信息搜索和研究。","我具备以下能力,专注于碳捕集(carbon capture)相关的研究与信息获取:\n\n1. 实时网络检索:我可以通过专业搜索工具实时获取最新关于碳捕集方法、技术进展、应用案例、政策法规等公开信息。\n2. 资料梳理与总结:对检索到的信息快速提炼要点,进行结构化、简明扼要的总结,便于决策与参考。\n3. 技术分类与比较:能够对比不同类型的碳捕集技术(如直接空气捕集、点源捕集、碳矿化、生物碳捕集等)的原理、优缺点和应用现状。\n4. 最新动态追踪:跟踪全球范围内碳捕集领域的最新动态、前沿研究和重大项目进展。\n5. FAQ解答:针对碳捕集相关的常见问题(如成本、能效、行业难点等)进行专业、准确回答。\n\n如需获取某一具体问题或领域的最新信息,请直接告诉我!","## Summary of Recent Sustainable Technology ... +``` + +- 运行后可以看到执行的结果。也表示了,我们的装配方式是没问题的。 + +## 五、读者作业 + +- 简单作业:完成本节功能的编写,理解此处的架构设计。对于节点的流转,打开思路,之后活学活用。 +- 复杂作业:尝试配置一个多层嵌套的智能体,来验证这样的装配。 + diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-14\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-\346\234\254\345\234\260mcp.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-14\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-\346\234\254\345\234\260mcp.md" new file mode 100644 index 000000000..64b058b53 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-14\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-\346\234\254\345\234\260mcp.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第2-14节:增强装配-本地mcp +pay: https://t.zsxq.com/KYNyM +--- + +# 《AI Agent 脚手架》第2-14节:增强装配-本地mcp + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/OoPsy](https://t.zsxq.com/OoPsy) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在用户使用 ai agent 脚手架的时候,会有诉求扩展一些自己实现的 mcp 服务。比如,做一些智能体客服场景,或者公司内部的系统巡检场景,这些场景并没有提供统一的 mcp 服务,则可能都要自己扩展,扩展后装配到整个智能体中。 + +同时因为引入了多种类型的 mcp 装配,sse、stdio 又加上这种本地自己实现的,所以这块还要做一些策略处理。 + +## 二、流程设计 + +如图,增强 mcp 服务装配能力设计; + +
+ +
+ +- ChatModelNode 装配 MCP 主要是 sse、stdio 两种方式,通过 if···else 判断的方式进行处理。但现在又要扩展新的方式装配,则不适合继续编写 if···else 代码,而是要通过类来拆分一个大的方法。 +- 这块会使用到工厂 + 策略接口来扩展实现,并区分出 mcp 客户端、服务端。客户端负责策略装配,服务端负责用户自己扩展新的 mcp 服务。 diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-15\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-\345\233\236\350\260\203plugin.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-15\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-\345\233\236\350\260\203plugin.md" new file mode 100644 index 000000000..c5660f157 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-15\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-\345\233\236\350\260\203plugin.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第2-15节:增强装配-回调plugin +pay: https://t.zsxq.com/U1p49 +--- + +# 《AI Agent 脚手架》第2-15节:增强装配-回调plugin + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/tTIdy](https://t.zsxq.com/tTIdy) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +为 InMemoryRunner 运行体扩展 Plugin 插件能力,允许用户在智能体执行的各个阶段获取到上下文信息,并做出一定的监控、调整、治理的动作。 + +如果你有学习过星球「码农会锁」的扳手工程,在设计模式框架章节,有一个 `applyBefore`、`applyAfter`、`applyAfterError` 的处理,它可以让你在使用的阶段做拦截或者打印最后的结果。这些设计都是相同的,所以说学编程,最后都是学的思想。语言就像你的盗抢棍棒,斧钺钩叉,思想才是你的一招一式。 + +## 二、流程设计 + +如图,增强运行体插件配置,可以在各个节点埋入钩子; + +
+ +
+ +- Runner 的 Plugin 通过回调钩子在 AI Agent 运行流程生命周期的各个阶段执行。包括;用户输入信息、调用模型、调用工具、智能体执行等步骤中。这一工具,可以用在日志记录、性能分析、步骤调试、策略执行(权限)、监控对接(普罗米修斯)、请求或响应的调整(如敏感词的处理)等。 +- 这些操作的步骤,就是图上的各个阶段的节点,可以被采集到。就像你设置的任何一个智能体 Agent 都可以拿到它的运行信息,甚至你可以在上下文中做一些拦截操作。 diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-16\350\212\202\357\274\232fix-\345\244\232\346\250\241\346\200\201\350\203\275\345\212\233\344\275\277\347\224\250.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-16\350\212\202\357\274\232fix-\345\244\232\346\250\241\346\200\201\350\203\275\345\212\233\344\275\277\347\224\250.md" new file mode 100644 index 000000000..a2a9a4a3c --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-16\350\212\202\357\274\232fix-\345\244\232\346\250\241\346\200\201\350\203\275\345\212\233\344\275\277\347\224\250.md" @@ -0,0 +1,123 @@ +--- +title: 【更】第2-16节:fix-多模态能力使用 +pay: https://t.zsxq.com/wF32j +--- + +# 《AI Agent 脚手架》第2-16节:fix-多模态能力使用 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/XqlKu](https://t.zsxq.com/XqlKu) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +为接入 Google ADK 的 Spring AI 提供图片识别的多模态能力。 + +这本应该是一个简单直接使用的功能,但在 `Google ADK 0.5.0`、`Spring AI 1.1.0` 版本上,它还是一个隐藏待处理的 Bug,小傅哥已于 2026年1月6日,提交 [https://github.com/google/adk-java/issues/705](https://github.com/google/adk-java/issues/705) + +Google ADK Java 开发工程师,在 2026年1月7日,处理提交了修复代码,应该会在后续版本更新。 + +不过,对于我们学习来说,这并不是坏事。我们可以借助这样的问题点,深入理解 Google ADK 和 Spring AI 的对接,以及学习如何排查这样的报错。最终,鉴于 Google ADK 版本更新周期,我们目前先在程序中打一个”补丁“实现。 + +## 二、发现问题 + +### 步骤1,功能诉求 + +```java +@Test +public void test_handlerMessage_03() throws IOException { + AiAgentRegisterVO aiAgentRegisterVO = applicationContext.getBean("100003", AiAgentRegisterVO.class); + + String appName = aiAgentRegisterVO.getAppName(); + InMemoryRunner runner = aiAgentRegisterVO.getRunner(); + Session session = runner.sessionService() + .createSession(appName, "xiaofuge") + .blockingGet(); + + Content userMsg = Content.fromParts(Part.fromText("这是什么图片?"), + Part.fromBytes(imageResource.getContentAsByteArray(), MimeTypeUtils.IMAGE_PNG_VALUE)); + + Flowable events = runner.runAsync("xiaofuge", session.id(), userMsg); + + List outputs = new ArrayList<>(); + events.blockingForEach(event -> outputs.add(event.stringifyContent())); + log.info("测试结果:{}", JSON.toJSONString(outputs)); +} +``` + +
+ +
+ +- 在新的章节,需要验证多模态能力的时候,传入了一个图片 byte,但无论如何修改运行,都只是提示无法识别图片。 +- 这个时候猜想,是不是 InMemoryRunner 构建问题,或者 Agent 实例化参数问题。所以,决定把问题缩小,单独验证 Google ADK + Spring AI。 + +### 步骤2,分块验证 + +```java +@Slf4j +public class SpringAiTest { + + @SneakyThrows + public static void main(String[] args) { + + OpenAiApi openAiApi = OpenAiApi.builder() + .baseUrl("https://apis.itedus.cn") + .apiKey("sk-2GQTYTNoQSs7qizlE9F00bD84d254c2994D44d6410B0Ac8f") + .completionsPath("v1/chat/completions") + .embeddingsPath("v1/embeddings") + .build(); + + ChatModel chatModel = OpenAiChatModel.builder() + .openAiApi(openAiApi) + .defaultOptions(OpenAiChatOptions.builder() + .model("gpt-4.1") + .build()) + .build(); + + LlmAgent agent = LlmAgent.builder() + .name("test") + .description("Chess coach agent") + .model(new SpringAI(chatModel)) + .instruction(""" + You are a knowledgeable chess coach + who helps chess players train and sharpen their chess skills. + """) + .build(); + + InMemoryRunner runner = new InMemoryRunner(agent); + + Session session = runner + .sessionService() + .createSession("test", "xiaofuge") + .blockingGet(); + + URL resource = Thread.currentThread().getContextClassLoader().getResource("dog.png"); + + byte[] bytes; + assert resource != null; + try (InputStream inputStream = resource.openStream()) { + bytes = inputStream.readAllBytes(); + } + + List parts = new ArrayList<>(); + parts.add(Part.fromText("这是什么图片")); + parts.add(Part.fromBytes(bytes, MimeTypeUtils.IMAGE_PNG_VALUE)); + + Content content = Content.builder().role("user").parts(parts).build(); + + Flowable events = runner.runAsync("xiaofuge", session.id(), + content + ); + + System.out.print("\nAgent > "); + events.blockingForEach(event -> System.out.println(event.stringifyContent())); + } + +} +``` + +- 效果;运行结果依然是识别不了,告诉我要上传图片,它才能识别。 +- 猜想;这说明单独按照官网案例构建 Agent 并测试依然不行,再细化验证。 diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-17\350\212\202\357\274\232\344\274\232\350\257\235\346\234\215\345\212\241\346\216\245\345\217\243\345\256\236\347\216\260-service.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-17\350\212\202\357\274\232\344\274\232\350\257\235\346\234\215\345\212\241\346\216\245\345\217\243\345\256\236\347\216\260-service.md" new file mode 100644 index 000000000..fdf87ec66 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-17\350\212\202\357\274\232\344\274\232\350\257\235\346\234\215\345\212\241\346\216\245\345\217\243\345\256\236\347\216\260-service.md" @@ -0,0 +1,27 @@ +--- +title: 【更】第2-17节:会话服务接口实现-service +pay: https://t.zsxq.com/lxqLY +--- + +# 《AI Agent 脚手架》第2-17节:会话服务接口实现-service + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/vLd8O](https://t.zsxq.com/vLd8O) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在智能体完成装配以后,接下来我们要做的就是提供标准的会话服务接口能力,使用智能体。这包括了,所装配智能体的列表(agentId)、会话的创建、消息的处理(同步/异步)。 + +## 二、流程设计 + +如图,会话接口服务所在分层; + +
+ +
+ +- 首先,在 Agent 装配后,是要对外提供服务,服务由 trigger 分层下的 http 接口提供。这个 trigger 也就是 mvc 分层里的 controller,但因为在微服务下,接口、消息、定时任务,都是一种触发行为。触发可以理解为,别人打你,可以用拳头,可以用石头,还分可以榔头,这些都可以抽象为一种名称,触发。所以在 ddd 分层下,增加了 trigger 触发器层。 +- 之后,这一节我们先来实现 service 服务层,也就是在 domain 领域下,agent 里除了做装配实现,还要做一层会话处理。在 service 实现后,后面就是包装 trigger 层的对外接口。 diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-18\350\212\202\357\274\232\344\274\232\350\257\235\346\234\215\345\212\241\346\216\245\345\217\243\345\256\236\347\216\260-trigger.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-18\350\212\202\357\274\232\344\274\232\350\257\235\346\234\215\345\212\241\346\216\245\345\217\243\345\256\236\347\216\260-trigger.md" new file mode 100644 index 000000000..61a2e5ca2 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-18\350\212\202\357\274\232\344\274\232\350\257\235\346\234\215\345\212\241\346\216\245\345\217\243\345\256\236\347\216\260-trigger.md" @@ -0,0 +1,27 @@ +--- +title: 【更】第2-18节:会话服务接口实现-trigger +pay: https://t.zsxq.com/IY7j3 +--- + +# 《AI Agent 脚手架》第2-18节:会话服务接口实现-trigger + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/leFf4](https://t.zsxq.com/leFf4) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +对 domain 领域层的 service 服务,进行 trigger 包装,提供 http 接口能力。这样,后续就可以包装页面到调用接口,完整整个会话服务的操作。 + +## 二、流程设计 + +如图,会话接口服务所在分层; + +
+ +
+ +- 如图,这一节主要是完成 trigger http 接口部分的能力处理,对外提供;`智能体列表`、`创建会话 session`、`发起会话(流式/非流式)` +- 注意,在实际业务开发中,接口的提供方式比较多的,也有可能提供 rpc 接口,还有可能对接口进行扩展,包装更多业务流程进去。那么这个时候,可以考虑增加 case 编排层(一个新的module模块),处理复杂流程业务。case 层的能力,主要就是分摊 trigger 层下的压力,让对外的接口层,更加轻量,只是做一些包装即可。 diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-19\350\212\202\357\274\232\344\274\232\350\257\235\346\234\215\345\212\241\346\216\245\345\217\243\345\257\271\346\216\245-ui.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-19\350\212\202\357\274\232\344\274\232\350\257\235\346\234\215\345\212\241\346\216\245\345\217\243\345\257\271\346\216\245-ui.md" new file mode 100644 index 000000000..d2a1a11ce --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-19\350\212\202\357\274\232\344\274\232\350\257\235\346\234\215\345\212\241\346\216\245\345\217\243\345\257\271\346\216\245-ui.md" @@ -0,0 +1,38 @@ +--- +title: 【更】第2-19节:会话服务接口对接-ui +pay: https://t.zsxq.com/gd2Ue +--- + +# 《AI Agent 脚手架》第2-19节:会话服务接口对接-ui + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/38RBe](https://t.zsxq.com/38RBe) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +开发脚手架接口对接 UI,简单展示服务端能力。 + +在业务场景中,使用 AI Agent 脚手架,构建项目后所提供的服务接口,一般是附带着业务应用场景能力的。这些提供的能力接口,可以对接到客服、巡检、数据、量化、风控等各类场景使用。 + +## 二、对接效果 + +这里小傅哥选择使用了 AI IDE 工具,设计 UI 界面,我们可以描述对接话术,让 AI 帮我们设计一套页面。`关于页面设计的话术提示词,我已经放到工程下。` + +### 1. 登录页 + +
+ +
+ +- 登录页,有一个演示账号,可以填充登录。 + +### 2. 对话页 + +
+ +
+ +- 对话,可以填写信息,发送请求。在一个会话ID下,它是可以记录历史上下文信息的。 \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-1\350\212\202\357\274\232\345\267\245\347\250\213\345\210\235\345\247\213\345\214\226\345\210\233\345\273\272.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-1\350\212\202\357\274\232\345\267\245\347\250\213\345\210\235\345\247\213\345\214\226\345\210\233\345\273\272.md" new file mode 100644 index 000000000..5fef2d62e --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-1\350\212\202\357\274\232\345\267\245\347\250\213\345\210\235\345\247\213\345\214\226\345\210\233\345\273\272.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第2-1节:工程初始化创建 +pay: https://t.zsxq.com/6z3Q1 +--- + +# 《AI Agent 脚手架》第2-1节:工程初始化创建 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/OxC6a](https://t.zsxq.com/OxC6a) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +搭建 AI Agent Scaffold 脚手架项目工程,并 push 代码到课程仓库,以及演示关于 Git 使用,方便后续学习使用。 + +## 二、环境配置 + +- JDK 17 +- Maven 3.8.x - [Maven 教程](https://bugstack.cn/md/road-map/maven.html) +- IntelliJ IDEA 社区版(免费) [IntelliJ IDEA 教程](https://bugstack.cn/md/road-map/intellij-idea.html) +- Git - 安装后会配置到 IntellJ IDEA 这样才能向服务端推送或者拉取代码。学习后可以知道怎么拉取、提交和比对代码。Git 教程:[https://bugstack.cn/md/road-map/git.html](https://bugstack.cn/md/road-map/git.html) + +
+ +
+ +>相关软件,在星球课程入口,编程环境中提供了下载链接。编程环境:[https://t.zsxq.com/19Rnk98M0](https://t.zsxq.com/19Rnk98M0) - 提供了已经配置好镜像的 maven 方便直接使用。 \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-20\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-skills.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-20\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-skills.md" new file mode 100644 index 000000000..d11452c49 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-20\350\212\202\357\274\232\345\242\236\345\274\272\350\243\205\351\205\215-skills.md" @@ -0,0 +1,34 @@ +--- +title: 【更】第2-20节:增强装配-skills +pay: https://t.zsxq.com/7uVom +--- + +# 《AI Agent 脚手架》第2-20节:增强装配-skills + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/7uVom](https://t.zsxq.com/7uVom) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +为对话模型(ChatModelNode)的装配,添加 skills 技能配置,允许用户使用 resource 资源和映射的 path 路径的方式,在构建 AI Agent 智能体时,完成装配。 + +skill 是什么?它像是一本技能书📚,把一阳指(mcp/py/shell/js)和狮吼功(prompt)合成了一整招。缩短了从用户把提示词发给AI客户端,进行分析,决策,再到 mcp 执行的过程,让诉求直达结果,token 减少了,幻觉减少了! + +随着 LLM 大模型能力的不断提升,并与 RAG、MCP、Skill 的结合,使得 Agent 智能体与完整的计算机环境(Computer/Phone)交互成为可能。这个过程中,一方面不断产生新的技术方案,一方面又不断的优化设计。就像 Skill 的出现,它不是替代 MCP,而是更准确的使用 MCP 能力。 + +## 二、技术介绍(skills 和 prompt + mcp) + +如图,演示了一段 skill 的编写案例; + +
+ +
+ +- 场景:案例中体现的是,对电脑性能检测后,用一段下达命令的方式,告知用户如何优化电脑性能。 +- 重点:如果不使用 skill,则需要描述一大段话术,让 ai 自己完成对用户场景诉求的分析,并按照步骤来调用对应的各个 mcp 服务(没有 skill 则需要把各类内容,都包装为 mcp 服务)。这个过程是比较消耗 token 的,也可能有不小的幻觉。现在有了 skill,我们可以适当的完整的写一段诉求文档,文档里嵌入可执行的脚本/mcp服务,让执行更可靠。 +- 用途:那都有哪些场景可以写 skill 技能书呢?🤔 如;互联网公司里的系统巡检,在接收到报警日志后,拿到一个报警的系统和接口信息,之后用 skill 技能书,分别采集出对应的系统配置、上线日志、数据库/缓存情况、运营操作记录、全链路监控上的接口耗时情况等。之后在根据我们日常排查问题的时候经验,编写过程步骤,这样会更加准确。 + +>所以,不是 skill、mcp 谁替代谁,而是 skill 对 mcp 进行增强,让 ai 执行时更加可靠。 diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-2\350\212\202\357\274\232Api\345\212\237\350\203\275\346\265\213\350\257\225.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-2\350\212\202\357\274\232Api\345\212\237\350\203\275\346\265\213\350\257\225.md" new file mode 100644 index 000000000..f19a2cb7e --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-2\350\212\202\357\274\232Api\345\212\237\350\203\275\346\265\213\350\257\225.md" @@ -0,0 +1,44 @@ +--- +title: 【更】第2-2节:Api功能测试 +pay: https://t.zsxq.com/uTPE2 +--- + +# 《AI Agent 脚手架》第2-2节:Api功能测试 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/q2Zug](https://t.zsxq.com/q2Zug) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +通过功能测试代码,使用 `Spring AI`、`LangChain4J`、`Google ADK` 框架对接 AI 服务,完成功能验证。为后续做 AI Agent 智能体脚手架做准备。 + +## 二、框架介绍 + +### 1. Spring AI + +官网:[https://docs.spring.io/spring-ai/reference/1.0/index.html](https://docs.spring.io/spring-ai/reference/1.0/index.html) + +Spring AI 项目旨在简化集成人工智能功能的应用程序的开发,避免不必要的复杂性。 + +该项目从 LangChain 和 LlamaIndex 等知名的 Python 项目中汲取灵感,但 Spring AI 并非这些项目的直接移植。该项目创立的初衷是,下一代生成式人工智能应用不仅面向 Python 开发者,还将广泛应用于多种编程语言。 + +> 在使用体验下 Spring AI 可以更好的结合 Spring 整个框架,整个接口的定义形式和使用方式,会更符合你对于 Spring 整体的使用习惯。 + +### 2. LangChain4J + +官网:[https://docs.langchain4j.info/](https://docs.langchain4j.info/) + +LangChain4j 的目标是简化将 LLM 集成到 Java 应用程序中的过程。 + +LangChain4j 始于 2023 年初 ChatGPT 热潮期间。 我们注意到与众多 Python 和 JavaScript LLM 库和框架相比,缺少 Java 对应物, 我们必须解决这个问题! 虽然我们的名字中有"LangChain",但该项目是 LangChain、Haystack、 LlamaIndex 和更广泛社区的想法和概念的融合,并加入了我们自己的创新。 + +### 3. Google ADK + +官网:[https://google.github.io/adk-docs/get-started/java/#example](https://google.github.io/adk-docs/get-started/java/#example) + +代理开发工具包 (ADK) 是一个灵活且模块化的框架,用于开发和部署 AI 代理 。ADK 针对 Gemini 和 Google 生态系统进行了优化,但它与模型和部署方式无关,并且是为……而构建的。 与其他框架的兼容性 。ADK 的设计宗旨是让代理开发更像软件开发,使开发人员能够更轻松地创建、部署和编排从简单任务到复杂工作流程的各种代理架构。 + +> 在使用体验上 Google ADK 自身是可以完整构建全部智能体的,但它又兼容了 Spring AI、LangChain4j 两个框架,让这2个框架负责 AI 对接,而 Google ADK 负责 Agent 的编排和插件的处理,这样使用起来非常不错。 diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-3\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223\351\205\215\347\275\256\350\241\250\350\256\276\350\256\241.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-3\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223\351\205\215\347\275\256\350\241\250\350\256\276\350\256\241.md" new file mode 100644 index 000000000..cd82e542a --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-3\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223\351\205\215\347\275\256\350\241\250\350\256\276\350\256\241.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第2-3节:智能体配置表设计 +pay: https://t.zsxq.com/hCtFC +--- + +# 《AI Agent 脚手架》第2-3节:智能体配置表设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/bHRBx](https://t.zsxq.com/bHRBx) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +定义使用工程 YML 文件方式,配置的通用的智能体配置表。允许用户在使用脚手架创建完成智能体后工程后,通过 YML 配置出自己需要的智能体,在结合业务场景做对应的衔接开发。 + +如果,你在思考把 YML 的配置表抽取到数据库中实现,那么就是另外一套项目[《DeepSeek RAG、MCP、Ai Agent 智能体》](https://t.zsxq.com/GwNZp) 通过前端页面拖拉拽的方式进行配置使用。感兴趣也可以扩展学习。 + +## 二、流程设计 + +如图,智能体配置表结构; + +
+ +
+ +- 首先,一个智能体配置所需的最基本信息包括;应用名称、智能体描述、智能体模块,主要的组件类配置都在智能体模块下,AiApi 负责对接 AI 接口,ChatModel 负责模型创建(也会把 AiApi 对接),之后还要创建出 MCP 工具。 +- 之后,就是对于单一智能体(Agent)的构建,这里可以顺序的创建出很多的智能体,之后到 AgentWorkflow 进行编排,构建出一个完整的智能体。**这部分映射了【第2-2节:系统架构设计】中的流程设计以及 YML 设计** \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-4\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\347\273\223\346\236\204\345\214\226\345\256\232\344\271\211.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-4\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\347\273\223\346\236\204\345\214\226\345\256\232\344\271\211.md" new file mode 100644 index 000000000..c37aec914 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-4\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\347\273\223\346\236\204\345\214\226\345\256\232\344\271\211.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第2-4节:装配域结构化定义 +pay: https://t.zsxq.com/pwR4K +--- + +# 《AI Agent 脚手架》第2-4节:装配域结构化定义 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/3GFbQ](https://t.zsxq.com/3GFbQ) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +通过`单一职责`、`规则树(组合模式)`、`工厂`、`上下文对象`、`泛型`等设计模式手段,结合领域驱动设计思想,定义智能体装配服务结构。 + +## 二、流程设计 + +如图,智能体装配结构设计; + +
+ +
+ +- 首先,最上面的是规则树(组合模式)的设计模块框架,用于各项节点流转实现,如;RootNode、AiApiNode、ChatModelNode 等。 +- 之后,定义了单一职责的 IArmoryService 装配服务接口,并通过工厂管理节点衔接服务,以及定义上下文对象。这个上下文对象,会在各个节点间记录数据并流转使用。 + +> 本节小傅哥先带着大家把功能实现框架结构定义出来,让大家厘清关于这样的框架结构设计(这是一个非常通用的手段)。之后在进行各个节点的编码实现。 \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-5\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-AiApiNode.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-5\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-AiApiNode.md" new file mode 100644 index 000000000..b46113981 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-5\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-AiApiNode.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第2-5节:装配域节点-AiApiNode +pay: https://t.zsxq.com/wetnI +--- + +# 《AI Agent 脚手架》第2-5节:装配域节点-AiApiNode + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/D3LGP](https://t.zsxq.com/D3LGP) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +从本节装配 AI Agent 智能体各个节点开始,每一节都只负责一小部分独立内容的实现,方便大家可以在回顾的时候,直接找到对应章节进行查看。 + +这一节装配第一个节点 AiApiNode,它的目的是和 AI 接口,建立请求连接。 + +## 二、流程设计 + +如图,智能体装配中 AiApiNode 部分; + +
+ +
+ +AiApiNode 节点的装配,使用的是 Spring AI 框架提供的构建方法。在咱们课程前面也讲解过 LangChain4j,后面如果你想锻炼,也可以更换下,完全都是可以到 Agent 装配的时候做兼容的。 \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-6\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-ChatModelNode.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-6\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-ChatModelNode.md" new file mode 100644 index 000000000..b738c7cc5 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-6\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-ChatModelNode.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第2-6节:装配域节点-ChatModelNode +pay: https://t.zsxq.com/mnTej +--- + +# 《AI Agent 脚手架》第2-6节:装配域节点-ChatModelNode + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/X0HRO](https://t.zsxq.com/X0HRO) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +这一节从 AiApiNode 节点流转 ChatModelNode 模型对话节点的实例化操作,以及实现 ChatModelNode 装配操作。 + +## 二、流程设计 + +如图,智能体装配中 ChatModelNode 部分; + +
+ +
+ +- 首先,这一个节点是从 AiApiNode 处理完流程,流转过来的节点。节点的流转是在 doApply 处理完成后,执行 router 路由方法。路由方法会调用当前实现类的 get 方法,获取下一个要执行节点。通过这样的方式分离逻辑区和流转区,可以让代码更好维护。 +- 之后,到了 ChatModelNode 使用 Spring AI 处理模型构建。构建前还需要从上下文获取 AiApiNode 中关于 OpenAiApi 实例化对象,用于填充到 ChatModel 实例化中。 +- 此外,ChatModelNode 还要构建关于 MCP 的构建,这里是把 MCP 填充到模型中使用,这一套都是基于 Spring AI 框架处理的。当然,除了可以使用 Spring AI 也可以使用 langchain4j、google adk 来处理关于 mcp 的部分。 \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-7\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-AgentNode.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-7\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-AgentNode.md" new file mode 100644 index 000000000..9d5236a05 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-7\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-AgentNode.md" @@ -0,0 +1,27 @@ +--- +title: 【更】第2-7节:装配域节点-AgentNode +pay: https://t.zsxq.com/908Fo +--- + +# 《AI Agent 脚手架》第2-7节:装配域节点-AgentNode + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/PFBNl](https://t.zsxq.com/PFBNl) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +这一节从 ChatModelNode 节点流转 AgentNode 节点,做智能体 LlmAgent 的实例化操作,以及实现 AgentNode 装配操作。 + +## 二、流程设计 + +如图,智能体装配中,AgentNode 部分; + +
+ +
+ +- 首先,AgentNode 节点是由 ChatModelNode 节点流转过来的,每个节点的流转都是类似的操作,处理完业务功能后,则路由到下一个节点继续完成其他业务。 +- 之后,AgentNode 是一个多 LlmAgent 装配的过程,我们在配置智能体的时候,有一些复杂的场景则要多个 LlmAgent 分别做不同的事情,来完成一个整体的流程。所以这类的智能体是多个 LlmAgent 配置。 \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-8\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-AgentWorkflowNode.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-8\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-AgentWorkflowNode.md" new file mode 100644 index 000000000..60bf9e157 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-8\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-AgentWorkflowNode.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第2-8节:装配域节点-AgentWorkflowNode +pay: https://t.zsxq.com/3mjk1 +--- + +# 《AI Agent 脚手架》第2-8节:装配域节点-AgentWorkflowNode + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/3EdmN](https://t.zsxq.com/3EdmN) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在 AiApi、ChatModel、Agent 装配完成后,接下来要进入到智能体工作流编排的操作了,他们的组合可能是 LoopAgent 把几个 LlmAgent 作为子 Agent,也有可能是 ParallelAgent 把几个 LlmAgent 作为并行,最后又会被 SequentialAgent 串行使用。 + +正是因为这块能有多重组合,所以,我们才需要有一个流转判断器的节点,让这些节点的执行可以串联起来。 + +## 二、流程设计 + +如图,智能体装配中,AgentWorkflowNode 部分; + +
+ +
+ +- 首先,这一节重点设计关于 AgentWorkflowNode 到其他3个节点节点的流转操作,包括;LoopAgent、ParallelAgentNode、SequentialAgentNode,并最终由 SequentialAgentNode 作为结束,也就是最后是一个序列化的执行。 +- 注意,LoopAgent、ParallelAgentNode、SequentialAgentNode 这三个节点,本节只关注他们的流转操作,后续在做具体的节点功能实现。 +- 另外,还有一种可能,就是单一智能体 LlmAgent 直接作为结束,没有配置 SequentialAgentNode 包装一层序列化执行,后续在扩展这部分。 \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-9\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-Loop\343\200\201Parallel\343\200\201Sequential.md" "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-9\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-Loop\343\200\201Parallel\343\200\201Sequential.md" new file mode 100644 index 000000000..4c8f4ef6a --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-2/\347\254\2542-9\350\212\202\357\274\232\350\243\205\351\205\215\345\237\237\350\212\202\347\202\271-Loop\343\200\201Parallel\343\200\201Sequential.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第2-9节:装配域节点-Loop、Parallel、Sequential +pay: https://t.zsxq.com/t29lj +--- + +# 《AI Agent 脚手架》第2-9节:装配域节点-Loop、Parallel、Sequential + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/6NKGA](https://t.zsxq.com/6NKGA) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +从 AgentWorkflowNode 开始,要进入 LoopAgent、ParallelAgent、SequentialAgent,这几个节点都是类似的,我们一起来处理下。 + +## 二、流程设计 + +如图,智能体装配中,LoopAgentNode、ParallelAgentNode、SequentialAgentNode 部分; + +
+ +
+ +- LoopAgentNode - 处理循环操作,如一个用户请求,要进行分析、执行、检测,也可以是一段git提交的代码,进行 diff 获取差异,检索代码匹配召回、做出执行review计划,后面在依次执行分析。这些都是可以做循环处理的。 +- ParallelAgentNode - 处理并行操作,如我们有一些场景,需要同步并行的一起完成数据处理任务,多条链路一起完成数据的获取、分析和决策,这样可以对复杂的流程显著的提高执行效率。 +- SequentialAgentNode - 处理串行操作,主要用于编排子智能体,和 loop 循环、parallel 并行,组合出复杂的智能体流程。当然,你也可以使用 loop 组合 sequence 或者 parallel 等处理过程。 diff --git "a/docs/md/project/ai-agent-scaffold/part-3/\347\254\2543-1\350\212\202\357\274\232Maven\350\204\232\346\211\213\346\236\266\351\205\215\347\275\256.md" "b/docs/md/project/ai-agent-scaffold/part-3/\347\254\2543-1\350\212\202\357\274\232Maven\350\204\232\346\211\213\346\236\266\351\205\215\347\275\256.md" new file mode 100644 index 000000000..d21e779af --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-3/\347\254\2543-1\350\212\202\357\274\232Maven\350\204\232\346\211\213\346\236\266\351\205\215\347\275\256.md" @@ -0,0 +1,34 @@ +--- +title: 【更】第3-1节:Maven脚手架配置 +pay: https://t.zsxq.com/jnqmk +--- + +# 《AI Agent 脚手架》第3-1节:Maven脚手架配置 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/EwCTb](https://t.zsxq.com/EwCTb) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +对 ai-agent-scaffold 脚手架工程配置 maven-archetype-plugin,生成工程脚手架。以及通过命令使用脚手架(jar)创建出新的工程。 + +脚手架的目的就在于此,我们使用一套通用的代码,按照不同的工程使用新的工程名、包名、版本,来构建一套具有相同基础能力的新的项目。 + +简单来说,maven-archetype-plugin 是 Maven 世界里的“项目模板生成器”。 + +如果把开发一个项目比作盖房子,这个插件的作用就是为你提供一套图纸和预制框架。你不需要每次都从零开始挖地基、垒砖头,只需要选好模板,它就会自动帮你把标准的目录结构和基础配置(pom.xml)搭建好。 + +## 二、流程设计 + +如图,从工程使用 maven 构建脚手架到使用的过程; + +
+ +
+ +- 左侧,对现有工程使用 maven-archetype-plugin 插件,构建工程脚手架。将当前的工程打包成一个可复用的 Archetype 模板。 +- 中间,打包好的脚手架,可以在本地直接使用,也可以发布jar到私服,让大家都可以使用。私服部分,后续在做处理。 +- 右侧,使用方可以基于命令,或者 IntelliJ IDEA 配置 Maven 脚手架的方式,创建和启动工程。这一节,我们先通过命令的方式使用。 diff --git "a/docs/md/project/ai-agent-scaffold/part-3/\347\254\2543-2\350\212\202\357\274\232\344\270\212\344\274\240jar\345\210\260maven\344\273\223\345\272\223.md" "b/docs/md/project/ai-agent-scaffold/part-3/\347\254\2543-2\350\212\202\357\274\232\344\270\212\344\274\240jar\345\210\260maven\344\273\223\345\272\223.md" new file mode 100644 index 000000000..6f3bb6717 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-3/\347\254\2543-2\350\212\202\357\274\232\344\270\212\344\274\240jar\345\210\260maven\344\273\223\345\272\223.md" @@ -0,0 +1,31 @@ +--- +title: 【更】第3-2节:上传jar到maven仓库 +pay: https://t.zsxq.com/GHNso +--- + +# 《AI Agent 脚手架》第3-2节:上传jar到maven仓库 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/6xBLn](https://t.zsxq.com/6xBLn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +发布脚手架工程 Jar 包到阿里云 Maven 私有制品库。 + +在公司里,这块的目的在于,我们设计一款通用的脚手架,让公司里的伙伴都可以使用。那么公司里会把这样的脚手架jar,推送到公司内的私服仓库,之后公司内的用户配置了私服 Maven 地址,就可以使用了。 + +注意,可以检索下 Maven 私服搭建,面试也可能会问,企业里应该怎么做。 + +## 二、流程设计 + +如图,把 jar 发布到 maven 私服仓库; + +
+ +
+ +- 在整个大流程中,我们要上传jar到maven私服仓库,这部分阿里云有提供,可以申请使用。另外,可以尝试检索下 Maven 私服搭建和使用。 +- 这一部分会使用到 IntelliJ IDEA Maven Deploy + Maven Settings.xml 配置阿里云私服。 diff --git "a/docs/md/project/ai-agent-scaffold/part-3/\347\254\2543-3\350\212\202\357\274\232\351\203\250\347\275\262\350\204\232\346\211\213\346\236\266\347\275\221\351\241\265.md" "b/docs/md/project/ai-agent-scaffold/part-3/\347\254\2543-3\350\212\202\357\274\232\351\203\250\347\275\262\350\204\232\346\211\213\346\236\266\347\275\221\351\241\265.md" new file mode 100644 index 000000000..023a3d9ba --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-3/\347\254\2543-3\350\212\202\357\274\232\351\203\250\347\275\262\350\204\232\346\211\213\346\236\266\347\275\221\351\241\265.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第3-3节:部署脚手架网页 +pay: https://t.zsxq.com/J3YHa +--- + +# 《AI Agent 脚手架》第3-3节:部署脚手架网页 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/UBTWu](https://t.zsxq.com/UBTWu) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +通过 Nginx 部署网页,把 archetype-catalog.xml 放到网页文件夹下,以便于可以通过 http 配置地址,使用脚手架。 + +这样做的目的,是为了提供一个公用的地址,让所有的用户配置地址后,都可以使用这套脚手架。 + +## 二、流程设计 + +如图,部署网页版后用户使用流程; + +
+ +
+ +- 当你打开 [https://repo.maven.apache.org/maven2/]([https://repo.maven.apache.org/maven2/) 公用脚手架你会发现,在最后面有一个 `archetype-catalog.xml` 文件,也就是这个文件约定了可以使用的脚手架。那么我们就可以依次方式,配置一个自己的网页,在网页下放自己的 `archetype-catalog.xml` 文件,这样我们就可以使用自己实现的脚手架了。 +- 当我们把脚手架这样设计后,所有使用这个网页版的用户,就都可以直接配置使用了。注意使用的过程中,网页版的脚手架配置后,会拉取私服仓库的脚手架jar包。 diff --git "a/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-0\350\212\202\357\274\232ai + draw.io \344\272\247\345\223\201\350\256\276\350\256\241.md" "b/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-0\350\212\202\357\274\232ai + draw.io \344\272\247\345\223\201\350\256\276\350\256\241.md" new file mode 100644 index 000000000..21afc1d5b --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-0\350\212\202\357\274\232ai + draw.io \344\272\247\345\223\201\350\256\276\350\256\241.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第4-0节:ai + draw.io 产品设计 +pay: https://t.zsxq.com/AAwjy +--- + +# 《AI Agent 场景应用 - ai draw.io》第4-0节:ai + draw.io 产品设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/035hj](https://t.zsxq.com/035hj) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +基于 AI Agent 智能体脚手架,在 draw.io 场景,使用 react 开发一套 ai + draw.io 智能绘图功能场景。 + +当前章节的这套场景功能会比较轻量,不会结合toc用户诉求。但当你越来越多的熟练星球的各个项目以后,你可以在 ai + draw.io 的功能上,添加公众号扫码登录、微信支付购买使用额度 + 拼团购买、数据库记录个人绘图信息、分享绘图数据在统一平台、其他用户可以查看和收藏,以及使用后有抽奖、积分、兑换营销能力等。这些功能在星球的其他项目都有体现,可以陆续学习后扩展补充。 + +## 二、产品效果 + +如图,ai + draw.io 使用 ai agent 脚手架,所能实现的效果; + +
+ +
+ +- 首先,需要结合 [react-drawio](https://github.com/marcveens/react-drawio) 插件,把 draw.io 嵌入到 react 程序里。在 react-drawio 的插件里,提供了相关的 API 操作,这可以让我们把 ai 生成的 xml 文件,让 draw.io 渲染出来。也可以读取到 draw.io 上的内容,再发给 ai 进行分析和调整。 +- 之后,是 ai agent 脚手架开发的程序,编写智能体提示词,让其可以以 xml 的格式返回。当然这部分也可以做一些限定,比如返回的数据是一个带有类型和内容的对象,如果类型 type 是对话,那么可以进行多次交流,如果返回类型是 xml,那么则直接渲染。目前的案例程序,会先直接返回 xml 直接渲染进来。 +- 最后,我们做这类内容,我们先有一个简单的清晰的流程和实现方案,能把整个流程串联起来。当你做的透彻以后,就可以继续扩展迭代功能了。 diff --git "a/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-1\350\212\202\357\274\232\345\210\235\345\247\213\345\214\226\345\267\245\347\250\213\346\220\255\345\273\272.md" "b/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-1\350\212\202\357\274\232\345\210\235\345\247\213\345\214\226\345\267\245\347\250\213\346\220\255\345\273\272.md" new file mode 100644 index 000000000..48d967c17 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-1\350\212\202\357\274\232\345\210\235\345\247\213\345\214\226\345\267\245\347\250\213\346\220\255\345\273\272.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第4-1节:初始化工程搭建 +pay: https://t.zsxq.com/PDeYZ +--- + +# 《AI Agent 场景应用 - ai draw.io》第4-1节:初始化工程搭建 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/KiliX](https://t.zsxq.com/KiliX) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +初始化搭建 ai draw.io 前端工程,因为 draw.io 的开发插件是 React 语言的,所以我们也要基于 React 语言构建工程。 + +>这部分前端的内容,会使用即可。如果感兴趣,也可以在 TypeScript 官网学习下,它的语言结构也比较清晰,甚至和我们学习的 Java 是有类似的地方的。 + +本节初始化工程搭建开发后,就可以基于 AI IDE 工具,来完成后续的开发了。这部分对后端程序员是比较友好的。当然找工作,一般后端岗位是不会问前端的,所以你可以仅仅是当做使用即可。 + +## 二、开发环境 + +- Node.js v20+ - [https://nodejs.org/zh-cn](https://nodejs.org/zh-cn) - 下载安装即可。 +- WebStorm 2023.1 - 因为自带了开发前端的工具,所以非常好用。星球课程入口,编程环境,软件下载。里面提供了安装包。地址:[https://drive.weixin.qq.com/s?k=ACMA4AfQABU0svnJ27](https://drive.weixin.qq.com/s?k=ACMA4AfQABU0svnJ27) +- 源地址设置;`npm config set registry https://registry.npmmirror.com` - 安装好环境后,设置下源地址。否则在后面构建项目会很慢。 +- TypeScript01:[https://www.runoob.com/typescript/ts-tutorial.html](https://www.runoob.com/typescript/ts-tutorial.html) - 课程资料,简单的菜鸟入门教程。学习之后也能看懂 TypeScript 代码。所有的面向对象语言代码,基本是通用的。 +- TypeScript02:[https://typescript.bootcss.com/namespaces.html](https://typescript.bootcss.com/namespaces.html) - 课程资料,简单的菜鸟入门教程。学习之后也能看懂 TypeScript 代码。所有的面向对象语言代码,基本是通用的。 diff --git "a/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-2\350\212\202\357\274\232\345\234\250\351\241\265\351\235\242\345\265\214\345\205\245draw.io\347\273\204\344\273\266\345\222\214\345\257\271\350\257\235\346\241\206.md" "b/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-2\350\212\202\357\274\232\345\234\250\351\241\265\351\235\242\345\265\214\345\205\245draw.io\347\273\204\344\273\266\345\222\214\345\257\271\350\257\235\346\241\206.md" new file mode 100644 index 000000000..98b916dcc --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-2\350\212\202\357\274\232\345\234\250\351\241\265\351\235\242\345\265\214\345\205\245draw.io\347\273\204\344\273\266\345\222\214\345\257\271\350\257\235\346\241\206.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第4-2节:在页面嵌入draw.io组件和对话框 +pay: https://t.zsxq.com/JoT4f +--- + +# 《AI Agent 场景应用 - ai draw.io》第4-2节:在页面嵌入draw.io组件和对话框 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/wtWx6](https://t.zsxq.com/wtWx6) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在 React 前端工程中,嵌入 draw.io 组件。以及在整个页面的右侧放入一个对话框,用于后续与服务端的 ai 接口进行对话。 + +这部分的实现,会使用到 ai ide 工具来处理,你常用的任何一款工具都可以。 + +## 二、流程设计 + +如图,前端页面交互的流程设计; + +
+ +
+ +- 这是一个简单的交互,引入 react-drawio 到初始页面,并在右侧设置一个对话框。 diff --git "a/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-3\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223API\346\216\245\345\217\243\345\257\271\346\216\245.md" "b/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-3\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223API\346\216\245\345\217\243\345\257\271\346\216\245.md" new file mode 100644 index 000000000..0edb53933 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-3\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223API\346\216\245\345\217\243\345\257\271\346\216\245.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第4-3节:智能体API接口对接 +pay: https://t.zsxq.com/hrQVL +--- + +# 《AI Agent 场景应用 - ai draw.io》第4-3节:智能体API接口对接 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/RnvaG](https://t.zsxq.com/RnvaG) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +通过脚手架创建 AI Agent 智能体服务端工程,并配置用于绘制 draw.io 流程图的专属提示词。之后在前端工程对接智能体 API 服务接口,包括;创建会话 SessionID、调用对话接口进行绘图(这部分会限制智能体以 drawio 格式返回结果)。 + +## 二、流程设计 + +如图,前端页面与服务端交互的UML流程设计; + +
+ +
+ +- 首先,从用户发起,打开页面开始,则从服务端的智能体列表加载接口,返回智能体列表。 +- 之后,选择智能体进行对话,这个过程要先创建会话ID。也就是所有的本次的交互,会有一个会话ID进行,这样在对话的过程中会记录上下文,输出的结果也会更加准确。 +- 最后,服务端返回智能体结果,是以 draw.io xml 的方式的方式返回的,之后渲染到 draw.io 面板上。 diff --git "a/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-4\350\212\202\357\274\232AI+\347\224\250\346\210\267+DrawIO\357\274\214\344\272\244\344\272\222\345\274\217\347\224\273\345\233\276.md" "b/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-4\350\212\202\357\274\232AI+\347\224\250\346\210\267+DrawIO\357\274\214\344\272\244\344\272\222\345\274\217\347\224\273\345\233\276.md" new file mode 100644 index 000000000..ed9ecd276 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-4\350\212\202\357\274\232AI+\347\224\250\346\210\267+DrawIO\357\274\214\344\272\244\344\272\222\345\274\217\347\224\273\345\233\276.md" @@ -0,0 +1,31 @@ +--- +title: 【更】第4-4节:AI+用户+DrawIO,交互式画图 +pay: https://t.zsxq.com/BLDCn +--- + +# 《AI Agent 场景应用 - ai draw.io》第4-4节:AI+用户+DrawIO,交互式画图 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[待更新](#) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +增强服务端 ai agent 智能体配置,以分析,绘制,检查的流程处理 draw.io 的图的制作,如果用户信息不准确的时候,则返回给前端让用户补全信息。 + +此外,对于前端的使用也做一些优化处理,包括;增加对话列表页、保存用户绘图信息到浏览器、交互式完成绘图操作、提供案例绘图、携带历史绘图等。 + +## 二、流程设计 + +如图,AI 交互式绘图流程设计; + +
+ +
+ +- 首先,第一个改造点是服务端的智能体流程配置,让 ai agent 对用户的请求进行分析、绘制、检查,如果用户提供的信息不全则让用户继续补充,如果全面则可以直接绘制。那么这个时候,就要给前端返回一个 json 结构,并按照不同的类型返回数据。 +- 之后,因为服务端智能体返回的不再是一个 draw.io 的 xml,所以要对 agent 智能体返回的结果,进行序列化成对象,再返回给前端。前端拿到结果后要对不同的类型的结果,反馈给用户(user)、渲染到 draw.io 页面(xml)。 +- 此外,除了结果的渲染,对前端的对话操作,增加一个历史记录页,保存 draw.io 的绘图内容到浏览器里。这样刷新页面也可以看到历史的画图。 +- 注意,你还可以再此基础上,增加更多的功能。如,学习了星球里的小型支付,那么可以把扫码登录、支付购买额度,对接进来。也可以把大营销的积分,兑换,抽奖对接进来。这些内容,都是可以衔接起来的。 diff --git "a/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-5\350\212\202\357\274\232ai-draw-io\357\274\214\344\272\221\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262.md" "b/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-5\350\212\202\357\274\232ai-draw-io\357\274\214\344\272\221\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262.md" new file mode 100644 index 000000000..25002cfd5 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-4/\347\254\2544-5\350\212\202\357\274\232ai-draw-io\357\274\214\344\272\221\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262.md" @@ -0,0 +1,34 @@ +--- +title: 【更】第4-5节:ai-draw-io,云服务器部署 +pay: https://t.zsxq.com/5h1K1 +--- + +# 《AI Agent 场景应用 - ai draw.io》第4-5节:ai-draw-io,云服务器部署 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/UaVxl](https://t.zsxq.com/UaVxl) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在云服务器(2c4g)部署 ai-draw-io 前后端项目,后端提供智能体能力,前端提供绘图操作。本次构建的镜像,小傅哥提供了动态更换前端访问服务的IP配置,在不进行构建镜像时,也可以直接使用。 + +>注意,ai-draw-io 绘图操作,模型配置的越好,效果也越好。gpt-5.1 比 gpt-4.1 绘制的效果更好。 + +## 二、部署过程 + +如图,部署过程步骤流程; + +
+ +
+ +- 首先,你需要一台2c4g云服务器(安装 Ubuntu 24),推荐购买 [https://618.gaga.plus](https://618.gaga.plus) - 腾讯云暂时有买1年送3个月,可以配和 [https://bugstack.cn/md/road-map/ssl-httpsok.html](https://bugstack.cn/md/road-map/ssl-httpsok.html) 申请免费 ssl(自动续期)适合后续有域名的时候使用。 +- 之后,在你购买了一台云服务器后,你可以使用小傅哥提供的一键安装脚本,把云服务器部署好 Docker 环境 + Portainer 管理面板。安装脚本:[https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install](https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install) +- 然后,这里还有项目的部署教程,这里是小傅哥录制好的视频,教你如何部署项目。教程:[https://t.zsxq.com/iDuCt](https://t.zsxq.com/iDuCt) - `你可以做为补充学习,本课程也会带着你部署项目。` +- 另外,这里还有一个本地对项目构建好镜像后推送到阿里云docker镜像库,方便大家上传和拉取。其实也可以推送到官网 docker hub,但会需要代理。教程(阿里云docker镜像使用):[https://t.zsxq.com/XdoWr](https://t.zsxq.com/XdoWr) 阿里云镜像库地址:[https://cr.console.aliyun.com/cn-hangzhou/instance/credentials](https://cr.console.aliyun.com/cn-hangzhou/instance/credentials) +- 注意,提前在云服务器安全组开放端口;`9000-docker 管理面板`、`8091-后端接口`、`3000-前端页面` + +> 综上,所有的云服务器操作,在星球「码农会锁」都提供好了学习教程,可以参考总地址:[https://t.zsxq.com/19osWS4qj](https://t.zsxq.com/19osWS4qj) diff --git "a/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-1\350\212\202\357\274\232\345\210\235\345\247\213\345\214\226\345\267\245\347\250\213\346\220\255\345\273\272.md" "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-1\350\212\202\357\274\232\345\210\235\345\247\213\345\214\226\345\267\245\347\250\213\346\220\255\345\273\272.md" new file mode 100644 index 000000000..783ab8a03 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-1\350\212\202\357\274\232\345\210\235\345\247\213\345\214\226\345\267\245\347\250\213\346\220\255\345\273\272.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第5-1节:初始化工程搭建 +pay: https://t.zsxq.com/ELrPx +--- + +# 《AI Agent 场景应用 - MobileOpenClaw》第5-1节:初始化工程搭建 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/dx4wS](https://t.zsxq.com/dx4wS) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +本节初始搭建 MobileOpenClaw - `智能体手机`,服务端工程和安卓网关工程。服务端基于 AI Agent Scaffold 脚手架创建,用于智能体决策部分。安卓作为网关终端,设计接收智能体下发的指令,以及完成一些列动作,如;`启动应用`、`点击指定坐标`、`输入文本`、`滑动屏幕`、`长按`、`双击`、`请求人工接管(登录/验证码)`等。 + +
+ +
+ +> 整个 MobileOpenClaw - 智能体手机,使用的是`安卓`开发的手机端 apk 应用,它可以拿到更高的权限,方便做工程开发测试。 + +## 二、开发环境 + +- JDK 17、Maven 3.8.x、SpringBoot 3.4.3 ~ 4.1.0-M1、Spring AI 1.1.0-M3 ~ 2.0.0-M2、Google ADK +- IntelliJ IDEA CE 2023+ +- Android Studio - 官网(下载):[https://developer.android.com/studio?hl=zh-cn#get-android-studio](https://developer.android.com/studio?hl=zh-cn#get-android-studio) 星球(下载):[https://t.zsxq.com/19Rnk98M0](https://t.zsxq.com/19Rnk98M0) `首次安装时间会比较长` diff --git "a/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-2\350\212\202\357\274\232\346\211\213\346\234\272\347\275\221\345\205\263\345\212\250\344\275\234\350\260\203\345\272\246\350\256\276\350\256\241.md" "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-2\350\212\202\357\274\232\346\211\213\346\234\272\347\275\221\345\205\263\345\212\250\344\275\234\350\260\203\345\272\246\350\256\276\350\256\241.md" new file mode 100644 index 000000000..14bc1e690 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-2\350\212\202\357\274\232\346\211\213\346\234\272\347\275\221\345\205\263\345\212\250\344\275\234\350\260\203\345\272\246\350\256\276\350\256\241.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第5-2节:手机网关动作调度设计 +pay: https://t.zsxq.com/ELrPx +--- + +# 《AI Agent 场景应用 - MobileOpenClaw》第5-2节:手机网关动作调度设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/GdwGE](https://t.zsxq.com/GdwGE) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +初步设计安卓手机端网关服务,通过接收指令,完成一系列动作调度。动作调度指令,由服务端开启一个 socket server,之后由手机端 socket client 连接,并接收指令驱动手机动作。包括;打开、点击、首屏、截图、输入等。 + +后续这套网关调度,由AI Agent 智能体根据用户的诉求,在一些列规划分析后,指令下达。让手机端完成用户诉求。 + +## 二、流程设计 + +如图,通信设备网关调度指令设计; + +
+ +
+ +- 首先,核心的内容是右侧的安卓端,开发一系列控制手机设备的指令动作。之后这些指令动作由 socket 客户端接收 socket 服务端下发的指令完成操作。这里的想法也就是让手机端成为一个指令执行器,具体操作都是由服务端控制,这样就可以满足后续 AI 操作手机的目的。 +- 之后,本节的服务端是编写一个 Socket Server 的测试代码,让手机端连接,之后由服务端下发指令进行测试验证。 diff --git "a/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-3\350\212\202\357\274\232\346\234\215\345\212\241\347\253\257\347\275\221\347\273\234\351\200\232\344\277\241\350\256\276\350\256\241(Netty).md" "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-3\350\212\202\357\274\232\346\234\215\345\212\241\347\253\257\347\275\221\347\273\234\351\200\232\344\277\241\350\256\276\350\256\241(Netty).md" new file mode 100644 index 000000000..e1956f74a --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-3\350\212\202\357\274\232\346\234\215\345\212\241\347\253\257\347\275\221\347\273\234\351\200\232\344\277\241\350\256\276\350\256\241(Netty).md" @@ -0,0 +1,31 @@ +--- +title: 【更】第5-3节:服务端网络通信设计(Netty) +pay: https://t.zsxq.com/IB8jJ +--- + +# 《AI Agent 场景应用 - MobileOpenClaw》第5-3节:服务端网络通信设计(Netty) + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/UUvY7](https://t.zsxq.com/UUvY7) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +引入 Netty 框架,设计服务端 Socket Server 通信模型 + Future 等待响应方式获取客户端(手机)反馈结果。 + +这样设计的目的就是为了整个流程设计,从用户端发起请求,到后续章节AI分析决策产生指令,再通过 Socket 服务下发到手机端完成一些列的操作动作。 + +## 二、流程设计 + +如图,从服务端下发指令到客户端(手机)的流程设计; + +
+ +
+ +- 首先,要为整个通信设计一个 Socket 通信模型,以便于服务端和客户端,保持信息数据交互。那么这里在领域层添加了一套 MobileClawService 的服务。 +- 之后,整个通信服务的处理,是由基础设施层完成的,发送给手机端指令后,还需要一个等待,用于达到同步响应的效果。否则 socket 通信是异步的,再从其他入口返回来就不好处理了。 + +> 关于 Netty 这里有一些基础案例教程可以学习[《Netty 基础教程》](https://bugstack.cn/md/netty/base/2019-07-30-netty%E6%A1%88%E4%BE%8B%EF%BC%8Cnetty4.1%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8%E7%AF%87%E9%9B%B6%E3%80%8A%E5%88%9D%E5%85%A5JavaIO%E4%B9%8B%E9%97%A8BIO%E3%80%81NIO%E3%80%81AIO%E5%AE%9E%E6%88%98%E7%BB%83%E4%B9%A0%E3%80%8B.html) diff --git "a/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-4\350\212\202\357\274\232\345\210\235\346\255\245\351\200\232\350\277\207\346\231\272\350\203\275\344\275\223\357\274\214\346\223\215\344\275\234\346\211\213\346\234\272\350\256\276\345\244\207.md" "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-4\350\212\202\357\274\232\345\210\235\346\255\245\351\200\232\350\277\207\346\231\272\350\203\275\344\275\223\357\274\214\346\223\215\344\275\234\346\211\213\346\234\272\350\256\276\345\244\207.md" new file mode 100644 index 000000000..2fbee856a --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-4\350\212\202\357\274\232\345\210\235\346\255\245\351\200\232\350\277\207\346\231\272\350\203\275\344\275\223\357\274\214\346\223\215\344\275\234\346\211\213\346\234\272\350\256\276\345\244\207.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第5-4节:初步通过智能体,操作手机设备 +pay: https://t.zsxq.com/O4m6n +--- + +# 《AI Agent 场景应用 - MobileOpenClaw》第5-4节:初步通过智能体,操作手机设备 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/dqpLb](https://t.zsxq.com/dqpLb) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +初步配置 AI Agent 智能体,分析用户意图,操作手机使用。以及搭配前端操作页面,实时渲染手机当前屏幕最新结果。让用户可以可视化的方式看到手机的动作变化。 + +>可扩展点;将来你可以在智能体功能上对接微信公众号,通过手机端微信通过文字或者语音的方式,操作这台放在家中手机设备完成一些任务的处理。 + +## 二、流程设计 + +如图,从前端用户请求 -> 智能体意图分析和执行 -> 安卓设备指令应答,流程设计; + +
+ +
+ +- 首先,我们先来初步的添加一个智能体配置,以及提供一个页面来串联从用户发起到智能体分析、决策、执行,再传递指令给安卓端的一个操作流程。 +- 之后,整个智能体的操作(轮训处理和拿到决策结果),目前先直接放到 trigger 里执行,后续在细化拆分到编排层。 \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-5\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223\345\267\245\344\275\234\346\265\201\350\256\276\350\256\241.md" "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-5\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223\345\267\245\344\275\234\346\265\201\350\256\276\350\256\241.md" new file mode 100644 index 000000000..c05931c0b --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-5\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223\345\267\245\344\275\234\346\265\201\350\256\276\350\256\241.md" @@ -0,0 +1,27 @@ +--- +title: 【更】第5-5节:智能体工作流设计 +pay: https://t.zsxq.com/v7M6t +--- + +# 《AI Agent 场景应用 - MobileOpenClaw》第5-5节:智能体工作流设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/dqpLb](https://t.zsxq.com/dqpLb) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +通过增加 case 层,分摊 trigger 触发器层,对智能体接口(`AgentServiceController#chat`)流程实现中的复杂逻辑处理。这种设计手段,在复杂的业务流程工程实现里是非常场景,我们经过会通过包的职责,来划分功能单元,让整个结构在复杂业务的迭代中,可以保持易于扩展和维护。 + +## 二、流程设计 + +如图,从 trigger 触发器层的功能实现到 case 编排层的设计; + +
+ +
+ +- 首先,一个大的方向,是把图中,上部分 5-4节中的 trigger 内实现的流程,迁移到 5-5 节中 编排层进行处理。以此降低 trigger 层的逻辑功能复杂度。 +- 之后,通过编排逻辑模块,按照功能职责划分不同的类,来实现各个功能逻辑。也就是以前一堆的编排,拆分出不同的逻辑单元,以后看到类就能知道它在做什么。 \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-6\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223\345\274\202\346\255\245\345\223\215\345\272\224\345\261\225\347\244\272\346\211\247\350\241\214\350\277\207\347\250\213.md" "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-6\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223\345\274\202\346\255\245\345\223\215\345\272\224\345\261\225\347\244\272\346\211\247\350\241\214\350\277\207\347\250\213.md" new file mode 100644 index 000000000..79126b0a7 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-6\350\212\202\357\274\232\346\231\272\350\203\275\344\275\223\345\274\202\346\255\245\345\223\215\345\272\224\345\261\225\347\244\272\346\211\247\350\241\214\350\277\207\347\250\213.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第5-6节:异步结果响应 +pay: https://t.zsxq.com/PfpTF +--- + +# 《AI Agent 场景应用 - MobileOpenClaw》第5-6节:异步结果响应 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/l1RLL](https://t.zsxq.com/l1RLL) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +修改智能体对话(web控制手机)请求为异步响应式接口,实时反馈到用户端(web)当前的执行动作。那么,这里要把 `Response` 调整为 `ResponseBodyEmitter` + +>**`ResponseBodyEmitter`** 是 Spring Framework(具体来说是 Spring Web MVC)中用于处理异步 HTTP 请求的一个核心类。它的主要作用是**允许服务端在一个 HTTP 请求的生命周期内,异步地、多次向客户端发送数据**。 + +## 二、流程设计 + +如图,在智能体处理流程中添加 ResponseBodyEmitter 异步响应设计; + +
+ +
+ +- 在整个接口调用流程中,穿插进入 ResponseBodyEmitter 进行异步结果的响应处理。 +- 这部分没有逻辑的变动,只是把过程数据渲染回去。如果你还想有一些其他的渲染,也可以通过这样的方式处理。 \ No newline at end of file diff --git "a/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-7\350\212\202\357\274\232\344\275\277\347\224\250AutoGLM-Phone-9B\346\236\204\345\273\272\346\211\213\346\234\272\346\231\272\350\203\275\344\275\223.md" "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-7\350\212\202\357\274\232\344\275\277\347\224\250AutoGLM-Phone-9B\346\236\204\345\273\272\346\211\213\346\234\272\346\231\272\350\203\275\344\275\223.md" new file mode 100644 index 000000000..d5f937f01 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-7\350\212\202\357\274\232\344\275\277\347\224\250AutoGLM-Phone-9B\346\236\204\345\273\272\346\211\213\346\234\272\346\231\272\350\203\275\344\275\223.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第5-7节:使用AutoGLM-Phone-9B构建手机智能体 +pay: https://t.zsxq.com/6qOqE +--- + +# 《AI Agent 场景应用 - MobileOpenClaw》第5-7节:使用AutoGLM-Phone-9B构建手机智能体 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/06kx8](https://t.zsxq.com/06kx8) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +引入智谱发布的 autoglm-phone-9b 专属模型,构建手机智能体。专属模型对手机上的内容操作有更为全面流程控制,比通用视觉模型在处理用户动作时会更加准确。目前这套模型可以使用官网(限时免费 [autoglm-phone](https://docs.bigmodel.cn/cn/guide/models/vlm/autoglm-phone)),也可以在 24G * 2 显卡[自己部署](https://bugstack.cn/md/algorithm/model/autoglm-phone-agent.html)。所以,如果你考虑的是将来在一些场景使用,成本相对也是很低的。 + +## 二、流程设计 + +如图,通过 autoglm-phone-9b 专属模型,构建手机智能体设计; + +
+ +
+ +- 首先,我们把之前的通用模型的实现,定义为 flow 我们要自己编写流程。把专属的手机模型定义为 auto,因为他提供了默认的一些专属特性,可以减少我们流程化上的操作。 +- 之后,对照来看,autoglm-phone-9b 模型,会为我们返回具体的手机的操作指令,如点击、打开、滑动、双击、回到主屏幕等。这部分内容在智谱官网访问也有说明 [AutoGLM-Phone](https://docs.bigmodel.cn/cn/guide/models/vlm/autoglm-phone) +- 那么,现在需要我们改动的内容,主要是围绕着特定官网的给的智能体 prompt 提示词,编写智能体处理过程,与网关通信完成一些列的流程操作。 diff --git "a/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-8\350\212\202\357\274\232\345\244\232\347\211\210\346\234\254\345\256\211\345\215\223\347\211\210\346\234\254\347\255\226\347\225\245\346\224\257\346\214\201.md" "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-8\350\212\202\357\274\232\345\244\232\347\211\210\346\234\254\345\256\211\345\215\223\347\211\210\346\234\254\347\255\226\347\225\245\346\224\257\346\214\201.md" new file mode 100644 index 000000000..21d970242 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-8\350\212\202\357\274\232\345\244\232\347\211\210\346\234\254\345\256\211\345\215\223\347\211\210\346\234\254\347\255\226\347\225\245\346\224\257\346\214\201.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第5-8节:多版本安卓版本策略支持 +pay: https://t.zsxq.com/kpgKo +--- + +# 《AI Agent 场景应用 - MobileOpenClaw》第5-8节:多版本安卓版本策略支持 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/kpgKo](https://t.zsxq.com/kpgKo) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +安卓端的网关终端接收 AI Agent 智能体,通过 Socket 下发指令,完成一系列操作动作。但在一些安卓设备测试中发现,不同的版本安卓它的 API 也是有差异的,如低版本的截图方法在高版本中就没法支持。因此我们需要做一些策略化的处理,自动检测安卓版本,选择不同的 API 进行处理。 + +> 本节的代码调整主要在安卓端(Kotlin),这部分代码直接使用就可以。如果看了不少 Kotlin 语言,也可以编写实现。 + +## 二、流程设计 + +如图,关于安卓端的API策略设计; + +
+ +
+ +- 首先,安卓网关终端的改动主要在于api策略这部分的处理,按照不同的 api 版本来处理。这部分是使用 AI IDE 工具实现的内容。AI 对于非业务的复杂串联的,开发单一工具的会比较容易。很适合有编程思维,但对某个类型的语言,没有太多开发的伙伴。 +- 另外,如果你有安卓设备测试,还可能还有一些其他截屏的限制,这部分后面还要引入录屏截取一帧的操作。 diff --git "a/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-9\350\212\202\357\274\232\344\274\232\350\257\235\344\270\212\344\270\213\346\226\207\347\273\206\345\214\226\345\244\204\347\220\206.md" "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-9\350\212\202\357\274\232\344\274\232\350\257\235\344\270\212\344\270\213\346\226\207\347\273\206\345\214\226\345\244\204\347\220\206.md" new file mode 100644 index 000000000..835785d82 --- /dev/null +++ "b/docs/md/project/ai-agent-scaffold/part-5/\347\254\2545-9\350\212\202\357\274\232\344\274\232\350\257\235\344\270\212\344\270\213\346\226\207\347\273\206\345\214\226\345\244\204\347\220\206.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第5-9节:会话上下文细化处理 +pay: https://t.zsxq.com/eSEVg +--- + +# 《AI Agent 场景应用 - MobileOpenClaw》第5-9节:会话上下文细化处理 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/kpgKo](https://t.zsxq.com/kpgKo) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +本章要解决2个场景问题;一个是智能体服务端,上下文对话内容超长报错。另外一个是安卓网关端,新版本的安卓API,会限制在隐藏当前app后对其他应用的截屏。 + +## 二、设计方案 + +### 1. 上下文超长 + +首先是 autoglm-phone 模型的上下文token限制 `You requested a total of 26891 tokens: 25867`,因此不能把过多的历史信息都在每次对话的发送给模型。 + +这里一种可以通过 `InMemoryMemoryService` 的方式,自己实现一个记忆上下文,每次只是记录用户请求和最后N条模型处理结果数据。 + +也可以使用另外一种方式是 `MySpringAI` 我们有在前面开发阶段自己实现了一个类,这个类会处理历史信息到模型请求里。因此可以从集合里遍历,拿到必要的信息来处理。 + +### 2. 录屏取一帧 + +鉴于测试验证中发现,不少新版安卓的设备,不限制在我们应用隐藏后,截图打开的应用的。因此这部分我们采用开启视频录制,之后在需要的时候,直接取一帧视频作为截图使用即可。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-0\350\212\202\357\274\232AiAgent \351\241\271\347\233\256\344\273\213\347\273\215\345\222\214\347\263\273\347\273\237\346\274\224\347\244\272.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-0\350\212\202\357\274\232AiAgent \351\241\271\347\233\256\344\273\213\347\273\215\345\222\214\347\263\273\347\273\237\346\274\224\347\244\272.md" new file mode 100644 index 000000000..a2309535b --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-0\350\212\202\357\274\232AiAgent \351\241\271\347\233\256\344\273\213\347\273\215\345\222\214\347\263\273\347\273\237\346\274\224\347\244\272.md" @@ -0,0 +1,124 @@ +--- +title: 【更】第3-0节:Ai Agent 项目介绍和系统演示 +lock: no +--- + +# 《Ai Agent》第3-0节:Ai Agent 项目介绍和系统演示 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/DcL2p](https://t.zsxq.com/DcL2p) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +**25年3月初**,小傅哥,带着大家开启了 DeepSeek RAG、MCP 项目,随后兴起 MCP 服务提供的热潮,包括;支付宝、百度、高德,等等大厂开启了 MCP 服务计划。直至现在,市面上已经有了场景非常丰富的 MCP 服务。**那些第一波跟着小傅哥学习的伙伴,早早的让简历上多了一笔 MCP 服务开发和使用的经验!** + +
+ +
+ +**接下来,小傅哥将带着小伙伴,再往前多走一步!** + +RAG 教了,MCP 搞了,那么现在是时候,实现一套自动化的 Ai Agent 服务了。 + +如图,以通过数据库表动态配置的手段,完成相关物料的加载,包括;`模型(gpt-4.1/deepseek)`、`客户端`、`对话预设`、`执行规划(Planning)`、`顾问(记忆、RAG、日志)`、`工具(MCP`)等,在把单个 Client 串联,完成整个 Agent 调用链。这样一个 Agent 调用链可以以对话形式使用或通过 Agent 动态任务自动执行。 + +
+ +
+ +这套项目,小傅哥为它干了`1.87万`行代码(前后端),`14张`数据库表,全程动态化构建模块 Bean 对象,预热装配 Agent 服务。达到随用随配,自主组建出想要的各类的 Agent 功能服务。就以现在的丰富的 MCP 市场来可以说是,广阔天地,大有可为!在这套项目架构下,可以扩展出非常多的东西。 + +接下来,小傅哥就给大家,细致的介绍下这套项目,以及截图演示运行效果。 + +> 🧧 文末提供了全套 AI、RAG、MCP、Agent 项目、开发教程以及工程源码。此外还有非常多的互联网大厂项目(17个),都可以一并获取学习。 + +## 一、项目演示 + +这套项目的功能非常强大,全部都以 Agent 方式进行通信。所有的 Agent 都可以动态化配置,解耦的非常强👍🏻。接下来,小傅哥给大家演示下使用效果。 + +### 1. 前端页面 + +
+ +
+ +- 首先,我为智能对话体(MCP)配置了联网、CSDN自动发帖、文件操作服务。 +- 之后,我们可以通过预设的提示词模板,来调用对应的 MCP 服务,也可以多个 MCP 一起调用。如联网检索文章、生成解答,发布到论坛,在把文章名称记录到本地文件。这一系列操作都是可以的。 +- MCP 服务平台; + + - https://mcpfound.cc/ + - https://mcp.so/ + - https://sai.baidu.com/mcp + +> 结合知识库、MCP、提示词规划、上下文记忆,可以有非常多的场景可以玩。后续小傅哥还会继续分享可玩场景。 + +### 2. 后台页面 + +#### 2.1 配置智能体(动态预热) + +
+ +
+ +#### 2.2 动态任务 + +
+ +
+ +- 系统会自动的把任务加载到系统内执行,完成智能体的调用。 +- 有了这个操作,你配置好的智能体,他就可以连续24小时的工作了。除了自动发文章,你可以配置出各种东西。比如特朗普推特、黄金、股票价格,每天早上出一个文件,邮件方式推送给自己。兼职美滋滋。 + +#### 2.3 MCP管理 + +
+ +
+ +- 市面上有非常的多的 MCP 服务,我们可以选择的这些服务来组装出我们的智能体。 +- 系统支持配置 stdio、sse,两种方式。无论是自己开发的 MCP 还是市面的都可以使用。(课程中有教大家,基于 Spring AI 怎么开发 MCP 服务) + +## 二、系统设计 + +### 1. 功能流程 + +
+ +
+ +- 如图,从上往下,以任务或会话方式,调用 agent 为目标,串联各个 client。形成内部处理 a2a 流程。 +- 之后,对于 client 则由系统都动态的方式创建 bean 对象。运营在 ai agent 后台配置相关数据即可。 + +### 2. 库表设计 + +
+ +
+ +如图,为整个系统对应的数据库表信息; + +- ai_agent_task_schedule,智能体任务调度配置表 +- ai_agent,AI智能体配置表 +- ai_agent_client,智能体-客户端关联表 +- ai_client,AI客户端配置表 +- 模型配置组;ai_client_model、ai_client_model_config、ai_client_model_tool_config +- 工具配置组;ai_client_tool_config、ai_client_tool_mcp +- 顾问配置组;ai_client_advisor、ai_client_advisor_config +- 提示词配置;ai_client_system_prompt、ai_client_system_prompt_config +- 知识库配置;ai_rag_order + +### 3. 系统工程 + +
+ +
+ +- 如图,为整个系统的工程结构,分为 api、app、domain、infrastructure、trigger、types,六边形架构。(现在各个互联网都在落地 DDD,因为 DDD 比最早出来的几年,已经有了非常明确的规范)相关资料;[https://bugstack.cn/md/road-map/ddd-guide-01.html](https://bugstack.cn/md/road-map/ddd-guide-01.html) +- Domain 核心领域层,处理 Agent 的预热、对话、知识库、任务的操作。后续 Agent 相关都维护到这个领域包下。 +- Trigger 触发器层,负责对外提供接口,让外部来调用。当有一些纯 crud 操作的流程时,这个架构下,会在 trigger 层直接调用基础设施层提供数据,而不需要在经过 domain 领域层,重复封装对象。 + +**注意** ai-agent-station 全套代码,可以直接获取后学习(持续更新最新方案)。之后课程会单独起一个 ai-agent-station-study 工程,带着大家从0到1学习。 + diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-10\350\212\202\357\274\232Agent\346\211\247\350\241\214\351\223\276\350\267\257\345\210\206\346\236\220.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-10\350\212\202\357\274\232Agent\346\211\247\350\241\214\351\223\276\350\267\257\345\210\206\346\236\220.md" new file mode 100644 index 000000000..db231e6be --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-10\350\212\202\357\274\232Agent\346\211\247\350\241\214\351\223\276\350\267\257\345\210\206\346\236\220.md" @@ -0,0 +1,38 @@ +--- +title: 【更】第3-10节:Agent执行链路分析 +pay: https://t.zsxq.com/bxh8h +--- + +# 《Ai Agent》第3-10节:Agent执行链路分析 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/ty1Yy](https://t.zsxq.com/ty1Yy) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +通过现有实现的动态化构建 Ai API、Model、Client、Tool(MCP)、Advisor(记忆、RAG)、Prompt,完成 Ai Agent 服务处理。 + +最早 OpenAi 出来时,我们只是对 Ai 单向询问(含上下文记忆)和提供问题结果。后来开始有了 RAG 知识库,可以让我们每次的提问结合知识库获取更全面的内容。再到后来开始有了 MCP 服务协议,让 AI 具备了调用外部服务的能力。 + +那么,到这再往后开始有了 Ai Agent 的概念,也就是让 Ai 具备环境感知能力、自主决策并执行行动,直至完成最终的结果。 + +这也就是我们目前在使用一些 Ai Agent 的时候,进行一些问题提问的时候,他会根据环境(询问)状态制定行动计划,调用各种工具和API执行具体任务,并在多轮交互中维持上下文状态,输出最终的结果。这也是我们要做的事情。 + +鉴于,整个 Ai Agent 的复杂性,我们不能一上来就直接去编码,这样很多伙伴会比较晕。所以我们先来完成 Agent 单元测试,在结合我们动态实例化的各项服务,处理 Agent 循环制定行动计划和执行多轮会话。 + +## 二、流程设计 + +如图,不同方案实现的 Agent 流程; + +
+ +
+ +Ai Agent 的处理过程也是分为几类的,用于适应不同的场景使用; + +1. 固定N个步骤,这类的一般是配置工作流的,提高任务执行的准确性。如,一些检索资料、发送帖子、处理通知等。 +2. 顺序循环调用,配置 Agent 要执行的多个 Client 端,以此顺序执行。适合一些简单的任务关系,并已经分配好的动作,类似于1的方式。 +3. 智能动态决策,这类是目前市面提供给大家使用的 Agent 比较常见的实现方式,它会动态的规划执行动作,完成行动步骤,观察执行结果,判断完成状态和步骤。并最终给出结果。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-11\350\212\202\357\274\232Agent\346\211\247\350\241\214\351\223\276\350\267\257\350\256\276\350\256\241.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-11\350\212\202\357\274\232Agent\346\211\247\350\241\214\351\223\276\350\267\257\350\256\276\350\256\241.md" new file mode 100644 index 000000000..ef358d38c --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-11\350\212\202\357\274\232Agent\346\211\247\350\241\214\351\223\276\350\267\257\350\256\276\350\256\241.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第3-11节:Agent执行链路设计 +pay: https://t.zsxq.com/eSLoH +--- + +# 《Ai Agent》第3-11节:Agent执行链路设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/hNFqE](https://t.zsxq.com/hNFqE) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +将上一节对 Ai Agent 执行链路的分析,以及对应的 AutoAgentTest 测试代码,使用规则树设计可执行链路节点。 + +本节是其中的一个 Ai Agent Auto 自动执行策略,后续还要把其他的 Ai Agent 执行策略也加入进来实现。 + +## 二、流程设计 + +如图,Auto Ai Agent 动态多轮会话执行流程图; + +
+ +
+ +- 首先,给入口保留一个多策略选择,以适应我们不同场景的多类型 Agent 选择使用,后续会在 agent 配置表增加策略选择属性来区分调用。本节我们先处理一个 AutoAgent 的实现。 +- 之后,进入到关键地方,在上一节 AutoAgentTest 章节,设计了一套自动化 Agent 执行方法,通过 for 循环处理。这里我们通过规则树,分多个多个节点步骤执行,节点间可循环调用,增强整体的灵活性。 +- 最后,以用户提问到所有的步骤执行完成后,进入到结束环节,产生结果。如果你上一节已经高透彻,那么到这里其实会更加容易理解对于节点的拆分。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-12\350\212\202\357\274\232Agent\346\234\215\345\212\241\346\216\245\345\217\243\345\222\214UI\345\257\271\346\216\245.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-12\350\212\202\357\274\232Agent\346\234\215\345\212\241\346\216\245\345\217\243\345\222\214UI\345\257\271\346\216\245.md" new file mode 100644 index 000000000..ceef27a8d --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-12\350\212\202\357\274\232Agent\346\234\215\345\212\241\346\216\245\345\217\243\345\222\214UI\345\257\271\346\216\245.md" @@ -0,0 +1,31 @@ +--- +title: 【更】第3-12节:Agent服务接口和UI对接 +pay: https://t.zsxq.com/T0H6n +--- + +# 《Ai Agent》第3-12节:Agent服务接口和UI对接 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/eaqbx](https://t.zsxq.com/eaqbx) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +以实现 Ai Auto Agent Server-Sent Events (SSE) 流式响应接口为目的,设计 SSE 异步响应结果对象,对 Step 1~4 步骤的过程数据进行异步流式响应返回。开发好接口后,与Ai实现的前端UI界面进行对接。 + +像是 Ai(Cursor、trae.ai) 对于前端这样没有太多复杂的流程代码,可以很好的实现出来。这对于后端工程师想做一些前端UI产品化的东西,就变得容易的很了! + +## 二、对接效果 + +如图,流式响应(SSE)接口对接UI效果; + +
+ +
+ +- 首先,小傅哥对 **Auto Agent - 自动智能对话体** 进行了数据库表(初始数据)和服务启动时自动装配 Ai Agent 所需的各项配置(客户端、模型、API、MCP等)。以便于可以在接口请求服务时,调用 Auto Agent 智能体。 +- 之后,用于就可以对智能体进行提问,所有的提问信息,会进入到服务端的 Step 1~4 步骤,并进行循环分析、执行、检测,以及最终输出结果。 + +> 接下来,小傅哥带着大家看看 Auto Agent 服务接口和对接是如何处理的。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-13\350\212\202\357\274\214Agent-ELK\346\227\245\345\277\227\345\210\206\346\236\220\345\234\272\346\231\257.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-13\350\212\202\357\274\214Agent-ELK\346\227\245\345\277\227\345\210\206\346\236\220\345\234\272\346\231\257.md" new file mode 100644 index 000000000..bdea85b3c --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-13\350\212\202\357\274\214Agent-ELK\346\227\245\345\277\227\345\210\206\346\236\220\345\234\272\346\231\257.md" @@ -0,0 +1,31 @@ +--- +title: 【更】第3-13节,Agent-ELK日志分析场景 +pay: https://t.zsxq.com/agZ9E +--- + +# 《Ai Agent》第3-13节,Agent-ELK日志分析场景 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/kMjAw](https://t.zsxq.com/kMjAw) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +增加 Agent-ELK 日志分析的实际应用场景,通过 Agent 根据用户诉求,自主分析、规划、执行和输出结果,来帮助我们对日志检索的提效。 + +ELK(或自研) 是各个互联网公司中都有的一套分布式日志设备,以便于研发在遇到线上系统报警和运营反馈事故问题时,快速检索日志。但往往这种检索的日志的方式都是非常耗时的,所以增加 Agent 方式来辅助提效是非常有必要的。 + +注意;面试往往就是需要这样的实际应用场景,而不是坦克大战、贪吃蛇、图书管理系统等一些不着边际的项目(适合练手但不适合写简历)。 + +## 二、功能流程 + +如图,Agent-ELK 的设计使用流程图; + +
+ +
+ +- 首先,虚线框内为模拟的系统的应用日志,部署一套 ELK 之后通过脚本把日志数据写入到 ELK。你也可以通过这套教程实际部署一套 ELK [https://bugstack.cn/md/road-map/elk.html](https://bugstack.cn/md/road-map/elk.html) 另外像星球项目,拼团、大营销等也都有 ELK 分布式日志的对接使用。 +- 之后,要为这套场景增加一套新的 Ai Agent 描述话术,在执行 ELK 日志分析的时候,我们先手动选择出要使用的 Ai Agent 服务。这样它就可以以 ELK 对应的 Prompt 话术分析方式使用了。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-14\350\212\202\357\274\214Agent-Prometheus\347\233\221\346\216\247\345\210\206\346\236\220\345\234\272\346\231\257.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-14\350\212\202\357\274\214Agent-Prometheus\347\233\221\346\216\247\345\210\206\346\236\220\345\234\272\346\231\257.md" new file mode 100644 index 000000000..790b7709c --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-14\350\212\202\357\274\214Agent-Prometheus\347\233\221\346\216\247\345\210\206\346\236\220\345\234\272\346\231\257.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第3-14节,Agent-Prometheus监控分析场景 +pay: https://t.zsxq.com/8BfkE +--- + +# 《Ai Agent》第3-14节,Agent-Prometheus监控分析场景 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/ymfSm](https://t.zsxq.com/ymfSm) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +上一节我们做了 Ai Agent ELK,这一节扩展增加 Prometheus(普罗米修斯监控) 监控系统,让 Ai Agent 具备智能监控问题分析场景。这种场景东西是在公司里非常重要的,且有实际使用用途的东西。 + +本节基于的是 Ai MCP Prometheus + Agent Prompt(分阶段提示词),来完成自动化分析、规划、执行、检测、输出的智能监控系统。 + +## 二、功能流程 + +如图,Agent-Prometheus 的设计使用流程图; + +
+ +
+ +- 首先,虚线框为模拟的系统监控日志脚本(含运行程序),部署的一套普罗米修斯监控系统。你可以通过这套教程来部署一套普罗米修斯监控 [https://bugstack.cn/md/road-map/grafana.html](https://bugstack.cn/md/road-map/grafana.html) 星球的拼团、大营销、openai应用都有这样的监控系统使用。 +- 之后,要为这套场景增加一套新的 Ai Agent 执行话术,另外还要配置一套对应的 RAG 知识库,来增强分析能力。 diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-15\350\212\202\357\274\232FlowAgent\346\211\247\350\241\214\351\223\276\350\267\257\345\210\206\346\236\220.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-15\350\212\202\357\274\232FlowAgent\346\211\247\350\241\214\351\223\276\350\267\257\345\210\206\346\236\220.md" new file mode 100644 index 000000000..8c10a272a --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-15\350\212\202\357\274\232FlowAgent\346\211\247\350\241\214\351\223\276\350\267\257\345\210\206\346\236\220.md" @@ -0,0 +1,31 @@ +--- +title: 【更】第3-15节:AgentFlow执行链路分析 +pay: https://t.zsxq.com/Ht0o1 +--- + +# 《Ai Agent》第3-15节:AgentFlow执行链路分析 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/u9tjH](https://t.zsxq.com/u9tjH) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +为了打开 Agent 的实现思路,本章我们再增加一种新的 Auto Agent 设计,这种设计方式以通过用户的提问和当前 Agent 配置的 MCP 工具集合,进行执行步骤的规划设计。之后在通过执行步骤按照拆分的步骤顺序号,依次进行执行。有点类似于 [manus](https://manus.im/) 的过程。 + +## 二、流程设计 + +如图,多种 Ai Agent 执行设计流程图; + +
+ +
+ +Ai Agent 的处理过程也是分为几类的,用于适应不同的场景使用; + +1. 固定N个步骤,这类的一般是配置工作流的,提高任务执行的准确性。如,一些检索资料、发送帖子、处理通知等。 +2. 顺序循环调用,配置 Agent 要执行的多个 Client 端,以此顺序执行。适合一些简单的任务关系,并已经分配好的动作,类似于1的方式。 +3. 智能动态决策,这类是目前市面提供给大家使用的 Agent 比较常见的实现方式,它会动态的规划执行动作,完成行动步骤,观察执行结果,判断完成状态和步骤。并最终给出结果。 +4. 【新增】规划分析决策,根据用户输入的信息诉求,以及配置的 MCP 的能力,进行步骤规划。之后把步骤拆分出 1、2、3 具体要做什么,在依次执行这些步骤。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-16\350\212\202\357\274\232FlowAgent\346\211\247\350\241\214\351\223\276\350\267\257\350\256\276\350\256\241.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-16\350\212\202\357\274\232FlowAgent\346\211\247\350\241\214\351\223\276\350\267\257\350\256\276\350\256\241.md" new file mode 100644 index 000000000..e3beecfb2 --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-16\350\212\202\357\274\232FlowAgent\346\211\247\350\241\214\351\223\276\350\267\257\350\256\276\350\256\241.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第3-16节:FlowAgent执行链路设计 +pay: https://t.zsxq.com/Htptt +--- + +# 《Ai Agent》第3-16节:FlowAgent执行链路设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/J68sk](https://t.zsxq.com/J68sk) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在 3-11 节的时候,我们做过一个这样的事情。针对于测试阶段的 Agent Test 代码,使用设计模式拆分出各个执行步骤,便于理解和维护。这一节我们同样需要把上一节分析的 FlowAgent 测试代码,按照模块化的流程进行拆分。 + +## 二、流程设计 + +如图,Flow Ai Agent 动态步骤分析执行流程图; + +
+ +
+ +- 首先,新增加一个 Agent 执行策略,流程步骤拆分执行。这个过程其实比上一 AutoAgent 要简单一些。 +- 之后,分贝设计出 Step1 工具分析、Step2 动作规划、Step3 拆分步骤、Step4 执行节点(循环执行),这四个步骤就是 FlowAgentTest.test_agent 里的步骤。 +- 最后,响应结果。后续章节会使用 sse 将结果响应到前端,这里我们暂时增加了判null操作,先不需要发送 sse 数据。 diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-17\350\212\202\357\274\232\345\242\236\345\212\240\350\260\203\345\272\246\345\231\250\347\255\226\347\225\245\346\211\247\350\241\214Agent\351\223\276\350\267\257.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-17\350\212\202\357\274\232\345\242\236\345\212\240\350\260\203\345\272\246\345\231\250\347\255\226\347\225\245\346\211\247\350\241\214Agent\351\223\276\350\267\257.md" new file mode 100644 index 000000000..0b3a12d46 --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-17\350\212\202\357\274\232\345\242\236\345\212\240\350\260\203\345\272\246\345\231\250\347\255\226\347\225\245\346\211\247\350\241\214Agent\351\223\276\350\267\257.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第3-17节:增加调度器策略执行Agent链路 +pay: https://t.zsxq.com/ayQWR +--- + +# 《Ai Agent》第3-17节:增加调度器策略执行Agent链路 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/44qnU](https://t.zsxq.com/44qnU) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +从ui页面开始,增加 ai agent 分类选择使用。因为这里有不同类型的 ai agent,所以要对调用的过程增加一个策略调度器,按照不同类型的 ai agent 选择不同的执行策略。 + +## 二、流程设计 + +如图,Ai Agent 策略调度器执行过程; + +
+ +
+ +- 首先,我们实现的 ai agent 有多种类型,所以在选择场景选择的时候,要根据不同的场景获取到走那种类型的 ai agent 执行策略。 +- 之后,这里我们就把 AutoAgent、FlowAgent 都放到调度器里执行,另外要在数据库表 ai_agent 中增加一个 strategy 执行策略配置,这样用户提问时候传入的 agent id 就可以获取到对应的策略了。 +- 最后,本节还有一点关于页面 UI 的完善,每次对话,会把对话消息存储到历史对话中。这部分前端的东西使用 ai 开发工具处理的。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-18\350\212\202\357\274\232\345\212\250\346\200\201\346\211\247\350\241\214\346\231\272\350\203\275\344\275\223\344\273\273\345\212\241.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-18\350\212\202\357\274\232\345\212\250\346\200\201\346\211\247\350\241\214\346\231\272\350\203\275\344\275\223\344\273\273\345\212\241.md" new file mode 100644 index 000000000..c4ac6c6bc --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-18\350\212\202\357\274\232\345\212\250\346\200\201\346\211\247\350\241\214\346\231\272\350\203\275\344\275\223\344\273\273\345\212\241.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第3-18节:动态执行智能体任务 +pay: https://t.zsxq.com/8yPe5 +--- + +# 《Ai Agent》第3-18节:动态执行智能体任务 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/j116r](https://t.zsxq.com/j116r) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +本节首先新增一个基于数据库固定配置步骤的简单循环执行智能体策略。随后,结合数据库中配置的智能体定时执行参数,以及工程中引入的扳手工程动态任务组件,实现对智能体动态任务的调度与执行。 + +那么,这里有一个前置学习,《通用技术组件 - 🔧扳手工程》第5节:任务调度组件 [https://t.zsxq.com/bLkoF](https://t.zsxq.com/bLkoF) - 需要先完成下,之后就可以在智能体项目中使用了。 + +## 二、功能流程 + +如图,Ai Agent 动态任务执行过程; + +
+ +
+ +- 首先,我们在项目中引入了扳手工程的任务调度组件。在调度组件内,配置检索出数据库表内可执行的任务以及对应的参数,之后由定时任务管理。 +- 之后,本节我们又增加了一个新的简单的 Agent 执行策略,依次循环数据库 Agent 配置的客户端。这个场景很适合工作流编排,把固定要执行的客户端,依次写入到数据库配置,就可以按照固定步骤执行了。这也是咱们在早期分析 Agent 执行方式的一种。 diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-19\350\212\202\357\274\232\346\213\226\346\213\211\346\213\275\347\274\226\346\216\222\346\225\260\346\215\256\345\255\230\345\202\250.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-19\350\212\202\357\274\232\346\213\226\346\213\211\346\213\275\347\274\226\346\216\222\346\225\260\346\215\256\345\255\230\345\202\250.md" new file mode 100644 index 000000000..6e06b11c7 --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-19\350\212\202\357\274\232\346\213\226\346\213\211\346\213\275\347\274\226\346\216\222\346\225\260\346\215\256\345\255\230\345\202\250.md" @@ -0,0 +1,31 @@ +--- +title: 【更】第3-19节:拖拉拽编排数据存储 +pay: https://t.zsxq.com/kPbFh +--- + +# 《Ai Agent》第3-19节:拖拉拽编排数据存储 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/oxIZg](https://t.zsxq.com/oxIZg) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +通过 [flowgram.ai](https://flowgram.ai/) 框架,实现项目中 Ai Agent 拖拉拽编排能力,增强使用的易用性。 + +这部分拖拉拽主要完成的就是一个 ai agent 所需的,client、prompt、advisor、model(api)的串联使用。通过拖拉拽方式替代 ai_client_config 中需要手动维护的数据关系链。 + +本节我们先来完成拖拉拽的页面搭建和数据存储处理。提示,对于后端开发人员,不非得学习前端代码,只要能用起来就可以。面试中往往主要考察项目完整性,但不会对后端人员必须会写前端。所以,如果你不会前端代码,也不用太担心。 + +## 二、实现效果 + +如图,是通过拖拉拽实现的 Ai Agent 编排效果; + +
+ +
+ +- 创建过程中,Agent 是用户本次新创建的智能体,这个智能体所需用到的Client、以及 Client 所需的 Advisor、Prompt、Model、MCP 则可以通过拖拉拽的方式进行串联编排。 +- 对于这些节点所拉取的数据,则是从服务端接口进行获取的。如,Client 客户端获取可用数据,Model 获取模型,之后链接的 MCP 工具可以自由组合。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-1\350\212\202\357\274\232Ai Agent \344\270\232\345\212\241\346\265\201\347\250\213\343\200\201\347\263\273\347\273\237\346\236\266\346\236\204\343\200\201\345\272\223\350\241\250\350\256\276\350\256\241\350\257\264\346\230\216.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-1\350\212\202\357\274\232Ai Agent \344\270\232\345\212\241\346\265\201\347\250\213\343\200\201\347\263\273\347\273\237\346\236\266\346\236\204\343\200\201\345\272\223\350\241\250\350\256\276\350\256\241\350\257\264\346\230\216.md" new file mode 100644 index 000000000..1b041207e --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-1\350\212\202\357\274\232Ai Agent \344\270\232\345\212\241\346\265\201\347\250\213\343\200\201\347\263\273\347\273\237\346\236\266\346\236\204\343\200\201\345\272\223\350\241\250\350\256\276\350\256\241\350\257\264\346\230\216.md" @@ -0,0 +1,32 @@ +--- +title: 【更】第3-1节,Ai Agent 业务流程、系统架构、库表设计说明 +pay: https://t.zsxq.com/qUYx0 +--- + +# 《Ai Agent》第3-1节,Ai Agent 业务流程、系统架构、库表设计说明 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/DcL2p](https://t.zsxq.com/DcL2p) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +了解 Ai Agent 构建元素,以 Spring AI 硬编码创建 Agent 过程,分析各个模块用途,并以此设计拆分元素和对应的库表设计。 + +经过本节我们可以了解到,怎么把这些硬编码的过程,以配置数据库表的方式,动态化构建。有了动态化的构建,也就可以按需配置出各种 Agent 服务来满足我们的业务诉求。尤其是现在 MCP 如火如荼的发展,有一套自动化的 Agent 是非常重要的。 + +> 第3-0节,介绍和演示中,涉及了本节的部分内容。本节主要站在开发视角,来讲解如何架构和开发系统。 + +## 二、Agent 介绍 + +AI 智能体是使用 AI 来实现目标并代表用户完成任务的软件系统。其表现出了推理、规划和记忆能力,并且具有一定的自主性,能够自主学习、适应和做出决定。 + +这些功能在很大程度上得益于生成式 AI 和 AI 基础模型的多模态功能。AI 智能体可以同时处理文本、语音、视频、音频、代码等多模态信息;可以进行对话、推理、学习和决策。它们可以随着时间的推移不断学习,并简化事务和业务流程。智能体可以与其他智能体协作,来协调和执行更复杂的工作流。 + +
+ +
+ +>Spring AI 框架,支持大语言模型构建 AI Agent 实现。AI Agent是整合多种技术手段的智能实体 ,其实现依赖于 Tools、MCP、Memory、RAG(Retrieval 增强检索生成) 等技术组件,但不是非得依赖全部组件才叫 AI Agent。 diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-20\350\212\202\357\274\232Agent\347\256\241\347\220\206\345\220\216\345\217\260\345\256\236\347\216\260.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-20\350\212\202\357\274\232Agent\347\256\241\347\220\206\345\220\216\345\217\260\345\256\236\347\216\260.md" new file mode 100644 index 000000000..b88505970 --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-20\350\212\202\357\274\232Agent\347\256\241\347\220\206\345\220\216\345\217\260\345\256\236\347\216\260.md" @@ -0,0 +1,78 @@ +--- +title: 【更】第3-20节:Agent管理后台实现 +pay: https://t.zsxq.com/5Sdfr +--- + +# 《Ai Agent》第3-20节:Agent管理后台实现 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/z0jRV](https://t.zsxq.com/z0jRV) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +设计实现一套 Ai Agent 管理后台页面,允许用户通过管理后台实现 Ai Agent 的资源配置和拖拉拽方式维护 Ai Agent 智能体。 +第 +本章节没有复杂的逻辑实现,都是 CRUD 操作,把原本在数据库中手动处理的过程,以更符合运营使用方式提供用户使用。所以,本节你只需要了解、看懂,可以跟着继续迭代你想要的内容即可。 + +## 二、实现效果 + +这是一套完整的 Ai Agent 智能体管理后台,包括了所有资源的配置(model、client、mcp、advisor、prompt),以及拖拉拽编排的方式完成 Ai Agent 智能体的构建。 + +以下的截图内容和使用,会在本节课程的视频里演示。也包括如何运行使用。 + +### 1. 登录界面 + +
+ +
+ +- 这一部分在数据库表增加了 admin_user 表,有配置登录账号和密码,可以简单做校验。 + +### 2. 管理界面 + +
+ +
+ +- 管理后台目前提供了,代理管理(拖拉拽编排方式配置智能体),资源管理(model、client、mcp、advisor、prompt) +- 数据分析、系统设置,是样例,你可以继续扩展你所需要的内容。 + +### 3. 代理管理 + +#### 3.1 代理列表 + +
+ +
+ +- 这里的代理列表,就是通过拖拉拽配置的智能体。可以点击【查看】看到明细,也可以【新建】,还可以删除。 +- 点击【加载】则是调用服务端,把数据加载到 Spring 容器,之后就可以使用了。 + +#### 3.2 代理配置 + +
+ +
+ +- 当你点击一个代理配置,则会展示出拖拉拽的数据到页面上。这部分会从数据库读取,之后展示出来,全部可视化。 +- 如果你点击了Save则会做出一份新的,之后对于旧的,你可以自己手动删除。 + +### 4. 资源管理 + +
+ +
+ +- 资源管理下,是配置一个智能体所需的各项资源信息,你可以在这里进行维护。如,MCP 工具管理。 + +### 5. 页面使用 + +
+ +
+ +- 配置后的智能体,可以在智能体选择里进行获取使用。之后进行提问。 +- 效果还不错,这里小傅哥验证了配置的智能体进行提问。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-21\350\212\202\357\274\232\345\234\250\344\272\221\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\344\270\212\347\272\277.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-21\350\212\202\357\274\232\345\234\250\344\272\221\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\344\270\212\347\272\277.md" new file mode 100644 index 000000000..13f92fbfb --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-21\350\212\202\357\274\232\345\234\250\344\272\221\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\344\270\212\347\272\277.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第3-21节:在云服务器部署上线 +pay: https://t.zsxq.com/HO8sx +--- + +# 《Ai Agent》第3-21节:在云服务器部署上线 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/wfgDS](https://t.zsxq.com/wfgDS) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在云服务器(2c4g)部署 Ai Agent 前端页面(html)、管理页面(react)、后端服务(java)、基础环境(MySql、PG向量库)。 + +## 二、部署过程 + +如图,为本次的部署过程 + +
+ +
+ +- 推荐2c4g云服务器购买,[http://618.gaga.plus/](http://618.gaga.plus/) 选个便宜的购买就可以。 +- 本次会进行本地构建镜像,之后 push 到阿里云私有个人镜像库(免费的可以申请)。这个可以代替 Docker Hub 作为代理使用。教程;[https://t.zsxq.com/XdoWr](https://t.zsxq.com/XdoWr) +- 云服务器部署教程:[https://t.zsxq.com/19osWS4qj](https://t.zsxq.com/19osWS4qj) - 需要云服务器安装 Docker、Portainer,以及配置镜像地址 [https://t.zsxq.com/2DGGY](https://t.zsxq.com/2DGGY) +- 记得在云服务器安全组开放端口 9000(Portainer)、8099(服务端)、3002(管理端)、8899(mysql管理端) 等你需要对外的端口。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-2\350\212\202\357\274\232\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256\345\267\245\347\250\213.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-2\350\212\202\357\274\232\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256\345\267\245\347\250\213.md" new file mode 100644 index 000000000..3c637aeb3 --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-2\350\212\202\357\274\232\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256\345\267\245\347\250\213.md" @@ -0,0 +1,60 @@ +--- +title: 【更】第3-2节:初始化项目工程 +pay: https://t.zsxq.com/3B4vv +--- + +# 《Ai Agent》第3-2节:初始化项目工程 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/K9NWT](https://t.zsxq.com/K9NWT) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +很多小伙伴可能都接触过一些入门级项目,简单地使用 IntelliJ IDEA 创建和开发。但在互联网公司中,如何规范地创建和管理一个新项目,往往缺乏清晰的认知。毕竟公司里有大量新项目需要启动,不可能让每个团队、每个人都随意创建风格各异的工程,这样会大幅增加后续维护和协作的难度。因此,建立统一的工具链和标准化流程显得尤为重要。 + +所以,跟着小傅哥学习,不仅仅是完成一个项目的开发,更是以互联网大型企业的标准化流程和规范,来设计、开发和实现功能,帮助大家掌握更专业、更高效的开发方法。 + +## 一、本章诉求 + +教会小伙伴使用统一的标准脚手架初始化创建项目工程,并了解工程模块的分层用途。 + +课程会循序渐进的从0到1,逐步带着大家完成项目的开发。开局只有一把 IntelliJ IDEA,完成项目后你可以学习到;业务、架构、设计、方案、配置、部署(Linux、Docker)等各项知识。 + +## 二、如何开始 + +### 1. 前置学习 + +小伙伴在学习的时候,可以依照课程的方式进行创建项目、变更配置、启动测试。这里有一些前置学习,包括:Git、Maven、Docker、脚手架,课程已经准备好了,可以刷下;**磨刀不误砍柴工,基础刷完更轻松!** + +- Git:[https://bugstack.cn/md/road-map/git.html](https://bugstack.cn/md/road-map/git.html) +- Maven:[https://bugstack.cn/md/road-map/maven.html](https://bugstack.cn/md/road-map/maven.html) +- Docker [https://bugstack.cn/md/road-map/docker-what.html](https://bugstack.cn/md/road-map/docker-what.html) +- 脚手架:[https://bugstack.cn/md/road-map/ddd-archetype-maven.html](https://bugstack.cn/md/road-map/ddd-archetype-maven.html) + +> 另外课程会使用 Java JDK 17、Maven 3.8.x,软件已经提供好,可以直接下载;[https://t.zsxq.com/19Rnk98M0](https://t.zsxq.com/19Rnk98M0) - `附件内含有配置好阿里云镜像的 Maven` + +### 2. 开始学习 + +1. 你需要通过 git clone 命令,或者 IntelliJ IDEA 自动的检出工程方式,把项目工程检出到本地。关于如何使用Git检出项目,在前置学习里提供了教程。 +2. 检出代码后,你可以通过 IntelliJ IDEA 打开项目,并按照每一节最开始说明的本节对应的代码分支,把工程代码切换到对应的这一节。 +3. 接下来你可以通过课程的视频和小册以及提供的代码进行学习,并跟随课程每节要完成的内容,一步步操作。过程中可以参考课程的代码进行学习。如果自己的代码运行出问题的时候,可以运行课程的代码验证是环境问题还是个人代码问题。**另外注意运行课程代码,要修改对应的环境为你的本地环境,mysql、redis等** +4. 对于课程中每节涉及的库表,会放到工程 docs/dev-ops mysql 下。你可以每节学习创建一个新的库名称,之后导入。但要记得在工程 app/application-dev.yml 文件中修改对应的库名称。 + +### 3. 环境安装 + +课程提供了使用 Docker 部署 MySQL、Redis 环境的脚本。因为使用 Docker 可以随时方便卸载,不会污染本地电脑的本机环境。而且后续部署 Linux 云服务器也会非常顺手。 + +关于环境的安装; + +
+ +
+ +1. Windows + wsl2,本地使用 powershell 切换到工程文件夹,执行 `docker-comopse -f docker-compose-environment-aliyun.yml up -d` +2. Mac 电脑的适配性会更好,直接点击这里的绿色箭头即可安装。 +3. 如果本机配置有问题,也可以选择使用云服务器。课程中有云服务器的操作教程,部署起来更方便。云服务器教程:[https://bugstack.cn/md/road-map/linux.html](https://bugstack.cn/md/road-map/linux.html) + +> 环境安装后就可以使用 MySql、Redis 链接工具使用了,也可以手动更新库表。 diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-3\350\212\202\357\274\232AiAgent\346\265\213\350\257\225\346\241\210\344\276\213.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-3\350\212\202\357\274\232AiAgent\346\265\213\350\257\225\346\241\210\344\276\213.md" new file mode 100644 index 000000000..ee56458cf --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-3\350\212\202\357\274\232AiAgent\346\265\213\350\257\225\346\241\210\344\276\213.md" @@ -0,0 +1,31 @@ +--- +title: 【更】第3-3节:Ai Agent 测试案例 +pay: https://t.zsxq.com/JFnzV +--- + +# 《Ai Agent》第3-3节:Ai Agent 测试案例 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/jI0BD](https://t.zsxq.com/jI0BD) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在项目中引入 Spring Ai 1.0.0 框架,通过编写测试案例的方式,了解 Ai Agent 的工作模式。 + +**那为什么要这么做呢?** + +通常对于软件设计的解决方案,我们都有一个这样共识,那就是目标结果驱动,最先搭建可运行的最小执行单元。因为软件设计原则,[康威定律](https://zh.wikipedia.org/wiki/%E5%BA%B7%E5%A8%81%E5%AE%9A%E5%BE%8B),也提到,`大的系统组织总是比小系统更倾向于分解`。当场景问题被拆解的越小以后,也就越容易被理解和处理。所以,我们要优先通过案例的方式,验证 Ai Agent 的工作模型和可执行方案。再通过这些案例,设计详细的流程和库表细节。 + +## 二、功能流程 + +如图,为整个 Ai Agent 的工作模型; + +
+ +
+ +- 概念:**Ai Agent 是整合多种技术手段的智能实体** ,其实现依赖于 Tools、MCP、Memory、RAG(Retrieval-Augmented Generation,检索增强生成) 等技术组件构建的智能体。并且每一个 Agent Client 又可以被连接通信,增强其 Agent 智能体能力。 +- 方案:这里我们基于 Spring AI 框架,通过编码的方式把模型、关键词、顾问角色、工具,放入到 LLM 客户端,构建 LLM 对话智能体。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-4\350\212\202\357\274\232\346\240\271\346\215\256AiAgent\346\241\210\344\276\213\357\274\214\350\256\276\350\256\241\345\272\223\350\241\250.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-4\350\212\202\357\274\232\346\240\271\346\215\256AiAgent\346\241\210\344\276\213\357\274\214\350\256\276\350\256\241\345\272\223\350\241\250.md" new file mode 100644 index 000000000..be57bd6c3 --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-4\350\212\202\357\274\232\346\240\271\346\215\256AiAgent\346\241\210\344\276\213\357\274\214\350\256\276\350\256\241\345\272\223\350\241\250.md" @@ -0,0 +1,39 @@ +--- +title: 【更】第3-4节:根据AiAgent案例,设计库表 +pay: https://t.zsxq.com/0tZhc +--- + +# 《Ai Agent》第3-4节:根据AiAgent案例,设计库表 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/Tx438](https://t.zsxq.com/Tx438) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +根据 Ai Agent 的代码案例,设计用于解耦,硬编码流程的库表。在后续的代码开发中,根据库表配置的 Ai Agent 流程所需的,模型、提示词、顾问、工具等,动态实例化出 Ai Agent 服务。 + +## 二、拆分设计 + +如图,为对应的Ai Agent 案例代码,映射出要拆分的库表设计; + +
+ +
+ +首先,整个代码构建的整个 Ai Agent 最小化单元服务,我们可以根据这样的服务信息设计出库表结构。 + +- 第一步,从上到下,OpenAiApi 是最基础单元结构,可以被多个 OpenAiChatModel 使用,它可以被拆分出第一张表。 +- 第二步,构建 OpenAiChatModel,这个阶段,需要 openAiApi、model对话模型、tool mcp 工具。其中`model对话模型`时一种固定固定资源,可以直接放到 ai_client_model 模型中,而 openAiApi、mcp 工具,都属于复杂配置,则需要额外的外部关联来衔接。也就是后面的 ai_client_config 配置,用于配置衔接关系。 +- 第三步,ChatClient 对话客户端,这部分的实例化过程都是和外部其他的资源关联,本身表设计只要有一个客户端的唯一id和客户端的描述介绍即可。 +- 第四步,给 mcp 增加一个表,mcp 服务是非常重要的,有 mcp 才有 agent 服务。mcp 的启动有 stido、sse 两种方式,每种方式都有对应的配置文件 json 数据。 +- 第五步,defaultSystem 系统提示词,需要单独拆分出来。提示词等于智能体的大脑,也有人说,其实 Ai Agent 就是 prompt 的堆叠,所以写提示词是很重要的。 +- 第六步,advisor 顾问角色,在 Spring Ai 框架中,以顾问的方式,访问记忆上下文,知识库资源,所以这部分也要单独设计库表。 +- 第七步,设计一个 ai_client_config,用于配置;api、model、client、prompt、mcp、advisor的衔接关系。 +- 第八步,设计 ai_agent、ai_agent_flow_config,也就是一个 ai agent,是可以连续调用多个 ai client 客户端的。 +- 第九步,设计 ai_agent_stask_schedule 任务,这是一种触达手段,可以把配置好的任务,让 task 定时执行,如自动发帖、系统异常巡检、舆情风险检测、系统配置变更、运营活动报表等。 +- 第十步,ai_client_rag_order,是知识库表,用于上传知识库做一个记录,这样顾问角色就可以访问知识库内容了。 + +注意;chat_client 客户端的初始化过程中,也可以增加 mcp 服务,这部分在 chat_model 模型构建中,也可以增加 mcp,选择在 chat_model 增加即可。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-5\350\212\202\357\274\232\345\244\232\346\225\260\346\215\256\346\272\220\345\222\214Mapper\351\205\215\347\275\256.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-5\350\212\202\357\274\232\345\244\232\346\225\260\346\215\256\346\272\220\345\222\214Mapper\351\205\215\347\275\256.md" new file mode 100644 index 000000000..b3427644d --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-5\350\212\202\357\274\232\345\244\232\346\225\260\346\215\256\346\272\220\345\222\214Mapper\351\205\215\347\275\256.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第3-5节:多数据源和Mapper配置 +pay: https://t.zsxq.com/099am +--- + +# 《Ai Agent》第3-5节:多数据源和Mapper配置 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/eYn4R](https://t.zsxq.com/eYn4R) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +为应用程序配置pgvector(向量库)、mysql(业务库)两套数据源,同时基于库表,编写基础设施层 Mapper 操作。 + +对于数据库表的 Mapper 编写,是一种固定的结构化代码,可以通过 MyBatis 工具生成,也可以使用 AI 编码工具处理。不过对于新人学习来说,更建议在这个阶段,通过手动的方式进行配置编写,这样可以更熟悉库表的设计和字段的理解。尤其是报错后,还可以基于报错排查错误增加编程经验。 + +## 二、功能流程 + +如图,两个数据源的配置和使用; + +
+ +
+ +- 首先,为了让应用程序具备多数据源链接,则需要增加一个扩展的 DataSourceConfig 配置类,来自己实现数据源的加载。这部分会替代原本配置到 yml 文件中,由 Spring 加载数据源的过程。 +- 之后,根据不同类型的数据源,注入到 AI 向量库使用场景和 MyBatis 业务使用场景中。这个过程类似于星球中 DB-Router 路由组件的课程。可以参考:[https://bugstack.cn/md/road-map/db-router.html](https://bugstack.cn/md/road-map/db-router.html) + diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-6\350\212\202\357\274\232\346\225\260\346\215\256\345\212\240\350\275\275\346\250\241\345\236\213\350\256\276\350\256\241.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-6\350\212\202\357\274\232\346\225\260\346\215\256\345\212\240\350\275\275\346\250\241\345\236\213\350\256\276\350\256\241.md" new file mode 100644 index 000000000..da40342cb --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-6\350\212\202\357\274\232\346\225\260\346\215\256\345\212\240\350\275\275\346\250\241\345\236\213\350\256\276\350\256\241.md" @@ -0,0 +1,33 @@ +--- +title: 【更】第3-6节:数据加载模型设计 +pay: https://t.zsxq.com/zrK3n +--- + +# 《Ai Agent》第3-6节:数据加载模型设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/USaZS](https://t.zsxq.com/USaZS) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在关于 Ai Agent 的功能实现中,有一个非常重要处理步骤,就是要想办法动态的实例化来自于用户配置的;API、对话模型、MCP、顾问角色以及提示词等。这也就是我们前面为什么要基于 ai agent case 案例,把代码抽象出库表配置。 + +好,那么到这一节,还要思考,怎么让程序来加载和实例化 Ai Agent 所需的各项组件。如,客户端的实例化、对话模型的实例化等。 + +注意;本节会引入星球组件项目《扳手工程》,通用设计模式框架。可以前置学习:[第2节:责任链和规则树通用模型框架](https://t.zsxq.com/o7IBm) + +## 二、功能流程 + +如图,Ai Agent 实现过程,数据加载策略设计; + +
+ +
+ +- 首先,整个 Ai Agent 的实例化过程,就是各项组件的创建和组装的过程。那么,为了让整体的实现代码更易于维护,我们可以把这样的创建过程,通过规则树的方式进行串联实现。而这部分需要的规则树,是不需要重复建设的,因为星球里的[《扳手工程组件项目》](https://t.zsxq.com/o7IBm),已经把这类的共性内容,凝练成了通用的组件,各个业务系统引用使用即可。所以,这部分建议刷下[《扳手工程组件项目》](https://t.zsxq.com/o7IBm),来看[第2节:责任链和规则树通用模型框架](https://t.zsxq.com/veRkQ) +- 之后,本节我们先把目标缩小到关于数据加载部分,因为后续所有的 Ai Agent 组件实例化的过程,都是需要基础数据的提供。所以组装数据就显得尤为重要了。 + + diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-7\350\212\202\357\274\232\345\212\250\346\200\201\345\256\236\344\276\213\345\214\226\345\256\242\346\210\267\347\253\257API.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-7\350\212\202\357\274\232\345\212\250\346\200\201\345\256\236\344\276\213\345\214\226\345\256\242\346\210\267\347\253\257API.md" new file mode 100644 index 000000000..7ca83a2bd --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-7\350\212\202\357\274\232\345\212\250\346\200\201\345\256\236\344\276\213\345\214\226\345\256\242\346\210\267\347\253\257API.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第3-7节:动态实例化客户端API +pay: https://t.zsxq.com/RdjkP +--- + +# 《Ai Agent》第3-7节:动态实例化客户端API + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/4r5r4](https://t.zsxq.com/4r5r4) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +完善数据加载操作,动态实例化`客户端API`(ai_client_api)并注册到 Spring 容器。 + +这是整个 armory 动态装配 Ai Agent 节点的第一步,涉及到了数据的获取,对象的创建和 Spring 容器的 Bean 对象注册。能看懂本节的操作,基本后续一直到整个 Ai Agent 构建也就都可以看懂了。 + +## 二、功能流程 + +如图,客户端API实例化过程设计; + +
+ +
+ +- 首先,整个 AI Agent 的实例化过程,就是各项组件的创建和组装的过程。为了让整体的实现代码更易于维护,我们把这样的创建过程,通过 规则树的方式 进行串联实现。这种设计模式的优势在于:模块化设计、易于扩展、代码复用度高。 +- 之后,从开始节点看,依次执行,数据构建节点、API构建节点。在 API 构建的过程中,会检查上下文中是否存在已经从数据库获取的数据,之后依次循环构建并注册到 Spring 容器。 diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-8\350\212\202\357\274\232\345\212\250\346\200\201\345\256\236\344\276\213\345\214\226\345\257\271\350\257\235\346\250\241\345\236\213.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-8\350\212\202\357\274\232\345\212\250\346\200\201\345\256\236\344\276\213\345\214\226\345\257\271\350\257\235\346\250\241\345\236\213.md" new file mode 100644 index 000000000..161eba5e9 --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-8\350\212\202\357\274\232\345\212\250\346\200\201\345\256\236\344\276\213\345\214\226\345\257\271\350\257\235\346\250\241\345\236\213.md" @@ -0,0 +1,27 @@ +--- +title: 【更】第3-8节:动态实例化对话模型 +pay: https://t.zsxq.com/zv79l +--- + +# 《Ai Agent》第3-8节:动态实例化对话模型 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/4r5r4](https://t.zsxq.com/4r5r4) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +整个 ChatModel 对话模型,所需的元素包括;ai api、tool mcp 两块内容。那么本节我们就分别通过不同的 Node 节点实现这些元素的实例化和 ChatModel 构建。 + +## 二、功能流程 + +如图,ai api、tool mcp、model,实例化过程; + +
+ +
+ +- 首先,如图 RootNode 负责数据加载,将构建节点元素的数据依次加载到内存中(写入到上下文里) +- 之后,除了上一节完成的 API 节点处理后,开始创建 MCP 服务的创建,之后是 ChatModel 对话模块的创建。因为 ChatModel 创建的时候会需要用到的 api、mcp 两个元素。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/agent/\347\254\2543-9\350\212\202\357\274\232\345\212\250\346\200\201\345\256\236\344\276\213\345\214\226\345\257\271\350\257\235\345\256\242\346\210\267\347\253\257.md" "b/docs/md/project/ai-knowledge/agent/\347\254\2543-9\350\212\202\357\274\232\345\212\250\346\200\201\345\256\236\344\276\213\345\214\226\345\257\271\350\257\235\345\256\242\346\210\267\347\253\257.md" new file mode 100644 index 000000000..92f9ac939 --- /dev/null +++ "b/docs/md/project/ai-knowledge/agent/\347\254\2543-9\350\212\202\357\274\232\345\212\250\346\200\201\345\256\236\344\276\213\345\214\226\345\257\271\350\257\235\345\256\242\346\210\267\347\253\257.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第3-9节:实例化对话客户端 +pay: https://t.zsxq.com/VcM68 +--- + +# 《Ai Agent》第3-9节:实例化对话客户端 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/bePzF](https://t.zsxq.com/bePzF) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +经过前面一系列的准备工作,包括;api、mcp、model,本节我们要进行 advisor 顾问角色的实例化,之后进行 ChatClient 对话客户端的实例化。 + +## 二、功能流程 + +如图,整体 ChatClient 客户端实例化过程; + +
+ +
+ +- 首先,以构建 AiClientNode 的对话客户端为目的,已经完成了相关的元素实例化步骤。本节这里要处理的是,顾问角色的构建,以及构建 AiClientNode 节点。 +- 之后,AiClientNode 的构建,是关联了其他各项元素的,所以在构建时,需要在 AiClientNode 节点,从 Spring 容器通过 getBean 的方式,检索到对应的各项元素。 +- 注意,ai_client_system_prompt 系统提示词,需要修改为 Map 结构数据。这样更方便我们从数据里获取,哪些是属于当前 AiClientNode 构建时所需的元素。 \ No newline at end of file diff --git a/docs/md/project/ai-knowledge/ai-knowledge.md b/docs/md/project/ai-knowledge/ai-knowledge.md new file mode 100644 index 000000000..c98deb917 --- /dev/null +++ b/docs/md/project/ai-knowledge/ai-knowledge.md @@ -0,0 +1,324 @@ +--- +title: AI Agent 拖拉拽 + 动态配置 +lock: no +--- + +# 《AI Agent 拖拉拽 + 动态配置(RAG、MCP、Prompt)》 - 解析文档&Git仓库代码&AI工作流 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +刚上周,老板说:`”把咱们招聘里也加一条,具备AI应用开发能力的优先!“`。是呀,现在越来越多的企业都在用AI开发能力提效了,如;聊天软件增加一键唯独信息归档提取、工作文档资料携AI对话分析、工程SQL语句脚本辅运营自动完成数据处理、代码编写用AI完成自动评审等等。这些都是在AI的基础上在构建应用,以后也会越来越多!所以,具备AI应用开发能力,也是每个工程师最应该具备的基础能力了。 + +并且用不了多久,各大互联网企业都将大量的推进落地,自有 [MCP](https://github.com/modelcontextprotocol) 服务的实现,用于增强企业 AI 应用的提效能力。因为 [MCP](https://github.com/modelcontextprotocol) 的加入,可以让你;一条命令`帮研发`,调用应用系统日志、排查系统CPU负载、自主选择是否调度数据库信息。也可以一条命令`帮运营`,搞定复杂的SQL执行、导出报表、分析数据、完成促活营销券的自动化配置上架。这就是 [MCP](https://github.com/modelcontextprotocol) 的魅力!👍🏻 + +
+ +
+ +**那么牛,MCP 是什么?** + +专业的术语 `MCP = Model Context Protocol` 模型上下文协议,可实现应用与外部数据源和工具之间的无缝集成。无论您是构建 AI 驱动的 IDE、增强聊天界面还是创建自定义 AI 工作流,MCP 都提供了一种标准化的方式来连接他们所需的上下文。 + +`来吧,上图!让你看看它是啥!` + +
+ +
+ +- 首先,站在用户的使用视角,研发或者运营,可以通过话术描述,完成系列的 AI 工作流,并拿到最终的结果。这就是 MCP 最终为你提供的服务。 +- 那么,你可以想象,在日常的工作中,运营、研发、产品、测试等,都有非常多的重复非创作性的工作,占用了大量的时间成本。尤其是研发,写写代码,就有运营过来,帮我查个问题吧,小嘚嘚。但如果有这样的借助于 MCP 实现的 AI 工作流,就可以完成80%以上的工作量。 +- 之后,站在技术的实现视角,MCP 是一个标准结构框架,你可以按照它(Spring AI)提供的 SDK 开发方式,完成本地化 API 的接入开发。让 AI 有明确的方式调用各类 API 服务接口。如果没有 MCP 这会是一件很麻烦的事情。 + +**跟着小傅哥学习,从不走偏!😄** + +- 2022年底,ChatGPT 开始火爆。 +- 2023年2月,小傅哥,开启了第一个基于AI的项目,ChatGPT AI 问答助手项目。让所有伙伴,都能学习到 AI 如何开发应用。 +- 2023年4月,启动OpenAI(ChatGPT/ChatGLM)微服务应用体系构建大型项目,让大家可以用微信登录、微信支付/蓝兔支付,构建自己的可对外付费提供服务的 OpenAI。这一年上车学习的伙伴,很多做了自己的 AI 产品,除了提高编程技能,又小赚了一辆宝马。 +- 2024年7月,结合企业诉求,开启 OpenAI + Github Acitons,实现代码自动化评审。这一年,不少伙伴在自己的公司中都有落地,个人也得到了述职晋升。 +- 2025年3月,咱们再起启航,基于 Ollama 部署 DeepSeek,开发 RAG 知识库,解析文档和Git仓库代码。这个东西,将是企业中构建自己知识库的又一项非常重要的事情。有了知识库,AI 代码的自动评审,会更加精准,也可以辅助分析需求等。 + +那么,接下来小傅哥就细致的介绍下,本次开启的新项目,可以让大家学习到哪些知识,掌握哪些技术。 + +> Spring AI MCP 与 24年末发布,学习此 AI 应用开发项目,你将是第一批具备 Java AI 应用实战开发能力的人。竞争力,嘎嘎滴! + +## 一、能学到啥 + +这是一套综合`前后端 + Dev-Ops`,基于 Spring Ai 框架实现,Ai Agent 智能体。耗时7个多月,38节课程(`视频`+`文档`),从 RAG 到 MCP,再实现出互联网企业级,可编排的 Ai Agent 智能体,现已全部开发完成 + 部署上线。💐 + +该项目是结合当下最火的 Ollama、DeepSeek、SpringAI 等技术构建的 RAG 知识库实现。从前端到后端到 dev-ops 的全栈式功能手把手实现。 + +- 前端,基于 AI 工具,设计前端对话页面,完成 HTML、JS、TailwindCSS 的编码工作。 +- 前端,配置跨域服务接口,前后端分离实现 UI + 服务端接口对接。 +- 后端,构建双层架构,直接面向需求编码。让学习伙伴更轻松完成 RAG 知识库核心知识的学习。 +- 后端,基于 Spring AI 完成 DeepSeek、OpenAI 双模型的策略对接,处理文本向量的解析和存储。 +- 后端,使用 postgresql 存储切割文本向量数据,完成知识库的解析和存储。 +- 后端,处理多样文本`(.md、.sql、.txt、.word...)`的解析储存以及Git克隆代码库遍历切割存储。 +- 后端,使用 Redis 存储知识库标签,用于检索展示使用。 +- 后端,基于 Flux 编写流式会话接口,以及增加知识库检索功能。 +- 运维,基于 Docker 部署 Ollama 环境,完成 DeepSeek 大模型配置。 +- 运维,使用 Linux、Docker、Nginx 完成项目的打包、构建、上线! + +虽然,知识库都有很多现成的工具。但研发的能力不是在于功能应用,而是具备这样的开发技能储备,在有需要的时候,可以举手🙋🏻‍♀️”我会,我来做!“ + +> 此项目,全程视频手把手操作 + 全部的小册文档,你可以轻松上手学会这样一个项目! + +## 二、项目介绍 + +这是一套基于 Ollama DeepSeek 大模型构建的增强 RAG 知识库检索项目,在这套项目上,实现了除普通文档知识解析外,增加了 Git 代码库的拉取和解析,并提供操作接口。为工程师做项目开发时,`需求分析`、`研发设计`、`辅助编码`、`代码评审`、`风险评估`、`上线检测`等,做工程交付提效。 + +
+ +
+ +### 第1期,RAG 我们做了什么 + +在 《DeepSeek RAG 增强知识库》第1阶段,基于 Spring AI 0.8.1 开发了一套可以上传文件和Git仓库进行解析、切割、存储,到使用向量库完成 AI 的知识库问答系统。并最终通过 Docker 部署上线。 + +#### 1. 对话页面 + +
+ +
+ +- 这是全程视频手把手,带着大家通过AI工具,完成的UI设计实现课程会演示这个操作),实现的一款非常简单漂亮的UI效果。 +- 我们可以结合知识库,进行更加有效的提问。像是公司中,会把知识库提供出一个标准接口,给其他各个AI应用平台提供能力。 + +#### 2. 上传知识 + +
+ +
+ +- 上传知识,可以解析不同类型的知识库。 +- 除了课程提供的文档库、代码库,你可以增加其他的知识库,如;网页的解析,与网页内容对话。让我们的UI,增加一个侧边栏,读取当前网页内容,分析对话。这样在公司中的一些工程的日志,错误分析时,可以更快的处理。 + +#### 3. 解析知识 - 后台日志 + +
+ +
+ +- 上传知识后,可以看到日志信息。 +- 一套工程作为知识库是非常具有开发价值的,在我们做提问的时候就不需要,人工的去分析工程,而是直接使用了。 + +### 第2期,MCP 我们要做什么 + +与第2期相比,第1期可以称之为小试牛刀,让小伙伴们以最快、最快的往事,积累,运用 Spring AI 框架,开发自己的 RAG 知识库。~~也是方便有些死鬼,早点写到简历上~~ + +到了第2期,你就开始吃上细糠了,小傅哥会带着你升级 Spring AI 框架为 1.0.0-M6 最新版本,多模型配置和操作 PG 向量库,使用 GPU 搭建响应速度更好的 Ollama DeepSeek 大模型(秒级处理),以及对接官网 DeepSeek 的大模型和统一 one-api 对接方式。 + +但这还只是开始,随着基础框架的升级完成,我们将进入 MCP 服务的开发实现。通过 AI 指令,完成 AI 工作流,调度各项 MCP 处理我们的任务作业。如图,举例操作; + +
+ +
+ +- 基于 MCP 服务的开发和对接,通过 AI 工作流指令,完成数据的采集和存放动作。💡 聪明的小伙伴以及开始联想,基于这样的 AI 开发,可以替代很多的日常工作啦。**没想到吧,也把自己替代了** 但仍然,蠢蠢欲动(我不做,别人也做呀)!~~实现后,晋升又有的讲啦!简历也有东西写啦!~~ +- 有了 MCP 后,相当于把我们需要;在一个网页操作数据库查询数据、打开另外一个网页看天气预报,再手动的创建个文件把以上的信息获取后,复制粘贴到文件里。这一些列操作,都让 AI 通过 MCP 模型上下文协议进行处理。也就是 AI 可以调用后台接口啦! + +### 第3期,Agent 我们要做什么 + +RAG 教了,MCP 搞了,那么现在是时候,实现一套自动化的 Ai Agent 服务了。 + +如图,以通过数据库表动态配置的手段,完成相关物料的加载,包括;`模型(gpt-4.1/deepseek)`、`客户端`、`对话预设`、`执行规划(Planning)`、`顾问(记忆、RAG、日志)`、`工具(MCP`)等,在把单个 Client 串联,完成整个 Agent 调用链。这样一个 Agent 调用链可以以对话形式使用或通过 Agent 动态任务自动执行。 + +
+ +
+ +本项目分为,用户端、管理端和服务端,服务端统一提供接口能力,管理端维护 AI Agent 智能体配置、用户端提供使用服务。 + +#### 1. 登录界面 + +
+ +
+ +- 这一部分在数据库表增加了 admin_user 表,有配置登录账号和密码,可以简单做校验。 + +#### 2. 管理界面 + +
+ +
+ +- 管理后台目前提供了,代理管理(拖拉拽编排方式配置智能体),资源管理(model、client、mcp、advisor、prompt) +- 数据分析、系统设置,是样例,你可以继续扩展你所需要的内容。 + +#### 3. 代理管理 + +##### 3.1 代理列表 + +
+ +
+ +- 这里的代理列表,就是通过拖拉拽配置的智能体。可以点击【查看】看到明细,也可以【新建】,还可以删除。 +- 点击【加载】则是调用服务端,把数据加载到 Spring 容器,之后就可以使用了。 + +##### 3.2 代理配置 + +
+ +
+ +- 当你点击一个代理配置,则会展示出拖拉拽的数据到页面上。这部分会从数据库读取,之后展示出来,全部可视化。 +- 如果你点击了Save则会做出一份新的,之后对于旧的,你可以自己手动删除。 + +#### 4. 资源管理 + +
+ +
+ +- 资源管理下,是配置一个智能体所需的各项资源信息,你可以在这里进行维护。如,MCP 工具管理。 + +#### 5. 页面使用 + +##### 5.1 对话交流 + +
+ +
+ +##### 5.2 场景解析 + +
+ +
+ +##### 5.3 监控分析 + +
+ +
+ +- 配置后的智能体,可以在智能体选择里进行获取使用。之后进行提问。 +- 效果还不错,这里小傅哥验证了配置的智能体进行提问。 + +## 三、关于系统设计 + +本套系统设计,也是花费了非常大的心思。 + +### 1. 执行流程 + +
+ +
+ +在整个 Ai Agent 的实现中,小傅哥带着大家分析设计了4种方案,包括;固定执行的、循环执行的、智能分析决策的还有一个按照步骤规划的。这些流程都有适合于自己业务场景使用。在代码中也都有不同方案的实现,之后通过用户选择后进行动态化的策略调度。 + +### 2. 核心动作 + +#### 2.1 数据装配 + +
+ +
+ +- 首先,以构建 AiClientNode 的对话客户端为目的,已经完成了相关的元素实例化步骤。本节这里要处理的是,顾问角色的构建,以及构建 AiClientNode 节点。 +- 之后,AiClientNode 的构建,是关联了其他各项元素的,所以在构建时,需要在 AiClientNode 节点,从 Spring 容器通过 getBean 的方式,检索到对应的各项元素。 + +#### 2.2 动态调度 + +
+ +
+ +- 这里会根据用户的请求,进行策略路由,找到所需的 Ai Agent 执行策略进行处理。这里小傅哥也有意加入不同的策略,让大家可以看到很多的 Ai Agent 设计思路。 + +#### 2.3 执行策略(01) + +
+ +
+ +- 以程序启动为开始,进行自动化装配。这个过程我们先把一些想预先启动的数据库中的 agent 配置所需的 client 客户端进行服务初始化。之后写入到 Spring 容器,方便在执行 Agent 时进行使用。`前面有伙伴问,为什么把实例化的对象写入到 Spring 容器,这里就是原因` +- 客户端(UI),进行 POST 接口请求,这个过程需要封装一个 SSE 流式响应的接口,让 Step 1~4 各个执行步骤,把过程信息写入到流式接口。这里要注意,需要给接口返回的**对象**添加上对应的类型(什么步骤、什么节点、什么过程),以便于反馈给用户 Agent 在做什么。 + +#### 2.4 执行策略(02) + +
+ +
+ +- 这是其中的一种 Ai Agent 执行策略方式,通过用户的提问进行分析、规划、列出执行步骤,之后依次执行。 +- 所有的这些实现都有相应的代码,带着大家使用规则树框架清晰的实现出来。 + +## 四、课程目录 + +### 1. 课程目录 + +**第1阶段** spring-ai v0.8.1 - RAG 静态知识库(本阶段,需要配置附件的 setting.xml) + +- 第1节:关于 AI RAG 知识库项目介绍 +- 第2节:初始化知识库工程&提交代码 +- 第3节:Ollama DeepSeek 流式应答接口... +- 第4节:Ollama DeepSeek 流式应答页面... +- 第5节:Ollama RAG 知识库上传、解析和验证 +- 第6节:Ollama RAG 知识库接口服务实现 +- 第7节:基于AI工具,设计知识库UI和接口对接 +- 第8节:Git仓库代码库解析到知识库 +- 第9节:扩展OpenAI模型对接,以及完整AI对接 +- 第10节:云服务器部署知识库(Docker、Ngin... + +**第2阶段** spring-ai v1.0.0 - MCP 动态知识库 + +- 第11节:吃上细糠,升级SpringAI框架 +- 第12节:康庄大道,上手 AI MCP 工作... +- 第13节,道山学海,实现MCP自动发帖服务(... +- 第14节,海纳百川,上线MCP自动发帖服务 +- 第15节,川流不息,实现MCP微信公众号消息通知服务 +- 第16节:息息相通,MCP 服务部署上线(sse 模式) + +**第3阶段** spring-ai v1.0.0 - Ai Agent 进行中「如果着急面试,可以直接做3阶段,完成到13节很够面试啦」 + +- 第3-0节:Ai Agent 项目介绍和系统演示【最初版本,含完整代码】 +- 第3-1节,Ai Agent 业务流程、系统架构、库表设计说明 +- 第3-2节:初始化项目工程 +- 第3-3节:Ai Agent 测试案例 +- 第3-4节:根据 Ai Agent 案例,设计库表 +- 第3-5节:多数据源和Mapper配置 +- 第3-6节:数据加载模型设计 +- 第3-7节:动态实例化客户端API +- 第3-8节:动态实例化对话模型 +- 第3-9节:实例化对话客户端 +- 第3-10节:Agent执行链路分析 +- 第3-11节:Agent执行链路设计 +- 第3-12节:Agent服务接口和UI对接(第一版AutoAgent效果) +- 第3-13节,Agent-ELK日志分析场景 +- 第3-14节,Agent-Prometheus监控分析场景 +- 第3-15节:AgentFlow执行链路分析(扩展思路) +- 第3-16节:FlowAgent执行链路设计(扩展思路) +- 第3-17节:增加调度器策略执行Agent链路 +- 第3-18节:动态执行智能体任务 +- 第3-19节:拖拉拽编排数据存储 +- 第3-20节:Agent管理后台实现 +- 第3-21节:在云服务器部署上线 + +### 2. 编程环境 + +- JDK 17 ~ 21 +- Postgresql +- SpringBoot 3.2.3 - Spring AI 0.8.1 ~ 1.0.0+ +- Redis +- Docker +- Ollama + DeepSeek + GPU - +- RAG、MCP、Function Call + +课程包括文档 + 小册,全程视频带着做。课程地址:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) + +> 综上,你可以看到此套项目的完整的介绍,这些也都是企业里非常实用的技能积累。有希望提高自己的编程能力和面试材料的,可以马上加入学习。 + +--- + +课程包括;视频、小册、1 对 1 答疑解惑、专属VIP项目交流群,并且提供简历编写模板结构的一条龙🐲服务。让你学习后,直接拉开与还在玩具项目其他人的差距,面试脱颖而出提高竞争力!!! + diff --git a/docs/md/project/ai-knowledge/ext/ai-agent-auto.md b/docs/md/project/ai-knowledge/ext/ai-agent-auto.md new file mode 100644 index 000000000..95cbe407e --- /dev/null +++ b/docs/md/project/ai-knowledge/ext/ai-agent-auto.md @@ -0,0 +1,137 @@ +--- +title: Ai Agent VS 字节扣子? +lock: no +--- + +# Ai Agent VS 字节扣子? + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +**媲美Dify,堪比扣子?🤔** 哈哈哈,经过哐哐的一顿卷,小傅哥这套 Ai Agent 项目,已经做出一版智能对话体(对接UI),在单一方面的功能体验上,确实可以和市面的 Ai Agent 产品握握手啦 🤝!效果很是不错,本文提供了视频和截图。 + +
+ +
+ +**什么是 Ai Agent?** + +做的越多理解的也越透彻,Ai Agent 更像是对人的行为的理解。一个人再有力气,也没法一天完全一年全部的工作,而是需要我们把这些工作,做好规划、定好目标、完成执行、结果检查,循序渐进的执行再到最终交付。 + +那么,Ai Agent 也是一样的,Ai Token 提升的在高(等于人的力气),也没法一次做完所有事情。所以在结合了 `Prompt(提示词)`、`Advisor(记忆、RAG)`、`Tool(MCP)`,也可以把一整个大任务,细分为独立的小块,每一块做好规划、执行、审查和交付。所以 Ai Agent 再趋向一个人的行为。 + +**跟着小傅哥,吃上一碗细糠!** 可能你也做过一些学习的项目,但往往这些项目都是一些功能逻辑的叠加和 CRUD 的拼装 + 好看一些的脸面(UI)。但是跟着小傅哥学习,给你的就不只是一个项目,还会带着你做架构,搞设计,用优雅的方式进行编码,深度积累编程思维和编码能力。 + +>🧧 文末已提供整套 Ai Agent 实战项目的全套代码 + 各个分支章节的文档(含视频),学习起来非常爽! + +## 一、先上效果 - 堪比扣子! + +😂 做的多了,也做的久了。我发现,Ai Agent 所有模块架构好后,剩下的就是 Prompt 提示词质量的对比。**Prompt = Ai Agent 大脑!** 目前小傅哥演示的这套自研的 Ai Agent 就是反复优化 Prompt 的结果。 + +### 1. 对话场景 - 通用场景 + +#### 1.1 截图效果 + +
+ +
+ +左侧是AI思考执行过程,右侧是最终执行结果。通过我们的提问,AI Agent 进行`分析`、`规划`、`执行`、`监督`,再到最终的结果产生。有了这样的步骤,最终的总结阶段数据就会更加准确。 + +#### 1.2 视频效果(对比扣子) + +视频:[https://www.bilibili.com/video/BV1VYbczDER6](https://www.bilibili.com/video/BV1VYbczDER6) + +### 2. 日志分析 - ELK 辅助提效(公司里非常需要这样的场景) + +#### 2.1 采集分析 + +
+ +
+ +如图,是一个系统日志 ELK + Ai Agent 的运行简图,通过 MCP 服务的对接,让 Ai Agent 具备检索日志的能力,再结合分析话术,以此来完成日志的自动化分析。 + +#### 2.2 数据案例 + +
+ +
+ +在互联网公司中,都会有一套类似 ELK 的分布式日志系统,之后各个应用会上报数据。研发在接收到系统报警和运营反馈线上问题的时候,研发就需要进入到 ELK 查看系统日志的情况,以此分析线上问题。 + +#### 2.3 智能分析 + +
+ +
+ +通过 Ai Agent 分析 ELK 应用系统分布式日志,自动排除出限流用户的相关信息,来辅助研发日常工作提效。 + +## 二、系统设计 - 这是一个正经项目! + +Ai Agent 会的模型架构会趋向稳定并形成标准,之后便是 Prompt + MCP + Client 多链路动态执行迭代和优化。所以,把架构定义好,具备强扩展性是非常有必要的,也是程序员👨🏻‍💻工作价值的体现。—— 堆功能只等于 demo 案例,驾驭架构解决复杂问题才是核心价值体现! + +### 1. 库表设计 + +
+ +
+ +
+ +
+ +- 这里小傅哥设计了一套非常灵活的 Ai Agent 库表结构,满足动态配置各项资源,再由程序动态化的随时加载和使用。 +- 有了这样的库表,我们就可以按需配置出多种使用类型的 Ai Agent,之后对话或者 Job 任务方式执行使用。 + +### 2. 数据加载 + +如图,整体 ChatClient 客户端实例化过程; + +
+ +
+ +- 首先,以构建 AiClientNode 的对话客户端为目的,已经完成了相关的元素实例化步骤。本节这里要处理的是,顾问角色的构建,以及构建 AiClientNode 节点。 +- 之后,AiClientNode 的构建,是关联了其他各项元素的,所以在构建时,需要在 AiClientNode 节点,从 Spring 容器通过 getBean 的方式,检索到对应的各项元素。 +- 注意,ai_client_system_prompt 系统提示词,需要修改为 Map 结构数据。这样更方便我们从数据里获取,哪些是属于当前 AiClientNode 构建时所需的元素。 + +### 3. 执行分析 + +如图,不同方案实现的 Agent 流程; + +
+ +
+ +Ai Agent 的处理过程也是分为几类的,用于适应不同的场景使用; + +1. 固定N个步骤,这类的一般是配置工作流的,提高任务执行的准确性。如,一些检索资料、发送帖子、处理通知等。 +2. 顺序循环调用,配置 Agent 要执行的多个 Client 端,以此顺序执行。适合一些简单的任务关系,并已经分配好的动作,类似于1的方式。 +3. 智能动态决策,这类是目前市面提供给大家使用的 Agent 比较常见的实现方式,它会动态的规划执行动作,完成行动步骤,观察执行结果,判断完成状态和步骤。并最终给出结果。 + +### 4. 功能架构 + +如图,从Agent服务的装配到接口调用和响应的关系图; + +
+ +
+ +- 以程序启动为开始,进行自动化装配。这个过程我们先把一些想预先启动的数据库中的 agent 配置所需的 client 客户端进行服务初始化。之后写入到 Spring 容器,方便在执行 Agent 时进行使用。`前面有伙伴问,为什么把实例化的对象写入到 Spring 容器,这里就是原因` +- 客户端(UI),进行 POST 接口请求,这个过程需要封装一个 SSE 流式响应的接口,让 Step 1~4 各个执行步骤,把过程信息写入到流式接口。这里要注意,需要给接口返回的**对象**添加上对应的类型(什么步骤、什么节点、什么过程),以便于反馈给用户 Agent 在做什么。 + +## 三、课程目录 + +整个课程分3个阶段讲解,包括;RAG、MCP,之后进入 Agent 阶段的学习。前面打好基础,后面进入应用。哪怕是小白,也可以跟着一起实战起来,而且每个阶段都有部署运行效果,越学越爽。 + +项目地址:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) + +
+ +
\ No newline at end of file diff --git a/docs/md/project/ai-knowledge/ext/ai-agent-flowgram.md b/docs/md/project/ai-knowledge/ext/ai-agent-flowgram.md new file mode 100644 index 000000000..b65d81c23 --- /dev/null +++ b/docs/md/project/ai-knowledge/ext/ai-agent-flowgram.md @@ -0,0 +1,84 @@ +--- +title: 有方案了,让自研 Ai Agent 可视化编排! +lock: no +--- + +# 有方案了,让自研 Ai Agent 可视化编排! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +每当一项新技术问世,市场上总会涌现出一批基于该技术的热门项目。以 AI 技术为例,紧随其后便出现了 `n8n`、`dify`、`coze` 等各类相关应用产品(当然,他们很优秀)。 + +然而,随着技术逐渐成熟和稳定,这些通用的解决方案往往会逐渐淡出市场。为什么呢?这是因为,各个企业下场后,都开始基于自身的业务,在细分领域,做自己的 Ai Agent 服务啦!所以,什么才是最重要的呢? + +
+ +
+ +**什么才是最重要的呢?** + +从研发的角度来看,最关键的是;学习业务场景经验、积累技术架构方案、落地应用项目能力。相比市场上层出不穷、功能纷繁复杂的各类产品,真正有价值的是对技术本质的持续储备。只有具备扎实的技术功底,形成闭环的技术体系,才能自身核心价值能力。 + +有了这样的能力积累,你可以在任何一个公司,任何一个场景,架构出一套最为符合的业务系统。所以,你的能力也等同于你的级别和薪资。 + +所以,对于最火的 Ai Agent 不要只是会用就行了,拿个项目过来,部署上就觉得可以了。你要做的,是把全套的业务弄透彻,实现的方案搞下来,怎么编码整明白。好啦,开冲,今天给这套 Ai Agent 加上可视化编排方案。 + +> 🧧 文末提供了全套 AI、RAG、MCP、Agent 项目、开发教程以及工程源码。此外还有非常多的互联网大厂项目(17个),都可以一并获取学习。 + +## 一、拖拉拽效果 + +鉴于整个 Ai Agent 的配置,需要一大堆东西,如;执行频次任务、客户端串联、模型选择、顾问角色知识库、MCP 工具、提示词等,有一套可视化拖拉拽配置的前端页面,就显得非常有必要了。 + +因此小傅哥调研了不少具备图形化编排能力的前端组件,发现一套 [flowgram.ai(官网有文档,可直接阅读)](https://flowgram.ai/) 可以很好的满足当前 Ai Agent 编排能力。😄 并且上手不困难,效果还不错。 + +
+ +
+ +- 首先,我们要基于 [flowgram.ai](https://flowgram.ai/) 框架,开发自己需要的 Node 节点(后面会有代码说明,方便伙伴扩展)。这里增加了;task、agent、client、too-mcp、model。 +- 之后,在页面点击添加节点,并选择好每个节点,应该配置的属性信息,以及连接节点关系。 +- 最后,点击保存,他会给你一个json 对象,按照对象的结构,创建服务端接口即可接收和保存。(相关保存操作,会在后续课程中添加,如果有诉求可以先把前端代码下载下去,对照json开发接口即可) + +> 本套全段代码 [ai-agent-station-front](#) 已经添加到课程中,可以进入获取。地址:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) + +## 二、怎么添加节点 + +### 1. 下载前端工程 + +首先,你要下载 [ai-agent-station-front](https://gitcode.net/KnowledgePlanet/ai-agent-station-front) 到本地使用 trae.ai 打开。如果没有提示你,要自己手动执行 npm install 初始化工程。 + +
+ +
+ +- 首先,[flowgram.ai](https://flowgram.ai/) 官网提供了各种案例,可以下载一个进行扩展。这里小傅哥就是下载好的一个,之后添加我们需要的节点。 +- 之后,docs 下的 ai-agent-station.sql 为的是让 ai 可以使用,自动创建 node 节点的(下文有演示)。 +- 另外,这里的代码,对于稍微有些 react 编码基础的伙伴,是可以非常方便看懂的。后端工程师,如果不懂也没关系,让 ai 来解答以及操作。 + +### 2. Ai 编码,添加节点 + +
+ +
+ +- 首先,下载一份国际版 trae.ai,这里有使用文档。[https://bugstack.cn/md/road-map/trae.html](https://bugstack.cn/md/road-map/trae.html) 使用 cursor 也可以,其实这东西,重要的就是好用的模型。 +- 之后,nodes 下是各种节点,我们可以拖拽一份让 ai 编码参考。并告诉ai,以哪个库表信息来编写新的节点。(有时候可能有问题,如果有问题,可以手动修改下) + +## 三、点击保存,查看json + +
+ +
+ +
+ +
+ +- 点击保存,就可以拿到节点和链接的关系数据了。这份数据是可以和数据库对应上。 +- 后续课程从0到1的实现过程中,会和后端接口联动,存储数据。现在你也可以先下载前端代码,尝试编码。 + diff --git a/docs/md/project/ai-knowledge/ext/ai-agent-job.md b/docs/md/project/ai-knowledge/ext/ai-agent-job.md new file mode 100644 index 000000000..01634d737 --- /dev/null +++ b/docs/md/project/ai-knowledge/ext/ai-agent-job.md @@ -0,0 +1,97 @@ +--- +title: 阶段性总结,Ai Agent 的重要性 +lock: no +--- + +# 阶段性总结,Ai Agent 的重要性 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +还好,还好早早的就开始了 AI 应用技术的储备,让我吃了互联网职场的第一碗创新类应用的技术饭。 + +其实从最早 OpenAI 发布 ChatGPT 开始,我就开始使用其接口陆续开发了应用,2022年年尾-开发智能问答助手、2023年年初-OpenAI应用项目(可支付买额度对话)、2023年终-OpenAI 代码自动评审。 + +可以说,在 AI 应用类开发这条路上,我一直走的很快也很靠前。甚至,我也思考怎么让 AI 识别接口,具备调用能力,而不是就只是做一些对话类操作。直至2024年他来啦! + +2024年11月份,Anthropic 公司推出了 MCP(Model Context Protocol,模型上下文协议)开放标准协议(JSON-RPC 2.0),其核心目标是通过提供一个标准化的接口,使AI模型能够无缝地访问本地和远程资源。 + +如果没有 MCP 可以说就没有 AI Agent 智能体,也不会有现在那么多的结合于 AI 来为工作提效的场景。 + +所以,当我看到 AI MCP 那一刻,我是很兴奋。也在 AI MCP 协议出了不久,立马筹备新的 AI Agent 项目,让大家都能学习到这一技术。而且我也早早的告诉过大家 **用不了多久,各大互联网企业都将大量的推进落地,自有 MCP 服务的实现,用于增强企业 AI 应用的提效能力。** 随后,我们看到了阿里支付宝 MCP、高德地图 MCP、百度搜索 MCP,等等各类 MCP 服务如雨后春笋一般。再往后各个公司推出了各种的 Ai Agent 能力,因为 AI 可以调用 MCP 服务,真正的帮我们做一些事情。 + +现在,公司里随便一个功能服务接口(RPC、HTTP),都可以通过简单配置走 MCP 网关转换为 MCP 协议接口能力,让 AI Agent 通过配置即可完成调用。也就是说,通过配置接口 + Prompt 提示词,既可以承接绝对部分日常工作,如;客诉排查、日志分析、监控巡检、文档评审、单测开发等等。 + +老板总说,我需要的不只是 AI 开发能力的人才,而且他还要懂得业务,具备应用项目落地能力。这样才能为我们企业的场景提效,而不是天马行空。所以,想学 AI 的伙伴来说,不要只是一头扎入到 AI 里,也要多积累业务场景经验。 + +## 一、市面的开源资料 + +**86.5k Star!** 关注 Ai Agent 实现的人超级多,也都知道这是一个热门方向。项目:[https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools](https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools) + +
+ +
+ +这是一款开源系统提示词项目,包含了市面的热门产品 Trae、Cursor、Claude、v0 等20多款 Ai Agent 项目的提示词 + MCP Tool。非常适合需要做 Ai Agent 项目的伙伴借鉴使用。 + +小傅哥还复制下来 Trae.ai 提示词(不过可能不是最新版)的内容进行本地验证,配置百度搜索 MCP 服务 + 本地文件处理。经过提问后,可以在本地创建出对应的文件夹内容,如果在结合进去 Shell 脚本能力,会更好。如果想要更好的效果,可以完全配置出一套 Trae 所需的工具服务组,那么效果会更好。 + +
+ +
+ +目前 Ai Agent 的开发实现,主要为;`分析`、`规划`、`执行`、`验证`,以及在这个过程中循环检测执行,对结果进行确认校验继续分析。可能将来也会由 OpenAI 主导,设计一套 Ai Agent 框架结构组件,那么 Ai Agent 的开发门口将更低也会更通用(目前就有不少这样的 Auto Agent 框架)。 + +## 二、也快接近尾声啦 + +2025年3月3日,小傅哥带着大家从 RAG 开始,之后进入 MCP,后来又做到 Ai Agent,持续了半年多。这块也快收尾了,核心功能都已经完成,陆续的开始做一些收尾的章节。 + +
+ +
+ +- RAG 10节、MCP 6节、Ai Agent 18节(还有待更新的),目前整体34节,后续整体都做完预计到40节,10.1假期后差不多。 + +## 三、总结下项目内容 + +### 1. 页面效果 + +
+ +
+ +- 如图,用户可以自己选择一个对话场景的智能体,之后后端会根据用户的请求进行动态化策略调度。 +- 目前,已经添加的场景有;CSDN发帖 + 通知(同类小红书也可以做)、智能对话分析、ELK日志检索分析、智能监控分析服务。只要你学习了这套系统,就可以设计出你所需要的 Ai Agent 使用场景。 + +### 2. 执行流程 + +
+ +
+ +在整个 Ai Agent 的实现中,小傅哥带着大家分析设计了4种方案,包括;固定执行的、循环执行的、智能分析决策的还有一个按照步骤规划的。这些流程都有适合于自己业务场景使用。在代码中也都有不同方案的实现,之后通过用户选择后进行动态化的策略调度。 + +### 3. 核心动作 + +#### 3.1 动态调度 + +
+ +
+这里会根据用户的请求,进行策略路由,找到所需的 Ai Agent 执行策略进行处理。这里小傅哥也有意加入不同的策略,让大家可以看到很多的 Ai Agent 设计思路。 + +#### 3.2 执行策略 + +
+ +
+ +- 这是其中的一种 Ai Agent 执行策略方式,通过用户的提问进行分析、规划、列出执行步骤,之后依次执行。 +- 所有的这些实现都有相应的代码,带着大家使用规则树框架清晰的实现出来。 + +好啦,欢迎感兴趣的伙伴一起加入学习,小傅哥的社群,有非常多的实战项目,涵盖;业务、组件、框架、源码、开源、创新等,让你加入后,就等同于加入一个互联网大厂的核心项目组,各项信息都能全部接触到,甚至包括产品 PRD 文档。**因为小傅哥就是大厂架构师,所以也是按照一个我所在的核心的组的方式来给大家建设与之匹配的资料内容。** + diff --git a/docs/md/project/ai-knowledge/ext/ai-agent-mcp-auth.md b/docs/md/project/ai-knowledge/ext/ai-agent-mcp-auth.md new file mode 100644 index 000000000..381acbf09 --- /dev/null +++ b/docs/md/project/ai-knowledge/ext/ai-agent-mcp-auth.md @@ -0,0 +1,450 @@ +--- +title: 给 MCP 服务加上安全认证! +lock: no +--- + +# 给 MCP 服务加上安全认证! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +刚刚过去两个月,市面的 MCP 服务,如雨后春笋一般不断涌现出来,包括;`百度`、`高德`、`网盘`、`支付宝`。这些 MCP 服务,可以让我们基于 Spring AI 框架构建的 Agent 具备非常丰富的使用功能。同时这也说明,程序员👨🏻‍💻,应该具备开发 MCP 服务的能力,Spring AI 让 Java 再次牛逼! + +
+ +
+ +>关于 RAG、MCP、Agent 是什么,这里小傅哥已经编写过了全套的教程,可以进入学习;[https://bugstack.cn/md/project/ai-knowledge/ai-knowledge.html](https://bugstack.cn/md/project/ai-knowledge/ai-knowledge.html) + +本节小傅哥主要给大家分享,关于市面上这些标准的带有验证权限的 MCP 服务,怎么使用 Spring AI 进行对接。同时我们自己开发的 MCP 服务,怎么加上权限校验。 + +## 一、举例,对接高德地图 MCP + +高德地图 MCP Server; + +```java +{ + "mcpServers": { + "amap-amap-sse": { + "url": "https://mcp.amap.com/sse?key=您在高德官网上申请的key" + } + } +} +``` + +- 官网:[https://lbs.amap.com/api/mcp-server/gettingstarted](https://lbs.amap.com/api/mcp-server/gettingstarted) - `官网提供了创建对接 Key` + +### 1. 代码使用示例 + +```java +@Configuration +public class McpConfig { + + @Bean + public List mcpClientTransport() { + McpClientTransport transport = HttpClientSseClientTransport + .builder("https://mcp.amap.com") + .sseEndpoint("/sse?key=") + .objectMapper(new ObjectMapper()) + .build(); + + return Collections.singletonList(new NamedClientMcpTransport("amap", transport)); + } + +} +``` + +- 对接时,需要设定 sseEndpoint 如果不设定个,Spring AI 默认是对 builder 的 baseUrl 值添加 `/sse` 的。 +- 所以,如果你要对接外部带有验证权限的 MCP 服务,需要手动设置下 sseEndpoint 值。 + +### 2. 项目中的配置 + +小傅哥,带着大家做的 Ai Agent,也支持了外部的这些带有权限校验的 MCP 服务。你可以,以多种方式进行配置。如; + +```java +{ + "baseUri":"https://mcp.amap.com", + "sseEndpoint":"/sse?key=801aabf79ed0ff78603cfe85****" +} +``` + +```java +{ + "baseUri":"https://mcp.amap.com", + "sseEndpoint":"/sse?key=801aabf79ed0ff78603cfe85****" +} +``` + +- 以上两种配置方式,在 ai-agent-station 都做了兼容处理。以下是兼容代码,学习这部分项目的伙伴,可以直接阅读课程代码。 + +```java +@Slf4j +@Component +public class AiClientToolMcpNode extends AbstractArmorySupport { + + // ... 省略部分代码 + + protected McpSyncClient createMcpSyncClient(AiClientToolMcpVO aiClientToolMcpVO) { + String transportType = aiClientToolMcpVO.getTransportType(); + + switch (transportType) { + case "sse" -> { + AiClientToolMcpVO.TransportConfigSse transportConfigSse = aiClientToolMcpVO.getTransportConfigSse(); + // http://127.0.0.1:9999/sse?apikey=DElk89iu8Ehhnbu + String originalBaseUri = transportConfigSse.getBaseUri(); + String baseUri; + String sseEndpoint; + + int queryParamStartIndex = originalBaseUri.indexOf("sse"); + if (queryParamStartIndex != -1) { + baseUri = originalBaseUri.substring(0, queryParamStartIndex - 1); + sseEndpoint = originalBaseUri.substring(queryParamStartIndex - 1); + } else { + baseUri = originalBaseUri; + sseEndpoint = transportConfigSse.getSseEndpoint(); + } + + sseEndpoint = StringUtils.isBlank(sseEndpoint) ? "/sse" : sseEndpoint; + + HttpClientSseClientTransport sseClientTransport = HttpClientSseClientTransport + .builder(baseUri) // 使用截取后的 baseUri + .sseEndpoint(sseEndpoint) // 使用截取或默认的 sseEndpoint + .build(); + + McpSyncClient mcpSyncClient = McpClient.sync(sseClientTransport).requestTimeout(Duration.ofMinutes(aiClientToolMcpVO.getRequestTimeout())).build(); + var init_sse = mcpSyncClient.initialize(); + log.info("Tool SSE MCP Initialized {}", init_sse); + return mcpSyncClient; + } + case "stdio" -> { + AiClientToolMcpVO.TransportConfigStdio transportConfigStdio = aiClientToolMcpVO.getTransportConfigStdio(); + Map stdioMap = transportConfigStdio.getStdio(); + AiClientToolMcpVO.TransportConfigStdio.Stdio stdio = stdioMap.get(aiClientToolMcpVO.getMcpName()); + + // https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem + var stdioParams = ServerParameters.builder(stdio.getCommand()) + .args(stdio.getArgs()) + .build(); + var mcpClient = McpClient.sync(new StdioClientTransport(stdioParams)) + .requestTimeout(Duration.ofSeconds(aiClientToolMcpVO.getRequestTimeout())).build(); + var init_stdio = mcpClient.initialize(); + log.info("Tool Stdio MCP Initialized {}", init_stdio); + return mcpClient; + } + } + + throw new RuntimeException("err! transportType " + transportType + " not exist!"); + } + +} +``` + +- 以上代码,是为了自动化构建 MCP 服务的,其中 case sse 的部分,会对 url 进行拆分,如果本身 url 配置了校验权限,则不会从另外一个参数获取,否则从另外参数拼接。这样就可以很好的扩展用户配置时的多样性问题了。 + +>以上是关于带有权限校验的 MCP 服务配置的问题,接下来,我们要说下怎么自己开发一个带有权限校验 + +## 二、实现,带有权限校验的 MCP 服务 + +首先,Spring AI 是有意提供基于自家的 OAuth2 框架,完成 MCP 服务的多样性权限校验的。不过目前提供的方案能用,但不算成熟。 + +
+ +
+ +官网:[https://spring.io/blog/2025/05/19/spring-ai-mcp-client-oauth2](https://spring.io/blog/2025/05/19/spring-ai-mcp-client-oauth2) + +### 1. 基于 OAuth2 认证 + +#### 1.1 工程结构 + +
+ +
+ +- 工程:[https://gitcode.net/KnowledgePlanet/mcp-server-auth](https://gitcode.net/KnowledgePlanet/mcp-server-auth) - `面向于学习 ai-agent-station 的伙伴` +- 使用 OAuth2 基于 Spring MVC 的方式到也简单,知道添加配置即可。 + +#### 1.2 所需的 POM 文件 + +```pom + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + + + + org.springframework.boot + spring-boot-starter-oauth2-authorization-server + + + + org.springframework.ai + spring-ai-starter-mcp-server-webmvc + +``` + +#### 1.3 测试验证 + +```java +@Slf4j +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "server.shutdown=immediate") +public class ApiTest { + + @LocalServerPort + private int port; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void test_access_token() throws IOException, InterruptedException { + String token = obtainAccessToken(); + log.info("token:{}", token); + // eyJraWQiOiJiMWQ0MGIxNi1hOTYzLTQ2NmYtYTVkOC02NGRjMzg0ODljYWEiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJtY3AtY2xpZW50IiwiYXVkIjoibWNwLWNsaWVudCIsIm5iZiI6MTc0ODA1MTc1NiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1ODA5OCIsImV4cCI6MTc0ODA1MjA1NiwiaWF0IjoxNzQ4MDUxNzU2LCJqdGkiOiI5NjY4ZmZkMi0wNjQ2LTRiNmItODQ4Ni1jYzk3ZjMxNTdmOTEifQ.CG4GYai_NYkmfcqmNi-_HYG06Kan04uNSsC2ivn_eC9Ra6xMKYTs9KIT7k5lKxSFRUOPI7K0zJNVvNXrrIe0iFl-csrG2vGukNTGTPMxtUi2hheBMRbnvjvuojW4DeOEE8UOpdA6uow67ucwcymTlDXE-k7OjRZeyp7UdVz2WyoDFQhLB6ihLbDSj5puAZxfNocirRzo36gmW243aW9f1gugPUcpND-oobc2q8xyBG2cX2AlGXUSS-v9PLjHr2W2smFTKHHGwu7FpMMBnJLUT5gZD0llIg6yqro91nFaAFOpGHXjRZYgVjkRlzxx08Zuquva9PbStxbUl2j8hI43_Q + + var client = HttpClient.newHttpClient(); + + var request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + port + "/sse")) + .header("Accept", "text/event-stream") + .header("Authorization", "Bearer " + token) + .GET() + .build(); + + var responseCode = new AtomicInteger(-1); + var sseRequest = client.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()).thenApply(response -> { + responseCode.set(response.statusCode()); + if (response.statusCode() == 200) { + log.info("response:{}", JSON.toJSONString(response)); + return response; + } + else { + throw new RuntimeException("Failed to connect to SSE endpoint: " + response.statusCode()); + } + }); + + await().atMost(Duration.ofSeconds(1)).until(sseRequest::isDone); + assertThat(sseRequest).isCompleted(); + assertThat(responseCode).hasValue(200); + } + + private String obtainAccessToken() throws IOException, InterruptedException { + var client = HttpClient.newHttpClient(); + + var clearTextCredentials = "mcp-client:secret".getBytes(StandardCharsets.UTF_8); + var credentials = new String(Base64.getUrlEncoder().encode(clearTextCredentials)); + var request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:" + port + "/oauth2/token")) + .header("Authorization", "Basic " + credentials) + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(ofString("grant_type=client_credentials")) + .build(); + + var rawResponse = client.send(request, HttpResponse.BodyHandlers.ofString()).body(); + + Map response = objectMapper.readValue(rawResponse, Map.class); + return response.get("access_token"); + } + +} +``` + +- 加上 OAuth2 以后,就需要获取并设置 accessToken 才能访问 sse 服务了。 + +### 2. 基于网关实现 + +其实我们到不非得依赖于 Spring OAuth2 往 MCP 服务里在添加一些其他的东西。倒不如直接走网关,让网关来管理权限,MCP 服务只做服务的事情就好。 + +这里我们基于 Nginx 来配置验证功能,当然你可以在学习本节的案例后,配置任何其他的网关来管理你的 MCP 服务。 + +注意,这里的前置条件为你已经跟着小傅哥,至少完成了一个 MCP 服务。课程;[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) + +当我们有了一套基于 sse 形式访问的 mcp 后,我们是可以给这套 mcp 基于 nginx 转发的形式进行访问后面真实的 mcp 服务的。在转发的过程中,拿到用户在地址 `http://127.0.0.1:9999/sse?apikey=DElk89iu8Ehhnbu` mcp 服务后面拼接的 apikey,并对 apikey 进行验证。 + +#### 2.1 配置工程 + +
+ +
+ +- 在 ai-agent-station 项目下,提供了 dev-ops-v2 配置 mcp 服务转发和验证能力。 +- 注意,部署的时候,要把 mcp.localhost.conf 转发的 mcp 服务的地址,更换为你的地址。 +- 另外,每一个 mcp.localhost.conf 还可以配置域名,这样就达到了高德地图 mcp 访问的效果。举例;`https://fatie.mcp.bugstack.cn/sse/apikey=*******` + +#### 2.2 服务转发&校验 + +```java +# 可以负载服务 +upstream backend_servers { + server 192.168.1.108:8101; +} + +server { + listen 80; + + server_name 192.168.1.104; # 修改为你的实际服务器 IP 或域名【域名需要备案】 + + location /sse { + # 验证apikey参数,这个apikey也可以对接服务端接口来处理。 + if ($arg_apikey != "DElk89iu8Ehhnbu") { + return 403; # 如果apikey不正确,返回403禁止访问 + } + + # 重写URL,去掉apikey参数 + rewrite ^(/sse/)\?apikey=.* $1 break; + + proxy_pass http://backend_servers; # 将请求代理到上游服务器组 + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + chunked_transfer_encoding off; + proxy_buffering off; + proxy_cache off; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /mcp/message { + proxy_pass http://backend_servers; # 将请求代理到上游服务器组 + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + +} +``` + +- 特别注意,mcp 服务是有2个步骤的,一个是 sse 访问,还有一个 mcp/message 的处理。我们只需要对 sse 的请求进行验证即可。 +- `/sse` 请求路径,需要会提取 apikey 与 nginx 配置的值进行对比,如果不正确则会返回一个 403 禁止访问,通过则放行。 +- 之后重写 url 地址,让转发到本身 mcp 的地址是干净的。从 `http://127.0.0.1:9999/sse?apikey=DElk89iu8Ehhnbu` 验证转发后为 `http://192.168.1.108:8101/sse` + +#### 2.3 功能验证 + +首先,要确保你的 mcp 服务是可以使用的。如,访问;`http://192.168.1.108:8101/sse` 可以获得到结果。 + +
+ +
+- 如图,验证成功。我们可以通过转发的方式进行验证和使用。 +- 另外,有了转发和验证,你原本的服务,sse 8101 就不用对外了。只有你的网关(nginx)可以访问即可。这样就可以控制权限了。 + +#### 2.4 动态验证 + +那么,目前我们配置的nginx 转发这不是一个固定的权限账号吗,怎么让不同的接入方都申请一个秘钥key来使用呢?这里我们需要使用到 nginx 的 auth 认证模块。 + +```java +# 可以负载服务 +upstream backend_servers { + server 192.168.1.108:8101; +} + +server { + listen 80; + + server_name 192.168.1.104; # 修改为你的实际服务器 IP 或域名【域名需要备案】 + + location /sse { + auth_request /auth; + + # 重写URL,去掉apikey参数 + rewrite ^(/sse/)\?apikey=.* $1 break; + + proxy_pass http://backend_servers; # 将请求代理到上游服务器组 + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + chunked_transfer_encoding off; + proxy_buffering off; + proxy_cache off; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /mcp/message { + proxy_pass http://backend_servers; # 将请求代理到上游服务器组 + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location = /auth { + # 发送子请求到HTTP服务,验证客户端的凭据,返回响应码 + internal; + # 设置参数 + set $query ''; + if ($request_uri ~* "[^\?]+\?(.*)$") { + set $query $1; + } + # 验证成功,返回200 OK + proxy_pass http://207.246.123.*:8090/auth/token?$query; + # 发送原始请求 + proxy_pass_request_body off; + # 清空 Content-Type + proxy_set_header Content-Type ""; + } + +} + +``` + +- 在访问 `/sse` 的时候,增加 auth 认证,auth 来访问本地一个 http 接口。你可以是 SpringBoot 实现的接口。这个接口负责验证你的秘钥是否正确。同时你的 SpringBoot 服务还可以提供出一个创建秘钥的平台,让接入方使用。 +- 其实类似这样的场景,使用功能更加丰富的 api 网关都是自带的,或者 github 一些专门为 mcp 做网关服务的也都有。 + +## 三、增强,学习 rag、mcp、agent + +小傅哥,已经为你准备好了一套 AI RAG、MCP、Agent 实践编程课程,使用 Java + Spring AI 框架,增强自己的 AI 应用开发能力,迅速囤积编程技能,满足各个公司招聘时对AI应用类开发的要求!如下,课程目录,全程文档小册 + 视频带着你从0到1学习。 + +#### **第1期 RAG Spring AI 0.8.1 - 完结** + +1. 【更】AI RAG 知识库,项目介绍&需求分析&环境说明 +2. 【更】初始化知识库工程&部署模型&提交代码 +3. 【更】Ollama DeepSeek 流式应答接口实现 +4. 【更】Ollama DeepSeek 流式应答页面对接 +5. 【更】Ollama RAG 知识库上传、解析和验证 +6. 【更】Ollama RAG 知识库接口服务实现 +7. 【更】基于AI工具,设计前端UI和接口对接 +8. 【更】Git仓库代码库解析到知识库并完善UI对接 +9. 【更】扩展OpenAI模型对接,以及完整AI对接 +10. 【更】云服务器部署知识库(Docker、Nginx) + +#### **第2期 MCP Spring AI 1.0.0 - 完结** + +1. 【更】吃上细糠,升级SpringAI框架 +2. 【更】康庄大道,上手 AI MCP 工作流 +3. 【更】道山学海,实现MCP自动发帖服务(stdio) +4. 【更】海纳百川,上线MCP自动发帖服务 +5. 【更】川流不息,实现MCP微信公众号消息通知服务 +6. 【更】息息相通,MCP 服务部署上线(sse 模式) + +#### 第3期 Agent Spring AI 1.0.0 - 进行中【全套源码和部署已提供】 + +1. 第3-0节,AiAgent项目介绍和系统演示 +2. 第3-1节,Ai Agent 业务流程、系统架构、库表设计说明 +3. 第3-2节,初始化工程和库表dao等,提交代码,讲解代码库使用 +4. 第3-3节,硬编码方式讲解 Ai Agent 构建,为后续拆分做准备 +5. 第3-4节,引入扳手工程,规则模型,整体设计Agent预热装配 +6. 第3-5节,规则节点,RootNode 异步加载数据 +7. 第3-6节,规则节点,AiClientToolMcpNode 工具MCP服务构建 +8. 第3-7节,规则节点,AiClientAdvisorNode 顾问角色服务构建 +9. 第3-8节,规则节点,AiClientModelNode 模型构建 bean 对象 +10. 第3-9节,规则节点,AiClientNode 客户端构建 +11. 第3-10节,Agent 服务预热和对话接口封装,使用验证 +12. 第3-11节,知识库接口封装和使用 +13. 第3-12节,智能体动态任务构建 +14. 第3-13节,Admin 管理端 API 接口讲解(CRUD) +15. 第3-14节,Ai Agent 对话与 UI 页面对接 +16. 第3-15节,构建镜像,上线云服务器 +17. 第3-16节,Agent 场景玩法分享 +18. ... 更多内容,随着课程开始逐步更新。 + +课程详细介绍:[https://mp.weixin.qq.com/s/j_G32TDfM_l-S76Wo0zPXw](https://mp.weixin.qq.com/s/j_G32TDfM_l-S76Wo0zPXw) + diff --git a/docs/md/project/ai-knowledge/ext/ai-agent-notes.md b/docs/md/project/ai-knowledge/ext/ai-agent-notes.md new file mode 100644 index 000000000..970b543dc --- /dev/null +++ b/docs/md/project/ai-knowledge/ext/ai-agent-notes.md @@ -0,0 +1,84 @@ +--- +title: Ai Agent 新项目,你要的简历模板来啦! +lock: no +--- + +# Ai Agent 新项目,你要的简历模板来啦! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +**简历怎么写?简历怎么写?简历怎么写?** 这群死鬼,一直催小傅哥,想让小傅哥把饭🍚喂嘴里。没办法,兄弟们着急秋招写简历了,让自己写总是感觉慌,不知道从哪下手。好啦,它来了,它来了,行了吧! + +
+ +
+ +**你就说吧,各个大厂都在做,它能不重要?** + +Dify、Coze、Claude,京东还开源了 JoyAgent,市面上互联网大厂做的 Ai Agent 产品可以说是如雨后春笋一般,越来越多了。Ai Agent 也成了互联网标配的业务场景,为各个应用业务提效,所以结于业务场景来看,Ai Agent 是有战略意义的。 + +所以,你想面试互联网类公司,在简历上多一笔关于 Ai 类的场景实现,总是能匹配到公司里更多的部门岗位。尤其是具备一些 Ai Agent 开发能力的,在现在看来,可以说是非常亮眼的存在。就趁现在吧,该让自己的简历增强下啦!🌶 + +>接下来,我会站在一个求职者的角度进行项目介绍和简历内容展示。可以作为你的参考。 + +## 一、运行效果 + +先看一眼系统架构和运行效果,之后我们对项目进行介绍和简历编写。—— 面试时,可能也会有面试官看你的项目运行效果,你可以把项目上线,也可以写一个技术博客文章,来介绍你做的项目。 + +
+ +
+ +
+ +
+ +
+ +
+ +- 更多可查看,[关于 Ai Agent 项目介绍](https://mp.weixin.qq.com/s/S3UJY0aWbulQ2OZH9XVYmw) + +## 二、项目介绍 + +面试官您好,本套 Ai Agent 综合智能体项目,主要为业务应用系统提效而构建,包括;需求文档分析、代码评审(可结合 openai 代码自动评审)、文档资料编写(+消息通知)、ELK 日志检索 + 普罗米修斯监控的智能 Ai Agent 分析等功能。 + +整套项目,抽象设计拆分了 Ai Agent 执行过程所需的各项组件(Advisor、Prompt、MCP)能力到数据库表中,使其具备自由配置编排组装的特性。以此方式可结合应用中实际场景诉求,编排类似 Diff 和智能分析 Coze 能力,达到需要什么场景就配置什么场景的 Ai Auto Agent。 + +该项目,在架构设计上使用了 DDD 分层架构进行设计,运用了组合模式的规则引擎构建执行链路,并结合工厂、策略、责任链等方式来处理具体流程细节(多种组合方式的Ai Agent执行过程),以此解耦系统功能的实现。这样就可以更加灵活方便的迭代各类扩展性诉求。 + +## 三、简历模板 + +**注意**:🙅🏻‍♀️不要直接复制粘贴简历模板内容,以此结构和描述方式,可以用你的个人第1学习视角来描述。包括;学习过程中的积累、检索的同类资料,以及对课程的扩展等多方面内容来编写简历。以下简历涵盖了课程 1~3 阶段内容; + +- 项目名称:`Ai Agent 综合应用提效智能体`/`Ai Agent 智能巡检系统`/`Ai Agent 可编排服务系统` - 基于你的实际场景/目的,修改项目名称 +- 项目架构:微服务架构、DDD 领域驱动四色模型、前后端分离设计、Agent 设计模式 +- 核心技术:Spring AI(RAG、MCP、Advisor)、SpringBoot、MyBatis、MySQL、PGVector、Redis、React、flowgram.ai、Nginx、Docker +- 项目描述:本项目是一套面向业务应用系统提效的综合智能体(Ai Agent)解决方案,支持将执行过程中的各项能力(如Advisor、Prompt、MCP)抽象并存储于数据库,实现自由配置和灵活编排。用户可根据实际业务场景,动态组合和调整智能分析、代码评审、日志检索等功能模块,打造定制化的Ai Auto Agent,从而显著提升开发设计、编码、运维效率。 +- 核心职责: + - 以产品(PRD)服务诉求和多方面调研评审,设计出具有可编排能力的 Ai Agent 服务架构。并以 DDD 领域驱动建模,构建系统架构。 + - 拆解 Ai Agent 执行过程所需的能力组件,包括;Advisor 顾问角色记忆上下文和访问RAG知识库、Tool(Function Call、MCP)调用服务端(推文、通知、ELK、普罗米修斯监控等)、Prompt(提示词)、Model(对话模型)、Api(使用 one-api/自研sdk组件,统一转换其他各个模型为 openai 格式) + - 设计通用对话分析模型,完成 Ai Agent 执行过程中所需的,问题分析、自主规划、精准执行、内容判罚(循环执行),直至输出最终结果。—— Ai Agent 可对不同步骤配置不同的 Model + MCP + Prompt 能力。并对执行过程中,通过 Advisor 顾问角色访问知识库和存储上下文数据。 + - 实现 MCP 服务能力,以 stdio/sse 方式,开发,公众号通知 MCP、推文 MCP(可以是内部的文档化服务)、ELK-MCP、普罗米修斯-MCP等。以及使用 MCP 服务平台,检索公用能力 https://sai.baidu.com/zh/(本地文件、Github、搜索引擎),统一配置使用。—— 数据库设计了多类型 MCP 服务的配置操作。 + - 设计通用 MCP Nginx Token 校验能力(也可以设计 MCP-GateWay),以配置化方式进行鉴权使用。增强 MCP 调用过程中,数据传输安全性。 + - 基于 Spring TaskScheduler 扩展实现,智能体任务调度服务,可自动化完成日常系统巡检(客诉、报警)产生 html 格式报告文档。也可以基于报警监听消息,触发巡检动作(公司内,报警信息有 MQ 消息)。 + - 提供 RAG 知识库能力,可自主上传文件 + 解析工程代码库,并对知识库设有标签为 Ai Agent Advisor 访问 RAG 提供数据使用能力,增强准确性。—— 解析的代码库,可以为 openai 代码自动评审,增强评审能力。 + - 设计一键 Ai Agent 预热能力,动态化注入 Spring 容器。支持运营配置服务,随时调整、变更、上线,方便运营配置和使用。 + - 基于 Racet + flowgram.ai 框架,为 Ai Agent 服务提供拖拉拽编排能力,增强运营使用体验。 + +> 此套 Ai Agent 以为企业/平台/系统,上线3个月以来,主动巡检解决数十次系统隐患问题和运营配置错误情况,以及撰写了上万篇有效文档 + 提炼技术关键信息对新人辅导。后续还会继续配置更多方面的 Ai Agent 服务能力,为企业提效。 + +## 四、课程目录 + +整个课程分3个阶段讲解,包括;RAG、MCP,之后进入 Agent 阶段的学习。前面打好基础,后面进入应用。哪怕是小白,也可以跟着一起实战起来,而且每个阶段都有部署运行效果,越学越爽。 + +项目地址:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) + +
+ +
\ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-4/\347\254\2544\350\212\202\357\274\232\351\241\271\347\233\256\344\270\212\347\272\277.md" b/docs/md/project/ai-knowledge/none.md similarity index 79% rename from "docs/md/project/s-pay-mall/part-4/\347\254\2544\350\212\202\357\274\232\351\241\271\347\233\256\344\270\212\347\272\277.md" rename to docs/md/project/ai-knowledge/none.md index 5fd539db5..f64218b2f 100644 --- "a/docs/md/project/s-pay-mall/part-4/\347\254\2544\350\212\202\357\274\232\351\241\271\347\233\256\344\270\212\347\272\277.md" +++ b/docs/md/project/ai-knowledge/none.md @@ -1,9 +1,9 @@ --- -title: 第4节:项目上线 +title: 新章节,编写中 lock: no --- -# 第4节:项目上线 +# 新章节,编写中 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) diff --git a/docs/md/project/ai-knowledge/notes.md b/docs/md/project/ai-knowledge/notes.md new file mode 100644 index 000000000..a85043fcf --- /dev/null +++ b/docs/md/project/ai-knowledge/notes.md @@ -0,0 +1,133 @@ +--- +title: 面试:技能、简历、问题汇总 +lock: no +--- + +# 《Ai Agent》,关于面试中的技能、简历、问题汇总 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +此部分主要用于向读者提供星球项目之一的《Ai Agent》项目如何体现到简历中,包括;专业技能、项目经验。 + +## 一、项目介绍 + +面试官您好,本套 Ai Agent 综合智能体项目,主要为业务应用系统提效而构建,包括;需求文档分析、代码评审(可结合 openai 代码自动评审)、文档资料编写(+消息通知)、ELK 日志检索 + 普罗米修斯监控的智能 Ai Agent 分析等功能。 + +整套项目,抽象设计拆分了 Ai Agent 执行过程所需的各项组件(Advisor、Prompt、MCP)能力到数据库表中,使其具备自由配置编排组装的特性。以此方式可结合应用中实际场景诉求,编排类似 Diff 和智能分析 Coze 能力,达到需要什么场景就配置什么场景的 Ai Auto Agent。 + +该项目,在架构设计上使用了 DDD 分层架构进行设计,运用了组合模式的规则引擎构建执行链路,并结合工厂、策略、责任链等方式来处理具体流程细节(多种组合方式的Ai Agent执行过程),以此解耦系统功能的实现。这样就可以更加灵活方便的迭代各类扩展性诉求。 + +## 二、简历模板 + +**注意**:🙅🏻‍♀️不要直接复制粘贴简历模板内容,以此结构和描述方式,可以用你的个人第1学习视角来描述。包括;学习过程中的积累、检索的同类资料,以及对课程的扩展等多方面内容来编写简历。以下简历涵盖了课程 1~3 阶段内容; + +- 项目名称:`Ai Agent 综合应用提效智能体`/`Ai Agent 智能巡检系统`/`Ai Agent 可编排服务系统` - 基于你的实际场景/目的,修改项目名称 +- 项目架构:微服务架构、DDD 领域驱动四色模型、前后端分离设计、Agent 设计模式 +- 核心技术:Spring AI(RAG、MCP、Advisor)、SpringBoot、MyBatis、MySQL、PGVector、Redis、React、flowgram.ai、Nginx、Docker +- 项目描述:本项目是一套面向业务应用系统提效的综合智能体(Ai Agent)解决方案,支持将执行过程中的各项能力(如Advisor、Prompt、MCP)抽象并存储于数据库,实现自由配置和灵活编排。用户可根据实际业务场景,动态组合和调整智能分析、代码评审、日志检索等功能模块,打造定制化的Ai Auto Agent,从而显著提升开发设计、编码、运维效率。 +- 核心职责: + - 以产品(PRD)服务诉求和多方面调研评审,设计出具有可编排能力的 Ai Agent 服务架构。并以 DDD 领域驱动建模,构建系统架构。 + - 拆解 Ai Agent 执行过程所需的能力组件,包括;Advisor 顾问角色记忆上下文和访问RAG知识库、Tool(Function Call、MCP)调用服务端(推文、通知、ELK、普罗米修斯监控等)、Prompt(提示词)、Model(对话模型)、Api(使用 one-api/自研sdk组件,统一转换其他各个模型为 openai 格式) + - 设计通用对话分析模型,完成 Ai Agent 执行过程中所需的,问题分析、自主规划、精准执行、内容判罚(循环执行),直至输出最终结果。—— Ai Agent 可对不同步骤配置不同的 Model + MCP + Prompt 能力。并对执行过程中,通过 Advisor 顾问角色访问知识库和存储上下文数据。 + - 实现 MCP 服务能力,以 stdio/sse 方式,开发,公众号通知 MCP、推文 MCP(可以是内部的文档化服务)、ELK-MCP、普罗米修斯-MCP等。以及使用 MCP 服务平台,检索公用能力 https://sai.baidu.com/zh/(本地文件、Github、搜索引擎),统一配置使用。—— 数据库设计了多类型 MCP 服务的配置操作。 + - 设计通用 MCP Nginx Token 校验能力(也可以设计 MCP-GateWay),以配置化方式进行鉴权使用。增强 MCP 调用过程中,数据传输安全性。 + - 基于 Spring TaskScheduler 扩展实现,智能体任务调度服务,可自动化完成日常系统巡检(客诉、报警)产生 html 格式报告文档。也可以基于报警监听消息,触发巡检动作(公司内,报警信息有 MQ 消息)。 + - 提供 RAG 知识库能力,可自主上传文件 + 解析工程代码库,并对知识库设有标签为 Ai Agent Advisor 访问 RAG 提供数据使用能力,增强准确性。—— 解析的代码库,可以为 openai 代码自动评审,增强评审能力。 + - 设计一键 Ai Agent 预热能力,动态化注入 Spring 容器。支持运营配置服务,随时调整、变更、上线,方便运营配置和使用。 + - 基于 React + flowgram.ai 框架,为 Ai Agent 服务提供拖拉拽编排能力,增强运营使用体验。 + +> 此套 Ai Agent 以为企业/平台/系统,上线3个月以来,主动巡检解决数十次系统隐患问题和运营配置错误情况,以及撰写了上万篇有效文档 + 提炼技术关键信息对新人辅导。后续还会继续配置更多方面的 Ai Agent 服务能力,为企业提效。 + +## 三、面试问题 + +### 1. 你们项目采用了DDD领域驱动设计,能简单介绍一下你们的四色模型是如何划分的? + +**回答**:我们项目严格按照DDD四色模型进行架构设计。首先是**值对象**层,主要包含AiClientVO、AiClientAdvisorVO等核心业务对象,承载业务状态和标识;**值对象(Value Object)**层包含各种配置信息如AiClientSystemPromptVO、AiClientModelVO等,保证数据的不可变性;**领域服务(Domain Service)**层实现了复杂的业务逻辑,如AiClientNode、AiClientAdvisorNode等节点服务,负责AI Agent的组装和编排;**聚合根(Aggregate Root)**则通过ExecuteCommandEntity等实体来管理整个AI Agent的生命周期。这种设计让我们的业务逻辑更加清晰,各层职责分明,便于维护和扩展。 + +### 2. 你们的微服务架构是如何设计的,各个模块之间是如何协作的? + +**回答**:我们采用了标准的DDD分层架构,分为六个核心模块:api层定义对外接口契约,app层作为应用启动入口和配置中心,domain层包含核心业务逻辑和领域模型,trigger层处理HTTP请求和事件触发,infrastructure层负责数据持久化和外部服务调用,types层定义通用类型和枚举。各模块通过依赖注入和事件驱动进行协作,domain层作为核心不依赖任何外部模块,infrastructure层实现domain层定义的接口,trigger层调用domain层的服务。这种设计保证了业务逻辑的纯净性和系统的可测试性。 + +### 3. Agent设计模式在你们项目中是如何体现的? + +**回答**:我们的Agent设计模式主要体现在多层次的智能体架构设计上。首先是**策略模式**的应用,通过IExecuteStrategy接口定义执行策略,AutoAgentExecuteStrategy实现自动执行逻辑;其次是**责任链模式**的核心应用,我们设计了四步执行链:RootNode→Step1AnalyzerNode(任务分析)→Step2PrecisionExecutorNode(精准执行)→Step3QualitySupervisorNode(质量监督)→Step4LogExecutionSummaryNode(执行总结),每个节点继承AbstractExecuteAutoSupport并实现特定的业务逻辑;再次是**工厂模式**,通过DefaultAutoAgentExecuteStrategyFactory创建执行策略处理器,管理DynamicContext动态上下文;最后是**模板方法模式**,AbstractExecuteAutoSupport定义了执行模板,各个Step节点实现具体的doApply方法。这种设计实现了"问题分析→自主规划→精准执行→质量监督"的完整AI Agent执行循环,每个步骤都可以独立配置不同的ChatClient、Prompt和Advisor,真正实现了智能体的可编排和可扩展。 + +### 4. Spring AI中的Advisor顾问角色是如何设计和实现的? + +**回答**:Advisor顾问角色是我们AI Agent的核心能力之一,主要负责上下文记忆和知识库访问。我们实现了两种主要的Advisor:PromptChatMemory用于维护对话历史,通过maxMessages参数控制记忆长度;RagAnswerAdvisor用于访问向量知识库,通过topK和filterExpression参数控制检索精度。在实现上,我们继承了Spring AI的BaseAdvisor,重写了aroundCall方法来拦截对话请求,在请求前注入相关上下文信息,在响应后更新记忆状态。这种设计让AI Agent具备了持续学习和知识积累的能力,大大提升了对话的准确性和连贯性。 + +### 5. RAG知识库的分词和向量化是如何设计的? + +**回答**:我们的RAG知识库基于PGVector实现,使用OpenAI的Embedding模型进行向量化。在分词策略上,我们使用TokenTextSplitter按照token数量进行智能分割,既保证了语义的完整性又控制了向量的维度。向量存储采用1536维的向量空间,支持余弦相似度检索。在数据预处理阶段,我们会对上传的文档进行清洗和标准化,提取关键信息并添加元数据标签,这些标签可以用于后续的过滤检索。检索时通过SearchRequest配置topK参数控制返回结果数量,通过filterExpression进行精确过滤,确保检索结果的相关性和准确性。 + +### 6. MCP协议的设计理念和实现方式是什么? + +**回答**:MCP(Model Context Protocol)是我们实现工具调用的核心协议,它定义了AI模型与外部工具之间的标准化通信接口。我们支持两种通信方式:stdio模式适用于本地工具调用,通过标准输入输出进行通信;sse模式适用于远程服务调用,通过Server-Sent Events实现实时通信。在实现上,我们为每个MCP服务定义了标准的Function接口,使用@Tool注解标记可调用的方法,通过MethodToolCallbackProvider将Java方法暴露为MCP工具。比如微信通知MCP通过WeiXinNoticeService提供消息推送能力,CSDN发帖MCP提供自动发布文章的能力。这种设计让AI Agent能够调用各种外部服务,大大扩展了智能体的能力边界。 + +### 7. 你们是如何实现AI Agent的动态编排和热部署的? + +**回答**:我们通过Spring的动态Bean注册机制实现了AI Agent的热部署能力。核心思路是将AI Agent的各个组件(Model、Prompt、Advisor、MCP)抽象为可配置的Bean,存储在数据库中。当配置发生变化时,通过ArmoryCommandEntity触发重新装配流程,使用DefaultArmoryStrategyFactory的策略模式动态创建新的组件实例,然后通过registerBean方法将新组件注册到Spring容器中。整个过程采用责任链模式,依次执行AiClientApiNode、AiClientModelNode、AiClientAdvisorNode、AiClientNode等节点,确保组件的正确装配顺序。这种设计让我们能够在不重启服务的情况下,动态调整AI Agent的能力配置,大大提升了系统的灵活性和运维效率。 + +### 8. 智能体任务调度服务是如何设计的,如何实现自动化巡检? + +**回答**:我们基于Spring TaskScheduler扩展实现了智能体任务调度服务,支持定时和事件驱动两种触发方式。定时巡检通过Cron表达式配置执行周期,自动收集系统指标、日志信息、告警数据等,然后调用专门的巡检Agent进行智能分析,最终生成HTML格式的巡检报告。事件驱动巡检则监听MQ消息,当收到告警信息时立即触发相应的巡检动作。在实现上,我们为每种巡检场景配置了专门的Agent,比如性能巡检Agent配置了Prometheus MCP工具,日志巡检Agent配置了ELK MCP工具。巡检结果会通过微信公众号MCP自动推送给相关人员,实现了从发现问题到通知处理的全自动化流程。 + +### 9. 你们的MCP服务是如何保证安全性的? + +**回答**:我们设计了通用的MCP Nginx Token校验机制来保证数据传输安全性。首先在Nginx层配置了统一的鉴权模块,所有MCP请求都需要携带有效的Token才能通过;Token采用JWT格式,包含用户身份、权限范围、过期时间等信息;在应用层,我们为每个MCP服务配置了独立的访问密钥,支持定期轮换;对于敏感操作如数据库访问、文件操作等,还增加了二次验证机制。此外,我们还实现了请求频率限制、IP白名单、操作审计日志等安全措施。在数据传输过程中,所有敏感信息都进行了加密处理,确保即使在网络传输过程中被截获也无法直接使用。 + +### 10. 前端的拖拽编排功能是如何实现的? + +**回答**:我们基于React和flowgram.ai框架实现了AI Agent的可视化编排功能。前端采用节点式的流程图设计,每个节点代表一个AI Agent组件,用户可以通过拖拽的方式组合不同的Model、Prompt、Advisor、MCP组件。在技术实现上,我们使用React Flow作为基础图形引擎,自定义了各种组件节点的渲染逻辑;通过Context API管理全局状态,实时同步编排配置;使用WebSocket与后端保持连接,支持实时预览和调试。当用户完成编排后,前端会将配置信息序列化为JSON格式发送给后端,后端解析配置并动态创建对应的AI Agent实例。这种设计让非技术人员也能够轻松配置和使用AI Agent,大大降低了使用门槛。 + +### 11. 在实现多模型适配时遇到了什么挑战,是如何解决的? + +**回答**:最大的挑战是不同AI模型的API格式和调用方式差异很大,直接适配会导致代码耦合度过高。我们的解决方案是引入one-api服务作为统一的模型网关,将所有第三方模型的API统一转换为OpenAI格式。在系统内部,我们只需要适配OpenAI的接口规范,通过配置不同的baseUrl和apiKey就能接入各种模型。同时我们还自研了SDK组件,封装了模型调用的通用逻辑,包括重试机制、超时处理、错误码转换等。这种设计不仅简化了开发复杂度,还提升了系统的稳定性和可扩展性,当需要接入新模型时只需要在one-api层配置即可。 + +### 12. 大规模并发场景下,AI Agent的性能是如何保证的? + +**回答**:我们从多个维度进行了性能优化。首先是连接池管理,为每个模型API配置了独立的连接池,避免相互影响;其次是异步处理,所有AI调用都采用异步方式,通过ResponseBodyEmitter实现流式响应,用户可以实时看到AI的思考过程;然后是缓存策略,对于相同的问题我们会缓存AI的回答,减少重复计算;在资源调度上,我们使用自定义的线程池进行任务分发,根据任务类型和优先级进行智能调度。此外,我们还实现了熔断降级机制,当某个模型服务不可用时自动切换到备用模型,保证服务的高可用性。通过这些优化,我们的系统能够支持数千并发用户同时使用。 + +### 13. 如何保证AI Agent执行过程中的数据一致性? + +**回答**:我们采用了事件驱动架构来保证数据一致性。每个AI Agent的执行过程被拆分为多个步骤,每个步骤完成后都会发布相应的事件,下一个步骤监听事件后开始执行。在数据库层面,我们使用了分布式事务来保证跨服务的数据一致性,关键操作都包装在事务中执行。对于长时间运行的AI任务,我们实现了断点续传机制,将执行状态持久化到数据库,即使服务重启也能从断点继续执行。同时我们还建立了完善的监控和告警机制,实时监控AI Agent的执行状态,一旦发现异常立即进行人工干预。这种设计确保了即使在复杂的业务场景下,数据的一致性和完整性也能得到保证。 + +### 14. 这个AI Agent系统给公司带来了什么实际价值? + +**回答**:我们的AI Agent系统在多个方面为公司创造了显著价值。在开发效率方面,代码评审Agent将人工评审时间从平均2小时缩短到15分钟,准确率达到95%以上;在运维效率方面,智能巡检Agent实现了7×24小时自动监控,故障发现时间从小时级缩短到分钟级,运维人员的重复性工作减少了80%;在内容创作方面,文章生成Agent帮助技术团队每月自动产出50+篇高质量技术文章,大大提升了公司的技术影响力。更重要的是,这套系统的可编排特性让我们能够快速响应新的业务需求,从需求提出到Agent上线的周期从原来的2周缩短到2天,大大提升了业务响应速度。 + +### 15. 在项目推广过程中遇到了什么阻力,是如何解决的? + +**回答**:最大的阻力来自于用户对AI准确性的担忧和使用习惯的改变。为了解决这个问题,我们采用了渐进式推广策略。首先选择了代码评审这个相对低风险的场景进行试点,通过大量的测试数据证明AI的准确性;然后我们设计了人机协作的工作模式,AI负责初步分析,人工负责最终决策,让用户逐步建立信任;在用户体验方面,我们提供了详细的操作文档和培训视频,还建立了用户反馈机制,根据用户建议持续优化产品功能。经过3个月的推广,用户接受度从最初的30%提升到了85%,现在已经成为团队日常工作的重要工具。 + +### 16. 未来你们计划如何进一步优化和扩展这个系统? + +**回答**:我们有几个重要的优化方向。首先是增强AI Agent的自主学习能力,通过强化学习让Agent能够从历史执行结果中学习,不断优化自己的决策策略;其次是扩展更多的业务场景,比如客服机器人、数据分析助手、项目管理助手等;在技术架构方面,我们计划引入更先进的向量数据库和图数据库,提升知识检索的准确性和效率;在用户体验方面,我们正在开发移动端应用,让用户能够随时随地使用AI Agent服务。同时我们也在探索多模态AI的应用,让Agent能够处理图片、音频、视频等多种类型的数据,进一步扩展应用场景。预计在未来一年内,我们的AI Agent系统将覆盖公司80%以上的业务流程。 + +### 17. 在设计通用对话分析模型时,你们是如何处理问题分析、自主规划、精准执行这个循环的? + +**回答**:我们设计了一个四阶段的执行循环:问题分析、自主规划、精准执行、内容判罚。在问题分析阶段,AI Agent首先理解用户意图,提取关键信息和上下文;自主规划阶段,Agent根据可用的工具和知识库制定执行计划,选择最优的执行路径;精准执行阶段,按照计划调用相应的MCP工具和Advisor,获取执行结果;内容判罚阶段,Agent评估执行结果是否满足用户需求,如果不满足则重新进入规划阶段。整个过程中,我们为每个阶段配置了不同的Model、MCP、Prompt组合,比如规划阶段使用逻辑推理能力强的模型,执行阶段使用工具调用能力强的模型。这种设计让AI Agent具备了类似人类的思考和执行能力。 + +### 18. 你们的向量数据库检索性能是如何优化的? + +**回答**:我们从多个层面优化了向量检索性能。在索引层面,PGVector使用了HNSW(Hierarchical Navigable Small World)算法构建高效的向量索引,支持近似最近邻搜索;在查询优化方面,我们实现了查询缓存机制,对于相似的查询直接返回缓存结果;在数据分片方面,我们按照业务领域对向量数据进行分片存储,减少检索范围;在并发控制方面,我们使用了连接池和异步查询,提升并发处理能力。此外,我们还实现了智能的预加载机制,根据用户的历史查询模式预先加载可能需要的向量数据到内存中。通过这些优化,我们的向量检索响应时间从原来的500ms优化到了50ms以内,同时支持千级并发查询。 + +### 19. 在实现MCP服务的过程中,stdio和sse两种模式各有什么优缺点? + +**回答**:stdio模式的优点是实现简单,适合本地工具调用,通信开销小,调试方便;缺点是只能用于本地服务,不支持远程调用,扩展性有限。sse模式的优点是支持远程调用,可以跨网络部署,支持实时双向通信,扩展性强;缺点是实现复杂度高,需要处理网络异常和重连机制,通信开销相对较大。在实际应用中,我们根据具体场景选择合适的模式:对于文件系统操作、本地命令执行等场景使用stdio模式;对于微信通知、CSDN发帖、远程API调用等场景使用sse模式。为了统一开发体验,我们封装了通用的MCP客户端,屏蔽了底层通信细节,开发者只需要关注业务逻辑即可。 + +### 20. 你们是如何保证AI Agent在复杂业务场景下的稳定性的? + +**回答**:我们建立了多层次的稳定性保障机制。在架构层面,采用微服务设计,单个服务的故障不会影响整个系统;在服务层面,实现了熔断降级机制,当某个依赖服务不可用时自动切换到备用方案;在数据层面,建立了完善的备份和恢复机制,关键数据都有多副本保护;在监控层面,实现了全链路监控,从请求接入到响应输出的每个环节都有详细的监控指标;在异常处理方面,我们为每种可能的异常场景都设计了对应的处理策略,包括重试、降级、人工介入等。此外,我们还建立了完善的测试体系,包括单元测试、集成测试、压力测试、混沌工程测试等,确保系统在各种极端情况下都能稳定运行。通过这些措施,我们的系统可用性达到了99.9%以上。 + +> 随着课程进展和大家面试遇到的问题,持续更新这部分内容。 + +### 21. AI Agent采用的是什么agent设计模式。以autoagent那套执行链路来说 + +链接:[https://t.zsxq.com/pqrtB](https://t.zsxq.com/pqrtB) + +课程里视频也讲到的,链路的执行分为4类,有固定模式,规划模式,步骤模型等。通过为 ai agent 配置可执行客户端链路,动态规划、执行步骤、审查结果(循环验证)、总结输出来完成。在整个执行过程中,使用到了,提示词prompt、顾问角色访问知识库和记忆上下文、mcp 工具调用等,来完成整个请求会话。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/promotion/AI MCP \345\206\215\350\277\231\344\271\210\347\224\250\344\270\213\345\216\273\357\274\214\345\217\257\345\260\261\350\246\201\342\200\235\345\210\233\344\270\232\342\200\234\345\217\230\347\216\260\344\272\206\345\221\200\357\274\201.md" "b/docs/md/project/ai-knowledge/promotion/AI MCP \345\206\215\350\277\231\344\271\210\347\224\250\344\270\213\345\216\273\357\274\214\345\217\257\345\260\261\350\246\201\342\200\235\345\210\233\344\270\232\342\200\234\345\217\230\347\216\260\344\272\206\345\221\200\357\274\201.md" new file mode 100644 index 000000000..13aa0851b --- /dev/null +++ "b/docs/md/project/ai-knowledge/promotion/AI MCP \345\206\215\350\277\231\344\271\210\347\224\250\344\270\213\345\216\273\357\274\214\345\217\257\345\260\261\350\246\201\342\200\235\345\210\233\344\270\232\342\200\234\345\217\230\347\216\260\344\272\206\345\221\200\357\274\201.md" @@ -0,0 +1,111 @@ +--- +title: AI MCP 再继续这么用,可就要”创业“变现了呀! +lock: no +--- + +# AI MCP 再继续这么用,可就要”创业“变现了呀! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在 [AI MCP 24小时为我”打工“](https://mp.weixin.qq.com/s/sB4EaP6HMtj3VxK-VMD8nQ),两周时间。已产生 `251篇文章`,带来`10万+阅读量`,`涨粉近1000人`!在这么搞下去,不得变现了哇! + +
+ +
+ +嘿嘿,不过这点点成绩根本挡不住我前进的脚步👣! + +AI MCP 的能力远不止于次,或者更准确的说是 AI Agent 的能力,还有非常多的场景可以运用,开玩笑讲,他会让 Java 再次伟大!这也是为什么 Spring AI 那么快速的迭代自己的框架设计,甚至不惜每次迭代还要推翻之前的结构模型,也要更好的支持未来 AI 工程的开发实现。 + +在有了 AI Agent 后,所有的 tob/toc 服务项目,都应该会变得更加智能,这会包括我们现在使用的各项软件,如;电商、出行、外卖等,也包括研发人员使用的各类技术软件。如果大公司还是牛马般的靠体力卷工时,甚至可能会被小公司的不断创新所掀翻。 + +好啦,那么这篇文章小傅哥会给大家介绍下 AI Agent 以及可运用的场景,帮助大家打开思路! + +>文末提供了 AI RAG&MCP 实战编程项目,可以快速掌握 Spring AI 应用开发能力! + +## 一、什么是 AI Agent + +AI Agent 是整合多种技术手段的智能实体,其实现依赖于 Tools、MCP、Memory、RAG(Retrieval 增强检索生成) 等技术组件。但不是非得依赖全部组件才叫 AI Agent。 + +
+ +
+ +AI Agents 是**系统** ,它通过赋予 **大型语言模型(LLMs)** **访问工具** 和**知识** 来扩展其能力,从而使 **LLMs** 能够**执行操作** 。 + +- **系统** :将 Agents 视为一个由许多组件组成的系统,而不仅仅是单个组件,这一点很重要。在基本层面上,AI Agent 的组件包括: + - **环境** - AI Agent 运行的定义空间。例如,如果我们有一个旅行预订 AI Agent,则环境可以是 AI Agent 用来完成任务的旅行预订系统。 + - **传感器** - 环境具有信息并提供反馈。AI Agents 使用传感器来收集和解释有关环境当前状态的信息。在旅行预订 Agent 示例中,旅行预订系统可以提供诸如酒店可用性或航班价格之类的信息。 + - **执行器** - 一旦 AI Agent 接收到环境的当前状态,对于当前任务,Agent 会确定要执行的操作以更改环境。对于旅行预订 Agent,它可能是为用户预订可用房间。 +- **大型语言模型** - Agents 的概念在 LLMs 创建之前就已存在。使用 LLMs 构建 AI Agents 的优势在于它们能够解释人类语言和数据。这种能力使 LLMs 能够解释环境信息并制定改变环境的计划。 +- **执行操作** - 在 AI Agent 系统之外,LLMs 仅限于根据用户提示生成内容或信息的情况。在 AI Agent 系统内部,LLMs 可以通过解释用户请求并使用其环境中可用的工具来完成任务。 +- **访问工具** - LLM 可以访问哪些工具由 1) 它运行的环境和 2) AI Agent 的开发者定义。对于我们的旅行 Agent 示例,Agent 的工具受预订系统中可用操作的限制,开发者可以将 Agent 的工具访问权限限制为航班。 +- **知识** - 除了环境提供的信息外,AI Agents 还可以从其他系统、服务、工具甚至其他 Agents 中检索知识。在旅行 Agent 示例中,此知识可以是位于客户数据库中的用户旅行偏好信息。 + +我们可以以一个人,作为视角来理解 AI Agent,Memory 记忆是人的大脑,Tools 是人的身体和四肢,Rag 知识库是过往的经验储备,MCP 是我们与外部的连接调用。而整个人就是这个智能体 AI Agent。 + +## 二、AI 智能体的工作原理 + +每个智能体都定义了角色、个性和沟通风格,包括具体指令和可用工具的说明。 + +
+ +
+ +- **角色**:角色是智能体的核心特征,定义了其性格和行为方式。一个定义良好的角色可以帮助智能体在与环境和用户互动时保持一致性。随着时间的推移,智能体会通过经验积累和环境互动不断发展和完善其角色。 +- **记忆**:智能体的记忆系统由短期记忆、长期记忆、共识记忆和情景记忆组成。短期记忆用于处理即时互动,长期记忆存储历史数据和对话,情景记忆记录过去的互动细节,而共识记忆则用于在智能体之间共享信息。通过这些记忆系统,智能体能够回忆过去的互动,适应新情况,保持上下文一致性,并从经验中学习以提高性能。 +- **工具**:工具是智能体用来与环境互动并增强其功能的资源。它们可以是函数或外部资源,帮助智能体访问信息、处理数据或控制外部系统以执行复杂任务。工具根据其界面类型进行分类,包括物理界面、图形界面和基于程序的界面。通过工具学习,智能体能够理解工具的功能及其应用场景,从而有效地使用这些工具。 +- **模型**:大语言模型 (LLM) 是构建 AI 智能体的基础,赋予智能体理解、推理和行动的能力。LLM 作为智能体的“大脑”,使其能够处理和生成语言,而其他组件则支持智能体的推理和行动能力。 + +> https://github.com/google/A2A 多个 Agent 间,可以使用 A2A 协议,完成 Agent 和 Agent 对接。 + +## 三、AI Agent 场景应用 + +### 1. BCP 智能巡检 + +
+ +
+ +- 场景:在日常的互联网toc场景的系统中,每天都会有不同程度的客诉,这些客诉问题需要进行大量的系统排查。 +- 方案:将企业内的各项系统服务,开发出 MCP 服务接口(APIs),并为每个核心业务流程提供排查链路计划。在发生系统报警时,以报警为触达手段,排查系统日志、账户、Redis、Dev-Ops 服务等,给给出综合的解决方案。 +- 其他:不同配置的 Agent 是可以连接通信的,一个 Agent 就是一个配置出来的 ChatClient 对话体。 + +### 2. 工具AI化设计 + +
+ +
+ +- 场景:其实现在除了编程方面,其他很多软件并没有那么快速的接入 AI Agent。如 trae.ai\cursor 都是编程的利器,可以更快速的迭代开发代码。那么同样的 SSH 链接云服务器的工具,也可以通过 AI Agent 进行扩展,提高我们的操作服务器部署软件的效率。 +- 方案:设计 Linux SSH MCP Server 服务,同时提供 SFTP 以及云服务器的对接。再加上 Linux RAG 知识库。这样我们就可以以对话和编码的方式操作服务器。如,部署 JDK,安装 NodeJS,执行系统镜像的构建、推送、拉取、部署等操作。 + +### 3. toc场景AI化 + +
+ +
+ +- 场景:目前的大部分购物操作,都是人工的方式自己在平台检索,之后对于不懂的在进行客服提问,最后去下单。那么这里也可以加入 AI 操作,自主的完成购物、下单,以及将来退货的操作。 +- 方案:为产品提供购物话术 RAG 增强检索能力,以及提供货物、下单、结算、物流的 MCP 服务。用户和 AI 对话过程中,完成货品的组装选择和下单。聊聊天就把东西买好了,还能给提供产品的使用和维护。 + +### 4. AI Agent 编排 + +
+ +
+ +- 当我们有大量的 MCP 服务实现、RAG 知识库沉淀后,会催生出 AI Agent 的编排能力实现。你可以按需组装一套自己的对话 AI Agent。 +- 类似的场景实现:[https://github.com/n8n-io/n8n](https://github.com/n8n-io/n8n) - 付费的。不过很多企业会借助之前的 BPMN 实现的低代码,扩展出 AI Agent 编排实现。 + +```java +docker volume create n8n_data +docker run -it --rm --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n registry.cn-hangzhou.aliyuncs.com/xfg-studio/n8n:1.88.0 +``` + diff --git "a/docs/md/project/ai-knowledge/promotion/AI MCP \345\267\262\347\273\217\345\270\256\346\210\221\342\200\234\345\271\262\346\264\273\342\200\235\344\272\206\357\274\201.md" "b/docs/md/project/ai-knowledge/promotion/AI MCP \345\267\262\347\273\217\345\270\256\346\210\221\342\200\234\345\271\262\346\264\273\342\200\235\344\272\206\357\274\201.md" new file mode 100644 index 000000000..88403fbe1 --- /dev/null +++ "b/docs/md/project/ai-knowledge/promotion/AI MCP \345\267\262\347\273\217\345\270\256\346\210\221\342\200\234\345\271\262\346\264\273\342\200\235\344\272\206\357\274\201.md" @@ -0,0 +1,119 @@ +--- +title: AI MCP 已经一天24小时,给我“打工”了! +lock: no +--- + +# AI MCP 已经一天24小时,给我“打工”了! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +一天24篇推文,500+收藏,2.6万+阅读量,我已经让 AI 帮我干活了!这是小傅哥最新实现的一套 `mcp-server-csdn`,完全不需要我上手,就可以定时的执行文章编写和发表。 + +
+ +
+ +
+ +
+ +只要你配置好对应的话题,AI MCP 就会自动创作文章和发表。虽然单篇流量不一定都高,但架不住我根本没出手呀,走的就是一个量大取胜!**这不是自动发帖,这是自动创业呀😂!简直美滋滋!** + +
+ +
+ +MCP 模型上下文协议,核心的作用就在于通过标准的协议设计,让 AI 可以以通用的方式调用各类服务的接口。所以,我们可以通过 MCP 的实现,让 AI 自动化的完成内容的创作和发表。 + +在这样的一个 CSDN 发文章的模型跑通后,我们就可以大批量的复制,完成不同类内容的创作和发表,也可以以这样的方式对接其他各类内容社区平台。甚至你还可以想到,这东西能辅助我们完成很多工作。 + +以前总有人说,AI 来了,可能会让很多程序员失业。但恰恰相反,不仅不会失业,反而 AI 会让程序员如虎添翼,推进改变其他行业的工作模式。毕竟,没有哪个行业不仅能用 AI,还能懂 AI,还能开发 AI 了! + +接下来,小傅哥就给大家,介绍下这套 MCP 的设计和工作模式。 + +> 🧧 文末提供了全套 AI、RAG、MCP 的开发、使用教程以及工程源码。此外还有非常多的互联网大厂项目,都可以一并获取学习。 + +## 一、MCP 的工作模式 + +MCP 服务,可以以工具 Tools 的形式配置到 AI MCP 客户端。当我们向 AI 发送执行指令后,AI 会携带工具 Tools 信息,一起发送给 AI。之后进行语义分析以及调用 AI MCP 执行业务诉求。 + +你可以把 AI MCP 当成你雇来的员工,你有什么想法就告诉他,让他充当那个跑腿和执行的人。而你只负责下达指令和验收结果。 + +
+ +
+ +
+ +
+ +如图,我们可以给程序设定一套话术描述,让它去做指定类型的文章创作和发表。在 AI 完成内容创作后,会调用 MCP 服务,传递接口入参值,再由 MCP 服务,完成文章的发表。 + +如果,我们希望发布的文章具备当前热点。可以增加一个 MCP 服务,这个服务来检索牛客网最新的求职面试信息,再加上各个大厂招聘要求描述信息等。基于这些信息先获取到面试热点话题,在结合话题与设定的面试场景话术一起生成对应的文章。**MCP 就像是你的员工,你可以交代A员工做什么后,交接给B员工继续处理。** + +## 二、MCP 怎么开发的 + +首先,MCP 是一套标准的模型上下文协议,它不限制非得使用那种语言实现。如;NodeJS、Python、Java,都可以实现 MCP 服务。以 Spring AI 框架举例,Java 工程师可以,以非常简单的使用 Java 代码开发普通的业务逻辑,之后配置上 AI MCP 工具类注解和完成 Bean 对象的实例化即可。 + +
+ +
+ +- 如图,正常的搭建 SpringBoot 应用程序,编写对接 CSDN 发帖接口。之后给服务方法配置上 Tool 工具注解。那么它就会被 Spring AI MCP 注册和使用了。 +- 同时,一个工程里可以有很多的这样的服务和工具。比如你要开发一个各大平台集成的发帖/文章的服务,那么也可以增加其他的对接类在同一个工程里。最终配置上 AI MCP 的注册即可。 + +## 三、MCP 怎么对接的 + +把 Java 开发实现的 MCP 服务端,打包成一个 Jar,把这个 Jar 配置到 MCP 客户端工程里。即可完成 MCP 服务的调用。并且一个 MCP 客户端,也可以对接多套 MCP 服务,这些服务可以以 AI 工作流的形式完成自己的工作。 + +
+ +
+ +
+ +
+ +- 如图,在 SpringBoot 工程中,增加MCP 服务的配置对接。这个时候 AI 对话就那可以拿到 MCP 工具进行对话。并将要执行的信息,通过 MCP 服务工具完成处理。 +- 并且,你可以把 MCP 服务,打包构建镜像部署到(服务器/Nas),让它一天24小时的干活。用不了多久,你就成为某个领域内容的专家了! + +## 四、MCP 怎么学习下? + +小傅哥,已经为你准备好了一套 AI RAG、MCP、Function Call 实践编程课程,使用 Java + Spring AI 框架,增强自己的 AI 应用开发能力,迅速囤积编程技能!如下,课程目录,全程文档小册 + 视频带着你从0到1学习。 + +
+ +
+ +#### 第1期 RAG Spring AI 0.8.1 - 完结 + +1. 【更】AI RAG 知识库,项目介绍&需求分析&环境说明 +2. 【更】初始化知识库工程&部署模型&提交代码 +3. 【更】Ollama DeepSeek 流式应答接口实现 +4. 【更】Ollama DeepSeek 流式应答页面对接 +5. 【更】Ollama RAG 知识库上传、解析和验证 +6. 【更】Ollama RAG 知识库接口服务实现 +7. 【更】基于AI工具,设计前端UI和接口对接 +8. 【更】Git仓库代码库解析到知识库并完善UI对接 +9. 【更】扩展OpenAI模型对接,以及完整AI对接 +10. 【更】云服务器部署知识库(Docker、Nginx) + +#### 第2期 MCP Spring AI 1.0.0 - 开冲 + +1. 【新】AI MCP 项目介绍 +2. 【新】吃上细糠,Spring AI 框架升级 + GPU 部署 AI +3. 【新】康庄大道,上手 AI MCP 工作流.md +4. 【新】道山学海,实现MCP自动发帖服务 +5. 【新】海纳百川,MCP 其他服务实现 +6. 【新】川流不息,官网 DeepSeek + open-api 对接 +7. 【新】息兵罢战,服务接口实现,增强 RAG 知识库 + MCP 服务使用 +8. 【新】应用服务接口与前端页面对接 +9. ... 随课程开发提供,包括后续的云服务部署。 + +> AI RAG&MCP 只是小傅哥社群里众多项目的一个,这里还有非常多的牛皮项目,一次加入都可以学习到。并且,不断的更新迭代新项目,社群嘎嘎活跃! \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/\347\254\25410\350\212\202\357\274\232\344\272\221\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\347\237\245\350\257\206\345\272\223\357\274\210Docker\343\200\201Nginx\357\274\211.md" "b/docs/md/project/ai-knowledge/\347\254\25410\350\212\202\357\274\232\344\272\221\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\347\237\245\350\257\206\345\272\223\357\274\210Docker\343\200\201Nginx\357\274\211.md" new file mode 100644 index 000000000..88ce48c59 --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\25410\350\212\202\357\274\232\344\272\221\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\347\237\245\350\257\206\345\272\223\357\274\210Docker\343\200\201Nginx\357\274\211.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第10节:云服务器部署知识库(Docker、Nginx) +pay: https://t.zsxq.com/YUG46 +--- + +# 《DeepSeek RAG 知识库》第10节:云服务器部署知识库(Docker、Nginx) + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/cWfL6](https://t.zsxq.com/cWfL6) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +部署项目到公网云服务器,让小伙伴们学习如何打包部署上线和Linux、Docker、Nginx的操作使用。 + +## 二、部署过程 + +如图,为本次的部署过程; + +
+ +
+ +- 首先,购买云服务器,之后搭建云环境。[http://618.gaga.plus/](http://618.gaga.plus/) 需要2c4g部署。 +- 之后,我们在本地构建软件镜像,之后推送到 Docker Hub,完成后再把 dev-ops 的脚本通过 sftp 上传到云服务器,执行安装。 +- 最后,记得部署完成后检查各个软件运行日志,以及开通下相关的服务端口。 diff --git "a/docs/md/project/ai-knowledge/\347\254\25411\350\212\202\357\274\232AIMCP\351\203\250\345\210\206\344\273\213\347\273\215.md" "b/docs/md/project/ai-knowledge/\347\254\25411\350\212\202\357\274\232AIMCP\351\203\250\345\210\206\344\273\213\347\273\215.md" new file mode 100644 index 000000000..0af867e4a --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\25411\350\212\202\357\274\232AIMCP\351\203\250\345\210\206\344\273\213\347\273\215.md" @@ -0,0 +1,109 @@ +--- +title: DeepSeep MCP 动态知识库 - AI工作流&智能体 +lock: no +--- + +# 《DeepSeep MCP 动态知识库》 - AI工作流&智能体 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +用不了多久,各大互联网企业都将大量的推进落地,自有 [MCP](https://github.com/modelcontextprotocol) 服务的实现,用于增强企业 AI 应用的提效能力。因为 [MCP](https://github.com/modelcontextprotocol) 的加入,可以让你;一条命令`帮研发`,调用应用系统日志、排查系统CPU负载、自主选择是否调度数据库信息。也可以一条命令`帮运营`,搞定复杂的SQL执行、导出报表、分析数据、完成促活营销券的自动化配置上架。这就是 [MCP](https://github.com/modelcontextprotocol) 的魅力!👍🏻 + +
+ +
+ +**那么牛,MCP 是什么?** + +专业的术语 `MCP = Model Context Protocol` 模型上下文协议,可实现应用与外部数据源和工具之间的无缝集成。无论您是构建 AI 驱动的 IDE、增强聊天界面还是创建自定义 AI 工作流,MCP 都提供了一种标准化的方式来连接他们所需的上下文。 + +`来吧,上图!让你看看它是啥!` + +
+ +
+ +- 首先,站在用户的使用视角,研发或者运营,可以通过话术描述,完成系列的 AI 工作流,并拿到最终的结果。这就是 MCP 最终为你提供的服务。 +- 那么,你可以想象,在日常的工作中,运营、研发、产品、测试等,都有非常多的重复非创作性的工作,占用了大量的时间成本。尤其是研发,写写代码,就有运营过来,帮我查个问题吧,小嘚嘚。但如果有这样的借助于 MCP 实现的 AI 工作流,就可以完成80%以上的工作量。 +- 之后,站在技术的实现视角,MCP 是一个标准结构框架,你可以按照它(Spring AI)提供的 SDK 开发方式,完成本地化 API 的接入开发。让 AI 有明确的方式调用各类 API 服务接口。如果没有 MCP 这会是一件很麻烦的事情。 + +好啦📢,这就是小傅哥即将为你开启的**《DeepSeek RAG 增强知识库》**第2阶段,`MCP 服务开发和对接`。让你具备 AI 开发能力,遥遥领先于还在扣 CRUD 项目的小伙伴,做面试最牛的仔,最职场最靓的人! + +> Spring AI MCP 与 24年末发布,学习此 AI 应用开发项目,你将是第一批具备 Java AI 应用实战开发能力的人。竞争力,嘎嘎滴! + +## 第1期,RAG 我们做了什么 + +在 《DeepSeek RAG 增强知识库》第1阶段,基于 Spring AI 0.8.1 开发了一套可以上传文件和Git仓库进行解析、切割、存储,到使用向量库完成 AI 的知识库问答系统。并最终通过 Docker 部署上线。 + +
+ +
+ +- 基于,RAG 这样的一套知识库,你可以完成文本和代码库的解析。以及自行扩展提供出 RAG 知识库的接口,对接到 OpenAI 代码自动评审(小傅哥社群的另外一个项目),增强代码评审效果。 +- 在这套项目中,可以学习到 Ollama DeepSeek 本地化&云服务部署,以及流式接口的开发、基于 AI 完成页面与知识库对话接口的处理,Linux、Docker 的部署等。小项目不大,但非常锻炼人! + +## 第2期,MCP 我们要做什么 + +与第2期相比,第1期可以称之为小试牛刀,让小伙伴们以最快、最快的往事,积累,运用 Spring AI 框架,开发自己的 RAG 知识库。~~也是方便有些死鬼,早点写到简历上~~ + +到了第2期,你就开始吃上细糠了,小傅哥会带着你升级 Spring AI 框架为 1.0.0-M6 最新版本,多模型配置和操作 PG 向量库,使用 GPU 搭建响应速度更好的 Ollama DeepSeek 大模型(秒级处理),以及对接官网 DeepSeek 的大模型和统一 one-api 对接方式。 + +但这还只是开始,随着基础框架的升级完成,我们将进入 MCP 服务的开发实现。通过 AI 指令,完成 AI 工作流,调度各项 MCP 处理我们的任务作业。如图,举例操作; + +
+ +
+ +- 基于 MCP 服务的开发和对接,通过 AI 工作流指令,完成数据的采集和存放动作。💡 聪明的小伙伴以及开始联想,基于这样的 AI 开发,可以替代很多的日常工作啦。**没想到吧,也把自己替代了** 但仍然,蠢蠢欲动(我不做,别人也做呀)!~~实现后,晋升又有的讲啦!简历也有东西写啦!~~ +- 有了 MCP 后,相当于把我们需要;在一个网页操作数据库查询数据、打开另外一个网页看天气预报,再手动的创建个文件把以上的信息获取后,复制粘贴到文件里。这一些列操作,都让 AI 通过 MCP 模型上下文协议进行处理。也就是 AI 可以调用后台接口啦! + +## 课程目录计划 💐 + +此课程会扩展很多基于 Java 的 AI 开发能力学习,帮助大家积累相关的场景解决方案。在这个过程中你可以最快的掌握最新的技术,早早的提前别人一步。 + +
+ +
+ +
+ +
+ +- 全课程包括文档 + 小册,全程视频手把手带着做。 +- 课程地址:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) - 含全套项目代码和视频。 + +### 第1期 RAG Spring AI 0.8.1 - 完结 + +1. 【更】AI RAG 知识库,项目介绍&需求分析&环境说明 +2. 【更】初始化知识库工程&部署模型&提交代码 +3. 【更】Ollama DeepSeek 流式应答接口实现 +4. 【更】Ollama DeepSeek 流式应答页面对接 +5. 【更】Ollama RAG 知识库上传、解析和验证 +6. 【更】Ollama RAG 知识库接口服务实现 +7. 【更】基于AI工具,设计前端UI和接口对接 +8. 【更】Git仓库代码库解析到知识库并完善UI对接 +9. 【更】扩展OpenAI模型对接,以及完整AI对接 +10. 【更】云服务器部署知识库(Docker、Nginx) + +### 第2期 MCP Spring AI 1.0.0 - 开冲 + +11. 【新】AI MCP 项目介绍 +12. 【新】吃上细糠,Spring AI 框架升级 + GPU 部署 AI +13. 【新】吃上细糠,官网 DeepSeek + open-api 对接 +14. 【新】MCP 服务的应用类演示和使用 +15. 【新】MCP Spring AI 客户端npx调用,以及资源讲解 +16. 【新】MCP Spring AI 服务端webflux实现 +17. 【新】MCP Spring AI 服务端 + 客户端对接使用 +18. 【新】服务接口实现,增强 RAG 知识库 + MCP 服务使用 +19. 【新】应用服务接口与前端页面对接 +20. ... 随课程开发提供,包括后续的云服务部署。 + +课程包括;视频、小册、1 对 1 答疑解惑、专属VIP项目交流群,并且提供简历编写模板结构的一条龙🐲服务。让你学习后,直接拉开与还在玩具项目其他人的差距,面试脱颖而出提高竞争力!!! + +>课程已经开始,早早加入,早早学习。时间、时机,比任何东西都珍贵!晚点学,只能是工具人。但早点学,就是开发工具的人!加入小傅哥的社群,如图的全套实战项目,都可以学习; \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/\347\254\25411\350\212\202\357\274\232\345\220\203\344\270\212\347\273\206\347\263\240\357\274\214\345\215\207\347\272\247SpringAI\346\241\206\346\236\266.md" "b/docs/md/project/ai-knowledge/\347\254\25411\350\212\202\357\274\232\345\220\203\344\270\212\347\273\206\347\263\240\357\274\214\345\215\207\347\272\247SpringAI\346\241\206\346\236\266.md" new file mode 100644 index 000000000..5413d1ed4 --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\25411\350\212\202\357\274\232\345\220\203\344\270\212\347\273\206\347\263\240\357\274\214\345\215\207\347\272\247SpringAI\346\241\206\346\236\266.md" @@ -0,0 +1,39 @@ +--- +title: 【更】第11节:吃上细糠,升级SpringAI框架 +pay: https://t.zsxq.com/zT6bl +--- + +# 《DeepSeek RAG&MCP 增强检索知识库系统》第11节:吃上细糠,升级SpringAI框架 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/q5rnP](https://t.zsxq.com/q5rnP) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +升级 Spring AI 框架到 1.0.0-M6 版本,以适应于二阶段 MCP(Model Context Protocol 模型上下文协议)服务开发。 + +## 二、本章诉求 + +本节升级包括; +- 提供,快速的 Ollama DeepSeek 部署,支持 1.5b、7b、30b 模型。服务器小时价格很低,速度非常快。 +- 提供,pgAdmin管理工具部署(Docker+本地软件),用于操作 PG 向量库。 +- 提供,向量库自主创建和多模型配置,满足不同模型的向量库使用。 + +## 三、升级框架 + +### 1. POM 配置 + +```pom + + org.springframework.ai + spring-ai-bom + 1.0.0-M6 + pom + import + +``` + +- Spring AI 目前最新版为 1.0.0-M6,[https://spring.io/projects/spring-ai#learn](https://spring.io/projects/spring-ai#learn) diff --git "a/docs/md/project/ai-knowledge/\347\254\25412\350\212\202\357\274\232\345\272\267\345\272\204\345\244\247\351\201\223\357\274\214\344\270\212\346\211\213 AI MCP \345\267\245\344\275\234\346\265\201.md" "b/docs/md/project/ai-knowledge/\347\254\25412\350\212\202\357\274\232\345\272\267\345\272\204\345\244\247\351\201\223\357\274\214\344\270\212\346\211\213 AI MCP \345\267\245\344\275\234\346\265\201.md" new file mode 100644 index 000000000..df9afd82c --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\25412\350\212\202\357\274\232\345\272\267\345\272\204\345\244\247\351\201\223\357\274\214\344\270\212\346\211\213 AI MCP \345\267\245\344\275\234\346\265\201.md" @@ -0,0 +1,23 @@ +--- +title: 【更】第12节:康庄大道,上手 AI MCP 工作流 +pay: https://t.zsxq.com/am5PO +--- + +# 《DeepSeek RAG&MCP 增强检索知识库系统》第12节:康庄大道,上手 AI MCP 工作流 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/GoWka](https://t.zsxq.com/GoWka) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +对接 Spring AI MCP,实现服务端 MCP 和 客户端 MCP,完成功能对接,体验 AI 工作流完成的指令动作。 + +## 二、本节重点 + +本节功能服务包括; +1. 增加,Spring AI MCP 框架接入。 +2. 对接,Spring AI MCP 共用服务端,如;[https://smithery.ai/](https://smithery.ai/)、[https://glama.ai/mcp/servers](https://glama.ai/mcp/servers) +3. 开发,Spring AI MCP 个人客户端,基于 Java 实现客户端。这块是一个独立的新工程组件。 diff --git "a/docs/md/project/ai-knowledge/\347\254\25413\350\212\202\357\274\214\351\201\223\345\261\261\345\255\246\346\265\267\357\274\214\345\256\236\347\216\260MCP\350\207\252\345\212\250\345\217\221\345\270\226\346\234\215\345\212\241.md" "b/docs/md/project/ai-knowledge/\347\254\25413\350\212\202\357\274\214\351\201\223\345\261\261\345\255\246\346\265\267\357\274\214\345\256\236\347\216\260MCP\350\207\252\345\212\250\345\217\221\345\270\226\346\234\215\345\212\241.md" new file mode 100644 index 000000000..0971be32d --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\25413\350\212\202\357\274\214\351\201\223\345\261\261\345\255\246\346\265\267\357\274\214\345\256\236\347\216\260MCP\350\207\252\345\212\250\345\217\221\345\270\226\346\234\215\345\212\241.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第13节,道山学海,实现MCP自动发帖服务 +pay: https://t.zsxq.com/WSM3k +--- + +# 《DeepSeek RAG&MCP 增强检索知识库系统》第13节,道山学海,实现MCP自动发帖服务 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/xTjYL](https://t.zsxq.com/xTjYL) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +分析 CSDN 文章发表接口,以 MCP 服务搭建的方式,实现一款 stdio 模式的 CSDN 发帖 MCP 服务。(后续开发 sse 模式) + +**注意**:不限于CSDN,你可以结合本节的学习,在任何一个平台使用它的接口,完成自动发帖服务。如,这里还有一个知识星球的发帖,也可以学习下之后对接实现一个 MCP 服务。地址:[https://bugstack.cn/md/road-map/http.html](https://bugstack.cn/md/road-map/http.html) + +## 二、功能流程 + +如图,实现 CSDN 发帖 MCP 服务流程; + +
+ +
+ +- 首先,无论你是对接任何的平台,都是需要先获得他的接口服务。这种接口一种是平台提供了专门的对接接口,另外就是没有这样的接口,我们是通过浏览器访问网站,获得的接口。哪这些接口通过代码方式完成请求。 +- 之后,基于得到的接口,封装成可以调用的服务 service,这样 MCP 的入口工具,设定好入参信息,就可以调用底层的接口服务了。 +- 最后,当用户提问时,如果你实现了不止一个 CSDN 发帖的 MCP,也包括如星球发帖。那么你的 AI 工作流,是可以顺序的向这些平台自动发帖。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/\347\254\25414\350\212\202\357\274\232\346\265\267\347\272\263\347\231\276\345\267\235\357\274\214\344\270\212\347\272\277MCP\350\207\252\345\212\250\345\217\221\345\270\226\346\234\215\345\212\241.md" "b/docs/md/project/ai-knowledge/\347\254\25414\350\212\202\357\274\232\346\265\267\347\272\263\347\231\276\345\267\235\357\274\214\344\270\212\347\272\277MCP\350\207\252\345\212\250\345\217\221\345\270\226\346\234\215\345\212\241.md" new file mode 100644 index 000000000..89fa1fa42 --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\25414\350\212\202\357\274\232\346\265\267\347\272\263\347\231\276\345\267\235\357\274\214\344\270\212\347\272\277MCP\350\207\252\345\212\250\345\217\221\345\270\226\346\234\215\345\212\241.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第14节,海纳百川,上线MCP自动发帖服务 +pay: https://t.zsxq.com/G5mog +--- + +# 《DeepSeek RAG&MCP 增强检索知识库系统》第14节,海纳百川,上线MCP自动发帖服务 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/W0u4s](https://t.zsxq.com/W0u4s) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +以 Jar 包的形式,打包 MCP 自动发帖服务,并以 stdio 方式引入到项目工程。再通过定时任务触达定时自动发帖。 + +## 二、功能流程 + +如图,以 stdio 方式,构建服务打包上线; + +
+ +
+ +- 首先,将 mcp-server-csdn 以 maven 命令方式打一个 jar。IntelliJ IDEA 也可以直接通过界面操作打包 Jar(视频里会演示) +- 之后,将 ai-mcp-knowledge 以 maven 命令方式打一个 jar,并执行 Dockerfile 构建出可部署的镜像。注意,这里额外增加一个阿里云 Docker 镜像仓库,为的是让他提供搭理,方便我们云服务器部署的时候,可以快速拉取下来镜像。此外,如果说你以云服务器当做本机一样使用,在云服务器配置好 maven、git、java jdk 17,那么就可以在云服务器直接构建镜像,也就不需要额外拉取了。(`这部分内容在课程入口-编程环境-云服务器操作中有讲解`) +- 最后,通过 docker-compose 脚本配置上线部署。 diff --git "a/docs/md/project/ai-knowledge/\347\254\25415\350\212\202\357\274\232\345\267\235\346\265\201\344\270\215\346\201\257\357\274\214\345\256\236\347\216\260MCP\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\346\266\210\346\201\257\351\200\232\347\237\245\346\234\215\345\212\241.md" "b/docs/md/project/ai-knowledge/\347\254\25415\350\212\202\357\274\232\345\267\235\346\265\201\344\270\215\346\201\257\357\274\214\345\256\236\347\216\260MCP\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\346\266\210\346\201\257\351\200\232\347\237\245\346\234\215\345\212\241.md" new file mode 100644 index 000000000..561d77da8 --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\25415\350\212\202\357\274\232\345\267\235\346\265\201\344\270\215\346\201\257\357\274\214\345\256\236\347\216\260MCP\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\346\266\210\346\201\257\351\200\232\347\237\245\346\234\215\345\212\241.md" @@ -0,0 +1,31 @@ +--- +title: 【更】第15节,川流不息,实现MCP微信公众号消息通知服务 +pay: https://t.zsxq.com/84IV7 +--- + +# 《DeepSeek RAG&MCP 增强检索知识库系统》第15节,川流不息,实现MCP微信公众号消息通知服务 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/Qlqkr](https://t.zsxq.com/Qlqkr) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +AI MCP 是可以让 AI 以工作流方式进行调用的,为了更好的体现这一点,同时也为了增强整体的自动发帖服务链路。本节我们实现一个微信公众号推送消息的 MCP 服务。 + +这一节暂时会先以 stdio 方式开发,之后下一节部署的时候,会把 CSDN、WeiXin 两个 MCP 服务都以 SSE 方式进行部署。让大家学习到不同的开发方式和部署方式。 + +## 二、功能流程 + +如图,自动发帖后,进行微信公众号,消息推送; + +
+ +
+ +- 首先,CSDN 自动发帖是上一节实现的内容,本节要实现一个微信公众号推送模板消息的实现。 +- 之后,AI 调用两套 MCP,可以一次会话,也可以使用 ChatMemory 进行记忆完成2次对话处理 MCP 流程。 +- 最终,实现自动发帖后,完成消息通知给我们自己。点击通知信息可进入具体文章。 + diff --git "a/docs/md/project/ai-knowledge/\347\254\25416\350\212\202\357\274\232\346\201\257\346\201\257\347\233\270\351\200\232\357\274\214MCP \346\234\215\345\212\241\351\203\250\347\275\262\344\270\212\347\272\277\357\274\210sse \346\250\241\345\274\217\357\274\211.md" "b/docs/md/project/ai-knowledge/\347\254\25416\350\212\202\357\274\232\346\201\257\346\201\257\347\233\270\351\200\232\357\274\214MCP \346\234\215\345\212\241\351\203\250\347\275\262\344\270\212\347\272\277\357\274\210sse \346\250\241\345\274\217\357\274\211.md" new file mode 100644 index 000000000..7bd661a88 --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\25416\350\212\202\357\274\232\346\201\257\346\201\257\347\233\270\351\200\232\357\274\214MCP \346\234\215\345\212\241\351\203\250\347\275\262\344\270\212\347\272\277\357\274\210sse \346\250\241\345\274\217\357\274\211.md" @@ -0,0 +1,32 @@ +--- +title: 【更】第16节:息息相通,MCP 服务部署上线(sse 模式) +pay: https://t.zsxq.com/Qexmh +--- + +# 《DeepSeek RAG&MCP 增强检索知识库系统》第16节:息息相通,MCP 服务部署上线(sse 模式) + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/J6kpc](https://t.zsxq.com/J6kpc) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +调整 mcp-server-csdn、mcp-server-weixin,两个 MCP 部署方式为 SSE 以及增加 Dockerfile 部署脚本。让服务支持以 sse 方式,被 ai-mcp-knowledge 调用。 + +## 二、功能流程 + +如图,以 sse 方式,构建服务打包上线; + +
+ +
+ +- `SSE` (Server-Sent Events) ,是一种基于 HTTP 的**服务器向客户端单向实时推送数据**的通信技术,常用于实现实时更新功能。 +- 在 Spring AI 框架中,SSE 的实现方式包括 spring-ai-starter-mcp-server-webmvc、spring-ai-starter-mcp-server-webflux 两种框架实现。课程以 webflux 进行使用。 +- SSE 的部署方式,要把每个 mcp 服务,通过 docker 进行部署,提供出可用的接口。之后 ai-mcp-knowledge 工程则配置 sse 方式进行使用。 + +> 接下来我们介绍,如何配置 sse 方式进行对接。这部分主要是配置文件的变化,以及 1.0.0-M6 版本号关于 sse bug 的处理。 + + diff --git "a/docs/md/project/ai-knowledge/\347\254\2541\350\212\202\357\274\232AI RAG \347\237\245\350\257\206\345\272\223\357\274\214\351\241\271\347\233\256\344\273\213\347\273\215.md" "b/docs/md/project/ai-knowledge/\347\254\2541\350\212\202\357\274\232AI RAG \347\237\245\350\257\206\345\272\223\357\274\214\351\241\271\347\233\256\344\273\213\347\273\215.md" new file mode 100644 index 000000000..4ecb2c07a --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\2541\350\212\202\357\274\232AI RAG \347\237\245\350\257\206\345\272\223\357\274\214\351\241\271\347\233\256\344\273\213\347\273\215.md" @@ -0,0 +1,50 @@ +--- +title: 【更】第1节:AI RAG 知识库,项目介绍 +pay: https://t.zsxq.com/bV1QU +--- + +# 《DeepSeek RAG 知识库》第1节:AI RAG 知识库,项目介绍 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/ssFF0](https://t.zsxq.com/ssFF0) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +AI 开发能力,几乎已经是每个工程师必备的能力。在我们去看各个公司招聘要求时,经常会看到具备 AI、AIGC、RAG 能力优先。因为这些东西可以帮助企业提效,结合AI增强自身产品能力。所以,学习一下这样的东西是非常重要的! + +在 AI 的使用场景中,我们考虑过;代码评审、需求开发、智能客服、SQL编写、需求分析等。但这些东西的回答,会随着我们发给 AI 的内容来解答,但受到AI对话的上线文字数限制,不太可能把且有的所有资料都一次发给 AI 进行解答。所以这里引出了企业知识库构建的诉求。它就是 RAG! + +RAG(检索增强生成)技术正在重构互联网知识规则,RAG不仅仅是一个简单的知识存储工具,它是一种将检索与生成相结合的智能系统,能够从海量数据中快速提取相关信息,并结合上下文生成精准、连贯的答案。对于互联网公司而言,构建自己的RAG知识库,意味着能够为用户提供更加个性化、专业化的服务,同时也能够在激烈的市场竞争中,建立起独特的技术壁垒。 + +虽然市面有一些开源的 RAG,但深入使用仍不能解决所有的场景问题,尤其是你想自定义业务诉求,解析更多场景,更复杂的知识库时候,它们就显得不合适了。**并且研发人员,自身应该具备 RAG 开发能力。** + +所以,我们来啦!构建一款属于自己的小型的 RAG 知识库,以此掌握 RAG 相关知识,扩宽自己的技术边界。 + +> 此项目小巧轻量,扩展性好,可以快速学习完成,掌握 RAG 知识库搭建和使用。 + +## 一、项目简述 + +基于 Ollama 部署 DeepSeek 大模型,提供 API 接口。运用 Spring AI 框架承接接口实现 RAG 知识库能力。这款 RAG 知识库支持文本解析,以及 Git 代码库的解析。 + +工程结构采取2层架构,轻量化设计,重点在于突出 RAG 功能实现。以此方式,帮助大家更好的理解,除了工程架构外的 RAG 知识库搭建。方便大家快速上手学习。 + +## 二、什么是 RAG + +[RAG:检索增强生成](https://www.promptingguide.ai/zh/techniques/rag) + +它通用语言模型通过微调就可以完成几类常见任务,比如分析情绪和识别命名实体。这些任务不需要额外的背景知识就可以完成。 + +要完成更复杂和知识密集型的任务,可以基于语言模型构建一个系统,访问外部知识源来做到。这样的实现与事实更加一性,生成的答案更可靠,还有助于缓解“幻觉”问题。 + +Meta AI 的研究人员引入了一种叫做检索增强生成(Retrieval Augmented Generation,RAG)的方法来完成这类知识密集型的任务。RAG 把一个信息检索组件和文本生成模型结合在一起。RAG 可以微调,其内部知识的修改方式很高效,不需要对整个模型进行重新训练。 + +RAG 会接受输入并检索出一组相关/支撑的文档,并给出文档的来源(例如维基百科)。这些文档作为上下文和输入的原始提示词组合,送给文本生成器得到最终的输出。这样 RAG 更加适应事实会随时间变化的情况。这非常有用,因为 LLM 的参数化知识是静态的。RAG 让语言模型不用重新训练就能够获取最新的信息,基于检索生成产生可靠的输出。 + +Lewis 等人(2021)提出一个通用的 RAG 微调方法。这种方法使用预训练的 seq2seq 作为参数记忆,用维基百科的密集向量索引作为非参数记忆(使通过神经网络预训练的检索器访问) + +
+ +
\ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/\347\254\2542\350\212\202\357\274\232\345\210\235\345\247\213\345\214\226\347\237\245\350\257\206\345\272\223\345\267\245\347\250\213&\346\217\220\344\272\244\344\273\243\347\240\201.md" "b/docs/md/project/ai-knowledge/\347\254\2542\350\212\202\357\274\232\345\210\235\345\247\213\345\214\226\347\237\245\350\257\206\345\272\223\345\267\245\347\250\213&\346\217\220\344\272\244\344\273\243\347\240\201.md" new file mode 100644 index 000000000..3b7af907d --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\2542\350\212\202\357\274\232\345\210\235\345\247\213\345\214\226\347\237\245\350\257\206\345\272\223\345\267\245\347\250\213&\346\217\220\344\272\244\344\273\243\347\240\201.md" @@ -0,0 +1,39 @@ +--- +title: 【更】第2节:初始化知识库工程&提交代码 +pay: https://t.zsxq.com/VZSnk +--- + +# 《DeepSeek RAG 知识库》第2节:初始化知识库工程&提交代码 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/07kXb](https://t.zsxq.com/07kXb) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +教会小伙伴使用 IntelliJ IDEA 创建多模块工程,并介绍分层模块的用途。以及相关基础环境安装。 + +课程会循序渐进的从0到1,逐步带着大家完成项目的开发。开局只有一把 IntelliJ IDEA,完成项目后你可以学习到;业务、架构、设计、方案、配置、部署(Linux、Docker)等各项知识。 + +## 二、如何开始 + +站在读者视角,该怎么学习呢?这里做个必要说明和前置的知识提供。 + +### 1. 前置学习 + +小伙伴在学习的时候,可以依照课程的方式进行创建项目、变更配置、启动测试。这里有一些前置学习,包括:Git、Maven、Docker,课程已经准备好了,可以刷下; + +- Git:[https://bugstack.cn/md/road-map/git.html](https://bugstack.cn/md/road-map/git.html) +- Maven:[https://bugstack.cn/md/road-map/maven.html](https://bugstack.cn/md/road-map/maven.html) +- Docker:[https://bugstack.cn/md/road-map/docker-what.html](https://bugstack.cn/md/road-map/docker-what.html) - `入门 Docker 必看` +- Docker 镜像:[https://t.zsxq.com/2DGGY](https://t.zsxq.com/2DGGY) + +另外课程会使用 Java JDK 17、Maven 3.8.x,软件已经提供好,可以直接下载;[https://t.zsxq.com/19Rnk98M0](https://t.zsxq.com/19Rnk98M0) - `附件内含有配置好阿里云镜像的 Maven` + +### 2. 开始学习 + +1. 你需要通过 `git clone https://xxx.git` 命令,或者 IntelliJ IDEA 自动的检出工程方式,把项目工程检出到本地。关于如何使用Git检出项目,在前置学习里提供了教程。 +2. 检出代码后,你可以通过 IntelliJ IDEA 打开项目,并按照每一节最开始说明的本节对应的代码分支,把工程代码切换到对应的这一节。 +3. 接下来你可以通过课程的视频和小册以及提供的代码进行学习,并跟随课程每节要完成的内容,一步步操作。过程中可以参考课程的代码进行学习。如果自己的代码运行出问题的时候,可以运行课程的代码验证是环境问题还是个人代码问题。**另外注意运行课程代码,要修改对应的环境为你的本地环境,postgresql、redis等** \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/\347\254\2543\346\216\245\357\274\232Ollama DeepSeek \346\265\201\345\274\217\345\272\224\347\255\224\346\216\245\345\217\243\345\256\236\347\216\260.md" "b/docs/md/project/ai-knowledge/\347\254\2543\346\216\245\357\274\232Ollama DeepSeek \346\265\201\345\274\217\345\272\224\347\255\224\346\216\245\345\217\243\345\256\236\347\216\260.md" new file mode 100644 index 000000000..a0aff68f5 --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\2543\346\216\245\357\274\232Ollama DeepSeek \346\265\201\345\274\217\345\272\224\347\255\224\346\216\245\345\217\243\345\256\236\347\216\260.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第3节:Ollama DeepSeek 流式应答接口实现 +pay: https://t.zsxq.com/h5VxZ +--- + +# 《DeepSeek RAG 知识库》第3节:Ollama DeepSeek 流式应答接口实现 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/4DbVB](https://t.zsxq.com/4DbVB) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +引入 Spring AI 框架组件,对接 Ollama DeepSeek 提供服务接口。包括;普通应答接口和流式接口。 + +## 二、技术方案 + +对接 AI 的方式有很多,比如;`AI 官网提供的 SDK`、`自研 SDK 组件`、`one-api 服务类统一包装接口`,其中自研类 SDK 已经在星球 openai 项目对接 chatglm、chatgpt 的时候进行设计,为了差异化学习到不同技术,本项目会采用 Spring AI 框架进行对接。 + +
+ +
+ +官网:[https://spring.io/projects/spring-ai](https://spring.io/projects/spring-ai) + +Spring AI 支持;OpenAI,Microsoft,Amazon,Google和Ollama,大模型的对接。其他不属于这个范围的,可以通过 [one-api](https://github.com/songquanpeng/one-api) 配置,统一转换为 OpenAI 接口服务格式进行使用。 + + diff --git "a/docs/md/project/ai-knowledge/\347\254\2544\350\212\202\357\274\232Ollama DeepSeek \346\265\201\345\274\217\345\272\224\347\255\224\351\241\265\351\235\242\345\257\271\346\216\245.md" "b/docs/md/project/ai-knowledge/\347\254\2544\350\212\202\357\274\232Ollama DeepSeek \346\265\201\345\274\217\345\272\224\347\255\224\351\241\265\351\235\242\345\257\271\346\216\245.md" new file mode 100644 index 000000000..8797a9c43 --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\2544\350\212\202\357\274\232Ollama DeepSeek \346\265\201\345\274\217\345\272\224\347\255\224\351\241\265\351\235\242\345\257\271\346\216\245.md" @@ -0,0 +1,31 @@ +--- +title: 【更】第4节:Ollama DeepSeek 流式应答页面对接 +pay: https://t.zsxq.com/PN4lw +--- + +# 《DeepSeek RAG 知识库》第3节:Ollama DeepSeek 流式应答接口实现 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/f82uj](https://t.zsxq.com/f82uj) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +实现一款简单的UI界面,与服务端 Ollama DeepSeek AI 进行对接。 + +## 二、技术方案 + +自从有了 AI 工具以后,所有以前头疼前端页面开发的后端程序员👨🏻‍💻,都漏出了友善😊微笑! + +主要我们可以清楚地表达编写页面诉求,AI 工具就可以非常准确且迅速的完成代码的实现。这里我们可以选择的 AI 有很多,包括;OpenAI、DeepSeek、智谱AI等等。 + +- [https://www.deepseek.com/](https://www.deepseek.com/) +- [https://v0.dev/](https://v0.dev/) +- [https://chatglm.cn/](https://chatglm.cn/) +- [https://openai.itedus.cn/](https://openai.itedus.cn/) + +>其他更多也可以网络检索下。总有一款你是可以使用的。 + + diff --git "a/docs/md/project/ai-knowledge/\347\254\2545\350\212\202\357\274\232Ollama RAG \347\237\245\350\257\206\345\272\223\344\270\212\344\274\240\343\200\201\350\247\243\346\236\220\345\222\214\351\252\214\350\257\201.md" "b/docs/md/project/ai-knowledge/\347\254\2545\350\212\202\357\274\232Ollama RAG \347\237\245\350\257\206\345\272\223\344\270\212\344\274\240\343\200\201\350\247\243\346\236\220\345\222\214\351\252\214\350\257\201.md" new file mode 100644 index 000000000..a2521598b --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\2545\350\212\202\357\274\232Ollama RAG \347\237\245\350\257\206\345\272\223\344\270\212\344\274\240\343\200\201\350\247\243\346\236\220\345\222\214\351\252\214\350\257\201.md" @@ -0,0 +1,36 @@ +--- +title: 【更】第5节:Ollama RAG 知识库上传、解析和验证 +pay: https://t.zsxq.com/fTK4R +--- + +# 《DeepSeek RAG 知识库》第5节:Ollama RAG 知识库上传、解析和验证 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/PM15B](https://t.zsxq.com/PM15B) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +以大模型向量存储的方式,提交本地文件到知识库。并在 AI 对话中增强检索知识库符合 AI 对话内容的资料,合并提交问题。 + +## 二、技术方案 + +以 Spring AI 提供的向量模型处理框架,将上传文件以 TikaDocumentReader 方式进行解析,再通过 TokenTextSplitter 拆分文件。完成这些操作后,在遍历文档添加标记。标记的作用是为了可以区分不同的知识库内容。完成这些动作后,把这些拆解并打标的文件存储到 postgresql 向量库中。 + +本技术方案旨在利用 Spring AI 提供的向量模型处理框架,对上传的文件进行解析、拆分、标记,并将处理后的数据存储到 PostgreSQL 向量库中。通过这一流程,可以实现对文件内容的高效管理和检索,特别是在需要区分不同知识库内容的场景下。 + +### 1. 技术组件 + +- **Spring AI**: 提供向量模型处理框架,支持文件的解析、拆分和向量化操作。 +- **TikaDocumentReader**: 用于解析上传的文件,支持多种文件格式(如 MD、TXT、SQL 等)。 +- **TokenTextSplitter**: 用于将解析后的文本内容拆分为更小的片段,便于后续处理和存储。 +- **PostgreSQL 向量库**: 用于存储处理后的文本向量数据,支持高效的相似性搜索和检索。 + +### 2. 方案流程 + +#### 2.1 文件上传与解析 + +1. **文件上传**: 用户通过前端界面或 API 上传文件,文件可以是多种格式(如 MD、TXT、SQL 等)。 +2. **文件解析**: 使用 `TikaDocumentReader` 对上传的文件进行解析,提取出文本内容。`TikaDocumentReader` 能够处理多种文件格式,并提取出结构化的文本数据。 \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/\347\254\2546\350\212\202\357\274\232Ollama RAG \347\237\245\350\257\206\345\272\223\346\216\245\345\217\243\346\234\215\345\212\241\345\256\236\347\216\260.md" "b/docs/md/project/ai-knowledge/\347\254\2546\350\212\202\357\274\232Ollama RAG \347\237\245\350\257\206\345\272\223\346\216\245\345\217\243\346\234\215\345\212\241\345\256\236\347\216\260.md" new file mode 100644 index 000000000..646517066 --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\2546\350\212\202\357\274\232Ollama RAG \347\237\245\350\257\206\345\272\223\346\216\245\345\217\243\346\234\215\345\212\241\345\256\236\347\216\260.md" @@ -0,0 +1,34 @@ +--- +title: 【更】第6节:Ollama RAG 知识库接口服务实现 +pay: https://t.zsxq.com/EvnBN +--- + +# 《DeepSeek RAG 知识库》第6节:Ollama RAG 知识库接口服务实现 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/yNiZl](https://t.zsxq.com/yNiZl) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +以上一节知识库的测试案例,将这部分功能以接口方式提供。包括;知识库的上传、选择和使用。 + +## 二、技术方案 + +知识库的上传和使用是明确的,但选择哪个知识库是需要把对应的知识库记录起来。这里我们选择 Redis 列表进行记录。如果是公司里大型的知识库,还需要使用 MySQL 数据库进行存储。 + +## 三、功能实现 + +### 1. 工程结构 + +### 2. 引入组件 + +```java + + org.redisson + redisson-spring-boot-starter + 3.44.0 + +``` \ No newline at end of file diff --git "a/docs/md/project/ai-knowledge/\347\254\2547\350\212\202\357\274\232\345\237\272\344\272\216AI\345\267\245\345\205\267\357\274\214\350\256\276\350\256\241\347\237\245\350\257\206\345\272\223UI\345\222\214\346\216\245\345\217\243\345\257\271\346\216\245.md" "b/docs/md/project/ai-knowledge/\347\254\2547\350\212\202\357\274\232\345\237\272\344\272\216AI\345\267\245\345\205\267\357\274\214\350\256\276\350\256\241\347\237\245\350\257\206\345\272\223UI\345\222\214\346\216\245\345\217\243\345\257\271\346\216\245.md" new file mode 100644 index 000000000..974f043ea --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\2547\350\212\202\357\274\232\345\237\272\344\272\216AI\345\267\245\345\205\267\357\274\214\350\256\276\350\256\241\347\237\245\350\257\206\345\272\223UI\345\222\214\346\216\245\345\217\243\345\257\271\346\216\245.md" @@ -0,0 +1,35 @@ +--- +title: 【更】第7节:基于AI工具,设计知识库UI和接口对接 +pay: https://t.zsxq.com/Jc7fE +--- + +# 《DeepSeek RAG 知识库》第7节:基于AI工具,设计知识库UI和接口对接 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/BeT7k](https://t.zsxq.com/BeT7k) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +基于我们要实现对话和知识的上传使用,使用AI工具完成UI页面的实现。 + +## 二、技术方案 + +找一个合适的喜欢的AI对话页面,截取上传到 AI 工具,并告知基于这样的 UI 效果完成页面的实现。之后在告诉 AI 处理接口的对接。当然也可以把接口一起交给 AI 工具进行处理。 + +- [https://www.deepseek.com/](https://www.deepseek.com/) +- [https://v0.dev/](https://v0.dev/) +- [https://chatglm.cn/](https://chatglm.cn/) +- [https://openai.itedus.cn/](https://openai.itedus.cn/) + +>其他更多也可以网络检索下。总有一款你是可以使用的。 + +## 三、功能实现 + +### 1. 对话页面 + +
+ +
diff --git "a/docs/md/project/ai-knowledge/\347\254\2548\350\212\202\357\274\232Git\344\273\223\345\272\223\344\273\243\347\240\201\345\272\223\350\247\243\346\236\220\345\210\260\347\237\245\350\257\206\345\272\223.md" "b/docs/md/project/ai-knowledge/\347\254\2548\350\212\202\357\274\232Git\344\273\223\345\272\223\344\273\243\347\240\201\345\272\223\350\247\243\346\236\220\345\210\260\347\237\245\350\257\206\345\272\223.md" new file mode 100644 index 000000000..ecf59d99a --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\2548\350\212\202\357\274\232Git\344\273\223\345\272\223\344\273\243\347\240\201\345\272\223\350\247\243\346\236\220\345\210\260\347\237\245\350\257\206\345\272\223.md" @@ -0,0 +1,34 @@ +--- +title: 【更】第8节:Git仓库代码库解析到知识库 +pay: https://t.zsxq.com/ByovV +--- + +# 《DeepSeek RAG 知识库》第8节:Git仓库代码库解析到知识库 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/EwqZH](https://t.zsxq.com/EwqZH) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +对知识库的解析进行扩展,增加Git仓库解析。用户填写Git仓库地址和账密,即可拉取代码并上传到知识库,之后就可以基于这套代码进行使用啦。 + +## 二、技术方案 + +引入 JGit 操作库到工程中,用于执行 Git 命令拉取代码仓库。之后对代码库文件进行遍历,依次解析分割上传到向量库中。 + +## 三、功能实现 + +### 1. 工程结构 + +### 2. 引入组件 + +```java + + org.eclipse.jgit + org.eclipse.jgit + 5.13.0.202109080827-r + +``` diff --git "a/docs/md/project/ai-knowledge/\347\254\2549\350\212\202\357\274\232\346\211\251\345\261\225OpenAI\346\250\241\345\236\213\345\257\271\346\216\245\357\274\214\344\273\245\345\217\212\345\256\214\346\225\264AI\345\257\271\346\216\245.md" "b/docs/md/project/ai-knowledge/\347\254\2549\350\212\202\357\274\232\346\211\251\345\261\225OpenAI\346\250\241\345\236\213\345\257\271\346\216\245\357\274\214\344\273\245\345\217\212\345\256\214\346\225\264AI\345\257\271\346\216\245.md" new file mode 100644 index 000000000..841bf2c1d --- /dev/null +++ "b/docs/md/project/ai-knowledge/\347\254\2549\350\212\202\357\274\232\346\211\251\345\261\225OpenAI\346\250\241\345\236\213\345\257\271\346\216\245\357\274\214\344\273\245\345\217\212\345\256\214\346\225\264AI\345\257\271\346\216\245.md" @@ -0,0 +1,33 @@ +--- +title: 【更】第9节:扩展OpenAI模型对接,以及完整AI对接 +pay: https://t.zsxq.com/YJxRy +--- + +# 《DeepSeek RAG 知识库》第9节:扩展OpenAI模型对接,以及完整AI对接 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
博客:[https://t.zsxq.com/1JLUq](https://t.zsxq.com/1JLUq) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +基于 Spring AI 扩展 OpenAI 模型对接,这样我们就可以使用一些代理的 ChatGPT 接口完成对话了。最终在完成全部接口与页面的对接。 + +## 二、技术方案 + +Spring AI 框架的好处,就是可以以统一的方式直接配置使用各类大模型。像是一些 Spring AI 没有直接对接的大模型,可以基于 one-api 配置转发,用统一 OpenAI 方式进行对接。 + +## 三、功能实现 + +### 1. 工程结构 + +### 2. 引入组件 + +```java + + org.springframework.ai + spring-ai-openai-spring-boot-starter + +``` \ No newline at end of file diff --git a/docs/md/project/ai-mcp-gateway/ai-mcp-gateway.md b/docs/md/project/ai-mcp-gateway/ai-mcp-gateway.md new file mode 100644 index 000000000..6ac01e671 --- /dev/null +++ b/docs/md/project/ai-mcp-gateway/ai-mcp-gateway.md @@ -0,0 +1,121 @@ +--- +title: AI MCP Gateway 网关服务系统 +lock: no +--- + +# 《AI MCP Gateway 网关服务系统》 - 为各类应用服务接口,便捷转换为MCP服务而设计。 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/SNsgH](https://t.zsxq.com/SNsgH) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +两年多了,从2023年1月起,小傅哥就开始关注AI、跟进AI,落地 AI 技术相关的场景项目。`做了 AI 问答自动回复助手`、`OpenAI 应用服务(含支付买额度 + OpenAI SDK 开发)`、`OpenAI 代码评审`、`Ai Agent 智能体(RAG、MCP)`,让一众伙伴积累到了丰富的AI应用开发技术,可以满足当下互联网AI应用开发招聘诉求。**那么接下来,关于 AI 小傅哥还要带着大家什么呢?🤔** + +
+ +
+ +**足够高频,互联网AI应用场景,必备项目!** + +现阶段,众多互联网公司把 AI 作为公司的战略目标,基于 AI 为公司各类场景提效。甚至不少公司要求程序员的编码,AI 占比要有30%以上(来自于某论坛研发分享)。还在各个部门设立 AI 应用创新组。 + +而 AI 的主要提效方式,则是自研实现或基于 Dify 搭建一套 AI Agent 智能体。通过智能体把公司的文档资料转换为 RAG 知识库,再通过 MCP 协议对接各类应用的服务接口。这样我们对 AI Agent 智能体下达命令后,就可以进行分析,规划,执行,直至产出最终的结果。更多关于智能体的实现介绍,可以参考[《AI Agent 智能体设计实现》](https://mp.weixin.qq.com/s/dwsfadYKs7Uy4YvHfLFsVQ) + +**死鬼,重点来啦!** + +公司里为了扩展智能体可提效的场景,就要把现有的公司的各类应用服务接口,`日志的`、`监控的`、`服务的`、`交易的`、`结算的`、`营销的`、`人群的`、`数据的`等等,都要转换为 AI Agent 智能体可识别的 MCP 服务接口。这样就可能有成百上千,成千上完,甚至几十万个接口要做实现。 + +那肯定不能每个接口都写一遍 MCP 服务!所以,对于这样的场景问题,公司里会做一套统一的 MCP Gateway 网关服务系统,其他个各类接口(http、rpc),都可以通过一键配置的方式转换为 MCP 协议类型的接口,被 AI 可以识别和使用。 + +
+ +
+ +而小傅哥这次带着你做的 AI 类项目,就是实现一套这样的 **MCP GateWay 网关服务系统**。小傅哥,会带着你,实现MCP服务,分析 MCP 协议,通过做AI服务代理、网页协议对接、JSON-RPC2标准等方式,把 MCP 协议厘清,之后在手把手的带着你编写响应式的 MCP Gateway 网关能力(鉴权也可以放到网关做)。 + +> 🧧 文末提供了,小傅哥所有编程实战项目获取方式,一次加入即可获得17个已完结的和本次新开展的。 + +## 一、能学到啥 + +该项目是 AI 应用场景下的通用技术服务组件类项目,以解决接口 MCP 协议转换而设计实现。在整个项目中,你可以积累到关于 MCP 协议的深度分析,学习分析协议的技巧和方案,并积累关于设计一个组件解决通用场景问题的能力。 + +- 【前端】基于 html、js、div、css,设计 MCP 协议分析页面。 +- 【前端】基于 html、js、div、css,构建一套服务端管理系统,便于 MCP 协议的录入和使用。 +- 【后端】MCP 协议的分析、理解、运用。掌握 MCP 开发和使用的能力。 +- 【后端】基于 MCP 协议的分析和网关设计诉求,构建网关服务库表。 +- 【后端】运用 DDD 分层架构,设计 MCP 网关服务系统。 +- 【后端】构建AI代理服务,断点调试分析 MCP 协议。 +- 【后端】设计 MCP 分析协议网页服务,链接 MCP 服务,观察 MCP 协议。 +- 【后端】基于 Flux 响应式接口,设计实现 MCP 协议的 sse 连接、initialize 初始化响应、tools 工具的 list 反馈和 call 调用等。 +- 【后端】提供 MCP 协议的动态录入和加载能力,以及提供录入接口组件,便于其他系统可快速录入。 +- 【后端】设计 MCP 网关协议鉴权服务,确保 MCP 服务使用的安全性。 +- 【后端】熟练使用 okhttp3、retrofit2 框架,动态对接 HTTP 服务接口,用于 MCP 协议 toos/call 工具调用。 +- 【后端】扩展学习 rpc 泛化调用,给 MCP 协议提供使用。其实有了这套东西,还可以对接如硬件设备 rs232 串口通信,让 MCP 服务,管理你的硬件设备。 +- 【运维】熟练使用 Docker 在本地和服务端的配置和部署应用,以及在本地构建前后端镜像。 +- 【运维】熟练掌握 Git、GitCode,对工程代码的管理,推送、拉取、切换分支、合并代码等操作。 + +此外,小傅哥对于每个章节还讲解了章节的诉求、流程的设计,之后再到方案实现和功能验证。并在每个章节留有作业让大家练习。当然这还没有完,你知道小傅哥这个架构师画图还是非常牛逼的,所以你还能看到各种画图的技巧,耳濡目染的把这些东西学习成自己的本事!~ + +## 二、项目介绍 + +本项目是 AI Agent 智能体,关于 MCP 协议对接的通用网关服务项目,以解决各类业务接口便捷转换为 MCP 协议而设计实现。通过这样的配置,可以大大的简化从普通http、rpc接口到 MCP 协议的转换操作。这样的项目,也是每个互联网公司在做 AI Agent 智能体时,必备的基础设施项目。 + +### 1. 更新计划 + +本项目目前已经做了基础的筹备和验证,计划于10.26日开始更新课程。整体课程预计在20+节左右。带着你完整的实现一套 AI MCP Gateway 网关服务项目。 + +### 2. 项目资料 + +#### 2.1 协议分析 - 页面 + +
+ +
+ +- 编写了一套网页对接 MCP 服务的页面,把以前直接在 AI Agent 配置 MCP 协议使用的过程,通过页面一步步对接和使用的方式进行展示。 +- 有了这样一个操作过程步骤,你可以更加清晰的了解到 MCP 的执行过程,也能更好的为后续做 MCP 网关服务实现打下基础。 + +#### 2.2 协议分析 - 代理 + +
+ +
+ +- 为了更好的体现出 AI 和 MCP 的交互,这里小傅哥会带着你做一个 AI 的代理接口,来调试观察 MCP 协议的传输。 + +#### 2.3 初始版本 - 案例 + +
+ +
+- 小傅哥这里先做了一个初始的 demo 版本,跑通 MCP 网关,后续会设计整套 DDD 架构,完整整体协议和服务的对接。 + +## 三、课程大纲 + +**不同于网上demo项目。小傅哥带着你做的项目,是一步步,一个个章节的带着大家从0到1的方式,进行分析、设计和开发。是一个纯手把手教大家学习实战技术的项目!** 大家可以先看看课程的大纲,就知道可以学习到哪些东西了。 + +- 第1节:项目功能需求分析 +- 第2节:项目系统架构设计 +- 第3节:MCP 功能服务实现 +- 第4节:AI 服务代理实现 +- 第5节:通过AI 服务代理,分析 MCP 协议 +- 第6节:通过设计网页对接,分析 MCP 协议 +- 第7节:通过 json-rpc2 标准,官网资料,总结 MCP 协议 +- 第8节:设计网关服务端系统,讲解模块关系 +- 第9节:设计拆分领域模型结构 +- 第10节:设计需求服务库表 +- 第11节:网关协议功能编写(1、2、3、4),分步骤设计实现 +- 第12节:网关协议与数据库表对接 +- 第13节:网关协议与http接口对接 +- 第14节:网关协议与rpc接口对接 +- 第15节:网关协议能力管理端编写(1、2、3、4) +- 第16节:MCP 网关服务打包上线 + +随着课程开展,陆续更新课程目录,也会有一些新的内容加入。 + +>课程包括;视频、小册、1 对 1 答疑解惑、专属VIP项目交流群,并且提供简历编写模板结构的一条龙🐲服务。让你学习后,直接拉开与还在玩具项目其他人的差距,面试脱颖而出提高竞争力!! + diff --git a/docs/md/project/ai-mcp-gateway/none.md b/docs/md/project/ai-mcp-gateway/none.md new file mode 100644 index 000000000..f64218b2f --- /dev/null +++ b/docs/md/project/ai-mcp-gateway/none.md @@ -0,0 +1,15 @@ +--- +title: 新章节,编写中 +lock: no +--- + +# 新章节,编写中 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、前言 + +... 新章节,编写中 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2541-1\350\212\202\357\274\232\347\275\221\345\205\263\351\234\200\346\261\202\345\210\206\346\236\220.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2541-1\350\212\202\357\274\232\347\275\221\345\205\263\351\234\200\346\261\202\345\210\206\346\236\220.md" new file mode 100644 index 000000000..bba7f38a4 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2541-1\350\212\202\357\274\232\347\275\221\345\205\263\351\234\200\346\261\202\345\210\206\346\236\220.md" @@ -0,0 +1,64 @@ +--- +title: 【更】第1-1节:网关需求分析 +pay: https://t.zsxq.com/f6fiZ +--- + +# 《AI MCP Gateway 网关服务系统》第1-1节:网关需求分析 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/i8tV1](https://t.zsxq.com/i8tV1) + +>大家好,我是技术UP主小傅哥。 + +今天是我们 **《AI MCP Gateway 网关服务系统》** 项目学习的第1节课程,小傅哥会带着大家,以互联网公司正规的承接产品需求到开发部署上线的流程,带着大家以第一主人公视角的方式进行学习。这样既可以保证你学习到项目内容,也能了解到公司里正规的开发模式,以后进入到公司也可以很好的融入团队,承接项目需求。加油💪🏻!让我们开启新项目之旅! + +## 一、本章诉求 + +站在产品视角,分析 AI MCP Gateway 网关服务系统,这样一个产品功能需求的背景、诉求和目的。 + +需求是怎么来的呢? + +作为互联网公司里的研发,我们通常都是从业务产品经理那承接需求,评审 PRD 文档,之后研发进行详细设计,给出设计文档在评审,评审通过后开始进入编码开发,以及推进后续的测试和上线。 + +那么,还有一类需求是不需要业务产品经理的,往往是纯技术产品经理或者研发和技术一起驱动的,这类的需求包括,系统的重构、组件的设计、框架的升级等。他们虽然也是需求,但不直接影响到产品经理的业务需求,所以往往由技术产品或者研发推动。 + +所以,像是 AI MCP Gateway 网关服务系统,是附属于 AI 应用开发部门的项目,一般是由 AI 技术产品经理推动,这类产品经理,往往比纯业务产品经理要多一些技术储备的。虽然他们编码不熟练,但对技术是有不错的储备,可以很好的规划和推进技术产品。 + +## 二、项目背景 + +MCP 协议的定义和发布,改变了我们使用 AI 的形态。 + +LLM 大模型第一次以 chatgpt 问世时,就足以震撼到我们。它具备各行各业的知识储备,可以识别人类语言,可以完成逻辑关系推理。在很长一段时间里,我们都是把问题抛给大模型,大模型回答后,我们在根据它的回复,复制粘贴到具体的场景进行处理。 + +但大模型不能无中生有,不能根据你的提问,直接帮你完成最终的处理。如;帮我查询最近一天内数据库账户表写入的数据量,这是做不到的,因为大模型并不能直接连接到我们的数据库或者其他任何服务。 + +在 2023 年前,如果想让大模型和程序代码互动,我们经常做的方式是写提示词,告诉大模型我的程序具备什么样的能力,有什么样的接口格式,你需要分析我的问题,并按照最终的执行给出结构化参数。json 格式为 `{"function":"query_user_account","arguments":{"sc":"渠道值"}}` 之后再根据大模型的结果调用对应的程序方法。不过以上方式执行起来的误差较大,经常是需要慢慢微调提示词。 + +到了 2023年6月,OpenAI 发布 gpt-3.5-turbo-0613 模型,给 API 的调用提供了 Function Calling 的能力,只需要在请求 API 的时候传入 functions 参数,告知大模型本地有哪些函数方法可以被调用使用即可。到了 2023年11月,gpt-3.5-turbo-1106 发布,这回开始支持 tools 函数,我们可以在提问的时候,进行网络检索,天气对接。但是这些功能代码, 都被嵌入到大模型调用中,编写起来耦合在一块,维护起来很麻烦。 + +直至到2024年11月,Anthropic 发布了 MCP 协议,将 tools 的封装单独抽离到独立的服务,这种服务称之为 MCP 服务,然后通过远程协议的模式提供给大模型调用。而 MCP 协议的主要作用是将服务转换为可以被大模型识别的格式结构(后面章节会细分析 MCP 协议)。 + +**MCP 为何重要?** + +- MCP 在构建或与 AI 应用程序或代理集成时减少了开发时间和复杂性。 +- MCP 提供对数据源、工具和应用程序生态系统的访问,这将增强功能并改善最终用户体验。 +- MCP 可产生功能更强大的 AI 应用程序或代理,它们可以在必要时访问您的数据并代表您采取行动。 + +
+ +
+ +自从有了 MCP 协议以后,市面上开始出现各类的 AI Agent 智能体服务,如被大家熟知的 `Dify`、`Corz`、`Trae.ai/Cursor` 等。这些都是通用的智能体服务,可以解决市面上大部分通用场景问题。 + +到这以后,各个公司开启了自己的 AI Agent 智能体实现,对公司里自身业务场景进行提效。如账户服务、交易订单、计息计罚、还款计划等,做成智能客户和AI运营工具,都可以为企业提效。那么这里就有一个问题,这些接口想被大模型识别,就要开发为 MCP 协议服务,只有 MCP 协议才能被大模型识别的协议,公司里的各项服务要想被大模型调用,就要编写为一个个的 MCP Server 服务端,这个工作量是非常大的。 + +
+ +
+ +所以,为了解决需要把大量接口开发成 MCP 协议服务的工作,我们可以设计一个 MCP 网关服务系统。它的核心工作原理在于,设计实现一套 MCP 协议的统一服务入口,管理和使用动态化注册的 HTTP/RPC 服务接口。MCP 协议的接口会被接入 MCP 服务的大模型,进行调用,核心过程包括;`建立sse连接创建会话ID`、`初始化服务`、`获取 tools 工具列表`、`响应工具调用`。这些内容,小傅哥会在后续的协议分析中带着大家学习。 + +综上,当我们有了一套 MCP 网关以后,就可以把我们各项所需的接口,快速🔜转换为 MCP 协议,配置给 AI Agent 智能体系统进行使用啦。这也是我们本次课程的最终目的。 + + diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2541-2\350\212\202\357\274\232\347\263\273\347\273\237\345\273\272\346\250\241\350\256\276\350\256\241.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2541-2\350\212\202\357\274\232\347\263\273\347\273\237\345\273\272\346\250\241\350\256\276\350\256\241.md" new file mode 100644 index 000000000..2ad3c04f6 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2541-2\350\212\202\357\274\232\347\263\273\347\273\237\345\273\272\346\250\241\350\256\276\350\256\241.md" @@ -0,0 +1,24 @@ +--- +title: 【更】第1-2节:系统建模设计 +pay: https://t.zsxq.com/FKXfD +--- + +# 《AI MCP Gateway 网关服务系统》第1-2节:系统建模设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/74OwC](https://t.zsxq.com/74OwC) + +>大家好,我是技术UP主小傅哥。 + +## 一、本章诉求 + +按照 AI MCP Gateway 网关功能实现诉求,对系统服务进行建模设计。包括;用例图、四色建模拆解、工程模型分析。 + +## 二、架构选型 + +此项目会选择 DDD 领域驱动设计的方式,进行系统建模和功能设计。那为啥选择 DDD 架构呢? + +因为 DDD 架构的四色建模方法可以更好的分析场景需求模型,同时它对应的六边形架构设计,非常合理的划分了微服务的各项单元功能。如;http、redis、mysql等都有自己的分层规划,同时又为领域服务与基础设施层的设计做了依赖倒置(这样的思想在Spring源码中很多),当我们在领域模块中实现服务时,就可以专心于各个模块的内聚服务了。 + +关于 DDD 可以在这部分补充学习;[https://bugstack.cn/md/road-map/ddd-guide-01.html](https://bugstack.cn/md/road-map/ddd-guide-01.html) - `有系列的5节课程` \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2541-3\350\212\202\357\274\232\347\275\221\345\205\263\345\215\217\350\256\256\350\241\250.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2541-3\350\212\202\357\274\232\347\275\221\345\205\263\345\215\217\350\256\256\350\241\250.md" new file mode 100644 index 000000000..1e517dffe --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2541-3\350\212\202\357\274\232\347\275\221\345\205\263\345\215\217\350\256\256\350\241\250.md" @@ -0,0 +1,25 @@ +--- +title: 【更】第1-3节:网关协议表 +pay: https://t.zsxq.com/YwZQE +--- + +# 《AI MCP Gateway 网关服务系统》第1-3节:网关协议表 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/pipVW](https://t.zsxq.com/pipVW) + +## 一、本章诉求 + +设计 AI MCP Gateway 网关服务,所需的核心必备的数据库表。以用于存储,mcp 到 http 的协议转换处理,如,用户通过 sse 请求指定的网关 ID 对应的服务,则可以调用到对应的 http 服务接口。 + +## 二、功能设计 + +如图,库表驱动下的业务; + +
+ +
+ +- 首先,以用户为入口,进行网关配置,他关心的是权限,以及配置的 http 怎么映射到 mcp 服务。 +- 之后,mcp 服务对应的 http 接口能力和出入参字段,都需要给出对应的描述,这样 ai 调用 mcp 服务,才能拿到工具列表说明以及进行调用。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2541-4\350\212\202\357\274\232\345\215\207\347\272\247\347\275\221\345\205\263\345\272\223\350\241\250.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2541-4\350\212\202\357\274\232\345\215\207\347\272\247\347\275\221\345\205\263\345\272\223\350\241\250.md" new file mode 100644 index 000000000..c2dfe56ee --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2541-4\350\212\202\357\274\232\345\215\207\347\272\247\347\275\221\345\205\263\345\272\223\350\241\250.md" @@ -0,0 +1,25 @@ +--- +title: 【更】第1-4节:升级网关库表 +pay: https://t.zsxq.com/eeZPc +--- + +# 《AI MCP Gateway 网关服务系统》第1-4节:升级网关库表 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/QCvqV](https://t.zsxq.com/QCvqV) + +## 一、本章诉求 + +增强网关库表设计,拆分出工具(tool)、工具协议类型(http),让网关配置可以支持一个网关下多个工具,工具可以绑定和切换到不同的协议上(1:n)。细节上会在 tool 上设计协议类型,以便于扩展支持不同的协议对接。 + +## 二、升级设计 + +如图,从旧版库表升级到新版库表的结构; + +
+ +
+ +- 旧版的设计中,是有一个 mcp_protocol_registry 协议注册,里面包含了工具描述和 http 接口协议信息。功能理解和编码实现上会比较直观,适合我们最开始让大家上手学习。 +- 新版的设计中,拆分了 tool 工具表,也就是一个网关(mcp_gateway)可以对应多个 tool 表,tool 表可以单独配置对应的协议信息,可以是 http,也可以是其他的。后续扩展的时候增加新的表即可。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2542-1\350\212\202\357\274\232MCP\346\234\215\345\212\241\345\256\236\347\216\260.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2542-1\350\212\202\357\274\232MCP\346\234\215\345\212\241\345\256\236\347\216\260.md" new file mode 100644 index 000000000..f96b7af4d --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2542-1\350\212\202\357\274\232MCP\346\234\215\345\212\241\345\256\236\347\216\260.md" @@ -0,0 +1,46 @@ +--- +title: 【更】第2-1节:MCP服务实现 +pay: https://t.zsxq.com/QdTsG +--- + +# 《AI MCP Gateway 网关服务系统》第2-1节:MCP服务实现 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/mUHg8](https://t.zsxq.com/mUHg8) + +>大家好,我是技术UP主小傅哥。 + +进入到第二部分开始,小傅哥会带着大家通过各种手段对 MCP 协议进行细致的实践验证的方式进行分析。这部分包括了实现一个 MCP 服务,完成 MCP 服务的对接,通过代理的方式调试对接中 MCP 接口协议的数据,以及通过开发网页测试工具对接协议等。最后在进行 json-rpc2 定义的协议标准讲解。通过这样一套内容串联,你会对 MCP 有非常强的理解,也能为后面做 MCP 网关实现的学习打下良好的基础。 + +## 一、本章诉求 + +基于 Spring AI 框架,实现一个简单的 MCP 服务,为后续做协议的分析和验证进行使用。 + +因为协议分析,主要包括了通信的格式结构,如通信的入参,所以实现这样的一个 MCP 服务,会多增加一些入参类型,便于以后做网关设计时使用。 + +通常来讲,这部分的操作,也可以理解为是技术调研验证阶段。当我们要实现一个大的功能服务时,就要先想办法把复杂的逻辑拆分为独立的细小单元。也就是软件第一设计原则康威定律提到的,问题越小,越容易被理解和处理。所以,当你想在此项目拓展功能,或则自己在公司承接需求的时候,也可以使用这样的方式进行辅助完成系统的详细设计。 + +## 二、协议说明(MCP) + +文档:[https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html) - 可以阅读官网文档,这里就包含了如何实现 MCP 服务,并提供了小案例。 + +```java + + org.springframework.ai + spring-ai-starter-mcp-server + +``` + +Spring AI MCP(模型上下文协议)服务启动器为在 Spring Boot 应用程序中设置 MCP 服务器提供了自动配置功能。它实现了 MCP 服务器功能与 Spring Boot 自动配置系统的无缝集成。 + +MCP 服务器启动器提供: +- MCP 服务器组件的自动配置 +- 支持同步和异步操作模式 +- 多种传输层选项 +- 灵活的工具、资源和提示规范 +- 更改通知功能 + +Spring AI MCP 框架是对 MCP 协议的实现,可以把我们实现的服务功能,以 MCP 格式进行转换处理。与我们要实现的 AI MCP Gateway 不同的是,Spring AI MCP 固定的框架,每一个 MCP 都要独立完成开发,而 AI MCP Gateway 是一个通用协议转换的服务,只需要配置就可以完成从接口(http/rpc)到 MCP 协议的转换。 + +但为了更好的理解 MCP 协议,我们可以先基于 Spring AI MCP 框架,来实现一个简单的 MCP 并陆续完成对接使用,再到协议分析和设计 AI MCP Gateway 网关服务。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2542-2\350\212\202\357\274\232MCP\344\273\243\347\220\206\350\260\203\347\224\250.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2542-2\350\212\202\357\274\232MCP\344\273\243\347\220\206\350\260\203\347\224\250.md" new file mode 100644 index 000000000..697f8a3ec --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2542-2\350\212\202\357\274\232MCP\344\273\243\347\220\206\350\260\203\347\224\250.md" @@ -0,0 +1,25 @@ +--- +title: 【更】第2-2节:MCP代理调用 +pay: https://t.zsxq.com/OkMLy +--- + +# 《AI MCP Gateway 网关服务系统》第2-2节:MCP代理调用 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/UAbZd](https://t.zsxq.com/UAbZd) + +>大家好,我是技术UP主小傅哥。 + +## 一、本章诉求 + +实现一个 MCP 客户端,用于对接 MCP 服务端,并通过代理 AI 接口的方式完成调用。该方案旨在调试 AI 调用 MCP 过程中的通信的请求接口协议,便于查看和分析相关数据。 + +## 二、流程设计 + +
+ +
+ +- 如图,是整个 Ai Client 以 Tools 工具,对接 MCP 的流程结构图。也是 Ai Agent 智能体最基础配置。如果感兴趣 [Ai Agent 项目](https://t.zsxq.com/GwNZp),也可以在星球里学习。 +- 之后,我们要在整个实现过程中,为 Ai 接口,通过 SpringBoot HTTP 方式做一层代理。这样在调用 MCP 的过程中,我们就可以清楚的知道这个过程的协议数据结构了。`代理的方式可以用在很多场景,还有一种是浏览器代理的主动安全扫描技术,甚至你服务器的应用暴漏了数据库密码都可以被扫描出来。` [扩展知识:安全漏洞扫描,他怎么拿到了我的数据库密码?](https://bugstack.cn/md/road-map/13scan-jdumpspider.html) diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2542-3\350\212\202\357\274\232MCP\351\200\232\344\277\241\345\215\217\350\256\256.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2542-3\350\212\202\357\274\232MCP\351\200\232\344\277\241\345\215\217\350\256\256.md" new file mode 100644 index 000000000..ff83dcb39 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2542-3\350\212\202\357\274\232MCP\351\200\232\344\277\241\345\215\217\350\256\256.md" @@ -0,0 +1,39 @@ +--- +title: 【更】第2-3节:MCP通信协议(json-rpc2) +pay: https://t.zsxq.com/9PlXx +--- + +# 《AI MCP Gateway 网关服务系统》第2-3节:MCP通信协议(json-rpc2) - debug 调试 Spring AI 源码 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/wwiTt](https://t.zsxq.com/wwiTt) + +>大家好,我是技术UP主小傅哥。 + +## 一、本章诉求 + +学习了解 JSON-RPC 2.0 消息协议定义,并通过工程实践调试(debug)验证的方式,分析 MCP 通信协议过程。 + +## 二、通信协议 + +MCP 等同于为 AI 安装上了手和脚,使其这个 AI 大脑具备了行为能力的执行。所以,25年以来,AI Agent 智能体才得以落地。 + +MCP 定义了一种标准化的通信协议,使客户端和服务器能够以一致且可预测的方式交换消息。这种标准化的定义对整个AI和服务的交互性至关重要。 + +而通信就要有数据的交互格式,MCP 采用的是 JSON-RPC 2.0 协议,作为客户端和服务端之间素有的通信消息格式。JSON-RPC 是一种轻量级的远程过程调用协议,采用 JSON 编码,易于阅读和调试、与编程语言无关,支持在任何编程环境中实现(Java、Python、Go、JS...),且成熟完善,规范明确,适合广泛使用。 + +
+ +
+ +> 在本节代码工程下,docs/pdf -> JSON-RPC 2.0 Specification.pdf 详细介绍了 json-rpc 2.0 通信协议,可以查阅。也可以阅读它的官网,但打开会卡一些。[https://www.jsonrpc.org/specification](https://www.jsonrpc.org/specification) + +### 1. 调用协议 + +
+ +
+ +- 首先,很多通信协议,也包括业务工程的流程处理,往往第一步是建立一个验证关系,拿到整个后续链路请求的会话ID,之后以会话ID作为全流程的串联关系进行通信。这和图中的 MCP 协议调用过程是一样的。 +- 之后,MCP 客户端和服务端的交互,分为4个步骤;初始化(连接)、发现工具列表(能力)、执行工具调用、断开连接。也就是说 AI 要拿到你配置的工具的 MCP 的能力,这样才能根据你的请求决定调用哪个 MCP 服务,以及处理 MCP 服务返回的结果。 diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-10\350\212\202\357\274\232\350\257\204\345\256\241\345\272\223\350\241\250\345\215\207\347\272\247\344\273\243\347\240\201.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-10\350\212\202\357\274\232\350\257\204\345\256\241\345\272\223\350\241\250\345\215\207\347\272\247\344\273\243\347\240\201.md" new file mode 100644 index 000000000..d92c1ebf5 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-10\350\212\202\357\274\232\350\257\204\345\256\241\345\272\223\350\241\250\345\215\207\347\272\247\344\273\243\347\240\201.md" @@ -0,0 +1,33 @@ +--- +title: 【更】第3-10节:评审库表升级代码 +pay: https://t.zsxq.com/FxVTE +--- + +# 《AI MCP Gateway 网关服务系统》第3-10节:评审库表升级代码 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/PzIhJ](https://t.zsxq.com/PzIhJ) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +针对升级的库表结构,调整工程代码`基础设施层`(dao、po、mapper),重新设计`领域层值对象`,附带调整InitializeHandler、ToolsListHandler、ToolsCallHandler的数据使用。 + +本节是一个很好的练习篇,原有的功能、流程、结构都不变,只是把库表升级,之后针对这些数据的时候重新定义对象。所以,这一节我们采用互联网公司中的代码评审方式来讲解变更信息,你可以在这个过程中,对比代码变化,来编写你的代码。也可以在学习文档和视频后,自己来编写。可能在这个过程中会遇到错误,但这些错误会驱动你深入的debug调试,快速的积累核心知识。这节学习透彻了以后,后面的章节将会非常好学习。 + +git 教程:[https://bugstack.cn/md/road-map/git.html](https://bugstack.cn/md/road-map/git.html) + +## 二、流程设计 + +如图,库表升级对于领域功能的改造; + +
+ +
+ +- InitializeHandler 旧版是通过网关配置和工具两部分拿到基础信息,新版直接从网关配置拿到即可。 +- ToolsListHandler 旧版从 McpGatewayToolConfigVO 定义的工具和映射,拿到 list 数据,之后做的拆分。新版定义了 McpToolConfigVO - 工具部分、McpToolProtocolConfigVO - 协议部分,有工具引入协议信息。 +- ToolsCallHandler 这部分增强了查询,通过 gatewayId 网关ID、toolName 工具名称,来获取到当前当前要调用的协议信息。这里查询的是 http 协议。如果对接了更多的协议,这部分要做策略处理。 + diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-11\350\212\202\357\274\232\344\274\232\350\257\235\345\206\205\345\256\271\347\274\226\346\216\222\345\244\204\347\220\206.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-11\350\212\202\357\274\232\344\274\232\350\257\235\345\206\205\345\256\271\347\274\226\346\216\222\345\244\204\347\220\206.md" new file mode 100644 index 000000000..31e04239c --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-11\350\212\202\357\274\232\344\274\232\350\257\235\345\206\205\345\256\271\347\274\226\346\216\222\345\244\204\347\220\206.md" @@ -0,0 +1,33 @@ +--- +title: 【更】第3-11节:会话内容编排处理 +pay: https://t.zsxq.com/7Oceg +--- + +# 《AI MCP Gateway 网关服务系统》第3-11节:会话内容编排处理 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/pxAAd](https://t.zsxq.com/pxAAd) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +将目前在 MCP 网关服务接口管理(McpGatewayController)中的 handleMessage 下的逻辑代码,抽取到 case 进行编排处理,减轻 Controller 层的代码压力。 + +
+ +
+ +这里有一个设计思想,Controller 接口实现的控制器层,在处理复杂逻辑的时候,都会调用很多 Service 服务。无论这个服务是贫血模型的 mvc 架构,还是充血模型的 ddd 架构。那么为了减轻 Controller 的职责,不至于让一个 Controller 的代码逻辑过于繁重,因此引入了 case 编排层。上承接 Controller 层的出入参需求,下处理 domian 领域服务的编排处理。这一层甚至不需要额外的对象包,它可以承接 Controller 的 DTO 对象作为出入参,也可以使用领域层的对象。 + +## 二、流程设计 + +如图,会话消息处理流程设计; + +
+ +
+ +- 首先,这部分的重点在于将原本的会话服务接口下的消息处理,直接调用 domain 领域层的部分,重构迁移到 case 层通过规则树的方式分摊 trigger 触发器下的 Controller 的压力。 +- 之后,这部分的 case 编排和会话 Session 处理的架构设计方案是一致的,使用的是星球「码农会锁」扳手工程下的通用设计模式组件。这部分的设计,只要具备编码式的规则树结构,可以划分职责的方式完成节点的拆分,就都可以作为编排设计工具使用。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-12\350\212\202\357\274\232\351\211\264\346\235\203\345\212\237\350\203\275\351\242\206\345\237\237\346\234\215\345\212\241.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-12\350\212\202\357\274\232\351\211\264\346\235\203\345\212\237\350\203\275\351\242\206\345\237\237\346\234\215\345\212\241.md" new file mode 100644 index 000000000..732cc055d --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-12\350\212\202\357\274\232\351\211\264\346\235\203\345\212\237\350\203\275\351\242\206\345\237\237\346\234\215\345\212\241.md" @@ -0,0 +1,27 @@ +--- +title: 【更】第3-12节:鉴权功能领域服务 +pay: https://t.zsxq.com/gLU35 +--- + +# 《AI MCP Gateway 网关服务系统》第3-12节:鉴权功能领域服务 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/I9dRQ](https://t.zsxq.com/I9dRQ) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +设计 MCP 网关通信过程中的鉴权领域功能,包括;权限注册、请求限流、权限校验,这样3个主要的服务能力。领域层设计好后,就可以让 case 串联逻辑完成权限功能的使用了。 + +## 二、流程设计 + +如图,关于鉴权功能的领域处理; + +
+ +
+ +- 首先,设计对鉴权领域的功能,校验阶段,判断当前用户传递 api_key 是否为配置的有效key,是否开启认证,是否在有效期。 +- 之后,是注册 api_key 的处理,以及 api_key 的使用限流。数据库表中设计了,速率限制(次/小时) 可以按需设计你的。`这部分值在使用中会转换为多少秒一次,不过程序调用过程中,一般会达到毫秒。所以这个值可以适当放大` \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-13\350\212\202\357\274\232\351\211\264\346\235\203\345\212\237\350\203\275\347\274\226\346\216\222\345\244\204\347\220\206.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-13\350\212\202\357\274\232\351\211\264\346\235\203\345\212\237\350\203\275\347\274\226\346\216\222\345\244\204\347\220\206.md" new file mode 100644 index 000000000..12e169216 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-13\350\212\202\357\274\232\351\211\264\346\235\203\345\212\237\350\203\275\347\274\226\346\216\222\345\244\204\347\220\206.md" @@ -0,0 +1,27 @@ +--- +title: 【更】第3-13节:鉴权功能编排处理 +pay: https://t.zsxq.com/AycUA +--- + +# 《AI MCP Gateway 网关服务系统》第3-13节:鉴权功能编排处理 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/wO9Cw](https://t.zsxq.com/wO9Cw) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在 case 的 mcp 模块下,将 auth 鉴权功能,串联到 `session 会话创建`、`message 消息处理中`去。让会话创建的时候可以校验 apiKey 的可用性,以及在消息处理中使用限流控制请求频次。 + +## 二、流程设计 + +如图,将鉴权功能串联到case编排中; + +
+ +
+ +- 首先,是 api 入参这部分,都需要添加一个 `apiKey` 作为后缀的请求入参。会话请求阶段,是用户配置的请求连接传递进来的,而后续的消息处理部分,是我们在会话阶段把 apiKey 拼接到请求地址里去的。 +- 之后,消息处理阶段,根据请求的 apiKey 做响应的限流处理。`基本你在各个官网申请的 mcp 服务,如百度搜索,都会让你创建一个 apiKey 针对你的这个 key 做一些列的流程处理。包括还会对你请求的数据做一个日志记录。` \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-14\350\212\202\357\274\232\350\247\243\346\236\220Swagger\346\240\207\345\207\206OpenAPI\345\215\217\350\256\256.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-14\350\212\202\357\274\232\350\247\243\346\236\220Swagger\346\240\207\345\207\206OpenAPI\345\215\217\350\256\256.md" new file mode 100644 index 000000000..d168eb169 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-14\350\212\202\357\274\232\350\247\243\346\236\220Swagger\346\240\207\345\207\206OpenAPI\345\215\217\350\256\256.md" @@ -0,0 +1,34 @@ +--- +title: 【更】第3-14节:解析Swagger标准OpenAPI协议 +pay: https://t.zsxq.com/wvb2k +--- + +# 《AI MCP Gateway 网关服务系统》第3-14节:解析Swagger标准OpenAPI协议 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/hTWme](https://t.zsxq.com/hTWme) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在前面章节,我们实现了关于 AI MCP 网关,解决 HTTP 协议向 MCP 协议的转换处理。相关的协议(HTTP)数据存储在数据库表中。那么现在的另外一个问题就是,数据库表里的协议映射数据应该怎么录入进去。 + +这个录入方案也比较多,比如,提供一个页面,让用户自己手动输入相关的协议映射信息。也可以提供一个 SDK 组件,让 HTTP 接口服务端引入,之后自动上报。之后这里还有一种方案,是通过 Swagger 导出标准 OpenAPI 协议接口 json 文件,以文件数据的方式,录入到数据库表中。 + +本节,我们先来处理关于 Swagger 的使用到提供一个工具包把 OpenAPI 的 JSON 转换为我们的设计的库表对应对象的关系。`本节操作转换的工具类包,不非得手动编码,能理解和使用即可`。 + +## 二、工具介绍(Swagger) + +官网:[https://swagger.io/](https://swagger.io/) + +Swagger 是一个开源的API 设计和文档工具,它可以帮助开发人员更快、更简单地设计、构建、文档化和测试 RESTful API。以及可以导出 [OpenAPI](https://openapi.apifox.cn/) 标准的协议接口 JSON 文件。 + +它的接入方式也非常简单,只要在项目工程中引入 Swagger 相关的 POM 文件,在工程启动后就可以访问 Swagger 页面,查看 HTTP 接口服务。如果希望接口描述信息更为准确,也可以在接口和出入参对象(属性)上添加上相关的注解描述。这个描述信息对我们 MCP 协议更为重要。 + +
+ +
+ +如图,我们需要的就是这份标准的 OpenAPI 接口的 JSON 文件,使用它解析并转换为目前 ai mcp gateway 库表结构中设计的 http 协议和字段映射关系。你可以把这部分的解析,当做一个工具包使用。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-15\350\212\202\357\274\232\345\215\217\350\256\256\345\237\237-\345\215\217\350\256\256\350\247\243\346\236\220\345\244\204\347\220\206.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-15\350\212\202\357\274\232\345\215\217\350\256\256\345\237\237-\345\215\217\350\256\256\350\247\243\346\236\220\345\244\204\347\220\206.md" new file mode 100644 index 000000000..eeb0f4957 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-15\350\212\202\357\274\232\345\215\217\350\256\256\345\237\237-\345\215\217\350\256\256\350\247\243\346\236\220\345\244\204\347\220\206.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第3-15节:协议域-协议解析处理 +pay: https://t.zsxq.com/dEsG8 +--- + +# 《AI MCP Gateway 网关服务系统》第3-15节:协议域-协议解析处理 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/wGt6C](https://t.zsxq.com/wGt6C) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +设计**协议域**,定义分层结构,用于承接协议的解析、存储、使用等场景功能。`在整个 DDD 架构下,我们会不断的思考这些内容的功能域设计,而不是一些单一的原则方法。` + +这一节我们把前面做的解析协议的案例代码,按照协议域的分层结构,拆分编写对应的功能逻辑。 + +## 二、流程设计 + +如图,设计协议域,封装解析逻辑(其他流程后续处理); + +
+ +
+ +- 首先,划分出【协议域】,增加协议解析、协议存储,对应的单一职责的接口定义。 +- 之后,把上一节的协议解析的案例代码,按照如图所示的结构,拆分设计。这里解析还增加了 rpc 包,是一个示意,如果后续大家做其他场景的接口对应的协议解析,可以都在这个结构下增加策略实现。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-16\350\212\202\357\274\232\345\215\217\350\256\256\345\237\237-\345\215\217\350\256\256\345\255\230\345\202\250\345\244\204\347\220\206.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-16\350\212\202\357\274\232\345\215\217\350\256\256\345\237\237-\345\215\217\350\256\256\345\255\230\345\202\250\345\244\204\347\220\206.md" new file mode 100644 index 000000000..3d4b804c2 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-16\350\212\202\357\274\232\345\215\217\350\256\256\345\237\237-\345\215\217\350\256\256\345\255\230\345\202\250\345\244\204\347\220\206.md" @@ -0,0 +1,27 @@ +--- +title: 【更】第3-16节:协议域-协议存储处理 +pay: https://t.zsxq.com/3kNZE +--- + +# 《AI MCP Gateway 网关服务系统》第3-16节:协议域-协议存储处理 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/wGt6C](https://t.zsxq.com/wGt6C) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在**协议域**添加协议存储服务,以及验证存储后的数据,在 AI MCP 网关,整个流程中完成调用处理。其实这部分的内容,就是在串联流程。协议解析、协议存储,存储后的数据到数据库表中的结构,是否还可以按照约定的方式转换为可以被 MCP 协议识别的结构。之后再继续完成调用的处理。 + +## 二、流程设计 + +如图,从协议解析到协议存储流程设计; + +
+ +
+ +- 首先,本节的重点是要验证,协议解析 -> 协议存储 -> 协议使用,是否可以完整整个链路调用处理。 +- 所以,在这一节完成协议存储后,我们就要做一个完整的案例,来验证整个数据解析存储和使用是否可以通过。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-17\350\212\202\357\274\232\347\275\221\345\205\263\345\237\237-\351\205\215\347\275\256\346\225\260\346\215\256\345\255\230\345\202\250(CRUD).md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-17\350\212\202\357\274\232\347\275\221\345\205\263\345\237\237-\351\205\215\347\275\256\346\225\260\346\215\256\345\255\230\345\202\250(CRUD).md" new file mode 100644 index 000000000..5c81f45ba --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-17\350\212\202\357\274\232\347\275\221\345\205\263\345\237\237-\351\205\215\347\275\256\346\225\260\346\215\256\345\255\230\345\202\250(CRUD).md" @@ -0,0 +1,28 @@ +--- +title: 【更】第3-17节:网关配置域-配置数据存储(CRUD) +pay: https://t.zsxq.com/BGsjf +--- + +# 《AI MCP Gateway 网关服务系统》第3-17节:网关配置域-配置数据存储(CRUD) + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/wGt6C](https://t.zsxq.com/wGt6C) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +本节我们要新增加一个网关配置域,对网关、工具提供基本的配置操作,也就是 CRUD 的代码从领域层操作数据库的过程。这部分的内容实现,为的就是在后续提供的 AI MCP 网关运营服务上,可以在后台配置出整个网关服务。 + +## 二、流程设计 + +如图,网关配置域功能流程设计; + +
+ +
+ +- 首先,我们知道的,一整套的 AI MCP 网关配置,包括了,协议的解析存储和使用,之后是鉴权,但最开始是有一个网关的配置的,也就是写入基本的网关配置信息。 +- 那么,为了能完整的串联全部流程,我们这里需要增加下网关配置域,处理网关配置、网关工具配置的内容,一个网关可以挂多个工具,一个工具映射了一个协议(http、rpc等) +- 注意,当前我们先实现了最基本的保存和更新,后续随着运营后台的开发,在陆续补充需要的接口。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-18\350\212\202\357\274\232\347\256\241\347\220\206\347\253\257-API\345\212\237\350\203\275\347\274\226\346\216\222\344\270\262\350\201\224.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-18\350\212\202\357\274\232\347\256\241\347\220\206\347\253\257-API\345\212\237\350\203\275\347\274\226\346\216\222\344\270\262\350\201\224.md" new file mode 100644 index 000000000..fa82c77e4 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-18\350\212\202\357\274\232\347\256\241\347\220\206\347\253\257-API\345\212\237\350\203\275\347\274\226\346\216\222\344\270\262\350\201\224.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第3-18节:管理端-API功能编排串联 +pay: https://t.zsxq.com/qr9CQ +--- + +# 《AI MCP Gateway 网关服务系统》第3-18节:管理端-API功能编排串联 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/MyLpx](https://t.zsxq.com/MyLpx) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +到本章节往下,我们要为 AI MCP Gateway(网关)提供一个管理端页面,维护网关的配置和验证。如配置网关和工具能力,为工具添加协议。协议来自于 Swagger 导出的 openapi json 文件。这些内容,我们陆续的添加。本节主要串联服务功能接口(看看这样的架构下怎么提供的页面功能),以及提供基础UI页面。 + +注意,关于网关后台的管理页面是使用 AI IDE 工具生成的。建议每个人都生成一套自己的,你只要在对话框中,把服务端的 api 接口拖到对话中,并告诉它在什么位置编写 html 代码,以及对接服务端页面。它就可以帮你完成一套页面。 + +## 二、流程设计 + +如图,从管理端页面到服务端的流程设计; + +
+ +
+ +- 首先,整个流程为;从前端页面(管理后台)通过 ajax 请求服务端 trigger 层的 http 接口开始,由 case 层分摊 trigger 层串联逻辑部分的流程。这部分流程,调用 domain 领域层处理,也就是完成 CRUD 操作。最终由基础设施层,依赖倒置于 domain 领域层,完成数据的增删改查操作。 +- 之后,本节我们的重点是完成从 trigger 往下的逻辑处理,对于页面端,先少量提供。后续陆续补充各个功能。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-19\350\212\202\357\274\232\347\256\241\347\220\206\347\253\257-API\344\270\216UI\345\257\271\346\216\245.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-19\350\212\202\357\274\232\347\256\241\347\220\206\347\253\257-API\344\270\216UI\345\257\271\346\216\245.md" new file mode 100644 index 000000000..3610e5ced --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-19\350\212\202\357\274\232\347\256\241\347\220\206\347\253\257-API\344\270\216UI\345\257\271\346\216\245.md" @@ -0,0 +1,31 @@ +--- +title: 【更】第3-19节:管理端-API与UI对接 +pay: https://t.zsxq.com/199zh +--- + +# 《AI MCP Gateway 网关服务系统》第3-19节:管理端-API与UI对接 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/JoVrf](https://t.zsxq.com/JoVrf) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +结合网关管理后台(UI)功能,在服务端提供相应的接口能力,与管理后台对接。这些功能主要是 CRUD 做页面管理的增删改查操作。 + +此部分功能使用 AI IDE 工具就可以完成,也很建议学习的伙伴使用 AI IDE 工具(opencode、trae.ai、openclaw(QClaw)),做一套属于自己的管理后台,这样你可以在投递简历的时候发送,也可以在面试的时候演示。 + +>提示,可以在你的 AI IDE 安装技能 [https://github.com/fuzhengwei/xfg-ddd-skills](https://github.com/fuzhengwei/xfg-ddd-skills) 这样处理起来更加准确。 + +## 二、流程设计 + +如图,管理端到服务端接口的设计; + +
+ +
+ +- 整个这部分的设计实现都是 CRUD,管理端需要什么,就可以配置什么接口,查询、修改、删除即可。 + diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-1\350\212\202\357\274\232\345\267\245\347\250\213\345\210\235\345\247\213\345\214\226\345\210\233\345\273\272.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-1\350\212\202\357\274\232\345\267\245\347\250\213\345\210\235\345\247\213\345\214\226\345\210\233\345\273\272.md" new file mode 100644 index 000000000..e6bb94615 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-1\350\212\202\357\274\232\345\267\245\347\250\213\345\210\235\345\247\213\345\214\226\345\210\233\345\273\272.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第3-1节:工程初始化创建 +pay: https://t.zsxq.com/xdnB0 +--- + +# 《AI MCP Gateway 网关服务系统》第3-1节:工程初始化创建 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/5PzN8](https://t.zsxq.com/5PzN8) + +>大家好,我是技术UP主小傅哥。 + +## 一、本章诉求 + +搭建 AI MCP Gateway 网关工程,并 push 代码到课程仓库,以及演示关于 Git 使用,方便后续学习使用。 + +## 二、环境配置 + +- JDK 17 +- Maven 3.8.x - [Maven 教程](https://bugstack.cn/md/road-map/maven.html) +- IntelliJ IDEA 社区版(免费) [IntelliJ IDEA 教程](https://bugstack.cn/md/road-map/intellij-idea.html) +- Git - 安装后会配置到 IntellJ IDEA 这样才能向服务端推送或者拉取代码。学习后可以知道怎么拉取、提交和比对代码。Git 教程:https://bugstack.cn/md/road-map/git.html + +
+ +
+ +>相关软件,在星球课程入口,编程环境中提供了下载链接。编程环境:[https://t.zsxq.com/19Rnk98M0](https://t.zsxq.com/19Rnk98M0) - 提供了已经配置好镜像的 maven 方便直接使用。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-2\350\212\202\357\274\232\344\274\232\350\257\235\347\256\241\347\220\206\346\234\215\345\212\241\345\256\236\347\216\260.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-2\350\212\202\357\274\232\344\274\232\350\257\235\347\256\241\347\220\206\346\234\215\345\212\241\345\256\236\347\216\260.md" new file mode 100644 index 000000000..ea2d8c14a --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-2\350\212\202\357\274\232\344\274\232\350\257\235\347\256\241\347\220\206\346\234\215\345\212\241\345\256\236\347\216\260.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第3-2节:会话管理服务实现 +pay: https://t.zsxq.com/c0WoQ +--- + +# 《AI MCP Gateway 网关服务系统》第3-2节:会话管理服务实现 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/nPibY](https://t.zsxq.com/nPibY) + +>大家好,我是技术UP主小傅哥。 + +## 一、本章诉求 + +从本章节开始,我们会以**第1-2节:系统建模设计**为标准,进行各个模块的逻辑编码实现。包括;协议、鉴权、会话等。这部分内容完成后,在定义 api 接口,以及在 trigger 的 http 下实现接口,以及调用 case 层,处理 domain 领域的编排。整个实现过程是逐步有`骨架`,之后陆续填充完善的过程,你只要跟住理解清楚了,就可以很容易的完成全部编码。 + +**温馨提示**:尽量不要完全对照视频写代码,可以是先看视频,之后对照工程中分支代码变化(前面一节教程有告诉大家怎么对比),之后来实现功能。这样你会注意到更多的细节。 + +## 二、功能设计 + +如图,会话领域服务功能; + +
+ +
+ +- 首先,我们是把一次连接请求作为一次会话来看。比如数据库查询会话、MyBatis 操作会话、信贷交易会话,会话的作用在于以统一的标识记录用户的操作行为,根据你的会话ID,可以找到你再次过程中所有的行为记录。 +- 那么,在 AI MCP Gateway 中,也是按照 MCP 的协议方式,进行会话请求和消息处理。会话的作用是拿到后续处理消息的请求地址,这个地址是在会话请求阶段进行分配的。`在前面章节进行协议分析的时候,有讲解过 /mcp/message?sessionId= 的获取和使用` \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-3\350\212\202\357\274\232\344\274\232\350\257\235\346\216\245\345\217\243\347\274\226\346\216\222.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-3\350\212\202\357\274\232\344\274\232\350\257\235\346\216\245\345\217\243\347\274\226\346\216\222.md" new file mode 100644 index 000000000..74030075b --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-3\350\212\202\357\274\232\344\274\232\350\257\235\346\216\245\345\217\243\347\274\226\346\216\222.md" @@ -0,0 +1,36 @@ +--- +title: 【更】第3-3节:会话接口编排 +pay: https://t.zsxq.com/Mmuqa +--- + +# 《AI MCP Gateway 网关服务系统》第3-3节:会话接口编排 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/c0ZDk](https://t.zsxq.com/c0ZDk) + +>大家好,我是技术UP主小傅哥。 + +## 一、本章诉求 + +定义 mcp 通信协议会话服务接口,并在 case 层做领域服务的编排,为接口提供服务能力。 + +## 二、功能设计 + +如图,会话服务编排接口; + +
+ +
+ +- 首先,这一节我们的主要定义并实现 mcp 服务,sse 请求接口,创建会话信息。地址案例:`http://localhost:8777/api-gateway/test10001/mcp/sse?api_key=xxx` + + - test10001 - 是每个MCP网关,申请获得的唯一标识ID + - mcp/sse - 是固定的接口格式,让使用方知道这是 mcp 服务,sse 通信协议。 + - api_key - 是一个服务网路请求时候的安全校验,确保是你申请了唯一的key,才可以访问的。这部分鉴权的操作,会放到后续实现。 + +- 之后,这里我们会看到 trigger 层是实现 MCP 服务接口,接口的实现,需要调用 domain 领域层(domain 是每一个内聚的服务方法)。而为了减轻 trigger 层的编码压力,这里我们引入下 case 层,来处理 trigger 层调用 domain 领域层所做的编排动作。让 trigger 层只负责一个接口的封装操作,如;日志打印、参数校验、对象转换、异常处理、结果封装,而具体的逻辑则有 case 层承接。 + +- 注意,case 层的编排操作,会采用星球中的扳手工程项目下的设计模式框架中的规则树,这个规则树非常适合节点的编排,对于流程的解耦非常有效。 + +> 在互联网大厂中,会有很多这样的解耦设计,架构也不是一成不变的。这些东西都会随着各种业务的迭代,不断的进行演进。所以,做为编码工程师,未来的架构师,都要大量的吸收这些编码设计经验。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-4\350\212\202\357\274\232\344\274\232\350\257\235\346\266\210\346\201\257\347\273\223\346\236\204\350\256\276\350\256\241.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-4\350\212\202\357\274\232\344\274\232\350\257\235\346\266\210\346\201\257\347\273\223\346\236\204\350\256\276\350\256\241.md" new file mode 100644 index 000000000..1dea6c710 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-4\350\212\202\357\274\232\344\274\232\350\257\235\346\266\210\346\201\257\347\273\223\346\236\204\350\256\276\350\256\241.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第3-4节:会话消息结构设计 +pay: https://t.zsxq.com/02FXE +--- + +# 《AI MCP Gateway 网关服务系统》第3-4节:会话消息结构设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/t0xJC](https://t.zsxq.com/t0xJC) + +>大家好,我是技术UP主小傅哥。 + +## 一、本章诉求 + +增加 MCP 会话通信,处理请求消息的 HTTP 服务入口方法,完成简单的消息请求接收验证。并根据消息信息,设计会话领域层中消息处理策略。 + +## 二、功能设计 + +如图,会话消息响应设计; + +
+ +
+ +- 首先,这里要设计一个同名接口的不同类型服务,get 用于创建会话服务,建立 sse 连接。而 post 则是处理端点消息,完成会话服务应答。 +- 之后,对于会话消息,我们在前面已经分析过,主要包括;InitializeHandler - 协议握手、ResourcesListHandler - 返回可用资源列表、ToolsCallHandler - 执行指定的工具调用、ToolsListHandler - 返回服务器支持的工具列表。本节我们先把这些策略结构设计出来,方便后续实现具体功能。 +- 重点,本节会先来实现接口和定义整个处理消息的结构,后续再做具体的功能实现,以及服务的编排动作。 +- 此外,本节还会引入 jdk16+ 定义的新语法关键字,**record**、**sealed**、**permits** 来定义对象。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-5\350\212\202\357\274\232\346\266\210\346\201\257\345\215\217\350\256\256\345\244\204\347\220\206\346\241\210\344\276\213.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-5\350\212\202\357\274\232\346\266\210\346\201\257\345\215\217\350\256\256\345\244\204\347\220\206\346\241\210\344\276\213.md" new file mode 100644 index 000000000..4540b8fdc --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-5\350\212\202\357\274\232\346\266\210\346\201\257\345\215\217\350\256\256\345\244\204\347\220\206\346\241\210\344\276\213.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第3-5节:消息协议处理案例 +pay: https://t.zsxq.com/zUvnY +--- + +# 《AI MCP Gateway 网关服务系统》第3-5节:消息协议处理案例 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/kWYZ9](https://t.zsxq.com/kWYZ9) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +整个 MCP 协议的通信调用过程,需要先创建 session 会话,之后通过 handler 接收下发的指令方法,完成整个 MCP 的处理。那么,为了让大家更清楚我们所开发的东西,这里我们要先做一些流程案例,完成整个 MCP 服务的通信过程。后续在把案例的固定的代码,拆分到数据库配置实现。 + +## 二、功能设计 + +如图,会话消息响应设计; + +
+ +
+ +- 首先,MCP 的通信过程,分为了初始化,后去工具列表,调用工具,以及资源和通知等。这里我们要硬编码返参实现这些方法。 +- 之后,我们这里做一个单词小写转换大写的方法,让 AI 通过 MCP 调用到网关服务。做完这部分,你就能联想到,这里既然也可以硬编码操作,那么也可以调用 http、rpc,甚至是 mq,以及还可以是 rs232 串口通信,控制硬件设备。 +- 注意,这一节的实现,还是从 trigger 触发器的 http 层,直接调用到 domain 领域方法,后续在从 case 层进行串联流程。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-6\350\212\202\357\274\232\345\237\272\347\241\200\345\261\202\346\225\260\346\215\256\345\244\204\347\220\206.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-6\350\212\202\357\274\232\345\237\272\347\241\200\345\261\202\346\225\260\346\215\256\345\244\204\347\220\206.md" new file mode 100644 index 000000000..a50901f92 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-6\350\212\202\357\274\232\345\237\272\347\241\200\345\261\202\346\225\260\346\215\256\345\244\204\347\220\206.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第3-6节:基础层数据处理(Dao) +pay: https://t.zsxq.com/LaFBT +--- + +# 《AI MCP Gateway 网关服务系统》第3-6节:基础层数据处理(Dao) + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/8xnuo](https://t.zsxq.com/8xnuo) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +将 AI MCP Gateway 库表设计,编写到工程中,映射成 PO、DAO、Mapper 文件,以便于后续章节的使用。 + +这一节,小傅哥会演示如何使用 AI IDE 工具,通过 Prompt 描述,来完成这些文件的生成。 + +## 二、结构介绍 + +如图,从领域层到基础设施层(mysql、redis...)的使用方式; + +
+ +
+ +- 首先,这里有个设计的思想的体现,这类思想也是 Spring、MyBatis 等框架源码中常用的思想,叫做【依赖倒置】。它的设计目标是,让数据使用方,不过渡依赖于提供方。提供方在`升级`、`替换`、`迭代`时候,都不影响使用方。 +- 之后,图里是依赖倒置的具体编码体现,从 domain 领域层,每个会话、鉴权、协议的功能编写时,所需的数据,是通过在 domain 领域层定义接口,之后由infrastructure 基础设施层做具体的功能实现。也就是说,每个功能区需要啥数据,就定义好接口,确定好入参和返回结果的,基础设施层引入 domain 层定义的这个标准接口,做具体的数据封装使用。**也类似于公司的领导,要这,要那,他不关心具体是谁做,最后做好就可以了。** diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-7\350\212\202\357\274\232\345\215\217\350\256\256\346\266\210\346\201\257\345\244\204\347\220\206-Initialize.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-7\350\212\202\357\274\232\345\215\217\350\256\256\346\266\210\346\201\257\345\244\204\347\220\206-Initialize.md" new file mode 100644 index 000000000..abb8afffe --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-7\350\212\202\357\274\232\345\215\217\350\256\256\346\266\210\346\201\257\345\244\204\347\220\206-Initialize.md" @@ -0,0 +1,33 @@ +--- +title: 【更】第3-7节:协议消息处理-Initialize +pay: https://t.zsxq.com/Re6ZW +--- + +# 《AI MCP Gateway 网关服务系统》第3-7节:协议消息处理-Initialize + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/yIOEM](https://t.zsxq.com/yIOEM) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +从本章开始,我们将进入消息协议的处理过程,把原本的硬编码的案例操作,通过网关ID(gatewayId)与数据库配置数据进行关联。 + +今天我们来处理第一个协议消息的处理场景,Initialize 初始化部分。这部分学习时,会附带调试 Spring AI 框架中 modelcontextprotocol 关于协议处理部分的源码,让大家有更多的积累。 + +- [https://github.com/modelcontextprotocol/java-sdk](https://github.com/modelcontextprotocol/java-sdk) +- [https://modelcontextprotocol.io/docs/getting-started/intro](https://modelcontextprotocol.io/docs/getting-started/intro) + +## 二、功能设计 + +如图,Initialize 初始化协议处理; + +
+ +
+ +- 首先,在 session 会话层的 adapter 下,创建调用基础设施层仓储服务的接口,并由基础设施层做功能实现。再通过依赖倒置的方式用于领域层使用。(这部分对于初次接触 DDD,又没学习过一些源码或者设计知识的伙伴,可能感觉有点绕,不过没关系,在看到课程源码以后,会逐步清晰) +- 然后,从数据库获取的数据,要进行协议转换。也就是把之前固定编码的部分,用数据库获取的数据来动态填充。这部分内容只是初次拿到数据并使用的小试牛刀,并不复杂。不过,我们还会增加对 Spring AI 源码的调试,扩展知识学习。 +- 之后,在我们陆续完成这些 handler 消息的处理后,则会在 case 层陆续做编排,以及验证网关ID和token等。 diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-8\350\212\202\357\274\232\345\215\217\350\256\256\346\266\210\346\201\257\345\244\204\347\220\206-ToolsList.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-8\350\212\202\357\274\232\345\215\217\350\256\256\346\266\210\346\201\257\345\244\204\347\220\206-ToolsList.md" new file mode 100644 index 000000000..0f81038e7 --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-8\350\212\202\357\274\232\345\215\217\350\256\256\346\266\210\346\201\257\345\244\204\347\220\206-ToolsList.md" @@ -0,0 +1,37 @@ +--- +title: 【更】第3-8节:协议消息处理-ToolsList +pay: https://t.zsxq.com/eOpMV +--- + +# 《AI MCP Gateway 网关服务系统》第3-8节:协议消息处理-ToolsList + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/U6Shg](https://t.zsxq.com/U6Shg) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +从 HTTP 接口到 MCP 协议的映射,这里要考虑的是怎么把一个完整请求 http 的接口描述录入到数据库,之后在通过数据库的配置,转换为 MCP 协议结构告诉 AI 客户端 tool/list,也就是这套 HTTP 接口到 MCP 以后所提供工具能力。 + +所以,小傅哥在带着大家实现的过程中,先做了基于 HTTP 接口所需存储的信息,做了库表的设计。之后到这一节,我们要把库表的数据转换为 MCP 协议结构数据。 + +拓展,像是 HTTP 可以做,那么 RPC、MQ、数据库等各类资源,你也可以转换为 MCP 服务协议进行使用。 + +## 二、流程设计 + +如图,Tool/List 工具列表协议处理; + +
+ +
+ +- 首先,我们要根据网关ID(gatewayId)从数据库中,获取网关配置和http工具字段配置列表,这部分数据相当于是把 HTTP 请求结构体,拆解喽放到数据库表中,之后再查询出来按照 MCP 协议结构组装使用。 +- 然后,是对 buildTools 工具细节的处理,这部分是对元素的拆分和组装。这部分还有一些细节在下面。 + +
+ +
+ +- 之后,映射数据库表 `mcp_protocol_mapping` 拆解字段的父子关系,一个字段以下的另外一个字段,如;`xxxRequest01 -> xxxRequest01.city` 的映射。所以在 buildProperty 的处理过程中要,要做递归循环,一层一层的找到这些内容,并拆解组装使用。 \ No newline at end of file diff --git "a/docs/md/project/ai-mcp-gateway/\347\254\2543-9\350\212\202\357\274\232\345\215\217\350\256\256\346\266\210\346\201\257\345\244\204\347\220\206-ToolsCall.md" "b/docs/md/project/ai-mcp-gateway/\347\254\2543-9\350\212\202\357\274\232\345\215\217\350\256\256\346\266\210\346\201\257\345\244\204\347\220\206-ToolsCall.md" new file mode 100644 index 000000000..5e4f90eca --- /dev/null +++ "b/docs/md/project/ai-mcp-gateway/\347\254\2543-9\350\212\202\357\274\232\345\215\217\350\256\256\346\266\210\346\201\257\345\244\204\347\220\206-ToolsCall.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第3-9节:协议消息处理-ToolsCall +pay: https://t.zsxq.com/U4Ouo +--- + +# 《AI MCP Gateway 网关服务系统》第3-9节:协议消息处理-ToolsCall + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/Vodcp](https://t.zsxq.com/Vodcp) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +从 AI 客户端,向 AI MCP 发起请求的过程中,小傅哥已经带着大家处理了;InitializeHandler - 初始化、ToolsListHandler - 获取工具列表,接下来再要处理的就是 ToolsCallHandler 的操作了,接收来自 AI 客户端,用户的请求,转换为对应的参数,发起接口请求(这部分我们会调用 http 接口)。 + +## 二、流程设计 + +如图,Tool/Call 工具接口调用协议处理; + +
+ +
+ +- 首先,从 ToolsCallHandler 入口开始,会接收到 AI 请求接口过程中,发过来的格式化参数信息(根据我们提供的工具列表说明提供过来的)。 +- 之后,根据获取的请求信息,解析请求参数(像是 http 接口分为 post、get,如果以后扩展 rpc 接口,就直接泛化调用,这部分就可以根据你想对接哪些东西来看了)并做协议调用。 +- 注意,当前章节还是gateway -> tool 是 `1:1` 的,这部分后续在做细化处理。我们先用一个简单的结构,把整个流程跑通。有了基础后,在深入的理解拆分会更好理解。 diff --git a/docs/md/project/big-market/big-market.md b/docs/md/project/big-market/big-market.md index c1acb795c..1426052cb 100644 --- a/docs/md/project/big-market/big-market.md +++ b/docs/md/project/big-market/big-market.md @@ -31,6 +31,8 @@ lock: no
+**体验地址**:[https://openai.gaga.plus/](https://openai.gaga.plus/) - 左侧Bar,抽奖进入 + 这里抽奖模块通过RPC接口,对接到大营销平台。这里不只是抽奖,还要串联账户、奖品、返利等各项内容。接下来,小傅哥就着重介绍下这套信息项目的重点,让大家可以知道学习到哪些知识,掌握哪些技术。 >文末有加入学习方式,还有优惠券可以使用。先到先得! diff --git a/docs/md/project/big-market/dev-ops/openai_big_market.md b/docs/md/project/big-market/dev-ops/openai_big_market.md new file mode 100644 index 000000000..24d9541ea --- /dev/null +++ b/docs/md/project/big-market/dev-ops/openai_big_market.md @@ -0,0 +1,415 @@ +--- +title: 第4节:课程完结,上线部署教程 +lock: no +--- + +# 《大营销平台系统设计实现》 - 开发运维 第4节:课程完结,上线部署教程 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +不少小伙伴在面试中总会被提问,你的微服务是哪两套项目对接,你是分布式体现在哪。好像这么一问,平时做的项目既不是微服务,也不是分布式,都不知道怎么回答啦!咋办!?🤔 + +
+ +
+ +**还是别做玩具项目了!** + +要说这种级别的东西,要不是在公司里真的实践过,要不是跟着小傅哥完完全全的做过。否则还真没有这类经验,很多市面的CRUD项目都是一个个孤岛单体,根本没有微服务对接,也谈不上分布式架构。所有的这类东西,都是真的在职场多年实践,才能一步步带着你学习掌握到! + +这次,我把两套项目完成了微服务对接,分布式架构部署。你可以完全全全的学习到这些东西到底是怎么玩的! + +>上车,这次项目做的很硬核!文末可以获取全部项目课程。 + +## 1. 效果展示 + +这是一次非常庞大的系统开发实践,学习这样一套东西,可以全面的提高个人综合技术实战能力。了解业务、懂得架构、提到思维、锻炼编码。一个个场景的解决方案,一个个设计模式的实践运用。 + +
+ +
+ +- 地址:[https://openai.gaga.plus/](https://openai.gaga.plus/) - 侧边栏,点击兑换、购物、营销。 +- 说明:你可以体验 OpenAI 兑换、抽奖、兑换、签到等各个功能。这些也都各个互联网公司C端场景的产品设计。 + +>接下来是一整套的项目的部署执行过程,公司中大家上线,对于中大型项目和需求,也会列出明确的上线执行步骤。 + +## 2. 部署结构 + +### 2.1 微服务&分布式 + +
+ +
+ +- 微服务:一套 OpenAi chatgpt-data 后端应用,一套 big-market 后端应用,两套微服务。 +- 分布式:Nginx 负载 http,大营销负载 rpc,支持多实例部署,mq 消息解耦流程、xxl-job 任务驱动、redis 缓存预热数据。分库分表、canal 完成数据的分离和聚合。 + +### 2.2 分层部署关系 + +
+ +
+ +- 从底层往上,依次是[服务器(4c16g)](http://618.gaga.plus/)、部署环境、应用环境、上线配置、应用构建、参数配置,之后就是执行应用启动啦。 +- 接下来我们的部署,也会做这些操作。 + +## 3. 环境诉求 + +>为了方便大家完成项目的部署,这里采用了 Linux 服务器直接搭建构建环境的方式进行处理。在以下操作中你可以把 Linux 当做一台本地的电脑进行使用。只不过都是命令方式操作。 + +本节需要在一台服务器上,部署分布式技术栈(nacos、mysql、redis、xxl-job、rabbitmq、Zookeeper等),2套 big-market 大营销后台(rpc 负载)、1套 chatgpt-data 后端、1套 chatgpt-web 前端。 + +1. 推荐 `4c16g` 服务器 3个月:https://618.gaga.plus - `158元(续费同价)`,这个价格比较适合临时做测试验证。【占用在12g+】 +2. docker、portainer - `在 bugstack.cn 路书中有安装教程` +3. jdk 1.8、maven 3.8.8、git,课程提供了安装部署视频 +4. Git使用教程:[https://bugstack.cn/md/road-map/git.html](https://bugstack.cn/md/road-map/git.html) +5. 申请微信公众号测试平台:[https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index](https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index) - 需要申请。 +6. 智谱AI,申请Key:[https://bigmodel.cn/usercenter/apikeys](https://bigmodel.cn/usercenter/apikeys) - OpenAI 项目会使用到 + +
+ +
+ +- 脚本:[https://gitcode.net/KnowledgePlanet/big-market/big-market-dev-ops](https://gitcode.net/KnowledgePlanet/big-market/big-market-dev-ops) +- 说明:这里小傅哥已经分各个阶段给大家提供好了部署脚本,你可以参照使用。在 mysql 包下,已经提供了本次项目部署所需的 sql 初始化文件。 + +**docker 镜像推荐** + +```java +# 清空 /etc/docker/daemon.json 文件,准备写入新内容 +echo >/etc/docker/daemon.json + +# 使用 cat 命令将以下内容写入 /etc/docker/daemon.json 文件 +# 配置 Docker 镜像加速器,使用多个镜像源来提高镜像下载速度 +cat >/etc/docker/daemon.json < + + + +- 推荐使用 [termius](https://termius.com/) 连接云服务器,在根目录创建 `/dev-ops` 文件夹。再通过 SFTP 工具,把本地的部署脚本上传到文件夹中。 + +### 2. 执行脚本 + +```shell +cd /dev-ops +# 方式1 +docker-compose -f docker-compose-environment.yml up -d + +# 方式2 +docker-compose -f docker-compose-environment-xfg-studio.yml up -d +``` + +- 方式1;需要配置可用的 docker 镜像,才能拉取。 +- 方式2;是小傅哥准备好的镜像地址,速度更快一些。如果方式2不可用了,可以继续用方式1 + +
+ +
+ +
+ +
+ +```java +- nacos:http://117.72.90.238:8848/nacos - 「账密:nacos/nacos」 +- rabbitmq:http://117.72.90.238:15672/ - 「账密:admin/12qw!@QW」 +- redis-admin:http://117.72.90.238:8081/ - 「账密:admin/12qw!@QW」 +- xxl-job-admin:http://117.72.90.238:9090/xxl-job-admin - 「账密:root/12qw!@QW」 +- phpmyadmin:http://117.72.90.238:8899/ - 「账密:root/12qw!@QW」 +``` + +- 部署完成后,可以依次访问 phpmyadmin、rabbitmq、redis-admin、xxl-job-admin、nacos 这些管理后台。检查数据库表是否已经全部初始化完成。 +- 账号、密码、IP,你可以按照自己的进行修改,密码是配置在 docker-compose-environment/environment-xfg-studio 脚本中。 + +## 5. 应用构建 + +在 /dev-ops/ 目录下创建创建 gitcode 文件夹,里面分别拉取代码; + +### 1. big-market 大营销后端 + +#### 1.1 参数配置 + +1. application.yml 修改 `active: prod` 为上线参数 +2. application-prod.yml 为上线部署配置,其中一些IP的地方被名称替代,如 mysql、zookeeper等,是因为这些IP可以在 docker-compose 部署中,在一个文件夹下,走同一个网络,进行内网通信。 +3. docker-compose-app.yml big-market 注意配置 rabbitmq 地址为你的服务器公网ip地址,并开放端口 5672 +4. docker-compose-app.yml 配置了2套 big-market 应用实例(不同端口)进行负载。 +5. gitcode 检出代码,可参考文章开头提到的 Git 使用教程。 + +#### 1.2 构建脚本 + +```shell +cd /dev-ops/gitcode/ +git clone -b docker-images-v5.0 https://gitcode.net/KnowledgePlanet/big-market/big-market.git + +cd big-market/ +mvn clean install + +cd big-market-app +chmod +x build.sh +./build.sh +``` + +### 2. chatgpt-data OpenAI 后端 + +#### 2.1 参数配置 + +1. application.yml 修改 `active: prod` 为上线参数 +2. application-prod.yml 为上线部署配置,其中一些IP的地方被名称替代,如 mysql、nacos,是因为这些IP可以在 docker-compose 部署中,在一个文件夹下,走同一个网络,进行内网通信。 +3. chatgpt.sdk.config.enabled、wxpay.config.enabled,可以都配置false,如果你有 chatgpt 和 微信支付那么可以配置。星球中还有关于支付宝沙箱、蓝兔支付,也可以更换对接。 + +#### 2.2 构建脚本 + +```shell +cd /dev-ops/gitcode/ +git clone -b docker-images-v5.0 https://gitcode.net/KnowledgePlanet/chatgpt/chatgpt-data.git + +cd chatgpt-data/ +mvn clean install + +cd chatgpt-data-app +chmod +x build.sh +./build.sh +``` + +### 3. chatgpt-web OpenAI 前端 + +#### 3.1 配置 + +**index.tsx** + +```java +const openAIApiHostUrl = "http://117.72.90.238:8091"; +const bigMarketApiHostUrl = "http://117.72.90.238:8092"; +``` + +- 修改为你的IP:PORT地址,如果你有域名也可以统一配置 https 的域名地址,但要全部都是统一的。避免跨域问题。 + +#### 3.2 脚本 + +```shell +cd /dev-ops/gitcode/ +git clone -b docker-images-v5.0 https://gitcode.net/KnowledgePlanet/chatgpt/chatgpt-web.git + +chmod +x build.sh +./build.sh +``` + +## 6. 应用部署 + +### 1. 脚本启动 + +以下为应用部署 docker compose 脚本,部署的时候进入linux此脚本所在文件夹,执行 `docker-compose -f docker-compose-app.yml up -d` 即可。 + +```java +version: '3.8' +# 命令执行 docker-compose -f docker-compose-app.yml up -d +services: + # 大营销后端 + big-market-app-01: + image: fuzhengwei/big-market-app:5.1 + container_name: big-market-app-01 + restart: always + ports: + - "8092:8092" + environment: + - TZ=PRC + - SERVER_PORT=8092 + - APP_CONFIG_API_VERSION=v1 + - APP_CONFIG_CROSS_ORIGIN=* + - ZOOKEEPER_SDK_CONFIG_ENABLE=false + - SPRING_RABBITMQ_ADDRESSES=117.72.90.238 + volumes: + - ./log:/data/log + networks: + - my-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + # 大营销后端 + big-market-app-02: + image: fuzhengwei/big-market-app:5.1 + container_name: big-market-app-02 + restart: always + ports: + - "8093:8093" + environment: + - TZ=PRC + - SERVER_PORT=8093 + - APP_CONFIG_API_VERSION=v1 + - APP_CONFIG_CROSS_ORIGIN=* + - ZOOKEEPER_SDK_CONFIG_ENABLE=false + - SPRING_RABBITMQ_ADDRESSES=117.72.90.238 + volumes: + - ./log:/data/log + networks: + - my-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + # OpenAI 应用后端 + chatgpt-data-app: + image: fuzhengwei/chatgpt-data-app:5.1 + container_name: chatgpt-data-app + ports: + - "8091:8091" + environment: + - TZ=PRC + - SERVER_PORT=8091 + - APP_CONFIG_API_VERSION=v1 + - APP_CONFIG_CROSS_ORIGIN=* + - APP_CONFIG_LIMIT_COUNT=3 + - APP_CONFIG_WHITE_LIST=ojbZUv18lbmriaTjcCWBYkOrSbHA + - SPRING_DATASOURCE_USERNAME=root + - SPRING_DATASOURCE_PASSWORD=12qw!@QW + - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/openai?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true + - WX_CONFIG_ORIGINALID=gh_e067c267e056 + - WX_CONFIG_APPID=wx5a228ff69e28a91f + - WX_CONFIG_TOKEN=b8b6 + - CHATGPT_SDK_CONFIG_ENABLED=false + - CHATGPT_SDK_CONFIG_API_HOST=https://service-d6wuqy4n-1320869466.cd.apigw.tencentcs.com/ + - CHATGPT_SDK_CONFIG_API_KEY=sk-cVvbudeJq3yQUvcyCeBeB97253C146BaAaC94d70D2890b8e + - CHATGLM_SDK_CONFIG_ENABLED=true + - CHATGLM_SDK_CONFIG_API_HOST=https://open.bigmodel.cn/ + - CHATGLM_SDK_CONFIG_API_KEY=96b1fb042a0b51f334ecfdb28ef95837.6pgWXziv5CdbJdGP + volumes: + - ./log:/data/log + networks: + - my-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + restart: always + + # OpenAI 应用前端 + chatgpt-web-app: + container_name: chatgpt-web-app + image: fuzhengwei/chatgpt-web-app:5.1 + ports: + - "3002:3002" + networks: + - my-network + restart: always + +networks: + my-network: + driver: bridge +``` + +
+ +
+ +- 注意:`SPRING_RABBITMQ_ADDRESSES=117.72.90.238`,需要配置云服务器IP地址,并开放 RabbitMQ 端口。 +- 执行预热活动:`http://117.72.90.238:8092/api/v1/raffle/activity/armory?activityId=100401` +- 本身大营销还有一个后台,但服务器可能不够,如果不部署后台,不做活动上架,那么可以通过执行预热活动接口完成活动预热。 +- 注意微信配置 + +```java +- WX_CONFIG_ORIGINALID=gh_e067c267e056 +- WX_CONFIG_APPID=wx5a228ff69e28a91f +- WX_CONFIG_TOKEN=b8b6 +``` + +
+ +
+- 全部更换为你的配置信息。注意,接口配置信息,需要在服务启动后配置。 + + +### 2. natapp 启动 - 无自己域名 + +#### 2.1 购买隧道 + +
+ +
+ +```java +[default] +authtoken=bcffa08ea0a7dde4 #对应一条隧道的authtoken,你需要更换为你的。否则不能正常启动。 +clienttoken= #对应客户端的clienttoken,将会忽略authtoken,若无请留空, +log=none #log 日志文件,可指定本地文件, none=不做记录,stdout=直接屏幕输出 ,默认为none +loglevel=ERROR #日志等级 DEBUG, INFO, WARNING, ERROR 默认为 DEBUG +http_proxy= #代理设置 如 http://10.123.10.10:3128 非代理上网用户请务必留空 +``` + +- 打开 natapp/config.ini 文件,复制 authtoken 替换为你的。 + +#### 2.2 执行启动 + +```java +[root@lavm-snw6pd3z62 chatgpt-web]# cd /dev-ops/ +[root@lavm-snw6pd3z62 dev-ops]# ls +canal docker-compose-app.yml gitcode kibana maven nginx redis +canal-adapter docker-compose-environment-xfg-studio.yml grafana log mysql prometheus +curl docker-compose-environment.yml java logstash natapp rabbitmq +[root@lavm-snw6pd3z62 dev-ops]# cd natapp/ +[root@lavm-snw6pd3z62 natapp]# ./natapp +``` + +
+ +
+ +- 启动 Natapp 穿透程序,主要是因为微信公众号配置,需要域名。如果你没有域名就按照这个方式,如果有域名,可以走自己的域名。 +- 在微信公众平台配置 URL 验签地址:[https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index](https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index) 配置地址:`http://xfg-studio.natapp1.cc/api/v1/wx/portal/wxad979c0307864a66` - 更换为你的 natapp 内网穿透地址。 + +### 3. Nginx 配置 - 有自己域名 + +
+ +
+ +- 域名:需要购买,各个云服务器厂商,都可以购买域名。 +- ssl:在 bugstack.cn 路书中有讲解如何配置免费 ssl。 +- 在微信公众平台配置 URL 验签地址:[https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index](https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index) 配置地址:`http://api-test.gaga.plus/api/v1/wx/portal/wxad979c0307864a66` - 更换为你的域名地址。 + +## 7. 应用访问 + +地址:[http://117.72.90.238:3002/](http://117.72.90.238:3002/) - `更换为你的IP地址` + +
+ +
+ +> 登录之后,你就可以愉快的玩耍啦! diff --git "a/docs/md/project/big-market/distributed/\347\254\2541\350\212\202\357\274\232\345\257\271\346\216\245OpenAI\351\241\271\347\233\256\351\242\235\345\272\246\345\245\226\345\223\201\346\216\245\345\217\243.md" "b/docs/md/project/big-market/distributed/\347\254\2541\350\212\202\357\274\232\345\257\271\346\216\245OpenAI\351\241\271\347\233\256\351\242\235\345\272\246\345\245\226\345\223\201\346\216\245\345\217\243.md" new file mode 100644 index 000000000..4b8aa7097 --- /dev/null +++ "b/docs/md/project/big-market/distributed/\347\254\2541\350\212\202\357\274\232\345\257\271\346\216\245OpenAI\351\241\271\347\233\256\351\242\235\345\272\246\345\245\226\345\223\201\346\216\245\345\217\243.md" @@ -0,0 +1,36 @@ +--- +title: 第1节:对接OpenAI项目额度奖品接口 +pay: https://t.zsxq.com/ByrMx +--- + +# 《大营销平台系统设计实现》 - 外部对接 第1节:对接OpenAI项目额度奖品接口 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +- **本章难度**:★★★☆☆ +- **本章重点**:新增 OpenAI 账户额度调整接口,增加大营销 openai_use_count 奖品发放实现类,完成发奖对接。 +- **课程视频**:[https://t.zsxq.com/w3Ebn](https://t.zsxq.com/w3Ebn) + +**版权说明**:©本项目与星球签约合作,受[《中华人民共和国著作权法实施条例》](http://www.gov.cn/zhengce/2020-12/26/content_5573623.htm) 版权法保护,禁止任何理由和任何方式公开(public)源码、资料、视频等内容到Github、Gitee等,违反可追究进一步的法律行动。 + +## 一、本章诉求 + +**前置说明**:在学习本章节前,需要对星球内的 [《OpenAI 应用项目》](https://t.zsxq.com/19aSkDvYB) 有所了解。 + +星球的 OpenAI 业务项目是一个以售卖额度提供 ChatGLM、ChatGPT 各类服务为载体的 OpenAI 业务应用。那么大营销项目就可以结合到 OpenAI 应用项目中提供积分、兑换、返利、抽奖这样的服务模块,增强 OpenAI 业务项目的拉新、促活、留存用户的能力。 + +整个对接过程分为2个阶段,一个是 OpenAI 项目提供账户调额能力作为奖品接口给大营销使用,另外一个是 OpenAI 项目,对接大营销的 RPC/HTTP 接口,搭建营销活动页。 + +## 二、对接流程 + +整个对接过程示意; + +
+ +
+ +- 如图,为用户使用 OpenAI 应用项目时候,一个前端,两个后端服务的对接过程。这里你就可以把大营销看做为一个微服务了。 +- 在这一节,我们先来完成,通过http接口,发放额度奖品的操作。 diff --git "a/docs/md/project/big-market/distributed/\347\254\2542\350\212\202\357\274\232\350\220\245\351\224\200\351\241\265\351\235\242\346\216\245\345\217\243\345\260\201\350\243\205.md" "b/docs/md/project/big-market/distributed/\347\254\2542\350\212\202\357\274\232\350\220\245\351\224\200\351\241\265\351\235\242\346\216\245\345\217\243\345\260\201\350\243\205.md" new file mode 100644 index 000000000..788b35f47 --- /dev/null +++ "b/docs/md/project/big-market/distributed/\347\254\2542\350\212\202\357\274\232\350\220\245\351\224\200\351\241\265\351\235\242\346\216\245\345\217\243\345\260\201\350\243\205.md" @@ -0,0 +1,34 @@ +--- +title: 第2节:营销页面接口封装 +pay: https://t.zsxq.com/L2ZdQ +--- + +# 《大营销平台系统设计实现》 - 外部对接 第2节:营销页面接口封装 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +- **本章难度**:★★★☆☆ +- **本章重点**:在 big-market 工程,开发适配 openai 项目,前端工程 chatgpt-web 所需的 http 接口。进行页面的开发和接口对接。 +- **课程视频**:[https://t.zsxq.com/A7eoq](https://t.zsxq.com/A7eoq) + +**版权说明**:©本项目与星球签约合作,受[《中华人民共和国著作权法实施条例》](http://www.gov.cn/zhengce/2020-12/26/content_5573623.htm) 版权法保护,禁止任何理由和任何方式公开(public)源码、资料、视频等内容到Github、Gitee等,违反可追究进一步的法律行动。 + +## 一、本章诉求 + +在 big-market 工程,开发适配 openai 项目,前端工程 chatgpt-web 所需的 http 接口。进行页面的开发和接口对接。 + +因为 openai 项目,前端工程 chatgpt-web 调用的接口都会在头信息中传递 token,所以我们也需要在 big-market 的接口中,新增加一份带有 token 的接口,对接解析和使用。 + +## 二、对接设计 + +在前端工程 chatgpt-web 中添加营销UI和接口对接。 + +
+ +
+ +- openai 项目后端服务,提供账户额度接口。 +- big-market 大营销服务,提供积分、抽奖、签到、兑换,过程中的查询和使用接口。 diff --git "a/docs/md/project/big-market/distributed/\347\254\2543\350\212\202\357\274\232RPC\346\216\245\345\217\243\345\257\271\346\216\245\346\224\257\344\273\230\350\277\224\345\210\251.md" "b/docs/md/project/big-market/distributed/\347\254\2543\350\212\202\357\274\232RPC\346\216\245\345\217\243\345\257\271\346\216\245\346\224\257\344\273\230\350\277\224\345\210\251.md" new file mode 100644 index 000000000..ebdba028f --- /dev/null +++ "b/docs/md/project/big-market/distributed/\347\254\2543\350\212\202\357\274\232RPC\346\216\245\345\217\243\345\257\271\346\216\245\346\224\257\344\273\230\350\277\224\345\210\251.md" @@ -0,0 +1,35 @@ +--- +title: 第3节:RPC接口对接支付返利 +pay: https://t.zsxq.com/fFntX +--- + +# 《大营销平台系统设计实现》 - 外部对接 第3节:RPC接口对接支付返利 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +- **本章难度**:★★★☆☆ +- **本章重点**:通过在大营销 big-market 新增提供的通用返利 RPC 接口,由 OpenAI 服务 chatgpt-data 系统在支付完成接收到回调消息后进行对接完成返利动作。 +- **课程视频**:[https://t.zsxq.com/15gLHtPaU](https://t.zsxq.com/15gLHtPaU) + +**版权说明**:©本项目与星球签约合作,受[《中华人民共和国著作权法实施条例》](http://www.gov.cn/zhengce/2020-12/26/content_5573623.htm) 版权法保护,禁止任何理由和任何方式公开(public)源码、资料、视频等内容到Github、Gitee等,违反可追究进一步的法律行动。 + +## 一、本章诉求 + +通过在大营销 big-market 新增提供的通用返利 RPC 接口,由 OpenAI 服务 chatgpt-data 系统在支付完成接收到回调消息后进行对接完成返利动作。 + +本节会使用到注册到 Nacos 的 Dubbo 服务,完成内部微服务的对接。Dubbo 的优势在于底层的通信协议比 HTTP 更加迅速,适合微服务间通信使用。不过这样的对接方式会强依赖另外一方系统的存在,否则启动会失败。所以后续我们部署的时候,也会把 chatgpt-data 依赖于 big-market 一起部署。 + +前置资料:关于dubbo配置使用的基础教程:[https://bugstack.cn/md/road-map/dubbo.html](https://bugstack.cn/md/road-map/dubbo.html) + +## 二、对接流程 + +通过 RPC 完成微服务的对接; + +
+ +
+ +- 用户下单完成支付后,会接收到支付消息,之后调用大营销提供的返利接口进行返利。返利为;积分和抽奖次数。 \ No newline at end of file diff --git "a/docs/md/project/big-market/distributed/\347\254\2544\350\212\202\357\274\232\346\264\273\345\212\250\344\270\212\346\236\266\345\217\221\345\270\203\351\242\204\347\203\255\345\257\271\346\216\245.md" "b/docs/md/project/big-market/distributed/\347\254\2544\350\212\202\357\274\232\346\264\273\345\212\250\344\270\212\346\236\266\345\217\221\345\270\203\351\242\204\347\203\255\345\257\271\346\216\245.md" new file mode 100644 index 000000000..ac229a9db --- /dev/null +++ "b/docs/md/project/big-market/distributed/\347\254\2544\350\212\202\357\274\232\346\264\273\345\212\250\344\270\212\346\236\266\345\217\221\345\270\203\351\242\204\347\203\255\345\257\271\346\216\245.md" @@ -0,0 +1,35 @@ +--- +title: 第4节:活动上架发布预热对接 +pay: https://t.zsxq.com/Gh1Py +--- + +# 《大营销平台系统设计实现》 - 外部对接 第4节:活动上架发布预热对接 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +- **本章难度**:★★★☆☆ +- **本章重点**:增加活动上架服务,通过运营后台管理上架,前端工程根据渠道sc值查询上架活动。 +- **课程视频**:[https://t.zsxq.com/15gLHtPaU](https://t.zsxq.com/15gLHtPaU) + +**版权说明**:©本项目与星球签约合作,受[《中华人民共和国著作权法实施条例》](http://www.gov.cn/zhengce/2020-12/26/content_5573623.htm) 版权法保护,禁止任何理由和任何方式公开(public)源码、资料、视频等内容到Github、Gitee等,违反可追究进一步的法律行动。 + +## 一、本章诉求 + +本节的内容是一个互联网中对外发布抽奖、发券、拉新等行为活动设计的通用方案。在实际运营作业中,会创建出很多的活动,这些活动会被分配到不同渠道给不同来源进行使用。那么这里就要有一个活动上架平台,让外部调用方根据传入的SC值,也就是渠道和来源调用到这一方可以使用的当前的活动ID。 + +这就有点像你去一个大超市看到的,每个货架上摆放着各类的的商品,这些商品其实是有它的仓库的,但当前你所看到的买到的,都是货架上摆放的。所以为了让用户参与到我们的活动,我们也需要把活动进行上架。 + +## 二、业务流程 + +活动上架流程,涉及到三块,如图; + +
+ +
+ +- 首先,运营负责把活动上架,点击审核为`有效`。有效后,也就是在这个时间点把活动预热到 Redis,在咱们大营销中的预热操作是装配的接口,会在这个过程中调用。 +- 之后,用户从前端页面进入后,程序会查询到当前上架的活动,这样就明确了具体参与到哪个活动上了。 + diff --git "a/docs/md/project/big-market/erp/\347\254\2541\350\212\202\357\274\232\345\210\235\345\247\213\345\220\216\345\217\260\350\277\220\350\220\245\351\241\265\351\235\242.md" "b/docs/md/project/big-market/erp/\347\254\2541\350\212\202\357\274\232\345\210\235\345\247\213\345\220\216\345\217\260\350\277\220\350\220\245\351\241\265\351\235\242.md" index da07e8c1e..5a8a1f8d0 100644 --- "a/docs/md/project/big-market/erp/\347\254\2541\350\212\202\357\274\232\345\210\235\345\247\213\345\220\216\345\217\260\350\277\220\350\220\245\351\241\265\351\235\242.md" +++ "b/docs/md/project/big-market/erp/\347\254\2541\350\212\202\357\274\232\345\210\235\345\247\213\345\220\216\345\217\260\350\277\220\350\220\245\351\241\265\351\235\242.md" @@ -1,5 +1,5 @@ --- -title: 运营后台 第1节:初始后台运营页面 +title: 第1节:初始后台运营页面 pay: https://t.zsxq.com/im8ZV --- diff --git "a/docs/md/project/big-market/erp/\347\254\2542\350\212\202\357\274\232querys\346\250\241\345\235\227\346\217\220\344\276\233\346\237\245\350\257\242\346\216\245\345\217\243.md" "b/docs/md/project/big-market/erp/\347\254\2542\350\212\202\357\274\232querys\346\250\241\345\235\227\346\217\220\344\276\233\346\237\245\350\257\242\346\216\245\345\217\243.md" new file mode 100644 index 000000000..242c209e1 --- /dev/null +++ "b/docs/md/project/big-market/erp/\347\254\2542\350\212\202\357\274\232querys\346\250\241\345\235\227\346\217\220\344\276\233\346\237\245\350\257\242\346\216\245\345\217\243.md" @@ -0,0 +1,45 @@ +--- +title: 第2节:querys模块提供查询接口 +pay: https://t.zsxq.com/YFckh +--- + +# 《大营销平台系统设计实现》 - 运营后台 第2节:querys模块提供查询接口 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +- **本章难度**:★★☆☆☆ +- **本章重点**:给 big-market 新增加 querys 模块,提供数据查询操作,并提供接口给前端使用。 +- **课程视频**:[https://t.zsxq.com/ByrMx](https://t.zsxq.com/ByrMx) + +**版权说明**:©本项目与星球签约合作,受[《中华人民共和国著作权法实施条例》](http://www.gov.cn/zhengce/2020-12/26/content_5573623.htm) 版权法保护,禁止任何理由和任何方式公开(public)源码、资料、视频等内容到Github、Gitee等,违反可追究进一步的法律行动。 + +## 一、本章诉求 + +在使用 DDD 做工程开发的时候,我们可以通过 domain 包,划分出一个个功能领域进行实现。这样强业务属性的逻辑,可以很好的拆分对应的边界,不至于像是 MVC 中让一堆的 Service 混乱。 + +但当我们遇到一些非强业务逻辑,只是对数据、缓存、ElasticSearch等做查询,给 ERP 运营系统提供数据时,就不时候全部都走一遍 domain 领域了,那样就显得非常重。所以这里我们要新增加一个 querys 模块,只做这类数据的查询操作。 + +在 big-market 提供好 querys 模块和相应的接口后,配置到前端页面使用。 + +## 二、后端实现 + +### 1. 添加 querys 模块 + +
+ +
+ +- 在工程上右键,新增加一个 querys 模块,并对 pom 进行配置。这个 pom 的配置与 domain 中的配置类似。 + +### 2. 实现 querys 接口 + +
+ +
+ +- 在 querys 中定义需要查询的的仓储接口,并由 domain 领域层实现接口。 +- 这个实现的过程也是依赖倒置的方式实现。 +- 另外注意,咱们是把 ElasticSerach 的查询,使用的是 x-pack-jdbc 方式,ElasticSerach 还有还有 SpringBoot 程序通过 `spring-boot-starter-data-elasticsearch` 提供查询的方式,也可以尝试试试。`面试或者做方案中,也有可能会问,你为什么选择 x-pack-jdbc 还有什么其他方式` \ No newline at end of file diff --git a/docs/md/project/big-market/extra/big-market-v6.md b/docs/md/project/big-market/extra/big-market-v6.md index e1cdbf80e..a785172c7 100644 --- a/docs/md/project/big-market/extra/big-market-v6.md +++ b/docs/md/project/big-market/extra/big-market-v6.md @@ -10,9 +10,7 @@ lock: no >沉淀、分享、成长,让自己和他人都能有所收获!😄 -大家好,我是技术UP主小傅哥。 - -耗时9个月,1.34万行代码,55节课程,全程视频手把手。这套微服务、分布式、DDD架构,涵盖了;抽奖、活动、积分、兑换,运用了分库分表、binlog同步数据、分段非竞态锁、动态配置、熔断、降级、限流、Nginx负载等综合前后端,Dev-Ops大型实战项目,大营销平台系统,终于完结了!💐 +大家好,我是技术UP主小傅哥。、;l.34万行代码,55节课程,全程视频手把手。这套微服务、分布式、DDD架构,涵盖了;抽奖、活动、积分、兑换,运用了分库分表、binlog同步数据、分段非竞态锁、动态配置、熔断、降级、限流、Nginx负载等综合前后端,Dev-Ops大型实战项目,大营销平台系统,终于完结了!💐
diff --git a/docs/md/project/big-market/extra/big-market-v7.md b/docs/md/project/big-market/extra/big-market-v7.md new file mode 100644 index 000000000..920eb2c29 --- /dev/null +++ b/docs/md/project/big-market/extra/big-market-v7.md @@ -0,0 +1,86 @@ +--- +title: 第五阶段完结,微服务对接 +lock: no +--- + +# 第五阶段完结,微服务对接 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +哎,你这一个电商/点评项目,一个营销活动项目,怎么没有两个项目的对接。你的营销活动可以给你的电商提供抽奖、积分、返利、兑换等等,但为啥都是独立存在的?你有思考过他们是怎么对接的吗? + +
+ +
+ +**那微服务的对接,你有经验吗?** + +没有🤔?没关系,小傅哥为你实打实的提供两套微服务项目的对接使用,包括;后端对接、前端对接,以及不同方式的接口形式对接方案。在这个过程中让你搞懂,这些微服务的对接思路、方式和落地手段。有了这些经验后续你也可以把这样的微服务,衔接到各种项目了上了。让你的项目成为一个蜘蛛网🕸一样的微服务布局。 + +本篇文章提到的两套微服务分别是;`OpenAI 应用项目`、`大营销系统服务 - 抽奖、积分、兑换、返利`,这两套微服务都是小傅哥在星球「码农会锁」为大家提供的实战项目,本节为大家提供出对接方案和效果。非常提高综合实战能力。 + +> 文末有加入学习方式,可以获得整套课程的;视频、文档、代码、面试题、简历模板等。 + +## 一、项目简述 + +- **OpenAi 应用项目**:前后端+Dev-Ops,全栈技术实践。以OpenAi场景,运用DDD架构,实现从微信公众号扫码登录,到下单支付对个人账户充值,完成 OpenAi 控制敏感词过滤以及多渠道策略模型的对话消费的全流程。 +- **大营销平台系统**:前后端+Dev-Ops,全栈技术实践。项目将先以最新DDD架构和模式进行重构Lottery项目,扩展用户、账户、积分、兑换、分享模块,以及和 OpenAI 进行微服务整合,RPC/HTTP 通信完成项目综合使用。 + +>项目演示地址:[https://gaga.plus](https://gaga.plus) - 你可以直接在线查看项目的演示运行效果。这些项目都是企业级的设计和实现,远比简单的 CRUD 那种 DEMO 项目要牛皮的多! + +## 二、对接方案 + +OpenAI 应用项目,提供了`支付购买对话额度`的服务。那么我们为了促进用户在 OpenAI 项目上的使用粘性,就可以添加营销模块。让用户在完成`每日签到和支付`后,就可以获得相应的积分,再通过积分兑换抽奖次数完成抽奖。抽奖有机会获得不同级别的`对话额度`赠送。以此完成用户行为旅程循环。 + +
+ +
+ +- OpenAI 前端应用,通过 Nginx 负载,HTTP 方式调用 OpenAI 后端和大营销后端服务。完成前端的UI的业务流程串联。 +- OpenAI 后端应用,在支付完成后,调用大营销的返利接口。大营销可以配置完成某个用户行为动作后对应给到积分或者抽奖次数。这个对接可以是 HTTP 或者 RPC 对接。 +- 大营销平台系统,在抽奖的时候增加 OpenAI 额度奖品。也就是抽奖后可以给一个n次数的对话额度,所以大营销需要对接到 OpenAI 提供的 HTTP 接口,处理额度奖品发放操作。 + +## 三、对接效果 + +OpenAI + 大营销,这是一套综合`前后端 + DevOps`的全体系技术实战项目。采用 DDD 架构设计落地,运用设计模式编写整洁的代码实现。结合 OpenAi 技术、微信支付渠道、敏感词过滤、营销积分、兑换、返利的综合玩法项目。 + +### 1. 营销页 + +
+ +
+ +- 在 OpenAI 页面,增加营销活动模块,展示出用户的额度、积分、签的到、抽奖次数。以及抽奖和奖品兑换操作。 +- 这些内容都是可以通过配置完成的,调整用户的获得积分的大小、以及兑换商品是的价值,再有就是抽奖的概率配置。可以非常灵活的调整,让用户非常喜欢这样一套产品。 + +### 2. 支付页 + +
+ +
+ +
+ +
+ +- 用户可以通过下单支付的方式完成商品的购买,购买后就可以对购买支付的回调,进行返利积分或者抽奖额度。 +- 星球的课程体系还提供了,微信支付、支付宝沙箱、蓝兔支付,多种方式都可以按需使用。 + +> 关于项目的更多了解:[https://bugstack.cn/md/project/chatgpt/review.html](https://bugstack.cn/md/project/chatgpt/review.html) + +## 四、加入学习 + +小傅哥的星球「码农会锁」提供了一整套的实战项目学习进阶路线,从小白到大佬,全程视频手把手带着从0到1,一步步完成项目的设计、开发和上线。在整套内容学习过程中,小傅哥为你提供了非常好的技术交流社群,及时解决学习问题。还包括调试你的问题代码,带你快速🔜出坑! + +
+ +
+ +- 首先,这一整套全体系的学习课程比私教培训实惠,更比培训班上万的培训费便宜。可能也就是培训班1天的💰钱,就能学习到这一整套内容了。 +- 之后,你学习的整套课程,就是小傅哥这个架构师自己全部原创编写的。这也就是说,你所提到的任何问题,小傅哥都能给你解答和讨论。 +- 那么,这么实惠的课程,成体系的课程,还是架构师编写的。还有什么可犹豫的,完全可以撸起来了! diff --git a/docs/md/project/big-market/notes.md b/docs/md/project/big-market/notes.md index 40069d140..6cac8d019 100644 --- a/docs/md/project/big-market/notes.md +++ b/docs/md/project/big-market/notes.md @@ -15,18 +15,18 @@ lock: no ## 一、项目介绍 -面试官您好,大营销平台的 Raffle 抽奖模块,是我独立负责实现的一个(学习/工作)项目,此项目模块在架构设计上运用了 DDD 分层架构和模板模式、责任链模式、组合模式、工厂模式等,这样的设计模式对业务流程进行解耦和实现。 +面试官您好,大营销平台的 Raffle 抽奖/积分/兑换/返利模块,是我独立负责实现的一个(学习/工作)项目,此项目模块在架构设计上运用了 DDD 分层架构和模板模式、责任链模式、组合模式、工厂模式等,这样的设计模式对业务流程进行解耦和实现。 -Raffle 抽奖模块的完整开发,让我对 SpringBoot 框架技术,分布式技术栈的运用更加熟练,也把设计模式在实际场景的使用了起来,积累了丰富的设计实现经验。这写技术学习的内容,也可以更好的应对以后的开发工作。非常感谢您给我这次面试机会。 +Raffle 抽奖/积分/兑换/返利,模块的完整开发,让我对 SpringBoot 框架技术,分布式技术栈的运用更加熟练,也把设计模式在实际场景的使用了起来,积累了丰富的设计实现经验。这些技术学习的内容,也可以更好的应对以后的开发工作。非常感谢您给我这次面试机会。 ## 二、简历模板 -**注意**:🙅🏻‍♀️不要直接复制粘贴简历模板,以此结构和描述方式,用个人第1学习视角来描述。 +**注意**:🙅🏻‍♀️不要直接复制粘贴简历模板内容,以此结构和描述方式,用个人第1学习视角来描述。项目课程还包括;活动、积分、兑换、返利、分布式应用内容。学习到每个阶段后,可以写简历。写好自己的简历后可以使用 [openai 4o模型](https://openai.itedus.cn) 告诉它你是一个 Java 技术专家,请根据描述内容,重新使用专业技术术语编写简历。几次下来,简历内容会非常好。 -- 项目名称:大营销平台 - Raffle 抽奖服务 +- 项目名称:大营销平台 - Raffle 抽奖/积分/兑换/返利服务 - 按需起名,可以是积分玩法,用户虚拟资产运营平台、积分返利抽奖服务等 - 项目架构:微服务架构、DDD 领域驱动模型、前后端分离设计 - 核心技术:SpringBoot、MyBatis、MySQL、Redis、SpringCloud/Dubbo【按需添加,只是对外的接口形式】、React、TypeScript -- 项目描述:Raffle 抽奖模块是整个大营销平台系统中非常重要的一个模块,也是本次项目中我来负责的设计和实现的模块。此模块主要以支撑各类差异化抽奖流程,如;通用抽奖、黑名单、人群、N消耗积分指定抽奖范围、抽奖N次解锁奖品等各类玩法的支持。在此系统模块的设计中运用到了模板模式、责任链模式、组合模式、工厂模式,解决代码的可扩展性,并对抽奖的计算和秒杀做了设计的优化,可以支撑单机 4c8g 服务器 1200 ~ 1500 TPS 的吞吐量(**参考值,以实际压测为准**),抽奖接口响应时长`45毫秒`左右。「不同服务器,带宽,以及是否还配置有环境相关,会有不同的数据效果」 +- 项目描述:Raffle 抽奖模块是整个大营销平台系统中非常重要的一个模块,也是本次项目中我来负责的设计和实现的模块。此模块主要以支撑各类差异化抽奖流程,如;通用抽奖、黑名单、人群、N消耗积分指定抽奖范围、抽奖N次解锁奖品等各类玩法的支持。在此系统模块的设计中运用到了模板模式、责任链模式、组合模式、工厂模式,解决代码的可扩展性,并对抽奖的计算和秒杀做了设计的优化,可以支撑单机 4c16g 服务器 500 ~ 800 TPS 的吞吐量(**参考值,以实际压测为准**),抽奖接口响应时长`45毫秒~100毫秒`左右。「不同服务器,带宽,以及是否还配置有环境相关,会有不同的数据效果」 - 核心职责: - 以PRD文档诉求和对功能的评审,设计出抽奖的领域模型功能,以及在抽奖的流程抽象上,分为;抽奖前、抽奖中、抽奖后,的节点上扩展各项行为动作。如抽奖前的人群判断、抽奖中库存扣减、抽奖后兜底奖励等。 - 依赖于领域模型的定义,设计出抽奖库表。抽象抽奖过程为抽奖策略表、策略明细表、规则配置表、规则树动作表,这样会让抽奖更好扩展。 @@ -34,6 +34,8 @@ Raffle 抽奖模块的完整开发,让我对 SpringBoot 框架技术,分布 - 在项目架构中定义统一标准的 api 由触发器层实现,在触发器层定义监听、任务、http、rpc模块,所有的行为动作,都理解为触发行为。 - 抽奖也是一种峰值流量高的业务场景,因此在设计奖品库存扣减上,采用了 Redis decr 分段消费和加锁兜底的设计,同时对于消费成功的库存,异步队列方式 + 定时任务更新库存。这样可以不超卖的同时,又减少数据库的压力。 - 在项目开发中熟练运用了 IntelliJ IDEA、WEbStorm、Docker、MySQL、云服务器、SSH工具,并已将项目完整部署到线上【在校伙伴可以提供线上案例版】。 + - 项目采用分布式架构设计,Dubbo 提供 RPC 接口,Nacos 作为注册中心。多机实例任务由 xxl-job 进行调度管理。分库分表数据通过 canal 同步 binlog 日志到 ElasticSearch 进行聚合查询。 + - 通过 RabbitMQ 解耦系统流程,包括;抽奖发奖流程、异步调账消息、异步行为返利,以及在 Redis 缓存库存消耗完毕后,推送MQ消息更新数据库库存和清空延迟队列。 ## 三、面试问题 @@ -43,6 +45,7 @@ Raffle 抽奖模块的完整开发,让我对 SpringBoot 框架技术,分布 - 架构设计:[https://www.bilibili.com/video/BV17x4y187nS](https://www.bilibili.com/video/BV17x4y187nS) - 设计模式:[https://www.bilibili.com/video/BV1f2421M7kc](https://www.bilibili.com/video/BV1f2421M7kc) +- 设计模式(扩展):[https://www.bilibili.com/video/BV1oYs3ejENB](https://www.bilibili.com/video/BV1oYs3ejENB) - 分布式问题:[https://www.bilibili.com/video/BV1Cr42137de](https://www.bilibili.com/video/BV1Cr42137de) ### 1. 你的项目工程是怎么搭建的? @@ -97,7 +100,7 @@ DDD 中的依赖倒置是一个非常好的设计,尤其是与 MVC 结构对 关于库存的扣减,是一个非常重要的流程。尤其是这种单独资源竞争的场景,如果设计的不好,很容易把服务打挂。 -所以在这套系统设计中,为了避免库存扣减直接更新库表的行级锁,而导致大量的用户进行等待状态。所以把数据库表的库存同步到 Redis 缓存中,在通过 incr 扣减的方式进行消费,同时为了确保在临界状态、库存恢复、异常处理等情况下不超卖,而对每一条产生从 incr 值,与抽奖的策略ID组合一个key,进行 setnx 加锁兜底,来保证不超卖。—— 这样的设计是颗粒度更小的锁方案设计,性能接近于无锁化。 +所以在这套系统设计中,为了避免库存扣减直接更新库表的行级锁,而导致大量的用户进行等待状态。所以把数据库表的库存同步到 Redis 缓存中,在通过 decr 扣减(incr 的话就和总量比)的方式进行消费,同时为了确保在临界状态、库存恢复、异常处理等情况下不超卖,而对每一条产生从 incr 值,与抽奖的策略ID组合一个key,进行 setnx 加锁兜底,来保证不超卖。—— 这样的设计是颗粒度更小的锁方案设计,性能接近于无锁化。 ### 12. 你讲到库存的扣减是通过 Redis 滑块锁实现的👍🏻,那么最终同步库是怎么做的,怎么降低对数据库的压力的? @@ -131,7 +134,7 @@ DDD 中的依赖倒置是一个非常好的设计,尤其是与 MVC 结构对 首先我们要知道,是前期就做好分库分表方案,还是后期在做系统重构分库分表和数据迁移哪个成本高。显然是后面的成本更高。 -而互联网中大厂中,分库分表的架构设计都是非常熟练的,因为有成熟方案,所以前期就分库分表了。但,为了解释服务器空间。所以把分库分表的库,用服务器虚拟出来机器安装。这样即不过多的占用服务器资源,也方便后续数据量真的上来了,好拆分。 +而互联网中大厂中,分库分表的架构设计都是非常熟练的,因为有成熟方案,所以前期就分库分表了。但,为了节省服务器空间。所以把分库分表的库,用服务器虚拟出来机器安装。这样即不过多的占用服务器资源,也方便后续数据量真的上来了,好拆分。 那么这里的分库分表后的数据怎么提供汇总、聚合的查询呢? @@ -192,6 +195,38 @@ DDD 中的依赖倒置是一个非常好的设计,尤其是与 MVC 结构对 - 2.3 如果删锁失败,对于是谁抢占的,谁可以做重入锁,继续执行。 - 2.4 锁有失效时间,如果抢占到的自己挂了,等待锁失效后,重新轮候抢占。 +### 26. 抽奖服务量化人群指标是什么?拉新 留存 促活吗 感觉这些数据好难算 面试官问留存率 拉新成本 我都不知道怎么答 + +量化人群,是量化分析师,通过 Python、R 语言对历史数据进行建模(R语言有数据分析公式)。目的是为了根据一个人的,人标签和行为数据,跑出谁喜欢xxx,谁爱购买xxx,谁有xxx意向。之后创建出人群包。这样系统会根据人群包做抽奖、发券等的差异化。 + +### 27. 有个问题想确认一下 大营销系统和业务系统 是在同一个注册中心里吗,业务系统是直接调用抽奖服务的dubbo接口么 + +一个公司里,rpc 都是一个注册中心。 + +### 28. 关于幂等和流程解耦 + +- Q1: rabbitMQ判断重复消费的逻辑是什么,是直接在数据库中查询返利记录表是否有相同的订单ID(这个订单ID对应着当天日期?)的记录,如果发现重复就不消费? +- Q2: 感觉“签到返利”这一块也有点像幂等性的实现,即可能会执行多次签到动作,但每天只会执行一次返利操作? +- Q3: 对于“签到返利”这种行为,用MQ解耦是不是太小题大做了。首先它并不是什么高流量的行为,没必要用MQ来削峰填谷;其次,这样会不会导致执行了 签到 操作之后,用户积分得隔较长一段时间才会更新,出现数据不一致的情况? + +回答:[https://t.zsxq.com/zbUUb](https://t.zsxq.com/zbUUb) + +### 29. 前几天面试官问我策略领域和奖品领域为什么要划分开 + +1. 这部分要从建模讲,最开似的系统建模是整理出用户用例图,根据用例图梳理四色建模的领域事件。[四色建模过程](https://bugstack.cn/md/project/big-market/ddd.html) +2. 在领域事件脑暴完成,之后就是识别领域角色和对象,这个过程会显而易见的发现有抽奖领域、发奖领域。他们可以作为解耦设计,独立使用。因为抽奖不一定发奖,抽奖可以独立提供算法结果,由外部其他系统使用。发奖也可以除了抽奖的发奖,还有积分兑换的发奖等。如果抽奖和发奖合并,那么外部调用就会不那么清晰。 + +### 30. 根据抽奖问题问了如果把redis中 滑块锁过期时间设置为活动过期时间的时候,如果活动时间很长导致滑块锁过多怎么解决 + +可以考虑给活动库存的锁的key上年月日,每个日的key,明天就重新从新的key开始了。之后这样就比较好较短时间存储了。 [更多讨论](https://t.zsxq.com/vNy0U) + +### 31. 分布式锁使用场景 + +项目中有两个地方使用了分布式锁,分别来处理库存的抢占竞争和分布式任务调度的抢占。 + +1. 库存的抢占设计的是接近于无锁化的库存编号自增后加锁,做兜底设计,这样的用户的抢占就是 incr 后的结果加锁,降低竞争。 +2. 另外一个是项目是分布式架构,有多个任务执行(补偿mq、流转订单状态等),之后如2个任务,一起补偿发mq,避免发送多了,就会做一个抢占设计。谁先拿到可执行key,那么这个任务就执行。这样确保了,一个任务挂了,也可以有另外任务做处理。 + ## 四、公司面试 ### 【美团】1. 领域模型是怎么设计的,抽奖过程是什么样,DDD四层架构和职责,以及为什么要这么设计?少卖和超卖。 @@ -256,4 +291,75 @@ DDD 是软件设计方法,对复杂的项目更为合适。但这里要清楚 1. 当你描述为积分和抽奖是单独的系统,你要生成兑换商品订单,拿订单的唯一单号,rpc/http 调用积分系统扣减积分,返回一个交易单号和时间。【如果是微信、支付宝类支付,就需要等待回调,因为还要走支付渠道很多流程,没法直接返回】 2. 你通过积分支付接口返回的信息开始变更订单记录,发放抽奖次数。 3. 用户是用自己的积分兑换的,账户会进行额度拦截。之后接口会配置频次拦截【大营销第4阶段有这个设计】 -4. 系统是有边界管控的,在实际工作中,当前的系统要保证发送mq,下游的系统要保证消费mq。mq的消费会有监控配置,比如日常每分钟100次,如果连续n次在n分钟内,低于80次或者高于140次,则进行报警。这样就可以监控到了。 \ No newline at end of file +4. 系统是有边界管控的,在实际工作中,当前的系统要保证发送mq,下游的系统要保证消费mq。mq的消费会有监控配置,比如日常每分钟100次,如果连续n次在n分钟内,低于80次或者高于140次,则进行报警。这样就可以监控到了。 + +### 【其他】8. 关于上下游交互的问题 + +1. 每次面试官都会问一嘴,基于ratelimiter是做单机限流吗? +实际生产中主要是使用分布式限流吗,为什么要基于分布式做呢,单机限流满足不了需求吗,分布式限流具体实现方式是什么呢,基于redis、zookeeper自己实现还是基于限流框架做呢 +2. 限流、降级有必要做到外部服务粒度的嘛?(例如有3个外部系统,有必要为每个系统单独限流、降级吗,例如只是不提供给某个系统服务) +3. 奖品单状态的变更,我还是有一点模糊,如果是下游发奖,那下游应该是不能访问奖品服务的库吧,那下游发完奖如何更新奖品单状态呢?会有回调接口或者是下游再发一个发奖完毕的消息吗? +4. 抽奖活动会和业务系统绑定吗?是不是得在活动表加一个字段,然后鉴权的时候只能调用当前系统的抽奖活动 + +解答:[https://t.zsxq.com/7uTKz](https://t.zsxq.com/7uTKz) + +### 【网易】9. 在抽奖过程时,需要预热处理,可是不可能让用户点击活动装配呀,这个问题你怎么解决? + +第一个视频里提到了,是在活动运营配置后,可以审核通过就预热了。等待活动到了有效期就可以使用了。 + +### 【网易】10. 在抽奖的结果中,如果一个用户在前端抽到了一个奖品,对用户是可见的。可是在扣减库存时,却发现没有了对应的库存,此时应该怎么办? + +库表设计中,抽奖的每条策略是有库存限制的,抽到后才会展示给用户。如果库存不足直接就是兜底积分了。这个也有人遇到过反过来问的,为什么要给策略上也加库存,直接奖品加库存不就可以。其实是不可以的。 + +### 【其他】11. 既然为了想承受更高并发使用redis做库存扣减,那生成奖品id后续要等中奖订单入库才能给用户展示结果吗?那用redis做库存扣减不就没意义了 + +最核心的其实是,如果没有redis做库存扣减,就要数据库里的一个库存记录做扣减。那么就会有成千上万条的请求在同一个表行记录开始独占竞争加锁,其余的请求进入等待,直至耗尽所有数据库连接。那么整个系统服务也就会被拖垮,一个普通的查询也会从原来的几十毫秒变成到一分钟也拿不到结果了。 + +使用redis,就是为了解决这个事情。之后在写入库里的记录,都是无竞争的。那么就不会让数据库被夯住。可以快速被处理。在大厂的数据库配置,基本这类操作不会被 redis 慢多少。 + +解答:[https://t.zsxq.com/kCjDL](https://t.zsxq.com/kCjDL) + +### 【其他】12. 你说你的系统压测指标是3000QPS(简历上我写了3000QPS压测指标),你认为你做的是这个系统压测到3000的时候,他的瓶颈在哪里? + +1. 你应该是描述的单个接口压测,3000qps,qps 指查询,这个过程没有写库,没有事务的操作。瓶颈往往在于接口串联的多,也包括rpc微服务,层层调用带来的性能损耗。其中性能损耗最大的,一般是风控类接口。之后优化可以用多线程并行调用,之后在统一把数据合并处理。你在回答的时候,可以讲,之前是多少qps,响应时间tp99、tp999、max是多少,之后经过与外部接口的协调,增加redis缓存预热,以及你在把接口通过多线程异步并行查询,提高了接口性能,增加了qps指标。另外,还有是单机还是分布式,每台机器配置的jvm,比如原来的指标配置是什么样,这次配置的是多少(这些可以从普罗米修斯监控得出,之后整理成回答)如果回答数据类的,一定要压测。 + +2. 抽奖用的是你的个人库存,这部分可以加分布式锁,一个活动,一个sc场景,只能一个抽奖进行中活动,这样组合一个key加分布式锁就可以了。 + +3. incr 这个星球里有很多资料了,分段锁接近于无锁化,乐观锁。而以前的直接加锁,锁全活动是独占锁,悲观锁。我们要的目的就是接近于不加锁,并且保证性能。另外 lua 脚本实际压测性能并不好。incr + 锁,尽可能避免超卖。但不加锁,基本等于裸奔,虽然大概率不出问题,但出问题是不可知的。我们做系统设计,就要考虑它可能存在的风险,尽可能降低,而不是等待它发生。资料;https://t.zsxq.com/F1J0L - 这里的话术可以使用「海恩法则、薛定谔的猫、墨菲定律、蝴蝶效应及熵增原理」。 + +- 解答:[https://t.zsxq.com/Gdttm](https://t.zsxq.com/Gdttm) +- 扩展:[https://t.zsxq.com/FWBzl](https://t.zsxq.com/FWBzl) + +>问题1:加分段锁的目的是为了什么? + +答:核心目标是为了防止低概率下集群、主从故障导致的超卖,做一个兜底逻辑。 + +>问题2:如果不需要补库存,分段锁是不是可以不用加? + +答:即使不考虑手动补库存的情况,如果集群、主从故障,不加分段锁还是会可能超卖的,所以这里的分段锁不单单是为了补库存的场景而设计。 + +>问题3:那直接 incr 不可以吗? + +答:在 redis 集群模式下,incr 请求操作可能发生网络抖动超时返回。这个时候 incr 有可能成功,也有可能失败。可能是请求超时,也可能是请求完的应答超时。那么 incr 的值可能就不准。【实际使用中10万次,可能会有10万零1和不足10万】,那么为了这样一个临界状态的可靠性,所以添加 setNx 加锁只有成功和失败。 + +还有一种情况是主从切换的时候,如果主节点的 incr 还没同步到从节点,主节点挂了,丢失了部分未同步的数据,incr 的值从 8 变成 6,如果没有加锁就可能超卖,属于极端情况下的一种兜底策略,有 setNX 锁拦截后,会更加可靠。 + +>问题4:那如果考虑集群故障,机器挂掉的情况,setNX 不也会报错吗? + +答:setNX 如果失败了,就直接报错返回 "活动库存不足" 即可,也就是可能会导致少卖,但是不会导致超卖。并且 incr 和 setNX 的 key 不同,incr 的 key 和滑块锁的 key 大概率不在同一节点上,从而双重保证,如果 senNx 的 key 和库存的 key 节点都 down 机了,那这里确实有超卖的可能,不过这个概率可以低到忽略不计。 + +>问题5:decr 和 incr 两种扣减方式有什么不同? + +答:二种方式都可以,decr 适合固定库存场景,和 0 对比,incr 适合可以补库存的场景,和库存总量对比。 + +>问题6:那为什么要分段,直接对一个 key senNX 不可以吗? + +答:分段锁的话,setNX 因为是非独占锁,所以 key 不存在释放。setNX 的 key 的过期时间可以优化为活动的有效期时间为结束。而独占锁,其实你永远也不好把握释放时间,因为秒杀都是瞬态的,释放的晚了活动用户都走了,释放的早了,流程可能还没处理完。 + +>问题7:incr 扣减模式下,如果同一个用户并发进来,那么缓存中的库存就会+并发数,但实际这个用户只会领取到一条数据,所以就要恢复并发数-1的库存数量。这样种情况并不是 redis 不稳定导致的,而是同一用户并发导致的,应该及时去恢复数据啊,不然的话缓存中的库存直接一下就给一个用户并发干没了,然后再去恢复,效率太低了吧? + +答:不需要恢复,还是回到上面,核心是保证不超卖,关于库存恢复,一般这类抽奖都是瞬态的,且 redis 集群非常稳定。所以很少有需要恢复库存,如果需要恢复库存,那么是把失败的秒杀 incr 对应的值的 key,加入到待消费队列中。等整体库存消耗后,开始消耗队列库存,等补偿恢复,活动已经基本过去了。所以超卖,快速结束是最好的。这个一般是基于运营策略配置何种方式恢复库存,可以失败的专门扫描到恢复库存列表用于消耗,也可以不恢复(因为失败概率很低,也允许不超买即可)。 + +### 【其他】13. decr已经是原子操作了「多个请求一定是串行的」,你为什么还要加setnx锁? + +答:[https://t.zsxq.com/0BC2f](https://t.zsxq.com/0BC2f) \ No newline at end of file diff --git a/docs/md/project/big-market/qa.md b/docs/md/project/big-market/qa.md new file mode 100644 index 000000000..7e63aa15f --- /dev/null +++ b/docs/md/project/big-market/qa.md @@ -0,0 +1,111 @@ +--- +title: Q&A:常见开发问题错误解答 +lock: no +--- + +# Q&A:常见开发问题错误解答 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/17gswKIeX](https://t.zsxq.com/17gswKIeX) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、断点调试 + +- [排查10个Bug](https://www.bilibili.com/video/BV1F6421w71e) +- [打断点查空指针](https://www.bilibili.com/video/BV1q1421Q7Uv) + +## 二、开发问题 + +### 1. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): top.duain.infrastructure.persistent.dao.IAwardDao.queryAwardList + +- 案例:[https://t.zsxq.com/ENr02](https://t.zsxq.com/ENr02) +- 解答: + - application.dev mybatis 配置,默认是被注释掉的,需要打开。 + - 自建工程结构,Application 启动层的文件夹路径,不是整个包结构的根路径,扫描不到 + - MyBatis Mapper 配置文件填写错误,没有配置对应的路径 + - app 层的 pom 文件,没有引入 infrastructure,所以不能被 Spring 容器管理导致。 + +### 2. Could not create to database server. Attempted reconnect 3 times. Giving up + +- 案例:[https://t.zsxq.com/7i31T](https://t.zsxq.com/7i31T) +- 解答: + - 课程中 docker compose 安装 MySQL,提供的是 13306 端口以及初始的密码(避免和你本地 MySQL 3306 冲突),所以你的 application.dev 数据库连接也要使用 13306 端口。 + - 安装到云服务器的,安全组 13306 端口没有打开。 + +### 3. java.lang.NullPointerException queryStrategyEntityByStrategyId(StrategyRepository.java:71) + +- 案例: + - [https://t.zsxq.com/x3Uz0](https://t.zsxq.com/x3Uz0) + - [https://t.zsxq.com/9QGLX](https://t.zsxq.com/9QGLX) + - [https://t.zsxq.com/BUtmX](https://t.zsxq.com/BUtmX) + - [https://t.zsxq.com/wstu6](https://t.zsxq.com/wstu6) + - [https://t.zsxq.com/P81oT](https://t.zsxq.com/P81oT) +- 解答: + - MyBatis Mapper resultMap 配置成了 resultType,导致数据库中的字段没法和 Java 对象的字段映射。如 `strategy_id -> strategyId` + - 注解忘记配置 + +### 4. java.lang.ArithmeticException: / by zero + +- 案例: + - [https://t.zsxq.com/4oSIt](https://t.zsxq.com/4oSIt) + - [https://t.zsxq.com/JxXhY](https://t.zsxq.com/JxXhY) +- 解答:粗心犯错,test_queryStrategyAwardListByStrategyId 入参为 100002L 不是 10002L。或者 redis 没有数据导致。 + +### 5. java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String + +- 案例:[https://t.zsxq.com/Uu8XA](https://t.zsxq.com/Uu8XA) +- 解答:由于 `getFromMap` 方法里是返回的 `String` 类型,而你设置的结果值为 `Integer` 类型,那么直接返回的值会报错类型转换异常。可以这样;`redisService.getMap("stratrgy_id_100001").get("1")` + +### 6. TooManyResultsExcepton: Expected one result (or null) to be returned by selectOne(), but found: 3 + +- 案例: + - [https://t.zsxq.com/7NUzA](https://t.zsxq.com/7NUzA) + - [https://t.zsxq.com/Di0oC](https://t.zsxq.com/Di0oC) + - [https://t.zsxq.com/gKu1H](https://t.zsxq.com/gKu1H) +- 解答:查询 sql 的条件入参写错,传了空值。用自己new的对象,获取里面的值,写错代码了。参考案例地址中的图片。 + +### 7. Redis 管理工具看错是乱码 + +- 案例:[https://t.zsxq.com/RpgCw](https://t.zsxq.com/RpgCw) +- 解答:RedisClientConfig 类,修改序列化方式 `config.setCodec(JsonJacksonCodec.INSTANCE);` + +### 8. map value can't be null + +- 案例:[https://t.zsxq.com/A4LaY](https://t.zsxq.com/A4LaY) +- 解答:修改对象类信息后,Redis 数据未清空重新测试。 + +### 9. 数据库查询无结果 + +- 案例:[https://t.zsxq.com/2DdEh](https://t.zsxq.com/2DdEh) +- 解答:入参格式化时间写错,导致格式的时间多了个空格。如案例图。 + +### 10. 决策树引擎,nextNode 计算失败,未找到可执行节点 + +- 案例:[https://t.zsxq.com/zNKob](https://t.zsxq.com/zNKob) +- 解答:规则树过滤章节后更细调整。可以跟着课程继续。 + +### 11. Cannot invoke String.split(String) because this.RuleModels is null + +- 案例:[https://t.zsxq.com/nENwa](https://t.zsxq.com/nENwa) +- 解答:可以看案例排查图 + +### 12. Unable to connect to Redis server: localhost/127.0.0.1:6379 + +- 案例:[https://t.zsxq.com/mrpne](https://t.zsxq.com/mrpne) +- 解答:缺少配置 Redis 启动类。 + +### 13. Mock 就走不到黑名单了 + +- 案例:[https://t.zsxq.com/iO5kL](https://t.zsxq.com/iO5kL) +- 解答:Mock 值未调整,参考案例解答图。 + +### 14. 找不到分库下的分表 + +- 解答:Dao 类缺少 `@DBRouterStrategy(splitTable = true)` + +## 三、DevOps + +- Docker 拉取不下来镜像,超时;配置镜像地址;[https://t.zsxq.com/EVDc9](https://t.zsxq.com/EVDc9) +- jdk1.8、maven(含镜像)下载:[https://t.zsxq.com/EVDc9](https://t.zsxq.com/EVDc9) \ No newline at end of file diff --git a/docs/md/project/big-market/system-design-diagram.md b/docs/md/project/big-market/system-design-diagram.md new file mode 100644 index 000000000..43da2080a --- /dev/null +++ b/docs/md/project/big-market/system-design-diagram.md @@ -0,0 +1,132 @@ +--- +title: 设计:架构图、拓扑图、用例图、流程图、建模图 +lock: no +--- + +# 《大营销平台系统》系统设计图:架构图、拓扑图、用例图、流程图、建模图 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/17gswKIeX](https://t.zsxq.com/17gswKIeX) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +😂 现在的面试是不是为难小朋友,怎么刚一毕业的面试,就让现场手画简历项目的系统架构图。面试官说,你不是计算机专业毕业🎓的吗,这不是你的基础吗?你作为一个合格的毕业生,不就应该学习到这些吗? + +
+ +
+ +**为什么毕业生,画不出来这些图?** + +其实不只毕业生,很多工作1-3年的也画不出这些系统的架构图。主要是因为,在校的时候没有学过,市面的一些简单学习项目也都是 CRUD 的 demo 级别项目,工作了以后如果又是一些小厂,大部分就是完成功能需求而已。所以很多人压根就没有画过这些图。 + +但作为程序员👨🏻‍💻这个行业的伙伴,如果还想多职业生涯走的更长,也多赚点米,那么就需要好好的在一个大型项目中锻炼这些画图的技能。因为一图胜前言,有时候图好,前途就好! + +那一个系统都会做出哪些个设计图呢?这里会包括;`系统架构图`、`业务拓扑图`、`用户用例图`、`业务流程图`、`系统建模图`,之后就是细分实现功能的 UML 流程图。这里小傅哥会以此的给大家做绘制和讲解,这趟车🚗你可以学习到很多! + +>文末提供了本次分享系统设计图对应的系统工程全套代码、文档、视频和面试官以及简历资料。 + +## 一、系统的场景 + +这是互联网公司C端场景,峰值流量最高的一套**营销类业务系统**,业务涵盖;`抽奖`、`活动`、`积分`、`返利`、`兑换`,这些核心的业务流程。像是在`抖音商城`、`京东金融`、`滴滴出行`、`拼多多`,都有这样业务场景。如图; + +
+ +
+ +整个系统是一个包括 `前后端 + Dev-Ops` 的全栈式综合编程实战项目,基于 React + SpringBoot + 分布式技术栈 + Nginx + Grafana + Docker 云服务,开发、部署、上线、监控,全体系技术运用构建。 + +> 接下来,小傅哥就给大家分别的展示出各项设计图,包括;`系统架构图`、`业务拓扑图`、`用户用例图`、`业务流程图`、`系统建模图`。 + +## 二、系统架构图 + +**软件架构**是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。软件架构会包括软件组件、组件之间的关系,组件特性以及组件间关系的特性。软件架构可以和建筑物的架构相比拟。软件架构是构建计算机软件,开发系统以及计划进行的基础,可以列出开发团队需要完成的任务。 + +
+ +
+ +- 这是一套大营销系统的分布式架构设计图,从前端到负载,从服务治理到后端分布式技术栈体现,从应用到部署和监控的全体系展示。在这样一套系统架构中,你可以清楚的知道从前到后的流程、各项分布式技术栈的用途、整个系统的脉络关系。所以这样的一个图可以清晰的指导我们做系统的搭建。 +- `佛瑞德·布鲁克斯`在写作《人月神话》一书时提及:软件系统的架构是有关软件系统该作什么以及不该作什么的实体观点。这些观点应和软件的实现分开。架构师的角色是“观点的看守者”,确认系统中增加的部分是符合此架构,因此可以保有概念完整性 +- 另外程序员`马尔文·康威`在1967年论文发表了康威定律,其中提到一个组织开发的软件,其架构会反映其组织架构。佛瑞德·布鲁克斯在写作《人月神话》一书时,就在书上时提到此例子,命名为“康威定律”。 + +## 三、用户用例图 + +用例图(英语:use case diagram)是用户与系统交互的最简表示形式,展现了用户和与他相关的用例之间的关系。通过用例图,人们可以获知系统不同种类的用户和用例。用例图也经常和其他图表配合使用。 + +- 用例图,也可以等同于是用户故事(英语:User story)(软件开发和项目管理中的常用术语),主旨是以日常语言或商务用语撰写句子,是一段简单的功能表述。以客户或使用者的观点撰写下有价值的功能、引导、框架来与使用者进行互动,进而推动工作进程。可以被认为是一种规格文件,但更精确而言,它代表客户的需求与方向。以该用户故事来反应对象在组织内的其工作职责、范围、需要进行的任务等。用户故事在敏捷开发方法中用来定义系统需要提供的功能和实现需求管理。 +- 尽管用例本身会涉及大量细节和各种可能性,用例图却能提纲挈领地让人了解系统概况。它为“系统做什么”提供了简化了的图形表示,因此被誉为“搭建系统的蓝图”。 + +
+ +
+- 用例图是研发进入设计阶段第一个图,通过用例图了解整个系统中发生的流程行为。这个图虽然很粗,但非常适合做后续的设计指导。 + + +## 四、业务拓扑图 + +系统业务拓扑图通常是指系统中各个组件和业务流程的可视化表示。这类图示有助于理解和分析系统如何运作、各组件之间的关系、数据流动的路径以及可能的瓶颈或失败节点。 + +
+ +
+ +- 业务拓扑图,展示出了业务实现中的关系模型,包括整个系统会从哪里展示,包括了哪些核心业务功能和执行的链路。以及数据的走向。 +- 有了系统业务拓扑图,开发者、系统架构师和运维人员可以更直观地理解系统的结构和业务逻辑,从而更有效地进行设计、部署、监控和故障排除。 + +## 五、四色建模图 + +如果系统是 DDD 开发的,还需要做四色建模。在使用 DDD 的标准对系统建模前,一堆人要先了解 DDD 的操作手段,这样才能让产品、研发、测试、运营等了解业务的伙伴,都能在同一个语言下完成系统建模。 + +- 蓝色 - 决策命令,是用户发起的行为动作,如;开始签到、开始抽奖、查看额度等。 +- 黄色 - 领域事件,过去时态描述。如;签到完成、抽奖完成、奖品发放完成。它所阐述的都是这个领域要完成的终态。 +- 粉色 - 外部系统,如你的系统需要调用外部的接口完成流程。 +- 红色 - 业务流程,用于串联决策命令到领域事件,所实现的业务流程。一些简单的场景则直接有决策命令到领域事件就可以了。 +- 绿色 - 只读模型,做一些读取数据的动作,没有写库的操作。 +- 棕色 - 领域对象,每个决策命令的发起,都是含有一个对应的领域对象。 + +
+ +
+ +- 系统建模后可以细分出系统开发中要实现的领域,包括;返利、活动、策略、奖品,兑换可以是单独的领域也可以合并到返利实现。 +- 具体的建模过程可以阅读 [《架构:DDD 领域驱动设计,战略、战术、战役,落地指引规范》](https://bugstack.cn/md/project/big-market/ddd.html) + +## 六、业务流程图 + +系统业务功能流程图(Business Functional Flow Diagram,BFD)是一种用于描述和展示系统内业务功能及其之间关系的图形化工具。它通常用于系统分析和设计阶段,以帮助理解和沟通业务流程、功能要求以及系统的各个组件如何协同工作。 + +
+ +
+ +- 在该流程中,详细的展示出了系统的业务流转关系,从1~6的用户行为,全面的展示出了系统中的流程动作。怎么抽奖、怎么返利、怎么兑换积分。 +- 画这个图到时候,首先,需要识别系统中的主要业务功能。这些业务功能通常可以通过业务需求文档、需求分析会谈以及与业务用户的交流中得出。之后,识别各业务功能之间的关系和依赖性。这包括理解哪些业务功能依赖于哪些其他功能,以及它们如何相互作用。最后,绘制流程图,以图形方式展示业务功能和它们之间的关系。 + +## 七、工程分层图 + +工程的分层有 MVC 三层架构、DDD 四层架构,其实 DDD 不能只是说它是架构,因为用于承载 DDD 的架构是;整洁架构、洋葱架构、六边形架构、菱形架构这些。 + +
+ +
+ +- 六边形架构,会把本身提供到外部的放到trigger,让接口调用、消息监听、任务调度,都可以统一一个入口处理。而对于需要调用外部同类的能力统一放到 infrastructure 基础设施层,包括;数据库、缓存、配置、调用其他方的接口。 +- querys 模块是为了提供查询设计的模块,这样一些基本简单的查询就不需要再走到 domain 领域层了。 +- 更多关于 DDD 的工程模型,可以在 [bugstack.cn](https://bugstack.cn) 进入《路书》中阅读9篇系统架构部分。 + +## 八、扩展类知识 + +这是小傅哥为大家提供的一套综合锻炼编程能力的实战项目大课。全程视频手把手,一个个章节、一步步流程的带着大家从0到1,需求分析、工程设计和代码实现。 + +课程完成后,有可参考简历编写模板、简历面试问题汇总、项目延展性思考和分析,以及项目中的架构、设计模式在场景方案中的运用。 + +- 课程目录:[https://bugstack.cn/md/project/big-market/big-market.html](https://bugstack.cn/md/project/big-market/big-market.html) +- 系统建模:[https://bugstack.cn/md/project/big-market/ddd.html](https://bugstack.cn/md/project/big-market/ddd.html) +- 简历参考:[https://bugstack.cn/md/project/big-market/notes.html](https://bugstack.cn/md/project/big-market/notes.html) +- 面试问题:[https://bugstack.cn/md/project/big-market/notes.html](https://bugstack.cn/md/project/big-market/notes.html) diff --git a/docs/md/project/chatgpt/chatgpt.md b/docs/md/project/chatgpt/chatgpt.md index 82d9b66a6..4597f78d0 100644 --- a/docs/md/project/chatgpt/chatgpt.md +++ b/docs/md/project/chatgpt/chatgpt.md @@ -7,6 +7,7 @@ lock: no 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) +
体验:[https://openai.gaga.plus](https://openai.gaga.plus) >沉淀、分享、成长,让自己和他人都能有所收获!😄 @@ -24,9 +25,9 @@ lock: no 作为一个纯搞技术的号主,我更希望做符合技术人员长期发展的学习事项。如 ChatGPT、文心一言、通义千问、AIGC、Civita,这样的东西会越来越多,而作为研发更应该注重以`生成式服务`所搭建出一套体系化应用微服务。所以小傅哥的星球又要带着大家搞新项目了 **《ChatGPT 微服务应用体系构建》** - 说到又,那小傅哥的星球搞了多少项目🤔? -除技术小册外,星球历经项目5个:- `加入小傅哥的知识星球,相当于付费1个项目的价格,就可以学习所有过往的项目!` +除技术小册外,星球所有项目都可以学习:- `加入小傅哥的知识星球,相当于付费1个项目的价格,就可以学习所有过往的项目!` -- 《ChatGPT 微服务应用体系构建 - API-SDK、鉴权、公众号对接、微信对接、交易支付》- **5.1日启动** 🌲 +- 《ChatGPT 微服务应用体系构建 - API-SDK、鉴权、公众号对接、微信对接、交易支付》 - [《ChatGPT AI 问答助手》](https://bugstack.cn/md/project/chatbot-api/chatbot-api.html) - [《API网关 - 中间件设计和实践》](https://bugstack.cn/md/assembly/api-gateway/api-gateway.html) - [《SpringBoot 中间件设计和开发》](https://bugstack.cn/md/assembly/middleware/2019-12-02-SpringBoot%E6%9C%8D%E5%8A%A1%E6%B2%BB%E7%90%86%E4%B8%AD%E9%97%B4%E4%BB%B6%E4%B9%8B%E7%BB%9F%E4%B8%80%E7%99%BD%E5%90%8D%E5%8D%95%E9%AA%8C%E8%AF%81.html) @@ -54,7 +55,7 @@ lock: no ## 三、`开发`的计划 -**死鬼**,5.1 假期即将来临,又到了疯狂的带着星球伙伴卷代码的时候。所以从 5.1 放假开始,小傅哥会逐步更新课程内容,粗略计划; +**死鬼**,又到了疯狂的带着星球伙伴卷代码的时候。 - OpenAI 接口服务 + Nginx SSL 配置 - OpenAI SDK diff --git a/docs/md/project/group-buy-market/group-buy-market.md b/docs/md/project/group-buy-market/group-buy-market.md new file mode 100644 index 000000000..a25927e41 --- /dev/null +++ b/docs/md/project/group-buy-market/group-buy-market.md @@ -0,0 +1,149 @@ +--- +title: 拼团支付平台系统 +lock: no +--- + +# 《拼团交易平台系统》- 为各类交易场景,提供拼团服务。 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/Yfbwo](https://t.zsxq.com/Yfbwo) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +**耗时9个月制作,48节课程,微服务分布式架构**,`前后端 + DevOps + AI MCP(场景运用)`,全栈式编程 + 全程视频 + 全套的技术小册,手把手👨🏻‍💻教学,终于完结啦!🎉 + +
+ +
+ +**讲道理,做项目,就得做公司里真实有的业务。** + +我在非常多的互联网业务应用中,都看到过这样一种产品形态,它就是**拼团交易营销场景**,如;`拼多多/京东购物🛒`、`滴滴拼券🧧`、`腾讯开团抢购服务器☁️`、`美团团购☕️`等等,都是以拼团方式增强交易单量的业务场景。所以,如果想面试互联网公司,还是要优先考虑做一些这样的真实场景业务,这样才能和面试官有东西可以讲,而不是什么都没的聊o(╥﹏╥)o。 + +此套项目,小傅哥已提供了对应的`简历模板`、`面试问题(一直梳理中)`,还有 AI MCP 场景的加入,通过 AI MCP 对接 ELK + 普罗米修斯监控,Ai Agent 智能化分析系统的日志和运行情况。 + +**本项目,和你之前学习过的一些项目最大的区别,就是!这是真实的业务,全核心流程覆盖,有非常好的架构和编码设计。这块学习后,进入公司完全可以跟着大家一起做需求,而不是瑟瑟发抖的不知道自己要做啥!** + +
+ +
+ +> 文末有加入学习方式,提供全套的课程代码、文档、视频,此外还有额外的16个实战项目一起获取! + +## 一、能学到啥 + +该项目是互联网toc场景的核心业务流程,以真实业务作为背景,实际可上线,可运行为目标,进行系统的需求分析、架构设计、功能实现,过程涵盖设计模式的运用,解决复杂场景问题。让大家感受到,🐂牛逼的代码,从来不是一顿写CRUD! + +- 【前端】以 Ai Agent 设计前端 UI,包括 HTML、Div、CSS 等前端编程技术。 +- 【前端】掌握 fetch 方式对后端接口的调用,处理相关的逻辑数据。 +- 【后端】熟练搭建项目工程,学习工程分层结构概率和设计思路。掌握更多的六边形、洋葱、整洁架构。`提高简历技术亮点` +- 【后端】熟练掌握 Spring、SpringBoot、MyBatis 等开发框架技术,并对框架源码所提供的扩展接口具备运用能力。 +- 【后端】熟练使用 SpringCloud 核心微服务分布式技术栈,包括:Fegin、Sentinel、Nacos、熔断、限流、降级等。`先做功能,后面逐步添加。` +- 【后端】熟练使用大厂中常用的设计模式手段和设计原则技术,对各类场景的方案设计和落地能力,深度提高自身编码思维和开发技术能力。 +- 【后端】深度学习复杂场景的架构设计、编程思维,如果处理系统功能的边界和上下文的维护。—— 这些东西一定是从实践中才能学习到的。 +- 【后端】熟练使用 Mock 单测工具、JMeter 压测工具,增强代码交付质量。 +- 【后端】熟练掌握异常、枚举、错误码的定义和使用,并学习到如何合理打印服务日志,便于问题排查。 +- 【后端】以通用场景设计为目的,提取共性逻辑为通用的设计框架,涵盖;动态配置、设计模式(规则树、责任链)、限流。 +- 【运维】熟练使用 Docker 在本地和服务端的配置和部署应用,以及在本地构建前后端镜像。 +- 【运维】熟练掌握 Git、GitCode,对工程代码的管理,推送、拉取、切换分支、合并代码等操作。 +- 【运维】熟练使用 Nginx 配置转发服务,并能申请ssl配置https服务。 +- 【运维】熟练使用 Grafana 监控系统 + AI MCP,对系统的 JVM、磁盘、Tomcat、应用(QPS、响应时间、调用量)完整监控。 + +此外,小傅哥已对全过程都做了需求的分析、功能的设计、编码的精细化处理,让你吃上细糠!也通过这种方式,真正的把你的技术储备整起来,以后进入到公司都是嘎嘎强的选手! + +## 二、运行展示 + +整个拼团交易的流程非常细腻,包括了,一套小型支付 + 拼团营销平台的完整对接,涵盖;`验签`、`扫码/无痕登录`、`试算`、`锁单`、`支付+结算`、`退单+退单`的完整链路流程。如图; + +
+ +
+ +
+ +
+ +
+ +
+ +前端页面体现了全部核心流程,看着前端不是太多,但后端支撑整套系统了,写了**1.38万行代码**! + +>体验地址(部分功能):[http://117.72.38.125:3080/index.html](http://117.72.38.125:3080/index.html) + +## 四、后端设计 + +### 1. 分层架构 + +
+ +
+ +- 整个系统是一个微服务分布式架构设计,通过两套系统的对接,体现微服务的全流程处理关系。 +- 下面是系统中用到的核心技术栈,框架、组件、监控、部署、发布、上线,可以说是非常全面。 + +### 2. 工程结构 + +
+ +
+ +- 拼团和交易系统,以面向对象的思维,划分出领域结构。活动域、标签域、交易域、鉴权域、商品域、订单域。 +- 两套系统通过 http/rpc(可配置对接)、mq(RabbitMQ)进行同步和异步交互,因为配有本地消息表,所以可以保证最终一致性。 +- 这里有非常精妙的编码设计,如;工厂模式、组合模式、策略模式(含枚举策略)、责任链、抽象类等,又提供了 Supplier 函数式编程,可以说是应有尽有! + +### 3. 库表数据 + +
+ +
+ +- 一看库表就知道,这不是小儿科!有标签表,有活动的优惠,组队,订单明细,本地消息表,商品活动配置表,sku表。 + +### 4. 用户旅程 + +
+ +
+ +- 拼团全流程简图,以用户旅程来看各个节点所做的事项。 + +### 5. 场景举例 - 设计模式 + +#### 5.1 试算 + +
+ +
+ +
+ +
+ +为了解决整个交易过程的复杂场景,做了一套通用设计模式框架,并结合一套异步数据加载的多线程设计,来解决加载数据效率问题。让整个框架的灵活性非常高。 + +#### 5.2 退单 + +
+ +
+ +- 第一条退单链路,以工厂🏭方式获取执行责任链,责任链的作用是拆分原有的流程结构,分节点进行逐步处理。之后到退单的具体操作,则根据枚举策略,拿到对应执行的退单策略模式,完成退单动作。退单执行后发送MQ消息,驱动后续流程。 +- 第二条消息消息,从接收 MQ 开始,以 MQ 消息中的策略类型进行库存恢复操作。这部分保持原有的走对应的策略即可。 + +>课程包括;视频、小册、1 对 1 答疑解惑、专属VIP项目交流群,并且提供简历编写模板结构的一条龙🐲服务。让你学习后,直接拉开与还在玩具项目其他人的差距,面试脱颖而出提高竞争力!!! + +## 四、加入学习 + +跟着小傅哥学习,不会浪费时间,不会走小道弯路。全程做技术兜底,遇到的各种问题都能帮你解决。包括你学习时候的代码bug,可以把代码提交到星球,我来帮你调试。最终把兄弟们送到各个竞争赛道的头部,拿到最牛的薪资待遇 Offer! + +
+ +
+ +>🧧 [加入](https://bugstack.cn/md/zsxq/other/join.html) 每年招聘,都能帮助兄弟们规划好学习路线,卷出最好的 Offer!星球里还有500份评审过的简历记录,看过后,就知道怎么写好简历了。 diff --git a/docs/md/project/group-buy-market/none.md b/docs/md/project/group-buy-market/none.md new file mode 100644 index 000000000..f64218b2f --- /dev/null +++ b/docs/md/project/group-buy-market/none.md @@ -0,0 +1,15 @@ +--- +title: 新章节,编写中 +lock: no +--- + +# 新章节,编写中 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、前言 + +... 新章节,编写中 \ No newline at end of file diff --git a/docs/md/project/group-buy-market/notes.md b/docs/md/project/group-buy-market/notes.md new file mode 100644 index 000000000..ddaf40e38 --- /dev/null +++ b/docs/md/project/group-buy-market/notes.md @@ -0,0 +1,173 @@ +--- +title: 面试:技能、简历、问题汇总 +lock: no +--- + +# 《拼团交易平台系统》,关于面试中的技能、简历、问题汇总 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/Yfbwo](https://t.zsxq.com/Yfbwo) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +此部分主要用于向读者提供星球项目之一的《拼团交易平台系统》项目如何体现到简历中,包括;专业技能、项目经验。 + +## 一、项目介绍 + +你可以根据是实习、实践、导师任务、学校课程、自己学习,几个方向来描述项目来源。 + +举例; + +面试官你好,拼团交易平台系统,是我在日常使用`拼多多`、`腾讯`、`京东`等服务平台,交易支付时候,了解到这样的一种营销手段。它可以通过用户自传播方式增强交易量,也是拼多多最开始起家形成巨大规模的一个业务逻辑。因此非常感兴趣这样的系统,所以根据大厂分享的资料、与对应的架构师UP进行交流学习了,设计了这样一套系统。 + +该系统采用了 DDD 领域驱动设计进行建模,拆分领域模块边界,形成;活动领域、人群领域、交易领域,来构建拼团营销交易流程,达到试算、锁单、结算等步骤流程。这个过程中提炼了通用设计模式,规则树、责任链,可以非常有效的统一的治理流程编排实现。 + +## 二、简历模板 + +注意:🙅🏻‍ 不要直接复制粘贴简历模板内容!视频提供了 DeepSeek AI 方式编写简历,可以参考。 + +- **项目名称**:`拼团营销服务系统`、`交易营销场景 - 拼团系统`、`营销拼团交易平台`、`仿拼多多/腾讯/京东,拼团玩法系统(以大厂项目为背书)`、`拼团外卖平台系统(结合其他项目一起组合)` - 参考以上方式编写自己的项目名称,尤其拼团还是一个微服务,可以和很多其他系统组合。 + +- **项目架构**:`微服务设计`、`分布式架构`、`DDD 领域驱动设计 + 六边形分层架构实现`、`前后端分离技术` + +- **核心技术**:SpringBoot、MyBatis、MySQL、Guava、Redis、RabbitMQ、动态配置中心(DCC)、普罗米修斯监控、Docker等 - 如果学习了其他技术栈也可以补充。 + +- **项目描述**: + - 方式1(以学习视角介绍):本项目参考`拼多多`交易购物拼团场景,调研中大厂相关营销业务场景和技术架构方案,设计实现了本套拼团营销服务系统,支持各类营销优惠(直减、折扣、N元购)。该系统以面向对象开发,运用 DDD 拆分领域边界,使用设计模式设计服务功能。提高系统的扩展性和可维护性。 + - 方式2(以提供服务介绍):该项目以`拉动/促进/提高`(小型支付商城/外卖点餐/购票出行/...)交易单量为目标,通过设计拼团优惠组队下单为手段,达到增强用户自传播分享私域提高整个交易GMV的结果。三段式描述,`...目标,...手段,...结果` + - 方式3(以实际场景介绍):该项目是以促进Xxx公司Xxx场景的核心营销优惠玩法系统,围绕公司的xxx、yyy、zzz等全部交易业务,设计通用的拼团优惠锁单和组队结算回调服务。此系统分布式架构设计,可支撑单机压测量 xxx tps,tp99 xxx 的数据指标,有效的满足公司的全量的业务场景接入使用。 + +- **核心方案**: + + - **架构设计**,以 DDD 领域驱动设计,四色建模方式,按照系统功能流程,拆解服务边界。包括;活动域、标签域、交易域。 + - **设计模式**,设计并提炼通用的`责任链`、`规则树`模型框架,解决领域场景中多处,需要使用设计模式解耦复杂流程链路的调度(避免过多的if...else判断)。鉴于多处场景的责任链使用,模块框架设计责任链为执行和链路分离组装,便于工厂可以组合出各类执行责任链,不被不同的链路管理影响(以往的责任链,一般是单例的,会被影响)。 + - **规则过滤**; + - (举例)以拼团试算场景举例,运用通用设计模式模型框架,完成试算;根节点、切量开关、营销折扣、人群标签、异常兜底等流程串联。设计这样解耦设计,极大的提到了程序的可扩展性。 + - (举例)以拼团锁单场景举例,拼团锁单场景,使用通用的责任链模型框架,校验活动的有效性(状态、有效期)和用户的参与资格。 + - (举例)以拼团结算场景举例,拼团结算场景,使用通用的责任链模型框架,校验渠道黑名单配置、拼团组队信息、交易时间属性、订单有效状态等。 + - (举例)以拼团试算场景举例,在查询优惠配置数据时候,抽象出模板结构,使用 Supplier 函数式编程,设计动态降级、缓存数据和 dao 的后置执行操作。通用模板的设计让所有场景更容易接入。`ActivityRepository#queryGroupBuyActivityDiscountVO` + + - **异步线程**,为提高用户体验,将拼团优惠试算所需的营销类数据加载,由串行改为异步线程并行执行。此执行方式由通用设计模式模型框架提供。(如果由引入星球的动态线程池,也可以在这里增加线程池的管理描述) + - **功能方案**; + - (举例)通过 Redis 发布订阅模型,结合 Spring AOP 切面和代理,以自定义注解的方式控制属性信息动态配置。减少系统与 Redis 的 IO 交互,提高对高频场景属性值的使用时间效率。 + - (举例)设计拼团组队结算的 HTTP、MQ 双重手段,满足外部应用和内部微服务的不同方式对接,增强系统的适配性。同时为了保证整体方案的可靠性,在结算触达时,先异步多线程方式即时触发回调(HTTP、MQ),再通过业务一致性任务数据补偿校验。(MQ、HTTP,都可能因网络原因导致失败,因此需要重试)任务的触达,还增加多分布式锁,让任务互备抢占方式执行,增强系统的鲁棒性设计。 + - (举例)设计 Redis BitSet/BitMap 人群标签,用于过滤可见和可参与,拼团活动的人群信息。该人群标签可依赖于过往用户数据(交易下单)通过 job 任务完成人群标签的录入。 + - (举例)通过策略模式,设计拼团折扣(MJ、ZJ、NYG)的计算策略。同时折扣的计算也会通过人群标签过滤,以满足运营策略配置,降低活动风险。 + - (举例)运用 retrofit2/okhttp3/spring cloud fegin + nginx 负载,对接拼团交易平台锁单服务,以及通过 http 回调和 MQ 监听来处理交易结算。 + - (举例)`三阶段实现的内容`,通过独占锁处理互备任务抢占执行回调,确保在同一时刻有一个运行的回调任务,提高系统的鲁棒性设计。 + - (举例)`三阶段实现的内容`,设计Redis无锁化拼团库存抢占和恢复库存处理,减轻数据库行锁独占的压力,提高系统吞吐量。 + - (举例)`三阶段实现的内容`,抽象通用函数式缓存分级设计,并结合扳手工程DCC动态配置,处理缓存降级到DB设计。 + - (举例)`三阶段实现的内容`,结合 RateLimiter + DCC 动态配置,实现动态限流配置。 + - (举例)`三阶段实现的内容`,以 Ai MCP + ELK + 普罗米修斯监控,以 Ai Agent 智能体方式,分析错误日志和异常监控,动态化展示监控报表。 + - (举例)`三阶段实现的内容`,通过枚举策略,设计多种类型退单(未支付&未成团、已支付&未成团、已支付&已成团),并通过回调处理退单退款。 + +> 不要局限于以上的描述,可以结合 Ai + 喂进去的信息,给你描述出属于你独一无二的简历描述。这样更有益于你的面试。 + +## 三、面试问题 + +### 1. 为什么需要拼团平台使用http或rpc,mq对接商城平台,而不是二者放到一起? + +http、rpc,属于即时性调用,立即反馈结果的场景。mq 用于异步驱动,流程解耦。而拼团组队的场景,组队是需要多人参与和支付的情形,只有统一完成拼团后,才能 mq 驱动后续流程。而不是一开始 http 请求就能立马拼团组队完成。 + +### 2. 为什么做了微服务的拆分,拆分的依据是什么?为什么拆分了微服务之后还要拆分领域?可不可以每个领域都作为一个微服务? + +微服务的目的是划分大的系统边界,拆分原则可以包括;按业务功能拆分、按数据模型拆分、按团队结构拆分、按技术特性拆分、按变更频率拆分,但不要过度细化的拆分,避免造成分布式系统过度复杂性。 + +而对于拼团场景是一个独立的营销玩法,可以被拆分成一个独立的微服务。这样迭代、维护、上线,也都会更加轻量,也便于与其他平台对接。之后对于拼团内的服务模块,都以支撑拼团为主,符合最新当前的诉求进行设计。当然没有永远的适合,如果将来拼团变得更大,需要支撑的场景更多,也会考虑做模块的微服务拆分。 + +### 3. 优惠试算使用了多线程异步加载,为什么这里不用缓存? + +试算加载的是当前用户行为的最新数据,而缓存则不适用于此场景。当然如果试算中有一些不频繁变化的偏固定的配置类数据,则可以通过缓存处理。另外,在公司(美团、京东、字节、滴滴等)拼团场景则更为复杂,试算时候需要的数据量更多,多线程则会更体现出必要性。 + +### 4. 平台在高并发下的扣减库存和防止超卖是怎么做的? + +这一块的库存扣减使用的是无锁化设计,setnx 兜底。但如果是加分布式锁,则会出现排队问题,达不到最大并发的效果。而因库存使用了 redis 计数 + 锁,以及添加了幂等恢复量,所以不会有超卖问题。 + +### 1. 项目设计与架构 + +1. **为什么选择DDD领域驱动设计?如何划分领域边界?** + **答**:DDD能有效解决复杂业务逻辑的拆解问题,通过四色建模和业务场景分析,划分出活动域(管理拼团规则)、标签域(用户画像和权限过滤)、交易域(订单和结算)。例如,拼团锁单流程属于交易域,而人群标签过滤属于标签域。 +2. **微服务间如何通信?如何保证数据一致性?** + **答**:对内外对接系统,分别采用HTTP(Feign/RestTemplate)和 MQ(RabbitMQ)方案。关键链路(如订单结算)通过MQ保证最终一致性,结合本地事务表+补偿任务(如定时检查未完成的结算请求)。 +3. **六边形架构如何落地?解决了什么问题?** + **答**:通过适配器层隔离核心业务与外部依赖(如数据库、Redis)。例如,订单结算的核心逻辑独立于HTTP回调或MQ监听的具体实现,提升核心代码的稳定性和可测试性。 + +> DDD 是一个亮点,中大厂公司都在推进 DDD 的项目重构。站在技术角度,这样的架构更好维护。站在领导角度,这样的拆分可以更好了解系统设计便于制订KPI。同时有清晰的业务领域划分,AI 开发工具可以更好的结合进来。[招聘里DDD的体现,jump 🏃🏻](https://bugstack.cn/md/zsxq/memorabilia/job-hire-jd.html) + +### 2. 核心技术实现 + +1. **Redis在项目中如何应用?举例说明** + **答**:1)BitMap存储用户标签(如是否参与过某活动);2)分布式锁控制拼团组队结算触达并发;3)缓存活动配置(如有效期、折扣规则),降低数据库压力。 + +2. **责任链模式如何解耦复杂流程?举例说明** + **答**:拼团锁单流程拆解为多个处理器链:活动状态校验→用户资格校验→库存检查。每个处理器独立实现,通过工厂模式动态组装,避免if-else嵌套。 + +3. **异步线程如何优化性能?如何管理线程池?** + **答**:将营销数据加载从串行改为并行(如使用CompletableFuture)。通过动态线程池监控任务队列和拒绝策略,结合普罗米修斯采集指标,避免线程池耗尽。`注意多准备下多线程、线程池的八股` + +### 3. 核心业务场景 + +1. **拼团结算的HTTP和MQ双重回调如何设计?如何保证可靠性?** + **答**:1)结算后同时发送HTTP请求和MQ消息;2)异步线程池处理回调,失败后进入重试队列;3)定时任务补偿未完成回调,配合分布式锁避免重复执行。 +2. **人群标签如何通过BitMap实现?举例说明** + **答**:例如,用户ID哈希后映射到BitMap的某一位。运营配置“仅限新用户”的活动时,Job任务扫描历史订单,将老用户对应位标记为0,查询时通过`BITCOUNT`判断资格。 +3. **策略模式在折扣计算中的应用?如何扩展新策略?** + **答**:定义接口`DiscountStrategy`,实现类 `MJCalculateService`(满减)、`NCalculateService`(N元购)、`ZJCalculateService`(直减)、`ZKCalculateService`(折扣)。新增策略时只需添加实现类并注册到Spring上下文,通过策略工厂按类型调用。 + +### 4. 高并发与容错(这部分会在第3阶段加入) + +1. **如何解决库存超卖问题?** + **答**:1)Redis原子操作(DECR)预扣库存;2)数据库最终扣减时加乐观锁;3)异步补偿任务回滚异常订单。 +2. **分布式锁的实现方案?遇到过哪些坑?** + **答**:基于Redis的Redisson(看门狗机制续期)。注意点:1)锁粒度细化(按活动ID+商品ID);2)避免锁过期后业务未执行完,需结合版本号校验。 +3. **如何设计熔断降级策略?** + **答**:Sentinel监控外部服务(如支付接口)的异常比例,超阈值时熔断,降级为返回默认错误码或缓存数据,并记录日志供补偿任务处理。 + +### 5. 监控与运维(这部分会在第3阶段加入) + +如配置说明接入普罗米修斯监控,同时也可以使用 arthas、dump mat。地址:[https://bugstack.cn/md/road-map/grafana.html](https://bugstack.cn/md/road-map/grafana.html) + +1. **普罗米修斯监控哪些指标?如何定位性能瓶颈?** + **答**:监控接口TP99、线程池活跃度、Redis命中率、MQ堆积量。通过Grafana仪表盘分析慢SQL(MyBatis拦截器采集)或高耗时责任链节点。 +2. **动态配置中心如何实现?如何保证实时性?** + **答**:基于Nacos/Zookeeper,配置变更时通过Spring Cloud Bus通知服务。关键配置(如活动开关)结合本地缓存,通过@RefreshScope实时生效。 +3. **Docker化部署的优化经验?** + **答**:1)多阶段构建减小镜像体积;2)JVM参数调优(-Xmx限制内存);3)健康检查接口 skywalking、artash 探针结合,实现系统监控。 + +### 6. 设计模式与代码规范 + +1. **规则树模式如何实现?举例说明** + **答**:根节点为入口,子节点为具体规则(如切量、标签过滤)。每个节点实现`RuleNode`接口,通过组合模式构建树形结构,支持动态扩展节点。 +2. **如何避免策略模式带来的类膨胀问题?** + **答**:1)将策略实现类定义为无状态Bean,复用实例;2)通过注解+自动扫描注册策略;3)策略参数化配置,减少重复代码。 +3. **AOP在项目中的典型应用场景?** + **答**:1)DCC 动态配置中心;2)@LogTrack 记录核心链路日志(切面加日志,可以让 DeepSeek 写个案例); + +### 7. 扩展性与业务,你怎么设计新功能? + +1. **如何支持多种拼团类型(如老带新、阶梯团)?** + **答**:抽象拼团模板(Template Pattern),定义成团条件接口(如人数满额、金额达标)。新增类型时实现接口,并通过工厂模式注入。 +2. **如何设计活动预热机制?** + **答**:1)活动开始前定时任务加载配置到Redis;2)缓存热门活动的商品信息;3)通过压测工具预热JVM和线程池。 +3. **如何实现灰度发布?** + **答**:1)Apollo配置中心按用户ID百分比切流;2)网关层根据请求头路由到新老服务;3)结合Prometheus监控异常,快速回滚。 + +### 8. 综合问题 + +1. **项目中最大的挑战是什么?如何解决?** + **答**:高并发下Redis雪崩。解决方案:1)缓存分层(本地缓存+Redis);2)热点数据预加载;3)随机过期时间。 +2. **如果让你重构系统,会优化哪些点?** + **答**:1)引入分库分表解决订单表膨胀;2)增加AI + RAG + MCP 提供智能分析和运营服务;3)使用Guava本地缓存,管理复杂数据结构。 +3. **如何向非技术人员解释系统设计?** + **答**:类比“组队购物”,系统像智能管家:1)自动匹配规则(如折扣);2)确保组队不超时;3)失败时自动重试,保证最终成功。 + +### 9. 人群标签 + +人群标签这一部分该怎么回答? + +在互联网公司里,量化数据分析师(经营分析)会把各类系统工程的数据采集到统一大数据集群,之后通过 Python、R 语言,建一个数据模型的方式跑数。比如 xxx 类人群,购物喜好、收藏喜好、用券喜好、高频下单、回购,以及从第三方获取的数据(键盘输入)、浏览器帖子等。根据这些数据定义一个量化模型,做一个跑数作业,之后这些数据,可以写成人群标签。标签为bitmap(小型只要判断不存在的),以及直接记录用户id到redis的,更准确的判断人是否存在。之后研发引入数据包到系统中(也就是 redis 对接)之后使用。 + +>关于系统面试问题,涉及到的监控、数据、指标类,最好使用云服务部署上线 + 普罗米修斯监控完成压测和优化。 diff --git a/docs/md/project/group-buy-market/promotion/group-buy-market-v1.md b/docs/md/project/group-buy-market/promotion/group-buy-market-v1.md new file mode 100644 index 000000000..7164dcd4b --- /dev/null +++ b/docs/md/project/group-buy-market/promotion/group-buy-market-v1.md @@ -0,0 +1,93 @@ +--- +title: 新"拼多多"系项目,编码3千行,进度35%,设计模式拉满! +lock: no +--- + +# 新"拼多多"系项目,编码3千行,进度35%,设计模式拉满! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +有道理,**不能再做大号的CRUD啦!** 这玩意没成长,面试也没得聊呀!不少伙伴在选择学习项目的时候,没有仔细看对应的项目的架构、设计、模型,一上来就是从头到尾的CRUD串流程,写到最后既没有编程思维的提升,也没有编码能力的积累。所以,面试贼吃亏! + +
+ +
+ +**面试官:”我们想要的不是CRUD仔!“** + +能作为面试官的,往往是这个团队里技术不错,级别较高的。这些人面试不只是看你对业务的理解,还包括非常重要的`架构知识`、`模型设计`、`技术技巧`这样内容项的积累。 + +而小傅哥带着大家做项目,也是一直秉承着一贯的高质量项目设计和编码落地。让大家学习时不只是简单的理解业务流程,还包括;怎么拆分业务边界、怎么进行工程建模、怎么驾驭设计模式、怎么处理复杂场景。所以大家学习后的反馈是:`”真爽,就像看爽文一样,每个项目都让我有非常高的提升!”` + +所以,在这次的新项目中,你又会看到不一样的设计模式技巧的运用,来拆解复杂的业务流程。—— 全项目从0到1,全程手把手视频+小册,冲起来非常爽。 + +## 一、类“拼多多”项目 + +本次小傅哥带着大家做的项目,是一个类“拼多多”的《拼团交易平台系统》,这类项目都可以被归类为营销系列系统。在各个互联网公司属于通用类的业务场景,也是流量规模最大,系统最为复杂的系统。所以学习起来收获也是非常大的。 + +
+ +
+ +- 看着页面挺简单,其实服务端一点也不好整。😂 这样一套东西的实现,需要非常好的设计,才能驾驭的了不断的需求迭代。 +- 有时候看到网上简单几行的服务端代码也能实现这样一个类似的流程,不过那东西就是闹玩的小儿科,实际公司里压根不会那么干。学习项目的时候,总得要知道公司里,`真实的业务模型` + `不错的架构设计` + `良好的编码实现`,缺一不可,否则跟没学也差不多。 + +## 二、编码3千行,进度35% + +《拼团交易平台系统》整个项目分为;`系统设计`、`服务实现`、`外部对接`、`开发运维`,目前系统设计3节已完成,服务实现开发了5节。😋 嘿嘿,马上25年的元旦和春节假期来了,又可以嘎嘎往前冲进度了! + +
+ +
+ +- 课程地址:[https://bugstack.cn/md/project/group-buy-market/group-buy-market.html](https://bugstack.cn/md/project/group-buy-market/group-buy-market.html) +- 进度说明:课程于11.11日启动,平均每周更新1节,遇到放假的时候就会加更。基本奔着25年的3-4月交付出一个可运行部署和写简历的版本。现在跟进学习,到时候简历就又有一个新项目啦! + +## 三、不只是完成功能! + +其实每个项目的学习,不只是学个流程,还要学它的系统设计。看看这样一个当前的场景下,做了哪些边界的拆分和功能逻辑的模型处理。从这部分开始才能体现出对项目的深度理解。 + +### 1. 系统建模 + +
+ +
+ +- 项目学习时,在编码前,会进行模型结构的分析「这部分有视频教程」。教大家用面向对象的思维理解系统是如何拆分边界的。 +- 当你有了更高的视角俯视系统,在到后面去开发时,就会有非常爽的编码指引。 + +### 2. 设计模式 + +
+ +
+ +- 每一节功能实现时,会帮大家理解和运用设计模式,让你知道拆分边界的重要性,以及如何做出高质量的编码。 +- 设计模式理解(你可以在这里补充学习,到项目中都是实战):[https://bugstack.cn/md/develop/design-pattern/2024-08-25-chain-tree.html](https://bugstack.cn/md/develop/design-pattern/2024-08-25-chain-tree.html) + +### 3. 工程结构 + +
+ +
+ +- 如工程结构全程视频手把手的教你学习逻辑功能的编码实现,而且这里会运用如模型设计拆分边界并进行编码功能逻辑实现。 +- 注意;编码时会设计出非常合适的模型,拆分功能逻辑边界。有了这些的积累,以后面试可以讲好长时间,在工作中也能运用起来。 + +## 四、加入学习 + +小傅哥的项目是成体系的,有不同的难度进阶。你可以循序渐进的学习,逐步的从小白成长为技术大拿。如图; + +
+ +
+- 首先,这一整套全体系的学习课程比私教培训实惠,更比培训班上万的培训费便宜。也就是培训班1天的💰,就能学习到这一整套内容了。 +- 之后,你学习的整套课程,就是小傅哥这个架构师自己全部原创编写的。这也就是说,你所提到的任何问题,小傅哥都能给你解答和讨论。 +- 那么,这么实惠的课程,成体系的课程,还是架构师编写的。还有什么可犹豫的,完全可以撸起来了! + +> 🧧优惠券,关注小傅哥公众号「码农会锁」回复「星球」获得,数量有限,先到先得! diff --git a/docs/md/project/group-buy-market/promotion/group-buy-market-v2.md b/docs/md/project/group-buy-market/promotion/group-buy-market-v2.md new file mode 100644 index 000000000..2150d69dc --- /dev/null +++ b/docs/md/project/group-buy-market/promotion/group-buy-market-v2.md @@ -0,0 +1,247 @@ +--- +title: 总结通用模型设计提取,设计模式玩的贼6! +lock: no +--- + +# 《拼团交易平台系统》总结通用模型设计提取,设计模式玩的贼6! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是小傅哥。 + +近几周在做公司的一个项目重构,有多复杂呢!`整个工程近40万行代码`,`重构部分单个类超过3000行`。历史最长周期的代码有`快10年以上`。而这东西到我手了,再继续这么写,早晚搞出事故!**所以,我决定改变一下。** + +
+ +
+ +**你不可能停了业务需求再重构!** + +在互联网公司中,产品需求交付永远是第1位的,他们不关心你代码是怎么实现的。但不要出问题,出了问题就是你的问题。 + +而长期需求迭代经历数年的代码,早已腐化的非常严重。但重构又绝对是非常考验工程师的业务经验和技术能力的。**往往重构不佳,就从维护一份屎山,到维护两份啦!** + +但好在,我的工程落地经验积累较多,通过巧妙的设计模式运用,能从复杂的流程中划分出边界结构,从而降低业务功能的理解难度。与此同时,为了让其他的伙伴在不是特别能熟练使用设计模式的情况下,我把设计模式常用的模型结构,独立成一个单独的组件包,主要引入就可以按照这样的结构来开发代码。从一定程度上,让大家的代码都能在不错的水平上。 + +>如果,你也想提高自己的代码能力和工程驾驭能力,那么可以跟着小傅哥一起学习下。 + +## 一、实践出真知 + +编程这东西,最好的学习方式就是实践。拿一个真实项目,结合实际的需求,上手操作一遍,小白也能扎扎实实的学习到实际的技术运用。 + +所以,小傅哥为了让大家能学习到,关于工程中运用设计模式,解决实际场景的重构问题。专门提供了一个新的项目,在项目中解耦出标准的通用设计模型结构,再到需求中运用处理实际问题。 + +这个项目就是小傅哥的技术社群,星球「码农会锁」,最新的第14个项目《拼团交易平台系统》,结合实际场景设计和落地的设计模式方案。—— 这个项目,会给你设计模式更牛的认知,妥妥的让你可以在自己的项目使用上设计模式! + +
+ +
+ +`拼多多`、`京东`、`腾讯`,都有很多这样的拼团场景,之所以选择这样的业务需求,就是让大家可以结合实际的项目来学习真实的技术。**这套项目目前已经进行了13节,全程视频+小册,手把手带着设计和编码。** + +>接下来,我们就看看,小傅哥是怎么带着大家玩转设计模式的! + +## 二、提炼通用模型 + +`条条大路通罗马,但放到项目工程中,就有点受不了了!` + +咋回事呢?🤔 + +只要不加规范,同样是做规则树、责任链、策略模式,都能有非常多的方式。那么,每来一个新人,就可能再多出来一份新的设计方式。这些一类的但非常差异化的东西,在下一个人要迭代需求的时候,就会有非常多的地方,有不同的改法。可能想死的新都有。 + +所以,为了把这些东西规范化,小傅哥设计了一套模型模板,单独提炼于项目需求逻辑之外。所有,有需要使用的场景,都可以引入使用。大家都在一个标准下使用设计模式,维护、迭代、扩展,也都非常容易。 + +
+ +
+ +- 首先,随着拼团项目的开发,定义2套了标准的通用设计模式结构。2种模式的责任链和1套规则树。这套责任链还用到了大家常学的数据结构中的链表设计和实现。 +- 之后,这套模型非常巧妙的运用到业务场景中。举例像是规则树,还提供了多线程数据异步加载,自由化功能逻辑编排。这样的设计模式,可以解决非常多的场景问题。 + +> 为了更好的理解这样的模型运行,接下来,小傅哥甩个图给大家感受下!—— 小傅哥,画图可牛了,见图就知意。 + +## 三、小图很美!💐 + +如图,是拼团的部分流程。营销类场景的系统都是很复杂的,它的流程节点非常多,也经常做扩展和调整。所以要做非常细腻的设计,满足复杂流程的实现。 + +
+ +
+ +- 以上这两部分流程分别包括试算和锁定优惠,这里会使用到规则树和责任链进行实现。 +- 下面,就介绍下关于规则树和责任链的设计和使用。 + +### 1. 规则树 + +`千万别觉得设计模式没有用`,否则也不会那么多源码框架中,会有那么多设计模式使用。MyBatis 一个框架,都用了10种设计模式! + +像是这些设计模式,合理的设计好,是真的可以解决非常复杂的业务流程编码,让代码变得优雅。既不会有那么多的 if···else,也不会让代码逻辑成片的堆到一个类中。 + +
+ +
+ +- 如图,这是一个规则树模型,解决的拼团中实际的场景业务。从根节点、开关节点、营销节点、人群节点,再到最终的正常和异常结束节点。每个节点分别处理自己的业务流程。 +- 你可以想象,如果没有这样的设计模式模型结构,那么在代码中,就是一个大方法中,一堆的逻辑编写,维护的成本是非常高的。 + +**展示一段代码,让兄弟👬🏻看看这是啥样的!** + +```java +@Slf4j +@Service +public class MarketNode extends AbstractGroupBuyMarketSupport { + + @Resource + private ThreadPoolExecutor threadPoolExecutor; + /** + * Spring 注入详细说明 + */ + @Resource + private Map discountCalculateServiceMap; + @Resource + private ErrorNode errorNode; + @Resource + private TagNode tagNode; + + @Override + protected void multiThread(MarketProductEntity requestParameter, DefaultActivityStrategyFactory.DynamicContext dynamicContext) throws ExecutionException, InterruptedException, TimeoutException { + // 异步查询活动配置 + QueryGroupBuyActivityDiscountVOThreadTask queryGroupBuyActivityDiscountVOThreadTask = new QueryGroupBuyActivityDiscountVOThreadTask(requestParameter.getActivityId(), requestParameter.getSource(), requestParameter.getChannel(), requestParameter.getGoodsId(), repository); + FutureTask groupBuyActivityDiscountVOFutureTask = new FutureTask<>(queryGroupBuyActivityDiscountVOThreadTask); + threadPoolExecutor.execute(groupBuyActivityDiscountVOFutureTask); + + // 异步查询商品信息 - 在实际生产中,商品有同步库或者调用接口查询。这里暂时使用DB方式查询。 + QuerySkuVOFromDBThreadTask querySkuVOFromDBThreadTask = new QuerySkuVOFromDBThreadTask(requestParameter.getGoodsId(), repository); + FutureTask skuVOFutureTask = new FutureTask<>(querySkuVOFromDBThreadTask); + threadPoolExecutor.execute(skuVOFutureTask); + + // 写入上下文 - 对于一些复杂场景,获取数据的操作,有时候会在下N个节点获取,这样前置查询数据,可以提高接口响应效率 + dynamicContext.setGroupBuyActivityDiscountVO(groupBuyActivityDiscountVOFutureTask.get(timeout, TimeUnit.MINUTES)); + dynamicContext.setSkuVO(skuVOFutureTask.get(timeout, TimeUnit.MINUTES)); + + log.info("拼团商品查询试算服务-MarketNode userId:{} 异步线程加载数据「GroupBuyActivityDiscountVO、SkuVO」完成", requestParameter.getUserId()); + } + + @Override + public TrialBalanceEntity doApply(MarketProductEntity requestParameter, DefaultActivityStrategyFactory.DynamicContext dynamicContext) throws Exception { + log.info("拼团商品查询试算服务-MarketNode userId:{} requestParameter:{}", requestParameter.getUserId(), JSON.toJSONString(requestParameter)); + + // 获取上下文数据 + GroupBuyActivityDiscountVO groupBuyActivityDiscountVO = dynamicContext.getGroupBuyActivityDiscountVO(); + if (null == groupBuyActivityDiscountVO) { + return router(requestParameter, dynamicContext); + } + + GroupBuyActivityDiscountVO.GroupBuyDiscount groupBuyDiscount = groupBuyActivityDiscountVO.getGroupBuyDiscount(); + SkuVO skuVO = dynamicContext.getSkuVO(); + if (null == groupBuyDiscount || null == skuVO) { + return router(requestParameter, dynamicContext); + } + + // 优惠试算 + IDiscountCalculateService discountCalculateService = discountCalculateServiceMap.get(groupBuyDiscount.getMarketPlan()); + if (null == discountCalculateService) { + log.info("不存在{}类型的折扣计算服务,支持类型为:{}", groupBuyDiscount.getMarketPlan(), JSON.toJSONString(discountCalculateServiceMap.keySet())); + throw new AppException(ResponseCode.E0001.getCode(), ResponseCode.E0001.getInfo()); + } + + // 折扣价格 + BigDecimal deductionPrice = discountCalculateService.calculate(requestParameter.getUserId(), skuVO.getOriginalPrice(), groupBuyDiscount); + dynamicContext.setDeductionPrice(deductionPrice); + + return router(requestParameter, dynamicContext); + } + + @Override + public StrategyHandler get(MarketProductEntity requestParameter, DefaultActivityStrategyFactory.DynamicContext dynamicContext) throws Exception { + // 不存在配置的拼团活动,走异常节点 + if (null == dynamicContext.getGroupBuyActivityDiscountVO() || null == dynamicContext.getSkuVO() || null == dynamicContext.getDeductionPrice()) { + return errorNode; + } + + return tagNode; + } + +} +``` + +这是其中的一个营销节点,处理拼团营销试算的过程; + +1. multiThread 负责异步多线程方式加载数据,节省数据获取时间。 +2. doApply 处理业务流程,最后用 router 路由到下一个节点。 +3. get 是获取到下一个节点,是走到哪里由这块判断。 + +
+ +
+ +> 这套结构模型可以解决非常多的业务场景,而且每一个类都可以非常清晰的表达出具体的业务逻辑。无论以后是维护代码、迭代需求还是排查线上问题都变得很容易。 + +### 2. 责任链 + +规则树与责任链相比,规则树会有很多分叉流程,但责任链比较轻量主要负责单链路流程,在编码过程中不需要考虑流程的流转。相对来说更轻量了。 + +这里小傅哥设计了2套责任链模型,model1 - 单例链、model2 - 多例链(动态组装多套)。如图; + +
+ +
+ +- 如图,ILink 使用了数据结构责任链模型,ILogicHandler 为处理具体的业务功能逻辑。这里巧妙的设计在于把链的管理和业务逻辑的受理进行拆分,之后再由 LinkArmory 进行链路装配。**「当你看到代码的时候会觉得这真爽!原来写代码可以这样有意思」** +- 因为 LinkedList 实现如链表一样的方法,有添加,也有摘除链,所以还可以根据数据库配置动态处理链的实例化。 + +```java +@Service +public class Rule02TradeRuleFactory { + + @Bean("demo01") + public BusinessLinkedList demo01(RuleLogic201 ruleLogic201, RuleLogic202 ruleLogic202) { + + LinkArmory linkArmory = new LinkArmory<>("demo01", ruleLogic201, ruleLogic202); + + return linkArmory.getLogicLink(); + } + + @Bean("demo02") + public BusinessLinkedList demo02(RuleLogic202 ruleLogic202) { + + LinkArmory linkArmory = new LinkArmory<>("demo02", ruleLogic202); + + return linkArmory.getLogicLink(); + } + + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class DynamicContext { + private String age; + } + +} +``` + +- 之后就可以动态的使用这套责任链完成功能需求的处理。demo01、demo02,分别组装了自己的责任链。 + +> 以上,在小傅哥的全部项目中也只是冰山一角,如果你加入小傅哥的社群学习,我还会让你感受到更多的关于工程在实际场景下设计的魅力! + +## 四、一套学习进阶路线图! + +**10年互联网大厂的经历,得出**;`最快的成长方式,是不要重复做一件事,而是能成体系的,有阶段性的成长。` + +为此小傅哥做了一整套的实战学习进阶项目,从小白到大佬,全程视频手把手带着从0到1,一步步完成项目的设计、开发和上线。在整套内容学习过程中,小傅哥为你提供了非常好的技术交流社群,及时解决学习问题。还包括调试你的问题代码,带你快速🔜出坑! + +
+ +
+ +**扫码加入即可获得全部项目学习!** + +- 首先,这一整套全体系的学习课程比私教培训实惠,更比培训班上万的培训费便宜。可能也就是培训班1天的💰钱,就能学习到这一整套内容了。 +- 之后,你学习的整套课程,就是小傅哥这个架构师自己全部原创编写的。这也就是说,你所提到的任何问题,小傅哥都能给你解答和讨论。 +- 那么,这么实惠的课程,成体系的课程,还是架构师编写的。还有什么可犹豫的,完全可以撸起来了! + +>🧧 注意,关注小傅哥公众号「bugstack虫洞栈」回复「星球」可以领取加入优惠哦! diff --git a/docs/md/project/group-buy-market/promotion/group-buy-market-v3.md b/docs/md/project/group-buy-market/promotion/group-buy-market-v3.md new file mode 100644 index 000000000..4dce14afc --- /dev/null +++ b/docs/md/project/group-buy-market/promotion/group-buy-market-v3.md @@ -0,0 +1,145 @@ +--- +title: 第1阶段完成上线,可体验! +lock: no +--- + +# 《拼团交易平台系统》第1阶段完成上线,可体验! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +经过春节假期🧨,接近于连续日更的一顿狂卷🌪🤨,第14个最新**拼团项目**,第一阶段已完结上线啦!只要`花费2周左右`的学习,就可以让简历有一个**全网最新的、又很硬核的编程项目**! + +
+ +
+ +**跟着小傅哥学习的好处是什么?** + +凌晨3点睡醒,还能在线回复社群伙伴的技术问题 😂,所有,在学习这方面,有小傅哥这样的卷王,为你保驾护航✈️。你可以平平稳稳的推进项目的进度,并且学习到有质量的、符合实际需求的真实项目。`”伙伴说:学习时候,最希望遇到问题,有人能指点!“` + +
+ +
+ +不少小伙伴反馈,之前学习的一些项目,遇到很多问题都没人解决,很耽误学习进度。尤其是都啃了一半了,放弃觉得浪费时间,不放弃学不下去。所以,在学习的时候,一定要加入有质量的社群,真心为伙伴们成长的社群,有责任心的社群!**把新人编程学习的伙伴当孩子一样培养。谁还不是从小白阶段过来的!** + +
+ +
+ +那么,当你体验过小傅哥的实战项目,就会感受到,这才是真的企业级项目。通过项目的学习,全程带着你从需求分析、功能设计、架构搭建、编码实现、设计模式运用,再到发布上线,全程视频手把手 + 技术小册,一步步带你完成!💐 + +- 项目地址:[https://bugstack.cn/md/project/group-buy-market/group-buy-market.html](https://bugstack.cn/md/project/group-buy-market/group-buy-market.html) +- 在线体验:[https://gaga.plus/](https://gaga.plus/) +- 加入社群:[https://t.zsxq.com/Yfbwo](https://t.zsxq.com/Yfbwo) - 关注公众号「`bugstack虫洞栈`」回复「`星球`」获得优惠券。 + +> 🧧 文末提供了加入红包,一次加入可以拿下14个实战项目,非常划算! + +## 一、能学到啥 + +该项目是互联网中大厂,非常常见的C端场景,营销类促进支付履约类实战项目,拼团交易平台系统。你可以在`美团`、`京东`、`拼多多`、`腾讯`等互联网产品中,都能看到拼团类场景,所以学习一个这样的项目,到面试了才能有和面试官聊的起劲。 + +- 业务,深入理解拼团场景的业务,并从产品 PRD 入手开始进行系统的分析和设计。 +- 前端,本次项目使用了最新的AI大模型DeepSeek,设计拼团UI,并处理UI与服务端接口的对接。效果非常不错。 +- 后端,分析业务场景需求,设计系统领域模型,构建系统分层架构。这些都是一个程序员👨🏻‍💻必须掌握的东西。但不是所有项目都能学到这些东西。 +- 后端,熟练使用 Spring、SpringBoot、MyBatis 等开发框架技术,并理解和使用 Spring 高级技巧进行设计和编码。 +- 后端,提炼和抽象通用的设计模式框架,多种责任链、规则树,让项目业务代码更加轻松的使用设计模式。 +- 后端,通过多线程异步同时加载多类数据,提高拼团营销优惠试算的能力。 +- 后端,熟练使用 okhttp3、retrofit2 框架,封装回调外部数据接口。拼团结算结束后,回调三方服务。 +- 后端,基于 Redis BitMap 设计人群标签,限定用户参与、用户展示。 +- 运维,熟练使用 Docker 在本地和服务端的配置和部署应用,以及在本地构建前后端镜像。 +- 运维,熟练掌握 Git、GitCode,对工程代码的管理,推送、拉取、切换分支、合并代码等操作。 + +此外,小傅哥会把系统开发过程中的思考、设计、编码,录制⏺成完整的全程手把手带着学习的视频,让大家可以学习到的更多、更细、更深! + +>小傅哥作为面试官,已经把面试中最容易考察的能力项,通过一个个功能的方式渗透到项目中。潜移默化的在面试的时候,就会回答出非常多有力的技术解决方案。 + +## 二、项目展示 + +本次项目是一个包含 `前后端 + Dev-Ops` 的全栈式综合编程实战项目,并且小傅哥的这些项目都是可以真实上线使用的,所以你会看到陆续完成的这些项目,会通过微服务的方式进行对接使用,而这样的方式,才是公司里真实的情况。 + +此次的拼团 UI 设计,运用了 DeepSeek 进行设计; + +
+ +
+ +> 体验地址:[http://117.72.38.125:3080](http://117.72.38.125:3080) - 临时体验,非长期有效 + +### 1. 课程目录 + +
+ +
+ +- 一阶段,24节,视频在12小时多。预计可在2周左右学习完成。 +- 学习后,可以写简历,投递春招或者实习。项目内容量很细腻,业务流程很完善。还有很多创新点,都可以面试讲。 + +### 2. 核心流程 + +
+ +
+ +- 如图,为从营销锁单、营销结算、回调的核心流程。也就是一个拼团的核心正向执行链路。 + +### 3. 库表设计 + +
+ +
+ +- 项目课程开始会带着你分析需求并做库表的设计,这个项目符合实际的业务场景,所以设计的库表也会非常细腻。 + +### 4. 设计模式 + +
+ +
+ +- 如图,这是项目中一个规则树模型,解决的拼团中实际的场景业务。从根节点、开关节点、营销节点、人群节点,再到最终的正常和异常结束节点。每个节点分别处理自己的业务流程。 +- 你可以想象,如果没有这样的设计模式模型结构,那么在代码中,就是一个大方法中,一堆的逻辑编写,维护的成本是非常高的。 + +## 三、学习辅助 + +### 1. 遇到问题怎么办? + +
+ +
+ +- 当你学习项目遇到问题时,小傅哥会为你提供全程的指引,帮你解决问题。 +- 所以跟着小傅哥学习,一点也不用慌,嘎嘎冲就是了! + +### 2. 课程详细改动点 + +
+ +
+ +- 对于复杂的业务流程实现,会把所有的改动点,依次的给你罗列出来。同时还有视频教程,一步步带着你完成。 + +### 3. 全程有视频教程 + +
+ +
+ +- 课程的视频,分为业务讲解、功能设计、编码改动,之后在一步步带着你手写实现。即使你是小白也能跟下来学习。 + +## 四、项目路线 + +跟着小傅哥学习,是成体系的学习成长,有完整的不同难度的进阶路线学习。这里有小白入门,再到小白深造,之后开始进阶,这个过程中有业务,也有组件,可以让你非常全面的成长。 + +
+ +
+ +- 首先,这一整套全体系的学习课程比私教培训实惠,更比培训班上万的培训费便宜。可能也就是培训班1天的💰钱,就能学习到这一整套内容了。 +- 之后,你学习的整套课程,就是小傅哥这个架构师自己全部原创编写的。这也就是说,你所提到的任何问题,小傅哥都能给你解答和讨论。 +- 那么,这么实惠的课程,成体系的课程,还是架构师编写的。还有什么可犹豫的,完全可以撸起来了! diff --git a/docs/md/project/group-buy-market/promotion/group-buy-market-v4.md b/docs/md/project/group-buy-market/promotion/group-buy-market-v4.md new file mode 100644 index 000000000..a00fe7cca --- /dev/null +++ b/docs/md/project/group-buy-market/promotion/group-buy-market-v4.md @@ -0,0 +1,104 @@ +--- +title: 第2阶段完成上线,可查阅! +lock: no +--- + +# 《拼团交易平台系统》第2阶段完成上线,可查阅! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +😂 不少加入小傅哥社群的伙伴,在体验过众多项目后,说:“小傅哥,是在做个小京东吧?”,有`小型支付商城`、`有营销抽奖`、`有积分兑换`、`有各类组件`,这次又有了**拼团营销 + 小型商城**对接,真的牛皮! + +
+ +
+ +**我们做项目,就是这样** + +讲道理,学习编程来说,就是不断地`打破认知`,`拓宽思维`,用实际的贴合企业中的项目,填补自己的知识储备。而那些玩具项目和大号的CRUD,都没法提高我们的编程能力。所以,小傅哥(10年+大厂经验)带着大家做的项目,都是以真实企业场景的业务诉求,设计方案和落地工程,并且会带着你,完成项目的云服务器上线。 + +
+ +
+ +小傅哥社群里的项目,除了`拼团营销 + 小型商城`,还有非常多的项目,都是可以组合使用的,如;openai 应用 + 大营销、动态线程池 + 拼团、IM + ChatGLM SDK、API 网关 + Lottery等。这不就妥妥的公司中一个项目组里在做的事嘛! + +>👨🏻‍💻文末提供了小傅哥社群7套组件项目、7套业务项目、1套手写源码教程,可以🧧加入获取。 + +## 一、两套微服务对接方案 + +介绍下小傅哥技术社群里这两套微服务和对接; + +- **小型支付商城**:接入微信扫码鉴权、支付宝沙箱环境,串联订单创建、唤起收银台,接收支付完成回调,扭转订单状态,模拟发货。完成真实的交易流程。 + +- **拼团交易营销**:提供商品下单支付链路中的营销微服务设计,处理商品优惠试算、支付营销锁单、支付营销结算。促进商品交易履约率。 + +
+ +
+ +如图,是两套微服务的对接链路。 + +- 首先,在小型支付商城,创建订单的过程中,调用拼团营销锁单。这个时候就拿到了当笔订单的优惠金额。之后创建支付订单唤起收银台,之后用户就可以按照最终的优惠金额进行支付了。 +- 之后,在支付完成后,收到回调消息,进行营销拼团进度结算。直至拼团组队进度完成,在回调给支付商城,触达交易结算。 + +这样一整套完整的交易营销流程,是非常真实的实际场景对接处理方案。尤其是营销场景下的复杂的试算、规则的过滤,再到结算的处理,都是使用了非常巧妙的编码操作,使用了非常好的设计模式进行设计。这块非常有的学! + +## 二、对接后,上线效果 + +从用户,`微信扫码登录`、`进入商品详情页`、`点击开团`、`确认支付`、`跳转支付宝`、`支付回调`、`营销结算`、`支付结算`、`模拟发货`。一整套流程完整实现。页面端效果; + +
+ +
+ +- 小傅哥的课程会全程带着你完成两套微服务的对接和云服务器操作上线,你可以体现一整套的小型商城 + 拼团营销的上线使用效果。 +- 并且在这套系统上线中,会设计 Nginx 负载,轮训调用后端拼团服务。 + +> 就这么学东西,才能嘎嘎有收获! + +## 三、课程目录 + +这是一套拼团交易平台,包括了小型支付商城课程 + 拼团营销平台系统; + +
+ +
+此套课程全程视频手把手 + 技术小册文档,想怎么学习就怎么学习,让小白快速入门上手完成。 + + +### 1. 小型支付商城 + +
+ +
+ +- 25节课程,MVC架构写一遍,DDD架构写一遍。非常适合新人上手的一套课程,全程视频手把手学习。 + +### 2. 拼团营销平台系统 + +
+ +
+ +- 28节课程,一阶段对接静态页面,二阶段与小型支付商城微服务对接。 +- 拼团项目,还会继续迭代,增加更多细节。让小伙伴满足当前找实习的前提下,可以继续学习,完善自己的知识储备。 + +## 四、大家的认可! + +小傅哥,做的项目,一向以高质量著称。在每个项目里,都花费大量的时间,将互联网公司里的实战经验,用到项目实现中。所以,你会看到非常多的场景解决方案和极其巧妙的工程设计手段。因此,也得到了大家的认可。 + +
+ +
+ +
+ +
+ +> 就这,我只能说,你越早加入,能力提高的越好! diff --git a/docs/md/project/group-buy-market/promotion/group-buy-market-v5.md b/docs/md/project/group-buy-market/promotion/group-buy-market-v5.md new file mode 100644 index 000000000..bdbbc4c22 --- /dev/null +++ b/docs/md/project/group-buy-market/promotion/group-buy-market-v5.md @@ -0,0 +1,438 @@ +--- +title: Ai MCP + ELK 系统日志,排错提效 100%! +lock: no +--- + +# Ai MCP + ELK 系统日志,排错提效 100%! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +自从 Ai MCP 模型上下文协议,2024年11月,推出开放标准以后。2025年,就进入了全面的 MCP 服务落地。也正因如此,程序员👨🏻‍💻的学习就又多了一项新的应用技能,同时也成了面试热门问题。如:**“你的项目,有使用 AI 方面的能力进行提效吗?”** 解封下码农的双手🙌🏻! + +
+ +
+ +**我能哪些方面使用 Ai 提效呢?** + +在互联网程,序员工程开发方面,关于 Ai 提效最为常见的,也是市面上使用最多的,就是各类的 Ai 编码软件。如 cursor、trae.ai、IntelliJ IDEA 中的各类 Ai 插件,都可以辅助我们完成项目的编码操作。甚至一些简单的 HTML 页面,几乎在刚开始开发阶段,可以快速搭建起来,确实非常提效。 + +不过这些都是固定的软件,他们并没有深度结合到业务场景中,从整个研发的生命周期看,还有非常多的节点可以被 Ai 提效。如;需求评审、研发设计、系统发布、代码评审、单测用例、业务监控、问题排查&故障分析等。都可以深入自身的业务,运用 Ai 开发进行提效。 + +这里尤其是问题排查和故障分析,在互联网企业中,尤其是大厂的业务,几乎每天都要配和运营的反馈的客诉,系统的报警日志,性能的降低反馈,进行人工检索`系统监控`、`日志`、`分析`,这部分要投入大量的人工成本,虽然可能系统并不是真的有问题,但也要一遍遍的排查这些问题。 + +所以,结合这样的场景,小傅哥在带着大家的实战项目,也逐步的引出关于 Ai 在应用项目上的提效处理。今天分享的一个场景就是基于 Ai MCP 分析系统的 ELK 日志。后面还会分析关于监控、数据库一起分析。 + +>🧧 文末提供了小傅哥技术社群全套的17个应用实战项目,一次加入可以获得全部的文档、源码、视频,嘎嘎提高能力! + +## 一、系统说明 + +小傅哥带着社群伙伴,做了一套 **《拼团交易平台系统》**,因为拼团是非常重要的 toc 业务场景,也是拼多多、腾讯、京东等服务平台,交易支付时候,最为常见的一种营销手段。它可以通过用户自传播方式增强交易量,也是拼多多最开始起家形成巨大规模的一个业务逻辑。 + +该系统采用了 DDD 领域驱动设计进行建模,拆分领域模块边界,形成;活动领域、人群领域、交易领域,来构建拼团营销交易流程,达到试算、锁单、结算等步骤流程。这个过程中提炼了通用设计模式,规则树、责任链,可以非常有效的统一的治理流程编排实现。 + +
+ +
+ +
+ +
+ +如图,是两套微服务的对接链路。 + +- 首先,在小型支付商城,创建订单的过程中,调用拼团营销锁单。这个时候就拿到了当笔订单的优惠金额。之后创建支付订单唤起收银台,之后用户就可以按照最终的优惠金额进行支付了。 +- 之后,在支付完成后,收到回调消息,进行营销拼团进度结算。直至拼团组队进度完成,在回调给支付商城,触达交易结算。 + +这样一整套完整的交易营销流程,是非常真实的实际场景对接处理方案。尤其是营销场景下的复杂的试算、规则的过滤,再到结算的处理,都是使用了非常巧妙的编码操作,使用了非常好的设计模式进行设计。这块非常有的学! + +## 二、配置日志 + +### 1. 系统部署(ELK) + +
+ +
+ +- 基于 Docker 部署 ELK 系统,采集上报日志。 + +### 2. 上报配置 + +```java + + + + + + + ${LOG_STASH_HOST}:4560 + + + + + + + + + + + + +``` + +- 通过增加 LogstashTcpSocketAppender 上报系统日志到 ELK。 + +### 3. 生产日志 + +开始下面的操作之前,需要启动 SpringBoot 服务,访问接口,让系统产生一些运行日志。 + +
+ +
+ +```java +25-06-08.08:05:08.441 [http-nio-8091-exec-2] INFO ZJCalculateService -b601d8d5-ff62-4adb-8260-16d8b6af53ef 优惠策略折扣计算:0 +25-06-08.08:05:08.445 [http-nio-8091-exec-2] INFO EndNode -b601d8d5-ff62-4adb-8260-16d8b6af53ef 拼团商品查询试算服务-EndNode userId:xfg04 requestParameter:{"channel":"c01","goodsId":"9890001","source":"s01","userId":"xfg04"} +25-06-08.08:05:08.451 [http-nio-8091-exec-2] INFO MarketIndexController -b601d8d5-ff62-4adb-8260-16d8b6af53ef 查询拼团营销配置完成:xfg04 goodsId:9890001 response:{"code":"0000","data":{"activityId":100123,"goods":{"deductionPrice":20.00,"goodsId":"9890001","originalPrice":100.00,"payPrice":80.00},"teamList":[],"teamStatistic":{"allTeamCompleteCount":0,"allTeamCount":2,"allTeamUserCount":4}},"info":"成功"} +``` + +- 访问的是拼团试算接口,产生一些数据运行日志。在这个过程中,会多次访问系统,触发拼团接口的限流操作。多一些日志也能更好的让 Ai MCP 进行分析。 + +### 4. 查看日志 + +
+ +
+ +- 配置文章后,访问 Kibana 数据可视化后台,这会你可以看到上报上来的日志信息。 +- 到这里,日志配置完成。接下来,我们就可以就 Ai MCP,来访问日志了。 + +## 三、日志分析 + +AI MCP 是小傅哥社群内的另外一套项目,[《DeepSeek RAG、MCP、Agent》](https://t.zsxq.com/GwNZp) 智能体,课程。课程里有讲解如何开发和使用 MCP 服务,以及构建 Agent 智能体。地址:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) - `感兴趣的伙伴可以进入学习` + +这里小傅哥选择一个 ElasticSearch MCP 服务,对接到咱们的 ELK 日志上,通过对接的 MCP 服务帮我们检索日志。 + +### 1. 环境说明 + +- AI 对话客户端;https://claude.ai/download - 不非得使用这个客户端。像是 trae.ai、cursor 等,能配置 mcp 服务的都可以的。 +- 发码平台:https://sms-activate.io/ - `claude.ai 注册需要使用` +- node 环境,需要 v18+ https://nodejs.org/en/download +- mcp 服务01;https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem +- mcp 服务02;https://github.com/elastic/mcp-server-elasticsearch + +### 2. 客户端使用 + +#### 2.1 配置文件 + +
+ +
+ +```java +{ + "mcpServers": { + "elasticsearch-mcp-server": { + "command": "npx", + "args": [ + "-y", + "@elastic/mcp-server-elasticsearch" + ], + "env": { + "ES_URL": "http://127.0.0.1:9200", + "ES_API_KEY": "your-api-key" + } + }, + "filesystem": { + "command": "npx", + "args": [ + "-y", + "@modelcontextprotocol/server-filesystem", + "/Users/fuzhengwei/Desktop" + ] + } + } +} +``` + +- 配置后要重启客户端。注意 `/Users/fuzhengwei/Desktop` 更换为你的文件夹。 + +#### 2.2 对话提问 + +
+ +
+ +
+ +
+ +- 对话提问:`获取所有限流用户,并在 /Users/fuzhengwei/Desktop 创建限流文件写入用户。` +- 这样他就可以通过 ES 查询我们产生的日志数据,并给出分析报告。 + +#### 2.3 日志文件 + +
+ +
+ +- 打开产生的日志文件,可以把限流的用户拉取出来。方便我们分析提供问题。 + +### 3. 代码调用 + +这部分涉及到星球的 AI Agent 项目,工程地址:[https://gitcode.net/KnowledgePlanet/ai-agent-station-study](https://gitcode.net/KnowledgePlanet/ai-agent-station-study) + +#### 3.1 直接调用 + +```java +package cn.bugstack.ai.test.spring.ai; + +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest +public class AiAgentMCPESTest { + + private ChatModel chatModel; + + private ChatClient chatClient; + + @Resource + private PgVectorStore vectorStore; + + public static final String CHAT_MEMORY_CONVERSATION_ID_KEY = "chat_memory_conversation_id"; + public static final String CHAT_MEMORY_RETRIEVE_SIZE_KEY = "chat_memory_response_size"; + + @Before + public void init() { + + OpenAiApi openAiApi = OpenAiApi.builder() + .baseUrl("https://apis.itedus.cn") + .apiKey("sk-vo81adWzUz1G0LBQ1cF1B804A1E04aC*****可申请") + .completionsPath("v1/chat/completions") + .embeddingsPath("v1/embeddings") + .build(); + + chatModel = OpenAiChatModel.builder() + .openAiApi(openAiApi) + .defaultOptions(OpenAiChatOptions.builder() + .model("gpt-4.1-mini") + .toolCallbacks(new SyncMcpToolCallbackProvider(stdioMcpClientElasticsearch()).getToolCallbacks()) + .build()) + .build(); + } + + @Test + public void test_chat_model_call() { + Prompt prompt = Prompt.builder() + .messages(new UserMessage( + """ + 有哪些工具可以使用 + """)) + .build(); + + ChatResponse chatResponse = chatModel.call(prompt); + + log.info("测试结果(call):{}", JSON.toJSONString(chatResponse)); + } + + @Test + public void test_chat_model_call_es() { + Prompt prompt = Prompt.builder() + .messages(new UserMessage( + """ + 查询xfg01日志,DSL 语句; + { + `index`: `springboot-logstash-2025.06.07`, + `queryBody`: { + `size`: 10, + `sort`: [ + { + `@timestamp`: { + `order`: `desc` + } + } + ], + `query`: { + `match`: { + `message`: `xfg01` + } + } + } + } + """)) + .build(); + + ChatResponse chatResponse = chatModel.call(prompt); + + log.info("测试结果(call):{}", JSON.toJSONString(chatResponse)); + } + + /** + * https://sai.baidu.com/server/Elasticsearch%2520MCP%2520Server/awesimon?id=02d6b7e9091355b91fed045b9c80dede + * https://github.com/elastic/mcp-server-elasticsearch + */ + public McpSyncClient stdioMcpClientElasticsearch() { + + Map env = new HashMap<>(); + env.put("ES_URL","http://127.0.0.1:9200"); + env.put("ES_API_KEY","none"); + + var stdioParams = ServerParameters.builder("npx") + .args("-y", "@elastic/mcp-server-elasticsearch") + .env(env) + .build(); + + var mcpClient = McpClient.sync(new StdioClientTransport(stdioParams)) + .requestTimeout(Duration.ofSeconds(100)).build(); + + var init = mcpClient.initialize(); + + System.out.println("Stdio MCP Initialized: " + init); + + return mcpClient; + + } + +} +``` + +
+ +
+ +- 以上代码,就是对接的 mcp 服务,以及通过 `查询xfg01日志,DSL 语句;` 来操作 ES。 + +#### 3.2 动态调用(Agent) + +```java +private String buildSystemPrompt() { + return """ + 你是一个专业的日志分析助手,具备以下能力: + 1. 可以查询Elasticsearch索引列表 - 使用list_indices()函数 + 2. 可以获取索引字段映射 - 使用get_mappings(index)函数 + 3. 可以执行Elasticsearch搜索 - 使用search(index, queryBody)函数 + + 当用户询问限流相关问题时,请按以下步骤执行: + + **步骤1:探索数据源** + - 首先调用list_indices()查看所有可用的索引 + - 识别可能包含日志信息的索引(通常包含log、logstash等关键词) + + **步骤2:分析数据结构** + - 对目标索引调用get_mappings()查看字段结构 + - 重点关注message、level、timestamp等字段 + + **步骤3:构建搜索查询** + - 使用多种限流相关关键词搜索:限流、rate limit、throttle、blocked、超过限制、黑名单、超频次 + - 按时间倒序排列结果 + - 示例查询结构: + { + `index`: `group-buy-market-log-2025.06.08`, + `queryBody`: { + `size`: 10, + `sort`: [ + { + `@timestamp`: { + `order`: `desc` + } + } + ], + `query`: { + `match`: { + `message`: `xfg01` + } + } + } + } + + **步骤4:优化搜索策略** + - 如果初始搜索结果不理想,尝试使用wildcard查询 + - 如果需要,使用单一关键词进行精确匹配 + + **步骤5:分析结果** + - 从搜索结果中提取用户信息 + - 识别限流类型(黑名单、超频次等) + - 统计触发次数和时间分布 + - 分析影响的服务和功能 + + **输出格式要求:** + - 明确列出被限流的用户ID + - 说明限流类型和原因 + - 提供触发时间和频率信息 + - 给出分析建议 + + 现在开始执行查询任务。 + """; +} + +@Test +public void queryRateLimitedUsers() { + // 第一步:系统初始化提示词 + String systemPrompt = buildSystemPrompt(); + // 第二步:用户查询提示词 + String userQuery = "查询哪个用户被限流了"; + // 第三步:构建完整的提示词 + String fullPrompt = buildFullPrompt(systemPrompt, userQuery); + // 第四步:调用AI模型 + Prompt prompt = Prompt.builder() + .messages(new UserMessage(fullPrompt)) + .build(); + ChatResponse chatResponse = chatModel.call(prompt); + log.info("测试结果:{}", chatResponse.getResult().getOutput().getText()); +} + +public String queryRateLimitedUsersStepByStep() { + StringBuilder result = new StringBuilder(); + // 步骤1:查询索引列表 + String step1Prompt = buildStepPrompt("步骤1:查询所有可用的Elasticsearch索引", + "请调用list_indices()函数查看所有可用的索引,并识别可能包含日志的索引。"); + result.append(executeStep(step1Prompt)).append("\n\n"); + // 步骤2:获取索引映射 + String step2Prompt = buildStepPrompt("步骤2:获取日志索引的字段映射", + "请对识别出的日志索引调用get_mappings()函数,查看字段结构,重点关注message、level、timestamp等字段。"); + result.append(executeStep(step2Prompt)).append("\n\n"); + // 步骤3:搜索限流日志 + String step3Prompt = buildStepPrompt("步骤3:搜索限流相关日志", + "请使用多种限流相关关键词(限流、rate limit、throttle、blocked、超过限制等)搜索日志,按时间倒序排列。"); + result.append(executeStep(step3Prompt)).append("\n\n"); + // 步骤4:分析结果 + String step4Prompt = buildStepPrompt("步骤4:分析限流用户", + "请分析搜索结果,提取被限流的用户信息,包括用户ID、限流类型、触发次数等,并生成详细报告。"); + result.append(executeStep(step4Prompt)).append("\n\n"); + return result.toString(); +} +``` + +```java +================================================================================ +📝 执行步骤日志: +================================================================================ +步骤 1: 经过索引查询,我们确定了一个名为 `group-buy-market-log-2025.06.08` 的索引,该索引包含了日志记录。在分析索引字段映射之后,发现字段 `message` 是存储日志内容的主要字段。因此,我们构建了一个搜索查询来查找日志中与“限流”相关的记录。 + +在向 Elasticsearch 发送查询请求时,首次尝试做了一个布尔查询,但由于格式问题请求失败。随后,我使用了一个更简洁的 `query_string` 查询,该查询成功返回了 16 条相关记录。这些记录主要显示了不同用户超限流量被拦截的情况。 具体限制用户如下: + +- 用户标识: `xfg01` +- 用户标识: `liergou` +- 用户标识: `xiaofuge` +- 用户标识: `zhangsan` +- 用户标识: `xiefeiji` + +这些记录均包含了时间戳和其他上下文信息,如日志级别、线程名和来源等。 +``` + +- 基于提示词和代码逻辑,可以动态执行调用和结果分析。Ai 提示词是构建 Agent 非常重要的一项技术,因为 提示词 = Ai 大脑! + +## 四、扩展能力 + +
+ +
+ +- Ai MCP 服务,也就是 Agent 能力,还可以用于全面的系统运行分析,帮助我们快速的处理线上运行情况。 + +>好啦,这次我们先分享关于 Ai MCP 如何为日志检索提效。下次我们在分析关于监控处理。 diff --git a/docs/md/project/group-buy-market/promotion/group-buy-market-v6.md b/docs/md/project/group-buy-market/promotion/group-buy-market-v6.md new file mode 100644 index 000000000..d16c0f347 --- /dev/null +++ b/docs/md/project/group-buy-market/promotion/group-buy-market-v6.md @@ -0,0 +1,82 @@ +--- +title: 拼团交易平台逆向流程启动 +lock: no +--- + +# 拼团交易平台逆向流程启动 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +经过小傅哥这么多年的努力,👨🏻‍💻认认真真的做编程项目之下,一点点把来自于互联网真实技术教给社群伙伴。现在也是行了起来。在大学里`优秀毕业生分享上`,也能被伙伴认可,拿出来写到黑板上啦! + +
+ +
+ +**他们是这么评价小傅哥的!** + +小傅哥在大型互联网,`toc业务场景,工作这么多年`,也确实积累了丰富的业务+技术经验。也深知,对于一个从事此行业的编程人员,应该学习哪些项目才能快速成长。 + +
+ +
+ +为此,小傅哥做了一整套项目,`由浅入深,循序渐进`。以不同难度级别的项目,带着小伙伴们稳扎稳打的成长。有了这样的真实场景学习,`既可以`提高自己的编程思维和编码能力,`又能`在面试中讲解出各种场景方案,`还能`为以后入职进入到公司快速融入团队。可以说是,一举多得。 + +> 🧧 文末提供了全套的实战项目,含有;业务项目、组件项目、创新AI项目,各项目对应的文档、视频、代码,全部提供给大家学习使用。 + +## 一、项目介绍 + +**于24年末,小傅哥以线上真实toc业务场景**,设计了一套 **《拼团交易平台系统》**,帮助大家深入学习,`前后端技术`、`分布式架构`、`微服务对接`、`Dev-Ops 发布上线`、`AI MCP + ELK + 普罗米修斯监控`、通用组件扳手工程设计等。可以说学习这样一套项目,就能完整的积累各项互联网toc场景常见方案和通用技术。 + +像是这样的项目,基本大家在使用各个互联网app的时候,都能体会到拼团的应用。如;`美团拼单`、`滴滴拼券`、`京东/拼多多购物`、`腾讯`等,都可以看到。所以这也是面试中面试官非常喜欢聊的业务和实现方案。 + +
+ +
+ +现在这套项目已经讲解了38节课程,所有的拼团正向流程 + 分布式方案 + Dev-Ops 部署和监控,都已完成。接下来将开启逆向退单流程。也就是7月5日,周末开启。 + +## 二、业务流程 + +如图,以用户旅途视角来看整个拼团流程。 + +
+ +
+ +- 如图,以上为用户旅途视角的全流程。从运营配置拼团活动,到用户从「小型支付商城(对接的一个场景)」,开始查看带有拼团优惠的上,进行试算,过滤规则。再到参与拼团,完成下单和一系列的流程处理。之后是拼团对于支付收单的入账计算,达成拼团目标后,回调(HTTP/MQ)商城服务,完成整个交易过程。 +- 之后,我们要考虑的是如何处理逆向流程,也就是退单的过程。退单分为当前过程中,拼团是否完成,未完成则根据是否支付了,取消锁单量和完成量。如果拼团已完成,则取消锁单量和完成量,拼团优惠释放后,则回调商城(refundGroupBuySuccess),完成退单退货服务。 +- 一般,对于已经完成拼团的,有用户退单是不会对其他用户已经完成交易的进行退单的,会造成很差的体验。这部分成本往往由商家和平台分摊,毕竟平台的目的是为了卖货。 + +## 三、详细设计 + +### 1. 服务对接 + +
+ +
+ +### 2. 正向流程 + +
+ +
+ +### 3. 逆向流程 + +
+ +
+ +以上,是整个`拼团系统` + `小型支付`的对接和正逆向流程设计。正向流程,已经全部完成。后面我们就要开启逆向流程啦,带着大家完完整整的把项目全部做完。 + +以上的流程分析,在课程中会有专门的视频讲解,一步步带着大家分析所有过程,以及各项细节。之后在技术社群的伙伴,完成所有的编码。 + + + diff --git a/docs/md/project/group-buy-market/promotion/group-buy-market-v7.md b/docs/md/project/group-buy-market/promotion/group-buy-market-v7.md new file mode 100644 index 000000000..68ad41d06 --- /dev/null +++ b/docs/md/project/group-buy-market/promotion/group-buy-market-v7.md @@ -0,0 +1,182 @@ +--- +title: 第3阶段开发完成,总结复盘 +lock: no +--- + +# 第3阶段开发完成,总结复盘 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +**耗时9个月制作,48节课程,微服务分布式架构**,`前后端 + DevOps + AI MCP(场景运用)`,全栈式编程 + 全程视频 + 全套的技术小册,手把手👨🏻‍💻教学,终于完结啦!🎉 + +
+ +
+ +**讲道理,做项目,就得做公司里真实有的业务。** + +我在非常多的互联网业务应用中,都看到过这样一种产品形态,它就是**拼团交易营销场景**,如;`拼多多/京东购物🛒`、`滴滴拼券🧧`、`腾讯开团抢购服务器☁️`、`美团团购☕️`等等,都是以拼团方式增强交易单量的业务场景。所以,如果想面试互联网公司,还是要优先考虑做一些这样的真实场景业务,这样才能和面试官有东西可以讲,而不是什么都没的聊o(╥﹏╥)o。 + +此套项目,小傅哥已提供了对应的`简历模板`、`面试问题(一直梳理中)`,还有 AI MCP 场景的加入,通过 AI MCP 对接 ELK + 普罗米修斯监控,Ai Agent 智能化分析系统的日志和运行情况。 + +**本项目,和你之前学习过的一些项目最大的区别,就是!这是真实的业务,全核心流程覆盖,有非常好的架构和编码设计。这块学习后,进入公司完全可以跟着大家一起做需求,而不是瑟瑟发抖的不知道自己要做啥!** + +
+ +
+ +> 文末有加入学习方式,提供全套的课程代码、文档、视频,此外还有额外的16个实战项目一起获取! + +## 一、能学到啥 + +该项目是互联网toc场景的核心业务流程,以真实业务作为背景,实际可上线,可运行为目标,进行系统的需求分析、架构设计、功能实现,过程涵盖设计模式的运用,解决复杂场景问题。让大家感受到,🐂牛逼的代码,从来不是一顿写CRUD! + +- 【前端】以 Ai Agent 设计前端 UI,包括 HTML、Div、CSS 等前端编程技术。 +- 【前端】掌握 fetch 方式对后端接口的调用,处理相关的逻辑数据。 +- 【后端】熟练搭建项目工程,学习工程分层结构概率和设计思路。掌握更多的六边形、洋葱、整洁架构。`提高简历技术亮点` +- 【后端】熟练掌握 Spring、SpringBoot、MyBatis 等开发框架技术,并对框架源码所提供的扩展接口具备运用能力。 +- 【后端】熟练使用 SpringCloud 核心微服务分布式技术栈,包括:Fegin、Sentinel、Nacos、熔断、限流、降级等。`先做功能,后面逐步添加。` +- 【后端】熟练使用大厂中常用的设计模式手段和设计原则技术,对各类场景的方案设计和落地能力,深度提高自身编码思维和开发技术能力。 +- 【后端】深度学习复杂场景的架构设计、编程思维,如果处理系统功能的边界和上下文的维护。—— 这些东西一定是从实践中才能学习到的。 +- 【后端】熟练使用 Mock 单测工具、JMeter 压测工具,增强代码交付质量。 +- 【后端】熟练掌握异常、枚举、错误码的定义和使用,并学习到如何合理打印服务日志,便于问题排查。 +- 【后端】以通用场景设计为目的,提取共性逻辑为通用的设计框架,涵盖;动态配置、设计模式(规则树、责任链)、限流。 +- 【运维】熟练使用 Docker 在本地和服务端的配置和部署应用,以及在本地构建前后端镜像。 +- 【运维】熟练掌握 Git、GitCode,对工程代码的管理,推送、拉取、切换分支、合并代码等操作。 +- 【运维】熟练使用 Nginx 配置转发服务,并能申请ssl配置https服务。 +- 【运维】熟练使用 Grafana 监控系统 + AI MCP,对系统的 JVM、磁盘、Tomcat、应用(QPS、响应时间、调用量)完整监控。 + +此外,小傅哥已对全过程都做了需求的分析、功能的设计、编码的精细化处理,让你吃上细糠!也通过这种方式,真正的把你的技术储备整起来,以后进入到公司都是嘎嘎强的选手! + +## 二、运行展示 + +整个拼团交易的流程非常细腻,包括了,一套小型支付 + 拼团营销平台的完整对接,涵盖;`验签`、`扫码/无痕登录`、`试算`、`锁单`、`支付+结算`、`退单+退单`的完整链路流程。如图; + +
+ +
+ +
+ +
+ +
+ +
+ +前端页面体现了全部核心流程,看着前端不是太多,但后端支撑整套系统了,写了**1.38万行代码**! + +## 三、简历模板 + +注意:🙅🏻‍ 不要直接复制粘贴简历模板内容!视频提供了 DeepSeek AI 方式编写简历,可以参考。 + +- **项目名称**:`拼团营销服务系统`、`交易营销场景 - 拼团系统`、`营销拼团交易平台`、`仿拼多多/腾讯/京东,拼团玩法系统(以大厂项目为背书)`、`拼团外卖平台系统(结合其他项目一起组合)` - 参考以上方式编写自己的项目名称,尤其拼团还是一个微服务,可以和很多其他系统组合。 + +- **项目架构**:`微服务设计`、`分布式架构`、`DDD 领域驱动设计 + 六边形分层架构实现`、`前后端分离技术` + +- **核心技术**:SpringBoot、MyBatis、MySQL、Guava、Redis、RabbitMQ、动态配置中心(DCC)、普罗米修斯监控、Docker等 - 如果学习了其他技术栈也可以补充。 + +- **项目描述**: + + - 方式1(以学习视角介绍):本项目参考`拼多多`交易购物拼团场景,调研中大厂相关营销业务场景和技术架构方案,设计实现了本套拼团营销服务系统,支持各类营销优惠(直减、折扣、N元购)。该系统以面向对象开发,运用 DDD 拆分领域边界,使用设计模式设计服务功能。提高系统的扩展性和可维护性。 + - 方式2(以提供服务介绍):该项目以`拉动/促进/提高`(小型支付商城/外卖点餐/购票出行/...)交易单量为目标,通过设计拼团优惠组队下单为手段,达到增强用户自传播分享私域提高整个交易GMV的结果。三段式描述,`...目标,...手段,...结果` + - 方式3(以实际场景介绍):该项目是以促进Xxx公司Xxx场景的核心营销优惠玩法系统,围绕公司的xxx、yyy、zzz等全部交易业务,设计通用的拼团优惠锁单和组队结算回调服务。此系统分布式架构设计,可支撑单机压测量 xxx tps,tp99 xxx 的数据指标,有效的满足公司的全量的业务场景接入使用。 + +- **核心方案**: + + - **架构设计**,以 DDD 领域驱动设计,四色建模方式,按照系统功能流程,拆解服务边界。包括;活动域、标签域、交易域。 + + - **设计模式**,设计并提炼通用的`责任链`、`规则树`模型框架,解决领域场景中多处,需要使用设计模式解耦复杂流程链路的调度(避免过多的if...else判断)。鉴于多处场景的责任链使用,模块框架设计责任链为执行和链路分离组装,便于工厂可以组合出各类执行责任链,不被不同的链路管理影响(以往的责任链,一般是单例的,会被影响)。 + + - **规则过滤**; + + - (举例)以拼团试算场景举例,运用通用设计模式模型框架,完成试算;根节点、切量开关、营销折扣、人群标签、异常兜底等流程串联。设计这样解耦设计,极大的提到了程序的可扩展性。 + - (举例)以拼团锁单场景举例,拼团锁单场景,使用通用的责任链模型框架,校验活动的有效性(状态、有效期)和用户的参与资格。 + - (举例)以拼团结算场景举例,拼团结算场景,使用通用的责任链模型框架,校验渠道黑名单配置、拼团组队信息、交易时间属性、订单有效状态等。 + - (举例)以拼团试算场景举例,在查询优惠配置数据时候,抽象出模板结构,使用 Supplier 函数式编程,设计动态降级、缓存数据和 dao 的后置执行操作。通用模板的设计让所有场景更容易接入。`ActivityRepository#queryGroupBuyActivityDiscountVO` + + - **异步线程**,为提高用户体验,将拼团优惠试算所需的营销类数据加载,由串行改为异步线程并行执行。此执行方式由通用设计模式模型框架提供。(如果由引入星球的动态线程池,也可以在这里增加线程池的管理描述) + + - **功能方案**; + + - (举例)通过 Redis 发布订阅模型,结合 Spring AOP 切面和代理,以自定义注解的方式控制属性信息动态配置。减少系统与 Redis 的 IO 交互,提高对高频场景属性值的使用时间效率。 + - (举例)设计拼团组队结算的 HTTP、MQ 双重手段,满足外部应用和内部微服务的不同方式对接,增强系统的适配性。同时为了保证整体方案的可靠性,在结算触达时,先异步多线程方式即时触发回调(HTTP、MQ),再通过业务一致性任务数据补偿校验。(MQ、HTTP,都可能因网络原因导致失败,因此需要重试)任务的触达,还增加多分布式锁,让任务互备抢占方式执行,增强系统的鲁棒性设计。 + - (举例)设计 Redis BitSet/BitMap 人群标签,用于过滤可见和可参与,拼团活动的人群信息。该人群标签可依赖于过往用户数据(交易下单)通过 job 任务完成人群标签的录入。 + - (举例)通过策略模式,设计拼团折扣(MJ、ZJ、NYG)的计算策略。同时折扣的计算也会通过人群标签过滤,以满足运营策略配置,降低活动风险。 + - (举例)运用 retrofit2/okhttp3/spring cloud fegin + nginx 负载,对接拼团交易平台锁单服务,以及通过 http 回调和 MQ 监听来处理交易结算。 + - (举例)`三阶段实现的内容`,通过独占锁处理互备任务抢占执行回调,确保在同一时刻有一个运行的回调任务,提高系统的鲁棒性设计。 + - (举例)`三阶段实现的内容`,设计Redis无锁化拼团库存抢占和恢复库存处理,减轻数据库行锁独占的压力,提高系统吞吐量。 + - (举例)`三阶段实现的内容`,抽象通用函数式缓存分级设计,并结合扳手工程DCC动态配置,处理缓存降级到DB设计。 + - (举例)`三阶段实现的内容`,结合 RateLimiter + DCC 动态配置,实现动态限流配置。 + - (举例)`三阶段实现的内容`,以 Ai MCP + ELK + 普罗米修斯监控,以 Ai Agent 智能体方式,分析错误日志和异常监控,动态化展示监控报表。 + - (举例)`三阶段实现的内容`,通过枚举策略,设计多种类型退单(未支付&未成团、已支付&未成团、已支付&已成团),并通过回调处理退单退款。 + +>以上仅对部分内容做了简历编写,这里还有非常多的内容可以写到简历,可以根据自己的学习和梳理,以及扩展进行简历编写。 + +## 四、后端设计 + +### 1. 分层架构 + +
+ +
+ +- 整个系统是一个微服务分布式架构设计,通过两套系统的对接,体现微服务的全流程处理关系。 +- 下面是系统中用到的核心技术栈,框架、组件、监控、部署、发布、上线,可以说是非常全面。 + +### 2. 工程结构 + +
+ +
+ +- 拼团和交易系统,以面向对象的思维,划分出领域结构。活动域、标签域、交易域、鉴权域、商品域、订单域。 +- 两套系统通过 http/rpc(可配置对接)、mq(RabbitMQ)进行同步和异步交互,因为配有本地消息表,所以可以保证最终一致性。 +- 这里有非常精妙的编码设计,如;工厂模式、组合模式、策略模式(含枚举策略)、责任链、抽象类等,又提供了 Supplier 函数式编程,可以说是应有尽有! + +### 3. 库表数据 + +
+ +
+ +- 一看库表就知道,这不是小儿科!有标签表,有活动的优惠,组队,订单明细,本地消息表,商品活动配置表,sku表。 + +### 4. 用户旅程 + +
+ +
+ +- 拼团全流程简图,以用户旅程来看各个节点所做的事项。 + +### 5. 场景举例 - 设计模式 + +#### 5.1 试算 + +
+ +
+ +
+ +
+ +为了解决整个交易过程的复杂场景,做了一套通用设计模式框架,并结合一套异步数据加载的多线程设计,来解决加载数据效率问题。让整个框架的灵活性非常高。 + +#### 5.2 退单 + +
+ +
+ +- 第一条退单链路,以工厂🏭方式获取执行责任链,责任链的作用是拆分原有的流程结构,分节点进行逐步处理。之后到退单的具体操作,则根据枚举策略,拿到对应执行的退单策略模式,完成退单动作。退单执行后发送MQ消息,驱动后续流程。 +- 第二条消息消息,从接收 MQ 开始,以 MQ 消息中的策略类型进行库存恢复操作。这部分保持原有的走对应的策略即可。 + +>整套项目,每一节都会有让你有新的感受,各个章节都有亮点设计,让你可以写到简历。 + diff --git a/docs/md/project/group-buy-market/qa.md b/docs/md/project/group-buy-market/qa.md new file mode 100644 index 000000000..648d63a43 --- /dev/null +++ b/docs/md/project/group-buy-market/qa.md @@ -0,0 +1,82 @@ +--- +title: Q&A:常见开发问题错误解答 +lock: no +--- + +# Q&A:常见开发问题错误解答 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/Yfbwo](https://t.zsxq.com/Yfbwo) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、断点调试 + +- [排查10个Bug](https://www.bilibili.com/video/BV1F6421w71e) +- [打断点查空指针](https://www.bilibili.com/video/BV1q1421Q7Uv) + +## 二、开发问题 + +### 1. Parameter 'teamIds' not found. + +如果遇到报错提示,有兼容问题,可以添加 `@Param("teamIds")` 到方法上 `Integer queryAllUserCount(@Param("teamIds") Set teamIds);` + +### 2. this is incompatible with sql_mode=only_full_group_by + +**添加 my.cnf 文件** + +```java +[client] +port = 3306 +default-character-set = utf8mb4 + +[mysqld] +user = mysql +port = 3306 +sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES + +default-storage-engine = InnoDB +default-authentication-plugin = mysql_native_password +character-set-server = utf8mb4 +collation-server = utf8mb4_unicode_ci +init_connect = 'SET NAMES utf8mb4' + +slow_query_log +#long_query_time = 3 +slow-query-log-file = /var/log/mysql/mysql.slow.log +log-error = /var/log/mysql/mysql.error.log + +default-time-zone = '+8:00' + +[mysql] +default-character-set = utf8mb4 +``` + +**修改 docker compose** + +```javascript +mysql: + image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/mysql:8.0.32 + container_name: mysql + command: --default-authentication-plugin=mysql_native_password + restart: always + environment: + TZ: Asia/Shanghai + MYSQL_ROOT_PASSWORD: 123456 + ports: + - "13306:3306" + volumes: + - ./mysql/my.cnf:/etc/mysql/conf.d/mysql.cnf:ro + - ./mysql/sql:/docker-entrypoint-initdb.d + healthcheck: + test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ] + interval: 5s + timeout: 10s + retries: 10 + start_period: 15s + networks: + - my-network +``` + +- 修改 MySQL 8.0 安装配置 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2541-1\350\212\202\357\274\232\346\213\274\345\233\242\351\234\200\346\261\202\345\210\206\346\236\220.md" "b/docs/md/project/group-buy-market/\347\254\2541-1\350\212\202\357\274\232\346\213\274\345\233\242\351\234\200\346\261\202\345\210\206\346\236\220.md" new file mode 100644 index 000000000..6a044b56c --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2541-1\350\212\202\357\274\232\346\213\274\345\233\242\351\234\200\346\261\202\345\210\206\346\236\220.md" @@ -0,0 +1,56 @@ +--- +title: 【更】第1-1节:拼团需求分析 +pay: https://t.zsxq.com/Wit9C +--- + +# 《拼团交易平台系统》第1-1节:拼团需求分析 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/1VRZq](https://t.zsxq.com/1VRZq) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +今天是我们《拼团交易平台系统》项目学习的第1节,我们先从需求分析开始理解这样一个项目要做什么,要解决什么场景问题。同时也要知道研发是怎么承接的产品需求。 + +在互联网公司中,一个需求首先是从业务侧发起的盈利目标,拆分为不同的运营策略。再把对应的策略由产品经理设计为可以支撑市场运营操作完成盈利目标的具体项目。所以这里有一般有3个角色,包括;业务人员、运营人员、产品经理。他们分别在自己的岗位产生不同的资料,包括;MRD、BRD、PRD。 + +- 市场需求文档(MRD): MRD是从市场的角度出发,描述目标市场的需求和机会。它通常包括目标客户群、市场趋势、竞争分析、市场机会、产品定位以及产品应该实现的市场目标等。MRD通常由产品经理或市场分析师编写,目的是定义产品应该解决的市场问题和满足的用户需求。 +- 业务需求文档(BRD): BRD更侧重于业务角度,描述业务目标、业务流程、业务规则、业务问题以及业务需求。它是从组织的业务视角来定义需求,包括业务背景、业务目标、影响分析、风险评估等。BRD通常由业务分析师编写,目的是确保项目解决了正确的业务问题,并与公司的业务战略保持一致。 +- 产品需求文档(PRD): PRD是更详细的文档,它根据MRD和BRD中确定的需求,具体描述产品的功能性和非功能性需求。PRD包括用户故事、用例、功能列表、性能要求、界面设计、用户体验等。PRD通常由产品经理编写,目的是为设计团队和开发团队提供一个明确的、详细的产品实现指南。 + +而研发最终看到的就是这份 PRD 文档,根据产品对 PRD 文档与各个负责的业务线研发进行的评审,让研发了解本次项目所需完成的工作。之后研发在会后根据 PRD 文档进行详细的设计和系统建模。这一部分前期的工作几乎占据了整个项目周期的50%以上的时间。所以研发写代码,只是众多环节中的一环。 + +接下来,我们来对本次的《拼团交易平台系统》进行需求分析,让大家细致的了解拼团的场景业务。你可以把这个过程就是当成你自己在承接一次产品需求,在学习的过程中把思考和扩展的点在评论区讨论,互相积累补充。 + +## 一、项目背景 + +>拼团系统可以用于,《小型支付商城》、《OpenAI应用》,这类带有支付场景购买商品的系统。我们这里以这样两个系统作为使用场景作为举例。也可以作用于任何其他的交易类系统。 + +针对目前的`小型支付商城系统`、`OpenAI应用系统`,商品购买交易同比增速放缓,需要引入新的营销策略促进商品交易量。在交易数据统计分析中得到,市场存在同类竞品,商品价格设定低于目前我们的商品定价,所以用户购买意愿偏低。 + +所以为了盘活沉睡用户,需要适当降低商品价格。但为了达到传播的效果,所以需要引入拼团方式,以客带客,靠用户自身传播的方式进行交易拉新。这样的处理方式对比于 KOL,会让利商品价值到用户自身。【KOL 等同于抖音大主播直播卖货】 + +
+ +
+ +另一方面,通过本项目的增加,逐步完善功能产品和运营服务体系,优化整体的产品架构,增强市场竞争力。 + +## 二、产品方案 + +因为我们所实现的是一个平台类系统,可以满足各类交易场景的拼团需求接入。所以在实现这套系统时候,不要与其他系统耦合。并提供相关的研发侧对接标准。 + +此外我们要提供前端案例对接展示,满足后续其他系统,如;《小型支付商城》、《OpenAI应用》对接时候有可参考样例。 + +### 1. 前端页面 + +
+ +
+ +- 进入商品页后,查询是否配置了拼团活动。并进行优惠试算,拼团成团价,最低优惠展示。 +- 参与首次拼团、参与拼团中拼团。拼团完成则不在展示此条拼团。 +- 所有参与中的拼团统计拼团人员。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2541-2\350\212\202\357\274\232\346\213\274\345\233\242\345\272\223\350\241\250\350\256\276\350\256\241.md" "b/docs/md/project/group-buy-market/\347\254\2541-2\350\212\202\357\274\232\346\213\274\345\233\242\345\272\223\350\241\250\350\256\276\350\256\241.md" new file mode 100644 index 000000000..05df83c38 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2541-2\350\212\202\357\274\232\346\213\274\345\233\242\345\272\223\350\241\250\350\256\276\350\256\241.md" @@ -0,0 +1,39 @@ +--- +title: 【更】第1-2节:拼团库表设计 +pay: https://t.zsxq.com/gSHjj +--- + +# 《拼团交易平台系统》第1-2节:拼团库表设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/iteVm](https://t.zsxq.com/iteVm) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +编程的代码是对数据逻辑的呈现,数据流转调度的好坏来自于数据结构设计的是否合理。而库表的设计就是对你过往学习数据结构知识的检测。 + +在库表设计时你需要了解整个业务执行过程,在这些过程中需要哪些数据作为支撑。合理的数据结构的库表设计,会让你的系统逻辑实现容易被人理解。反之,你可能要做大量的代码处理,也就是算法过程复杂度会变得很高。 + +这块知识的积累,最佳的手段就是多做实际的项目。从库表设计到编码实现,从编码实现反推库表合理性。做的多了,自然也就懂了。 + +## 一、本章诉求 + +通过拼团业务,讲解拼团流程实现中,所需的库表结构。包括;运营视角的配置诉求、用户视角的使用诉求。 + +只要你可以看懂库表设计,基本你也可以了解整个业务系统是如何实现的了。有了这样的积累,进入公司接触新的项目时,可以先从库表进行了解。知道它们的流转关系,之后在看系统设计和代码实现会更加清晰。 + +## 二、库表关系 + +在设计一套库表时,需要根据业务流程划分出大块的功能区,知道这些功能区的流转关系。 + +
+ +
+ +- 首先,站在运营的角度,要为这次拼团配置对应的拼团活动。那么就会涉及到;给哪个渠道的什么商品ID配置拼团,这样用户在进入商品页就可以看到带有拼团商品的信息了。之后要考虑,这个拼团的商品所提供的规则信息,包括;折扣、时间、人数等。还要拿到折扣的一个试算金额。这个试算出来的金额,就是告诉用户,通过拼团可以拿到的最低价格。 +- 之后,站在用户的角度,是参与拼团。首次发起一个拼团与参与已存在的拼团进行数据的记录,达成拼团约定拼团人数后,开始进行通知。这个通知的设计站在平台角度可以提供回调,那么任何的系统也就都可以接入了。 +- 另外,为了支撑这套库表,也会有人群的设计。人群是互联网公司中非常常用的手段,比如要把所有符合某个条件的用户ID,全部写入到一个特定的 Redis 记录中,之后就可以专门为这些人做特定的拼团活动了。 +- 那么,拼团活动表,为什么会把折扣拆分出来呢。因为这里的折扣可能有多种迭代到一个拼团上。比如,给一个商品添加了直减10元的优惠,又对符合的人群id的用户,额外打9折,这样就有了2个折扣迭代。所以拆分出来会更好维护。这是对常变的元素和稳定的元素进行设计的思考。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2541-3\350\212\202\357\274\232\347\240\224\345\217\221\347\263\273\347\273\237\350\256\276\350\256\241.md" "b/docs/md/project/group-buy-market/\347\254\2541-3\350\212\202\357\274\232\347\240\224\345\217\221\347\263\273\347\273\237\350\256\276\350\256\241.md" new file mode 100644 index 000000000..140d609ca --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2541-3\350\212\202\357\274\232\347\240\224\345\217\221\347\263\273\347\273\237\350\256\276\350\256\241.md" @@ -0,0 +1,34 @@ +--- +title: 【更】第1-3节:研发系统设计 +pay: https://t.zsxq.com/ESHMx +--- + +# 《拼团交易平台系统》第1-3节:研发系统设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/UoowL](https://t.zsxq.com/UoowL) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +对于程序员👨🏻‍💻来说,虽然写代码是最直接的工作体现,但工作可不是就只写代码。就一个产品功能需求而言,研发在参与评审后,还需要对需求进行功能的研发系统设计。 + +这个过程是比较消耗时间的,一般在2-3天完成,或者大型项目与外部对接的较多的情况,会需要3-5天以上。一般初级的开发在不具有系统的把控能力的时候,会考虑在工程中写伪代码的过程,来梳理系统设计。包括;涉及模块、功能流程、外部对接、接口字段等,全新的系统还要做架构的设计、分层的设计、模块的设计等。 + +那么对于小伙伴们学习的本节来说,就是一个全新的系统,我们可以全部的了解到系统设计所需的内容。 + +## 一、本章诉求 + +通过对拼团需求的理解,进行研发系统设计。包括;用例图、系统建模、工程模型、功能流程、UML时序图。另外像是库表设计已经在前面完成了,它也属于研发系统设计的一部分,提前做了这部分是为了让大家更好的理解系统需求。 + +## 二、设计目的 + +为什么,不上来就写代码? + +在15年刚加入互联网大厂的时候,基本上是一上来就写代码。产品聊完需求,研发简单记录,之后就是打开工程直接编码了。需求是上午写的,代码是下午干的。这样对于刚起步阶段是比较合适的,可以快速迭代。 + +但随着公司的体系化越来越完整,一个小项目也变成一个个独立业务线的大项目,一个人开发也变成了一个团队开发。所有的系统功能的实现,一点点小问题,都可能是一个个大问题。甚至一个bug,一会时间就会被传到微博,之后就是一片的舆情和客诉。 + +所以,到了目前这个阶段,研发不能只是为了功能而直接开发。还要遵守一些列的流程,确保开发迭代的需求,都能平稳的交付。所以要有研发设计、要有评审、要有测试、要有预发、要有黑白名单验证和功能切量。 diff --git "a/docs/md/project/group-buy-market/\347\254\2542-10\350\212\202\357\274\232\350\264\243\344\273\273\351\223\276\346\212\275\350\261\241\346\250\241\346\235\277\350\256\276\350\256\241.md" "b/docs/md/project/group-buy-market/\347\254\2542-10\350\212\202\357\274\232\350\264\243\344\273\273\351\223\276\346\212\275\350\261\241\346\250\241\346\235\277\350\256\276\350\256\241.md" new file mode 100644 index 000000000..736655732 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-10\350\212\202\357\274\232\350\264\243\344\273\273\351\223\276\346\212\275\350\261\241\346\250\241\346\235\277\350\256\276\350\256\241.md" @@ -0,0 +1,37 @@ +--- +title: 【更】第2-10节:责任链抽象模板设计 +pay: https://t.zsxq.com/pUS6P +--- + +# 《拼团交易平台系统》第2-10节:责任链抽象模板设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/Ao3ox](https://t.zsxq.com/Ao3ox) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +做开发了这么久,其实业务类的开发大部分都是串联流程,其实复杂度并不高。但之所以最后非常难理解,是写的人,驾驭能力不强,把工程写的越来越难以理解。 + +而如果想让工程实现的逻辑好理解,就要做好解耦设计。而这些解耦的流程大部分是具有通用性的,所以我们可以设计出能解决大部分通用业务场景的共性模型结构。 + +在之前小傅哥就带着大家设计了一个规则树的模型,本节我们借着项目的开发在设计一款通用的责任链模型结构。 + +## 一、本章诉求 + +在拼团交易的下单锁定优惠的过程中,以及后续的流程,都会有简单的规则串联。所以,我们先来提前做好通用的责任链模型结构,便于后续使用。 + +本节会涉及到链表的基础数据结构知识,可以提前补充学习;[https://bugstack.cn/md/algorithm/data-structures/2022-07-22-linked-list.html](https://bugstack.cn/md/algorithm/data-structures/2022-07-22-linked-list.html) + +## 二、模型设计 + +责任链是一种简单的单链路结构,在工程中会有多个这样的单链,为了可以让不同的场景都能创建出自己的链,则需要解耦责任链的链路和执行,再有执行器处理。在本次实现中小傅哥会给大家体统两种责任链,让大家对照学习。设计如图; + +
+ +
+ +- 如图,这是一种多实例对象责任链的设计结构,会使用到如 Java JDK 源码中 Link 的方式填写链路,之后再有业务链路处理链路执行。而每一个链路都会被填充一个逻辑处理器的实现类(ILogicHandler)来处理具体的业务。 +- 那么,这样就很好的扩展了各种链路的使用诉求。我们可以结合代码来学习。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-11\350\212\202\357\274\232\344\272\244\346\230\223\350\247\204\345\210\231\350\264\243\344\273\273\351\223\276\350\277\207\346\273\244.md" "b/docs/md/project/group-buy-market/\347\254\2542-11\350\212\202\357\274\232\344\272\244\346\230\223\350\247\204\345\210\231\350\264\243\344\273\273\351\223\276\350\277\207\346\273\244.md" new file mode 100644 index 000000000..d08ebba70 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-11\350\212\202\357\274\232\344\272\244\346\230\223\350\247\204\345\210\231\350\264\243\344\273\273\351\223\276\350\277\207\346\273\244.md" @@ -0,0 +1,41 @@ +--- +title: 【更】第2-11节:交易规则责任链过滤 +pay: https://t.zsxq.com/PaSMk +--- + +# 《拼团交易平台系统》第2-11节:交易规则责任链过滤 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/wxTw6](https://t.zsxq.com/wxTw6) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +为什么公司里有些人做了很多事情,写了很多代码,但到最后也没有多大的成绩呢? + +其实很多时候就是太重复了,从刚开始对工程不理解,到能熟练上手以后,就从脑力活变成了体力活,一遍遍的重复自己。所以,就算是工作几年,也和前面刚开始工作差不多,就只是熟练了业务,但技术却没有提升。 + +所以,多提高编程思维,锻炼编码能力,一次次对工程进行抽象,提炼出骨架的核心设计,才是非常重要的。 + +## 一、本章诉求 + +完善拼团交易营销锁单的流程,增加锁单流程中的规则处理。 + +本节的规则过滤,会使用到前面章节设计的统一的设计模式框架中的责任链模式。对这类轻量的场景,一般只需要选择单链的执行模型即可,而与之对比的规则树,是适合于那种节点间的复杂分支流转。 + +## 二、业务流程 + +如图,增加交易规则处理; + +
+ +
+ +
+ +
+ +- 在前面章节,我们实现了拼团锁单中,参数校验、幂等校验、达成校验,之后做了营销试算和营销锁单。 +- 那么在本节,还需要对营销锁单继续完善,过滤拼团活动配置的规则。包括;活动的有效期、状态,以及个人参与拼团的次数。在实际公司中的项目里,还会有更多的规则要被处理。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-12\350\212\202\357\274\232\346\213\274\345\233\242\347\273\204\351\230\237\347\273\223\347\256\227\347\273\237\350\256\241.md" "b/docs/md/project/group-buy-market/\347\254\2542-12\350\212\202\357\274\232\346\213\274\345\233\242\347\273\204\351\230\237\347\273\223\347\256\227\347\273\237\350\256\241.md" new file mode 100644 index 000000000..5bb0a9553 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-12\350\212\202\357\274\232\346\213\274\345\233\242\347\273\204\351\230\237\347\273\223\347\256\227\347\273\237\350\256\241.md" @@ -0,0 +1,38 @@ +--- +title: 【更】第2-12节:拼团组队结算统计 +pay: https://t.zsxq.com/OvyY1 +--- + +# 《拼团交易平台系统》第2-12节:人群标签生成任务 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/89N6w](https://t.zsxq.com/89N6w) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +其实互联网大厂也是从草蜢阶段过来的,所以到现在才有这么大的技术债。几乎每年我们都要为工程制定体系化建设的计划,新的工程采用纯心的架构模型实现,旧的工程分为重构计划和工程内编码治理。 + +通过这样的手段,让工程一点点从严重的腐化中拆解出来。所以你在学习咱们的新项目时候,也会感受到不断的抽象和治理,让代码变得容易被理解和迭代。 + +## 一、本章诉求 + +首先,你可以回忆下咱们整个拼团业务的流程。 + +拼团的过程是用户在商城下单,锁定拼团优惠(也就是拼团系统里锁单的过程)。之后就是用户给这笔商品完成支付交易,交易后不会直接发货,直至拼团组队完成后才会发货。 + +那么,这里有一个流程,就是支付完成后,需要做拼团数量的统计结算。如,拼团需要3个用户一起下单,那么每完成一笔支付,就要给拼团的组队加上一笔记录。这个就是本节要实现的流程。 + +## 二、业务流程 + +如图,拼团结算流程。 + +
+ +
+ +- 首先,交易订单的营销结算,核心就是更新拼团队伍的参与人数数量。每完成一笔支付,就有一笔拼团进度数量+1。 +- 之后,这里要知道,更新拼团订单的明细状态(交易完成)和更新拼团进度数量要在一个事务下完成。 +- 另外,更新拼团的进度要判断,当前是否为最后一次拼团完结状态。比如计算剩余1个,即可完成拼团目标量,那么这最后一笔更新完成后,既是整个拼团队伍的进度完成了。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-13\350\212\202\357\274\232\344\272\244\346\230\223\347\273\223\347\256\227\350\264\243\344\273\273\351\223\276\350\277\207\346\273\244.md" "b/docs/md/project/group-buy-market/\347\254\2542-13\350\212\202\357\274\232\344\272\244\346\230\223\347\273\223\347\256\227\350\264\243\344\273\273\351\223\276\350\277\207\346\273\244.md" new file mode 100644 index 000000000..8c60e7133 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-13\350\212\202\357\274\232\344\272\244\346\230\223\347\273\223\347\256\227\350\264\243\344\273\273\351\223\276\350\277\207\346\273\244.md" @@ -0,0 +1,44 @@ +--- +title: 【更】第2-13节:交易结算责任链过滤 +pay: https://t.zsxq.com/I2cmu +--- + +# 《拼团交易平台系统》第2-13节:交易结算责任链过滤 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/ScKNa](https://t.zsxq.com/ScKNa) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在我整个互联网编程的职业生涯中,有一段时间一个人负责了4-5个业务系统,还有3-4个技术类组件。领导看我有这么多系统,就给我招聘了几个人,让我把活分配出去。 + +但最开始我是比较抗拒的,因为这些系统已经非常手到擒来了,想做什么设计实现,也是能非常容易的迭代完成,并且随着每次的迭代也会做细腻的重构设计。 + +而我抗拒的原因是因为中间招聘的伙伴,有几次都是来了半年多又走了,系统又交接回来了。这个时候在对这个系统做实现时候,就会发现很多细节的地方,与预期非常不符。不过,后来也慢慢习惯了,增加了很多的评审、提供了的设计,让工程尽量别走型严重。 + +## 一、本站诉求 + +拼团交易结算的过程,需要一些列的规则过滤。包括;我们上一节提到的校验外部交易单的时间是否在拼团有效时间内,同时还有关于这笔外部交易单是否为有效的拼团锁单订单。另外像是 SC 渠道的有效性也需要在结算时进行校验。 + +所以,本节我们需要实现一套规则链,来处理这些业务规则。因为规则链已经被抽取为通用的模板了,那么本节使用起来会非常容易。 + +## 二、业务流程 + +如图,拼团交易结算流程设计; + +
+ +
+ +- 首先,本节的重点在于新增加结算规则过滤的责任链,处理;SC渠道管控、有效的外部交易单号、结算实现是否为拼团时效内。 +- 那么这里会有一些功能改造点; + - 拼团表,group_buy_order 增加 valid_start_time(有效开始时间)、valid_end_time(有效结束时间) 字段。用于每笔交易结算时候,用结算时间判断是否匹配到拼团有效时间范围内。 + - 拼团明细,group_buy_order_list 增加 out_trade_time(交易时间) 字段,记录每笔结算的订单结算的时间。随着状态更新的时候更新。 + - trade 领域下,lock 锁单。实体对象,修改名称。TradeRuleCommandEntity -> TradeLockRuleCommandEntity,TradeRuleFilterBackEntity -> TradeLockRuleFilterBackEntity 增加了 Lock 标识。便于在添加 TradeSettlementRuleCommandEntity、TradeSettlementRuleFilterBackEntity 时更好理解。 + - PayActivityEntity 添加 validTime,GroupBuyTeamEntity 添加 validStartTime、validEndTime + - trade 领域下,settlement 结算服务中,使用责任链模板,实现营销交易规则的过滤。SCRuleFilter(SC黑名单管控过滤 DCCService 配置新的属性 scBlacklist)、OutTradeNoRuleFilter(外部交易单号有效性过滤)、SettableRuleFilter(交易时间是否在拼团有效时间内过滤)、EndRuleFilter(结束节点封装返回数据) + - 交易服务,TradePaySettlementEntity 调用 tradeSettlementRuleFilter 责任链方法,并返回相关的数据信息。 + - settlementMarketPayOrder 结算一个事务下操作,增加 updateOrderStatus2COMPLETE 更新时候添加 outTradeTime 时间。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-14\350\212\202\357\274\232\346\213\274\345\233\242\345\233\236\350\260\203\351\200\232\347\237\245\344\273\273\345\212\241.md" "b/docs/md/project/group-buy-market/\347\254\2542-14\350\212\202\357\274\232\346\213\274\345\233\242\345\233\236\350\260\203\351\200\232\347\237\245\344\273\273\345\212\241.md" new file mode 100644 index 000000000..ec4f9860d --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-14\350\212\202\357\274\232\346\213\274\345\233\242\345\233\236\350\260\203\351\200\232\347\237\245\344\273\273\345\212\241.md" @@ -0,0 +1,42 @@ +--- +title: 【更】第2-14节:拼团回调通知任务 +pay: https://t.zsxq.com/IWiNu +--- + +# 《拼团交易平台系统》第2-14节:拼团回调通知任务 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/ysSyW](https://t.zsxq.com/ysSyW) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +## 一、本章诉求 + +在微服务设计中,当一个微服务系统的流程结束后,要通知下一个微服务系统。这个通知的过程,可以是 RPC、MQ,也可以是 HTTP 方式。 + +RPC、MQ,这一类的都是需要有一个公用的注册中心,它的技术架构比较适合于公司内部的统一系统使用。如果是有和外部其他系统的对接,通常我们会使用 HTTP 这样统一标准协议的接口进行使用。 + +那么,本章节要为拼团组队交易结算完结后,实现一个回调通知的任务处理。告知另外的微服务系统可以进行后续的流程了。 + +注意:微信支付,支付宝支付,也是在完成支付后,做的这样的回调处理。 + +## 二、业务流程 + +如图,拼团结算组队完成,回调通知; + +
+ +
+ +- 首先,本节的重点在拼团成团后,实现回调通知流程。回调的过程,需要在用户锁单时需要增加一个回调的地址,并在拼团完结后发起回调。 +- 那么,这里的一些功能改造点; + - `group_buy_order` 在设计的时候有一个 `notify_url` 回调地址,本节我们修改库表添加上这个字段。并对工程中的 `dao&po&mapper` 操作,增加 `notify_url` 字段。 + - MarketTradeController 营销交易服务,lockMarketPayOrder 锁单接口入参对象,增加 notifyUrl 回调地址。并有 PayDiscountEntity 对象透传到 `TradeRepository#lockMarketPayOrder` 仓储操作。这样写到 `group_buy_order` 表就有回调地址了,等做回调操作的时候,就可以把这个地址写入到回调任务表中。 + - `TradeSettlementOrderService#settlementMarketPayOrder` 结算服务,需要把锁单记录中的 notify_url 拿到,放到 GroupBuyTeamEntity 中,这样在写入 notify_task 表记录的时候就可以把 notify_url 一起写入进去了。 + - 基于 okhttp 框架,封装对 http 接口的调用。用于处理调用外部其他微服务,实现回调通知的处理。因为外部的接口是随着每个服务调用拼团写入进来的 http 请求地址,所以在封装这部分调用的时候,要允许动态透传请求地址。实现类写到 infrastructure 基础设置层的 gateway 调用外部网关层。实现类;`GroupBuyNotifyService` 提供方法;`groupBuyNotify` + - 在交易结算服务类 ITradeSettlementOrderService,定义执行结算回调通知接口,包括;`execSettlementNotifyJob()、execSettlementNotifyJob(String teamId)` 一个是有入参的,一个无入参。这样可以指定给某个拼团队伍做结算。结算的过程就是调用 `GroupBuyNotifyService#groupBuyNotify` 完成回调通知,并根据返回的结果更新 notify_task 表状态记录(成功、失败、重试),并记录回调次数,小于5次的时候都可以继续回调。 + - 回调通知,可以分为两个阶段处理。一个是拼团完成后立即执行,另外一个任务补偿。立即执行是为了提供时效性,但因为远程的 http 调用受网络和服务的影响可能会失败,所以要增加一个任务补偿来做定时检查。其中立即执行在 `TradeSettlementOrderService#settlementMarketPayOrder -> settlementMarketPayOrder` 处理。另外定时任务在 `GroupBuyNotifyJob` 处理。 + - 测试接口,`trigger/http` 下,增加 `TestApiClientController` 接口实现类,提供回调接口服务。这个是模拟的其他的微服务,将来要提供的接口。 diff --git "a/docs/md/project/group-buy-market/\347\254\2542-15\350\212\202\357\274\232\346\240\271\346\215\256UI\345\261\225\347\244\272\345\260\201\350\243\205\346\216\245\345\217\243.md" "b/docs/md/project/group-buy-market/\347\254\2542-15\350\212\202\357\274\232\346\240\271\346\215\256UI\345\261\225\347\244\272\345\260\201\350\243\205\346\216\245\345\217\243.md" new file mode 100644 index 000000000..f036b2760 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-15\350\212\202\357\274\232\346\240\271\346\215\256UI\345\261\225\347\244\272\345\260\201\350\243\205\346\216\245\345\217\243.md" @@ -0,0 +1,33 @@ +--- +title: 【更】第2-15节:根据UI展示封装接口 +pay: https://t.zsxq.com/eQHFl +--- + +# 《拼团交易平台系统》第2-15节:根据UI展示封装接口 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/2C7df](https://t.zsxq.com/2C7df) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +## 一、本章诉求 + +根据在上一节使用 DeepSeek 实现的拼团 UI,设计并实现所需的服务端接口。 + +在互联网公司里的开发过程也是这样,产品在评审期间,会提供 UI 工程师做好的设计图,研发拿到设计图后,提供所需的接口提供相应的字段。 + +## 二、接口分析 + +如图,根据UI分析所需接口数据; + +
+ +
+ +- 紫色圈;10人再抢,是拼团的统计数据。类似的还有总共开多少团、成功的拼团等,如果有展示需求,都可以在拼团统计中给出。 +- 灰色圈;商品信息,商品金额、优惠金额、支付金额等。 +- 绿色圈;参与拼团,UI 调用的操作是锁单的处理。在完整的流程中是调用商城类系统,发起交易,之后由商城类系统进行营销锁单。我们这里模拟,所以从前端开始锁单。 +- 黄色券;这里不是真实对接扫码支付,所以要点支付完成,才能触发拼团结算。所以这里需要调用拼团里的结算接口。 diff --git "a/docs/md/project/group-buy-market/\347\254\2542-16\350\212\202\357\274\232\345\274\225\345\205\245RabbitMQ\345\210\206\345\270\203\345\274\217\345\244\232\347\253\257\346\266\210\350\264\271.md" "b/docs/md/project/group-buy-market/\347\254\2542-16\350\212\202\357\274\232\345\274\225\345\205\245RabbitMQ\345\210\206\345\270\203\345\274\217\345\244\232\347\253\257\346\266\210\350\264\271.md" new file mode 100644 index 000000000..031b7aae5 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-16\350\212\202\357\274\232\345\274\225\345\205\245RabbitMQ\345\210\206\345\270\203\345\274\217\345\244\232\347\253\257\346\266\210\350\264\271.md" @@ -0,0 +1,34 @@ +--- +title: 【更】第2-16节:引入RabbitMQ分布式多端消费 +pay: https://t.zsxq.com/fhRso +--- + +# 《拼团交易平台系统》第2-16节:引入RabbitMQ分布式多端消费 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/mipvF](https://t.zsxq.com/mipvF) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +## 一、本章诉求 + +引入 RabbitMQ 分布式技术框架,实现分布式消息消费和多服务消费的能力。 + +消息,是一种解耦服务间直接(http/rpc)调用的手段,以发送消息和接收消息的模式,完成业务流程的异步化处理。 + +**RabbitMQ 基础教程**:[https://bugstack.cn/md/road-map/rabbitmq.html](https://bugstack.cn/md/road-map/rabbitmq.html) + +## 二、业务流程 + +在互联网公司中,往往一个微服务发送出来的 MQ,除了自己接收消费处理自己的业务流程,也会有很多其他微服务进行消费。那么这里就会有一个 Topic,被多个应用消费的配置。如图; + +
+ +
+ +- 以拼团发送结算完成消息举例,拼团是负载均衡部署了2套服务,发送的MQ消息,由小型支付对接。 +- 那么,负载均衡的拼团服务,发送MQ后,自己的2套微服务,会分别接收到消息。另外一套小型支付,假设只部署了一套,那么这里会消费5个MQ消息。 +- 注意,以 RabbitMQ举例,这里会需要使用到同一套交换机,同一个路由Key,但队列要分别每个服务配置不同的。同时消息支持持久化,也就是拼团发送的MQ消息,即使小型支付服务暂时没有启动,也可以在启动后消费队列里的MQ消息。 diff --git "a/docs/md/project/group-buy-market/\347\254\2542-17\350\212\202\357\274\232\345\217\221\351\200\201MQ\347\273\223\347\256\227\346\266\210\346\201\257.md" "b/docs/md/project/group-buy-market/\347\254\2542-17\350\212\202\357\274\232\345\217\221\351\200\201MQ\347\273\223\347\256\227\346\266\210\346\201\257.md" new file mode 100644 index 000000000..8c18ac900 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-17\350\212\202\357\274\232\345\217\221\351\200\201MQ\347\273\223\347\256\227\346\266\210\346\201\257.md" @@ -0,0 +1,36 @@ +--- +title: 【更】第2-17节:发送MQ结算消息 +pay: https://t.zsxq.com/zvx7v +--- + +# 《拼团交易平台系统》第2-17节:发送MQ结算消息 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/OtfX8](https://t.zsxq.com/OtfX8) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +## 一、本章诉求 + +增加拼团结算完成 MQ 触达方式,HTTP、MQ 触达,由调用方通过入参类型决定。 + +MQ 一般用在企业内的微服务系统间通信,因为企业内的微服务,共用了一套的 MQ 注册中心,MQ 可以更加高效的触达和分布式部署。而对于企业外的调用,与我们完全不是一个公司的系统,那么不再同一个微服务环境内,则需要通过 HTTP 方式这样标准的协议调用。如;支付宝支付完成回调、微信公众号发送消息后的回调,都是基于 HTTP 的方式实现。 + +## 二、业务流程 + +如图,HTTP、MQ,由调用方配置使用那种方式进行处理。 + +
+ +
+ +- 用户创建营销锁单时,选择MQ、HTTP回调方式。这个类型会被写入到对应的拼团订单记录里。 + +
+ +
+ +- 拼团完成结算后,在根据写入到拼团订单的记录,回调的方式,来回调通知结算。 diff --git "a/docs/md/project/group-buy-market/\347\254\2542-18\350\212\202\357\274\232\346\266\210\350\264\271MQ\347\273\223\347\256\227\346\266\210\346\201\257.md" "b/docs/md/project/group-buy-market/\347\254\2542-18\350\212\202\357\274\232\346\266\210\350\264\271MQ\347\273\223\347\256\227\346\266\210\346\201\257.md" new file mode 100644 index 000000000..626547b08 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-18\350\212\202\357\274\232\346\266\210\350\264\271MQ\347\273\223\347\256\227\346\266\210\346\201\257.md" @@ -0,0 +1,27 @@ +--- +title: 【更】第2-18节:消费MQ结算消息 +pay: https://t.zsxq.com/dZEBT +--- + +# 《拼团交易平台系统》第2-18节:消费MQ结算消息 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/rclqJ](https://t.zsxq.com/rclqJ) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +完善小型支付商城对拼团组队结算消息的处理,同时完成小型支付商城中支付交易结算消息的处理。这样我们整个系统就都具备分布式部署的能力了。也就是多个应用实例同时部署,一个MQ在一个应用实例消费宕机,可以被其他应用实例继续拉取消费。 + +## 二、业务流程 + +如图,MQ 在小型支付和拼团的执行流程。 + +
+ +
+ +- MQ 具有解耦、消峰,最终一致性的特性。所以很多的分布式设计中,都会引入 MQ 来解耦复杂的业务流程,除了数据库事务处理外的流程节点,则由 MQ 进行驱动。 +- 从拼团下单到锁单结算,完成后触达MQ消费。之后由小型支付商城消费 MQ 结算消息,变更订单状态,之后触达下一个支付结算的动作。在接收支付结算完成模拟发货。第二个MQ的发送不用写数据库任务来补偿,如果发MQ失败了,就直接抛异常重试继续发就可以。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-19\350\212\202\357\274\232\347\213\254\345\215\240\351\224\201\345\222\214\346\227\240\351\224\201\345\214\226\345\234\272\346\231\257\350\277\220\347\224\250.md" "b/docs/md/project/group-buy-market/\347\254\2542-19\350\212\202\357\274\232\347\213\254\345\215\240\351\224\201\345\222\214\346\227\240\351\224\201\345\214\226\345\234\272\346\231\257\350\277\220\347\224\250.md" new file mode 100644 index 000000000..4057a7ff0 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-19\350\212\202\357\274\232\347\213\254\345\215\240\351\224\201\345\222\214\346\227\240\351\224\201\345\214\226\345\234\272\346\231\257\350\277\220\347\224\250.md" @@ -0,0 +1,27 @@ +--- +title: 【更】第2-19节:独占锁和无锁化场景运用 +pay: https://t.zsxq.com/NxC2G +--- + +# 《拼团交易平台系统》第2-19节:独占锁和无锁化场景运用 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/o7toC](https://t.zsxq.com/o7toC) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +以独占锁抢占方式,迭代拼团结算通知互备执行任务。再以无锁化设计,处理用户拼团锁单,库存抢占处理,降低对数据库的行锁压力,提高整体吞吐量。 + +## 二、业务流程 + +如图,两种锁应对的场景; + +
+ +
+ +- 分段锁,颗粒度缩小到库存维度。先加(incr)后锁的操作,是一种无锁化设计。锁的目的只是作为兜底。这类似于我们操作账户,操作完写一条流水。incr 操作是原子的,基本不会产生一样的值。但在实际生产中,遇到过集群的运维配置问题,以及业务运营配置数据问题,导致 incr 得到的值相同。 +- 独占锁,在分布式架构系统设计中,会有多个实例部署。这些实例都会做job任务的执行,为了保障既能让任务互备,同时不要重复执行。这里要加独占锁,谁抢占到谁执行。执行完成后,释放锁,下一轮继续抢占。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-1\350\212\202\357\274\232\345\210\235\345\247\213\345\267\245\347\250\213\346\220\255\345\273\272.md" "b/docs/md/project/group-buy-market/\347\254\2542-1\350\212\202\357\274\232\345\210\235\345\247\213\345\267\245\347\250\213\346\220\255\345\273\272.md" new file mode 100644 index 000000000..0cf736547 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-1\350\212\202\357\274\232\345\210\235\345\247\213\345\267\245\347\250\213\346\220\255\345\273\272.md" @@ -0,0 +1,62 @@ +--- +title: 【更】第2-1节:初始工程搭建 +pay: https://t.zsxq.com/1ZafX +--- + +# 《拼团交易平台系统》第2-1节:初始工程搭建 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/mT399](https://t.zsxq.com/mT399) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +可能不少小伙伴都学习过一些入门项目,简单的使用 IntelliJ IDEA 创建和使用。但对于在互联网公司中如何创建和使用一套新工程,往往是不清楚他们是使用了什么样的统一标准的。因为在公司中,那么多新项目要创建,不太可能让每个组的每个人都创建风格迥异的项目工程,这样对维护成本来说是非常大的。所以这里要建立工具和标准化。 + +所以,跟着小傅哥学习,不只是做项目。而是以互联网中大型公司标准化的方式来开发、设计、实现功能。 + +## 一、本章诉求 + +教会小伙伴使用统一标准脚手架方式创建项目工程,并了解工程模块的分层用途。以及完成2张关于拼团互动库表的创建和使用。 + +课程会循序渐进的从0到1,逐步带着大家完成项目的开发。开局只有一把 IntelliJ IDEA,完成项目后你可以学习到;业务、架构、设计、方案、配置、部署(Linux、Docker)等各项知识。 + +## 二、如何开始 + +站在读者视角,该怎么学习呢?这里做个必要说明和前置的知识提供。 + +### 1. 前置学习 + +小伙伴在学习的时候,可以依照课程的方式进行创建项目、变更配置、启动测试。这里有一些前置学习,包括:Git、Maven、Docker、脚手架,课程已经准备好了,可以刷下; + +- Git:[https://bugstack.cn/md/road-map/git.html](https://bugstack.cn/md/road-map/git.html) +- Maven:[https://bugstack.cn/md/road-map/maven.html](https://bugstack.cn/md/road-map/maven.html) +- Docker [https://bugstack.cn/md/road-map/docker-what.html](https://bugstack.cn/md/road-map/docker-what.html) +- 脚手架:[https://bugstack.cn/md/road-map/ddd-archetype-maven.html](https://bugstack.cn/md/road-map/ddd-archetype-maven.html) + +另外课程会使用 Java JDK 1.8、Maven 3.8.x,软件已经提供好,可以直接下载;[https://t.zsxq.com/19Rnk98M0](https://t.zsxq.com/19Rnk98M0) - `附件内含有配置好阿里云镜像的 Maven` + +### 2. 开始学习 + +1. 你需要通过 git clone 命令,或者 IntelliJ IDEA 自动的检出工程方式,把项目工程检出到本地。关于如何使用Git检出项目,在前置学习里提供了教程。 +2. 检出代码后,你可以通过 IntelliJ IDEA 打开项目,并按照每一节最开始说明的本节对应的代码分支,把工程代码切换到对应的这一节。 +3. 接下来你可以通过课程的视频和小册以及提供的代码进行学习,并跟随课程每节要完成的内容,一步步操作。过程中可以参考课程的代码进行学习。如果自己的代码运行出问题的时候,可以运行课程的代码验证是环境问题还是个人代码问题。**另外注意运行课程代码,要修改对应的环境为你的本地环境,mysql、redis等** +4. 对于课程中每节涉及的库表,会放到工程 docs/dev-ops mysql 下。你可以每节学习创建一个新的库名称,之后导入。但要记得在工程 app/application-dev.yml 文件中修改对应的库名称。 + +### 3. 环境安装 + +课程提供了使用 Docker 部署 MySQL、Redis 环境的脚本。因为使用 Docker 可以随时方便卸载,不会污染本地电脑的本机环境。而且后续部署 Linux 云服务器也会非常顺手。 + +关于环境的安装; + +
+ +
+ +1. Windows + wsl2,本地使用 powershell 切换到工程文件夹,执行 `docker-comopse -f docker-compose-environment-aliyun.yml up -d` +2. Mac 电脑的适配性会更好,直接点击这里的绿色箭头即可安装。 +3. 如果本机配置有问题,也可以选择使用云服务器。课程中有云服务器的操作教程,部署起来更方便。云服务器教程:[https://bugstack.cn/md/road-map/linux.html](https://bugstack.cn/md/road-map/linux.html) + +> 环境安装后就可以使用 MySql、Redis 链接工具使用了,也可以手动更新库表。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-20\350\212\202\357\274\232\345\207\275\346\225\260\345\274\217\346\225\260\346\215\256\347\274\223\345\255\230\345\222\214\351\231\215\347\272\247\345\210\260DB\345\244\204\347\220\206.md" "b/docs/md/project/group-buy-market/\347\254\2542-20\350\212\202\357\274\232\345\207\275\346\225\260\345\274\217\346\225\260\346\215\256\347\274\223\345\255\230\345\222\214\351\231\215\347\272\247\345\210\260DB\345\244\204\347\220\206.md" new file mode 100644 index 000000000..576127833 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-20\350\212\202\357\274\232\345\207\275\346\225\260\345\274\217\346\225\260\346\215\256\347\274\223\345\255\230\345\222\214\351\231\215\347\272\247\345\210\260DB\345\244\204\347\220\206.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第2-20节:函数式数据缓存和降级到DB处理 +pay: https://t.zsxq.com/pEE1a +--- + +# 《拼团交易平台系统》第2-20节:函数式数据缓存和降级到DB处理 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/6IYJ6](https://t.zsxq.com/6IYJ6) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +以查询活动配置为场景,增加缓存处理。同时使用降级服务,控制走缓存还是走DB数据库。并把这部分功能统一抽象成函数式编程。 + +## 二、功能流程 + +如图,缓存和降级的使用; + +
+ +
+ +- 首先,在日常的业务场景中,很多高频使用的数据,都是从 Redis 缓存获取。如果缓存不存在,才会从数据库读取。 +- 之后,也会给缓存配置降级,如果缓存有问题,或者要做一些验证,必须从库里读取,则会动态的配置,让当时的操作从数据库获取。 +- 注意,整个操作过程,缓存、降级、数据库,是一整条代码编程。如果在每个方法里都加这样的内容,就会显得很臃肿,所以一般会抽象一个方法,使用函数式的方式进行编程,降低使用者的编码量。**这个技巧很重要** \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-21\350\212\202\357\274\232\345\274\225\345\205\245\346\211\263\346\211\213\345\267\245\347\250\213.md" "b/docs/md/project/group-buy-market/\347\254\2542-21\350\212\202\357\274\232\345\274\225\345\205\245\346\211\263\346\211\213\345\267\245\347\250\213.md" new file mode 100644 index 000000000..0f6a2d062 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-21\350\212\202\357\274\232\345\274\225\345\205\245\346\211\263\346\211\213\345\267\245\347\250\213.md" @@ -0,0 +1,35 @@ +--- +title: 【更】第2-21节:引入扳手工程 +pay: https://t.zsxq.com/YXJjM +--- + +# 《拼团交易平台系统》第2-21节:引入扳手工程 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/lqZKr](https://t.zsxq.com/lqZKr) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +引入星球内的[《通用技术组件 - 🔧扳手工程》](https://t.zsxq.com/o7IBm)到拼团系统中,替代原本在拼团系统编写的设计模式框架和动态配置(DCC)服务。 + +那为什么要引入这一个扳手工程呢? + +其实你可以想象下,在互联网公司中,有非常多的业务系统。这些业务系统都需要,解决一些非业务场景的共性问题。如,通用的设计模式,共用的错误码,统一的动态配置中心等等。当你进入公司以后,会发现这样的场景非常多。 + +所以,你学习本节不只是完成功能,而是吸收了同类的这样场景的设计方案,以后遇到各类这样的问题,都可以考虑做成一个独立的技术组件,让业务系统引入使用。 + +> 建议,学习扳手工程(1-3节)后在开始下面的内容。这样会很清楚扳手工程的一个设计和实现手段。 + +## 二、功能流程 + +如图,替换拼团工程中的通用能力; + +
+ +
+ +- 首先,要在工程中引入扳手工程的清单pom配置。在本节课程之前,已经把扳手工程发布到 maven 中心仓库,可以直接使用。地址:[https://mvnrepository.com/artifact/cn.bugstack.wrench/xfg-wrench-bom/3.0.0](https://mvnrepository.com/artifact/cn.bugstack.wrench/xfg-wrench-bom/3.0.0) +- 之后,删掉 group-buy-market 工程 types 下;设计模式(design/framework)、dcc(annotations/DccValue + DCCValueBeanFactory)。删除后,工程 install 会报错。这个时候就引入 xfg-wrench 扳手工程内提供的框架和组件即可。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-22\350\212\202\357\274\232\345\212\250\346\200\201\351\231\220\346\265\201\351\205\215\347\275\256.md" "b/docs/md/project/group-buy-market/\347\254\2542-22\350\212\202\357\274\232\345\212\250\346\200\201\351\231\220\346\265\201\351\205\215\347\275\256.md" new file mode 100644 index 000000000..59d507dbd --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-22\350\212\202\357\274\232\345\212\250\346\200\201\351\231\220\346\265\201\351\205\215\347\275\256.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第2-22节:动态限流配置 +pay: https://t.zsxq.com/IQsZl +--- + +# 《拼团交易平台系统》第2-22节:动态限流配置 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/Iazmx](https://t.zsxq.com/Iazmx) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +通过在拼团项目系统中,引入的[《通用技术组件 - 🔧扳手工程》](https://t.zsxq.com/o7IBm),使用其带有的动态限流组件,在拼团系统中配置使用。让通过 DCC 动态控制是否限流,让接口支持动态限流配置。 + +本节的代码量不多,主要是因为我们已经在`扳手工程`中完成了动态限流的设计和开发,到拼团系统中直接使用即可。建议学习本节内容时,前置的学习下扳手工程。 + +## 二、功能流程 + +如图,在接口方法中配置动态限流能力; + +
+ +
+ +- 首先,如,动态配置中心,统一设计模式,限流组件,都是在扳手工程内的引入的 bom 清单中。当需要使用限流组件时,直接在项目对应的模块下,引入pom即可。 +- 之后,限流组件的动态控制,依赖的是动态配置中心。所以,在使用限流组件时,则需要顺序的引入下动态配置中心。这里还有另外一种做法,如 Spring AI 发布框架组件时候,提供3层关系结构。包括;功能件、自动装配件、整合 Starter 件。那么我们这里如果想让用户更简单的使用限流组件,而不需要关心是否要引入动态配置中心组件,则可以为限流组件,发布一个带有动态配置中心的pom文件的组件,这样用户就不需要单独引入了。 diff --git "a/docs/md/project/group-buy-market/\347\254\2542-23\350\212\202\357\274\232ELK+AI MCP\346\243\200\347\264\242.md" "b/docs/md/project/group-buy-market/\347\254\2542-23\350\212\202\357\274\232ELK+AI MCP\346\243\200\347\264\242.md" new file mode 100644 index 000000000..2c7f9c307 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-23\350\212\202\357\274\232ELK+AI MCP\346\243\200\347\264\242.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第2-23节:ELK + AI MCP 检索 +pay: https://t.zsxq.com/AV4Jp +--- + +# 《拼团交易平台系统》第2-23节:ELK + AI MCP 检索 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/6BHXt](https://t.zsxq.com/6BHXt) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +为拼团项目增加 ELK 分布式日志采集和查询系统,以及通过 AI MCP 的方式,检索系统运行日志和数据分析。 + +系统的运行日志,是排查系统问题的重要手段,尤其是分布式复杂系统,一次行为请求会执行多个接口查询。这些接口查询会被分布式系统承接,到不同的服务节点上执行。因此分布式日志就非常有用,可以串联出在哪个系统上执行的,并拿到全部日志进行分析。 + +## 二、框架介绍 + +Elastic Stack 技术栈,别是 `Elasticsearch`、`Logstash`、`Kibana` 组成,简称 ELK 是一套针对日志数据做解决方案的框架。它使您能够聚合来自所有系统和应用程序的日志,分析这些日志,并创建可视化来进行应用程序和基础设施监控、更快的故障排除、安全分析等。 + +- E = Elasticsearch:Elasticsearch 是在 Apache Lucene 上构建的分布式搜索和分析引擎。对各种语言、高性能和无架构 JSON 文档的支持使 Elasticsearch 成为各种日志分析和搜索使用案例的理想选择。 +- L = Logstash:Logstash 是一个开源数据摄取工具,允许您从各种来源收集数据,转换数据,并将数据发送到您希望的目标。通过预构建的筛选器和对 200 多种插件的支持,Logstash 使用户能够轻松摄取数据,无论数据源或类型如何。 +- K = Kibana:Kibana 是一种数据可视化和挖掘工具,可以用于日志和时间序列分析、应用程序监控和运营智能使用案例。它提供了强大且易用的功能,例如直方图、线形图、饼图、热图和内置的地理空间支持。此外,付费的 Kibana 还有 x-pack-jdbc 可以使用,让你就像使用 MyBatis 操作 MySQL 数据库一样操作 Elasticsearch 数据。 + +综上,3个组件的组合使用。由 Logstash 将摄取、转换数据并将其发送到 Elasticsearch 为摄取的数据编制索引,并且分析和搜索这些数据。最终 Kibana 会将分析结果可视化。也就是你可以在 Kibana 上实时看到系统的运行日志。 diff --git "a/docs/md/project/group-buy-market/\347\254\2542-24\350\212\202\357\274\232\347\263\273\347\273\237\347\233\221\346\216\247+AIMCP\345\210\206\346\236\220.md" "b/docs/md/project/group-buy-market/\347\254\2542-24\350\212\202\357\274\232\347\263\273\347\273\237\347\233\221\346\216\247+AIMCP\345\210\206\346\236\220.md" new file mode 100644 index 000000000..404513383 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-24\350\212\202\357\274\232\347\263\273\347\273\237\347\233\221\346\216\247+AIMCP\345\210\206\346\236\220.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第2-24节:系统监控 + AI MCP 分析 +pay: https://t.zsxq.com/Gz6PG +--- + +# 《拼团交易平台系统》第2-24节:系统监控 + AI MCP 分析 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/afbln](https://t.zsxq.com/afbln) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +为拼团系统配置`普罗米修斯`监控,并使用 AI MCP 工具,分析监控数据。通过这样的学习,让大家了解到企业里如何使用 AI 在软件工程方面的提效。 + +现在的互联网公司内,在每个大的业务部门,都陆续的开始搭建了 AI 团队。专门为本团队的业务系统做关于 AI 提效方面的开发。像是智能巡检、系统监控、代码开发、PRD文档评审、代码评审、智能客服等,都是 AI 方面的应用。 + +## 二、功能流程 + +如图,整个功能流程如下; + +
+ +
+ +- 首先,拼团应用系统,需要配置对应的监控暴漏端点,这样的目的是为了把数据暴漏出去。注意,对外使用要增加上验证权限,避免数据暴漏出去。 +- 之后,进入普罗米修斯和监控面板的配置文件,修改对应的配置,主要是IP、数据库文件等(课程下有说明),之后通过 Docker 启动,普罗米修斯 + 监控面板 + AI MCP 服务端,这样的目的是为了采集来自于系统的暴漏端点数据。 +- 最后,监控相关配置完成后,调用拼团系统接口,产生一些业务数据。之后通过 AI 客户端,配置 MCP 服务,这样就可以通过 AI 客户端分析系统监控情况了。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-25\350\212\202\357\274\232\351\200\206\345\220\221\346\265\201\347\250\213\345\234\272\346\231\257\345\210\206\346\236\220.md" "b/docs/md/project/group-buy-market/\347\254\2542-25\350\212\202\357\274\232\351\200\206\345\220\221\346\265\201\347\250\213\345\234\272\346\231\257\345\210\206\346\236\220.md" new file mode 100644 index 000000000..e94bea4e6 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-25\350\212\202\357\274\232\351\200\206\345\220\221\346\265\201\347\250\213\345\234\272\346\231\257\345\210\206\346\236\220.md" @@ -0,0 +1,32 @@ +--- +title: 【更】第2-25节:逆向流程场景分析 +pay: https://t.zsxq.com/Batrz +--- + +# 《拼团交易平台系统》第2-25节:逆向流程场景分析 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/afbln](https://t.zsxq.com/afbln) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +对于拼团这样的业务场景,有正向流程的下单,就有逆向流程退单。基本你在各类应用 APP 中,如;商城、外卖、出行、票务等,都是可以下单或者退单的。这也是一个互联网toc业务场景中,非常常见的流程。 + +所以,从这一节开始,我们将进入逆向流程的分析和后续的功能实现。先有这一节的场景分析,让小白伙伴知道这样一个流程,之后在详细设计和编码也会更加容易。 + +建议;学习这一节的时候,可以看看其他的应用类 APP 他们的退单流程都发生了什么动作,这些知识点以及不同的处理方式,都可以作为你学习后的对项目扩展实现的增强点。 + +## 二、功能流程 + +如图,以用户旅途视角来看整个拼团流程。 + +
+ +
+ +- 首先,我们来回顾下前面章节,完成的业务流程。从运营配置拼团活动,到用户从「小型支付商城(对接的一个场景)」,开始查看带有拼团优惠的上,进行试算,过滤规则。再到参与拼团,完成下单和一系列的流程处理。之后是拼团对于支付收单的入账计算,达成拼团目标后,回调(HTTP/MQ)商城服务,完成整个交易过程。 +- 那么,从本节开始,我们要考虑的是如何处理逆向流程,也就是退单的过程。退单分为当前过程中,拼团是否完成,未完成则根据是否支付了,取消锁单量和完成量。如果拼团已完成,则取消锁单量和完成量,拼团优惠释放后,则回调商城(refundGroupBuySuccess),完成退单退货服务。 +- 一般,对于已经完成拼团的,有用户退单是不会对其他用户已经完成交易的进行退单的,会造成很差的体验。这部分成本往往由商家和平台分摊,毕竟平台的目的是为了卖货。 diff --git "a/docs/md/project/group-buy-market/\347\254\2542-26\350\212\202\357\274\232\346\234\252\346\224\257\344\273\230\351\200\200\345\215\225\346\265\201\347\250\213.md" "b/docs/md/project/group-buy-market/\347\254\2542-26\350\212\202\357\274\232\346\234\252\346\224\257\344\273\230\351\200\200\345\215\225\346\265\201\347\250\213.md" new file mode 100644 index 000000000..6282b0fdd --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-26\350\212\202\357\274\232\346\234\252\346\224\257\344\273\230\351\200\200\345\215\225\346\265\201\347\250\213.md" @@ -0,0 +1,32 @@ +--- +title: 【更】第2-26节:未支付退单流程(枚举策略模式应用) +pay: https://t.zsxq.com/S9cnj +--- + +# 《拼团交易平台系统》第2-26节:未支付退单流程(枚举策略模式应用) + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/MVr1a](https://t.zsxq.com/MVr1a) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +退单,分为退掉拼团组队记录和外部对接的商城(也可以是其他平台)退单。当前我们在处理的流程为退掉拼团的组队记录,在这部分流程中,还包括;`未支付退单`、`已支付未成团退单`、`已支付已成团退单`。 + +本节我们先来串联`未支付退单`部分,搭建此部分的领域功能服务逻辑,以及编写出退单策略框架结构。整体的功能实现,后续还会引入责任链进行优化处理。可以先对照使用责任链和不使用时候的代码实现方式。 + +## 二、功能流程 + +如图,退单流程设计领域结构。 + +
+ +
+ +- 首先,在 trade 领域层,新增加一个逆向流程接口,之后在领域层增加退单策略。 +- 之后,退单策略分为三个实现类,`未支付退单`、`已支付未成团退单`、`已支付已成团退单`,本节先实现其中未支付退单。由未支付退单,一定是这个人参与了锁单,但拼团未完成。 +- 最后,在仓储层实现实现对数据库的事务操作。更新退单记录,更新拼团锁单量扣减。 +- 此外,本部分在后续章节还要迭代,使用设计模式的方式优化实现逻辑。因为整个退单的步骤也比较多,还包括了后需要发送 MQ 消息的过程。 + diff --git "a/docs/md/project/group-buy-market/\347\254\2542-27\350\212\202\357\274\232\345\267\262\346\224\257\344\273\230\346\234\252\346\210\220\345\233\242\351\200\200\345\215\225.md" "b/docs/md/project/group-buy-market/\347\254\2542-27\350\212\202\357\274\232\345\267\262\346\224\257\344\273\230\346\234\252\346\210\220\345\233\242\351\200\200\345\215\225.md" new file mode 100644 index 000000000..09c490f4a --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-27\350\212\202\357\274\232\345\267\262\346\224\257\344\273\230\346\234\252\346\210\220\345\233\242\351\200\200\345\215\225.md" @@ -0,0 +1,32 @@ +--- +title: 【更】第2-27节:已支付未成团退单 +pay: https://t.zsxq.com/Aw3qI +--- + +# 《拼团交易平台系统》第2-27节:已支付未成团退单 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/319Es](https://t.zsxq.com/319Es) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +继续迭代退单流程,处理已支付未成团退单。 + +而对于已支付未成团的退单,拼团退单完成后,需要驱动退款流程。也就是另外一个项目(小型支付)在用户发起退单后,需要先把优惠逆向处理掉,之后等待逆向完成进行支付退款。 + +那么,为什么不是项目(小型支付)调用完拼团,就直接退款呢。其实是做直接退款的,但有时候会出现一个临界的异常。如,调用拼团退掉优惠完成后,rpc/http 请求返回结果,可能因为网络超时,导致项目(小型支付)拿不到结果。这个时候,一种是可以重试,另外一种是可以等待MQ消息,驱动后续流程。而在大厂中,MQ消息驱动,是更为常见的使用方式。 + +## 二、功能流程 + +如图,退单流程设计领域结构。 + +
+ +
+ +- 首先,整体我们设计了3个退单策略,`未支付退单策略`、`已支付未成团退单策略`、`已支付已成团退单策略`。在这几个章节,会陆续的处理。 +- 之后,结合上一节的`未支付退单策略`,本节继续实现`已支付未成团退单策略`。不过这里有一个差异,需要写一个本地消息表,对于已支付的退单,要发送一个退单完成的MQ消息。其实后续`未支付退单策略`也要补充这个MQ,用于恢复参与拼团量。 +- 另外,因为这里也用到了,MQ 的发送和任务补偿。所以要把之前写到 trade 结算里的任务发送操作,抽取一个接口方法,进行共用。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-28\350\212\202\357\274\232\345\267\262\346\224\257\344\273\230\345\267\262\346\210\220\345\233\242\351\200\200\345\215\225.md" "b/docs/md/project/group-buy-market/\347\254\2542-28\350\212\202\357\274\232\345\267\262\346\224\257\344\273\230\345\267\262\346\210\220\345\233\242\351\200\200\345\215\225.md" new file mode 100644 index 000000000..d3ca3fc9d --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-28\350\212\202\357\274\232\345\267\262\346\224\257\344\273\230\345\267\262\346\210\220\345\233\242\351\200\200\345\215\225.md" @@ -0,0 +1,32 @@ +--- +title: 【更】第2-28节:已支付已成团退单 +pay: https://t.zsxq.com/msTia +--- + +# 《拼团交易平台系统》第2-28节:已支付已成团退单 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/PI7bY](https://t.zsxq.com/PI7bY) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +本章节是退单流程中最后一个步骤,对已支付,已成团状态的订单进行退单操作。 + +通过我们在前面的流程分析,已成团的退单,则只退个人单,不会影响到全局所有人的订单。那么这里如果一个拼团有多人退单,哪怕整个队伍只有一个人没有退单,也是可以的。 + +注意,这类的业务流程,主要受公司的产品设计的流程影响。如果一些特点的任务,一人退单,全队解散。那么就要针对不同类型的退单,做不同的策略实现。这块可以思考下。 + +## 二、功能流程 + +如图,退单流程设计领域结构。 + +
+ +
+ +- 如图,本节扩展实现第3个操作,`已支付已成团退单策略`的处理。 +- 注意,所有的退单策略,都要发MQ,本节把未支付未成团,也添加上MQ的发送。但要注意,添加MQ,他们都属于同一类,task 任务表要增加类型区分和 uuid 字段仿重。 + diff --git "a/docs/md/project/group-buy-market/\347\254\2542-29\350\212\202\357\274\232\351\200\200\345\215\225\351\224\201\345\215\225\351\207\217\346\201\242\345\244\215.md" "b/docs/md/project/group-buy-market/\347\254\2542-29\350\212\202\357\274\232\351\200\200\345\215\225\351\224\201\345\215\225\351\207\217\346\201\242\345\244\215.md" new file mode 100644 index 000000000..f7040d2e1 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-29\350\212\202\357\274\232\351\200\200\345\215\225\351\224\201\345\215\225\351\207\217\346\201\242\345\244\215.md" @@ -0,0 +1,28 @@ +--- +title: 【更】第2-29节:退单锁单量恢复 +pay: https://t.zsxq.com/4p5Vd +--- + +# 《拼团交易平台系统》第2-29节:退单锁单量恢复 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/o8Sz5](https://t.zsxq.com/o8Sz5) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +接收拼团组队退单消息,驱动锁单量redis库存恢复操作。这是一个数据库和缓存数据一致性的设计,在很多场景都非常实用。 + +## 二、功能流程 + +如图,退单恢复库存核心流程; + +
+ +
+ +- 首先,退单恢复库存最重要的就是数据一致性。数据库中已经变更完 lock 锁单记录了,之后就是更新 redis 缓存的量。 +- 那么,这里为了保证更新 redis 是一致性库存的,且成功的。所以需要添加一个分布式锁,来维护,确保不会被重复更新。 +- 所以,当加锁失败则表示重复恢复库存,如果incr 失败,则删掉分布式锁,抛异常,让 MQ 重试。这个概率很低,但也需要添加,以保证整体的可靠性。 diff --git "a/docs/md/project/group-buy-market/\347\254\2542-2\350\212\202\357\274\232\350\257\225\347\256\227\346\250\241\345\236\213\346\212\275\350\261\241\346\250\241\346\235\277\350\256\276\350\256\241.md" "b/docs/md/project/group-buy-market/\347\254\2542-2\350\212\202\357\274\232\350\257\225\347\256\227\346\250\241\345\236\213\346\212\275\350\261\241\346\250\241\346\235\277\350\256\276\350\256\241.md" new file mode 100644 index 000000000..c4d04df77 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-2\350\212\202\357\274\232\350\257\225\347\256\227\346\250\241\345\236\213\346\212\275\350\261\241\346\250\241\346\235\277\350\256\276\350\256\241.md" @@ -0,0 +1,37 @@ +--- +title: 【更】第2-2节:试算模型抽象模板设计 +pay: https://t.zsxq.com/uTLt9 +--- + +# 《拼团交易平台系统》第2-2节:试算模型抽象模板设计 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/fEB5s](https://t.zsxq.com/fEB5s) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +编程能力突飞猛进的成长,往往都来自于对复杂业务场景的拆分解耦和设计模式运用过程锻炼。虽然有时候是同样的业务,但不同的编程方式,带来的思维锻炼也是不同的。 + +就像 CRUD 的方式写代码,只能让你了解业务流程,但不会提高工程建模能力和编程思维的提升。所以整个小傅哥带着你做的项目,都会循序渐进的为你从模型设计解决业务场景问题出发。既可以提高你的编程思维,也能锻炼你的编码能力。 + +## 一、本章诉求 + +在一个工程中,随着不断地承接业务需求逻辑的实现,会有很多复杂场景需要解决。这个时候就会引入设计模式进行解耦和实现,提高工程代码的扩展性。 + +但随着开发的场景越来越多,在各个service实现中会存在相同的设计模式,如果是不同的人开发,那么一个责任链,一个规则树,也会有非常多的实现方式。那么这样就会导致后面在进入开发的人,对已存在的代码,维护的成本就越来越高了。 + +所以,本节小傅哥带着大家先做设计模式抽象模板的通用结构定义,添加一个 tree规则树抽象模型,在引入到工程中进行使用。这样后续工程中就可以不断的定义通用的设计模式被不同的场景统一使用了。 + +## 二、模型设计 + +这是一种链式的多分支规则树模型结构,由功能节点自行决定后续流程的执行链路。它的设计比责任链的扩展性更好,自由度也更高。 + +
+ +
+ +- 首先,定义抽象的通用的规则树模型结构。涵盖;StrategyMapper - 策略映射器、StrategyHandler - 策略处理器、`AbstractStrategyRouter` - 策略路由抽象类。通过泛型设计允许使用方可以自定义出入参和动态上下文,让抽象模板模型具有通用性。 +- 之后,由使用方自定义出工厂、功能抽象类和一个个流程流转的节点。这些节点可以自由组装进行流转,相比于责任链它的实现方式更具有灵活性。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-30\350\212\202\357\274\232\350\256\276\350\256\241\346\250\241\345\274\217\351\207\215\346\236\204\351\200\200\345\215\225.md" "b/docs/md/project/group-buy-market/\347\254\2542-30\350\212\202\357\274\232\350\256\276\350\256\241\346\250\241\345\274\217\351\207\215\346\236\204\351\200\200\345\215\225.md" new file mode 100644 index 000000000..fdf87674b --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-30\350\212\202\357\274\232\350\256\276\350\256\241\346\250\241\345\274\217\351\207\215\346\236\204\351\200\200\345\215\225.md" @@ -0,0 +1,31 @@ +--- +title: 【更】第2-30节:设计模式重构退单 +pay: https://t.zsxq.com/DJCKB +--- + +# 《拼团交易平台系统》第2-30节:设计模式重构退单 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/TsTt5](https://t.zsxq.com/TsTt5) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +通过设计模式重构现有退单流程。 + +在整个退单的功能实现的过程中,是没有过多引入设计模式的,更多的是以完成功能流程为主。那么本节我们则使用责任链、抽象类、工厂,来把目前的退单流程设计进行优化调整。 + +这样做的目的是为了让小白伙伴,具备了业务流程的理解和对应代码功能的开发基础上,在学习使用设计模式来优化流程代码,会更加得心应手! + +## 二、功能流程 + +如图,整个退单通过设计模式优化的结构; + +
+ +
+ +- 第一条退单链路,以工厂🏭方式获取执行责任链,责任链的作用是拆分原有的流程结构,分节点进行逐步处理。之后到退单的具体操作,则根据枚举策略,拿到对应执行的退单策略模式,完成退单动作。退单执行后发送MQ消息,驱动后续流程。 +- 第二条消息消息,从接收 MQ 开始,以 MQ 消息中的策略类型进行库存恢复操作。这部分保持原有的走对应的策略即可。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-31\350\212\202\357\274\232\351\200\200\350\256\242\346\216\245\345\217\243\345\222\214\345\256\232\346\227\266\344\273\273\345\212\241.md" "b/docs/md/project/group-buy-market/\347\254\2542-31\350\212\202\357\274\232\351\200\200\350\256\242\346\216\245\345\217\243\345\222\214\345\256\232\346\227\266\344\273\273\345\212\241.md" new file mode 100644 index 000000000..b0cae63ab --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-31\350\212\202\357\274\232\351\200\200\350\256\242\346\216\245\345\217\243\345\222\214\345\256\232\346\227\266\344\273\273\345\212\241.md" @@ -0,0 +1,29 @@ +--- +title: 【更】第2-31节:退订接口和定时任务 +pay: https://t.zsxq.com/S4pdB +--- + +# 《拼团交易平台系统》第2-31节:退订接口和定时任务 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/Ga9uG](https://t.zsxq.com/Ga9uG) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在触发器层实现调度逻辑,一个是退单的 HTTP 服务接口实现,另外一个是 Job 定时任务处理。 + +HTTP 退单接口为的是给外部系统(小型支付)调用使用,Job 任务则是定时检查是否有参与拼团锁单,但超时没有完成支付的进行拼团组队的,则进行自动退单处理。 + +## 二、功能流程 + +如图,退单触发条件流程图; + +
+ +
+ +- 退单的触发流程分为2类,一个是定时任务处理,自动扫描未完成订单,另外一个是提供接口,让外部调用方进行处理。 + diff --git "a/docs/md/project/group-buy-market/\347\254\2542-3\350\212\202\357\274\232\345\244\232\347\272\277\347\250\213\345\274\202\346\255\245\346\225\260\346\215\256\345\212\240\350\275\275.md" "b/docs/md/project/group-buy-market/\347\254\2542-3\350\212\202\357\274\232\345\244\232\347\272\277\347\250\213\345\274\202\346\255\245\346\225\260\346\215\256\345\212\240\350\275\275.md" new file mode 100644 index 000000000..f1ad7ec32 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-3\350\212\202\357\274\232\345\244\232\347\272\277\347\250\213\345\274\202\346\255\245\346\225\260\346\215\256\345\212\240\350\275\275.md" @@ -0,0 +1,36 @@ +--- +title: 【更】第2-3节:多线程异步数据加载 +pay: https://t.zsxq.com/yofwB +--- + +# 《拼团交易平台系统》第2-3节:多线程异步数据加载 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/UoiFa](https://t.zsxq.com/UoiFa) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在互联网公司中的业务功能开发,会非常重视接口的响应效率,一般整体的接口响应要控制在350毫秒,那么在每个细分领域的接口可能会被压缩到50~100毫秒。 + +这样的响应时间对于一些简单的接口到不会有什么影响,但如果是复杂较多的业务流程串联的接口,那么控制接口的响应时长就是一个非常大的挑战了。对于这样的情况,往往会引入异步线程加载数据的方式进行处理,之后在做统一的逻辑处理,这样就可以很好的降低接口响应时间。 + +## 一、本章诉求 + +扩展规则树模型结构,增加异步数据加载区。将用于试算营销优惠的接口使用异步线程进行加载,之后写入上下文,用于后续的逻辑处理。 + +这部分的模型设计是非常巧妙的,通过解耦逻辑和划分功能区,让代码具有了文档属性,看到对应的类和类下的方法区,就可以轻松的理解代码实现方式。这样的处理非常有利于后续功能的迭代。 + +## 二、模型链路 + +如图,为整个模型链路的执行过程图; + +
+ +
+ +- 首先,对通用设计模式树结构扩展出异步数据加载区,这样可以把接口实现中所需的数据前置到异步数据加载区完成加载操作。以此提高接口的响应效率。 +- 之后,本节串联功能节点,并在 MarketNode 节点,添加数据加载操作。 +- 另外,注意本节需要新增加一个表 sku,也就是商品信息表,通过商品信息表获得当前商品的价格配置,以此来做商品的折扣计算。这块在实际生产中有两种实现方式,一种是每次都调用外部接口获取商品,另外一种是有商品统一同步库可以查询。我们这里先通过一个统一的商品库进行处理。那么后续谁要对接这个系统,就调用sku商品库,同步好商品即可。【库表已更新到工程下】 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-4\350\212\202\357\274\232\347\255\226\347\225\245\346\250\241\345\274\217\344\274\230\346\203\240\346\212\230\346\211\243\350\256\241\347\256\227.md" "b/docs/md/project/group-buy-market/\347\254\2542-4\350\212\202\357\274\232\347\255\226\347\225\245\346\250\241\345\274\217\344\274\230\346\203\240\346\212\230\346\211\243\350\256\241\347\256\227.md" new file mode 100644 index 000000000..30ccb4654 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-4\350\212\202\357\274\232\347\255\226\347\225\245\346\250\241\345\274\217\344\274\230\346\203\240\346\212\230\346\211\243\350\256\241\347\256\227.md" @@ -0,0 +1,35 @@ +--- +title: 【更】第2-4节:策略模式优惠折扣计算 +pay: https://t.zsxq.com/NGF2u +--- + +# 《拼团交易平台系统》第2-4节:策略模式优惠折扣计算 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/inWxL](https://t.zsxq.com/inWxL) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +程序员的价值不在于只是完成业务需求,而是怎么架构系统、设计边界、凝练功能,让原本只是 CRUD 串联大量逻辑的代码,分区、分职责、用不同的策略模型承接。以此提高软件的交付质量,才是程序员的价值。 + +所以,我也从不敢说什么东西没有用。比如;DDD、设计模式,否则也不会有那么多我们日常使用源码框架,都有这些思想的体现了。 + +## 一、本章诉求 + +通过策略模式处理多类型折扣方式的逻辑计算,同时设定抽象模板,用于扩展后续人群标签的过滤。 + +不断的拆解功能逻辑边界的过程,比只是编写流水式代码要重要的多。在整个系统实现的过程中,要多体会这些思想。 + +## 二、模型设计 + +如图,继续在执行链路上像乐高积木一样拼装优惠折扣的计算逻辑; + +
+ +
+ +- 首先,MarketNode 节点的数据异步加载工作已经在上一节完成,这一节开始使用这里的数据做折扣计算。 +- 之后,折扣是在数据库中配置的,按照类型包括;ZJ - 直减、MJ - 满减、ZK - 折扣、N - n元购。那么这些不同的类型就可以用策略模型进行包装,每个实现类专门负责自己的逻辑计算。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-5\350\212\202\357\274\232\344\272\272\347\276\244\346\240\207\347\255\276\346\225\260\346\215\256\351\207\207\351\233\206.md" "b/docs/md/project/group-buy-market/\347\254\2542-5\350\212\202\357\274\232\344\272\272\347\276\244\346\240\207\347\255\276\346\225\260\346\215\256\351\207\207\351\233\206.md" new file mode 100644 index 000000000..22146d2c0 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-5\350\212\202\357\274\232\344\272\272\347\276\244\346\240\207\347\255\276\346\225\260\346\215\256\351\207\207\351\233\206.md" @@ -0,0 +1,41 @@ +--- +title: 【更】第2-5节:人群标签数据采集 +pay: https://t.zsxq.com/ovDqo +--- + +# 《拼团交易平台系统》第2-5节:人群标签数据采集 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/sWPg0](https://t.zsxq.com/sWPg0) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在抖音里经常可能会刷到一些视频,说:“你搜白酒,如果出来的都是茅台、五粮液”,那么证明你是有钱人! + +这个东西其实到不一定多准,但这里体现了一个技术上的东西叫做人群标签🏷,所有你的行为所产生的数据,都会被不同的标签类型统计。比如;年龄、性别、购物喜好、品类喜好、下单频次、浏览频次、搜索频次等。这些都会被归类为人群标签。 + +其实,还有一个。怎么感觉自己微信上聊天,过一会在京东、拼多多搜索,就出来了自己聊天时候的商品呢?这里一种是来自于输入法内容的获取,另外一个是广告联盟,这些商家的广告数据是互通的。你在一个地方搜索过,那么在进去到其他商城里就会展示出你搜索的数据。 + +所以,在互联网运营的手里中,你早已被圈定好该给你什么,才能刺激到你做什么。 + +## 一、本章诉求 + +以轻量化的方式构建人群标签数据,将人群数据写入到 Redis BitMap 用于后续使用。 + +在公司中,所有部门产生的业务数据都会回流到数仓,它有一个非常庞大的数据集市系统。之后这些数据会被量化分析师使用,通过 R 语言建模,执行模型任务,把符合模型所需的标签数据跑到一个新的指定表文件中,这些文件在通过加工存放到 Redis BitMap 进行使用。一般一个标签可能会有 50万、100万、500万的数据规模。 + +有了这些标签数据,运营人员就可以精准的对这些用户做定向活动投放,比如;特定的券、特定的通知等。以此达到更加精准的运营效果。 + +## 二、业务流程 + +虽然,我们不能像公司那样有那么大规模的数据量,但我们也可以仅使用拼团商品的数据,做人群标签的实现,让大家了解这样一个场景。 + +
+ +
+ +- 首先,人群标签是通过创建的采集任务所产生的数据。任务里包含了要采集业务中什么类型的数据规则。本项目中会采集拼团交易数据,不过本节还没有这类数据,所以先来模拟这部分数据。 +- 之后,把采集的数据除了放数据库,还需要写入到 Redis 的 BitMap 中,这个数据结构比较适合高并发场景判断用户是否存在。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-6\350\212\202\357\274\232\346\213\206\345\210\206\345\272\223\350\241\250\345\205\263\350\201\224\345\205\263\347\263\273.md" "b/docs/md/project/group-buy-market/\347\254\2542-6\350\212\202\357\274\232\346\213\206\345\210\206\345\272\223\350\241\250\345\205\263\350\201\224\345\205\263\347\263\273.md" new file mode 100644 index 000000000..1f48179c5 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-6\350\212\202\357\274\232\346\213\206\345\210\206\345\272\223\350\241\250\345\205\263\350\201\224\345\205\263\347\263\273.md" @@ -0,0 +1,44 @@ +--- +title: 【更】第2-6节:拆分库表关联关系 +pay: https://t.zsxq.com/SisVe +--- + +# 《拼团交易平台系统》第2-6节:拆分库表关联关系 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/MyFI0](https://t.zsxq.com/MyFI0) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +有伙伴问,看视频写项目,能跟着完成,也能运行出结果。但怎样才算是真正的掌握了这个项目的内容呢? + +多年的工作经验,要想掌握一个项目,只听分享、只看视频、只看文档,都是不行的,这些都只能让你了解但不是深入。只要上手写代码,一行行的完成需求逻辑,才能算是真正的掌握了这个项目。 + +所以,趁着项目不大,本节我们设定一个作业。我会给你讲解诉求和需要改动的功能点,你可以按照这样的流程来做编码和调试。完成后,在继续跟进课程学习,比对代码。当然如果你目前还处于小白阶段,也可以直接跟着课程学习。 + +## 一、本章诉求 + +在系统开始之初,简化功能设计,让拼团活动配置表直接耦合商品ID。也就是一个拼团活动,只关联一个商品ID。那么如果现在需要给10个商品,全配置一个相同的拼团活动,就没法配置了。总不能一个个全配置一遍。所以本节要对这块的内容做拆分解耦。 + +
+ +
+ +- group_buy_activity 拼团活动配置表中,融合了渠道和商品ID,属于和活动配置绑定了。 +- sku 商品信息,已经包含了渠道SC值和商品ID。而商品表咱们前面提到过,它是由接入方同步的商品信息,也可以不走这里,直接用 RPC/HTTP 接口查询数据,所以 sku 表不适合绑定互动ID。 +- 那么,就需要一个新的表来关联活动和商品信息配置,表名为 sc_sku_activity 必备字段;SC渠道、活动ID、商品ID。(自己创建库表后可以和课程的库表对比) +- 你可以根据这样的信息来创建你的库表,同时移除 group_buy_activity 表中 SC渠道值和商品ID。 + +## 二、业务流程 + +如图,整个改动流程的核心为让 MarketNode 节点的查询由原来方式改为先查询SC商品活动配置关联表,获得到活动ID,再查询活动信息。这期间如果有效的活动配置信息无,那么则走到 ErrorNode 节点,返回一个指定的错误码。 + +
+ +
+ +- 首先,你可以先通过如图的调用过程,理解本节要完成的编程动作。包括解耦后的新的库表关联关系。 +- 之后,编码的时候异步多线程查询商品关联配置,如果配置的信息为空,或者不存在有效的活动,那么可以返回一个 null。当拿到null 以后,可以做判断进行路由,走到 ErrorNode 节点。「这部分代码一定自己尝试下,多思考。」 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-7\350\212\202\357\274\232\344\272\272\347\276\244\346\240\207\347\255\276\350\212\202\347\202\271\350\277\207\346\273\244.md" "b/docs/md/project/group-buy-market/\347\254\2542-7\350\212\202\357\274\232\344\272\272\347\276\244\346\240\207\347\255\276\350\212\202\347\202\271\350\277\207\346\273\244.md" new file mode 100644 index 000000000..4f4da3c8f --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-7\350\212\202\357\274\232\344\272\272\347\276\244\346\240\207\347\255\276\350\212\202\347\202\271\350\277\207\346\273\244.md" @@ -0,0 +1,33 @@ +--- +title: 【更】第2-7节:人群标签节点过滤 +pay: https://t.zsxq.com/EL4gD +--- + +# 《拼团交易平台系统》第2-7节:人群标签节点过滤 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/E5VKd](https://t.zsxq.com/E5VKd) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +什么样的代码算好代码?做编程开发这么多年,我一直追求将代码简单化,让代码即是文档,看代码即可知道每一块功能的边界。因为一个功能开发出来,基本就要伴随着业务的发展一直持续下去。那么好的代码,就可以更好的维护,尤其是遇到问题的时候,可以快速定位。 + +## 一、本章诉求 + +在整个首页营销试算流程中,需要添加一个新的人群标签🏷节点 TagNode,来处理人群过滤的操作。 + +在本节你会看到目前的模型结构设计是非常容易添加出一个新的流程节点,同时对原有的功能不会有破坏性。这样既可以让我们更好的维护代码,也能方便持续的需求迭代。 + +## 二、业务流程 + +如图,增加 TagNode 节点,调整节点调用关系; + +
+ +
+ +- 首先,添加一个新的 TagNode 节点,调整营销 MarketNode 节点完成业务功能后,流转到新的 TagNode 节点。 +- 之后,在从个 TagNode 节点流转到 EndNode 结束节点。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-8\350\212\202\357\274\232\345\212\250\346\200\201\351\205\215\347\275\256\345\274\200\345\205\263\346\223\215\344\275\234.md" "b/docs/md/project/group-buy-market/\347\254\2542-8\350\212\202\357\274\232\345\212\250\346\200\201\351\205\215\347\275\256\345\274\200\345\205\263\346\223\215\344\275\234.md" new file mode 100644 index 000000000..e8dd4a7ab --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-8\350\212\202\357\274\232\345\212\250\346\200\201\351\205\215\347\275\256\345\274\200\345\205\263\346\223\215\344\275\234.md" @@ -0,0 +1,39 @@ +--- +title: 【更】第2-8节:动态配置开关操作 +pay: https://t.zsxq.com/wp9GE +--- + +# 《拼团交易平台系统》第2-8节:动态配置开关操作 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/yHvNc](https://t.zsxq.com/yHvNc) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在编程能力积累进阶的过程中,核心框架源码(Spring、MyBatis)的掌握是非常必要的过程之一。这些源码的组件学习后是可以帮助自身做业务功能逻辑的实现。 + +有些伙伴可能会觉得就做个业务开发,是不没有必要学习?🤔 其实不是的,对于源码这样的东西,往往是因为它并没有成为你熟悉的知识,所以也不会成为你设计的方案之一。当你熟练掌握后,会很巧妙的结合源码做自己的技术实现方案。 + +## 一、本章诉求 + +如何不停车就给汽车换个轮子? + +这是互联网应用程序中经常干的事情,在程序运行过程中,直接动态变更某些属性配置。这些动态变更的配置包括降级和切量的开关,也包括一些功能程序的白名单用户测试。 + +那么对于配置中心,有 SpringCloud Config + Event Bus,也有 Nacos,还有各个大厂中会基于各类组件做的自研实现。那么本节我们先来做一个基于 Redis 发布/订阅处理动态配置的自研的实现,之后对于 SpringCloud 的动态配置变更已经有案例,小伙伴也可以学习。 + +案例:[https://bugstack.cn/md/road-map/springcloud-bus.html](https://bugstack.cn/md/road-map/springcloud-bus.html) + +## 二、业务流程 + +如图,基于 Redis 实现一套动态配置中心 DCC 服务;Dynamic Config Control + +
+ +
+ +- 注意,本节会涉及到 Spring源码、Java 动态配置的一些编码操作,属于组件类开发是思想。如本节实现的功能也可以被独立出一个工程组件开发后被业务系统引入使用。 +- 方案,动态配置的处理可以使用 Zookeeper 的节点监听,也可以基于 Redis 的发布/订阅。本节咱们使用 Redis 这套方案,当你学习到后面的大营销项目,还会看到 Zookeeper 的实现方案。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2542-9\350\212\202\357\274\232\346\213\274\345\233\242\344\272\244\346\230\223\350\220\245\351\224\200\351\224\201\345\215\225.md" "b/docs/md/project/group-buy-market/\347\254\2542-9\350\212\202\357\274\232\346\213\274\345\233\242\344\272\244\346\230\223\350\220\245\351\224\200\351\224\201\345\215\225.md" new file mode 100644 index 000000000..23bc3e226 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2542-9\350\212\202\357\274\232\346\213\274\345\233\242\344\272\244\346\230\223\350\220\245\351\224\200\351\224\201\345\215\225.md" @@ -0,0 +1,36 @@ +--- +title: 【更】第2-9节:拼团交易营销锁单 +pay: https://t.zsxq.com/csVlH +--- + +# 《拼团交易平台系统》第2-9节:拼团交易营销锁单 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/csVlH](https://t.zsxq.com/csVlH) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在编程开发实现业务逻辑的过程中,头脑中可以有一个乐高积木的思想,考虑分拆逻辑聚合每一块业务。让这些业务具备良好的复用性。 + +尤其是复杂的下单过程,会有很多模块会被使用,所以这部分要想好你在整个下单过程中,会有哪些逻辑应该被聚合,怎么串联上下文。 + +## 一、本章诉求 + +当商城类系统接入拼团时,则需要在下单过程中使用一笔营销优惠。这里的营销优惠可以为;无券平台营销、有券消费营销、拼团折扣营销、积分抵扣营销等。 + +那么,当商城类系统接入使用下单时,则需要到拼团系统锁定一笔优惠,也就是占用一个名额。完事后,商城类系统继续操作支付交易的过程。 + +## 二、业务流程 + +如图,完善原有业务流程。 + +
+ +
+ +- 首先,团购的商品下单。下单过程分为创建流水单、锁定营销优惠(拼团、积分、券)、创建支付订单、唤起收银台支付、用户扫码支付、支付完成核销优惠等。 +- 那么,这里用户以拼团方式下单,创建流水单完成后,需要与拼团系统交互,锁定营销优惠。更新流水单优惠金额和支付金额。接下来就可以创建支付单了(支付单需要最终的支付金额)。 +- 注意,拼团表 group_buy_order 除了有目标量(target_count)、完成量(complete),还要有一个锁单量(lock_count),当锁单量达到目标量后,用户在此组织下,不能在参与拼团。直至这些用户支付完成达成拼团或者锁单超时回退支付营销,空出可参与锁单量,这样其他用户可以继续参与。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2543-1\350\212\202\357\274\232DeepSeek\350\256\276\350\256\241\346\213\274\345\233\242UI.md" "b/docs/md/project/group-buy-market/\347\254\2543-1\350\212\202\357\274\232DeepSeek\350\256\276\350\256\241\346\213\274\345\233\242UI.md" new file mode 100644 index 000000000..6b35c4ec2 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2543-1\350\212\202\357\274\232DeepSeek\350\256\276\350\256\241\346\213\274\345\233\242UI.md" @@ -0,0 +1,36 @@ +--- +title: 【更】第3-1节:DeepSeek设计拼团UI +pay: https://t.zsxq.com/TnhqL +--- + +# 《拼团交易平台系统》第3-1节:DeepSeek设计拼团UI + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/0ef6r](https://t.zsxq.com/0ef6r) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +国外比较擅长做创新,国内比较适合做应用。但好在这次在 OpenAI 的赛道上,横空出世了一个 DeepSeek,与过往的几个 OpenAI 产品相比,这次是可以和 ChatGPT 掰掰手腕了。 + +那 OpenAI 会抢了程序员的饭碗吗?🤔 首先,我认为是不会。就像 OpenAI 也会给你讲医学知识,那你敢自己开刀吗?OpenAI 也能讲法律知识,你能出去给人家当律师吗?甚至,在你没有某方面知识积累的时候,你也没法提出更专业的问题和完善类的资料。 + +其实都不能,OpenAI 的作用是让强的人更强,厉害的人更厉害。本身在哪一方面有积累,那么就能运用这些积累的知识借助 OpenAI 这个伙伴,把它做的更好。 + +## 一、本章诉求 + +结合 DeepSeek 等同类型 OpenAI 产品设计拼团 UI。 + +在我体验过的整个 OpenAI 产品中,以前 ChatGPT 4o 系列模型对代码的需求的理解是不错的,可以给还原出比较好的 UI 样式。不过这次在体验了 DeepSeek 后,它也可以还原出很不错的 UI 样式。 + +>本节要做一个简单对接的流程设计,关于商品下单支付这部分会模拟,暂时不走商城类系统。 + +## 二、UI 效果展示 + +按照本节的实现,最终你会得到一个这样的效果。 + +
+ +
\ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2543-2\350\212\202\357\274\232DeepSeek\345\244\204\347\220\206UI\344\270\216\346\216\245\345\217\243\345\257\271\346\216\245.md" "b/docs/md/project/group-buy-market/\347\254\2543-2\350\212\202\357\274\232DeepSeek\345\244\204\347\220\206UI\344\270\216\346\216\245\345\217\243\345\257\271\346\216\245.md" new file mode 100644 index 000000000..2180bc079 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2543-2\350\212\202\357\274\232DeepSeek\345\244\204\347\220\206UI\344\270\216\346\216\245\345\217\243\345\257\271\346\216\245.md" @@ -0,0 +1,35 @@ +--- +title: 【更】第3-2节:DeepSeek处理UI与接口对接 +pay: https://t.zsxq.com/LtzHY +--- + +# 《拼团交易平台系统》第3-2节:DeepSeek处理UI与接口对接 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/qKjOi](https://t.zsxq.com/qKjOi) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +OpenAI 适合什么场景的编程?我觉得前端算一个,为什么呢? + +前端相对于后端,没有数据库、缓存、RPC、MQ、任务调度等等一系列的复杂组件运用,而更多的工作都是在既定路线上的重复处理。所以,它的场景就更适合 OpenAI 一次的加载和理解,并给出正确性更高的编码实现,从而减轻开发人员的工作量。 + +在有这类的 OpenAI 产品后,我在开发前端代码上,确实更加得心应手了。 + +## 一、本章诉求 + +结合 DeepSeek 等同类型 OpenAI 产品,辅助完成 UI 与服务端接口的对接。 + +前端的 UI 已经明确,服务端的接口已经开发完成,他们中间没有什么额外的复杂逻辑了。只要告诉 OpenAI 调用接口,并明确出 UI 中位置的内容展示是来自于接口里的位置,那么就可以完成自动化的对接。 + +## 二、效果展示 + +
+ +
+ +- UI 与 服务端接口完整对接后,可以看到数据接口数据的使用,并渲染到前端页面。 +- 在没有用户参与拼团的时候,首次展示引导用户开启拼团。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2543-3\350\212\202\357\274\232\345\260\217\345\225\206\345\237\216\345\257\271\346\216\245\350\220\245\351\224\200\351\224\201\345\215\225.md" "b/docs/md/project/group-buy-market/\347\254\2543-3\350\212\202\357\274\232\345\260\217\345\225\206\345\237\216\345\257\271\346\216\245\350\220\245\351\224\200\351\224\201\345\215\225.md" new file mode 100644 index 000000000..9d8c71104 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2543-3\350\212\202\357\274\232\345\260\217\345\225\206\345\237\216\345\257\271\346\216\245\350\220\245\351\224\200\351\224\201\345\215\225.md" @@ -0,0 +1,41 @@ +--- +title: 【更】第3-3节:小商城对接营销锁单 +pay: https://t.zsxq.com/x2sHW +--- + +# 《拼团交易平台系统》第3-3节:小商城对接营销锁单 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/1QJTP](https://t.zsxq.com/1QJTP) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +从本章开始,我们会进入到2套系统的对接,陆续完成星球「码农会锁」里的`小型支付商城`与`拼团`在业务流程层面完成接口对接。 + +通过这样的学习,你可以积累到关于微服务间是如何通信和流程衔接的。在这公司里也是非常常见的设计和开发方式。 + +那么,本节我们先来完成商品下单过程中,营销锁单的接口对接。小型支付商城选择的是 `s-pay-mall-ddd` 工程,单独拿出一套命名为 `s-pay-mall-ddd-market` 方便大家学习。 + +**前置学习**;在开始这部分对接前,需要对星球的《小型支付商城系统》有所学习。课程地址:[https://t.zsxq.com/3X9GA](https://t.zsxq.com/3X9GA) + +## 二、业务流程 + +如图,两套微服务对接节点; + +
+ +
+ +- 左侧,小型支付商城,用户下单过程。增加一个营销锁单,从营销锁单中获取拼团营销拿到的优惠价格。之后小型商城继续往下走,创建支付订单。 +- 右侧,拼团交易平台,提供营销锁单流程,锁单目标、优惠试算,规则过滤,最终落库和返回结果(订单ID、原始价格、折扣金额、支付金额、订单状态)。 + +- 功能改造点; + + - 【拼团系统】lockMarketPayOrder 营销拼团锁单,增加返回字段值。原来只返回了优惠金额,为了方便使用方不需要自己在做计算,可以直接返回,原始价格、折扣金额、支付金额。这样的话,拼团就需要在 group_buy_order_list 表增加 pay_price,这样就更方便的拿到这个值了。 + - 【小型商城】基于 Retrofit2,在 infrastructure 基础设施层,封装对拼团接口的对接。`Call> lockMarketPayOrder(@Body LockMarketPayOrderRequestDTO requestDTO);` 并在 app 启动层的配置里,修改 `Retrofit2Config` 提供 `groupBuyMarketService` 服务。 + - 【小型商城】对 AliPayController#createPayOrder 创建订单服务的接口入参类,添加拼团队伍ID、活动ID、营销标识。如果前端前端没有拿到拼团活动信息则传递无营销。 + - 【小型商城】对 AbstractOrderService#createOrder 创建订单的过程中,通过 port 端口,添加 `port.lockMarketPayOrder(userId, teamId, activityId, productId, orderId);` 锁单。 + - 【小型商城】对于锁单返回的支付金额,为拼团交易订单金额。最终营销标识、优惠金额、支付金额,都会更新到 pay_order 表中,这个表要增加这样3个字段。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2543-4\350\212\202\357\274\232\345\260\217\345\225\206\345\237\216\345\257\271\346\216\245\350\220\245\351\224\200\347\273\223\347\256\227.md" "b/docs/md/project/group-buy-market/\347\254\2543-4\350\212\202\357\274\232\345\260\217\345\225\206\345\237\216\345\257\271\346\216\245\350\220\245\351\224\200\347\273\223\347\256\227.md" new file mode 100644 index 000000000..4ce6ccb7a --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2543-4\350\212\202\357\274\232\345\260\217\345\225\206\345\237\216\345\257\271\346\216\245\350\220\245\351\224\200\347\273\223\347\256\227.md" @@ -0,0 +1,37 @@ +--- +title: 【更】第3-4节:小商城对接营销结算 +pay: https://t.zsxq.com/rBemT +--- + +# 《拼团交易平台系统》第3-4节:小商城对接营销结算 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/0V186](https://t.zsxq.com/0V186) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +处理小型支付商城在用户完成支付后,调用拼团营销组队结算,并接收组队完成的回调消息执行后续交易结算发货。—— `这里一个是拼团结算,一个是交易结算` + +也就是说每一笔用户支付完成,拼团组队也就有一人推进了组队的进度,直至组队完成,即可回调交易系统进行通知组队完成,进行后续发货流程。 + +## 二、业务流程 + +如图,拼团交易结算流程; + +
+ +
+ +- 上半部分,是拼团交易过程,进行营销锁单。是咱们上一节实现的。 +- 下办部分,是拼团结算过程,进行营销结算。本节我们要做的新流程。 +- 功能改造点; + + - 基础设施层 infrastructure gateway 下的 IGroupBuyMarketService 增加营销拼团结算方法(顺便加入拼团中DTO对象)。 + - 修改 OrderService#changeOrderPaySuccess 方法,判断订单是否有营销,无营销的继续走老流程。有营销则通过 port 适配调用基础设施层拼团的结算方法。 + - 在 trigger 层,AliPayController 增加 groupBuyNotify 回调方法。并把地址配置到 application-dev.yml 中。这样拼团系统在接收小型商城的用户订单组队完成后,就可以接收回调方法了。 + - domain order 领域服务,增加 changeOrderMarketSettlement 修改订单状态方法,增加一个拼团结算的状态。之后发送MQ消息,这个时候就每一笔分别结算发货了。 + - domain 领域服务,增加 goods 商品领域,模拟发货和修改订单状态。这个方法交给,OrderPaySuccessListener 接收到结算消息后进行调用。 + - 注意;为了方便拼团测试,我们可以把拼团活动的组队人数修改为1个。 diff --git "a/docs/md/project/group-buy-market/\347\254\2543-5\350\212\202\357\274\232\345\260\217\345\225\206\345\237\216UI\344\270\216\346\216\245\345\217\243\345\257\271\346\216\245.md" "b/docs/md/project/group-buy-market/\347\254\2543-5\350\212\202\357\274\232\345\260\217\345\225\206\345\237\216UI\344\270\216\346\216\245\345\217\243\345\257\271\346\216\245.md" new file mode 100644 index 000000000..bab684655 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2543-5\350\212\202\357\274\232\345\260\217\345\225\206\345\237\216UI\344\270\216\346\216\245\345\217\243\345\257\271\346\216\245.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第3-5节:小商城UI与接口对接 +pay: https://t.zsxq.com/Jh698 +--- + +# 《拼团交易平台系统》第3-5节:小商城UI与接口对接 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/jPjFC](https://t.zsxq.com/jPjFC) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +基于 DeepSeek/OpenAI 等AI产品,把UI代码、接口代码,增加逻辑描述,一起喂给AI,来处理小型支付商城UI与接口的对接。 + +在前面章节我们开发了一款静态页面UI,直接和拼团后端对接。这回走正式的逻辑,下单将走到小型支付商城,由商城后端处理锁单和结算。之后和前端页面UI对接。 + +这是一次微服务的前后端全流程衔接,支付商城和拼团营销,就是2个微服务系统。学到这块,你即可以实践的方式理解微服务,而哪些RPC、MQ、xxl-job、分库分表等,则是为每个微服务提供分布式负载能力的技术。这些东西将在后续章节展开。 + +## 二、效果展示 + +
+ +
+ +- UI 与小型支付商城对接后,可以扫码登录,确认支付时走支付宝沙箱登录。 +- 这样就是一个完整的,商品营销下单支付,再到结算的流程了。 + diff --git "a/docs/md/project/group-buy-market/\347\254\2543-6\350\212\202\357\274\232\351\200\232\350\277\207\346\265\217\350\247\210\345\231\250\346\214\207\347\272\271\350\216\267\345\217\226\347\231\273\345\275\225ticket\346\227\240\347\227\225\347\231\273\345\275\225.md" "b/docs/md/project/group-buy-market/\347\254\2543-6\350\212\202\357\274\232\351\200\232\350\277\207\346\265\217\350\247\210\345\231\250\346\214\207\347\272\271\350\216\267\345\217\226\347\231\273\345\275\225ticket\346\227\240\347\227\225\347\231\273\345\275\225.md" new file mode 100644 index 000000000..f0ae657b7 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2543-6\350\212\202\357\274\232\351\200\232\350\277\207\346\265\217\350\247\210\345\231\250\346\214\207\347\272\271\350\216\267\345\217\226\347\231\273\345\275\225ticket\346\227\240\347\227\225\347\231\273\345\275\225.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第3-6节:通过浏览器指纹获取登录ticket + 无痕登录 +pay: https://t.zsxq.com/cGRlq +--- + +# 《拼团交易平台系统》第3-6节:通过浏览器指纹获取登录ticket + 无痕登录 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/8Oa5K](https://t.zsxq.com/8Oa5K) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +增强登录安全性,使用浏览器指纹,获取唯一 Ticket 作为登录二维码使用。 + +本章节属于知识点的扩展,即使没实现,也不影响整体功能。 + +## 二、业务流程 + +如图,增加浏览器指纹标识; + +
+ +
+ +- 原有的微信扫码登录拿到的是同一个 Tikcet,这样是满足测试,但对于上线给其他人一起使用是不太安全的。所以我们可以通过浏览器指纹的方式进行处理。 +- 浏览器指纹生成唯一标识,通过唯一标识获取ticket,并在轮训验证中使用浏览器指纹加验。确保浏览器指纹缓存的 ticket 和登录后的 ticket 保持一致。 + diff --git "a/docs/md/project/group-buy-market/\347\254\2543-7\350\212\202\357\274\232\347\224\250\346\210\267\350\256\242\345\215\225\345\210\227\350\241\250\345\222\214\351\200\200\345\215\225UI.md" "b/docs/md/project/group-buy-market/\347\254\2543-7\350\212\202\357\274\232\347\224\250\346\210\267\350\256\242\345\215\225\345\210\227\350\241\250\345\222\214\351\200\200\345\215\225UI.md" new file mode 100644 index 000000000..9c02ba5e7 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2543-7\350\212\202\357\274\232\347\224\250\346\210\267\350\256\242\345\215\225\345\210\227\350\241\250\345\222\214\351\200\200\345\215\225UI.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第3-7节:用户订单列表和退单UI +pay: https://t.zsxq.com/8D4SE +--- + +# 《拼团交易平台系统》第3-7节:用户订单列表和退单UI + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/Yng4V](https://t.zsxq.com/Yng4V) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +给现有的商品拼团下单页面,增加一个`我的订单列表页`,这样用户可以查询订单以及申请退单操作。 + +本节的操作主要是配和 UI 页面,增加对应的 CRUD 接口,为了后续对接拼团退单使用。难度不大。关于支付(支付宝沙箱)退单,已经有单测案例,可以参考。后续会使用。 + +## 二、业务流程 + +如图,查询订单列表和退单的流程; + +
+ +
+ +- 订单查询,查询个人订单记录。这样用户就可以知道下了多少订单了,类似于你京东、淘宝、拼多多查询的个人订单记录。 +- 退单流程,在每个订单上,可以点击退单操作。这部分主要为了后续对接拼团进行退单处理。 +- 整个本节的内容其实主要是 CURD 来配和 UI 的,难度不大。对于 UI 界面,可以使用 ai 工具进行设计。前端部分就是为了配和整个完整性的,面试中主要考察后端。所以,如果不太会写前端代码也不要太担心。 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2543-8\350\212\202\357\274\232\351\200\200\345\215\225\351\200\200\346\254\276\346\234\215\345\212\241\345\257\271\346\216\245.md" "b/docs/md/project/group-buy-market/\347\254\2543-8\350\212\202\357\274\232\351\200\200\345\215\225\351\200\200\346\254\276\346\234\215\345\212\241\345\257\271\346\216\245.md" new file mode 100644 index 000000000..9384cdda6 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2543-8\350\212\202\357\274\232\351\200\200\345\215\225\351\200\200\346\254\276\346\234\215\345\212\241\345\257\271\346\216\245.md" @@ -0,0 +1,32 @@ +--- +title: 【更】第3-8节:退单退款服务对接 +pay: https://t.zsxq.com/u7vu9 +--- + +# 《拼团交易平台系统》第3-8节:退单退款服务对接 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/ysPNN](https://t.zsxq.com/ysPNN) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +处理小型支付商城与拼团营销的接口和MQ消息对接,完成退单退款的业务实现。 + +整个过程会包括从小型支付发起退单申请,调用拼团解除组队锁单量/完成量。由拼团发送的MQ,被小型支付监听,发起退款操作。这部分有接口,也有 MQ 的异步处理,是一个综合的链路调度技术运用。这类设计方案,在互联网公司里的业务场景是非常常见的。 + +## 二、页面流程(UI) + +
+ +
+ +
+ +
+ +
+ +
\ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2544-1\350\212\202\357\274\232\347\254\2541\351\230\266\346\256\265\351\203\250\347\275\262\344\272\221\347\216\257\345\242\203.md" "b/docs/md/project/group-buy-market/\347\254\2544-1\350\212\202\357\274\232\347\254\2541\351\230\266\346\256\265\351\203\250\347\275\262\344\272\221\347\216\257\345\242\203.md" new file mode 100644 index 000000000..3f396bb50 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2544-1\350\212\202\357\274\232\347\254\2541\351\230\266\346\256\265\351\203\250\347\275\262\344\272\221\347\216\257\345\242\203.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第4-1节:第1阶段部署云环境 +pay: https://t.zsxq.com/cgBDM +--- + +# 《拼团交易平台系统》第4-1节:第1阶段部署云环境 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/izUPl](https://t.zsxq.com/izUPl) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +将项目上线部署到云服务器环境,提供公网IP地址,可以访问体验。 + +现阶段的很多面试,面试官在面试过程中都比较重视考察求职者对于项目学习的完整性,从设计、开发、测试、迭代,再到部署上线,一整套的内容,全都了解清楚是非常好的。 + +## 二、部署过程 + +如图,为本次的部署过程; + +
+ +
+ +- 首先,购买云服务器,之后搭建云环境。[http://618.gaga.plus/](http://618.gaga.plus/) 2c2g 很便宜,不过更推荐2c4g也不贵,避免以后部署其他的不够用了。 +- 之后,检出项目、构建镜像。以及部署操作。 +- 最后,要记得,开放使用的端口。这个过程会使用到 `9000`、`8091`、`8899` \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2544-2\350\212\202\357\274\232\347\254\2542\351\230\266\346\256\265\351\203\250\347\275\262\344\272\221\347\216\257\345\242\203.md" "b/docs/md/project/group-buy-market/\347\254\2544-2\350\212\202\357\274\232\347\254\2542\351\230\266\346\256\265\351\203\250\347\275\262\344\272\221\347\216\257\345\242\203.md" new file mode 100644 index 000000000..410b5cfe5 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2544-2\350\212\202\357\274\232\347\254\2542\351\230\266\346\256\265\351\203\250\347\275\262\344\272\221\347\216\257\345\242\203.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第4-2节:第2阶段部署云环境 +pay: https://t.zsxq.com/jzoIz +--- + +# 《拼团交易平台系统》第4-2节:第2阶段部署云环境 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/Mjr20](https://t.zsxq.com/Mjr20) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +将支付商城 + 拼团,Nginx 负载部署到云服务器,使用穿透映射提供的域名,进行访问体验。 + +这一阶段部署,就有微服务的体现了。要注意,微服务是微服务,分布式是分布式。不要混淆概念。两个技术方案可以一起使用,也可以单独使用。 + +## 二、部署过程 + +如图,为本次的部署过程; + +
+ +
+ +- 首先,购买云服务器,之后搭建云环境。[http://618.gaga.plus/](http://618.gaga.plus/) 需要2c4g部署,本节需要部署2个项目,并进行负载方式多实例部署。 +- 之后,检出项目、构建镜像。以及部署操作。 +- 最后,要记得,开放使用的端口。这个过程会使用到 `9000`、`8091`、`8092`、`8899`、`9091`等,需要开放的端口 \ No newline at end of file diff --git "a/docs/md/project/group-buy-market/\347\254\2544-3\350\212\202\357\274\232\347\254\2543\351\230\266\346\256\265\351\203\250\347\275\262\344\272\221\347\216\257\345\242\203.md" "b/docs/md/project/group-buy-market/\347\254\2544-3\350\212\202\357\274\232\347\254\2543\351\230\266\346\256\265\351\203\250\347\275\262\344\272\221\347\216\257\345\242\203.md" new file mode 100644 index 000000000..44b193b32 --- /dev/null +++ "b/docs/md/project/group-buy-market/\347\254\2544-3\350\212\202\357\274\232\347\254\2543\351\230\266\346\256\265\351\203\250\347\275\262\344\272\221\347\216\257\345\242\203.md" @@ -0,0 +1,30 @@ +--- +title: 【更】第4-3节:第3阶段部署云环境 +pay: https://t.zsxq.com/cycJ1 +--- + +# 《拼团交易平台系统》第4-3节:第3阶段部署云环境 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/kcqaK](https://t.zsxq.com/kcqaK) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +将支付商城 + 拼团系统,以 Nginx 负载的方式,在云服务器通过 Docker 方式进行部署。 + +部署包括;环境(mysql、redis、rabbitmq)、监控(prometheus、grafana)、分布式日志(elk)、应用(小型支付、拼团),natapp(内网穿透)、微信公众号、支付宝沙箱 + +## 二、部署过程 + +如图,为本次的部署过程; + +
+ +
+ +- 首先,购买云服务器,之后搭建云环境。[http://618.gaga.plus/](http://618.gaga.plus/) 最低2c4g部署(仅部署项目),2c8g全量部署,本节需要部署2个项目,并进行负载方式多实例部署。 +- 之后,检出项目、构建镜像。以及部署操作。 +- 最后,要记得,开放使用的端口。这个过程会使用到 `9000`、`8091`、`8092`、`8899`、`9091`、`4000`、`15672`等,需要开放的端口。 \ No newline at end of file diff --git a/docs/md/project/local-task-message/local-task-message.md b/docs/md/project/local-task-message/local-task-message.md new file mode 100644 index 000000000..5153f1068 --- /dev/null +++ b/docs/md/project/local-task-message/local-task-message.md @@ -0,0 +1,99 @@ +--- +title: 本地任务消息组件 +lock: no +--- + +# 《本地任务消息组件》- 为事务和消息推送(HTTP、MQ),提供最终一致性解决方案 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/WCWAb](https://t.zsxq.com/WCWAb) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +**你说气人不**,每每公司`晋升提报`和`加薪`的时候,总是那些手里有俏活的👬🏻兄弟。业务项目虽然是根基,但大家都做也就拉不开差距,而技术类组件、通用服务、功能平台,倒不是所有人都能搞的,这类结合业务场景的提取共性问题,凝练成通用解决方案的项目,可以开发一个就解决了全大部门的问题,所以做这类项目很亮眼! + +
+ +
+ +**这类项目也有门槛!** + +看着好像做个技术组件也没啥,但实际真想做的时候,你会发现你不知道什么服务可以被抽取为通用组件,不具备这样的经验和眼界。同时即使知道做啥了,也不知道如何结合像 Spring、MyBatis 源码能力,开发出一个通用的组件来,能让其他业务项目引入使用。 + +有人讲这东西不就是重复造轮子吗?🤔 还真不是,重复造轮子,指的市面上有的,或者公司里有个基础平台组有的。但这类的轮子往往不是深度结合业务的,而是那种无业务属性的功能逻辑的轮子,比如;rpc、xxl-job、mq 等。但一个业务组,他所需要的是解决通用业务场景问题的轮子,但这类东西又不属于基础平台研发组,所以往往都是业务组自己来解决这类场景问题。 + +所以,让自己具备开发组件的能力,是非常非常重要的,这即是抽象业务也是驾驭源码的能力体现。 + +小傅哥已经为大家提供了非常多的通用组件项目,如;`扳手工程(DCC动态配置中心、设计模式、动态限流、任务调度)`、`BCP 透视业务监控`、`动态线程池`、`支付SDK组件`、`SpringBoot Starter (16个合集)`、`IntelliJ IDEA Plugin 插件开发能力(具备这个的,开发了不少AI类组件)`。 + +这次小傅哥给大家再加一个新的组件《本地任务消息组件》,该组件解决业务场景远程调用HTTP或推送MQ消息,最终一致的问题。 + +## 一、能学到啥 + +- 【架构】掌握 DDD 分层与端口-适配器模式,清晰划分 domain/infrastructure/trigger/config 模块,提升可维护性与扩展性。 +- 【后端】学习注解+AOP 方式受理任务消息,结合事务边界进行统一处理,理解 `@LocalTaskMessage` 与切面配合的落地实践。 +- 【后端】掌握本地消息表设计与分片扫描策略(按门牌号 houseNumber 分片),实现高效拉取与顺序处理,提升系统可靠性。 +- 【后端】熟悉 Spring Event 事件驱动与异步消费,使用 `ApplicationEvent`+`@EventListener`+`@Async` 实现解耦通知链路。 +- 【后端】实践策略模式实现可插拔通知能力,支持 HTTP 与 RabbitMQ 两种通知通道,并在成功/失败时更新任务状态。 +- 【后端】熟练使用 OkHttp3 与 Retrofit2 统一封装 HTTP 网关,掌握动态 URL、Header、Body 的组合与异常处理。 +- 【后端】了解 RabbitMQ 事件发布的可选依赖注入方式,避免未配置 MQ 时的强依赖导致应用启动失败。 +- 【配置】掌握 `@ConfigurationProperties` 驱动的多任务组动态调度配置,支持 cron 与 fixedDelay 两种触发方式,并可配置批次大小 limit。 +- 【运维】学习 `ThreadPoolTaskScheduler` 的线程池化调度管理,合理设置线程名与池大小,提升任务调度的可观测性与稳定性。 +- 【数据】掌握原生 JDBC 访问与 DAO 封装,完成插入、状态更新、分片条件查询、最小游标查询等落地实现。 +- 【测试】通过示例命令对象 `TaskMessageEntityCommand` 的构建与调用,理解入参约定、枚举策略与配置对象的协作。 +- 【实践】提升异常、日志与枚举的综合使用能力,建立稳定的错误处理。 + +## 二、项目介绍 + +**《本地消息任务组件》** 项目,是以自定义注解 AOP 切入或编程的方式,动态化完成数据库表事务和消息推送(HTTP、MQ),达到最终一致性的目的。 + +>在没有这样的组件的时候,为了完成业务流程的同时,在发送一个MQ消息或则远程调用 HTTP 操作,都需要自己写一个本地消息表,之后还要维护消息表的扫描补偿。 + +操作方式如图; + +
+ +
+ +- 用户可以选择通过注解或者直接调用组件服务的方式进行使用。也就不用业务项目工程再维护关于本地消息表的写入和 MQ 或者 HTTP 的处理和补偿了。 +- 注解方式,会自动获取入参,入参需要为 TaskMessageEntityCommand 对象,它可以是某个入参的对象。之后配置 req.command 也可以获取。 + +## 三、产品方案 + +### 1. 产品概述 + +本地任务消息组件基于 Spring 框架能力,设计并实现了通用功能内核,便于集成到各类业务系统中。在业务系统中,组件支持在事务内完成数据写库的同时,写入一条本地消息记录(需在业务系统数据库中创建符合组件规范的本地消息表)。写入完成后,组件同步推送 Spring 事件,触发事务外的异步处理,如 MQ 消息发送或 HTTP 回调。即使异步处理失败,组件内置的本地消息表定时任务(支持自定义配置“门牌号”多任务并行扫描,提升扫描吞吐量)会持续检测并重试通知,确保消息最终一致性和业务流程的可靠执行。 + +### 2. 技术架构 + +
+ +
+ +- 首先,Local Task Message 任务消息组件,是以解决通用业务场景中的,本地数据库事务和外部MQ/HTTP调用一致性问题而设计实现的。让上游业务系统,不需要在每个流程中,都要做大量的重复编码。而是通过注解或者直接调用组件内核服务即可完成消息的通知操作。 +- 之后,Local Task Message 任务消息组件,并不是一个单纯的工具性功能,而是剩余一个领域服务内核,它具备完整的领域功能,具备操作数据库表的能力,以及接收 Spring Event 事件,对接 MQ、HTTP 完成和外部的交互处理。 +- 然后,上游系统在使用这套服务时,只需要配置好对应的本地消息表(一个事务下,连的同一个库),以及引入组件和完成yml配置,即可直接使用。 + +### 3. 功能流程 + +
+ +
+ +- 引入本地消息组件后,以用户开发dao入库操作为开始,可以通过注解或者调用组件服务 `ILocalTaskMessageHandleService` 驱动同一个事务下,进行消息推送。 +- 切面的方式,会更为优雅简洁,不需要用户自己在维护调用关系。 +- 整个操作会由组件自行处理写库操作,基于 Spring Event 的监听和通知,触发消息推送。完成 http、mq 的调用逻辑。同时还有基于门牌号扫描的逻辑,增强吞吐量。 + +## 四、课程目录 + +现课程已全部录制完成,接下来会日更📅项目💐; + +
+ +
+ +- 6节课程,全程视频手把手,带着你分析需求,编写代码。快速完成一个组件项目。 +- 课程代码,以互联网公司方式逐步拉分支开发,你可以学习到正规的编码操作。 diff --git "a/docs/md/project/local-task-message/\347\254\2541\350\212\202\357\274\232\347\273\204\344\273\266\351\234\200\346\261\202\345\210\206\346\236\220.md" "b/docs/md/project/local-task-message/\347\254\2541\350\212\202\357\274\232\347\273\204\344\273\266\351\234\200\346\261\202\345\210\206\346\236\220.md" new file mode 100644 index 000000000..9982faaf3 --- /dev/null +++ "b/docs/md/project/local-task-message/\347\254\2541\350\212\202\357\274\232\347\273\204\344\273\266\351\234\200\346\261\202\345\210\206\346\236\220.md" @@ -0,0 +1,31 @@ +--- +title: 第1节:组件需求分析 +pay: https://t.zsxq.com/Tscyn +--- + +# 《本地任务消息组件》- 第1节:组件需求分析 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
视频:[https://t.zsxq.com/7Dsu2](https://t.zsxq.com/7Dsu2) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +从今天开始,我们将进入一个新的组件项目学习。该组件聚焦于业务功能开发中的通用技术场景,提炼出一个技术解决方案,专门解决在完成数据库事务的同时,还需对外发送消息(MQ)或发起HTTP调用的最终一致性问题。 + +由于MQ消息发送和HTTP调用无法与数据库写操作在同一事务中完成,导致一致性难以保障。若没有统一的组件支持,各业务系统需各自实现这部分逻辑,造成重复开发且难以维护。为此,我们提取并开发了该技术组件,统一解决这一共性难题,提升系统的可靠性和开发效率。 + +## 二、功能案例 + +使用方通过引入本地消息组件,使用服务; + +
+ +
+ +- 用户可以选择通过注解或者直接调用组件服务的方式进行使用。 +- 注解方式,会自动获取入参,入参需要为 TaskMessageEntityCommand 对象,它可以是某个入参的对象。之后配置 req.command 也可以获取。 + +> 这个组件,解决的就是所有需要在完成业务流程时候,还要发送 MQ 或者 http 外部调用的场景。并提供本地消息表,确保最终一致性。 \ No newline at end of file diff --git "a/docs/md/project/local-task-message/\347\254\2542\350\212\202\357\274\232SpringEvent\344\272\213\344\273\266\346\266\210\346\201\257.md" "b/docs/md/project/local-task-message/\347\254\2542\350\212\202\357\274\232SpringEvent\344\272\213\344\273\266\346\266\210\346\201\257.md" new file mode 100644 index 000000000..d394c6592 --- /dev/null +++ "b/docs/md/project/local-task-message/\347\254\2542\350\212\202\357\274\232SpringEvent\344\272\213\344\273\266\346\266\210\346\201\257.md" @@ -0,0 +1,28 @@ +--- +title: 第2节:SpringEvent事件消息 +pay: https://t.zsxq.com/u9vRf +--- + +# 《本地任务消息组件》- 第2节:SpringEvent事件消息 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/ySbTf](https://t.zsxq.com/ySbTf) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +构建本地任务消息组件系统工程框架和对应的测试工程服务,并使用 Spring Event 事件消息,进行行为触达的通知和监听,用于后续处理外部 HTTP、MQ 的调用操作。 + +## 二、功能流程 + +如图,是本节关于 Spring Event 事件消息部分的流程。本节以这样一个简单功能诉求,引导工程创建。 + +
+ +
+ +- 首先,搭建一套基础的消息组件工程框架,提供受理任务消息的请求,进行 Spring Event 事件的发布和监听。让大家初步了解组件类框架的实现和简单案例的验证。 +- 之后,把本地消息组件构建成一个 jar,让测试工程通过 pom 的方式进行引入使用。 +- 注意,本组件是一个核心内核服务,会陆续的完善全部功能,使其具备;切面拦截、数据库操作、Spring Event 监听,Job 任务扫描等。所以类似的场景,以DDD工程架构,构建内核更为合适。内核有点类似于,一个业务项目中,从上到下一整套流程,被单独提取出来做成一个独立的小项目,之后引入到上游使用方的系统,就可以运行。扩展资料:[DDD 工程模型](https://bugstack.cn/md/road-map/ddd-guide-03.html) \ No newline at end of file diff --git "a/docs/md/project/local-task-message/\347\254\2543\350\212\202\357\274\232\344\273\273\345\212\241\350\241\250\350\256\276\350\256\241\345\222\214\346\225\260\346\215\256\345\206\231\345\205\245.md" "b/docs/md/project/local-task-message/\347\254\2543\350\212\202\357\274\232\344\273\273\345\212\241\350\241\250\350\256\276\350\256\241\345\222\214\346\225\260\346\215\256\345\206\231\345\205\245.md" new file mode 100644 index 000000000..10d53cd9d --- /dev/null +++ "b/docs/md/project/local-task-message/\347\254\2543\350\212\202\357\274\232\344\273\273\345\212\241\350\241\250\350\256\276\350\256\241\345\222\214\346\225\260\346\215\256\345\206\231\345\205\245.md" @@ -0,0 +1,28 @@ +--- +title: 第3节:任务表设计和数据写入 +pay: https://t.zsxq.com/CWzsg +--- + +# 《本地任务消息组件》- 第3节:任务表设计和数据写入 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/Pfekb](https://t.zsxq.com/Pfekb) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +设计通用的本地消息任务表和数据的插入处理。此表由引入技术组件的上游系统自行在数据库中配置。之后在调用组件的时候,就可以以同一个数据源对库表进行操作。 + +## 二、功能流程 + +如图,是本节关于写库操作的功能流程。 + +
+ +
+ +- 首先,为了可以在组件中完成数据库表的操作,则需要引入 DataSource 数据源,以便于在处理数据库操作的时候,可以以同一个数据库连接进行操作。 +- 之后,这里我们会直接使用 JDBC 的方式操作数据库,不会单独在引入 MyBatis 框架。这样做的目的是为了上游系统使用组件的时候,避免一些版本问题。最原始的方法,兼容性也是最好的。 +- 另外,本节还需要单独设计一下任务消息表。 \ No newline at end of file diff --git "a/docs/md/project/local-task-message/\347\254\2544\350\212\202\357\274\232\351\200\232\347\237\245\347\255\226\347\225\245\345\244\204\347\220\206.md" "b/docs/md/project/local-task-message/\347\254\2544\350\212\202\357\274\232\351\200\232\347\237\245\347\255\226\347\225\245\345\244\204\347\220\206.md" new file mode 100644 index 000000000..da612f4e3 --- /dev/null +++ "b/docs/md/project/local-task-message/\347\254\2544\350\212\202\357\274\232\351\200\232\347\237\245\347\255\226\347\225\245\345\244\204\347\220\206.md" @@ -0,0 +1,29 @@ +--- +title: 第4节:通知策略处理(HTTP&MQ) +pay: https://t.zsxq.com/AjdgW +--- + +# 《本地任务消息组件》- 第4节:通知策略处理(HTTP&MQ) + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/9FgAG](https://t.zsxq.com/9FgAG) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +增加 HTTP、MQ(RabbitMQ)服务,在接收 Spring Event 监听后,以通知行为策略的方式,完成 HTTP 远程调用和 MQ 消息推送。 + +## 二、功能流程 + +如图,是本节关于事件消息回调通知的处理流程(暂时先不处理关于数据库的更新流程); + +
+ +
+ +- 首先,事件消息的监听在 trigger 层的监听,之后调用领域层的通知服务方法。这里需要新增加一个领域方法。 +- 之后,领域服务方法,要以 notifyType 不同类型进行通知操作。如;http、mq,这部分你将来想扩展其他的,就在这里添加。 +- 最后,http 和 mq,都会进入基础设施层完成服务的调用处理。http 使用的是 retrofit2 框架进行封装。mq(RabbitMQ)直接使用 RabbitTemplate 模板 push 消息即可。 + diff --git "a/docs/md/project/local-task-message/\347\254\2545\350\212\202\357\274\232\345\212\250\346\200\201\344\273\273\345\212\241\350\241\245\345\201\277\345\244\204\347\220\206.md" "b/docs/md/project/local-task-message/\347\254\2545\350\212\202\357\274\232\345\212\250\346\200\201\344\273\273\345\212\241\350\241\245\345\201\277\345\244\204\347\220\206.md" new file mode 100644 index 000000000..ec0131d6a --- /dev/null +++ "b/docs/md/project/local-task-message/\347\254\2545\350\212\202\357\274\232\345\212\250\346\200\201\344\273\273\345\212\241\350\241\245\345\201\277\345\244\204\347\220\206.md" @@ -0,0 +1,29 @@ +--- +title: 第5节:动态任务补偿处理 +pay: https://t.zsxq.com/cyeBu +--- + +# 《本地任务消息组件》- 第5节:动态任务补偿处理 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/9gZ6T](https://t.zsxq.com/9gZ6T) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +在 Spring Event 接收到事件消息后,无论是 MQ 的发送,还是 HTTP 的调用,都是有可能失败的。可能是网络超时,可能是服务宕机,可能是线程阻塞,可能是流量洪峰等等原因。 + +所以,我们需要对完成 MQ、HTTP 的处理后,首先更新数据库任务表状态,是成功还是失败。之后再由定时扫描任务来做补偿处理,以确保最终一致性。 + +## 二、功能流程 + +如图,定时扫描任务流程图,以及在 http、mq 通知完成后,也要调用 dao 做变更状态操作; + +
+ +
+ +- 首先,任务补偿,它是一个定时任务扫描库表的过程。这里为了提高整体的扫描效率,设计了门牌号,可以配置多个任务,每个任务扫描自己的门牌号范围。另外扫描库表,还要根据条件获取一个最小的符合的id,之后在 `> id limit x` 获取数据列表。 +- 然后,还要对之前的流程做一些补充。http 调用操作、MQ 推送操作,之后要做数据库表任务记录的更新,成功或者失败。这里看,从 Spring Event 接收到消息后,执行通知操作(http、mq),之后更新数据库。这些都不是一个事务的,也就是说从事务(业务数据+任务表数据写入)往后,都是有可能失败的。所以要做任务补偿操作,那么这里也带来一个问题,补偿就有可能重复,比如 http 重复调用一次,mq 重复发送一次,所以在对这些业务长交给你对接的时候,一定要做幂等操作(比如 OrderId 做唯一索引处理)。 \ No newline at end of file diff --git "a/docs/md/project/local-task-message/\347\254\2546\350\212\202\357\274\232\345\210\207\351\235\242\346\213\246\346\210\252\344\273\273\345\212\241\346\223\215\344\275\234.md" "b/docs/md/project/local-task-message/\347\254\2546\350\212\202\357\274\232\345\210\207\351\235\242\346\213\246\346\210\252\344\273\273\345\212\241\346\223\215\344\275\234.md" new file mode 100644 index 000000000..316f5b0f6 --- /dev/null +++ "b/docs/md/project/local-task-message/\347\254\2546\350\212\202\357\274\232\345\210\207\351\235\242\346\213\246\346\210\252\344\273\273\345\212\241\346\223\215\344\275\234.md" @@ -0,0 +1,29 @@ +--- +title: 第6节:切面拦截任务操作 +pay: https://t.zsxq.com/wcAAq +--- + +# 《本地任务消息组件》- 第6节:切面拦截任务操作 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/RVhlT](https://t.zsxq.com/RVhlT) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +因为我们做的是一个通用组件项目,对于它的使用应该要提供出更简单轻量的方式,让使用方可以轻量化的接入。所以对于 `handleService.acceptTaskMessage(taskMessageEntityCommand)` 编码的方式,可以提供更为优化的处理手段。 + +这里我们选择增加一个本地任务消息的自定义注解,对于配置了此注解的方法进行拦截,并获取入参信息的 taskMessageEntityCommand 对象。之后,开始进行同一个事务或开启新的事物的方式,完成数据的插入操作,并进行 Spring Event 消息推送。这样可以让用户的使用更加简洁。 + +## 二、功能流程 + +如图,通过自定义注解加切面拦截方式,完成本地消息的受理。 + +
+ +
+ +- 首先,我们要添加一个自定义注解,并在 config 配置下编写切面的逻辑,这个逻辑主要是获取出配置自定义注解的方法的入参,从里面拿到任务消息对象。 +- 之后,要判断当前当前是否有事务操作,如果没有则开启一个新的事物,如果有则使用同一个事务,完成数据库表数据的插入。之后在推送 SpringEvent 事件消息。和面的流程就一致了。 \ No newline at end of file diff --git a/docs/md/project/lucky-tackout/lucky-tackout.md b/docs/md/project/lucky-tackout/lucky-tackout.md new file mode 100755 index 000000000..5c61f9429 --- /dev/null +++ b/docs/md/project/lucky-tackout/lucky-tackout.md @@ -0,0 +1,157 @@ +--- +title: 吉祥外卖系统 PLUS 版 +lock: no +--- + +# 吉祥外卖系统 PLUS 版 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
项目:[https://t.zsxq.com/g57ja](https://t.zsxq.com/g57ja) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +**是的,我干了一套吉祥外卖系统 PLUS 版本!** + +临近秋招,小傅哥又开始为非常多的小伙伴提供简历评审服务。在这个过程中,发现不少伙伴的简历都有一款**外卖系统**,但在项目描述上,大家把简历写的更像是八股文,缺少了很多核心流程描述。 + +
+ +
+ +这样写简历,其实就等同于没做项目,投递出去肯定是非常吃亏的。即使靠着学历进入到面试阶段,在后续的2、3轮面试中,也非常有风险被其他同届伙伴刷下去。而好的项目,除了有这样的`热点场景`,也要有非常细腻的核心流程。让面试官一看简历,就有非常大的兴趣对你进行提问。 + +不过,都这个时候了,也马上要进入面试了。对于一些非常忙的伙伴,来不及换项目时候。所以,小傅哥这段时间,赶出了一套”**吉祥外卖**“,提供相关的;设计图稿、系统设计、课程资料、章节课程、简历模板、工程代码(可运行展示)等,方便小伙伴结合已经有的外卖项目基础,扩展学习刷课程即可。 + +接下来,小傅哥就介绍下这套项目,方便小伙伴们了解下,运行效果是什么样,都包括哪些东西。 + +> 💐 文末提供了课程的全套源码和资料,以及还有额外的17个实战项目,全程视频手把手做,增强小伙伴们的综合能力。 + +## 一、运行效果 + +该项目是一个基于真实业务场景的**快餐外卖生态系统** ,以互联网ToC场景的核心业务流程为背景,采用分布式架构设计 + 领域驱动建模,完成项目场景功能实现。项目涵盖用户端、商家端、配送端、运营端四大业务场景,构建完整的外卖生态闭环。 + +### 1. 用户端 + +#### 1.1 登录进首页 + +
+ +
+ +#### 1.2 下单到结算 + +
+ +
+ +#### 1.3 支付和我的 + +
+ +
+ +### 2. 配送端 + +
+ +
+ +### 3. 商家端 + +
+ +
+ +### 4. 运营端 + +
+ +
+ +以上UI,用户端完整对接了后端接口。配送端、商家端、运营端,后端接口已提供,后续可对接。 + +综上,是一个完整的从`登录`,`选品`、`下单`、`结算`、`支付`的全流程,非常全面的展示出系统功能。所有的操作都有后台的接口调用和数据库表输入的录入,在这个过程你可以完整的理解到关于外卖系统的全核心流程。那么有这样一套东西,你就可以在学习后,完善自己的简历了。 + +**程序员**,还是要看到可演示运行的东西 + 项目的代码,才好编写自己的简历。 + +## 二、项目信息 + +接下来,小傅哥带着大家在看看关于这套项目所能给大家提供的工程代码和资料。 + +### 1. 工程结构 + +
+ +
+ +- 工程:[https://gitcode.net/KnowledgePlanet/lucky-tackout](https://gitcode.net/KnowledgePlanet/lucky-tackout) - `文末加入小傅哥社群,即可获得全部代码,以及其他17个实战项目` +- 说明:工程提供了前后端代码,设计资料,文档资料等。主要适合于速刷系统,补充简历的伙伴使用。如果需要手把手教程类的项目,可以做小傅哥社群里其他17个实战项目。 +- 另外:本套项目主要为了方便伙伴快速刷来对应面试的,小傅哥也是快速出的,暂时没有相关的视频类资料。后续会录制一些视频讲解。 + +### 2. 功能领域 + +
+ +
+ +- 如图,功能领域涵盖;用户端、商家端、配送端、平台运营,之后这些模块使用核心服务层提供的能力。 +- 注意,关于页面,小傅哥提供了用户端的UI,后续在补充其他端的页面UI。 + +### 3. 领域模型 + +
+ +
+ +- 基于我们所需要的功能场景,进行了领域建模。分为;用户领域、订单领域、商家领域、配送领域、支付领域、产品领域。 +- 这些内容可以体现到简历上,也就有非常细腻的流程可以讲出来了。 + +### 4. 库表设计 + +
+ +
+ +
+ +
+ +- 本套项目设计了非常全面的库表,你可以理解到整体外卖的全部核心体系。 + +## 三、启动说明 + +### 1. 环境说明 + +- JDK 1.8 +- Maven 3.8.x +- MySql 8.x +- SpringBoot 2.7.12 + +### 2. 导入库表 + +在工程路径 `docs/dev-ops/mysql/sql/fast_food_delivery.sql` 提供了库表脚本,要导入到本地数据库中。 + +### 3. 配置链接 + +```java +spring: + datasource: + username: root + password: 12345678 + url: jdbc:mysql://127.0.0.1:3306/fast_food_delivery?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true + driver-class-name: com.mysql.cj.jdbc.Driver +``` + +- 在工程的 yml 文件,配置你的数据库表信息。 + +### 4. 启动项目 + +
+ +
+ +- 配置好相关信息后,启动项目,之后进入到 `nginx/html/h5-food-delivery` 打开 html 页面即可。 + diff --git "a/docs/md/project/s-pay-mall/part-2/\347\254\2542\350\212\202\357\274\232\346\224\257\344\273\230\345\225\206\345\237\216\345\233\233\350\211\262\345\273\272\346\250\241\350\256\276\350\256\241.md" "b/docs/md/project/s-pay-mall/part-2/\347\254\2542\350\212\202\357\274\232\346\224\257\344\273\230\345\225\206\345\237\216\345\233\233\350\211\262\345\273\272\346\250\241\350\256\276\350\256\241.md" index ce6c21817..0bf0dffa8 100644 --- "a/docs/md/project/s-pay-mall/part-2/\347\254\2542\350\212\202\357\274\232\346\224\257\344\273\230\345\225\206\345\237\216\345\233\233\350\211\262\345\273\272\346\250\241\350\256\276\350\256\241.md" +++ "b/docs/md/project/s-pay-mall/part-2/\347\254\2542\350\212\202\357\274\232\346\224\257\344\273\230\345\225\206\345\237\216\345\233\233\350\211\262\345\273\272\346\250\241\350\256\276\350\256\241.md" @@ -1,15 +1,31 @@ --- -title: 第2节:支付商城四色建模设计 -lock: no +title: 第2-2节:工程四色建模设计 +pay: https://t.zsxq.com/XeucE --- -# 第2节:支付商城四色建模设计 +# 《小型支付商城系统》第2-2节:工程四色建模设计 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +在公司中实际做项目,会先有产品拉一个评审会,对本地需求的 PRD 进行评审。这个过程会有产品、研发(前后端)、测试,一起参与评审。一般在 `30分钟 ~ 2小时`的会议。评审完成后,研发会对需求进行分工,较大型的项目,会有几个研发同时介入。之后每个研发进行设计阶段,设计会包括新项目的工程框架、技术栈选择、需求的模型设计(DDD)、功能的流程(MVC)实现、要实现和改动点说明等。 + +本节我们就按照这样的一个过程进行需求的研发设计,主要包括;用户用例图、四色建模(领域拆分)、UML流程图、改动点。有这些东西就可以指导研发开发了。 + +本项目会搭建 MVC、DDD 双套工程,四色建模主要给 DDD 工程使用。 + +## 二、画用例图 + +研发可以根据产品PRD提供的业务UI和流程,分析出用户会有的行为,根据行为画出用户用例图; + +
+ +
+ +- 用例图(英语:use case diagram)是用户与系统交互的最简表示形式,展现了用户和与他相关的用例之间的关系。通过用例图,人们可以获知系统不同种类的用户和用例。用例图也经常和其他图表配合使用。 +- 用例图,也可以等同于是用户故事(英语:User story)(软件开发和项目管理中的常用术语),主旨是以日常语言或商务用语撰写句子,是一段简单的功能表述。以客户或使用者的观点撰写下有价值的功能、引导、框架来与使用者进行互动,进而推动工作进程。可以被认为是一种规格文件,但更精确而言,它代表客户的需求与方向。以该用户故事来反应对象在组织内的其工作职责、范围、需要进行的任务等。用户故事在敏捷开发方法中用来定义系统需要提供的功能和实现需求管理。 +- 尽管用例本身会涉及大量细节和各种可能性,用例图却能提纲挈领地让人了解系统概况。它为“系统做什么”提供了简化了的图形表示,因此被誉为“搭建系统的蓝图”。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-2/\347\254\2543\350\212\202\357\274\232\346\224\257\344\273\230\350\256\242\345\215\225\345\234\272\346\231\257\350\241\250\350\256\276\350\256\241.md" "b/docs/md/project/s-pay-mall/part-2/\347\254\2543\350\212\202\357\274\232\346\224\257\344\273\230\350\256\242\345\215\225\345\234\272\346\231\257\350\241\250\350\256\276\350\256\241.md" index cebcd2c93..4877256ed 100644 --- "a/docs/md/project/s-pay-mall/part-2/\347\254\2543\350\212\202\357\274\232\346\224\257\344\273\230\350\256\242\345\215\225\345\234\272\346\231\257\350\241\250\350\256\276\350\256\241.md" +++ "b/docs/md/project/s-pay-mall/part-2/\347\254\2543\350\212\202\357\274\232\346\224\257\344\273\230\350\256\242\345\215\225\345\234\272\346\231\257\350\241\250\350\256\276\350\256\241.md" @@ -1,15 +1,25 @@ --- -title: 第3节:支付订单场景表设计 -lock: no +title: 第2-3节:支付订单场景表设计 +pay: https://t.zsxq.com/MUIJB --- -# 第3节:支付订单场景表设计 +# 《小型支付商城系统》第2-3节:支付订单场景表设计 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +讲解库表设计规范,包括;建表、字段、索引,在中大厂开发中也是非常重视这些规范的。之后我们结合上一节的研发设计所需开发的流程,设计对应的库表。 + +## 二、设计规范 + +为了能让读者更加清晰地看到这些相关规范都是如何体现的,小傅哥这里准备了个大图,把库表字段和规范全部整合在一起,方便学习使用。如下; + +
+ +
+ +如上所列规范包括:建表相关规范、字段相关规范、索引相关规范、使用相关规范。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2541\350\212\202\357\274\232DDD \345\267\245\347\250\213\346\241\206\346\236\266\346\220\255\345\273\272.md" "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2541\350\212\202\357\274\232DDD \345\267\245\347\250\213\346\241\206\346\236\266\346\220\255\345\273\272.md" index 61cfe9ace..1236bb43d 100644 --- "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2541\350\212\202\357\274\232DDD \345\267\245\347\250\213\346\241\206\346\236\266\346\220\255\345\273\272.md" +++ "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2541\350\212\202\357\274\232DDD \345\267\245\347\250\213\346\241\206\346\236\266\346\220\255\345\273\272.md" @@ -1,15 +1,43 @@ --- -title: 第1节:DDD 工程框架搭建 -lock: no +title: 第3-1节:DDD 工程框架搭建 + 基础配置 + Git 使用 +pay: https://t.zsxq.com/bjFkO --- -# 第1节:DDD 工程框架搭建 +# 《小型支付商城系统》第3-1节:DDD 工程框架搭建 + 基础配置 + Git 使用 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +手把手的,分别通过手动创建和脚手架创建 DDD 工程结构。以及完成基础配置和 Git 使用。 + +从本节进入 DDD 部分的学习开始,会对照 MVC 进行差异化的对比讲解。可能有时候文字没法直接关的表达两个工程的使用差异,可以先看视频在看文档和代码,这样会更好的理解 MVC 到 DDD 的工程设计实现。 + +首先 DDD 是一种软件设计方法,它的规范标准和思想指导着软件设计实现,而为了更好的承接这样一套思想,有了新的架构结构。也就是我们常提到的;整洁架构、洋葱架构、六边形架构、菱形架构,这些架构的设计,合理的划分出了不同的分层结构,用于承接各项组件、服务、功能领域。在我们做这部分 DDD 实现时,会不断的体现出这些内容。 + +## 二、环境配置 + +- Jdk 1.8 +- Maven 3.x - [Maven 教程](https://bugstack.cn/md/road-map/maven.html) +- IntellJ IDEA 社区版(免费) [IntelliJ IDEA 教程](https://bugstack.cn/md/road-map/intellij-idea.html) 推荐`2023`及以上版本,使用起来更方便。 +- Git - 安装后会配置到 IntellJ IDEA 这样才能向服务端推送或者拉取代码。[Git 教程 ](https://t.zsxq.com/19Rnk98M0) 学习后可以知道怎么拉取、提交和比对代码。 +- 在线版脚手架:[https://bugstack.cn/md/road-map/ddd-archetype-maven.html](https://bugstack.cn/md/road-map/ddd-archetype-maven.html) - 直接配置使用即可。 + +--- + +```xml + + + alimavenrepository + aliyun maven repository + http://maven.aliyun.com/nexus/content/groups/public/ + central + + +``` + +- 如果你的 Maven 拉取 Jar 包速度很慢,可以在 Maven 的 conf 下 settings.xml 添加阿里云镜像。 +- [https://t.zsxq.com/19Rnk98M0](https://t.zsxq.com/19Rnk98M0) 已提供配置好了 阿里云 Maven 镜像的 Maven 压缩包。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2542\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\351\211\264\346\235\203.md" "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2542\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\351\211\264\346\235\203.md" index e111a1a16..ab2d7f9a3 100644 --- "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2542\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\351\211\264\346\235\203.md" +++ "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2542\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\351\211\264\346\235\203.md" @@ -1,15 +1,31 @@ --- -title: 第2节:DDD 重构,微信公众号鉴权 -lock: no +title: 第3-2节:DDD 重构,微信公众号鉴权 +pay: https://t.zsxq.com/wBobE --- -# 第2节:DDD 重构,微信公众号鉴权 +# 《小型支付商城系统》第3-2节:DDD 重构,微信公众号鉴权 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +在【第2部分 - 需求设计】[工程四色建模](https://articles.zsxq.com/id_pj4jlidovrpd.html)里,我们已经做了 DDD 部分的建模设计。到这一节学习前,可以回顾下四色建模设计时所做的内容。关于 DDD 的知识,一部分是工程四色建模拆分领域功能的界限上下文战略知识,另外一部分就是本节这里的战术设计指导落地。 + +本节小傅哥会带着大家,对照 MVC 中的微信公众号鉴权代码实现,拆解到 DDD 中进行实现。 + +> 因为在前面的内容讲解中已经介绍了很多的业务,所以在本节的实现过程中,重点会关注 mvc 到 ddd 的功能重构细节差异。 + +## 二、功能分区 + +DDD 映射下的六边形架构,会有非常明确的分层分区,各个模块都在自己的职责范围内实现。 + +
+ +
+ +- trigger 下实现让外部调用我们的接口,这里是微信公众号接口的鉴权和接收消息。 +- types 下加入了 sdk 微信的对接实现。 +- app 是启动层,里面增加 yml 配置信息。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2543\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\347\231\273\345\275\225\345\212\237\350\203\275\345\256\236\347\216\260.md" "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2543\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\347\231\273\345\275\225\345\212\237\350\203\275\345\256\236\347\216\260.md" index 0984a6cd1..ac5fc99fc 100644 --- "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2543\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\347\231\273\345\275\225\345\212\237\350\203\275\345\256\236\347\216\260.md" +++ "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2543\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\347\231\273\345\275\225\345\212\237\350\203\275\345\256\236\347\216\260.md" @@ -1,15 +1,27 @@ --- -title: 第3节:DDD 重构,登录功能实现 -lock: no +title: 第3-3节:DDD重构,登录功能设计实现 +pay: https://t.zsxq.com/Vc1Os --- -# 第3节:DDD 重构,登录功能实现 +# 《小型支付商城系统》第3-3节:DDD重构,登录功能设计实现 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +通过 DDD 领域设计,从 MVC 工程中拆分登录功能到 DDD 工程中实现。 + +本节会涉及到 api、domain、infrastructure、trigger、app,几层模块的使用,有了这一节的功能实现,会更加清楚 MVC 和 DDD 实现差异。不过编码的核心本质是不变的,所有的分层结构都是为了让代码实现逻辑更加清晰,降低后续的迭代成本。 + +## 二、登录模型 + +通过 DDD 领域驱动设计,陆续实现扫描登录、下单等流程模块。这一部分的设计可以参考第2部分中的四色建模设计。 + +
+ +
+ +- 本节我们先来实现登录功能领域,登录凭证、校验凭证以及保存登录状态。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2544\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\345\225\206\345\223\201\344\270\213\345\215\225.md" "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2544\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\345\225\206\345\223\201\344\270\213\345\215\225.md" index dd1a91528..351b57ab8 100644 --- "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2544\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\345\225\206\345\223\201\344\270\213\345\215\225.md" +++ "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2544\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\345\225\206\345\223\201\344\270\213\345\215\225.md" @@ -1,15 +1,31 @@ --- -title: 第4节:DDD 重构,商品下单 -lock: no +title: 第3-4节:DDD重构,商品下单 +pay: https://t.zsxq.com/3X9GA --- -# 第4节:DDD 重构,商品下单 +# 《小型支付商城系统》第3-4节:DDD重构,商品下单 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +通过 DDD 领域设计,从 MVC 工程拆分下单中的创建订单到 DDD 工程中实现。 + +相对于 MVC 工程的设计,DDD 的每个领域就是独立的空间,它会仔细考虑请求方法的出入参对象,而这些对象叫做领域对象。 + +在整个实现过程,每一个领域的功能,我们可以想象为;一个人,拿着一把钥匙,开锁到进屋。那么这里的一个人是用户、一把钥匙是入参领域对象、开锁是决策命令,完成开锁进屋是做完了一件事的领域事件。这个过程就是四色建模中的战略设计过程。 + +那么本节的下单,就是这样一个过程,用户通过购物车创建订单到支付。那么这里你可以思考,它的决策命令、领域事件、领域对象都是什么,接下来我们就要做这样一个实现。 + +## 二、下单模型 + +通过 DDD 领域驱动设计,本节实现点击下单,创建订单的处理。这一部分的设计可以参考第2部分中的四色建模设计。 + +
+ +
+ +- 本节我们先来实现用户点击下单的动作,完成商品下单。到下一节在处理关于支付宝沙箱的支付单处理。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2545\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\345\257\271\346\216\245\346\224\257\344\273\230.md" "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2545\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\345\257\271\346\216\245\346\224\257\344\273\230.md" index 9e5eaabcb..ba8a515c5 100644 --- "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2545\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\345\257\271\346\216\245\346\224\257\344\273\230.md" +++ "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2545\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\345\257\271\346\216\245\346\224\257\344\273\230.md" @@ -1,15 +1,27 @@ --- -title: 第5节:DDD 重构,对接支付 -lock: no +title: 第3-5节:DDD 重构,对接支付 +pay: https://t.zsxq.com/NYvtw --- -# 第5节:DDD 重构,对接支付 +# 《小型支付商城系统》第3-5节:DDD 重构,对接支付 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +通过 DDD 领域设计,从 MVC 工程拆分创建支付单到 DDD 工程中实现。 + +在我们不断把功能从 MVC 拆分到 DDD 的实现中,也是从面向过程到面向对象的开发思维转变。编程的能力提升就是不断地锻炼各种能力。 + +## 二、下单模型 + +通过 DDD 领域驱动设计,本节实现点击下单到完成支付宝订单创建过程。这一部分的设计可以参考第2部分中的四色建模设计。 + +
+ +
+ +- 本节我们实现点击下单创建出支付宝沙箱订单完成。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2546\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\346\224\257\344\273\230\345\233\236\350\260\203.md" "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2546\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\346\224\257\344\273\230\345\233\236\350\260\203.md" index eb2cbcb1f..7f02c1bfc 100644 --- "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2546\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\346\224\257\344\273\230\345\233\236\350\260\203.md" +++ "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2546\350\212\202\357\274\232DDD \351\207\215\346\236\204\357\274\214\346\224\257\344\273\230\345\233\236\350\260\203.md" @@ -1,15 +1,27 @@ --- -title: 第6节:DDD 重构,支付回调 -lock: no +title: 第3-6节:DDD 重构,支付回调处理 +pay: https://t.zsxq.com/CWVQM --- -# 第6节:DDD 重构,支付回调 +# 《小型支付商城系统》第3-6节:DDD 重构,支付回调处理 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +通过 DDD 领域设计,从 MVC 工程拆分支付回调和接口到 DDD 工程中实现。 + +从 MVC 到 DDD,是编码分层清晰,是逻辑实现整洁,也是后续的维护更加容易。其实也说明 DDD 的工程标准更加强。 + +## 二、回调模型 + +通过 DDD 领域驱动设计,本节实现支付回调过程。这一部分的设计可以参考第2部分中的四色建模设计。 + +
+ +
+ +- 本节我们实现支付回调处理。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2547\350\212\202\357\274\232\345\211\215\347\253\257\351\241\265\351\235\242.md" "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2547\350\212\202\357\274\232\345\211\215\347\253\257\351\241\265\351\235\242.md" new file mode 100644 index 000000000..d94b3891d --- /dev/null +++ "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2547\350\212\202\357\274\232\345\211\215\347\253\257\351\241\265\351\235\242.md" @@ -0,0 +1,23 @@ +--- +title: 第3-7节:前端页面 +pay: https://t.zsxq.com/qE34U +--- + +# 《小型支付商城系统》第3-7节:前端页面 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +搭建简单的前端页面,自动轮训检查扫描登录状态,完成登录跳转商品下单页。 + +## 二、业务流程 + +如图,本节可以串联用户UI流程,登录下单到支付完成。 + +
+ +
\ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2548\350\212\202\357\274\232Docker\346\236\204\345\273\272\345\222\214\351\203\250\347\275\262.md" "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2548\350\212\202\357\274\232Docker\346\236\204\345\273\272\345\222\214\351\203\250\347\275\262.md" new file mode 100644 index 000000000..c0adfda52 --- /dev/null +++ "b/docs/md/project/s-pay-mall/part-3-ddd/\347\254\2548\350\212\202\357\274\232Docker\346\236\204\345\273\272\345\222\214\351\203\250\347\275\262.md" @@ -0,0 +1,26 @@ +--- +title: 第3-8节:Docker构建和部署 +pay: https://t.zsxq.com/8vXVI +--- + +# 《小型支付商城系统》第3-8节:Docker构建和部署 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +通过 Docker 给工程配置 Dockerfile、build.sh 文件对项目进行构建和部署,前端应用采用 Nginx 进行部署。 + +## 二、Docker 是什么? + +Docker 你可以把它当做一个小型的轻量的虚拟机(虚拟的电脑),它可以帮你屏蔽各类软件环境安装时候的复杂性,你只需要一段脚本,即可完成 mysql、redis、nginx 等等各类你能想到的软件的部署和卸载。—— 不知道多少伙伴自己电脑装完 MySQL 就不会卸载了! + +
+ +
+ +- 官网:[https://www.docker.com/](https://www.docker.com/) - 本地电脑直接安装即可。Windows 电脑因为不是 linux 所以需要开启 wsl2(百度/星球搜索有配置教程) +- 云教程:[https://bugstack.cn/md/road-map/docker.html](https://bugstack.cn/md/road-map/docker.html) - 也可以选择云服务器安装。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2541\350\212\202\357\274\232MVC \345\267\245\347\250\213\346\241\206\346\236\266\346\220\255\345\273\272.md" "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2541\350\212\202\357\274\232MVC \345\267\245\347\250\213\346\241\206\346\236\266\346\220\255\345\273\272.md" index dd3727df5..1388ceeff 100644 --- "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2541\350\212\202\357\274\232MVC \345\267\245\347\250\213\346\241\206\346\236\266\346\220\255\345\273\272.md" +++ "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2541\350\212\202\357\274\232MVC \345\267\245\347\250\213\346\241\206\346\236\266\346\220\255\345\273\272.md" @@ -1,15 +1,46 @@ --- -title: 第1节:MVC 工程框架搭建 -lock: no +title: 第3-1节:MVC 工程框架搭建 + 基础配置 + Git 使用 +pay: https://t.zsxq.com/K4xTs --- -# 第1节:MVC 工程框架搭建 +# 《小型支付商城系统》第3-1节:MVC 工程框架搭建 + 基础配置 + Git 使用 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +手把手搭建,单 model 和多 model 的 mvc 分层架构,并配置 pom、yml 等,以及讲解分层结构的功能职责。最后将工程使用 Git 提交到 gitcode 仓库中。 + +mvc 的优势在于快,这个快是来自于不对系统进行建模、不考虑防腐(多层调用间的对象,不做隔离处理,可互相调用),也没有为分布式的各项连接资源做分层考虑,所以它的实现方式更快。 + +在最早我们实现单体类应用中,一个工程基本就使用2个东西,一个是 mysql 数据库,另外一个是 redis 缓存。这样的 mvc 工程复杂度是很低的,所以也比较好维护。 + +但随着分布式微服务的引入,在一个工程中除了有,数据库、缓存,还有 rpc、mq、任务调度、配置中心、一致性组件、分库分表、ElasticSearch 等等各项技术栈,这样在 mvc 中在实现这些就变得复杂了。所以这也是为什么大家开始逐步往 DDD 迁移,因为一方面是 DDD 的建模思维,另外一方面是 DDD 与新的架构模型,洋葱、整洁、六边形更加契合。新的架构模型,也能更好的承载分布式微服务架构设计实现。 + +不过,所有东西的学习最后学的就是思想。工程框架结构的设计,也就是用合理的分层结构,有效的填充各项资源,提高资源的调配效率。这句你要细细的琢磨下。如果你面试能讲出这么一句,那么对工程的框架理解的非常深入的。 + +## 二、环境配置 + +- Jdk 1.8 +- Maven 3.x - [Maven 教程](https://bugstack.cn/md/road-map/maven.html) +- IntellJ IDEA 社区版(免费) [IntelliJ IDEA 教程](https://bugstack.cn/md/road-map/intellij-idea.html) +- Git - 安装后会配置到 IntellJ IDEA 这样才能向服务端推送或者拉取代码。[Git 教程 ](https://t.zsxq.com/19Rnk98M0) 学习后可以知道怎么拉取、提交和比对代码。 + +--- + +```xml + + + alimavenrepository + aliyun maven repository + http://maven.aliyun.com/nexus/content/groups/public/ + central + + +``` + +- 如果你的 Maven 拉取 Jar 包速度很慢,可以在 Maven 的 conf 下 settings.xml 添加阿里云镜像。 +- [https://t.zsxq.com/19Rnk98M0](https://t.zsxq.com/19Rnk98M0) 已提供配置好了 阿里云 Maven 镜像的 Maven 压缩包。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2542\350\212\202\357\274\232\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\351\211\264\346\235\203.md" "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2542\350\212\202\357\274\232\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\351\211\264\346\235\203.md" index c39f763ff..87d64ec0b 100644 --- "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2542\350\212\202\357\274\232\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\351\211\264\346\235\203.md" +++ "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2542\350\212\202\357\274\232\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\351\211\264\346\235\203.md" @@ -1,15 +1,28 @@ --- -title: 第2节:微信公众号鉴权 -lock: no +title: 第3-2节:微信公众号鉴权 +pay: https://t.zsxq.com/ryhqq --- -# 第2节:微信公众号鉴权 +# 《小型支付商城系统》第3-2节:微信公众号鉴权 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +在 mvc 分层框架结构下添加微信公众号鉴权所需的接口,并通过 natapp 内网穿透组件,暴漏本地接口,让微信公众号平台可以配置使用。 + +在前面章节中已经讲解了,关于微信公众号鉴权的代码实现以及配置使用。所以本节我们会把重点放在 mvc 工程结构的使用,把关于微信的公众号鉴权操作流程按需放到所属模块下。 + +## 二、功能分区 + +mvc 工程结构区内,简单的划分了基础包、数据库、逻辑实现、接口实现。我们在这一节先使用到基础包和提供接口。 + +
+ +
+ +- common 承载着对接微信公众号的基础功能。 +- web 下的 controller 用于实现对外提供的接口。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2543\350\212\202\357\274\232\347\231\273\345\275\225\345\212\237\350\203\275\345\256\236\347\216\260.md" "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2543\350\212\202\357\274\232\347\231\273\345\275\225\345\212\237\350\203\275\345\256\236\347\216\260.md" index c8c9c1a6c..57805d808 100644 --- "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2543\350\212\202\357\274\232\347\231\273\345\275\225\345\212\237\350\203\275\345\256\236\347\216\260.md" +++ "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2543\350\212\202\357\274\232\347\231\273\345\275\225\345\212\237\350\203\275\345\256\236\347\216\260.md" @@ -1,15 +1,29 @@ --- -title: 第3节:登录功能实现 -lock: no +title: 第3-3节:登录功能设计实现 +pay: https://t.zsxq.com/fsEpq --- -# 第3节:登录功能实现 +# 《小型支付商城系统》第3-3节:登录功能设计实现 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +通过微信公众号平台提供的 API 接口,做微信公众号扫码登录。 + +扫码登录主要是需要微信公众号平台,提供一个生成带参的二维码,让用户使用微信扫描二维码登录。扫码后我们在微信公众号对接的接口中会接收到扫码完成消息,里面就会含带二维码参数,这样就可以知道到是谁扫描的二维码。我们把扫描后解析的信息和用户做绑定,也就可以完成登录操作了。 + +## 二、登录流程 + +微信扫码登录的流程主要包括;用户、浏览器、后端服务、公众号,这四个部分。我们可以先通过UML流程图,了解下整个调用关系。此流程已在[《第2部分,工程四色建模设计》](https://t.zsxq.com/XeucE)中讲解。 + +
+ +
+ +- 首先,由用户发起登录操作。让WEB页面从服务端获取登录凭证。 +- 之后,前端页面拿到登录凭证后,可以使用 Ticket 从公众号服务平台换取二维码。 +- 最后,用户扫码登录。扫码后,服务端会接收到来自公众号的回调消息,服务端再把回调消息中的 openid【用户唯一标识】和 ticket 进行绑定。这个时候你也可以创建出 jwt token 反馈给前端,作为登录成功的存储信息,后续校验 jwt token 就可以了。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2544\350\212\202\357\274\232\345\225\206\345\223\201\344\270\213\345\215\225.md" "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2544\350\212\202\357\274\232\345\225\206\345\223\201\344\270\213\345\215\225.md" index 891b7e974..afb7fe72d 100644 --- "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2544\350\212\202\357\274\232\345\225\206\345\223\201\344\270\213\345\215\225.md" +++ "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2544\350\212\202\357\274\232\345\225\206\345\223\201\344\270\213\345\215\225.md" @@ -1,15 +1,31 @@ --- -title: 第4节:商品下单 -lock: no +title: 第3-4节:商品下单 +pay: https://t.zsxq.com/g6Szl --- -# 第4节:商品下单 +# 《小型支付商城系统》第3-4节:商品下单 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +对接数据库表,完成商品下单。 + +要注意商品下单中,要考虑整个流程中可能存在的失败节点。`做编程开发很多时候都是在处理异常。`商品下单中,或者下单完成都可能存在失败的情况。比如写库失败,或者调用外部支付平台创建支付单失败,也可能存在用户创建完支付单但未支付的情况。 + +这些流程都是要在下单中做的处理,在公司的实际场景中,下单还要过很多规则校验。比如账户状态、风控、营销、试算、锁券等等流程,才会到下单。所以很多这样的场景,都会考虑使用设计模式进行解耦,否则很难完成后续的迭代。 + +## 二、下单流程 + +如图,本节我们先做下单流程。调用 Alipay 支付宝创建支付单和等待回调我们后续章节在处理。 + +
+ +
+ +- 首先,用户在系统中创建订单(流水单),创建过程中需要判断是否存在未支付订单,存在则可以直接返回。另外还有一种可能,创建的订单存在,但没有支付单,也就是【掉单】。这是因为本身的业务系统和外部的支付创建(支付宝)不是一个事务,不能一起成功或失败,所以要做一些流程的校验。比如我们创建订单成功,但创建支付单失败。这个之后用户继续创建订单,就会优先使用这笔订单创建支付单。如果流程中没有存在的掉单,则直接创建支付单即可。 +- 之后,创建完支付宝订单,会由页面跳转到网络收银台,引导用户完成支付操作。 +- 最后,就是接收支付回调消息,更新本地的订单状态,以及推动后续流程。比如;发放商品、驱动物流、虚拟支付等。当然在实际的商城中,还会有逆向流程,比如商品有问题,或者用户主动发起退单。这个时候就要走逆向流程,退单、审核、退款流程。你可以尝试完成。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2545\350\212\202\357\274\232\345\257\271\346\216\245\346\224\257\344\273\230.md" "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2545\350\212\202\357\274\232\345\257\271\346\216\245\346\224\257\344\273\230.md" index 285e72d86..728bb346b 100644 --- "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2545\350\212\202\357\274\232\345\257\271\346\216\245\346\224\257\344\273\230.md" +++ "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2545\350\212\202\357\274\232\345\257\271\346\216\245\346\224\257\344\273\230.md" @@ -1,15 +1,30 @@ --- -title: 第5节:对接支付 -lock: no +title: 第3-5节:对接支付 +pay: https://t.zsxq.com/2TPVn --- -# 第5节:对接支付 +# 《小型支付商城系统》第3-5节:对接支付 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +通过引入支付宝支付 sdk,实例化支付对象,完成支付对接。并提供商品交易下单和回调接口。 + +这里要记住一点,所有不是数据库一次事务提交的操作,都没法保证事务一致性。包括;http接口、rpc接口、mq消息等。这些调用过程,都需要有任务作为补偿处理,保证最终一致性。 + +他们的失败可能是网络超时,导致在调用过程中发生,也可能是消费时发生进行重试。所以这类接口调用除了有任务保持一致性,还有就是要有唯一幂等字段。确保在重复消费的过程中,也只是有一条记录产生或者发生变更。 + +## 二、业务流程 + +如图,本节我们来完成支付宝沙箱对接的流程; + +
+ +
+ +- 创建完成本地订单后,调用支付宝沙箱创建支付订单。 +- 在这个过程,如果发生 http 超时失败,那么会有二次用户请求时,检查到`掉单`重新发起创建动作。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2546\350\212\202\357\274\232\346\224\257\344\273\230\345\233\236\350\260\203.md" "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2546\350\212\202\357\274\232\346\224\257\344\273\230\345\233\236\350\260\203.md" index 228f48bf1..43b842772 100644 --- "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2546\350\212\202\357\274\232\346\224\257\344\273\230\345\233\236\350\260\203.md" +++ "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2546\350\212\202\357\274\232\346\224\257\344\273\230\345\233\236\350\260\203.md" @@ -1,15 +1,28 @@ --- -title: 第6节:支付回调 -lock: no +title: 第3-6节:支付回调处理 +pay: https://t.zsxq.com/Ydjmt --- -# 第6节:支付回调 +# 《小型支付商城系统》第3-6节:支付回调处理 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +对支付流程收尾,完成支付回调、掉单补偿、超时关单的处理,以及监听支付成功消息。 + +到本节的处理后,我们就把支付流程全部做完了。其实这也是面试中喜欢的问的场景,只有把一个支付的流程,从下单到支付再到回调处理,以及处理各项补偿和监听。面试官才会觉得你是真的对接了支付,而不是在描述一个 CRUD 流程。 + +## 二、业务流程 + +如图,本节我们来完成支付宝沙箱回调和补偿的流程; + +
+ +
+ +- 本节完成支付成功后的回调处理,更新数据库订单状态。同时发送MQ消息。比如一些发货场景,就是这个MQ发送出来之后做的处理。 +- 另外,我们在完成一些关于超时关单、掉单补偿的流程。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2547\350\212\202\357\274\232\345\211\215\347\253\257\351\241\265\351\235\242.md" "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2547\350\212\202\357\274\232\345\211\215\347\253\257\351\241\265\351\235\242.md" new file mode 100644 index 000000000..c1c84f643 --- /dev/null +++ "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2547\350\212\202\357\274\232\345\211\215\347\253\257\351\241\265\351\235\242.md" @@ -0,0 +1,23 @@ +--- +title: 第3-7节:前端页面 +pay: https://t.zsxq.com/L1Fpx +--- + +# 《小型支付商城系统》第3-7节:前端页面 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +搭建简单的前端页面,自动轮训检查扫描登录状态,完成登录跳转商品下单页。 + +## 二、业务流程 + +如图,本节可以串联用户UI流程,登录下单到支付完成。 + +
+ +
\ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2548\350\212\202\357\274\232Docker\346\236\204\345\273\272\345\222\214\351\203\250\347\275\262.md" "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2548\350\212\202\357\274\232Docker\346\236\204\345\273\272\345\222\214\351\203\250\347\275\262.md" new file mode 100644 index 000000000..6afea2c72 --- /dev/null +++ "b/docs/md/project/s-pay-mall/part-3-mvc/\347\254\2548\350\212\202\357\274\232Docker\346\236\204\345\273\272\345\222\214\351\203\250\347\275\262.md" @@ -0,0 +1,26 @@ +--- +title: 第3-8节:Docker构建和部署 +pay: https://t.zsxq.com/IWhOM +--- + +# 《小型支付商城系统》第3-8节:Docker构建和部署 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## 一、本章诉求 + +通过 Docker 给工程配置 Dockerfile、build.sh 文件对项目进行构建和部署,前端应用采用 Nginx 进行部署。 + +## 二、Docker 是什么? + +Docker 你可以把它当做一个小型的轻量的虚拟机(虚拟的电脑),它可以帮你屏蔽各类软件环境安装时候的复杂性,你只需要一段脚本,即可完成 mysql、redis、nginx 等等各类你能想到的软件的部署和卸载。—— 不知道多少伙伴自己电脑装完 MySQL 就不会卸载了! + +
+ +
+ +- 官网:[https://www.docker.com/](https://www.docker.com/) - 本地电脑直接安装即可。Windows 电脑因为不是 linux 所以需要开启 wsl2(百度/星球搜索有配置教程) +- 云教程:[https://bugstack.cn/md/road-map/docker.html](https://bugstack.cn/md/road-map/docker.html) - 也可以选择云服务器安装。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-4/\347\254\2541\350\212\202\357\274\232natapp \345\206\205\347\275\221\347\251\277\351\200\217.md" "b/docs/md/project/s-pay-mall/part-4/\347\254\2541\350\212\202\357\274\232natapp \345\206\205\347\275\221\347\251\277\351\200\217.md" index 9207d4a17..5853c3a63 100644 --- "a/docs/md/project/s-pay-mall/part-4/\347\254\2541\350\212\202\357\274\232natapp \345\206\205\347\275\221\347\251\277\351\200\217.md" +++ "b/docs/md/project/s-pay-mall/part-4/\347\254\2541\350\212\202\357\274\232natapp \345\206\205\347\275\221\347\251\277\351\200\217.md" @@ -1,15 +1,30 @@ --- -title: 第1节:natapp 内网穿透 -lock: no +title: 第4-1节:natapp 内网穿透 +pay: https://t.zsxq.com/qM7uL --- -# 第1节:natapp 内网穿透 +# 《小型支付商城系统》第4-1节:natapp 内网穿透 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +教会伙伴们,了解内网穿透和使用内网穿透。 + +## 二、了解穿透 + +说白了,内网穿透,就是想办法让本地这个只有内网IP的服务,被外网访问。 + +曾经有个伙伴问我,我云服务器部署了服务,配置了本地的 192.168.1.109 IP 下的 xxl-job 怎么执行失败呢?这是因为我们本地可以访问公网IP地址,但公网IP没法访问你的内网地址。 + +
+ +
+ +- 内网穿透服务会部署在服务端,之后提供一个内网穿透的客户端,在本地启动。这样本地的frp客户端和frp服务端,就可以建立连接进行通信。 +- 有了这个通信的连接,用户访问到frp服务端,就可以把请求到的内容转发给客户端。客户端在请求本地的服务,把数据回传回去。这样,也就把本地的服务暴漏出去了。具体的详细实现,可以检索frp穿透设计。 + +> 内网穿透是一种技术手段,用于访问位于防火墙或路由器后面的本地网络(内网)中的设备或服务。通常情况下,内网中的设备无法直接通过公网(互联网)进行访问,从而实现隐私保护和安全性。内网穿透技术的目标是突破这一限制,使外部用户能够通过互联网访问内网中的服务或设备。 \ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-4/\347\254\2542\350\212\202\357\274\232\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\346\265\213\350\257\225\350\257\204\345\256\241\347\224\263\350\257\267.md" "b/docs/md/project/s-pay-mall/part-4/\347\254\2542\350\212\202\357\274\232\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\346\265\213\350\257\225\350\257\204\345\256\241\347\224\263\350\257\267.md" index 09f19760c..3a1cfa225 100644 --- "a/docs/md/project/s-pay-mall/part-4/\347\254\2542\350\212\202\357\274\232\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\346\265\213\350\257\225\350\257\204\345\256\241\347\224\263\350\257\267.md" +++ "b/docs/md/project/s-pay-mall/part-4/\347\254\2542\350\212\202\357\274\232\345\276\256\344\277\241\345\205\254\344\274\227\345\217\267\346\265\213\350\257\225\350\257\204\345\256\241\347\224\263\350\257\267.md" @@ -1,15 +1,27 @@ --- -title: 第2节:微信公众号测试评审申请 -lock: no +title: 第4-2节:微信公众号,测试平台申请使用 +pay: https://t.zsxq.com/iaOEW --- -# 第2节:微信公众号测试评审申请 +# 《小型支付商城系统》第4-2节:微信公众号,测试平台申请使用 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +因为课程后面会需要用到微信公众号作为登录、通知、消息发送的载体,所以本节先带着大家做下微信公众号的申请和简单的验签配置,可以满足消息自动回复操作。 + +## 二、平台说明 + +微信公众号,分为个人和企业,个人的公众号会有很多限制,基本只能使用最基础功能。企业的公众号需要有公司主体,可以使用全量功能,但需要一年¥300的认证费用。 + +为了使用到所有的公众号号接口能力,本节我们这里使用的是微信公众号测试平台,它直接支持所有的公众号接口能力。也方面我们学习使用。 + +平台地址:[https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index](https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index) - 每个人都可以申请。进入后会看到官网文档。 + +
+ +
\ No newline at end of file diff --git "a/docs/md/project/s-pay-mall/part-4/\347\254\2543\350\212\202\357\274\232\346\224\257\344\273\230\345\256\235\346\262\231\347\256\261\347\224\263\350\257\267.md" "b/docs/md/project/s-pay-mall/part-4/\347\254\2543\350\212\202\357\274\232\346\224\257\344\273\230\345\256\235\346\262\231\347\256\261\347\224\263\350\257\267.md" index 4f078d1a1..e9ee9e1ef 100644 --- "a/docs/md/project/s-pay-mall/part-4/\347\254\2543\350\212\202\357\274\232\346\224\257\344\273\230\345\256\235\346\262\231\347\256\261\347\224\263\350\257\267.md" +++ "b/docs/md/project/s-pay-mall/part-4/\347\254\2543\350\212\202\357\274\232\346\224\257\344\273\230\345\256\235\346\262\231\347\256\261\347\224\263\350\257\267.md" @@ -1,15 +1,37 @@ --- -title: 第3节:支付宝沙箱申请 -lock: no +title: 第4-3节:支付宝沙箱申请使用 +pay: https://t.zsxq.com/b0U7F --- -# 第3节:支付宝沙箱申请 +# 《小型支付商城系统》第4-3节:支付宝沙箱申请使用 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 -## 一、前言 +## 一、本章诉求 -... 新章节,编写中 \ No newline at end of file +申请支付宝沙箱环境,使用支付宝沙箱API,完成简单支付订单的创建、支付和接收回调消息。 + +其实不只支付宝沙箱,包括我们对接微信支付或者其他第三方支付,都是这样一个流程。之后对于没有企业资质的一般只能做支付宝沙箱模拟,或者想真实对接支付,就需要使用虎皮椒、蓝兔支付的三方服务结构。 + +蓝兔支付在星球里提供了对接的 sdk 文档,如果你需要做真实支付可以学习下。[《支付SDK设计和开发》](https://t.zsxq.com/19WqNkhr2) + +## 二、支付申请 - Alipay 沙箱支付 + +### 1. 沙箱应用 + +**支付宝|开放平台** 地址:[https://open.alipay.com/develop/manage](https://open.alipay.com/develop/manage) - `任何人都可以申请,不要企业资质` + +
+ +
+ +
+ +
+ +- 开启沙箱应用以后,还需要下载支付宝秘钥工具。秘钥工具创建的秘钥,需要填写到查看中。 +- 📢 【沙箱账号】,里面提供了后续在网页上支付时,输入的账号、密码和支付密码。 +- 📢 【沙箱工具】,里面提供了安卓版测试软件,可以在手机扫码支付。 diff --git a/docs/md/project/s-pay-mall/s-pay-mall.md b/docs/md/project/s-pay-mall/s-pay-mall.md index 29794c7a0..19ced3664 100644 --- a/docs/md/project/s-pay-mall/s-pay-mall.md +++ b/docs/md/project/s-pay-mall/s-pay-mall.md @@ -7,6 +7,7 @@ lock: no 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) +
项目:[https://t.zsxq.com/3X9GA](https://t.zsxq.com/3X9GA) >沉淀、分享、成长,让自己和他人都能有所收获!😄 diff --git a/docs/md/project/xfg-fish-pond/xfg-fish-pond.md b/docs/md/project/xfg-fish-pond/xfg-fish-pond.md new file mode 100644 index 000000000..a07df3449 --- /dev/null +++ b/docs/md/project/xfg-fish-pond/xfg-fish-pond.md @@ -0,0 +1,200 @@ +--- +title: 钓鱼佬-网页游戏项目 +lock: no +--- + +# 钓鱼佬-网页游戏项目 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
项目:[https://t.zsxq.com/g57ja](https://t.zsxq.com/g57ja) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +哈哈哈,不是干项目,就是在干项目的路上。除了正式的全程视频手把手带着做的,小傅哥也陆续的开始更新了大厂的 PRD 资料、市面上火热的外卖,进行DDD重构编写。这次又带来一个轻量基于 SpringBoot + Redis 实现的, 🎮 🐟 **钓鱼佬,网页游戏项目** 。 + +这个项目还在线部署过,让伙伴们体验效果。😄 下面有介绍,你可以自己部署体验。 + +
+ +
+ +**为啥会有这样一个项目呢?🤔** + +在互联网应用场景中,京东、淘宝、拼多多等,我们时常会看到一些游戏化玩法的场景,如;集卡、浇水、养动物,通过这些场景增强用户粘性,以及提高转化率。因为这些游戏化场景的背后,还是一套套的营销玩法,最终把一些券、积分、物品发放给用户。 + +而小傅哥的社群,是按照互联网公司级别的一个项目组进行规划、设计、落地的。在这个社群有非常丰富的项目资源,已经提供的有,业务的 - 交易、拼团、营销、openai应用、ai agent、IM等,组件的 - api网关、扳手工程、动态线程池、透视业务监控、支付sdk组件、IntelliJ IDEA 插件等。 + +那么为了让小傅哥的社群,给大家提供的项目,是一个有立体化分层关系结构的,可以通过对接形成各个环节的流程闭环。所以小傅哥在全程视频手把手带着做以外,又增加了 PRD 文档、吉祥外卖、这次又增加一个钓鱼佬娱乐的项目。 + +**基本你在小傅哥的这个社群,就等同于你在一个一线互联网大厂进行一次实习!** 接下来,小傅哥来介绍下这个小游戏项目。 + +## 一、运行效果 + +该项目是一个轻量的网页游戏应用项目,提供了 Java、Python 2个版本,数据使用 Redis 进行存储。以娱乐化的方式,让伙伴学习到 Redis 的相关技术。此外,你可以把这样的一个项目,与星球里的大营销(积分、兑换、返利、抽奖)进行对接使用。在描述上,是以调研了xxx互联网公司的xxx游戏化场景,进行设计实现的这样一整套系统。 + +### 1. 登录 + +
+ +
+ +### 2. 画鱼 + +
+ +
+ +### 3. 鱼塘 + +
+ +
+ +- 鱼塘页面,可以看到所有登录用户投放进来的鱼,还可以钓鱼🎣。也许会把别人的鱼钓鱼到自己的鱼篓里。当然,钓鱼是需要积分的,你需要点击签到获得积分。 +- 页面里还有一些问题的话术和救赎时间(上班摸鱼等于救赎自己!) +- 本次设计的页面和后端的代码,都比较简单,后端也仅有一层架构。如果想添加功能,可以自己实现,也可以使用 trae.ai、Cursor 等工具,来辅助开发。 +- 哈哈哈,还有伙伴提建议,让这些鱼,可以支持在线售卖。如果你还有很多想法,可以拿到这套代码,做一些扩展。 + +### 4. 居民 + +
+ +
+ +在鱼塘居民下,可以看到各个伙伴画的各种鱼。你可以对这些鱼点一个喜欢或者不喜欢。 + +## 二、项目介绍 + +### 1. 工程代码 + +
+ +
+ +- 地址:[https://gitcode.net/KnowledgePlanet/xfg-fish-pond](https://gitcode.net/KnowledgePlanet/xfg-fish-pond) - `文末加入小傅哥社群,即可获得全部代码,以及其他17个实战项目` +- 说明:项目提供了前端代码,SpringBoot 服务端代码,以及一个 python 版本的代码。 + +### 2. 项目启动 + +
+ +
+- 首先,在 xfg-fish-pond-app 下,resources/application-dev.yml 配置 redis 链接信息。 +- 之后,启动项目后,点击打开页面即可访问了。如果你要部署云服务器,可以通过 docker 构建镜像在云服务器部署即可。 + +> 如果你正在做星球的项目,那么很多都可以与这套项目做微服务对接。如;大营销的积分、兑换、返利、抽奖,也可以把 ai 场景对接进来,还可以把小型支付对接进来,买卖鱼的交易。 + +## 三、技术学习 + +本套项目的数据存储都是基于 Redis 实现的,你可以在这套代码中学习到非常多的 Redis 应用技术。 + +### 1. 用户会话管理(UserController) + +**登录时存储用户信息:** +```java +RMap userMap = redisService.getMap(userKey); +userMap.put("userId", userId); +userMap.put("username", username); +userMap.put("loginTime", LocalDateTime.now().toString()); +userMap.expire(86400, TimeUnit.SECONDS); // 24小时过期 +``` + +**用户列表管理:** +```java +redisService.addSetMember(USER_LIST_KEY, userId); // 添加到在线用户列表 +redisService.removeSetMember(USER_LIST_KEY, userId); // 从在线用户列表移除 +``` + +### 2. 积分系统(PointsController) + +**积分存储和操作:** +```java +// 获取用户积分 +int points = Integer.parseInt(pointsMap.getOrDefault("points", "0")); + +// 更新积分 +pointsMap.put("points", String.valueOf(newPoints)); +pointsMap.put("lastUpdated", LocalDateTime.now().toString()); +``` + +**签到记录:** +```java +String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); +RMap signMap = redisService.getMap(signKey); +signMap.put(today, LocalDateTime.now().toString()); +``` + +**积分变动记录:** +```java +String recordValue = points + "|" + type + "|" + reason + "|" + LocalDateTime.now().toString(); +recordsMap.put(recordId, recordValue); +``` + +### 3. 鱼类管理(FishController) + +**添加鱼到池塘:** +```java +RMap fishMap = redisService.getMap(fishKey); +fishMap.put("name", fishName); +fishMap.put("emoji", emoji); +fishMap.put("userId", userId); +fishMap.put("createTime", LocalDateTime.now().toString()); + +// 添加到鱼类列表 +redisService.addSetMember(FISH_LIST_KEY, fishId); +``` + +### 4. 钓鱼系统(FishingController) + +**钓鱼记录:** +```java +String recordValue = success + "|" + fishEmoji + "|" + fishName + "|" + fishRarity + "|" + + LocalDateTime.now().toString() + "|" + transferred + "|" + + originalOwner + "|" + fishId; +recordsMap.put(recordId, recordValue); +``` + +**鱼篓管理:** +```java +String fishValue = emoji + "|" + name + "|" + rarity + "|" + + LocalDateTime.now().toString() + "|" + originalFishId + "|" + image; +basketMap.put(fishId, fishValue); +``` + +### 5. 投票系统(VoteController) + +**用户投票记录:** +```java +RMap userVotesMap = redisService.getMap(userVotesKey); +userVotesMap.put(fishId, voteType); // "like" 或 "dislike" +``` + +**投票统计:** +```java +fishVotesMap.put("likes", String.valueOf(currentLikes)); +fishVotesMap.put("dislikes", String.valueOf(currentDislikes)); +fishVotesMap.put("score", String.valueOf(currentLikes - currentDislikes)); +``` + +### 6. 系统监控(SystemController) + +**Redis 健康检查:** +```java +// 设置测试值 +redisService.setValue("health_check", "ok"); + +// 读取测试值 +String value = redisService.getValue("health_check"); + +// 删除测试值 +redisService.remove("health_check"); + +// 获取用户总数 +Map userList = redisService.getMapAll("user_list"); +``` + +好啦,如果你现在需要实战项目锻炼自己的能力,积累自己的储备,那么一定要加入小傅哥知识星球(码农会锁)。这里有非常多的类型丰富的项目,带着你一起起飞🛫! + diff --git a/docs/md/road-map/13scan-jdumpspider.md b/docs/md/road-map/13scan-jdumpspider.md new file mode 100644 index 000000000..40fe15f29 --- /dev/null +++ b/docs/md/road-map/13scan-jdumpspider.md @@ -0,0 +1,229 @@ +--- +title: w13scan-jdumpspider 安全漏洞扫描 +lock: need +--- + +# 安全漏洞扫描,他怎么拿到了我的数据库密码? + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +你有没有想过,你部署到线上的 SpringBoot 应用,在做互联网`安全人员`的手里,已经成了"小肉鸡"?可怕的攻击不一定是 DDOS 玩命的访问你的网站,消耗你的 CDN 流量。而是拿到你的应用系统的一系列配置,如;数据库账号密码和连接地址、微信公众平台核心配置、OpenAI APIKey。可以说这些东西一暴漏,那你得遭老罪喽。 + +
+ +
+ +**那这是怎么被发现暴漏的呢?🤔** + +做安全的有一套应用漏洞检查扫描的软件,它通过启动被动流量扫描服务,通过代理的方式,挂载到自身的浏览器。日常的访问一些网站时,所有的流量节点都会进入到被动扫描代理服务中,之后消耗这些流量节点,依次检测每个地址下可能发生的;XSS、jsonp信息泄露、sql注入、http smuggling 走私攻击,以及可以根据各类组件提供的漏洞问题做扫描补偿。这样就可以拿到你的网站都有哪些安全漏洞问题了。 + +这里有一个最典型的就是 SpringBoot Actuator 安全点暴漏,这东西是可以拿到你的 heapdump,之后再通过 JDumpSpider 扫描,也就可以拿到你应用中的数据源、配置文件、Redis配置、ShiroKey等信息。此时如果你的数据库恰好没有配置IP访问限制,那么直接远程连接登录进去,一顿操作了。 + +那么整个这样一个流程怎么玩一下呢?这东西只有亲自上下手,才会感受到它的恐怖。接下来,小傅哥就教你做被动安全扫描操作和 heapdump 下载分析提取数据库密码。 + +## 一、流程介绍 + +关于被动扫描系统安全漏洞的服务系统有很多,包括 w13scan 免费开源的,也有 xray 付费的,还有的是公司或者个人独立开发的。本节我们主要使用 w13scan 作为安全漏洞扫描的案例。 + +
+ +
+ +- 首先, w13scan 的流程是这样,你需要先启动一个这样的被动扫描服务,之后再你的浏览器中配置网页请求代理地址。这个代理地址就是 w13scan 服务。 +- 那么,这个时候你所有在浏览器发起的请求,都会经过 w13scan 走一圈。这样,就可以把请求的网址进行一系列安全扫描检查,查看是什么样的漏洞。 +- 另外,w13scan 不只是可以被动扫描还可以主动配置路径扫描一个固定的网站地址检测。 +- 最后,w13scan 会把扫描到的安全漏洞以html方式展示出来,我们可以在这个网页上查看漏洞检测结果。也就可以在进一步对存在的漏洞进行挖局,如拿到 heapdump 在解析它的信息了。 + +## 二、案例工程 + +这里小傅哥为你提供了完整的案例测试工程,你可以直接完整体验。`你需要有 docker 环境或者 Python 3.6+` + +
+ +
+ +地址:[https://github.com/fuzhengwei/xfg-dev-tech-w13scan-jdumpspider](https://github.com/fuzhengwei/xfg-dev-tech-w13scan-jdumpspider) + +- 首先,你需要下载这个工程到本地电脑,便于安装环境和测试。 +- 如图,已经为你描述了案例的功能。 + +## 三、被动扫描 + +**源码**:[https://github.com/fuzhengwei/w13scan](https://github.com/fuzhengwei/w13scan) - 小傅哥 fork 的 w13scan 并做了镜像打包。源码文档里提供了安装和使用说明。 + +### 1. 组件安装 - docker 方式 + +```java +# docker-compose -f docker-compose.yml up -d +version: '3.8' +services: + w13scan: + image: fuzhengwei/w13scan:1.0 + container_name: w13scan + ports: + - "7778:7778" + volumes: + - ./output:/w13scan/W13SCAN/output + entrypoint: ["python3", "w13scan.py", "-s", "0.0.0.0:7778", "--html"] + tty: true +``` + +
+ +
+ +- 你可以通过脚本 `docker-compose -f docker-compose.yml up -d` 脚本执行 w13scan 的服务安装。 +- 另外,如果你不能执行 docker-compose 还可以通过提供的 `docker run -d --name w13scan -p 7778:7778 -v ./output:/w13scan/w13scan/output fuzhengwei/w13scan:1.0 python3 w13scan.py -s 127.0.0.1:7778 --html` + +### 2. 组件安装 - Python 方式 + +这个方式就把代码拉到自己本地,进行构建和启动。 + +
+ +
+ +```java +git clone https://github.com/fuzhengwei/w13scan.git +cd w13scan # 进入git目录 +pip3 install -r requirements.txt +cd W13SCAN # 进入源码目录 +python3 w13scan.py -h +``` + +```java +python3 w13scan.py -s 127.0.0.1:7778 --html # 端口可省略,默认为7778,开启--html即实时生成html报告 +``` + +- 安装完成后启动,也可以看到一个 ` HTTPServer is running at address('0.0.0.0','7778')......` 日志。 + +### 3. 代理配置 + +无论使用那种方式部署,启动完成后,都需要给浏览器配置代理。其实也就是你的电脑的网络哪里配置下代理。 + +
+ +
+ +- 给你的网络配置代理服务,我这里是 mac 电脑点网络wifi那里进入的配置。你可以找到你的位置进行添加。 + +### 4. 下载证书 + +下载:[http://w13scan.ca/](http://w13scan.ca/) + +一定是你服务启动成功,代理配置成功。那么你在点击下载后,才能下载一个 `download.crt` 文件。之后双击点开信任即可。 + +### 5. 开始使用 + +一切配置成功后,你可以在浏览器访问你想检查漏洞的网址,一段时间后就可以看到被动扫描组件检测的数据信息了。之后进入到 `w13scan/W13SCAN/output` 查看检测文件了。这些 html 文件直接用浏览器打开和刷新即可。 + +
+ +
+ +
+ +
+ +- 现在你就看到一些展示的系统安全漏洞了,再根据这些漏洞进行**友好的访问** + +## 四、heapdump 下载 + +测试前你可以先启动 xfg-dev-tech-w13scan-jdumpspider 应用。这样就可以做后面的流程以及获取 heapdump 日志了。 + +### 1. 问题背景 + +测试工程中的 yml 配置。这个配置为了配合普罗米修斯做监控使用的,但要注意如果只是这样配置,是很有风险的。 + +```java +# 监控 +management: + endpoints: + web: + exposure: + include: "*" + endpoint: + health: + show-details: always + metrics: + export: + prometheus: + enabled: true + prometheus: + enabled: true +``` + +- 如果你的 SpringBoot 系统配置了这样的监控,并且没有配置相关的安全校验,Spring Security 那么现在你就暴漏了自己的端点。 + +### 2. 端点访问 + +地址:[http://127.0.0.1:8091/actuator/env](http://127.0.0.1:8091/actuator/env) + +
+ +
+ +- 这个地址,就可以由被动扫描检测出来。不过不同的被动扫描组件检测点不同,有些是没有的。 + +### 3. 下载 dump + +地址:[http://127.0.0.1:8091/actuator/heapdump](http://127.0.0.1:8091/actuator/heapdump) + +
+ +
+ +- 把工程的 heapdump 文件下载下来。下载后可以放到案例工程 docs 里 JDumpSpider-1.1-SNAPSHOT-full.jar 的同层路径下。 + +## 五、heapdump 解析 + +以前小傅哥带着大家做一篇[《Eclipse MAT 分析 Java heap space dump 日志》](https://bugstack.cn/md/road-map/dump-mat.html) 这个也能分析 dump 日志查看系统中的核心数据。不过这里我们选择个更针对性的 JDumpSpider 做日志分析,直接提取核心配置。 + +源码:[https://github.com/whwlsfb/JDumpSpider](https://github.com/whwlsfb/JDumpSpider) - 有相关的使用说明。 + +命令:`java -jar JDumpSpider-1.1-SNAPSHOT-full.jar heapdump` + +```java +/bin/zsh /xiaofuge/develop/github/xfg-dev-tech-w13scan-jdumpspider/docs/jdumpspider.sh +(base) xiaofuge@ZBMac-GV47H1GXD docs % /bin/zsh /Users/xiaofuge/Documents/develop/github/xfg-dev-tech-w13scan-jdumpspider/docs/jdumpspider.sh +=========================================== +SpringDataSourceProperties +------------- +password = 123456 +driverClassName = com.mysql.cj.jdbc.Driver +url = jdbc:mysql://127.0.0.1:13306/road_map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true +username = root + +=========================================== +WeblogicDataSourceConnectionPoolConfig +------------- +not found! + +=========================================== +MongoClient +------------- +not found! + +=========================================== +AliDruidDataSourceWrapper +------------- +not found! + +=========================================== +HikariDataSource +------------- +not found! +``` + +- 命令执行后可以看到你的工程中连接数据库的配置,密码也会直接暴漏出来。其他的配置如果你有添加,也会一并给你拿出来。**底裤给你扒掉** + +## 六、安全建议 + +- 对于自己上线的应用,尤其独立开发者,一定多进行安全扫描。 +- 不要无密码暴漏自己的应用,包括任何监控、数据采集、以及第三方组件。 +- 数据库、缓存、文件等连接,在云服务器要配置上可访问IP限制。这样就算底裤拔掉了,也还有一个玻璃罩。只能看,不能连。 \ No newline at end of file diff --git a/docs/md/road-map/1panel.md b/docs/md/road-map/1panel.md new file mode 100644 index 000000000..f6252cc43 --- /dev/null +++ b/docs/md/road-map/1panel.md @@ -0,0 +1,85 @@ +--- +title: 1Panel 运维面板 +lock: need +--- + +# 1Panel 云服务器运维面板 | 操作云服务器,这套东西还适合小白的! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在编程的这条路上,大家都经历过小白阶段。在小白阶段,即使是简简单单的环境安装,也都会遇到一堆堆的报错。所以最开始学习编程的时候,我们都希望找到那些简单、方便、好用的工具,让我们线上手✋🏻。 + +
+ +
+ +**那云服务器操作有Easy工具吗?🤔** + +小傅哥,在最早使用云服务器的时候,为了快速简单的搭建博客对外使用,选择过宝塔面板。这个东西虽然不大,但对于最开始云服务器操作能力和对编程的理解都比较偏弱的伙伴还是非常好用的。 + +但当大家开始使用 Linux + Docker,对一些列分布式环境继续安装和项目构建部署时,有些小白就会遇到一些各类小问题了。只有写好了 docker compose 和对应的文档,才能让小白快速完成安装。但有一些小白用到的新的服务安装时,自己不会写 docker compose 就会遇到新问题了。所以,今天我们来体验下一个新的云服务器运维面板,非常好用。 + +## 一、面板介绍 + +1Panel 是新一代的 Linux 服务器运维管理面板,它可以帮助你非常方便管理云服务器上的软件操作。`也不需要再配置 docker 代理了。` + +
+ +
+ +- 用户可以通过 Web 图形界面轻松管理 Linux 服务器,实现主机监控、文件管理、数据库管理、容器管理等功能。 +- 深度集成开源建站软件 WordPress 和 Halo,域名绑定、SSL 证书配置等一键搞定。 +- 精选上架各类高质量的开源工具和应用软件,协助用户轻松安装并升级。 +- 基于容器管理并部署应用,实现最小的漏洞暴露面,同时提供病毒防护、防火墙和日志审计等功能。 +- 支持一键备份和恢复,用户可以将数据备份到各类云端存储介质,永不丢失。 + +> 好啦,介绍的还挺🐂皮的,咱们来体验下! + +## 二、安装软件 + +### 1. 安装脚本 + +```java +curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sh quick_start.sh +``` + +- Centos 一键安装脚本,复制到云服务器直接执行即可。 +- 其他的云服务器系统安装脚本:https://1panel.cn/docs/installation/online_installation/ +- 2c2g 云服务器,活动价,一年26元 [https://618.gaga.plus](https://618.gaga.plus) + +### 2. 安装效果 + +
+ +
+ +- 安装过程中你可以顺序点回车即可,注意是否配置镜像加速,因为我配置过,所以没有配置。你可以选 Y 统一配置镜像加速。 +- 安装完成后,会得到一个外网地址,端口是默认的 19166,同时给会你用户和密码。注意,需要在云服务器开放端口(安全组/防火墙)19166 另外账号密码可以在登录后修改。 + +## 三、软件功能 + +### 1. 查看容器 + +
+ +
+ +- 你的 Linux 安装 Docker 会直接被 1Panel 接管。在 1Panel 会看到你安装过的软件。 +- 同时可以看到每个软件占用的 CPU、内存,这个还是非常好用的。 + +### 2. 安装软件 + +
+ +
+ +- 在 1Panel 的应用商店里,可以按照你需要的各类软件(它的覆盖度还是非常全的),包括常用的:Nginx、MySQL、MQ、Nacos、PHPAdmin等等,都是有的。 +- 如图,是个 OneAPI 它是用于访问兼容访问各类其他 OpenAI 的软件的。比如,文心一言、通义千问、讯飞星火、智谱 ChatGLM、腾讯混元,都可以按照 ChatGPT 的格式进行使用啦。 + +>好啦,你可以美滋滋的去体验下啦!🌶 + diff --git a/docs/md/road-map/a2a.md b/docs/md/road-map/a2a.md new file mode 100644 index 000000000..8974a9fc5 --- /dev/null +++ b/docs/md/road-map/a2a.md @@ -0,0 +1,388 @@ +--- +title: a2a +lock: need +--- + +# A2A,实际跑起来是什么样? + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +chatgpt(22年)-> LLM 进阶(23年)-> MCP 协议(24年)-> Skils 技能(25年)-> A2A 标准(25年),这几年 AI 发展的非常迅速,定义了协议,开发了组件,发布了产品。每个阶段,都有非常牛皮的代表性的内容,车速非常快🚌,不知道在坐的各位有没有掉队。 + +
+ +
+ +针对这些 LLM 大模型的相关知识,小傅哥也分别提供了相关实战类项目,包括;**AI 问答助手(23年)**、**OpenAi(ChatGPT/ChatGLM) 微服务应用体系构(23年)**、**OpenAI 代码自动评审组件(24年)**、**AI Agent 智能体 - 拖拉拽(25年)**、**AI MCP Gateway 网关服务系统(25年)**、**AI Agent 脚手架 + 场景应用(26年)**,通过这些实战项目,实践各类标准协议和技术组件(spring ai、google adk...)的使用,以及提供非常出色的解决方案。 + +因为后续的 ai agent 智能体项目,还会涉及到 a2a 协议,所以先给大家做个相关技术的使用方便大家快速实践理解。 + +>🧧 文末提供了20个实战项目(6个AI、5个业务、8个组件、1套源码),以及各类编程技术小册等。欢迎一起加入学习。 + +## 一、A2A 是什么? + +A2A (Agent2Agent) 协议是 Google于2025年4月推出、并由 Linux基金会托管的开源开放标准。它作为AI智能体之间的“通用语言”,旨在实现不同框架、不同厂商构建的智能体(Agent)间跨平台发现、通信与协作。 + +随后25年底,Google 发布了 [a2a adk](https://central.sonatype.com/artifact/com.google.adk/google-adk-a2a/0.4.0) 组件(迭代速度很快)。之后借助代理开发工具包 (Google ADK),我们可以构建复杂的多代理系统,其中不同的代理需要使用代理对代理 (A2A) 协议进行协作和交互!本节提供了一个全面的指南,指导您构建强大的多代理系统,使代理能够安全高效地进行通信和协作。 + +框架:[https://google.github.io/adk-docs/a2a/](https://google.github.io/adk-docs/a2a/) + +源码:[https://github.com/google/adk-java](https://github.com/google/adk-java) + +资料:[https://www.ibm.com/cn-zh/think/topics/agent2agent-protocol](https://www.ibm.com/cn-zh/think/topics/agent2agent-protocol) + +文档:[https://a2aprotocol.ai/docs/](https://a2aprotocol.ai/docs/) + +--- + +如图,整套智能体架构(含A2A); + +
+ +
+ +- 左侧,是 LLM 模型智能体构建,基于 Spring AI 框架实现。这部分包括,AiApi 使用、RAG、MCP、Skills 的组合构建。 +- 右侧,是 AI Agent 智能体编排,基于 Google ADK 框架实现。这套框架,提供了智能体工作流组装,插件回调钩子等各项基于 Google 发布的协议进行构建的。 +- 之后,右上方,是 Google ADK 26年基于 A2A 协议实现的框架组件,方便我们设计出远程的 A2A 服务对接,把远程服务,转换为本地功能组件,编排进智能体中。因此 A2A 协议的作用,就是让一个远程的智能体,可以像构建本地智能体一样,连接起来进行使用。 + +> 基于 a2a 的协议,也有很多三方框架,但我们需要的是一个整体的解决方案,单一一个功能,还不能解决所有问题。所以这里优先选择 google adk 框架。 + +## 二、实践案例 + +### 1. 编程环境 + +- jdk 17 +- google adk 0.8 +- spring ai 1.1.0-M3 + +>相关的版本包,已经在测试工程中的 pom 里引入了。可以打开工程查看。 + +### 2. 工程结构 + +
+ +
+ +- 工程:[https://github.com/fuzhengwei/xfg-dev-tech-google-adk-a2a-server](https://github.com/fuzhengwei/xfg-dev-tech-google-adk-a2a-server) +- 说明:基于 Google ADK 框架,构建 A2A 服务端和客户端。注意,服务端的启动方式为 `quarkus.sh` 方式启动服务,之后使用客户端连接。 +- 注意:这部分还有一些关于关于 Spring AI + Google ADK 的基础使用知识,是在 ApiTest 中有案例。也可以学习项目 [《AI Agent 脚手架 + 场景应用》](https://bugstack.cn/md/project/ai-agent-scaffold/ai-agent-scaffold.html) + +### 3. 测试案例 + +```java +public class ApiTest { + + public static void main(String[] args) throws Exception { + OpenAiApi openAiApi = OpenAiApi.builder() + .baseUrl("https://apis.****.cn") + .apiKey("sk-tIYdEUUnMqKX3bRf756a31449a4942***需要配置你的key") + .completionsPath("v1/chat/completions") + .embeddingsPath("v1/embeddings") + .build(); + + ChatModel chatModel = OpenAiChatModel.builder() + .openAiApi(openAiApi) + .defaultOptions(OpenAiChatOptions.builder() + .model("gpt-4o") + .build()) + .build(); + + // agent 测试 + LlmAgent agent = LlmAgent.builder() + .name("test") + .description("Chess coach agent") + .model(new SpringAI(chatModel)) + .instruction(""" + You are a knowledgeable chess coach + who helps chess players train and sharpen their chess skills. + """) + .build(); + + InMemoryRunner runner = new InMemoryRunner(agent); + + Session session = runner + .sessionService() + .createSession("test", "fzw") + .blockingGet(); + + Flowable events = runner.runAsync("fzw", session.id(), + Content.fromParts(Part.fromText("1+1"))); + + System.out.print("\nAgent > "); + events.blockingForEach(event -> System.out.println(event.stringifyContent())); + } + +} +``` + +- 这是一个 Spring AI + Google ADK 构建的简单智能体,由 LlmAgent 构建时候,创建模型 `new SpringAI(chatModel)` 关联到 Spring AI 框架。 +- 之后,由 Google ADK 构建的智能体,使用内存记忆,创建会话之后进行测试。也可以学习项目 [《AI Agent 脚手架 + 场景应用》](https://bugstack.cn/md/project/ai-agent-scaffold/ai-agent-scaffold.html) 锻炼使用相关内容。 + +### 4. A2A 测试 + +#### 4.1 服务端 + +这部分内容的学习,可以打开案例代码,方便对比。 + +##### 4.1.1 服务提供 + +```java +@ApplicationScoped +public class AgentExecutorProducer { + + @ConfigProperty(name = "my.adk.app.name", defaultValue = "default-app") + String appName; + + @Produces + public AgentExecutor agentExecutor() { + return new com.google.adk.a2a.executor.AgentExecutor.Builder() + .agent(Agent.ROOT_AGENT) + .appName(appName) + .sessionService(new InMemorySessionService()) + .artifactService(new InMemoryArtifactService()) + .agentExecutorConfig(AgentExecutorConfig.builder().build()) + .build(); + } + +} +``` + +- 这部分是把智能体提供出去,通过 google adk 框架,创建 AgentExecutor 实例。 +- 之后 Agent.ROOT_AGENT 类似于上面的测试案例,智能体构建的部分。你可以创建任何之后通过 AgentExecutor 发布出去。 + +##### 4.1.2 卡片提供 + +```java +@ApplicationScoped +public class AgentCardProducer { + + @Produces + @PublicAgentCard + public AgentCard agentCard() { + try (InputStream is = getClass().getResourceAsStream("/agent/agent.json")) { + if (is == null) { + throw new RuntimeException("agent.json not found in resources"); + } + + // Read the JSON file content + String json = new String(is.readAllBytes(), StandardCharsets.UTF_8); + + // Use the SDK's built-in mapper to convert JSON string to AgentCard record + return Utils.OBJECT_MAPPER.readValue(json, AgentCard.class); + + } catch (Exception e) { + throw new RuntimeException("Failed to load AgentCard from JSON", e); + } + } + +} +``` + +**/agent/agent.json** + +```java +{ + "capabilities": {"streaming": true}, + "defaultInputModes": ["text/plain"], + "defaultOutputModes": ["application/json"], + "description": "一个专门检查数字是否为素数的智能体。它可以高效地确定单个数字或数字列表的素性。", + "name": "check_prime_agent", + "skills": [ + { + "id": "prime_checking", + "name": "Prime Number Checking", + "description": "使用高效的数学算法检查列表中的数字是否为素数", + "tags": ["mathematical", "computation", "prime", "numbers"] + } + ], + "preferredTransport": "JSONRPC", + "url": "http://localhost:9090", + "version": "1.0.0" +} + +``` + +- 这里要构建一个智能体卡,A2A 的协议中,把服务包装成一个卡片的概念。 +- agent.json 配置的是 `Agent.ROOT_AGENT` 智能体的信息。 +- 如果你之前学习过小傅哥的 AI MCP 网关项目,会对 JSONRPC 有印象, MCP 协议和 A2A 协议,都是走到 JSONRPC 标准进行的通信。 + +#### 4.2 客户端 + +##### 4.2.1 构建端 + +```java +public final class A2AAgent { + + private static final Random RANDOM = new Random(); + + private static final OpenAiApi openAiApi = OpenAiApi.builder() + .baseUrl("https://apis.****.cn") + .apiKey("sk-tIYdEUUnMqKX3bRf756a31449a4942***需要配置你的key") + .completionsPath("v1/chat/completions") + .embeddingsPath("v1/embeddings") + .build(); + + private static final ChatModel chatModel = OpenAiChatModel.builder() + .openAiApi(openAiApi) + .defaultOptions(OpenAiChatOptions.builder() + .model("gpt-4.1") + .build()) + .build(); + + @SuppressWarnings("unchecked") + public static ImmutableMap rollDie(int sides, ToolContext toolContext) { + ArrayList rolls = + (ArrayList) toolContext.state().computeIfAbsent("rolls", k -> new ArrayList<>()); + int result = RANDOM.nextInt(Math.max(sides, 1)) + 1; + rolls.add(result); + return ImmutableMap.of("result", result); + } + + public static final LlmAgent ROLL_AGENT = + LlmAgent.builder() + .name("roll_agent") + .model(new SpringAI(chatModel)) + .description("处理不同面数骰子的投掷。") + .instruction( + """ + 当被要求掷骰子时,始终调用 roll_die 工具并指定面数(如果未指定,默认为 6)。不要编造结果。 + """) + .tools(ImmutableList.of(FunctionTool.create(A2AAgent.class, "rollDie"))) + .build(); + + public static LlmAgent createRootAgent(String primeAgentBaseUrl) { + // 远程 agent + BaseAgent primeAgent = createRemoteAgent(primeAgentBaseUrl); + + // 本地 agent + return LlmAgent.builder() + .name("root_agent") + .model(new SpringAI(chatModel)) + .instruction( + """ + 你可以在本地掷骰子,并将素数检查委托给远程的 prime_agent。 + 1. 当用户要求掷骰子时,将请求路由给 roll_agent。 + 2. 当用户要求检查素数时,委托给 prime_agent。 + 3. 如果用户要求先掷骰子然后检查,先调用 roll_agent,然后将结果传给 prime_agent。 + 在讨论素数之前,始终先简述骰子结果。 + """) + .subAgents(ImmutableList.of(ROLL_AGENT, primeAgent)) + .build(); + } + + private static BaseAgent createRemoteAgent(String primeAgentBaseUrl) { + + String agentCardUrl = primeAgentBaseUrl + "/.well-known/agent-card.json"; + AgentCard publicAgentCard = + new A2ACardResolver(new JdkA2AHttpClient(), primeAgentBaseUrl, agentCardUrl).getAgentCard(); + + Client a2aClient = + Client.builder(publicAgentCard) + .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) + .clientConfig( + new ClientConfig.Builder() + .setStreaming(publicAgentCard.capabilities().streaming()) + .build()) + .build(); + + return RemoteA2AAgent.builder() + .name(publicAgentCard.name()) + .a2aClient(a2aClient) + .agentCard(publicAgentCard) + .build(); + } + +} +``` + +- createRootAgent 是构建入口,一个是创建 createRemoteAgent 远程智能体,一个是 `LlmAgent.builder()` 构建本地智能体。之后在构建本地智能体的时候,通过 subAgents 把远程智能体填充到本地的智能体里去了。这个编排的方式有多种多样的。 +- createRemoteAgent 远程构建,这是固定协议路径 `/.well-known/agent-card.json`拿到智能体卡片以后(一个卡片上有各类的信息),之后通过 a2aClient 创建客户端,在通过 RemoteA2AAgent 完成本地智能体的转换。 + +##### 4.2.2 使用端 + +```java +public final class A2AAgentRun { + private final String userId; + private final String sessionId; + private final Runner runner; + + public A2AAgentRun(BaseAgent agent) { + this.userId = "test_user"; + String appName = "A2AAgentApp"; + this.sessionId = UUID.randomUUID().toString(); + + InMemoryArtifactService artifactService = new InMemoryArtifactService(); + InMemorySessionService sessionService = new InMemorySessionService(); + this.runner = + new Runner(agent, appName, artifactService, sessionService, /* memoryService= */ null); + + ConcurrentMap initialState = new ConcurrentHashMap<>(); + var unused = + sessionService.createSession(appName, userId, initialState, sessionId).blockingGet(); + } + + // ... 省略部分 + + public static void main(String[] args) throws InterruptedException { + BaseAgent agent = A2AAgent.createRootAgent("http://localhost:9090"); + A2AAgentRun a2aRun = new A2AAgentRun(agent); + + List events = + a2aRun.run("掷一个6面的骰子。").toList().timeout(90, TimeUnit.SECONDS).blockingGet(); + + events.forEach(A2AAgentRun::printOutEvent); + + events = + a2aRun.run("这是素数吗?").toList().timeout(90, TimeUnit.SECONDS).blockingGet(); + + events.forEach(A2AAgentRun::printOutEvent); + } + +} +``` + +- A2AAgentRun 测试入口,连接远程的智能体,之后做相关的调用验证。 + +## 三、测试验证 + +### 1. 前置准备 + +1. IntelliJ IDEA 右侧的 maven 点击执行 clean -> install 构建 +2. 通过命令启动服务,`mvn quarkus:dev -pl xfg-dev-tech-app` + +### 2. 访问服务 + +#### 2.1 服务首页 + +
+ +
+ +- 地址:[http://localhost:9090/q/dev-ui/welcome](http://localhost:9090/q/dev-ui/welcome) +- 说明:访问首页,localhost:9090 会看到上面的地址信息,这个是 a2a 协议的入口。 + +#### 2.2 服务协议 + +
+ +
+ +- 地址:[http://localhost:9090/.well-known/agent-card.json](http://localhost:9090/.well-known/agent-card.json) +- 说明:点击 agent-card.json 可以看到具体的服务协议信息。 + +### 3. 调用验证 + +
+ +
+ +- 点击运行,你可以看到它在进行多个智能体的调用(可能模型原因不准,但核心点在于多个智能体的调用)。 +- 好啦,到这关于 A2A 整个内容就演示完了,可以时刻关注 google adk a2a 协议的迭代,这部分内容后续还会有一些调整。 + diff --git a/docs/md/road-map/agent-skill.md b/docs/md/road-map/agent-skill.md new file mode 100644 index 000000000..123e16dd1 --- /dev/null +++ b/docs/md/road-map/agent-skill.md @@ -0,0 +1,226 @@ +--- +title: agent-skills +lock: need +--- + +# Agent Skill,你记一下,我做如下部署调整! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +skill 是什么?它像是一本技能书📚,把一阳指(`mcp/py/shell/js`)和狮吼功(`prompt`)合成了一整招。缩短了从用户把提示词发给AI客户端,进行分析,决策,再到 mcp 执行的过程,**让诉求直达结果**,token 减少了,幻觉减少了! + +
+ +
+ +随着 LLM 大模型能力的不断提升,并与 RAG、MCP、Skill 的结合,使得 Agent 智能体与完整的计算机环境(Computer/Phone)交互成为可能。这个过程中,一方面不断产生新的技术方案,一方面又不断的优化设计。就像 Skill 的出现,它不是替代 MCP,而是更准确的使用 MCP 能力。 + +接下来,小傅哥就带着大家使用一波 skill,让小伙伴们可以在 opencode、trae.ai,以及基于 Spring AI 也可以使用上 skill 能力。 + +## 一、skill 和 prompt + mcp + +如图,演示了一段 skill 的编写案例; + +
+ +
+ +- 场景:案例中体现的是,对电脑性能检测后,用一段下达命令的方式,告知用户如何优化电脑性能。 +- 重点:如果不使用 skill,则需要描述一大段话术,让 ai 自己完成对用户场景诉求的分析,并按照步骤来调用对应的各个 mcp 服务(没有 skill 则需要把各类内容,都包装为 mcp 服务)。这个过程是比较消耗 token 的,也可能有不小的幻觉。现在有了 skill,我们可以适当的完整的写一段诉求文档,文档里嵌入可执行的脚本/mcp服务,让执行更可靠。 +- 用途:那都有哪些场景可以写 skill 技能书呢?🤔 如;互联网公司里的系统巡检,在接收到报警日志后,拿到一个报警的系统和接口信息,之后用 skill 技能书,分别采集出对应的系统配置、上线日志、数据库/缓存情况、运营操作记录、全链路监控上的接口耗时情况等。之后在根据我们日常排查问题的时候经验,编写过程步骤,这样会更加准确。 + +> 所以,不是 skill、mcp 谁替代谁,而是 skill 对 mcp 进行增强,让 ai 执行时更加可靠。 + +## 二、配置使用 + +首先,像是市面上的 claude code、opencode 这些软件,都是支持了 skill 技能书配置使用的,如果遇到一些软件暂时还不支持 skill,或者自己使用 spring ai、langchain4j、google adk 构建的智能体时候需要使用 skil 技能,则可以通过 skillport-mcp 来使用 skill 配置。 + +这里小傅哥分别演示下 opencode、trae.ai + mcp、spring ai + google adk + mcp 的方式使用 skill; + +### 1. 测试工程(skill) + +
+ +
+ +- 地址:[https://github.com/fuzhengwei/xfg-dev-tech-agent-skills](https://github.com/fuzhengwei/xfg-dev-tech-agent-skills) +- 说明: + - 工程里 `docs/skills` 下面就是一个个技能书,battle-plan、pdf,每一个技能书下都必须有一个 SKILL.md 文件,作为入口。这个文件,可以描述 prompt 提示词,以及在提示词中明确给出可执行的脚本(py\shell\js)和可参考的文档。 + - 此外,在 xfg-dev-tech-app 下,test 里编码的是 SpringAiToolTest 测试技能书案例。 + +### 2. opencode 使用 + +- 文档:[https://opencode.ai/docs/skills/](https://opencode.ai/docs/skills/) +- 安装:[https://bugstack.cn/md/road-map/ai-ssh-opencode.html](https://bugstack.cn/md/road-map/ai-ssh-opencode.html) - `做好了安装脚本,方便小白伙伴使用` + +#### 2.1 配置skill + +```java +fuzhengwei@fuzhengweideMacBook-Pro-2 skill % ls +battle-plan +fuzhengwei@fuzhengweideMacBook-Pro-2 skill % pwd +/Users/fuzhengwei/.opencode/skill +fuzhengwei@fuzhengweideMacBook-Pro-2 skill % cd battle-plan +fuzhengwei@fuzhengweideMacBook-Pro-2 battle-plan % ls +reference.md scripts SKILL.md +fuzhengwei@fuzhengweideMacBook-Pro-2 battle-plan % +``` + +进入到 opencode 配置文件下,如果是 linux 一般会放到 `/root/.config/opencode/` 下。首先你要进入到这个 opencode 配置文件夹,之后在这个文件夹添加一个 skill,再之后就在 skill 下创建你的具体的技能书了。现在你可以把 xfg-dev-tech-agent-skills 案例工程的技能书,battle-plan 放到 skill 里。 + +#### 2.2 开启skill + +```java +fuzhengwei@fuzhengweideMacBook-Pro-2 ~ % cd /Users/fuzhengwei/.opencode +fuzhengwei@fuzhengweideMacBook-Pro-2 .opencode % ls +bin node_modules package.json +bun.lock opencode.json skill +fuzhengwei@fuzhengweideMacBook-Pro-2 .opencode % cat opencode.json +{ + "permission": { + "skill": { + "pr-review": "allow", + "internal-*": "deny", + "experimental-*": "ask", + "*": "allow" + } + }, + "$schema": "https://opencode.ai/config.json" +}% fuzhengwei@fuzhengweideMacBook-Pro-2 .opencode % +``` + +- 注意 `opencode.json` 需要配置下 `"*": "allow"` + +#### 2.3 使用skill + +
+ +
+ +- 提问:`基于 skill 解答,电脑性能优化` +- 说明:这里的`电脑性能优化`就是 skill 工具名称的描述。 + +### 3. trae.ai + mcp + skill + +#### 3.1 工具说明 + +工具:[https://github.com/gotalab/skillport](https://github.com/gotalab/skillport) + +目前还有不少 AI Agent 智能体,在底层设计上,还不支持直接使用 skill,也包括一些 ai 组件框架,也都没有 skill 的直接支持。那么这里要引入一个 skillport-mcp 服务来解决。借助 mcp 能力,使用 skill。 + +#### 3.2 工具安装 + +```java +# 需要安装 python3 +pip3 config set global.index-url http://mirrors.aliyun.com/pypi/simple/ +pip3 install uvx +``` + +- 安装 skillport 前,要确保本地安装了 pyhton/python3 环境。之后有 uvx 的安装。 + +```java +pip3 install skillport +# or: uv tool install skillport +``` + +- 如果安装过程中遇到一些失败的问题,可以用 trae.ai 里面执行安装,之后把报错拖进去提问。 + +#### 3.3 mcp 配置 + +
+ +
+ +```java +{ + "mcpServers": { + "skillport": { + "command": "uvx", + "args": ["skillport-mcp"], + "env": { "SKILLPORT_SKILLS_DIR": "~/.skillport/skills" } + } + } +} +``` + +- 这里你要配置下自己 skill mcp 服务,到你的 trae.ai 中。确保一定安装好了 python 环境,可以执行 `pip3 install skillport` 安装。 + +#### 3.4 工具使用 + +
+ +
+ +当你选择 Builder with MCP(涵盖了skillport-mcp),之后提问 `基于 skill 解答,电脑性能优化` 那么就可以得到上面的命令了。 + +### 4. spring ai + skill + +```java +public class SpringAiToolTest { + + private static final Logger log = LoggerFactory.getLogger(SpringAiToolTest.class); + + public static void main(String[] args) { + OpenAiApi openAiApi = OpenAiApi.builder() + .baseUrl("https://apis.itedus.cn") + .apiKey("sk-efen7WX8Q8vGvBps3f7c9a34578d41BbBc508dC5Df33A9Fb") + .completionsPath("v1/chat/completions") + .embeddingsPath("v1/embeddings") + .build(); + + ChatModel chatModel = OpenAiChatModel.builder() + .openAiApi(openAiApi) + .defaultOptions(OpenAiChatOptions.builder() + .model("gpt-4.1") + .toolCallbacks(new ArrayList<>() {{ + addAll(List.of(sseMcpClient())); + }}) + .build()) + .build(); + +// String call = chatModel.call("你哪有哪些 skill 工具能力"); + String call = chatModel.call("基于 skill 解答,电脑性能优化"); + + log.info("测试结果:{}", call); + + } + + /** + * https://github.com/gotalab/skillport + * pip3 config set global.index-url http://mirrors.aliyun.com/pypi/simple/ + * pip3 config set install.trusted-host mirrors.aliyun.com + * pip3 config list + * pip3 install uvx + */ + public static ToolCallback[] sseMcpClient() { + ServerParameters stdioParams = ServerParameters.builder("uvx") + .args("skillport-mcp") + .env(new HashMap<>() {{ + put("SKILLPORT_SKILLS_DIR", "/Users/fuzhengwei/coding/gitcode/KnowledgePlanet/road-map/xfg-dev-tech-agent-skills/docs/skills"); + }}) + .build(); + + McpSyncClient mcpSyncClient = McpClient.sync(new StdioClientTransport(stdioParams, new JacksonMcpJsonMapper(new ObjectMapper()))) + .requestTimeout(Duration.ofSeconds(35000)).build(); + + McpSchema.InitializeResult initialize = mcpSyncClient.initialize(); + + return SyncMcpToolCallbackProvider.builder().mcpClients(mcpSyncClient).build() + .getToolCallbacks(); + } + +} +``` + +- 在 Spring AI 程序中,添加 `skillport-mcp` 服务,之后在 ChatModel 模型里,使用 mcp 服务。 +- 如果你正在开发一些 AI Agent,那么也可以把 `skillport-mcp` 配置进去使用。如小傅哥带着做 [AI Agent 智能体项目](https://bugstack.cn/md/project/ai-knowledge/ai-knowledge.html) 你现在可以加进去更多的扩展操作了。 + + + diff --git a/docs/md/road-map/ai-ssh-opencode.md b/docs/md/road-map/ai-ssh-opencode.md new file mode 100644 index 000000000..d7c22695a --- /dev/null +++ b/docs/md/road-map/ai-ssh-opencode.md @@ -0,0 +1,229 @@ +--- +title: ai ssh opencode +lock: need +--- + +# ai ssh opencode 命令行工具 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获! + + + +大家好,我是技术UP主小傅哥。 + +天才般的发明,**ai ssh 命令行工具**,让 ai 的使用不只局限在 `ai 对话提问`、`ai idea 辅助编码`,也可以直接让操作系统具备 ai 能力。其实这才是我一直想要的东西!😄 + +
+ +
+ +**ai 正在改变产品设计!** + +2025年,是 ai agent 智能体爆发的一年,它所提效的接入方式可以分三层来看; + +先是中间这一层,是 ai agent 接入服务和软件,像是大家使用的 trae.ai 或者小傅哥分享过的 [draw.io + ai](https://bugstack.cn/md/road-map/draw.io.html),以及各个互联网公司用 ai 提效做的一些场景客服,系统巡检,日志分析等。 + +之后上面这一层,是从用户视角,模拟用户行为使用软件,而不是直接接入到软件api上。它使用的方式是 AutoGLM-Phone-9B 手机模型,以 ADB 或者无障碍模式,让手机可以接收用户指令,完成操作。如;`打开京东,搜索东北老式麻辣烫,加入购物车,以默认地址,进行支付购买。下单支付完成后,微信发给xxx告诉,她预计送达时间。` 如果感兴趣,可以基于这篇文章进行实践。[《手机 + agent,这是要掀桌子!》](https://bugstack.cn/md/algorithm/model/autoglm-phone-agent.html) + +然后底下这一层,是从系统层面,不再依赖于直接对接某个软件,某个api,而是以系统层面直接操作软件,或者完成整个行为动作。如,在云服务器/本地,配置好 jdk、maven、docker 环境,之后帮我拉取 git clone xxx 仓库代码,本地完成 maven 构建和启动。以及在遇到问题时候,让 ai 直接检索并处理都是非常可以的。 + +好,那接下来,小傅哥给大家分享下,如何安装一个 ai ssh 工具(没有这个教程,很多人是安装不上的!)。 + +>🧧 文末提供了小傅哥所有编程实战项目获取方式,一次加入即可获得19个已完结的实战项目,也有非常多的 AI 类项目,一定要补充学习! + +## 一、工具介绍 + +ai ssh 是命令行工具,可以安装到 Mac、Windows、Linux 上,以通过 terminal(终端)直接操作系统进行使用。它的场景也包括你打开的 IntelliJ IDEA 下面的 terminal 终端中使用,这样就天然的嵌入到了 IntelliJ IDEA 中了,非常方便。 + +目前这类的 ai ssh 命令行工具软件也非常多,包括;[opencode.ai](https://opencode.ai/)、[claude](https://claude.com/product/claude-code)、[openai codex](https://github.com/openai/codex)、[阿里千问 - qianwen code](https://github.com/QwenLM/qwen-code),都出了对应的软件。 + +在整体体验后,效果还是都不错的,这里是 opencode 的终端使用截图; + +
+ +
+ +- opencode 默认提供了一些免费模型,可以输入 `/models` 进行选择。 +- 另外还可以通过配置文件,添加其他模型,如 claude 模型、openai 模型、小米模型等。 + +## 二、软件安装 + +以下软件安装,会需要用到 gcc、nodejs 20+ 版本,建议安装 Ubuntu 24 版本,可以不需要折腾系统环境。 + +### 1. 脚本说明 + +这软件好用是挺好用,但它的源都在 Github 上,很多伙伴在执行官网脚本 `curl -fsSL https://opencode.ai/install | bash` 是安装不上的。所以,小傅哥做了一个对应的脚本,方便大家更加简化的安装使用。 + +
+ +
+ +- 脚本(gitcode):[https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install](https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install) +- 脚本(github):[https://github.com/fuzhengwei/xfg-dev-tech-docker-install](https://github.com/fuzhengwei/xfg-dev-tech-docker-install) + +### 2. 脚本下载 + +```java +git clone https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install.git +``` + +- 你可以通过命令的方式把脚本拉取到本地电脑或者云服务器上。 + +### 3. 脚本授权 + +```java +find . -name "*.sh" -type f -exec chmod +x {} \; +``` + +- 全部授权 + +```java +chmod +x terminal.sh +``` + +- 指定授权 + +### 4. 执行安装 + +
+ +
+ +```java +./terminal.sh +``` + +- 执行安装时,选择1,opencode code,这个是比较推荐的。 +- 无论是 Windows、Mac、Linux 都可以使用这个脚本进行安装,我已经做好了对应的脚本。 +- 安装完成后,需要输入 `opencode` 之后 Enter(回车)进入到系统中。如果提示 opencode 不是有效的命令,可以检查是否安装过程中有个提示 `source .../bashrc` 可以自行执行刷新。 + +## 三、软件配置 + +### 1. 命令使用 + +
+ +
+ +
+ +
+ +- `/init` - 创建/更新 Agents.md" +- `/review` - 检查变化" +- `/new` - 创建新的会话" +- `/models` - 选择模型" +- `/agents` - 智能体方式" +- `/session` - 会话列表" +- `/status` - 查看状态" +- `/mcp` - 选择mcp服务" +- `/theme` - 选择主题" +- `/editor` - 编辑" +- `/connect` - 链接模型提供者" +- `/help` - 帮助" +- `/commands` - 命令" +- `/exit` - 调试模式" + +> 这些可能会随着版本更新而调整,你可以依次尝试下。 + +### 2. 配置模型(自定义 - 可选) + +
+ +
+ +
+ +
+ +```java +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "my-model-openai": { + "npm": "@ai-sdk/openai-compatible", + "name": "OpenAPI", + "options": { + "apiKey": "你的apikey", + "baseURL": "https://你的baseURL/v1" + }, + "models": { + "gpt-4.1": { + "name": "gpt-4.1" + } + } + }, + "my-model-glm": { + "npm": "@ai-sdk/openai-compatible", + "name": "GLMAPI", + "options": { + "apiKey": "你的apikey", + "baseURL": "https://open.bigmodel.cn/api/paas/v4" + }, + "models": { + "glm-4.7": { + "name": "glm-4.7" + } + } + } + }, + "model": "my-model-openai/gpt-4.1" +} +``` + +- 如果你想自己更换下模型,比如使用 openai 的或则 claude 的,那么需要你在脚本下的 terminal/opencode.json 进行更换,之后执行 `./opencode.json.sh` 进行创建。 +- 如果先执行了 ``./opencode.json.sh`` 之后想更换配置的模型,则可以通过 vim 命令,编辑 `/root/.config/opencode/opencode.json` +- 其他的还有一些像是 mcp 的配置,可以参考官网(避免调整了配置错),[https://opencode.ai/docs/mcp-servers/](https://opencode.ai/docs/mcp-servers/) + + +## 三、软件使用 + +### 1. Linux + +#### 1.1 构建项目 + +
+ +
+ +#### 1.2 安装软件 + +
+ +
+ +#### 1.3 巡检系统 + +
+ +
+ +#### 1.4 编写文件 + +
+ +
+ +>通过命令操作云服务器是非常便捷的,尤其是很多小白伙伴,有了这个可以说是如小白虎添翼!打开思路,你可以在更多地方使用上,尤其哪些环境安装都困难的伙伴。 + +### 2. Mac/Windows + IntelliJ IDEA + +
+ +
+ +- 在本地电脑,除了可以像 Linux 举例那种安装和检查各类软件,也可以直接在 IntelliJ IDEA 开启,之后管理你的项目。 +- 尤其是很多伙伴,拿到一个项目,不知道里面都是什么,也不清楚脚本能干啥,那你都可以使用 opencode 帮你解决。 + +### 3. IPad Pro + +
+ +
+ +虽然 IPad Pro 没啥开发类软件,但如果你使用的是云服务器、Nas等,这些软件里安装 opencode,那么你也可以在 IPad Pro 安装 [termius.com](https://termius.com/) SSH 工具,通过 SSH 工具操作部署了 opencode 的 Linux 系统。 + +现在日常出门,带着 IPad Pro 也是可以处理一些小的开发的维护的,非常方便。IPad Pro + Nas 嘎嘎舒服! diff --git a/docs/md/road-map/aigc.md b/docs/md/road-map/aigc.md new file mode 100644 index 000000000..613830d63 --- /dev/null +++ b/docs/md/road-map/aigc.md @@ -0,0 +1,173 @@ +--- +title: AiGC +lock: need +--- + +# 入局AiGC,分币没赚!咋整滴? + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +AiGC 入局后,连更一周小说,分币不赚,还被催更`擦边小故事`!我把这当做,不是 AiGC 入局,而是跳河!如果有想做这个方向的,可以先冷静下,看看自己适合不。 + +
+ +
+ +最近一段时间受不少 AiGC 类广告的影响,`文生图`、`文生视频`、`故事成片`,在家动动手就能赚钱。一个视频都几千、几万的点赞。 + +听起来做这个也挺简单,让 DeepSeek 生成口播故事,把故事放到 AiGC 软件(现在一堆),选择故事成片,在把视频上传到抖音、快手、头条,完活!**就是不赚钱!** + +>本文会分享 AiGC 视频制作的过程和注意点。另外作为技术人员,我们可以自己部署一个文生视频的软件服务,以及了解相关的 API 技术,也为后续自己开发 AiGC 做积累。 + +## 选择一个赛道!下场! + +首先,你可以想好一个创作的主题,如果有多个主题,可以分别投放到不同的软件平台,尽量先垂直一个系列更新,如果一直没有流量,后面可以干掉重新换主题来。 + +主题可以包括;`婆媳关系`、`中老年相亲`、`农村故事`、`鬼故事`、`好看的景色+音乐`、`儿童诗歌`,也就是你尽量要找一些高频有大量客群的场景,只要推荐到这样的人群标签下,视频的播放量还是很高的。 + +
+ +
+ +但不要想着这样就能赚钱,如果只是试试水,基于 DeepSeek 生成关键信息的故事(主题、背景、人物、故事线),再把故事放到文生视频完成后上传即可。**但这样做好,基本属于徒劳!** + +在我尝试推了几个鬼故事后,没有看到什么流量,这时候有个哥们加我,说我这样推没用的。我也好奇的去加了下关注,他是专门做鬼故事系列的,每个内容都很精良,而且属于 TM 鬼故事 + 擦边!还备注上(收徒)! + +
+ +
+ +所以,从这块开始,我发现要想让一个内容有较不错的流量,需要以下几点; + +1. 故事主体框架是明确、不能纯用 DeepSeek 来写。故事可以基于一些比较火的小说来制造。看过越多小说的,做这方面越有优势。 +2. 故事内容太干净了也没有人看,在 DeepSeek + 文生视频允许的范围内,你都可以“肆意”创作。 +3. 如果你时间更多,也更想做好,那么要对生成的视频,逐帧剪辑,也可能要多生成几次来使用。并制造好吸引人的封面! +3. 长期主义,1~3,你可以都不用考虑。而是真的一点点来结合 AI 来写长期有意义的故事。 + +**不过,就算以上这样你都做了,也可能一点流量都没有!**😂 + +## AiGC 软件工具 + +在有了内容以后,就是 AI 生成视频了。AI 生成视频的软件有很多,基本也都是付费的。😂 所以说,你不一定赚不赚钱,但 AI 创作课程和 AI 软件是赚钱。 + +我体验了,可灵 AI、录咖 AI,还有抖音剪映自带的 AI 生成类工具。可灵 AI 适合文生图片、数字人口播,剪映 AI 适合文生视频。因为我本身就需要日常剪辑视频,开了剪映会员,所以可以直接使用。可灵 AI 是少量付费体验了下。 + +
+ +
+ +- 剪映 APP 有个 AI 图片成片,进入后选择 AI 故事成片。 +- 你可以把 DeepSeek/AI 生成口播故事(2000字 - 3000字),放进来转换即可。完成后,把视频下载下来,上传到你的各个平台。 + +## 我以为一分钱也赚不到的时候! + +**在我折腾了快一周,以为分币赚不到的时候,来活了!** + +有个“粉丝”,关注了我。给我讲,接活不。我问啥活,她说,关注这个没事主播,点赞视频和收藏,完成后给6块钱。我没想到,她真给! + +
+ +
+ +o(╥﹏╥)o 这是我做 AIGC 的第一笔收入!虽然,它看起来不正常! + +晚上,这个粉丝小姐姐,问我还做不。我说行,她说你要大量做,要下载一个软件“魅信”。我去TM的,我是一个程序员,能信你这!不是“魅信”可怕,是你给我来个自动录屏,整走我点信息不完犊子了。 + +所以,我给这假粉丝讲!我是一个程序员,我对这个不放心,我不做了!没过多久,我就看XXX视频平台给这个假粉丝账号封了,没法查看完整聊天。以至于我只能截图这一丢丢,给大家看。 + +
+ +
+ +- 因为它的账号被封了,已经看不到内容了。只能通过录制视频,在截取一下。不过截取不全了。 +- 所以,如果你遇到这种的,赚个6块就跑吧🏃🏻‍! + +## 回到本质,仍然是技术! + +说到底,其实做各类东西都需要大量的时间精力投入,也有努力 + 运气,才可能有机会做成。想随随便便加个“副业社群”,不一定都能赚到什么钱。 + +就像你自己,如果用了大量的核心知识储备,那么你所用的这些产品就是工具,反之他们就不是工具,而是收割你的工具。 + +所以,作为研发人员,我们储备多的是技术知识,可以依赖于技术底层的积累,增强对工具的实现技术了解。看看这样的 AIGC 工具是如何实现的,能部署一个深入了解不,看看API接口从哪调用的,以后我们自己搞下是不更好。 + +### 1. 软件部署 + +有这么一个开源软件「利用AI大模型,一键生成高清短视频 Generate short videos with one click using AI LLM.」,可以通过 Docker 部署体现。 + +代码:[https://github.com/harry0703/MoneyPrinterTurbo](https://github.com/harry0703/MoneyPrinterTurbo) + +**docker-compose.yml** + +```java +services: + webui: + image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/moneyprinterturbo:latest + container_name: MPTwebui + ports: + - "8501:8501" + restart: unless-stopped + logging: + driver: "json-file" + options: + max-size: "2m" + command: > + streamlit run /MoneyPrinterTurbo/webui/Main.py + --browser.serverAddress=127.0.0.1 + --server.enableCORS=True + --browser.gatherUsageStats=False + api: + image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/moneyprinterturbo:latest + container_name: MPTapi + ports: + - "8080:8080" + restart: unless-stopped + logging: + options: + max-size: "2m" + command: python3 /MoneyPrinterTurbo/main.py +``` + +- 通过 Docker Compose 脚本,执行软件安装。`docker-compose -f docker-compose.yml up -d` 来执行安装。 +- 安装后访问 ip:8501 + +### 2. 访问服务 + +
+ +
+ +
+ +
+ +- 首先,需要点开设置。配置你的 openai 地址服务,之后配置 [Pexels API Key](https://www.pexels.com/api/key/) +- 之后,填写文案,文案也可以由 AI 工具生成复制进来。之后点击生成视频(其他选型也可以尝试更换)。 +- 最后,生成完视频,就可以扔了。这个效果基本就是体验,与剪映那个差太多了。 + +### 3. 访问API + +AIGC 相当于根据你的文案,检索/生成对应图片,好的AI产品会设置分镜头不同视角的检索。在结合这些图片、视频资源合成你最后要生成的视频效果。 + +如:[https://www.pexels.com/](https://www.pexels.com/) 就是一个图片视频资源库,你可以免费申请一个 API,之后使用它来生成图片。它的官网有对应的文档描述使用。举例如下; + +
+ +
+ +```java +curl -H "Authorization: 8aHBe0CyGtMZVMji32RVEvgzIRNx38rrkHlbp9HK*****申请你的" \ + "https://api.pexels.com/v1/search?query=美女&per_page=1" +``` + +
+ +
+ +- 调用接口返回的 JSON 可以查看图片信息,基本你要的内容还是可以大部分时候准确获取的。 +- 如果感兴趣,还可以深入体验下它的 API。 + diff --git a/docs/md/road-map/aliyun-workbench.md b/docs/md/road-map/aliyun-workbench.md new file mode 100644 index 000000000..310ab443e --- /dev/null +++ b/docs/md/road-map/aliyun-workbench.md @@ -0,0 +1,233 @@ +--- +title: Docker 镜像构建 - Aliyun +lock: need +--- + +# Docker 镜像构建 - Aliyun + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +对于搞编程开发的伙伴来说,我一直都推荐使用 Mac 电脑,因为 Windows 电脑除了相对省点钱,其他的什么也不省!为啥?那我 Windows 电脑推沟里? + +
+ +
+ +**大厂更多的都是给程序员👨🏻‍💻配Mac!** + +其实到也不是 Windows 不好,只是在编程开发中的环境配置,要有太多的额外的兼容问题。因为 Windows 是一个系统,这个系统被各个厂商使用,安装到自己家的电脑上。因此一个软件安装后,不同的机器,都可能在一些细节功能上,有自己的差异化处理方案。就像 Docker 安装,Mac 电脑直接安装即可,Windows 不是安装虚拟机,就是搞个 wsl2,不少小白基本就在这崩溃了。 + +相对说,Mac 电脑就好的多,因为人家的系统只给自己家的电脑使用。所以各类软件的安装和使用也不会有那么多的适配问题了。另外 Mac 电脑也等同于是在 Linux 上做开发,你的所有编程中使用的命令,几乎就是无差别的可以在云环境 Linux 执行。因此,Mac 电脑除了不省钱,其他的都省;省时、省心、省力。 + +不过,Windows 电脑也不能推沟里呀!所以,我们要想点办法,让一些如 Docker 的环境安装和镜像构建,让外部系统解决。不就可以了噻! + +>接下来,小傅哥就教大家搞一下这个事情。—— 学到手的全是技术! + +## 一、DevOps 流水线 + +DevOps 流水线,是一种可持续集成交付的手段。用户可以使用流水线自定义编排项目发布过程中所涉及的代码打包、单元测试、自动部署等各项阶段。 通过一系列自动化任务的组合解决日常开发工作中繁琐而重复的任务。 + +
+ +
+ +官网(JD):[https://docs.jdcloud.com/cn/devops/application-scenarios](https://docs.jdcloud.com/cn/devops/application-scenarios) + +--- + +市面上也有很多的免费的可持续交付工具,方便我们自己部署项目使用。如 [Github Actions](https://bugstack.cn/md/road-map/github-actions-workflows.html)、[buddy.works](https://bugstack.cn/md/road-map/buddy.html)、[Jenkins](https://bugstack.cn/md/road-map/jenkins.html),这些已经在 [bugstack.cn](https://bugstack.cn/) 编程路书(发布部署)中分享。今天小傅哥再分享一个阿里云的 DevOps 流水线操作,实际使用体验效果还不错。 + +## 二、云效工作台介绍 + +本次案例会涉及到使用阿里云效平台的 `代码管理`、`流水线配置`、`容器镜像` + +### 1. 代码&流水线 + +
+ +
+ +- 地址:[https://devops.aliyun.com/workbench](https://devops.aliyun.com/workbench) +- 说明:用于管理工程代码和配置流水线。你可以提交本地代码,也可以把其他仓库的代码导入到`代码管理`中,如;Github、Gitee、Gitlab,其他的也可以通过 url 导入。 + +### 2. 容器镜像服务 + +#### 2.1 容器申请 + +
+ +
+ +- 地址:[https://cr.console.aliyun.com/cn-hangzhou/instance/dashboard](https://cr.console.aliyun.com/cn-hangzhou/instance/dashboard) +- 说明:容器镜像,相当于代理的 [Docker Hub](https://hub.docker.com/) 可以把我们通过流水线构建的项目(SpringBoot/React/...)构建的镜像,放到容器镜像服务中。之后就可以在其他云环境或者本地环境拉取使用了。 + +#### 2.2 新建服务 + +
+ +
+ +
+ +
+ +- 这里要新建一个镜像名称,`xfg-dev-tech-aliyun-workbench` 的镜像。这个镜像为后续的流水线构建使用。 +- 创建的时候,要选择对应的仓库。可以是 Codeup 的阿里云代码库,也可以是 Github 关联地址的仓库。 + +> 再往下开始平台,你需要注册一个云校平台和容器镜像服务。 + +## 三、上传代码库 + +这部分会涉及一些 Git 的操作,这里小傅哥准备好了教程可以使用 [https://bugstack.cn/md/road-map/git.html](https://bugstack.cn/md/road-map/git.html) + +### 1. 案例工程 + +
+ +
+ +```java +# 基础镜像 openjdk:8-jre-slim 代理地址;registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:8-jre-slim +FROM registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:8-jre-slim + +# 作者 +MAINTAINER xiaofuge + +# 配置 +ENV PARAMS="" + +# 时区 +ENV TZ=PRC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# 在容器内创建目录/home/project 用于存放应用程序和相关文件 +RUN mkdir -p /home/project + +# 设置工作目录为/home/project,即后续的命令都在这个工作目录下执行。 +WORKDIR /home/project + +# 添加应用 +ADD xfg-dev-tech-app/target/xfg-dev-tech-app.jar /home/project/xfg-dev-tech-app.jar + +## 在镜像运行为容器后执行的命令 +ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS /home/project/xfg-dev-tech-app.jar $PARAMS"] +``` + +- 地址:[https://github.com/fuzhengwei/xfg-dev-tech-aliyun-workbench](https://github.com/fuzhengwei/xfg-dev-tech-aliyun-workbench) +- 说明:这里小傅哥给你准备好了一个测试工程,你可以使用验证阿里云效流水线操作。 +- 脚本:注意配置的脚本信息,如果你是新的其他的工程,可以参考配置。 + +### 2. 上传项目 + +把案例代码上传到阿里云代码库的方式有很多,可以从 Github 导入,也可以先把代码拉取到本地,在从本地上传到阿里云代码库。但两个方式都建议把代码拉取到本地代码一份,方便进行修改。 + +#### 2.1 导入代码 + +
+ +
+ +- 首先,进入案例工程地址(Github),点击 Fork 克隆到自己的仓库中。 +- 之后,在阿里云效点击导入仓库,这里可以选择从 Github 导入。导入的时候,需要填写 Access Token。创建地址:[https://github.com/settings/tokens](https://github.com/settings/tokens) +- 最后,在确认后会展示你的 Github 仓库列表,选择要导入的工程即可。 + +#### 2.2 上传代码 + +
+ +
+ +- 首先,开始操作之前,你要把提供的案例代码拉取到本地。 +- 之后,在云效代码库,新建一个代码库。新建后可以获得一个 https 提交代码库的地址。另外,要注意你还要在云效仓库个人设置里,创建一个,个人访问令牌(地址:[https://account-devops.aliyun.com/settings/profile](https://account-devops.aliyun.com/settings/profile))。 +- 最后,在自己 Intellij IDEA 菜单栏上,点击 Git 选择 Manage Remotes 添加阿里云效仓库地址,之后就可以把代码提交到阿里云效了。 + +### 3. 添加流水线 + +#### 3.1 构建操作 + +
+ +
+ +- 如图,配置构建信息。注意,☑️ 制品中包含打包路径的目录。 + +#### 3.2 添加步骤;Docker镜像构建 + +
+ +
+ +- 添加新的步骤,选择构建并推送至ACR(个人版)注意配置路径正确。 + +#### 3.3 添加步骤;邮件通知 + +
+ +
+ +- 添加一个邮件通知的插件,构建后会接收到邮件。 + +### 4. 构建镜像 + +#### 4.1 执行构建 + +
+ +
+ +- 点击运行,之后就可以构建镜像了。如果哪个节点失败了,可以点日志查看失败原因。 + +#### 4.2 构建结果 + +##### 4.2.1 邮件通知 + +
+ +
+ +- 你会收到一个来自云效构建的通知邮件。代表着构建的结果。 + +##### 4.2.2 查看镜像 + +
+ +
+ +- 构建完成镜像后,可以进入`容器镜像服务`中找到镜像。地址:[https://cr.console.aliyun.com/cn-hangzhou/instance/repositories](https://cr.console.aliyun.com/cn-hangzhou/instance/repositories) +- 之后还可以通过公网地址拉取镜像,命令:`docker pull registry.cn-hangzhou.aliyuncs.com/fuzhengwei/xfg-dev-tech-aliyun-workbench:1.0.0` + +##### 4.2.3 拉取镜像 + +
+ +
+ +```java +[root@hcss-ecs-decd ~]# docker pull registry.cn-hangzhou.aliyuncs.com/fuzhengwei/xfg-dev-tech-aliyun-workbench:1.0.0 +1.0.0: Pulling from fuzhengwei/xfg-dev-tech-aliyun-workbench +1efc276f4ff9: Already exists +a2f2f93da482: Already exists +1a2de4cc9431: Already exists +d2421c7a4bbf: Already exists +64e0330ea35f: Pull complete +4da07e374896: Pull complete +4f4fb700ef54: Pull complete +eb9d0e194679: Pull complete +Digest: sha256:a7af08fff4ea0b76184a2fad7e7ca639ab4a9ad16573480b526eda672ed8a483 +Status: Downloaded newer image for registry.cn-hangzhou.aliyuncs.com/fuzhengwei/xfg-dev-tech-aliyun-workbench:1.0.0 +registry.cn-hangzhou.aliyuncs.com/fuzhengwei/xfg-dev-tech-aliyun-workbench:1.0.0 +[root@hcss-ecs-decd ~]# docker tag registry.cn-hangzhou.aliyuncs.com/fuzhengwei/xfg-dev-tech-aliyun-workbench:1.0.0 fuzhengwei/xfg-dev-tech-aliyun-workbench:1.0.0 +[root@hcss-ecs-decd ~]# docker images +REPOSITORY TAG IMAGE ID CREATED SIZE +fuzhengwei/xfg-dev-tech-aliyun-workbench 1.0.0 df740ba425bb 24 minutes ago 221MB +``` + +- 镜像构建完成后,就可以在云服务器上拉取镜像了。 +- 好啦,到这你就可以愉快的完善了,前端构建镜像也是一样的操作。 diff --git a/docs/md/road-map/arex-test.md b/docs/md/road-map/arex-test.md new file mode 100755 index 000000000..1f281ac36 --- /dev/null +++ b/docs/md/road-map/arex-test.md @@ -0,0 +1,435 @@ +--- +title: AREX - 流量录制&回放 +lock: need +--- + +# AREX - 流量录制&回放 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在互联网大厂应用系统开发中,有一项非常重要的技术手段,保证新迭代功能的可靠性。虽然,这像技术也不是“银弹(啥都能搞定)”,但缺少这项技术,对于极其复杂的业务场景新上线功能,总感觉心里没底!—— 它就是`流量录制`和`流量回放`! + +
+ +
+ +**如何保证系统的可靠性?** + +互联网大厂toc场景,非常重视交付的可靠性,甚至大于交付的效率性。所以,在整个研发声明周期过程中,要有 PRD 评审、研发设计代码、代码评审、代码分支合并评审,以及在这个过程中还有测试人员进行全流程的验证。 + +但即使这样,面对经历了数十年迭代的系统,单工程甚至几十万行代码,极其复杂的业务系统流程,测试也是可能会出现疏漏。这种疏漏如,虽然非本次需求迭代的场景,但是其他业务场景因当前系统的一个枚举,一个参数的变动,都会影响到数十条业务。哪怕不是代码变动,仅仅是重构了小部分代码块,调整了前后顺序,当前业务无影响,但确影响了某次其他任务的跑批结果! + +一次事故,可能是扣绩效和年终奖,也可能是影响晋升提名,还可能是直接毕业🎓啦!所以,在互联网大厂班组🧱搬砖,会学到很多高级技巧,来保证系统的可靠性。 + +>关注小傅哥 [bugstack.cn](https://bugstack.c) 博客,编程路书,可以学习到非常多的互联网企业使用技能,补全自己的短板!如;系统架构、开发环境、开发技术、授权框架、常用类库、工程测试、质量监控、发布部署等。 + +## 一、说说概念 + +其实简单来讲,流量录制,核心的本质就是把线上运行的应用,在有流量请求到服务接口后,把请求接口的入参和执行的结果,都保存下来。之后流量回放,则是把这些保存下来的入参信息,在开发环境/测试环境/预发环境,进行请求,之后验证请求后的结果是否与线上录制的流量结果一致。整个的这个过程,就是流量的录制和回放。 + +但实际的操作场景要比这个过程复杂,如;录制流量的操作,要无侵入代码的,要把整个调用链路,全部录制下来,而不是单个接口。同时录制的不只是对接口的操作,还有缓存、rpc、数据库(MyBatis)、es,等各类组件兼容,都能确保可正确录制到完整数据,以便在流量回放时,可以mock掉数据接口,以此只验证功能逻辑。 + +说到,逻辑和数据,这里想到了DDD架构的领域层和基础设施层,领域层(domain)专门业务功能逻辑的,而基础设置层(infrastructure)则是提供数据的。这样有了业务功能和数据获取的分离,不让核心业务逻辑又掺杂外部接口的调用,其实维护和迭代起来,是会更加容易的。 + +## 二、讲讲原理 + +为了可以无侵入式的完成系统的流量录制和流量回放,这里引入了一个 Java Agent 字节码增强技术,通过在程序启动阶段,对工程代码的方法进行埋点。这个埋点,就等同于动态的通过 class 文件写入新的代码,新的代码可以采集到方法的出入参信息,并把这些信息发送到流量录制存储方,或者执行时进行mock接口请求结果处理。 + +这部分技术方案,小傅哥于19-20年,编写了先关的技术资料。其中包括了用于处理字节码增强技术的,asm、javassist、byte-buddy 三种框架。 + +
+ +
+ +文档:[https://bugstack.cn/md/bytecode/asm/2020-04-05-%5BASM%E5%AD%97%E8%8A%82%E7%A0%81%E7%BC%96%E7%A8%8B%5DJavaAgent+ASM%E5%AD%97%E8%8A%82%E7%A0%81%E6%8F%92%E6%A1%A9%E9%87%87%E9%9B%86%E6%96%B9%E6%B3%95%E5%90%8D%E7%A7%B0%E4%BB%A5%E5%8F%8A%E5%85%A5%E5%8F%82%E5%92%8C%E5%87%BA%E5%8F%82%E7%BB%93%E6%9E%9C%E5%B9%B6%E8%AE%B0%E5%BD%95%E6%96%B9%E6%B3%95%E8%80%97%E6%97%B6.html](https://bugstack.cn/md/bytecode/asm/2020-04-05-%5BASM%E5%AD%97%E8%8A%82%E7%A0%81%E7%BC%96%E7%A8%8B%5DJavaAgent+ASM%E5%AD%97%E8%8A%82%E7%A0%81%E6%8F%92%E6%A1%A9%E9%87%87%E9%9B%86%E6%96%B9%E6%B3%95%E5%90%8D%E7%A7%B0%E4%BB%A5%E5%8F%8A%E5%85%A5%E5%8F%82%E5%92%8C%E5%87%BA%E5%8F%82%E7%BB%93%E6%9E%9C%E5%B9%B6%E8%AE%B0%E5%BD%95%E6%96%B9%E6%B3%95%E8%80%97%E6%97%B6.html) + +### 1. 增强代码 + +```java +mv.visitVarInsn(LLOAD, startTimeIdentifier); +mv.visitLdcInsn(methodId); +if (parameterTypeList.isEmpty()) { + mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ProfilingAspect.class), "point", "(JI)V", false); +} else { + mv.visitVarInsn(ALOAD, parameterIdentifier); // 5 + mv.visitVarInsn(ALOAD, localCount); // 6 + mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ProfilingAspect.class), "point", "(JI[Ljava/lang/Object;Ljava/lang/Object;)V", false); +} +``` + +### 2. 拦截信息 + +```java +ASM类输出路径:/Users/xiaofuge/itstack/git/github.com/SQM/target/test-classes/org/itstack/test/ApiTest$1SQM.class +监控 - Begin +类名:org.itstack.test.ApiTest +方法:queryUserInfo +入参类型:["I","I"] +入数[值]:[111,17] +出参类型:Ljava/lang/String; +出参[值]:"你好,bugstack虫洞栈 | 精神小伙!" +耗时:95(s) +监控 - End + +测试结果:你好,bugstack虫洞栈 | 精神小伙! +``` + +- 以上为简要的案例代码,通过ASM字节码增强框架来对方法修改,增加日志打印信息,在执行方法时,获取出入参。 +- 字节码增强技术应用的方面非常多,如;MapStruct、非入侵的全链路监控、Lombok,甚至你用过的 IntelliJ IDEA 破解也是字节码增强技术。 + +## 三、工具介绍 + +关于流量录制和流量回放的工具是蛮多的,其中包括;[jvm-sandbox-repeater](https://github.com/alibaba/jvm-sandbox-repeater)、[MoonBox](https://github.com/vivo/MoonBox)、[arextest](https://arextest.com/) 等。 + +- jvm-sandbox-repeater,是一个基于 JVM-Sandbox 采用Java来实现的流量录制回放工具,或者可以理解为它是一个基于Java虚拟机的插件,可以直接运行中JVM中,无需对目标应用程序进行任何修改。 +- Moonbox(月光宝盒),是一个无侵入的线上流量录制 和流量回放平台,沿用了jvm-sandbox-repeater的SPI设计,并提供了大量的常用插件,同时也提供数据统计和存储能力。通过Moonbox可以实现自动化测试、线上问题追踪、和业务监控等能力 +- arextest,AREX 通过将真实的在线流量复制到测试环境进行自动化 API 测试来解决自动化测试的挑战。**作为本文分享场景工具使用。** + +**名词解释** + +- **录制**:把一次请求的入参、出参、**下游RPC、DB、缓存**等序列化并存储的过程 +- **回放**:把录制数据还原,重新发起一次或N次请求,对特定的下游节点进行MOCK的过程 +- **入口调用**:入口调用一般是应用的**流量来源**,比如http/dubbo,在调用过程中录制调用入参,返回值。回放时作为流量发起和执行结果对比依据 +- **子调用**:区别于入口调用,子调用是调用执行过程中某次方法调用。子调用在录制时会记录该方法的入参、返回值;回放时用该返回值进行MOCK +- **MOCK**:在回放时,被拦截的子调用**不会发生真实调用**,利用字节码动态干预能力,将录制时的返回值直接返回 +- **降噪**:在回放时,部分回放子调用入参或者回放流量响应结果和原始流量对比不一致字段,对这些非必要字段进行排除对比过程 + +## 四、工具使用 + +### 1. 案例工程 + +
+ +
+ +- 地址:[https://github.com/fuzhengwei/xfg-dev-tech-traffic-agent](https://github.com/fuzhengwei/xfg-dev-tech-traffic-agent) +- 如图:1~6点,说明了各个模块的用途。 +- 提示:建议使用云服务器部署流量录制&回放服务,非常方便。 + +### 2. 安装插件 + +地址:[https://chromewebstore.google.com/detail/arex-chrome-extension/jmmficadjneeekafmnheppeoehlgjdjj](https://chromewebstore.google.com/detail/arex-chrome-extension/jmmficadjneeekafmnheppeoehlgjdjj) + +
+ +
+ +- 安装插件是为了有权限访问接口。 + +### 3. 服务部署(arex) + +**前置条件**,2c4g云服务器,完成初始化Docker环境。这里有一键安装脚本,[https://bugstack.cn/md/road-map/docker-install.html](https://bugstack.cn/md/road-map/docker-install.html) + +```java +[root@iv-jdyun ~]# cd / +[root@iv-jdyun ~]# mkdir dev-ops +[root@iv-jdyun ~]# cd dev-ops +[root@iv-jdyun ~]# sudo yum install git +[root@iv-jdyun ~]# git clone --depth 1 https://github.com/arextest/deployments.git +[root@iv-jdyun ~]# cd deployments +[root@iv-jdyun ~]# docker-compose up -d +``` + +
+ +
+ +- 执行脚本安装完成后,在云服务器安全组开放端口号(出/入规则)。 +- 之后访问:http://ip:8088 首次访问会慢一些,进入后会让设置你的登录账号。 + +### 4. 启动项目 - 录制流量 + +
+ +
+ +- 首先,需要给项目工程加入一个 agent,来录制和回放。arex 的 agent jar,下载后方到工程下,lib 中。目前工程中已经下载了,如果将来有更新,可以重新下载最新的。地址:[https://github.com/arextest/arex-agent-java/releases](https://github.com/arextest/arex-agent-java/releases) +- 之后,本地项目测试验证的时候,可以先 **install**,成功之后使用 `run_application_2_agent.sh` 启动项目,这个操作会把 agent 加载到程序启动中。 + +#### 4.1 本地测试 + +```java +#!/bin/bash + +# AREX Agent 启动脚本 +# 用于在不同环境下启动应用并加载 AREX Agent + +# 设置 AREX Agent 相关参数 +AREX_AGENT_PATH="./lib/arex-agent.jar" +AREX_SERVICE_NAME="xfg-dev-tech-app" +AREX_STORAGE_HOST="115.190.107.206:8093" + +# 应用 JAR 包路径(相对于项目根目录) +APP_JAR="../../xfg-dev-tech-app/target/xfg-dev-tech-app.jar" + +# JVM 参数 +JVM_OPTS="-Xms512m -Xmx1024m" + +# 检查 AREX Agent 文件是否存在 +if [ ! -f "$AREX_AGENT_PATH" ]; then + echo "错误: AREX Agent 文件不存在: $AREX_AGENT_PATH" + echo "请确保 arex-agent.jar 文件已放置在正确位置" + exit 1 +fi + +# 检查应用 JAR 包是否存在 +if [ ! -f "$APP_JAR" ]; then + echo "错误: 应用 JAR 包不存在: $APP_JAR" + echo "请先执行 mvn clean package 构建应用" + exit 1 +fi + +echo "正在启动应用..." +echo "AREX Agent: $AREX_AGENT_PATH" +echo "Service Name: $AREX_SERVICE_NAME" +echo "Storage Host: $AREX_STORAGE_HOST" +echo "Application: $APP_JAR" +echo "" + +echo "执行配置:"$JVM_OPTS \ + -javaagent:"$AREX_AGENT_PATH" \ + -Darex.service.name="$AREX_SERVICE_NAME" \ + -Darex.storage.service.host="$AREX_STORAGE_HOST" \ + -jar "$APP_JAR" + +# 启动应用 +java $JVM_OPTS \ + -javaagent:"$AREX_AGENT_PATH" \ + -Darex.service.name="$AREX_SERVICE_NAME" \ + -Darex.storage.service.host="$AREX_STORAGE_HOST" \ + -jar "$APP_JAR" +``` + +#### 4.2 docker 镜像 + +##### 4.2.1 dockerfile + +```java +# 基础镜像 +FROM openjdk:8-jre-slim + +# 作者 +MAINTAINER xiaofuge + +# 配置 +ENV PARAMS="" + +# AREX Agent 配置 +ENV AREX_SERVICE_NAME="xfg-dev-tech-app" +ENV AREX_STORAGE_HOST="115.190.107.206:8093" + +# 时区 +ENV TZ=PRC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# 添加 AREX Agent +ARG AREX_AGENT_PATH=docs/dev-ops/lib/arex-agent.jar +ADD ${AREX_AGENT_PATH} /arex-agent.jar + +# 添加应用 +ADD target/xfg-dev-tech-app.jar /xfg-dev-tech-app.jar + +ENTRYPOINT ["sh","-c","java $JAVA_OPTS -javaagent:/arex-agent.jar -Darex.service.name=$AREX_SERVICE_NAME -Darex.storage.service.host=$AREX_STORAGE_HOST -jar /xfg-dev-tech-app.jar $PARAMS"] +``` + +##### 4.2.2 docker-compose + +```java +version: '3.8' + +services: + xfg-dev-tech-app: + image: fuzhengwei/xfg-dev-tech-app:traffic-agent-v1 + container_name: xfg-dev-tech-app + ports: + - "8091:8091" + environment: + # AREX Agent 配置 + - AREX_SERVICE_NAME=xfg-dev-tech-app + - AREX_STORAGE_HOST=115.190.107.206:8093 + # JVM 配置 + - JAVA_OPTS=-Xms512m -Xmx1024m + volumes: + # 日志目录挂载(可选) + - ./data/logs:/var/log/app + networks: + - app-network + restart: unless-stopped + +networks: + app-network: + driver: bridge + +volumes: + app-logs: + driver: local +``` + +- 此方式适用于项目部署上线。 + +### 5. 启动程序 + +```java +./bin/bash /xfg-dev-tech-traffic-agent/docs/dev-ops/run_application_2_agent.sh +``` + +```java +(base) fuzhengwei1@ZBMac-GV47H1GXD dev-ops % /bin/bash /Users/fuzhengwei1/Documents/develop/github/xfg-dev-tech-traffic-agent/docs/dev-ops/run_application_2_agent.sh +正在启动应用... +AREX Agent: ./lib/arex-agent.jar +Service Name: xfg-dev-tech-app +Storage Host: 115.190.107.206:8093 +Application: ../../xfg-dev-tech-app/target/xfg-dev-tech-app.jar + +执行配置:-Xms512m -Xmx1024m -javaagent:./lib/arex-agent.jar -Darex.service.name=xfg-dev-tech-app -Darex.storage.service.host=115.190.107.206:8093 -jar ../../xfg-dev-tech-app/target/xfg-dev-tech-app.jar +2025-06-21 17:57:25:792 [AREX] Agent-v0.4.8 starts initialization... +Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended + + . ____ _ __ _ _ + /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ +( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ + \\/ ___)| |_)| | | | | || (_| | ) ) ) ) + ' |____| .__|_| |_|_| |_\__, | / / / / + =========|_|==============|___/=/_/_/_/ + :: Spring Boot :: (v2.7.12) + +25-06-21.17:57:27.856 [main ] INFO Application - Starting Application v1.0-SNAPSHOT using Java 17.0.7 on ZBMac-GV47H1GXD with PID 96181 (/Users/fuzhengwei1/Documents/develop/github/xfg-dev-tech-traffic-agent/xfg-dev-tech-app/target/xfg-dev-tech-app.jar started by fuzhengwei1 in /Users/fuzhengwei1/Documents/develop/github/xfg-dev-tech-traffic-agent/docs/dev-ops) +25-06-21.17:57:27.858 [main ] INFO Application - The following 1 profile is active: "dev" +25-06-21.17:57:28.635 [main ] INFO TomcatWebServer - Tomcat initialized with port(s): 8091 (http) +25-06-21.17:57:28.641 [main ] INFO Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8091"] +25-06-21.17:57:28.641 [main ] INFO StandardService - Starting service [Tomcat] +25-06-21.17:57:28.642 [main ] INFO StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.75] +25-06-21.17:57:28.683 [main ] INFO [/] - Initializing Spring embedded WebApplicationContext +25-06-21.17:57:28.683 [main ] INFO ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 781 ms +25-06-21.17:57:28.913 [main ] INFO Http11NioProtocol - Starting ProtocolHandler ["http-nio-8091"] +25-06-21.17:57:28.928 [main ] INFO TomcatWebServer - Tomcat started on port(s): 8091 (http) with context path '' +25-06-21.17:57:28.935 [main ] INFO Application - Started Application in 1.575 seconds (JVM running for 3.285) +``` + +- 启动程序,会看到 arex-agent.jar 的加载,这代表是正确✅的,可以上报服务信息。 + +### 6. 流量录制 + +```java +@Slf4j +@RestController +@RequestMapping("/api/traffic") +public class TrafficController { + + @GetMapping("/query_user_age") + public Integer queryUserAge(@RequestParam("userId") String userId) { + log.info("请求参数:{}", userId); +// return getCache(); + return getDB(); + } + + // 模拟从缓存获取数据 + public Integer getCache() { + return 20; + } + + // 模拟从数据库获取数据 + public Integer getDB() { + return 21; + } + +} +``` + +
+ +
+ +- 你可以使用工程下,test-api-curl.sh 脚本访问接口,也可以其他方式请求接口。 +- 当你请求完成接口后,就可以去arex控制台检查上报的信息和流量录制的数据了。 + +### 7. 流量回放 + +#### 7.1 内网穿透 + +流量回放是从云服务器调用本地,但本地没有对外的公网IP,所以需要内网穿透,让云服务器可以调用。这里的内网穿透工具很多,可以选择;[natapp](https://natapp.cn/)、[cpolar.com](https://www.cpolar.com/) 等。 + +
+ +
+ +```java +Powered By NATAPP Please visit https://natapp.cn (Ctrl+C to Quit) + +Tunnel Status Online + +Version 2.3.9 (New Version 2.4.0) + +Forwarding http://xfg-studio.natapp1.cc -> 127.0.0.1:8091 + +Web Interface Disabled + +Total Connections 0 +``` + +- 启动后,会把本地的服务:端口,暴漏出去,通过 http 域名地址访问。 +- 注意,在natapp配置你的应用端口,如 8091,如果是其他就修改下。 + +#### 7.2 回放配置 - 正确回放 + +
+ +
+ +- 如图,填写回放配置信息。 +- 这次我们是正确回放,也就是本地程序没有任何变更。配置后点OK。 +- 点击后,可以在我们本地服务看到回调的日志,但还要稍微等待一会 arex 平台,他要比对回放结果。完成后,Passed 表示回放通过。 + +#### 7.2 回放配置 - 异常回放 + +首先,我们要修改下代码。 + +```java +@RestController +@RequestMapping("/api/traffic") +public class TrafficController { + + @GetMapping("/query_user_age") + public Integer queryUserAge(@RequestParam("userId") String userId) { + log.info("请求参数:{}", userId); +// return getCache(); + return getDB(); + } + + // 模拟从缓存获取数据 + public Integer getCache() { + return 20; + } + + // 模拟从数据库获取数据 + public Integer getDB() { + return 21; + } + +} +``` + +- 这个接口方法,如果录制流量是用的 getCache(),那么这会就修改为 getDB(),让两次结果不一样。 +- 之后,要重新 install 并重新执行 `run_application_2_agent.sh` 启动项目。关闭执行 Ctrl/Command + C + +配置,流量回放操作。 + +
+ +
+ +- 之后,再来一遍回放。这样就是错误的结果了。 + +### 8. 接口请求(Debug) + +
+ +
+ +- arex 工具,还支持线上请求本地接口操作。 +- 也就是说,你从线上录制的流量,可以直接拿流量,调试本地接口。有了这样一个操作,哪些线上请求参数非常复杂的结构,就可以直接一键对本地进行验证了。 diff --git a/docs/md/road-map/arthas.md b/docs/md/road-map/arthas.md new file mode 100644 index 000000000..914830721 --- /dev/null +++ b/docs/md/road-map/arthas.md @@ -0,0 +1,465 @@ +--- +title: arthas +lock: need +--- + +# 面试官:“程序内存溢出,你怎么找出大对虾(像)”? —— arthas 使用教程 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +👬🏻 兄弟,你被看过手相不,你被号过脉相没。一个没与你生活过就知道你的过去和现在,一个不了解你的日常就知道你是否怀孕是男是女。而你自己亲手开发的Java代码,上线后报错都不知道怎么发生的!!!咋办? + +
+ +
+ +**那有什么手段给 Java 代码号脉吗?🤔** + +还真有这么一个工具,也是大多数老司机程序员👨🏻‍💻非常喜欢用的一款组件,很多时候不好排查的 Bug 都用这个工具进行分析。它可以知道哪个对象创建的过多、方法的出入参、系统运行时候JVM的参数等等,让你随时可以知道系统运行的细节状态。 + +它就是 Arthas,但很多伙伴还没有使用过,这篇文章为大家分享下,如何使用这样一款组件。以及怎么使用这个组件监控部署到 Docker 中的 Java 应用。 + +## 一、组件介绍 + +官网:[https://arthas.aliyun.com/doc/](https://arthas.aliyun.com/doc/) + +Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。 + +当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决: + +1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception? +2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了? +3. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗? +4. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现! +5. 是否有一个全局视角来查看系统的运行状况? +6. 有什么办法可以监控到 JVM 的实时运行状态? +7. 怎么快速定位应用的热点,生成火焰图? +8. 怎样直接从 JVM 内查找某个类的实例? + +## 二、快速入门 + +在 Arthas 官网有一个简单🔜快速入门的案例,它提供了2个程序,一个是 Java 的随机数分解的程序代码,另外一个是 arthas-boot.jar 监控组件。这个套代码可以在任何安装了 Java 环境的服务器上使用,包括你本地、云服务器都可以运行。 + +### 1. 步骤1,案例程序 + +```java +curl -O https://arthas.aliyun.com/math-game.jar +java -jar math-game.jar +``` + +### 2. 步骤2,监控程序 + +```java +curl -O https://arthas.aliyun.com/arthas-boot.jar +java -jar arthas-boot.jar +``` + +- 启动后会出来一个 math-game.jar 之后再敲下回车,就进入了 Arthas 的监控程序了。之后你可以使用监控程序提供的各种命令进行使用。 +- 命令列表:[https://arthas.aliyun.com/doc/commands.html](https://arthas.aliyun.com/doc/commands.html) + +## 三、应用使用 + +### 1. 环境准备 + +为了方便大家进行学习验证,小傅哥这里准备好了一个测试工程和相关的环境安装。你可以如下文的说明进行使用和验证。 + +
+ +
+ +- 工程:[https://github.com/fuzhengwei/xfg-dev-tech-arthas](https://github.com/fuzhengwei/xfg-dev-tech-arthas) +- 说明:`dev-ops` 下提供了部署测试工程的 docker compose 脚本,以及 arthas-boot 启动程序的脚本。另外工程提供了一个接口,每次访问都会创建对象。接口在 Application 中,简单实现。地址:[http://localhost:8091/api/exec](http://localhost:8091/api/exec) - 接口内容可详见代码。 +- 前置:如果你需要云服务器部署操作,可以在 [bugstack.cn](https://bugstack.cn) <路书> 中有云服务器操作,可以学习使用。 + +### 2. 应用安装 + +**操作过程预览** + +
+ +
+ +>如图所示,接下来我们会进行部署操作。 + +#### 2.1 构建脚本 + +```java +# 基础镜像 openjdk:8-jre-slim openjdk:8-jdk-alpine 8-jdk-alpine +FROM openjdk:8-jdk + +# 作者 +MAINTAINER xiaofuge + +# 配置 +ENV PARAMS="" + +# 时区 +ENV TZ=PRC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# 添加应用 +ADD target/xfg-dev-tech-app.jar /xfg-dev-tech-app.jar + +# arthas https://hub.docker.com/r/hengyunabc/arthas +COPY --from=hengyunabc/arthas:latest /opt/arthas /opt/arthas + +## 在镜像运行为容器后执行的命令 +ENTRYPOINT ["sh","-c","java -Djava.security.egd=file:/dev/./urandom -jar $JAVA_OPTS /xfg-dev-tech-app.jar $PARAMS"] + +# 暴露容器的端口 +EXPOSE 8989 +``` + +- `FROM openjdk:8-jdk`:因为 arthas 需要 jps 的相关命令,所以需要指定安装 jdk 版本。`openjdk:8-jre-slim` 是没有这些脚本的。 +- `hengyunabc/arthas:latest`:把 arthas 的镜像打包到程序中,这样我们可以直接在程序中使用 arthas 组件。 +- 构建过程:无论是本地还是云服务器 Docker 启动后,先执行 `maven install` 程序、后执行 `build.sh` 构建应用镜像。[云服务器操作视频](https://bugstack.cn/md/road-map/linux.html) + +#### 2.2 部署项目 + +```java +version: '3.8' +# docker-compose -f docker-compose-app.yml up -d +# 你需要修改system为你自身系统的仓库名 +services: + xfg-dev-tech: + image: xiaofuge/xfg-dev-tech-app:1.0 + container_name: xfg-dev-tech + restart: on-failure + ports: + - "8091:8091" + environment: + - TZ=PRC + - SERVER_PORT=8091 + # 2c4g 配置,4c8g 翻倍,-Xms4096m -Xmx4096m | -Xmx –Xms:指定java堆最大值(默认值是物理内存的1/4(<1GB))和初始java堆最小值(默认值是物理内存的1/64(<1GB)) + - JAVA_OPTS=-Xms2048m -Xmx2048m -XX:MaxMetaspaceSize=128m -XX:MetaspaceSize=128m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps + volumes: + - ./log:/data/log + - ./arthas/profiler:/arthas-output + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + networks: + - my-network + +networks: + my-network: + driver: bridge +``` + +
+ +
+ +- 脚本说明;脚本提供了 docker compose 安装的配置参数,包括端口、jvm、日志和arthas的映射路径等。 +- 执行脚本;`docker-compose -f docker-compose-app.yml up -d`这样会帮助你启动项目。 +- Mac 电脑 + Docker 可以直接在 IntelliJ IDEA 中点击启动。 + +### 3. 监控部署 + +```java +docker exec -it xfg-dev-tech /bin/sh -c "java -jar /opt/arthas/arthas-boot.jar" +``` + +
+ +
+ +- 在案例工程下有一个 dev-ops/arthas-boot.sh 你可以执行启动 arthas +- 启动后有一个 arthas 的控制台,这个控制台可以输入各种 arthas 提供的命令来监控程序。**非常强大** + +### 4. 访问接口 + +在案例工程中提供了一个用于创建对象的程序,方便进行测试。 + +```java +@Slf4j +@SpringBootApplication +@RestController() +@RequestMapping("/api/") +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class); + } + + // 创建线程池 + ExecutorService executorService = Executors.newFixedThreadPool(10); + // 用于存储内存占用对象的列表 + private static final List memoryHolder = new ArrayList<>(); + + /** + * http://localhost:8091/api/exec + */ + @RequestMapping(value = "/exec", method = RequestMethod.GET) + public String exec() { + executorService.submit(() -> { + try { + // 创建一个大对象 +// byte[] largeObject = new byte[10 * 1024 * 1024]; // 10MB + byte[] largeObject = new byte[10 * 1024]; // 10MB + + // 将其加入内存占用列表中,防止被gc + synchronized (memoryHolder) { + memoryHolder.add(largeObject); + } + + log.info("模拟填充大对象"); + + // 模拟一些工作 + Thread.sleep(1000); + + } catch (OutOfMemoryError e) { + System.err.println("Out of memory! Halting further allocation."); + // 如果出现OOM,暂停分配以防止程序崩溃 + executorService.shutdown(); + + } catch (InterruptedException e) { + // 捕获并处理睡眠中断 + Thread.currentThread().interrupt(); + System.err.println("Task interrupted"); + } + }); + return "ok"; + } + +} +``` + +
+ +
+ +- 请求地址:[http://localhost:8091/api/exec](http://localhost:8091/api/exec) +- 请求脚本:提供了请求1次和循环多次的脚本,方便测试。 + +## 四、命令使用 + +使用监控命令前,可以先执行上图中的 curl-one.sh 调用程序接口。你还可以在使用命令的过程中调用测试。 + +命令:[https://arthas.aliyun.com/doc/commands.html](https://arthas.aliyun.com/doc/commands.html) + +### 4.1 dashboard - 当前系统的实时数据面板 + +> [arthas@7]$ dashboard + +
+ +
+ +- 运行脚本后,可以查看到当前服务的运行数据信息。另外这里还有一些 JVM 基础知识,补充给大家。 + +#### 4.1.1 jvm 内存空间都有啥 + +在 Java 运行环境中,JVM(Java Virtual Machine, Java 虚拟机)是执行 Java 程序的引擎,而内存管理是 JVM 非常重要的一部分。JDK 1.8 中的 JVM 内存空间主要分为以下几个区域,每个区域都有其特定的用途: + +1. 堆(Heap): + - 用途:堆是 JVM 中内存最大的一块,用于存储所有的对象实例和数组。几乎所有对象都在此分配内存,垃圾收集器也在这里执行。 + - 分代垃圾收集机制:堆内存被进一步划分为新生代和老年代。 + - 新生代(Young Generation):用于存放新创建的对象。其中又分为伊甸园区(Eden Space)和两个幸存者区(Survivor Spaces,通常称为 S0 和 S1)。 + - 老年代(Old Generation):用于存放生命周期较长的对象。 + +2. 方法区(Method Area)(在 JDK 1.8 中已被细化为元空间 Metaspace): + - 用途:存储已被加载的类元数据、常量、静态变量等。在 JDK 1.8 中,用于取代永久代(PermGen)。 + - 元空间(Metaspace):与永久代不同,元空间用的是本地内存而不是堆内存,这避免了 Java 中永久代容量不足导致的内存问题。 + +3. 栈(Stack): + - 用途:每个线程创建时会分配一个栈,它用来存储局部变量表、操作数栈、动态链接、方法出口等。栈内存会自动随着方法的进出而分配和释放。 + - 特性:栈是线程私有的,每个线程都有自己的栈。 + +4. 程序计数器(Program Counter Register): + - 用途:是一个较小的内存空间,用于指示当前线程所执行的字节码的行号。 + - 特性:它是唯一一个在 Java 虚拟机规范中没有规定任何 OutOfMemoryError 情况的区。 + +5. 本地方法栈(Native Method Stack): + - 用途:与 Java 栈类似,但它主要用于处理本地方法(Native Method)的执行。 + - 特性:也是线程私有的,负责本地方法的调度和执行。 + +这些内存区的设计是为了支持 Java 的垃圾收集机制和多线程并发运行,确保 Java 应用程序能够高效和稳定地执行。了解这些内存区的功能和作用,可以帮助开发者优化 Java 应用的性能,并有效管理内存使用。 + +#### 4.1.2 垃圾回收算法 + +GC 核心在于通过不同的算法来高效管理内存资源。常用的 GC 算法包括: + +1. 标记-清除算法(Mark and Sweep): + - 标记阶段:遍历所有的对象引用,标记活动的对象。 + - 清除阶段:清理掉未被标记的对象。 + - 缺点:容易造成内存碎片,因为清除后内存是不连续的。 + +2. 复制算法(Copying): + - 将活动的对象从一块内存(From space)复制到另一块(To space),然后清理整块 From space。 + - 优点:内存分配简单,不会产生碎片。 + - 缺点:需要预留多余的内存空间实行复制。 + +3. 标记-整理算法(Mark-Compact): + - 标记阶段:和标记-清除相似。 + - 整理阶段:将所有活动对象移到一端,处理剩余的空间为可用。 + - 减少了碎片化问题,但相比复制算法更复杂。 + +4. 分代收集算法: + - 根据对象的生命周期不同,将堆分为新生代和老年代。 + - 新生代使用复制算法,老年代使用标记-清除 或 标记-整理。 + - 优点:优化了大多数对象短命这一特性带来的效率。垃圾回收算法。 + +#### 4.1.3 垃圾收集器 + +Java 提供了多种垃圾收集器,适用于不同应用场景: + +1. Serial GC: + - 单线程收集器,非常适合单线程环境和小型应用。 + - 效率高但可能造成长时间的停顿。 + +2. Parallel GC (Throughput Collector): + - 多线程收集器,用于最大化 CPU 吞吐量。 + - 适合后台处理任务和高效利用系统资源的场景。 + +3. CMS GC (Concurrent Mark-Sweep Collector): + - 重点在于缩短停顿时间,适合响应时间敏感的应用。 + - 较轻量级的 GC,但处理老年代垃圾时效率不如 Parallel。 + +4. G1 GC (Garbage-First Collector): + - 设计用于大堆,提供可预测的停顿时间。 + - 将堆划分为不同的区域(Region),针对不同老化级别进行回收。 + +5. ZGC / Shenandoah GC: + - 尝试实现低延迟垃圾回收,几乎不会造成任何长时间的停顿。 + +#### 4.1.4 code_cache (代码缓存区)、compressed_class_space (压缩类空间)、metaspace (元空间),他们的用途是什么,有什么要注意的。 + +在 Java 虚拟机(JVM)中,非堆内存部分包括多个区域,每个区域负责存储不同种类的数据,这里重点介绍 Code Cache(代码缓存区)、Compressed Class Space(压缩类空间)和 Metaspace(元空间)的用途及注意事项。 + +##### 1. Code Cache(代码缓存区) + +用途: +- JIT 编译代码:Java 虚拟机的即时编译器(Just-In-Time Compiler,JIT)会将频繁使用的字节码编译成本地机器码,以提高运行性能。编译后的本地代码存储在代码缓存区中。 +- 性能提升:通过存储这些编译后的代码,JVM 可以避免对同一代码片段重复进行解释,从而提升执行速度。 + +注意事项: +- 内存限制:代码缓存区有固定的最大值(可通过 `-XX:ReservedCodeCacheSize` 参数配置),需要注意在长时间运行的应用程序中这个区不会被耗尽,否则可能导致性能退化。 +- 清理与优化:JVM 在启动时和运行过程中可能会执行代码缓存的清理和优化,这个过程会对性能有一定影响。 + +##### 2. Compressed Class Space(压缩类空间) + +用途: +- 存储类元数据:在开启类指针压缩的情况下(默认开启),这个空间用于存储类元数据的压缩指针,以节省内存空间。 +- 支持元空间:压缩类空间是元空间的一部分,专门用来优化类加载器的内存消耗。 + +注意事项: +- 有固定最大限制:虽然是元空间的一部分,但压缩类空间有自己的最大内存限制(默认为 1GB),可以通过 `-XX:CompressedClassSpaceSize` 参数调整。 +- 适配性告诉:32 位 JVM 不使用压缩类空间功能,64 位 JVM 在默认情况下是开启的,因其节省的内存对大型应用尤其重要。 + +##### 3. Metaspace(元空间) + +用途: +- 替换永久代:Java 8 开始,用元空间替代了永久代,用于存储类的元数据(类的结构信息、方法、字段等)。 +- 动态调整大小:与永久代不同,元空间作为物理内存的一部分,不断增长(直到达到物理内存上限),默认不设置上限,灵活性更高。 + +注意事项: +- 内存泄漏风险:尽管更灵活,但如果不加限制,糟糕的类加载策略可能导致元空间内存泄漏。在开发环境中尤其要防止过度类加载。 +- 调整与监控:可以通过 `-XX:MetaspaceSize` 和 `-XX:MaxMetaspaceSize` 进行调节,适当限制,在实际使用中密切监控。 +- 自动释放:JVM 在内存不足时会尝试回收未使用的类加载的内存,虽然一般无需手动干预,了解这方面的配置有助于优化内存使用。 + +这些部分的配置和监控是调优 JVM 的重要组成部分,适当的配置可以防止内存泄漏、排查性能瓶颈,并为应用程序的稳定性提供保障。 + +### 4.2 火焰图 + +#### 4.2.1 生成脚本 + +profiler 命令支持生成应用热点的火焰图。本质上是通过不断的采样,然后把收集到的采样结果生成火焰图。火焰图可以清楚的看到程序运行中对象的创建,这样你就可以发现那些大对虾(像)从哪来的? + +操作过程,开启采集 `profiler start --event alloc` 等待程序执行,关闭采集 `profiler stop --format html` + +我们操作中,开启采集后,可以先执行多次的 curl-one.sh 调用接口,多产生点对象。 + +```java +profiler start --event alloc + +profiler getSamples + +profiler status + +profiler stop --format html +``` + +
+ +
+ +- 执行完成后,你会得到一个火焰图的 html 文件。之后就可以打开了。 + +#### 4.2.2 查看图表 + +
+ +
+ +1. 这里的x轴代表采样总量(也就是此刻所有执行的耗时cpu的方法)。这是注意的是x 轴并不代表时间,而是所有的调用方法合并后,按字母顺序排列。 +2. Y轴代表方法的调用栈深度,每一层都是一个方法。顶部是正在执行的方法。当然调用栈越深,火焰就越高。 +3. 鼠标可以点击的选中的每个框就代表了一个栈里的函数,其宽度可以直接理解为CPU时间占比(其实是采样的数量以及与采样总量的占比)。 +4. 那么,也就是说占比比较宽的框就表示:a.该函数运行时间较长(单次时间长)b.被调用次数较多.(调用频率高)进而被采样的次数比较多,占用的CPU时间多。 +4. 这样你就知道了是哪里在创建大对像。比如一些数据库对象,缓存对象等,特别大,又耗时,一下就监控出来了。 + +> Arthas 提供的功能还有很多,不过咱们要换个更加舒服的方式使用了。如下。 + +## 五、IDEA Plugin Arthas + +### 1. 安装插件 + +
+ +
+ +### 2. 使用插件 + +这些命令你都可以通过 Arthas IDEA Plugin 插件复制出来使用。 + +- [monitor](https://arthas.aliyun.com/doc/monitor.html) - 方法执行监控 +- [stack](https://arthas.aliyun.com/doc/stack.html) - 输出当前方法被调用的调用路径 +- [trace](https://arthas.aliyun.com/doc/trace.html) - 方法内部调用路径,并输出方法路径上的每个节点上耗时 +- [tt](https://arthas.aliyun.com/doc/tt.html) - 方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测 +- [watch](https://arthas.aliyun.com/doc/watch.html) - 方法执行数据观测 + +更多命令 [https://arthas.aliyun.com/doc/commands.html](https://arthas.aliyun.com/doc/commands.html) + +#### 2.1 复制命令 + +
+ +
+ +#### 2.2 使用命令 + +
+ +
+ +- 如图你就可以监控到方法的运行信息了。 + +### 3. 其他命令 + +#### 3.1 查看代码 + +
+ +
+ +- 线上运行的代码,不确定是否是最新的,那么这样就可以一步获取到并对比。 + +#### 3.2 接口参数 + +
+ +
+ +- 有时候预发验证服务,因为不会打印所有的服务接口出入参信息,但遇到问题不好排查。 +- 那么使用 Arthas 插件,就可以直接获取到接口的出入参了,方便排查问题。 + +> 其他更多命令可以通过官网的命令提示和插件一起使用验证了。 diff --git a/docs/md/road-map/buddy.md b/docs/md/road-map/buddy.md index 341579bd0..0902d75f4 100644 --- a/docs/md/road-map/buddy.md +++ b/docs/md/road-map/buddy.md @@ -1,9 +1,9 @@ --- -title: Buddy +title: Docker 镜像构建 - Buddy lock: need --- -# 一款在线使用的,更轻量、更好用的 CI&CD 工具 buddy.works +# Docker 镜像构建 - Buddy 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) diff --git a/docs/md/road-map/cainiao.md b/docs/md/road-map/cainiao.md new file mode 100644 index 000000000..b723195a8 --- /dev/null +++ b/docs/md/road-map/cainiao.md @@ -0,0 +1,96 @@ +--- +title: 菜鸟教程 - 交互式学习 +lock: need +--- + +# 菜鸟教程 - 交互式学习 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +一直以来我都有一个想法,做一套更符合新人上手学习的 **🐦菜鸟教程**,以在线互动交互的方式学习入门编程技术。 + +但原本`互动交互`这东西太耗前端能力了,好在,现在有大量的 Ai Agent 工具,帮我我把想法落地了!—— 我有创新和内容,Ai Agent 出设计和效果!嘎嘎舒服!**美美桑内,一个劲叭叭!** + +
+ +
+ +**这是一个什么样的教程?** + +小傅哥做的教程分为3大类,一类是带着做**实战项目**(拼团、大营销、技术组件等)、一类是**编程路书**(系统架构、开发技术、发布部署等),现在再准备开启一项更基础的,辅助刚入门的小白来学习编程技能。 + +这套教程,专门为小白设计,包括;环境配置(Mac、Windows)、`SpringBoot`、`MyBatis`、`Redis`、`Mysql`、`Maven` 等各项编程技术的入门讲解。后续还会继续迭代新的课程进去。 + +本套教程不只是干巴巴的讲技术,而是做了学习互动,你可以看到如 SpringBoot 课程下模拟的在线 IntelliJ IDEA 打开教程代码,还可以看到 Dev-Ops 云服务器操作时候的互动过程。这样的学习,即使是小白,也可以很好理解自己在做什么,为什么做。 + +## 一、能学到啥 + +此套教程,以入门编程为主,让小卡拉米和小菜鸟,快速补充基础技术知识。全套教程,会以目前最新的环境配置、技术框架、编程技巧等为本,设计基础入门教程。包括; + +- 【框架】22节课程,SpringBoot 入门教程,涵盖;环境搭建与项目初始化、核心概念与配置管理、数据库集成与容器管理、高级特性与性能优化、测试与监控管理、企业级应用特性。 +- 【运维】Dev-Ops 云服务器操作,一键安装脚本、云服务器 SSH 模拟(学习命令)、本地环境 + 云服务器,配置、构建、上线,学习环境基础使用。 +- 【环境】基于 Apache Maven 3.8.9 版本编写,涵盖了 Maven 的核心概念、配置和实际应用。 +- 【后端】MySQL 从基础到高级,掌握 MySQL 数据库开发与管理,完整覆盖 MySQL 基础到高级概念,详细对比 MySQL 5.7 与 8.x 版本差异,涵盖性能优化和高级特性。 +- 【后端】Redis 教程,从入门到精通的完整学习指南。学习 Redis 的核心概念和高性能特性,掌握字符串、哈希、列表、集合等数据类型。 + +> 以上内容,已更新完成 SpringBoot、Dev-Ops 部分,其他内容也更新了目录,后续详细更新内容。 + +## 二、课程展示 + +**课程地址**:[https://gaga.plus/](https://gaga.plus/) + +
+ +
+ +你可以进入到 gaga.plus,之后点击菜鸟教程,开启你的入门编程之旅! + +### 1. 课程目录 + +
+ +
+ +### 2. 教程举例 - SpringBoot + +
+ +
+ +
+ +
+ +- 进入教程,学习章节内容。还可以在线看,模拟 IntelliJ IDEA 打开的工程代码。非常方便学习。 + +### 3. 教程举例 - Dev-Ops + +#### 3.1 云服务器连接 + +地址:[https://gaga.plus/app/dev-ops/tutorials/what-is-a-cloud-server.html](https://gaga.plus/app/dev-ops/tutorials/what-is-a-cloud-server.html) + +
+ +
+ +
+ +
+ +#### 3.2 云服务器使用 + +地址:[https://gaga.plus/app/dev-ops/tutorials/cloud-server-dev-ops.html](https://gaga.plus/app/dev-ops/tutorials/cloud-server-dev-ops.html) + +
+ +
+ +- 你可以点击各个按钮【本地环境搭建、Linux服务器配置、SSH远程连接、本地开发连接、代码部署(1、2)】,这样可以动态的看到各个演示环节。 +- 此外,你可以在 SSH 连接后,基于提供的命令教程进行学习。 + +好啦,如果你还有什么样的基础内容学习诉求,可以在评论区留言,我会优先进行开发上线! diff --git a/docs/md/road-map/cloud-server.md b/docs/md/road-map/cloud-server.md new file mode 100644 index 000000000..c12df0158 --- /dev/null +++ b/docs/md/road-map/cloud-server.md @@ -0,0 +1,98 @@ +--- +title: CloudServer 云服务器是什么? +lock: need +--- + +# CloudServer 云服务器是什么? + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +可以这么说,云服务器的使用,是每个程序员在编程路上的必备技能。因为我们所有开发的代码,最终都将部署到云服务器运行,为用户提供运算能力。包括;`京东`、`淘宝`、`拼多多`、`滴滴`、`美团`,他们的服务,都是在云服务器上运行。**不过,你会使用云服务器吗?🤔** + +
+ +
+ +**你是否对云服务器比较陌生?** + +其实不少伙伴没怎么使用过云服务器,一方面是因为没有意识到项目最终是在云服务器部署(也没有主动虚席),另一方面是因为云服务器基本是使用 Linux 系统,不像是 Windows/Mac 电脑一样,基本是没有图形化界面的,所以对于云服务器的使用就有了一道**障碍**。 + +不过,鉴于云服务器的技能这么重要。所以,小傅哥准备做一套基础的**免费教程**,来教会小白伙伴上手云服务器使用。这套教程,通过在线网站提供图形化界面 + 模拟体验的方式,教会小白伙伴上手云服务器。 + +> 📢 本套课程,是小傅哥多年的沉淀的经验,转化最易接受和上手学习的方式,让小白伙伴可以轻松的掌握全套关于云服务器的知识和实践运用。 + +## 一、课程地址 + +**地址**:[https://gaga.plus/](https://gaga.plus/) + +
+ +
+ +> 如图,教程地址,会陆续更新在线课程。可以收藏地址,关注后续课程更新(更新内容会在公众号「bugstack虫洞栈」发布通知)。 + +## 二、我能学到什么? + +通过这套教程,你可以完成的理解云服务器的用途,掌握云服务器的操作技能。从零基础到熟练运用云服务器 + 本地环境完成项目的开发、测试和部署的全流程。教程采用在线演示体验,互动式学习方式,以及一键安装的脚本,让复杂的云服务器操作,变得简单和易于理解。 + +- 🏗️理解云服务器的概念、选择、配置、管理,以及通过 shell 脚本,完成自动化的初始化环境操作。 +- ☕ 在云服务器部署 Git、Java、Maven 环境,可以通过云服务器完成项目的构建。 +- 🐳 Docker 容器化技术,完成项目的构建镜像、操作部署等。 +- 🔐 远程连接与安全,学习 SSH 链接云服务器和 Linux 命令操作云服务器。 +- 🌿 版本控制与协作,可以在云服务器通过 Git 检出项目进行维护使用。 +- 🚀 部署与运维,以代码开发、Git Push、Git Pull、mvn clean install、docker,一些列命令,完成项目的打包和上线。 + +这套教程的特色在于完全可视化学习,注重理论与实践,不仅让您了解云服务器的基本概念,更重要的是通过交互式演示和自动化脚本,让您能够快速上手并在实际项目中应用这些技术。无论您是初学者还是有一定经验的开发者,都能从中获得有价值的知识和技能提升。 + +## 三、小傅哥为你准备了什么? + +小傅哥,今天为你准备了第一套在线教程**《第1节:云服务器,是什么?》** + +在这套教程,你可以直接直观的理解到云服务器相对于本地电脑,其实就等同于你的另外一个电脑而已。并且,小傅哥这里做了模拟的链接,**你可以在线体验通过 SSH 连接云服务器,并执行 Linux 脚本运行**。关于这些写脚本,已经写好了相关的执行动作和说明,很适合小白伙伴学习使用。 + +### 1. 云服务器链接 + +
+ +
+ +- 首先,云服务器,就是你在互联网上的另一台电脑,随时随地访问使用,任意安装和卸载软件。尤其对软件学习来说,可以避免windows电脑的兼容问题。 +- 之后,你可以点击建立 SSH 链接,这个时候会弹出 SSH 链接操作。让你真的的体验到如何通过 SSH 链接云服务器。 + +### 2. Linux 命令模拟 + +#### 2.1 建立链接(SSH) + +
+ +
+ +- 如图,IP、用户名、密码、端口号,就是你在获得一个云服务器后,可以拿到的连接信息。在你真实使用云服务器时,也是需要获得这些信息进行连接操作。 +- 之后,通过点击建立SSH连接,模拟登录云服务器。**没有云服务器的伙伴,也能随时体验云服务器操作** + +#### 2.2 体验登录 + +
+ +
+ +- 我知道很多小伙伴,不太熟悉 Linux 命令。所以,小傅哥这里做了模拟操作,你可以点击命令,之后就可以看到执行结果,以及告诉你命令的用途。此外还有 Git、Maven、Docker 常见命令的学习。 +- 通过这套东西的学习,对于云服务器的使用,基本就可以有一个操作的使用认知了。后续在看到要执行命令,也都能理解,是怎么的一个操作过程。 + +#### 2.3 常用命令 + +**如下,这些命令都已经加入到体验区 👨🏻‍💻** + +
+ +
+ +- 你可以点击各个命令,学习对应的场景用途。 +- 如果,小伙伴还有其他命令想学习,也可以留言。我会进行补充。 + +> 后续,还有更炸裂的在线模拟学习课,让你身临其境的学习云服务器的操作。我们下一节再见👋🏻 diff --git a/docs/md/road-map/ddd-archetype-maven.md b/docs/md/road-map/ddd-archetype-maven.md index 4ed19365b..38913d073 100644 --- a/docs/md/road-map/ddd-archetype-maven.md +++ b/docs/md/road-map/ddd-archetype-maven.md @@ -20,7 +20,7 @@ lock: need -- 配置地址 https://gaga.plus +- 配置地址 https://gaga.plus - `备用地址:[https://maven.xiaofuge.cn](https://maven.xiaofuge.cn)` - ddd-scaffold-lite 提供了默认版本和 v2 版本。v2 做了少量调整。将 repository、port 统一归属到 adapter 下管理。 --- @@ -178,6 +178,20 @@ lock: need + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + org.apache.maven.plugins @@ -217,20 +231,6 @@ lock: need - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - org.apache.maven.plugins maven-release-plugin @@ -287,7 +287,7 @@ lock: need - 注意 groupId、artifactId 名字,如果你有发布诉求,需要和你自己的一致。 - maven-javadoc-plugin:生成 doc 文档。这里要注意,因为我们脚手架不是代码文件,没有doc的,所以要在工程中加一个任意类名文件。工程中小傅哥加了个 Api 类。 - maven-source-plugin:生成 source 文件。 -- maven-gpg-plugin:是签名的加密文件,需要本地安装过 gpg 包。 +- maven-gpg-plugin:是签名的加密文件,需要本地安装过 gpg 包。注意;`checksum-maven-plugin` 需要在 `maven-gpg-plugin` 执行,这样就不用做下面的手动 md5 逻辑了。 - checksum-maven-plugin:生成 md5、sha1 文件,但这里不会对 pom 生成此文件,还需要单独命令处理。 ```shell diff --git a/docs/md/road-map/ddd-guide-00.md b/docs/md/road-map/ddd-guide-00.md new file mode 100644 index 000000000..c09cbd1be --- /dev/null +++ b/docs/md/road-map/ddd-guide-00.md @@ -0,0 +1,77 @@ +--- +title: DDD 架构演进 +lock: need +--- + +# DDD 架构演进,从单层、三层,四层,工程分层演进过程! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +`定义接口`、`创建方法`、`调用展示`,其实编程写代码说到底也就这3步,人人都是程序员👨🏻‍💻。公司老板都觉得,它有个AI工具,它都能写代码。但现在的系统工程的分层结构,可不只是一层就写个 Controller,甚至是3层(Model-View-Controller),也有可能是4层(DDD)架构。这样的分层架构怎么理解呢? + +
+ +
+ +**刚入行,直接就开大吗?** + +在我最早接触编程的时候,还是9大内置对象,servlet、jsp、前端也是刚接触《锋利的JQuery》的时代。甚至很多流程代码都堆到了 jsp 页面,后端也就是连库做 CRUD 操作。多好的时代,学一点东西,就能上班赚钱了。现在要学的可就多了,仅专业技能部分,都能在写满简历 1/3 篇幅了! + +但没办法,人嘛,总是要向钱低头的,向前!毕竟,互联网公司都是飞速迭代发展的,所以,要想混个能在群里喊【收到、收到】的资格,也得加倍学习。 + +所以,小傅哥就给大家分享下,关于系统分层架构的演进过程,看看这东西是怎么从简简单单变得复复杂杂的。 + +## 一、单层架构 + +单层架构并不算一个规范的架构定义,只是在早期 MVC 三层架构(模型、试图、控制器)还没有那么普及,以及国内开发的项目程序还没有那么规范的时候,用于快速搭建简单网页功能的一种设计。 + +
+ +
+ +所有的分层结构的设计,都是以承接功能实现诉求为目的,这一阶段仅仅是完成网页的数据展示,也几乎没有用户交互。所以,很多时候是有多少个页面,就有多少个 Controller 提供接口,以及编写好调用数据库查询数据的操作。 + +## 二、三层架构 + +1978年,MVC模式最早由 [Trygve Reenskaug](https://zh.wikipedia.org/w/index.php?title=Trygve_Reenskaug&action=edit&redlink=1) 提出,**MVC模式**的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。除此之外,此模式透过对复杂度的简化,使程序结构更加直观。 + +
+ +
+ +- 当 Controller 里承载业务功能逐步变多以后,我们开始思考怎么把这些东西分区存放。那么可以把各类对象归类到一个文件夹,之后把 Controller 里的复杂逻辑拆分为一个个原子的 service 服务,让 Controller 的接口负责调用。 +- 目前的分层架构,就可以适合开发一些复杂逻辑的场景诉求了,不过整体系统的承载量仍然是偏弱一些的。 + +## 三、三层架构(分布式) + +3层架构出现的很早,其实本身的设计没有考虑复杂的分布式场景。在从三层架构演变到可以支持分布式架构的时候,是没有一个统一的标准规范的,更多的各个公司里自己直接从旧工程里添加了新的 module 分层模块。 + +
+ +
+ +- 首先,一个分布式架构要,对接 rpc、提供 rpc、消费 mq、生产 mq,还要做定时任务(最终一致性补偿),单一个 rpc 的使用,就需要在程序定义出一个 export 层,要打包对外的服务接口,让使用方式引入使用。关于为什么需要这样的方式,可以在 [bugstack.cn](https://bugstack.cn/md/road-map/dubbo.html) 编程路书中,开发技术部分 dubbo 学习。 +- 之后,原本的 MVC 三层结构就不够用了。只要添加上,export、rpc 这样的分层,原本 service 直接处理数据库的操作,也要考虑拆分出来。可能这部分每个公司还不一样,其实即使一个公司,不同组,也是有很大的差异。这个也是目前互联网公司中的项目里的一个现状问题。 +- 思考,现在的工程模型结构其实很杂,装填了太多的东西进去了。除此之外,因为都是原子化编写,没有在做分区。一个系统里 service 都有上千个类,每个类里又有上千行代码。在坐的各位,应该都会在这些屎山中赚钱。 + +## 四、四层架构 + +DDD 是思想,六边形/菱形/整洁架构是分层,DDD 通过建模思想,指导我们以从用例图(use case diagram)出发,与产品、研发、测试一起在一个规范下,脑暴建模。在这个过程中,以结果为导向,分析出可能存在的领域服务。这些领域服务,如登录完成,下单完成,支付完成,收货完成,根据结果态,分析支撑这样的服务所需的对象(实体)、流程、规则等。这样我们可以更加清晰的构建一套系统。 + +而,六边形(常用的)架构,则是用于承接 DDD 领域驱动设计对系统分析后的编码实现。六边形可以说是专门为 DDD 做的配套架构,虽然也可以用 MVC 来编写,但这样是会失去面向对象设计和编码的优势,让代码逻辑混乱在一起。所以,这也是各个互联网公司开始往 DDD 架构切换的目的。这件事,我已经干了好几年了! + +
+ +
+ +- 首先,六边形架构,以 DDD 领域驱动实际为指引,为 domai 层,设计充血模型结构,如;登录、下单、支付,在每个模块下,包含完整的服务、模型、适配。适配的目的是这个领域里所需的数据,都通过适配的方式从外部调用进来,比如;数据库、缓存、接口等。这是一种 ACL 防腐设计,将来外部的接口变化了,也不会影响我们的领域服务,只要按照领域服务的适配标准提供即可。 +- 之后,围绕着领域 domain 开始,需要啥就让外部的基础设施层实现领域层的接口来提供。而接口要提供啥能力,就调用 case 编排 domain 层,或则简单的由 domain 层直接提供也可以。 +- 最后,也就是 trigger 触发器,我们把接口、任务、mq等都理解为一种触发,之后让 trigger 调用 case 层。case 或者 domain 的目的,就是分摊 trigger 以前 Controller 编写逻辑代码的压力。让 trigger 只是负责对外逻辑的封装,错误码,异常即可。 + +综上,就是关于架构分层的一个演进过程,现在还有 AI 的加入,AI 也会逐步成为整个工程架构中的一块。关于这部分的架构设计,与业务工程的结合,小傅哥也会在 bugstack.cn 博客中陆续更新。 + diff --git a/docs/md/road-map/ddd-guide-01.md b/docs/md/road-map/ddd-guide-01.md index 5b9d1d247..1b8868b28 100755 --- a/docs/md/road-map/ddd-guide-01.md +++ b/docs/md/road-map/ddd-guide-01.md @@ -28,11 +28,11 @@ DDD 是什么,这应该是每个想使用 DDD 开发项目的研发伙伴, ## 2. DDD 的概念 -什么是充血模型,领域内都包括什么,实体、聚合、值对象,有什么区别?这样一些"为什么"的概念,也是战术设计过程中非常重要的知识项。搞清楚它们才能做 DDD 设计。 +什么是充血模型?领域内都包括什么?实体、聚合、值对象,有什么区别?这样一些"为什么"的概念,也是战术设计过程中非常重要的知识项。搞清楚它们才能做 DDD 设计。 ### 2.1 充血模型 -**充血模型**,指将对象的属性信息与行为逻辑聚合到一个类中,常用的手段如在对象内提供属于当前对象的`信息校验`、`拼装缓存Key`、`不含服务接口调用的逻辑处理`等。 +**充血模型**,指将对象的属性信息与行为逻辑聚合到一个类中,常用的手段如:在对象内提供属于当前对象的`信息校验`、`拼装缓存Key`、`不含服务接口调用的逻辑处理`等。
@@ -46,15 +46,15 @@ DDD 是什么,这应该是每个想使用 DDD 开发项目的研发伙伴, **领域模型**,指特定业务领域内,业务规则、策略以及业务流程的抽象和封装。在设计手段上,通过风暴模型拆分领域模块,形成界限上下文。最大的区别在于把原有的`众多 Service + 数据模型`的方式,拆分为独立的有边界的领域模块。每个领域内创建自身所属的;领域对象(实体、聚合、值对象)、仓储服务(DAO 操作)、工厂、端口适配器Port(调用外部接口的手段)等。 -那么,现在这里有几个概念;领域服务、领域对象、仓储定义、事件消息、端口适配器。我们先来看他们是怎么从贫血模型演变过来的,在细分讲解每个概念。 +那么,现在这里有几个概念:领域服务、领域对象、仓储定义、事件消息、端口适配器。我们先来看他们是怎么从贫血模型演变过来的,在细分讲解每个概念。
-- 在原本的 Service + 贫血的数据模型开发指导下,Service 串联调用每一个功能模块。这些基础设施(对象、方法、接口)是被相互掉调用的。这也是因为贫血模型并没有面向对象的设计,所有的需求开发只有详细设计。 -- 换到充血模型下,现在我们以一个领域功能为聚合,拆分一个领域内所需的 Service 为领域服务,VO、Req、Res 重新设计为领域对象,DAO、Redis 等持久化操作为仓储等。举例;一套账户服务中的,授信认证、开户、提额降额等,每一个都是一个独立的领域,在每个独立的领域内,创建自身领域所需的各项信息。 -- 领域模型还有一个特点,它自身只关注业务功能实现,不与外部任何接口和服务直连。如;不会直接调用 DAO 操作库,也不会调用缓存操作 Redis,更不会直接引入 RPC 连接其他微服务。而是通过仓库和端口适配器,定义调用外部数据的含有出入参对象的接口标准,让基础设施层做具体的调用实现。通过这样的方式让领域只关心业务实现,同时做好防腐。 +- 在原本的 Service + 贫血的数据模型开发指导下,Service 串联调用每一个功能模块。这些基础设施(对象、方法、接口)是被相互调用的。这也是因为贫血模型并没有面向对象的设计,所有的需求开发只有详细设计。 +- 换到充血模型下,现在我们以一个领域功能为聚合,拆分一个领域内所需的 Service 为领域服务,VO、Req、Res 重新设计为领域对象,DAO、Redis 等持久化操作为仓储等。举例:一套账户服务中的,授信认证、开户、提额降额等,每一个都是一个独立的领域,在每个独立的领域内,创建自身领域所需的各项信息。 +- 领域模型还有一个特点,它自身只关注业务功能实现,不与外部任何接口和服务直连。如;不会直接调用 DAO 操作库,也不会调用缓存操作 Redis,更不会直接引入 RPC 连接其他微服务。而是通过仓库和端口适配器,定义调用外部数据的含有出入参对象的接口标准,让基础设施层做具体的调用实现——通过这样的方式让领域只关心业务实现,同时做好防腐。 ### 2.3 实体、聚合、值对象 @@ -62,15 +62,19 @@ DDD 是什么,这应该是每个想使用 DDD 开发项目的研发伙伴, 但在 DDD 的领域模型设计下,领域对象的设计是非常面向对象的。而且在整个风暴事件的四色建模过程也是在以领域对象为驱动进行的。 -实体、聚合、值对象,三者位于每个领域下的领域对象内,服务于领域内的领域服务。三个对象定义具体如下; +实体、聚合、值对象,三者位于每个领域下的领域对象内,服务于领域内的领域服务。三个对象定义具体如下:
+1. 胳膊、腿、身体,都是实体对象,和这个人生命有关。 +2. 帽子、手套、裤衩,都是值对象,是这个人穿戴的,不具有生命属性。 +3. 聚合,就是要写库一个事务,一次形成,可以聚合。把胳膊、腿、身体,放一块,一起让数据库执行事务。 + > **实体** -是依托于持久化层数据以领域服务功能目标为指导设计的领域对象。持久化PO对象是原子类对象,不具有业务语义,而实体对象是具有业务语义且有唯一标识的对象,跟随于领域服务方法的全生命周期对象。如;用户PO持久化对象,会涵盖,用户的开户实体、授信实体、额度实体对象。也包括如商品下单时候的购物车实体对象。这个对象也通常是领域服务方法的入参对象。 +是依托于持久化层数据以领域服务功能目标为指导设计的领域对象。持久化PO对象是原子类对象,不具有业务语义,而实体对象是具有业务语义且有唯一标识的对象,跟随于领域服务方法的全生命周期对象。如:用户PO持久化对象,会涵盖,用户的开户实体、授信实体、额度实体对象。也包括如商品下单时候的购物车实体对象。这个对象也通常是领域服务方法的入参对象。 - 概念:实体 = 唯一标识 + 状态属性 + 行为动作(功能),是DDD中的一个基本构建块,它代表了具有唯一标识的领域对象。实体不仅仅包含数据(状态属性),还包含了相关的行为(功能),并且它的标识在整个生命周期中保持不变。 - 特征: @@ -91,7 +95,7 @@ DDD 是什么,这应该是每个想使用 DDD 开发项目的研发伙伴, > **值对象** -这个对象在领域服务方法的生命周期过程内是不可变对象,也没有唯一标识。它通常是配合实体对象使用。如为实体对象提供对象属性值的描述,比如;一个公司雇员的级别值对象,一个下单的商品收货的四级地址信息对象。所以在开发值对象的时候,通常不会提供 setter 方法,而是提供构造函数或者 Builder 方法来实例化对象。这个对象通常不会独立作为方法的入参对象,但做可以独立作为出参对象使用。 +这个对象在领域服务方法的生命周期过程内是不可变对象,也没有唯一标识。它通常是配合实体对象使用。如为实体对象提供对象属性值的描述,比如:一个公司雇员的级别值对象,一个下单的商品收货的四级地址信息对象。所以在开发值对象的时候,通常不会提供 setter 方法,而是提供构造函数或者 Builder 方法来实例化对象。这个对象通常不会独立作为方法的入参对象,但做可以独立作为出参对象使用。 - 概念:值对象是由一组属性组成的,它们共同描述了一个领域概念。与实体(Entity)不同,值对象不需要有一个唯一的标识符来区分它们。值对象通常是不可变的,这意味着一旦创建,它们的状态就不应该改变。 - 特征: @@ -115,7 +119,7 @@ DDD 是什么,这应该是每个想使用 DDD 开发项目的研发伙伴, > **聚合** -当你对数据库的操作需要使用到多个实体时,可以创建聚合对象。一个聚合对象,代表着一个数据库事务,具有事务一致性。聚合中的实体可以由聚合提供创建操作,实体也被称为聚合根对象。一个订单的聚合,会涵盖;下单用户实体对象、订单实体、订单明细实体和订单收货四级地址值对象。而那个作为入参的购物车实体对象,已经被转换为实体对象了。—— 聚合内事务一致性,聚合外最终一致性。 +当你对数据库的操作需要使用到多个实体时,可以创建聚合对象。一个聚合对象,代表着一个数据库事务,具有事务一致性。聚合中的实体可以由聚合提供创建操作,实体也被称为聚合根对象。一个订单的聚合,会涵盖:下单用户实体对象、订单实体、订单明细实体和订单收货四级地址值对象。而那个作为入参的购物车实体对象,已经被转换为实体对象了。—— 聚合内事务一致性,聚合外最终一致性。 - 概念:聚合是领域模型中的一个关键概念,它是一组具有内聚性的相关对象的集合,这些对象一起工作以执行某些业务规则或操作。聚合定义了一组对象的边界,这些对象可以被视为一个单一的单元进行处理。 - 特征: @@ -179,4 +183,4 @@ DDD 是什么,这应该是每个想使用 DDD 开发项目的研发伙伴, 在所有的模型都定义完成后,领域业务被串联了。那么接下来则是使用,而使用的方式可以包括;接口(http/rpc)、消息监听、定时任务等方式,这些方式统一被定义为触发动作。 -由触发发起对编排功能的调用处理。如;定时任务做信贷的计息、开户成功消息通知返利优惠券、提供接口让外部调用授信逻辑等。这些都是触发动作。 \ No newline at end of file +由触发发起对编排功能的调用处理,如:定时任务做信贷的计息、开户成功消息通知返利优惠券、提供接口让外部调用授信逻辑等——这些都是触发动作。 diff --git a/docs/md/road-map/ddd-guide-02.md b/docs/md/road-map/ddd-guide-02.md index cef1e0ba5..c74c5e72a 100755 --- a/docs/md/road-map/ddd-guide-02.md +++ b/docs/md/road-map/ddd-guide-02.md @@ -20,30 +20,30 @@ lock: need ## 1. 建模目的 -工程的建模的目的是为了我们做工程开发时提供指导方案,就像一栋大楼的设计蓝图一样,也像一个超市中会有不同品类的货架,需要提前规划好。所以你需要在工程开发时所需的各类核心内容,都会在建模中体现,如;分几个包、有哪些核心对象、要串联什么流程、有哪些核心业务要实现、过程中与外部服务的交互。 +工程的建模的目的是为了我们做工程开发时提供指导方案,就像一栋大楼的设计蓝图一样,也像一个超市中会有不同品类的货架,需要提前规划好。所以你需要在工程开发时所需的各类核心内容,都会在建模中体现,如:分几个包、有哪些核心对象、要串联什么流程、有哪些核心业务要实现、过程中与外部服务的交互。 -那么为了达成一个讨论的共识,而不是每个人都有一套的标准和词汇。所以会使用 DDD 提供专门的建模方法和名词进行统一的设计,此外因为 DDD 的统一建模语言,不涉及技术编码,也具有通用性,所以可以在建模过程让产品、研发、测试、架构师等人员一起参与讨论。如;领域、领域模型(实体、聚合、值对象)、领域服务、端口适配器、仓储、界限上下文、领域编排等名词。*这在上一节已经做了相关的解释。* +为了达成讨论的共识,避免每个人都有不同的标准和词汇,我们通常会使用 DDD (领域驱动设计)提供的专门建模方法和统一的名词进行设计。DDD 的统一建模语言不涉及具体的技术编码,具有较强的通用性,因此可以让产品、研发、测试、架构师等人员一起参与讨论建模过程,促进跨职能的沟通和协作。如:领域、领域模型(实体、聚合、值对象)、领域服务、端口适配器、仓储、界限上下文、领域编排等名词。*这在上一节已经做了相关的解释。* -## 2. 怎么建模 +## 2. 如何建模 DDD 的建模过程,是以一个用户为起点,通过行为命令,发起行为动作,串联整个业务。而这个用户的起点最初来自于用例图的分析。用例图是用户与系统交互的最简表示形式,展现了用户和与他相关的用例之间的关系。通过用例图,我们可以分析出所有的行为动作。 -在 DDD 中用于完成用户的行为命令和动作分析的过程,是一个四色建模的过程,也称作风暴模型。在使用 DDD 的标准对系统建模前,一堆人要先了解 DDD 的操作手段,这样才能让产品、研发、测试、运营等了解业务的伙伴,都能在同一个语言下完成系统建模。 +在 DDD 中用于完成用户的行为命令和动作分析的过程,是一个四色建模的过程,也称作风暴模型。在使用 DDD 的标准对系统建模前,一定要先了解 DDD 的操作手段,这样才能让产品、研发、测试、运营等了解业务的伙伴,都能在同一个语言下完成系统建模。
-此图是整个四色建模的指导图,通过寻找领域事件,发起事件命令,完成领域事件的过程,完成 DDD 工程建模。 +上图是整个四色建模的指导图,通过寻找领域事件,发起事件命令,完成领域事件的过程,完成 DDD 工程建模。 -- 蓝色 - 决策命令,是用户发起的行为动作,如;开始签到、开始抽奖、查看额度等。 -- 黄色 - 领域事件,过去时态描述。如;签到完成、抽奖完成、奖品发放完成。它所阐述的都是这个领域要完成的终态。 +- 蓝色 - 决策命令,是用户发起的行为动作,如:开始签到、开始抽奖、查看额度等。 +- 黄色 - 领域事件,过去时态描述。如:签到完成、抽奖完成、奖品发放完成。它所阐述的都是这个领域要完成的终态。 - 粉色 - 外部系统,如你的系统需要调用外部的接口完成流程。 -- 红色 - 业务流程,用于串联决策命令到领域事件,所实现的业务流程。一些简单的场景则直接有决策命令到领域事件就可以了。 +- 红色 - 业务流程,用于串联决策命令到领域事件,所实现的业务流程。一些简单的场景则直接由决策命令到领域事件就可以了。 - 绿色 - 只读模型,做一些读取数据的动作,没有写库的操作。 - 棕色 - 领域对象,每个决策命令的发起,都是含有一个对应的领域对象。 -**👩🏻‍🏫敲黑板** 综上,左下角的示意图。是一个用户,通过一个策略命令,使用领域对象,通过业务流程,完成2个领域事件,调用1次外部接口个过程。我们在整个 DDD 建模过程中,就是在寻找这些节点。 +**👩🏻‍🏫敲黑板** 综上,上图左下部分的示意图表达的是:“一个用户,通过一个策略命令,使用领域对象,通过业务流程,完成2个领域事件,调用1次外部接口”的过程。我们在整个 DDD 建模过程中,就是在寻找这些节点。 ## 3. 超市举例 @@ -61,7 +61,7 @@ DDD 的建模过程,是以一个用户为起点,通过行为命令,发起 ## 4. 业务案例 -接下来,我们在以一个真实的业务场景来分析系统的四色建模过程。 +接下来,我们在以一个真实的业务场景来分析系统的四色建模过程: ### 1. 产品诉求 @@ -109,7 +109,7 @@ DDD 的建模过程,是以一个用户为起点,通过行为命令,发起 ### 4. 识别领域角色和对象 -在确定了领域事件以后,接下来要做的就是通过决策命令串联领域事件,并填充上所需要的领域对象。这块的操作,新手可以分开处理,如先给领域事件添加决策命令、执行用户和领域对象,最后在串联流程。就像 `事件风暴定义` 中的示意一样。 +在确定了领域事件以后,接下来要做的就是通过决策命令串联领域事件,并填充上所需要的领域对象。这块的操作,新手可以分开处理,如先给领域事件添加决策命令、执行用户和领域对象,最后再串联流程。就像 `事件风暴定义` 中的示意一样。
diff --git a/docs/md/road-map/ddd-guide-03.md b/docs/md/road-map/ddd-guide-03.md index 356a5e0ff..84602a710 100755 --- a/docs/md/road-map/ddd-guide-03.md +++ b/docs/md/road-map/ddd-guide-03.md @@ -57,7 +57,7 @@ lock: need
-无论是六边形架构,还是洋葱架构,或是[张毅老师](http://zhangyi.xyz/)提到的南向网关/北向网关的菱形架构,他们的目标都是以领域服务为核心,隔离内部实现与外部资源的耦合。 +无论是六边形架构,还是洋葱架构,或是 张毅老师 - http://zhangyi.xyz/ 提到的南向网关/北向网关的菱形架构,他们的目标都是以领域服务为核心,隔离内部实现与外部资源的耦合。 在 DDD 分层架构下,以支撑 domain 核心领域实现拆分出基础设施(infrastructure),来承接对外部资源的调用。触发器(trigger)向外部提供服务。之后 app 为应用启动、api 为接口定义、types 为通用信息、case 为编排。 @@ -71,7 +71,8 @@ lock: need
-整洁架构的分包形式,会将所有的外部依赖使用和工程内要对外的,统一定义到适配器层。这里可以理解为对适配和对内适配。 +- 整洁架构的分包形式,会将所有的外部依赖使用和工程内要对外的,统一定义到适配器层。这里可以理解为对外适配和对内适配。 +- 阿里的 cola 偏整洁架构 [阿里架构 cola 的相关内容](https://www.aliyun.com/sswb/610119.html) ### 2. 六边形架构 - 工程结构 @@ -125,6 +126,28 @@ DDD 领域驱动设计的中心,主要在于领域模型的设计,以领域 当进入领域层开始,也是智力集中体现的开始了。所有你对工程的抽象能力,都在这一块区域体现。 +**关于对象定义**;vo、po、dto、entity、aggregate、req、res、response + +以下描述使用场景为,在 DDD 领域驱动架构下(六边形、整洁、COLA) + +domain 领域层; +- entity,实体对象,如雇员用户的基本信息、订单信息、配送信息 +- vo(value object),值对象,用于描述实体对象信息。如一个人,这个雇员用户的基本 level 枚举值对象、这个人居住地址四级信息对象。这些对象不具有唯一性,也就是不具有生命特征。就像你,之后你的衣服,你的胡子。 +- aggregate,聚合对象,当我们要写一笔订单入口的时候,需要做事务,事务如果需要一组对象;订单记录、账户记录、库存记录等,这些实体对象+值对象,写入到聚合对象内,一起提交过去。 + +* 以前的 MVC 下的 XXXVo、XxxReq、XxxRes,现在被领域细分成各个模块下的,实体、聚合、值对象了。* + +infrastructure 基础设施层; +- po 数据库持久化对象,用于映射数据库表字段的。这个对象不要做业务流程,只提供数据库数据 +- dto 数据传输对象,这个对象也会在基础设施层出现,用于与外部的接口对接。比如 rpc 接口、http 接口,出入参的对象,都叫做数据传输对象。命名为 XxxRequestDTO、XxxResponseDTO 支付包的sdk包里就是这样命名的。 + +api 层: +- dto 对象,接口的出入参,数据传输对象。命名为 XxxRequestDTO、XxxResponseDTO +- response 对象,包装结果对象,提供 code、info、data,准确描述错误码以及data数据,data数据是泛型,用于包装 XxxResponseDTO 结果。当你f12浏览器,一些互联网的web服务,观察他的接口,就会看到这样的结构。 + +case 编排层: +- 这一层承接 web 的接口编排动作,串联 domain 领域流程。通常2个方案,一个是引入 api 层,定义的对象。另外一个就是多一层转换,在一层定义 api 层对应的 XxxRequestDTO -> XxxRequest、XxxResponseDTO -> XxxResponse + ## 五、工程架构案例 ### 1. 环境 diff --git a/docs/md/road-map/ddd.md b/docs/md/road-map/ddd.md index 69c3442f6..e1eb279cc 100644 --- a/docs/md/road-map/ddd.md +++ b/docs/md/road-map/ddd.md @@ -26,7 +26,7 @@ lock: need
-- 如果你接触过较大型且已经长期维护项目的 MVC 架构,你就会发现这里的 DAO、PO、VO 对象,在 Service 层相互调用。那么长期开发后,就导致了各个 PO 里的属性字段数量都被撑的特别大。这样的开发方式,将`”状态”`、`“行为“`分离到不同的对象中,代码的意图渐渐模糊,膨胀、臃肿和不稳定的架构,让迭代成本增加。 +- 如果你接触过较大型且已经长期维护项目的 MVC 架构,你就会发现这里的 DAO、PO(持久化)、VO(业务对象) 对象,在 Service 层相互调用。那么长期开发后,就导致了各个 VO 里的属性字段数量都被撑的特别大。这样的开发方式,将`”状态”`、`“行为“`分离到不同的对象中,代码的意图渐渐模糊,膨胀、臃肿和不稳定的架构,让迭代成本增加。 - 而 DDD 架构首先以解决此类问题为主,将各个属于自己领域范围内的行为和逻辑封装到自己的领域包下处理。这也是 DDD 架构设计的精髓之一。它希望在分治层面合理切割问题空间为更小规模的若干子问题,而问题越小就容易被理解和处理,做到高内聚低耦合。这也是康威定律所提到的,解决复杂场景的设计主要分为:分治、抽象和知识。 ## 二、简化理解 diff --git a/docs/md/road-map/disruptor.md b/docs/md/road-map/disruptor.md new file mode 100644 index 000000000..73362e753 --- /dev/null +++ b/docs/md/road-map/disruptor.md @@ -0,0 +1,183 @@ +--- +title: Disruptor +lock: need +--- + +# Disruptor 高性能环形消息队列应用,Log4j 2 也用到了这套技术。 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +说到底,无论是晋升述职还是面试考察,编程技能的展现总是在那些技术的横向对比和深度的了解运用。知其一,也知其二。一个场景的问题,往往也会对应着多种的解决方案,从没有绝对的好和不好,都是是否适合而已。所以,往往技术越好的,也越低调,不那么咋咋呼呼的。 + +
+ +
+ +**什么是柔性事务?** + +在分布式软件系统架构设计中,所有的并发资源的竞争,都会往`无锁化`、`非独占竞争`,以及`柔性事务`设计。柔性事务用于替代传统事务管理中(如ACID属性:原子性、一致性、隔离性、持久性),在分布式架构系统中的使用场景。通过消息、补偿,协调不同服务间的一致性。 + +
+ +
+ +那么在消息的使用中,除了有 MQ 消息,使用于微服务之间。还有本地消息,可以作用在各个领域间驱动流程。关于本地消息可以用,Spring 的监听、Redis 发布订阅、Guava EventBus 事件总线,这些内容在小傅哥博客 [bugstack.cn](https://bugstack.cn) 《路书》中有相关的案例。之后本节咱们介绍一个新的高性能组件 Disruptor 的使用。 + +## 一、关于 Disruptor + +Disruptor 是一种高性能的并发框架,最初由 LMAX 开发,用于解决高吞吐量、低延迟的消息处理问题。它提供了一种无锁的、有序的事件处理模型,非常适合处理需要高性能的场景。Disruptor 本身并不是用于实现事务的框架,而是一个事件处理器。因此,要在 Disruptor 上实现柔性事务,需要结合其事件处理能力与柔性事务的模式。 + +- 源码:[https://github.com/LMAX-Exchange/disruptor](https://github.com/LMAX-Exchange/disruptor) +- 文档:[https://lmax-exchange.github.io/disruptor/](https://lmax-exchange.github.io/disruptor/) - 谷歌浏览器右键点翻译为中文。 + +## 二、实战案例 + +### 1. 工程结构 + +小傅哥准备好了一份基于 Disruptor 事件消息的使用案例工程,你可以直接上手体现。 + +
+ +
+ +- app 是使用的启动层、trigger 是提供接口、监听消息、处理任务的触发器层。 +- 在这里我们通过 trigger 下的 event 包,监听事件消息。之后把这个 XxxEventHandler 让 app 层下的 Disruptor 进行实例化。 + +### 2. 引入POM + +```pom + + + com.lmax + disruptor + 3.4.4 + +``` + +- 引入 disruptor pom 包。 + +### 3. 监听消息 + +```java +@Slf4j +public class XxxEventHandler implements EventHandler { + + @Override + public void onEvent(Message longEvent, long l, boolean b) throws Exception { + log.info("接收消息:{}", longEvent.getValue()); + } + + @Data + public static class Message { + private String value; + } + +} +``` + +- 在 trigger 下 event 包内,加一个实现了 disruptor EventHandler 的监听实现类,消息体类型我们定义到 XxxEventHandler 中,也就是 Message。具体生产使用的时候,按需调整。 +- 这个接收消息的过程和使用 MQ 的方式是一样的。 + +### 4. 实例化监听 + +```java +@Configuration +public class DisruptorConfig { + + private final ExecutorService executor = Executors.newCachedThreadPool(); + + @Bean("xxxEventDisruptor") + public Disruptor disruptor() { + // 环形队列的大小,注意要是2的幂 + int bufferSize = 1024; + + // 创建Disruptor + Disruptor disruptor = new Disruptor<>(XxxEventHandler.Message::new, bufferSize, executor); + + // 连接事件处理器 + disruptor.handleEventsWith(new XxxEventHandler()); + + // 开始Disruptor + disruptor.start(); + + return disruptor; + } + +} +``` + +- 在 App 模块下,有一个 config 专门的配置类,在这里配置下消息监听。这个过程和我们之前使用的 Redis 发布订阅是一样的。 + +### 5. 推送消息(Test) + +```java +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class DisruptorTest { + + @Resource + private Disruptor xxxEventDisruptor; + + @Test + public void test_publishEvent() throws InterruptedException { + + for (int i = 0; i < 10; i++) { + xxxEventDisruptor.publishEvent((event, sequence) -> event.setValue("你好,我是 Disruptor Message")); + } + + // 暂停 - 测试完手动关闭程序 + new CountDownLatch(1).await(); + } + +} +``` + +```java +24-10-26.11:55:55.827 [main ] INFO DisruptorTest - Starting DisruptorTest using Java 1.8.0_311 on MacBook-Pro.local with PID 92827 (started by fuzhengwei in /Users/fuzhengwei/1024/KnowledgePlanet/road-map/xfg-dev-tech-disruptor/xfg-dev-tech-app) +24-10-26.11:55:55.829 [main ] INFO DisruptorTest - The following 1 profile is active: "dev" +24-10-26.11:55:57.749 [main ] INFO DisruptorTest - Started DisruptorTest in 2.526 seconds (JVM running for 3.741) +24-10-26.11:55:58.125 [pool-2-thread-1 ] INFO XxxEventHandler - 接收消息:你好,我是 Disruptor Message +24-10-26.11:55:58.128 [pool-2-thread-1 ] INFO XxxEventHandler - 接收消息:你好,我是 Disruptor Message +24-10-26.11:55:58.128 [pool-2-thread-1 ] INFO XxxEventHandler - 接收消息:你好,我是 Disruptor Message +24-10-26.11:55:58.128 [pool-2-thread-1 ] INFO XxxEventHandler - 接收消息:你好,我是 Disruptor Message +24-10-26.11:55:58.128 [pool-2-thread-1 ] INFO XxxEventHandler - 接收消息:你好,我是 Disruptor Message +24-10-26.11:55:58.128 [pool-2-thread-1 ] INFO XxxEventHandler - 接收消息:你好,我是 Disruptor Message +24-10-26.11:55:58.128 [pool-2-thread-1 ] INFO XxxEventHandler - 接收消息:你好,我是 Disruptor Message +24-10-26.11:55:58.128 [pool-2-thread-1 ] INFO XxxEventHandler - 接收消息:你好,我是 Disruptor Message +24-10-26.11:55:58.128 [pool-2-thread-1 ] INFO XxxEventHandler - 接收消息:你好,我是 Disruptor Message +24-10-26.11:55:58.128 [pool-2-thread-1 ] INFO XxxEventHandler - 接收消息:你好,我是 Disruptor Message +``` + +- 提供一个单测来测试消息推送,这样你就可以监听到消息了。 + +## 三、总结 + +在美团、京东、阿里,等各个大厂中都有很多这样的组件使用,在美团发布过的文章中[《高性能队列——Disruptor》](https://tech.meituan.com/2016/11/18/disruptor.html) 还有一个对应的压测数据。CPU:Intel Core i7-2720QM,JVM:Java 1.6.0_25 64-bit,OS:Ubuntu 11.04 + +| - | ABQ | Disruptor | +| :----------------- | :-------- | :--------- | +| Unicast: 1P – 1C | 4,057,453 | 22,381,378 | +| Pipeline: 1P – 3C | 2,006,903 | 15,857,913 | +| Sequencer: 3P – 1C | 2,056,118 | 14,540,519 | +| Multicast: 1P – 3C | 260,733 | 10,860,121 | +| Diamond: 1P – 3C | 2,082,725 | 15,295,197 | + +- 依据并发竞争的激烈程度的不同,Disruptor比ArrayBlockingQueue吞吐量快4~7倍。 + +--- + +另外,Log4j 2 采用了 Disruptor(一种无锁的线程间通信库),提高吞吐量降低延迟。在生产使用中,大并发的系统注意 Log4j 版本。官网说明:[https://logging.apache.org/log4j/2.12.x/manual/async.html](https://logging.apache.org/log4j/2.12.x/manual/async.html) + +
+ +
+ +- **异步 Logger**是 Log4j 2 中的新增功能。其目的是尽快从对 Logger.log 的调用返回到应用程序。您可以选择使所有 Logger 异步,或使用同步和异步 Logger 的混合。使所有 Logger 异步将提供最佳性能,而混合使用则可为您提供更大的灵活性。 +- **LMAX Disruptor 技术**。异步记录器内部使用 [Disruptor(](https://logging.apache.org/log4j/2.12.x/manual/async.html#UnderTheHood)一种无锁的线程间通信库)而不是队列,从而实现更高的吞吐量和更低的延迟。 +- 作为异步日志记录器工作的一部分,**异步附加器**已得到增强,可以在批处理结束时(当队列为空时)刷新到磁盘。这会产生与配置“immediateFlush=true”相同的结果,即所有收到的日志事件始终在磁盘上可用,但效率更高,因为它不需要在每个日志事件上都接触磁盘。(异步附加器在内部使用 ArrayBlockingQueue,不需要类路径上的 Disruptor jar。) diff --git a/docs/md/road-map/docker-deploy-project.md b/docs/md/road-map/docker-deploy-project.md new file mode 100644 index 000000000..27fec75b6 --- /dev/null +++ b/docs/md/road-map/docker-deploy-project.md @@ -0,0 +1,623 @@ +--- +title: Docker 部署项目 +lock: need +--- + +# Docker 部署项目 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +在实践中发现,不少伙伴不了解云服务器是什么,搞不清楚云服务器和本地电脑的关系,也不知道怎么把一个项目部署到云服务器。但作为程序员学习编程,又离不开云服务器,逃避不了一点! + +
+ +
+ +**看看是不你也遇到了这些问题** + +云服务器选什么系统、云服务器怎么安装环境、Intellij IDEA 怎么连接云服务器、云服务器安装了 Docker 本地电脑还用安装吗、SpringBoot 项目怎么部署到云服务器、构建的镜像推送不到 Docker Hub 怎么办? + +等等,一些列的问题,把小白拦截在云服务器的门外。不过,没关系,今天小傅哥就帮你把这接腿🦵🏻的事办啦,让你以后畅通无阻。 + +>文末提供了,5个AI项目、5个业务项目、8个组件项目、1套源码项目,还有非常多的学习资料,你可以全部获取学习,积累来自互联网大厂的经验。 + +## 零、所需资源 + +- [购买云服务器 2c4g](http://618.gaga.plus/) +- [工程案例代码 xfg-dev-tech-docker-deploy](https://github.com/fuzhengwei/xfg-dev-tech-docker-deploy) +- [云服务器安装脚本](https://gaga.plus/app/dev-ops/index.html) +- [云服务器连接工具](https://origin.bugstack.cn/md/road-map/tool.html) +- [阿里云docker镜像仓库](https://cr.console.aliyun.com/cn-hangzhou/instance/repositories) + +## 一、云服务器是什么? + +在使用云服务器之前,我们先来理解下云服务器是什么,把定位搞清楚,后面的事才好办。如图; + +
+ +
+ +- 云服务器,你可以理解为是你的书桌上摆着的2台电脑。你可以通过其中一台电脑,以 SSH 方式连接另外一台电脑,并在另外一台电脑安装 MySQL、Redis、Ollama 等,以减轻当前这台电脑的压力。让手里的这台电脑只负责代码开发,需要什么资源就连接另外一台电脑的上软件即可。 +- 现在为了方便的让每个人都可以拥有自己的另外一台电脑,有一些公司就把电脑集中起来搭建成了服务器机房,在通过提供公网IP让你在购买云服务器后,可以用你的电脑连接上云服务器电脑,进行软件的部署和程序对软件的连接。 + +## 二、云服务器咋操作(命令) + +当然,云服务器的操作也需要一点 Linux 命令的知识,它不是那种`点点点`的方式使用电脑,而是通过命令行。比如,`ls` 查看文件列表、`mkdir` 创建文件夹、`chmod +x` 给文件授予执行权限,当然也有些死鬼告诉你执行 `rm -rf /*` 今天一天都不用干活! + +为了,让小伙伴们,先不需要看非常的多的资料,就能快速的使用起这些命令。这里小傅哥做了个模拟 Linux 服务器,进行命令练习的网页,你可以通过页面的模拟建立 SSH 连接,之后学习这些命令。 + +
+ +
+ +地址:[https://gaga.plus/app/dev-ops/tutorials/what-is-a-cloud-server.html](https://gaga.plus/app/dev-ops/tutorials/what-is-a-cloud-server.html) + +说明:你每点击一个右侧的命令,他就会在左侧进行输入,之后提示命令的用途和效果。这些命令包括了常用的文件、目录、系统、用户的操作,也给大家增加了 Git、Docker、Maven 的命令(右侧往下翻即可) + +## 三、云系统环境安装 + +### 1. 环境选择 + +在你首次购买和设置云服务器的时候,它会让你选择需要安装的系统(也可以重置重新安装),安装完成后你就可以通过命令操作,部署 Docker 以及安装软件了。 + +
+ +
+ +这里比较推荐 Centos 7.6、7.9 或则 Ubuntu 24+,这两个系统,我已经做好了一键安装脚本,可以让你非常方便的把 Docker 以及一些常用的软件,全部安装完成。 + +### 2. 安装脚本 + +#### 2.1 Git 安装 + +**Centos** + +```java +sudo yum install git +``` + +**Ubuntu** + +```java +# sudo apt update +# sudo apt install nodejs npm +# node -v +# npm -v +``` + + +```java +apt-get install git +``` + +#### 2.2 Docker + Portainer + +```java +root@iv-ydw2iok0lcbw80bxaha0:~# ls +root@iv-ydw2iok0lcbw80bxaha0:~# cd / +root@iv-ydw2iok0lcbw80bxaha0:/# mkdir dev-ops +root@iv-ydw2iok0lcbw80bxaha0:/# ls +bin cdrom etc lib64 media proc sbin sys var +bin.usr-is-merged dev home lib.usr-is-merged mnt root sbin.usr-is-merged tmp +boot dev-ops lib lost+found opt run srv usr +root@iv-ydw2iok0lcbw80bxaha0:/# cd dev-ops/ +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops# ls +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops# git clone https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install.git +Cloning into 'xfg-dev-tech-docker-install'... +remote: Enumerating objects: 181, done. +remote: Counting objects: 100% (35/35), done. +remote: Compressing objects: 100% (21/21), done. +remote: Total 181 (delta 20), reused 25 (delta 14), pack-reused 146 (from 1) +Receiving objects: 100% (181/181), 12.51 MiB | 1.26 MiB/s, done. +Resolving deltas: 100% (75/75), done. +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops# ls +xfg-dev-tech-docker-install +``` + +- 推荐;git clone https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install.git +- 备用;git clone https://github.com/fuzhengwei/xfg-dev-tech-docker-install.git + +- 在 Linux 系统的根目录,通过命令创建一个空文件夹,进入文件夹,通过 git clone 检出代码。 +- 这里有2个地址,如果 github.com 检出很慢,可以使用 gitcode.com 地址检出。 + +```java +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install# chmod +x ubuntu_run_install_docker_local.sh +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install# ./ubuntu_run_install_docker_local.sh +[INFO] 使用本地Docker安装脚本: ubuntu_install_docker.sh +[INFO] 设置可执行权限... +[INFO] 开始执行Docker安装脚本... +[INFO] 注意:安装过程可能需要root权限,如果需要会自动请求 +----------------------------------------------------------- +[INFO] docker 环境安装脚本 By xiaofuge,建议使用 https://618.gaga.plus 优惠购买服务器,安装 Ubuntu 24.04 LTS 系统。 +[INFO] 开始安装 Docker 环境... +[INFO] 检查系统信息... +内核版本: 6.8.0-55-generic +操作系统: Ubuntu 24.04 LTS +[INFO] 检测网络连接状态... +[INFO] 网络连接正常,可以访问: https://www.baidu.com +[INFO] 网络连接检测通过 +... +Status: Downloaded newer image for registry.cn-hangzhou.aliyuncs.com/xfg-studio/portainer:latest +1c2d6211944ced359ebec2e5d28b9cf30eec55bc781b386838c54abc944ed1f3 +[INFO] Portainer安装成功! +[WARNING] 重要提示:请确保您的云服务器已开放9000端口! +----------------------------------------------------------- +Portainer访问方式: +1. 通过公网访问:http://您的服务器公网IP:9000 +2. 首次访问需要设置管理员账号和密码 +3. 登录后即可通过Web界面管理Docker容器 +----------------------------------------------------------- +[INFO] 您可以使用Portainer来方便地管理Docker容器、镜像、网络和卷等资源 +``` + +- Centos 执行 `chmod +x centos_run_install_docker_local.sh` `./centos_run_install_docker_local.sh` +- Ubuntu 执行 `chmod +x ubuntu_run_install_docker_local.sh` `./ubuntu_run_install_docker_local.sh` + +执行的中间,他会有一些提示你的操作,你可以按照提示输入之后继续运行就好。安装到最后,Docker + Portainer 就安装完成了。注意,云服务器的访问,需要开放对应的端口在云服务器的安全组中找到出入站配置(也可以在云服务器官网搜,他都会提供文档)。 + +#### 2.3 软件安装(JDK、Maven)可选 + +在 xfg-dev-tech-docker-install 一键安装脚本中,还有提供 JDK、Maven 的安装。这个软件安全是为了在云服务器直接构建 Java 项目,如果你不需要,是完全可以不用安装的。 + +**Centos 安装** + +```java +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install# ls +centos_install_docker.sh help.md software +centos_run_install_docker_local.sh README.md ubuntu_install_docker.sh +environment run_install_software.sh ubuntu_run_install_docker_local.sh +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install# cd environment/ +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment# ls +jdk maven +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment# cd jdk/ +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment/jdk# ls +install-java.sh remove-java.sh +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment/jdk# chmod +x install-java.sh +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment/jdk# ./install-java.sh +[INFO] 开始JDK安装程序... +[INFO] 检测到系统: Ubuntu 24.04 + +[INFO] 请选择要安装的JDK版本: +1. JDK 8 (1.8.0_202) +2. JDK 17 (17.0.14) + +请选择版本 (1/2): 1 +[INFO] 已选择JDK 8 +[INFO] JDK配置: 版本=1.8.0_202, 包名=jdk-8u202-linux-x64.tar.gz +[INFO] 检查并安装依赖包... +[INFO] JDK包已存在: ./jdk-8u202-linux-x64.tar.gz +[SUCCESS] JDK包验证通过 +[INFO] 开始安装JDK 1.8.0_202 到: /usr/local/java +[INFO] 解压JDK包... +[SUCCESS] JDK解压完成 +... +\033[0;34m环境变量:\033[0m +JAVA_HOME=/usr/local/java +PATH=$JAVA_HOME/bin:$PATH +CLASSPATH=$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar +是否删除下载的JDK包? (y/N): N +[SUCCESS] JDK 1.8.0_202 安装完成! +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment/jdk# java -version +``` + +```java +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment# ls +jdk maven +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment# cd maven/ +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment/maven# ls +apache-maven-3.8.8.zip install-maven.sh remove-maven.sh +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment/maven# chmod +x install-maven.sh +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment/maven# ./install-maven.sh +[INFO] 开始Maven安装程序... +[INFO] 检测到系统: Ubuntu 24.04 +[INFO] 检测到Java版本: 1.8.0_472 +[INFO] 检查并安装依赖包... +[SUCCESS] Maven包验证通过 +[INFO] 开始安装Maven 3.8.8 到: /usr/local/maven +[INFO] 解压Maven包... +[SUCCESS] Maven解压完成 +[INFO] 配置环境变量... +[SUCCESS] 环境变量配置完成 +[INFO] 环境变量已在当前会话中生效 +[INFO] 验证安装... +[SUCCESS] Maven安装成功! +``` + +**Ubuntu 安装** + +```java +sudo apt update +sudo apt install openjdk-8-jdk + +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment# java -version +openjdk version "1.8.0_472" +OpenJDK Runtime Environment (build 1.8.0_472-8u472-ga-1~24.04-b08) +OpenJDK 64-Bit Server VM (build 25.472-b08, mixed mode) +``` + +```java +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment/maven# apt install maven +Reading package lists... Done +Building dependency tree... Done +Reading state information... Done +The following packages were automatically in + +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment/maven# mvn --version +Apache Maven 3.8.7 +Maven home: /usr/share/maven +... +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/environment/maven# cd /usr/share/maven +root@iv-ydw2iok0lcbw80bxaha0:/usr/share/maven# ls +bin boot conf lib man +root@iv-ydw2iok0lcbw80bxaha0:/usr/share/maven# cd conf +root@iv-ydw2iok0lcbw80bxaha0:/usr/share/maven/conf# ls +logging m2.conf settings.xml toolchains.xml +``` + +Ubuntu 基本通过 apt 就可以完整这些软件的安装了。注意进入 conf 替换 settings.xml 文件带有阿里云 maven 镜像的地址。 + +地址:[https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install/blob/main/environment/maven/apache-maven-3.8.8/conf/settings.xml](https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install/blob/main/environment/maven/apache-maven-3.8.8/conf/settings.xml) + +#### 2.4 软件安装(MySQL、Redis) + +```java +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install# cd software/ +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/software# ls +docker-compose-software-aliyun.yml grafana logstash pgvector rabbitmq +docker-compose-software.yml kibana mysql prometheus redis +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install/software# cd .. +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install# ls +centos_install_docker.sh help.md software +centos_run_install_docker_local.sh README.md ubuntu_install_docker.sh +environment run_install_software.sh ubuntu_run_install_docker_local.sh +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install# chmod +x run_install_software.sh +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-install# ./run_install_software.sh +[INFO] 当前磁盘空间信息:总空间 40G,已使用 4.3G,可用 34G,使用率 12% +----------------------------------------------------------- +[HEADER] 选择配置文件: +----------------------------------------------------------- +1. 使用原始配置文件 (推荐,但可能需要从Docker Hub拉取镜像) +2. 使用阿里云镜像配置文件 (国内网络环境推荐) +----------------------------------------------------------- +请选择配置文件 [1/2] (默认: 1): 1 +[INFO] 已选择使用原始配置文件 +----------------------------------------------------------- +[HEADER] 可安装的软件列表: +----------------------------------------------------------- +1. nacos (预计占用空间: 500MB) +2. mysql (预计占用空间: 600MB) +3. phpmyadmin (预计占用空间: 100MB) +4. redis (预计占用空间: 50MB) +5. redis-admin (预计占用空间: 50MB) +6. rabbitmq (预计占用空间: 300MB) +7. elasticsearch (预计占用空间: 500MB) +8. logstash (预计占用空间: 300MB) +9. kibana (预计占用空间: 200MB) +10. xxl-job-admin (预计占用空间: 150MB) +11. prometheus (预计占用空间: 100MB) +12. grafana (预计占用空间: 100MB) +13. ollama (预计占用空间: 200MB) +14. pgvector (预计占用空间: 150MB) +15. pgvector-admin (预计占用空间: 50MB) +----------------------------------------------------------- +请选择要安装的软件(多选,用空格分隔,如:1 3 5): +2 3 +----------------------------------------------------------- +[HEADER] 您选择了以下软件: +- phpmyadmin (预计占用空间: 100MB) +- mysql (预计占用空间: 600MB) +总计预计占用空间: 700MB +----------------------------------------------------------- +----------------------------------------------------------- +[HEADER] MySQL初始化提示: +----------------------------------------------------------- +[INFO] 您选择了安装MySQL,安装完成后可以使用phpmyadmin进行管理 +[INFO] 如果您希望在初始化时创建数据库和表,可以将SQL脚本放在以下目录: + /dev-ops/xfg-dev-tech-docker-install/software/mysql/sql/ +[INFO] 目前该目录已包含以下SQL文件: + - init.sql + - nacos.sql + - xxl_job.sql +[INFO] 您可以添加自己的SQL文件到该目录,它们将在MySQL初始化时自动执行 +----------------------------------------------------------- +确认安装以上软件?(y/n): y +[INFO] 正在检查服务依赖关系... +[INFO] 开始安装选中的软件... +[+] Running 34/34 + ✔ phpmyadmin 21 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled 499.9s + ✔ 858a356e9dad Pull complete 1.7s + ✔ Container phpmyadmin Started 5.8s +[INFO] 软件安装完成! +----------------------------------------------------------- +[HEADER] 已安装的软件及访问信息: +- phpmyadmin: 访问地址:http://服务器IP:8899 (连接到MySQL) +- mysql: 账号:root 密码:123456 端口:13306 +[INFO] MySQL已安装成功,您可以使用phpmyadmin进行管理 +[INFO] 初始化SQL脚本已自动执行,包括: + - init.sql + - nacos.sql + - xxl_job.sql +----------------------------------------------------------- +[INFO] 如需修改账号密码,请编辑 /dev-ops/xfg-dev-tech-docker-install/software/docker-compose-software.yml 文件 +[INFO] 修改后,重新运行此脚本即可更新配置 +``` + +- 执行提供好的脚本,即可完成各项软件的安装。其他的软件,也可以搜索教程安装。 + +### 3. 应用配置 + +
+ +
+ +- 云服务器环境 Docker + Portainer(管理docker的软件) 以及软件安装完成后,你就可以在你的 IntelliJ IDEA 的程序里配置对应的连接信息了。这样你的本地就可以连接到云服务器上的 Docker 里安装的 MySQL 了。 +- Docker 是非常常用的软件,也是非常好用的软件,对于开发学习部署和卸载各类软件都非常方便,不会破坏本地环境。 + +## 四、项目部署 + +Docker 部署项目需要的是程序的镜像,镜像的目的是把一个程序运行所需的各类环境都给打包进行,等运行部署的时候直接执行即可。 + +所以,这里我们会通过各种方式来完成镜像的构建和部署,包括; +| 方案 | 复杂度 | +| ------------------------------------------------------------ | ------ | +| 本地打包Jar + 云上构建镜像。 | ⭐️⭐️ | +| 云上打包Jar + 云上构建镜像。 | ⭐️⭐️⭐️ | +| 本地打包Jar + 本地构建镜像 + 上传到阿里云 Docker 镜像仓库 + 云上拉取构建 | ⭐️⭐️⭐️⭐️ | + +### 1. 文件配置 + +#### 1.1 dockerfile + +```java +# 基础镜像 openjdk:8-jre-slim +FROM registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:8-jre-slim + +# 作者 +MAINTAINER xiaofuge + +# 配置 +ENV PARAMS="" + +# 时区 +ENV TZ=PRC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# 添加应用 +ADD target/xfg-dev-tech-docker-deploy-app.jar /xfg-dev-tech-docker-deploy-app.jar + +ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS /xfg-dev-tech-docker-deploy-app.jar $PARAMS"] +``` + +- 这里配置了构建镜像的地址信息。 + +#### 1.2 build.sh + +```java +# 普通镜像构建,随系统版本构建 amd/arm +docker build -t system/xfg-dev-tech-docker-deploy-app:1.0-SNAPSHOT -f ./Dockerfile . + +# 兼容 amd、arm 构建镜像 +# docker buildx build --load --platform liunx/amd64,linux/arm64 -t xiaofuge/xfg-frame-archetype-app:1.0 -f ./Dockerfile . --push +``` + +- 配置了构建镜像的名称。 + +### 2. 构建镜像 + +#### 2.1 本地打包Jar + 云上构建镜像 + +##### 2.1.1 打包jar + +
+ +
+ +- 在本地 install 构建项目 jar,target 目录下可以只保留项目的 jar 其他的删掉就可以。 + +##### 2.1.2 上传jar + +
+ +
+ +- 把本地构建的jar,通过 sftp 把整个 xfg-dev-tech-deploy-app 上传到云服务器。 + +##### 2.1.3 构建镜像 + +```java +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops# ls +xfg-dev-tech-docker-deploy-app xfg-dev-tech-docker-install +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops# cd xfg-dev-tech-docker-deploy-app/ +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy-app# ls +build.sh Dockerfile pom.xml src target +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy-app# chmod +x build.sh +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy-app# ./build.sh +[+] Building 64.5s (8/8) FINISHED docker:default + => [internal] load build definition from Dockerfile 0.0s + => => transferring dockerfile: 484B 0.0s + => WARN: MaintainerDeprecated: Maintainer instruction is deprecated in favor of using label (line 5 0.0s + => [internal] load metadata for registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:8-jre-slim 0.7s + => [internal] load .dockerignore 0.0s + => => transferring context: 2B 0.0s +... + => => unpacking to docker.io/system/xfg-dev-tech-docker-deploy-app:1.0-SNAPSHOT 0.1s + + 1 warning found (use docker --debug to expand): + - MaintainerDeprecated: Maintainer instruction is deprecated in favor of using label (line 5) +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy-app# docker images + i Info → U In Use +IMAGE ID DISK USAGE CONTENT SIZE EXTRA +mysql:8.0.32 f496c25da703 728MB 157MB U +phpmyadmin:5.2.1 6e75aa8f767c 798MB 193MB U +registry.cn-hangzhou.aliyuncs.com/xfg-studio/portainer:latest + 11384457b374 374MB 86.8MB U +system/xfg-dev-tech-docker-deploy-app:1.0-SNAPSHOT 14e1cd401829 332MB 98.2MB +``` + +- 通过这样的方式就把整个镜像构建出来,`docker images` 可以查看镜像列表,system/xfg-dev-tech-docker-deploy-app:1.0-SNAPSHOT 就是咱们构建的镜像。 + +#### 2.2 云上打包Jar + 云上构建镜像 + +##### 2.2.1 拉取项目 + +```java +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy# ls +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy# git clone https://github.com/fuzhengwei/xfg-dev-tech-docker-deploy.git +Cloning into 'xfg-dev-tech-docker-deploy'... +remote: Enumerating objects: 176, done. +remote: Counting objects: 100% (176/176), done. +remote: Compressing objects: 100% (87/87), done. +remote: Total 176 (delta 23), reused 175 (delta 22), pack-reused 0 (from 0) +Receiving objects: 100% (176/176), 75.84 KiB | 40.00 KiB/s, done. +Resolving deltas: 100% (23/23), done. +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy# ls +xfg-dev-tech-docker-deploy +``` + +- 通过 git clone 命令,拉取项目。 + +##### 2.2.2 打包jar + +```java +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy# ls +docs pom.xml README.md xfg-dev-tech-docker-deploy-app +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy# mvn clean install +[INFO] Scanning for projects... +Downloading from central: https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-starter-parent/2.7.12/spring-boot-starter-parent-2.7.12.pom +... +[INFO] ------------------------------------------------------------------------ +[INFO] Reactor Summary for xfg-dev-tech-docker-deploy 1.0-SNAPSHOT: +[INFO] +[INFO] xfg-dev-tech-docker-deploy ......................... SUCCESS [ 0.219 s] +[INFO] xfg-dev-tech-docker-deploy-app ..................... SUCCESS [05:29 min] +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 05:29 min +[INFO] Finished at: 2025-12-21T10:56:57+08:00 +[INFO] ------------------------------------------------------------------------ +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy# ls +docs pom.xml README.md xfg-dev-tech-docker-deploy-app +``` + +- 进入到项目,通过 `mvn clean install` 打包项目 jar + +##### 2.2.3 构建镜像 + +```java +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy-app# ls +build.sh Dockerfile pom.xml src target +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy-app# chmod +x build.sh +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy-app# cat build.sh +# 普通镜像构建,随系统版本构建 amd/arm +docker build -t system/xfg-dev-tech-docker-deploy-app:1.1-SNAPSHOT -f ./Dockerfile . + +# 兼容 amd、arm 构建镜像 +# docker buildx build --load --platform liunx/amd64,linux/arm64 -t xiaofuge/xfg-frame-archetype-app:1.0 -f ./Dockerfile . --pushroot@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy-app# ./build.sh +[+] Building 1.3s (8/8) FINISHED docker:default + => [internal] load build definition from Dockerfile 0.0s + => => transferring dockerfile: 484B 0.0s + => WARN: MaintainerDeprecated: Maintainer instruction is deprecated in favor of using label (line 5) 0.0s + => [internal] load metadata for registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:8-jre-slim 0.4s + => [internal] load .dockerignore 0.0s + => => transferring context: 2B 0.0s + => [1/3] FROM registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:8-jre-slim@sha256:285c61a1e5e6b7b3709729b69558670148c5fdc6eb7104fae 0.0s + => => resolve registry.cn-hangzhou.aliyuncs.com/xfg-studio/openjdk:8-jre-slim@sha256:285c61a1e5e6b7b3709729b69558670148c5fdc6eb7104fae 0.0s + => [internal] load build context 0.1s + => => transferring context: 26.15MB 0.1s + => CACHED [2/3] RUN ln -snf /usr/share/zoneinfo/PRC /etc/localtime && echo PRC > /etc/timezone 0.0s + => [3/3] ADD target/xfg-dev-tech-docker-deploy-app.jar /xfg-dev-tech-docker-deploy-app.jar 0.0s + => exporting to image 0.7s + => => exporting layers 0.6s + => => exporting manifest sha256:14e4dd6822541669e1ac4c0c6957c74be06f401556ffca134fa42133df9dacb1 0.0s + => => exporting config sha256:f4581c52995e78750c432c2bd3c7bcaa393398ee7d7d62c331ccb69c2825a724 0.0s + => => exporting attestation manifest sha256:5c7a6af7000015669c2e5dccd10d74b68357359994f42a5e211883ab2b0d7335 0.0s + => => exporting manifest list sha256:335d04f3bc894e32e70b2c126a6e0abccd4c6136d44e6b9c1f0060e492816419 0.0s + => => naming to docker.io/system/xfg-dev-tech-docker-deploy-app:1.1-SNAPSHOT 0.0s + => => unpacking to docker.io/system/xfg-dev-tech-docker-deploy-app:1.1-SNAPSHOT 0.1s + + 1 warning found (use docker --debug to expand): + - MaintainerDeprecated: Maintainer instruction is deprecated in favor of using label (line 5) +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy/xfg-dev-tech-docker-deploy-app# docker images + i Info → U In Use +IMAGE ID DISK USAGE CONTENT SIZE EXTRA +mysql:8.0.32 f496c25da703 728MB 157MB U +phpmyadmin:5.2.1 6e75aa8f767c 798MB 193MB U +registry.cn-hangzhou.aliyuncs.com/xfg-studio/portainer:latest 11384457b374 374MB 86.8MB U +system/xfg-dev-tech-docker-deploy-app:1.0-SNAPSHOT 14e1cd401829 332MB 98.2MB +system/xfg-dev-tech-docker-deploy-app:1.1-SNAPSHOT 335d04f3bc89 332MB 98.2MB +``` + +- 这样,就在云服务器把项目镜像构建出来了。 + +#### 2.3 阿里云 DockerHub + +##### 2.3.1 账号申请 + +官网:[https://cr.console.aliyun.com/cn-hangzhou/instance/dashboard](https://cr.console.aliyun.com/cn-hangzhou/instance/dashboard) + +
+ +
+ +- 如图所示,申请账号,创建个人的命名空间。步骤3、4可选。 +- 之后你这里可以手动操作上传镜像,也可以走下面的流程自动操作。 + +##### 2.3.2 上传镜像 + +
+ +
+ +- 在项目下,有一个 push.sh 文件,可以把镜像推送到阿里云 DockerHub 镜像库。这样操作的目的是有个统一地方来维护镜像,各个云服务器都可以拉取部署了。 +- 推送后,可以到仓库查看镜像 [https://cr.console.aliyun.com/cn-hangzhou/instance/repositories](https://cr.console.aliyun.com/cn-hangzhou/instance/repositories) + +### 3. 项目部署 + +#### 3.1 脚本说明 + +
+ +
+ +- 这里的镜像名称,要修改成你的镜像名称。 + +#### 3.2 上传脚本 + +
+ +
+ +- 上传项目下的部署脚本到云服务器,dev-ops 创建个文件夹。 + +#### 3.3 执行部署 + +```java +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/docker-compose# ls +app docker-compose-app.yml docker-compose-environment-aliyun.yml docker-compose-environment.yml mysql +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/docker-compose# docker-compose -f docker-compose-app.yml up -d +[+] Running 6/6 + ✔ xfg-dev-tech-docker-deploy 5 layers [⣿⣿⣿⣿⣿] 0B/0B Pulled 205.7s + ✔ f355a2e0723d Pull complete 34.0s + ✔ f7ec5a41d630 Pull complete 65.9s + ✔ b747e468795b Pull complete 203.7s + ✔ 88f5ee065d77 Pull complete 0.3s + ✔ faf4c47c8c61 Pull complete 36.0s +[+] Running 1/2 + ⠋ Network docker-compose_my-network Created 2.0s + ✔ Container xfg-dev-tech-docker-deploy Started 1.9s +root@iv-ydw2iok0lcbw80bxaha0:/dev-ops/docker-compose# +``` + +
+ +
+ +- 部署后,就可以访问服务看最终的效果了!** diff --git a/docs/md/road-map/docker-install.md b/docs/md/road-map/docker-install.md new file mode 100644 index 000000000..86979b0c8 --- /dev/null +++ b/docs/md/road-map/docker-install.md @@ -0,0 +1,350 @@ +--- +title: Docker 环境配置(一键安装) +lock: need +--- + +# Docker 环境配置(一键安装) + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +说实话,做项目不上线,等于吃面不配蒜🧄,效果少一半!面试官也说:“所有做Java编程项目,没有上线云服务器的,一律当玩具看!” 是呀,做完项目不上线,是不你做的项目没法运行,是个小卡拉米练手的?🤔 那怎么办? + +其实,上线云服务器非常非常简单,而且云服务器价格也非常非常便宜!趁着618活动月,**28块钱**,都能买一年的云服务器☁️,干嘛不上车! + +
+ +
+ +**啥是云服务器?** + +云服务器,就等同于自己的另外一个电脑💻,在另外一台电脑部署 redis、mysql、mq等,本地电脑连接过去使用。尤其是 Windows 电脑用户,真心建议搞个云服务器,否则你会浪费非常多的时间这套 Windows 适配问题。 + +
+ +
+ +这样有了云服务器,就可以不用嚯嚯本地电脑了,安装了卸,卸了安装,把自己本机电脑环境弄的乱码起糟,全是费时费力的事。有这精力,不如用一台云服务器部署环境,开发完成项目后,再上线云服务器。既节省本地电脑资源,又锻炼了云服务器操作,起步一举两得! + +
+ +
+ +不过,放心!别担心你不会用云服务器,因为小傅哥已经给你准备了一件安装云服务器环境的脚本,和各类部署环境和构建项目的视频。**即使是小卡拉米,也能跟着学习下来。** + +> 🧧小傅哥还提供了非常多的编程实战项目,包括;业务的、组件的、AI的、源码的、轮子的,可以关注公众号「bugstack虫洞栈」回复「星球」加入。 + +## 一、优惠云服务器地址 + +
+ +
+ +- 购买地址:[https://618.gaga.plus](https://618.gaga.plus) +- 购买地址:[https://618.gaga.plus](https://618.gaga.plus) +- 购买地址:[https://618.gaga.plus](https://618.gaga.plus) + +**我适合买哪个服务器?** + +- 2c2g 1年,28¥,可部署一套 docker、mysql、redis、SpringBoot 单体项目,用于替代本地电脑的环境部署。 +- 2c4g 1年(非常推荐3年),109¥,可部署一套 docker、mysql、redis、rabbitmq、xxl-job、SpringBoot 分布式微服务项目。 +- 2c8g 1年,328¥,适合部署小傅哥星球社群[大部分项目](https://bugstack.cn/md/zsxq/material/student-learn-advanced.html),可以完成多个微服务项目部署。 + +注意📢:购买选择系统时,推荐系统镜像,**centos 7.9** + +>如果自己账号不是新人身份,可以自己注册个新账号,用家里人JD扫码认证一下即可。 + +🎁 礼物赠送,购买2c4g 3年的,赠送Joy公仔,邮寄到家!购买后,联系小傅哥(微信:fustack) + +## 二、一键部署脚本 + +小傅哥,这里为你准备一键安装 Docker 环境的脚本文件,你可以非常省心的完成 Docker 部署。使用方式如下。 + +
+ +
+ +- **地址**: +- **地址**: + +本文档介绍如何执行项目中的各个脚本,包括权限设置和执行步骤。 + +### 1. 上传脚本&设置权限 + +
+ +
+ +- ssh 工具,推荐 termius。[https://bugstack.cn/md/road-map/tool.html](https://bugstack.cn/md/road-map/tool.html) 免费的就够用,带有 sftp 工具。 +- 左侧是云服务器空间 root 下,右侧是本地环境。可以把整个文件夹全部拖到云服务器。 +- 另外,也可以在云服务器执行 `sudo yum install git` 安装 Git,通过 git clone 拉取脚本。 + +在执行任何脚本之前,需要先为脚本文件添加可执行权限: + +``` +# 为所有脚本添加可执行权限 +chmod +x environment/jdk/install-java.sh +chmod +x environment/jdk/remove-java.sh +chmod +x run_install_docker_local.sh +chmod +x run_install_software.sh +chmod +x install-maven.sh +chmod +x remove-maven.sh + +``` +或者一次性为所有脚本添加权限: + +``` +find . -name "*.sh" -type f -exec chmod +x {} \; +``` + +### 2. JDK 安装脚本 + +#### 2.1 安装 JDK + +脚本位置: environment/jdk/install-java.sh + +功能: 支持安装 JDK 8 和 JDK 17 + +执行方式: + +``` +# 交互式安装(推荐) +sudo ./environment/jdk/install-java.sh + +# 指定版本安装 +sudo ./environment/jdk/install-java.sh -v 8 # 安装 JDK 8 +sudo ./environment/jdk/install-java.sh -v 17 # 安装 JDK 17 + +# 强制安装(覆盖已有安装) +sudo ./environment/jdk/install-java.sh -f -v 8 + +# 静默安装 +sudo ./environment/jdk/install-java.sh -q -v 8 + +# 自定义安装目录 +sudo ./environment/jdk/install-java.sh -d /opt/java -v 8 +``` +注意事项: + +- 需要 root 权限执行 +- 脚本会提示手动下载 JDK 包到 /dev-ops/java 目录 +- 支持的版本:JDK 8 (1.8.0_202) 和 JDK 17 (17.0.14) +- 安装完成后环境变量会自动配置 + +#### 2.2 卸载 JDK + +脚本位置: environment/jdk/remove-java.sh + +功能: 彻底清理 JDK 安装和环境配置 + +执行方式: + +``` +# 交互式删除(推荐) +sudo ./environment/jdk/remove-java.sh + +# 强制删除 +sudo ./environment/jdk/remove-java.sh -f + +# 静默删除 +sudo ./environment/jdk/remove-java.sh -f -q + +# 指定安装目录删除 +sudo ./environment/jdk/remove-java.sh -d /opt/java + +# 删除时不备份配置文件 +sudo ./environment/jdk/remove-java.sh --no-backup +``` +注意事项: + +- 需要 root 权限执行 +- 会自动备份配置文件(除非使用 --no-backup) +- 清理系统和用户级环境变量配置 + +### 2.3 Maven 安装脚本 + +#### 2.3.1 安装 Maven + +脚本位置:`environment/maven/install-maven.sh` + +功能:自动安装 Apache Maven 3.8.8 + +执行方式: + +```bash +# 交互式安装(推荐) +sudo ./environment/maven/install-maven.sh + +# 自定义安装目录 +sudo ./environment/maven/install-maven.sh -d /opt/maven + +# 使用本地Maven包 +sudo ./environment/maven/install-maven.sh -p /path/to/apache-maven-3.8.8.zip + +# 强制安装(覆盖已有安装) +sudo ./environment/maven/install-maven.sh -f + +# 静默安装 +sudo ./environment/maven/install-maven.sh -q + +# 强制静默安装 +sudo ./environment/maven/install-maven.sh -f -q +``` + +### 3. Docker 安装脚本 + +脚本位置: run_install_docker_local.sh + +功能: 使用本地的 install_docker.sh 脚本安装 Docker + +执行方式: + +``` +# 执行 Docker 安装 +./run_install_docker_local.sh +``` +注意事项: + +- 脚本会自动检查 install_docker.sh 文件是否存在 +- 如果需要 root 权限会自动请求 +- 安装完成后会询问是否安装 Portainer 容器管理界面 +- Portainer 访问地址: http://服务器IP:9000 + +### 4. 软件安装脚本 + +脚本位置: run_install_software.sh + +功能: 使用 Docker Compose 安装各种开发软件 + +执行方式: + +``` +# 执行软件安装 +sudo ./run_install_software.sh +``` + +支持的软件: + +- nacos - 服务注册与发现 +- mysql - 数据库 +- phpmyadmin - MySQL 管理界面 +- redis - 缓存数据库 +- redis-admin - Redis 管理界面 +- rabbitmq - 消息队列 +- elasticsearch - 搜索引擎 +- logstash - 日志处理 +- kibana - 日志分析界面 +- xxl-job-admin - 任务调度 +- prometheus - 监控系统 +- grafana - 监控面板 +- ollama - AI 模型服务 +- pgvector - 向量数据库 +- pgvector-admin - 向量数据库管理界面 + 注意事项: + +- 需要 root 权限执行 +- 需要先安装 Docker 和 docker-compose +- 脚本会检查磁盘空间并显示预计占用 +- 支持选择原始配置或阿里云镜像配置 +- 可以多选软件进行批量安装 + +### 5. 常见问题 + +#### 5.1 权限问题 + +如果遇到权限拒绝错误: + +``` +# 确保脚本有执行权限 +ls -la *.sh +# 如果没有 x 权限,重新添加 +chmod +x script_name.sh +``` + +#### 5.2 环境变量生效 + +JDK 安装后,环境变量在当前会话中已生效,新开终端需要: + +``` +# 重新加载配置 +source /etc/profile +# 或者重新登录 +``` + +#### 5.3 Docker 相关 + +确保 Docker 服务正在运行: + +``` +# 检查 Docker 状态 +sudo systemctl status docker +# 启动 Docker 服务 +sudo systemctl start docker +``` + +### 6. 执行顺序建议 + +1. 首先安装 JDK (如果需要): + + ``` + sudo ./environment/jdk/install-java.sh -v 8 + ``` + +2. 然后安装 Docker : + + ``` + ./run_install_docker_local.sh + ``` + +3. 然后安装 Docker : + + ``` + ./install-maven.sh + ``` + +4. 最后安装开发软件 : + + ``` + sudo ./run_install_software.sh + ``` + 按照以上步骤,您就可以成功执行所有脚本并搭建完整的开发环境。 + +### 7. 安装演示 + +#### 7.1 docker 安装 + +
+ +
+ +```java +[root@xiaofuge ~]# ls +run_install_docker_local.sh +[root@xiaofuge ~]# chmod +x run_install_docker_local.sh +[root@xiaofuge ~]# ./run_install_docker_local.sh +``` + +- 执行完 `./run_install_docker_local.sh ` 全程会自动化安装,如果已经过 docker 会提示是否卸载。使用起来非常方便。 + +#### 7.2 软件安装 + +```java +[root@xiaofuge dev-ops]# ls +install_docker.sh README.md run_install_docker_local.sh run_install_docker.sh run_install_software.sh software +[root@xiaofuge dev-ops]# chmod +x run_install_software.sh +[root@xiaofuge dev-ops]# ls +install_docker.sh README.md run_install_docker_local.sh run_install_docker.sh run_install_software.sh software +``` + +
+ +
+ +- 安装时候可以选择需要安装的软件,重复安装也会提示卸载。 + diff --git a/docs/md/road-map/docker-what.md b/docs/md/road-map/docker-what.md new file mode 100644 index 000000000..24d2d8ea9 --- /dev/null +++ b/docs/md/road-map/docker-what.md @@ -0,0 +1,76 @@ +--- +title: Docker 是什么? +lock: need +--- + +# Docker 是什么? + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +**好用,真的好用!** 自从使用 Docker 后,我可以非常简单的`安装`、`使用`、`卸载`各类所需的软件,如;MySql、Redis、RabbitMQ、XXL-Job、FRP,等一些列开发环境和我自己开发的好的项目进行上线发布。以前一个MySql安装到卸载,可能半天时间都没了。但有 Docker 后,我自己既可以是开发工程师也是可以是软件实施工程师。因为他可以一行脚本即可完成所有的操作,脚本在,环境就在,服务就在。 + +
+ +
+ +**那 Docker 是什么呢?** + +Docker 是什么,其实来自于 Docker 的图标已经说明。Docker 的图标是一条鲸鱼 🐳一样的大船,上面摆放了很多集装箱。你可以把这些集装箱当做是一个个不同的应用程序,虽然不同但可以统一用一套集装箱(脚本命令)承载,并承放在统一一条大船上(环境上)。而且这些集装箱都有自己的编号ID(有自己的IP)互相隔离,不受影响。 + +Docker 是一个用于开发、发布和运行应用程序的开放平台。Docker 可让您将应用程序与基础架构分离,以便快速交付软件。借助 Docker,您可以像管理应用程序一样管理基础架构。通过利用 Docker 的发布、测试和部署代码方法,您可以显著减少编写代码和在生产中运行代码之间的延迟。 + +官网:[https://www.docker.com/](https://www.docker.com/) +文档:[https://docs.docker.com/get-started/docker-overview/](https://docs.docker.com/get-started/docker-overview/) + +## 一、Docker 安装在哪 + +Docker 可以安装在 Windows + wsl2、Mac、Linux,支持 ARM、AMD 架构。它可以通过软件下载安装和执行脚本命令安装,也可以通过云服务器提供的镜像直接购买云服务器时选择使用。我们可以看下 Docker 和虚拟机安装在操作系统上的关系来了解 Docker 的安装位置。 + +
+ +
+ +与虚拟机的安装使用相比,Docker 会把应用所需的依赖、函数库、甚至其他的软件应用可以一起打包成一个镜像,这样在应用程序运行时,就可以直接调用本地函数库,然后和 Linux 内核进行通信。有了这样的设计,你也就不需要关心每一个应用所需的环境都是啥了,也不用为每一个应用安装各类环境到 Linux 或者虚拟机了。也就做到了跨系统的运行。这有点类似于 Java 的 JVM 虚拟机。 + +- 本地安装:[https://www.docker.com/](https://www.docker.com/) - 下载 Mac、Windows 你需要的版本进行安装。 +- 云服务器:[https://bugstack.cn/md/road-map/docker.html](https://bugstack.cn/md/road-map/docker.html) - centos 7.9 其他的也都类似操作即可。 + +>安装完成后都可以通过命令操作,安装、部署、卸载软件。文末提供了教程链接。 + +## 二、Docker 怎么工作 + +Docker 为了屏蔽软件使用差异,会统一对这些软件进行镜像打包,把一个软件所需的各类环境都打包到镜像中。我们在使用的时候,就是使用各类平台提供好的软件镜像,进行服务部署。同样的我们也可以作为镜像提供方,把我们的应用程序 SpringBoot、React、VUE 等,打包成镜像,让我们在其他地方,如云服务器进行部署。或者提供给全网的人员,进行部署使用。 + +
+ +
+ +如图,这是一整套的,本地拉取镜像、部署环境、开发代码、发布镜像,再到云服务器拉取镜像、部署项目和环境的过程。在这个过程中,我们也可以借助于如 Github Action 完成镜像的构建和发布,还可以在云服务器上直接构建镜像,减少了拉取拉取的过程。 + +> 你可以理解为,Docker 就是一个中心和一个客户端,中心管理镜像,客户端拉取使用或者构建发布镜像。 + +## 三、Docker 命令说明 + +Docker 的操作是通过脚本命令配置和执行完成使用,不过不用害怕命令😱,命令是最简单、直接、可靠的方式。当你习惯命令以后,你会很喜欢它,并且知道只要执行这个命令就一定会有结果,而不像被软件包装后,不确定是软件的问题还是命令的问题。 + +Docker 安装软件分为直接使用和通过 Docker Compose 脚本。直接使用如;`docker run -d --restart=always --name portainer -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer` 这条命令会自动拉取和执行脚本。不过对于更大的项目部署,Docker Compose 脚本更好用。 + +
+ +
+ +- 如图,是整个 Docker Compose 在配置一套执行脚本后,各个脚本的核心用途。当然 Docker Compose 还有不少的命令,比如容量的限制、端口的处理、默认的命令等,都是可以操作的,凡是你想的合理的,它都可以支持。 +- 特别注意,安装到云服务器的docker部署的应用,外部访问需要走公网IP:Port端口,之后这个端口要在安全组打开。这样就类似于你再本地自己的电脑发,访问另外一台电脑上的服务了。 +- 如果在使用中遇到其他命令不理解的,可以让 [openai](https://openai.itedus.cn) 解释。 + +## 四、Docker 实操教程 + +此外,为了大家更好的使用 Docker 搭建各类环境,小傅哥为大家准备好了文档和视频。可以放心食用。 + +- 文档:[https://bugstack.cn/md/road-map/docker.html](https://bugstack.cn/md/road-map/docker.html) - 这是一个系列,你可以从左侧目录选择阅读。 +- 视频:[https://www.bilibili.com/video/BV1xw411W7xf](https://www.bilibili.com/video/BV1xw411W7xf) - 对应一整套的视频,手把手操作。 \ No newline at end of file diff --git a/docs/md/road-map/docker.md b/docs/md/road-map/docker.md index 282f28e99..3fb609b15 100644 --- a/docs/md/road-map/docker.md +++ b/docs/md/road-map/docker.md @@ -1,9 +1,9 @@ --- -title: Docker +title: Docker 环境配置(手动安装) lock: need --- -# Docker 环境配置 +# Docker 环境配置(手动安装) 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) @@ -133,6 +133,7 @@ Available Packages ```java [root@CodeGuide ~]# sudo yum install docker-ce +[root@CodeGuide ~]# 推荐;sudo yum install -y docker-ce-25.0.5 docker-ce-cli-25.0.5 containerd.io ``` - 安装默认最新版本的 Docker `最新版本可能有坑,最好指定版本安装` @@ -157,8 +158,6 @@ sudo chmod +x /usr/local/bin/docker-compose **镜像地址** ```shell -# 默认路径 -wget https://gitee.com/fustack/docker-compose/releases/download/v2.24.1/docker-compose-linux-x86_64 # 指定路径【推荐】 sudo curl -L https://gitee.com/fustack/docker-compose/releases/download/v2.24.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose # 设置权限 @@ -244,7 +243,8 @@ Docker version 20.10.11, build dea9396 ### 12. 设置国内源 -阿里云提供了镜像源:[https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors](https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors) - 登录后你会获得一个专属的地址。 +1. 【推荐】1panel 提供了镜像源 [https://status.1panel.top/status/docker](https://status.1panel.top/status/docker) - `直接进去就可以找到最新的镜像源` +2. 阿里云提供了镜像源:[https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors](https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors) - 登录后你会获得一个专属的地址。 使用以下命令来设置 Docker 国内源:- 或者你可以通过 `vim /etc/docker/daemon.json` 进入修改添加 registry-mirrors 内容后重启 Docker @@ -259,13 +259,19 @@ sudo systemctl daemon-reload sudo systemctl restart docker ``` -**软件配置** +可用镜像检测:[https://status.1panel.top/status/docker](https://status.1panel.top/status/docker) + +#### 12.1 本地Docker软件配置 + +
+ +
```yaml { "registry-mirrors" : [ - "https://h1log1d5.mirror.aliyuncs.com", - "http://docker.mirrors.ustc.edu.cn", - "http://hub-mirror.c.163.com" + "https://docker.1panel.live", + "https://dc.j8.work", + "https://docker.m.daocloud.io" ], "builder": { "gc": { @@ -288,7 +294,7 @@ sudo systemctl restart docker 这样对国内服务器拉取Docker仓库影响比较大。不过得亏国内有Docker Hub镜像平台。有付费的,有免费的! -**配置镜像** +#### 12.2 Linux 配置 Docker 镜像 ```yaml sudo mkdir -p /etc/docker @@ -309,9 +315,8 @@ sudo systemctl restart docker ``` - 参考链接:https://cloud.tencent.com/developer/article/2301228 -- 可信镜像中心:[https://atomhub.openatom.cn/](https://atomhub.openatom.cn/) -### 13. 远程连接 +### 13. 远程连接 - 不推荐 ```shell script vim /lib/systemd/system/docker.service diff --git a/docs/md/road-map/draw.io.md b/docs/md/road-map/draw.io.md new file mode 100644 index 000000000..4ffdac94a --- /dev/null +++ b/docs/md/road-map/draw.io.md @@ -0,0 +1,140 @@ +--- +title: draw.io + ai agent +lock: need +--- + +# draw.io + ai Agent,确实打开新思路 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获! + + + +大家好,我是技术UP主小傅哥。 + +又到年底了,又要必不可少的开始画图做PPT述职啦 😂,述职的好坏和年终奖都有可能挂钩!这对天天写代码大部分的程序员👨🏻‍💻来说是一件非常头疼的事,但好在这次可以使用个**神器**! + +
+ +
+ +**Ai Agent 会结合到各个场景!** + +可以想象,将来我们使用的各种工具,都会很方便的以标准的协议方式结合到 AI Agent 智能体。这就像小傅哥,25年,年初开始做 Ai Agent 时,对一个智能体的执行过程,是需要自己进行分析,设计,实现的(`那时候我就在讲,Agent 也会出标准框架`)。到了年中的时候 Google ADK 除了 0.1.0 最初的版本,年尾发布了 0.4.0,这个框架提供了构建智能体的最基本框架,可以整合 Spring AI、Langchain4j 快速构建智能体。 + +>Spring AI、Langchain4j 提供的是 AI 封装能力,Google ADK 提供的是 Agent 执行能力(并行、循环、串行)的组装和使用。 + +未来(甚至不会太久),各个软件与 Ai Agent 的对接会变得非常容易,你手里用到的各项软件,都可以很方便的添加上智能体的能力。就像,我们现在用到的 `trae.ai`、`Cursor`,在以后 Ai Agent 基础能力成熟后,在结合 `Visual Studio Code` 给出软件对接标准协议,那么任何一个人都可以快速的搭建出一个智能体编码工具。除此之外,其他的软件也都会逐步提供出这样的能力。 + +扩展的思路分析完毕,小傅哥这次先带着大家了解下,draw.io 是怎么与 Ai 结合使用的。 + +>🧧 文末提供了小傅哥所有编程实战项目获取方式,一次加入即可获得19个已完结的和本次新开展的。 + +## 一、关于 draw.io + +draw.io 是一个用于绘制通用图表的 JavaScript 客户端编辑器。 + +官网:[https://www.drawio.com/](https://www.drawio.com/) +代码:[https://github.com/jgraph/drawio](https://github.com/jgraph/drawio) + +
+ +
+ +我所有的这类的绘图,都来自于使用 draw.io 完成([bugstack.cn](https://bugstack.cn) 还有很多绘图)。它可以下载到本地使用,也可以在网页使用。如果你是开发人员,还可以使用它的开发组件引入到自己的程序中进行使用。也正因如此,有了 Ai Agent 能力的结合,一种是通过 MCP,另外一种是直接通过扩展功能,直接在 draw.io 二开上完成。接下来小傅哥会分别介绍这两种方式以及使用。 + +## 二、MCP 方式对接 + +MCP(Model Context Protocol)是用于解决 AI 与服务接口通信的标准模型上下文协议,该协议通过标准化通信方式,使AI应用程序能够访问和使用实时数据、执行操作,从而克服了模型训练数据的局限性。 你可以将MCP想象成AI应用程序的“USB-C接口”,它提供了一个标准化的方法,让AI模型能够连接各种外部资源。 + +**Draw.io Model Context Protocol (MCP) Server**,就是基于此协议实现的对接 Draw.io 的 MCP 服务。我们可以使用这样一套服务,把 AI 与 Draw.io 建立起使用链接。 + +源码:[https://github.com/lgazo/drawio-mcp-server](https://github.com/lgazo/drawio-mcp-server) + +### 1. 插件安装 + +- 谷歌浏览器:[https://chromewebstore.google.com/detail/drawio-mcp-extension/okdbbjbbccdhhfaefmcmekalmmdjjide](https://chromewebstore.google.com/detail/drawio-mcp-extension/okdbbjbbccdhhfaefmcmekalmmdjjide) +- 火狐浏览器:[https://addons.mozilla.org/en-US/firefox/addon/drawio-mcp-extension/](https://addons.mozilla.org/en-US/firefox/addon/drawio-mcp-extension/) + +
+ +
+ +安装完成后,可以看到这样一个小插件(右侧插件文件里可以点击让常驻浏览器),之后后面可以等着使用(继续下面的步骤)。 + +### 2. 配置服务 + +```java +{ + "mcpServers": { + "drawio": { + "command": "npx", + "args": [ + "-y", + "drawio-mcp-server" + ] + } + } +} +``` + +#### 2.1 trae.ai - 也可以其他的 + +
+ +
+ +#### 2.2 spring ai + +
+ +
+ +### 3. 使用服务 + +首先打开:[https://app.diagrams.net/#](https://app.diagrams.net/) + +
+ +
+ +- 对接上之后,你就可以在右侧提问了。之后他就可以实时的出设计图。`受限于MCP服务对接,它不是在 Draw.io 上扩展,会缺少一些交互和判断,画图有时候会有重叠。` +- 不过,这个方式的好处是,你可以结合自己的代码,拖进去,让它直接出架构图、流程图、模型图等。之后在自己做一些调整。 + +## 三、软件方式使用 + +现在 Github 上有很多基于 Draw.io 的二次开发,结合了 Ai 的能力,这里小傅哥找到一个做这块功能比较早的,next-ai-draw-io 来演示给大家。感兴趣的伙伴,还可以结合代码做二次开发。 + +这是一个基于 Next.js 的 Web 应用程序,它将 AI 功能与 draw.io 图表集成在一起。该应用程序允许您通过自然语言命令和 AI 辅助可视化来创建、修改和增强图表。 + +### 1. 代码下载 + +代码:[https://github.com/DayuanJiang/next-ai-draw-io](https://github.com/DayuanJiang/next-ai-draw-io) + +```java +git clone https://github.com/DayuanJiang/next-ai-draw-io.git +``` + +
+ +
+ +下载代码后,注意修改配置文件。 + +### 2. 启动工程 + +
+ +
+ +- 进入 package.json 点击绿色箭头执行启动。 + +### 3. 访问项目 + +
+ +
+ +- 访问 http://localhost:6002 这样你就可以提问来让它绘制图了。这个效果还不错。 \ No newline at end of file diff --git a/docs/md/road-map/dump-mat.md b/docs/md/road-map/dump-mat.md index ba978facf..15b94bd5e 100644 --- a/docs/md/road-map/dump-mat.md +++ b/docs/md/road-map/dump-mat.md @@ -20,7 +20,7 @@ lock: need **什么场景才会有 OutOfMemoryError** -能写出 OutOfMemoryError 的不是编码不精,就是故意埋坑。其实很多时候我们很难在正常编码写写出一个 OutOfMemoryError,因为这个过程你需要大量的往内存加数据,逐步把 JVM 的内存耗尽。而只是1G内存容量(-Xmx1G),仅订单数据就要300多万条记录,谁又能写个 MyBatis SQL 操作,要一次直接把`300万`数据查询到程序内存里呢。 +能写出 OutOfMemoryError 的不是编码不精,就是故意埋坑。其实很多时候我们很难在正常编码写出一个 OutOfMemoryError,因为这个过程你需要大量的往内存加数据,逐步把 JVM 的内存耗尽。而只是1G内存容量(-Xmx1G),仅订单数据就要300多万条记录,谁又能写个 MyBatis SQL 操作,要一次直接把`300万`数据查询到程序内存里呢。 不过,还真可能有!但这个不是程序员故意编码查询300万,而是在做数据导出的时候,处理分页的加法计算有问题,导致每次都是 limit 0,n,n 不断的加大。正确的应该是 limit m,n 这样的查询。这样的 `OutOfMemoryError`,在过往工作中就遇到过,最终经过排查到一次要从数据库获取几百万条数据,导致服务宕机。 @@ -232,4 +232,8 @@ public void test_java_heap_space_list() throws InterruptedException { - 我们本案例采用的是 MySql 8.x 如果你使用其他线程池工具,还可能会返回具体的 SQL 语句一起打印出来。方便分析。 -好啦,有了这样一个分析过程,你也可以尝试熟悉下工具,分析分析其他的 Java heap space 场景。几次玩下来也就熟悉这个工具了。 \ No newline at end of file +好啦,有了这样一个分析过程,你也可以尝试熟悉下工具,分析分析其他的 Java heap space 场景。几次玩下来也就熟悉这个工具了。 + +--- + +其他工具;[https://visualvm.github.io/](https://visualvm.github.io/) diff --git a/docs/md/road-map/dump-visualvm.md b/docs/md/road-map/dump-visualvm.md new file mode 100644 index 000000000..fc2d6eb42 --- /dev/null +++ b/docs/md/road-map/dump-visualvm.md @@ -0,0 +1,533 @@ +--- +title: dump VisualVM +lock: need +--- + +# VisualVM 分析 Java heap space dump 日志 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +没毕业前以为学编程,以为工作后就只是写代码。工作后才发现,写代码只是一少部分工作。 + +`JMeter 压测`、`Remote JVM Debug - 远程调试`、`AREX - 流量录制&回放`、`ELK - 分布式日志`、`普罗米修斯监控`、`Arthas`、`Dump日志分析`等,但凡一样不会,基本就会在某一个场景踩坑。**小则是报警异常,大则是线上事故!** + +
+ +
+ +**👨🏻‍💻程序员,也是高危行业呀!** + +从互联网草蜢时代,到现在工作了这么多年,也是见证了很多程序员因为写Bug毕业啦🎓,即使不是被开除,往往重大的事故也会影响未来的绩效、加薪和晋升。这些事故按;照影响时长、影响用户量、造成的资损、解决的时长等,会被定级为 P0、P1、P2、P3 不同级别的事故。 + +所以,到目前有越来越多的辅助工具,来帮助研发提高代码交付质量,以及各类系统异常分析工具,提高问题排查效率。类似这样的系统、服务、组件,小傅哥已经在 [bugstack.cn 编程路书](https://bugstack.cn/md/road-map/road-map.html) 做了大量的案例讲解。今天小傅哥在给大家分享一个关于 VisualVM 的使用。 + +## 一、关于 VisualVM + +VisualVM 是一款可视化 Java 故障排除工具,集成了 JDK 命令行工具和轻量级性能分析功能。专为开发和生产环境设计。 + +
+ +
+ +下载:[https://visualvm.github.io/download.html](https://visualvm.github.io/download.html) + +> 接下来,小傅哥会结合 VisualVM 做一些常用的案例,方便伙伴学习。 + +## 二、案例 - 分析大对象 + +### 1. 测试工程 + +
+ +
+ +- 地址:[https://github.com/fuzhengwei/xfg-dev-tech-visualvm](https://github.com/fuzhengwei/xfg-dev-tech-visualvm) +- 说明:这是一个简单的测试工程,通过访问接口产生大对象。之后在通过 JmapDumpController 接口,执行命令,产生 Dump 文件。之后在使用 VisualVM 分析产生的 Dump 日志,定位是哪个对象导致的问题。 + +### 2. 执行程序 + +首先,启动 xfg-dev-tech-visualvm 应用程序。之后执行 visualvm-test.sh 脚本,Windows 用户需要在 powershell 里执行,Mac 电脑可以直接在 IntelliJ IDEA 点击绿色箭头执行。 + +
+ +
+ +- 首先,点击启动程序,本地运行即可。一般公司里线上的应用,也有专门下载 dump 日志的地方。 +- 之后,执行 `./visualvm-test.sh` 这部分写了测试程序的脚本和获取 dump 日志的操作。 + +#### 2.1 接口;创建对象 + +```java +@RestController +@RequestMapping("/api/memory") +public class MemoryTestController { + + // 用于存储大对象的静态变量,模拟内存泄漏 + private static final Map MEMORY_CACHE = new ConcurrentHashMap<>(); + private static final List BIG_OBJECTS = new ArrayList<>(); + + /** + * 大对象接口 - 创建大量对象占用内存 + */ + @GetMapping("/big-object") + public Map bigObjectApi() { + // 创建大对象(10MB的字节数组) + byte[] bigData = new byte[10 * 1024 * 1024]; // 10MB + for (int i = 0; i < bigData.length; i++) { + bigData[i] = (byte) (i % 256); + } + + // 将大对象存储到静态集合中,模拟内存泄漏 + BIG_OBJECTS.add(bigData); + + Map result = new HashMap<>(); + result.put("status", "success"); + result.put("message", "创建了一个大对象(10MB)"); + result.put("timestamp", System.currentTimeMillis()); + result.put("bigObjectsCount", BIG_OBJECTS.size()); + result.put("totalMemoryUsed", BIG_OBJECTS.size() * 10 + "MB"); + + return result; + } + + /** + * 内存泄漏接口 - 持续创建对象并缓存 + */ + @GetMapping("/memory-leak") + public Map memoryLeakApi() { + String key = "data_" + System.currentTimeMillis(); + + // 创建大量小对象并缓存 + List dataList = new ArrayList<>(); + for (int i = 0; i < 10000; i++) { + dataList.add("这是第" + i + "个数据对象,包含一些文本内容用于占用内存空间"); + } + + MEMORY_CACHE.put(key, dataList); + + Map result = new HashMap<>(); + result.put("status", "success"); + result.put("message", "创建了10000个小对象并缓存"); + result.put("timestamp", System.currentTimeMillis()); + result.put("cacheSize", MEMORY_CACHE.size()); + result.put("cacheKey", key); + + return result; + } + + /** + * 超大对象接口 - 创建超大对象 + */ + @GetMapping("/huge-object") + public Map hugeObjectApi() { + // 创建超大对象(100MB的字节数组) + byte[] hugeData = new byte[100 * 1024 * 1024]; // 100MB + + // 填充数据 + for (int i = 0; i < hugeData.length; i++) { + hugeData[i] = (byte) (Math.random() * 256); + } + + BIG_OBJECTS.add(hugeData); + + Map result = new HashMap<>(); + result.put("status", "success"); + result.put("message", "创建了一个超大对象(100MB)"); + result.put("timestamp", System.currentTimeMillis()); + result.put("bigObjectsCount", BIG_OBJECTS.size()); + + return result; + } + +} +``` + +#### 2.2 接口;获取日志(dump) + +```java +@RestController +@RequestMapping("/api/jmap") +public class JmapDumpController { + + // 使用相对路径,基于项目根目录 + private static final String DUMP_DIR = "docs/dump"; + + /** + * 获取绝对路径的dump目录 + */ + private String getDumpDirectory() { + // 获取项目根目录 + String userDir = System.getProperty("user.dir"); + // 如果当前目录是xfg-dev-tech-app,则需要回到上级目录 + if (userDir.endsWith("xfg-dev-tech-app")) { + userDir = new File(userDir).getParent(); + } + return userDir + File.separator + DUMP_DIR; + } + + /** + * 生成堆转储文件 + */ + @GetMapping("/dump") + public Map generateHeapDump() { + Map result = new HashMap<>(); + + try { + // 获取dump目录的绝对路径 + String dumpDir = getDumpDirectory(); + + // 确保目录存在 + File dir = new File(dumpDir); + if (!dir.exists()) { + dir.mkdirs(); + } + + // 获取当前进程的PID + String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; + + // 生成文件名(包含时间戳) + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); + String timestamp = sdf.format(new Date()); + String fileName = "heap_dump_" + timestamp + ".hprof"; + String filePath = dumpDir + File.separator + fileName; + + // 执行jmap命令生成堆转储 + String command = "jmap -dump:format=b,file=" + filePath + " " + pid; + Process process = Runtime.getRuntime().exec(command); + int exitCode = process.waitFor(); + + if (exitCode == 0) { + result.put("status", "success"); + result.put("message", "堆转储文件生成成功"); + result.put("filePath", filePath); + result.put("fileName", fileName); + } else { + result.put("status", "error"); + result.put("message", "堆转储文件生成失败"); + result.put("exitCode", exitCode); + } + + } catch (IOException | InterruptedException e) { + result.put("status", "error"); + result.put("message", "生成堆转储文件时发生异常: " + e.getMessage()); + } + + result.put("timestamp", System.currentTimeMillis()); + return result; + } + +} +``` + +#### 2.3 脚本;统一执行 + +```java +#!/bin/bash + +# VisualVM 内存测试自动化脚本 +# 作者: xiaofuge +# 用途: 自动化测试内存接口并生成dump文件 + +# 配置参数 +BASE_URL="http://localhost:8091" +DUMP_DIR="../dump" +LOG_FILE="$DUMP_DIR/test_log_$(date +%Y%m%d_%H%M%S).txt" + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# 日志函数 +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" +} + +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" | tee -a "$LOG_FILE" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" | tee -a "$LOG_FILE" +} + +log_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" | tee -a "$LOG_FILE" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE" +} + +# 检查应用是否启动 +check_app_status() { + log_info "检查应用状态..." + response=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/api/memory/status") + if [ "$response" = "200" ]; then + log_success "应用已启动,状态正常" + return 0 + else + log_error "应用未启动或状态异常 (HTTP: $response)" + return 1 + fi +} + +# 等待应用启动 +wait_for_app() { + log_info "等待应用启动..." + for i in {1..30}; do + if check_app_status > /dev/null 2>&1; then + log_success "应用启动成功" + return 0 + fi + log_info "等待中... ($i/30)" + sleep 2 + done + log_error "应用启动超时" + return 1 +} + +# 调用API接口 +call_api() { + local endpoint=$1 + local description=$2 + local count=${3:-1} + + log_info "调用接口: $description" + for ((i=1; i<=count; i++)); do + response=$(curl -s "$BASE_URL$endpoint") + status=$(echo "$response" | grep -o '"status":"[^"]*"' | cut -d'"' -f4) + if [ "$status" = "success" ]; then + log_success "[$i/$count] $description - 成功" + else + log_error "[$i/$count] $description - 失败: $response" + fi + sleep 1 + done +} + +# 显示内存状态 +show_memory_status() { + log_info "获取内存状态..." + response=$(curl -s "$BASE_URL/api/memory/status") + echo "$response" | python3 -m json.tool 2>/dev/null || echo "$response" + echo "" +} + +# 生成dump文件 +generate_dump() { + log_info "生成堆转储文件..." + response=$(curl -s "$BASE_URL/api/jmap/dump") + status=$(echo "$response" | grep -o '"status":"[^"]*"' | cut -d'"' -f4) + if [ "$status" = "success" ]; then + filename=$(echo "$response" | grep -o '"fileName":"[^"]*"' | cut -d'"' -f4) + log_success "堆转储文件生成成功: $filename" + else + log_error "堆转储文件生成失败: $response" + fi +} + +# 生成内存信息文件 +generate_memory_info() { + log_info "生成内存信息文件..." + response=$(curl -s "$BASE_URL/api/jmap/memory-info") + status=$(echo "$response" | grep -o '"status":"[^"]*"' | cut -d'"' -f4) + if [ "$status" = "success" ]; then + filename=$(echo "$response" | grep -o '"fileName":"[^"]*"' | cut -d'"' -f4) + log_success "内存信息文件生成成功: $filename" + else + log_error "内存信息文件生成失败: $response" + fi +} + +# 清理缓存 +clear_cache() { + log_info "清理缓存..." + response=$(curl -s "$BASE_URL/api/memory/clear-cache") + status=$(echo "$response" | grep -o '"status":"[^"]*"' | cut -d'"' -f4) + if [ "$status" = "success" ]; then + log_success "缓存清理成功" + else + log_error "缓存清理失败: $response" + fi +} + +# 主测试流程 +run_test() { + log_info "开始VisualVM内存测试" + + # 检查dump目录 + if [ ! -d "$DUMP_DIR" ]; then + log_info "创建dump目录: $DUMP_DIR" + mkdir -p "$DUMP_DIR" + fi + + # 等待应用启动 + if ! wait_for_app; then + log_error "应用启动失败,退出测试" + exit 1 + fi + + # 显示初始内存状态 + log_info "=== 初始内存状态 ===" + show_memory_status + + # 测试普通接口 + call_api "/api/memory/normal" "普通接口测试" 5 + + # 显示内存状态 + log_info "=== 普通接口调用后内存状态 ===" + show_memory_status + + # 测试大对象接口 + call_api "/api/memory/big-object" "大对象接口测试" 10 + + # 显示内存状态 + log_info "=== 大对象创建后内存状态 ===" + show_memory_status + + # 生成第一次dump + generate_dump + generate_memory_info + + # 测试内存泄漏接口 + call_api "/api/memory/memory-leak" "内存泄漏接口测试" 20 + + # 显示内存状态 + log_info "=== 内存泄漏测试后内存状态 ===" + show_memory_status + + # 测试超大对象接口 + call_api "/api/memory/huge-object" "超大对象接口测试" 5 + + # 显示内存状态 + log_info "=== 超大对象创建后内存状态 ===" + show_memory_status + + # 生成第二次dump + generate_dump + generate_memory_info + + # 清理缓存 + clear_cache + + # 显示清理后内存状态 + log_info "=== 缓存清理后内存状态 ===" + show_memory_status + + # 生成第三次dump + generate_dump + generate_memory_info + + log_success "VisualVM内存测试完成" + log_info "日志文件: $LOG_FILE" + log_info "dump文件目录: $DUMP_DIR" +} + +# 显示帮助信息 +show_help() { + echo "VisualVM 内存测试脚本" + echo "" + echo "用法: $0 [选项]" + echo "" + echo "选项:" + echo " test 运行完整测试流程" + echo " check 检查应用状态" + echo " status 显示内存状态" + echo " dump 生成堆转储文件" + echo " memory-info 生成内存信息文件" + echo " clear 清理缓存" + echo " help 显示帮助信息" + echo "" + echo "示例:" + echo " $0 test # 运行完整测试" + echo " $0 check # 检查应用状态" + echo " $0 dump # 生成dump文件" +} + +# 主程序 +case "${1:-test}" in + "test") + run_test + ;; + "check") + check_app_status + ;; + "status") + show_memory_status + ;; + "dump") + generate_dump + ;; + "memory-info") + generate_memory_info + ;; + "clear") + clear_cache + ;; + "help") + show_help + ;; + *) + log_error "未知选项: $1" + show_help + exit 1 + ;; +esac +``` + +- 整个脚本,会帮助我们执行接口请求以及获取 dump 日志。 + +### 3. Dump 分析 + +
+ +
+ +- 首先,先通过 VisualVM load dump 日志文件,之后点击 Instances By Size 大的文件。 +- 之后,对大的文件对象,点击 references 这样就可以看到是哪个对象影响的问题了。很快的就能帮你分析出程序内产生大的对象的问题原因。 + +## 三、案例;GC 插件 + +VisualVM 还有类似于[普罗米修斯](https://bugstack.cn/md/road-map/grafana.html)一样的监控,可以查看到 JVM 运行情况。也可以帮助我们分析程序运行情况。 + +### 1. 安装插件 - VisualVM + +
+ +
+ +- 在 VisualVM 安装 Visual GC 插件。 + +### 2. 安装插件 - IntelliJ IDEA + +
+ +
+ +- 也可以给 Intellij IDEA 安装一个 VisualVM Launcher 插件,启动程序可以直接使用。 + +### 3. 进入监控 + +
+ +
+ +- 打开 VisualVM 看到本地启动的程序,之后打开 Visual GC +- 这里还可以看见 Monitor、Threads、Profiler,方便我们分析程序 + +### 4. GC 说明 + +
+ +
+ +- 如图,各个模块展示了 JVM 运行状况,从这里可以看到程序占用内存的情况。如果是压测验证,可以打开辅助分析。 + diff --git a/docs/md/road-map/frp.md b/docs/md/road-map/frp.md new file mode 100644 index 000000000..c3c29d2b8 --- /dev/null +++ b/docs/md/road-map/frp.md @@ -0,0 +1,273 @@ +--- +title: Frp 内网穿透 +lock: need +--- + +# Frp 内网穿透,用云服务器IP,教你搭一套内网穿透服务! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +作为一个研发人员,我们经常有诉求把本机正在开发阶段的应用,通过本地部署的方式让外部其他人进行访问验证。尤其是一些给远程远程客户演示的时候,也是非常需要这样的服务。但本机并不是公网IP,都是内网的,怎么样外部访问呢? + +
+ +
+ +**FRP 内网穿透是什么?** + +内网穿透是一种技术手段,用于访问位于防火墙或路由器后面的本地网络(内网)中的设备或服务。通常情况下,内网中的设备无法直接通过公网(互联网)进行访问,从而实现隐私保护和安全性。内网穿透技术的目标是突破这一限制,使外部用户能够通过互联网访问内网中的服务或设备。 + +虽然市面也有一些内网穿透的服务,包括; `natapp`、`coplar`、`花生壳`等,如果你不想折腾,也可以直接使用。但折腾一下,往往会省钱! + +## 1. 搭建脚本 + +这里小傅哥使用了 `fatedier/frp` 0.60 版本进行搭建,提供了相关的运行脚本。 + +
+ +
+ +- 地址:[https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-frp](https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-frp) +- 官网:[https://github.com/fatedier/frp](https://github.com/fatedier/frp) + +### 1.1 frps - 服务端 + +```java +# https://github.com/fatedier/frp/blob/dev/conf/frps_full_example.toml +[common] +# 监听端口 +bind_port = 7000 +# 面板端口 +dashboard_port = 7500 +# 登录面板的账号密码(修改成自己的) +dashboard_user = admin +dashboard_pwd = admin +# token = +``` + +- token 如果设定了,需要保持客户端和服务端一致。 + +```java +# 命令执行 docker-compose -f docker-compose.yml up -d +version: '3.9' +services: + frps: + image: fatedier/frps:v0.60.0 + hostname: frps + container_name: frps + volumes: + - "./config/frps.toml:/frps.toml" + command: + - "-c" + - "/frps.toml" + network_mode: "host" +``` + +- docker compose 按照脚本,走的是 `network_mode: "host"` 不需要额外指定端口。 +- 你需要在云服务器开放 7000、7500 以及需要映射出去的端口。比如客户端配置了 8080、9001 也需要在云服务器开放端口,这样才能访问进来。 +- 官网配置:[https://github.com/fatedier/frp/blob/dev/conf/frps_full_example.toml](https://github.com/fatedier/frp/blob/dev/conf/frps_full_example.toml) - 这里有很全的配置可以参考。 + +### 1.2 frpc - 客户端 + +```java +# 服务端地址 https://github.com/fatedier/frp/blob/dev/conf/frpc_full_example.toml +serverAddr = "117.72.37.243" +# 服务端配置的bindPort +serverPort = 7000 +# token = + +[[proxies]] +# 代理应用名称,根据自己需要进行配置 +name = "xfg-dev-tech-01" +# 代理类型 有tcp\udp\stcp\p2p +type = "tcp" +# 客户端代理应用IP +localIP = "127.0.0.1" +# 客户端代理应用端口 +localPort = 8080 +# 服务端反向代理端口;提供给外部访问 +remotePort = 8080 + +[[proxies]] +# 代理应用名称,根据自己需要进行配置 +name = "xfg-dev-tech-02" +# 代理类型 有tcp\udp\stcp\p2p +type = "tcp" +# 客户端代理应用IP +localIP = "127.0.0.1" +# 客户端代理应用端口 +localPort = 9001 +# 服务端反向代理端口;提供给外部访问 +remotePort = 9001 +``` + +- `localPort = 8080` 是本地应用的端口。 +- `remotePort = 8080` 是远程服务器要暴漏出去的端口,这个端口你可以按需调整。 + +```java +# 命令执行 docker-compose -f docker-compose.yml up -d +version: '3.9' +services: + frpc: + image: fatedier/frpc:v0.60.0 + hostname: frpc + container_name: frpc + volumes: + - "./config/frpc.toml:/frpc.toml" + command: + - "-c" + - "/frpc.toml" + network_mode: "host" +``` + +- docker compose 安装,同样需要指定 `network_mode: "host"` + +## 2. 执行安装 + +搭建FRP内网穿透需要一台云服务器,其实主要用的就是它的公网IP。不过现在的云服务器都非常便宜,36元就可以购买1年,还能抽取京豆。折算下来也就26元1年了! + +
+ +
+ +- 专属价:[http://618.gaga.plus/](http://618.gaga.plus/) +- 云服务器使用:[https://bugstack.cn/md/road-map/docker.html](https://bugstack.cn/md/road-map/docker.html) - 已录制了相关 Docker、Portainer 环境安装,你可以直接对照操作。 + +### 2.1 frps - 云服务器安装 + +#### 2.1.1 上传文件 + +
+ +
+ + +#### 2.1.2 执行脚本 + +```java +[root@lavm-aqhgp9nber frps]# docker-compose -f docker-compose.yml up -d +[+] Running 1/1 + ✔ Container frps Started +``` + +
+ +
+ +你可以进入📃查看启动日志; + + +```java +WARNING: ini format is deprecated and the support will be removed in the future, please use yaml/json/toml format instead! +2024-09-08 09:51:50.581 [I] [frps/root.go:105] frps uses config file: /frps.toml +2024-09-08 09:51:50.674 [I] [server/service.go:237] frps tcp listen on 0.0.0.0:7000 +2024-09-08 09:51:50.674 [I] [frps/root.go:114] frps started successfully +2024-09-08 09:51:50.674 [I] [server/service.go:351] dashboard listen on 0.0.0.0:7500 +2024-09-08 09:51:52.429 [I] [server/service.go:576] [cd9f610f66475f3a] client login info: ip [223.72.84.77:10816] version [0.60.0] hostname [] os [linux] arch [amd64] +2024-09-08 09:51:52.447 [I] [proxy/tcp.go:82] [cd9f610f66475f3a] [xfg-dev-tech-02] tcp proxy listen port [9001] +2024-09-08 09:51:52.448 [I] [server/control.go:399] [cd9f610f66475f3a] new proxy [xfg-dev-tech-02] type [tcp] success +2024-09-08 09:51:52.448 [I] [proxy/tcp.go:82] [cd9f610f66475f3a] [xfg-dev-tech-01] tcp proxy listen port [8080] +2024-09-08 09:51:52.448 [I] [server/control.go:399] [cd9f610f66475f3a] new proxy [xfg-dev-tech-01] type [tcp] success +``` + +#### 2.1.3 开放端口 + +
+ +
+ +- 进入云服务器防火墙,开放访问端口。 + +### 2.2 frpc - 本地安装客户端 + +#### 2.2.1 执行脚本 + +
+ +
+ +- 注意 frpc.toml 是配置服务器的ip和本机应用的ip信息。你需要修改 serverAddr 的 IP 地址,为你的服务器公网 IP 地址。 +- 如果你的 IntelliJ IDEA 带有绿色箭头,且本机也安装了 Docker 那么可以直接安装 frpc 客户端。 + +#### 2.2.2 客户端日志 + +
+ +
+ +```java +2024-09-08 10:00:16.472 [I] [sub/root.go:142] start frpc service for config file [/frpc.toml] +2024-09-08 10:00:16.473 [I] [client/service.go:295] try to connect to server... +2024-09-08 10:00:16.533 [I] [client/service.go:287] [adab2679b41d410f] login to server success, get run id [adab2679b41d410f] +2024-09-08 10:00:16.534 [I] [proxy/proxy_manager.go:173] [adab2679b41d410f] proxy added: [xfg-dev-tech-01 xfg-dev-tech-02] +2024-09-08 10:00:16.550 [I] [client/control.go:168] [adab2679b41d410f] [xfg-dev-tech-01] start proxy success +2024-09-08 10:00:16.550 [I] [client/control.go:168] [adab2679b41d410f] [xfg-dev-tech-02] start proxy success +``` + +#### 2.2.3 服务端日志 + +
+ +
+ +
+ +
+ +- 客户端启动后,你可以进入到服务端 frps 查看日志,这个时候会注册进来客户端信息。 + +**你还可以进入 frp 管理后台查看** + +地址:[http://117.72.37.243:7500/static/#/](http://117.72.37.243:7500/static/#/) - 修改为你的服务器ip进行访问。 + +
+ +
+ +- 这里也可以看到你注册上来的各项信息。 + +## 3. 测试验证 + +### 3.1 部署应用 + +在工程中提供了 xfg-dev-tech-app 的应用,你可以本地执行 docker 脚本进行镜像构建和部署。 + +
+ +
+ +
+ +
+ +- 如图,执行1、2、3步骤,打包、构建和部署应用。 + +### 3.2 访问验证 + +#### 3.2.1 本地访问 + +地址:[http://127.0.0.1:8080/api/test](http://127.0.0.1:8080/api/test) + +
+ +
+ +#### 3.2.2 穿透访问 + +地址:[http://117.72.37.243:8080/api/test](http://117.72.37.243:8080/api/test) + +## 4. 同类产品 + +- [EasyTier 一个简单、安全、去中心化的内网穿透 VPN 组网方案](https://www.easytier.top/) + +
+ +
+ diff --git a/docs/md/road-map/git.md b/docs/md/road-map/git.md index 7358ff8c5..a033ebd6c 100644 --- a/docs/md/road-map/git.md +++ b/docs/md/road-map/git.md @@ -12,7 +12,7 @@ lock: need -大家伙,我是技术UP主小傅哥。 +大家好,我是技术UP主小傅哥。 **不会Git操作的伙伴,轻则写不了代码,重则误操作搞丢自己的代码或者干掉别人的代码。** 因为进入公司后,就不只是你一个人在一个工程上写代码,而是所有这个项目组的伙伴都需要在这个工程上写代码,大家要在统一的Git的规范完成代码开发和提交。—— 🤨 不信的话,进入公司乱删个Git分支或者随便任何一个分支提交代码试试。 @@ -47,7 +47,14 @@ Git 是一个软件工具,在使用前需要进行安装。 - 地址:[https://git-scm.com/downloads](https://git-scm.com/downloads) - `选择需要的版本下载` 网盘资源:[https://www.alipan.com/s/LqwsNfHRx54](https://www.alipan.com/s/LqwsNfHRx54) - `也提供了 Git 软件,在 dev-ops -> 环境 -> git 下` - 演示:[https://learngitbranching.js.org/](https://learngitbranching.js.org/) - `可直接查看动画效果,引导式学习Git命令操作。` +**配置代理** +```java +git config --global http.proxy ip:port +git config --global https.proxy ip:port +``` + +- 如果你有代理地址可以配置 ### 2.1 Mac @@ -67,6 +74,17 @@ brew install git 获取适用于您的 Debian/Ubuntu 版本的最新稳定版本 +**如果没有安装npm可以安装** + +``` +# sudo apt update +# sudo apt install nodejs npm +# node -v +# npm -v +``` + +**安装git** + ``` # apt-get install git ``` @@ -97,6 +115,14 @@ sudo yum install git >你要做都是配置账户 ssh 秘钥,或者下载的时候输入 git 仓库账号密码(目前很多仓库为了安全,不在支持账号密码方式下载代码了。) +**注意**:gitcode.com、github.com 都需要创建访问令牌当做账号密码的密码使用。而不是直接使用账号里你设置的那个密码。 + +如 [https://gitcode.com/setting/token-classic](https://gitcode.com/setting/token-classic) + +
+ +
+ ### 1. 配置git账户 ```java @@ -143,7 +169,7 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7eYQiDe46Jq5CJ6vXtIiM0hxUKKgCoSFIkSQucsZo ``` - 命令:`ssh-keygen -t rsa -C "184172133@qq.com"` -- 操作:`Your public key has been saved in /root/.ssh/id_rsa.pub.` 按照提示地址,获取 pub 公钥。如果是linux就通过 cat 获取。如果是本机电脑就按照路径打开。 +- 操作:`Your public key has been saved in /root/.ssh/id_rsa.pub.` 按照提示地址,获取 pub 公钥。如果是linux就通过 cat 获取。如果是本机电脑就按照路径打开。如,我的地址(你要更换为你的):`cat /Users/fuzhengwei/.ssh/id_rsa.pub` - 注意:`.ssh` 点开头的文件夹是隐藏文件,Windows/Mac 都可以设置查看隐藏文件。Windows 是设置里配置,Mac 是通过 `Shift + Command + .` 开启和关闭查看隐藏文件。 ### 4. 配置ssh秘钥 @@ -204,7 +230,7 @@ git clone -b 240720-xfg-init-project git@github.com:fuzhengwei/openai-code-revie - git branch -r:查看远程分支列表 - git pull:拉取分支最新代码 - git push:推送本地变更的代码。【这样的操作有图形化界面,更方便】 -- git fetch:后去远程仓库最新分支变动,这个很有用。在你想操作分支创建新或者看其他人的分支时候,先操作下 git fetch 看下最新的分支变动。 +- git fetch:获取远程仓库最新分支变动,这个很有用。在你想操作分支创建新或者看其他人的分支时候,先操作下 git fetch 看下最新的分支变动。 - git merge origin/master:将远程分支的 master 代码合并到本地分支 master 上。【类似这样的操作有图形化界面,点击即可】 ## 5. 检出代码 - IntelliJ IDEA @@ -266,6 +292,46 @@ IntelliJ IDEA 本身就提供了 Git 的图形化操作,也是最简单最常 #### 5.3.5 合并分支 +在公司中很多时候是大家一起在一个工程开发代码,那么这个时候就会涉及合并代码的。如果有多人共同开发一个接口方法,就会在合并的时候产生冲突。所以要特别注意。 + +注意,📢在Git中,`merge`和`rebase`是两种用于合并分支变更的方法。每种方法都有其特定的用途和行为: + +Merge + +- **概念**: `merge`命令用于将一个分支的更改合并到当前分支,通常会生成一次新的合并提交(commit),从而保留分支历史。 +- **历史记录**: 使用`merge`会保留所有开发历史记录,包括分支点,这使得历史记录图呈现出一个分叉和合并的树状结构。 +- **使用场景**: + - 当你想保留完整的历史记录,了解如何以及何时进行了分支。 + - 通常用于将分支合并到主分支(如`main`或`master`)时,以保留分支的历史上下文。 +- **命令**: + ```bash + git checkout main + git merge feature-branch + ``` + +Rebase + +- **概念**: `rebase`命令用于重新定位一系列的提交,可以将分支上的更改申请到另一分支的顶端,因而能得到更线性的历史。 +- **历史记录**: Rebase重新写了提交历史(改变了提交的父提交),这会导致更线性的提交历史,从而更清晰,但会丢失分支合并信息。 +- **使用场景**: + - 当你希望提交历史更加简洁和线性。 + - 合并特性分支到主分支前用以避免杂乱的分支合并历史。 + - 需要小心在共享分支上使用,因为重写的提交历史会影响他人。 +- **命令**: + ```bash + git checkout feature-branch + git rebase main + ``` + +选择何时使用 + +- **Merge**适合用于保持完整的提交历史,不改变现有提交的哈希。 +- **Rebase**适合用于清理提交历史,通常在提交尚未推送至共享存储库时使用。 + +一般情况下,对于已对外分享的分支,尤其是共享存储库中的`main`或`master`分支,尽量避免使用`rebase`。而对于个人开发的特性分支,`rebase`可以帮助维护一个清晰的提交历史。 + +**普通合并** +
@@ -274,12 +340,39 @@ IntelliJ IDEA 本身就提供了 Git 的图形化操作,也是最简单最常 - 之后切换到master分支,通过把自己的开发的分支合并回master分支进行提交。 - 注意:如果多人开发,同时修改一个类,可能会引起合并冲突,这个审核要点开类,查看冲突进行合并,不要把自己和他人的代码合并丢失。 +**冲突合并** + +
+ +
+ +1. 选择,你要从哪个分支合并到 test 分支。右键选择 Merge into test +2. 如果你合并到test分支的代码,有其他人也在同一行做了改变或者格式化了代码,就会弹出一个合并冲突。这个时候你需要点 Merge 进行合并。 +3. 在点击 Merge 后,你会看到具体冲突的代码是什么,你可以有选择的从左右合并到中,最后点击 Apply。这个时候要注意不要把让别人的代码合并丢喽。 +4. 合并完的代码,不要直接 push,你要先本地 install 看是否可以打包。以及如果可以运行的话,可以本地先跑一下。 最后 push 提交合并代码即可。 + #### 5.3.6 回滚分支 +回滚提交和回滚push +
+如果出现了合并代码冲突后,丢失了代码,那么这个时候一般要进行回滚操作,重新合并。 + +虽然 Git 提供了回滚代码的功能,但一定要谨慎使用。怎么谨慎?第一个谨慎就是 push 的代码一定确保可以构建和运行,否则不要 push!第二个谨慎是要回滚代码,需要和团队中对应的伙伴打招呼,避免影响别人测试或者上线。 + +
+ +
+ +1. 先选择要在哪个分支的哪次提交上进行回滚。这里选择的是 test 分支上的提交进行回滚。 +2. 这里选择 Hard 回滚。因为我们所有的都是合并到 test 分支,所以 test 分支丢失也没问题。可以重新合并。但要和同组伙伴提前说明。 +3. 回滚后,你会看到代码只剩下从回滚往下的提交内容了。 +4. 回滚后,你不能直接 push 提交了,这个之后会报错;`fast-forward` 因为此时本地分支落后于远程分支。 +5. 所以要通过 `git push origin HEAD --force` 进行强制提交。或者你可以把 test 的远程分支删掉,之后在提交。 + ## 6. 提交工程 - IntelliJ IDEA 那么首次创建的工程怎么提交到代码库呢?🤔 @@ -336,11 +429,29 @@ Git 附带了用于提交 ( [git-gui](https://git-scm.com/docs/git-gui) ) 和浏 - Git 提供了操作的客户端界面,你可以按需下载使用。 - 地址:[https://git-scm.com/docs/git-gui](https://git-scm.com/docs/git-gui) -## 8. 提交规范 +## 8. 分支命名 + +不同公司中对Git的使用分支命名规范也略有差异,不过整体都会分为;`上线`、`预发`、`开发`、`测试`,这样几个分支。如图是一种比较简单使用的拉取分支方式。 + +
+ +
+ +- master/main 作为主分支,不可直接修改代码代码,只能从分支合并到主分支进行进行提交。同时,master 分支的合并需要进行审批,审批后才能合并。 +- 开发前,先从 master 分支,拉一个开发分支。`2024/10/11/xfg-xxx` 使用带有斜线的分支命名会自动创建文件夹,对于多人开发的项目,可以直接归档。 +- 后开发,也就是研发已经完成了本地的验证。进行测试时,可以把研发的开发分支合并到 test 分支,提交、部署、测试。遇到测试bug,需要回到可发分支修改代码,之后合并到 test 分支部署验证。 +- pre/release 预发分支,用于测试完成后,把研发的开发分支合并到预发分支进行预发上线,上线后测试人员进行验证。最终完成验证后,把开发分支合并到 master 分支,并需要由架构师对合并代码审批通过。最后进行上线开量验证。 +- 如果是修复bug的,可以添加一个 `fix-用户名缩写-具体功能` -**分支命名**:日期_姓名首字母缩写_功能单词,如:`210804_xfg_buildFramework` +## 9. 提交规范 -**提交规范**:`作者,type: desc` 如:`小傅哥,fix:修复查询用户信息逻辑问题` *参考Commit message 规范* +保持一个标准的统一的规范提交代码,在后续的评审、检查、合并,都会非常容易处理。 + +
+ +
+ +**提交规范**:`type:【需求名】desc #id` 如:`feat:【抽奖算法】O1、Ologn 时间复杂度算法实现 #需求id(github pr/行云等会有自动关联)` *参考Commit message 规范* ```java # 主要type @@ -361,7 +472,9 @@ ci: 与CI(持续集成服务)有关的改动 chore: 不修改src或者test的其余修改,例如构建过程或辅助工具的变动 ``` -## 9. 操作手册 +> 前提通知,谨慎回滚。如果是回滚 Master 更要特别小心,别把工作回滚丢了。 + +## 10. 操作手册 - 文档:[https://git-scm.com/book/zh/v2](https://git-scm.com/book/zh/v2) - `可以直接对照着操作,练习命令` - PDF:[https://github.com/progit/progit2-zh/releases/download/2.1.62/progit.pdf](https://github.com/progit/progit2-zh/releases/download/2.1.62/progit.pdf) @@ -372,4 +485,4 @@ chore: 不修改src或者test的其余修改,例如构建过程或辅助工
-- 中文PDF,直接深度学习Git操作!下载:**微信公众号「bugstack虫洞栈」回复「gitbook」** \ No newline at end of file +- 中文PDF,直接深度学习Git操作!下载:**微信公众号「bugstack虫洞栈」回复「gitbook」** diff --git a/docs/md/road-map/github-actions-workflows.md b/docs/md/road-map/github-actions-workflows.md index 26b00bca0..6d75985b6 100644 --- a/docs/md/road-map/github-actions-workflows.md +++ b/docs/md/road-map/github-actions-workflows.md @@ -1,9 +1,9 @@ --- -title: Github Actions WorkFlows +title: Docker 镜像构建 - Github Action lock: need --- -# Github 给了我们一台免费的"云服务器",Docker 问题也解决了! +# Docker 镜像构建 - Github Action 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) diff --git a/docs/md/road-map/github-models.md b/docs/md/road-map/github-models.md new file mode 100644 index 000000000..08fbfcac4 --- /dev/null +++ b/docs/md/road-map/github-models.md @@ -0,0 +1,212 @@ +--- +title: Github Models +lock: need +--- + +# Github Models(AI接口),申请使用教程 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +现在做 AI 应用开发的小伙伴越来越多了,随之而来的是对 LLM 大模型接口的使用依赖。一般的模型,可能会让程序出现幻觉。而高质量的模型,大部分是需要付费,比如 `openai/gpt-5`、`azureml-xai/grok3`、`azureml/Phi-4` 等。**那怎么办!?🤔** + +
+ +
+ +这些免费的不错的大模型(LLM),也都是有对应的频次和最大出入/输出token的限制。虽然不会让咱们玩命的调用测试。但在程序开发初期,对于单个功能的验证还是非常方便的。接下来,小傅哥就给大家演示下,关于 Github 免费提供的大模型如何配置使用。 + +## 一、模型说明 + +### 1. 官网地址 + +官网:[https://github.com/marketplace?type=models](https://github.com/marketplace?type=models) + +
+ +
+ +在 Github marketplace 下提供了非常多的免费的 LLM 使用,gpt-5、gpt-4.1 都是有的,具备完整的测试功能。有时候还会新增加其他模型。 + +### 2. 频次限制 + +地址:[https://docs.github.com/en/github-models/use-github-models/prototyping-with-ai-models#rate-limits](https://docs.github.com/en/github-models/use-github-models/prototyping-with-ai-models#rate-limits) + +
+ +
+ +- 每日150次、每分钟15次,每次token,8000进、4000出。对于单个模型的验证是没问题的,不过对于复杂的 ai agent 智能体是跑不动的。所以,这块测试的话,要分开验证。之后对于全流程的,在购买 api 进行测试即可。 +- 如果小伙伴还觉得,每分钟15次,有点不够干的,那你可以弄10个账号,通过 nginx 负载下,这样基本每分钟150次,一天1500次还是很够用的。 + +## 二、模型使用 + +### 1. 测试工程 + +
+ +
+ +- 地址:[https://github.com/fuzhengwei/xfg-dev-tech-github-models](https://github.com/fuzhengwei/xfg-dev-tech-github-models) +- 说明:这里小傅哥准备了一套基于 Spring AI 的测试工程,来验证 Github LLM 的使用。你可以下载后,替换 token/apikey 即可调用验证。 +- 环境:jdk 17、maven 3.8.x、spring ai 1.1.0 + +### 2. 对接申请 + +#### 2.1 申请token + +地址:https://github.com/settings/tokens/new + +
+ +
+ +- 在 Tokens 下,添加 Note 描述和过期时间,完事后不用加任何其他权限,拉到最后设置点击 `Generate token` 生成令牌即可。 +- 生成后复制你的 Token,复制后关闭就看不见了。只有删除和创建新的。 + +#### 2.2 查看curl(api) + +地址:[https://github.com/marketplace/models/azure-openai/gpt-4-1/playground](https://github.com/marketplace/models/azure-openai/gpt-4-1/playground) + +
+ +
+ +在左侧你可以选择需要使用的模型,之后进行对话验证。之后,在右侧有一个 `Use this model` 这里可以获得模型 API 请求信息。 + +
+ +
+ +你现在单独验证 api,在整个程序测试前,要确保你的 api 是可用的。 + +### 3. 测试验证 + +```java +public class ApiTest { + + public static void main(String[] args) throws Exception { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Resource resource = new ClassPathResource("dog.png", classLoader); + + OpenAiApi openAiApi = OpenAiApi.builder() + .baseUrl("https://models.github.ai/inference") + // apikey 要替换为你的,在 https://github.com/settings/tokens 创建即可。 + .apiKey("ghp_FfiwBkVunYDQyhIwaQSccVw******") + .completionsPath("/chat/completions") + .embeddingsPath("/embeddings") + .build(); + + ChatModel chatModel = OpenAiChatModel.builder() + .openAiApi(openAiApi) + .defaultOptions(OpenAiChatOptions.builder() + .model("openai/gpt-4.1") + .build()) + .build(); + + // 模型测试,没问题可以识别图片 + ChatResponse response = chatModel.call(new Prompt( + UserMessage.builder() + .text("请描述这张图片的主要内容,并说明图中物品的可能用途。") + .media(Media.builder() + .mimeType(MimeType.valueOf(MimeTypeUtils.IMAGE_PNG_VALUE)) + .data(resource) + .build()) + .build())); + + System.out.println("测试结果" + JSON.toJSONString(response)); + + } + +} +``` + +```java +测试结果{"metadata":{"empty":false,"id":"chatcmpl-CzHhVYaXPv3HjJ3oKE4YKPamPQRQB","model":"gpt-4.1-2025-04-14","rateLimit":{"requestsLimit":1000,"requestsRemaining":996,"tokensLimit":1000000,"tokensRemaining":980423},"usage":{"completionTokens":0,"nativeUsage":{},"promptTokens":0,"totalTokens":0}},"result":{"metadata":{"contentFilters":[],"empty":true,"finishReason":"STOP"},"output":{"media":[],"messageType":"ASSISTANT","metadata":{"role":"ASSISTANT","messageType":"ASSISTANT","finishReason":"STOP","refusal":"","index":0,"annotations":[{"$ref":"$.metadata.rateLimit.usage.nativeUsage"}],"id":"chatcmpl-CzHhVYaXPv3HjJ3oKE4YKPamPQRQB"},"text":"这张图片的主要内容是一只卡通风格的小狗。小狗是棕色的,脸部较大,眼睛圆而突出,表情看起来有些疑惑或惊讶,嘴巴微微张开,尾巴翘起。整个形象简洁可爱,线条和颜色运用都比较简单。\n\n**物品的可能用途:**\n1. **图标或表情包**:这种卡通形象常用于聊天软件中的表情包或头像,传达惊讶、困惑等情感。\n2. **儿童绘本或动画角色**:可以作为儿童图书或动画中的形象角色,吸引小朋友的注意力。\n3. **宠物相关宣传设计**:可用于宠物店、宠物产品的宣传海报、包装或logo,增加亲和力。\n4. **教育材料**:在教学课件或教育类APP中,用于引导、示范或者增加趣味性。\n\n整体而言,这是一种很常见且可爱的卡通动物形象,主要用于与宠物、儿童或者情感表达相关的领域。","toolCalls":[]}},"results":[{"$ref":"$.metadata.rateLimit.usage.nativeUsage.result"}]} +``` + +- 这是一段基于 Spring AI 配置 github llm api的使用方式,尤其注意,baseUrl、apiKey、completionsPath、embeddingsPath、openai/gpt-4.1,这些配置信息和你直接使用管的 gpt 配置是有差异的。 +- 本案例,是识别图片的用途,你也可以验证其他功能。这样的项目在小傅哥的 [《AI Agent 智能体》](https://bugstack.cn/md/project/ai-knowledge/ai-knowledge.html) 都有讲解。 + +## 三、使用拓展 + +### 1. 部署脚本 + +
+ +
+ +- 这是一套 nginx 转发脚本。你需要有自己的域名(各个云服务器厂商都可以购买)以及申请 ssl 后才可以配置使用。 +- ssl 可以从 [httpok](https://bugstack.cn/md/road-map/ssl-httpsok.html) 申请使用。地址:[https://bugstack.cn/md/road-map/ssl-httpsok.html](https://bugstack.cn/md/road-map/ssl-httpsok.html) + +### 2. 转发说明(nginx) + +如果你希望在使用的过程中,让模型是以你之前使用 openai 一样的方式,那么可以配置一套 Nginx 转发; + +```java +server { + listen 80; + listen [::]:80; + server_name 需要配置域名(api.xxx.cn); + + rewrite ^(.*) https://$server_name$1 permanent; + +} + +server { + listen 443 ssl; + server_name 需要配置域名(api.xxx.cn); + + ssl_certificate /etc/nginx/ssl/_.itedus.cn.pem; + ssl_certificate_key /etc/nginx/ssl/_.itedus.cn.key; + + ssl_session_cache shared:SSL:1m; + ssl_session_timeout 5m; + + ssl_ciphers HIGH:!aNULL:!MD5; + ssl_prefer_server_ciphers on; + + location / { + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + root /usr/share/nginx/html; + index index.html index.htm; + } + + location /v1/ { + # 去掉路径中的/v1前缀 + rewrite ^/v1/(.*) /$1 break; + proxy_pass https://models.inference.ai.azure.com; + proxy_http_version 1.1; + chunked_transfer_encoding off; + proxy_buffering off; + proxy_cache off; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} +``` + +- nginx 的方式是,当访问有 v1/ 路径的时候,在进行路径重写 `rewrite ^/v1/(.*) /$1 break;` 之后转发到 `https://models.inference.ai.azure.com` - `这个也是 gpt 里的一种模型对接地址` +- 转发后,你就可以直接使用模型服务了。 + +### 3. curl 验证 + +
+ +
+ +- 配置转发后,就可以使用 curl_nginx.sh 脚本进行验证了。 + +好啦,本文到这,你就可以初步使用免费的 LLM 进行一些一些初始功能验证。2025年,ai agent 开始崛起,2026年,必然是 ai agent 爆发的时候。一定要多学习这类实战项目,企业里 spring 是大盘,所以结合 spring ai 做的项目也必然会非常多。 + diff --git a/docs/md/road-map/google-adk.md b/docs/md/road-map/google-adk.md new file mode 100644 index 000000000..805cf6e95 --- /dev/null +++ b/docs/md/road-map/google-adk.md @@ -0,0 +1,344 @@ +--- +title: google adk +lock: need +--- + +# Google Agent ADK,20分钟,帮你搭建一个简单智能体 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +💐 从22年至今,小傅哥已经带着大家做了5个AI类项目,包括;`(22年)问答助手`、`(23年)OpenAI应用(含支付、敏感词过滤)`、`(24年)AI 代码自动评审`、`(25年)Ai Agent 智能体`、`(25年)Ai MCP Gateway 网关`。 + +这些项目也都是结合这,AI 这一年最新的技术动向和应用方向,而做的设计和落地。所以,每次小傅哥都给大家讲了,接下来 AI 将影响的一些场景,也都陆续的发生了。就像,24年11月发布 MCP 协议后,我给大家说,所有互联网企业都将大量的落地 MCP 服务,并开始 Ai Agent 智能体实现(别看市面有 dify、扣子,各个且用还是要做自己的业务智能体)。 + +随后,25年年初,小傅哥就带着大家开始了 RAG、MCP、Ai Agent 智能体的开发,并告诉大家,以后 Ai Agent 智能体也会出标准的框架,让开发更加容易。这不,**谷歌的 ADK 就来了**。并且这哥们👬🏻还定义A2A协议。这会让不是那么大型的互联网公司,也会具备 Ai Agent 智能体开发的能力。 + +接下来的几年,所有的业务项目,都会以 Ai Agent 智能体翻一遍,程序员新增的岗位和工作量仍然会很多。因为在咱们这,你做的越快,你就得做的越多! + +>接下来,小傅哥就带着大家做一下 Google ADK 搭建 AI Agent。如果你感兴趣 AI 类项目,还可以在文末获取全部实战项目源码,深度积累此类技术内容。**文末有Google ADK 运行效果,交互式对话智能体,对 ELK 进行巡检分析。** + +## 一、官网资料 + +- 官网:[https://google.github.io/adk-docs/](https://google.github.io/adk-docs/) +- 搭建:[https://google.github.io/adk-docs/get-started/](https://google.github.io/adk-docs/get-started/) + +
+ +
+ +- ADK 以轻便化构建 Ai Agent 智能体,解决智能体开发的复杂流程而设计。目前支持 Python、Java、Go 3种语言对应的技术框架。 +- 整个文档完整的描述了,智能体的创建和运行、工具的调用(tools、function、mcp)、可观测性以及 A2A 协议等。 +- Agent Development Kit (ADK) is designed to empower developers to quickly build, manage, evaluate and deploy AI-powered agents. These quick start guides get you set up and running a simple agent in less than **20 minutes**. + +## 二、工程实践 + +### 1. 前置说明 + +本次的 Ai Agent 实践,是以 Google ADK 框架为基础,配和 Github [system-prompts-and-models-of-ai-tools](https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools) 开源提示词项目中的 claude-code-system-prompt 作为必要描述。来实验,ELK 系统日志智能分析场景。 + +- API Key:[https://ai.google.dev/gemini-api](https://ai.google.dev/gemini-api) 需要申请开发 API 秘钥,是免费的。 +- Docker 环境,本项目部署了一套 ELK 日志服务,基于 Docker 部署,之后对 ELK 模拟写入日志,让 Ai Agent 智能体进行分析。`如果暂时配置不了,可以在测试的时候去掉这部分 mcp 服务` +- `JDK 17+`、`Maven 3.8.x` + +### 2. 工程说明 + +
+ +
+ +- 工程地址:[https://github.com/fuzhengwei/xfg-dev-tech-google-adk](https://github.com/fuzhengwei/xfg-dev-tech-google-adk) +- 这是一套引入了 Google ADK 0.1.0 版本的 Agent 最基础智能体测试。如果需要扩展,还要额外增加很多东西,可以参考 [《Ai Agent 智能体项目》](https://bugstack.cn/md/project/ai-knowledge/ai-knowledge.html) + +#### 2.1 YML 配置 + +```java +server: + port: 8901 + +# 可申请API秘钥;https://ai.google.dev/gemini-api +google: + api: + base-url: https://generativelanguage.googleapis.com + key: AIzaSyDF6JnvFx7xWEsARS*******可以自己申请免费的 + cloud: + project: xfg-google-adk + +logging: + level: + root: info + config: classpath:logback-spring.xml +``` + +- 在 `application-dev.yml` 修改你的参数配置,配置你的 Google api key + +#### 2.2 ADK 单测 + +```java +import com.google.adk.agents.LlmAgent; +import com.google.adk.events.Event; +import com.google.adk.models.Gemini; +import com.google.adk.runner.InMemoryRunner; +import com.google.adk.sessions.Session; +import com.google.genai.Client; +import com.google.genai.types.Content; +import com.google.genai.types.HttpOptions; +import com.google.genai.types.Part; +import io.reactivex.rxjava3.core.Flowable; + +public class ApiTest { + + /** + * 可申请免费测试api + * https://ai.google.dev/gemini-api/docs/quickstart?hl=zh-cn#apps-script + */ + public static void main(String[] args) { + LlmAgent agent = LlmAgent.builder() + .name("test") + .description("test agent help user do work") + .model(Gemini.builder() + .apiClient(Client.builder() + .apiKey("AIzaSyDF6JnvFx7xWEsARSGosNmvTU3ZoCwo-mc") + .httpOptions(HttpOptions + .builder() + .baseUrl("https://generativelanguage.googleapis.com") + .timeout(500000) + .build()) + .build()) + .modelName("gemini-2.0-flash") + .build()) + .build(); + + InMemoryRunner runner = new InMemoryRunner(agent); + + Session session = runner + .sessionService() + .createSession("test", "xiaofuge") + .blockingGet(); + + Flowable events = runner.runAsync("xiaofuge", session.id(), Content.fromParts(Part.fromText("hi agent can you help me"))); + + System.out.print("\nAgent > "); + events.blockingForEach(event -> System.out.println(event.stringifyContent())); + + } + +} +``` + +```java +Agent > Hi there! Yes, I'm here to help. To best assist you, could you tell me what you need help with? The more information you give me, the better I can understand your request and provide a useful response. +``` + +- 这是一套最基础的 Ai Agent 智能体 ADK 的测试使用代码。其实它的配置和调用与 Spring AI 框架是有类似之处的,基本上这类框架也都是这样的使用模式。 +- LlmAgent 提供了一整套构建智能体的方式,可以设置客户端(Gemini),并设置相关的 baseUrl、apiKey 参数,以及模型和超时时间等。 +- InMemoryRunner 的用途是把 Agent 放入一个记忆执行里,让一整个 Session 会话下的执行都被记录下,这样才能记录上下文。 +- 之后就是放到响应框架进行之后和拿到最后结果啦。 + +#### 2.3 Agent 智能体测试 + +```java +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest +public class AutoAgentTest { + + @Value("${google.api.base-url}") + private String baseUrl; + + @Value("${google.api.key}") + private String apiKey; + + private static final String USER_ID = "xiaofuge"; + private static final String NAME = "multi_tool_agent"; + + public static BaseAgent agent; + + @Before + public void init() { + List mcpTools = new ArrayList<>(); + mcpTools.addAll(mcp_elk()); + mcpTools.addAll(mcp_filesystem()); + + agent = LlmAgent.builder() + .name(NAME) + .model(Gemini.builder() + .apiClient(Client.builder() + .apiKey(apiKey) + .httpOptions(HttpOptions + .builder() + .baseUrl(baseUrl) + .timeout(500000) + .build()) + .build()) + .modelName("gemini-2.0-flash") + .build()) + .description("You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.") + .instruction( + """ + You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user. + + 可以在这里复制全部提示词;https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools/blob/main/Claude%20Code/claude-code-system-prompt.txt + """) + .tools(mcpTools) + .build(); + } + + /** + * - 需要配置后,才能在单测控制台输入内容 + * IntelliJ IDEA Help -> Edit Custom VM Options -> -Deditable.java.test.console=true + *
+ * - ai.google.dev/api + */ + @Test + public void test_agent() { + InMemoryRunner runner = new InMemoryRunner(agent); + + Session session = + runner + .sessionService() + .createSession(NAME, USER_ID) + .blockingGet(); + + try (Scanner scanner = new Scanner(System.in, StandardCharsets.UTF_8)) { + while (true) { + System.out.print("\nYou > "); + String userInput = scanner.nextLine(); + + if ("quit".equalsIgnoreCase(userInput)) { + break; + } + + Content userMsg = Content.fromParts(Part.fromText(userInput)); + Flowable events = runner.runAsync(USER_ID, session.id(), userMsg); + + System.out.print("\nAgent > "); + events.blockingForEach(event -> System.out.println(event.stringifyContent())); + } + } + + } + + private List mcp_elk() { + Map env = new HashMap<>(); + env.put("ES_HOST", "http://127.0.0.1:9200"); + env.put("ES_API_KEY", "none"); + + ServerParameters mcp_elk = ServerParameters.builder("npx") + .args(List.of( + "-y", + "@awesome-ai/elasticsearch-mcp" + )) + .env(env) + .build(); + + CompletableFuture futureResult = + McpToolset.fromServer(mcp_elk, JsonBaseModel.getMapper()); + + McpToolset.McpToolsAndToolsetResult result = futureResult.join(); + + return result.getTools(); + } + + private List mcp_filesystem() { + ServerParameters mcp_filesystem = ServerParameters.builder("npx") + .args(List.of( + "-y", + "@modelcontextprotocol/server-filesystem", + "/Users/fuzhengwei/Desktop" + )) + .build(); + + CompletableFuture futureResult = + McpToolset.fromServer(mcp_filesystem, JsonBaseModel.getMapper()); + + McpToolset.McpToolsAndToolsetResult result = futureResult.join(); + + return result.getTools(); + } + +} +``` + +- AutoAgentTest 智能体,配置了两个 mcp,mcp_elk、mcp_filesystem 服务。其实 AI Agent 智能体,都少不了 MCP 服务的加持,这样才能让这个大脑有手脚可以行动起来。 +- init 初始化阶段,instruction 配置了对应的智能体提示词,这部分很重要,有点像智能体的神经。[https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools/blob/main/Claude%20Code/claude-code-system-prompt.txt](https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools/blob/main/Claude%20Code/claude-code-system-prompt.txt) - 可以选择这里的提示词配置到智能体进行测试。 +- 这部分也可以运行测试,之后会你可以进行提问。注意,如果你没有配置 elk,那么可以删掉 `mcpTools.addAll(mcp_elk());` 代码。 +- mcp_filesystem() 配置了,`/Users/fuzhengwei/Desktop` 你需要修改为你的本地的有权限访问的地址。 + +#### 2.4 Agent 智能体服务 + +有了前面的案例测试基础,就可以把服务配置成对应的接口,以及开发个简单的页面进行对接验证了。 + +##### 2.4.1 服务接口 + +```java +@Slf4j +@RestController +@RequestMapping("/trigger") +@CrossOrigin(origins = "*") +public class AgentController { + + private final AgentService agentService; + + public AgentController(AgentService agentService) { + this.agentService = agentService; + } + + @PostMapping(path = "/session", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public CreateSessionResponse createSession(@RequestBody CreateSessionRequest req) { + String sessionId = agentService.createOrGetSession(req.getUserId()); + log.info("创建会话ID:{}", sessionId); + return new CreateSessionResponse(sessionId); + } + + @PostMapping(path = "/chat", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ChatResponse chat(@RequestBody ChatRequest req) { + String sessionId = req.getSessionId(); + if (sessionId == null || sessionId.isEmpty()) { + sessionId = agentService.createOrGetSession(req.getUserId()); + } + log.info("使用会话ID:{}", sessionId); + List outputs = agentService.chat(req.getUserId(), sessionId, req.getMessage()); + return new ChatResponse(sessionId, String.join("\n", outputs)); + } +} +``` + +- 这里就是把单测的服务,包装成接口。详细的部分可以直接看工程代码。 + +##### 2.4.2 页面对接 + +
+ +
+ +- 把服务端的接口对接到页面。 + +## 三、功能测试 + +### 1. 部署 elk 日志服务 + +
+ +
+ +- 整个 Ai Agent 案例,配置了 ELK 作为日志分析的基础,所以最好配置下。 +- 这里也有云服务器的部署操作,也可以参考教程来部署。教程:[https://bugstack.cn/md/road-map/docker-install.html](https://bugstack.cn/md/road-map/docker-install.html) +- 注意配置完成后,要执行 `elk-blacklist-data.sh` 模拟的写入进去一些日志,这样才能用于分析使用。 + +### 2. 启动服务访问页面 + +
+ +
+ +
+ +
+ +- 以上演示了,使用 Ai Agent 进行 ELK 日志分析,通过对话可以看到,最终我们可以拿到系统的日志数据。 +- 你还可以尝试配置其他的 MCP 服务,之后验证各种场景功能。担任如果你希望更细化的做 Ai Agent,还是要看下 [《Ai Agent 智能体项目》](https://bugstack.cn/md/project/ai-knowledge/ai-knowledge.html) 这样可以更细腻的做出这样的系统,以及对应的可视化编排操作。 diff --git a/docs/md/road-map/grafana.md b/docs/md/road-map/grafana.md index f8f7e7cb3..fa2b2e393 100644 --- a/docs/md/road-map/grafana.md +++ b/docs/md/road-map/grafana.md @@ -6,11 +6,11 @@ lock: need # Prometheus + Grafana 监控,验证 Hystrix 超时熔断 作者:小傅哥 -博客:[https://bugstack.cn](https://bugstack.cn) +
博客:[https://bugstack.cn](https://bugstack.cn) > 沉淀、分享、成长,让自己和他人都能有所收获!😄 - + 本文的宗旨在于通过简单干净实践的方式教会读者,使用 Prometheus + Grafana 部署监控,同时结合监控了解到为什么需要使用 Hystrix 对接口进行超时熔断处理。 diff --git a/docs/md/road-map/higress-ai.md b/docs/md/road-map/higress-ai.md new file mode 100644 index 000000000..47319e42e --- /dev/null +++ b/docs/md/road-map/higress-ai.md @@ -0,0 +1,322 @@ +--- +title: Higress-Ai +lock: need +--- + +# AI(+MCP)网关,快速集成(LLM API/HTTP/RPC/Nacos) + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +**傻,是不傻?** 有些伙伴问,Dify、Coze,市面都有了,怎么公司里还要基于 Spring AI 框架,开发自己的智能体,主要原因是什么呢?🤔 + +
+ +
+ +**何止 Dify,Java JDK 都有公司自己干一套的!为啥呢?** + +如果你还纠结这个事,说明你还是个小白,小卡拉米。公司干一套新的,对于企业来说,这东西叫技术资产,人才储备,所有开发的出来东西,既可以申请著作权,又可以申请技术专利。转而,就把这些专利作为企业的注册资金当做投资款抵扣了,也可以用于企业所得税的抵扣。 + +从公司大目标再往下看,随着 LLM 大模型的发展,以及各类框架的完善,AI 应用场景的智能体开发,会越来越标准化,且越来也有容易被实现。不再需要像最早的一些 Dify、Coze 方案那样笨重。 + +再者,企业需要沉淀 AI 技术能力(+人才),为公司适应各类 AI 应用场景开发做储备。而直接使用市面的产品,很多时候都没法做到快速迭代新的需求,甚至要在公司发展后期遇到极端问题,甚至还要考虑重新做技术选型以及重建。这个成本就非常大了。 + +所以,你能理解为啥公司都要做自己的服务平台了吧。而且,公司也非常需要一个像你一样,具备 AI 方面开发知识的研发人员。这也是为什么小傅哥,要带着你做这么多 AI 类的项目。今天分享的这套 AI MCP 网关服务,小傅哥也正在带着大家做。 + +>接下来,小傅哥就带着大家实践下阿里旗下 Higress AI 网关能力的使用。 + +## 一、网关介绍 + +官网:[https://higress.io/](https://higress.io/) +源码:[https://github.com/alibaba/higress](https://github.com/alibaba/higress) +文档:[https://higress.cn/ai/quick-start](https://higress.cn/ai/quick-start) + +Higress AI 网关快速集成 LLM API,通过 AI 网关、API 网关及Himarket,解决模型、工具及Agent统一代理问题,并助力企业构建AI中台,加速AI落地。 + +这套网关服务,可以统一管理你的 LLM API 服务接口,如你访问的 OpenAI、智谱、千问、文心,都可以在Higress AI 网关做一个统一管理。另外,就是 MCP 网关能力,可以把注册的 HTTP 服务、Nacos 服务等,都可以转换为 MCP 接口服务能力,让 AI 客户端使用。 + +恰好,这个事小傅哥也在带着大家做一套 [《AI MCP Gateway 网关服务系统》](https://bugstack.cn/md/project/ai-mcp-gateway/ai-mcp-gateway.html) 如果想在 AI 开发方面做一些储备积累,那么一定要学习这套项目。 + +> 本案例会使用 docker 进行部署,如果你不了解 docker 是什么,可以阅读系列教程 [https://bugstack.cn/md/road-map/docker-what.html](https://bugstack.cn/md/road-map/docker-what.html) + +## 二、网关使用 + +### 1. 案例工程 + +
+ +
+ +- 地址:[https://github.com/fuzhengwei/xfg-dev-tech-higress-ai](https://github.com/fuzhengwei/xfg-dev-tech-higress-ai) +- 说明:案例工程,提供了部署 Higress AI 网关脚本(+redis环境),以及包括工程提供了一个测试 http 接口,并配置了 swagger api 文档。网关可以支持从 swagger api json 转换为 MCP 协议结构。 +- 环境:如果你是使用云服务器部署 Higress AI 网关,那么可以使用提供好的一键部署脚本安装环境 [https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install](https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install) + +### 2. 接口说明 + +#### 2.1 swagger api + +```java + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.5.0 + + + + org.springdoc + springdoc-openapi-starter-webmvc-api + 2.5.0 + +``` + +- 官网:[https://swagger.io/](https://swagger.io/) +- 添加 swagger api pom,项目启动后可以访问;[http://localhost:8091/swagger-ui/index.html](http://localhost:8091/swagger-ui/index.html) - 就可以看到项目的 http 接口信息了。 + +#### 2.2 接口开发 + +```java +@RestController +@CrossOrigin("*") +@RequestMapping("/api/v1/") +@Tag(name = "测试服务", description = "示例接口") +public class TestServiceController { + + private static final Logger logger = LoggerFactory.getLogger(TestServiceController.class); + + /** + * API文档;swagger
+ * API测试;http://127.0.0.1:8091/api/v1/to_upper_case?word=xiaofuge + */ + @GetMapping("to_upper_case") + @Operation(summary = "字符串转大写", description = "将传入 word 转换为大写") + public String toUpperCase(@RequestParam String word) { + logger.info("接收信息:{}", word); + return word.toUpperCase(); + } + +} +``` + +- 在接口上增加描述信息,这些信息可以用作于 mcp 协议结构中方法和字段上的介绍。如下就是 mcp 接口的 @Tool 工具配置。 + +```java +@Tool(description = "获取公司雇员信息") +public XxxResponse getCompanyEmployee(XxxRequest01 xxxRequest01, XxxRequest02 xxxRequest02) { + log.info("根据公司和雇员,查询工资和工作工时。{} {}",xxxRequest01.getCompany(), xxxRequest02.getEmployeeName()); + // 这部分可以实际调用你需要的接口,比如调用http接口获取个数据或者做一些操作等。 + XxxResponse xxxResponse = new XxxResponse(); + xxxResponse.setSalary(new Random().longs(10000).toString()); + xxxResponse.setDayManHour(String.valueOf(new Random().nextInt(24))); + return xxxResponse; +} +``` + +- 所以,即使是我们自己开发 AI MCP 网关,也是在找这样的衔接点。怎么把 http 接口,借住什么标准的桥梁,转换为 mcp 协议,让用户使用起来更加简单。而 swagger api 就是中间的标准 open api 桥梁。 + +### 3. 网关部署 + +#### 3.1 脚本说明 + +```java +# 命令执行 docker-compose -f docker-compose-environment-aliyun.yml up -d +# docker 代理和使用文档;https://bugstack.cn/md/road-map/docker.html +version: '3.9' +services: + # https://github.com/alibaba/higress + # docker run -d --rm --name higress-ai -v ${PWD}:/data \ + # -p 8001:8001 -p 8080:8080 -p 8443:8443 \ + # higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/all-in-one:latest + higress-ai: + image: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/all-in-one:latest + container_name: higress-ai + hostname: higress-ai + ports: + - 8001:8001 + - 8080:8080 + - 8443:8443 + volumes: + - ./higress-ai/data:/data + networks: + - my-network + + # Redis + redis: + image: redis:6.2 + container_name: redis + restart: always + hostname: redis + privileged: true + ports: + - 16379:6379 + volumes: + - ./redis/redis.conf:/usr/local/etc/redis/redis.conf + command: redis-server /usr/local/etc/redis/redis.conf + networks: + - my-network + healthcheck: + test: [ "CMD", "redis-cli", "ping" ] + interval: 10s + timeout: 5s + retries: 3 + +networks: + my-network: + driver: bridge +``` + +- 这里把 higress-ai 通过 docker-compose 脚本进行部署,因为部署后还需要配置 Redis 环境,基于 Redis 的 pub/sub 发布订阅能力,让网关具备分布式部署能力,所以在 docker-compose 脚本里,提供了 higress-ai、redis 的部署。 +- 部署;`docker-compose -f docker-compose-environment-aliyun.yml up -d` + +#### 3.2 部署网关 + +##### 3.2.1 部署脚本 + +
+ +
+ +- 如图说明,进行部署。Mac 电脑本地测试即可。如果 Windows 电脑有兼容问题,可以考虑 Linux 云服务器。[https:618.gaga.plus](https:618.gaga.plus) + +##### 3.2.2 部署结果 + +
+ +
+ +- 部署后,访问 portainer(这个是 docker 的管理后台) + +##### 3.2.3 访问网关 + +
+ +
+ +- 地址:[http://127.0.0.1:8001/](http://127.0.0.1:8001/) +- 说明:首次登录需要设置下登录账号和密码,设置后登录即可。 + +### 4. 获取接口 + +#### 4.1 启动服务(springboot) + +
+ +
+ +- 测试:[http://127.0.0.1:8091/api/v1/to_upper_case?word=xiaofuge](http://127.0.0.1:8091/api/v1/to_upper_case?word=xiaofuge) - `把小写的xiaofuge转换为大写` +- 接口:[http://localhost:8091/swagger-ui/index.html#/%E6%B5%8B%E8%AF%95%E6%9C%8D%E5%8A%A1/toUpperCase](http://localhost:8091/swagger-ui/index.html#/%E6%B5%8B%E8%AF%95%E6%9C%8D%E5%8A%A1/toUpperCase) + +#### 4.2 获取接口 + +
+ +
+ +- 地址:[http://localhost:8091/swagger-ui/index.html](http://localhost:8091/swagger-ui/index.html) +- 说明:启动服务后,访问 swagger 地址,你就可以拿到接口文档了。这里主要需要的就是这份json结构。 + +### 5. 网关配置 + +#### 5.1 开启网关(mcp) + +
+ +
+ +- 注意,在系统设置里,需要开启 mcp 网关服务。enable = true +- 另外,redis 地址,需要配置上。默认本文给的案例,是支持直接使用 redis 别名链接的,如果 redis 不是本案例安装的,则可以用 ip:port 连接。如果有密码,记得填写密码。 + +#### 5.2 服务来源 + +
+ +
+ +- 可以在网关页,配置服务来源。这里的服务来源支持多种类型,Nacos、Eureka、Zookeeper,以及我们图中这种固定地址的案例,都是可以的。 +- 注意下面配置的服务协议,这里选择的是 HTTP,也支持 HTTPS,GRPC 的格式。 + +#### 5.3 创建服务(MCP) + +
+ +
+ +在 AI网关管理下,MCP 管理中,添加一个 MCP 服务。这里的用途是建一个 MCP 网关和后端服务建立起连接。 + +#### 5.4 添加工具(协议转换) + +
+ +
+ +
+ +
+ +- 接下来,还需要添加下工具。也就是 http 接口的具体能力。这里可以把 Swagger 的 json 文件复制过来,添加进去即可。 + +#### 5.5 验证接口(sse) + +
+ +
+ +
+ +
+ +在添加接口的地方,你会看到一个网关服务的地址。也就是 SSE 接入点,用于配置到 AI 客户端里。访问地址;http://127.0.0.1:8080/mcp-servers/toUpperCase/sse + +**好了,到这你的 AI MCP 网关就配置成功了,你可以把各类服务端的接口转换为 MCP 协议结构进行使用。** + +### 6. 接口转发(AI) + +
+ +
+ +AI 网关管理里,还提供了关于 AI 接口的配置。它可以进行统一管理,适合项目的接入使用。做 AI 类的项目,可以把 AI 请求,统一用这样一套东西管理起来。 + +## 三、调用测试 + +
+ +
+ +```java +13:55:19.581 [main] INFO cn.bugstack.xfg.dev.tech.test.ApiTest -- 测试结果:字符串 "xiaofuge" 转换为大写后是 "XIAOFUGE"。 +``` + +- 调用后可以看到把小写的字符串 `xiaofuge` 转换为大写的 `XIAOFUGE` +- 你也可以进入到 TestServiceController 看到调用的日志。 + +## 四、深入学习 + +目前,小傅哥也正在带着粉丝伙伴学习 AI 项目,[《AI MCP 网关》](https://origin.bugstack.cn/md/project/ai-mcp-gateway/ai-mcp-gateway.html),就是目前在持续更新的一个实战类项目。 + +该项目是 AI Agent 智能体,关于 MCP 协议对接的通用网关服务项目,以解决各类业务接口便捷转换为 MCP 协议而设计实现。通过这样的配置,可以大大的简化从普通http、rpc接口到 MCP 协议的转换操作。这样的项目,也是每个互联网公司在做 AI Agent 智能体时,必备的基础设施项目。 + +### 1. 项目架构 + +
+ +
+ +### 2. 工程模块 + +
+ +
+ +### 3. 协议转换 + +
+ +
+ +在此项目中,小傅哥一遍带着你分析调试 Spring AI MCP 上下文源码,一边带着你写 AI MCP 网关代码。让你全面的厘清系统设计,又能亲手实现出一套 AI MCP 网关。 + diff --git a/docs/md/road-map/higress.md b/docs/md/road-map/higress.md index 65aa9ac67..5316e16b2 100644 --- a/docs/md/road-map/higress.md +++ b/docs/md/road-map/higress.md @@ -26,7 +26,7 @@ lock: need 那么为了让大家更好的了解下大厂的API,今天我们就来体验一款大厂开发的元原生API网关。有了这样一个学习,在看API网关项目,也会更清楚自己在做什么。 -- 官网:[https://higress.io/zh-cn/](https://higress.io/zh-cn/) +- 官网:[https://higress.io/](https://higress.io/) - 源码:[https://github.com/alibaba/higress](https://github.com/alibaba/higress) - 部署:[https://github.com/higress-group/higress-standalone](https://github.com/higress-group/higress-standalone) - `独立运行版,用于测试` - 案例:[https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-higress](https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-higress) - `部署测试` diff --git a/docs/md/road-map/intellij-idea-remote-jvm-debug.md b/docs/md/road-map/intellij-idea-remote-jvm-debug.md new file mode 100644 index 000000000..185282c0f --- /dev/null +++ b/docs/md/road-map/intellij-idea-remote-jvm-debug.md @@ -0,0 +1,225 @@ +--- +title: IntelliJ IDEA Remote JVM Debug +lock: need +--- + +# IntelliJ IDEA Remote JVM Debug - 本地远程调试服务器运行代码 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +我遇到过一种bug场景,本地没什么问题,部署到服务器上就不行了。往往遇到这样的问题,要花费大量的时间检查程序逻辑,一个个方法 mock 测试验证。那有人会问了,你怎么不在本地 debug 调试下呢? + +
+ +
+ +**你的代码本地没法启动!** + +其实并不是所有的工程代码,都能本地启动运行的。尤其复杂的工程,与外部对接非常多,甚至还有一些是风险控制的问题,本地是不能启动直接调用的。也就是控制研发人员,不允许本地程序调用其他程序的接口。那么对于这样的工程,研发的自测就要通过编写 [mock](https://bugstack.cn/md/road-map/mock.html) 方式进行单元化测试。 + +不过这里会有一个问题,单元化的测试,mock 的数据是不会随着外部所有程序的调整动态的变更的,而是随着研发编写需求,一次写好后,后续如果这个功能没有被调整,那么 mock 测试也不会在调整了。同时还因为 mock 覆盖的场景不全,不知道引入的外部那么多接口都有哪些新增的逻辑。因而,你可能本地运行没问题,但部署到测试环境,就会有一些不缺性的报错。 + +对于这里的报错,当你没有 debug 手段的时候,就要把前后的报错数据,都要复制到本地,通过 mock 的方式验证程序逻辑,一点点排查。不过,这个过程也要花费好长时间,尤其是一些复杂的逻辑与外部交互又非常多的时候,调试起来很耗费时间。 + +所以,程序员👨🏻‍💻对于实在难以调试的代码,还有一种方式就是远程调试。把代码部署到服务器,通过请求服务器的接口,本地的 IntelliJ IDEA 打开的工程,就可以调试对应的运行数据。可以非常高效的解决 bug! + +接下来,小傅哥就带着大家做一个这样的案例。如果你是一个新手小白,就更有必要学习一下这样的手段了。 + +> 🧧 文末还提供了17个实战项目,全套的文档、视频、代码,都可以获取。还有非常清晰的学习路线!嘎嘎冲! + +## 一、测试工程 + +这里小傅哥为你准备好了一个测试工程,你可以直接下载验证。 + +
+ +
+ +- 地址:[https://github.com/fuzhengwei/xfg-dev-tech-remote-jvm-debug](https://github.com/fuzhengwei/xfg-dev-tech-remote-jvm-debug) +- 环境:JDK 1.8、SpringBoot 2.7 +- 如图,工程提供了简单的 TestApiController 一个 http 测试入口。之后通过 Dockerfie 方式构建镜像,以及提供了 docker-compose-app.yml 启动工程。重要的是 JAVA_REMOTE_DEBUG 的配置。这是一种 JavaAgent 技术,如果感兴趣可以进入小傅哥的博客,[https://bugstack.cn/](https://bugstack.cn/) 字节码编程中学习。 + +### 1. 测试接口 + +```java +@Slf4j +@RestController() +@CrossOrigin("*") +@RequestMapping("/api/v1/test/") +public class TestApiController { + + /** + * curl --request POST \ + * --url 'http://127.0.01:8091/xfg/api/v1/test/group_buy_notify?requestDTO=1111' + * + * 注意,yml 里配置了应用根目录;server.servlet.context-path: /xfg + */ + @RequestMapping(value = "group_buy_notify", method = RequestMethod.POST) + public String groupBuyNotify(@RequestParam String requestDTO) { + log.info("请求参数 {}", JSON.toJSONString(requestDTO)); + + return "success"; + } + +} +``` + +- 一个简单的测试接口,访问接口地址为;`http://127.0.01:8091/xfg/api/v1/test/group_buy_notify?requestDTO=1111` +- 你可以复制 curl 部分,导入到 apipost/apifox 等工具里使用。 + +### 2. Dockerfile + +```java +# 基础镜像 +FROM openjdk:8-jre-slim + +# 作者 +MAINTAINER xiaofuge + +# 配置 +ENV PARAMS="" + +# 时区 +ENV TZ=PRC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# 添加应用 +ADD target/xfg-dev-tech-remote-jvm-debug-app.jar /xfg-dev-tech-remote-jvm-debug-app.jar +EXPOSE 8091 5005 + +ENTRYPOINT ["sh","-c","java $JAVA_REMOTE_DEBUG -jar $JAVA_OPTS /xfg-dev-tech-remote-jvm-debug-app.jar $PARAMS"] +``` + +- ENTRYPOINT,添加了一个 $JAVA_REMOTE_DEBUG 的动态入参,其实这个位置要填入的就是 `-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:5005` 但并不是上线的所有程序都要做这样的事情,一般只有测试环境才需要。 +- EXPOSE 8091 5005 对外暴漏应用程序所需的 8091 5005 端口。 + +### 3. DockerCompose 部署脚本 + +```java +# /usr/local/bin/docker-compose -f /docs/dev-ops/environment/environment-docker-compose-2.4.yml up -d +version: '3.8' +# docker-compose -f docker-compose-app.yml up -d +services: + xfg-dev-tech-remote-jvm-debug-app: + image: fuzhengwei/xfg-dev-tech-remote-jvm-debug-app:1.0 + container_name: xfg-dev-tech-remote-jvm-debug-app + restart: on-failure + ports: + - "5005:5005" + - "8091:8091" + environment: + - TZ=PRC + - SERVER_PORT=8091 + # 2c4g 配置,4c8g 翻倍,-Xms4096m -Xmx4096m | -Xmx –Xms:指定java堆最大值(默认值是物理内存的1/4(<1GB))和初始java堆最小值(默认值是物理内存的1/64(<1GB)) + - JAVA_OPTS=-Xms2048m -Xmx2048m + - JAVA_REMOTE_DEBUG=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:5005 + volumes: + - ./log:/data/log + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + networks: + - my-network + +networks: + my-network: + driver: bridge +``` + +- 部署服务注意,要对外提供 5005、8091 两个映射端口。对于这种端口的暴漏说明,我已经提供好了基础教程,可以在这里扩展学习;[https://bugstack.cn/md/road-map/docker-what.html](https://bugstack.cn/md/road-map/docker-what.html) +- 另外在 environment 环境中,配置 `- JAVA_REMOTE_DEBUG=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:5005` 这样就可以把远侧调试的服务给启动起来了。相当于你在自己的电脑的 IntelliJ IDEA 与服务器上的应用,通过 5005 端口进行通信完成测试debug验证。 + +## 二、部署程序 + +确保你自己本地已经安装好了 [Docker](https://www.docker.com/) Mac、Windows 电脑都可以安装。 + +### 1. 打包程序 + +
+ +
+ +- 通过 IntelliJ Install 打包程序。其实就是 Maven 命令,mvn clean install 的操作。 + + +### 2. 构建镜像 + +
+ +
+ +1. mac 电脑可以点绿色箭头。 +2. windows 电脑,可以通过 powershell 执行 ./build.sh + +### 3. 发布项目 + +
+ +
+ +
+ +
+ +- mac 点击绿色箭头启动程序即可。 +- windows 打开 powershell 执行脚本 `docker-compose -f docker-compose-app.yml up -d` + +## 三、调试程序 + +### 1. IntelliJ IDEA 配置 + +
+ +
+ +- 首先,在运行调试按钮那,点击下拉框。增加一个新的调试配置。 +- 之后,点击+号,添加 `Remote JVM Debug` +- 最后,填写 IP 地址和端口,点击 Apply OK 即可。 + +### 2. 导入接口 + +
+ +
+ +- 导入接口到 ApiPost 中调用。其他的工具也可以,这样接口可以保存起来,方便以后调试。 + +### 3. 远程调试 + +#### 3.1 启动程序 + +
+ +
+ +- 以新建的远程 debug 方式,启动程序。 + +#### 3.2 添加断点 + +
+ +
+ +- 添加断点。注意,这会的程序部署的要一致,不能动代码。否则和远程部署的不一致,是不能调试的。 + +#### 3.3 调用接口 + +
+ +
+ +
+ +
+ +- 首先,在 ApiPost 中点击【发送】按钮。 +- 这会,你可以在打了断点的程序中,查看到请求的调用会进来。最终执行完,远程的部署的程序也会执行完。 + +🌶 好啦,到这你就已经学会了远程调试了。以后自己的简历中,对于项目的描述,此类问题,你也可以讲自己是如何做的远程调试。 diff --git a/docs/md/road-map/jenkins.md b/docs/md/road-map/jenkins.md index fc959d55c..79e943532 100644 --- a/docs/md/road-map/jenkins.md +++ b/docs/md/road-map/jenkins.md @@ -1,5 +1,5 @@ --- -title: Jenkins +title: Jenkins 发布部署 lock: need --- @@ -118,7 +118,7 @@ Jenkins Docker 执行安装脚本。 - 1~2步,设置镜像源,设置后重启一下 Jenkins。 - 镜像源地址:https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json + 镜像源地址:https://mirrors.huaweicloud.com/jenkins/updates/update-center.json - 3~4步,下载插件,先下载安装 chinese 汉化插件,方便不太熟悉 Jenkins 的伙伴更好的知道页面都是啥内容。 - 5步,所有的插件安装完成后,都需要重启才会生效。`安装完 chinese 插件,重启在进入到 Jenkins 就是汉化的页面了` - 除了以上步骤,你还需要同样的方式安装 maven、git、docker 插件。 diff --git a/docs/md/road-map/joycode.md b/docs/md/road-map/joycode.md new file mode 100644 index 000000000..4bdf9bb1f --- /dev/null +++ b/docs/md/road-map/joycode.md @@ -0,0 +1,209 @@ +--- +title: JoyCode +lock: need +--- + +# JoyCode - 代码洪流 一念即成! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +**🧨25年以来**,先是 RAG 知识库,再到发布 MCP 协议。到这,各个互联网公司哇哇进入了 AI Agent 智能体开发,在各个应用场景探索提效,做出了很多的智能体产品,如;`Dify`、`Coze`、`Claude`,以及 `AI IDEA` 产品辅助编码(`Trae.ai`、`Cursor`等)。 + +曾经还以为 AI 出了这么多产品,是不程序员的工作岗位会变少🤔?**好家伙,一点没少不说,还变多了**。因为互联网的思维是,**你干的越快,你活tm越多**。甚至不少公司已经要求,程序员的 AI 编码量要在50%以上。**说白了就是,你得快点整 😂**。 + +
+ +
+ +**但,凡事不是坏事!** + +其实我们公司也要求了 AI 编码量,他所编写的代码提交是有 Git 记录和 AI IDEA 记录的,以此进行分析使用情况。公司里这么做也能理解,大家都用才能整体提高编码效率。而且这事多老程序员是有好处的,老程序员的`架构思维厚实`、`编码经验充足`,`邪修技巧多样`,把这些思维转换为提示词,可以节省大量的编码量(毕竟老码农体力不如新生代)。 + +此外,像是这些 AI IDEA 除了企业的编码外,对程序员的学习是非常有好处的。比如对代码的理解,对模块的分析、对bug的检查处理,以及通过提问的方式拓展式的增强理解工程代码都是有好处的。**新人一定使用!** 因为不只是学习,而是进入企业后还要使用。 + +那么有哪些不错的 AI IDEA 吗?有的,Cursor、Trae.ai 都不错的,之后,还有一个可以免费使用的 Joycode 京东出的,使用起来也不错,支持很多模型。地址:[https://joycode.jd.com/docs/start/intro/](https://joycode.jd.com/docs/start/intro/) + +
+ +
+ +> 接下来,小傅哥就分享下关于 JoyCode 的使用。让小伙伴们更好的使用 AI 辅助编码和学习代码。 + +## 一、软件下载 + +官网地址:[https://joycode.jd.com/](https://joycode.jd.com/) + +
+ +
+ +- 代码洪流 一念即成。JoyCode,专为应对企业级复杂任务而设计的智能编码工具。 +- 在使用的时候,你可以一个工程同时在 IntelliJ IDEA 打开,也使用 Trae 打开。😂 因为习惯 IntelliJ IDEA,各类调试还是很舒服的。 + +> 同类软件 [Cursor](https://www.cursor.com/cn),不过这个想使用好的模型得付费,Joycode 暂时是不需要付费的!其实我们需要百家争鸣,各家都用一些才好。 + +## 二、使用场景 + +### 1. 提问代码 + +拖拽代码/文件夹/工程 + +
+ +
+ +
+ +
+ +- 对于需要的代码进行选择式的提问,选中后的代码,在对话框中会标注出来。如果你在对话中还要告诉AI用其他部分的代码,则把对应位置的代码,写到对话框里就可以,如;`cn.bugstack.domain.auth.service.WeixinLoginService` +- 所有我们编程过程中,可以做的操作,都可以让 AI 来做,但尽量描述准确。这也就是老码农,为啥能更准确的使用 AI IDEA 工具,因为可以知道描述的内容最终可以产出的结果。 + +### 2. 完善注释 + +
+ +
+ +
+ +
+ +对于类、方法、字段属性,都可以让 AI 来补全注释说明,辅助我们学习使用。如果你对某一快逻辑厘不清的时候,也可以使用 AI 这样理解代码。 + +### 3. 开发功能 + +#### 3.1 curl 接口 + +
+ +
+ +#### 3.2 开发接口 + +
+ +
+ +**描述的话术,尽量准确** + +```java +在 s-pay-mall-ddd-infrastructure 模块下, cn.bugstack.infrastructure.gateway 文件包下,编写 IJueJinService 类,以 retrofit2 方式包装 curl 请求接口。接口入参仅为必要参数,如;cookie,发文的 Request 对象。 + +curl 如下; + +curl 'https://api.juejin.cn/content_api/v1/article_draft/create?aid=2608&uuid=7058897578062890496' \ + -H 'accept: */*' \ + -H 'accept-language: zh-CN,zh;q=0.9,en;q=0.8' \ + -H 'content-type: application/json' \ + -b 'store-region=cn-bj; store-region-src=uid; __tea_cookie_tokens_2608=%******a51b13e5; uid_tt_ss=7aff2f2394310b3b71f07006a51b13e5; sid_tt=3813572f48984e4b5b3cc7f90733f2e9; sessionid=3813572f48984e4b5b3cc7f90733f2e9; sessionid_ss=3813572f48984e4b5b3cc7f90733f2e9; sid_ucp_v1=1.0.0-KDU4N2NlM2Q2NjFiODhjOGNhZGE5YzVlOTM4ZWZkY2U3ZTc3MzVjMjAKFwjemIC67ozUAxDT_ci_BhiwFDgCQPEHGgJsZiIgMzgxMzU3MmY0ODk4NGU0YjViM2NjN2Y5MDczM2YyZTk; ssid_ucp_v1=1.0.0-KDU4N2NlM2Q2NjFiODhjOGNhZGE5YzVlOTM4ZWZkY2U3ZTc3MzVjMjAKFwjemIC67ozUAxDT_ci_BhiwFDgCQPEHGgJsZiIgMzgxMzU3MmY0ODk4NGU0YjViM2NjN2Y5MDczM2YyZTk' \ + -H 'dnt: 1' \ + -H 'origin: https://juejin.cn' \ + -H 'priority: u=1, i' \ + -H 'referer: https://juejin.cn/' \ + -H 'sec-ch-ua: "Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"' \ + -H 'sec-ch-ua-mobile: ?0' \ + -H 'sec-ch-ua-platform: "macOS"' \ + -H 'sec-fetch-dest: empty' \ + -H 'sec-fetch-mode: cors' \ + -H 'sec-fetch-site: same-site' \ + -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36' \ + -H 'x-secsdk-csrf-token: 00010000000152d838f2c09c65e4feef033c275a8cff940c12228719074fe36f9ce2d18b4d251833ae62ea768117' \ + --data-raw '{"category_id":"0","tag_ids":[],"link_url":"","cover_image":"","title":"测试文章","brief_content":"","edit_type":10,"html_content":"deprecated","mark_content":"","theme_ids":[],"pics":[]}' + +接口返回结果; + +{ + "err_no": 0, + "err_msg": "success", + "data": { + "id": "7489358088379531291", + "article_id": "0", + "user_id": "2058727733595230", + "category_id": "0", + "tag_ids": [], + "link_url": "", + "cover_image": "", + "is_gfw": 0, + "title": "测试文章", + "brief_content": "", + "is_english": 0, + "is_original": 1, + "edit_type": 10, + "html_content": "deprecated", + "mark_content": "", + "ctime": "1743929226", + "mtime": "1743929226", + "status": 0, + "original_type": 0, + "theme_ids": [] + } +} + +根据接口信息封装 DTO 对象,放到 gateway dto 下。 +``` + +### 4. 单元测试 + +
+ +
+ +
+ +
+ +- 编写单测试一个很好用的场景,因为单测即使写错了也不会影响到线上的业务流程。 + +### 5. 系统分析 + +
+ +
+ +- 让 ai idea 工具分析系统工程,它分析的还是很不错的。这非常有利于伙伴对项目的学习、理解、重构,是非常提效的。 + +## 三、AI 来了吗? + +刷”知乎“的时候,有伙伴问,AI 真的来了吗?这何止是来了,我已经感受到它来的太快了,21年 AI 可以对话、22 年各种代理的服务、23 年大家结合AI 做各种服务,24年推出 MCP 协议,25年大家进入了 AI Agent 智能体,谷歌发布 A2A 协议。照这样发展,明年、后年,将会有更加成熟的 AI 场景使用,企业里也会开启大量的 AI 应用开发岗位,为各个场景提效。 + +
+ +
+ +你会在各个公司的招聘里看到 AI 应用开发岗,我以后也是会回天津的,顺手搜了下。附近就有联想公司的这样的岗位。早点储备能力! + +关于 AI 小傅哥已完成项目包括;OpenAI 代码自动评审、OpenAI 应用(含支付)、AI Agent 智能体,以及正在开展的 AI MCP Gateway 网关服务项目。感兴趣的伙伴,可以一起加入学习。 + +### 1. AI Agent 智能体 + +
+ +
+ +
+ +
+ +### 2. OpenAI 应用(含支付) + +
+ +
+ +
+ +
+ +### 3. AI MCP GateWay + +
+ +
+ +> 很多能力就是这样,早早的储备起来,以备不时之需!程序员也是一个一直学习的行业!春江水暖鸭先知🦆,码农需要学知识! diff --git a/docs/md/road-map/kafka.md b/docs/md/road-map/kafka.md index a20ed89d6..303f75fef 100644 --- a/docs/md/road-map/kafka.md +++ b/docs/md/road-map/kafka.md @@ -44,7 +44,8 @@ lock: need - Mac 电脑会比较好安装一些,直接在 IntelliJ IDEA 点击小绿色按钮即可完成安装。安装完成后进入 [http://localhost:9000/#!/2/docker/containers](http://localhost:9000/#!/2/docker/containers) 可看到 zookeeper、kafka、kafka-eagle 运行啦。 - Windows 电脑安装 Docker 需要折腾下 - Linux 服务器,需要上传整个 dev-ops 后在云服务器执行脚本安装;`docker-compose -f docker-compose.yml up -d` -- 如图29行,有一个 kafka:9092 这个 kafka 是个 host 地址,就是 SwitchHost 打开后配置本地的 ip地址映射 kafka +- 如图29行,有一个 kafka:9092 这个 kafka 是个 host 地址,就是 SwitchHost 打开后配置本地的 ip地址映射 kafka +- 另外推荐 [kafka king](https://github.com/Bronya0/Kafka-King/releases) 作为管理界面 ### 3. 访问地址 @@ -310,4 +311,4 @@ public class UserServiceTest { 24-03-17.12:29:01.647 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO KafkaMessageListener - Kafka消费成功! Topic:xfg-topic,Message:{"data":{"userId":"10001","userName":"小傅哥","userType":"架构师"},"id":"15051699480","timestamp":1710649741313} ``` -- 运行测试,可以看到消息的推送和接收。 \ No newline at end of file +- 运行测试,可以看到消息的推送和接收。 diff --git a/docs/md/road-map/linux.md b/docs/md/road-map/linux.md index 405a0ae25..6c8e992af 100644 --- a/docs/md/road-map/linux.md +++ b/docs/md/road-map/linux.md @@ -1,5 +1,5 @@ --- -title: Linux +title: Linux 开发环境 lock: need --- @@ -24,9 +24,10 @@ lock: need 本文涉及的工程; -- xfg-dev-tech-linux:[https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-linux](https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-linux) +- xfg-dev-tech-linux:[https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-linux](https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-linux) 注意 jdk 从下面的地址单独下载。 - 云服务器配置要求:2c2g [https://618.gaga.plus](https://618.gaga.plus) - 工程提供了git、 java、maven、redis、mysql 的环境安装,可以让本地连接云服务器的配置,也可以在云服务器拉取项目进行构建操作。 +- 环境软件下载:[https://drive.weixin.qq.com/s?k=ACMA4AfQABUYiIGUXy](https://drive.weixin.qq.com/s?k=ACMA4AfQABUYiIGUXy) - 所需的 `jdk-8u202-linux-x64.tar.gz` 从这里下载。 >文末有加入学习方式,提供了8个Java实战项目,非常有东西可以学! @@ -87,6 +88,48 @@ chmod +x install-java.sh - 提示:如果未输出 java,可以手动执行 `source /etc/profile` - 卸载:如果不需要 Java 环境了,可以同样方式执行 `./remove-java.sh` +**也可以手动安装** + +1. 解压jdk + +```java +tar -zxvf jdk-8u202-linux-x64.tar.gz +``` + +2.修改解压后文件的文件名 + +```java +mv jdk1.8.0_202 jdk-8u202 +``` + +3.配置Java环境,编辑/etc/profile文件 + +```java +vim /etc/profile +``` + +4.打开以后将下面三句输入到文件里面并保存退出 + +```java +export JAVA_HOME=/software/jdk-8u202 +export JRE_HOME=${JAVA_HOME}/jre +export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib:$CLASSPATH +export JAVA_PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin +export PATH=$PATH:${JAVA_PATH} +``` + +5.生效profile + +```java +source /etc/profile +``` + +6.查询Java版本,出现的版本是自己下载的版本,则安装成功。 + +```java +java -version +``` + ### 3. 安装 Maven ```java diff --git a/docs/md/road-map/mac.md b/docs/md/road-map/mac.md new file mode 100644 index 000000000..555c13981 --- /dev/null +++ b/docs/md/road-map/mac.md @@ -0,0 +1,102 @@ +--- +title: MacBook Pro +lock: need +--- + +# MacBook Pro - 关于我是不是该买Mac电脑? + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +不少程序员👨🏻‍💻伙伴,一到618、双11和开学季的时候,总会问买个 Windows 电脑,还是搞个 MacBook Pro?网上搜的很多对比,都是说同配置的苹果更贵,但心里总痒痒也好奇,MacBook Pro 是不更好用还能装个B! + +
+ +
+ +**如果你是程序员👨🏻‍💻,我更推荐苹果电脑。为啥?** + +首先,Windows 和 Mac 没有好坏之分,只不过 Windows 有 Windows 的使用场景、Mac 有 Mac 的应用领域。你喜欢打游戏、折腾些硬件对接、综合工作和娱乐,那 Windows 就是最强的选择。 + +但如果只在程序员这一行业对比编程写代码,一台笔记本,灵敏的触控板让你忘记鼠标的存在,苹果 IOS、IPad、Mac 全家桶式的多设备互通,可以做到极致的体验。 + +而更重要的是,Java 写好的代码是要放到 Linux 运行,而不是 Windows,所有你在所需的环境、所编写的脚本,可以无差别从 Mac 转移到 Linux 使用。这是 Windows 没法做到的,甚至 Windows 要在这块浪费掉你很多的时间。*不是不能用,就是不丝滑!* + +>接下来,小傅哥分享下 Mac 电脑的使用经验。新入坑伙伴可以参考。 + +## 一、我的经历 - 入坑 Mac! + +2019年,在这之前我只用过 Windows 电脑,包括;台式机、笔记本,还有自己DIY的台式机。Windows 给我感觉就是抗造,能自己折腾,加个内存,换个固态硬盘。打起来游戏方便,无论是澄海3c还是lol英雄联盟。 + +但在这之前,我也就只有一台 thinkstation 的台式机,每次长假期赔媳妇出门,我都想着要是有个笔记本电脑,我就可以在外面写代码。要不多没意思。所以,我的理由就有了! + +2019年,趁着618活动,搞了第一台 Mac 电脑 i5 8G 256G SSD。说实话这个配置一点也不高,而且价格也不便宜 `¥10189.00` 元。好在送一个 `Beats Solo3 Wireless`耳麦。 + +
+ +
+ +不过 `Beats Solo3 Wireless` 被我在咸鱼转手卖掉回血了。 + +
+ +
+**但谁能想得到,这台电脑在5个月以后,还能给我返回来 5000 元!** + +2019年,双11备战誓师大会。抽取幸运备战人员,清空购物车!最高清空额度,就是同年 618 期间消费的额度,上限 5000 元! + +
+ +
+ +这不巧了🐴,这不巧了🐴!618,我呀,我买了电脑,` ¥10189.00`!Duang、Duang、Duang,大转盘一转,还真抽中我了!那一刻,我决定做个抽奖系统! + +
+ +
+ +从此开启了苹果全家桶系列,苹果手机、IPad mini、IPad Pro ...,讲真,确实好用!那有人问,你 Mac 电脑,也打不了游戏呀?嗯,我媳妇给我买了PS5,还中了一台 Switch 😂 + +> 是的,后来我做了 Lottery 抽奖系统,还有大营销系统(Lottery Plus)! + +## 二、体验对比 - Mac 优势 + +这里我不谈那些打游戏、或者和一些硬件的适配。因为你有那些诉求,直接选择 Windows 就可以。比如;外星人也不错。 + +- 续航基本在10个小时左右,你是不需要带着充电电源的。像是在公司,双周需求评审,要占用一整个下午,这个期间电脑不需要插电源。 +- 不需要每天早上来开机,晚上回去关机。只要它不死机,甚至半年不都不关机。合上就走,打开就用。 +- 对于常用的技术编程环境类软件,直接下载就安装。因为这类软件是按照 Linux 系统做的,不是按照 Windows 系统做的。很多时候 Windows 要做兼容。比如执行脚本、安装 Docker,Windows 都要折腾一下。 +- 不需要安装各类杀毒软件,安装和卸载软件十分方便。有一些 Mac 的软件是付费的软件,但很多是一次付费终身使用,一点广告没有。不付费也可以破解使用,很多 Mac 软件都提供了破解版。 +- 尤其是 M2、M3 系列的 Mac,性能很炸裂,同时开几个 IDEA + 一堆环境类软件,以及一堆的打开的网页也很丝滑。 +- 切屏极其容易,多屏幕工作在 Mac 上是利器,可以不同的屏幕处理不同的事项。但在 Windows 切屏就挺费力气! +- Mac 电脑可以外接显示器,这个 Windows 也有。但 Mac 还可以和 IPad 联动,功能叫随行。 +- Mac 上复制的内容,或者苹果手机上复制内容,可以互相粘贴。也可以极其简单的方式互传文件。 +- Mac 电脑的触控板,一周内可习惯,习惯后不需要使用鼠标了。感受过 Mac 的触控板,会感觉鼠标是个鸡肋。间接的你不会有一个鼠标手「长时间用鼠标会做病」。 +- 和其他的软件设备,比如 nas 可以直接链接操作。你可以 Mac 电脑打开 idea,但代码放到 nas 上。这个很爽!并且 nas 可以直接给你提供 docker 环境。下一期可以介绍下 nas 的使用。 + +>其实,我认为还有一点是最重要的。做软件开发的,应该体验最好的软件逻辑。这可以让你的编程思维得到提升。虽然 Mac 比 Windows 贵,但折腾 Windows 浪费的时间也很贵。 + +## 三、装机分享 - 我的软件 + +Mac 电脑的软件非常好安装,双击打卡,之后交给它! + +
+ +
+ +安装软件资源库; + +- 推荐:[https://aerolite.dev/applite](https://aerolite.dev/applite) +- 其他:[https://macwk.cn/](https://macwk.cn/) +- 其他:[https://macapp.org.cn/](https://macapp.org.cn/) + +## 四、避坑经验 - 别浪费钱 + +- 钱少,但想体现Mac,可以考虑 Mac mini,教育版。尽量在16G起。这样价格和一台 Windows 笔记本差不多。 +- 做编程开发,别买二手的Mac。这些软件都是不断的升级的,太老的 Mac 一般都很卡,升级 Mac 系统,就跟升级 苹果手机 IOS 一样,越升级越卡。 +- 推荐买上一年的版本,价格合适。版本也不旧。但别买太低配置或者年限太老的。其实我们天天用的东西,价格高点也合适。 +- Mac 的 M4 也快出了。我下一个会考虑等下 M4。 \ No newline at end of file diff --git a/docs/md/road-map/maven-central.md b/docs/md/road-map/maven-central.md new file mode 100644 index 000000000..75ad2eee9 --- /dev/null +++ b/docs/md/road-map/maven-central.md @@ -0,0 +1,1001 @@ +--- +title: Maven Central +lock: no +--- + +# Maven Central 微服务包发布管理 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +诶,`你八股背的挺好,怎么实操这么差?`哎,`你算法刷的挺多,怎么编码这么烂?`啊,`你不是做过微服务,怎么不知道咋引包?`这是越来越多的面试官在招聘完的真实反馈,很多伙伴的经验不是来自于实践而是背诵! + +
+ +
+ +**有些东西没做过就是不知道!** + +所有那些背的东西,都是对结果的单一描述,而不是用大量的实践验证得出的结果,那么就会缺少各种可能的回答。以及对结果的各种论点/观点。 + +如,很多伙伴都提到做的是微服务项目,但对于基础的 Maven 在微服务中的使用,几乎是不知道的。那么就反向说明,你没有真的做过这些。所以你才不知道。 + +所以,如果你想真的学习下来这些经验,就要对这些知识点一个个的实践、验证、积累。在小傅哥的编程路书中以及积累了大量的知识内容,可以学习;[https://bugstack.cn/md/road-map/road-map.html](https://bugstack.cn/md/road-map/road-map.html) + +案例工程; +- [https://github.com/fuzhengwei/xfg-dev-tech-micro-service-a](https://github.com/fuzhengwei/xfg-dev-tech-micro-service-a) +- [https://github.com/fuzhengwei/xfg-dev-tech-micro-service-b](https://github.com/fuzhengwei/xfg-dev-tech-micro-service-b) + +> 接下来,我们再分享下关于微服务 Maven 发包的实践知识。 + +## 一、我为什么报错? + +“傅哥,这怎么报错了,我怎么引不到这个包?” + +
+ +
+ +对于这样的报错,我估计不少伙伴碰到了都有点慌。怎么我刚下载下来的工程,什么都做没做就报错了。这个包在仓库里也没有呀?之所以你会感觉很慌,是因为没有微服务项目的开发经验。 + +
+ +
+只要你碰到这样一个报错,那么在“作者/开发者/公司”的仓库中,一定会有这样一个其他的微服务,只要下载到自己本地,用 IntelliJ IDEA 打开,点击右侧的 maven install 就可以初始化包到你的本地 Maven 仓库了,这样你就能引入了。 + +那关于微服务的包的构建和使用有什么管理和规范吗?🤔 有的! + +## 二、微服务包管理 + +无论是我们个人开发还是在公司开发,都是有一套微服务包的开发和推送以及使用的规范。大家默认统一遵守,所以开发中才会非常协调的进行。 + +
+ +
+ +首先,公司中有很多业务,很多需求,这些东西不能都在一个工程里开发。那么势必就会拆分为多个微服务系统以及通用的技术解决方案组件。那么这些微服务和组件之间就会存在引入调用关系。尤其是一些大的互联网公司,更是会采用 RPC 的通信解决内部微服务之间的高效调用,而 RPC 通信不同于 HTTP 是需要引入接口定义包的,所以必然存在一个微服务中引入另外一个微服务的 Jar 也就是 POM 配置。 + +那么,如果是你个人验证阶段,是先在自己本地开发验证。这个时候不会发包到 maven 公司统一仓库或者中心仓库,那么就需要你自己本地在 A 服务中进行 install,把包发到个人的 maven 本地仓库文件夹中,之后你的 B 服务就可以引入使用了。 + +之后,站在整个公司的视角。你开发完的组件,不只是你使用,还有其他很多人使用。但跨部门,跨组的别人又不一定都有你的代码库权限,这个时候就需要把本地微服务的 Jar 发包到公司的 Maven 镜像库中。一般稍微大一点的公司都会有自己的 Maven 镜像库,如果公司比较小则会使用阿里云这类云厂商提供的的制品库,如;[https://packages.aliyun.com/](https://packages.aliyun.com/) 让公司的所有人 Maven setting 配置文件都配置这套制品库,这样就解决了一个人发包,其他人也能拉取到使用。 + +另外,如果你想你发的包,不只是你自己或公司里的人使用,那么就要把包发到 Maven 统一的中心仓库。[https://central.sonatype.com/publishing](https://central.sonatype.com/publishing) 这个过程稍微有点漫长,会持续 `4-12` 个小时才能完全同步好。 + +> 下文会提到如何发包到阿里云制品库和 Maven 中心仓库。 + +## 三、微服发包规范 + +工程发包会分为开发阶段的 snapshot 包和正式上线使用的 release 包,snapshot 包同一个版本发包后可以被替代,release 包,只能每次更换版本号。 + +```pom + + cn.bugstack + xfg-dev-tech-api + 0.0.0-SNAPSHOT + + + + cn.bugstack + xfg-dev-tech-api + 1.0 + +``` + +- 0.0.0-SNAPSHOT 以 SNAPSHOT 结尾是开发阶段包,都是 0.0.0-SNAPSHOT 命名。 +- release 包,只需要命名版本号即可。 + +另外这样的微服务包的版本号,在一个工程中每个模块都需要在发包的时候一起操作修改。如果是手动的修改就容易遗漏导致问题,所以这里我们要使用 Maven 提供的插件管理包。如; + +``` + + org.codehaus.mojo + versions-maven-plugin + 2.7 + +``` + +
+ +
+ +- 配置好 `versions-maven-plugin` 点击 `version:set` 就可以统一管理工程的版本号了。 + +## 四、阿里云效发包 - 研发组内用 + +### 1. 阿里云制品库 + +地址:[https://packages.aliyun.com/](https://packages.aliyun.com/) - 填写个人信息申请即可。 + +
+ +
+ +申请后,你会看到制品仓库配置,包括生产库和非生产库,他们主要负责给你提供 release、snapshot 发包和拉取。 + +### 2. 发包配置 + +分别进入 release、snapshot,都可以获得一份 Maven settings.xml 配置文件,把两份文件夹下载后可以找到 release、snapshot 的差异,合并成一份文件。这样你就可以在本地发 release、snapshot 包了。 + +
+ +
+ +**配置文件** + +
+ +
+ +**样例文件** + +```pom + + + + + /Users/fuzhengwei/Applications/apache-maven-3.8.4/repository + + + + mirror + central,jcenter,!2452122-snapshot-XqjwfN + mirror + https://maven.aliyun.com/nexus/content/groups/public + + + + + 2452122-snapshot-XqjwfN + 65b081c2242105ca211dd310 + 每个人会有自己的密码 + + + 2452122-release-dbuebF + 65b081c2242105ca211dd310 + 每个人会有自己的密码 + + + + + rdc + + + + + 2452122-snapshot-XqjwfN::default::https://packages.aliyun.com/65b081d4076e069afe3d2f50/maven/2452122-snapshot-xqjwfn + + + + 2452122-release-dbuebF::default::https://packages.aliyun.com/65b081d4076e069afe3d2f50/maven/2452122-release-dbuebf + + + + + + central + https://maven.aliyun.com/nexus/content/groups/public + + true + + + false + + + + snapshots + https://maven.aliyun.com/nexus/content/groups/public + + false + + + true + + + + 2452122-snapshot-XqjwfN + https://packages.aliyun.com/65b081d4076e069afe3d2f50/maven/2452122-snapshot-xqjwfn + + false + + + true + + + + 2452122-release-dbuebF + https://packages.aliyun.com/65b081d4076e069afe3d2f50/maven/2452122-release-dbuebf + + true + + + false + + + + + + central + https://maven.aliyun.com/nexus/content/groups/public + + true + + + false + + + + snapshots + https://maven.aliyun.com/nexus/content/groups/public + + false + + + true + + + + 2452122-snapshot-XqjwfN + https://packages.aliyun.com/65b081d4076e069afe3d2f50/maven/2452122-snapshot-xqjwfn + + false + + + true + + + + 2452122-release-dbuebF + https://packages.aliyun.com/65b081d4076e069afe3d2f50/maven/2452122-release-dbuebf + + true + + + false + + + + + + + rdc + + + +``` + +### 3. 本地发包 + +
+ +
+ +### 4. 查看仓库 + +
+ +
+ +- 发包后,可以到你的仓库查看是否已经将本地包发到了仓库中。 +- 到这里,你的整个研发组,都配置好来自 [https://packages.aliyun.com/](https://packages.aliyun.com/) Maven 配置下的下载链接,就可以统一使用这套包拉取到自己本来进行使用了。 + +## 五、中心仓库发包 - 全球研发用 + +官网:[https://central.sonatype.com/publishing](https://central.sonatype.com/publishing) +文档:[https://central.sonatype.org/publish/publish-portal-upload/](https://central.sonatype.org/publish/publish-portal-upload/) + +### 1. GPG 安装 + +我们需要一个GPG环境,用来对上传的文件进行加密和签名,保证你的jar包不被篡改。这也是发包到 Maven 中心仓库必须的操心。 + +>1991年,程序员Phil Zimmermann为了避开政府监视,开发了加密软件PGP。这个软件非常好用,迅速流传开来,成了许多程序员的必备工具。但是,它是商业软件,不能自由使用。所以,自由软件基金会决定,开发一个PGP的替代品,取名为GnuPG。这就是GPG的由来。 + +#### 1.1 windows + +1. 下载地址:[https://gpg4win.org/download.html](https://gpg4win.org/download.html) +2. 下载完成后直接安装即可,比较傻瓜式安装很简单,记得选中文(如果你英文硬也可以不选) +3. 生成密钥(可以使用命令行生成,也可以直接在操作界面生成) + 1. 文件>新建密钥对(Ctrl+N) -- 创建个人 OpenPGP 密钥对 + ![](https://bugstack.cn/assets/images/pic-content/2019/11/itstack-middleware-schedule-1.png) + 2. 填写个人信息姓名和邮箱 并点击到 新建 + ![](https://bugstack.cn/assets/images/pic-content/2019/11/itstack-middleware-schedule-2.png) + 3. 填写密钥密码 + ![](https://bugstack.cn/assets/images/pic-content/2019/11/itstack-middleware-schedule-3.png) + 4. 将公钥上传到目录服务{如果上传失败,则通过:设置(S)->配置Kleopatra(C),修改 OpenPGP密钥服务器为:hkp://keyserver.ubuntu.com:80} + ![](https://bugstack.cn/assets/images/pic-content/2019/11/itstack-middleware-schedule-4.png) + + +#### 1.2 mac + +1. 下载地址:[https://gpgtools.org/](https://gpgtools.org/) + +
+ +
+ +
+ +
+ +
+ +
+ +- 下载后安装,打开后。点新建,即可创建新的秘钥。记得点击上传公钥,如果没有点击后续也可以在秘钥上右键上传。 +- 注意新秘钥的名称(姓名)是后续配置到 setting.xml、工程 pom 内的名称。 + +### 2. 命名空间配置 + +
+ +
+ +Maven 中心仓库发包需要验证你的域名,确保全世界的唯一性。如果选择 github 登录,你会有一个默认配置的 NameSpace(io.github.fuzhengwei),这个东西的作用就是要和本地工程名 groupId 保持一致的。如工程是 cn.bugstack、plus.gaga、com.liergou,那么你在的 NameSpace 就需要配置一个这样的调过来的域名。 + +
+ +
+ +- 如图配置完添加验证即可,最后验证成功就可以使用了。 + +### 3. maven setting.xml + +```java + + + + + /Users/fuzhengwei/Applications/apache-maven-3.8.4/repository + + + + 填写,你的秘钥密码 + l4Mw+E3f + 你在 + + + + + + ossrh + + true + + + gpg + 填写,你的秘钥密码 + /Users/fuzhengwei/.gnupg/ + + + + + + ossrh + + + +```` + +
+ +
+ +- 注意,打开你的 maven setting.xml 配置文件,完善以上配置内容。 +- servers 下的 username、password,来自于 [https://central.sonatype.com/account](https://central.sonatype.com/account) +- 官网使用说明:[https://central.sonatype.org/publish/generate-portal-token/](https://central.sonatype.org/publish/generate-portal-token/) + +### 4. 手动上传 + +#### 4.1 上传要求 + +文档:[https://central.sonatype.org/publish/publish-portal-upload/](https://central.sonatype.org/publish/publish-portal-upload/) + +
+ +
+ +- 如文档上传要求,你需要把jar、pom、doc、sources 全部打包到 zip 包,同时每个文件的 asc、md5、sha1 也需要打包进来。 +- 这些文件也都是在旧版上传 maven 中央仓库的时候,所需提供的内容。 + +#### 4.2 项目配置 + +**源码**:[https://gitcode.net/KnowledgePlanet/road-map/xfg-frame-archetype-lite/-/tree/master/scaffold-lite](https://gitcode.net/KnowledgePlanet/road-map/xfg-frame-archetype-lite/-/tree/master/scaffold-lite) + +```pom + + + 4.0.0 + + + + + + + + cn.bugstack + xfg-dev-tech-api + 0.0.0-SNAPSHOT + + + 1.8 + UTF-8 + 1.8 + 1.8 + 2.9.0 + 2.0.6 + 3.2.0 + 3.2.1 + 1.6 + 1.10 + + + xfg-dev-tech-api + ce API . Copyright © 2023 bugstack虫洞栈 All rights reserved. 版权所有(C)小傅哥 https://github.com/fuzhengwei + https://github.com/fuzhengwei/xfg-dev-tech-micro-service-a + + + + Apache License + https://opensource.org/license/apache-2-0/ + repo + + + + + + Xiaofuge + Xiaofuge + 184172133@qq.com + https://github.com/fuzhengwei + xfg-dev-tech-micro-service-a + https://github.com/fuzhengwei/xfg-dev-tech-micro-service-a + + architect + developer + + Asia/Shanghai + + + + + scm:git:https://github.com/fuzhengwei/xfg-dev-tech-micro-service-a.git + scm:git:https://github.com/fuzhengwei/xfg-dev-tech-micro-service-a.git + HEAD + https://github.com/fuzhengwei/xfg-dev-tech-micro-service-a + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.0 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12.4 + + true + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + UTF-8 + true + UTF-8 + UTF-8 + + + + attach-javadocs + + jar + + + -Xdoclint:none + + /Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home/bin/javadoc + + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + true + false + release + deploy + + + + net.nicoulaj.maven.plugins + checksum-maven-plugin + ${maven-checksum-plugin.version} + + + create-checksums + + artifacts + + + + + + + + + + release + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + attach-javadocs + + jar + + + -Xdoclint:none + + /Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home/bin/javadoc + + + + + + + + + + + +``` + +- 注意,`cn.bugstack` 这里不能是继承。 +- maven-javadoc-plugin:生成 doc 文档。这里要注意,因为我们脚手架不是代码文件,没有doc的,所以要在工程中加一个任意类名文件。工程中小傅哥加了个 Api 类。 +- maven-source-plugin:生成 source 文件。 +- maven-gpg-plugin:是签名的加密文件,需要本地安装过 gpg 包。注意;`checksum-maven-plugin` 需要在 `maven-gpg-plugin` 执行,这样就不用做下面的手动 md5 逻辑了。 +- checksum-maven-plugin:生成 md5、sha1 文件,但这里不会对 pom 生成此文件,还需要单独命令处理。 +- `/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home/bin/javadoc` 配置你自己的 jdk 地址。 + +```shell +md5 ddd-scaffold-lite-1.0.pom > ddd-scaffold-lite-1.0.pom.md5 +shasum ddd-scaffold-lite-1.0.pom > ddd-scaffold-lite-1.0.pom.sha1 +``` + +- 检查生成后的文件,去掉不需要的内容。 + +#### 4.3 构建项目 + +##### 1. 首次构建 + +
+ +
+ +- 需要构建 Release 包。 + +##### 2. 执行命令 + +
+ +
+ +```java +md5 xfg-dev-tech-api-1.0.pom > xfg-dev-tech-api-1.0.pom.md5 +shasum xfg-dev-tech-api-1.0.pom > xfg-dev-tech-api-1.0.pom.sha1 +``` + +- 构建后,执行命令。增加新的校验文件。 + +##### 3. 打包文件 + +
+ +
+ +- 创建一个和构建一样路径的文件夹,mac/linux 操作命名;`mkdir -p cn/bugstack/xfg-dev-tech-api/1.0/` +- 之后把文件复制到文件夹中打一个zip包。 + +#### 6. 发包 + +##### 6.1 提交 + +
+ +
+ +- 提交你的压缩包。 + +##### 6.2 等待通过&发包 + +
+ +
+ +- 稍微等待,验证通过后可以点击 Publish 发布。 +- 预计4-12小时后会同步到 maven 中心仓库以及阿里云的仓库。 + +##### 6.3 发布效果 + +
+ +
+ +- 地址:[https://mvnrepository.com/search?q=cn.bugstack](https://mvnrepository.com/search?q=cn.bugstack) + +### 5. 自动发包(推荐) + +#### 5.1 pom 配置 + +为你的工程配置 pom; + +```java + + + 4.0.0 + + + cn.bugstack + xfg-dev-tech-micro-service-a + 1.0.0 + + + xfg-dev-tech-api + + + 1.8 + UTF-8 + 1.8 + 1.8 + 2.9.0 + 2.0.6 + 3.2.0 + 3.2.1 + 1.6 + 1.10 + + + xfg-dev-tech-api + ce API . Copyright © 2023 bugstack虫洞栈 All rights reserved. 版权所有(C)小傅哥 https://github.com/fuzhengwei + https://github.com/fuzhengwei/xfg-dev-tech-micro-service-a + + + + Apache License + https://opensource.org/license/apache-2-0/ + repo + + + + + + Xiaofuge + Xiaofuge + 184172133@qq.com + https://github.com/fuzhengwei + xfg-dev-tech-micro-service-a + https://github.com/fuzhengwei/xfg-dev-tech-micro-service-a + + architect + developer + + Asia/Shanghai + + + + + scm:git:https://github.com/fuzhengwei/xfg-dev-tech-micro-service-a.git + scm:git:https://github.com/fuzhengwei/xfg-dev-tech-micro-service-a.git + HEAD + https://github.com/fuzhengwei/xfg-dev-tech-micro-service-a + + + + + com.alibaba + fastjson + 2.0.28 + + + org.apache.commons + commons-lang3 + 3.9 + + + org.slf4j + slf4j-api + ${slf4j.version} + + + + + + + src/main/resources + true + + **/** + + + + + + src/test/resources + true + + **/** + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.2.0 + + UTF-8 + + + src/main/resources + false + + + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + UTF-8 + UTF-8 + UTF-8 + -Xdoclint:none + + + + attach-javadocs + package + + jar + + + -Xdoclint:none + + ${java.home}${file.separator}..${file.separator}bin${file.separator}javadoc + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + + shade + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + ossrh + + + + sign-artifacts + verify + + sign + + + + + + + net.nicoulaj.maven.plugins + checksum-maven-plugin + 1.10 + + + create-checksums + + artifacts + + + + MD5 + SHA-1 + + true + + + + create-pom-checksums + + files + + + + + ${project.build.directory} + + *.pom + + + + + MD5 + SHA-1 + + + + + + + + + org.sonatype.central + central-publishing-maven-plugin + 0.4.0 + true + + ossrh + true + true + + + + + + + +``` + +##### Maven 插件 + +项目使用了多个 Maven 插件来支持构建、打包和发布流程: +1. maven-resources-plugin (v3.2.0) + - 用于资源文件处理,确保 UTF-8 编码 +2. maven-source-plugin (v2.2.1) + - 生成源码 jar 包,便于开发者查看源码 +3. maven-javadoc-plugin (v2.9.1) + - 生成 JavaDoc 文档 + - 配置了 UTF-8 编码 + - 禁用了文档检查 (-Xdoclint:none) + 4 . maven-shade-plugin (v3.2.4) + - 用于创建可执行 jar 包 + - 配置了过滤器排除签名文件 +5. maven-gpg-plugin (v1.5) + - 用于对构建产物进行 GPG 签名 + - 指定了签名密钥名称: ossrh +6. checksum-maven-plugin (v1.10) + - 生成构建产物的校验和 (MD5, SHA-1) + - 为 jar 包和 pom 文件创建校验和 +7. central-publishing-maven-plugin (v0.4.0) + - 用于将项目发布到 Maven Central 仓库 + - 配置了自动发布功能 + +##### 发布配置 + +项目配置了发布到 Maven Central 仓库的相关信息: + +- 发布服务 ID : ossrh +- 认证方式 : 令牌认证 (tokenAuth=true) +- 自动发布 : 启用 (autoPublish=true) + +文档:[https://central.sonatype.org/publish/publish-portal-maven/#wait-for-publishing](https://central.sonatype.org/publish/publish-portal-maven/#wait-for-publishing) + +>每个插件和配置项都为项目的构建、发布和管理提供了特定的功能支持。 + +#### 5.2 发布 + +##### 点击发布 + +
+ +
+ +##### 查看结果 + +
+ +
+ +>发布完成后,需要1-3天,才能同步到 [https://mvnrepository.com/](https://mvnrepository.com/) + diff --git a/docs/md/road-map/nas.md b/docs/md/road-map/nas.md new file mode 100644 index 000000000..15a9e6b2e --- /dev/null +++ b/docs/md/road-map/nas.md @@ -0,0 +1,126 @@ +--- +title: Nas +lock: need +--- + +# Nas - 这是我犹豫了很久,才买的设备! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在这之前我犹豫🦑了好久,一台不错的 Nas 四五千块,买这个东西能帮助我啥呢 🤔?但后来发现,这台 2c8g 双盘位 4TB Nas,等同于个人拥有了一台永久可用的,软件丰富的,具备远程访问能力的,终身 Linux 服务器。 + +
+ +
+ +**谁更适合买一台 Nas?** + +虽然 Nas 确实很不错,但也不是所有人都有诉求,也不用都买很高配置很贵的。那谁有 Nas 诉求呢?家里有娃的,有大量的照片、视频、文件,需要家人一起存储使用。另外是喜欢看4k蓝光电影,可以用 Nas 搭建一套家庭影院。很多 Nas 也是主打这些功能。 + +但其实我买 Nas,有上面的功能诉求,但还有作为程序员👨🏻‍💻的编程诉求。我希望能在这台 Nas 上安装 Docker 部署环境,并能通过 SSH 客户端,以使用 Linux 的方式,连接 Nas 完成项目的构建、镜像打包和部署。 + +>嘿嘿,使用起来,它还真可以!不过,别买错 Nas,有些并不支持! + +## 一、Nas 是啥? + +NAS(Network Attached Storage,网络附加存储)是一种通过标准的网络拓扑结构(例如以太网)连接到一群计算机上的存储设备。它是一种具有很大存储容量的电脑外敷设备,通过集线器或交换机直接连在网络上,提供跨平台文件共享功能。 + +更简单的来讲,你就把它当做一台部署在家里的 Linux 服务器就好,只不过它的体积不大,但有很大的硬盘容量。所有开通了权限的用户,都可以使用这台共享服务器。并且它提供了很多的软件资源和网络访问服务。 + +## 二、买的哪家的 Nas? + +市面的 Nas 有很多,如;群晖、威联通、绿联、极空间、华为。它们到没有绝对的谁家好,只不过有会一些目标人群的不同。有一些网上的对比,可以参考; + +| 品牌 | 优势 | 劣势 | +|----------|----------------------------------------------------------------------|----------------------------------------------------------------------| +| 群晖 | - 软件生态丰富,DSM系统用户友好 | - 价格较高 | +| | - 稳定性和可靠性强 | - 硬件规格在同价位上可能不如竞争对手 | +| | - 拥有庞大的用户社区和丰富的在线资源 | | +| | - 提供多种数据保护和备份解决方案 | | +| 威联通 | - 硬件性能强,提供更高的硬件规格 | - 软件复杂性较高,新手用户可能较难上手 | +| | - 支持虚拟化、容器化应用和多媒体功能 | - 某些情况下软件更新可能导致系统不稳定 | +| | - 提供丰富的扩展选项 | | +| 绿联 | - 价格实惠,适合预算有限的用户 | - 功能较为基础,适合简单存储需求 | +| | - 简单易用,适合家庭用户和小型办公室 | - 在NAS市场的知名度和用户基础不如群晖和威联通 | +| 极空间 | - 性价比高,适合中小企业和个人用户 | - 软件生态和用户界面不如群晖和威联通成熟 | +| | - 提供较为合理的硬件配置 | - 相对较小的用户社区和技术支持资源 | + + +我买的是一台 `群晖 DS723+` 并配了`8G内存` + `2*2TB`硬盘互备,因为咱们要做 Docker 安装各类软件,内存大一些更好。选择群晖主要就是想着这东西资源丰富,可以像使用 Linux 服务器一样使用 Nas 满足开发和存储需求。 + +
+ +
+ +> 用了群晖 Nas 有5个月了,越用越爽。电脑里的东西基本都搬到群晖了,电脑只成为一个工具了,不在搞那么多存储。 + +## 三、Nas 的编程用途 + +群晖 Nas 提供了 群晖管家 APP,只要开启 QuickConnect,无论在家内网还是外网都可以访问和管理 Nas。另外群晖还提供了专门做照片和视频同步管理的 Photos Mobile APP 你可以直接下载使用。 + +它所有的这些东西,只要对照提供的说明书都可以下载使用。难度极低,很好上手。这里小傅哥主要给大家分享下编程的用途。 + +这里首先,对于使用 Windows 的小伙伴,如果你有台 Nas,就不需要本地做那么多让 Windows 兼容 Linux 的事情了。你可以直接在这个上面安装提供的 Docker 套件,并完成对应用程序的打包、构建以及 PUSH 镜像到 DockerHub。 + +另外就是很多小伙伴的电脑配置不高,容量也不大,可以考虑购买 Nas 分摊一部分本身电脑的压力。就像我,如果开启多个 IntelliJ IDEA,在开启 Docker 提供分布式软件环境、在搞一堆网页,以及开启视频录制。这个时候就会非常卡顿了。所以我搞了台 Nas 来解决这个事情。 + +### 1. 有很多编程软件 + +群晖 Nas 提供了非常多的配套软件,适合于不同场景诉求的伙伴使用。所以很多买群晖的伙伴都说,是买软件送设备。嘿嘿,不过我更喜欢这部分编程相关的,尤其是这个 Docker、Git Server,嗖的就安装好。 + +
+ +
+ +- Nas 还支持配置定时开机关机、休眠,这样会比较省电,也不用一直在那打开着。 +- 另外可以自建frp,让自己的nas服务可以直接被公网访问。一年¥48 2c2g 服务器即可。[https://618.gaga.plus](https://618.gaga.plus) 专属地址。[frp](https://bugstack.cn/md/road-map/frp.html) 教程在 bugstack.cn - 路书中。 + +### 2. Docker 使用 + +
+ +
+ +
+ +
+ +- 你可以在提供的操作界面配置 Docker Compose,完成项目文件的配置和启动。之后的体验就和正常 Linux 安装 Docker 部署软件一样了。 +- 不过我通常把这里都只是作为配置后的操作界面,配置的操作,我会在用SSH工具直接链接到Nas上。 + +### 3. SSH 连接 Nas + +因为本身 Nas 也是一台 Linux 服务器,所以可以直接用 SSH 连接使用。推荐使用 [https://termius.com/](https://termius.com/) 工具链接,很好用。 + +- 账号:你的 Nas 登录账号 +- 密码:你的 Nas 登录密码 + +
+ +
+ +登录以后,你就可以像使用 Linux 一样操作了,不过大部分执行类命令,要加上 sudo,比如 `sudo docker images` + +### 4. 构建项目 + +有了 Nas 有个很大的好处就是,你可以本地直接当 Nas 的硬盘是本地的一个文件夹,直接打开就操作。里面的文件直接复制粘贴进去或者拿出来就可以。 + +
+ +
+ +通过 IntelliJ IDEA 直接打开 Nas 中的项目即可,之后你可以用它上面的 Docker 对项目进行构建了。如下; + +
+ +
+ +- build.sh 中执行的就是 docker 命令;`docker build -t system/s-pay-mall-mvc-app:1.0 -f ./Dockerfile .` +- 构建完,就可以部署项目了。Linux 上怎么用,这里你就怎么用。 + +> 当然 Nas 还有很多其他的用途,喜欢折腾的还可以搭建一些你需要的。 diff --git a/docs/md/road-map/nginx.md b/docs/md/road-map/nginx.md index e4e8d874d..35ee7c714 100644 --- a/docs/md/road-map/nginx.md +++ b/docs/md/road-map/nginx.md @@ -1,5 +1,5 @@ --- -title: Nginx +title: Nginx 环境配置 lock: need --- @@ -130,9 +130,10 @@ nginx ### 4.1 创建证书 -SSL 免费的证书,一种是 [freessl - 支持自动续期](https://bugstack.cn/md/road-map/ssl.html) 另外各个云服务厂商都有提供,可以自己申请。这里以阿里云举例; +SSL 免费的证书,一种是 [ssl - 支持自动续期](https://bugstack.cn/md/road-map/ssl-httpsok.html) 另外各个云服务厂商都有提供,可以自己申请。这里以阿里云/京东云举例; -阿里云免费域名证书:[https://yundun.console.aliyun.com/?p=cas#/certExtend/free/cn-hangzhou](https://yundun.console.aliyun.com/?p=cas#/certExtend/free/cn-hangzhou) +- 阿里云免费域名证书:[https://yundun.console.aliyun.com/?p=cas#/certExtend/free/cn-hangzhou](https://yundun.console.aliyun.com/?p=cas#/certExtend/free/cn-hangzhou) +- 京东云免费域名证书:[https://certificate-console.jdcloud.com/jsecssl/create?fastConfig=false&certBrand=TrustAsia&certType=domainType&protectionType=DV-1&gDomainCount=0](https://certificate-console.jdcloud.com/jsecssl/create?fastConfig=false&certBrand=TrustAsia&certType=domainType&protectionType=DV-1&gDomainCount=0) - 选择 TrustAsia 单域名 3个月 0元 ![](https://bugstack.cn/images/article/devops/dev-ops-nginx-230418-02.png) @@ -293,18 +294,18 @@ docker run \ ![](https://bugstack.cn/images/article/devops/dev-ops-nginx-230418-04.png) -## 五、OpenAI 访问 +## 五、重定向 -### 1. 重定向 +### 1. default.conf 在 default.conf 中添加如下配置后重启 Nginx 即可; ```shell location /d5fe/ { rewrite ^/d5fe/(.*)$ /$1 break; - proxy_pass https://api.openai.com; + proxy_pass https://api.x.com; proxy_ssl_server_name on; - proxy_set_header Host api.openai.com; + proxy_set_header Host api.x.com; proxy_set_header Connection ''; proxy_http_version 1.1; chunked_transfer_encoding off; @@ -351,9 +352,9 @@ server { location /abc/ { auth_request /auth; rewrite ^/abc/(.*)$ /$1 break; - proxy_pass https://api.openai.com; + proxy_pass https://api.x.com; proxy_ssl_server_name on; - proxy_set_header Host api.openai.com; + proxy_set_header Host api.x.com; proxy_set_header Connection ''; proxy_http_version 1.1; chunked_transfer_encoding off; diff --git a/docs/md/road-map/ollama.md b/docs/md/road-map/ollama.md new file mode 100644 index 000000000..753ad3832 --- /dev/null +++ b/docs/md/road-map/ollama.md @@ -0,0 +1,242 @@ +--- +title: Nas + Ollama + DeepSeek +lock: need +--- + +# 【教程】在Nas上部署Ollama,搭建DeepSeek、配置PageAssist AI、提供API调用 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在 OpenAI 刚兴起的时候,一个非算法的外行Java,想在个人电脑上部署个 GPT2 都费老鼻子👃🏻劲了。现在 DeepSeek 开源以后,拿这 Ollama 直接就能部署,兼职比程序员👨🏻‍💻安装 Java JDK 都容易。😂Java 二狗,也能过上算法的日子。 + +
+ +
+ +**自己部署的 DeepSeek 功能还挺多!** + +自己基于 Ollama 部署的一套 DeepSeek,可以提供独属于你自己一套的 AI,并且可以做图片识别、联网、知识库。而且如果你是一个需要使用 DeepSeek 接口做开发的码农,还可以直接使用自己提供的这套 API 做开发。 + +接下来,小傅哥就带着你使用 Docker 完成 Ollama 的安装和 DeepSeek 模型的部署。Docker 可以在任何环境执行,小傅哥自己是放到 Nas 环境里部署。部署完成后,安装谷歌浏览器插件 Page Assist 使用 Ollama 部署的 DeepSeek 模型。 + +## 一、部署脚本 + +小傅哥这里为你提供了执行安装的脚本,以及测试API的方法; + +
+ +
+ +- 代码:[https://github.com/fuzhengwei/xfg-dev-tech-ollama](https://github.com/fuzhengwei/xfg-dev-tech-ollama) +- dev-ops,提供了 docker-compose.yml 部署 ollama 脚本。这个文件你可以放到任何安装了 Docker 的环境里执行。 +- src 代码,提供的是测试这套 Ollama 下的大模型。除了你本节部署的 DeepSeek,以后部署其他的也可以这样使用。 + +## 二、部署安装 + +### 1. 执行脚本 + +
+ +
+ +```java +# docker compose -f docker-compose.yml up -d +version: '3.8' +services: + ollama: +# image: ollama/ollama:0.5.10 + image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/ollama:0.5.10 + container_name: ollama + restart: unless-stopped + ports: + - "11434:11434" +``` + +- 原始镜像 `image: ollama/ollama:0.5.10` 代理镜像 `registry.cn-hangzhou.aliyuncs.com/xfg-studio/ollama:0.5.10` +- Nas 可以通过界面操作执行启动,如果你是 Linux 服务器,安装了 Docker,可以使用命令执行 `docker compose -f docker-compose.yml up -d` + +### 2. 模型说明 - DeepSeek + +| 模型 | 内存 | 存储 | 特点 | +| ---------------- | ---- | ------ | ---------------------------------------------------- | +| deepseek-r1:1.5b | 8G | 12GB | 轻量级模型,运行速度快,性能有限。 | +| deepseek-r1:7b | 16G | 80GB | 平衡型模型,性能较好,硬件需求适中。 | +| deepseek-r1:14b | 32G | 200GB | 高性能模型,擅长复杂任务(数学推理,代码生成) | +| deepseek-r1:32b | 64G | 320GB | 专业级模型,性能强大,适合高精度任务 | +| deepseek-r1:70b | 128G | 500GB+ | 顶级模型,性能最强,适合大规模计算和高复杂任务执行。 | + +- 这里小傅哥选择的是 1.5b 模型,你可以按照自己的机器配置进行选择。 + +### 3. 模型安装 - DeepSeek + +你需要进入到 Ollama 管理后台执行安装模型脚本; + +
+ +
+ +```java +# 拉取模型 +ollama pull deepseek-r1:1.5b + +# 运行模型 +ollama run deepseek-r1:1.5b + +# 联网模型 +ollama pull nomic-embed-text +``` + +- 命令:`docker exec -it ollama /bin/bash` 也可以进入控制台 +- 首先,安装完成后,可以执行运行之后在后台进行对话。对话完成需要关闭的话,运行 Ctrl + D 关闭。 +- 之后,安装联网模型。这个过程要持续一会。另外不要一下就选很大的模型,怕你扛不住。 + +## 三、配置插件 + +官网:[https://github.com/n4ze3m/page-assist](https://github.com/n4ze3m/page-assist) + +### 1. 搜索安装 + +为了更方便的使用 DeepSeek 模型,这里可以在谷歌浏览器安装一个 Page Assist 插件。 + +
+ +
+ +- 点击安装 Page Assist 插件 + +### 2. 链接地址 + +
+ +
+ +### 3. 设置中文 + +
+ +
+ +### 4. 配置知识库 - RAG + +
+ +
+ +### 5. 添加知识库 - PDF/MD + +
+ +
+ +## 四、对话使用 + +### 1. ai对话 + +
+ +
+ +- 你可以选择模型、联网、图片识别和自己设定的知识库。 + +### 2. 页面对话 + +
+ +
+ +- 你可以在插件上右键,之后就可以与你需要的另外的网页进行对话。理解网页内容做解答。 + +## 五、API 对接 + +### 1. curl 接口 + +```java +curl http://192.168.1.109:11434/api/generate \ + -H "Content-Type: application/json" \ + -d '{ + "model": "deepseek-r1:1.5b", + "prompt": "1+1", + "stream": false + }' + +``` + +- 这是请求 Ollama DeepSeek 模型的 curl 操作。 + +### 2. 代码请求 + +#### 2.1 配置接口 + +```java +@Configuration +public class OllamaConfig { + + @Bean + public OllamaApi ollamaApi() { + Retrofit retrofit = new Retrofit.Builder() + .baseUrl("http://192.168.1.109:11434") + .addConverterFactory(JacksonConverterFactory.create()).build(); + + return retrofit.create(OllamaApi.class); + } + + public interface OllamaApi { + @POST("/api/generate") + Call generate(@Body OllamaRequest request); + } + + @Data + @AllArgsConstructor + @NoArgsConstructor + public static class OllamaRequest { + private String model; + private String prompt; + private boolean stream; + } + + // ... 省略部分代码 +} +``` + +- 这里我们使用 retrofit2 框架封装对模型API的访问。 + +#### 2.2 访问接口 + +```java +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest +public class OllamaTest { + + @Resource + private OllamaConfig.OllamaApi api; + + @Test + public void test_chat() throws IOException { + OllamaConfig.OllamaRequest request = new OllamaConfig.OllamaRequest( + "deepseek-r1:1.5b", + "1+1", + false + ); + + Call generate = api.generate(request); + Response execute = generate.execute(); + OllamaConfig.OllamaResponse response = execute.body(); + + log.info("测试结果:{}", JSON.toJSONString(response.getResponse())); + } + +} +``` + +
+ +
+ +- 如图,运行结果可以看到调用API没问题啦。 +- 另外,SpringAI 也提供了访问 ollama 的 Jar,也可以使用。后续会提供这块的内容。 \ No newline at end of file diff --git a/docs/md/road-map/openclaw.md b/docs/md/road-map/openclaw.md new file mode 100644 index 000000000..85fc8b974 --- /dev/null +++ b/docs/md/road-map/openclaw.md @@ -0,0 +1,347 @@ +--- +title: OpenClaw +lock: need +--- + +# 🦞OpenClaw,你是不还没有安装上?这个中文版,可以试试! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +🦞OpenClaw,大龙虾,看着挺复杂,其实一点也不简单。都火成这德行了,但也还是有很多伙伴在安装这一块就挂壁了。想体验呀,咋整? + +
+ +
+ +**怎么理解 OpenClaw 🦞** + +OpenClaw 是一款开源 AI 助手,不到2个月时间 [Github](https://github.com/openclaw/openclaw) 点赞量已经超过 170k Star ⭐️,它的出现为我们提供了更俏的思路使用 LLM 大模型。从24年底,定义了 MCP 协议,25年爆发了 Ai Agent 的落地,随后出现 [GLM AutoPhone](https://bugstack.cn/md/algorithm/model/autoglm-phone-agent.html) 控制手机,现在又来了大龙虾 OpenClaw 控制电脑。 + +你可以把 OpenClaw 理解为一个从你到电脑设备,需要敲键盘的过程,**设计了一个中间网关层**。你的指令可以通过各类 APP/Web 对话的方式,下发给 OpenClaw 完成电脑的一些列操作。如;`帮我安装个Docker`、`在Docker中部署下Redis`、`告诉我现在运行状况和剩余可用资源`等等操作。 + +
+ +
+ +综上,这让我们离`数字员工`又近了一步,后续可以拷贝个人工作技能到 skills 编写,如一些高频重复的场景,对现存系统运行的巡检,对运营类数据的排查,对活动经营情况的分析等。都可以被制作为 skills 让 OpenClaw 使用。 + +接下来,小傅哥就带着大家安装下 OpenClaw + 飞书配置,这套组合还是蛮好用的。 + +## 一、安装介绍 + +### 1. 软件 + +官网:[https://openclaw.ai/](https://openclaw.ai/) +源码:[https://github.com/openclaw/openclaw](https://github.com/openclaw/openclaw) + +中文社区: +- [https://clawd.org.cn/](https://clawd.org.cn/) - `新人伙伴比较推荐实用这个,全是中文提示,安装起来更友好。` +- [https://openclaw.qt.cool/](https://openclaw.qt.cool/) +- [https://1panel.cn](https://1panel.cn/) + +> 除了官网的 OpenClaw 资源,还有不少中文社区,对 OpenClaw 做了镜像和汉化的处理。安装方式也都一样,小白伙伴也可以体验下,全是中文对小白更友好。另外,这部分汉化是基于 openclaw 源码来做的,如果你有一些预安装诉求,以及汉化或者有自身公司想做些扩展也可以基于源码 fork 来改造。 + +### 2. 环境 + +- nodejs 22+ (不少安装包里会提供检测和安装)[https://nodejs.org/zh-cn/download](https://nodejs.org/zh-cn/download) +- 2c4g 云服务器/本地电脑 [https://618.gaga.plus](https://618.gaga.plus) - `推荐买1年送3个月的` + Ubuntu 24 系统。 +- 环境初始化脚本 [https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install](https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install) - `执行 sudo ./openclaw.sh 会帮你在云服务器安装 nodejs 22+` +- 镜像资源 `--registry https://registry.npmmirror.com` 如使用 `sudo npm install -g openclaw@latest --registry https://registry.npmmirror.com` + +### 3. 资源 + +- GLM ApiKey:[https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys](https://www.bigmodel.cn/glm-coding?ic=KFLKGANUMO) - 可以换账号新注册下,获取2000万token,可以提前申请好,复制到自己的文档里(你可能会失败好多次,反复使用)。 +- 飞书:[https://open.feishu.cn/app](https://open.feishu.cn/app) - `企业自建应用(下载个桌面版更好用)`,先发布一次(拿到App ID、App Secret)让 OpenClaw 对接上,之后再飞书机器人配置上**事件配置**,之后在发布一次应用。这样就建立起链接了,下文教程有详细处理过程。 + +## 二、部署介绍 + +### 1. 部署流程 + +OpenClaw 的安装过程中,会涉及一些列命令的使用,我把这些放到一个图里,方便大家理解; + +
+ +
+ +- 首先,关于安装可以使用 curl 向导式一次安装,也可以使用 npm 安装软件后,在启动配置向导。在 [xfg-dev-tech-docker-install](https://gitcode.com/Yao__Shun__Yu/xfg-dev-tech-docker-install) 一键安装脚本中,提供了 `sudo ./openclaw.sh` 安装脚本,附带的会帮助你完成 nodejs 22+ 的检测和安装,以及飞书组件的提示,会简化一些你的操作。 +- 然后,在执行 `sudo openclaw onboard` 运行向导后,会告诉你这个软件的安全提示,你可以通过`←` `→`选择 yes 安装即可。再往后,会进行模型的选择,这里支持好多模型,本案例使用的 [glm apikey](https://www.bigmodel.cn/glm-coding?ic=KFLKGANUMO) +- 之后,一系列选择后(不分可以跳过),包括通信渠道(飞书)也可以先跳过,即可完成安装。安装后可以通过 `sudo openclaw gateway` 启动网关。这样 openclaw 也就正式启动起来了。 +- 再后,安装飞书插件 `sudo openclaw plugins install @m1heng-clawd/feishu --registry https://registry.npmmirror.com` 这东西的目的是让 openclaw 可以对接上飞书。 + +### 2. 常用命令 + +| 命令 | 作用 | 备注 / 参数 | +| :----------------------------------------------------------- | :---------------------- | :-------------------------------------------- | +| `npm install -g openclaw@latest --registry https://registry.npmmirror.com` | 安装 openclaw | | +| `openclaw onboard` | 安装引导 | | +| `openclaw status` | 查看 Gateway 状态 | 检查网关是否可达及运行状况 | +| `openclaw health` | 健康检查 | 主要检测 core 运行和依赖情况 | +| `openclaw doctor` | 综合诊断与修复建议 | 可配合 `--yes` / `--non-interactive` 自动执行 | +| `openclaw configure` | 交互式配置向导 | 用于设置模型、通道、凭据等 | +| `openclaw config get ` | 获取配置值 | 指定路径提取配置 | +| `openclaw config set ` | 设置配置项 | 支持 JSON5/raw 文本 | +| `openclaw config unset ` | 清除配置项 | 移除单个键值 | +| `openclaw channels list` | 列出已登录通道 | 可观察 WhatsApp/Telegram 等登录状态 | +| `openclaw channels login` | 登录新的通道账号 | 用于扫描/授权链接 | +| `openclaw skills list` | 列出技能 | 查看可用/已安装的技能 | +| `openclaw skills info ` | 技能详情 | 观察某项技能参数或版本 | +| `openclaw plugins list` | 列出插件 | 查看已安装插件 | +| `openclaw plugins install ` | 安装插件 | 例如 @openclaw/voice-call | +| `openclaw plugins enable ` | 启用插件 | 之后通常需要重启网关 | +| `openclaw logs --follow` | 显示日志 | `--json / --plain / --limit` 等组合使用 | +| `openclaw gateway` | 启动 Gateway 网关 | | +| `openclaw gateway install` | 安装系统服务 | 根据平台注册 Gateway 守护进程 | +| `openclaw gateway start` | 启动 Gateway 网关 | 系统服务模式下启动 | +| `openclaw gateway stop` | 停止 Gateway 网关 | 同上 | +| `openclaw gateway restart` | 重启 Gateway 网关 | 适合配置变更后应用 | +| `openclaw gateway status` | 网关系统服务状态 | 不同于 `openclaw status`,会探测服务单元 | +| `openclaw uninstall` | 卸载 Gateway 服务及数据 | 官方推荐使用 | +| `openclaw uninstall --all --yes --non-interactive` | 全自动卸载 | 包含状态、workspace、插件等 | +| `openclaw uninstall --state` | 删除状态文件 | 不删除 workspace/CLI | +| `openclaw uninstall --workspace` | 删除工作区 | 移除 agent/workspace 文件 | +| `openclaw uninstall --service` | 仅卸载服务 | 不删除数据 | +| `openclaw uninstall --dry-run` | 模拟卸载 | 显示结果但不实际执行 | + +## 三、部署操作 + +### 1. 创建飞书 + +
+ +
+ +#### 1.1 创建应用 + +
+ +
+ +**批量导入,权限列表** + +```java +{ + "scopes": { + "tenant": [ + "aily:file:read", + "aily:file:write", + "application:application.app_message_stats.overview:readonly", + "application:application:self_manage", + "application:bot.menu:write", + "cardkit:card:write", + "contact:contact.base:readonly", + "contact:user.employee_id:readonly", + "corehr:file:download", + "docs:document.content:read", + "event:ip_list", + "im:chat", + "im:chat.access_event.bot_p2p_chat:read", + "im:chat.members:bot_access", + "im:message", + "im:message.group_at_msg:readonly", + "im:message.group_msg", + "im:message.p2p_msg:readonly", + "im:message:readonly", + "im:message:send_as_bot", + "im:resource", + "sheets:spreadsheet", + "wiki:wiki:readonly" + ], + "user": [ + "aily:file:read", + "aily:file:write", + "im:chat.access_event.bot_p2p_chat:read" + ] + } +} +``` + +- 创建应用后,你可以获得到应用凭证(appid、appsecret)这个信息是用于 openclaw 对接使用的。 + +#### 1.2 发布应用 + +
+ +
+ +- 创建应用后,点击发布应用。这样你创建的应用才是有效的。 + +#### 1.3 事件配置(机器人)- openclaw 配置之前 + +
+ +
+ +- 飞书应用创建后,还需要配置机器人。但这会配置也是失败的,因为 openclaw 还没有关联上来。 +- 这里需要在 openclaw 配置飞书通信渠道,之后重启 openclaw 网关,这里点击保存并配置权限(`接收消息`、`通讯录基本信息`),点击确认开通权限。在发布一个新应用,再和飞书机器人对话就可以使用了。 + +### 2. 安装应用(openclaw) + +#### 2.1 执行脚本(含带引导) + +```java +curl -fsSL https://openclaw.ai/install.sh | sudo bash -s -- --registry https://registry.npmmirror.com +``` + +- openclaw 官网版 + +```java +curl -fsSL https://clawd.org.cn/install.sh | sudo bash -s -- --registry https://registry.npmmirror.com +``` + +- openclaw-cn 中文社区版,适合新人伙伴使用。熟练后,使用官网版即可。他们操作的方式是一样的。 +- 安装后的使用差异,一个是 `sudo openclaw config` 一个是 `sudo openclaw-cn config` + +#### 2.2 引导配置 + +```java +sudo npm install -g openclaw@latest --registry https://registry.npmmirror.com +sudo npm install -g openclaw-cn@latest --registry https://registry.npmmirror.com + +# 运行向导 +sudo openclaw onboard +sudo openclaw-cn onboard +``` + +- 注意 `-cn` 为中文版,如果你不是执行的 curl 一键安装版本,是采用了 安装 `openclaw@latest` 程序,那么需要自己执行引导配置。 + +##### 2.2.1 安全提示 + +
+ +
+ +##### 2.2.2 配置方式 + +
+ +
+ +##### 2.2.3 模型配置 + +
+ +
+ +
+ +
+ +##### 2.2.4 通信通道(飞书) + +**选择渠道** + +
+ +
+ +**安装插件** + +
+ +
+ +- 如果未安装过飞书插件,可以选择安装,也可以跳过后,后续在安装。 +- 单独安装插件 `sudo openclaw-cn plugins install @m1heng-clawd/feishu` + +**配置凭证** + +
+ +
+ +- 把你的应用凭证,配置到 openclaw 应用程序里。之后继续回车。 +- 注意,一会要会到飞书页面,配置事件关联到 openclaw 上。 + +##### 2.2.5 技能配置 + +
+ +
+ +##### 2.2.6 部署完成 + +
+ +
+ +
+ +
+ +```java +ubuntu@VM-0-2-ubuntu:~$ sudo openclaw-cn gateway +``` + +- 配置完成后,要启动下网关。能看到以上信息,表示运行没问题了。 +- 现在要到 3.1 接着配置飞书。 + +### 3. 配置飞书 + +#### 3.1 事件配置(机器人) + +
+ +
+ +- 注意,完成 2.2.6 步骤后,再回来操作。 +- openclaw 关联上飞书以后,点击**添加事件**,以及添加上相关权限。完成后,会提示你发布一个新应用。 + +#### 3.2 发布应用 + +
+ +
+ +- 点击发布应用,版本号 +1 + +#### 3.3 打开应用 + +
+ +
+ +- 这会对话飞书,会提示执行一个命令,类似于验证签名。 +- 命令 `sudo openclaw-cn pairing approve feishu KF2BRAXW` + +#### 3.4 验证前面(+重启网关) + +
+ +
+ +```java +ubuntu@VM-0-2-ubuntu:~$ sudo openclaw-cn pairing approve feishu KF2BRAXW + +🦞 Clawdbot-CN 0.1.4 (b161cdd) — 唯一不能在你的私信上训练的机器人Mark。 + +Approved feishu sender ou_762197513d3d1cb907f4c0d2ed3c3b2b. +ubuntu@VM-0-2-ubuntu:~$ sudo openclaw-cn gateway + +🦞 Clawdbot-CN 0.1.4 (b161cdd) — 我不是魔法——我只是在重试和应对策略上极其执着。 + +06:39:38 [canvas] host mounted at http://127.0.0.1:18789/__clawdbot__/canvas/ (root /root/clawd/canvas) +06:39:38 [heartbeat] started +06:39:38 [gateway] agent model: zai/glm-4.7 +06:39:38 [gateway] listening on ws://127.0.0.1:18789 (PID 20687) +06:39:38 [gateway] listening on ws://[::1]:18789 +06:39:38 [gateway] log file: /tmp/clawdbot/clawdbot-2026-02-08.log +06:39:38 [browser/server] Browser control listening on http://127.0.0.1:18791/ +06:39:38 [feishu] [default] starting Feishu provider (你的应用名称) +06:39:38 [info]: [ 'event-dispatch is ready' ] +``` + +- 如上方式,执行你的签名验证,并重启网关。 +- 到这,就配置完成了,可以使用了。 + +## 四、使用体验 + +
+ +
+ +现在你可以发挥想象的让 openclaw 帮你做事情了,很多运维的活,他也都可以完成。美滋滋! diff --git a/docs/md/road-map/portainer.md b/docs/md/road-map/portainer.md index 8378999a2..05872d792 100644 --- a/docs/md/road-map/portainer.md +++ b/docs/md/road-map/portainer.md @@ -1,9 +1,9 @@ --- -title: Portainer +title: Docker 管理面板(Portainer) lock: need --- -# Portainer 环境配置 +# Docker 管理面板(Portainer) 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) @@ -31,15 +31,20 @@ Status: Downloaded newer image for portainer/portainer:latest docker.io/portainer/portainer:latest ``` -- docker pull portainer/portainer +- 默认镜像:`docker pull portainer/portainer` +- 代理镜像:`docker pull registry.cn-hangzhou.aliyuncs.com/xfg-studio/portainer:latest` - 拉取 portainer ### 2. 安装和启动 +**注意**:如果是阿里云服务器,还需要先执行 `docker volume crete portainer_data` + ```java [root@CodeGuide]# docker run -d --restart=always --name portainer -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer ``` +代理安装(推荐):`docker run -d --restart=always --name portainer -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock registry.cn-hangzhou.aliyuncs.com/xfg-studio/portainer:latest` + ### 3. 访问 Portainer - 地址:[http://39.96.*.*:9000/](#) diff --git a/docs/md/road-map/private-docker-hub.md b/docs/md/road-map/private-docker-hub.md index d1e8a62d4..ed3a35484 100644 --- a/docs/md/road-map/private-docker-hub.md +++ b/docs/md/road-map/private-docker-hub.md @@ -1,5 +1,5 @@ --- -title: Private DockerHub +title: Docker 私有仓库 lock: need --- diff --git a/docs/md/road-map/spring-ai.md b/docs/md/road-map/spring-ai.md index accfc81e1..89d85372b 100644 --- a/docs/md/road-map/spring-ai.md +++ b/docs/md/road-map/spring-ai.md @@ -3,7 +3,7 @@ title: Spring AI lock: need --- -# Spring AI +# spring ai 作者:小傅哥
博客:[https://bugstack.cn](https://bugstack.cn) diff --git a/docs/md/road-map/spring-oauth2-sso-01.md b/docs/md/road-map/spring-oauth2-sso-01.md new file mode 100644 index 000000000..9e029ad50 --- /dev/null +++ b/docs/md/road-map/spring-oauth2-sso-01.md @@ -0,0 +1,502 @@ +--- +title: OAuth2 SSO +lock: need +--- + +# OAuth2 SSO - 前后端分离,单点登录案例 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +当你进入一个较大一些的中大厂互联网公司以后,你会发现自己参与的业务系统开发,好像从来没有关心过关于用户的身份鉴权,而是直接拿到用户的ID就做业务了。那这里的鉴权跑到哪里去了呢?🤔 + +
+ +
+ +其实在公司里是一套统一的授权服务和组件的,并且维护用户的ID、用户的关联绑定也都是这套系统来处理的。之后这套系统会和 API 网关进行对接,等网关下发到你的后端服务系统时,在内部微服间流转就是真实的用户ID啦。 + +那么为了让伙伴们更好的理解关于 OAuth2 SSO 统一单点登录的前后端分离服务,小傅哥这里做了一个结合 Spring Security OAuth2很容易理解案例工程。学习后就可以扩展使用 SSO 到你自己的系统了,比如可以做一个统一的用户鉴权中心。 + +## 一、单点登录 + +单点登录(Single Sign-On,SSO)是一种认证技术,用户只需进行一次身份验证,就可以访问多个相互信任的应用系统,而无需再次输入凭证。SSO的主要目的是简化用户的登录过程,提高用户体验和安全性,同时减少管理多个用户名和密码的复杂性。 + +
+ +
+ +SSO的工作原理通常涉及以下几个步骤: + +1. **身份验证**:用户在第一次访问SSO系统时输入用户名和密码等凭据进行验证。 +2. **创建会话**:成功验证后,系统创建一个会话,可以是令牌、票证或其他凭据,以证明用户的身份。 +3. **访问授权**:当用户访问不同的应用时,SSO系统将会话信息传递给这些应用,以确认用户的身份并授予访问权限。 +4. **信任机制**:应用之间需要建立信任关系,通常通过共享密钥或使用公钥基础设施(PKI)来实现验证和授权。 + +SSO的优点包括: + +- **提高用户体验**:用户只需记住一个用户名和密码,减少了填写登录信息的次数。 +- **增强安全性**:集中管理用户身份,方便监控和保护密码策略。 +- **降低管理成本**:减少IT部门处理密码重置等事务的工作量。 + +## 二、案例工程 + +### 1. 编程环境 + +- JDK 1.8 + +- SpringBoot 2.6.2 + +- Maven 3.8.1 + +- Docker - 负责安装 Nginx,如果没有 Docker 就本地直接安装 Nginx + +- SwitchHosts - 切换host,映射自定义域名地址,可以避免跨域问题。如果没有就直接修改本地的 host 文件。你可以配置自己的。 + +```java +192.168.1.107 sso.xfg.com +192.168.1.107 client1.xfg.com +192.168.1.107 client2.xfg.com +``` + +- 工程:[https://github.com/fuzhengwei/xfg-dev-tech-oauth2-sso](https://github.com/fuzhengwei/xfg-dev-tech-oauth2-sso) + +### 2. 工程结构 + +
+ +
+ +- xfg-dev-tech-app 是 SSO Auth 的鉴权服务。 +- test 模块下有2个 client,方便验证一个登录成功后,另外一个不会再跳转登录了。 +- docs/dev-ops 下提供了 docker compose 脚本,用于部署 Nginx 以及配合的前后端分离的前端页面。 + +### 3. 鉴权服务 + +```yml +server: + port: 8091 + application: + name: xfg-dev-tech-sso + servlet: + context-path: /auth + session: + cookie: + name: OAuth2SSOToken + +``` + +- yml 配置了 auth 路径和一个 session 名称。 + +#### 3.1 鉴权配置 + +**AuthorizationServerConfig** + +```java +@Bean +public ClientDetailsService inMemoryClientDetailsService() throws Exception { + return new InMemoryClientDetailsServiceBuilder() + // client1 mall + .withClient("client1") + .secret(passwordEncoder.encode("client1_secret")) + .scopes("all") + .authorizedGrantTypes("authorization_code", "refresh_token") + .redirectUris("http://client1.xfg.com/client1/login") + .accessTokenValiditySeconds(7200) + .autoApprove(true) + .and() + + // client2 lottery + .withClient("client2") + .secret(passwordEncoder.encode("client2_secret")) + .scopes("all") + .authorizedGrantTypes("authorization_code", "refresh_token") + .redirectUris("http://client2.xfg.com/client2/login") + .accessTokenValiditySeconds(7200) + .autoApprove(true) + .and() + .build(); +} +``` + +- 配置鉴权信息,这里配置了两个客户端信息。 + +#### 3.2 验证入口 + +```java +@Component("unauthorizedEntryPoint") +public class AppUnauthorizedEntryPoint implements AuthenticationEntryPoint { + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { + Map paramMap = request.getParameterMap(); + StringBuilder param = new StringBuilder(); + paramMap.forEach((k, v) -> { + param.append("&").append(k).append("=").append(v[0]); + }); + + param.deleteCharAt(0); + String isRedirectValue = request.getParameter("isRedirect"); + + if (!StringUtils.isEmpty(isRedirectValue) && Boolean.parseBoolean(isRedirectValue)) { + response.sendRedirect("http://sso.xfg.com/authPage/#/login?" + param); + return; + } + + String authUrl = "http://sso.xfg.com/auth/oauth/authorize?" + param + "&isRedirect=true"; + + Map result = new HashMap<>(); + result.put("code", 800); + result.put("msg", "授权地址"); + result.put("data", authUrl); + + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + PrintWriter writer = response.getWriter(); + ObjectMapper mapper = new ObjectMapper(); + writer.print(mapper.writeValueAsString(result)); + writer.flush(); + writer.close(); + } + +} +``` + +- 需要实现 AuthenticationEntryPoint 接口,配置一个转发的地址。 + +### 4. 客户端 - client1/client2 + +#### 4.1 client1 + +```java +server: + port: 8001 + servlet: + context-path: /client1 + +security: + oauth2: + client: + client-id: client1 + preEstablishedRedirectUri: + client-secret: client1_secret + access-token-uri: http://sso.xfg.com/auth/oauth/token + user-authorization-uri: http://sso.xfg.com/auth/oauth/authorize + resource: + user-info-uri: http://sso.xfg.com/auth/user + token-info-uri: http://sso.xfg.com/auth/oauth/check_token +``` + +```java +@RestController +public class Client01Controller { + + @GetMapping("/create_pay_order") + public Result createPayOrder() { + Result result = new Result(); + result.setCode(0); + result.setData("下单完成"); + return result; + } + + @GetMapping("/") + public void callback(HttpServletResponse response) throws IOException { + response.sendRedirect("http://client1.xfg.com/client1Page/#/home"); + } + +} +``` + +- 模拟下单,和 callback 地址配置。 + +#### 4.2 client2 + +```java +server: + port: 8002 + servlet: + context-path: /client2 + +security: + oauth2: + client: + client-id: client2 + client-secret: client2_secret + preEstablishedRedirectUri: + access-token-uri: http://sso.xfg.com/auth/oauth/token + user-authorization-uri: http://sso.xfg.com/auth/oauth/authorize + resource: + user-info-uri: http://sso.xfg.com/auth/user + token-info-uri: http://sso.xfg.com/auth/oauth/check_token +``` + +```java +@RestController +public class Client02Controller { + + @GetMapping("/lottery") + public Result lottery() { + Result result = new Result(); + result.setCode(0); + result.setData("下单红包,金额:" + RandomStringUtils.randomNumeric(10) + "元"); + return result; + } + + @GetMapping("/") + public void callback(HttpServletResponse response) throws IOException { + response.sendRedirect("http://client2.xfg.com/client2Page/#/home"); + } + +} +``` + +- 模拟另外一个微服务获取红包,以及 callback 地址服务。 + +### 5. 前端页面 + +#### 5.1 校验 + +```html + + + + +``` + +- 登录跳转操作,这里会走到 Nginx 中进行转发。 + +#### 5.2 客户端01 + +```html +
+ +

下单结果:

+
+ + + +``` + +- 下单的时候会检查是否登录,否则会被调整到 auth 校验。 + +#### 5.2 客户端02 + +```html +
+ +

红包结果:

+
+ + + +``` + +- 与 client1 的操作是一样的,但这里只要有一个登录了,另外一个就不会调整到 auth 页面登录了。 + +### 6. Nginx 配置 + +
+ +
+ +- Nginx 配置结构,docker compose 启动的时候会进行安装。 + +#### 6.1 sso.conf + +```java +server { + listen 80; + server_name sso.xfg.com; + + location /auth/ { + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://192.168.1.107:8091/auth/; + } + + location /authPage/ { + alias /usr/share/nginx/html/; + index auth.html; + } + + location ~ .*\.(js|css)$ { + alias /usr/share/nginx/html/; + index auth.html; + } + +} +``` + +#### 6.2 client1.conf + +```java +server { + listen 80; + server_name client1.xfg.com; + + location /client1/ { + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://192.168.1.107:8001/client1/; + } + + location /client1Page/ { + alias /usr/share/nginx/html/; + index client1.html; + } + + location ~ .*\.(js|css)$ { + alias /usr/share/nginx/html/; + index client1.html; + } +} +``` + +#### 6.3 client2.conf + +```java +server { + listen 80; + server_name client2.xfg.com; + + location /client2/ { + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://192.168.1.107:8002/client2/; + } + + location /client2Page/ { + alias /usr/share/nginx/html/; + index client2.html; + } + + location ~ .*\.(js|css)$ { + alias /usr/share/nginx/html/; + index client2.html; + } +} +``` + +> 更多的代码从工程中阅读即可,复杂度不高。 + +## 三、测试验证 + +### 1. 启动服务 + +
+ +
+ +
+ +
+ +- 你需要启动 Docker 的 Nginx,之后顺序启动 SSO 服务和2个客户端服务。 +- 另外要配置好 host,这样访问你的自定义域名地址,才会正确的跳转。(这东西在日常公司开发中会用到的很频繁) + +### 2. 访问客户端 + +
+ +
+ +你可以访问地址1进行验证,登录之后也可以进入地址2进行验证; + +- [http://client1.xfg.com/client1Page/#/home](http://client1.xfg.com/client1Page/#/home) +- [http://client2.xfg.com/client2Page/#/home](http://client2.xfg.com/client2Page/#/home) + +测试过程: + +- 首次登录,点击开始下单。会跳转登录,账密(xiaofuge/123456)。 +- 登录后再点击开始下单,则会看到下单完成,领红包。 +- 点击领红包,会跳转到 client2 的页面,点击随机红包,会进行服务端授权校验,之后就可以点击随机红包了。 diff --git a/docs/md/road-map/spring-oauth2.md b/docs/md/road-map/spring-oauth2.md new file mode 100644 index 000000000..fa0d1e13b --- /dev/null +++ b/docs/md/road-map/spring-oauth2.md @@ -0,0 +1,327 @@ +--- +title: OAuth2 +lock: need +--- + +# OAuth2 - 图解+案例,理解和实战OAuth2认证授权 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +你知道互联网大厂最怕的是什么吗?但凡有点这样的风吹草动,我们就要花费大量的时间进行修复和上线。一点都不敢耽误,对于紧急类型的,基本当天发现,当天就要升级上线。那是什么问题呢?🤔 + +
+ +
+ +**其实最怕的就是各类组件漏洞!** + +有这么一个东西,[13scan - 安全漏洞扫描](https://bugstack.cn/md/road-map/13scan-jdumpspider.html) 它可以扫描出系统组件的各项存在的漏洞,给出整改建议。因为这些漏洞的存在,就可能让不法用户通过接口调用到系统数据。比如,随意输入个订单号,就知道是谁,什么时间、购买的什么、地址在哪。这是非常可怕的。 + +所以,在互联网大厂中,会有统一的安全授权认证服务 OAuth2。这样即使有外部对接的系统确实需要授权获得用户的数据,也可以在可靠的范围内进行授权和使用。 + +那么,OAuth2 是个啥呢?🤔 本节我们来分享下并做个代码案例运行验证。 + +## 一、OAuth2 是啥? + +**OAuth 2.0 的标准 RFC 6749,解释了 OAuth 是什么。** + +
+ +
+ +**官网**:[https://datatracker.ietf.org/doc/html/rfc6749](https://datatracker.ietf.org/doc/html/rfc6749) + +OAuth 2.0 本身是一种开放标准,不是一个具体的服务类组件,而是一种标准。旨在为用户提供授权,允许第三方应用程序访问用户在某个服务提供者(如社交网络或云服务)上的信息,而无需将用户的凭证(如用户名和密码)透露给这些应用程序。OAuth 2.0 主要用于授权,而不是身份验证。 + +而 Spring 中 OAuth2 就是对这套标准的具体实现,但这不是唯一实现,你甚至可以通过这套标准做一套自己的 OAuth2 授权框架。 + +## 二、举个例子 + +大家在日常的生活中使用互联网类的产品,包括;购物、视频、出行等,都可能收到活动类的短信,问你是否要参与一个这样的活动,如果参与则需要点击授权允许。那么这个过程就有 OAuth2 的授权使用。如图; + +
+ +
+ +- 这是一套用户参与小傅哥分享的星球用户活动页面。用户点击参与后,会引导进入授权验证。显示进入微信登录,之后跳转到用户数据授权使用页。 +- 用户允许授权后,小傅哥的这套活动页就可以拿到用户个人的数据,通过个人的数据为唯一标识,允许用户参与本次活动。这些活动可以是一些抽奖、礼包领取、代码仓库授权等。这些场景的使用,就是 OAuth2 的授权框架作用。 + +## 三、授权方式 + +在看 OAuth2 之前,可以代入的思考下,如果是你做一个认证授权框架,你会怎么做。其实你在最开始学习编程使用账号密码在数据库里匹配验证,完成后生成一个 Token 让前端保存到 Cookie 里,之后每次请求后端都携带上这个 Cookie 进行校验。 + +其实这个模型就是认证授权框架。认证;使用账密证明你是你,授权,则通过账密分配一个Token,让使用放通过 Token 进行数据访问。 + +那么,OAuth2 作为认证授权框架,提供了四种授权访问,包括; +- 授权模型(authorization-code) +- 隐藏模式(简单授权)(implicit) +- 密码模式(password) +- 客户端凭证模式(client credentials) + +这四种授权方式,逐渐减弱。不过,无论那种授权方式,在第三方应用申请可调用数据的令牌前,都需要先完成系统备案,验明自身身份。包括客户端 ID、客户端秘钥 Client Secret。 + +### 1. 授权模型 + +授权模式:指第三方应用先申请一个授权码,之后再使用该码获得令牌。授权码模式通常用于具有浏览器界面的应用程序,尤其是在需要用户交互的场景下,例如传统的Web应用。由于使用了重定向和授权码,维护了更高的安全性。 + +
+ +
+ +**工作流程:** + +1. 用户在客户端(第三方应用)上点击登录。 +2. 客户端将用户重定向到授权服务器,携带其注册的客户端ID、重定向URI和请求的权限范围。 +3. 用户在授权服务器上验证身份,并同意授权后,授权服务器将用户重定向回客户端,附带一个授权码。 +4. 客户端使用该授权码向授权服务器请求访问令牌,同时发送客户端ID、客户端密钥和重定向URI。 +5. 授权服务器验证请求,并返回访问令牌(和可选的刷新令牌)。 +6. 客户端使用访问令牌访问受保护的资源。 + +### 2. 隐藏模式 + +隐式模式主要适用于在Web浏览器中运行的单页应用(SPA)等不安全的客户端环境,因为不需要后台服务器交换授权码,简化了流程。然而,隐式模式由于直接暴露令牌,安全性较低,不建议用于敏感操作。 + +
+ +
+ +**工作流程:** + +1. 用户在客户端上点击登录。 +2. 客户端将用户重定向到授权服务器,携带客户端ID、重定向URI及请求的权限范围。 +3. 用户在授权服务器进行身份验证,并同意授权后,授权服务器立即将访问令牌作为URI片段重定向回客户端。 +4. 客户端在接收到重定向后,解析URI以获取访问令牌,随后可直接使用该令牌访问受保护的资源。 + +### 3. 密码模式 + +密码模式适用于用户信任客户端的情况,如用户通过原生应用(移动应用)访问服务。在此情况下,客户端直接处理用户的凭据,使用时要确保应用的安全性。 + +
+ +
+ +**工作流程:** + +1. 用户在客户端直接输入其用户名和密码。 +2. 客户端将用户的凭据(用户名和密码)发送到授权服务器,请求访问令牌。 +3. 授权服务器验证凭据并返回访问令牌(和可选的刷新令牌)。 +4. 客户端使用访问令牌访问受保护的资源。 + +### 4. 客户端凭证模式 + +客户端凭证模式主要用于服务器与服务器之间的通信,如后台服务相互访问API,或者服务自身需要访问其资源。适用于没有用户上下文的场景,更多用于机器对机器(M2M)通信。 + +
+ +
+ +**工作流程** + +1. 客户端向授权服务器发送包含其客户端ID和客户端密钥的请求,请求访问令牌。 +2. 授权服务器验证客户端身份,并返回访问令牌。 +3. 客户端使用访问令牌访问受保护的资源,通常是与服务器本身相关的资源。 + +## 四、授权代码 + +有了上面的概念,我们再来看个实际的案例工程,验证四种授权模式。环境信息如下; + +- JDK 1.8 +- Maven 3.8.* +- MySQL 5.x ~ 8.x,案例使用的是 8.x + +### 1. 工程结构 + +
+ +
+ +- 首先,案例工程提供了 OAuth2 的授权框架 + 数据库配置实现。 +- docs 下提供了 docker compose 安装 MySQL 的脚本和导入库表的操作,这套库表就是授权框架的库表。 +- 验证功能的时候需要使用到 ApiPost,你可以下载使用,并到 api-json 导入。 + +### 2. 核心实现 + +除了 OAuth2 关于 Spring Security 部分已经在前面的课程讲解过,可以补充学习。[https://bugstack.cn/md/road-map/spring-security.html](https://bugstack.cn/md/road-map/spring-security.html) + +#### 2.1 账户认证 + +```java +@Override +public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + String clientId; + if (authentication != null) { + Object principal = authentication.getPrincipal(); + if (principal instanceof User) { + User clientUser = (User) principal; + clientId = clientUser.getUsername(); + } else if (principal instanceof OauthAccountUserDetails) { + getClientIdByRequest(); + return (OauthAccountUserDetails) principal; + } else { + throw new UnsupportedOperationException(); + } + } else { + clientId = getClientIdByRequest(); + } + // 校验用户 - 直接从数据库查询 + OauthAccount account = oauthAccountDao.loadUserByUsername(clientId, username); + if (account == null || !account.getAccountNonDeleted()) { + throw new UsernameNotFoundException("err user is not found!"); + } + return new OauthAccountUserDetails(account, new ArrayList<>()); +} +``` + +#### 2.2 刷新授权 + +```java +@Bean +public TokenEnhancer additionalInformationTokenEnhancer() { + return (accessToken, authentication) -> { + Map information = new HashMap<>(8); + Authentication userAuthentication = authentication.getUserAuthentication(); + if (userAuthentication instanceof UsernamePasswordAuthenticationToken) { + UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) userAuthentication; + Object principal = token.getPrincipal(); + if (principal instanceof OauthAccountUserDetails) { + OauthAccountUserDetails userDetails = (OauthAccountUserDetails) token.getPrincipal(); + OauthAccount oauthAccount = userDetails.getOauthAccount(); + information.put("account_info", UserAccountVO.builder() + .id(oauthAccount.getId()) + .clientId(oauthAccount.getClientId()) + .username(oauthAccount.getUsername()) + .mobile(oauthAccount.getMobile()) + .email(oauthAccount.getEmail()) + .build()); + ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(information); + } + } + return accessToken; + }; +} +``` + +#### 2.3 添加账户 + +
+ +
+ +```java +@Resource +private PasswordEncoder passwordEncoder; +@Test +public void test_passwordEncoder() { + log.info("测试结果:{}", passwordEncoder.encode("123456")); +} +``` + +- 这里测试可以生成一个需要的密码,账户填写到数据库中使用。 + +### 3. 测试验证 + +在测试之前,你要启动服务,确保运行没问题。启动前配置数据库连接。 + +```java +spring: + datasource: + username: root + password: 123456 + url: jdbc:mysql://192.168.1.109:13306/xfg-dev-tech-oauth2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&useSSL=true + driver-class-name: com.mysql.cj.jdbc.Driver +``` + +- 关于 ApiPost 的测试,你可以直接从工程中的 json 导入的你的 ApiPost 就可以使用了。 + +#### 3.1 客户端凭证 + +
+ +
+ +```java +{ + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiYmlnLW1hcmtldC1hcHAiXSwic2NvcGUiOlsicmVhZCIsIndyaXRlIl0sImV4cCI6MTczNjY3OTA4MCwiYXV0aG9yaXRpZXMiOlsidXNlciJdLCJqdGkiOiI4NWY0YjY2Ni1mNDliLTRiNGEtOTM1Ni0xYjRiMTVmZmI5MWEiLCJjbGllbnRfaWQiOiJ4Zmctc3R1ZGlvIn0.CqMOMbBkHMnQicpkBEeqMyJEp9HbSiGgXoYUke_PWtI", + "token_type": "bearer", + "expires_in": 7198, + "scope": "read write", + "jti": "85f4b666-f49b-4b4a-9356-1b4b15ffb91a" +} +``` + +- 请求:[http://127.0.0.1:8091/oauth/token?grant_type=client_credentials](http://127.0.0.1:8091/oauth/token?grant_type=client_credentials) +- 认证:`xfg-studio/123456` + +#### 3.2 用户密码模式 + +
+ +
+ +```java +{ + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiYmlnLW1hcmtldC1hcHAiXSwiZXhwIjoxNzM2Njc5MTQxLCJ1c2VyX25hbWUiOiJ4aWFvZnVnZSIsImp0aSI6ImVhZWMzZmQ0LTViOTAtNGRhNy1hODQ1LTA2MDFmMjJiNDc2ZCIsImNsaWVudF9pZCI6InhmZy1zdHVkaW8iLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXX0.JgUxx6_aHqCBxuvYXvekw-ZW5pPnSw5LEKlfsd4qVyI", + "token_type": "bearer", + "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiYmlnLW1hcmtldC1hcHAiXSwidXNlcl9uYW1lIjoieGlhb2Z1Z2UiLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiYXRpIjoiZWFlYzNmZDQtNWI5MC00ZGE3LWE4NDUtMDYwMWYyMmI0NzZkIiwiZXhwIjoxNzM5MjYzOTQyLCJqdGkiOiI5ZDc4ZjVjZS0xZTMwLTRiZTYtYWUyNi01NjY1NWQ4YjYzZjIiLCJjbGllbnRfaWQiOiJ4Zmctc3R1ZGlvIn0.8gMfqhBnc4wI9BsRENu_16RmZFqeCWVSyWcF4B9nA1I", + "expires_in": 7198, + "scope": "read write", + "account_info": { + "id": null, + "clientId": "xfg-studio", + "username": "xiaofuge", + "mobile": "13500002222", + "email": "523088136@qq.com" + } +} +``` + +- 请求:[http://127.0.0.1:8091/oauth/token](http://127.0.0.1:8091/oauth/token) +- 认证:`xfg-studio/123456` +- 参数:`grant_type = password`、`username = xiaofuge`、`password = 123456` + +#### 3.3 授权模式 + +##### 3.3.1 登录认证 + +
+ +
+ +```java +{ + "status": 200, + "message": "hi login success!" +} +``` + +- 请求:[http://127.0.0.1:8091/login](http://127.0.0.1:8091/login) +- 认证:`xfg-studio/123456` +- 参数:`username = xiaofuge`、`password = 123456` +- 说明:你会拿到一个 Cookie `JSESSIONID=9000E64733AA6E947054AC4326C91AF8` 这个 cookie 用于获取授权码 + +##### 3.3.2 获取授权码&跳转 + +
+ +
+ +
+ +
+ +
+ +
+ +- 请求:[http://127.0.0.1:8091/oauth/authorize?client_id=xfg-studio&response_type=code&grant_type=authorization_code](http://127.0.0.1:8091/oauth/authorize?client_id=xfg-studio&response_type=code&grant_type=authorization_code) +- 认证:无 +- 参数:`client_id = xfg-studio`、`response_type = code`、`grant_type=authorization_code` +- 注意:如果 oauth_client_details 表字段配置 autoapprove = false 则不会直接跳转页面,会进行让用户确认。 + +之后刷新令牌、检查令牌,就可以单独测试了。如果部署到云服务器,那么还可以走浏览器访问,单独有一个获取令牌的操作,之后再跳转地址。 diff --git a/docs/md/road-map/spring-security.md b/docs/md/road-map/spring-security.md new file mode 100644 index 000000000..2994d05bc --- /dev/null +++ b/docs/md/road-map/spring-security.md @@ -0,0 +1,777 @@ +--- +title: Spring Security +lock: need +--- + +# Spring Security + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +在互联网大厂这些年做研发这么多年,有一个非常指导性的开发原则就是;你做的这个东西是否能让整个大组内的其他系统使用。所以,从15年入职开始,我有的各种创新的想法都落地实现了,一直被使用到现在。`那些组件也都成了一个个技术专利 👍🏻` + +
+ +
+ +但其实这样对通用逻辑的共性凝练,开发成统一的组件,在 Spring 框架中是有非常多的,这些东西也都在我们日常使用 Spring 时有所涉猎。包括我们本节要讲解的 Spring Security 组件。 + +当你想让系统实现登录校验的服务,那么你不可能在每个系统里都写认证和授权服务,那么这个时候就要做一套统一的认证框架。这里 Spring Security 就是专注于为 Java 应用程序提供身份验证和授权的框架。提供;验证、授权、防止会话固定、点击劫持、跨域请求等。 + +## 一、为啥需要安全框架 + +举个例子;SpringBoot 有一个 actuator 框架,可以配合普罗米修斯做系统监控。包括采集系统的接口运行数据、JVM 信息、负载等各项指标。 + +```java +# 监控 +management: + endpoints: + web: + exposure: + include: "*" + endpoint: + health: + show-details: always + metrics: + export: + prometheus: + enabled: true + prometheus: + enabled: true +``` + +虽然很好用,但如果你一点安全都不加就直接在工程中配置,那么在网安人员的手里,基本就是一台肉鸡。一套 w13scan 正向代理,就能把你的工程底裤拔掉,拿出你的数据库账号密码。 + +操作教程:[https://bugstack.cn/md/road-map/13scan-jdumpspider.html](https://bugstack.cn/md/road-map/13scan-jdumpspider.html) + +```java +/bin/zsh /xiaofuge/develop/github/xfg-dev-tech-w13scan-jdumpspider/docs/jdumpspider.sh +(base) xiaofuge@ZBMac-GV47H1GXD docs % /bin/zsh /Users/xiaofuge/Documents/develop/github/xfg-dev-tech-w13scan-jdumpspider/docs/jdumpspider.sh +=========================================== +SpringDataSourceProperties +------------- +password = 123456 +driverClassName = com.mysql.cj.jdbc.Driver +url = jdbc:mysql://127.0.0.1:13306/road_map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true +username = root +``` + +所以,任何你暴漏出去对外使用的服务,都要做安全框架的认证和授权。 + +## 二、认证和授权的原理 + +有不少伙伴在初次使用 Spring Security 框架的时候,会觉得复杂度有些高。其实在之前没有 SpringBoot 之前,Security 这个框架使用是更复杂的。这也主要是因为 Security 支持的灵活性更高,所以抽象的也更复杂。但其实能做一个完整的小案例,也就不会觉得有多复杂了。 + +
+ +
+ +- 其实 Spring Security 要做也就2件事,认证(Authentication)你是谁,授权(Authorization)你干啥。其实就算你不使用 Spring Security 你自己做一个登录的功能,以及允许登录的用户可以操作的流程,也要做这样的事情。 +- Spring Security 在内部维护一个过滤器链,其中每个过滤器都有特定的职责,并且根据所需的服务在配置中添加或删除过滤器。过滤器的顺序很重要,因为它们之间存在依赖关系。 +- 文档:[https://docs.spring.io/spring-security/site/docs/3.0.x/reference/security-filter-chain.html](https://docs.spring.io/spring-security/site/docs/3.0.x/reference/security-filter-chain.html) - Web 应用程序安全过滤链 + +## 三、一个简单的小案例 + +Spring Security 提供了最简单的登录访问校验配置,如果你只是想给一些页面添加一个登录页面。那么只需要配置下 pom 和 yml 中提供的用户账密就可以登录校验了。 + +源码:[https://github.com/fuzhengwei/xfg-dev-tech-spring-security-demo](https://github.com/fuzhengwei/xfg-dev-tech-spring-security-demo) + +### 1. 引入 pom + +```java + + org.springframework.boot + spring-boot-starter-security + +``` + +### 2. 配置yml + +```java +server: + port: 8099 + +spring: + security: + user: + name: xiaofuge + password: 123456 +``` + +- security 的账号密码,就是你访问一个链接需要登录的账密。 +- 如果不配置账号,它会有一个固定的 user 加上在启动程序时控制台会随机生成密码。 + +### 3. 测试接口 + +```java +@RestController +@RequestMapping("/api/auth/") +public class TestController { + + @GetMapping("hi") + public String hi(){ + return "hi security"; + } +} +``` + +### 4. 访问验证 + +地址:[http://localhost:8099/api/test/hi](http://localhost:8099/api/test/hi) + +
+ +
+ +- 首次访问地址后,会自动跳转到一个登录页面。属于我们配置的账密进行登录。登录完成后,这里会写入一个 cookie,之后就可以访问我们的接口信息了。 + +## 四、正式工程案例对接 + +### 1. 工程结构 + +
+ +
+ +- 地址:[https://github.com/fuzhengwei/xfg-dev-tech-spring-security](https://github.com/fuzhengwei/xfg-dev-tech-spring-security) +- 这是一套在 DDD 六边形分层结构中添加的 Spring Security 认证框架。如图,介绍了分层模块的使用。 +- 接下来我们注册讲解这些代码块的用途。 + +### 2. GuavaConfig - 本地缓存模拟用户 + +```java +@Slf4j +@Configuration +public class GuavaConfig { + + @Bean(name = "userCache") + public Cache userCache(PasswordEncoder passwordEncoder) { + Cache cache = CacheBuilder.newBuilder() + .expireAfterWrite(365, TimeUnit.DAYS) + .build(); + + UserEntity userEntity01 = UserEntity.builder() + .userName("xiaofuge") + .password(passwordEncoder.encode("123456")) + .roles(Arrays.asList(RoleTypeEnum.ADMIN)) + .build(); + + UserEntity userEntity02 = UserEntity.builder() + .userName("liergou") + .password(passwordEncoder.encode("123456")) + .roles(Arrays.asList(RoleTypeEnum.USER)) + .build(); + + log.info("测试账密01 xiaofuge/123456 权限;admin"); + log.info("测试账密02 liergou/123456 权限;user"); + + cache.put(userEntity01.getUserName(), userEntity01); + cache.put(userEntity02.getUserName(), userEntity02); + return cache; + } + +} +``` + +- 程序启动后,模拟注册完成的用户用户测试验证。用户也可以在测试中自己在注册用户。 + +### 3. UserDetails 用户身份信息 + +#### 3.1 身份实现 + +```java +public class UserDetailAuthSecurity implements UserDetails { + + @Serial + private static final long serialVersionUID = 931859819772024712L; + + private final UserEntity userEntity; + + public UserDetailAuthSecurity(UserEntity userEntity) { + this.userEntity = userEntity; + } + + @Override + public Collection getAuthorities() { + return userEntity.getRoles() + .stream() + .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getCode())) + .collect(Collectors.toList()); + } + + @Override + public String getPassword() { + return userEntity.getPassword(); + } + + @Override + public String getUsername() { + return userEntity.getUserName(); + } + + // ... + +} +``` + +- 做授权校验是基于用户的 UserDetails 详细身份进行的。这东西就是一个依赖倒置,Spring 定义好接口标准,之后由使用方实现。 + +#### 3.2 身份获取 + +```java +@Service +public class UserDetailsServiceImpl implements UserDetailsService { + + @Resource + private Cache userCache; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + UserEntity userEntity = userCache.getIfPresent(username); + if (null == userEntity) return null; + return new UserDetailAuthSecurity(userEntity); + } + +} +``` + +- 这里还需要对 UserDetails 包装一层提供一个 UserDetailsService 接口的实现类。 + +### 4. 授权&校验处理 + +#### 4.1 JwtAuthenticationProvider - 验证账密 + +```java +public class JwtAuthenticationProvider implements AuthenticationProvider { + + private final PasswordEncoder passwordEncoder; + private final UserDetailsService userDetailsService; + + public JwtAuthenticationProvider(PasswordEncoder passwordEncoder, UserDetailsService userDetailsService) { + this.passwordEncoder = passwordEncoder; + this.userDetailsService = userDetailsService; + } + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + String username = String.valueOf(authentication.getPrincipal()); + String password = String.valueOf(authentication.getCredentials()); + + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + if (passwordEncoder.matches(password, userDetails.getPassword())) { + return new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities()); + } + + throw new BadCredentialsException("Auth Error!"); + } + + @Override + public boolean supports(Class authentication) { + return UsernamePasswordAuthenticationToken.class.equals(authentication); + } + +} +``` + +- 这一部分是获取用户名和密码,通过 userDetailsService 获取信息进行密码比对。这个就和我们自己要做一个登录校验的方式是一样的。 + +#### 4.2 JwtAuthenticationTokenFilter - 校验登录 + +```java +@Slf4j +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + + private final static String AUTH_HEADER = "Authorization"; + private final static String AUTH_HEADER_TYPE = "Bearer"; + + private final UserDetailsService userDetailsService; + + public JwtAuthenticationTokenFilter(UserDetailsService userDetailsService) { + this.userDetailsService = userDetailsService; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + String authHeader = request.getHeader(AUTH_HEADER); + if (Objects.isNull(authHeader) || !authHeader.startsWith(AUTH_HEADER_TYPE)){ + filterChain.doFilter(request,response); + return; + } + + String authToken = authHeader.split(" ")[1]; + log.info("authToken:{}" , authToken); + + if (!JWTUtil.verify(authToken, "key".getBytes(StandardCharsets.UTF_8))) { + filterChain.doFilter(request,response); + return; + } + + final String userName = (String) JWTUtil.parseToken(authToken).getPayload("username"); + UserDetails userDetails = userDetailsService.loadUserByUsername(userName); + + UsernamePasswordAuthenticationToken authentication = + new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + + SecurityContextHolder.getContext().setAuthentication(authentication); + + filterChain.doFilter(request, response); + } + +} +``` + +```java +fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` // Include the token in the request headers + } +}) +``` + +- 这一部分是对 http 请求信息中的 Authorization Bearer 后面带有的 token 信息进行解析校验。如代码中提供了一部分前端请求代码,就是这里的 Token + +### 5. 认证&授权配置 + +```java +@Configuration +@EnableWebSecurity +@EnableMethodSecurity(prePostEnabled = true) +public class SpringSecurityConfig { + + // 不拦截的 URL + private final String[] requestMatchers = {"/api/auth/login", "/api/auth/register", "/api/auth/query_user_name", "/test/**"}; + + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { + return authConfig.getAuthenticationManager(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(UserDetailsService userDetailsService) { + return new JwtAuthenticationTokenFilter(userDetailsService); + } + + @Bean + public JwtAuthenticationProvider jwtAuthenticationProvider(PasswordEncoder passwordEncoder, UserDetailsService userDetailsService) { + return new JwtAuthenticationProvider(passwordEncoder, userDetailsService); + } + + @Bean + public SecurityFilterChain filterChain(HttpSecurity httpSecurity, + JwtAuthenticationProvider jwtAuthenticationProvider, + JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter, + AppUnauthorizedHandler appUnauthorizedHandler, + AppAccessDeniedHandler appAccessDeniedHandler + ) throws Exception { + // 使用JWT,可屏蔽csrf防护 + httpSecurity.csrf(CsrfConfigurer::disable) + // 基于token存储到浏览器,不需要session + .sessionManagement(sessionManagementConfigurer -> sessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .authorizeHttpRequests(authorizationRegistry -> authorizationRegistry + // 允许对于网站静态资源的无授权访问 + .requestMatchers(HttpMethod.GET, "/", "/*.html").permitAll() + // 对登录注册允许匿名访问 + .requestMatchers(requestMatchers).permitAll() + // 访问授权,所有 /user/** 路径下的请求需要 ADMIN 角色。注意;Spring Security在处理角色时,会自动为角色名添加"ROLE_"前缀。因此,"ADMIN"角色实际上对应权限"ROLE_ADMIN"。 + .requestMatchers("/api/mall/**").permitAll() + // 跨域请求会先进行一次options请求 + .requestMatchers(HttpMethod.OPTIONS).permitAll() + // 对所有请求开启授权保护 + .anyRequest() + // 已认证的请求自动被授权 + .authenticated() + ) + // 禁用缓存 + .headers(headersConfigurer -> headersConfigurer + .cacheControl(HeadersConfigurer.CacheControlConfig::disable) + ) + // 使用自定义 provider + .authenticationProvider(jwtAuthenticationProvider) + // 添加 JWT filter + .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class) + // 添加自定义未授权和未登录结果返回 + .exceptionHandling(exceptionConfigure -> exceptionConfigure + .accessDeniedHandler(appAccessDeniedHandler) + .authenticationEntryPoint(appUnauthorizedHandler)); + + return httpSecurity.build(); + } + +} +``` + +- 那么这里所做的就是认证授权的配置,对哪些URL进行放行,哪些是要做拦截。 +- appAccessDeniedHandler、appUnauthorizedHandler,是自定义的鉴权拦截,如果登录不通过,可以统一返回给前端一个固定的错误码,便于跳转登录。 + +### 6. 注册登录 + +```java +@Service +public class AuthService implements IAuthService { + + @Autowired + private PasswordEncoder passwordEncoder; + + @Resource + private Cache userCache; + + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public void register(String userName, String password) { + + UserEntity userEntity = UserEntity.builder() + .userName(userName) + .password(passwordEncoder.encode(password)) + .roles(Arrays.asList(RoleTypeEnum.USER, RoleTypeEnum.ADMIN)) + .build(); + + userCache.put(userName, userEntity); + } + + @Override + public String login(String userName, String password) { + // 登录验证 + authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userName, password)); + // 验证通过,获取 token + String token = JWT.create() + .setExpiresAt(new Date(System.currentTimeMillis() + (1000 * 30))) + .setPayload("username", userName) + .setKey("key".getBytes(StandardCharsets.UTF_8)) + .sign(); + + return token; + } + +} +``` + +- 在 domain 模块中提供了一个简单的注册&登录服务。注册就是简单的像本地缓存 Guava 写入数据。登录校验会调用登录密码校验处理。在登录成功后返回 JWT 生成的 token 信息。 + +### 7. 访问拦截 + +#### 1. 认证授权 + +```java +@Slf4j +@CrossOrigin("*") +@RestController +@RequestMapping("/api/auth/") +public class AuthController { + + @Resource + private IAuthService authService; + + @Autowired + private AuthenticationManager authenticationManager; + + @PostMapping("query_user_name") + public Response queryUserName() { + try { + // 获取当前认证的用户信息 + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Object principal = authentication.getPrincipal(); + return Response.builder() + .code(Response.ResponseCode.SUCCESS.getCode()) + .info(Response.ResponseCode.SUCCESS.getInfo()) + .data(principal.toString()) + .build(); + } catch (Exception e) { + return Response.builder() + .code(Response.ResponseCode.UN_ERROR.getCode()) + .info(Response.ResponseCode.UN_ERROR.getInfo()) + .build(); + } + } + + @PostMapping("register") + public Response register(@RequestParam String userName, @RequestParam String password) { + try { + log.info("注册用户:{}", userName); + authService.register(userName, password); + return Response.builder() + .code(Response.ResponseCode.SUCCESS.getCode()) + .info(Response.ResponseCode.SUCCESS.getInfo()) + .data(true) + .build(); + } catch (Exception e) { + log.info("注册用户失败:{}", userName); + return Response.builder() + .code(Response.ResponseCode.UN_ERROR.getCode()) + .info(Response.ResponseCode.UN_ERROR.getInfo()) + .build(); + } + } + + @PostMapping("login") + public Response login(@RequestParam String userName, @RequestParam String password) { + try { + log.info("登录用户:{}", userName); + // 登录获取 token + String token = authService.login(userName, password); + + return Response.builder() + .code(Response.ResponseCode.SUCCESS.getCode()) + .info(Response.ResponseCode.SUCCESS.getInfo()) + .data(token) + .build(); + } catch (Exception e) { + log.info("登录用户失败:{}", userName); + return Response.builder() + .code(Response.ResponseCode.UN_ERROR.getCode()) + .info(Response.ResponseCode.UN_ERROR.getInfo()) + .build(); + } + } + +} +``` + +- 提供注册、登录和查询用户信息接口。 +- 查询用户有些场景是会通过路径地址获取用户id,再根据用户id查询。但一些安全级别较高的,甚至不会透彻用户id,而是校验登录token,之后缓存用户id在使用。 + +#### 2. 角色权限 + +```java +@Slf4j +@CrossOrigin("*") +@RestController +@RequestMapping("/api/mall/") +public class MallController { + + @PreAuthorize("hasRole('ADMIN')") +// @PreAuthorize("hasRole('USER')") + @RequestMapping(value = "create_pay_order", method = RequestMethod.POST) + public Response createPayOrder(@RequestBody CreatePayRequestDTO createPayRequestDTO) { + try { + // 获取当前认证的用户信息 + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Object principal = authentication.getPrincipal(); + + String userName = (String) principal; + String productId = createPayRequestDTO.getProductId(); + + log.info("商品下单,根据商品ID创建支付单开始 userName:{} productId:{}", userName, productId); + + return Response.builder() + .code(Response.ResponseCode.SUCCESS.getCode()) + .info(Response.ResponseCode.SUCCESS.getInfo()) + .data(userName + " 下单成功。单号:" + RandomStringUtils.randomAlphabetic(12)) + .build(); + } catch (Exception e) { + log.error("商品下单,根据商品ID创建支付单开始 productId:{}", createPayRequestDTO.getProductId(), e); + return Response.builder() + .code(Response.ResponseCode.UN_ERROR.getCode()) + .info(Response.ResponseCode.UN_ERROR.getInfo()) + .build(); + } + } + +} +``` + +- 用户登录完成后,提供一个下单接口。 +- 注意,接口上有;ADMIN、USER 权限注解,我们在配置默认账号的时候,给xiaofuge是 ADMIN权限,liergou 是USER权限。配置不同的注解,会导致下单成功或者失败。 + +## 五、通过页面验证逻辑 + +这里小傅哥提供了一套前端简单的验证页面,方便大家学习; + +
+ +
+ +- 如果感兴趣前端代码的调用,也可以进入源码学习。 + +```java + . ____ _ __ _ _ + /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ +( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ + \\/ ___)| |_)| | | | | || (_| | ) ) ) ) + ' |____| .__|_| |_|_| |_\__, | / / / / + =========|_|==============|___/=/_/_/_/ + :: Spring Boot :: (v3.1.6) + +24-12-15.11:22:10.786 [main ] INFO Application - Starting Application using Java 17.0.12 with PID 3656 (/Users/fuzhengwei/1024/KnowledgePlanet/road-map/xfg-dev-tech-spring-security/xfg-dev-tech-app/target/classes started by fuzhengwei in /Users/fuzhengwei/1024/KnowledgePlanet/road-map/xfg-dev-tech-spring-security) +24-12-15.11:22:10.789 [main ] INFO Application - The following 1 profile is active: "dev" +24-12-15.11:22:12.330 [main ] INFO TomcatWebServer - Tomcat initialized with port(s): 8091 (http) +24-12-15.11:22:12.340 [main ] INFO Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8091"] +24-12-15.11:22:12.343 [main ] INFO StandardService - Starting service [Tomcat] +24-12-15.11:22:12.343 [main ] INFO StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.16] +24-12-15.11:22:12.466 [main ] INFO [/] - Initializing Spring embedded WebApplicationContext +24-12-15.11:22:12.466 [main ] INFO ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 1615 ms +24-12-15.11:22:12.705 [main ] INFO GuavaConfig - 测试账密01 xiaofuge/123456 权限;admin +24-12-15.11:22:12.705 [main ] INFO GuavaConfig - 测试账密02 liergou/123456 权限;user +24-12-15.11:22:13.188 [main ] INFO DefaultSecurityFilterChain - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@1e225820, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@8aeab9e, org.springframework.security.web.context.SecurityContextHolderFilter@3332c7a5, org.springframework.security.web.header.HeaderWriterFilter@5099c59b, org.springframework.security.web.authentication.logout.LogoutFilter@6ac4c3f7, cn.bugstack.xfg.dev.tech.config.security.JwtAuthenticationTokenFilter@65eb76cd, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@3e39baf0, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@25a94b55, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@2a2dc0a, org.springframework.security.web.session.SessionManagementFilter@3635099, org.springframework.security.web.access.ExceptionTranslationFilter@5eb5da12, org.springframework.security.web.access.intercept.AuthorizationFilter@654e6a90] +24-12-15.11:22:13.372 [main ] INFO Http11NioProtocol - Starting ProtocolHandler ["http-nio-8091"] +24-12-15.11:22:13.419 [main ] INFO TomcatWebServer - Tomcat started on port(s): 8091 (http) with context path '' +24-12-15.11:22:13.432 [main ] INFO Application - Started Application in 3.597 seconds (process running for 4.098) +``` + +- 测试前启动 SpringBoot 服务。 + +### 1. 首次登录 + +地址:[login.html](login.html) + +```java +function login() { + const username = document.getElementById('username').value; + const password = document.getElementById('password').value; + + fetch('http://127.0.0.1:8091/api/auth/login', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: new URLSearchParams({ + userName: username, + password: password + }) + }) + .then(response => response.json()) + .then(data => { + if (data.code === '0000') { + // Store token in localStorage on successful login + localStorage.setItem('xfg-dev-tech-spring-security-token', data.data); + window.location.href = 'index.html'; // 假设登录成功后跳转到首页 + } else { + alert('登录失败: ' + data.info); + } + }) + .catch(error => { + console.error('Error during login:', error); + alert('登录失败'); + }); +} +``` + +
+ +
+ +- 测试账号;`xiaofuge/123456`、`liergou/123456`,xiaofuge 是 admin 权限,liergou 是 user 权限,你可以分别测试验证。 +- 你还可以自己注册新的账号进行验证。 + +### 2. 首页下单 + +```java +document.addEventListener("DOMContentLoaded", function () { + var token = localStorage.getItem('xfg-dev-tech-spring-security-token'); + if (!token) { + window.location.href = "login.html"; // Redirect to the login page + return; + } + + var productId = "100010090091"; + var url = 'http://127.0.0.1:8091/api/auth/query_user_name'; + + fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` // Include the token in the request headers + } + }) + .then(response => response.json()) // Parse the JSON response + .then(json => { + const userNameDisplay = document.getElementById('userNameDisplay'); + if (json.code === "0000") { + userNameDisplay.textContent = json.data; + } else { + userNameDisplay.textContent = '未登录'; + } + }) + .catch(error => { + console.error('Error fetching user name:', error); + document.getElementById('userNameDisplay').textContent = '未登录'; + }); + + }); + +document.getElementById('orderButton').addEventListener('click', function() { + var token = localStorage.getItem('xfg-dev-tech-spring-security-token'); + if (!token) { + window.location.href = "login.html"; // Redirect to the login page + return; + } + + var productId = "100010090091"; + var url = 'http://127.0.0.1:8091/api/mall/create_pay_order'; + + var requestBody = { + productId: productId + }; + + fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` // Include the token in the request headers + }, + body: JSON.stringify(requestBody) // Convert the request body to a JSON string + }) + .then(response => response.json()) // Parse the JSON response + .then(json => { + if (json.code === "0000") { // Assume success code is "0000" + alert(json.data); + } else { + alert("code:"+json.code +" "+json.info) + console.error('Error:', json.info); // Output error information + } + }) + .catch(error => console.error('Error:', error)); +}); +``` + +
+ +
+ +- 登录成功后可以通过浏览器 F12 查看到登录的 Token,如果要取消登录,可以操作代码把 Token 删掉。 +- 登录成功后就可以点击下单了。默认代码的权限配置的是只有 xiaofuge 可以下单,liergou不能下单。 + +#### 2.1 下单通过 + +
+ +
+ +```java +24-12-15.11:26:48.606 [http-nio-8091-exec-6] INFO MallController - 商品下单,根据商品ID创建支付单开始 userName:xiaofuge productId:100010090091 +24-12-15.11:26:57.721 [http-nio-8091-exec-7] INFO JwtAuthenticationTokenFilter - authToken:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzQyMzMwMDYsInVzZXJuYW1lIjoieGlhb2Z1Z2UifQ.Dm1Mi_lmm-O9MTte77252ATzNca_2s5bZG_90mdq-48 +24-12-15.11:26:59.069 [http-nio-8091-exec-8] INFO JwtAuthenticationTokenFilter - authToken:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzQyMzMwMDYsInVzZXJuYW1lIjoieGlhb2Z1Z2UifQ.Dm1Mi_lmm-O9MTte77252ATzNca_2s5bZG_90mdq-48 +``` + +#### 2.2 下单拒绝 + +
+ +
+ +```java +24-12-15.11:26:59.074 [http-nio-8091-exec-8] INFO MallController - 商品下单,根据商品ID创建支付单开始 userName:xiaofuge productId:100010090091 +24-12-15.11:27:50.157 [http-nio-8091-exec-9] INFO AuthController - 登录用户:liergou +24-12-15.11:27:50.393 [http-nio-8091-exec-1] INFO JwtAuthenticationTokenFilter - authToken:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzQyMzMzMDAsInVzZXJuYW1lIjoibGllcmdvdSJ9.mVRzMx9tLj6A-oEDRElZwfRslhmP5AE0gQGeA6oI0N4 +24-12-15.11:27:51.438 [http-nio-8091-exec-3] INFO JwtAuthenticationTokenFilter - authToken:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzQyMzMzMDAsInVzZXJuYW1lIjoibGllcmdvdSJ9.mVRzMx9tLj6A-oEDRElZwfRslhmP5AE0gQGeA6oI0N4 +24-12-15.11:27:51.449 [http-nio-8091-exec-3] ERROR AppAccessDeniedHandler - access error +org.springframework.security.access.AccessDeniedException: Access Denied +``` + +- 如日志,当权限拦截后,就会弹出指定的错误码信息。 +- 权限拦截是在 AppAccessDeniedHandler 实现类中指定的错误码。 diff --git a/docs/md/road-map/springcloud-bus.md b/docs/md/road-map/springcloud-bus.md new file mode 100644 index 000000000..2d1942874 --- /dev/null +++ b/docs/md/road-map/springcloud-bus.md @@ -0,0 +1,422 @@ +--- +title: SpringCloud Bus +lock: need +--- + +# SpringCloud Bus 消息总线 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在互联网公司中开发的项目经常有一种场景,是在不重启应用的情况下,变更应用中某个属性信息的值。比如,我们为系统新增加允许外部调用接入的SC渠道值,测试阶段验证名单PIN、持续发布上线后的切量。这些东西都是不重启应用的情况下,动态做配置变更,那这样的东西在 SpringCloud 有什么现成的组件可以使用呢? + +
+ +
+ +**在大厂这个组件叫什么?** + +这个东西它不同于 Redis,而是把配置写到本地类对应的属性上。而不是像 Redis 那样从一个统一的地方每次去取使用。在大厂中我们管这个组件叫统一配置中,专门应对分布式工程中类对应属性的值的控制。 + +在小傅哥的大营销项目中,也带着大家实现过这样一款组件,叫[DCC](https://bugstack.cn/md/project/big-market/api/%E7%AC%AC29%E8%8A%82%EF%BC%9A%E5%88%86%E5%B8%83%E5%BC%8F%E5%8A%A8%E6%80%81%E9%85%8D%E7%BD%AE%E6%B4%BB%E5%8A%A8%E9%99%8D%E7%BA%A7.html),基于 Zookeeper + AOP 切面实现。 + +那么我们本节来看看 SpringCloud 是如何来处理这样一个场景的。 + +## 一、组件介绍 + +Spring Cloud Bus 将分布式系统的节点与轻量级消息代理相链接。然后可以使用它来广播状态更改(例如配置更改)或其他管理指令。该项目包含 AMQP 和 Kafka 代理实现。 + +
+ +
+ +在微服务架构中,通常使用轻量级的消息代理来创建一个共享的消息主题,让所有微服务实例都可以连接到这个主题上。因为这个主题中的消息会被所有实例监听和消费,因此通常称之为“消息总线”。连接到总线的每个实例都可以轻松地广播消息,以便所有其他连接该主题的实例能够接收到这些信息。 + +## 二、测试工程 + +小傅哥这里搭建了一套用于测试验证 SpringCloud Bus 消息总线的服务。 + +
+ +
+**工程**:[https://github.com/fuzhengwei/xfg-dev-tech-springcloud-bus](https://github.com/fuzhengwei/xfg-dev-tech-springcloud-bus) - `你可以把工程fork到你的github仓库,之后做后面的操作。` + +- 环境要求;jdk 1.8、maven 3.8.x、kafka - 提供了 docker 安装脚本在 docs 下。之后还有一个 [natapp](https://natapp.cn/) 做内网穿透。 +- 模块职责;config-bus 配置了整套消息总线所需的服务模块,一个是 eureka 的 registry 注册中心,一个是 SpringCloud Bus 消息总线的服务 server。kafka 是通用的模块,便于统一配置。xfg-dev-tech-app 是测试工程模块。 + +## 三、环境安装 + +本节的案例工程会需要用到 Kafka、RabbitMQ,所以需要安装这两套环境。 + +
+ +
+ +
+ +
+ +- Mac 电脑会比较好安装一些,直接在 IntelliJ IDEA 点击小绿色按钮即可完成安装。安装完成后进入 [http://localhost:9000/#!/2/docker/containers](http://localhost:9000/#!/2/docker/containers)- 可看到 Kafka、RabbitMQ 运行。 +- Windows 需要开启 wsl2 在安装 Docker 之后就可以安装 docker 使用了。 +- 如果本机电脑配合低或者比较旧不好安装,推荐使用云服务器进行操作。云服务器就相当于你的一个远程电脑了,非常适合部署这些环境,同时怎么这套都不会影响你的本地环境。[https://618.gaga.plus - 推荐2c4g云服务。 + +## 四、功能实现 + +### 1. config-bus-kafka + +```java +@Configuration +@PropertySource("classpath:system.properties") +public class KafkaConfig { +} +``` + +```java +spring.kafka.bootstrap-servers=127.0.0.1:9092 + +spring.kafka.producer.retries=0 +spring.kafka.producer.batch-size=16384 +spring.kafka.producer.buffer-memory=33554432 +spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer +spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer + +spring.kafka.consumer.group-id=springcloud-config-bus-group +spring.kafka.consumer.auto-offset-reset=earliest +spring.kafka.consumer.enable-auto-commit=false +spring.kafka.consumer.auto-commit-interval=100 +spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer +spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer +``` + +- 做一个统一的 kafka 配置 model,让其他模块引入。 + +### 2. config-bus-registry + +```java +package cn.bugstack.xfg.dev.tech; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; + +@SpringBootApplication +@EnableEurekaServer +public class ConfigBusRegistryApplication { + + public static void main(String[] args) { + SpringApplication.run( ConfigBusRegistryApplication.class, args ); + } + +} +``` + +```java +server: + port: 7397 + +spring: + application: + name: eureka-server + +eureka: + instance: + # 使用 ip 代替实例名 + prefer-ip-address: true + # 实例的主机名 + hostname: ${spring.cloud.client.ip-address} + # 实例的 ID 规则 + instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} + client: + # 是否向注册中心注册自己 + registerWithEureka: false + # 是否向注册中心获取注册信息 + fetchRegistry: false + serviceUrl: + # 注册中心地址 + defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ +``` + +- 这部分是一个 eureka 的服务端,让注册中心和客户端,都被 eureka 管理。 + +### 3. config-bus-server + +```java +package cn.bugstack.xfg.dev.tech; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.config.server.EnableConfigServer; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; + +@SpringBootApplication +@EnableConfigServer +@EnableEurekaClient +public class ConfigBusServerApplication { + + public static void main(String[] args) { + SpringApplication.run(ConfigBusServerApplication.class, args); + } + +} +``` + +```java +# 端口 +server: + port: 8000 + +spring: + application: + name: config-bus-server + cloud: + config: + server: + git: + # 仓库地址 + uri: https://github.com/fuzhengwei/xfg-dev-tech-springcloud-bus + # 对应 {label} 部分,即 Git 的分支 + label: master + # 仓库文件夹名称,多个以逗号分隔 + search-paths: config-bus/config-repo + # git 仓库用户名(公开库可以不用填写) + username: + # git 仓库密码(公开库可以不用填写) + password: + bus: + # 开启消息跟踪 + enabled: true + trace: + enabled: true + kafka: + consumer: + group-id: config-bus-server-group + +eureka: + instance: + prefer-ip-address: true + hostname: ${spring.cloud.client.ip-address} + instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} + client: + serviceUrl: + defaultZone: http://${eureka.instance.hostname}:7397/eureka/ + +management: + endpoints: + web: + exposure: + # 开启刷新端点 + include: bus-refresh +``` + +- git 部分的配置,如注释说明。之后你要修改为自己的 Github 地址,这样你在修改配置时候,才能做 webhook 调用变更。 +- kafka 是默认的消费id,不需要修改。 +- management 需要开启 bus-refresh 刷新断点。 + +### 4. config-repo + +system-dev.properties + +```java +hello=I'm xfg dev config 09 +hi=I'm xfg dev config 08 +``` + +- 这一层是配置文件,后面在你提交代码修改的时候,工程里也会一起修改。 + +### 5. xfg-dev-tech-app + +#### 5.1 动态配置 + +```java +@RestController +@RefreshScope +public class ConfigClientController { + + @Value("${hello}") + private String hi; + + @RequestMapping("/hi") + public String hi() { + return this.hi; + } + +} +``` + +验证时访问地址;[http://127.0.0.1:9000/hi](http://127.0.0.1:9000/hi) + +#### 5.2 刷新配置 + +```java +package cn.bugstack.xfg.dev.tech.trigger; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; + +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +@Slf4j +@RestController +public class GitHubWebhookController { + + @PostMapping("/webhook") + public String handleGitWebhook(@RequestBody String payload) { + try { + ObjectMapper mapper = new ObjectMapper(); + JsonNode content = mapper.readTree(payload); + + log.info("收到 webhook {} 更新配置通知", content.get("pusher")); + + // 创建URL对象 + URL url = new URL("http://127.0.0.1:8000/actuator/bus-refresh"); + + // 打开连接 + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + + // 设置请求方法为POST + connection.setRequestMethod("POST"); + + // 开启输入输出流 + connection.setDoOutput(true); + + // 设置请求头,如果需要,可以设置Content-Type等 + connection.setRequestProperty("Content-Type", "application/json"); + + // 获取输出流 + try (OutputStream os = connection.getOutputStream()) { + // 如果有请求体数据,也可以在这里写入 + // String jsonInputString = "{\"key\": \"value\"}"; + // os.write(jsonInputString.getBytes("utf-8")); + os.flush(); + } + + // 发送请求并获取响应码 + int responseCode = connection.getResponseCode(); + + log.info("调用 actuator/bus-refresh 更新全局配置完成 code:{}", responseCode); + + } catch (Exception e) { + e.printStackTrace(); + } + + return "done"; + } + +} +``` + +- 做一个 webhook 接口,github 回调后,调用 `http://127.0.0.1:8000/actuator/bus-refresh` 刷新配置。 +- 也可以手动访问 `http://127.0.0.1:8000/actuator/bus-refresh` 自己刷新配置验证。 + +## 五、功能验证 + +### 1. 前置配置 + +#### 1.1 内网穿透 + +获取 natapp 免费隧道 authtoken,[https://natapp.cn/tunnel/lists](https://natapp.cn/tunnel/lists) 配置到工程中。 + +
+ +
+ +- 注意:免费隧道配置端口为9000,因为是要把本地这个 9000 端口的服务,映射出去。 + +
+ +
+ +- 启动 natapp 后,会得到一个公网域名地址。这个地址免费的会不断地变化,测试的时候注意。 + +#### 1.2 webhook 配置 + +进入 GitHub 工程中,Settings -> Webhooks 页面。地址:[https://github.com/fuzhengwei/xfg-dev-tech-springcloud-bus/settings/hooks/517530722](https://github.com/fuzhengwei/xfg-dev-tech-springcloud-bus/settings/hooks/517530722) - `你的和我的不同` + +
+ +
+ +- 拿到公网地址后,配置 webhook。如图配置完点击下面完成。更新的时候点击 update webhook。 + +### 2. 启动服务 + +陆续的启动;config-bus-registry、config-bus-server、xfg-dev-tech-app。 + +### 3. 服务测试 + +#### 3.1 第1次,访问配置接口 + +地址:[http://127.0.0.1:9000/hi](http://127.0.0.1:9000/hi) + +```java +I'm xfg dev config 09 +``` + +#### 3.2 更新线上配置 + +
+ +
+ +- 你可以在线更新配置,也可以本地更新配置后提交代码到 github。 +- 变更后点击 commit changes + +
+ +
+ +- 查看到 webhook 推送的记录。是成功的。 + +
+ +
+ +- 查看日志变更记录。`webhook {"name":"fuzhengwei","email":"fuzhengwei@users.noreply.github.com"} 更新配置通知` + +#### 3.2 第2次,访问配置接口 + +地址:[http://127.0.0.1:9000/hi](http://127.0.0.1:9000/hi) + +```java +I'm xfg dev config 10 +``` + +- 配置已经从09变更为10,代表测试成功了。 +- 另外你还可以访问 [http://127.0.0.1:8000/system/dev](http://127.0.0.1:8000/system/dev) 查看整体的配置信息。 + +```java +{ + "name": "system", + "profiles": [ + "dev" + ], + "label": null, + "version": "fccaf3233af6d0ae16571d2c907ff87eaf1c8946", + "state": null, + "propertySources": [ + { + "name": "https://github.com/fuzhengwei/xfg-dev-tech-springcloud-bus/config-bus/config-repo/system-dev.properties", + "source": { + "hello": "I'm xfg dev config 10", + "hi": "I'm xfg dev config 08" + } + } + ] +} +``` + + + + + diff --git a/docs/md/road-map/springcloud-feign.md b/docs/md/road-map/springcloud-feign.md new file mode 100644 index 000000000..f72cdef72 --- /dev/null +++ b/docs/md/road-map/springcloud-feign.md @@ -0,0 +1,229 @@ +--- +title: SpringCloud Feign +lock: need +--- + +# SpringCloud Feign + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在过往几年中在帮助大家学习编程中,我会看到不少新人伙伴在项目的时候会纠结,这个是RPC(Dubbo)的、这个是 SpringCloud(Feign)的,这个是 MVC 的、这个是 DDD 的。但其实不用纠结一点都。 + +
+ +
+ +**其实这些东西都是一通百通** + +一个能把 Dubbo 用的透彻的人,换成 Feign 就是小儿科。一个能把 MVC 搞的明明白白的人,换成 DDD 那就是手到擒来。之所以有人会觉得换一下就不会了,是因为原本另外一个就没用明白。各类的工具、框架、组件,在编程中都有非常多的同类替代品。就算即使是 RPC 也是有非常多的产品,尤其中大厂中还有很多自研的组件。 + +那么今天小傅哥就再分享下 SpringCloud Feign 结合到 DDD 战术设计六边形架构中的使用方式。 + +## 一、组件介绍 + +官网:[https://spring.io/projects/spring-cloud](https://spring.io/projects/spring-cloud) + +Spring Cloud 为开发人员提供了一系列工具,用于快速构建分布式系统中的一些常见模式(例如配置管理、服务发现、断路器、智能路由、微代理、控制总线、微服务和契约测试)。分布式系统的协调产生了样板模式,使用 Spring Cloud,开发人员可以快速建立实现这些模式的服务和应用程序。它们可以在任何分布式环境中很好地工作,包括开发人员自己的笔记本电脑、裸机数据中心和 Cloud Foundry 等托管平台。 + +本节会涉及到 Eureka 注册中心、Feign 简化微服务 HTTP 调用组件; + +
+ +
+ +- Eureka 是一个由 Netflix 开发的服务发现工具,主要用于云端分布式系统中。它允许各个服务在启动时注册自己的信息,并能够动态地发现其他服务的位置和状态,从而实现负载均衡和故障转移。Eureka 在微服务架构中扮演着重要角色,帮助提高系统的可用性和弹性。其易于集成的特性使其成为许多企业在构建复杂分布式应用时的首选工具之一。 +- Feign 是一个受欢迎的 Java HTTP 客户端库,主要用于简化服务间的 HTTP 通信。它通过使用注解来定义 HTTP 请求接口,使得开发者可以更直观地调用远程服务。Feign 提供了可插拔的编码器和解码器,支持多种数据格式,并且可以与 Spring Cloud 集成,方便地实现负载均衡和服务发现。其简洁的 API 和高度的可扩展性,使得 Feign 成为微服务架构中常用的工具之一。 + +## 二、测试工程 + +小傅哥这里给搭建了一套测试 Feign 案例的六边形系统架构; + +
+ +
+ +**工程**:[https://github.com/fuzhengwei/xfg-dev-tech-springcloud-feign](https://github.com/fuzhengwei/xfg-dev-tech-springcloud-feign) + +- eureka 模块,包括;server、client 端,server 端是注册中心,用于接收注册上来的服务接口,统一管理负载。client 端是为了模拟提供一个服务接口。你可以任何其他工程来提供 feign 客户端接口,也就是接口的提供方。这样消费方就可以通过注册中心调用了。 +- infrastructure 是基础设施层,在六边形架构中,用于处理调用外部的接口,内部的数据库,缓存等这样的基础功能。在 DDD 的软件设计方法中,会把这部分基础的东西从功能实现中拆分出来。 +- domain 和 infrastructure 是依赖倒置关系,所有 domain 要实现的服务需要的基础数据,都可以通过依赖倒置方式处理。也就是 domain 领域层定义接口,之后由基础设置层做功能实现。在通过 Spring 注入到 domain 领域中 service 具体的类中,这样就可以使用。 +- trigger 名词为触发器,用于承载给外部提供的服务能力,包括;http接口、rpc接口、job任务等,这些要调用我们服务能力的方式,都可以通过 trigger 层来实现。 + +>更多的关于 DDD 六边形架构,可以从编程路书中学习;[https://bugstack.cn/md/road-map/ddd-guide-03.html](https://bugstack.cn/md/road-map/ddd-guide-03.html) + +## 三、功能实现 + +### 1. 引入 spring cloud + +```java + + org.springframework.boot + spring-boot-starter-parent + 2.0.6.RELEASE + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Finchley.SR2 + pom + import + + + com.alibaba + fastjson + 2.0.28 + + + +``` + +- 在官网中有对应版本关系可以参考:[https://spring.io/projects/spring-cloud](https://spring.io/projects/spring-cloud) + +### 2. eureka-server + +在公司中 eureka-server 是统一一套的,我们个人学习需要搭建一个这样的工程。 + +#### 2.1 yml 配置 + +```java +server: + port: 7397 + +eureka: + instance: + hostname: localhost + client: + registerWithEureka: false + fetchRegistry: false + serviceUrl: + defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ + +spring: + application: + name: eureka-server +``` + +- 添加 eureka 配置信息。这个端口 7397 后面其他的客户端调用就连接这个端口。 + +#### 2.2 启动类 + +```java +package cn.bugstack.xfg.dev.tech; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; + +@SpringBootApplication +@EnableEurekaServer +public class EurekaServerApplication { + + public static void main(String[] args) { + SpringApplication.run( EurekaServerApplication.class, args ); + } + +} +``` + +### 3. Eureka-client + +#### 3.1 yml 配置 + +```java +server: + port: 8002 + +spring: + application: + name: eureka-client-api + +eureka: + client: + serviceUrl: + defaultZone: http://localhost:7397/eureka/ +``` + +- 模拟启动一个客户端接口,并填写注册中心地址。 + +#### 3.2 api 接口 + +```java +@EnableEurekaClient +@RestController +public class TestApiController { + + @Value("${server.port}") + private int port; + + @RequestMapping(path = "/api/queryUserInfo", method = RequestMethod.GET) + public String queryUserInfo(@RequestParam String userId) { + return "Hi 小傅哥,微信公众号:bugstack虫洞栈 | " + userId + " >: from eureka client port: " + port; + } + +} +``` + +- 添加一个客户端的接口,这里需要注意的是添加了一个 `@EnableEurekaClient` 注解。这样这个接口就可以被 eureka 注册中心管理。 +- 如果你有学习过小傅哥的[API网关](https://bugstack.cn/md/assembly/api-gateway/api-gateway.html)项目,那么就可以了解这样的设计,是如何完成接口注册的。 + +### 4. 接口使用 - infrastructure + +在工程的基础设置层配置对外部的接口调用; + +
+ +
+ +- 如果没有 fegin 我们最开始调用外部的 http 接口时候,就需要写很多的关于 http 的调用,这个过程是比较复杂的。在使用 feign 后,这个事就变得简单了,同时还增加了负载和故障迁移的能力。 + +- 当然现在调用http的方式不只是以前的刀耕火种了,可以用 okttp、retrofit2 这样的框架处理 http 调用过程。如下这样的调用方式也是非常好维护的。 + +```java +@GET("cgi-bin/token") +Call getToken(@Query("grant_type") String grantType, +@Query("appid") String appId, +@Query("secret") String appSecret); +``` + +## 四、测试验证 + +### 1. eureka 启动 + +
+ +
+ +
+ +
+ +- 分别启动 eureka 的服务端和测试的客户端,提供接口能力。 +- 启动后访问 eureka 服务端:[http://127.0.0.1:7397/](http://127.0.0.1:7397/) + +### 2. 测试工程启动 + +
+ +
+ +```java +fuzhengwei@MacBook-Pro xfg-dev-tech-springcloud-feign % curl http://127.0.0.1:8091/api/v1/query_user_info +Hi 小傅哥,微信公众号:bugstack虫洞栈 | xfg >: from eureka client port: 8002% +``` + +```java +]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@680aded0 +24-11-24.10:32:49.968 [PollingServerListUpdater-0] INFO ChainedDynamicProperty - Flipping property: eureka-client-api.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647 +``` + +- 启动应用测试工程,启动后可以访问验证。 +- 验证接口:`http://127.0.0.1:8091/api/v1/query_user_info` \ No newline at end of file diff --git a/docs/md/road-map/springcloud-stream.md b/docs/md/road-map/springcloud-stream.md new file mode 100644 index 000000000..52e735683 --- /dev/null +++ b/docs/md/road-map/springcloud-stream.md @@ -0,0 +1,436 @@ +--- +title: SpringCloud Stream +lock: need +--- + +# SpringCloud Stream + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在我们日常开发中,有很多的同类共性功能组件,如;MQ 的有 Kafka、RabbitMQ,RPC 的有 GRpc、Dubbo。那如果我们想让服务可以平滑的从一套组件切换到另外一套,应该如何处理呢?🤔 + +
+ +
+ +**这样的东西我也做过** + +在我工作的公司,近10年的发展中,Redis 的缓存服务组件陆续的变换了3、4款,目前有2套最终稳定共用的。那么我为此开发了一款缓存中间件,可以做到动态切换、读写控制、监控管理,可以非常方便的迁移和升级。 + +那么,在我们使用 MQ 的时候,如果在不改变系统工程代码的情况下,该怎样优雅的从一套MQ迁移到另外一套呢?今天小傅哥就带着大家来办这样一个事。 + +## 一、组件介绍 + +官网:[https://spring.io/projects/spring-cloud-stream](https://spring.io/projects/spring-cloud-stream) + +Spring Cloud Stream 是一个用于构建与共享消息系统连接的高度可扩展的事件驱动微服务的框架。 + +该框架提供了一个灵活的编程模型,该模型建立在已建立且熟悉的 Spring 习语和最佳实践之上,包括对持久发布/订阅语义、消费者组和有状态分区的支持。 + +
+ +
+ +Spring Cloud Stream 支持对接的 MQ 包括:RabbitMQ、Kafka、RocketMQ、Azure Service Bus 等。 + +## 二、测试工程 + +小傅哥这里搭建了一套测试 MQ 案例的六边形架构; + +
+ +
+ +**工程**:[https://github.com/fuzhengwei/xfg-dev-tech-springcloud-stream](https://github.com/fuzhengwei/xfg-dev-tech-springcloud-stream) + +- docs 提供了使用 docker 安装 kafka、rabbitmq 的环境脚本。docker 安装和使用教程:[https://bugstack.cn/md/road-map/docker.html](https://bugstack.cn/md/road-map/docker.html) +- trigger 是六边形架构的触发器层,用于接收 MQ 消息。接收后就可以通过调用 domain 领域服务,完成功能的串联。另外 trigger 作为触发器,不只是可以接收 MQ 消息,还可以提供HTTP接口、RPC接口,Job任务调度。 +- domain 领域层是具体的业务逻辑实现层,当业务逻辑中有需要发MQ消息的时候,则可以通过 infrastructure 基础设施层通过依赖倒置实现 domain 领域层 adapter 适配器中的接口,完成消息的发送。 + +## 三、环境安装 + +本节的案例工程会需要用到 Kafka、RabbitMQ,所以需要安装这两套环境。 + +
+ +
+ +
+ +
+ +- Mac 电脑会比较好安装一些,直接在 IntelliJ IDEA 点击小绿色按钮即可完成安装。安装完成后进入 [http://localhost:9000/#!/2/docker/containers](http://localhost:9000/#!/2/docker/containers)- 可看到 Kafka、RabbitMQ 运行。 +- Windows 需要开启 wsl2 在安装 Docker 之后就可以安装 docker 使用了。 +- 如果本机电脑配合低或者比较旧不好安装,推荐使用云服务器进行操作。云服务器就相当于你的一个远程电脑了,非常适合部署这些环境,同时怎么这套都不会影响你的本地环境。[https://618.gaga.plus](https://618.gaga.plus) - 推荐2c4g云服务。 + +## 四、功能验证 + +在做项目的案例前,我们可以先做下 SpringCloud Stream 对接 Kafka、RabbitMQ 的案例,有了这个基础在做整个工程的案例就更容易了。 + +### 1. pom 配置 + +```java + + org.springframework.cloud + spring-cloud-dependencies + Finchley.SR2 + pom + import + + + + org.springframework.cloud + spring-cloud-stream-binder-kafka + + + + org.springframework.cloud + spring-cloud-stream-binder-rabbit + +``` + +- 首先在 [spring-cloud-stream](https://spring.io/projects/spring-cloud-stream) 组件官网中是有一套对应的 SpringBoot、SpringCloud 版本匹配的关系的。如果你需要升级版本可以参考官网中的关系。 +- 这里的 kafka、rabbitmq,使用的时候要分别使用,把另外一套不使用的注释掉就可以。 +- 这里我们注释掉 rabbit 的引入,只测试 kafka 部分。 + +### 2. yml 配置 + +```java +spring: +# rabbitmq: +# addresses: 192.168.1.108 +# port: 5672 +# username: admin +# password: admin +# listener: +# simple: +# prefetch: 10 # 每次投递n个消息,消费完在投递n个 + kafka: + bootstrap-servers: 192.168.1.105:9092 + producer: + # 发生错误后,消息重发的次数。 + retries: 1 + #当有多个消息需要被发送到同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算。 + batch-size: 16384 + # 设置生产者内存缓冲区的大小。 + buffer-memory: 33554432 + acks: 1 + consumer: + # 自动提交的时间间隔 在spring boot 2.X 版本中这里采用的是值的类型为Duration 需要符合特定的格式,如1S,1M,2H,5D + auto-commit-interval: 1S + # 该属性指定了消费者在读取一个没有偏移量的分区或者偏移量无效的情况下该作何处理: + # latest(默认值)在偏移量无效的情况下,消费者将从最新的记录开始读取数据(在消费者启动之后生成的记录) + # earliest :在偏移量无效的情况下,消费者将从起始位置读取分区的记录 + auto-offset-reset: earliest + # 是否自动提交偏移量,默认值是true,为了避免出现重复数据和数据丢失,可以把它设置为false,然后手动提交偏移量 + enable-auto-commit: false + cloud: + stream: + bindings: + output: + destination: ${mq.topic.user} + input: + destination: ${mq.topic.user} + myoutput: + destination: ${mq.topic.user02} + myinput: + destination: ${mq.topic.user02} + +mq: + topic: + user: xfg-topic + user02: xfg-topic-02 +``` + +- SpringCloud Stream,支持你以统一一套的方式配置不同的 MQ 渠道。需要使用 kafka、rabbitmq,就可以分别配置。 +- 之后你可以看到,cloud.stream.bindings 可以指定 input、output,这个既可以使用本身 SpringCloud Stream 提供的,也可以自定义。通过这样的一个方式,让所有的 MQ 都以这样的方式进行输入、输出对接。 +- 这里我们注释掉 rabbitmq 只测试 kafka + +### 3. 案例代码 + +#### 3.1 自定义输入输出key + +```java +public interface MyProcessor { + + String INPUT = "myinput"; + String OUTPUT = "myoutput"; + + @Input(INPUT) + SubscribableChannel input(); + + @Output(OUTPUT) + MessageChannel output(); +} +``` + +#### 3.2 单测类 + +##### 3.2.1 默认方式 + +```java +Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest +public class StreamTest01 { + + @Autowired + private MessageProducer producer; + + @Test + public void test_publish() throws InterruptedException { + for (int i = 0; i < 2; i++) { + producer.send("mq 消息,哈喽哇!"); + } + + new CountDownLatch(1).await(); + } + + @Component + @EnableBinding(Source.class) + static class MessageProducer { + + @Autowired + private Source source; + + public void send(String message) { + source.output().send(MessageBuilder.withPayload(message).build()); + } + + } + + @Component + @EnableBinding({Sink.class}) + static class MessageConsumer { + + @StreamListener(Sink.INPUT) + public void onMessage(String message) { + System.out.println("@测试 -> " + message); + } + + } + +} +``` + +```java +@测试 -> mq 消息,哈喽哇! +@测试 -> mq 消息,哈喽哇! +@测试 -> mq 消息,哈喽哇! +@测试 -> mq 消息,哈喽哇! +``` + +- 使用组件中提供的 Source、Sink 带有的 input、output 方式处理消息。 + +##### 3.2.2 自定义方式 + +```java +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest +public class StreamTest02 { + + @Autowired + private MessageProducer producer; + + @Test + public void test_publish() throws InterruptedException { + for (int i = 0; i < 2; i++) { + producer.send("mq 消息,哈喽哇!"); + } + + new CountDownLatch(1).await(); + } + + @Component + @EnableBinding(MyProcessor.class) + static class MessageProducer { + + @Autowired + private MyProcessor source; + + public void send(String message) { + source.output().send(MessageBuilder.withPayload(message).build()); + } + + } + + @Component + @EnableBinding({MyProcessor.class}) + static class MessageConsumer { + @StreamListener(MyProcessor.INPUT) + public void onMessage(String message) { + System.out.println("@测试 -> " + message); + } + + } + +} +``` + +```java +@测试 -> mq 消息,哈喽哇! +@测试 -> mq 消息,哈喽哇! +@测试 -> mq 消息,哈喽哇! +@测试 -> mq 消息,哈喽哇! +``` + +- 自定义了 MyProcessor 可以自定设定 input、output 的名称。我这里设定的是 myinput、myoutput + +## 五、工程案例 - 六边形架构 + +### 1. 消息事件定义 + +```java +public class UserMessageEvent extends BaseEvent { + + @Value("${mq.topic.user}") + private String topic; + + @Override + public EventMessage buildEventMessage(UserMessage data) { + return EventMessage.builder() + .id(RandomStringUtils.randomNumeric(11)) + .timestamp(new Date()) + .data(data) + .build(); + } + + @Override + public String topic() { + return topic; + } + + /** + * 要推送的事件消息,聚合到当前类下。 + */ + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class UserMessage { + private String userId; + private String userName; + private String userType; + } + +} +``` + +- 在 domain 领域层,adapter 适配器中定义消息事件。这也就是一个规范,当有基础层需要发送消息的时候,则需要通过定义的消息结构来处理。也就是我们在领域层定义标准,之后由基础设施层完成处理。 + +### 2. 基础层添加发送工具 + +```java +@Slf4j +@Component +@EnableBinding(Source.class) +public class EventPublisher { + + @Autowired + @Qualifier(Source.OUTPUT) + private MessageChannel messageChannel; + + @Autowired + private Source source; + + public void publish(String topic, BaseEvent.EventMessage eventMessage) { + try { + String messageJson = JSON.toJSONString(eventMessage); + source.output().send(MessageBuilder.withPayload(messageJson).build()); + log.info("发送MQ消息 topic:{} message:{}", topic, messageJson); + } catch (Exception e) { + log.error("发送MQ消息失败 topic:{} message:{}", topic, JSON.toJSONString(eventMessage), e); + throw e; + } + } + +} +``` + +- 工程中所有的消息发送方式都是统一一套的,所以我们在基础层定义出发送消息的方法。各个模块需要使用的时候,直接调用就可以了。 + +### 3. 发送事件消息 + +```java +@Service +public class UserRepository extends UserMessageEvent implements IUserRepository { + + @Resource + private EventPublisher publisher; + + @Override + public void doSaveUser(UserEntity userEntity) { + // 推送消息 + publisher.publish(this.topic(), this.buildEventMessage(UserMessageEvent.UserMessage.builder() + .userId(userEntity.getUserId()) + .userName(userEntity.getUserName()) + .userType(userEntity.getUserTypeVO().getDesc()) + .build())); + } + +} +``` + +- 在基础设施层实现了领域层定义的方法后,就可以在完成业务领域服务功能后,开始推送消息了。 + +### 4. 监听消费 + +```java +@Slf4j +@Component +@EnableBinding({Sink.class}) +public class MessageListener { + + @StreamListener(Sink.INPUT) + public void onMessage(String message) { + log.info("接收消息:{}", message); + } + +} +``` + +- 监听消息,配置一个 INPUT,这样就可以接收到消息了。 + +### 5. 测试验证 + +```java +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserServiceTest { + + @Resource + private IUserService userService; + + @Test + public void test_register() throws InterruptedException { + while (true) { + UserEntity userEntity = new UserEntity(); + userEntity.setUserId("10001"); + userEntity.setUserName("小傅哥"); + userEntity.setUserTypeVO(UserTypeVO.T8); + + userService.register(userEntity); + Thread.sleep(1500); + } + + } + +} +``` + +```java +24-12-01.13:33:53.003 [main ] INFO AppInfoParser - Kafka version : 1.0.2 +24-12-01.13:33:53.003 [main ] INFO AppInfoParser - Kafka commitId : 2a121f7b1d402825 +24-12-01.13:33:53.043 [main ] INFO EventPublisher - 发送MQ消息 topic:xfg-topic message:{"data":{"userId":"10001","userName":"小傅哥","userType":"架构师"},"id":"89743057693","timestamp":1733031232650} +24-12-01.13:33:54.549 [main ] INFO EventPublisher - 发送MQ消息 topic:xfg-topic message:{"data":{"userId":"10001","userName":"小傅哥","userType":"架构师"},"id":"80224746522","timestamp":1733031234546} +``` + +- 模拟测试持续发送消息。发送后就可以在监听消息的 MessageListener 收到具体的消息数据。 + diff --git a/docs/md/road-map/ssl-httpsok.md b/docs/md/road-map/ssl-httpsok.md index 42b89a20e..acf051569 100644 --- a/docs/md/road-map/ssl-httpsok.md +++ b/docs/md/road-map/ssl-httpsok.md @@ -1,5 +1,5 @@ --- -title: ssl - httpsok +title: 域名证书 ssl - httpsok lock: need --- @@ -58,6 +58,8 @@ lock: need +- 如果验证不成功,可以修改下自己的域名 DNS:`ns1.alidns.com` + ### 步骤5;等待下发
@@ -137,12 +139,14 @@ server { #### 1.2 修改证书 +#### 方式1 + ```java version: '3' # docker-compose -f docker-compose.yml up -d services: nginx: - image: nginx:1.25.3 + image: nginx:alpine container_name: nginx ports: - '443:443' @@ -159,6 +163,35 @@ services: - 脚本映射了 ssl、conf.d 等文件内容。 +#### 方式2 + +```java +# 命令执行 docker-compose up -d +# docker-compose -f docker-compose-nginx.yml up -d +# 自动部署 https https://httpsok.com/doc/faq/docker-nginx.html +version: '3.9' +services: + # yum install -y httpd-tools + nginx: + image: registry.cn-hangzhou.aliyuncs.com/xfg-studio/nginx:1.28.0-alpine # 原镜像 httpsok/nginx:1.28.0-alpine + container_name: nginx + restart: always + ports: + - '443:443' + - '80:80' + environment: + HTTPSOK_TOKEN=https://httpsok.com/console/dashboard 写你的 token curl -s https://get.httpsok.com/ | bash -s 【这里的值】 + volumes: + - ./nginx/logs:/var/log/nginx + - ./nginx/html:/usr/share/nginx/html + - ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf + - ./nginx/conf/conf.d:/etc/nginx/conf.d + - ./nginx/ssl:/etc/nginx/ssl/ + privileged: true +``` + +- 官网说明:[https://httpsok.com/doc/course/deploy-to-nginx-indocker.html](https://httpsok.com/doc/course/deploy-to-nginx-indocker.html) + ### 2. 上传文件
diff --git a/docs/md/road-map/ssl.md b/docs/md/road-map/ssl.md index 4f2614d08..b8b8cbc87 100644 --- a/docs/md/road-map/ssl.md +++ b/docs/md/road-map/ssl.md @@ -1,5 +1,5 @@ --- -title: ssl - freessl +title: 域名证书 ssl - freessl lock: need --- diff --git a/docs/md/road-map/tool.md b/docs/md/road-map/tool.md new file mode 100644 index 000000000..603327e7a --- /dev/null +++ b/docs/md/road-map/tool.md @@ -0,0 +1,36 @@ +--- +title: Tool +lock: need +--- + +# Tool 工具整理 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +## SSH 客户端工具 + +1. [nuoshell](https://www.nuoshell.com/) - 一款免费的专门为 Mac OSX 系统打造的,集多功能于一身的 SSH 客户端工具。 +2. [termius](https://termius.com/) - 含付费Plus功能,但基础功能已够用。可以支持电脑和移动设备使用,包括 SFTP 功能。 +3. [WindTerm](https://github.com/kingToolbox/WindTerm) - 专业的跨平台SSH/Sftp/Shell/Telnet/串口终端。完全免费,可用于商业和非商业用途,无任何限制。 +4. [SSH Config Editor](http://hejki.tilda.ws/ssheditor) - 一款用于管理OpenSSH ssh客户端配置文件的工具。 +5. [ZOC](https://www.emtec.com/zoc/) - ZOC • 适用于 macOS 和 Windows 的 SSH 客户端和终端仿真器。 +6. [SecureCRT](https://mobaxterm.mobatek.net/) - 带有 X11 服务器、选项卡式 SSH 客户端、网络工具等的增强型 Windows 终端。 +7. [Electerm](https://github.com/electerm/electerm) - 开源终端/ssh/telnet/serialport/sftp客户端(linux, mac, win)。 +8. [PuTTY](https://www.putty.org/) - PuTTY 是一个 SSH 和 telnet 客户端,最初由 Simon Tatham 为 Windows 平台开发。PuTTY 是开源软件,提供源代码,由一群志愿者开发和支持。 +9. [FinalShell SSH工具](http://www.hostbuf.com/t/988.html) - FinalShell是一体化的的服务器,网络管理软件,不仅是ssh客户端,还是功能强大的开发,运维工具,充分满足开发,运维需求. +10. [Xterminal](https://www.terminal.icu/) - 不仅是强大的SSH工具,更提供本地控制台,以及更多即将推出的开发相关功能,让您专注于创造卓越的代码。 + +## MySql 客户端工具 + +1. [DBeaver Community - Free Universal Database Tool](https://dbeaver.io/download/) - `MySQL、Azure SQL Server、Apache Ignite...` +2. [Sequel Pro](https://www.sequelpro.com/) - `不太推荐了,有bug` +3. [Sequel Ace](https://apps.apple.com/us/app/sequel-ace/id1518036000?ls=1) - `推荐,是 Sequel Pro 的扩展维护版。免费好用!` +4. [Navicat](https://www.navicat.com.cn/products) - `同好用的就是收费,破解的在公司用可不行` +5. [IntelliJ Datagrip](https://www.jetbrains.com/zh-cn/datagrip/) - `免费使用30天` + +--- + +个人在使用 nuoshell、termius 挺稳又好用。如果你还有好用的客户端,可以点击文末的 `在 GitHub 上编辑此页` 进行提交。这样会记录你的贡献。 diff --git a/docs/md/road-map/trae.md b/docs/md/road-map/trae.md new file mode 100644 index 000000000..3294a349b --- /dev/null +++ b/docs/md/road-map/trae.md @@ -0,0 +1,210 @@ +--- +title: Trae.ai +lock: need +--- + +# Trae.ai - 真好用,码农必备工具! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +有人说程序员这个行业👨🏻‍💻总是在革自己的命,一个个编码 AI 工具的出现,是不已经不需要那么多初级 CRUD 程序员了🤔。但恰恰相反,AI 工具的出现,是把初级程序员,迅速培养到了高级工程师! + +
+ +
+ +`其实 AI 让程序员更牛!` + +以前初学编程看不懂的代码,现在使用AI能动态做解释和提供案例,以前跨语言(java->vue/react)不能做的事情,现在可以搞了。以前不能写的插件(IntelliJ IDEA、谷歌浏览器),现在能实现了。以前写不出的高级感代码,现在随手就拿到全球最优秀的编码方案。 + +今天介绍一款 AI 开发工具 [Trae.ai](https://www.trae.ai/) ,让刚入门编程的找到学习方法,让初级工程也能写出优秀的代码,让高级研发嘎嘎提高效率! + +>文末提供了 AI 应用开发实战项目,想提高 AI 应用编程能力的伙伴,可以获取学习项目。 + +## 一、软件下载 + +官网地址:[https://www.trae.ai/](https://www.trae.ai/) + +
+ +
+ +- Trae 是一个自适应的 AI IDE,它可以改变您的工作方式,与您协作以更快地运行。 +- 在使用的时候,你可以一个工程同时在 IntelliJ IDEA 打开,也使用 Trae 打开。😂 `因为习惯 IntelliJ IDEA,各类调试还是很舒服的。` + +> 同类软件 [Cursor](https://www.cursor.com/cn),不过这个想使用好的模型得付费,Trae 是不需要付费的! + +## 二、使用体验 + +### 1. 提问代码 + +**拖拽代码/文件夹/工程** + +
+ +
+ +**添加代码到对话** + +
+ +
+ +**通过#号,选择要对话的内容** + +
+ +
+ +> 之所以分享这个软件,也是因为很多小白初学编程,拿到一个项目不知道从哪里看。现在你有了这个软件,就可以非常简单的对工程的代码进行提问了。也不需要复制到任何 AI 对话工具了,并且这套软件是免费的。 + +### 2. 生成代码 - 后端 + +这里我们举例,复制掘金发文接口,之后让 Trae.ai 帮我包装; + +#### 2.1 复制接口 + +
+ +
+ +#### 2.2 研发设计 - 话术 + +
+ +
+ +**生成话术,类似于研发设计** + +```java +在 gateway 文件夹下,编写 IJueJinService 类,以 retrofit2 方式包装 curl 请求接口。接口入参仅为必要参数,如;cookie,发文的 Request 对象。 + +curl 如下; + +curl 'https://api.juejin.cn/content_api/v1/article_draft/create?aid=2608&uuid=7058897578062890496' \ + -H 'accept: */*' \ + -H 'accept-language: zh-CN,zh;q=0.9,en;q=0.8' \ + -H 'content-type: application/json' \ + -b 'store-region=cn-bj; store-region-src=uid; __tea_cookie_tokens_2608=%******a51b13e5; uid_tt_ss=7aff2f2394310b3b71f07006a51b13e5; sid_tt=3813572f48984e4b5b3cc7f90733f2e9; sessionid=3813572f48984e4b5b3cc7f90733f2e9; sessionid_ss=3813572f48984e4b5b3cc7f90733f2e9; sid_ucp_v1=1.0.0-KDU4N2NlM2Q2NjFiODhjOGNhZGE5YzVlOTM4ZWZkY2U3ZTc3MzVjMjAKFwjemIC67ozUAxDT_ci_BhiwFDgCQPEHGgJsZiIgMzgxMzU3MmY0ODk4NGU0YjViM2NjN2Y5MDczM2YyZTk; ssid_ucp_v1=1.0.0-KDU4N2NlM2Q2NjFiODhjOGNhZGE5YzVlOTM4ZWZkY2U3ZTc3MzVjMjAKFwjemIC67ozUAxDT_ci_BhiwFDgCQPEHGgJsZiIgMzgxMzU3MmY0ODk4NGU0YjViM2NjN2Y5MDczM2YyZTk' \ + -H 'dnt: 1' \ + -H 'origin: https://juejin.cn' \ + -H 'priority: u=1, i' \ + -H 'referer: https://juejin.cn/' \ + -H 'sec-ch-ua: "Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"' \ + -H 'sec-ch-ua-mobile: ?0' \ + -H 'sec-ch-ua-platform: "macOS"' \ + -H 'sec-fetch-dest: empty' \ + -H 'sec-fetch-mode: cors' \ + -H 'sec-fetch-site: same-site' \ + -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36' \ + -H 'x-secsdk-csrf-token: 00010000000152d838f2c09c65e4feef033c275a8cff940c12228719074fe36f9ce2d18b4d251833ae62ea768117' \ + --data-raw '{"category_id":"0","tag_ids":[],"link_url":"","cover_image":"","title":"测试文章","brief_content":"","edit_type":10,"html_content":"deprecated","mark_content":"","theme_ids":[],"pics":[]}' + +接口返回结果; + +{ + "err_no": 0, + "err_msg": "success", + "data": { + "id": "7489358088379531291", + "article_id": "0", + "user_id": "2058727733595230", + "category_id": "0", + "tag_ids": [], + "link_url": "", + "cover_image": "", + "is_gfw": 0, + "title": "测试文章", + "brief_content": "", + "is_english": 0, + "is_original": 1, + "edit_type": 10, + "html_content": "deprecated", + "mark_content": "", + "ctime": "1743929226", + "mtime": "1743929226", + "status": 0, + "original_type": 0, + "theme_ids": [] + } +} + +根据接口信息封装 DTO 对象,放到 gateway dto 下。 +``` + +#### 2.3 编码效果 + +
+ +
+ +- 生成后,代码会直接写入到你说明的文件夹下,创建好相关的类信息。之后你可以点击全部接受,他会审查代码,如果代码有问题还会检修编写。 + +### 3. 生成代码 - 前端 + +
+ +
+ +- 这是小傅哥实现的一套 AI RAG&MCP 知识库项目,设计的一套页面。这套页面使用了 AI 做了大量的编码。`以前能写前端,但总感觉是屎上雕花,不出活!`这回有 AI 工具,省心多了。 +- AI 对于这类既定的,没有复杂的逻辑和各类框架综合使用的,真的描述一句优化UI,它就`苦吃苦吃`的干活了! + +> 你发现没,你只要写一些描述,它就能很好的干活了。这是因为 AI Agent 智能体会包括;规划、记忆、召回、工具(MCP),来把需求转换为可以看到的代码。 + +## 三、实战项目 + +这是小傅哥最近带着大家做的一套 AI 应用实战项目,《DeepSeek RAG&MCP 增强检索知识库系统》 - 解析文档&Git仓库代码&AI工作流,全程视频手把手教学。 + +RAG:实现了除普通文档知识解析外,增加了 Git 代码库的拉取和解析,并提供操作接口。为工程师做项目开发时,`需求分析`、`研发设计`、`辅助编码`、`代码评审`、`风险评估`、`上线检测`等,做工程交付提效。 + +MCP:用不了多久,各大互联网企业都将大量的推进落地,自有 MCP 服务的实现,用于增强企业 AI 应用的提效能力。因为 MCP 的加入,可以让你;一条命令`帮研发`,调用应用系统日志、排查系统CPU负载、自主选择是否调度数据库信息。也可以一条命令`帮运营`,搞定复杂的SQL执行、导出报表、分析数据、完成促活营销券的自动化配置上架。这就是 MCP的魅力!👍🏻 + +**RAG + MCP = 智能AI工作流,如智能客服,智能编码助手,智能运维工程师等。** + +
+ +
+ +```java +@Test +public void test_weixinNotice_chatMemory() { + System.out.println("\n>>> ASSISTANT: " + chatClient + .prompt(""" + 我需要你帮我生成一篇文章,要求如下; + + 1. 场景为互联网大厂java求职者面试 + 2. 面试管提问 Java 核心知识、JUC、JVM、多线程、线程池、HashMap、ArrayList、Spring、SpringBoot、MyBatis、Dubbo、RabbitMQ、xxl-job、Redis、MySQL、Linux、Docker、设计模式、DDD等不限于此的各项技术问题。 + 3. 按照故事场景,以严肃的面试官和搞笑的水货程序员谢飞机进行提问,谢飞机对简单问题可以回答,回答好了面试官还会夸赞。复杂问题胡乱回答,回答的不清晰。 + 4. 每次进行3轮提问,每轮可以有3-5个问题。这些问题要有技术业务场景上的衔接性,循序渐进引导提问。最后是面试官让程序员回家等通知类似的话术。 + 5. 提问后把问题的答案,写到文章最后,最后的答案要详细讲述出技术点,让小白可以学习下来。 + + 根据以上内容,不要阐述其他信息,请直接提供;文章标题、文章内容、文章标签(多个用英文逗号隔开)、文章简述(100字) + + 将以上内容发布文章到CSDN。 + """) + .advisors(advisor -> advisor + .param(CHAT_MEMORY_CONVERSATION_ID_KEY, "1001") + .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)) + .call() + .content()); + + + System.out.println("\n>>> ASSISTANT: " + chatClient + .prompt(""" + 之后进行,微信公众号消息通知,平台:CSDN、主题:为文章标题、描述:为文章简述、跳转地址:从发布文章到CSDN获取 url + """) + .advisors(advisor -> advisor + .param(CHAT_MEMORY_CONVERSATION_ID_KEY, "1001") + .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)) + .call() + .content()); +} +``` + +- 两轮对话,发文到CSDN,之后推送消息到公众号平台。这两轮对话是配置有记忆功能的,所以可以衔接上下文。 +- 这样的技术,还是非常有必要积累的,因为很多中大厂也都开了 AI 开发工程师的岗位。 diff --git "a/docs/md/spring/develop-spring/2021-06-30-\347\254\25410\347\253\240\357\274\232\346\250\252\345\210\200\350\267\203\351\251\254\357\274\214\345\205\263\344\272\216Bean\345\257\271\350\261\241\344\275\234\347\224\250\345\237\237\344\273\245\345\217\212FactoryBean\347\232\204\345\256\236\347\216\260\345\222\214\344\275\277\347\224\250.md" "b/docs/md/spring/develop-spring/2021-06-30-\347\254\25410\347\253\240\357\274\232\346\250\252\345\210\200\350\267\203\351\251\254\357\274\214\345\205\263\344\272\216Bean\345\257\271\350\261\241\344\275\234\347\224\250\345\237\237\344\273\245\345\217\212FactoryBean\347\232\204\345\256\236\347\216\260\345\222\214\344\275\277\347\224\250.md" index 75cf8e09e..6113d86d4 100755 --- "a/docs/md/spring/develop-spring/2021-06-30-\347\254\25410\347\253\240\357\274\232\346\250\252\345\210\200\350\267\203\351\251\254\357\274\214\345\205\263\344\272\216Bean\345\257\271\350\261\241\344\275\234\347\224\250\345\237\237\344\273\245\345\217\212FactoryBean\347\232\204\345\256\236\347\216\260\345\222\214\344\275\277\347\224\250.md" +++ "b/docs/md/spring/develop-spring/2021-06-30-\347\254\25410\347\253\240\357\274\232\346\250\252\345\210\200\350\267\203\351\251\254\357\274\214\345\205\263\344\272\216Bean\345\257\271\350\261\241\344\275\234\347\224\250\345\237\237\344\273\245\345\217\212FactoryBean\347\232\204\345\256\236\347\216\260\345\222\214\344\275\277\347\224\250.md" @@ -552,7 +552,7 @@ Process finished with exit code 0 ``` - 从测试结果来看,我们的代理类 ProxyBeanFactory 已经完美替换掉了 UserDao 的功能。 -- 虽然看上去这一点实现并不复杂,甚至有点简单。但就是这样一点点核心内容的设计了,解决了所有需要和 Spring 结合的其他框架交互链接问题。*如果对此类内容感兴趣,也可以阅读小傅哥[《中间件设计和开发》](https://bugstack.cn/itstack-ark-middleware/2021/03/31/SpringBoot-%E4%B8%AD%E9%97%B4%E4%BB%B6%E8%AE%BE%E8%AE%A1%E5%92%8C%E5%BC%80%E5%8F%91-%E4%B8%93%E6%A0%8F%E5%B0%8F%E5%86%8C%E4%B8%8A%E7%BA%BF%E5%95%A6.html)* +- 虽然看上去这一点实现并不复杂,甚至有点简单。但就是这样一点点核心内容的设计了,解决了所有需要和 Spring 结合的其他框架交互链接问题。*如果对此类内容感兴趣,也可以阅读小傅哥[《中间件设计和开发》](https://bugstack.cn/md/assembly/middleware/2021-03-31-%E3%80%8ASpringBoot%20%E4%B8%AD%E9%97%B4%E4%BB%B6%E8%AE%BE%E8%AE%A1%E5%92%8C%E5%BC%80%E5%8F%91%E3%80%8B%E4%B8%93%E6%A0%8F%E5%B0%8F%E5%86%8C%E4%B8%8A%E7%BA%BF%E5%95%A6%EF%BC%81.html)* ## 六、总结 diff --git a/docs/md/zsxq/introduce.md b/docs/md/zsxq/introduce.md index 1dfa0cc38..e76dd8cdd 100644 --- a/docs/md/zsxq/introduce.md +++ b/docs/md/zsxq/introduce.md @@ -13,64 +13,106 @@ lock: no ## 一、前言:星球介绍 -知识星球是 [小傅哥](https://bugstack.cn/md/zsxq/about/xiaofuge.html) 的 **付费** 编程学习圈,不同于网上的攒出来几百个T的免费资料,在星球内小傅哥会对你的问题 **1v1** 解答,帮你制定学习方案和规划职业路线。目标是针对性的帮每一个同学,通过星球内的有深度的[高质量原创项目](https://bugstack.cn/md/zsxq/other/join.html),提升编程思维、领悟架构经验、吸收设计模式、掌握开发技巧,不只是为了面试,更是为了给自己的职业生涯续期。 +知识星球是 [小傅哥](https://bugstack.cn/md/zsxq/about/xiaofuge.html) 的技术社群,不同于网上的拼凑出来几百个G的免费资料,而是专门为大家的学习诉求进行的原创。在星球内小傅哥会对你的问题 **1v1** 解答,帮你制定学习方案和规划职业路线。目标是针对性的帮每一个同学,通过星球内的有深度的[高质量原创项目](https://bugstack.cn/md/zsxq/other/join.html),提升编程思维、领悟架构经验、吸收设计模式、掌握开发技巧,不只是为了面试,更是为了给自己的职业生涯续期。 如果你正在迷茫,找不到除了CRUD以外的深度项目、不知道该从哪学习、怎么更好的提升自己、如何让自己更有竞争力,以及怎么把自己的能力在简历上秀出来,星球会给你答案,帮你铺路,让你不在做一个躺平仔!—— *身为码农,多半穷苦,谁想躺平!* 知识星球支持 APP【[安卓](https://a.app.qq.com/o/simple.jsp?pkgname=com.unnoo.quan)/[IOS](https://apps.apple.com/cn/app/xiao-mi-quan/id904106920?l=cn)】、[网页端](https://wx.zsxq.com/dweb2/index/group/48411118851818)和小程序,可随时随地使用。每天早/晚坐地铁花几分钟刷一刷,就能收获学习的幸福感。*可能就是某一次的学习,就能帮助你在面试、述职、答辩中脱颖而出!* +1. 从你加入开始,所有过往的课程和积累内容,你都可以学习。从21年的积累到现在。 +2. 加入有效期1年内再新创作项目,都可以学习。 +3. 过期后,星球内从过期日到过去的内容,全部可以学习。 +4. 即使续费也是有效期内5折续费,续费只是相当于续费新项目和小傅哥的服务。 + **星球 APP / 小程序截图**:
- +
**星球 PC 网页版截图**:
- +
-大家可以下载一个知识星球 APP 来提前体验~ - -## 二、为啥:加入星球? - -加入星球,你可以获得已经在这条路上摸爬滚打多年的架构师,为你提供的如下服务。 +**星球 APP/PC 课程入口**
- +
-### 1. 学习项目 +大家可以下载一个知识星球 APP 来提前体验~ -很多来自中小公司、外包公司或者尚未毕业的本科生、研究生,手里都没有什么能拿的出手的项目,到大厂去刚一下。 +## 二、步骤;使用指引 -而加入星球就可以学习到小傅哥为你编写的在大厂水平以上的实战项目,包括你会学习到:分布式架构、微服务设计、领域驱动设计、设计模式实现、规则引擎决策树、秒杀分段锁、API网关通信等等,只有加入大厂才能学习到的核心技能。 +
+ +
-#### 1.1 业务项目 +## 三、为啥:加入星球? -- [大营销平台系统设计实现](https://bugstack.cn/md/project/big-market/big-market.html) - 进行中👣 -- [OpenAi 大模型应用体系构建 - API-SDK、鉴权、公众号、微信支付](https://bugstack.cn/md/zsxq/project/chatgpt.html) -- [Lottery 分布式抽奖系统 - 基于领域驱动设计的四层架构实践](https://bugstack.cn/md/zsxq/project/lottery.html) -- [Netty+JavaFx实战:仿桌面版微信聊天](https://bugstack.cn/md/zsxq/project/im.html) -- [ChatGPT AI 问答助手 - 小型,对接知识星球](https://bugstack.cn/md/zsxq/project/chatbot-api.html) +加入星球,你可以获得已经在这条路上摸爬滚打多年的架构师,为你提供的如下服务。 -#### 1.2 组件项目 +
+ +
-- [API网关:中间件设计和实践](https://bugstack.cn/md/zsxq/project/api-gateway.html) -- [SpringBoot Starter 中间件设计和开发](https://bugstack.cn/md/zsxq/project/springboot-starter.html) -- [IDEA Plugin 开发手册](https://bugstack.cn/md/zsxq/booklet/idea-plugin.html) +这是一整套的实战项目学习进阶路线,从小白到大佬,全程视频手把手带着从0到1,一步步完成项目的设计、开发和上线。在整套内容学习过程中,小傅哥为你提供了非常好的技术交流社群,及时解决学习问题。还包括调试你的问题代码,带你快速🔜出坑! -#### 1.3 技术小册 +- 首先,这一整套全体系的学习课程比私教培训实惠,更比培训班上万的培训费便宜。可能也就是培训班1天的💰钱,就能学习到这一整套内容了。 +- 之后,你学习的整套课程,就是小傅哥这个架构师自己全部原创编写的。这也就是说,你所提到的任何问题,小傅哥都能给你解答和讨论。 +- 那么,这么实惠的课程,成体系的课程,还是架构师编写的。还有什么可犹豫的,完全可以撸起来了! -- [字节码编程 - ASM、Javassist、Byte-Buddy](https://bugstack.cn/md/zsxq/booklet/bytecode.html) -- [重学Java设计模式](https://bugstack.cn/md/zsxq/booklet/java-design.html) -- [Java 面经手册](https://bugstack.cn/md/zsxq/booklet/java-interview.html) -- [倚天村 • 图解数据结构](https://bugstack.cn/md/zsxq/booklet/data-structures.html) +### 1. 学习项目 + +很多来自中小公司、外包公司或者尚未毕业的本科生、研究生,手里都没有什么能拿的出手的项目,到大厂去刚一下。 -#### 1.4 手撕源码 +而加入星球就可以学习到小傅哥为你编写的在大厂水平以上的实战项目,包括你会学习到:分布式架构、微服务设计、领域驱动设计、设计模式实现、规则引擎决策树、秒杀分段锁、API网关通信等等,只有加入大厂才能学习到的核心技能。 -- [手写Mybatis:渐进式源码实践](https://bugstack.cn/md/zsxq/source-code/develop-mybatis.html) +#### 1.1 课程资源 + +**课程链接**:- 整个课程路线参考【课程日历图📅】,对应的资源链接汇总如下; + +- 创新项目(AI) + - 【3星】[(1.20w) AI MCP Gateway 网关服务系统](https://bugstack.cn/md/project/ai-mcp-gateway/ai-mcp-gateway.html) + - 【3星】[(1.87w) Deepseek RAG、MCP、Agent 智能体](https://t.zsxq.com/Zq7hV) + - 【2星】[(0.11w) OpenAI 代码自动评审组件](https://t.zsxq.com/gYEVX) + - 【3星】[(0.77w) OpenAi(ChatGPT\ChatGLM) 微服务应用体系构建](https://t.zsxq.com/19aSkDvYB) + - 【1星】[(0.12w) ChatGPT AI问答助手](https://t.zsxq.com/zGj7F) + +- 业务项目 + - 【3星】[(1.15w) 拼团交易平台系统 - 微服务&分布式](https://t.zsxq.com/3X9GA) + - 【2星】[(0.6w) 小型支付商城系统 - 双架构开发(带小白入门)](https://t.zsxq.com/BDFJJ) + - 【4星】[(1.41w) 大营销平台系统 - 微服务&分布式](https://t.zsxq.com/199mpn9Lt) + - 【4星】[(1.28w) Lottery DDD分布式抽奖系统](https://t.zsxq.com/qrUSd) + - 【2星】[(0.78w) IM实战(Netty+JavaFx):仿桌面版微信聊天](https://t.zsxq.com/NcPgw) + +- 组件项目 + - 【3星】[(0.21w)本地任务消息组件](https://bugstack.cn/md/zsxq/project/local-task-message.html) + - 【3星】[(0.36w) 通用技术组件 - 🔧扳手工程](https://bugstack.cn/md/zsxq/project/xfg-wrench.html) + - 【2星】[(0.23w) BCP透视业务流程 - 监控系统](https://t.zsxq.com/CVzpL) + - 【2星】[(0.15w) 动态线程池组件](https://t.zsxq.com/nSebo) + - 【2星】[(0.31w) 支付SDK设计和开发](https://t.zsxq.com/19WqNkhr2) + - 【5星】[(0.78w) API网关:中间件设计和实践](https://t.zsxq.com/xIe9E) + - 【3星】[(0.38w) SpringBoot 中间件设计和开发](https://t.zsxq.com/LZ82D) + - 【2星】[(0.39w) IDEA Plugin 插件开发](https://t.zsxq.com/VMaSW) + +- 其他项目(源码 + 基础) + + - 【5星】[(1.06w) 手写Mybatis:渐进式源码实践](https://t.zsxq.com/xMQ6W) + - 【3星】[分布式技术栈基础教程](https://t.zsxq.com/Hl0W4) + +#### 1.2 课程收获 + +1. 熟练掌握 Spring、SpringBoot、MyBatis 等开发框架技术,并对其使用源码所提供的接口、类、SPI标准开发各类组件,有一定的设计思路和落地能力。 +2. 熟练使用 RPC(Dubbo)、MQ(RabbitMQ、Kafka)、Redis、分库分表、XXL-JOB、Zookeeper、等分布式技术栈,在各个场景的运用。 +3. 深入积累 Spring AI、AI SDK、AI 应用、RAG、MCP、Agent 开发技能和实际项目运用能力 +4. 深度了解 MVC、DDD 架构知识,和框架搭建技巧以及微服务设计思想。 +5. 熟练使用设计模式、设计原则,对各类场景的方案设计和落地能力,深度提高自身编码思维和开发技术能力。 +6. 熟练运用 Docker、Portainer 等Dev-Ops手段,部署和运维 Nginx、Skywalking、Otter、Canal、ELK 等技术框架。 +7. 具备多类项目的开发能力,业务项目、技术项目、组件项目,以及对应的架构模型和设计思路。 +8. 积累八股问题、项目问题、场景问题的解答技巧,同时会有辅助简历编编写优化和评审,提高面试通过率。 ### 2. 问题解答 @@ -94,6 +136,30 @@ lock: no - 提交你的简历:[《面试简历;优化、完善、辅导》简历作业太阳](https://t.zsxq.com/0epLHDzcD) +#### 3.1 简历模板 + +有好经历,有不错的项目,还需要一套上档次的描述方式,这样才能更加完美的展示出自己的实力!这里小傅哥给大家提供了一个描述经历的结构,这样写的简历会更好的突出自己的能力,提高筛选通过率。 + +
+ +
+ +- 首先,个人信息,可以突出下过往的经验积累,包括;在过往的XXX经历中,积累了XXX场景的经验,使个人具备了XXX方面不错的能力。同时兼具着对(技术/场景)的(喜好/热忱),长期(学习/从事/钻研)某项技术,并做出了对应的(开源)(产品/服务/组件/插件)。此个人XXX发布到XXX市场以后,得到了用户(下载量/点赞量/使用数)的规模,获得了非常好的认可。地址:http://github.com/xxxx/xxxx +- 之后,描述个人`教育背景`、`实习/实践经历`、`专业技能`和项目的编写。专业技能,要注意描述顺序和内容量,不宜过多,但要把招聘中核心技术栈体现出来。紧接着到项目描述,这部分最好有1~2个业务项目 + 1个组件类型项目,这样的组合简历内容,还是非常好用的。 +- 最后,补充一个自我评价。把自己描述成有技术追求的、有团队精神、有奋斗品质的优秀好青年。 + +#### 3.2 编写案例 + +
+ +
+ +
+ +
+ +- 在每个大项目下,提供了简历编写案例和问题汇总。举例;[《拼团交易平台系统》,关于面试中的技能、简历、问题汇总](https://bugstack.cn/md/project/group-buy-market/notes.html) + ### 4. 学习氛围 当然,被这样的“鼓励”下,我的周末😭全用在星球上了,不是录制课程视频,就是手写源码,也因为大家的图越画越牛,我也跟着让自己的图更上层楼。点名:课代表阿曦、新晋卷王奥斯卡最佳配角、画图侠诏无言、优秀作业无名氏🧐等等。 @@ -116,6 +182,12 @@ lock: no ### 5. 用户反馈 +经过小傅哥这么多年的努力,👨🏻‍💻认认真真的做编程项目之下,一点点把来自于互联网真实技术教给社群伙伴。也越来越多的被高校老师、在校学生、企业公司、社群粉丝、海外伙伴的认可。 + +
+ +
+ - [@待佳人晚归](https://t.zsxq.com/0eAFk84M7):`写Lottery项目前,因为之前没有接触ddd,也没看过傅哥的视频,想先理解各个模块,然后再编写,傅哥讲的很好,代码太优雅了,一下子就上头了。` - [@念](https://t.zsxq.com/0euNUBW9H):`对Lottery项目分支的开发过程需要多看几遍小傅哥的视频,会有更好的理解.特别是写完之后再去回顾视频,思路会清晰的多` - [@星期一](https://t.zsxq.com/0chHS92j5):`通过两天的学习成功将第五、第六章节跑通并完成了测试,感受最深的是对策略模式和模板模式的进一步了解,之前在看重学java设计模式的时候,对于很多设计模式都处于一知半解的状态,现在结合这个抽奖系统,让我对这两个设计模式有了不一样的理解与认识,感觉真的很棒。这种边记笔记,边学习的感觉真的很好,以前可能看视频学,一天能看很多章节,但其实很多东西都没有弄懂,现在是一天一个章节,慢慢去理解代码怎么编写,怎么完成。这些天虽然还有些地方理解的不是很清楚,我还是继续接着学,到时候回头再来温习一遍。` @@ -125,9 +197,9 @@ lock: no - [@BookSea](https://t.zsxq.com/0cxV12kki):`加入傅哥的星球是我做过最好的投资之一,2022年3月,加入了傅哥的星球。2023年3月,迎来了我的职业生涯的第一次跳槽。` - [@素质男孩](https://t.zsxq.com/10e3wb5vf):`现在一天差不多只能写一节(我是小卡拉米...)比之前看着视频一步步做项目感觉更充实,比如今天在最后跑单元测试的时候,报了个空指针,然后打了断点,一步一步的往下走,很清晰感受到了整个流程,完整的走下来后,真的感觉不一样,最后发现是queryAwardInfoByAwardId(awardId)没有查到对应的id,查看数据库发现award表比strategy_detail中少了一个奖品。` -## 三、加入:知识星球 +## 四、加入:知识星球 -星球价格 **¥159** 一年,老用户续费 **5折** 一年(星球每年都会开发新的学习项目和技术小册等资料)。[查看星球项目](https://bugstack.cn/md/zsxq/other/join.html) +星球价格 **¥159** 一年(全网最实惠社群),老用户续费 **5折** 一年(星球每年都会开发新的学习项目和技术小册等资料)。[查看星球项目](https://bugstack.cn/md/zsxq/other/join.html) >加入 3 天内可以全额退款,感兴趣的同学可以先加入体验,自己判断是否有价值。 @@ -140,7 +212,7 @@ lock: no **注意**:加入星球后,阅读`星球🔝置顶消息` [https://t.zsxq.com/05VB66uzz](https://t.zsxq.com/05VB66uzz) - 项目小册、权限申请、资料文件、简历批阅等。 -## 四、星球:适合我吗? +## 五、星球:适合我吗? 那么,小傅哥的码农会锁,私有技术朋友圈,适合什么样的你加入呢? @@ -159,14 +231,14 @@ lock: no **综上**,如果你想多赚一些钱,也希望自己的职业生涯长久一些,有一定的硬核技术积累,在往后的职场中更稳一些,那么可以加入小傅哥的星球。这些足够硬核的内容,可以帮助你更加平稳的度过往后的路,企业不会永远一帆风顺,但只要你手里技术硬,就会相对平稳。 -## 五、指南:使用星球 +## 六、指南:使用星球 - [指南:🔜快速了解,开启学习之旅!](https://bugstack.cn/md/zsxq/material/guide.html) -## 六、关于:星球定价 +## 七、关于:星球定价 1. 星球内的服务和实战项目都是小傅哥本人提供和**原创**,相信能够给大家带来**超过该价格的价值** 。举个例子,渐进式手把手带大家做**进大厂才可能看得见的项目**、有笔记有源码、有问题可以提,这比单独买一个课程或一套源码要值得多。其实都不到大城市一节补习班的钱,**哪怕把我的课程时长换算成培训机构的课时,也是便宜的超级多**。 -2. 持续的内容创作 + 回答问题 + 知识星球的运营(简历批阅、就业指导、架构设计) 需要小傅哥每个早上6点-8点以及周末/假期持续维护。如果不提高门槛(本次提价¥20),真的是维护不过来。也希望加入星球的同学都是真的下定了决心想要进步,而不是像免费的交流群和社区一样 “闲聊扯淡”。 +2. 持续的内容创作 + 回答问题 + 知识星球的运营(简历批阅、就业指导、架构设计) 需要小傅哥每个早上6点-8点以及周末/假期持续维护。也希望加入星球的同学都是真的下定了决心想要进步,而不是像免费的交流群和社区一样 “闲聊扯淡”。 3. 希望加入进来的同学能够利用好星球来坚持学习。如果这个星球真的帮助你达成了目标(比如晋升加了薪、跳槽诺了坑、校招进了厂),回过头来你会发现,这绝对是你 最值得的一笔投资 !(免费的东西往往不会珍惜,别问我为什么知道!) 4. 星球仍将随着人数和项目的增加会每次提价,感谢理解!—— 但已付费的加入的用户,续费折扣会很大,相当于只续费小傅哥的服务和新项目费用,没有什么比这更爽的了!**如果当年有人这样对我,我会买它个10年!** diff --git a/docs/md/zsxq/material/guide.md b/docs/md/zsxq/material/guide.md index bc1fee971..85e41efe1 100644 --- a/docs/md/zsxq/material/guide.md +++ b/docs/md/zsxq/material/guide.md @@ -56,6 +56,7 @@ lock: no 申请加入仓库后,小傅哥会按照你的申请信息进行审核授权,授权完成后就可以访问项目地址,看到完整的星球课程学习项目了。地址:[https://gitcode.net/KnowledgePlanet](https://gitcode.net/KnowledgePlanet) **仓库使用**:`2种使用方式` + 1. 密码方式:登录的用户ID为 CSDN 个人中心的用户ID,[https://i.csdn.net/#/user-center/profile](https://i.csdn.net/#/user-center/profile) 密码为 CSDN 登录密码。如果没有密码或者忘记,可以在 CSDN 登录页找回密码。 2. SSH 秘钥免登录方式,设置:[https://gitcode.net/-/profile/keys](https://gitcode.net/-/profile/keys) 文档:[生成 SSH 密钥](https://gitcode.net/codechina/help-docs/-/wikis/docs/ssh#%E7%94%9F%E6%88%90-ssh-%E5%AF%86%E9%92%A5) @@ -63,15 +64,21 @@ lock: no
+课程和视频,使用说明; + +1. 申请一次仓库后(星球,课程入口,指引,仓库申请),就可以拉取课程代码(git clone),之后idea打开项目,可以切换分支。教程;https://bugstack.cn/md/road-map/git.html +2. 文档;课程入口,每个项目,进入后,往下翻,会有一个【目录】。目录里的文章,进入后,是评论区,在点击链接进入文章详情。 +3. 视频;每个文章上面会有,视频地址,以及源码地址(审核仓库后直接点击就可以看) + ## 三、课程:学习路线 星球学习项目较多,建议学习路线如下; -1. **为了面试**:Java面经手册(八股)、Lottery 分布式抽奖(项目)、SpringBoot Starter 中间件设计和开发(拉伸技术)、手写Spring/手写Mybatis(2选1) -2. **夯实能力**:重学Java设计模式、Lottery 分布式抽奖、手写Spring、手写Mybatis +1. **为了面试**:Java面经手册(八股)、Ai Agent、拼团交易、大营销(Lottery Plus)/Lottery 分布式抽奖(项目)、SpringBoot Starter 中间件设计和开发(拉伸技术)、手写Spring/手写Mybatis(2选1) +2. **夯实能力**:重学Java设计模式、拼团交易、大营销(Lottery Plus)/Lottery 分布式抽奖(项目)、手写Spring、手写Mybatis、OpenAi 应用项目 3. **拉伸技术**:字节码、IDEA Plugin 开发手册、SpringBoot Starter、API网关 4. **网络编程**:Netty 4.x 小册、IM(Netty 4.x + JavaFx) -5. **应届小白**:重学Java设计模式、Java面经手册、手写Spring/手写Mybatis(2选1)、Lottery 分布式抽奖、SpringBoot Starter 中间件设计和开发,之后学习拉伸技术、网络编程 +5. **应届小白**:重学Java设计模式、Java面经手册、手写Spring/手写Mybatis(2选1)、小型支付商城、SpringBoot Starter 中间件设计和开发,之后学习拉伸技术、网络编程 6. **创新学习**:IDEA Plugin 插件开发、ChatGPT 微服务应用体系 —— `星球项目较多,也可以自行组合。如 IM + ChatGPT,开发角色智能AI。` --- @@ -80,7 +87,7 @@ lock: no ## 四、简历:项目组合 -1. 建议的项目组合是;a【业务】Lottery、IM + b【技术】API 网关 + c【组件】SpringBoot Starter + d【创新】ChatGPT 项目 + e【开源】IDEA Plugin 插件发布到 IDEA 插件市场。 +1. 建议的项目组合是;a【业务】拼团/大营销、IM + b【技术】API 网关 + c【组件】SpringBoot Starter + d【创新】ChatGPT 项目 + e【开源】IDEA Plugin 插件发布到 IDEA 插件市场。 1. 基础组合;a、c 2. 中级组合;a、c、d/e 3. 高级组合;a、b、e diff --git a/docs/md/zsxq/material/speaking-skills.md b/docs/md/zsxq/material/speaking-skills.md new file mode 100644 index 000000000..f38d86aba --- /dev/null +++ b/docs/md/zsxq/material/speaking-skills.md @@ -0,0 +1,290 @@ +--- +title: 面试:嘴笨问题 +lock: no +--- + +# 面试:嘴笨问题 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn/) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +面试时介绍,怼着简历读,感觉不像自己做的。面试官提问,东一句,西一句,讲不出重点。为啥?一方面是不熟悉,一方面是不会结构化表达,导致这脸上的**死嘴**就像不会动了一样。 + +
+ +
+ +**我也想成为 Offer 收割机!** + +同样的一份项目,同样的一个积累,在面试中,”嘴笨“的会吃很的亏。但嘴笨是有治疗办法的,我们可以刻意的锻炼自己的表述能力,形成一个结构化的过程阐述模型,让听众在框架内清晰的理解阐述方所要表达的内容。表述的清晰了,也就更容易交流了。 + +曾经,我们组有个兄弟,2次晋升述职失败。第3次的时候,评委都着急了。你就说,你到底是做什么的,你的价值在哪,你做和其他人做有什么不同? + +好在,调整部门后,他这次的直属领导是一个很会表达的leader,几句话把大家对他的认可度拉回来了。大致如下,他说; + +各位评委好,我来补充几句。坦白说,他在之前的述职中可能因为紧张,表达上没有完全展现出他应有的价值和担当。但我想强调的是,他确实是我们XXX支付营销组的第一负责人,肩负着极其重要的职责。这个场景每年处理数以XXX亿的交易规模,交易量巨大且复杂,任何细微的失误都可能带来严重影响。 + +在他的带领下,系统全年无重大事故,稳定性和可靠性得到了充分保障;同时,团队100%完成了所有需求迭代,确保业务能够快速响应市场和用户的变化。他不仅技术能力过硬,更在跨部门合作中赢得了广泛认可,展现了极强的责任心和团队精神。 + +我相信,随着他逐渐适应和沉淀,他的表达和展示能力会越来越好,但他的核心价值和贡献是毋庸置疑的。希望大家能够看到他背后的实力和潜力,给予他应有的认可和支持。 + +--- + +那一场述职后,他晋升了,第一次晋升。而我也是那年参加述职,我也晋升了,100%全票通过。因为领导给我们培训了很多关于如何阐述自己的价值,怎么做到结论先行,如何承上启下,有因有果的,框架式的循序渐进的铺开一个故事,让评委了解并认可你的能力。 + +## 一、我嘴臭,不会说话? + +面试官让我介绍项目,我对着简历读了介绍,又说了几条核心实现。面试官问我项目是自己做的吗,有做过总结吗,为什么还需要看着简历来讲?不过面试官并没有问我,而是不感兴趣一样,开始转到下一个话题,之后再问了几句八股文,好像凑够了时间一样,说今天的面试到这里,感谢你的参加。 + +其实很多时候,程序员在面试/述职的时候,并没有一个清晰的逻辑来表述自己所做的事项,甚至往往找不出所做项目的核心价值。就像; + +- 问:你先介绍下项目。答:我做了一个拼团系统,可以让用户参与拼团购买商品。拼团里有组队,完成拼团组队成团,之后再mq通知,让商城系统发货。大概这样。 +- 问:这项目的难点是什么?答:我都做出来了能有什么难点,我做不出来才难。 +- 问:这项目最大价值是什么?答:需求就是这样呀,价值不是产品关心的吗? +- 问:这项目有什么亮点?答:好像也没什么亮点,就是写数据返回结果。 +- 问:你在这个项目,发挥的最大价值是什么?答:写代码,改bug呗。 + +综上,这是一个反例,让人举得好像也没做什么,也没有聊下去的想法。尤其是面试官,他也不是你,他不知道你到底做了什么,所以你阐述不出亮点和价值的时候,也就没法对你进行有效提问。 + +面试官您好,我的项目是基于对市面同类竞品的调研,包括;拼多多、京东、美团、滴滴等大厂对拼团场景的使用,综合了产品实际功能诉求和未来的发展趋势,设计了一套拼团营销服务系统。 + +该项目目标是通过拼团优惠组队下单,提升交易GMV和用户自传播能力。系统采用微服务架构,基于DDD领域驱动设计拆分活动、人群、交易等核心领域,运用责任链和规则树设计模式,实现试算、锁单、结算等关键流程的解耦和高扩展性。 + +同时为保证系统高可用和性能,设计了异步线程并行处理、Redis缓存与BitMap人群标签过滤、MQ与HTTP双重结算回调机制,以及分布式锁和无锁化库存抢占方案。整体方案有效支撑高并发交易,提升了系统的鲁棒性和维护效率。 + +这样的一个STAR模型阐述,面试官就会理解`情景`、`任务`、`行动`、`结果`,分别都是什么,但 STAR 法则不非得一定顺序的阐述,也可以结论先行,突出重点结果和情景,在阐述任务和行动。往往结果先行的表述,会让面试官更为感兴趣,第一句就是重点,之后再讲支撑重点的过程条件,条件又可以框架式思维、总分思维、线性思维来阐述。 + +**注意阐述时观察面试官的眼神,重点的地方,眼睛一亮,可以多讲一点** + +## 二、你需要,逻辑思维! + +什么是逻辑思维?简单说,就是有条理、有层次、有逻辑的思考和表达方式。而在面试中,最有效的逻辑思维模型就是**金字塔结构**。 + +金字塔结构,是由线性思维组成的结构化思维模型。当你把结构化的思维聚象成一幅画后,会形成类似三角形结构的树状图。它直观地体现了由结论、论点、论据组成的"先总后分"结构。 + +就像盖房子一样,你得先有个框架,再往里面填砖头。字塔结构就是你表达的框架,让面试官能够清晰地跟上你的思路。 + +> 金字塔原理是*由巴巴拉·明托提出的逻辑学术语*,*指通过层次化、结构化的思维组织方式提升信息传递效率的沟通技术*。 + +### 1. 结论先行 - 别让面试官猜谜 + +面试官脑子不行,一天面那么多人,脑子都僵化了屁的。如果我们不结论先行,在面试官大脑里已经塞满了各种业务、流程、背景、冲突、要素、论点、论证等信息,就没有空间接受我们阐述的重要观点了。 + +**程序员汇报问题对比:** + +**反面例子:** + +> 领导,我们这个项目遇到了一些问题,昨天测试那边反馈说登录模块有bug,然后我查了一下发现是数据库连接的问题,但是运维说服务器配置没问题,后来发现是代码里面有个地方写错了,改了之后又发现另一个接口也有类似问题,然后我又改了一遍,现在基本上差不多了,但是可能还需要再测试一下... + +听到这里,领导是不是已经骂你,让说人话了?这就是典型的流水账式汇报。 + +**正面例子:** + +> 领导,项目已解决登录bug,预计今天下午可以正常上线。问题原因是代码逻辑错误导致数据库连接异常,已修复相关代码并完成回归测试。具体详细的问题和修复过程,我会出一份事故报告,在下次周例会进行分享。 + +看到区别了吧?结论先行,一句话就知道结果,后面的都是支撑理由。 + +**程序员简历案例对比:** + +**反面例子:** + +> 我们系统之前用的是单体架构,随着业务发展,用户量增加,系统响应越来越慢,经常出现超时,数据库压力很大,运维也很困难,代码耦合严重,一个小改动可能影响整个系统,测试周期很长,发布风险很高,所以我们决定进行微服务改造... + +**正面例子:** + +> 我主导了公司核心交易系统的微服务架构改造,将系统响应时间从3秒优化到300ms,支撑了10倍业务增长。改造背景是单体架构已无法满足业务快速发展需求,存在性能瓶颈、扩展困难、发布风险高等问题。 + +### 2. 以上统下 - 让逻辑有层次 + +以上统下就是在金字塔的纵向结构中,上一层是下一层的核心观点或结论,上一层统领下一层。简单说,就是大观点管小观点,小观点支撑大观点。 + +**程序员技能展示案例:** + +✅ **结构化表达:** +> 我具备全栈开发能力,能够独立完成项目从0到1的建设: + +- **后端技术栈:** 精通Java Spring生态,熟练使用MySQL、Redis、MQ等中间件 +- **前端技术栈:** 熟练React/Vue框架,具备移动端H5开发经验 +- **架构设计:** 具备微服务架构设计经验,了解分布式系统常见问题及解决方案 +- **项目管理:** 有敏捷开发经验,能够进行需求分析和技术方案设计 + +这样的表达,层次清晰,每个小点都在支撑"全栈开发能力"这个大结论。 + +### 3. 归类分组 - 让信息有序 + +归类分组是根据信息的共同属性分组的,共同属性包括但不限于性质、功能、方向、层次、对象、时间等。分组的基本原则符合"MECE原则",即"相互独立,又完全穷尽",各要素信息之间"不重不漏"。 + +**程序员项目需求讨论案例:** + +**反面例子:** + +> 产品:这个拼团系统你看一下,用户要能登录,然后可以参与拼团,还要有试算功能,对了还要锁单,组队成功后要结算,如果不成功要退单,还要有个页面能查看拼团数据,另外要支持微信登录,还有就是要有拼团规则配置,对了忘了说,还要有库存管理,还有就是要支持分布式锁... +> 程序员:等等,你能不能整理一下,我有点乱了... + +这样的需求沟通,东一句西一句,没有章法。程序员跟产品讨论一天,产品需求出来了,程序员一天没干活!打回去重写去! + +**✅ 结构化的表达方式:** + +> 产品:拼团营销系统需求如下: +- **核心交易:** 试算、锁单、组队结算、退单处理 +- **数据管理:** 拼团数据查看、库存管理、规则配置 +- **用户体验:** 微信登录、页面展示、状态通知 + +✅ **按业务领域分组:** +> 我有3年多项目开发经验,涉及多个业务领域: + +- **电商领域:** 负责商品管理系统、订单系统、支付系统的开发和维护 +- **金融领域:** 参与风控系统、清算系统的核心模块开发 +- **营销领域:** 主导优惠券系统、积分系统、拼团系统的架构设计和实现 + +✅ **按技术栈分组:** +> 我的技术能力覆盖前后端及运维: + +- **后端开发:** Java、Spring Boot、MyBatis、MySQL、Redis +- **前端开发:** React、Vue、TypeScript、Webpack +- **运维部署:** Docker、K8s、Jenkins、监控告警 + +### 4. 逻辑递进 - 让思路有顺序 + +逻辑递进是金字塔结构的最后一个原则,是指按照一定的顺序进行排序,这个顺序需要遵守逻辑性原则。 + +#### 4.1 时间顺序 +又称为步骤顺序,是指按照事物发展的流程进行排序。 + +**程序员项目开发流程案例:** +> 我负责的拼团系统开发,严格按照标准流程推进: + +- **第一阶段:** 需求调研和技术方案设计(1周) +- **第二阶段:** 核心功能开发和单元测试(3周) +- **第三阶段:** 联调测试和性能优化(1周) +- **第四阶段:** 灰度发布和全量上线(1周) + +#### 4.2 空间顺序 +又称为结构顺序,按照事物的结构进行排序。 + +**程序员系统架构案例:** +> 我设计的微服务架构采用分层设计: + +- **接入层:** 网关负责路由、限流、鉴权 +- **业务层:** 用户服务、商品服务、订单服务、支付服务 +- **数据层:** MySQL主从、Redis集群、MQ消息队列 +- **基础层:** 监控、日志、配置中心、注册中心 + +#### 4.3 重要性顺序 +按照重要程度进行排序,从最重要到最不重要。 + +**程序员核心能力案例:** +> 我认为一个优秀程序员最重要的能力排序是: + +- **第一:** 学习能力和解决问题的能力(技术更新快,这是根本) +- **第二:** 系统设计和架构思维(决定系统的可扩展性和稳定性) +- **第三:** 编码规范和工程化能力(保证代码质量和团队协作) +- **第四:** 沟通协作和业务理解(技术服务于业务) + +#### 4.4 演绎顺序 +经过一定的逻辑推演出结论,通常用到的演绎表达方式:大前提-小前提-结论,提出问题-找到原因-解决方案。 + +**程序员问题解决案例:** +- **问题:** 系统在高并发场景下出现频繁超时 +- **原因分析:** 通过监控发现数据库连接池耗尽,慢SQL导致连接长时间占用 +- **解决方案:** 优化慢SQL、增加数据库连接池、引入Redis缓存热点数据 +- **结果:** 系统响应时间从5秒降低到500ms,支撑10倍并发量 + +--- + +掌握了字塔结构的四个原则,你就有了表达的框架。但光有框架还不够,还需要在实际面试中灵活运用。记住,**结构化思维不是为了炫技,而是为了让面试官更容易理解你的价值**。 + +下次面试时,试试用字塔结构来组织你的回答,你会发现面试官的眼神都不一样了。 + +## 三、套路,总得人心 + +掌握了字塔结构的四个原则,你已经有了表达的基本框架。但在实际面试中,光有框架还不够,你还需要一些具体的思考工具来快速组织语言。这些工具就像是你的"套路",但这些套路不是为了忽悠,而是为了让你的表达更加清晰、有逻辑。 + +好的套路,总能得人心。因为它让沟通变得高效,让听众更容易理解你的价值。 + +### 1. 5W1H分析法 - 全面思考问题 + +5W1H是一个经典的思考框架:Who(谁)、What(什么)、When(何时)、Where(何地)、Why(为什么)、How(如何)、How much(多少)。 + +**程序员面试介绍项目经验案例:** + +> 面试官,关于我负责的用户登录模块优化项目,我用5W1H来介绍一下: + +- **Who(谁):** 我作为后端负责人,与前端工程师和测试工程师协作 +- **What(什么):** 优化登录响应速度,从平均3秒降到500ms以内 +- **When(何时):** 项目周期2周,已成功上线运行3个月 +- **Where(何地):** 主要涉及登录服务、Redis缓存层和数据库层 +- **Why(为什么):** 用户反馈登录太慢,日活跃用户流失率达到15% +- **How(如何):** 引入Redis缓存、优化SQL索引、异步处理用户信息 +- **How much(多少):** 最终用户满意度提升30%,登录成功率从85%提升到99.5% + +这样的介绍,信息全面,逻辑清晰,面试官能快速了解你的项目价值和技术能力。 + +### 2. 流程思维 - 按时间线思考 + +流程思维是按照时间顺序,将一个事件进行分解,可以简单地分为:事前、事中、事后。 + +**程序员向产品汇报线上bug处理案例:** + +> 产品,关于昨天的支付异常问题,我按流程汇报一下: + +- **事前(预防):** 我们有监控告警,但这次是新场景,监控覆盖不到 +- **事中(处理):** 收到用户反馈后,10分钟定位问题,30分钟修复上线 +- **事后(改进):** 已补充监控规则,增加异常场景的单元测试 + +这种表达方式让产品清楚地了解整个处理过程,也体现了你的专业性。 + +### 3. 故事思维 - 让技术有温度 + +一个好的故事必备四个要素:背景、冲突、问题、解决方案。程序员往往只会说技术,不会讲故事,但故事思维能让你的技术更有说服力。 + +**程序员向面试官介绍项目亮点案例:** + +- **背景:** 我们电商系统在双11期间面临10倍流量冲击 +- **冲突:** 原有单体架构无法支撑,系统频繁宕机,用户投诉激增 +- **问题:** 如何在有限时间内快速提升系统承载能力? +- **解决方案:** 我主导了核心交易链路的微服务拆分,引入Redis集群和MQ削峰,最终支撑了双11零故障运行,GMV同比增长300% + +这样的表达,有情节、有冲突、有结果,比单纯的技术介绍更吸引人。 + +### 4. 经营分析法 - 用数据说话 + +经营分析报告的表述四段论:陈述事实、作出判断、寻找归因、改进方案。这个方法特别适合向领导汇报工作。 + +**程序员向领导汇报系统性能优化成果案例:** + +> 领导,关于本月系统性能优化成果汇报: + +- **陈述事实:** 系统响应时间从平均2秒降到500ms,环比提升75%,同比提升80% +- **作出判断:** 这个数据超出了我们的预期目标(目标是降到1秒以内) +- **寻找归因:** 主要得益于数据库索引优化和Redis缓存策略调整,其中缓存命中率提升到95% +- **改进方案:** 下一步计划引入CDN加速静态资源,预计还能再提升20%性能 + +这种汇报方式,有数据、有分析、有规划,领导听了会很满意。 + +### 5. PDCA循环 - 持续改进思维 + +PDCA是Plan(计划)、Do(执行)、Check(检查)、Action(行动)的循环。这个思维模型特别适合展示你的项目管理能力。 + +**程序员向测试汇报代码质量提升计划案例:** + +> 测试同学,关于提升代码质量,我有个PDCA计划: + +- **Plan(计划):** 制定代码规范,引入SonarQube静态检查,目标是bug率降低50% +- **Do(执行):** 已配置好检查规则,团队开始按规范开发,每次提交都会自动检查 +- **Check(检查):** 运行两周后,发现bug率确实下降了30%,但还有改进空间 +- **Action(行动):** 下个循环计划增加单元测试覆盖率要求,从60%提升到80% + +这样的表达,体现了你的系统性思维和持续改进意识。 + +--- + +这五个思考工具,就像是你的"武器库"。不同的场景用不同的工具,让你的表达更有针对性。记住,**套路不是为了套路,而是为了更好地传达你的想法和价值**。 + +在面试中,当面试官问你项目经验时,你可以用故事思维;当问你如何解决问题时,你可以用5W1H;当问你项目管理经验时,你可以用PDCA。灵活运用这些工具,你的表达会更加专业和有说服力。 + +最后,关于面试、述职,都要提前写好逐字稿,反复的练习,让自己形成阐述过程记忆。这样在回答面试官问题也不会因为紧张而导致没法正常表达。加油! diff --git a/docs/md/zsxq/material/student-learn-advanced.md b/docs/md/zsxq/material/student-learn-advanced.md new file mode 100644 index 000000000..b6c42b78d --- /dev/null +++ b/docs/md/zsxq/material/student-learn-advanced.md @@ -0,0 +1,87 @@ +--- +title: 路线:从小白到大佬,实战项目进阶路线 +lock: no +--- + +# 路线:从小白到大佬,实战项目进阶路线 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +经过🇨🇳10.1假期的狂卷,小傅哥的星球,又一个新业务项目《MVC + DDD 双架构 - 小型支付商城》完结啦。至此已交付6套业务、7套组件以及源码学习和基础教程,**共300节+课程!** 这也代表着,从小白到大佬的一整条进阶路线,小傅哥全部给你搭建出来了! + +
+ +
+ +**从不废话,强的可怕!** + +在小傅哥给大家搭建的原创体系化成长路线学习内容中,可以系列的掌握,MVC 架构、DDD 架构,以及设计模式的实际场景巧妙运用,也有全体系的 Spring、SpringBoot、MyBatis 等基础框架的使用,综合微服务分布式架构 RPC、MQ、分库分表、任务调度、本地缓存、分布式环境、熔断、降级、限流、动态配置中心等的使用。以及普罗米修斯 + Grafana 监控、前端热力图,在结合 Docker、Portainer、Nginx、Jenkins、Github Actions 等运维实施能力的掌握。 + +可以这么说,小傅哥在大厂用到的技术体系,会全程在项目中陆续体现出来,循序渐进的教给你使用。等你进入公司中,做这些内容都不会陌生了。甚至你还可以给公司提出可靠性解决方案,让领导对你刮目相看! + +## 一、进阶路线 - 300+节课程 + +### 1. 课程目录 + +这是一整套的实战项目学习进阶路线,从小白到大佬,全程视频手把手带着从0到1,一步步完成项目的设计、开发和上线。在整套内容学习过程中,小傅哥为你提供了非常好的技术交流社群,及时解决学习问题。还包括调试你的问题代码,带你快速🔜出坑! + +
+ +
+ +- 首先,这一整套全体系的学习课程比私教培训实惠,更比培训班上万的培训费便宜。可能也就是培训班1天的💰钱,就能学习到这一整套内容了。 +- 之后,你学习的整套课程,就是小傅哥这个架构师自己全部原创编写的。这也就是说,你所提到的任何问题,小傅哥都能给你解答和讨论。 +- 那么,这么实惠的课程,成体系的课程,还是架构师编写的。还有什么可犹豫的,完全可以撸起来了! + +### 2. 课程资源 + +**课程链接**:- 整个课程路线参考【课程日历图📅】,对应的资源链接汇总如下; + +- 【3星】[(1.87w) Deepseek RAG、MCP、Agent 智能体](https://t.zsxq.com/Zq7hV) +- 【2星】[(0.6W) 小型支付商城系统 - 双架构开发(带小白入门)](https://t.zsxq.com/3X9GA) +- 【4星】[(1.41W) 大营销平台系统 - 微服务&分布式](https://t.zsxq.com/199mpn9Lt) +- 【3星】[(0.77W) OpenAi(ChatGPT\ChatGLM) 微服务应用体系构建](https://t.zsxq.com/19aSkDvYB) +- 【4星】[(1.28w) Lottery DDD分布式抽奖系统](https://t.zsxq.com/qrUSd) +- 【2星】[(0.78w) IM实战(Netty+JavaFx):仿桌面版微信聊天](https://t.zsxq.com/NcPgw) +- 【2星】[(0.11W) OpenAI 代码自动评审组件](https://t.zsxq.com/gYEVX) +- 【2星】[(0.23W) BCP透视业务流程 - 监控系统](https://t.zsxq.com/CVzpL) +- 【2星】[(0.15W) 动态线程池组件](https://t.zsxq.com/nSebo) +- 【2星】[(0.31w) 支付SDK设计和开发](https://t.zsxq.com/19WqNkhr2) +- 【5星】[(0.78w) API网关:中间件设计和实践](https://t.zsxq.com/xIe9E) +- 【3星】[(0.38w) SpringBoot 中间件设计和开发](https://t.zsxq.com/LZ82D) +- 【2星】[(0.39w) IDEA Plugin 插件开发](https://t.zsxq.com/VMaSW) +- 【5星】[手写Mybatis:渐进式源码实践](https://t.zsxq.com/xMQ6W) +- 【3星】[分布式技术栈基础教程](https://t.zsxq.com/Hl0W4) + +### 3. 课程收获 + +1. 熟练掌握 Spring、SpringBoot、MyBatis 等开发框架技术,并对其使用源码所提供的接口、类、SPI标准开发各类组件,有一定的设计思路和落地能力。 +2. 熟练使用 RPC(Dubbo)、MQ(RabbitMQ、Kafka)、Redis、分库分表、XXL-JOB、Zookeeper、等分布式技术栈,在各个场景的运用。 +3. 深度了解 MVC、DDD 架构知识,和框架搭建技巧以及微服务设计思想。 +4. 熟练使用设计模式、设计原则,对各类场景的方案设计和落地能力,深度提高自身编码思维和开发技术能力。 +5. 熟练运用 Docker、Portainer 等Dev-Ops手段,部署和运维 Nginx、Skywalking、Otter、Canal、ELK 等技术框架。 +6. 具备多类项目的开发能力,业务项目、技术项目、组件项目,以及对应的架构模型和设计思路。 +7. 积累八股问题、项目问题、场景问题的解答技巧,同时会有辅助简历编编写优化和评审,提高面试通过率。 + +## 二、简历使用 + +编程这一行,要想真的掌握些东西,就是需要大量的做有质量的项目,提高自己的编程思维,锻炼自己的编码能力!学习完的项目,陆续完善到自己简历,让自己的竞争力越来越强👍🏻。像六边形战士一样! + +### 举例1 - 大营销 + +
+ +
+ +### 举例2 - Api网关 + +
+ +
+ +说实话,有如此`清晰的架构设计`、有如此`规模的工程拆分`、有如此`运用的设计模式`,这样的实战项目,又是本身一个大厂架构师,所编码、写文档、录课程,其实真的不多。但这样的项目在小傅哥的星球【码农会锁】**已有10多个啦** !你可以想象,你加入这样的技术社群,所能学习到多少硬核的技术东西。 diff --git a/docs/md/zsxq/memorabilia/campus-recruitment-offer.md b/docs/md/zsxq/memorabilia/campus-recruitment-offer.md new file mode 100644 index 000000000..321aa476a --- /dev/null +++ b/docs/md/zsxq/memorabilia/campus-recruitment-offer.md @@ -0,0 +1,132 @@ +--- +title: 秋招总结,6家大厂,5个SSP级别Offer!最终选择了最赚钱的方向。 +lock: need +--- + +# 2023年7月25日,校招简历应该怎么写 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +在互联网大厂,我写过11年的代码,带过团队,培养过新人,经历了非常多的业务场景设计和实现。总结一句,我是一位经验丰富的软件开发&架构师! + +
+ +
+ +**我清楚的知道,技术人怎么从小兵走到“头部”** + +15年入职大厂,23年走到T8架构师,连续晋升。无论是;承接项目、晋升述职,还是技术分享和培养新人,我都可以完成的非常漂亮。并在晋升T8时,以全票通过,获得领导的认可。 + +所以,在个人技术成长和职业成长方面,我是有非常多的经验的。因为有这样的经历和这些经验,小傅哥于2021年,建设了一个自己运营的技术社群**「星球:码农会锁」**,直至今日已有1.6万人加入,帮助了超级多的伙伴完成了技术的成长和职业的进阶。 + +`有伙伴辣评:“裸辞半年,我是被小傅哥,抬着进入的这家公司!”` + +
+ +
+ +为了,让伙伴们更好的知道小傅哥有多值得,今天给大家分享一个在小傅哥社群学习成长的伙伴,拿到 Offer 的自我总结。这样的经验,可以非常好的帮助大家了解到如何学习、怎么有价值的学习! + +>接下来,是这位星球伙伴的自述。 + + +秋招顺利拿到offer,并且这几天毕业论文盲审顺利通过了,总算尘埃落定。感谢小傅哥的知识星球陪伴我走完了硕士生涯,写个帖子记录下我的学习历程以及我个人的秋招面试总结,希望对星球里的大家有些帮助~ + +## 1. 我的背景 + +先简单介绍下本人背景,211本985软工硕,一段美团日常实习一段淘天暑期实习,秋招拿到了字节ssp、美团sp😭、快手ssp、淘天ssp、蚂蚁ssp、京东ssp,都是交易/支付方向的offer,最终通过综合比较选择去了淘天。 + +## 2. 学习的碎碎叨叨 + +以下是碎碎叨叨的开始,长文⚠️,不想看的小伙伴可以直接下滑到「秋招总结」,有我的一些面试经验总结~ + +我加入小傅哥的知识星球已经快近2年了,还记得当时刚开始学Java是在2023年的1月,那个时候我几乎天天去市图书馆,从最基础的Java基础开始学起,从早上学习到傍晚,学习时间其实不是很长,23年的寒假算是学了一些Java基础和SSM(虽然本科也学过一点皮毛,不过后来都忘记了)。 + +寒假结束回到学校之后,我开始从早到晚的疯狂学习,一周稳定学习6天,大概每天除去吃饭、休息、睡觉的时间可以学习八个小时以上,每天大概有2-3小时来干科研,其余时间都学Java相关的。 + +这段时间有种每天都在过期末周的感觉……在23年的3月份,我看到了小傅哥的知识星球,加入其中,并坚持每天打卡了几个月,这几个月,我主要集中学习的还是Java的八股,看了很多优质八股的网站,例如 `JavaGuide`、`Java进阶之路`、`小林coding`等,结合牛客的面经,综合学习了操作系统、计算机网络、`JUC`、`JVM`、`Redis`、`MySQL`、`Kafka`、`RocketMQ`、`zookeeper`、`分布式`、`Dubbo`等。 + +这些八股知识我一直学习、补充完善、复习到秋招为止,也是这样反复的整理、理解、压缩、记忆,在面美团和秋招面试的时候,面试官问的八股问题我基本都能在2秒内快速回忆起,且问的问题90%都是我已经知道的。 + +此外,在算法方面,我当时系统刷完了左程云的算法视频课程,这个课程比较的难,算是培养了我的算法思维吧(真实情况是感觉针对性不高……),以及后续我跟随代码随想录系统刷了2遍,代码随想录的算法题给我的感觉比左程云的课程更适合用来应对面试,其总结的方法非常实用。 + +23年的6-8月份,由于毕业方向调整,我去学习了一段时间的Java Performance,这段时间了解了一些性能调优方面的基础知识,对于常规Java那块的知识就耽搁了。 + +在9月份,我重新调整了毕业方向,再次投入到常规的Java学习路线中来,这个时候我是没有做实践项目的,在对比了几个知识星球的项目之后,我选择做了小傅哥的lottery抽奖系统(大营销)。小傅哥不仅录制了视频,让我可以跟着一步一步操作,而且也详细写了项目手册,这对于我这个鲜有实践经验的人来说是非常宝贵的。 + +后面的10-11月份,我对lottery抽奖系统(大营销)可能会问的问题都进行了整理思考,为此我把小傅哥的知识星球上关于lottery相关的帖子翻了个遍,收获巨大。后面在面试美团的时候,我真切的感受到了吃透自己做的项目的重要性,面试官真的会问的很细很具体,如果能答上来,并据此进行不足之处的展望,那是非常加分的。 + +在之后,23年的12月份,我开始投简历面试,月底各大公司招聘的机会不多,幸运的是美团招聘的岗位相对比较多,于是我最终选择去了美团。之后24年的1月到8月,我分别在美团和阿里实习,在9月系统准备秋招面试,1个月时间基本面完了,10月-11月写毕业论文,12月花了一点时间修改论文,大部分时间用来玩了,算是毕业入职前最后的放松😊。 + +回看我这一路的学习历程,中间有过曲折,但总体都是顺顺利利的,这种顺利我认为一部分原因是我选对了学习的路径,从学习八股到学习项目,我选的都是非常优质的内容,这帮助我少走了很多的弯路。真的感觉非常幸运在正确的时间加入了小傅哥的知识星球,并学习收获了如此硬核的知识。后面我仍然会跟随小傅哥继续学习,并尝试将所学的内容写成文章沉淀下来~ + +## 3. 秋招总结 + +秋招可以斩获那么多的offer,我认为可以归因于以下几个方面,分别是学历与奖项、八股、算法、项目、实习、简历书写、面试表现。 + +### 1、学历与奖项 + +学历和奖项这块,只能从大一大二还处于大学较早期的时候开始发力,包括卷绩点保研、考研、参加大赛、参加科研项目等。目前学历和奖项是有些大厂能否过简历筛选的硬性标准,比如淘天会筛掉双非(非强校)的同学,但大部分厂还是可以放低要求的。学历这块我感觉只是起到了敲门砖的作用,面试官看重的还是同学面试时候展现出来的技术能力。 + +### 2、八股 + +虽然有了项目以及实习经历,但我在面试的时候,还是会问一些八股,因为公司的招聘规则里面需要考察候选人的基础,这个时候还是会问一些基础八股的。此外,八股往浅了说是一些基础的八股知识,往深了说,从项目、实习经历延伸开来的问题也可以归类为八股,例如一些架构题、三高性能等。 + +八股的学习也可以从浅到深,浅的包括了面试常见的Java基础、JUC、JVM、Redis、MySQL、计算机网络、操作系统、MQ,如果时间有限,这些常规的八股题利用【JavaGuide+牛客面经+ChatGPT】可以速成一下。 + +八股学习方式,我个人会采用【问答】的方式先进行整体的理解,每个知识点的问答题目可能会非常多,如果记忆那么多文字负担也会非常重,所以为了简化记忆的难度,我会用【思维导图】进行知识的压缩,利用思维导图记录知识的【关键词】,在回答的时候,可以利用这些关键词来补全上下文。这个方法总结来说就是我们常说的把书读薄再读厚,读薄是提取关键点,读厚是进行扩充以及建立知识点之间的关联性。 + +更加深层的八股例如限流、熔断、高并发这些,可以结合自己的项目、实习经历进行针对性的学习,这些深层次的八股面试官问的时候也是从项目和实习经历展开。 + +### 3、算法 + +算法这块,日常时候可以跟随「代码随想录」系统刷上2遍,学习方法;然后反复地来刷leetCode的hot100以及top250,题目出现的频次可以查阅「CodeTop题库」。 + +我在面试的过程中,面试官出的题基本都在这个范围内,哪怕不在这个范围内,也是这些题进行小的一些修改。在面试的时候,面试官给的做题时间比较短,这需要平时多刷几遍才能做到面试的时候可以立刻想到思路并写出代码。 + +### 4、项目 + +个人项目在面试第一份实习岗位的时候,非常重要。项目需要使用到一些常见的技术,例如MQ、MySQL、Redis等,并需要适当的复杂性。 + +这里小傅哥写的项目就非常适合拿来写在简历上。在跟着学完一遍项目之后,还需要考虑到以下几个方面: + +1. 项目的难点与重点,也是需要在简历上呈现的点 +2. 项目一段话概括性介绍以及详细流程介绍 +3. 项目为什么用这个技术,例如为什么用Redis的分段锁,如果不用会怎么样,能否用其他技术代替,其他技术与该技术的区别等 +4. 项目使用了这个技术,会不会出现某些异常情况,例如Redis的锁超时释放了。是否会出现一些极端情况以及应对极端情况的措施,我在面试的时候会经常被询问到,面试官也比较看重这方面思考的周到性,一定要多准备这块。 +5. 项目技术相关的一些基础八股,例如Redis的锁的看门狗机制 +6. 项目的不足之处,对这些不足之处你认为可以从哪些方面进行优化完善 +7. 项目取得的一些技术性指标,例如耗时、QPS、节省人力等 + +>小傅哥,有非常多的实战项目,包括不同难度的业务类型和组件类型的项目,可以按个人学习积累选择学习。 + +![](https://bugstack.cn/images/article/zsxq/zsxq-241007-02.png) + +### 5、实习 + +实习需要做的就是能拿一个项目写到简历上,项目需要有些复杂度,如果实习干的是打杂的活,那可能需要去看一些组里别的项目,吃透之后写到简历上。 + +实习除了问项目之外,面试官也会问到实习期间学了什么技术,可以在实习期间再跟着学一些项目用到的技术原理。如果是日常实习,推荐带着学习的目的性去实习,毕竟后面很大概率是要跳到别的公司的;如果是暑期实习,并且感觉实习部门氛围不错的话,需要花点心思在转正上。 + +### 6、简历书写与面试表现 + +简历书写如果经历比较丰富的话,个人感觉可以写2页。简历上一般都会有的模块:教育经历(学校不错且成绩不错可以放开头)、实习经历、项目经历、个人技能、个人评价。简历书写的时候注重文字之间的排版以及不要写错别字,表达去除大白话,尽量写的精简专业一些。 + +还有非常重要的是,很多星球都提供免费的简历修改服务,可以多修改几个版本。简历模板我用的是「简历本」,需要付费,市面上也有很多免费的网站,大家可以去搜索。 + +在面试过程中,面对面试官问的问题,可以尽量回答的久一些,将一些可以联系的知识点也说出来,这样不仅可以减少面试提问的数量,也可以放一个🪝,引导面试官从自己熟悉的这块知识提问。还有面试表达的时候,最好能有条理,如果记忆的是知识点关键词的话,可以先说关键词,再对此进行补充。 + +除了上面这些,还有非常重要的一点是运气🍀,祝愿大家都能遇到一个对口的面试官,顺利斩获offer~ + +以上的秋招面试经验源自我个人经历的一些感悟,不同的人可能会不一样,仅供大家参考一下~最后祝愿大家都能有个好的offer🍀🍀🍀~ + +>好啦🌶,以上就是来自小傅哥社群伙伴的分享,我认为非常有价值,非常值得大家参考。以这样的认知和学习,将来职业发展会走的非常好。 + +
+ +
\ No newline at end of file diff --git a/docs/md/zsxq/memorabilia/java-interview-experience.md b/docs/md/zsxq/memorabilia/java-interview-experience.md new file mode 100644 index 000000000..dc3c604e6 --- /dev/null +++ b/docs/md/zsxq/memorabilia/java-interview-experience.md @@ -0,0 +1,100 @@ +--- +title: 这21套大厂Java资料,写够1万行,校招够了。写够10万行,可以冲P7了! +lock: no +--- + +# 这21套大厂Java资料,写够1万行,校招够了。写够10万行,可以冲P7了! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
星球:[https://t.zsxq.com/05zj2niYR](https://t.zsxq.com/05zj2niYR) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +你见过面试评价表吗?`常用框架应用经验不足`、`缺少分布式项目经验`、`无C端场景开发经验`、`项目流程不完善`、`CRUD偏多,无架构和设计思考`、`复杂问题思考不足`、`伪场景需求,无实际应用`等。看完是不有点🥶冷汗直流。那怎么提升这些方面的知识? + +
+ +
+ +**项目不行,编码量还不够!** + +之所以遇到这些面试问题,就是因为很多伙伴从毕业🎓到工作,以及在工作中基本都没做过什么好项目。不是毕业前做了一堆CRUD流程的Demo项目,就是工作后组装API接口的。往往这些过程都是有连带关系的,因为起步做的项目弱,缺少技术的积累和技术视野的认知,所以面试中表现的不够强,导致最终找工作的坑也会差。 + +当然,聪明一些有想法的伙伴,肯定会想办法去找一些在大厂真实工作的架构师进行`"偷师"`。把来自中大厂的`业务经验`、`架构经验`、`编程思维`、`编码技巧`,学习下来在用于实践验证和增强简历竞争力。所以跟谁学习很重要! + +**注意**:📢 你的有效代码量,与你的能力息息相关。尤其是代码中含架构设计、设计模式、高级编码、场景问题的指标量占比越高越好。当你的积累远超过这一阶段诉求时候,你的能力也会很容易匹配到工作岗位。 + +
+ +
+ +>小傅哥准备了21套内容,帮你做有规划的、成体系的、可高效的,成为面试中、职场中,有竞争力的人!文末可以获取全部内容。 + +## 一、初学踩坑 + +`程序员👨🏻‍💻,大量的编码,才能锻炼出大量的经验。` + +在我初学编程以及到了每个阶段的瓶颈期,需要提升自己的时候,也尝试过在网上找资料。但往往这些资料都是不成体系的,很碎片化,后来才知道那都是一些博主为了博取流量,四处整合的资料,打包在给你。 + +关于内容的质量、内容的连贯性、博主是不知道的,因为博主自己也没有学习过这些资料。但我们拿到后在花大量的时间看,而且还可能是看了一些过时不用的,就非常耗费精力。 + +如图,19年的时候,级别T6,再上一层就是架构师。于是为了扩展知识学习,我找到2个T资料(后来又删了很多!) + +
+ +
+ +- 首先,是想锻炼一些架构思维、编码思维、逻辑思维,但往往市面这类资料几乎是没有。大部分都是基础教程,以及一些简单的管理类项目。代码质量还不及公司同事写的。 +- 之后,这些资料缺少连贯性,学习时候的前置知识说明和文档说明,都是缺失的(毕竟都是免费的)。 +- 最后,遇到问题是真没有人能问到,别说提升能力了,自己的那点能力都被薅干净,去解决课程bug! + +## 二、新的计划 + +`19年,因为自身就有晋升的诉求,预期可哪找资料,不如公司里找人!` + +本身自己就在互联网大厂,身边这么多资源,还都是认识了很久的一群高级架构师。那还可哪找啥人学习,直接拉着架构师,让他们做各类分享,从分享的干货中学习多好。后来,我也把不断积累到的高级能力运用到了项目和编码中,还在后来开始做了技术分享,也就是大家看到的一整套、一整套的内容。 + +我不图快,我只想认真的想把自己的技术,从基础到应用,一点点的全部分享出来。让伙伴们学习基础可以运用到项目,学习项目可以从基础中查阅到相关的案例。这样循序渐进,有紧有收的方式,才是正确的学习方式。 + +**想写好这些东西,确实耗精力!5年了!** + +
+ +
+ +- 这是小傅哥,为大家陆续编写的编程技术资料。包括;基础教程、技术小册、源码学习,再到业务项目6套、组件项目7套。并且还在继续更新中,后续还有更多项目加入。—— 我要把大厂中做的项目,全部陆续的做成一个个学习项目,让大家可以提高自己的能力。 +- 业务项目6个,代码行数5万。组件项目7个,代码行数2.35万。源码学习,代码行数1.06万,整体将近10万行。每个项目都具有独特的架构、场景、设计、编码。学习任何一个都能带来非常多的技术收获,而且会学习到耳目一新的东西! + +## 三、成绩认可 + +这5年来,我用大厂锻炼的一身技能,帮助了非常多的伙伴,实打实的提到了编程技术。还为星球伙伴做简历评审,现已积累了将近500份简历+评审记录(看过之后都会写简历了!)。在学习后,更有伙伴坦言:”我是被傅哥的技术,抬着进的这家公司!“ + +### 1. 斩获Offer + +
+ +
+ +
+ +
+ +
+ +
+ +### 2. 简历优化 + +
+ +
+ +
+ +
+ +>这些都是可以在小傅哥的社群学习到的内容和获得到的服务,有大厂架构师这样手把手的教,可以说是非常实在。并且你在以后工作中遇到的实际场景问题,也都可以给予解答,**让你顺利度过试用期!🍻** + diff --git a/docs/md/zsxq/memorabilia/job-hire-jd.md b/docs/md/zsxq/memorabilia/job-hire-jd.md new file mode 100644 index 000000000..8ed6688ed --- /dev/null +++ b/docs/md/zsxq/memorabilia/job-hire-jd.md @@ -0,0 +1,140 @@ +--- +title: 不废话,公司需要什么能力,我们就安排什么项目! +lock: no +--- + +# 不废话,公司需要什么能力,我们就安排什么项目! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
星球:[https://t.zsxq.com/05zj2niYR](https://t.zsxq.com/05zj2niYR) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +“小傅哥,是真想把我教会!”,跟着小傅哥学习的越久,越发现很多以前单点的碎片知识,都被成体系的串联起来了。并且学习的这些东西,是真的匹配到了招聘的岗位,同时在面试中与面试官有的聊。**这是真的爽!** + +
+ +
+ +**匹配大厂招聘诉求学习!** + +就编程类的知识、项目、方向来讲有非常非常多,但如果你全心的投入到;`servlet`、`jsp`、`Struts2` 的过时技术,`坦克大战`、`学生管理系统`、`图书管理系统` 的大CRUD流水账项目,那么在投递简历的时候,真的很难匹配到招聘要求。 + +而在我做互联网大厂架构师这么多年,经历过的众多各类型的项目,以及在这个过程中完成的技术调研、技术选型、方案设计、架构设计、项目交付,可以明确的给你讲,C端、高并发、分布式、微服务、DDD(越来越多中大厂使用)、AIGC(开始结合),这样的项目是可以更多的匹配到招聘诉求,也是更能提升个人能力的编程项目。**举例;如图,去哪网招聘** + +
+ +
+ +- 首先,如招聘诉求描述,活动、营销、交易、AIGC、DDD、C端、抽象、拆分、以及常用分布式技术栈,都是各类互联网大厂中,最常做的业务类型和所需的技术方案。 +- 之后,你会发现右侧的内容,嘎嘎的匹配到了左侧的招聘诉求上!哈哈哈,这些内容都是小傅哥为你提供的实战编程项目,它们出身名门大厂,自带高级架构和巧妙的逻辑设计。在这些项目上,你可以学习到互联网大厂 + 大架构师的编码(`小公司出来的根本写不出这样的代码`),这不只是一场课程,也是一次优雅的编程旅行,携助你去期待的大厂入职。✈️ + +## 他们都要DDD! + +
+ +
+网图,排名不一定准确,但在搜索官网的招聘中,会看到很多核心C端的岗位,都有;DDD、营销、交易、AIGC、高并发、分布式、微服务、设计模式的相关经验优先。举例;京东、小红书、百度。 + + +### 1. 京东 + +
+ +
+ +官网:[https://zhaopin.jd.com/web/job_info_list/3?isHunterFlag=false](https://zhaopin.jd.com/web/job_info_list/3?isHunterFlag=false) + +### 2. 小红书 + +
+ +
+ +官网:[https://job.xiaohongshu.com/](https://job.xiaohongshu.com/) + +### 3. 百度 + +
+ +
+ +官网:[https://talent.baidu.com/jobs/social-list](https://talent.baidu.com/jobs/social-list) + +>所以,这也是为什么小傅哥,把这些知识体系,拆开了、揉碎了,一口口的喂给你!并且小傅哥是真的复刻大厂的工作方式,把这些知识传授给你。 + +## 1:1 复刻大厂流程 + +**图,是对业务流程的深入理解,是对系统架构的逻辑抽象。** + +项目的承接,并不是一上来就直接干代码,而是要做一列的BRD评审、PRD评审,再到研发做系统的架构设计、库表设计、流程设计、外部对接,这个过程中会产生出很多的各类型图稿。这些东西都是非常有价值的内容,让我们可以更好的、更深入、更全面的理解一套系统。而且,在你工作以后,你很多时候都要和这些图打交道,这样你才能更好的完成工作的交付。 + +那么,这些东西在小傅哥的社群里,都是随着项目一点点的渗透给你的。潜移默化的你也就学会了分析需求和设计系统。举例; + +### 1. 系统架构图 + +**软件架构**是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。软件架构会包括软件组件、组件之间的关系,组件特性以及组件间关系的特性。软件架构可以和建筑物的架构相比拟。软件架构是构建计算机软件,开发系统以及计划进行的基础,可以列出开发团队需要完成的任务。 + +
+ +
+ +- 这是一套大营销系统的分布式架构设计图,从前端到负载,从服务治理到后端分布式技术栈体现,从应用到部署和监控的全体系展示。在这样一套系统架构中,你可以清楚的知道从前到后的流程、各项分布式技术栈的用途、整个系统的脉络关系。所以这样的一个图可以清晰的指导我们做系统的搭建。 +- `佛瑞德·布鲁克斯`在写作《人月神话》一书时提及:软件系统的架构是有关软件系统该作什么以及不该作什么的实体观点。这些观点应和软件的实现分开。架构师的角色是“观点的看守者”,确认系统中增加的部分是符合此架构,因此可以保有概念完整性 +- 另外程序员`马尔文·康威`在1967年论文发表了康威定律,其中提到一个组织开发的软件,其架构会反映其组织架构。佛瑞德·布鲁克斯在写作《人月神话》一书时,就在书上时提到此例子,命名为“康威定律”。 + +### 2. 四色建模图 + +如果系统是 DDD 开发的,还需要做四色建模。在使用 DDD 的标准对系统建模前,一堆人要先了解 DDD 的操作手段,这样才能让产品、研发、测试、运营等了解业务的伙伴,都能在同一个语言下完成系统建模。 + +- 蓝色 - 决策命令,是用户发起的行为动作,如;开始签到、开始抽奖、查看额度等。 +- 黄色 - 领域事件,过去时态描述。如;签到完成、抽奖完成、奖品发放完成。它所阐述的都是这个领域要完成的终态。 +- 粉色 - 外部系统,如你的系统需要调用外部的接口完成流程。 +- 红色 - 业务流程,用于串联决策命令到领域事件,所实现的业务流程。一些简单的场景则直接有决策命令到领域事件就可以了。 +- 绿色 - 只读模型,做一些读取数据的动作,没有写库的操作。 +- 棕色 - 领域对象,每个决策命令的发起,都是含有一个对应的领域对象。 + +
+ +
+ +- 系统建模后可以细分出系统开发中要实现的领域,包括;返利、活动、策略、奖品,兑换可以是单独的领域也可以合并到返利实现。 +- 具体的建模过程可以阅读 [《架构:DDD 领域驱动设计,战略、战术、战役,落地指引规范》](https://bugstack.cn/md/project/big-market/ddd.html) + +### 3. 设计模式图 + +设计模式是解耦系统流程非常重要的手段,通过设计模式把复杂的流程切割成可以被容易处理的执行单元,在通过设计模式的创建、行为、结构,三类模型完成执行动作的处理。 + +
+ +
+ +- 如图,这是一个规则树模型,解决的拼团中实际的场景业务。从根节点、开关节点、营销节点、人群节点,再到最终的正常和异常结束节点。每个节点分别处理自己的业务流程。 +- 你可以想象,如果没有这样的设计模式模型结构,那么在代码中,就是一个大方法中,一堆的逻辑编写,维护的成本是非常高的。 + +### 4. 源码解析图 + +各类的框架源码中有非常多的设计技巧,也有很多的架构思维模型。如大家常用的 MyBatis 框架,拆解后的设计,就可以看出有多少东西可以学习。 + +
+ +
+ +这是整个《手写 Mybatis》的全貌地图,小傅哥会带着大家逐步实现这里面的功能模块,分章节细化各个模块的实现流程,最终让读者实现出一个丰富、全面、细致的 ORM 框架。在学习的过程中,大家也可以参考这张图来对照手写的代码以及 Mybatis 的源码,这样更加有利于对 Mybatis 框架的理解。 + +## 我是小白怎么开始 + +我的学习伙伴有在校的,有实习的,有毕业的,大家处于不同阶段。所以,小傅哥花费近4年时间,以大厂晋级能力项的要求,拆分出14个项目,以不同难度方式从小白到大白,一路培养,直至成长为高端的码农!在这个过程,你不只是学习到了想法,还学习到了一整套方法论。 + +如图,这是一整套的实战项目学习进阶路线,从小白到大佬,全程视频手把手带着从0到1,一步步完成项目的设计、开发和上线。在整套内容学习过程中,小傅哥为你提供了非常好的技术交流社群,及时解决学习问题。还包括调试你的问题代码,带你快速🔜出坑! + +
+ +
+ +- 首先,这一整套全体系的学习课程比私教培训实惠,更比培训班上万的培训费便宜。可能也就是培训班1天的💰钱,就能学习到这一整套内容了。 +- 之后,你学习的整套课程,就是小傅哥这个架构师自己全部原创编写的。这也就是说,你所提到的任何问题,小傅哥都能给你解答和讨论。 +- 那么,这么实惠的课程,成体系的课程,还是架构师编写的。还有什么可犹豫的,完全可以撸起来了! diff --git a/docs/md/zsxq/memorabilia/sideline.md b/docs/md/zsxq/memorabilia/sideline.md new file mode 100755 index 000000000..1f4179c38 --- /dev/null +++ b/docs/md/zsxq/memorabilia/sideline.md @@ -0,0 +1,101 @@ +--- +title: 啊?小傅哥的技术"副业",已经发展到了海外! +lock: no +--- + +# 啊?小傅哥的技术"副业",已经发展到了海外! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
星球:[https://t.zsxq.com/05zj2niYR](https://t.zsxq.com/05zj2niYR) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +😱一觉醒来我的社群地域范围又扩大了,从国内扩展到了海外。虽然以前也有海外的伙伴,但基本都是过去留学的,他们知道国内的各类论坛资料和公众号推文,所以也更容易关注到小傅哥。但这回不一样啦,直接微信加上来了“歪国仁”:**“hi brother, can you chat by english. i'm not in china.”** + +
+ +
+ +**brother 我,给👬🏻兄弟们建了一个很全面的技术社群** + +做技术号主,做久了才发现,其实并不非得一直追热点,也不非得张牙舞爪的玩活宣传。而是踏踏实实的把技术做好,服务好每一个加入社群的用户,把他的问题当做自己的问题一样处理。就能形成良好的口碑,那么自然就有这些兄弟伙伴帮你做宣传。 + +- 高校老师👩🏻‍🏫:"去学小傅哥应用级别的项目经验,看看互联网公司都需要什么技术" +- 哈工大师妹:"如获至宝呀,终于不用再做烂大街项目了" +- C9 f硕:"组里师姐极力推荐您的知识星球,全面有细致" +- 小红书用户:"最近跟着小傅哥,原来真的会有大佬手把手教着写代码,规划学习路线,还能每天答疑解惑,甚至能教简历怎么写" +- linux.do 用户:"搜小傅哥,把上面的都学了,不敢说大厂,其他的你都能进" +- 知乎用户:"没有吹牛,不是托,那个 OpenAI 大模型和营销项目看的我头皮发麻,确实学到了很多的东西。" + +>还有来自海外的伙伴,也加入了小傅哥技术社群学习实战项目。@kirito、@arthurshby 👏🏻 + +
+ +
+ +
+ +
+ +按照这样的发展势头,以后要给 [bugstack.cn](https://bugstack.cn/) 做中英文两个版本了 😂。小傅哥社群的伙伴反馈说,我是来学习技术的,没想到还顺便学习了英文。 + +
+ +
+ +小傅哥的社群有不少清北、北邮、哈工大以及很多C9、211、985的伙伴,还有很多来自阿里、美团、字节、京东、腾讯,等互联网大厂公司中的伙伴,这些人伙伴很多都能做英文交流,还能分享来自大厂的技术。这个社群已经形成了正向循环,不断探讨和积累实用技术,这让加入的伙伴只要认真学习,都会有非常大的提升。 + +## 一、学习能力 + +小傅哥,非常重视社群内伙伴的学习培养,从基础入门到进阶提升,花费了数年编写了大量的资料。这些成体系的内容,能把一个Java编程基础小白,抬着进入到高级开发。可以说跟着小傅哥学习,你会节省非常多的时间。并且目标感十足,有小傅哥为你解答,你会清楚的知道学习多少能走到哪。因为小傅哥的发展,也基本是这个行业的普通人打工人天花板呢了。 + +
+ +
+ +另外,小傅哥截取了社群伙伴的学习分享,你可以看到正是因为社区内有良好的学习氛围,又有可以深入研究的课程,所以大家也才更有东西,也真的能学习到东西。 + +
+ +
+ +
+ +
+ + +>小傅哥的社群内有大量的技术积累,这里面搜索🔍的都是真实有价值的东西;大量的场景问题方案学习后就够面试讲的了,500多份简历评审记录就够为你做简历编写的蓝本了。 + +## 二、手把手教 + +就学习来说,只要你是个新人,就一定会遇到各种各样的问题。不少伙伴在加入前,给小傅哥说:"我是新人,我装环境可能都会遇到问题,可以问你吗"。当然没问题,你加入我的社群,这都是我应该服务你的。不会你加入后,我就不管了,那还是人吗! + +所以,无论是编程环境问题、业务理解问题、编码实现问题,都有小傅哥一次次解答的身影。还专门为场景问题建立 Q&A 帮助大家快速排查处理。如;[https://bugstack.cn/md/project/big-market/qa.html](https://bugstack.cn/md/project/big-market/qa.html) + +
+ +
+ +- 类似这样的问题排查解答,星球里有非常非常多。主要就是帮助伙伴排查问题代码,引导学习并提高解决问题的思维。 +- 因为小傅哥的经验是非常清楚的知道的,编程这东西是过程经验积累学习,不是结果答案学习。错误是千千万的,但排查错误的过程方式是固定的。所以要学习根本的东西。那么这样一次次引导,慢慢也就积累了解决问题的能力。 + +## 三、找到工作 + +跟着小傅哥学习,不会浪费时间,不会走小道弯路。全程做技术兜底,遇到的各种问题都能帮你解决。包括你学习时候的代码bug,可以把代码提交到星球,我来帮你调试。最终把兄弟们送到各个竞争赛道的头部,拿到最牛的薪资待遇 Offer! + +
+ +
+ +## 四、实战项目 + +这一年,干了近900万字!包括;小傅哥的社群干了一个大营销项目、一个小型支付、4个技术组件,还有一系列的技术文章和回答大家的技术类问题等。**更新频次嘎嘎高,知识积累相当大!** + +
+ +
+ +>🧧[加入学习](https://bugstack.cn/md/zsxq/other/join.html) diff --git a/docs/md/zsxq/project/ai-agent-scaffold.md b/docs/md/zsxq/project/ai-agent-scaffold.md new file mode 100644 index 000000000..6c9c050fd --- /dev/null +++ b/docs/md/zsxq/project/ai-agent-scaffold.md @@ -0,0 +1,295 @@ +--- +title: AI Agent 脚手架 + 场景应用 +lock: no +--- + +# 《AI Agent 脚手架 + 场景应用》- 综合 Spring AI、LangChain4j + Google ADK(a2a、mcp、skills),打造全新智能体架构方案。 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
项目:[https://t.zsxq.com/a8AJj](https://t.zsxq.com/a8AJj) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +💥炸了!**日更,日更,接下来这套新项目,即刻开启日更!** 是的,小傅哥又一个新 AI 项目来啦。可以说,现阶段 AI 是每个工程师都必备的技术技能。 + +从 `RAG` 到 `MCP`、`A2A` 再到 `Skills`,一系列的 AI 编程技术技能陆续迭代更新, +各个互联网企业也随之跟进开发自身的 AI Agent 智能体,解决业务场景问题。 + +因此你在 Boss 直聘,校招/社招,都能看到大量的 AI 应用开发岗位。`AI 没让程序员工作丢失,反而多了更多的岗位!` + +
+ +
+ +新项目,📅于25年12月初启动,26年2月底完结,将近耗时90天打造精品企业级智能体解决方案项目。 + +在小傅哥社群,`OpenAI 代码自动评审做了`、`OpenAI 应用 + 扫码登录 + 微信支付 + 敏感词过滤 + SDK 开发做了`、`AI Agent 可视化编排也做了`、`AI MCP 网关深入理解 MCP 协议还做了`! + +那为什么还要做一个 AI Agent 呢?🤔🤔🤔 + +因为 **【AI Agent 可视化编排】** 解决的是横向通用性场景方案,而本次要做的 **【AI Agent 脚手架 + 场景方案】** 是纵深业务场景细化方案(也是企业里必备的架构设计,针对细化场景,通用的编排就失效啦!)。`这些东西,不是个架构师带着你,那你就根本理解不到!` + +好,该项目为大家带来一套企业级 AI Agent 智能体脚手架底座及场景应用方案的实战编程项目。项目采用 `Spring AI`、`Langchain4j(对照学习)` + `Google ADK`(a2a 框架 + 工作流编排),融合 `MCP`、`Skills`、`Plugin`、`Session` 等多项智能体开发技术,构建通用智能体脚手架工程。 + +并借助该脚手架,用户能够快速高效地搭建各类智能体应用场景。就像本次项目,既带着你搭建脚手架,也带着你使用脚手架做场景用(价值超级大,还要带着你做手机版大龙虾 MobileOpenClaw 🦞!)。 + +
+ +
+ +**💻 每个工程师,都需要AI应用编程技能!** + +竹外桃花三两枝,春江水暖鸭先知🦆。没有哪个行业,有程序员👨🏻‍💻可以这么快的接触到世界的科技变化。甚至也只有程序员行业,可以驾驭 AI 技术,做出各项 AI 应用软件。`AutoPhone`、`OpenClaw`,码农正在加速改变这个世界! + +> 当前互联网企业,Java 有庞大的市场,如美团、京东、阿里、饿了么、滴滴等。这些业务都要大量的引入 AI 进行提效,如;客服、巡检、运营、监控等。因为这些业务本身也都是基于 Java 构建,背靠 Spring 框架。所以很多公司也就天然的选择了 Spring AI 框架开发智能体应用。包括;阿里还基于 Spring AI 做了 alibaba 版本,谷歌也做了 google adk 框架。现在你懂了,为什么我们选择 Spring AI 实现业务智能体项目了吧!当然,这些框架也都类似,选择一套学习后,其他的也都很容易上手。 + + + +>🧧 文末提供了本套项目的完整工程代码,此外还有其他的业务项目 + 组件项目,共计20个全部可以获取。 + +## 一、我能学到什么 + +首先,这是一整套从0到1,文档 + 视频 + 源码,包含前后端 + DevOps 的综合实战项目。带着大家进行需求分析、底座构建、脚手架设计、应用场景实践。所以,你可以非常完整的学习到关于 AI Agent 智能体的全部内容,让你具备企业级项目开发能力。 + +- 【后端】熟练 Spring AI、Langchain4j(对照学习)框架的使用知识,掌握 api、model、client 的组装构建。 +- 【后端】深入 Spring AI 框架,使用 spring-ai-community 包,引入 Agent Skills 技能。 +- 【后端】设计多种 MCP 加载策略,满足 local、sse、stdio 各种类型的加载操作。 +- 【后端】运用 Google ADK 框架,整合 Spring AI、Langchain4j 分别验证学习,做好技术调研。 +- 【后端】使用 Google ADK 框架,通过提供的 loop(循环)、parallel(并行)、sequential(串行),构建多样性智能体。 +- 【后端】通过 Google ADK 框架,掌握 Runner 运行插件机制,掌握智能体运行中各个节点的数据采集和控制操作。 +- 【后端】设计通用智能体配置 yml 文件,通过配置文件的内容编排,可以配置出复杂的智能体。 +- 【后端】深入 Google ADK 源码,调试源码找到bug,并提供解决方案。已经在google adk 发布了[issue #705 - 小傅哥为 Google ADK 框架,提交的 issue 记录](https://github.com/google/adk-java/issues/705) +- 【后端】拓展设计模式的使用,在智能体构建中,使用规则树模式进行各个节点的编排。编排依赖于 agent.yml 文件的配置。这是非常灵活的设计。 +- 【后端】基于 Maven 脚手架构建方式,对底座工程创建出通用脚手架项目。 +- 【后端】积累 Netty 通信技术,基于 Netty 构建通信网关。 +- 【前端】安卓 Android(Kotlin) 网关终端开发,做智能设备控制。`基于 AutoPhone 9B + OpenClaw 理解,构建 MobileOpenClaw` +- 【前端】使用 React 构建前端工程 + draw.io,实现出一套智能体绘图操作。这部分会结合 AI IDE + prompt 进行编程实现。 +- 【运维】在云服务器环境(Ubuntu 24)安装 Docker 环境 + Protainer 管理面板,以及初始化环境等(提供了一件安装脚本)。 +- 【运维】分别对前后端进行 docker 镜像构建,以及在云服务器上完成项目的部署操作。 +- 【其他】积累应用设计经验,面向对象开发,在整个工程实现中,都有非常干净,清晰,具备高内聚,低耦合,有单一职责的逻辑体现。 + +>小傅哥带着你做的是企业级项目架构和技术积累,通过这些东西的学习,在面试中与面试官交流,才会显得更为专业。 + +## 二、适合哪些伙伴 + +- 需要快速🔜写到简历(每个阶段完成都可以写简历),用于秋招/社招面试(本项目可快速部署验证结果)。 +- 对 AI Agent 智能体感兴趣,但不知道如何自己实现一套的。 +- 希望提高自己的架构设计思维,设计模式运用的。 +- 增强核心竞争力,储备一些非业务的核心技术类知识的。 +- 需要掌握 Spring AI、Langchain4j、Google ADK 框架使用。 + +## 三、项目是否硬核 + +很多小伙伴都害怕学习到一个`(前端)外壳漂亮`,`(后端)代码水货`的项目,满是 CRUD 缺少架构设计,也没有编程思维的体现。这样的项目,在面试后端工程师的时候,很难讲出东西。所以,这里小傅哥先把一些核心的架构设计给大家看看,让大家知道小傅哥带着你学习的东西质量如何。 + +### 1. 智能体整体设计 + +
+ +
+ +- 2025年11月27日,Google 正式在 Maven 仓库管理中心,推送了 0.4.0 版本 ADK,该版本新增加了 Spring AI 的集成。[google-adk-spring-ai](https://central.sonatype.com/artifact/com.google.adk/google-adk-spring-ai) 至此,也因此,小傅哥决定基于这套服务组合,设计智能体脚手架。 +- 首先,Google ADK 是一个智能体框架,他自身也是支持直接对接各类大模型的 API,以及构建 ChatModel 的。但在整合 Spring AI、LangeChain4J 以后,Google ADK 的使用,将会得到已经使用上述组件的公司更大的青睐。 +- 之后,Spring AI 解决的 AI 对接的前半部分,让你可以把 AI API、Model、Prompt、RAG、Tool(Function、MCP)等,非常方便的构建出一个单一的 AI Agent 服务(也可以称之为是一个客户端)。 +- 然后,Google ADK 解决的是,多个 AI Agent 怎么协同工作的问题。这里包括,Sequential 序列顺序执行、Loop 循环执行、Parallel 并行执行,而这些执行方式,又可以组合搭配的配置到一个 Sequential 中进行顺序执行(注意图中颜色)。绿色的是大模型服务,绿色部分可以被深黄色或者浅青色包装,之后在组合到 SequentialAgent - 序列执行中。 +- 最后,Google ADK 提供了记忆上下文 Runner 执行器(也可以自己扩展实现),在这里又提供了钩子插件,你可以对执行过程中的流程,进行拦截。这个过程类似 Spring 容器中对 Bean 对象的处理,before、after 的过程。 + +### 2. 系统的分层结构 + +如图,整体简要架构设计(剥离其他流程,方便理解); + +
+ +
+ +整个应用架构分为3层,包括;基础底座、脚手架、业务场景; + +- 基础底座,负责整 Spring AI + Google ADK 框架的使用,这里的重点在于整个智能体工作流程的设计和使用(第2部分20节课程)。 +- 脚手架,将基础底座使用 maven 抽取出脚手架,脚手架可以让我们快速复刻出一套基础工程(第3部分3节)。 +- 业务场景,结合 draw.io 绘图操作 + ai agent 智能体,做一套AI交互式画图系统(第4部分6节)。 + +### 3. 底座的运行流程 + +
+ +
+ +- 首先,从用户基于脚手架创建完成后,在使用 YML 文件进行智能体的配置,之后在启动项目后,会进行一些利的装配。api、model、agent、workflow、runner,再到 spring 容器。 +- 其中,关于智能体的工作流组装是非常巧妙的,可以自由组合出多种类型智能体。这部分不需要硬编码即可完成。 +- 最后,是整个内容装配完成后,提供了通用的接口能力可以进行对话。 + +### 4. 脚手架配置发布 + +
+ +
+ +- 左侧,对现有工程使用 maven-archetype-plugin 插件,构建工程脚手架。将当前的工程打包成一个可复用的 Archetype 模板。 +- 中间,打包好的脚手架,可以在本地直接使用,也可以发布jar到私服,让大家都可以使用。私服部分,后续在做处理。 +- 右侧,使用方可以基于命令,或者 IntelliJ IDEA 配置 Maven 脚手架的方式,创建和启动工程。这一节,我们先通过命令的方式使用。 + +## 四、应用场景举例 + +### 1. 普通对话 + +
+ +
+ +- 智能体搭建后,可以进行对话操作,基于你配置的 MCP 能力,它可以做很多事项。 + +### 2. draw.io + 画图 + +
+ +
+ +```java +agents: + # 1. 需求分析与检索智能体 + - name: agent_analyst + description: 负责理解用户意图,调用工具检索信息,并决定是请求补充信息还是继续绘图。 + instruction: | + 你是一个专业的需求分析师。你的任务是分析用户的绘图请求。 + 1. 如果用户提供了具体的上下文或需要引用外部知识(如Git仓库、本地文件),请使用可用的工具(MCP)进行检索和分析。 + 2. 分析用户的意图: + - 如果用户的描述模糊、不完整,无法直接生成图表,你需要返回 JSON 格式要求用户补充信息。 + 格式:{"type": "user", "content": "请补充关于...的具体信息"} + - 如果用户意图清晰,请整理出详细的绘图需求(图表类型、节点、关系、布局要求等)。 + 3. 输出你的分析结果。 + output-key: analysis_result + # 2. 绘图执行智能体 + - name: agent_drawer + description: 根据分析结果生成 Draw.io 的 XML 数据。 + instruction: | + 你是一个 Draw.io 绘图专家。请根据输入 {analysis_result} 进行操作: + 1. 如果输入是 {"type": "user", ...},请直接原样输出该 JSON。 + 2. 如果输入是详细的绘图需求: + - 设计图表的结构(UML、流程图、时序图等)。 + - 生成符合 Draw.io 规范的 XML 代码。 + - 确保节点布局合理,逻辑清晰,连线不能交叉等。 + - 输出生成的 XML 内容。 + output-key: draft_diagram + # 3. 检查与优化智能体 + - name: agent_reviewer + description: 检查绘图结果,确保无连线交叉等问题,并格式化最终输出。 + instruction: | + 你是一个图表质量检查员。请审查输入 {draft_diagram}: + 1. 如果输入是 {"type": "user", ...},请直接原样输出。 + 2. 如果输入是 XML 代码: + - 检查连线是否混乱或有严重的交叉(在文本层面尽力优化布局逻辑)。 + - 检查 XML 语法是否正确。 + - 如果有问题,请尝试修正 XML。 + - 最终输出必须严格符合 JSON 格式: + {"type": "drawio", "content": "这里放最终的XML字符串"} + output-key: final_result +``` + +- ai agent + draw.io,可以配置出一套交互式绘图智能体。我们可以把诉求发给 AI,之后 AI 进行分析和决策,让用户补充信息或者直接画图。 +- 在大量的测试和体验中,这套智能体 + gpt 5.1 可以绘制出非常符合企业中真实场景的流程图,效果还是非常不错的。如果你还配置 mcp 可以结合本地代码库,文档库,产品PRD库,那么它还可以更好的绘制出相关的流程图。 + +### 3. AutoPhone 实验性场景 + +智谱发布过一个 [Open-AutoGLM](https://github.com/zai-org/Open-AutoGLM) 类似于豆包手机,可以通过指令发送 AI,AI 操作手机完成一系列动作。目前官网这套产品目前使用的是 ADB 连接手机,数据线调试方式。 + +- 文档(手机 + Agent):[https://bugstack.cn/md/algorithm/model/autoglm-phone-agent.html](https://bugstack.cn/md/algorithm/model/autoglm-phone-agent.html) +- 官网:[https://github.com/zai-org/Open-AutoGLM](https://github.com/zai-org/Open-AutoGLM) + +这里小傅哥在体验了 OpenClaw 大龙虾的设计后,对 AutoPhone 也有了想法。我们可以设计一套安卓版的手机 MobileOpenClaw,在手机端开发一个网关,网关功能具备;`启动应用`、`点击指定坐标`、`输入文本`、`滑动屏幕`等。之后在让 AI 以借助 Socket 通信,对手机设备进行管理。 + +
+ +
+ +- 首先,需要实现一套 MobileOpenClaw 的网关,这部分内容是安卓开发的一个软件,如果 IOS 也还有其他方案。可以在 Github 检索相关资料 [https://github.com/search?q=phone%20agent&type=repositories](https://github.com/search?q=phone%20agent&type=repositories) +- 之后,基于脚手架,开发 MobileOpenClaw 智能体,这部分要通过 Socket 和 手机端进行通信。让 AI 识别用户意图,控制手机端执行相关操作。因为这里大量的视觉识别,所以 gemini-3-pro-preview 效果不错,另外就是 GLM 定制的 [AutoGLM-Phone-9B](https://github.com/zai-org/Open-AutoGLM) 模型,可以自己在 GPU 部署。 + +## 五、课程学习目录 + +全程`视频` + `文档` + `源码`,开局 IntelliJ IDEA + Webstorm + Android Studio,手把手带着你一路狂飙! + +
+ +
+ +>以下2、3、4部分,每部分做完,都可以写简历,也就是最早学习完2部分20节,就可以写一份简历啦! + +### 介绍 + +[AI Agent 脚手架 + 场景应用](#) - 综合 Spring AI、LangChain4j + Google ADK(a2a、mcp、skills),打造全新智能体架构方案。 + +[面试:技能、简历、问题汇总](#) + +### 第1部分:需求与架构 + +- [第1-1节:脚手架需求分析](#) +- [第1-2节:系统架构设计](#) + +### 第2部分:基础底座开发 + +- [第2-1节:工程初始化创建](#) +- [第2-2节:Api功能测试](#) +- [第2-3节:智能体配置表设计](#) +- [第2-4节:装配域结构化定义](#) +- [第2-5节:装配域节点-AiApiNode](#) +- [第2-6节:装配域节点-ChatModelNode](#) +- [第2-7节:装配域节点-AgentNode](#) +- [第2-8节:装配域节点-AgentWorkflowNode](#) +- [第2-9节:装配域节点-Loop、Parallel、Sequential](#) +- [第2-10节:装配域节点-RunnerNode](#) +- [第2-11节:智能体加载使用验证](#) +- [第2-12节:增强装配-RunnerNode](#) +- [第2-13节:增强装配-AgentWorkflowNode](#) +- [第2-14节:增强装配-本地mcp](#) +- [第2-15节:增强装配-回调plugin](#) +- [第2-16节:fix-多模态能力使用](#) +- [第2-17节:会话服务接口实现-service](#) +- [第2-18节:会话服务接口实现-trigger](#) +- [第2-19节:会话服务接口对接-ui](#) +- [第2-20节:增强装配-skills](#) + +### 第3部分:脚手架工程化 + +- [第3-1节:Maven脚手架配置](#) +- [第3-2节:上传jar到maven仓库](#) +- [第3-3节:部署脚手架网页](#) + +### 第4部分:业务场景(ai+draw.io) - `这部分内容非常有实用价值!` + +- [第4-0节:ai + draw.io 产品设计](#) +- [第4-1节:初始化工程搭建](#) +- [第4-2节:在页面嵌入draw.io组件和对话框](#) +- [第4-3节:智能体API接口对接](#) +- [第4-4节:AI+用户+DrawIO,交互式画图](#) +- [第4-5节:ai-draw-io,云服务器部署](#) + +### 第5部分:业务场景(MobileOpenClaw)- `这部分内容非常有意思!` + +- [第5-0节:MobileOpenClaw 产品设计](#) +- [第5-1节:初始化工程搭建](#) +- [第5-2节:手机网关能力设计](#) +- [第5-3节:通过 Netty 进行同步等待通信](#) +- [第5-4节:智能体初步配置使用](#) +- [第5-5节:智能体工作流设计](#) +- [第5-6节:异步结果响应](#) +- [第5-7节:图片位点识别增强](#) +- [第5-8节:多版本安卓版本策略支持](#) +- [第5-9节:会话上下文细化处理](#) + +>星球里另外一套 AI Agent 还对接了 ELK、普罗米修斯、微信公众号等,也可以把 MCP 对接过来进行系统巡检。有了这套脚手架的学习,你可以完成非常多的场景对接使用。 + +## 六、学习路线推荐(AI) + +小傅哥的社群星球「码农会锁」,现已经有20个实战项目,6个AI、5个业务、8个组件 + 1套源码(MyBatis),这6个AI项目,你可以按需选择学习。 + +
+ +
+ +> 综上,所有的实战项目,加入小傅哥社群,全部都可以学习的到! \ No newline at end of file diff --git a/docs/md/zsxq/project/ai-knowledge.md b/docs/md/zsxq/project/ai-knowledge.md new file mode 100644 index 000000000..f1f141032 --- /dev/null +++ b/docs/md/zsxq/project/ai-knowledge.md @@ -0,0 +1,167 @@ +--- +title: AI Agent 拖拉拽 + 动态配置 +lock: no +--- + +# 《AI Agent 拖拉拽 + 动态配置(RAG、MCP、Prompt)》 - 解析文档&Git仓库代码&AI工作流 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + + + +大家好,我是技术UP主小傅哥。 + +刚上周,老板说:`”把咱们招聘里也加一条,具备AI应用开发能力的优先!“`。是呀,现在越来越多的企业都在用AI开发能力提效了,如;聊天软件增加一键唯独信息归档提取、工作文档资料携AI对话分析、工程SQL语句脚本辅运营自动完成数据处理、代码编写用AI完成自动评审等等。这些都是在AI的基础上在构建应用,以后也会越来越多!所以,具备AI应用开发能力,也是每个工程师最应该具备的基础能力了。 + +并且用不了多久,各大互联网企业都将大量的推进落地,自有 [MCP](https://github.com/modelcontextprotocol) 服务的实现,用于增强企业 AI 应用的提效能力。因为 [MCP](https://github.com/modelcontextprotocol) 的加入,可以让你;一条命令`帮研发`,调用应用系统日志、排查系统CPU负载、自主选择是否调度数据库信息。也可以一条命令`帮运营`,搞定复杂的SQL执行、导出报表、分析数据、完成促活营销券的自动化配置上架。这就是 [MCP](https://github.com/modelcontextprotocol) 的魅力!👍🏻 + +
+ +
+ +**那么牛,MCP 是什么?** + +专业的术语 `MCP = Model Context Protocol` 模型上下文协议,可实现应用与外部数据源和工具之间的无缝集成。无论您是构建 AI 驱动的 IDE、增强聊天界面还是创建自定义 AI 工作流,MCP 都提供了一种标准化的方式来连接他们所需的上下文。 + +`来吧,上图!让你看看它是啥!` + +
+ +
+ +- 首先,站在用户的使用视角,研发或者运营,可以通过话术描述,完成系列的 AI 工作流,并拿到最终的结果。这就是 MCP 最终为你提供的服务。 +- 那么,你可以想象,在日常的工作中,运营、研发、产品、测试等,都有非常多的重复非创作性的工作,占用了大量的时间成本。尤其是研发,写写代码,就有运营过来,帮我查个问题吧,小嘚嘚。但如果有这样的借助于 MCP 实现的 AI 工作流,就可以完成80%以上的工作量。 +- 之后,站在技术的实现视角,MCP 是一个标准结构框架,你可以按照它(Spring AI)提供的 SDK 开发方式,完成本地化 API 的接入开发。让 AI 有明确的方式调用各类 API 服务接口。如果没有 MCP 这会是一件很麻烦的事情。 + +**跟着小傅哥学习,从不走偏!😄** + +- 2022年底,ChatGPT 开始火爆。 +- 2023年2月,小傅哥,开启了第一个基于AI的项目,ChatGPT AI 问答助手项目。让所有伙伴,都能学习到 AI 如何开发应用。 +- 2023年4月,启动OpenAI(ChatGPT/ChatGLM)微服务应用体系构建大型项目,让大家可以用微信登录、微信支付/蓝兔支付,构建自己的可对外付费提供服务的 OpenAI。这一年上车学习的伙伴,很多做了自己的 AI 产品,除了提高编程技能,又小赚了一辆宝马。 +- 2024年7月,结合企业诉求,开启 OpenAI + Github Acitons,实现代码自动化评审。这一年,不少伙伴在自己的公司中都有落地,个人也得到了述职晋升。 +- 2025年3月,咱们再起启航,基于 Ollama 部署 DeepSeek,开发 RAG 知识库,解析文档和Git仓库代码。这个东西,将是企业中构建自己知识库的又一项非常重要的事情。有了知识库,AI 代码的自动评审,会更加精准,也可以辅助分析需求等。 + +那么,接下来小傅哥就细致的介绍下,本次开启的新项目,可以让大家学习到哪些知识,掌握哪些技术。 + +> Spring AI MCP 与 24年末发布,学习此 AI 应用开发项目,你将是第一批具备 Java AI 应用实战开发能力的人。竞争力,嘎嘎滴! + +## 一、能学到啥 + +该项目是结合当下最火的 Ollama、DeepSeek、SpringAI 等技术构建的 RAG 知识库实现。从前端到后端到 dev-ops 的全栈式功能手把手实现。 + +- 前端,基于 AI 工具,设计前端对话页面,完成 HTML、JS、TailwindCSS 的编码工作。 +- 前端,配置跨域服务接口,前后端分离实现 UI + 服务端接口对接。 +- 后端,构建双层架构,直接面向需求编码。让学习伙伴更轻松完成 RAG 知识库核心知识的学习。 +- 后端,基于 Spring AI 完成 DeepSeek、OpenAI 双模型的策略对接,处理文本向量的解析和存储。 +- 后端,使用 postgresql 存储切割文本向量数据,完成知识库的解析和存储。 +- 后端,处理多样文本`(.md、.sql、.txt、.word...)`的解析储存以及Git克隆代码库遍历切割存储。 +- 后端,使用 Redis 存储知识库标签,用于检索展示使用。 +- 后端,基于 Flux 编写流式会话接口,以及增加知识库检索功能。 +- 运维,基于 Docker 部署 Ollama 环境,完成 DeepSeek 大模型配置。 +- 运维,使用 Linux、Docker、Nginx 完成项目的打包、构建、上线! + +虽然,知识库都有很多现成的工具。但研发的能力不是在于功能应用,而是具备这样的开发技能储备,在有需要的时候,可以举手🙋🏻‍♀️”我会,我来做!“ + +> 此项目,全程视频手把手操作 + 全部的小册文档,你可以轻松上手学会这样一个项目! + +## 二、项目介绍 + +这是一套基于 Ollama DeepSeek 大模型构建的增强 RAG 知识库检索项目,在这套项目上,实现了除普通文档知识解析外,增加了 Git 代码库的拉取和解析,并提供操作接口。为工程师做项目开发时,`需求分析`、`研发设计`、`辅助编码`、`代码评审`、`风险评估`、`上线检测`等,做工程交付提效。 + +
+ +
+ +### 第1期,RAG 我们做了什么 + +在 《DeepSeek RAG 增强知识库》第1阶段,基于 Spring AI 0.8.1 开发了一套可以上传文件和Git仓库进行解析、切割、存储,到使用向量库完成 AI 的知识库问答系统。并最终通过 Docker 部署上线。 + +#### 1. 对话页面 + +
+ +
+ +- 这是全程视频手把手,带着大家通过AI工具,完成的UI设计实现课程会演示这个操作),实现的一款非常简单漂亮的UI效果。 +- 我们可以结合知识库,进行更加有效的提问。像是公司中,会把知识库提供出一个标准接口,给其他各个AI应用平台提供能力。 + +#### 2. 上传知识 + +
+ +
+ +- 上传知识,可以解析不同类型的知识库。 +- 除了课程提供的文档库、代码库,你可以增加其他的知识库,如;网页的解析,与网页内容对话。让我们的UI,增加一个侧边栏,读取当前网页内容,分析对话。这样在公司中的一些工程的日志,错误分析时,可以更快的处理。 + +#### 3. 解析知识 - 后台日志 + +
+ +
+ +- 上传知识后,可以看到日志信息。 +- 一套工程作为知识库是非常具有开发价值的,在我们做提问的时候就不需要,人工的去分析工程,而是直接使用了。 + +### 第2期,MCP 我们要做什么 + +与第2期相比,第1期可以称之为小试牛刀,让小伙伴们以最快、最快的往事,积累,运用 Spring AI 框架,开发自己的 RAG 知识库。~~也是方便有些死鬼,早点写到简历上~~ + +到了第2期,你就开始吃上细糠了,小傅哥会带着你升级 Spring AI 框架为 1.0.0-M6 最新版本,多模型配置和操作 PG 向量库,使用 GPU 搭建响应速度更好的 Ollama DeepSeek 大模型(秒级处理),以及对接官网 DeepSeek 的大模型和统一 one-api 对接方式。 + +但这还只是开始,随着基础框架的升级完成,我们将进入 MCP 服务的开发实现。通过 AI 指令,完成 AI 工作流,调度各项 MCP 处理我们的任务作业。如图,举例操作; + +
+ +
+ +- 基于 MCP 服务的开发和对接,通过 AI 工作流指令,完成数据的采集和存放动作。💡 聪明的小伙伴以及开始联想,基于这样的 AI 开发,可以替代很多的日常工作啦。**没想到吧,也把自己替代了** 但仍然,蠢蠢欲动(我不做,别人也做呀)!~~实现后,晋升又有的讲啦!简历也有东西写啦!~~ +- 有了 MCP 后,相当于把我们需要;在一个网页操作数据库查询数据、打开另外一个网页看天气预报,再手动的创建个文件把以上的信息获取后,复制粘贴到文件里。这一些列操作,都让 AI 通过 MCP 模型上下文协议进行处理。也就是 AI 可以调用后台接口啦! + +### 课程目录 + +#### 第1期 RAG Spring AI 0.8.1 - 完结 + +1. 【更】AI RAG 知识库,项目介绍&需求分析&环境说明 +2. 【更】初始化知识库工程&部署模型&提交代码 +3. 【更】Ollama DeepSeek 流式应答接口实现 +4. 【更】Ollama DeepSeek 流式应答页面对接 +5. 【更】Ollama RAG 知识库上传、解析和验证 +6. 【更】Ollama RAG 知识库接口服务实现 +7. 【更】基于AI工具,设计前端UI和接口对接 +8. 【更】Git仓库代码库解析到知识库并完善UI对接 +9. 【更】扩展OpenAI模型对接,以及完整AI对接 +10. 【更】云服务器部署知识库(Docker、Nginx) + +#### 第2期 MCP Spring AI 1.0.0 - 开冲 + +11. 【新】AI MCP 项目介绍 +12. 【新】吃上细糠,Spring AI 框架升级 + GPU 部署 AI +13. 【新】吃上细糠,官网 DeepSeek + open-api 对接 +14. 【新】MCP 服务的应用类演示和使用 +15. 【新】MCP Spring AI 客户端npx调用,以及资源讲解 +16. 【新】MCP Spring AI 服务端webflux实现 +17. 【新】MCP Spring AI 服务端 + 客户端对接使用 +18. 【新】服务接口实现,增强 RAG 知识库 + MCP 服务使用 +19. 【新】应用服务接口与前端页面对接 +20. ... 随课程开发提供,包括后续的云服务部署。 + + +### 课程计划 + +课程已全部录制完成,计划在3月3日开更,3月16日之前全部剪辑更新完成。 + +
+ +
+ +- 全课程包括文档 + 小册,全程视频手把手带着做。 +- 课程地址:[https://t.zsxq.com/GwNZp](https://t.zsxq.com/GwNZp) + +--- + +课程包括;视频、小册、1 对 1 答疑解惑、专属VIP项目交流群,并且提供简历编写模板结构的一条龙🐲服务。让你学习后,直接拉开与还在玩具项目其他人的差距,面试脱颖而出提高竞争力!!! \ No newline at end of file diff --git a/docs/md/zsxq/project/ai-mcp-gateway.md b/docs/md/zsxq/project/ai-mcp-gateway.md new file mode 100644 index 000000000..6ac01e671 --- /dev/null +++ b/docs/md/zsxq/project/ai-mcp-gateway.md @@ -0,0 +1,121 @@ +--- +title: AI MCP Gateway 网关服务系统 +lock: no +--- + +# 《AI MCP Gateway 网关服务系统》 - 为各类应用服务接口,便捷转换为MCP服务而设计。 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/SNsgH](https://t.zsxq.com/SNsgH) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +两年多了,从2023年1月起,小傅哥就开始关注AI、跟进AI,落地 AI 技术相关的场景项目。`做了 AI 问答自动回复助手`、`OpenAI 应用服务(含支付买额度 + OpenAI SDK 开发)`、`OpenAI 代码评审`、`Ai Agent 智能体(RAG、MCP)`,让一众伙伴积累到了丰富的AI应用开发技术,可以满足当下互联网AI应用开发招聘诉求。**那么接下来,关于 AI 小傅哥还要带着大家什么呢?🤔** + +
+ +
+ +**足够高频,互联网AI应用场景,必备项目!** + +现阶段,众多互联网公司把 AI 作为公司的战略目标,基于 AI 为公司各类场景提效。甚至不少公司要求程序员的编码,AI 占比要有30%以上(来自于某论坛研发分享)。还在各个部门设立 AI 应用创新组。 + +而 AI 的主要提效方式,则是自研实现或基于 Dify 搭建一套 AI Agent 智能体。通过智能体把公司的文档资料转换为 RAG 知识库,再通过 MCP 协议对接各类应用的服务接口。这样我们对 AI Agent 智能体下达命令后,就可以进行分析,规划,执行,直至产出最终的结果。更多关于智能体的实现介绍,可以参考[《AI Agent 智能体设计实现》](https://mp.weixin.qq.com/s/dwsfadYKs7Uy4YvHfLFsVQ) + +**死鬼,重点来啦!** + +公司里为了扩展智能体可提效的场景,就要把现有的公司的各类应用服务接口,`日志的`、`监控的`、`服务的`、`交易的`、`结算的`、`营销的`、`人群的`、`数据的`等等,都要转换为 AI Agent 智能体可识别的 MCP 服务接口。这样就可能有成百上千,成千上完,甚至几十万个接口要做实现。 + +那肯定不能每个接口都写一遍 MCP 服务!所以,对于这样的场景问题,公司里会做一套统一的 MCP Gateway 网关服务系统,其他个各类接口(http、rpc),都可以通过一键配置的方式转换为 MCP 协议类型的接口,被 AI 可以识别和使用。 + +
+ +
+ +而小傅哥这次带着你做的 AI 类项目,就是实现一套这样的 **MCP GateWay 网关服务系统**。小傅哥,会带着你,实现MCP服务,分析 MCP 协议,通过做AI服务代理、网页协议对接、JSON-RPC2标准等方式,把 MCP 协议厘清,之后在手把手的带着你编写响应式的 MCP Gateway 网关能力(鉴权也可以放到网关做)。 + +> 🧧 文末提供了,小傅哥所有编程实战项目获取方式,一次加入即可获得17个已完结的和本次新开展的。 + +## 一、能学到啥 + +该项目是 AI 应用场景下的通用技术服务组件类项目,以解决接口 MCP 协议转换而设计实现。在整个项目中,你可以积累到关于 MCP 协议的深度分析,学习分析协议的技巧和方案,并积累关于设计一个组件解决通用场景问题的能力。 + +- 【前端】基于 html、js、div、css,设计 MCP 协议分析页面。 +- 【前端】基于 html、js、div、css,构建一套服务端管理系统,便于 MCP 协议的录入和使用。 +- 【后端】MCP 协议的分析、理解、运用。掌握 MCP 开发和使用的能力。 +- 【后端】基于 MCP 协议的分析和网关设计诉求,构建网关服务库表。 +- 【后端】运用 DDD 分层架构,设计 MCP 网关服务系统。 +- 【后端】构建AI代理服务,断点调试分析 MCP 协议。 +- 【后端】设计 MCP 分析协议网页服务,链接 MCP 服务,观察 MCP 协议。 +- 【后端】基于 Flux 响应式接口,设计实现 MCP 协议的 sse 连接、initialize 初始化响应、tools 工具的 list 反馈和 call 调用等。 +- 【后端】提供 MCP 协议的动态录入和加载能力,以及提供录入接口组件,便于其他系统可快速录入。 +- 【后端】设计 MCP 网关协议鉴权服务,确保 MCP 服务使用的安全性。 +- 【后端】熟练使用 okhttp3、retrofit2 框架,动态对接 HTTP 服务接口,用于 MCP 协议 toos/call 工具调用。 +- 【后端】扩展学习 rpc 泛化调用,给 MCP 协议提供使用。其实有了这套东西,还可以对接如硬件设备 rs232 串口通信,让 MCP 服务,管理你的硬件设备。 +- 【运维】熟练使用 Docker 在本地和服务端的配置和部署应用,以及在本地构建前后端镜像。 +- 【运维】熟练掌握 Git、GitCode,对工程代码的管理,推送、拉取、切换分支、合并代码等操作。 + +此外,小傅哥对于每个章节还讲解了章节的诉求、流程的设计,之后再到方案实现和功能验证。并在每个章节留有作业让大家练习。当然这还没有完,你知道小傅哥这个架构师画图还是非常牛逼的,所以你还能看到各种画图的技巧,耳濡目染的把这些东西学习成自己的本事!~ + +## 二、项目介绍 + +本项目是 AI Agent 智能体,关于 MCP 协议对接的通用网关服务项目,以解决各类业务接口便捷转换为 MCP 协议而设计实现。通过这样的配置,可以大大的简化从普通http、rpc接口到 MCP 协议的转换操作。这样的项目,也是每个互联网公司在做 AI Agent 智能体时,必备的基础设施项目。 + +### 1. 更新计划 + +本项目目前已经做了基础的筹备和验证,计划于10.26日开始更新课程。整体课程预计在20+节左右。带着你完整的实现一套 AI MCP Gateway 网关服务项目。 + +### 2. 项目资料 + +#### 2.1 协议分析 - 页面 + +
+ +
+ +- 编写了一套网页对接 MCP 服务的页面,把以前直接在 AI Agent 配置 MCP 协议使用的过程,通过页面一步步对接和使用的方式进行展示。 +- 有了这样一个操作过程步骤,你可以更加清晰的了解到 MCP 的执行过程,也能更好的为后续做 MCP 网关服务实现打下基础。 + +#### 2.2 协议分析 - 代理 + +
+ +
+ +- 为了更好的体现出 AI 和 MCP 的交互,这里小傅哥会带着你做一个 AI 的代理接口,来调试观察 MCP 协议的传输。 + +#### 2.3 初始版本 - 案例 + +
+ +
+- 小傅哥这里先做了一个初始的 demo 版本,跑通 MCP 网关,后续会设计整套 DDD 架构,完整整体协议和服务的对接。 + +## 三、课程大纲 + +**不同于网上demo项目。小傅哥带着你做的项目,是一步步,一个个章节的带着大家从0到1的方式,进行分析、设计和开发。是一个纯手把手教大家学习实战技术的项目!** 大家可以先看看课程的大纲,就知道可以学习到哪些东西了。 + +- 第1节:项目功能需求分析 +- 第2节:项目系统架构设计 +- 第3节:MCP 功能服务实现 +- 第4节:AI 服务代理实现 +- 第5节:通过AI 服务代理,分析 MCP 协议 +- 第6节:通过设计网页对接,分析 MCP 协议 +- 第7节:通过 json-rpc2 标准,官网资料,总结 MCP 协议 +- 第8节:设计网关服务端系统,讲解模块关系 +- 第9节:设计拆分领域模型结构 +- 第10节:设计需求服务库表 +- 第11节:网关协议功能编写(1、2、3、4),分步骤设计实现 +- 第12节:网关协议与数据库表对接 +- 第13节:网关协议与http接口对接 +- 第14节:网关协议与rpc接口对接 +- 第15节:网关协议能力管理端编写(1、2、3、4) +- 第16节:MCP 网关服务打包上线 + +随着课程开展,陆续更新课程目录,也会有一些新的内容加入。 + +>课程包括;视频、小册、1 对 1 答疑解惑、专属VIP项目交流群,并且提供简历编写模板结构的一条龙🐲服务。让你学习后,直接拉开与还在玩具项目其他人的差距,面试脱颖而出提高竞争力!! + diff --git a/docs/md/zsxq/project/api-gateway.md b/docs/md/zsxq/project/api-gateway.md index fbe30900d..60dec2374 100644 --- a/docs/md/zsxq/project/api-gateway.md +++ b/docs/md/zsxq/project/api-gateway.md @@ -115,5 +115,4 @@ lock: no ![](https://bugstack.cn/images/article/assembly/api-gateway/api-gateway-220809-07.png) - [x] [第2章:代理RPC泛化调用](https://bugstack.cn/md/assembly/api-gateway/2022-08-20-%E7%AC%AC2%E7%AB%A0%EF%BC%9A%E4%BB%A3%E7%90%86RPC%E6%B3%9B%E5%8C%96%E8%B0%83%E7%94%A8.html) - [x] [第3章:分治处理会话流程](https://bugstack.cn/md/assembly/api-gateway/2022-08-27-%E7%AC%AC3%E7%AB%A0%EF%BC%9A%E5%88%86%E6%B2%BB%E5%A4%84%E7%90%86%E4%BC%9A%E8%AF%9D%E6%B5%81%E7%A8%8B.html) -- [ ] [第4章:方法执行器封装](#) -- [ ] 梳理中 ... 每周更新 +- 现已全部更新完成 diff --git a/docs/md/zsxq/project/group-buy-market.md b/docs/md/zsxq/project/group-buy-market.md new file mode 100644 index 000000000..7cf2b9928 --- /dev/null +++ b/docs/md/zsxq/project/group-buy-market.md @@ -0,0 +1,132 @@ +--- +title: 拼团支付平台系统 +lock: no +--- + +# 《拼团交易平台系统》- 为各类交易场景,提供拼团服务。 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/Yfbwo](https://t.zsxq.com/Yfbwo) + +> 沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +🌻 讲道理,为了提升能力冲击面试,不做点C端场景,不搞透业务流程,只是包个壳的小demo项目,真的进入面试官眼不了一点。面试官更喜欢的是他自己做过的真实的业务场景,这些东西都是非常成熟的业务和可上线使用的系统设计。所以,多做点这样的东西,才是提升能力的东西。 + +
+ +
+ +**那咱们做什么项目呢?🤔** + +在小傅哥的项目版图中,为大家提供了;`下单支付(支付宝、微信、蓝兔)`、`抽奖活动`、`积分兑换`、`行为返利`等,那么咱这次再做一个与支付相关的,中大厂都有的,互联网中必备的项目 **《拼团交易平台系统》** - 为各类交易场景,提供拼团服务。 + +在你看到的`拼多多`、`京东`、`腾讯`,都有很多的拼团场景。因为拼团可以在,设置折扣低价的情况下,激励用户分享到自身的圈子范围,完成拉新一起成单,提高交易完成量。所以这是一个互联网中必备的营销类系统。 + +
+ +
+ +跟着小傅哥(大厂架构师)学习,早些了解真正的真实业务项目,成为这个圈子里的技术佼佼者。横卷Offer! + +>🧧 文末提供了获取项目课程和代码。包括;已完结的6个业务项目、7个组件项目、以及各类基础教程。 + +## 一、能学到啥 + +小傅哥带着学习的项目,主打一个真实。全程从0到1,带着学习。直至完成开发再部署上线,并提供上线系统的域名配置、前端埋点、后端监控等一些列的真实实操技能。所以你能学习到的也是非常丰富的。 + +- 【前端】熟练使用,HTML、Div、CSS、React、Typescript 等前端编程技术。 +- 【前端】掌握 fetch 方式对后端接口的调用,处理相关的逻辑数据。 +- 【后端】熟练搭建项目工程,学习工程分层结构概率和设计思路。掌握更多的六边形、洋葱、整洁架构。`提高简历技术亮点` +- 【后端】熟练掌握 Spring、SpringBoot、MyBatis 等开发框架技术,并对框架源码所提供的扩展接口具备运用能力。 +- 【后端】熟练使用 SpringCloud 核心微服务分布式技术栈,包括:Fegin、Sentinel、Nacos、熔断、限流、降级等。`先做功能,后面逐步添加。` +- 【后端】熟练使用大厂中常用的设计模式手段和设计原则技术,对各类场景的方案设计和落地能力,深度提高自身编码思维和开发技术能力。 +- 【后端】深度学习复杂场景的架构设计、编程思维,如果处理系统功能的边界和上下文的维护。—— 这些东西一定是从实践中才能学习到的。 +- 【后端】熟练使用 Mock 单测工具、JMeter 压测工具,增强代码交付质量。 +- 【后端】熟练掌握异常、枚举、错误码的定义和使用,并学习到如何合理打印服务日志,便于问题排查。 +- 【运维】熟练使用 Docker 在本地和服务端的配置和部署应用,以及在本地构建前后端镜像。 +- 【运维】熟练掌握 Git、GitCode,对工程代码的管理,推送、拉取、切换分支、合并代码等操作。 +- 【运维】熟练使用 Nginx 配置转发服务,并能申请ssl配置https服务。 +- 【运维】熟练使用 Grafana 监控系统,对系统的 JVM、磁盘、Tomcat、应用(QPS、响应时间、调用量)完整监控。 + +此外,小傅哥会把系统开发过程中的思考、设计、编码,录制⏺成完整的**全程手把手带着学习的视频**,让大家可以学习到的更多、更细、更深! + +> 学项目,就要学一些有深度的、流程完善的、而不是连业务流程都串不下来的项目。这样的小demo项目,面试的时候,也会很容易被面试官攻击。 + +## 二、项目介绍 + +本次项目是一个包含 `前后端 + Dev-Ops` 的全栈式综合编程实战项目,完成后会与小傅哥星球「码农会锁」的其他项目进行对接使用,以此学习真实的微服务对接。如;之前的`大营销 + OpenAI` 完成上线部署,体验地址:[https://openai.gaga.plus](https://openai.gaga.plus) + +C端场景项目的特点,就是感觉前端展示的很少,但后端往往要有一大的流程等着实现。如;你要认领任务,邀请用户、完成既定目标、驱动流程流转、结算结果或逆向结果。所以这也是面试中,面试官喜欢扣场景细节的部分。 + +在我们完成`拼团`项目后,会在星球的小型支付单独一个分支进行验证,以及对接到 OpenAI 业务项目上。如图示意(后续会做更漂亮的UI); + +
+ +
+ +>体验地址:[https://openai.gaga.plus](https://openai.gaga.plus) + +### 1. 产品流程 - 核心流程 + +
+ +
+ +### 2. 功能流程 - UML + +如图这是一套拼团业务功能的研发设计流程图,涵盖了功能的流转细节。后续的功能实现会以这个为参考进行设计。 + +
+ +
+ +> 很多的学习就是这样,要把细节夯实。不用贪多,但要求精。 + +## 三、课程计划 + +课程在`24年11月16日`开更,预计在30-40节课程。全程视频手把手带着做,即使是小白也能跟着学习下来。`实习/校招生也是小白,在公司也是直接快速进入项目理解和承接需求。` + +课程地址:[https://t.zsxq.com/Yfbwo](https://t.zsxq.com/Yfbwo) + +- 拼团支付营销平台介绍 +- 第1部分:系统设计 + - 第1-1节:拼团需求分析 + - 第1-2节:拼团库表设计(7~10张表) + - 第1-3节:研发系统设计(建模、架构) +- 第2部分:服务实现 + - 第2-1节:初始工程搭建 + - 第2-2节:拼团活动实现 + - 第2-3节:拼团规则设计 - 切量、黑白名单等、免拼、最低成团、次数限制、达成目标 + - 第2-4节:折扣计算规则 + - 第2-5节:人群标签设计 - 自动跑数据服务 + - 第2-6节:拼团规则服务 + - 第2-7节:参与拼团设计 + - 第2-8节:拼团记账实现 + - 第2-9节:拼团回调实现 + - 第2-10节:拼团结果记录 - 接收外部拼单数据 + - 第2-11节:拼团超时失败检测任务 - 退单流程 + - 第2-12节:人群标签生成任务 + - 第2-13节:外部接口设计 + - 更多随课程揭晓 ... +- 第3部分:外部对接 + - 第3-1节:简易对接案例 + - 第3-2节:对接小型支付,拼团下单 + - 第3-3节:对接OpenAI大营销,拼团下单 +- 第4部分:开发运维 + - 第4-1节:构建打包部署 + - 第4-2节:HTTPS(ssl)、后端监控、前端监控 + +>课程包括;视频、小册、1 对 1 答疑解惑、专属VIP项目交流群,并且提供简历编写模板结构的一条龙🐲服务。让你学习后,直接拉开与还在玩具项目其他人的差距,面试脱颖而出提高竞争力!!! + +## 四、加入学习 + +跟着小傅哥学习,不会浪费时间,不会走小道弯路。全程做技术兜底,遇到的各种问题都能帮你解决。包括你学习时候的代码bug,可以把代码提交到星球,我来帮你调试。最终把兄弟们送到各个竞争赛道的头部,拿到最牛的薪资待遇 Offer! + +
+ +
+ +>🧧 [加入](https://bugstack.cn/md/zsxq/other/join.html) 每年招聘,都能帮助兄弟们规划好学习路线,卷出最好的 Offer!星球里还有500份评审过的简历记录,看过后,就知道怎么写好简历了。 diff --git a/docs/md/zsxq/project/local-task-message.md b/docs/md/zsxq/project/local-task-message.md new file mode 100644 index 000000000..0bd33540a --- /dev/null +++ b/docs/md/zsxq/project/local-task-message.md @@ -0,0 +1,99 @@ +--- +title: 本地任务消息组件 +lock: no +--- + +# 《本地任务消息组件》- 为事务和消息推送(HTTP、MQ),提供最终一致性解决方案 + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/Pfekb](https://t.zsxq.com/Pfekb) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +**你说气人不**,每每公司`晋升提报`和`加薪`的时候,总是那些手里有俏活的👬🏻兄弟。业务项目虽然是根基,但大家都做也就拉不开差距,而技术类组件、通用服务、功能平台,倒不是所有人都能搞的,这类结合业务场景的提取共性问题,凝练成通用解决方案的项目,可以开发一个就解决了全大部门的问题,所以做这类项目很亮眼! + +
+ +
+ +**这类项目也有门槛!** + +看着好像做个技术组件也没啥,但实际真想做的时候,你会发现你不知道什么服务可以被抽取为通用组件,不具备这样的经验和眼界。同时即使知道做啥了,也不知道如何结合像 Spring、MyBatis 源码能力,开发出一个通用的组件来,能让其他业务项目引入使用。 + +有人讲这东西不就是重复造轮子吗?🤔 还真不是,重复造轮子,指的市面上有的,或者公司里有个基础平台组有的。但这类的轮子往往不是深度结合业务的,而是那种无业务属性的功能逻辑的轮子,比如;rpc、xxl-job、mq 等。但一个业务组,他所需要的是解决通用业务场景问题的轮子,但这类东西又不属于基础平台研发组,所以往往都是业务组自己来解决这类场景问题。 + +所以,让自己具备开发组件的能力,是非常非常重要的,这即是抽象业务也是驾驭源码的能力体现。 + +小傅哥已经为大家提供了非常多的通用组件项目,如;`扳手工程(DCC动态配置中心、设计模式、动态限流、任务调度)`、`BCP 透视业务监控`、`动态线程池`、`支付SDK组件`、`SpringBoot Starter (16个合集)`、`IntelliJ IDEA Plugin 插件开发能力(具备这个的,开发了不少AI类组件)`。 + +这次小傅哥给大家再加一个新的组件《本地任务消息组件》,该组件解决业务场景远程调用HTTP或推送MQ消息,最终一致的问题。 + +## 一、能学到啥 + +【架构】掌握 DDD 分层与端口-适配器模式,清晰划分 domain/infrastructure/trigger/config 模块,提升可维护性与扩展性。 +【后端】学习注解+AOP 方式受理任务消息,结合事务边界进行统一处理,理解 `@LocalTaskMessage` 与切面配合的落地实践。 +【后端】掌握本地消息表设计与分片扫描策略(按门牌号 houseNumber 分片),实现高效拉取与顺序处理,提升系统可靠性。 +【后端】熟悉 Spring Event 事件驱动与异步消费,使用 `ApplicationEvent`+`@EventListener`+`@Async` 实现解耦通知链路。 +【后端】实践策略模式实现可插拔通知能力,支持 HTTP 与 RabbitMQ 两种通知通道,并在成功/失败时更新任务状态。 +【后端】熟练使用 OkHttp3 与 Retrofit2 统一封装 HTTP 网关,掌握动态 URL、Header、Body 的组合与异常处理。 +【后端】了解 RabbitMQ 事件发布的可选依赖注入方式,避免未配置 MQ 时的强依赖导致应用启动失败。 +【配置】掌握 `@ConfigurationProperties` 驱动的多任务组动态调度配置,支持 cron 与 fixedDelay 两种触发方式,并可配置批次大小 limit。 +【运维】学习 `ThreadPoolTaskScheduler` 的线程池化调度管理,合理设置线程名与池大小,提升任务调度的可观测性与稳定性。 +【数据】掌握原生 JDBC 访问与 DAO 封装,完成插入、状态更新、分片条件查询、最小游标查询等落地实现。 +【测试】通过示例命令对象 `TaskMessageEntityCommand` 的构建与调用,理解入参约定、枚举策略与配置对象的协作。 +【实践】提升异常、日志与枚举的综合使用能力,建立稳定的错误处理。 + +## 二、项目介绍 + +**《本地消息任务组件》** 项目,是以自定义注解 AOP 切入或编程的方式,动态化完成数据库表事务和消息推送(HTTP、MQ),达到最终一致性的目的。 + +>在没有这样的组件的时候,为了完成业务流程的同时,在发送一个MQ消息或则远程调用 HTTP 操作,都需要自己写一个本地消息表,之后还要维护消息表的扫描补偿。 + +操作方式如图; + +
+ +
+ +- 用户可以选择通过注解或者直接调用组件服务的方式进行使用。也就不用业务项目工程再维护关于本地消息表的写入和 MQ 或者 HTTP 的处理和补偿了。 +- 注解方式,会自动获取入参,入参需要为 TaskMessageEntityCommand 对象,它可以是某个入参的对象。之后配置 req.command 也可以获取。 + +## 三、产品方案 + +### 1. 产品概述 + +本地任务消息组件基于 Spring 框架能力,设计并实现了通用功能内核,便于集成到各类业务系统中。在业务系统中,组件支持在事务内完成数据写库的同时,写入一条本地消息记录(需在业务系统数据库中创建符合组件规范的本地消息表)。写入完成后,组件同步推送 Spring 事件,触发事务外的异步处理,如 MQ 消息发送或 HTTP 回调。即使异步处理失败,组件内置的本地消息表定时任务(支持自定义配置“门牌号”多任务并行扫描,提升扫描吞吐量)会持续检测并重试通知,确保消息最终一致性和业务流程的可靠执行。 + +### 2. 技术架构 + +
+ +
+ +- 首先,Local Task Message 任务消息组件,是以解决通用业务场景中的,本地数据库事务和外部MQ/HTTP调用一致性问题而设计实现的。让上游业务系统,不需要在每个流程中,都要做大量的重复编码。而是通过注解或者直接调用组件内核服务即可完成消息的通知操作。 +- 之后,Local Task Message 任务消息组件,并不是一个单纯的工具性功能,而是剩余一个领域服务内核,它具备完整的领域功能,具备操作数据库表的能力,以及接收 Spring Event 事件,对接 MQ、HTTP 完成和外部的交互处理。 +- 然后,上游系统在使用这套服务时,只需要配置好对应的本地消息表(一个事务下,连的同一个库),以及引入组件和完成yml配置,即可直接使用。 + +### 3. 功能流程 + +
+ +
+ +- 引入本地消息组件后,以用户开发dao入库操作为开始,可以通过注解或者调用组件服务 `ILocalTaskMessageHandleService` 驱动同一个事务下,进行消息推送。 +- 切面的方式,会更为优雅简洁,不需要用户自己在维护调用关系。 +- 整个操作会由组件自行处理写库操作,基于 Spring Event 的监听和通知,触发消息推送。完成 http、mq 的调用逻辑。同时还有基于门牌号扫描的逻辑,增强吞吐量。 + +## 四、课程目录 + +现课程已全部录制完成,接下来会日更📅项目💐; + +
+ +
+ +- 6节课程,全程视频手把手,带着你分析需求,编写代码。快速完成一个组件项目。 +- 课程代码,以互联网公司方式逐步拉分支开发,你可以学习到正规的编码操作。 diff --git a/docs/md/zsxq/project/xfg-wrench.md b/docs/md/zsxq/project/xfg-wrench.md new file mode 100644 index 000000000..1d0fe1144 --- /dev/null +++ b/docs/md/zsxq/project/xfg-wrench.md @@ -0,0 +1,111 @@ +--- +title: 通用技术组件 - 🔧扳手工程 +lock: no +--- + +# 通用技术组件 - 🔧扳手工程,凝练共性功能,实现通用组件。为各个业务系统赋能! + +作者:小傅哥 +
博客:[https://bugstack.cn](https://bugstack.cn) +
课程:[https://t.zsxq.com/o7IBm](https://t.zsxq.com/o7IBm) + +>沉淀、分享、成长,让自己和他人都能有所收获!😄 + +大家好,我是技术UP主小傅哥。 + +哈哈哈,死鬼!又带来了一个新项目,**《扳手工程》** 一个通用场景解决方案项目,嘎嘎的冲过来啦!`这已经是小傅哥社群里,第17个项目啦!😱` + +
+ +
+ +**这是一个什么项目?** + +在互联网公司真实业务开发场景下,往往会有很多的业务工程系统进行落地,如;电商、交易、信贷、营销、分润、清分/结算等等,这些业务场景会落地非常多的业务系统。而这些业务系统中,会有很多的相同的非业务逻辑的共性技术诉求的处理,如;动态属性配置、熔断、限流、异常、数据采集监控、增强的mock服务、流量录制回放、切面拦截日志、模型设计框架等等。 + +这些共性的组件东西,不可能让每个系统全部自己实现一遍,既耗费人力,最后又实现的五花八门非常难维护。所以,在互联网公司中,会单独把这类通用的逻辑凝练成共用的技术组件,让所需的业务场景进行引入使用。 + +
+ +
+ +那么,这就是小傅哥要带着你做的一款通用《扳手工程》 SpringBoot Starter 系列组件,用于星球的业务项目中使用。**😂 星球里也确实有非常多的业务项目了,不开一个这样东西,那么就要很多业务项目都重复的实现!** + +> 💐 文末提供了17套实战项目源码,8套业务(含最新 AI RAG MCP)、8套组件,还有1套源码教程。 + +## 一、能学到啥 + +该项目是以真实的互联网企业架构方案为指导,建设星球业务项目通用技术组件支撑平台。全程手把手分析需求、架构工程、从0到1编码,让大家可以深入理解和学习组件化设计和落地。 + +- 深入学习 Spring、SpringBoot、MyBatis 框架源码,掌握 SPI 机制实例化组件入口,理解 Spring Bean 生命周期与 BeanPostProcessor 的实际应用,实现属性级别的动态注入与代理。 +- 掌握 Redisson 客户端的配置与使用,基于 Redis 实现分布式发布/订阅消息机制。 +- 理解自定义注解实现配置属性的自动注入与动态刷新,学习分布式系统中配置中心的设计与实现,提升组件化开发与扩展能力。 +- 深入学习 Spring AOP 切面编程,掌握注解驱动的方法拦截与增强技术。 +- 熟练运用 Guava RateLimiter 实现令牌桶算法的接口限流保护机制。 +- 掌握自定义注解与反射机制结合,实现灵活的功能配置与参数提取,精通本地缓存设计与管理,提升系统性能与资源利用率。 +- 深入理解分布式系统限流与降级策略,构建高可用服务保障体系。 +- 熟练应用代理模式与策略模式,提升代码的可扩展性与可维护性,掌握 Java 反射机制在属性获取与方法调用中的高级应用。 +- 精通动态配置管理与功能开关设计,实现系统的灵活控制,深入理解异常处理与日志记录的最佳实践,提升系统可观测性。 +- 掌握面向接口编程思想,设计支持分布式场景扩展的组件架构,深入掌握责任链模式在复杂业务流程中的应用,提升系统解耦与扩展能力。 +- 学习策略模式在动态业务路由与决策中的实现,增强系统灵活性,掌握泛型与函数式接口在设计模式中的高阶用法,提升代码复用性与类型安全。 +- 理解链式调用与链路装配技术,实现业务处理链的灵活组装与动态扩展,掌握多线程与异步策略路由的设计与实现,提升系统并发处理能力。 +- 学习接口+抽象类+实现类的分层设计思想,为后续 SPI 等机制扩展预留入口。 + +以上,仅是关于组件技术开发的一部分,如果你想把一些之前硬背过的关于核心技术组件场景解决方案的东西彻底学会,而不是简简单单的背,那么这趟技术列车千万别错过。 + +## 二、项目介绍 + +本次项目你会学习到非常多的共性场景解决方案,这些内容可以引入到你做过的业务项目中进行使用。全过程以实际问题场景触发,设计解决方案,手把手编码。组件项目完成后,还会带着你发布自己的Jar到共有平台(https://mvnrepository.com/) 其他人也能引入使用。 + +### 1. 背景举例 + +
+ +
+ +当你学习大营销、拼团、OpenAI 应用等业务系统时,会遇到很多同类的功能诉求,如;规则树的设计模式、DCC 动态配置中心、接口限流配置等。这些东西其实都可以被抽象凝练成一个通用的技术组件,引入后直接配置使用即可,而不需要在每个业务系统中都开发一遍。 + +### 2. 架构设计 + +设计通用的统一规范的扳手工程; + +
+ +
+ +- 首先,我们会搭建一套标准的扳手框架 Spring Starter 工程。在工程内,以模块化方式陆续实现,动态配置、限流服务、通用设计模块框架。 +- 之后,以 Redis 作为简单注册中心使用,管理动态配置、限流服务等,再以 admin 管理端,下达配置命令,来动态操作工程配置。 + +### 3. 工程模型 + +
+ +
+ +- 定义 xfg-wrench 扳手工程,以 xfg-wrench-starter 为前缀,命名各项服务组件。如;`xfg-wrench-starter-dynamic-config-center` +- xfg-wrench-test 为测试工程,用于验证各个模块的功能实现。 +- xfg-wrench-admin 为管理后台,后续陆续创建完成。以及其他模块组件陆续迭代开发。 + +### 4. 流程设计(举例 DCC 动态配置) + +如图,动态配置中心功能流程设计; + +
+ +
+ +- 以 SPI 机制,实现组件入口类的注册。驱动注册中心和 Spring 容器工作。也就是工程的 `META-INF/spring.factories` 文件里配置的类,会被引入此组件的其他 SpringBoot 应用进行调用启动。 +- 接下来,注册配置会链接 Redis 当做注册中心使用。因为 Redis 具备了存储和发布订阅的功能,如 Dubbo 也可以使用 Redis 作为简单注册中心使用一样。而后出初始化动态配置中心的服务,以及监听订阅消息。 +- 在之后,拦截 Spring 容器实例化的 Bean 对象,找到使用了自定义注解 `@DCCValue` 的属性,对其拦截动态读取 Redis 中配置属性值(如无则首次设置值),之后对属性进行反射调用,设置变更后端 属性值。 +- 最后是,我们操作推送 Redis 发布订阅消息,则可以被消息回调,变更属性值。 + +## 三、加入学习 + +课程采用 `文档` + `视频`教程,全流程带着你分析和实现,并且会把组件也业务项目结合。小傅哥带着你做的,就是互联网中真实场景的运用。 + +
+ +
+**注意📢**,本项目也只是**【星球:码农会锁】**众多项目中的1个,其他的项目还包括:拼团、大营销、小型支付商城、AI RAG MCP、OpenAI 代码自动评审、动态线程池、支付SDK、API网关、Lottery抽奖、IM通信、SpringBoot Starter 组件开发、IDEA Plugin 插件开发等,并还有开源项目学习。 + +> 这将是一个新的技术旅程,在这趟车上🚗,你会了解到互联网公司大厂🏭是如何对这类场景的方案落地的。 diff --git a/package.json b/package.json index 40ef97668..356fbb2af 100755 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "@vssue/vuepress-plugin-vssue": "^1.4.8", "@vuepress/core": "^1.8.2", "browserslist": "^4.16.3", - "caniuse-lite": "^1.0.30001196", "screenfull": "^5.1.0", "vuepress-plugin-baidu-autopush": "^1.0.1", "vuepress-plugin-code-copy": "^1.0.6", @@ -30,4 +29,4 @@ "vuepress-plugin-img-lazy": "^1.0.4", "vuepress-plugin-table-of-contents": "^1.1.7" } -} \ No newline at end of file +}