1 - 简介

Capa(cloud application api): To be the high-level api layer for all application runtime.

This is a placeholder page that shows you how to use this template site.

Capa(cloud application api): To be the high-level api layer for all application runtime.

让代码实现"一次编写,随处运行"。

借助Capa体系,使你的Java应用在改动量较小的情况下,拥有跨云、混合云运行的能力。

动机

Mecha架构

Capa项目基于Mecha架构的设计理念,使用 富SDK模式 提供Multi-Runtime的标准API。

您可以简单的将Capa项目理解为 Dapr / Layotto 等Sidecar模式项目的SDK实现版本。

欲要理解Mecha架构的设计思路,请阅读以下文章:

死生之地不可不察:论API标准化对Dapr的重要性

MOSN子项目Layotto:开启服务网格+应用运行时新篇章

Sidecar or SDK

基于Mecha架构理念的Multi-Runtime,以Sidecar的方式提供标准API的功能,看起来似乎是最合理的选择。

那为什么不直接使用Dapr/Layotto等项目,而是选择开发 富SDK模式 的Capa项目呢。

概括:以Dapr为代表的Sidecar架构是未来,但现有的很多企业和系统很难一步到位的升级到Sidecar架构,富SDK架构将会长期的存在下去。

引申:面对庞大的Java系统体系,Capa项目将使用富SDK模型支持Java系统向Mecha架构过渡。在Dapr等项目成熟后,也可以无缝衔接到Sidecar架构。

关于此问题的具体讨论请参考:

SDK模型的Dapr API

Dapr API的未来计划

Java SDK的设计讨论

特征

API定义

Capa API设计follow社区标准,请参考 Dapr / Layotto 等开源项目的API定义。

API定义放置于以下独立仓库中,与Capa项目解绑,希望发展成为社区的API标准定义:

为什么不直接使用Dapr API?

由于目前Dapr API和Dapr项目强绑定,但我们希望这套API能够成为整个社区的标准,所以Capa将API定义放在独立仓库中,并时刻和上游社区标准保持同步。

我们希望后续Dapr能够将其API独立部署出来,与Dapr项目相解耦,成为整个社区的标准。

关于此项的讨论,请查看:

Future plans for dapr api

Capa特性

Capa(Java SDK)是面向Java应用实现Mecha架构的SDK解决方案,它目前支持以下领域的特性:

  • Service Invocation (RPC服务调用)
  • Configuration Centor (Configuration动态配置)
  • Publish/Subscribe (Pub/Sub发布订阅)
  • State Management (State状态管理)
  • Application Log/Metrics/Traces (Telemetry可观测性)
  • Database (SQL关系型数据库) -alpha
  • Schedule (Schedule定时调度) -alpha

设计

Capa设计

设计思路:标准API + 可拔插可替换的SDK组件 模式

在不同的分布式中间件领域,Capa提供与具体中间件API无关的统一的标准编程API。 所以应用程序在使用Capa编程时不需要依赖任何具体的中间件API,只需要依赖Capa的标准编程API即可。

在部署到不同的目标环境时,Capa将会装载标准API的不同实现类到应用程序中。当调用统一的编程API时,底层运行时会适配到不同的具体中间件SDK实现。

中间件团队需要针对不同目标环境,开发标准API在目标环境下的实现类即可;而应用代码可以拥有"一次编写,随处运行"的开发体验。

SDK设计

Capa module划分主要为以下几个部分:

  • sdk
  • sdk-component
  • sdk-spi
  • sdk-spi-demo/…

capa-design

应用程序编程时只需要依赖sdk即可,并使用SDK模块中定义的统一编程API。

在运行前,会将具体的SPI实现包引入进去,作为统一编程API的具体实现。

使用

Getting Started

Importing Capa’s Java SDK

For a Maven project, add the following to your pom.xml file:


<project>
    ...
    <dependencies>
        ...
        <!-- Capa's core SDK with all features. -->
        <dependency>
            <groupId>group.rxcloud</groupId>
            <artifactId>capa-sdk</artifactId>
            <version>1.0.7.RELEASE</version>
        </dependency>
        ...
    </dependencies>
    ...
</project>

Sample implementation library:


<project>
    ...
    <dependencies>
        ...
        <!-- Capa's core SDK with all features. -->
        <dependency>
            <groupId>group.rxcloud</groupId>
            <artifactId>capa-sdk-spi-demo</artifactId>
            <version>1.0.7.RELEASE</version>
        </dependency>
        ...
    </dependencies>
    ...
</project>

Running the examples

Try the following examples to learn more about Capa’s Java SDK:

低改造成本迁移

如果要使用原生的Capa API,您的遗留系统需要面对较大的重构工作量。

为了使迁移做到低成本,我们可以复用目前使用到的中间件API。

通过开发一个适配层项目(提供相同的注解/接口调用方式),将原中间件API的实现更改为Capa API。

如此一来,应用程序只需要更改很少的代码(例如更换注解/接口的路径名)即可迁移到Capa架构。

关于该问题的讨论,请查看:

Java sdk design 调研:能否复用业界已有的事实标准

Capa API adapted to spring annotation.

遗留中间件SDK无感迁移到Capa.

开发

Reactor API

考虑到异步调用模式,以及非阻塞IO的使用,我们原生提供Reactor的编程模型,您也可以通过其block()方法使用同步调用的功能。

The Java SDK for Capa is built using Project Reactor. It provides an asynchronous API for Java. When consuming a result is consumed synchronously, as in the examples referenced above, the block() method is used.

The code below does not make any API call, it simply returns the Mono publisher object. Nothing happens until the application subscribes or blocks on the result:

Mono<String> result=capaRpcClient.invokeMethod(SERVICE_APP_ID,"say","hello",HttpExtension.POST,null,TypeRef.STRING);

To start execution and receive the result object synchronously, use block(). The code below shows how to execute the call and consume an empty response:

Mono<String> result=capaRpcClient.invokeMethod(SERVICE_APP_ID,"say","hello",HttpExtension.POST,null,TypeRef.STRING);
        String response=result.block();

Exception handling

Most exceptions thrown from the SDK are instances of CapaException. CapaException extends from RuntimeException, making it compatible with Project Reactor.

未来发展

关于Multi-Runtime的思考

Multi-Runtime 2022:待解决的问题

2 - 快速开始

快速开始使用

感谢您对Capa的支持!

2.1 - 使用Configuration API

使用Configuration API进行应用级配置管理.

简介

  1. CapaConfigurationClient提供的配置能力,需要实现具体的实现类来适配不同的平台(通过继承CapaConfigStoreSpi抽象类),如示例DemoCapaConfigStore

  2. 通过spi机制实现对具体实现类的加载。具体配置过程为:在项目resources路径下,新增capa-component-configuration.properties文件。

    在文件中新增属性key:“group.rxcloud.capa.component.configstore.CapaConfigStore”,value:“实现类的全路径”;新增属性key:“CONFIGURATION_COMPONENT_STORE_NAME”,value:“config store name"示例如下:

    //capa-component-configuration.properties文件
    group.rxcloud.capa.component.configstore.CapaConfigStore=group.rxcloud.capa.spi.demo.configstore.DemoCapaConfigStore
    CONFIGURATION_COMPONENT_STORE_NAME=DEMO CONFIG
    
  3. 调用相应Configuration API进行应用级配置管理

API使用步骤

Demo示例

第一步:构建单例Configuration Client

public final class CapaConfigStoreClientProvider {

    private static volatile CapaConfigurationClient client;

    public static CapaConfigurationClient getClient() {
        if (client == null) {
            synchronized (CapaConfigStoreClientProvider.class) {
                if (client == null) {
                    StoreConfig storeConfig = new StoreConfig();
                    storeConfig.setStoreName(Optional.ofNullable(CapaProperties.COMPONENT_PROPERTIES_SUPPLIER.apply("configuration").getProperty("CONFIGURATION_COMPONENT_STORE_NAME")).orElse("UN_CONFIGURED_STORE_CONFIG_NAME"));
                    client = new CapaConfigurationClientBuilder(storeConfig).build();
                }
            }
        }
        return client;
    }

    private CapaConfigStoreClientProvider() {
    }
}

第二步:通过提供的api对配置进行读/订阅/删除/保存等操作

  1. 读配置操作(getConfiguration)
//拿到单例client
private static final CapaConfigurationClient client = CapaConfigurationClientSingleton.getClient();

//getConfiguration()其中一个重载方法
Mono<List<ConfigurationItem<User>>> configMono = client.getConfiguration(new ConfigurationRequestItem(),TypeRef.get(User.class));

//getConfiguration()另一个重载方法
Mono<List<ConfigurationItem<User>>> configMono = client.getConfiguration("config", 
        SERVICE_APP_ID,
        Lists.newArrayList("test.json"),
        metaDataMap,
        "group",
        "label"
        TypeRef.get(User.class));

//阻塞获取配置结果
List<ConfigurationItem<User>> config = configMono.block();
  1. 订阅配置操作(subscribeConfiguration)
//本地存配置的变量
private SubConfigurationResp<String> cur;

//subscribeConfiguration()其中一个重载方法
Flux<SubConfigurationResp<User>> configFlux = client.subscribeConfiguration(new ConfigurationRequestItem(),TypeRef.get(User.class))

//subscribeConfiguration()另一个重载方法
Flux<SubConfigurationResp<User>> configFlux = client.subscribeConfiguration("config", 
        SERVICE_APP_ID,
        Lists.newArrayList("test.json"),
        metaDataMap,
        "group",
        "label"
        TypeRef.get(User.class));

//订阅后续的变更并更新原数据
configFlux.subscribe(resp -> cur.setItems(resp.getItems()));
  1. 保存配置操作(saveConfiguration)
Mono<Void> configFlux = client.saveConfiguration(new SaveConfigurationRequest());
  1. 删除配置操作()
Mono<Void> configFlux = client.deleteConfiguration(new ConfigurationRequestItem());

ps:以上api存在重载方法,点击此处查询全部api列表

2.2 - 使用RPC API

使用RPC API进行远程调用.

步骤

示例

  1. 构建 RPC Client
CapaRpcClient capaRpcClient = new CapaRpcClientBuilder().build();
  1. 调用请求
  Mono<byte[]> responseMono = capaRpcClient.invokeMethod(SERVICE_APP_ID,
        "hello",
        "hello",
        HttpExtension.POST,
        null,
        TypeRef.BYTE_ARRAY);
  1. 获取调用结果
byte[] response = responseMono.block();

解释

  1. CapaRpcClient 提供的 RPC 能力,需要具体实现,如示例 DemoCapaHttp
  2. 实现后的DemoCapaHttp,需要在 capa-component-rpc.properties 中进行配置,通过SPI机制实现加载。

3 - Demo示例

Demo示例

感谢您对Capa的支持!

3.1 - Configuration API示例

Configuration API 的Demo示例

Configuration API的实现类Demo示例

实现类Demo

配置文件Demo

ps:其中配置文件Demo中仅“group.rxcloud.capa.component.configstore.CapaConfigStore”和Configuration相关,其他property可以忽略

3.1.1 - Configuration AWS-App Config示例

使用App Config实现在AWS云环境下的应用级配置管理.

文档更新时间

由于当前处于高速迭代中,代码和版本都很不稳定,文档可能不是最新版本,接入jar包版本和流程都可能会有较大改动,请查看最后更新时间,若和当前时间超过一周请咨询相关开发询问是否有较大改动!!!

**last updated on 2021/12/06

接入使用流程

21/12/06/18:32 updated maven dependency

step1.引入maven依赖

<dependencyManagement>        
     <dependency>
            <groupId>group.rxcloud</groupId>
            <artifactId>capa-framework-dependencies</artifactId>
            <version>1.0.1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependency>
    <groupId>group.rxcloud</groupId>
    <artifactId>capa-spi-aws-config</artifactId>
</dependency>
<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-core</artifactId>
</dependency>

携程用户需要额外引入(目前jar包在携程私服上,仅限携程开发使用)

<dependency>
    <groupId>group.rxcloud</groupId>
    <artifactId>capa-adaptor-group.rxcloud-qconfig</artifactId>
</dependency>

此外还提供foundation方法包,供使用方获取appId,provider,env,namespace,region使用(该foundation中的其他方法并未测试,请不要使用)

<dependency>
    <groupId>group.rxcloud</groupId>
    <artifactId>capa-foundation</artifactId>
    <version>1.0.4.RELEASE</version>
</dependency>

ps:后续会统一放入capa-framework-dependencies bom中进行管理

step2.代码改动

非携程接入方(不使用adaptor包)使用流程

参照快速开始-使用Configuration API

  • 创建单例单例Configuration Client
public final class CapaConfigStoreClientProvider {

    private static volatile CapaConfigurationClient client;

    public static CapaConfigurationClient getClient() {
        if (client == null) {
            synchronized (CapaConfigStoreClientProvider.class) {
                if (client == null) {
                    StoreConfig storeConfig = new StoreConfig();
                    //对应实现的storeName
                    storeConfig.setStoreName(storeName);
                    client = new CapaConfigurationClientBuilder(storeConfig).build();
                }
            }
        }
        return client;
    }

    private CapaConfigStoreClientProvider() {
    }
}
private static final CapaConfigurationClient client = CapaConfigStoreClientProvider.getClient();
  • 调用get/subscribe接口获取/订阅数据
