当前位置: 首页 > news >正文

区块链链服务架构优化 - zhyyao

调整区块链开发架构,优化链服务与主业务的耦合性,以及策略模式的应用场景...

背景

在链服务的开发中,由于交易成功具有一定的滞后性,即交易成功上链,但是最后这比交易的状态失败了。 出现的问题可能有:

  1. 并发问题:同一个钱包地址发起交易,第一笔交易未到pending状态,第二笔交易很快发布,导致使用了相同的nonce,导致交易失败。
  2. 合约设计:同一block中,不允许有重复的函数调用,否则会生成一个相同的链上签名hash,导致交易失败。
  3. 业务层面:需要根据交易状态进行后续的上链业务处理,但是由于交易状态的滞后性,导致第一笔交易未成功,之后的业务全部失败。
  4. 设计层面:由于上链调用的底层方法相同,区别在于函数的名称与构建合约如参数,所有就有大量的if else 逻辑,导致代码维护和扩展性差。
  5. 其他偶发与并发导致的上链、监听失败问题...

解决方案

  1. 参考消息队列机制,将所有需要上链的交易先存入一张表中,通过异步方式起一个定时任务查找需要上链的任务。
  2. 添加错误重发机制,避免出现因并发或者合约问题而交易失败,保证只要参数合法,交易必须完成上链。
  3. 拆分为上链服务与监听服务,上链服务只负责上链,监听服务负责监听链上交易状态,并根据状态进行后续业务处理。
  4. 利用Java的反射机制,以及通过策略优化上链逻辑,减少if else 逻辑,提高代码扩展性。

可能会带来的问题:整个项目流程可能变慢,需要定时任务轮询,才可以完成对应业务的上链处理。数据量大时,需要排队等待上链,但是可以保证业务的稳定性。

代码实现

数据库设计

添加Todo 表,用于存储需要上链的交易信息,包含交易hash、交易参数、交易状态、重试次数等。

create table if not exists request_list
(id                bigint auto_increment primary key comment 'key id',contract_address  varchar(66) null comment '合约地址',function_name     varchar(66) not null comment '请求方法名称',from_address      varchar(66) not null comment '交易发起方钱包地址',blockchain_params text        null comment '上链参数',transaction_hash  varchar(66)          default null comment '交易hash',request_status    int         not null default 0 comment '请求当前状态 0-未上链 1-pending 2-上链成功 3-上链失败',times             int         not null default 0 comment '重试次数',create_time       datetime    not null default current_timestamp comment '请求创建时间',update_time       datetime             default null on update current_timestamp comment '请求更新时间'
)

说明:

  • contract_address: 合约地址,记录该交易所使用的合约地址
  • function_name: 请求方法名称,用于构建合约方法的名称
  • from_address: 交易发起方钱包地址
  • blockchain_params: 上链参数,用于构建合约方法的参数
  • transaction_hash: 交易hash,上链成功后返回的交易hash,交易失败后存储合约的错误信息
  • request_status: 请求当前状态,实时监听链上交易状态,并更新状态,如果失败,则进行重新上链
  • times: 重试次数,用于控制需要发起的交易,如果超过一定次数,则不再发起交易

定时任务控制

