Oinone如何支持构建分布式项目

分布式调用下的[强制]约束

1、[强制]分布式调用情况下base库和redis需共用;
2、[强制]如果环境有设计器,设计器的base库和redis保持一致也需与项目中的保持一致;
3、[强制]相同base库下,不同应用的相同模块的数据源需保持一致;
4、[强制]项目中需引入分布式缓存包。参考下文的分布式包依赖

分布式支持

1、分布式包依赖

1) 父pom的依赖管理中先加入pamirs-distribution的依赖

<dependency>
    <groupId>pro.shushi.pamirs</groupId>
    <artifactId>pamirs-distribution</artifactId>
    <version>${pamirs.distribution.version}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

2) 启动的boot工程中增加pamirs-distribution相关包

<!-- 分布式服务发布 -->
<dependency>
    <groupId>pro.shushi.pamirs.distribution</groupId>
    <artifactId>pamirs-distribution-faas</artifactId>
</dependency>
<!-- 分布式元数据缓存 -->
<dependency>
    <groupId>pro.shushi.pamirs.distribution</groupId>
    <artifactId>pamirs-distribution-session</artifactId>
</dependency>
<dependency>
    <groupId>pro.shushi.pamirs.distribution</groupId>
    <artifactId>pamirs-distribution-gateway</artifactId>
</dependency>

3)启动工程的Application中增加类注解@EnableDubbo

@EnableDubbo
public class XXXStdApplication {

    public static void main(String[] args) throws IOException {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // ………………………………
        log.info("XXXX Application loading...");
    }
}

2、修改bootstrap.yml文件

注意序列化方式:serialization: pamirs

以下只是一个示例(zk为注册中心),注册中心支持zk和Nacos;
Nacos作为注册中心参考:https://doc.oinone.top/kai-fa-shi-jian/5835.html

spring:
  profiles:
    active: dev
  application:
    name: pamirs-demo
  cloud:
    service-registry:
      auto-registration:
        enabled: false
pamirs:
  default:
    environment-check: true
    tenant-check: true

---
spring:
  profiles: dev
  cloud:
    service-registry:
      auto-registration:
        enabled: false
    config:
      enabled: false
      uri: http://127.0.0.1:7001
      label: master
      profile: dev
    nacos:
      server-addr: http://127.0.0.1:8848
      discovery:
        enabled: false
        namespace:
        prefix: application
        file-extension: yml
      config:
        enabled: false
        namespace:
        prefix: application
        file-extension: yml
dubbo:
  application:
    name: pamirs-demo
    version: 1.0.0
  registry:
    address: zookeeper://127.0.0.1:2181
  protocol:
    name: dubbo
    port: -1
    serialization: pamirs
  scan:
    base-packages: pro.shushi
  cloud:
    subscribed-services:
  metadata-report:
    disabled: true

3、模块启动的最⼩集

pamirs:
boot:
 init: true
 sync: true
 modules:
 - base
 - sequence
 - 业务工程的Module