//根据自身填入storeName,appId
Mono<List<ConfigurationItem<User>>> configMono = client.getConfiguration(
    	storeName, 
        appId,
        Lists.newArrayList("test.json"),
        null,
        "",
        "",
        TypeRef.get(User.class));

//阻塞获取配置结果
List<ConfigurationItem<User>> config = configMono.block();
//带超时时间的阻塞,自定义超时时间
List<ConfigurationItem<User>> config = configMono.block(Duration.ofSeconds(30));

subscribe

//本地存配置的变量
private static SubConfigurationResp<User> cur;

static {
    //根据自身填入storeName,appId
        Flux<SubConfigurationResp<User>> configFlux = client.subscribeConfiguration(
            	storeName,
                appId,
                Lists.newArrayList("test.json"),
                null,
                "",
                "",
                TypeRef.get(User.class));
    //阻塞初始化配置
		cur = configFlux.blockFirst();
    //或使用带超时时间的阻塞初始化配置,自定义超时时间
    	cur = configFlux.blockFirst(Duration.ofSeconds(30));
	//订阅变更并更新原数据
        configFlux.subscribe(resp -> cur.setItems(resp.getItems()));
    }
  • 代码中,通过本地存配置的变量cur使用相关配置
public String getConfig() {
        User user = cur.getItems().get(0).getContent();
        System.out.println("-----------------------------------age:" + user.getName());
 }

携程接入方使用流程

注解使用流程

  • 使用adaptor包中的@QConfig注解替换QConfig中原来的@QConfig注解:将import qunar.tc.qconfig.client.spring.QConfig;修改为import group.rxcloud.capa.adaptor.group.rxcloud.qconfig.annotation.QConfig;

  • 代码写法

@Service
public class JsonConfigService {
    @QConfig("testjson.json")
    private Person person;//非监听模式,支持热更新

    @QConfig("testjson.json")
    private void onChange(Person person) {//监听模式
        System.out.println(person);
    }

    public String getPerson() {
        return JSON.toJSONString(person);
    }
}
  • 注解支持范围:只支持@QConfig注解,并且只支持注解加载field上和method上

API使用流程

  • 从adaptor中获取单例config client
private static final CapaConfigurationClient client = CapaConfigurationClientProvider.getClient();
  • 调用get/subscribe接口获取/订阅数据
//从adaptor中CapaConfigStoreClientProvider静态方法中获取storeName(必须)和appid(可选,可以自己从app.properties中读,也可以使用Foundation.app().getAppId() ps:此包为capa-foundation包提供的方法,仅在aws实现下使用)
Mono<List<ConfigurationItem<User>>> configMono = client.getConfiguration(
    	CapaConfigurationClientProvider.provideStoreName(), 
        Foundation.app().getAppId(),
        Lists.newArrayList("test.json"),
        null,
        TypeRef.get(User.class));
//阻塞获取配置结果
List<ConfigurationItem<User>> config = configMono.block();
//或带超时时间的阻塞,自定义超时时间
List<ConfigurationItem<User>> config = configMono.block(Duration.ofSeconds(30));

subscribe

//本地存配置的变量
private static SubConfigurationResp<User> cur;

static {
    //从adaptor中CapaConfigStoreClientProvider静态方法中获取storeName(必须)和appid(可选,可以自己从app.properties中读,也可以使用Foundation.app().getAppId() ps:此包为capa-foundation包提供的方法,仅在aws实现下使用)
        Flux<SubConfigurationResp<User>> configFlux = client.subscribeConfiguration(
            	CapaConfigurationClientProvider.provideStoreName(),
                Foundation.app().getAppId(),
                Lists.newArrayList("test.json"),
                null,
                TypeRef.get(User.class));
    //阻塞初始化配置
	cur = configFlux.blockFirst();
    //或使用带超时时间的阻塞初始化配置,自定义超时时间
    cur = configFlux.blockFirst(Duration.ofSeconds(30));
	//订阅变更并更新原数据
        configFlux.subscribe(resp -> cur.setItems(resp.getItems()));
    }
  • 代码中,通过本地存配置的变量cur使用相关配置
public String getConfig() {
        User user = cur.getItems().get(0).getContent();
        System.out.println("-----------------------------------age:" + user.getName());
 }

目前支持的功能范围

  1. 配置文件类型:.json和.properties结尾的文件
  2. 注解支持范围:仅支持@QConfig注解(不支持其他注解),注解支持修饰在field上和method上
    • 修饰在field上,为非监听模式,仅支持热更新
    • 修饰在方法上,为监听模式,同时支持热更新
  3. API支持范围如下

目前支持的API

@Override
<T> Mono<List<ConfigurationItem<T>>> getConfiguration(String storeName, String appId, List<String> keys, Map<String, String> metadata, TypeRef<T> type);

@Override
<T> Mono<List<ConfigurationItem<T>>> getConfiguration(String storeName, String appId, List<String> keys, Map<String, String> metadata, String group, TypeRef<T> type);

@Override
<T> Mono<List<ConfigurationItem<T>>> getConfiguration(String storeName, String appId, List<String> keys, Map<String, String> metadata, String group, String label, TypeRef<T> type);
@Override
<T> Flux<SubConfigurationResp<T>> subscribeConfiguration(String storeName, String appId, List<String> keys, Map<String, String> metadata, TypeRef<T> type);

@Override
<T> Flux<SubConfigurationResp<T>> subscribeConfiguration(String storeName, String appId, List<String> keys, Map<String, String> metadata, String group, TypeRef<T> type);

@Override
<T> Flux<SubConfigurationResp<T>> subscribeConfiguration(String storeName, String appId, List<String> keys, Map<String, String> metadata, String group, String label, TypeRef<T> type);

暂不支持的API

@Override
<T> Mono<List<ConfigurationItem<T>>> getConfiguration(ConfigurationRequestItem configurationRequestItem, TypeRef<T> type);

@Override
<T> Flux<SubConfigurationResp<T>> subscribeConfiguration(ConfigurationRequestItem configurationRequestItem, TypeRef<T> type);

@Override
Mono<Void> saveConfiguration(SaveConfigurationRequest saveConfigurationRequest);

@Override
Mono<Void> deleteConfiguration(ConfigurationRequestItem configurationRequestItem);

中间件开发者配置AppConfig应用规范

  1. AppConfig应用名格式为:“AppId_ENV”,e.g.100012345_FAT(环境与group.rxcloud环境定义一致,且保持全大写)
  2. 创建配置文件选择托管文件的方式
  3. 文件发布部署时,选择immediate_shixu的部署方式,或者自己创建部署方式,选择创建部署时间0min,烘焙时间0min,百分比100%,线性的部署方式

实现步骤

  1. 针对AWS云的设施基础现状下,选型AWS AppConfig为应用级别配置管理组件

  2. 继承CapaConfigStoreSpi抽象类,底层通过对appconfig的封装,实现相应的Configuration API

  3. 通过SPI机制引入相关实现类。具体流程为:

    • 引入相关实现类的jar包
    • 在项目resources路径下,新增capa-component-configuration.properties文件。文件内容如下
    #capa-component-configuration.properties文件
    group.rxcloud.capa.component.configstore.CapaConfigStore=group.rxcloud.capa.spi.aws.config.AwsCapaConfigStore
    
    • 在项目resources路径下,新增capa-component-configuration-common.properties
    # configuration component store names
    CONFIGURATION_COMPONENT_STORE_NAMES=aws.appconfig
    
    • 在项目resources路径下,新增capa-component-configuration-aws.propertoes
    # configstore aws app config env
    CONFIG_AWS_APP_CONFIG_ENV=ENV
    
  4. 调用方通过使用Capa统一规范的Configuration API即可完成对应用级别配置的管理需求。

3.1.2 - Configuration Ctrip-Qconfig示例

使用Qconfig API实现在携程全家桶环境下的应用级配置管理##

文档更新时间

由于当前处于高速迭代中,代码和版本都很不稳定,文档可能不是最新版本,接入jar包版本和流程都可能会有较大改动,请查看最后更新时间,若和当前时间超过一周请咨询相关开发询问是否有较大改动!!!

last updated on 2021/12/06

接入使用流程

step1.引入maven依赖

21/12/06/18:32 updated maven dependency

<dependencyManagement>        
     <dependency>
            <groupId>group.rxcloud</groupId>
            <artifactId>capa-framework-dependencies</artifactId>
            <version>1.0.1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependency>
    <groupId>group.rxcloud</groupId>
    <artifactId>capa-spi-group.rxcloud-qconfig</artifactId>
</dependency>
<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-core</artifactId>
</dependency>
<dependency>
    <groupId>group.rxcloud</groupId>
    <artifactId>capa-adaptor-group.rxcloud-qconfig</artifactId>
</dependency>

step2.相关代码修改

注解接入使用流程

  • 使用adaptor包中的@QConfig注解替换QConfig中原来的@QConfig注解:将import qunar.tc.qconfig.client.spring.QConfig;修改为import group.rxcloud.capa.adaptor.group.rxcloud.qconfig.annotation.QConfig;
  • 使用如下
@Service
public class JsonConfigService {
    @QConfig("testjson.json")
    private Person person;//非监听模式,支持热更新

    @QConfig("testjson.json")
    private void onChange(Person person) {//监听模式
        System.out.println(person);
    }

    public String getPerson() {
        return JSON.toJSONString(person);
    }
}

API接入使用流程

  • 调用adaptor中方法,创建单例单例Configuration Client
private static final CapaConfigurationClient client = CapaConfigurationClientProvider.getClient();
  • 调用get/subscribe接口获取/订阅数据
//从adaptor中CapaConfigStoreClientProvider静态方法中获取storeName(必须)
Mono<List<ConfigurationItem<User>>> configMono = client.getConfiguration(
    	CapaConfigurationClientProvider.provideStoreName(), 
        appid,
        Lists.newArrayList("test.json"),
        null,
        TypeRef.get(User.class));

//阻塞获取配置结果
List<ConfigurationItem<User>> config = configMono.block();
//带超时时间的阻塞,自定义超时时间
List<ConfigurationItem<User>> config = configMono.block(Duration.ofSeconds(30));
//本地存配置的变量
private static SubConfigurationResp<User> cur;

static {
    //从adaptor中CapaConfigStoreClientProvider静态方法中获取storeName(必须)
        Flux<SubConfigurationResp<User>> configFlux = client.subscribeConfiguration(
            	CapaConfigurationClientProvider.provideStoreName(),
                appid,
                Lists.newArrayList("test.json"),
                null,
                TypeRef.get(User.class));
	//阻塞初始化配置
    cur = configFlux.blockFirst();
    //或使用带超时时间的阻塞初始化配置,自定义超时时间
    cur = configFlux.blockFirst(Duration.ofSeconds(30));
	//订阅变更并更新原数据
        configFlux.subscribe(resp -> cur.setItems(resp.getItems()));
    }
  • 代码中,通过本地存配置的变量cur使用相关配置
public String getConfig() {
        User user = cur.getItems().get(0).getContent();
        System.out.println("-----------------------------------age:" + user.getName());
 }

目前支持的功能范围

  1. 配置文件类型:.json和.properties结尾的文件
  2. 注解支持范围:仅支持@QConfig注解(不支持其他注解),注解支持修饰在field上和method上
    • 修饰在field上,为非监听模式,仅支持热更新
    • 修饰在方法上,为监听模式,同时支持热更新
  3. API支持范围如下

目前支持的API

@Override
<T> Mono<List<ConfigurationItem<T>>> getConfiguration(String storeName, String appId, List<String> keys, Map<String, String> metadata, TypeRef<T> type);

@Override
<T> Mono<List<ConfigurationItem<T>>> getConfiguration(String storeName, String appId, List<String> keys, Map<String, String> metadata, String group, TypeRef<T> type);

@Override
<T> Mono<List<ConfigurationItem<T>>> getConfiguration(String storeName, String appId, List<String> keys, Map<String, String> metadata, String group, String label, TypeRef<T> type);
@Override
<T> Flux<SubConfigurationResp<T>> subscribeConfiguration(String storeName, String appId, List<String> keys, Map<String, String> metadata, TypeRef<T> type);

@Override
<T> Flux<SubConfigurationResp<T>> subscribeConfiguration(String storeName, String appId, List<String> keys, Map<String, String> metadata, String group, TypeRef<T> type);

@Override
<T> Flux<SubConfigurationResp<T>> subscribeConfiguration(String storeName, String appId, List<String> keys, Map<String, String> metadata, String group, String label, TypeRef<T> type);

暂不支持的API

@Override
<T> Mono<List<ConfigurationItem<T>>> getConfiguration(ConfigurationRequestItem configurationRequestItem, TypeRef<T> type);

@Override
<T> Flux<SubConfigurationResp<T>> subscribeConfiguration(ConfigurationRequestItem configurationRequestItem, TypeRef<T> type);

@Override
Mono<Void> saveConfiguration(SaveConfigurationRequest saveConfigurationRequest);

@Override
Mono<Void> deleteConfiguration(ConfigurationRequestItem configurationRequestItem);

调用逻辑

configuration_in_group.rxcloud

ps:Service(appid:123)为举例,表示一个应用id为123的服务,下面直接缩写成ServiceA

  • ServiceA:服务调用方
  • ServiceA通过调用Capa SDK中统一规范制定的Capa Configuration API发起该应用的配置管理请求
  • 找到通过SPI机制注册Capa Configuration API的Ctrip实现类,并执行相关逻辑
  • Configuration API内部关于Ctrip的实现,底层调用Qconfig API进行相应的配置管理
  • 获取Qconfig Service返回的数据,并一路返回给服务调用方ServiceA
  • ServiceA获取相关配置操作的结果,实现应用级别的配置管理

