Dubbo配置详解

概述

Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

Oinone平台默认使用dubbo-v2.7.22版本,本文以该版本为例进行描述。

基本概念

Dubbo在注册provider/consumer时使用Netty作为RPC调用的核心服务,其具备客户端/服务端(C/S)的基本特性。即:provider作为服务端consumer作为客户端

客户端通过服务中心发现有服务可被调用时,将通过服务中心提供的服务端调用信息,连接服务端并发起请求,从而实现远程调用。

服务注册(绑定Host/Port)

JAVA程序启动时,需要将provider的信息注册到服务中心,并在当前环境为Netty服务开启Host/Port监听,以实现服务注册功能。

在下文中,我们通过绑定Host/Port表示Netty服务的访问地址,通过注册Host/Port表示客户端的访问地址。

使用yaml配置绑定Host/Port

PS:该配置可在多种环境中通用,改变部署方式无需修改此配置。

dubbo:
  protocol:
    name: dubbo
    # host: 0.0.0.0
    port: -1

假设当前环境的可用IP为192.168.1.100

以上配置将使得Netty服务默认绑定在0.0.0.0:20880地址,服务注册地址为192.168.1.100:20880

客户端将通过192.168.1.100:20880调用服务端服务

若发生20880端口占用,则自动向后查找可用端口。如20881、20882等等

若当前可用端口为20881,则以上配置将使得Netty服务默认绑定在0.0.0.0:20881地址,服务注册地址为192.168.1.100:20881

使用环境变量配置注册Host/Port

当服务端被放置在容器环境中时,由于容器环境的特殊性,其内部的网络配置相对于宿主机而言是独立的。因此为保证客户端可以正常调用服务端,还需在容器中配置环境变量,以确保客户端可以通过指定的注册Host/Port进行访问。

以下示例为体现无法使用20880端口的情况,将宿主机可访问端口从20880改为20881。

DUBBO_IP_TO_REGISTRY=192.168.1.100
DUBBO_PORT_TO_REGISTRY=20881

假设当前宿主机环境的可用IP为192.168.1.100

以上配置将使得Netty服务默认绑定在0.0.0.0:20881地址,服务注册地址为192.168.1.100:20881

客户端将通过192.168.1.100:20881调用服务端服务

使用docker/docker-compose启动

需添加端口映射,将20881端口映射至宿主机20881端口。(此处容器内的端口发生变化,若需要了解具体原因,可参考题外话章节)

docker-run

IP=192.168.1.100

docker run -d --name designer-allinone-full \
-e DUBBO_IP_TO_REGISTRY=$IP \
-e DUBBO_PORT_TO_REGISTRY=20881 \
-p 20881:20881 \

docker-compose

services:
  backend:
    container_name: designer-backend
    image: harbor.oinone.top/oinone/designer-backend-v5.0
    restart: always
    environment:
      DUBBO_IP_TO_REGISTRY: 192.168.1.100
      DUBBO_PORT_TO_REGISTRY: 20881
    ports:
     - 20881:20881 # dubbo端口

使用kubernetes启动

工作负载(Deployment)

kind: Deployment
apiVersion: apps/v1
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: designer-backend
          image: harbor.oinone.top/oinone/designer-backend-v5.0
          ports:
            - name: dubbo
              containerPort: 20881
              protocol: TCP
          env:
            - name: DUBBO_IP_TO_REGISTRY
              value: "192.168.1.100"
            - name: DUBBO_PORT_TO_REGISTRY
              value: "20881"

服务(Services)

kind: Service
apiVersion: v1
spec:
  type: NodePort
  ports:
    - name: dubbo
      protocol: TCP
      port: 20881
      targetPort: dubbo
      nodePort: 20881

PS:此处的targetPort为对应Deployment#spec. template.spec.containers.ports.name配置的端口名称。若未配置,可使用20881直接指定对应容器的端口号。

使用kubernetes其他暴露服务方式