4、业务模型间的依赖关系

  1. 服务调用方(即Client端),在启动yml中modules不安装服务提供方的Module
  2. 服务调用方(即Client端),项目的pom中只依赖服务提供方的API(即模型和API的定义)
  3. 服务调用方(即Client端),项目模块定义(即模型Module定义),dependencies中增加服务提供方的Modeule. 如下面示例代码中的FileModule
    @Module(
        name = DemoModule.MODULE_NAME,
        displayName = "oinoneDemo工程",
        version = "1.0.0",
        dependencies = {ModuleConstants.MODULE_BASE, CommonModule.MODULE_MODULE, 
                FileModule.MODULE_MODULE, SecondModule.MODULE_MODULE/**服务提供方的模块定义*/
        }
    )
  4. 服务调用方(即Client端),启动类的ComponentScan需要配置服务提供方API定义所在的包. 如下面示例中的:pro.shushi.pamirs.second
    @ComponentScan(
        basePackages = {"pro.shushi.pamirs.meta",
                "pro.shushi.pamirs.framework",
                "pro.shushi.pamirs",
                "pro.shushi.pamirs.demo",
                "pro.shushi.pamirs.second" /**服务提供方API定义所在的包*/
        },
        excludeFilters = {
                @ComponentScan.Filter(
                        type = FilterType.ASSIGNABLE_TYPE,
                        value = {RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
                                RedisClusterConfig.class}
                )
        })
    @Slf4j
    @EnableTransactionManagement
    @EnableAsync
    @EnableDubbo
    @MapperScan(value = "pro.shushi.pamirs", annotationClass = Mapper.class)
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, FreeMarkerAutoConfiguration.class})
    public class DemoApplication {

5、模块启动顺序

服务提供方的模块需先启动。原因:模块在启动过程中,会校验依赖模块是否存在。

6、Dubbo日志相关

关闭Dubbo元数据上报

dubbo:  
    metadata-report:
            disabled: true

关闭元数据上报,还有错误日志打印出来的话,可以在log中配置

logging:
      level:
        root: info
        pro.shushi.pamirs.framework.connectors.data.mapper.PamirsMapper: info
        pro.shushi.pamirs.framework.connectors.data.mapper.GenericMapper: info # mybatis sql日志
        RocketmqClient: error
        # Dubbo相关的日志
        org.apache.dubbo.registry.zookeeper.ZookeeperRegistry: error
        org.apache.dubbo.registry.integration.RegistryDirectory: error
        org.apache.dubbo.registry.client.metadata.store.RemoteMetadataServiceImpl: off
        org.apache.dubbo.metadata.store.zookeeper.ZookeeperMetadataReport: off
        org.apache.dubbo.metadata.store.nacos.NacosMetadataReport: off

更详细的教程参考:https://shushi.yuque.com/yoxz76/oio3/deaa1p

分布式支持-事务相关

1、分布式事务解决方案

完成某一个业务功能可能需要横跨多个服务,操作多个数据库。这就涉及到到了分布式事务,分布式事务就是为了保证不同资源服务器的数据一致性。典型的分布式事务场景:
1、跨库事务, 补充具体场景
2、微服务拆分带来的跨内部服务;
3、微服务拆分带来的跨外部服务;

2、事务策略

采用微服务架构,需考虑分布式事务问题(即平台各子系统之间的数据一致性)。
1)对于单个系统/模型内部, 比如:库存中心、账户中心等,采用强事务的方式。比如:在扣减库存的时候,库存日志和库存数列的变化在一个事务中,保证两个表的数据同时成功或者失败。
强事务管理采用编码式,Oinone事务管理兼容Spring的事务管理方式;
2)为了提高系统的可用性、可扩展性和性能,对于某些关键业务和数据一致性要求特别高的场景,采用强一致性外,其他的场景建议采用最终一致性的方案;
对于分布式事务采用最终数据一致性,借助可靠消息和 Job 等方式来实现。

2.1 基于MQ的事务消息

Oinone如何支持构建分布式项目

采用最终一致性方案,基于MQ的事务消息的方式。
事务消息的逻辑由发送端 Producer进行保证(消费端无需考虑)。基于MQ事务消息的实现步骤:
1)首先,发送一个事务消息,MQ将消息状态标记为Prepared,注意此时这条消息消费者是无法消费到的。
2)接着,执行业务代码逻辑,可能是一个本地数据库事务操作
3)确认发送消息,这个时候,MQ将消息状态标记为可消费,这个时候消费者,才能真正的保证消费到这条数据。

2.2 基于JOB的补偿

定期校对:业务活动的被动方,根据定时策略,向业务活动主动方查询(主动方提供查询接口),恢复丢失的业务消息。

2.3 数据一致性

  • 对RPC超时和重试机制设计的检查,是否会带来重复数据
  • 对数据幂等、去重机制的设计是否有考虑到
  • 对事务、数据(最终)一致性设计是否有考虑到
  • 数据缓存时,当数据发生变化时,是否有相应的机制保证缓存数据的一致性和有效性

Oinone构建分布式项目一些注意点

参考文档:https://doc.oinone.top/kai-fa-shi-jian/6475.html

Oinone社区 作者:shao原创文章,如若转载,请注明出处:https://doc.oinone.top/kai-fa-shi-jian/5572.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (0)
shao's avatarshao数式管理员
Previous 2024年2月20日 pm6:37
Next 2024年2月20日 pm6:46