实现步骤

  1. 针对携程全家桶的设施基础现状下,选型Qconfig为应用级别配置管理组件

  2. 继承CapaConfigStoreSpi抽象类,底层通过对Qconfig的封装,实现相应的Configuration API

  3. 通过SPI机制引入相关实现类。具体流程为:

    • 引入相关实现类的jar包
    • 在项目resources路径下,新增capa-component-configuration.properties文件。文件内容如下
    #capa-component-configuration.properties文件
    group.rxcloud.capa.component.configstore.CapaConfigStore=group.rxcloud.capa.spi.group.rxcloud.configstore.CtripCapaConfigStore
    
    • 在项目resources路径下,新增capa-component-configuration-common.properties
    CONFIGURATION_COMPONENT_STORE_NAME=group.rxcloud.qconfig
    
    • 在项目resources路径下,新增capa-component-configuration-group.rxcloud.propertoes
    #暂无配置
    
  4. 调用方通过使用Capa统一规范的Configuration API即可完成对应用级别配置的管理需求。

3.2 - RPC API示例

RPC API 的Demo示例

RPC API 设计文档

3.2.1 - RPC AWS-App Mesh示例

使用RPC API 在 AWS 的 App Mesh 中进行远程调用.

目前支持的API

  @Override
    <T> Mono<T> invokeMethod(String appId, String methodName, Object data, HttpExtension httpExtension, Map<String, String> metadata, TypeRef<T> type);

    @Override
    <T> Mono<T> invokeMethod(String appId, String methodName, Object request, HttpExtension httpExtension, Map<String, String> metadata, Class<T> clazz);

    @Override
    <T> Mono<T> invokeMethod(String appId, String methodName, Object request, HttpExtension httpExtension, TypeRef<T> type);

    @Override
    <T> Mono<T> invokeMethod(String appId, String methodName, Object request, HttpExtension httpExtension, Class<T> clazz);

    @Override
    <T> Mono<T> invokeMethod(String appId, String methodName, HttpExtension httpExtension, Map<String, String> metadata, TypeRef<T> type);

    @Override
    <T> Mono<T> invokeMethod(String appId, String methodName, HttpExtension httpExtension, Map<String, String> metadata, Class<T> clazz);

    @Override
    Mono<Void> invokeMethod(String appId, String methodName, Object request, HttpExtension httpExtension, Map<String, String> metadata);

    @Override
    Mono<Void> invokeMethod(String appId, String methodName, Object request, HttpExtension httpExtension);

    @Override
    Mono<Void> invokeMethod(String appId, String methodName, HttpExtension httpExtension, Map<String, String> metadata);

    @Override
    Mono<byte[]> invokeMethod(String appId, String methodName, byte[] request, HttpExtension httpExtension, Map<String, String> metadata);

    @Override
    <T> Mono<T> invokeMethod(InvokeMethodRequest invokeMethodRequest, TypeRef<T> type);

调用逻辑

下图为 Capa 的 RPC 在携程的 App Mesh 服务调用逻辑

  • Service A 为服务调用方, Service B 为服务被调用方
  • Service A 通过 Capa SDK 发起对 Service B 的服务调用
  • Capa RPC API 是统一的 API 规范
  • 通过 SPI 机制可以找到 Capa RPC API 的在 AWS 中的具体 RPC 实现 Capa-Aws RPC Impl
  • 获取 Service B 的返回数据,并返回给服务调用方 Service A

实现步骤

  1. 实现 RpcServiceOptions (实际 RPC 调用需要的参数) 和 CtripSpiOptionsLoader (加载 RpcServiceOptions 的实现类) 接口。

    例如 AwsRpcServiceOptions 和 AwsSpiOptionsLoader

  2. 继承 CapaSerializeHttpSpi , 实现在携程 Service Mesh 的 RPC 调用。

    例如 AwsCapaHttp

  3. 构建 capa-component-rpc.properties 文件,添加 group.rxcloud.capa.component.http.CapaHttp 和 group.rxcloud.capa.spi.config.CapaSpiOptionsLoader 对应的类的路径,以支持 SPI 方式加载对应的类。

    例如:

 group.rxcloud.capa.component.http.CapaHttp=group.rxcloud.capa.spi.group.rxcloud.http.AwsCapaHttp
 group.rxcloud.capa.spi.config.CapaSpiOptionsLoader=group.rxcloud.capa.spi.group.rxcloud.config.AwsSpiOptionsLoader   

3.2.2 - RPC Ctrip-Service Mesh示例

使用RPC API 在携程的 Service Mesh 中进行远程调用.

目前支持的API

  @Override
    <T> Mono<T> invokeMethod(String appId, String methodName, Object data, HttpExtension httpExtension, Map<String, String> metadata, TypeRef<T> type);

    @Override
    <T> Mono<T> invokeMethod(String appId, String methodName, Object request, HttpExtension httpExtension, Map<String, String> metadata, Class<T> clazz);

    @Override
    <T> Mono<T> invokeMethod(String appId, String methodName, Object request, HttpExtension httpExtension, TypeRef<T> type);

    @Override
    <T> Mono<T> invokeMethod(String appId, String methodName, Object request, HttpExtension httpExtension, Class<T> clazz);

    @Override
    <T> Mono<T> invokeMethod(String appId, String methodName, HttpExtension httpExtension, Map<String, String> metadata, TypeRef<T> type);

    @Override
    <T> Mono<T> invokeMethod(String appId, String methodName, HttpExtension httpExtension, Map<String, String> metadata, Class<T> clazz);

    @Override
    Mono<Void> invokeMethod(String appId, String methodName, Object request, HttpExtension httpExtension, Map<String, String> metadata);

    @Override
    Mono<Void> invokeMethod(String appId, String methodName, Object request, HttpExtension httpExtension);

    @Override
    Mono<Void> invokeMethod(String appId, String methodName, HttpExtension httpExtension, Map<String, String> metadata);

    @Override
    Mono<byte[]> invokeMethod(String appId, String methodName, byte[] request, HttpExtension httpExtension, Map<String, String> metadata);

    @Override
    <T> Mono<T> invokeMethod(InvokeMethodRequest invokeMethodRequest, TypeRef<T> type);

调用逻辑

下图为 Capa 的 RPC 在携程的 Service Mesh 服务调用逻辑

  • Service A 为服务调用方, Service B 为服务被调用方
  • Service A 通过 Capa SDK 发起对 Service B 的服务调用
  • Capa RPC API 是统一的 API 规范
  • 通过 SPI 机制可以找到 Capa RPC API 的在 Ctrip 中的具体 RPC 实现 Capa-Ctrip RPC Impl
  • 获取 Service B 的返回数据,并返回给服务调用方 Service A

实现步骤

  1. 实现 RpcServiceOptions (实际 RPC 调用需要的参数) 和 CtripSpiOptionsLoader (加载 RpcServiceOptions 的实现类) 接口。

    例如 CtripRpcServiceOptions 和 CtripSpiOptionsLoader

  2. 继承 CapaSerializeHttpSpi , 实现在携程 Service Mesh 的 RPC 调用。

    例如 CtripCapaHttp

  3. 构建 capa-component-rpc.properties 文件,添加 group.rxcloud.capa.component.http.CapaHttp 和 group.rxcloud.capa.spi.config.CapaSpiOptionsLoader 对应的类的路径,以支持 SPI 方式加载对应的类。

    例如:

 group.rxcloud.capa.component.http.CapaHttp=group.rxcloud.capa.spi.group.rxcloud.http.CtripCapaHttp
 group.rxcloud.capa.spi.config.CapaSpiOptionsLoader=group.rxcloud.capa.spi.group.rxcloud.config.CtripSpiOptionsLoader   

4 - 设计文档

Capa设计概述

背景

在跨云、混合云的场景下,我们希望应用程序可以使用一套代码,部署到不同的云环境上。在运行时,采用对应云环境提供的云原生实现方案

技术思路

api design

定义与具体中间件无关的API层(无强绑定),使应用程序在编程时仅依赖该API层。 如此一来,应用本身便与具体中间件解耦;然后在部署到不同云环境时,将API的不同云的实现层加载到应用进程中。

4.1 - Actuator可观测性

应用级组件可观测性规范定义

可观测性 规范定义

全面的可观测指标度量规范定义

A、可观测性理论探究

参考资料:https://segmentfault.com/a/1190000040061004

参考资料:https://www.51cto.com/article/691184.html

参考资料:https://segmentfault.com/a/1190000040061004

一、命名空间 规范定义

命名空间采用分级域名命名方式:

(顶级域名).一级域名.二级域名.三级域名.x.y.z

0、顶级域名: 云划分

顶级域名应标识所属云(私有云、公有云)等基础设施。

但目前各云监控指标命名空间本身隔离,故不考虑加入顶级域名。

A、一级域名: 技术栈领域划分

将云原生技术栈划分为4个领域,一级域名标识了所属的层级。

  • 运维层(Maintainance)
  • 应用层(Application)
  • 中间件层(Middleware)
  • 基础设施层(Infrastructure)

对应一级域命名空间为:

  • Ops
  • App
  • Fxc
  • Inf

参考设计1:云原生技术栈Stack

参考云原生技术栈图示给出的四个层次,使一级域名能够显示出Actuator所属的层级。

参考设计2:携程现有监控指标分类

携程监控指标的一级域名主要有SystemFrameworkNameApp等等。

不过其技术栈领域的监控划分主要依赖于:使用不同看板进行呈现,相当于不同的监控平台本身对应于不同的技术栈领域。

应用层的监控主要还是以FrameworkName为主,反映出了携程是以框架为主体,框架就强绑定了该领域的概念(看到Dal就意味着关系型数据库、看到SOA就意味着RPC领域)。

B、二次域名: 组件领域划分

1. Ops

Ops运维和管理领域:

  • CICD

2. App

应用层,应在二级域名进行应用类型的划分。

在这里,我们参考携程的应用类型设计,取运行时语言作为划分:

  • Java
  • Node
  • Python
  • Golang

3. Fxc

主要基于中间件维度进行定义:

  • RPC
  • MQ
  • Configuration
  • DB
  • Redis
  • Metric
  • Log

4. Inf

以基础设施作为划分:

  • K8S
  • ECS
  • AppMesh

C、三次域名: 中间件/语种/… 细节划分

基于以上 一级域名(技术栈领域).二级域名(组件领域划分) 的命名空间,我们已经能够体现具体领域。

但每个领域,都可能有多种实现。 例如在中间件领域,携程命名空间做了 中间件-领域 的强绑定。

所以在三级域名的设计上,我们希望体现一些更细节的信息。

但没有必要像一二级域名一样,保持独立的语义。 故使用 小写+下划线 作为三级域名的格式标准。 包含更丰富的语义,但视觉上不像一二级域名一样强烈。

三级域名如果有更多细节需要体现,通过追加的方式进行拓展。

1. Ops

2. App

从实用性上来看,可以不使用三级域名,直接基于appId等。

如果要使用,参考携程应用类型定义。

  • web
  • service
  • job
  • serverless

3. Fxc

3.1 中间件/工具

组件领域,可能有多种 中间件实现 / 工具。

所以在三级域名上,我们希望体现 中间件/工具 的概念。

3.2 语种

组件领域,中间件领域,都可能有多种编程语言的实现,其SDK内部逻辑不可能完全一致。

所以在三级域名上,我们希望体现 编程语言 的概念。

3.3 总结

对于Fxc而言,目前已有(中间件名称_编程语言):

  • capa_java
  • ibu_java
  • ibu_node

4. Inf

对于Inf而言,目前已有(工具/产品名称):

  • ecs
  • eks

参考设计1:携程框架监控

携程在监控命名上,强体现 框架名称

D、命名空间划分效果

1. Ops

CICD

  • Ops.CICD.codepipeline

2. App

业务应用

  • App.Java.service
  • App.Node.web

3. Fxc

中间件领域命名空间

RPC

  • Fxc.RPC.capa_java
  • Fxc.RPC.ibu_node

MQ

  • Fxc.MQ.ibu_java

Configuration

  • Fxc.Configuration.capa_java
  • Fxc.Configuration.ibu_java

DB

  • Fxc.DB.dal_java

Redis

  • Fxc.Redis.ibu_java

Metric

  • Fxc.Metric.capa_java
  • Fxc.Metric.ibu_node

Log

  • Fxc.Log.capa_java
  • Fxc.Log.ibu_node

4. Inf

K8S

  • Inf.K8S.ecs
  • Inf.K8S.eks

二、监控指标 规范定义

使用 小写+下划线 作为 监控指标 名称的格式标准。

监控指标设计分为:Level0、Level1、Level2层次。

1. level0

必需监控指标:

  • 请求量
  • 耗时
    • avg
    • 95
    • 99
    • max
  • 成功率
    • 成功量
    • 失败量

2. level1

拓展监控指标

A、Fxc

level0

xx定义为 操作/业务 名称

请求量:

  • xx_count

耗时:

  • xx_duration

成功率:

  • xx_success
  • xx_failure

三、Attributes 规范定义

使用 小写+下划线 作为attributes的格式标准。

A、必需(建议)

  • app_id(广义的app_id)
  • env

