Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cmd_all): support single_node mode #14951

Merged
merged 17 commits into from
Feb 5, 2024

Conversation

kwannoel
Copy link
Contributor

@kwannoel kwannoel commented Feb 2, 2024

I hereby agree to the terms of the RisingWave Labs, Inc. Contributor License Agreement.

What's changed and what's your intention?

single_node mode is a new mode for users who wish to run risingwave in a single process.

Previously users would rely on etcd and minio to run such an instance, now we use file system and embedded sqlite to power the state store and meta stores.

For the configurations of single_node, we don't need to expose node_level options to the end-user. As such we create a new options struct with the essential options.

For the internals, we just:

  1. Map these options to node level options.
  2. Pass the options to standalone_mode.
  3. Use standalone_mode to spawn all these nodes in a single process.

Checklist

  • I have written necessary rustdoc comments
  • I have added necessary unit tests and integration tests
  • I have added test labels as necessary. See details.
  • I have added fuzzing tests or opened an issue to track them. (Optional, recommended for new SQL features Sqlsmith: Sql feature generation #7934).
  • My PR contains breaking changes. (If it deprecates some features, please create a tracking issue to remove them in the future).
  • All checks passed in ./risedev check (or alias, ./risedev c)
  • My PR changes performance-critical code. (Please run macro/micro-benchmarks and show the results.)
  • My PR contains critical fixes that are necessary to be merged into the latest release. (Please check out the details)

Documentation

  • My PR needs documentation updates. (Please use the Release note section below to summarize the impact on users)

Release note

This is considered a "pre-release".

In this PR, we release a new mode: single_node mode.

./risingwave will invoke this new mode by default.

Setup

You can run it simply with the following steps:

git clone git@github.com:risingwavelabs/risingwave.git
git checkout kwannoel/standalone-easy-defaults
cd risingwave
./risedev build-risingwave
./target/debug/risingwave

Trying it

In a separate terminal connect to risingwave:

 psql -h localhost -p 4566 -d dev -U root

Cleaning the cluster

The default data directory is in ~/.risingwave. You can rm that directory to purge associated data.

Configurations

> ./target/debug/risingwave single_node --help

Usage: risingwave single_node [OPTIONS]

Options:
      --prometheus-listener-addr <PROMETHEUS_LISTENER_ADDR>
          The address prometheus polls metrics from [env: RW_SINGLE_NODE_PROMETHEUS_LISTENER_ADDR=]
      --config-path <CONFIG_PATH>
          The path to the cluster configuration file [env: RW_SINGLE_NODE_CONFIG_PATH=]
      --store-directory <STORE_DIRECTORY>
          The store directory used by meta store and object store [env: RW_SINGLE_NODE_STORE_DIRECTORY=]
      --meta-addr <META_ADDR>
          The address of the meta node [env: RW_SINGLE_NODE_META_ADDR=]
      --compute-addr <COMPUTE_ADDR>
          The address of the compute node [env: RW_SINGLE_NODE_COMPUTE_ADDR=]
      --frontend-addr <FRONTEND_ADDR>
          The address of the frontend node [env: RW_SINGLE_NODE_FRONTEND_ADDR=]
      --compactor-addr <COMPACTOR_ADDR>
          The address of the compactor node [env: RW_SINGLE_NODE_COMPACTOR_ADDR=]
  -h, --help
          Print help
  -V, --version
          Print version

Hiding other features

  • Playground mode will be hidden.
  • Standalone mode will be hidden.

@kwannoel kwannoel added the user-facing-changes Contains changes that are visible to users label Feb 2, 2024
@kwannoel kwannoel requested a review from a team as a code owner February 2, 2024 06:55
@kwannoel kwannoel mentioned this pull request Feb 2, 2024
22 tasks
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

license-eye has totally checked 4785 files.

Valid Invalid Ignored Fixed
2081 1 2703 0
Click to see the invalid file list
  • src/cmd_all/src/single.rs

@kwannoel kwannoel force-pushed the kwannoel/standalone-easy-defaults branch from 027206e to d84d076 Compare February 2, 2024 07:01
src/compute/src/lib.rs Outdated Show resolved Hide resolved
@kwannoel kwannoel force-pushed the kwannoel/standalone-easy-defaults branch from 6560863 to a57cf07 Compare February 2, 2024 07:49

pub fn make_single_node_sql_endpoint(store_directory: &String) -> String {
format!(
"sqlite://{}/meta_store/single_node.db?mode=rwc",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"sqlite://{}/meta_store/single_node.db?mode=rwc",
"sqlite://{}/meta_store.db?mode=rwc",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm why this change? IMO this structure looks more consistent:

noelkwan@Noels-MacBook-Pro risingwave % tree ~/.risingwave/ 
/Users/noelkwan/.risingwave/
├── meta_store
│   └── single_node.db
└── state_store
    └── hummock_001
        ├── checkpoint
        │   └── 0
        └── cluster_id
            └── 0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Than this:

noelkwan@Noels-MacBook-Pro risingwave % tree ~/.risingwave/ 
/Users/noelkwan/.risingwave/
├── single_node.db
└── state_store
    └── hummock_001
        ├── checkpoint
        │   └── 0
        └── cluster_id
            └── 0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Eric's idea is:

/Users/noelkwan/.risingwave/
├── meta_store.db
└── state_store
    └── hummock_001
        ├── checkpoint
        │   └── 0
        └── cluster_id
            └── 0

src/cmd_all/src/bin/risingwave.rs Show resolved Hide resolved
@BugenZhao
Copy link
Member

Will take a look next weekday. 🥺

Copy link
Member

@BugenZhao BugenZhao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now we have 3 single-process deployment modes:

  • playground: all config managed
  • single-node: some config managed
  • standalone: almost no config managed

Intuitively, they're different from each other and exist for some different demand. IMO, however, they could be understood as a single mode with different sets of command-line options being set to the default value.

For example, imagine that we have a single mode like this:

risingwave single
[--preset <profile>]
# fields that will be mapped, use default value if absent
[--meta-address ".."]
[--config-file ".."]
# Extra options to override those from the preset
[--meta-extra-opts ".."]
[--compute-extra-opts ".."]
[--frontend-extra-opts ".."]
[--compactor-extra-opts ".."]

Then...

  • playground is single --preset in-memory
  • single-node is single --preset local-disk
  • standalone is single without preset and specify the address and extra options manually.

In this approach there's not a clear boundary of 3 modes. If users want to tweak a few options for playground or single-node, they don't have to fall back to standalone. Just simply provide some extra-opts.


BTW, the map_opts seems to actually achieve the idea I proposed for improving the UX for standalone mode in #12142 (comment)

For example, if we have specified the listen address of the meta service, then we don't need to specify the meta address again for compute and frontend services. That's why I propose this issue: perhaps we need a (cluster-level ?) configuration file for this as a better replacement for raw command-line arguments.

It's available only for single-node under current design, but I still believe it's a good to have for standalone. With the unified single --preset approach, I guess all single deployment modes can benefit from this.

}

impl SingleNodeOpts {
fn default_frontend_opts() -> FrontendOpts {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO these methods could be painful to maintain. I'd suggest specifying the mapped fields only and leave other fields default with ..Default::default().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm not sure how to expose clap's defaults. e.g. the default values specified by default_value.

I think I tried ..Default::default() for FrontendOpts previously, but it gives an error that the trait is not implemented for FrontendOpts.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. Thought it's serde.

#[command(
version,
about = "The Standalone mode allows users to start multiple services in one process, it exposes node-level options for each service",
hide = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are now hiding the entrance of standalone, it may be more appropriate to assign the name to single_node instead, as discussed. 🤣

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename single_node -> standalone? Not quite sure what you mean.

We hide it from the end user, but cloud will still invoke it with ./risingwave standalone.

@kwannoel
Copy link
Contributor Author

kwannoel commented Feb 5, 2024

For now we have 3 single-process deployment modes:

* `playground`: all config managed

* `single-node`: some config managed

* `standalone`: almost no config managed

Intuitively, they're different from each other and exist for some different demand. IMO, however, they could be understood as a single mode with different sets of command-line options being set to the default value.

For example, imagine that we have a single mode like this:

risingwave single
[--preset <profile>]
# fields that will be mapped, use default value if absent
[--meta-address ".."]
[--config-file ".."]
# Extra options to override those from the preset
[--meta-extra-opts ".."]
[--compute-extra-opts ".."]
[--frontend-extra-opts ".."]
[--compactor-extra-opts ".."]

Then...

* `playground` is `single --preset in-memory`

* `single-node` is `single --preset local-disk`

* `standalone` is `single` without `preset` and specify the address and extra options manually.

In this approach there's not a clear boundary of 3 modes. If users want to tweak a few options for playground or single-node, they don't have to fall back to standalone. Just simply provide some extra-opts.

BTW, the map_opts seems to actually achieve the idea I proposed for improving the UX for standalone mode in #12142 (comment)

For example, if we have specified the listen address of the meta service, then we don't need to specify the meta address again for compute and frontend services. That's why I propose this issue: perhaps we need a (cluster-level ?) configuration file for this as a better replacement for raw command-line arguments.

It's available only for single-node under current design, but I still believe it's a good to have for standalone. With the unified single --preset approach, I guess all single deployment modes can benefit from this.

Some considerations:

  • I think that the default, if no preset is provided, should be to default to single-node. Otherwise having to specify the preset option is troublesome for users. It must be as simple as ./risingwave, if they want to run it.
  • For default options, their defaults will all be determined by what makes sense for single-node mode.

Otherwise, seems like this can unify all 3 execution modes and reduce maintenance overhead.
Let me give it a try.

@kwannoel
Copy link
Contributor Author

kwannoel commented Feb 5, 2024

Otherwise, seems like this can unify all 3 execution modes and reduce maintenance overhead.
Let me give it a try.

Some extra work needs to be done:

  1. Need to provide some proc macro to generate the extra override opts from existing options.
--meta-extra-opts="
  --prometheus-addr="localhost:123"
  > default options
"

#[derive(Debug, Clone, Parser, OverrideConfig)]
#[command(version, about = "The central metadata management service")]
pub struct MetaNodeOpts {
    #[clap(long, env = "RW_VPC_ID")]
    vpc_id: Option<String>,

    #[clap(long, env = "RW_VPC_SECURITY_GROUP_ID")]
    security_group_id: Option<String>,

    // TODO: use `SocketAddr`
    #[clap(long, env = "RW_LISTEN_ADDR", default_value = "127.0.0.1:5690")]
    pub listen_addr: String,

Proc macro output:

pub struct MetaNodeOptsBuilder {
    #[clap(long, env = "RW_VPC_ID")]
    vpc_id: Option<Option<String>>,

    #[clap(long, env = "RW_VPC_SECURITY_GROUP_ID")]
    security_group_id: Option<Option<String>>,

    // TODO: use `SocketAddr`
    #[clap(long, env = "RW_LISTEN_ADDR", default_value = "127.0.0.1:5690")]
    pub listen_addr: Option<String>,
}

Thanks @BugenZhao for mentioning:
Use update_matches to pass in string options, no need to maintain a builder it seems:
https://docs.rs/clap/latest/clap/trait.Parser.html#method.update_from.

@kwannoel
Copy link
Contributor Author

kwannoel commented Feb 5, 2024

Discussed offline with bugen, we can merge this PR, and update the internals later to unify standalone, playground and single_node.

Track: #14997

@kwannoel kwannoel added this pull request to the merge queue Feb 5, 2024
Merged via the queue into main with commit afc3028 Feb 5, 2024
27 of 28 checks passed
@kwannoel kwannoel deleted the kwannoel/standalone-easy-defaults branch February 5, 2024 09:52
github-actions bot pushed a commit that referenced this pull request Feb 5, 2024
kwannoel added a commit that referenced this pull request Feb 5, 2024
kwannoel added a commit that referenced this pull request Feb 5, 2024
Co-authored-by: Noel Kwan <47273164+kwannoel@users.noreply.github.com>
Co-authored-by: Noel Kwan <noelkwan1998@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type/feature user-facing-changes Contains changes that are visible to users
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants