特点
Hmily 日志存储支持 数据库,mongoDb,File,Redis,Zookeeper
多种不同日志序列化方式(Kryo,protostuff,hession)。
支持内嵌事务的依赖传递。
存储事务日志是SPI扩展
目前已经Hmily已经集成了:
org.dromara.hmily.core.spi.repository.FileCoordinatorRepository @HmilySPI("file")
org.dromara.hmily.core.spi.repository.JdbcCoordinatorRepository @HmilySPI("db")
org.dromara.hmily.core.spi.repository.MongoCoordinatorRepository @HmilySPI("mongodb")
org.dromara.hmily.core.spi.repository.RedisCoordinatorRepository @HmilySPI("redis")
org.dromara.hmily.core.spi.repository.ZookeeperCoordinatorRepository @HmilySPI("zookeeper")
实现其他的方式存储:
首先实现 org.dromara.hmily.core.spi.HmilyCoordinatorRepository
在你的实现类上加上 @HmilySPI("你定的名称")
在你的项目 resources 目前下新建 META-INF.services 目录,然后新增文本 文本名称为
org.dromara.hmily.core.spi.HmilyCoordinatorRepository . 里面内容写你自定义类的全路径
在Springboot配置文件中配置属性值
org:
dromara:
hmily :
repositorySupport: 你定义的名称
集成了多种序列化方式
org.dromara.hmily.common.serializer.HessianSerializer @HmilySPI("hessian")
org.dromara.hmily.common.serializer.JavaSerializer @HmilySPI("hessian")
org.dromara.hmily.common.serializer.KryoSerializer @HmilySPI("kryo")
org.dromara.hmily.common.serializer.ProtostuffSerializer @HmilySPI("protostuff")
org.dromara.hmily.common.serializer.HessianSerializer @HmilySPI("hessian")
实现其他的序列化方式:
首先实现 org.dromara.hmily.common.serializer.ObjectSerializer
在你的实现类上加上 @HmilySPI("你定的名称")
在你的项目 resources 目前下新建 META-INF.services 目录,然后新增文本 文本名称为
org.dromara.hmily.common.serializer.ObjectSerializer 里面内容写你自定义类的全路径
在Springboot配置文件中配置属性值
org:
dromara:
hmily :
serializer: @HmilySPI注解中的名称
Hmily 代码流程:
AbstractHmilyTransactionAspect
拦截标记了@Hmily注解的方法
@Pointcut("@annotation(org.dromara.hmily.annotation.Hmily)")
通过 HmilyTransactionInterceptor 拦截器处理
而
org.dromara.hmily.springcloud.interceptor.SpringCloudHmilyTransactionInterceptor 实现了HmilyTransactionInterceptor拦截器
所以由该类的public Object interceptor(final ProceedingJoinPoint pjp)方法处理
public Object interceptor(final ProceedingJoinPoint pjp) throws Throwable {
HmilyTransactionContext hmilyTransactionContext = HmilyTransactionContextLocal.getInstance().get();
if (Objects.nonNull(hmilyTransactionContext)) {
if (HmilyRoleEnum.START.getCode() == hmilyTransactionContext.getRole()) {
hmilyTransactionContext.setRole(HmilyRoleEnum.SPRING_CLOUD.getCode());
}
} else {
try {
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
hmilyTransactionContext = RpcMediator.getInstance().acquire((key) -> {
HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
return request.getHeader(key);
});
} catch (IllegalStateException var4) {
LogUtil.warn(LOGGER, () -> {
return "can not acquire request info:" + var4.getLocalizedMessage();
});
}
}
return this.hmilyTransactionAspectService.invoke(hmilyTransactionContext, pjp);
}
其中处理逻辑为: 先获取 HmilyTransactionContext Hmily事务上下文从 HmilyTransactionContextLocal 从线程本地变量获取,线程安全
刚开启事务时 HmilyTransactionContext 是空的,后续从请求头中获取 hmilyTransactionContext 远程调用时会将 事务放到请求头字段 HMILY_TRANSACTION_CONTEXT 上 详细请参考:org.dromara.hmily.springcloud.feign.HmilyFeignInterceptor类
HmilyTransactionAspectServiceImpl 实现 HmilyTransactionAspectService类
所以调用 HmilyTransactionAspectServiceImpl的
public Object invoke(final HmilyTransactionContext hmilyTransactionContext, final ProceedingJoinPoint point) throws Throwable {
final Class clazz = hmilyTransactionFactoryService.factoryOf(hmilyTransactionContext);
final HmilyTransactionHandler txTransactionHandler =
(HmilyTransactionHandler) SpringBeanUtils.getInstance().getBean(clazz);
return txTransactionHandler.handler(point, hmilyTransactionContext);
}
hmilyTransactionFactoryService.factoryOf(hmilyTransactionContext) 根据 hmilyTransactionContext 获取对应的事务阶段处理类
public Class factoryOf(final HmilyTransactionContext context) {
if (Objects.isNull(context)) {
//全局事务开始时调用该类
return StarterHmilyTransactionHandler.class;
} else {
//why this code? because spring cloud invoke has proxy.
if (context.getRole() == HmilyRoleEnum.SPRING_CLOUD.getCode()) {
context.setRole(HmilyRoleEnum.START.getCode());
return ConsumeHmilyTransactionHandler.class;
}
// if context not null and role is inline is ParticipantHmilyTransactionHandler.
if (context.getRole() == HmilyRoleEnum.LOCAL.getCode()) {
return LocalHmilyTransactionHandler.class;
} else if (context.getRole() == HmilyRoleEnum.START.getCode()
|| context.getRole() == HmilyRoleEnum.INLINE.getCode()) {
//事务参与者调用
return ParticipantHmilyTransactionHandler.class;
}
return ConsumeHmilyTransactionHandler.class;
}
}
刚开始HmilyTransactionContext 为空,所以 返回: StarterHmilyTransactionHandler 流程:
@Override
public Object handler(final ProceedingJoinPoint point, final HmilyTransactionContext context)
throws Throwable {
Object returnValue;
try {
//开启hmily transaction,事务状态pre_try
HmilyTransaction hmilyTransaction = hmilyTransactionExecutor.preTry(point);
try {
//execute try
//执行本地方法
returnValue = point.proceed();
hmilyTransaction.setStatus(HmilyActionEnum.TRYING.getCode());
//记录hmily日志
hmilyTransactionExecutor.updateStatus(hmilyTransaction);
} catch (Throwable throwable) {
//if exception ,execute cancel
final HmilyTransaction currentTransaction = hmilyTransactionExecutor.getCurrentTransaction();
disruptorProviderManage.getProvider().onData(() -> hmilyTransactionExecutor.cancel(currentTransaction));
throw throwable;
}
//execute confirm
final HmilyTransaction currentTransaction = hmilyTransactionExecutor.getCurrentTransaction();
disruptorProviderManage.getProvider().onData(() -> hmilyTransactionExecutor.confirm(currentTransaction));
} finally {
HmilyTransactionContextLocal.getInstance().remove();
hmilyTransactionExecutor.remove();
}
return returnValue;
}