B、操作字段

  • method 操作名称
  • stub 端标识(client/server、pub/sub)

4.1.1 - RPC Actuator可观测性

RPC组件可观测性规范定义

RPC Actuator可观测性

Client技术选型

Server技术选型

4.2 - Configuration服务调用

执行应用级的配置管理

介绍

通过调用Capa SDK API的方式,管理应用级配置。底层通过SPI的方式注册适配各平台的实现类。

调用逻辑

下图为Capa的Configuration服务调用逻辑

Configuration

  • Service(appid:A):服务调用方,CloudX Configuration Service为服务被调用方,服务被调用方可以是任意云厂商的配置服务
  • Service(appid:A)通过Capa SDK发起对Cloud Configuration Service的服务调用
  • Capa Configuration API是统一的API规范
  • Capa-CloudX Configuration Adaptor SDK为Capa的适配器实现类,通过spi的形式注册
  • CloudX Configuration Service提供实际的配置服务

API设计

Capa Configuration API的设计参考了社区的规范

Layotto API

Capa Configuration API

具体参数含义如下:

参数含义
storeName存储名称
appId同一命名空间内的服务唯一ID
keys配置key列表
metadata发送配置请求的元信息
group配置组(Optional)
label配置标签(Optional)
type请求响应对象中的泛型对应的具体类型
ConfigurationRequestItem请求对象
ConfigurationItem获取配置的响应对象
SubConfigurationResp订阅配置的响应对象

4.3 - RPC服务调用

执行直接、安全、服务到服务的方法调用

介绍

调用逻辑

下图为 Capa 的 RPC 服务调用逻辑

  • Service A 为服务调用方, Service B 为服务被调用方
  • Service A 通过 Capa SDK 发起对 Service B 的服务调用
  • Capa RPC API 是统一的 API 规范
  • 通过 SPI 机制可以找到 Capa RPC API 的具体 RPC 实现 RPC Impl
  • 获取 Service B 的返回数据,并返回给服务调用方 Service A

API 设计

Capa的 api 设计参照了社区的规范

Dapr API

Layotto API

Capa API

具体参数含义如下:

参数含义
appId同一命名空间内的服务唯一ID
methodName被调用服务的方法名
request要发送调用的服务请求
httpExtensionHTTP请求方式
metadata发送请求的元数据(GRPC)或者请求头(HTTP)
clazz请求响应的类型
type请求响应的类型
invokeMethodRequest请求对象

4.3.1 - RPC AWS技术方案

RPC中间件在AWS云上的技术方案

AWS RPC技术选型

经过调研,发现AWS在RPC上

Client技术选型

Server技术选型

4.3.2 - RPC Ctrip技术方案

RPC中间件在Ctrip云上的技术方案

介绍

通过服务调用,应用程序可以使用 HTTP 这样的标准协议来发现并可靠地与其他应用程序通信。

调用逻辑

下图为 Capa 的 RPC 服务调用逻辑

  • Service A 为服务调用方, Service B 为服务被调用方
  • Service A 通过 Capa SDK 发起对 Service B 的服务调用
  • Capa RPC API 是统一的 API 规范
  • 通过 SPI 机制可以找到 Capa RPC API 的具体 RPC 实现 RPC Impl
  • 获取 Service B 的返回数据,并返回给服务调用方 Service A

API 设计

Capa的 api 设计参照了社区的规范

Dapr API

Layotto API

Capa API

具体参数含义如下:

参数含义
appId同一命名空间内的服务唯一ID
methodName被调用服务的方法名
request要发送调用的服务请求
httpExtensionHTTP请求方式
metadata发送请求的元数据(GRPC)或者请求头(HTTP)
clazz请求响应的类型
type请求响应的类型
invokeMethodRequest请求对象

5 - 开发指南

What can your user do with your project?

This is a placeholder page that shows you how to use this template site.

Think about your project’s features and use cases. Use these to choose your core tasks. Each granular use case (enable x, configure y) should have a corresponding tasks page or tasks page section. Users should be able to quickly refer to your core tasks when they need to find out how to do one specific thing, rather than having to look for the instructions in a bigger tutorial or example. Think of your tasks pages as a cookbook with different procedures your users can combine to create something more substantial.

You can give each task a page, or you can group related tasks together in a page, such as tasks related to a particular feature. As well as grouping related tasks in single pages, you can also group task pages in nested folders with an index page as an overview, as seen in this example site. Or if you have a small docset like the Docsy User Guide with no Tutorials or Concepts pages, consider adding your feature-specific pages at the top level of your docs rather than in a Tasks section.

Each task should give the user

  • The prerequisites for this task, if any (this can be specified at the top of a multi-task page if they’re the same for all the page’s tasks. “All these tasks assume that you understand….and that you have already….”).
  • What this task accomplishes.
  • Instructions for the task. If it involves editing a file, running a command, or writing code, provide code-formatted example snippets to show the user what to do! If there are multiple steps, provide them as a numbered list.
  • If appropriate, links to related concept, tutorial, or example pages.

5.1 - Bed and Chair Metrics

A short lead description about this content page. It can be bold or italic and can be split over multiple paragraphs.

This is a placeholder page. Replace it with your own content.

Text can be bold, italic, or strikethrough. Links should be blue with no underlines (unless hovered over).

There should be whitespace between paragraphs. Vape migas chillwave sriracha poutine try-hard distillery. Tattooed shabby chic small batch, pabst art party heirloom letterpress air plant pop-up. Sustainable chia skateboard art party banjo cardigan normcore affogato vexillologist quinoa meggings man bun master cleanse shoreditch readymade. Yuccie prism four dollar toast tbh cardigan iPhone, tumblr listicle live-edge VHS. Pug lyft normcore hot chicken biodiesel, actually keffiyeh thundercats photo booth pour-over twee fam food truck microdosing banh mi. Vice activated charcoal raclette unicorn live-edge post-ironic. Heirloom vexillologist coloring book, beard deep v letterpress echo park humblebrag tilde.

90’s four loko seitan photo booth gochujang freegan tumeric listicle fam ugh humblebrag. Bespoke leggings gastropub, biodiesel brunch pug fashion axe meh swag art party neutra deep v chia. Enamel pin fanny pack knausgaard tofu, artisan cronut hammock meditation occupy master cleanse chartreuse lumbersexual. Kombucha kogi viral truffaut synth distillery single-origin coffee ugh slow-carb marfa selfies. Pitchfork schlitz semiotics fanny pack, ugh artisan vegan vaporware hexagon. Polaroid fixie post-ironic venmo wolf ramps kale chips.

There should be no margin above this first sentence.

Blockquotes should be a lighter gray with a border along the left side in the secondary color.

There should be no margin below this final sentence.

First Header 2

This is a normal paragraph following a header. Knausgaard kale chips snackwave microdosing cronut copper mug swag synth bitters letterpress glossier craft beer. Mumblecore bushwick authentic gochujang vegan chambray meditation jean shorts irony. Viral farm-to-table kale chips, pork belly palo santo distillery activated charcoal aesthetic jianbing air plant woke lomo VHS organic. Tattooed locavore succulents heirloom, small batch sriracha echo park DIY af. Shaman you probably haven’t heard of them copper mug, crucifix green juice vape single-origin coffee brunch actually. Mustache etsy vexillologist raclette authentic fam. Tousled beard humblebrag asymmetrical. I love turkey, I love my job, I love my friends, I love Chardonnay!

Deae legum paulatimque terra, non vos mutata tacet: dic. Vocant docuique me plumas fila quin afuerunt copia haec o neque.

On big screens, paragraphs and headings should not take up the full container width, but we want tables, code blocks and similar to take the full width.

Scenester tumeric pickled, authentic crucifix post-ironic fam freegan VHS pork belly 8-bit yuccie PBR&B. I love this life we live in.

Second Header 2

This is a blockquote following a header. Bacon ipsum dolor sit amet t-bone doner shank drumstick, pork belly porchetta chuck sausage brisket ham hock rump pig. Chuck kielbasa leberkas, pork bresaola ham hock filet mignon cow shoulder short ribs biltong.

Header 3

This is a code block following a header.

Next level leggings before they sold out, PBR&B church-key shaman echo park. Kale chips occupy godard whatever pop-up freegan pork belly selfies. Gastropub Belinda subway tile woke post-ironic seitan. Shabby chic man bun semiotics vape, chia messenger bag plaid cardigan.

Header 4

  • This is an unordered list following a header.
  • This is an unordered list following a header.
  • This is an unordered list following a header.
Header 5
  1. This is an ordered list following a header.
  2. This is an ordered list following a header.
  3. This is an ordered list following a header.
Header 6
WhatFollows
A tableA header
A tableA header
A tableA header

There’s a horizontal rule above and below this.


Here is an unordered list:

  • Liverpool F.C.
  • Chelsea F.C.
  • Manchester United F.C.

And an ordered list:

  1. Michael Brecker
  2. Seamus Blake
  3. Branford Marsalis

And an unordered task list:

  • Create a Hugo theme
  • Add task lists to it
  • Take a vacation

And a “mixed” task list:

  • Pack bags
  • ?
  • Travel!

And a nested list:

  • Jackson 5
    • Michael
    • Tito
    • Jackie
    • Marlon
    • Jermaine
  • TMNT
    • Leonardo
    • Michelangelo
    • Donatello
    • Raphael

Definition lists can be used with Markdown syntax. Definition headers are bold.

Name
Godzilla
Born
1952
Birthplace
Japan
Color
Green

Tables should have bold headings and alternating shaded rows.

ArtistAlbumYear
Michael JacksonThriller1982
PrincePurple Rain1984
Beastie BoysLicense to Ill1986

If a table is too wide, it should scroll horizontally.

ArtistAlbumYearLabelAwardsSongs
Michael JacksonThriller1982Epic RecordsGrammy Award for Album of the Year, American Music Award for Favorite Pop/Rock Album, American Music Award for Favorite Soul/R&B Album, Brit Award for Best Selling Album, Grammy Award for Best Engineered Album, Non-ClassicalWanna Be Startin’ Somethin’, Baby Be Mine, The Girl Is Mine, Thriller, Beat It, Billie Jean, Human Nature, P.Y.T. (Pretty Young Thing), The Lady in My Life
PrincePurple Rain1984Warner Brothers RecordsGrammy Award for Best Score Soundtrack for Visual Media, American Music Award for Favorite Pop/Rock Album, American Music Award for Favorite Soul/R&B Album, Brit Award for Best Soundtrack/Cast Recording, Grammy Award for Best Rock Performance by a Duo or Group with VocalLet’s Go Crazy, Take Me With U, The Beautiful Ones, Computer Blue, Darling Nikki, When Doves Cry, I Would Die 4 U, Baby I’m a Star, Purple Rain
Beastie BoysLicense to Ill1986Mercury RecordsnoawardsbutthistablecelliswideRhymin & Stealin, The New Style, She’s Crafty, Posse in Effect, Slow Ride, Girls, (You Gotta) Fight for Your Right, No Sleep Till Brooklyn, Paul Revere, Hold It Now, Hit It, Brass Monkey, Slow and Low, Time to Get Ill

Code snippets like var foo = "bar"; can be shown inline.

Also, this should vertically align with this and this.

Code can also be shown in a block element.

foo := "bar";
bar := "foo";

Code can also use syntax highlighting.

func main() {
  input := `var foo = "bar";`

  lexer := lexers.Get("javascript")
  iterator, _ := lexer.Tokenise(nil, input)
  style := styles.Get("github")
  formatter := html.New(html.WithLineNumbers())

  var buff bytes.Buffer
  formatter.Format(&buff, style, iterator)

  fmt.Println(buff.String())
}
Long, single-line code blocks should not wrap. They should horizontally scroll if they are too long. This line should be long enough to demonstrate this.

Inline code inside table cells should still be distinguishable.