相关推荐

  • 如何通过 Oineone 平台自定义视图

    在 Oineone 平台上,自定义视图允许用户替换默认提供的页面布局,以使用自定义页面。本文将指导您如何利用 Oineone 提供的 API 来实现这一点。 默认视图介绍 Oineone 平台提供了多种默认视图,包括: 表单视图 表格视图 表格视图 (左树右表) 详情视图 画廊视图 树视图 每种视图都有其标准的 layout。自定义视图实际上是替换这些默认 layout 的过程。 默认的表单视图 layout <view type="FORM"> <element widget="actionBar" slot="actionBar" slotSupport="action"> <xslot name="actions" slotSupport="action" /> </element> <element widget="form" slot="form"> <xslot name="fields" slotSupport="pack,field" /> </element> </view> 内嵌的的表单视图 layout <view type="FORM"> <element widget="form" slot="form"> <xslot name="fields" slotSupport="pack,field" /> </element> </view> 默认的表格 <view type="TABLE"> <pack widget="group"> <view type="SEARCH"> <element widget="search" slot="search" slotSupport="field" /> </view> </pack> <pack widget="group" slot="tableGroup"> <element widget="actionBar" slot="actionBar" slotSupport="action"> <xslot name="actions" slotSupport="action" /> </element> <element widget="table" slot="table" slotSupport="field"> <element widget="expandColumn" slot="expandRow" /> <xslot name="fields" slotSupport="field" /> <element widget="rowActions" slot="rowActions" slotSupport="action" /> </element> </pack> </view> 内嵌的的表格 <view type="TABLE"> <view type="SEARCH"> <element widget="search" slot="search" slotSupport="field" /> </view> <element widget="actionBar" slot="actionBar" slotSupport="action"> <xslot name="actions" slotSupport="action" /> </element> <element widget="table" slot="table"> <element widget="expandColumn" slot="expandRow" /> <xslot name="fields" slotSupport="field" /> <element widget="rowActions" slot="rowActions" /> </element> </view> 左树右表 <view type="table"> <pack title="" widget="group"> <view type="search"> <element slot="search" widget="search"/> </view> </pack> <pack title="" widget="group"> <pack widget="row" wrap="false"> <pack widget="col" width="257"> <pack title="" widget="group"> <pack widget="col"> <element slot="tree" widget="tree"/> </pack> </pack> </pack> <pack mode="full" widget="col"> <pack widget="row"> <element justify="START" slot="actionBar"…

    2024年4月3日
    1.5K00
  • OSS(CDN)配置和文件系统的一些操作

    目前Oinone支持的OSS类型 类型 服务 OSS 阿里云OSS UPYUN 又拍云 MINIO MinIO HUAWEI_OBS 华为云OBS LOCAL 本地NGINX文件存储 TENCENT_COS 腾讯云COS CTYUN_ZOS 天翼云ZOS OSS通用yaml配置 cdn: oss: name: # 名称 type: # 类型 bucket: uploadUrl: # 上传URL downloadUrl: # 下载URL accessKeyId: accessKeySecret: mainDir: # 主目录 validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: others: [key]: name: # 名称 type: # 类型 bucket: uploadUrl: # 上传URL downloadUrl: # 下载URL accessKeyId: accessKeySecret: mainDir: # 主目录 validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: PS:others中使用自定义key来指定OSS服务进行文件上传/下载功能。上传/下载必须匹配,否则无法正常使用。 OSS配置示例 阿里云OSS cdn: oss: name: 阿里云 type: OSS bucket: pamirs(根据实际情况修改) uploadUrl: oss-cn-hangzhou.aliyuncs.com downloadUrl: oss-cn-hangzhou.aliyuncs.com accessKeyId: 你的accessKeyId accessKeySecret: 你的accessKeySecret # 根据实际情况修改 mainDir: upload/ validTime: 3600000 timeout: 600000 active: true imageResizeParameter: referer: 华为云OBS cdn: oss: name: 华为云 type: HUAWEI_OBS bucket: pamirs(根据实际情况修改) uploadUrl: obs.cn-east-2.myhuaweicloud.com downloadUrl: obs.cn-east-2.myhuaweicloud.com accessKeyId: 你的accessKeyId accessKeySecret: 你的accessKeySecret # 根据实际情况修改 mainDir: upload/ validTime: 3600000 timeout: 600000 active: true allowedOrigin: http://192.168.95.31:8888,https://xxxx.xxxxx.com referer: 华为云OBS需要在启动工程增加以下依赖 <okhttp3.version>4.9.3</okhttp3.version> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>${okhttp3.version}</version> </dependency> 注意事项华为云OBS的防盗链配置,仅允许携带特定referer的才可以,而excel导入后端处理的逻辑匿名读的时候是不带referer的,所以会被拒绝 MINIO 文件系统,mino的配置: cdn: oss: name: minio type: MINIO bucket: pamirs(根据实际情况修改) uploadUrl: http://192.168.243.6:32190(根据实际情况修改) downloadUrl: http://192.168.243.6:9000(根据实际情况修改) accessKeyId: 你的accessKeyId accessKeySecret: 你的accessKeySecret # 根据实际情况修改 mainDir: upload/ validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: MINIO无公网访问地址下OSS的配置方式: https://doc.oinone.top/yun-wei-shi-jian/7112.html 又拍云 cdn: oss: name: 又拍云…

    后端 2023年11月1日
    2.0K00
  • 项目中常用的 Tools 工具类

    模型拷贝工具类 KryoUtils.get().copy(modelData); ArgUtils.convert(DataReport.MODEL_MODEL, DataDesignerReport.MODEL_MODEL, report); pro.shushi.pamirs.framework.common.utils.ObjectUtils#clone(T) Rsql工具类 RsqlParseHelper.parseRsql2Sql(queryWrapper.getModel(), rsql); RSQLHelper.getRsqlValues(sql.getOriginRsql(), fieldSet); 序列化工具类 后端使用的JSON序列化 JsonUtils.toJSONString(nodes); 前端使用的JSON序列化 PamirsJsonUtils.toJSONString(nodes, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.BrowserCompatible); 生成ID //根据模型生成id Long generate = (Long) Spider.getDefaultExtension(IdGenerator.class).generate(PamirsTableInfo.fetchKeyGenerator(Teacher.MODEL_MODEL)); //生成id Long l = Long.valueOf(UidGeneratorFactory.getCachedUidGenerator().getUID()); 权限相关 // 获取权限路径path AccessResourceInfoSession.getInfo().getOriginPath(); 其他 PamirsSession相关 PamirsSession.isAdmin() # 是否admin用户 PamirsSession.getUserId() # 获取登录用户ID PamirsSession.getRequestVariables() PamirsSession.getContext().getModelCache().get(PetShop.MODEL_MODEL).getTable(); # 获取模型信息 PamirsSession.getContext().getExtendCache(ActionCacheApi.class).get(Teacher.MODEL_MODEL, "importArchivesInfo") # 获取函数信息

    2025年5月8日
    1.1K01
  • 函数之触发与定时配置和示例

    异步任务总体介绍 函数的触发和定时在很多场景中会用到,也是一个oinone的基础能力。比如我们的流程产品中在定义流程触发时就会让用户选择模型触发还是时间触发,就是用到了函数的触发与定时能力。 触发任务TriggerTaskAction 触发任务的创建,使用sql-record模块监听mysql的binlog事件,通过rocketmq发送变更数据消息,收到MQ消息后,创建TriggerAutoTask。 触发任务的执行,使用TBSchedule拉取触发任务后,执行相应函数。 项目中引入依赖 1、项目的API工程引入依赖pamirs-core-trigger模块 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-trigger-api</artifactId> </dependency> 2、DemoModule在模块依赖定义中增加@Module(dependencies={TriggerModule.MODULE_MODULE}) @Component @Module( name = DemoModule.MODULE_NAME, displayName = "oinoneDemo工程", version = "1.0.0", dependencies = {ModuleConstants.MODULE_BASE, CommonModule.MODULE_MODULE, UserModule.MODULE_MODULE, TriggerModule.MODULE_MODULE} ) @Module.module(DemoModule.MODULE_MODULE) @Module.Advanced(selfBuilt = true, application = true) @UxHomepage(PetShopProxy.MODEL_MODEL) public class DemoModule implements PamirsModule { ……其他代码 } 3、项目的boot工程引入依赖 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-trigger-core</artifactId> </dependency> <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-trigger-bridge-tbschedule</artifactId> </dependency> <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-sql-record-core</artifactId> </dependency> yml文件修改(applcation-xxx.yml) a. 修改pamris.event.enabled和pamris.event.schedule.enabled为trueb. pamirs_boot_modules增加启动模块:trigger、sql_record pamirs: record: sql: #改成自己路径 store: /opt/pamirs/logs … event: enabled: true schedule: enabled: true rocket-mq: namesrv-addr: 127.0.0.1:9876 boot: init: true sync: true modules: – base -…… – trigger – sql_record -…… 新建触发任务 新建PetTalentTrigger类,当PetTalent模型的数据记录被新建时触发系统做一些事情 package pro.shushi.pamirs.demo.core.trigger; import pro.shushi.pamirs.demo.api.model.PetTalent; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j; import pro.shushi.pamirs.trigger.annotation.Trigger; import pro.shushi.pamirs.trigger.enmu.TriggerConditionEnum; @Fun(PetTalent.MODEL_MODEL) @Slf4j public class PetTalentTrigger { @Function @Trigger(displayName = “PetTalent创建时触发”,name = “PetTalent#Trigger#onCreate”,condition = TriggerConditionEnum.ON_CREATE) public PetTalent onCreate(PetTalent data){ log.info(data.getName() + “,被创建”); //可以增加逻辑 return data; } } 定时任务 定时任务是一种非常常见的模式,这里就不介绍概念了,直接进入示例环节 新建PetTalentAutoTask实现ScheduleAction getInterfaceName()需要跟taskAction.setExecuteNamespace定义保持一致,都是函数的命名空间 taskAction.setExecuteFun("execute");跟执行函数名“execute”一致 TaskType需配置为CYCLE_SCHEDULE_NO_TRANSACTION_TASK,把定时任务的schedule线程分开,要不然有一个时间长的任务会导致普通异步或触发任务全部延时。 package pro.shushi.pamirs.demo.core.task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import pro.shushi.pamirs.core.common.enmu.TimeUnitEnum; import pro.shushi.pamirs.demo.api.model.PetTalent; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j; import pro.shushi.pamirs.meta.domain.fun.FunctionDefinition; import pro.shushi.pamirs.middleware.schedule.api.ScheduleAction; import pro.shushi.pamirs.middleware.schedule.common.Result; import pro.shushi.pamirs.middleware.schedule.domain.ScheduleItem; import pro.shushi.pamirs.middleware.schedule.eunmeration.TaskType; import pro.shushi.pamirs.trigger.enmu.TriggerTimeAnchorEnum; import pro.shushi.pamirs.trigger.model.ScheduleTaskAction; import pro.shushi.pamirs.trigger.service.ScheduleTaskActionService; @Slf4j @Component @Fun(PetTalent.MODEL_MODEL) public class PetTalentAutoTask implements…

    2024年5月25日
    1.6K00
  • Oinone构建分布式项目一些注意点

    1. Oinone如何支持构建分布式项目 参考文档:https://doc.oinone.top/kai-fa-shi-jian/5572.html 2. Oinone远程服务发布范围 泛化服务范围,可选值:module、namespacemodule:按模块维度发布远程服务namespace:按Fun的namespace维度发布远程服务默认按module维度发布服务 pamirs: distribution: service: #serviceScope: 可选值namespace、module serviceScope: module 3.关闭Dubbo服务注册元数据上报日志 logging: level: root: info pro.shushi.pamirs.framework.connectors.data.mapper.PamirsMapper: error pro.shushi.pamirs.framework.connectors.data.mapper.GenericMapper: error # mybatis sql日志 RocketmqClient: error org.apache.dubbo.registry.zookeeper.ZookeeperRegistry: error org.apache.dubbo.registry.integration.RegistryDirectory: error org.apache.dubbo.config.ServiceConfig: error com.alibaba.nacos.client.naming: error org.apache.dubbo.registry.nacos.NacosRegistry: error org.apache.dubbo.registry.support.AbstractRegistryFactory: error org.apache.dubbo.registry.integration.RegistryProtocol: error org.apache.dubbo.registry.client.metadata.store.RemoteMetadataServiceImpl: off org.apache.dubbo.metadata.store.zookeeper.ZookeeperMetadataReport: off org.apache.dubbo.metadata.store.nacos.NacosMetadataReport: off 4.Naocs配置列表出现多余配置 dubbo 集成 nacos注册中心,会出现多余的配置,详细参考:配置列表会自动创建很多无关的配置: https://github.com/apache/dubbo/issues/6645配置列表出现多余的配置:https://github.com/alibaba/nacos/issues/8843 按照下面的配置可以将其关闭(📢主要是这三项配置use-as-config-center, use-as-metadata-center,metadata-report.failfast),已生成的配置需要手动删除掉。 dubbo: application: name: pamirs-demo version: 1.0.0 metadata-type: local registry: id: pamirs-demo-registry address: nacos://192.168.0.129:8848 username: nacos password: nacos # dubbo使用nacos的注册中心往配置中心写入配置关闭配置 use-as-metadata-center: false use-as-config-center: false config-center: address: nacos://192.168.0.129:8848 username: nacos password: nacos metadata-report: failfast: false # 关闭错误上报的功能 address: nacos://192.168.0.129:8848 username: nacos password: nacos protocol: name: dubbo port: -1 serialization: pamirs scan: base-packages: pro.shushi cloud: subscribed-services:

    2024年2月1日
    1.7K10

Leave a Reply

Please Login to Comment