// 伪代码
// 发送待处理请求
@Async
@Scheduled(cron = "0/10 * * * * ? ")
public void requestListHandler() {try {// 查询所有需要上链的数据,包括未上链的请求和上链失败需要重试的请求List<RequestList> requestLists = requestListService.getResultListToSend(RequestState.NOT_ON_CHAIN.getStateCode(),ReTimes);// 轮训所有待上链的数据for (RequestList requestList : requestLists) {// 获取上链数据对应的 实现类名FunctionNameEnum functionNameEnum = FunctionNameEnum.queryByName(requestList.getFunctionName());if (functionNameEnum ==null){...continue;}// 利用 反射机制 获取对应的实现类FunctionHandleService functionHandleService = SpringBeanUtil.getBeanByName(functionNameEnum.getTradeServiceName(), FunctionHandleService.class);if (functionHandleService == null){...continue;}// 处理对应实现类的发送交易逻辑Result<Object> result = functionHandleService.handleFunc(requestList);if (result.getResultCode() == ResultDesc.SUCCESS.getResultCode()){// 交易发送成功,存储hash// 此时交易的状态为需要修改为 pending...}else {// 交易发送失败,记录失败原因...// 重试次数+1,如果重试次数大于一定次数,则修改状态为失败,下一次轮训不再处理该数据if (requestList.getTimes() == ReTimes){// 多次处理之后仍然没有成功logger.warn("send transaction failed:{},reason:{}", JacksonUtil.obj2json(requestList),result.getData());...}}// 更新数据this.updateRequestList(updateRequestList,true);}} catch (Exception e) {logger.error("requestListHandler have error:{}", String.valueOf(e));throw new RuntimeException(e);}
}// 伪代码
// 处理交易发送但是未成功的交易
@Async
@Scheduled(cron = "0/10 * * * * ? ")
public void transactionStatusHandler() {try {// 获取已经上链成功,但是状态为pending的数据List<RequestList> requestLists = requestListService.getResultListToSend(RequestState.PENDING.getStateCode(),ReTimes);// 轮训所有待查询状态的数据for (RequestList requestList : requestLists) {// 查询并更新交易的状态Integer requestStatus = this.getTransactionStatus(requestList.getTransactionHash());requestList.setRequestStatus(requestStatus);// 不管什么状态,都不添加重试次数,总不能一直没状态吧,除非链有问题this.updateRequestList(updateRequestList,false);}}catch (Exception e){logger.error("transactionStatusHandler have error:{}",e);}
}

策略模式引入

定义接口,所有发送交易的实现类都需要实现该接口

// 伪代码// 定义接口,所有发送交易的实现类都需要实现该接口
public interface FunctionHandleService {Result<Object> handleFunc(RequestList requestList);
}

实现BaseFunctionHandleService公共实现类,用于统一链上处理,避免重复代码。

// 实现公共实现类,避免重复代码
public class BaseFunctionHandleService {// 发送合约交易public String callContractFunction(RequestList requestList, Type... args) {// 根据实现类构造的args参数,构造并发送交易String fromAddress = CommonUtil.removeHexPrefixIfExists(requestList.getFromAddress());String privateKey = EthTransactionUtil.decryptKeystore(fromAddress);    // 获取交易发起方的私钥...EthSendTransaction transaction = ercUtil.ethSendRawTransaction(privateKey, requestList.getContractAddress(), requestList.getFunctionName(), args);return transaction.getTransactionHash();}// 其他业务相同的逻辑,比如:校验是否为hash,处理函数.....
}

实现类根据业务逻辑实现,需要继承BaseFunctionHandleService,并实现FunctionHandleService。
主要用于构建合约方法参数,通过类控制来减少if...else if...else的逻辑。

// 伪代码
@Service
public class DemoHandleService extends BaseFunctionHandleService implements FunctionHandleService {@Overridepublic Result<Object> handleFunc(RequestList requestList) {Result<Object> result = new Result<>();// 构建合约参数DemoParam param = JacksonUtil.json2pojo(requestList.getBlockchainParams(), DemoParam.class);Type<?>[] chainArguments = {new Address(CommonUtil.removeHexPrefixIfExists(param.getToAddress())),...};// 发送交易String transactionHash = this.callContractFunction(requestList,chainArguments);if (StringUtils.isBlank(transactionHash)) {// 遇到交易失败的情况,打印日志记录失败原因// 不用更新数据库等逻辑...}return result;}
}

延伸

此方法也可以用于监听区块链事件:

  • 比如A方法抛出了event_A,B方法抛出了event_B
  • 通过topic来区分,获取对应的事件处理实现类,进入对应的业务处理

总结

  • 通过策略模式,实现了业务逻辑的解耦,同时实现了业务逻辑的复用,实现了代码的扩展性
  • 引入队列模式,可以实现异步处理,提高系统的吞吐量,提高系统的可用性
http://www.zskr.cn/news/82926.html

相关文章:

  • 2025年重庆输变电资质转让服务推荐排行榜,专业输变电资质代 - mypinpai
  • 2025-2026北京律师事务所好口碑 TOP5:权威测评,帮你选对机构 - 苏木2025
  • 2025年哈尔滨直播间搭建推荐,专业活动搭建企业全解析 - 工业品牌热点
  • 2025年重庆建筑资质代办机构TOP5排行榜,重庆海湖集团在 - mypinpai
  • 联考随记
  • 2025血蛋白实力派榜单:佰倍优35%高浓款,凭硬核实力领跑 - 速递信息
  • 2025年实力强的自动喷砂机厂家排名:自动喷砂机定制厂家哪家 - myqiye
  • 树上拓扑序计数(P4099)
  • 【转载】pros and cons是什么的缩写 - ENGINEER
  • 2025年中国流水线测试静音房推荐:静音室静音房流水线静音房 - 工业品牌热点
  • 2025年设备隔音房/瓦楞机隔音房/打磨机隔音房厂家推荐TO - 工业品牌热点
  • 全网热议!2025年国内测温仪厂家品牌排行榜 - 讯息观点
  • 无需进口!国产推荐真空匀质机、真空混合机、真空自转公转搅拌机 - 品牌推荐大师1
  • 2025年轨道交通技校口碑排名:五大轨道交通类院校招生专业全 - mypinpai
  • 新能源小型电池模块测试效率提升方案:上海柏毅试验箱技术解析
  • LLM学习路线
  • 传统园艺巨头如何用AI节省1.5亿美元
  • 告别 “孩子看牙难”!2025年长沙 5 家权威儿童牙科/口腔医院盘点,家长直接抄作业 - 博客万
  • 2025年中东地区EOR名义雇主服务商推荐:聚焦Safeguard Global人力资源服务商 - 品牌2025
  • 阿里云CentOS环境下Docker运用教程
  • 2025年美国名义雇主EOR公司推荐,Safeguard Global服务特点全面解读 - 品牌2025
  • 计算机工程师必懂的100个为什么的数学底层原理 - wanghongwei
  • 多通道自动化测量控制板 振弦传感器 存储、无线扩展 振弦测量控制板
  • 2025年武汉地区电竞学校推荐:报名电竞学校需要多少钱? - 工业推荐榜
  • 2025年全球名义雇主服务商深度测评:如何选择海外人力资源公司实现合规雇佣 - 品牌2025
  • 2025电缆生产厂家TOP5权威推荐:柔性矿物质防火电缆厂家 - mypinpai
  • 电弧喷涂供应服务商:工艺定制与行业界定准则解析 - myqiye
  • top10香港硕士申请机构2025实时排名更新 - 留学品牌推荐官
  • 2025年四川红酒回收公司榜单:四川红酒回收正规收购中心/四川回收拉菲红酒/四川红酒回收价格专业机构盘点 - 品牌推荐官
  • 2025年12月山东环氧富锌底漆厂家推荐:综合实力排行榜单深度评测与选购指南 - 品牌推荐