LanguageCode
Javascriptvar foo = "bar";
Rubyfoo = "bar"{

Small images should be shown at their actual size.

Large images should always scale down and fit in the content container.

The photo above of the Spruce Picea abies shoot with foliage buds: Bjørn Erik Pedersen, CC-BY-SA.

Components

Alerts

Another Heading

Add some sections here to see how the ToC looks like. Bacon ipsum dolor sit amet t-bone doner shank drumstick, pork belly porchetta chuck sausage brisket ham hock rump pig. Chuck kielbasa leberkas, pork bresaola ham hock filet mignon cow shoulder short ribs biltong.

This Document

Inguina genus: Anaphen post: lingua violente voce suae meus aetate diversi. Orbis unam nec flammaeque status deam Silenum erat et a ferrea. Excitus rigidum ait: vestro et Herculis convicia: nitidae deseruit coniuge Proteaque adiciam eripitur? Sitim noceat signa probat quidem. Sua longis fugatis quidem genae.

Pixel Count

Tilde photo booth wayfarers cliche lomo intelligentsia man braid kombucha vaporware farm-to-table mixtape portland. PBR&B pickled cornhole ugh try-hard ethical subway tile. Fixie paleo intelligentsia pabst. Ennui waistcoat vinyl gochujang. Poutine salvia authentic affogato, chambray lumbersexual shabby chic.

Contact Info

Plaid hell of cred microdosing, succulents tilde pour-over. Offal shabby chic 3 wolf moon blue bottle raw denim normcore poutine pork belly.

Stumptown PBR&B keytar plaid street art, forage XOXO pitchfork selvage affogato green juice listicle pickled everyday carry hashtag. Organic sustainable letterpress sartorial scenester intelligentsia swag bushwick. Put a bird on it stumptown neutra locavore. IPhone typewriter messenger bag narwhal. Ennui cold-pressed seitan flannel keytar, single-origin coffee adaptogen occupy yuccie williamsburg chillwave shoreditch forage waistcoat.

This is the final element on the page and there should be no margin below this.

5.2 - Porridge Assessment

A short lead description about this content page. It can be bold or italic and can be split over multiple paragraphs.

This is a placeholder page. Replace it with your own content.

Text can be bold, italic, or strikethrough. Links should be blue with no underlines (unless hovered over).

There should be whitespace between paragraphs. Vape migas chillwave sriracha poutine try-hard distillery. Tattooed shabby chic small batch, pabst art party heirloom letterpress air plant pop-up. Sustainable chia skateboard art party banjo cardigan normcore affogato vexillologist quinoa meggings man bun master cleanse shoreditch readymade. Yuccie prism four dollar toast tbh cardigan iPhone, tumblr listicle live-edge VHS. Pug lyft normcore hot chicken biodiesel, actually keffiyeh thundercats photo booth pour-over twee fam food truck microdosing banh mi. Vice activated charcoal raclette unicorn live-edge post-ironic. Heirloom vexillologist coloring book, beard deep v letterpress echo park humblebrag tilde.

90’s four loko seitan photo booth gochujang freegan tumeric listicle fam ugh humblebrag. Bespoke leggings gastropub, biodiesel brunch pug fashion axe meh swag art party neutra deep v chia. Enamel pin fanny pack knausgaard tofu, artisan cronut hammock meditation occupy master cleanse chartreuse lumbersexual. Kombucha kogi viral truffaut synth distillery single-origin coffee ugh slow-carb marfa selfies. Pitchfork schlitz semiotics fanny pack, ugh artisan vegan vaporware hexagon. Polaroid fixie post-ironic venmo wolf ramps kale chips.

There should be no margin above this first sentence.

Blockquotes should be a lighter gray with a border along the left side in the secondary color.

There should be no margin below this final sentence.

First Header 2

This is a normal paragraph following a header. Knausgaard kale chips snackwave microdosing cronut copper mug swag synth bitters letterpress glossier craft beer. Mumblecore bushwick authentic gochujang vegan chambray meditation jean shorts irony. Viral farm-to-table kale chips, pork belly palo santo distillery activated charcoal aesthetic jianbing air plant woke lomo VHS organic. Tattooed locavore succulents heirloom, small batch sriracha echo park DIY af. Shaman you probably haven’t heard of them copper mug, crucifix green juice vape single-origin coffee brunch actually. Mustache etsy vexillologist raclette authentic fam. Tousled beard humblebrag asymmetrical. I love turkey, I love my job, I love my friends, I love Chardonnay!

Deae legum paulatimque terra, non vos mutata tacet: dic. Vocant docuique me plumas fila quin afuerunt copia haec o neque.

On big screens, paragraphs and headings should not take up the full container width, but we want tables, code blocks and similar to take the full width.

Scenester tumeric pickled, authentic crucifix post-ironic fam freegan VHS pork belly 8-bit yuccie PBR&B. I love this life we live in.

Second Header 2

This is a blockquote following a header. Bacon ipsum dolor sit amet t-bone doner shank drumstick, pork belly porchetta chuck sausage brisket ham hock rump pig. Chuck kielbasa leberkas, pork bresaola ham hock filet mignon cow shoulder short ribs biltong.

Header 3

This is a code block following a header.

Next level leggings before they sold out, PBR&B church-key shaman echo park. Kale chips occupy godard whatever pop-up freegan pork belly selfies. Gastropub Belinda subway tile woke post-ironic seitan. Shabby chic man bun semiotics vape, chia messenger bag plaid cardigan.

Header 4

  • This is an unordered list following a header.
  • This is an unordered list following a header.
  • This is an unordered list following a header.
Header 5
  1. This is an ordered list following a header.
  2. This is an ordered list following a header.
  3. This is an ordered list following a header.
Header 6
WhatFollows
A tableA header
A tableA header
A tableA header

There’s a horizontal rule above and below this.


Here is an unordered list:

  • Liverpool F.C.
  • Chelsea F.C.
  • Manchester United F.C.

And an ordered list:

  1. Michael Brecker
  2. Seamus Blake
  3. Branford Marsalis

And an unordered task list:

  • Create a Hugo theme
  • Add task lists to it
  • Take a vacation

And a “mixed” task list:

  • Pack bags
  • ?
  • Travel!

And a nested list:

  • Jackson 5
    • Michael
    • Tito
    • Jackie
    • Marlon
    • Jermaine
  • TMNT
    • Leonardo
    • Michelangelo
    • Donatello
    • Raphael

Definition lists can be used with Markdown syntax. Definition headers are bold.

Name
Godzilla
Born
1952
Birthplace
Japan
Color
Green

Tables should have bold headings and alternating shaded rows.

ArtistAlbumYear
Michael JacksonThriller1982
PrincePurple Rain1984
Beastie BoysLicense to Ill1986

If a table is too wide, it should scroll horizontally.

ArtistAlbumYearLabelAwardsSongs
Michael JacksonThriller1982Epic RecordsGrammy Award for Album of the Year, American Music Award for Favorite Pop/Rock Album, American Music Award for Favorite Soul/R&B Album, Brit Award for Best Selling Album, Grammy Award for Best Engineered Album, Non-ClassicalWanna Be Startin’ Somethin’, Baby Be Mine, The Girl Is Mine, Thriller, Beat It, Billie Jean, Human Nature, P.Y.T. (Pretty Young Thing), The Lady in My Life
PrincePurple Rain1984Warner Brothers RecordsGrammy Award for Best Score Soundtrack for Visual Media, American Music Award for Favorite Pop/Rock Album, American Music Award for Favorite Soul/R&B Album, Brit Award for Best Soundtrack/Cast Recording, Grammy Award for Best Rock Performance by a Duo or Group with VocalLet’s Go Crazy, Take Me With U, The Beautiful Ones, Computer Blue, Darling Nikki, When Doves Cry, I Would Die 4 U, Baby I’m a Star, Purple Rain
Beastie BoysLicense to Ill1986Mercury RecordsnoawardsbutthistablecelliswideRhymin & Stealin, The New Style, She’s Crafty, Posse in Effect, Slow Ride, Girls, (You Gotta) Fight for Your Right, No Sleep Till Brooklyn, Paul Revere, Hold It Now, Hit It, Brass Monkey, Slow and Low, Time to Get Ill

Code snippets like var foo = "bar"; can be shown inline.

Also, this should vertically align with this and this.

Code can also be shown in a block element.

foo := "bar";
bar := "foo";

Code can also use syntax highlighting.

func main() {
  input := `var foo = "bar";`

  lexer := lexers.Get("javascript")
  iterator, _ := lexer.Tokenise(nil, input)
  style := styles.Get("github")
  formatter := html.New(html.WithLineNumbers())

  var buff bytes.Buffer
  formatter.Format(&buff, style, iterator)

  fmt.Println(buff.String())
}
Long, single-line code blocks should not wrap. They should horizontally scroll if they are too long. This line should be long enough to demonstrate this.

Inline code inside table cells should still be distinguishable.

LanguageCode
Javascriptvar foo = "bar";
Rubyfoo = "bar"{

Small images should be shown at their actual size.

Large images should always scale down and fit in the content container.

The photo above of the Spruce Picea abies shoot with foliage buds: Bjørn Erik Pedersen, CC-BY-SA.

Components

Alerts

Another Heading

Add some sections here to see how the ToC looks like. Bacon ipsum dolor sit amet t-bone doner shank drumstick, pork belly porchetta chuck sausage brisket ham hock rump pig. Chuck kielbasa leberkas, pork bresaola ham hock filet mignon cow shoulder short ribs biltong.

This Document

Inguina genus: Anaphen post: lingua violente voce suae meus aetate diversi. Orbis unam nec flammaeque status deam Silenum erat et a ferrea. Excitus rigidum ait: vestro et Herculis convicia: nitidae deseruit coniuge Proteaque adiciam eripitur? Sitim noceat signa probat quidem. Sua longis fugatis quidem genae.

Pixel Count

Tilde photo booth wayfarers cliche lomo intelligentsia man braid kombucha vaporware farm-to-table mixtape portland. PBR&B pickled cornhole ugh try-hard ethical subway tile. Fixie paleo intelligentsia pabst. Ennui waistcoat vinyl gochujang. Poutine salvia authentic affogato, chambray lumbersexual shabby chic.

Contact Info

Plaid hell of cred microdosing, succulents tilde pour-over. Offal shabby chic 3 wolf moon blue bottle raw denim normcore poutine pork belly.

Stumptown PBR&B keytar plaid street art, forage XOXO pitchfork selvage affogato green juice listicle pickled everyday carry hashtag. Organic sustainable letterpress sartorial scenester intelligentsia swag bushwick. Put a bird on it stumptown neutra locavore. IPhone typewriter messenger bag narwhal. Ennui cold-pressed seitan flannel keytar, single-origin coffee adaptogen occupy yuccie williamsburg chillwave shoreditch forage waistcoat.

This is the final element on the page and there should be no margin below this.

5.3 - Another Task

A short lead description about this content page. It can be bold or italic and can be split over multiple paragraphs.

This is a placeholder page. Replace it with your own content.

Text can be bold, italic, or strikethrough. Links should be blue with no underlines (unless hovered over).

There should be whitespace between paragraphs. Vape migas chillwave sriracha poutine try-hard distillery. Tattooed shabby chic small batch, pabst art party heirloom letterpress air plant pop-up. Sustainable chia skateboard art party banjo cardigan normcore affogato vexillologist quinoa meggings man bun master cleanse shoreditch readymade. Yuccie prism four dollar toast tbh cardigan iPhone, tumblr listicle live-edge VHS. Pug lyft normcore hot chicken biodiesel, actually keffiyeh thundercats photo booth pour-over twee fam food truck microdosing banh mi. Vice activated charcoal raclette unicorn live-edge post-ironic. Heirloom vexillologist coloring book, beard deep v letterpress echo park humblebrag tilde.

90’s four loko seitan photo booth gochujang freegan tumeric listicle fam ugh humblebrag. Bespoke leggings gastropub, biodiesel brunch pug fashion axe meh swag art party neutra deep v chia. Enamel pin fanny pack knausgaard tofu, artisan cronut hammock meditation occupy master cleanse chartreuse lumbersexual. Kombucha kogi viral truffaut synth distillery single-origin coffee ugh slow-carb marfa selfies. Pitchfork schlitz semiotics fanny pack, ugh artisan vegan vaporware hexagon. Polaroid fixie post-ironic venmo wolf ramps kale chips.

There should be no margin above this first sentence.

Blockquotes should be a lighter gray with a border along the left side in the secondary color.

There should be no margin below this final sentence.

First Header 2

This is a normal paragraph following a header. Knausgaard kale chips snackwave microdosing cronut copper mug swag synth bitters letterpress glossier craft beer. Mumblecore bushwick authentic gochujang vegan chambray meditation jean shorts irony. Viral farm-to-table kale chips, pork belly palo santo distillery activated charcoal aesthetic jianbing air plant woke lomo VHS organic. Tattooed locavore succulents heirloom, small batch sriracha echo park DIY af. Shaman you probably haven’t heard of them copper mug, crucifix green juice vape single-origin coffee brunch actually. Mustache etsy vexillologist raclette authentic fam. Tousled beard humblebrag asymmetrical. I love turkey, I love my job, I love my friends, I love Chardonnay!

Deae legum paulatimque terra, non vos mutata tacet: dic. Vocant docuique me plumas fila quin afuerunt copia haec o neque.

On big screens, paragraphs and headings should not take up the full container width, but we want tables, code blocks and similar to take the full width.

Scenester tumeric pickled, authentic crucifix post-ironic fam freegan VHS pork belly 8-bit yuccie PBR&B. I love this life we live in.

Second Header 2

This is a blockquote following a header. Bacon ipsum dolor sit amet t-bone doner shank drumstick, pork belly porchetta chuck sausage brisket ham hock rump pig. Chuck kielbasa leberkas, pork bresaola ham hock filet mignon cow shoulder short ribs biltong.

Header 3

This is a code block following a header.

Next level leggings before they sold out, PBR&B church-key shaman echo park. Kale chips occupy godard whatever pop-up freegan pork belly selfies. Gastropub Belinda subway tile woke post-ironic seitan. Shabby chic man bun semiotics vape, chia messenger bag plaid cardigan.

Header 4

  • This is an unordered list following a header.
  • This is an unordered list following a header.
  • This is an unordered list following a header.
Header 5
  1. This is an ordered list following a header.
  2. This is an ordered list following a header.
  3. This is an ordered list following a header.
Header 6
WhatFollows
A tableA header
A tableA header
A tableA header

There’s a horizontal rule above and below this.


Here is an unordered list:

  • Liverpool F.C.
  • Chelsea F.C.
  • Manchester United F.C.

And an ordered list:

  1. Michael Brecker
  2. Seamus Blake
  3. Branford Marsalis

And an unordered task list:

  • Create a Hugo theme
  • Add task lists to it
  • Take a vacation

And a “mixed” task list:

  • Pack bags
  • ?
  • Travel!

And a nested list:

  • Jackson 5
    • Michael
    • Tito
    • Jackie
    • Marlon
    • Jermaine
  • TMNT
    • Leonardo
    • Michelangelo
    • Donatello
    • Raphael

Definition lists can be used with Markdown syntax. Definition headers are bold.

Name
Godzilla
Born
1952
Birthplace
Japan
Color
Green

Tables should have bold headings and alternating shaded rows.

ArtistAlbumYear
Michael JacksonThriller1982
PrincePurple Rain1984
Beastie BoysLicense to Ill1986

If a table is too wide, it should scroll horizontally.

ArtistAlbumYearLabelAwardsSongs
Michael JacksonThriller1982Epic RecordsGrammy Award for Album of the Year, American Music Award for Favorite Pop/Rock Album, American Music Award for Favorite Soul/R&B Album, Brit Award for Best Selling Album, Grammy Award for Best Engineered Album, Non-ClassicalWanna Be Startin’ Somethin’, Baby Be Mine, The Girl Is Mine, Thriller, Beat It, Billie Jean, Human Nature, P.Y.T. (Pretty Young Thing), The Lady in My Life
PrincePurple Rain1984Warner Brothers RecordsGrammy Award for Best Score Soundtrack for Visual Media, American Music Award for Favorite Pop/Rock Album, American Music Award for Favorite Soul/R&B Album, Brit Award for Best Soundtrack/Cast Recording, Grammy Award for Best Rock Performance by a Duo or Group with VocalLet’s Go Crazy, Take Me With U, The Beautiful Ones, Computer Blue, Darling Nikki, When Doves Cry, I Would Die 4 U, Baby I’m a Star, Purple Rain
Beastie BoysLicense to Ill1986Mercury RecordsnoawardsbutthistablecelliswideRhymin & Stealin, The New Style, She’s Crafty, Posse in Effect, Slow Ride, Girls, (You Gotta) Fight for Your Right, No Sleep Till Brooklyn, Paul Revere, Hold It Now, Hit It, Brass Monkey, Slow and Low, Time to Get Ill

Code snippets like var foo = "bar"; can be shown inline.

Also, this should vertically align with this and this.

Code can also be shown in a block element.

foo := "bar";
bar := "foo";

Code can also use syntax highlighting.

func main() {
  input := `var foo = "bar";`

  lexer := lexers.Get("javascript")
  iterator, _ := lexer.Tokenise(nil, input)
  style := styles.Get("github")
  formatter := html.New(html.WithLineNumbers())

  var buff bytes.Buffer
  formatter.Format(&buff, style, iterator)

  fmt.Println(buff.String())
}
Long, single-line code blocks should not wrap. They should horizontally scroll if they are too long. This line should be long enough to demonstrate this.

Inline code inside table cells should still be distinguishable.

LanguageCode
Javascriptvar foo = "bar";
Rubyfoo = "bar"{

Small images should be shown at their actual size.

Large images should always scale down and fit in the content container.

The photo above of the Spruce Picea abies shoot with foliage buds: Bjørn Erik Pedersen, CC-BY-SA.

Components

Alerts

Another Heading

Add some sections here to see how the ToC looks like. Bacon ipsum dolor sit amet t-bone doner shank drumstick, pork belly porchetta chuck sausage brisket ham hock rump pig. Chuck kielbasa leberkas, pork bresaola ham hock filet mignon cow shoulder short ribs biltong.

This Document

Inguina genus: Anaphen post: lingua violente voce suae meus aetate diversi. Orbis unam nec flammaeque status deam Silenum erat et a ferrea. Excitus rigidum ait: vestro et Herculis convicia: nitidae deseruit coniuge Proteaque adiciam eripitur? Sitim noceat signa probat quidem. Sua longis fugatis quidem genae.

Pixel Count

Tilde photo booth wayfarers cliche lomo intelligentsia man braid kombucha vaporware farm-to-table mixtape portland. PBR&B pickled cornhole ugh try-hard ethical subway tile. Fixie paleo intelligentsia pabst. Ennui waistcoat vinyl gochujang. Poutine salvia authentic affogato, chambray lumbersexual shabby chic.

Contact Info

Plaid hell of cred microdosing, succulents tilde pour-over. Offal shabby chic 3 wolf moon blue bottle raw denim normcore poutine pork belly.

Stumptown PBR&B keytar plaid street art, forage XOXO pitchfork selvage affogato green juice listicle pickled everyday carry hashtag. Organic sustainable letterpress sartorial scenester intelligentsia swag bushwick. Put a bird on it stumptown neutra locavore. IPhone typewriter messenger bag narwhal. Ennui cold-pressed seitan flannel keytar, single-origin coffee adaptogen occupy yuccie williamsburg chillwave shoreditch forage waistcoat.

This is the final element on the page and there should be no margin below this.

5.4 - SDK管理实践

SDK管理与实践经验.

Capa采用SDK模型,相比于Sidecar模型将带来很多问题:

  • 依赖版本冲突管理
  • SDK升级推动
  • …………….

本章主要介绍Capa在SDK实践中,遇到的一些问题以及相关的解决思路。

5.4.1 - SDK-Java管理实践

SDK Java管理与实践经验.

Java SDK主要使用Maven进行管理,故以下内容主要基于Maven进行实践。

动态加载不同的SDK实现包

根据Capa设计,接入层面向API层的SDK进行编程,然后在运行时动态调用不同的实现层SDK。

实现包如何加载到运行时空间?

思路一:打包时包含了所有实现层SDK,运行时仅加载对应的实现包。

问题:

若包含所有的实现层SDK,则面对依赖冲突的可能性大增。

有的实现层SDK在初始化时执行了操作,若将A云的实现层jar打包到B云的包中,可能有未知的问题出现。

综上,不使用该方案。

思路二:将不同云的实现,打包成不同的包/镜像。

基于Maven提供的profile机制,可以将不同云的实现打包到不同的包中,最终生成不同的镜像。

可以避免不同云SDK之间的冲突,以及可以针对性的添加个性化的配置。

具体实现主要有以下思路:

1. 使用maven插件自动化该步骤

但动态修改 pom 文件本身并不推荐。

maven 官方建议直接指定需要的依赖:

  • 可以更方便的解决依赖冲突的问题
  • 为项目提供了更容易阅读的文档,只需要阅读项目中的 pom 文件或者执行 mvn dependency: tree 即可了解更多信息

综上,不使用该方案。

2. 手动指定profile

面对的问题:

  • 接入方需要编写额外的pom内容。
  • 需要生成不同的包/镜像,需要改动原有的CI流程。
  • profile在查看依赖冲突等问题时,IDE支持的不如直接引用的方式。

但以上问题,提高了复杂度,但减少了面对未知问题的可能性,更有利于生产的稳定性。

所以使用该种方式。


实现包加载到运行时空间实践


依赖冲突管理

本文介绍在SDK-Java中的依赖管理实践经验。

Maven依赖管理

依赖版本传递

因为有了依赖传递,我们就不需要考虑依赖的依赖如何管理了,maven都会把他们加载进来,但是这么多依赖都进来到底用哪个,会不会冲突呢?

maven在解析pom时,会使用依赖调解,具体原则有:

  1. 第一原则 路径最近者优先

    A -> B -> X(1.0) A -> C -> D -> X(2.0)

X(1.0) 路径长度为2,X(2.0)路径长度3,所以 X(1.0) 会被真正的使用

  1. 第二原则 第一声明者优先

    A -> B -> X(1.0) A -> C -> X(2.0)

这次X(1.0) X(2.0)路径长度相同了,因为B比C声明的早,所以取B依赖的X(1.0)版本

scope的分类

compile

默认就是compile,什么都不配置也就是意味着compile。compile表示被依赖项目需要参与当前项目的编译,当然后续的测试,运行周期也参与其中,是一个比较强的依赖。打包的时候通常需要包含进去。

test

scope为test表示依赖项目仅仅参与测试相关的工作,包括测试代码的编译,执行。比较典型的如junit。

runtime

runntime表示被依赖项目无需参与项目的编译,不过后期的测试和运行周期需要其参与。与compile相比,跳过编译而已,说实话在终端的项目(非开源,企业内部系统)中,和compile区别不是很大。比较常见的如JSR×××的实现,对应的API jar是compile的,具体实现是runtime的,compile只需要知道接口就足够了。oracle jdbc驱动架包就是一个很好的例子,一般scope为runntime。另外runntime的依赖通常和optional搭配使用,optional为true。我可以用A实现,也可以用B实现。

provided

provided意味着打包的时候可以不用包进去,别的设施(Web Container)会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。相当于compile,但是在打包阶段做了exclude的动作。

scope使用provided,表示用于当前项目编译使用,不向下传递。

system

从参与度来说,也provided相同,不过被依赖项不会从maven仓库抓,而是从本地文件系统拿,一定需要配合systemPath属性使用。

总结

  • compile: 默认配置适用于所有阶段,会随着项目一起发布。
  • runtime: 只在运行时使用,如JDBC驱动
  • provided: 期望JDK、容器或使用者会提供这个依赖。如 servlet.jar需要tomcat来提供
  • test:只在测试时使用,用于编译和运行测试代码。不会随 项目发布, 比如junit
  • import: 用来导入依赖, 比如tcdev

scope的依赖传递

A–>B–>C。当前项目为A,A依赖于B,B依赖于C。知道B在A项目中的scope,那么怎么知道C在A中的scope呢?答案是:

  • 当C是test或者provided时,C直接被丢弃,A不依赖C;
  • 否则A依赖C,C的scope继承于B的scope。

5.5 - Working with Ponycopters

A short lead description about this section page. Text here can also be bold or italic and can even be split over multiple paragraphs.

This is a placeholder page. Replace it with your own content.

This is the section landing page.

5.5.1 - Configuring Ponycopters

A short lead description about this content page. It can be bold or italic and can be split over multiple paragraphs.

This is a placeholder page. Replace it with your own content.

Text can be bold, italic, or strikethrough. Links should be blue with no underlines (unless hovered over).

There should be whitespace between paragraphs. Vape migas chillwave sriracha poutine try-hard distillery. Tattooed shabby chic small batch, pabst art party heirloom letterpress air plant pop-up. Sustainable chia skateboard art party banjo cardigan normcore affogato vexillologist quinoa meggings man bun master cleanse shoreditch readymade. Yuccie prism four dollar toast tbh cardigan iPhone, tumblr listicle live-edge VHS. Pug lyft normcore hot chicken biodiesel, actually keffiyeh thundercats photo booth pour-over twee fam food truck microdosing banh mi. Vice activated charcoal raclette unicorn live-edge post-ironic. Heirloom vexillologist coloring book, beard deep v letterpress echo park humblebrag tilde.

90’s four loko seitan photo booth gochujang freegan tumeric listicle fam ugh humblebrag. Bespoke leggings gastropub, biodiesel brunch pug fashion axe meh swag art party neutra deep v chia. Enamel pin fanny pack knausgaard tofu, artisan cronut hammock meditation occupy master cleanse chartreuse lumbersexual. Kombucha kogi viral truffaut synth distillery single-origin coffee ugh slow-carb marfa selfies. Pitchfork schlitz semiotics fanny pack, ugh artisan vegan vaporware hexagon. Polaroid fixie post-ironic venmo wolf ramps kale chips.

There should be no margin above this first sentence.

Blockquotes should be a lighter gray with a border along the left side in the secondary color.

There should be no margin below this final sentence.

First Header 2

This is a normal paragraph following a header. Knausgaard kale chips snackwave microdosing cronut copper mug swag synth bitters letterpress glossier craft beer. Mumblecore bushwick authentic gochujang vegan chambray meditation jean shorts irony. Viral farm-to-table kale chips, pork belly palo santo distillery activated charcoal aesthetic jianbing air plant woke lomo VHS organic. Tattooed locavore succulents heirloom, small batch sriracha echo park DIY af. Shaman you probably haven’t heard of them copper mug, crucifix green juice vape single-origin coffee brunch actually. Mustache etsy vexillologist raclette authentic fam. Tousled beard humblebrag asymmetrical. I love turkey, I love my job, I love my friends, I love Chardonnay!

Deae legum paulatimque terra, non vos mutata tacet: dic. Vocant docuique me plumas fila quin afuerunt copia haec o neque.

On big screens, paragraphs and headings should not take up the full container width, but we want tables, code blocks and similar to take the full width.

Scenester tumeric pickled, authentic crucifix post-ironic fam freegan VHS pork belly 8-bit yuccie PBR&B. I love this life we live in.

Second Header 2

This is a blockquote following a header. Bacon ipsum dolor sit amet t-bone doner shank drumstick, pork belly porchetta chuck sausage brisket ham hock rump pig. Chuck kielbasa leberkas, pork bresaola ham hock filet mignon cow shoulder short ribs biltong.

Header 3

This is a code block following a header.

Next level leggings before they sold out, PBR&B church-key shaman echo park. Kale chips occupy godard whatever pop-up freegan pork belly selfies. Gastropub Belinda subway tile woke post-ironic seitan. Shabby chic man bun semiotics vape, chia messenger bag plaid cardigan.

Header 4

  • This is an unordered list following a header.
  • This is an unordered list following a header.
  • This is an unordered list following a header.
Header 5
  1. This is an ordered list following a header.
  2. This is an ordered list following a header.
  3. This is an ordered list following a header.
Header 6
WhatFollows
A tableA header
A tableA header
A tableA header

There’s a horizontal rule above and below this.


Here is an unordered list:

  • Liverpool F.C.
  • Chelsea F.C.
  • Manchester United F.C.

And an ordered list:

  1. Michael Brecker
  2. Seamus Blake
  3. Branford Marsalis

And an unordered task list:

  • Create a Hugo theme
  • Add task lists to it
  • Take a vacation

And a “mixed” task list:

  • Pack bags
  • ?
  • Travel!

And a nested list:

  • Jackson 5
    • Michael
    • Tito
    • Jackie
    • Marlon
    • Jermaine
  • TMNT
    • Leonardo
    • Michelangelo
    • Donatello
    • Raphael

Definition lists can be used with Markdown syntax. Definition headers are bold.

Name
Godzilla
Born
1952
Birthplace
Japan
Color
Green

Tables should have bold headings and alternating shaded rows.

ArtistAlbumYear
Michael JacksonThriller1982
PrincePurple Rain1984
Beastie BoysLicense to Ill1986

If a table is too wide, it should scroll horizontally.

ArtistAlbumYearLabelAwardsSongs
Michael JacksonThriller1982Epic RecordsGrammy Award for Album of the Year, American Music Award for Favorite Pop/Rock Album, American Music Award for Favorite Soul/R&B Album, Brit Award for Best Selling Album, Grammy Award for Best Engineered Album, Non-ClassicalWanna Be Startin’ Somethin’, Baby Be Mine, The Girl Is Mine, Thriller, Beat It, Billie Jean, Human Nature, P.Y.T. (Pretty Young Thing), The Lady in My Life
PrincePurple Rain1984Warner Brothers RecordsGrammy Award for Best Score Soundtrack for Visual Media, American Music Award for Favorite Pop/Rock Album, American Music Award for Favorite Soul/R&B Album, Brit Award for Best Soundtrack/Cast Recording, Grammy Award for Best Rock Performance by a Duo or Group with VocalLet’s Go Crazy, Take Me With U, The Beautiful Ones, Computer Blue, Darling Nikki, When Doves Cry, I Would Die 4 U, Baby I’m a Star, Purple Rain
Beastie BoysLicense to Ill1986Mercury RecordsnoawardsbutthistablecelliswideRhymin & Stealin, The New Style, She’s Crafty, Posse in Effect, Slow Ride, Girls, (You Gotta) Fight for Your Right, No Sleep Till Brooklyn, Paul Revere, Hold It Now, Hit It, Brass Monkey, Slow and Low, Time to Get Ill

Code snippets like var foo = "bar"; can be shown inline.

Also, this should vertically align with this and this.

Code can also be shown in a block element.

foo := "bar";
bar := "foo";

Code can also use syntax highlighting.

func main() {
  input := `var foo = "bar";`

  lexer := lexers.Get("javascript")
  iterator, _ := lexer.Tokenise(nil, input)
  style := styles.Get("github")
  formatter := html.New(html.WithLineNumbers())

  var buff bytes.Buffer
  formatter.Format(&buff, style, iterator)

  fmt.Println(buff.String())
}
Long, single-line code blocks should not wrap. They should horizontally scroll if they are too long. This line should be long enough to demonstrate this.

Inline code inside table cells should still be distinguishable.

LanguageCode
Javascriptvar foo = "bar";
Rubyfoo = "bar"{

Small images should be shown at their actual size.

Large images should always scale down and fit in the content container.

The photo above of the Spruce Picea abies shoot with foliage buds: Bjørn Erik Pedersen, CC-BY-SA.

Components

Alerts

Another Heading

Add some sections here to see how the ToC looks like. Bacon ipsum dolor sit amet t-bone doner shank drumstick, pork belly porchetta chuck sausage brisket ham hock rump pig. Chuck kielbasa leberkas, pork bresaola ham hock filet mignon cow shoulder short ribs biltong.

This Document

Inguina genus: Anaphen post: lingua violente voce suae meus aetate diversi. Orbis unam nec flammaeque status deam Silenum erat et a ferrea. Excitus rigidum ait: vestro et Herculis convicia: nitidae deseruit coniuge Proteaque adiciam eripitur? Sitim noceat signa probat quidem. Sua longis fugatis quidem genae.

Pixel Count

Tilde photo booth wayfarers cliche lomo intelligentsia man braid kombucha vaporware farm-to-table mixtape portland. PBR&B pickled cornhole ugh try-hard ethical subway tile. Fixie paleo intelligentsia pabst. Ennui waistcoat vinyl gochujang. Poutine salvia authentic affogato, chambray lumbersexual shabby chic.

Contact Info

Plaid hell of cred microdosing, succulents tilde pour-over. Offal shabby chic 3 wolf moon blue bottle raw denim normcore poutine pork belly.

Stumptown PBR&B keytar plaid street art, forage XOXO pitchfork selvage affogato green juice listicle pickled everyday carry hashtag. Organic sustainable letterpress sartorial scenester intelligentsia swag bushwick. Put a bird on it stumptown neutra locavore. IPhone typewriter messenger bag narwhal. Ennui cold-pressed seitan flannel keytar, single-origin coffee adaptogen occupy yuccie williamsburg chillwave shoreditch forage waistcoat.

This is the final element on the page and there should be no margin below this.

5.5.2 - Launching Ponycopters

A short lead description about this content page. It can be bold or italic and can be split over multiple paragraphs.

This is a placeholder page. Replace it with your own content.

Text can be bold, italic, or strikethrough. Links should be blue with no underlines (unless hovered over).

There should be whitespace between paragraphs. Vape migas chillwave sriracha poutine try-hard distillery. Tattooed shabby chic small batch, pabst art party heirloom letterpress air plant pop-up. Sustainable chia skateboard art party banjo cardigan normcore affogato vexillologist quinoa meggings man bun master cleanse shoreditch readymade. Yuccie prism four dollar toast tbh cardigan iPhone, tumblr listicle live-edge VHS. Pug lyft normcore hot chicken biodiesel, actually keffiyeh thundercats photo booth pour-over twee fam food truck microdosing banh mi. Vice activated charcoal raclette unicorn live-edge post-ironic. Heirloom vexillologist coloring book, beard deep v letterpress echo park humblebrag tilde.

90’s four loko seitan photo booth gochujang freegan tumeric listicle fam ugh humblebrag. Bespoke leggings gastropub, biodiesel brunch pug fashion axe meh swag art party neutra deep v chia. Enamel pin fanny pack knausgaard tofu, artisan cronut hammock meditation occupy master cleanse chartreuse lumbersexual. Kombucha kogi viral truffaut synth distillery single-origin coffee ugh slow-carb marfa selfies. Pitchfork schlitz semiotics fanny pack, ugh artisan vegan vaporware hexagon. Polaroid fixie post-ironic venmo wolf ramps kale chips.

There should be no margin above this first sentence.

Blockquotes should be a lighter gray with a border along the left side in the secondary color.

There should be no margin below this final sentence.

First Header 2

This is a normal paragraph following a header. Knausgaard kale chips snackwave microdosing cronut copper mug swag synth bitters letterpress glossier craft beer. Mumblecore bushwick authentic gochujang vegan chambray meditation jean shorts irony. Viral farm-to-table kale chips, pork belly palo santo distillery activated charcoal aesthetic jianbing air plant woke lomo VHS organic. Tattooed locavore succulents heirloom, small batch sriracha echo park DIY af. Shaman you probably haven’t heard of them copper mug, crucifix green juice vape single-origin coffee brunch actually. Mustache etsy vexillologist raclette authentic fam. Tousled beard humblebrag asymmetrical. I love turkey, I love my job, I love my friends, I love Chardonnay!

Deae legum paulatimque terra, non vos mutata tacet: dic. Vocant docuique me plumas fila quin afuerunt copia haec o neque.

On big screens, paragraphs and headings should not take up the full container width, but we want tables, code blocks and similar to take the full width.

Scenester tumeric pickled, authentic crucifix post-ironic fam freegan VHS pork belly 8-bit yuccie PBR&B. I love this life we live in.

Second Header 2

This is a blockquote following a header. Bacon ipsum dolor sit amet t-bone doner shank drumstick, pork belly porchetta chuck sausage brisket ham hock rump pig. Chuck kielbasa leberkas, pork bresaola ham hock filet mignon cow shoulder short ribs biltong.

Header 3

This is a code block following a header.

Next level leggings before they sold out, PBR&B church-key shaman echo park. Kale chips occupy godard whatever pop-up freegan pork belly selfies. Gastropub Belinda subway tile woke post-ironic seitan. Shabby chic man bun semiotics vape, chia messenger bag plaid cardigan.

Header 4

  • This is an unordered list following a header.
  • This is an unordered list following a header.
  • This is an unordered list following a header.
Header 5
  1. This is an ordered list following a header.
  2. This is an ordered list following a header.
  3. This is an ordered list following a header.
Header 6
WhatFollows
A tableA header
A tableA header
A tableA header

There’s a horizontal rule above and below this.


Here is an unordered list:

  • Liverpool F.C.
  • Chelsea F.C.
  • Manchester United F.C.

And an ordered list:

  1. Michael Brecker
  2. Seamus Blake
  3. Branford Marsalis

And an unordered task list:

  • Create a Hugo theme
  • Add task lists to it
  • Take a vacation

And a “mixed” task list:

  • Pack bags
  • ?
  • Travel!

And a nested list:

  • Jackson 5
    • Michael
    • Tito
    • Jackie
    • Marlon
    • Jermaine
  • TMNT
    • Leonardo
    • Michelangelo
    • Donatello
    • Raphael

Definition lists can be used with Markdown syntax. Definition headers are bold.

Name
Godzilla
Born
1952
Birthplace
Japan
Color
Green

Tables should have bold headings and alternating shaded rows.

ArtistAlbumYear
Michael JacksonThriller1982
PrincePurple Rain1984
Beastie BoysLicense to Ill1986

If a table is too wide, it should scroll horizontally.

ArtistAlbumYearLabelAwardsSongs
Michael JacksonThriller1982Epic RecordsGrammy Award for Album of the Year, American Music Award for Favorite Pop/Rock Album, American Music Award for Favorite Soul/R&B Album, Brit Award for Best Selling Album, Grammy Award for Best Engineered Album, Non-ClassicalWanna Be Startin’ Somethin’, Baby Be Mine, The Girl Is Mine, Thriller, Beat It, Billie Jean, Human Nature, P.Y.T. (Pretty Young Thing), The Lady in My Life
PrincePurple Rain1984Warner Brothers RecordsGrammy Award for Best Score Soundtrack for Visual Media, American Music Award for Favorite Pop/Rock Album, American Music Award for Favorite Soul/R&B Album, Brit Award for Best Soundtrack/Cast Recording, Grammy Award for Best Rock Performance by a Duo or Group with VocalLet’s Go Crazy, Take Me With U, The Beautiful Ones, Computer Blue, Darling Nikki, When Doves Cry, I Would Die 4 U, Baby I’m a Star, Purple Rain
Beastie BoysLicense to Ill1986Mercury RecordsnoawardsbutthistablecelliswideRhymin & Stealin, The New Style, She’s Crafty, Posse in Effect, Slow Ride, Girls, (You Gotta) Fight for Your Right, No Sleep Till Brooklyn, Paul Revere, Hold It Now, Hit It, Brass Monkey, Slow and Low, Time to Get Ill

Code snippets like var foo = "bar"; can be shown inline.

Also, this should vertically align with this and this.

Code can also be shown in a block element.

foo := "bar";
bar := "foo";

Code can also use syntax highlighting.

func main() {
  input := `var foo = "bar";`

  lexer := lexers.Get("javascript")
  iterator, _ := lexer.Tokenise(nil, input)
  style := styles.Get("github")
  formatter := html.New(html.WithLineNumbers())

  var buff bytes.Buffer
  formatter.Format(&buff, style, iterator)

  fmt.Println(buff.String())
}
Long, single-line code blocks should not wrap. They should horizontally scroll if they are too long. This line should be long enough to demonstrate this.

Inline code inside table cells should still be distinguishable.

LanguageCode
Javascriptvar foo = "bar";
Rubyfoo = "bar"{

Small images should be shown at their actual size.

Large images should always scale down and fit in the content container.

The photo above of the Spruce Picea abies shoot with foliage buds: Bjørn Erik Pedersen, CC-BY-SA.

Components

Alerts

Another Heading

Add some sections here to see how the ToC looks like. Bacon ipsum dolor sit amet t-bone doner shank drumstick, pork belly porchetta chuck sausage brisket ham hock rump pig. Chuck kielbasa leberkas, pork bresaola ham hock filet mignon cow shoulder short ribs biltong.

This Document

Inguina genus: Anaphen post: lingua violente voce suae meus aetate diversi. Orbis unam nec flammaeque status deam Silenum erat et a ferrea. Excitus rigidum ait: vestro et Herculis convicia: nitidae deseruit coniuge Proteaque adiciam eripitur? Sitim noceat signa probat quidem. Sua longis fugatis quidem genae.

Pixel Count

Tilde photo booth wayfarers cliche lomo intelligentsia man braid kombucha vaporware farm-to-table mixtape portland. PBR&B pickled cornhole ugh try-hard ethical subway tile. Fixie paleo intelligentsia pabst. Ennui waistcoat vinyl gochujang. Poutine salvia authentic affogato, chambray lumbersexual shabby chic.

Contact Info

Plaid hell of cred microdosing, succulents tilde pour-over. Offal shabby chic 3 wolf moon blue bottle raw denim normcore poutine pork belly.

Stumptown PBR&B keytar plaid street art, forage XOXO pitchfork selvage affogato green juice listicle pickled everyday carry hashtag. Organic sustainable letterpress sartorial scenester intelligentsia swag bushwick. Put a bird on it stumptown neutra locavore. IPhone typewriter messenger bag narwhal. Ennui cold-pressed seitan flannel keytar, single-origin coffee adaptogen occupy yuccie williamsburg chillwave shoreditch forage waistcoat.

This is the final element on the page and there should be no margin below this.

6 - 参考手册

Capa SDK API参考文档

本节包含 Capa SDK 组件的 API 参考文档。

API 文档

Capa 为云应用开发提供统一的 API 层。以下参考文档可用:

核心 API

  • Service Invocation (RPC) - HTTP/gRPC 服务间通信
  • Configuration - 动态配置管理
  • Pub/Sub - 发布订阅消息
  • State Management - 键值状态存储
  • Telemetry - 日志、指标和分布式追踪

API 规范

Capa API 规范遵循社区标准,定义在 cloud-runtimes-jvm 仓库中。

6.1 - Parameter Reference

A short lead description about this content page. It can be bold or italic and can be split over multiple paragraphs.

This is a placeholder page. Replace it with your own content.

Text can be bold, italic, or strikethrough. Links should be blue with no underlines (unless hovered over).

There should be whitespace between paragraphs. Vape migas chillwave sriracha poutine try-hard distillery. Tattooed shabby chic small batch, pabst art party heirloom letterpress air plant pop-up. Sustainable chia skateboard art party banjo cardigan normcore affogato vexillologist quinoa meggings man bun master cleanse shoreditch readymade. Yuccie prism four dollar toast tbh cardigan iPhone, tumblr listicle live-edge VHS. Pug lyft normcore hot chicken biodiesel, actually keffiyeh thundercats photo booth pour-over twee fam food truck microdosing banh mi. Vice activated charcoal raclette unicorn live-edge post-ironic. Heirloom vexillologist coloring book, beard deep v letterpress echo park humblebrag tilde.

90’s four loko seitan photo booth gochujang freegan tumeric listicle fam ugh humblebrag. Bespoke leggings gastropub, biodiesel brunch pug fashion axe meh swag art party neutra deep v chia. Enamel pin fanny pack knausgaard tofu, artisan cronut hammock meditation occupy master cleanse chartreuse lumbersexual. Kombucha kogi viral truffaut synth distillery single-origin coffee ugh slow-carb marfa selfies. Pitchfork schlitz semiotics fanny pack, ugh artisan vegan vaporware hexagon. Polaroid fixie post-ironic venmo wolf ramps kale chips.

There should be no margin above this first sentence.

Blockquotes should be a lighter gray with a border along the left side in the secondary color.

There should be no margin below this final sentence.

First Header 2

This is a normal paragraph following a header. Knausgaard kale chips snackwave microdosing cronut copper mug swag synth bitters letterpress glossier craft beer. Mumblecore bushwick authentic gochujang vegan chambray meditation jean shorts irony. Viral farm-to-table kale chips, pork belly palo santo distillery activated charcoal aesthetic jianbing air plant woke lomo VHS organic. Tattooed locavore succulents heirloom, small batch sriracha echo park DIY af. Shaman you probably haven’t heard of them copper mug, crucifix green juice vape single-origin coffee brunch actually. Mustache etsy vexillologist raclette authentic fam. Tousled beard humblebrag asymmetrical. I love turkey, I love my job, I love my friends, I love Chardonnay!

Deae legum paulatimque terra, non vos mutata tacet: dic. Vocant docuique me plumas fila quin afuerunt copia haec o neque.

On big screens, paragraphs and headings should not take up the full container width, but we want tables, code blocks and similar to take the full width.

Scenester tumeric pickled, authentic crucifix post-ironic fam freegan VHS pork belly 8-bit yuccie PBR&B. I love this life we live in.

Second Header 2

This is a blockquote following a header. Bacon ipsum dolor sit amet t-bone doner shank drumstick, pork belly porchetta chuck sausage brisket ham hock rump pig. Chuck kielbasa leberkas, pork bresaola ham hock filet mignon cow shoulder short ribs biltong.

Header 3

This is a code block following a header.

Next level leggings before they sold out, PBR&B church-key shaman echo park. Kale chips occupy godard whatever pop-up freegan pork belly selfies. Gastropub Belinda subway tile woke post-ironic seitan. Shabby chic man bun semiotics vape, chia messenger bag plaid cardigan.

Header 4

  • This is an unordered list following a header.
  • This is an unordered list following a header.
  • This is an unordered list following a header.
Header 5
  1. This is an ordered list following a header.
  2. This is an ordered list following a header.
  3. This is an ordered list following a header.
Header 6
WhatFollows
A tableA header
A tableA header
A tableA header

There’s a horizontal rule above and below this.


Here is an unordered list:

  • Liverpool F.C.
  • Chelsea F.C.
  • Manchester United F.C.

And an ordered list:

  1. Michael Brecker
  2. Seamus Blake
  3. Branford Marsalis

And an unordered task list:

  • Create a Hugo theme
  • Add task lists to it
  • Take a vacation

And a “mixed” task list:

  • Pack bags
  • ?
  • Travel!

And a nested list:

  • Jackson 5
    • Michael
    • Tito
    • Jackie
    • Marlon
    • Jermaine
  • TMNT
    • Leonardo
    • Michelangelo
    • Donatello
    • Raphael

Definition lists can be used with Markdown syntax. Definition headers are bold.

Name
Godzilla
Born
1952
Birthplace
Japan
Color
Green

Tables should have bold headings and alternating shaded rows.

ArtistAlbumYear
Michael JacksonThriller1982
PrincePurple Rain1984
Beastie BoysLicense to Ill1986

If a table is too wide, it should scroll horizontally.

ArtistAlbumYearLabelAwardsSongs
Michael JacksonThriller1982Epic RecordsGrammy Award for Album of the Year, American Music Award for Favorite Pop/Rock Album, American Music Award for Favorite Soul/R&B Album, Brit Award for Best Selling Album, Grammy Award for Best Engineered Album, Non-ClassicalWanna Be Startin’ Somethin’, Baby Be Mine, The Girl Is Mine, Thriller, Beat It, Billie Jean, Human Nature, P.Y.T. (Pretty Young Thing), The Lady in My Life
PrincePurple Rain1984Warner Brothers RecordsGrammy Award for Best Score Soundtrack for Visual Media, American Music Award for Favorite Pop/Rock Album, American Music Award for Favorite Soul/R&B Album, Brit Award for Best Soundtrack/Cast Recording, Grammy Award for Best Rock Performance by a Duo or Group with VocalLet’s Go Crazy, Take Me With U, The Beautiful Ones, Computer Blue, Darling Nikki, When Doves Cry, I Would Die 4 U, Baby I’m a Star, Purple Rain
Beastie BoysLicense to Ill1986Mercury RecordsnoawardsbutthistablecelliswideRhymin & Stealin, The New Style, She’s Crafty, Posse in Effect, Slow Ride, Girls, (You Gotta) Fight for Your Right, No Sleep Till Brooklyn, Paul Revere, Hold It Now, Hit It, Brass Monkey, Slow and Low, Time to Get Ill

Code snippets like var foo = "bar"; can be shown inline.

Also, this should vertically align with this and this.

Code can also be shown in a block element.

foo := "bar";
bar := "foo";

Code can also use syntax highlighting.

func main() {
  input := `var foo = "bar";`

  lexer := lexers.Get("javascript")
  iterator, _ := lexer.Tokenise(nil, input)
  style := styles.Get("github")
  formatter := html.New(html.WithLineNumbers())

  var buff bytes.Buffer
  formatter.Format(&buff, style, iterator)

  fmt.Println(buff.String())
}
Long, single-line code blocks should not wrap. They should horizontally scroll if they are too long. This line should be long enough to demonstrate this.

Inline code inside table cells should still be distinguishable.

LanguageCode
Javascriptvar foo = "bar";
Rubyfoo = "bar"{

Small images should be shown at their actual size.

Large images should always scale down and fit in the content container.

The photo above of the Spruce Picea abies shoot with foliage buds: Bjørn Erik Pedersen, CC-BY-SA.

Components

Alerts

Another Heading

7 - 参与贡献

如何参与贡献

感谢您对Capa的支持!

7.1 - 贡献者指南

为任何Capa项目资源库做出贡献的通用指南

Capa 基于 Apache 2.0 许可发布,遵循标准的 Github 开发流程。 本文档描述了如何使用 Github Issue 和 Pull Request 对Capa做出贡献。

Issues 约定

  1. Question: 提出一个关于 Capa 的问题
  2. Feature Request: 提出一个关于 Capa 新功能的请求
  3. Bug Report: 提出一个 Bug 的报告
  4. Discussion: 对 Capa 的讨论
  5. Proposal: 对 Capa 的提案

编码规范约定

  1. 提交的代码一律要添加 Apache License(可以通过checkstyle插件来检测)
  2. 每次只允许提交一个 Commit,如果有多个在本地 Rebase 成一个 Commit
  3. 建议一个 Commit 只解决一个 Issue
  4. Commit 中要有详细的说明,且一律使用英文来描述
  5. CI Pipeline 构建失败的代码不会进入 Code Review 环节
  6. 代码仓库有且仅有一个主干分支(master分支)
  7. 主干分支上的代码只能通过 Merge PR(MR)向前推进
  8. 所有实现的 Feature 都要有完善使用说明文档
  9. 仅在 UT 中引用到的 Package 的 Scope 必须是 test
  10. 每个问题都要先提交一个Issue

单测规范约定

  1. 单元测试统一用 junit 和 mockito
  2. 遵守AIR原则
    • Automatic(自动化)。单元测试应该是全自动执行的,并且非交互式的。测试用例通常是被定期执行的,执行过程必须完全自动化。
    • Independent(独立性)。保持单元测试的独立性。为了保证单元测试稳定可靠且便于维护,单元测试用例之间决不能互相调用,也不能依赖执行的先后次序。
    • Repeatable(可重复)。单元测试是可以重复执行的,不能受到外界环境的影响。
  3. 保持单元测试用例的运行速度,不要将大的集成用例放在单元测试中
  4. UT类命名规范 BeTestedClassTest
   范例:
   源类的全限定名为 com.api.Matching
   源文件路径 src/main/java/com/api/Matching.java
   UT文件路径 src/test/java/com/api/MatchingTest.java
  1. UT方法命名规范
   范例:
   源方法名为 matching()
   UT方法命名为 testMatching_Success()/testMatching_SuccessWhenResultGreaterThanZero()/testMatching_FailWhenThrowException()

Commit 约定

  1. Commit style
 <type>(<scope>): <subject>
 <BLANK LINE>
 <body>
 <BLANK LINE>
 <footer>
  1. Commit type
    • feat: 新增 feature
    • fix:修复 bug
    • docs:仅仅修改了文档,比如 README, CHANGELOG, CONTRIBUTE等等
    • style:仅仅修改了空格、格式缩进、逗号等等,不改变代码逻辑
    • refactor:代码重构,没有加新功能或者修复 bug
    • perf:优化相关,比如提升性能、体验
    • test:测试用例,包括单元测试、集成测试等
    • chore:改变构建流程、或者增加依赖库、工具等
    • revert:回滚到上一个版本
  2. Commit scope: 提交代码适用的范围(选填)
  3. Commit subject:50个字符以内,描述主要变更内容(必填)
  4. Commit body:更详细的说明文本,建议72个字符以内(必填)
  5. Commit footer:如果需要的化可以添加一个链接到issue地址或者其它文档,或者关闭某个issue(选填)

7.2 - 文档贡献指南

为Capa文档贡献的指南

本文档描述了如何为 Capa 文档库做出贡献。文档库使用 Markdown 语法编写。已发布到 capa-cloud/capa.io

先决条件

Capa 文档库使用 Hugo 的 Docsy 主题构建。

文档搭建步骤

文档开发步骤

规范约定

  1. 确保你所贡献文件在层次结构中的位置是正确的。
  2. 确保你所贡献内容在名称、参数、术语方面保持一致。
  3. 确保任何贡献内容在 Web 站点可以构建成功。
  4. 确保读者能够理解为什么他们应该关注贡献内容,以及能够为他们解决什么问题。

文档路径说明

文件路径说明

文件统一放在 content/ 目录下,其中中文文档存放于 content/zh ,英文文档存放于 content/en。

如果需要新增文档,需要按照目录结构新增文件夹和.md文件。

图片路径说明

图片统一放在 content/images/ 目录下,其中图片目录结构与所引用的 md 文件的目录保持一致。需要选用清晰且与背景适配的图片。

文档中统一使用全路径来引用图片,Url前缀 https://raw.githubusercontent.com/capa-cloud/capa.io/master/content/images

例如,引入下图的图片(contribution_file.png),Markdown写法如下:

 ![Architecture](https://raw.githubusercontent.com/capa-cloud/capa.io/master/content/images/zh/docs/ContributionGuidelines/contribution_file.png)
  • master 表示分支名
  • content/images/zh/docs/ContributionGuidelines/contribution_file.png 表示图片的相对路径