在Kubernetes中部署服务,有多种配置方式均可用暴露服务。上述配置仅用于通过Service/NodePort20881端口暴露至宿主机,其他服务可用通过任意Kubernetes节点IP进行调用。

若其他服务也在Kubernetes中进行部署,则可以通过Service/Service方式进行调用。将DUBBO_IP_TO_REGISTRY配置为${serviceName}.${namespace}即可。

若其他服务无法直接访问Kubernetes的master服务,则可以通过Ingress/Service方式进行调用。将DUBBO_IP_TO_REGISTRY配置为Ingress可解析域名即可。

Dubbo调用链路图解

PS: Consumer绑定Host/Port是其作为Provider使用的,下面所有图解仅演示单向的调用链路。

名词解释

  • Provider: 服务提供者(JVM)
  • Physical Machine Provider: 服务提供者所在物理机
  • Provider Container: 服务提供者所在容器
  • Kubernetes Service: Kubernetes Service资源类型
  • Consumer: 服务消费者(JVM)
  • Registration Center: 注册中心;可以是zookeepernacos等。
  • bind: 服务绑定Host/Port到指定ip:port
  • registry: 服务注册;注册Host/Port到注册中心的信息。
  • discovery: 服务发现;注册Host/Port到消费者的信息。
  • invoke: 服务调用;消费者通过注册中心提供的提供者信息向提供者发起服务调用。
  • forward: 网络转发;通常在容器环境需要进行必要的网络转发,以使得服务调用可以到达服务提供者。

物理机/物理机调用链路

image.png

``` mermaid
sequenceDiagram

participant p as Provider<br>(bind 0.0.0.0:20880)
participant m as Physical Machine Provider<br>(bind 192.168.1.100:20881)
participant rc as Registration Center<br>(zookeeper/nacos)
participant c as Consumer<br>(bind 0.0.0.0:20881)

p-->>+m: bind 192.168.1.100:20880
m->>+rc: registry 192.168.1.100:20880
rc->>+c: discovery 192.168.1.100:20880
c->>+m: invoke 192.168.1.100:20880
m-->>+p: forward 0.0.0.0:20881
```

PS: 此处虚线部分表示提供者部署在物理机上,并不存在真实的网络处理。

容器/物理机调用链路

image.png

``` mermaid
sequenceDiagram

participant p as Provider<br>(bind 0.0.0.0:20881)
participant pc as Provider Container<br>(bind 172.17.1.100:20881)
participant m as Physical Machine Provider<br>(bind 192.168.1.100:20881)
participant rc as Registration Center<br>(zookeeper/nacos)
participant c as Consumer<br>(bind 0.0.0.0:20882)

p-->>+pc: bind 172.26.1.100:20881
pc->>+m: mapping 192.168.1.100:20881
pc->>+rc: registry 192.168.1.100:20881
rc->>+c: discovery 192.168.1.100:20881
c->>+m: invoke 192.168.1.100:20881
m->>+pc: forward 172.17.1.100:20881
pc-->>+p: forward 0.0.0.0:20881
```

PS: 此处虚线部分表示提供者部署在容器中,并不存在真实的网络处理。

Kubernetes/物理机(Service/NodePort模式)调用链路

image.png

``` mermaid
sequenceDiagram

participant p as Provider<br>(bind 0.0.0.0:20881)
participant pc as Provider Container<br>(bind 172.17.1.100:20881)
participant ks as Kubernetes Service<br>targetPort 172.17.1.100:20881<br>nodePort 192.168.1.100:20881
participant m as Physical Machine Provider<br>(bind 192.168.1.100:20881)
participant rc as Registration Center<br>(zookeeper/nacos)
participant c as Consumer<br>(bind 0.0.0.0:20882)

p-->>+pc: bind 172.26.1.100:20881
pc->>+ks: mapping 192.168.1.100:20881
ks->>+m: mapping 192.168.1.100:20881
pc->>+rc: registry 192.168.1.100:20881
rc->>+c: discovery 192.168.1.100:20881
c->>+m: invoke 192.168.1.100:20881
m->>+ks: forward 192.168.1.100:20881
ks->>+pc: forward 172.17.1.100:20881
pc-->>+p: forward 0.0.0.0:20881
```

