LOGO
首页 网站广场 站长动态 活跃度榜 全部站长 审核查询 逛逛好站 留言交流 提交申请 关于本站

站长动态

站长动态所展示的是已加入好站网成员站长文章
共同步 2704 篇文章
(每2小时更新一次)
姓王者
入驻第1年
本来想搬fishport_serverwiki来着
本来想搬fishport_server_wiki来着一个我的世界服务器wiki图片感觉\x7e~还行~~,但是能力不足,况且搬到github上托管,对别的玩家来说,写wiki门槛似乎有点高了应该...
姓王者
入驻第1年
我的第一个博客
头像大头我的第一个博客应该不是最后一个为什么我想写一个博客最佳回答:我不知道显而易见的是,纯粹是我闲着没事干,又或者算是心血来潮,就像某些人明明没有什么需求缺偏要弄ipv6或者免流什么的 至少我...
九仞
入驻第1年
在Arch Liunx里只用Intel Ultra 7 155H跑stable-diffusion-webui
引言 虽然我把arch linux装在了移动硬盘里,使得我可以同时在我的轻薄本和游戏本之间运行同一个系统,并拥 […]
姓王者
入驻第1年
forever
记录一下搭建博客所用的资料真的非常感谢他们 !致以由衷的敬意!链接如下别忘了给他们点个star!Hexo 个人博客搭建及主题配置教程 [2024]在Hexo中给自己的博客添加萌萌Live2d看板...
乌托邦
入驻第1年
一些近况-202404
好久不见!距离上一次更新文章已经是两个月之前的事情了,在这两个月里,Utopia’s添加了一些新的业务和功能,下面让我们来看看都有什么新升级吧。 最大的升级,我们启用了全新的二级域名: utopias.site 这是一个比原来的域名更加具有辨识度的域名。因此,我们的博客也使用了全新的域名 b.utopias.site 。同时,Utopia‘s已经不只局限于单一的博客网站了,新的域名将更加方便构建“Utopia’s Universe”。 小改动。友链功能全新升级成为Utopias导航页,这里将收录不只是友链,还有Utopias系列站点。所有的页面都可以在导航页方便地查询和一键直达。 在经过4月的试点和5月的调整后,我们推出全新的功能UtopiAI。这是一个基于开源项目私有化部署的AIGC对话平台,接入了市面上主流的大模型,让与全世界最先进的AI对话不再复杂。 与UtopiAI同时上线的,还有乌托邦的小店Utopishop。目前店铺处于测试阶段,仅负责UtopiAI的点卡发行和售卖。 Todo: 筹备私有化部署的AI绘画平台Utopaint,接入mj、sd和通义万象。 完善UtopiAI的doc帮助文档,让UtopiAI接入更多的大模型。
陈仓颉
入驻第1年
《富兰克林自传》书摘
我最早在和菜头的《把自己安放妥当》这篇文章中得知《富兰克林自传》后开始阅读,开了个头不久便搁置,直到近期才一口 […]
Debug
入驻第1年
Phoenix框架 从0到1设计业务并发框架 自动构建有向无循环图设计
从 0 到 1 设计业务并发框架系列: Phoenix 框架 小米商城产品站革新之路 Phoenix 框架 怎么组织设计一个框架 Phoenix 框架 并发线程池的核心设计 Phoenix 自动构建有向无环图的业务并发框架,核心就在于不需要开发人员关心调用分层和依赖互斥的排序问题,通过算法进行自动构建、收集 Task 任务、检测环或者依赖,最后打印并发组分层信息。 本篇文章就讲解下如何构建有向无环图的设计实现方案及遇到的问题。 实现方案 有向无环图的构建采用的是设计模式中的策略模式,首先定义好 Builder 的实现方式,如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /** * @author debuginn */ public interface PhoenixBuilder { // 过滤 Phoenix API 使用到的 Task 任务 Map<String, ArrayList<TaskObj>> filterApiUsedTask(ArrayList<TransObj> transObjArrayList); // 根据 api 获取需要执行的 trans Map<String, ArrayList<TransObj>> apiTransMap(ArrayList<TransObj> transObjArrayList); // 是否存在依赖关系 void isHaveLoop(Map<String, ArrayList<TaskObj>> apiUsedTaskMap); // 处理并发组分层划分 Map<String, ArrayList<ArrayList<TaskObj>>> processConcurrentGroup(Map<String, ArrayList<TaskObj>> apiUsedTaskMap); // 打印并发组分层信息 void printConcurrentGroup(Map<String, ArrayList<ArrayList<TaskObj>>> phoenixApiArrayListMap); } PhoenixBuilder 需要实现 6 种方法: 首先,将收集上来的 Task,按照 API 进行分组,Task 存在依赖调用的都进行收集; 按照 API 进行收集 Trans,后续 Trans 使用请求线程进行串行执行; 判定每个 API 收集上来的 Task 是否存在相互依赖或循环依赖; 将每个 API 收集上来的 Task 按照先后依赖关系进行分组划分; 打印并发分组信息,用来给开发者调试及校验使用; 由于存在依赖关系,需要进行分层设计,这里可以结合 Phoenix 框架 怎么组织设计一个框架 来看,然而每一层并不需要关系执行的顺序问题,这里采用了最简单的数据结构存储分层信息,Map<String, ArrayList<ArrayList<TaskObj>>> Key 用来标识属于哪个 API 请求的并发分组,Value 则采用最简单的二维数组进行存储,每一维分别存储需要进行执行的 Task 任务。 遇到的问题 怎么判定存在环 由于我们要进行构建的是有向无环图,那么存在相互依赖的 Task,在框架设计逻辑中是行不通的,若存在相互依赖,那么究竟该先执行哪个 Task 呢? 可以看到上图,只要有两个场景: 相互依赖关系:TaskB 与 TaskD 存在相互依赖,那么就不能确定执行顺序; 环状依赖关系:TaskD、TaskF、TaskG 和 TaskE 存在依赖环,也无法确定执行顺序; 相互依赖关系判定比较简单,就是检索一个 TaskA 依赖的 TaskB 是不是也依赖这个 TaskA, 循环依赖判定相对来说比较复杂,需要遍历图的所有路径,若路径存在闭环,则代表着存在环,反之,就是不存在环路,代表就是单向依赖的分支路径。 怎么划分并发分组 划分并发分组,就是将彼此没有依赖关系的 Task 按照依赖的先后顺序进行分组,其实就是按照图的深度遍历。 这里的遍历,由于有依赖关系,可以采用向上遍历或者向下遍历的方式,我们采用了压栈的方式处理: 向上遍历 首先找到没有被依赖的 Task,这是一组,之后存入数组压入栈底; 之后栈底的 Task 收集出来需要依赖的 Task,这些收集上来的 Task 需要再判定是不是被其他 Task 依赖,若是依赖的话,则保存在临时的 Task 数组中,最后将剩下 Task 就是只被栈底 Task 数组依赖的 Task,那么将这个分组继续压入栈内; 重复第 2 步,把栈底的 Task 换成栈内最上层的数组,之后再把临时 Task 追加到收集出来需要依赖的 Task 上,去重,之后重复执行; 最后执行到剩下的 Task 没有依赖的 Task,这就是最后一个并发组,之后压入栈内; 最后程序执行的时候,就是先执行栈顶部的并发组,之后一次出栈执行。 向下遍历 首先找到不依赖其他 Task 的 Task,这是一组,之后存入数组压入栈底; 之后栈底的 Task 收集出来依赖这个分组的 Task,这些收集上来的 Task 判定是不是被其他 Task 依赖,若是依赖,也是保存在临时的 Task 数组中,最后就只剩下只依赖栈底的 Task 数组的 Task,之后将这个数组压入栈内; 重复第 2 步,把栈底的 Task 换成栈内最上层的数组,之后再把临时 Task 追加到收集出来需要依赖的 Task 上,去重,之后重复执行; 最后执行到剩下的 Task 没有任何 Task 依赖,这就是最后一个并发组,之后压入栈内; 此时,这个堆栈存储的是最先执行的 Task 并发分组在栈底,最后执行的在栈顶,需要进行反转操作,之后再依次进行执行。 为何要使用"策略模式" 在开发程序的时候,大家都不约而同地讲究程序的横向扩展能力,将核心的关键的任务拆分成具体执行的子任务,这样不仅可以提高程序的可阅读性,而且还可以扩展不同的遍历算法,用来后续框架的持续优化。 不仅这里,Phoenix 框架尽可能的采用策略模式实现,将核心功能点都进行拆分,做到模块化设计,这样的设计正是 Phoenix 框架的设计初衷,生生不息,持续迭代。 写在最后 本篇文章主要讲了如何进行自动构建有向无循环图的思路及遇到的问题,其实在开发中,这种解决依赖关系的场景还有很多,其实抛开上层的业务实现或者框架需求来看,底层就是最基本的数据结构,算法,图的遍历场景在当今比较火的 AI 场景下也是如此。 感谢你的阅读,你要是有好的方案或者好的 idea 可以与我一起交流,最后,如果你感兴趣,推荐关注公众号或订阅本站,欢迎互动与交流,让我们一起变得更强~ 关注微信公众号,第一时间获取最新内容,让我们一起变得更强!Debug客栈:订阅本站· 文章归档· 我的项目· 友情链接· 我的使用· 飞湾计划· 摄影展集· 我的主页
小生
入驻第1年
我这31年的漫漫人生路
  我叫李会生,1993年生人,妈妈跟我说在当时为了要我,差了一点要了我母亲的命!当时医疗条件并不发达,在我们当地的卫生院都不敢留,到县里医院更是拒绝,万般无奈我的姥爷赶着牛车将母亲送回到了姥姥...
林墨白
入驻第1年
给BearSimple主题加一个友链随机跳转
话说因为BearSimple主题功能太多,昨天才发现有一个幻灯片的功能没使用,但是我好像没有什么东西可以放上去,思来想去好像可以做一个友链随机跳转。本站随机跳转链接(点击幻灯片一样的效果):ht...
乌托邦
入驻第1年
Golang笔记-概况
//Hello World package main import "fmt" func main() {    /* 这是我的第一个简单的程序 */    fmt.Println("Hello, World!") } 关于包: 文件名与包名没有直接关系,不一定要将文件名与包名定成同一个。 文件夹名与包名没有直接关系,并非需要一致。 同一个文件夹下的文件只能有一个包名,否则编译报错。 main函数只能出现在main包里 行的分割并不需要分号; 但若两个语句需要在同一行(并不推荐这样做),可以用分号隔开。 注释 //单行注释 /**/多行注释 无效标识符: 以数字开头的 Go 语言的关键字 有运算符 字符串连接用加号+ //字符串连接 package main import "fmt" func main() {     fmt.Println("Google" + "Runoob") } GoogleRunoob 格式化字符串(输出) Sprintf 根据格式化参数生成格式化的字符串并返回该字符串。(作为返回值输出不打印) Printf 根据格式化参数生成格式化的字符串并写入标准输出。(打印输出) // 当前程序的包名 package main // 导入其他包 import . "fmt" // 常量定义 const PI = 3.14 // 全局变量的声明和赋值 var name = "gopher" // 一般类型声明 type newType int // 结构的声明 type gopher struct{} // 接口的声明 type golang interface{} // 函数声明 由main函数作为程序入口点启动 func main() { Println("Hello World!") } Go 程序是通过 package 来组织的。 只有 package 名称为 main 的源码文件可以包含 main 函数。 一个可执行程序有且仅有一个 main 包。 通过 import 关键字来导入其他非 main 包。 //import单个导入 import "fmt" import "io" //import多个导入 import( "fmt" "io" ) //给import导入包起别名 import fmt2 "fmt" 别名 原名 //省略调用(不建议使用) import . "fmt" func main (){ Println("hello,world") } 函数的private和public //函数名首字母小写为private func getid() {} //函数名首字母大写为public func Printf() 同理 包内调用方法名可小写首字母,包外调用方法名必须大写
乌托邦
入驻第1年
Welcome Back!
欢迎回来!现在是2024年4月 或许你会怀疑自己的眼睛,会疑惑为什么这个网页跟过去不一样了,会质疑浏览器打开了错误的网页,甚至会猜测是不是上任站长跑路了。 没错,正如你所见,在我们因为种种原因而无法相见的日子里,我们的网站完成了大改版重新上线了。 在过去的几个月里,我常常因为各种原因拖更文章,到最后更是彻底摆烂。各种bug和小毛病越攒越多,甚至网站的一些授权已经过期很久才被发现。 但现在,我回来了。人是喜新厌旧的,因此我决定重新改造这个网站,用一种新的面貌重新面对新的伙伴。或许全新的页面也能督促我多多更新吧。 最后,如果你想知道我们更新了些什么,欢迎访问全新改版的动态(现在叫瞬间),我会在那里发布更新日志。你也可以在这里催更(或许有用)闲聊,或者是提出你的意见。 总之,祝你我在见不到彼此的日子里,早安午安晚安。
九仞
入驻第1年
浙江财经大学校庆50周年之“三行代码作情诗”
代码 抽象版本如下 我为其添加了可运行的版本 运行说明,由于使用了JS的ES Module写法, 所以要手动将 […]
陈仓颉
入驻第1年
绿箭侠
You Have Failed This City! Arrow 时隔多年终于把大学时期未看完的 CW 台柱子 […]
Debug
入驻第1年
Phoenix框架 从0到1设计业务并发框架 并发线程池的核心设计
背景 从 0 到 1 设计业务并发框架系列: Phoenix 框架 小米商城产品站革新之路 Phoenix 框架 怎么组织设计一个框架 前两篇文章已经讲述了我设计框架的背景以及抽象设计的细节,今天讲一下并发框架最为关键的并发线程池的核心设计,主要讲一下在设计线程池划分遇到的问题以及最终我采用了哪种方式实现的。 将存在依赖关系的 Task 进行划分分组后,依次执行分组就可以拿到所有想要的结果,但是怎么划分线程池、设置线程池是面临的问题。 接下来,我将实际业务中的复杂度简化设计,将问题具象化呈现给大家。 方案:公用线程池 方案 最开始,我计划将分配的 Task 公用一个线程池,让 Task 去线程池竞争资源,如下图: 但是很快发现,单个线程池一旦请求数量上来,某个 Task 接口变慢就会导致整个接口成功率急速下降,直至不可用的状态。 为什么会出现这种情况呢? 效果 T1 时刻,第 1 波流量进来,之后率先执行 TaskA 或者 TaskB; TaskA 请求的快速递增,接口变得越来越慢; T2 时刻,还有两个 TaskA 并没有执行完毕,之后第二波流量进来: 第 1 波流量开始执行 TaskC 和 TaskD; 第 2 波流量进来,也有 TaskA 和 TaskB 获取到线程执行; T3 时刻,此时已经有 4 个 TaskA 还没有执行完,并且最开始的两个 TaskA 要面临着超时情况: 第 1 波流量执行的 TaskA 面临超时中断的情况; 第 2 波流量执行的 TaskA 也在运行状态中; 第 3 波流量进来,情况变得复杂,新的流量,有 TaskA 和 TaskB 进行执行; 此时第 1 波流量前两层运行完毕,开始执行 TaskE; 此时第 2 波流量的前一层运行完毕,开始执行 TaskC 和 TaskD; 之后按照 TaskA 始终慢的情况继续发展……. Tn 时刻,此时线程池大部分已经被前 n 波流量的 TaskA 占据着,并且大量被中断超时,其他 Task 无法竞争到线程进行执行。 这样的话,接口的可用性完全取决于 TaskA 的可用性,但是还有一个致命的问题就是其他 Task 无法执行或者由于依赖问题,前置该获取用作请求参数大部分为空,也无法正常请求,这样就算是接口返回了数据,也是不全的数据。 这种方案存在共用线程池大量线程等待超时的情况,是不可取的。 方案:分层线程池 方案 公用线程池的情况肯定是有问题的,在此基础上,尝试将分层并发划分不同的并发池,每一层公用线程池,如下图: 上了分层公用线程池之后,压力测试发现效果只有小幅的提升,没有达到预期的目标,甚至来说相差很远,为啥会出现这个问题? 效果 我们还是假设 TaskA 会随着请求量上来会大面积超时来举例。 T1 时刻,第 1 波流量进来,之后率先执行 TaskA 或者 TaskB,此次线程池 2、3 没有执行到; TaskA 请求的快速递增,接口变得越来越慢; T2 时刻,还有两个 TaskA 并没有执行完毕,之后第二波流量进来: 第 1 波流量开始执行线程池 2 的线程 TaskC 和 TaskD; 第 1 波流量存在 TaskC 执行完,陆续开始执行线程池 3 的线程 TaskE; 第 2 波流量进来,也有 TaskA 和 TaskB 获取到线程执行; T3 时刻,此时已经有 4 个 TaskA 还没有执行完,并且最开始的两个 TaskA 要面临着超时情况: 第 1 波流量执行的线程池 1 TaskA 面临超时中断的情况; 第 2 波流量执行的线程池 1 TaskA 也在运行状态中; 第 3 波流量进来,情况变得相对来说比较复杂,新的流量; 此时第 1 波流量前两层运行完毕,开始执行线程池 3 TaskE; 此时第 2 波流量的前一层运行完毕,开始执行线程池 2 TaskC 和 TaskD; 之后按照 TaskA 始终慢的情况继续发展……. Tn 时刻,此时线程池 1 大部分已经被前 n 波流量的 TaskA 占据着,并且大量被中断超时,由于依赖于 TaskA 和 TaskB 的结果作为下层的入参数: TaskA 过慢占据着接近 100% 的线程池 1 的资源; TaskB 竞争不到资源,被超时中断; 最后接口还是发展到不可用的状态,其实和公用线程池的问题一样,也还是存在大量线程等待超时 的情况。 这种公用线程池的现状是不可取的,那么该如何划分线程池来执行呢?其实分而治之的思想就可以解决这个问题,也就带来了 3.0 版本,独立 Task 线程池的方案。 方案:独立线程池 无论怎么公用线程池,都会出现被挤占的情况,只有将每个 Task 划分单独的线程池,才不会出现抢占等待的问题,那么如何设计的呢? 方案 每个 Task 单独创建线程池来承接流量,各个线程池互相不干扰,同时承接流量交给 CPU 抢占资源进行调度运行。 效果 由于是单独承接流量,这种设计满足了高可用的目标,还是依照 TaskA 接口随着并发请求的提升,接口越来越慢直至不可用,之后再加入一个条件,就是 TaskC 的执行条件是 TaskA 执行完毕的结果。 T1 时刻,第一波流量进来,所有线程池的线程都占满,开始进入核心调度执行; T2 时刻,第二波请求进来,第一波请求的 2 个 TaskA 还没有执行完毕,其他线程池的线程逐渐承接第二波请求等待调度; T3 时刻,第三波请求进来,这时候情况比较复杂: 第一波流量的 2 个 TaskA 已经超时被中断了,对应的 TaskC 的线程池的两个 TaskC 线程等待 Task 的执行结果失败,结束任务; 第二波流量的 2 个 TaskA 还没有执行完毕,也濒临超时; 其他线程池执行均正常运行; 就这样过了一段时间 … Tn 时刻: TaskA 已经达到了不可用的状态; 对此有依赖关系的 TaskC 也逐渐达到不可用状态; 其他线程执行正常; 这么看,针对于一个接口调用几十个上百个接口的场景,不会因为一个接口或者有依赖关系的接口可用性降低而影响整个接口的可用性,同时只要对单个线程池做好监控,加上报警即可动态感知哪些上游接口失败而及时通知到对应的系统维护同学,这样就大大的降低了维护成本。 这个版本作为线上生产环境的第一个版本推了上去,单台 8C 8G (k8s) 的配置空跑框架达到了 QPS 在 1.4w,接口可用性在 99.96%(结果仅供参考,根据公司集群部署策略、机器性能等问题会有浮动)。 但是,这种目前还是存在着显而易见的问题,就是每个 Task 执行的接口的接口响应都不是一致的,有的在 50ms 内、有的在 100ms 内、有的比较慢 500ms 内,分配相同的线程池数量是不合理的,因为这样就会造成 CPU 调度不公平,那么怎么让调度运行的比较公平呢? 优化 针对于这个问题,将线程池大小按照权重创建,像是比较慢的接口但是多等待一定时间可以返回的,我们就多分配线程池大小,接口响应很快的,我们就相对减少线程池大小,这样的设计可以在保证接口的可用性兼顾接口返回字段的完整性。 写在最后 本篇文章主要讲框架设计中怎么将划分好的分层并发执行,最终我们采用了独立线程池的方案,并且按照耗时、CPU 核数等权重评估分配每个 Task 任务线程池的大小,让 CPU 线程调度来确保线程都尽可能的公平执行到,最终保证接口的并发需求及高可用的场景。 如果你感兴趣,推荐关注公众号或订阅本站,欢迎互动与交流,让我们一起变得更强~ 关注微信公众号,第一时间获取最新内容,让我们一起变得更强!Debug客栈:订阅本站· 文章归档· 我的项目· 友情链接· 我的使用· 飞湾计划· 摄影展集· 我的主页
陈仓颉
入驻第1年
三体问题
一个周末的时间品鉴完网飞三体,有三体腾讯剧版珠玉在前,网飞三体就像一坨。原著1.5本的剧情压缩到8集(一集60 […]
林墨白
入驻第1年
Brave「Lv-1.5.6」- Typecho情侣主题魔改版
Brave Love❤️Forever Love❤️介绍Brave是一款好看且拥有多功能Typecho情侣主题,它非常适合有对象的博主使用。原版本作者:赵阿卷教程:https://blog.zw...
Debug
入驻第1年
Phoenix框架 从0到1设计业务并发框架 怎么组织设计一个框架
上篇文章主要讲了设计 Phoenix 框架前的遇到的问题和设计框架的思路 《 Phoenix 框架 从0到1设计业务并发框架 小米商城产品站革新之路》,本篇文章主要讲一下如何设计框架的。 不死鸟并发框架,是自动构建有向图按照深度进行构建并发组并进行并发调用结果的框架。 产品站业务静态接口与动态接口都需要调用大量的后台服务进行获取数据进行业务编排,而各个并发调用之间又相互存在依赖,采用并发组设计拆解依赖,同时并发控制调用,BO to DTO 采用统一的 Transfer 层进行设计,开发人员只需要关系定义每次调用事件的 Task 和 Transfer 代码逻辑的书写,直接返回业务数据。 名词解释 PhoenixFramework 不死鸟(凤凰)框架,此业务并发框架的名称; Task 在业务并发中定义一次调用,可以是 HTTP、DUBBO 或者是 Redis 获取、MySQL 读库操作; Transfer 在业务定义中是一个子业务模块的转换逻辑将 BO 数据转换为 DTO 数据; Task 与 Trans 注解 怎么定义 Task 在框架设计之初,我们内部有两种方案,一种是继承抽象类实现的方式,Task 通过继承实现 PhoenixTask 类实现定义 Task,另外一种是采用注解的方式,将每个 Task 都定义成具有强约束的 Task ,并且把详细的描述信息在注解中定义,给开发人员一目了然的设计思路。 经过内部讨论,我们选择了 Java 优秀的语言特性,注解的方式声明定义 Task ,这样的定义使得代码简洁明了,也有利于通过 Spring Bean 收集工具来收集我们的定义。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 /** * PhoenixTask * 任务注解 * * @author debuginn */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface PhoenixTask { String taskName(); // 任务名称 String[] beforeTaskName() default {}; // 前置任务 String[] filterPlatform() default {}; // 过滤渠道,黑名单 String[] taskBoName(); // 任务生成的 BO 数据 用来校验冲突 } PhoenixTask 注解定义非常简单: taskName用来标识任务名称,采用枚举,强制约束命名的唯一; beforeTaskName前置任务,前面讲到每个任务都是一次事件,区分前置任务是需要在并发调用的时候等待结果的返回,之后用来作为此 Task 调用的前置参数; filterPlatform 过滤渠道,也就是黑名单的功能,但请求渠道在 Task 中声明了黑名单,在并发执行的时候就自动屏蔽掉执行; taskBoName任务转化为 BO 的数据,通过接口调用或者中间件获取数据,转化为 Transfer 层使用的数据,在框架层做数据参数校验; 怎么定义 Trans Trans 是 Transfer 的简称,同样和 Task 设计一样,也是采用注解的方式定义: 1 2 3 4 5 6 7 8 9 10 11 12 13 /** * PhoenixTrans * 业务编排注解 * * @author debuginn */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface PhoenixTrans { String transName(); // 业务编排块名称 String apiName(); // 执行 使用并发 api String[] tasks() default {}; // 依赖的 task 任务 } PhoenixTrans 注解定义同样非常简单: transName用来标识业务编排块名称; apiName 用来区分这个 Transfer 业务编排是隶属于哪个并发 API 所属的; tasks就是定义依赖的 Task 任务有哪些,一个业务编排可能会利用 n 个 Task 返回的 BO 数据进行编排; 大家在这里可能会比较疑惑,为啥 Task 中没有定义 apiName 而是 Transfer 中定义的,是因为在设计中,为了便于后续 Task 可以被 n 个并发 API 共·用,这样在 Transfer 定义了 apiName,之后通过 tasks 定义依赖的 Task 就可以推断出这个 Task 目前是被哪一个并发 API 使用的。 怎么收集 Task 和 Trans 自定义了 PhoenixTask 和 PhoenixTrans 注解,通过声明一个 AnnotationProcessor 继承 BeanPostProcessor 来进行收集定义的注解。 首先是根据注解类收集上来对应的 Task 和 Trans; 根据不同的 Trans 划分不同的 API,收集不同 API 依赖的 Task; 按照 Trans 是否进行依赖过滤使用到的 Task; 根据 Task 之间的相互依赖关系,将 Task 进行分组; 这样就完成了对框架的分层与自动构建的设计,框架的设计主要的是要思考如何将实际业务中使用的模块抽象化设计,同时要思考框架的扩展性与强约束性。 结尾 本篇文章主要讲解我如何将业务与调用关系进行抽象成 Trans 与 Task 的,接下来我将讲述并发框架并发线程池的核心设计、配置化思考、监控设计以及自动构建算法等系列文章。 如果你感兴趣,推荐关注公众号或订阅本站,欢迎互动与交流,让我们一起变得更强~ 关注微信公众号,第一时间获取最新内容,让我们一起变得更强!Debug客栈:订阅本站· 文章归档· 我的项目· 友情链接· 我的使用· 飞湾计划· 摄影展集· 我的主页
林墨白
入驻第1年
对现代爱情的看法
语文课堂作文选题其一:对爱情的看法爱情本应是一种强烈的感情和亲密的体现。这种关系建立在互相尊重、信任和包容的基础上,并可能带来深深的幸福感和满足感。鲁迅曾说过:“恋爱就像放风筝,你不必过度束缚,...
阿川
入驻第1年
搞个公众号
阿川
入驻第1年
腾讯云COS文件跨域

© 2026 好站网-HaoZhan.Wang V1.9 版权所有,正在试运行中! 本站由 Zhou's Notes 强力支持!

苏ICP备19065220号-4 公安备案 苏公网安备32100302011680号 萌ICP备20269980号 茶ICP备2026050346号
本站数据 2026年报 版本历史 小黑屋 关于本站 统计代码