PS: 此处虚线部分表示提供者部署在容器中,并不存在真实的网络处理。

题外话

dubbo-v2.7.22源码中,作者发现Host/Port的获取方式并不对等,这里目前不太清楚是dubbo设计如此还是作者对dubbo设计理解不足。

  • 现象:

    • DUBBO_IP_TO_REGISTRY配置与dubbo.protocol.host无关。
    • DUBBO_PORT_TO_REGISTRY配置优先级高于dubbo.protocol.port配置。
  • 作者理解:

    • 客户端向服务端发起请求时,应使用注册Host/Port进行调用,只要该访问地址可以与服务端连通,则远程调用就可以正常运行。
    • 注册Host/Port绑定Host/Port应支持完全独立配置。当注册Host/Port绑定Host/Port均被配置时,注册Host绑定Host是独立生效的,但绑定Port却强制使用了注册Port。(这一点也是经常在容器环境中无法正常调用的主要原因)

常用配置

yaml配置

dubbo:
  application:
    name: pamirs-test
    version: 1.0.0
  registry:
    address: zookeeper://127.0.0.1:2181
    # group: demo
    # timeout: 5000
  protocol:
    name: dubbo
    # host: 0.0.0.0
    port: -1
    serialization: pamirs
    payload: 104857600
  scan:
    base-packages: pro.shushi
  cloud:
    subscribed-services:
  • dubbo.registry.address: 注册中心地址
  • dubbo.registry.group: 全局group配置
  • dubbo.registry.timeout: 全局超时时间配置
  • dubbo.protocol.name: 协议名称
  • dubbo.protocol.host: 绑定主机IP配置;默认:0.0.0.0
  • dubbo.protocol.port: 绑定主机端口配置;-1表示自动获取可用端口;默认:20880
  • dubbo.protocol.serialization: 序列化配置;Oinone平台必须使用pamirs作为序列化方式。
  • dubbo.protocol.payload: RPC调用数据大小限制;单位:字节(byte)
  • dubbo.scan.base-packages: provider/consumer扫描包路径
  • dubbo.cloud.subscribed-services: 多提供者配置;示例中该参数配置为空是为了避免启动时的警告日志,一般无需配置。

环境变量配置

DUBBO_IP_TO_REGISTRY=127.0.0.1
DUBBO_PORT_TO_REGISTRY=20880
  • DUBBO_IP_TO_REGISTRY:注册Host配置
  • DUBBO_PORT_TO_REGISTRY:注册Port配置

源码参考

  • org.apache.dubbo.config.ServiceConfig#findConfigedHosts
private String findConfigedHosts(ProtocolConfig protocolConfig,
                                 List<URL> registryURLs,
                                 Map<String, String> map) {
    boolean anyhost = false;

    String hostToBind = getValueFromConfig(protocolConfig, DUBBO_IP_TO_BIND);
    if (hostToBind != null && hostToBind.length() > 0 && isInvalidLocalHost(hostToBind)) {
        throw new IllegalArgumentException("Specified invalid bind ip from property:" + DUBBO_IP_TO_BIND + ", value:" + hostToBind);
    }

    // if bind ip is not found in environment, keep looking up
    if (StringUtils.isEmpty(hostToBind)) {
        hostToBind = protocolConfig.getHost();
        if (provider != null && StringUtils.isEmpty(hostToBind)) {
            hostToBind = provider.getHost();
        }
        if (isInvalidLocalHost(hostToBind)) {
            anyhost = true;
            logger.info("No valid ip found from environment, try to get local host.");
            hostToBind = getLocalHost();
        }
    }

    map.put(BIND_IP_KEY, hostToBind);

    // registry ip is not used for bind ip by default
    String hostToRegistry = getValueFromConfig(protocolConfig, DUBBO_IP_TO_REGISTRY);
    if (hostToRegistry != null && hostToRegistry.length() > 0 && isInvalidLocalHost(hostToRegistry)) {
        throw new IllegalArgumentException(
                "Specified invalid registry ip from property:" + DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
    } else if (StringUtils.isEmpty(hostToRegistry)) {
        // bind ip is used as registry ip by default
        hostToRegistry = hostToBind;
    }

    map.put(ANYHOST_KEY, String.valueOf(anyhost));

    return hostToRegistry;
}
  • org.apache.dubbo.config.ServiceConfig#findConfigedPorts
private Integer findConfigedPorts(ProtocolConfig protocolConfig,
                                  String name,
                                  Map<String, String> map, int protocolConfigNum) {
    Integer portToBind = null;

    // parse bind port from environment
    String port = getValueFromConfig(protocolConfig, DUBBO_PORT_TO_BIND);
    portToBind = parsePort(port);

    // if there's no bind port found from environment, keep looking up.
    if (portToBind == null) {
        portToBind = protocolConfig.getPort();
        if (provider != null && (portToBind == null || portToBind == 0)) {
            portToBind = provider.getPort();
        }
        final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();
        if (portToBind == null || portToBind == 0) {
            portToBind = defaultPort;
        }
        if (portToBind <= 0) {
            portToBind = getRandomPort(name);
            if (portToBind == null || portToBind < 0) {
                portToBind = getAvailablePort(defaultPort);
                putRandomPort(name, portToBind);
            }
        }
    }

    // registry port, not used as bind port by default
    String key = DUBBO_PORT_TO_REGISTRY;
    if (protocolConfigNum > 1) {
        key = getProtocolConfigId(protocolConfig).toUpperCase() + "_" + key;
    }
    String portToRegistryStr = getValueFromConfig(protocolConfig, key);
    Integer portToRegistry = parsePort(portToRegistryStr);
    if (portToRegistry != null) {
        portToBind = portToRegistry;
    }

    // save bind port, used as url's key later
    map.put(BIND_PORT_KEY, String.valueOf(portToBind));

    return portToBind;
}
  • org.apache.dubbo.config.ServiceConfig#getValueFromConfig
private String getValueFromConfig(ProtocolConfig protocolConfig, String key) {
    String protocolPrefix = protocolConfig.getName().toUpperCase() + "_";
    String value = ConfigUtils.getSystemProperty(protocolPrefix + key);
    if (StringUtils.isEmpty(value)) {
        value = ConfigUtils.getSystemProperty(key);
    }
    return value;
}
  • org.apache.dubbo.common.utils.ConfigUtils#getSystemProperty
public static String getSystemProperty(String key) {
    String value = System.getenv(key);
    if (StringUtils.isEmpty(value)) {
        value = System.getProperty(key);
    }
    return value;
}

Oinone社区 作者:张博昊原创文章,如若转载,请注明出处:https://doc.oinone.top/backend/16028.html

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

(1)
张博昊的头像张博昊数式管理员
上一篇 2024年8月9日 pm6:02
下一篇 2024年8月12日 pm5:37

相关推荐

  • Oinone协同开发源码分析

    前提 源码分析版本是 5.1.x版本 什么是协同开发模式 协同开发模式解决的是不同开发,在开发同一个模型时,不会相互影响,也不会影响到测试环境详见:Oinone协同开发使用手册 协同开发原理 在协同模式下,本地开发的元数据,配置pamirs.data.distribution.session.ownSign参数后,元数据前缀加ownSign值,然后只存在redis缓存,不落库。其它环境无法直接访问到该数据。测试环境,或其它环境访问,需要在url上加ownSign等于设置的,则读redis数据时,除了加载通用数据,也会合并ownSign前缀的redis数据,显示出来 注意事项 协同开发仅支持界面设计器,其他设计器均不支持 不支持权限配置 不支持工作流触发 版本支持 完整支持5.1.0及以上 功能详解 启动时操作 做元数据保护检查 配置ownSign,则key拼接为 ownSign + ‘:’ + key 清除掉ownSign的redis缓存数据;非ownSign不用清理 计算差量数据 有差量数据,放入ownSign标识数据,并清理本地标识 dubbo注册服务,group拼接group + ownSign 后进行注册 读取时操作 读本地 组装key: ownSign + ‘:’ + key 本地缓存有数据,更新缓存本地数据,返回 本地没有数据,读redis,并插入本地缓存 读远程 dubbo注册消费者,group拼接group + ownSign 后进行泛化调用 元数据保护检查 开启数据保护模式,在启动参数里加-PmetaProtected=pamirs 会在启动时,往redis里写入数据 private static final String META_PROTECTED_KEY = “pamirs:check:meta-protected”; private void writeMetaProtected(String metaProtected) { stringRedisTemplate.opsForValue().set(META_PROTECTED_KEY, metaProtected); } 如果同时又设置 pamirs.data.distribution.session.ownSign则会报错 在使用元数据保护模式下,不允许设置 [pamirs.distribution.session.ownSign] 处理逻辑如下 看redis是否启用保护标识的值 获取pamirs.distribution.session.ownSign配置 没有启动参数 且redis没有值,则retrun 如果有启动参数且配置了ownSign,报错 在使用元数据保护模式下,不允许设置 [pamirs.distribution.session.ownSign] 如果有启动参数且 redis没有值或启动参数设置 -P metaForceProtected,则写入redis 如果有启动参数, 且启动参数跟redis值不同,则报错[公共环境开启了元数据保护模式,本地开发环境需配置[pamirs.distribution.session.ownSign]] 如果没有启动参数且redis有值,但没有配置ownSign 报错[公共环境开启了元数据保护模式,本地开发环境需配置[pamirs.distribution.session.ownSign]] 核心代码如下MetadataProtectedChecker public void process(AppLifecycleCommand command, Set<String> runModules, List<ModuleDefinition> installModules, List<ModuleDefinition> upgradeModules, List<ModuleDefinition> reloadModules) { String currentMetaProtected = stringRedisTemplate.opsForValue().get(META_PROTECTED_KEY); String metaProtected = getMetaProtected(); boolean hasCurrentMetaProtected = StringUtils.isNotBlank(currentMetaProtected); boolean hasMetaProtected = StringUtils.isNotBlank(metaProtected); if (!hasCurrentMetaProtected && !hasMetaProtected) { return; } if (hasMetaProtected) { if (Spider.getDefaultExtension(SessionFillOwnSignApi.class).handleOwnSign()) { // 如果有启动参数且配置了ownSign throw new UnsupportedOperationException(“在使用元数据保护模式下,不允许设置 [pamirs.distribution.session.ownSign]”); } if (!hasCurrentMetaProtected || isForceProtected()) { writeMetaProtected(metaProtected); } else if (!metaProtected.equals(currentMetaProtected)) { // 如果有启动参数, 且启动参数跟redis值不同 throw unsupportedLocalOperation(); } } else { if (Spider.getDefaultExtension(SessionFillOwnSignApi.class).handleOwnSign()) { return; } // 没有启动参数且redis有值,但没有配置ownSign 报错 throw unsupportedLocalOperation(); } } 取ownSign方式 看header是否有ownSign这个标识 header没有,则从配置里取,并放到header里 ownSign的获取核心代码 CdDistributionSessionFillOwnSignApi @Override public String getCdOwnSign() { String cdOwnSign = null; // 看header是否有ownSign这个标识…

    2024年9月12日
    1.7K00
  • 引入搜索(增强模型Channel)常见问题解决办法

    总体描述 引入Oinone的搜索(即Channel模块)后,因错误的配置、缺少配置或者少引入一些Jar包,会出现一些报错。 问题1:启动报类JCTree找不到 具体现象 启动过程可能会出现报错:java.lang.NoClassDefFoundError: com/sun/tools/javac/tree/JCTree$JCExpression 产生原因 引入Channel模块后,启动过程中会扫描Class包找寻Enhance的注解,Pamirs底层有使用到jdk的tools中的类, com/sun/tools/javac/tree/JCTree$JCExpression 特定版本的jdk可能会缺少tools.jar导致启动失败 具体报错 at org.springframework.boot.loader.Launcher.launch(Launcher.java:107) [pamirs-venus-boot.jar:na] at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) [pamirs-venus-boot.jar:na] at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88) [pamirs-venus-boot.jar:na] Caused by: java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: com/sun/tools/javac/tree/JCTree$JCExpression at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357) ~[na:1.8.0_381] at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908) ~[na:1.8.0_381] at pro.shushi.pamirs.boot.common.initial.PamirsBootMainInitial.init(PamirsBootMainInitial.java:66) ~[pamirs-boot-api-4.6.10.jar!/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_381] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_381] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_381] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_381] at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:305) ~[spring-context-5.2.12.RELEASE.jar!/:5.2.12.RELEASE] … 20 common frames omitted Caused by: java.lang.NoClassDefFoundError: com/sun/tools/javac/tree/JCTree$JCExpression at java.lang.Class.forName0(Native Method) ~[na:1.8.0_381] at java.lang.Class.forName(Class.java:264) ~[na:1.8.0_381] at pro.shushi.pamirs.meta.util.ClassUtils.getClasses(ClassUtils.java:157) ~[pamirs-meta-model-4.6.8.jar!/:na] at pro.shushi.pamirs.meta.util.ClassUtils.getClassesByPacks(ClassUtils.java:73) ~[pamirs-meta-model-4.6.8.jar!/:na] at pro.shushi.pamirs.channel.core.manager.EnhanceModelScanner.enhanceModel(EnhanceModelScanner.java:51) ~[pamirs-channel-core-4.6.15.jar!/:na] at pro.shushi.pamirs.channel.core.init.ChannelSystemBootAfterInit.init(ChannelSystemBootAfterInit.java:31) 解决办法 方式一【推荐】、配置channel的扫描路径 pamirs: channel: packages: – com.pamirs.ic 方式二、使用Oracle版本的jdk,确保jdk的lib目录,tools.jar有com/sun/tools/javac/tree/JCTree对应的类 问题2:启动报类JsonProvider找不到 具体报错 如果启动报错信息如下: Caused by: java.lang.NoClassDefFoundError: jakarta/json/spi/JsonProvider at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_181] at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_181] at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_181] at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) ~[na:1.8.0_181] 产生原因 项目中只引入了pamirs-channel-core,但未引入elasticsearch相关的包 解决办法 <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>8.4.1</version> </dependency> <dependency> <groupId>jakarta.json</groupId> <artifactId>jakarta.json-api</artifactId> <version>2.1.1</version> </dependency> 其他参考: Oinone引入搜索引擎步骤:https://doc.oinone.top/backend/7235.html

    2024年5月17日
    1.5K00
  • 【后端】项目开发后端知识要点地图

    大类 明细 文档链接 平台基础 如何开发Action,理解前后端协议 如何开发Action,理解前后端协议 CDN配置及文件操作相关 OSS(CDN)配置和文件系统的一些操作 MINIO无公网访问地址下OSS的配置 MINIO无公网访问地址下OSS的配置 分库分表与自定义分表规则 分库分表与自定义分表规则 Oinone引入搜索引擎(增强模型) Oinone引入搜索引擎(增强模型) 引入搜索/增强模型Channel)常见问题解决办法 引入搜索(增强模型Channel)常见问题解决办法 框架之MessageHub(信息提示) 框架之MessageHub(信息提示) DsHint和BatchSizeHint的使用 DsHint(指定数据源)和BatchSizeHint(查询批次数量) Oinone连接外部数据源方案 Oinone连接外部数据源方案 如何自定义SQL(Mapper)语句 如何自定义SQL(Mapper)语句 IWrapper、QueryWrapper和LambdaQueryWrapper使用 IWrapper、QueryWrapper和LambdaQueryWrapper使用 如何在代码中使用自增ID、手动方式获取CODE 如何在代码中使用自增ID、手动方式获取CODE 函数之触发与定时配置和示例 函数之触发与定时配置和示例 函数之异步执行 函数之异步执行 查询时自定义排序字段和排序规则 查询时自定义排序字段和排序规则 非存储字段搜索 非存储字段搜索,适应灵活的搜索场景 枚举/二进制枚举/多值枚举 如何使用位运算的数据字典 全局首页及应用首页配置方法(homepage) 全局首页及应用首页配置方法(homepage) 缓存连接由Jedis切换为Lettuce 缓存连接由Jedis切换为Lettuce GraphQL请求:后端接口实现逻辑解析 GraphQL请求:后端接口实现逻辑解析 Nacos支持 Nacos作为注册中心 Oinone项目引入Nacos作为注册中心 Nacos作为配置中心 Oinone项目引入Nacos作为配置中心 Nacos做为注册中心调用SpringCloud服务 Nacos做为注册中心调用SpringCloud服务 分布式相关 如何构建分布式项目 Oinone如何支持构建分布式项目 构建分布式项目一些要点(dubbo日志关闭等) Oinone构建分布式项目一些注意点 信创支持 后端部署使用达梦数据库 【达梦】后端使用达梦数据库 后端部署使用PostgreSQL数据库 【PostgreSQL】后端使用PostgreSQL数据库 后端部署使用OpenGauss数据库 【OpenGauss】后端使用OpenGauss数据库 后端部署使用MSSQL数据库(SQLServer) 【MSSQL】后端部署使用MSSQL数据库(SQLServer) 东方通Web和Tomcat部署Oinone项目 东方通Web和Tomcat部署Oinone项目 常见扩展 如何增加用户中心的菜单 如何增加用户中心的菜单 导入导出 如何批量导入 如何批量导入 如何支持多Excel多个Sheet导入功能 如何支持多Excel多个Sheet导入功能 如何自定义Excel导入功能 如何自定义Excel导入功能 如何自定义Excel导出功能 如何自定义Excel导出功能 如何自定义表达式 如何自定义表达式 登录扩展 对接外部SSO Oinone登录扩展:对接SSO(4.7.8及之后的版本) 自定义占位符 自定义RSQL占位符及在权限中使用 自定义RSQL占位符(placeholder)及在权限中使用 自定义数据权限拦截处理 自定义数据权限拦截处理 设计器公共 后端无代码设计器Jar包启动方法 后端无代码设计器Jar包启动方法 界面设计器 页面跳转时增加跳转参数 页面跳转时增加跳转参数 界面设计器的导入导出 界面设计器的导入导出 流程设计器 项目中工作流引入和流程触发 项目中工作流引入和流程触发 流程扩展自定义函数示例代码汇总 工作流-流程扩展自定义函数示例代码汇总 工作流-流程代办等页面自定义 工作流-流程代办等页面自定义 审核撤回/回退/拒绝钩子使用 工作流审核撤回/回退/拒绝钩子使用 流程设计器的导入导出 流程设计器的导入导出 如何添加工作流运行时依赖 如何添加工作流运行时依赖 数据可视化 项目中图表设计器引入 数据可视化-项目中数据可视化的实现引入 自定义图表模版 数据可视化中图表的低无一体 图表设计器数据获取示例 数据可视化-数据可视化数据获取示例 如何添加数据可视化运行时依赖 如何添加数据可视化运行时依赖 图表设计器的设计数据导入导出 图表设计器的设计数据导入导出

    2024年5月21日
    2.4K00
  • 流程设计流程结束通知SPI接口

    1.实现SPI接口 import pro.shushi.pamirs.meta.common.spi.SPI; import pro.shushi.pamirs.meta.common.spi.factory.SpringServiceLoaderFactory; import pro.shushi.pamirs.workflow.app.api.entity.WorkflowContext; import pro.shushi.pamirs.workflow.app.api.model.WorkflowInstance; @SPI(factory = SpringServiceLoaderFactory.class) public interface WorkflowEndNoticeApi { void execute(WorkflowContext context, WorkflowInstance instance); } 自定义通知逻辑 /** * 自定义扩展流程结束时扩展点 */ @Order(999) @Component @SPI.Service public class MyWorkflowEndNoticeApi implements WorkflowEndNoticeApi { @Override public void execute(WorkflowContext context, WorkflowInstance instance) { Long dataBizId = instance.getDataBizId(); //todo自定义逻辑 } }

    2023年12月26日
    1.4K00
  • 【HighGo】后端部署使用HighGo数据库

    HighGo数据库配置 驱动配置 jdbc仓库 https://mvnrepository.com/artifact/com.highgo/HgdbJdbc Maven配置(6.0.1版本可用) <highgo.version>6.0.1.jre8</highgo.version> <dependency> <groupId>com.highgo</groupId> <artifactId>HgdbJdbc</artifactId> <version>${highgo.version}</version> </dependency> JDBC连接配置 pamirs: datasource: base: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.highgo.jdbc.Driver url: jdbc:highgo://127.0.0.1:5866/oio_base?currentSchema=base,utl_file username: xxxxxx password: xxxxxx initialSize: 5 maxActive: 200 minIdle: 5 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true asyncInit: true 连接url配置 官方文档 https://www.highgo.com/document/zh-cn/application/jdbc.html url格式 jdbc:highgo://ip:端口号/数据库名?currentSchema=schema1,schema2 在jdbc连接配置时,${database}和${schema}必须完整配置,不可缺省。 jdbc指定schema时可以在currentSchema后指定多个schema,中间用,分隔,第一个schema为业务库表存放的主schema。 highgo数据库6.0版本里每个数据库默认会带一个utl_file的schema,该模式与文件访问功能有关,需要带在jdbc的schema中,但不能放在第一个。 其他连接参数如需配置,可自行查阅相关资料进行调优。 方言配置 pamirs方言配置 pamirs: dialect: ds: base: type: HighGoDB version: 6 major-version: 6.0.1 biz_data: type: HighGoDB version: 6 major-version: 6.0.1 数据库版本 type version majorVersion 6.0.x HighGo 6 6.0.1 PS:由于方言开发环境为6.0.1版本,其他类似版本(6.0.x)原则上不会出现太大差异,如出现其他版本无法正常支持的,可在文档下方留言。 schedule方言配置 pamirs: event: enabled: true schedule: enabled: true dialect: type: HighGoDB version: 6 major-version: 6.0.1 其他配置 逻辑删除的值配置 pamirs: mapper: global: table-info: logic-delete-value: (EXTRACT(epoch FROM CURRENT_TIMESTAMP) * 1000000 + EXTRACT(MICROSECONDS FROM CURRENT_TIMESTAMP))::bigint Highgo数据库用户初始化及授权 — init oio_base user (user name can be modified by oneself) CREATE USER oio_base WITH PASSWORD 'Test@12345678'; — if using automatic database and schema creation, this is very important. ALTER USER oio_base CREATEDB; SELECT * FROM pg_roles; — if using highgo database, this authorization is required. GRANT CREATE ON DATABASE highgo TO oio_base;

    2025年7月10日
    47800

Leave a Reply

登录后才能评论