本文尝试分享下以最小方式(单机、容器化 Spark、Hadoop、Nebula Graph),快速趟一下 Nebula Exchange 中 SST 写入方式的步骤。本文适用于 v2.5 以上版本的 Nebula- Exchange。

原文链接:

  • 国外访问:https://siwei.io/nebula-exchange-sst-2.x/
  • 国内访问:https://cn.siwei.io/nebula-exchange-sst-2.x/

什么是 Nebula Exchange?

之前我在 Nebula Data Import Options 之中介绍过,Nebula Exchange 是一个 Nebula Graph 社区开源的 Spark Applicaiton,它专门用来支持批量或者流式地把数据导入 Nebula Graph Database 之中。

Nebula Exchange 支持多种多样的数据源(从 Apache Parquet、ORC、JSON、CSV、HBase、Hive MaxCompute 到 Neo4j、MySQL、ClickHouse,再有 Kafka、Pulsar,更多的数据源也在不断增加之中)。

如上图所示,在 Exchange 内部,从除了不同 Reader 可以读取不同数据源之外,在数据经过 Processor 处理之后通过 Writer写入(sink) Nebula Graph 图数据库的时候,除了走正常的 ServerBaseWriter 的写入流程之外,它还可以绕过整个写入流程,利用 Spark 的计算能力并行生成底层 RocksDB 的 SST 文件,从而实现超高性能的数据导入,这个 SST 文件导入的场景就是本文带大家上手熟悉的部分。

详细信息请参阅:Nebula Graph 手册:什么是 Nebula Exchange

Nebula Graph 官方博客也有更多 Nebula Exchange 的实践文章

步骤概观

  • 实验环境
  • 配置 Exchange
  • 生成 SST 文件
  • 写入 SST 文件到 Nebula Graph

实验环境准备

为了最小化使用 Nebula Exchange 的 SST 功能,我们需要:

  • 搭建一个 Nebula Graph 集群,创建导入数据的 Schema,我们选择使用 Docker-Compose 方式、利用 Nebula-Up 快速部署,并简单修改其网络,以方便同样容器化的 Exchange 程序对其访问。
  • 搭建容器化的 Spark 运行环境
  • 搭建容器化的 HDFS

1. 搭建 Nebula Graph 集群

借助于 Nebula-Up 我们可以在 Linux 环境下一键部署一套 Nebula Graph 集群:

curl -fsSL nebula-up.siwei.io/install.sh | bash

待部署成功之后,我们需要对环境做一些修改,这里我做的修改其实就是两点:

  1. 只保留一个 metaD 服务
  2. 起用 Docker 的外部网络

详细修改的部分参考附录一

应用 docker-compose 的修改:

cd ~/.nebula-up/nebula-docker-compose
vim docker-compose.yaml # 参考附录一
docker network create nebula-net # 需要创建外部网络
docker-compose up -d --remove-orphans

之后,我们来创建要测试的图空间,并创建图的 Schema,为此,我们可以利用 nebula-console ,同样,Nebula-Up 里自带了容器化的 nebula-console。

  • 进入 Nebula-Console 所在的容器
~/.nebula-up/console.sh
/ #
  • 在 console 容器里发起链接到图数据库,其中 192.168.x.y 是我所在的 Linux VM 的第一个网卡地址,请换成您的
/ # nebula-console -addr 192.168.x.y -port 9669 -user root -p password
[INFO] connection pool is initialized successfullyWelcome to Nebula Graph!
  • 创建图空间(我们起名字叫 sst ),以及 schema
create space sst(partition_num=5,replica_factor=1,vid_type=fixed_string(32));
:sleep 20
use sst
create tag player(name string, age int);

示例输出

(root@nebula) [(none)]> create space sst(partition_num=5,replica_factor=1,vid_type=fixed_string(32));
Execution succeeded (time spent 1468/1918 us)(root@nebula) [(none)]> :sleep 20(root@nebula) [(none)]> use sst
Execution succeeded (time spent 1253/1566 us)Wed, 18 Aug 2021 08:18:13 UTC(root@nebula) [sst]> create tag player(name string, age int);
Execution succeeded (time spent 1312/1735 us)Wed, 18 Aug 2021 08:18:23 UTC

2. 搭建容器化的 Spark 环境

利用 big data europe 做的工作,这个过程非常容易。

值得注意的是:

  • 现在的 Nebula Exchange 对 Spark 的版本有要求,在现在的 2021 年 8 月,我是用了 spark-2.4.5-hadoop-2.7 的版本。
  • 为了方便,我让 Spark 运行在 Nebula Graph 相同的机器上,并且指定了运行在同一个 Docker 网络下
docker run --name spark-master --network nebula-net \-h spark-master -e ENABLE_INIT_DAEMON=false -d \bde2020/spark-master:2.4.5-hadoop2.7

然后,我们就可以进入到环境中了:

docker exec -it spark-master bash

进到 Spark 容器中之后,可以像这样安装 maven:

export MAVEN_VERSION=3.5.4
export MAVEN_HOME=/usr/lib/mvn
export PATH=$MAVEN_HOME/bin:$PATHwget http://archive.apache.org/dist/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz && \tar -zxvf apache-maven-$MAVEN_VERSION-bin.tar.gz && \rm apache-maven-$MAVEN_VERSION-bin.tar.gz && \mv apache-maven-$MAVEN_VERSION /usr/lib/mvn

还可以这样在容器里下载 nebula-exchange 的 jar 包:

cd ~
wget https://repo1.maven.org/maven2/com/vesoft/nebula-exchange/2.1.0/nebula-exchange-2.1.0.jar

3. 搭建容器化的 HDFS

同样借助 big-data-euroupe 的工作,这非常简单,不过我们要做一点修改,让它的 docker-compose.yml 文件里使用 nebula-net 这个之前创建的 Docker 网络。

详细修改的部分参考附录二

git clone https://github.com/big-data-europe/docker-hadoop.git
cd docker-hadoop
vim docker-compose.yml
docker-compose up -d

配置 Exchange

这个配置主要填入的信息就是 Nebula Graph 集群本身和将要写入数据的 Space Name,以及数据源相关的配置(这里我们用 csv 作为例子),最后再配置输出(sink)为 sst

  • Nebula Graph

    • GraphD 地址
    • MetaD 地址
    • credential
    • Space Name
  • 数据源
    • source: csv

      • path
      • fields etc.
    • ink: sst

详细的配置参考附录二

注意,这里 metaD 的地址可以这样获取,可以看到 0.0.0.0:49377->9559 表示 49377 是外部的地址。

$ docker ps | grep meta
887740c15750   vesoft/nebula-metad:v2.0.0                               "./bin/nebula-metad …"   6 hours ago    Up 6 hours (healthy)    9560/tcp, 0.0.0.0:49377->9559/tcp, :::49377->9559/tcp, 0.0.0.0:49376->19559/tcp, :::49376->19559/tcp, 0.0.0.0:49375->19560/tcp, :::49375->19560/tcp                  nebula-docker-compose_metad0_1

生成 SST 文件

1. 准备源文件、配置文件

docker cp exchange-sst.conf spark-master:/root/
docker cp player.csv spark-master:/root/

其中 player.csv 的例子:

1100,Tim Duncan,42
1101,Tony Parker,36
1102,LaMarcus Aldridge,33
1103,Rudy Gay,32
1104,Marco Belinelli,32
1105,Danny Green,31
1106,Kyle Anderson,25
1107,Aron Baynes,32
1108,Boris Diaw,36
1109,Tiago Splitter,34
1110,Cory Joseph,27
1111,David West,38

2. 执行 exchange 程序

进入 spark-master 容器,提交执行 exchange 应用。

docker exec -it spark-master bash
cd /root/
/spark/bin/spark-submit --master local \--class com.vesoft.nebula.exchange.Exchange nebula-exchange-2.1.0.jar\-c exchange-sst.conf

检查执行结果:

spark-submit 输出:

21/08/17 03:37:43 INFO TaskSetManager: Finished task 31.0 in stage 2.0 (TID 33) in 1093 ms on localhost (executor driver) (32/32)
21/08/17 03:37:43 INFO TaskSchedulerImpl: Removed TaskSet 2.0, whose tasks have all completed, from pool
21/08/17 03:37:43 INFO DAGScheduler: ResultStage 2 (foreachPartition at VerticesProcessor.scala:179) finished in 22.336 s
21/08/17 03:37:43 INFO DAGScheduler: Job 1 finished: foreachPartition at VerticesProcessor.scala:179, took 22.500639 s
21/08/17 03:37:43 INFO Exchange$: SST-Import: failure.player: 0
21/08/17 03:37:43 WARN Exchange$: Edge is not defined
21/08/17 03:37:43 INFO SparkUI: Stopped Spark web UI at http://spark-master:4040
21/08/17 03:37:43 INFO MapOutputTrackerMasterEndpoint: MapOutputTrackerMasterEndpoint stopped!

验证 HDFS 上生成的 SST 文件:

docker exec -it namenode /bin/bashroot@2db58903fb53:/# hdfs dfs -ls /sst
Found 10 items
drwxr-xr-x   - root supergroup          0 2021-08-17 03:37 /sst/1
drwxr-xr-x   - root supergroup          0 2021-08-17 03:37 /sst/10
drwxr-xr-x   - root supergroup          0 2021-08-17 03:37 /sst/2
drwxr-xr-x   - root supergroup          0 2021-08-17 03:37 /sst/3
drwxr-xr-x   - root supergroup          0 2021-08-17 03:37 /sst/4
drwxr-xr-x   - root supergroup          0 2021-08-17 03:37 /sst/5
drwxr-xr-x   - root supergroup          0 2021-08-17 03:37 /sst/6
drwxr-xr-x   - root supergroup          0 2021-08-17 03:37 /sst/7
drwxr-xr-x   - root supergroup          0 2021-08-17 03:37 /sst/8
drwxr-xr-x   - root supergroup          0 2021-08-17 03:37 /sst/9

写入 SST 到 Nebula Graph

这里的操作实际上都是参考文档:SST 导入,得来。其中就是从 console 之中执行了两步操作:

  • Download
  • Ingest

其中 Download 实际上是触发 Nebula Graph 从服务端发起 HDFS Client 的 download,获取 HDFS 上的 SST 文件,然后放到 storageD 能访问的本地路径下,这里,需要我们在服务端部署 HDFS 的依赖。因为我们是最小实践,我就偷懒手动做了这个 Download 的操作。

1. 手动下载

这里边手动下载我们就要知道 Nebula Graph 服务端下载的路径,实际上是 /data/storage/nebula/<space_id>/download/,这里的 Space ID 需要手动获取一下:

这个例子里,我们的 Space Name 是 sst,而 Space ID 是 49

(root@nebula) [sst]> DESC space sst
+----+-------+------------------+----------------+---------+------------+--------------------+-------------+-----------+
| ID | Name  | Partition Number | Replica Factor | Charset | Collate    | Vid Type           | Atomic Edge | Group     |
+----+-------+------------------+----------------+---------+------------+--------------------+-------------+-----------+
| 49 | "sst" | 10               | 1              | "utf8"  | "utf8_bin" | "FIXED_STRING(32)" | "false"     | "default" |
+----+-------+------------------+----------------+---------+------------+--------------------+-------------+-----------+

于是,下边的操作就是手动把 SST 文件从 HDFS 之中 get 下来,再拷贝到 storageD 之中。

docker exec -it namenode /bin/bash$ hdfs dfs -get /sst /sst
exit
docker cp namenode:/sst .
docker exec -it nebula-docker-compose_storaged0_1 mkdir -p /data/storage/nebula/49/download/
docker exec -it nebula-docker-compose_storaged1_1 mkdir -p /data/storage/nebula/49/download/
docker exec -it nebula-docker-compose_storaged2_1 mkdir -p /data/storage/nebula/49/download/
docker cp sst nebula-docker-compose_storaged0_1:/data/storage/nebula/49/download/
docker cp sst nebula-docker-compose_storaged1_1:/data/storage/nebula/49/download/
docker cp sst nebula-docker-compose_storaged2_1:/data/storage/nebula/49/download/

2. SST 文件导入

  • 进入 Nebula-Console 所在的容器
~/.nebula-up/console.sh
/ #
  • 在 console 容器里发起链接到图数据库,其中 192.168.x.y 是我所在的 Linux VM 的第一个网卡地址,请换成您的
/ # nebula-console -addr 192.168.x.y -port 9669 -user root -p password
[INFO] connection pool is initialized successfullyWelcome to Nebula Graph!
  • 执行 INGEST 开始让 StorageD 读取 SST 文件
(root@nebula) [(none)]> use sst
(root@nebula) [sst]> INGEST;

我们可以用如下方法实时查看 Nebula Graph 服务端的日志

tail -f ~/.nebula-up/nebula-docker-compose/logs/*/*

成功的 INGEST 日志:

I0817 08:03:28.611877   169 EventListner.h:96] Ingest external SST file: column family default, the external file path /data/storage/nebula/49/download/8/8-6.sst, the internal file path /data/storage/nebula/49/data/000023.sst, the properties of the table: # data blocks=1; # entries=1; # deletions=0; # merge operands=0; # range deletions=0; raw key size=48; raw average key size=48.000000; raw value size=40; raw average value size=40.000000; data block size=75; index block size (user-key? 0, delta-value? 0)=66; filter block size=0; (estimated) table size=141; filter policy name=N/A; prefix extractor name=nullptr; column family ID=N/A; column family name=N/A; comparator name=leveldb.BytewiseComparator; merge operator name=nullptr; property collectors names=[]; SST file compression algo=Snappy; SST file compression options=window_bits=-14; level=32767; strategy=0; max_dict_bytes=0; zstd_max_train_bytes=0; enabled=0; ; creation time=0; time stamp of earliest key=0; file creation time=0;
E0817 08:03:28.611912   169 StorageHttpIngestHandler.cpp:63] SSTFile ingest successfully

附录

附录一

docker-compose.yaml

diff --git a/docker-compose.yaml b/docker-compose.yaml
index 48854de..cfeaedb 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -6,11 +6,13 @@ services:USER: rootTZ:   "${TZ}"command:
-      - --meta_server_addrs=metad0:9559,metad1:9559,metad2:9559
+      - --meta_server_addrs=metad0:9559- --local_ip=metad0- --ws_ip=metad0- --port=9559- --ws_http_port=19559
+      - --ws_storage_http_port=19779- --data_path=/data/meta- --log_dir=/logs- --v=0
@@ -34,81 +36,14 @@ services:cap_add:- SYS_PTRACE-  metad1:
-    image: vesoft/nebula-metad:v2.0.0
-    environment:
-      USER: root
-      TZ:   "${TZ}"
-    command:
-      - --meta_server_addrs=metad0:9559,metad1:9559,metad2:9559
-      - --local_ip=metad1
-      - --ws_ip=metad1
-      - --port=9559
-      - --ws_http_port=19559
-      - --data_path=/data/meta
-      - --log_dir=/logs
-      - --v=0
-      - --minloglevel=0
-    healthcheck:
-      test: ["CMD", "curl", "-sf", "http://metad1:19559/status"]
-      interval: 30s
-      timeout: 10s
-      retries: 3
-      start_period: 20s
-    ports:
-      - 9559
-      - 19559
-      - 19560
-    volumes:
-      - ./data/meta1:/data/meta
-      - ./logs/meta1:/logs
-    networks:
-      - nebula-net
-    restart: on-failure
-    cap_add:
-      - SYS_PTRACE
-
-  metad2:
-    image: vesoft/nebula-metad:v2.0.0
-    environment:
-      USER: root
-      TZ:   "${TZ}"
-    command:
-      - --meta_server_addrs=metad0:9559,metad1:9559,metad2:9559
-      - --local_ip=metad2
-      - --ws_ip=metad2
-      - --port=9559
-      - --ws_http_port=19559
-      - --data_path=/data/meta
-      - --log_dir=/logs
-      - --v=0
-      - --minloglevel=0
-    healthcheck:
-      test: ["CMD", "curl", "-sf", "http://metad2:19559/status"]
-      interval: 30s
-      timeout: 10s
-      retries: 3
-      start_period: 20s
-    ports:
-      - 9559
-      - 19559
-      - 19560
-    volumes:
-      - ./data/meta2:/data/meta
-      - ./logs/meta2:/logs
-    networks:
-      - nebula-net
-    restart: on-failure
-    cap_add:
-      - SYS_PTRACE
-storaged0:image: vesoft/nebula-storaged:v2.0.0environment:USER: rootTZ:   "${TZ}"command:
-      - --meta_server_addrs=metad0:9559,metad1:9559,metad2:9559
+      - --meta_server_addrs=metad0:9559- --local_ip=storaged0- --ws_ip=storaged0- --port=9779
@@ -119,8 +54,8 @@ services:- --minloglevel=0depends_on:- metad0
-      - metad1
-      - metad2healthcheck:test: ["CMD", "curl", "-sf", "http://storaged0:19779/status"]interval: 30s
@@ -146,7 +81,7 @@ services:USER: rootTZ:   "${TZ}"command:
-      - --meta_server_addrs=metad0:9559,metad1:9559,metad2:9559
+      - --meta_server_addrs=metad0:9559- --local_ip=storaged1- --ws_ip=storaged1- --port=9779
@@ -157,8 +92,8 @@ services:- --minloglevel=0depends_on:- metad0
-      - metad1
-      - metad2healthcheck:test: ["CMD", "curl", "-sf", "http://storaged1:19779/status"]interval: 30s
@@ -184,7 +119,7 @@ services:USER: rootTZ:   "${TZ}"command:
-      - --meta_server_addrs=metad0:9559,metad1:9559,metad2:9559
+      - --meta_server_addrs=metad0:9559- --local_ip=storaged2- --ws_ip=storaged2- --port=9779
@@ -195,8 +130,8 @@ services:- --minloglevel=0depends_on:- metad0
-      - metad1
-      - metad2healthcheck:test: ["CMD", "curl", "-sf", "http://storaged2:19779/status"]interval: 30s
@@ -222,17 +157,19 @@ services:USER: rootTZ:   "${TZ}"command:
-      - --meta_server_addrs=metad0:9559,metad1:9559,metad2:9559
+      - --meta_server_addrs=metad0:9559- --port=9669- --ws_ip=graphd- --ws_http_port=19669
+      - --ws_meta_http_port=19559- --log_dir=/logs- --v=0- --minloglevel=0depends_on:- metad0
-      - metad1
-      - metad2healthcheck:test: ["CMD", "curl", "-sf", "http://graphd:19669/status"]interval: 30s
@@ -257,17 +194,19 @@ services:USER: rootTZ:   "${TZ}"command:
-      - --meta_server_addrs=metad0:9559,metad1:9559,metad2:9559
+      - --meta_server_addrs=metad0:9559- --port=9669- --ws_ip=graphd1- --ws_http_port=19669
+      - --ws_meta_http_port=19559- --log_dir=/logs- --v=0- --minloglevel=0depends_on:- metad0
-      - metad1
-      - metad2healthcheck:test: ["CMD", "curl", "-sf", "http://graphd1:19669/status"]interval: 30s
@@ -292,17 +231,21 @@ services:USER: rootTZ:   "${TZ}"command:
-      - --meta_server_addrs=metad0:9559,metad1:9559,metad2:9559
+      - --meta_server_addrs=metad0:9559- --port=9669- --ws_ip=graphd2- --ws_http_port=19669
+      - --ws_meta_http_port=19559- --log_dir=/logs- --v=0- --minloglevel=0
+      - --storage_client_timeout_ms=60000
+      - --local_config=truedepends_on:- metad0
-      - metad1
-      - metad2healthcheck:test: ["CMD", "curl", "-sf", "http://graphd2:19669/status"]interval: 30s
@@ -323,3 +266,4 @@ services:networks:nebula-net:
+    external: true

附录二

https://github.com/big-data-europe/docker-hadoop 的 docker-compose.yml

diff --git a/docker-compose.yml b/docker-compose.yml
index ed40dc6..66ff1f4 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -14,6 +14,8 @@ services:- CLUSTER_NAME=testenv_file:- ./hadoop.env
+    networks:
+      - nebula-netdatanode:image: bde2020/hadoop-datanode:2.0.0-hadoop3.2.1-java8
@@ -25,6 +27,8 @@ services:SERVICE_PRECONDITION: "namenode:9870"env_file:- ./hadoop.env
+    networks:
+      - nebula-netresourcemanager:image: bde2020/hadoop-resourcemanager:2.0.0-hadoop3.2.1-java8
@@ -34,6 +38,8 @@ services:SERVICE_PRECONDITION: "namenode:9000 namenode:9870 datanode:9864"env_file:- ./hadoop.env
+    networks:
+      - nebula-netnodemanager1:image: bde2020/hadoop-nodemanager:2.0.0-hadoop3.2.1-java8
@@ -43,6 +49,8 @@ services:SERVICE_PRECONDITION: "namenode:9000 namenode:9870 datanode:9864 resourcemanager:8088"env_file:- ./hadoop.env
+    networks:
+      - nebula-nethistoryserver:image: bde2020/hadoop-historyserver:2.0.0-hadoop3.2.1-java8
@@ -54,8 +62,14 @@ services:- hadoop_historyserver:/hadoop/yarn/timelineenv_file:- ./hadoop.env
+    networks:
+      - nebula-netvolumes:hadoop_namenode:hadoop_datanode:hadoop_historyserver:
+
+networks:
+  nebula-net:
+    external: true

附录三

nebula-exchange-sst.conf

{# Spark relation configspark: {app: {name: Nebula Exchange 2.1}master:localdriver: {cores: 1maxResultSize: 1G}executor: {memory:1G}cores:{max: 16}}# Nebula Graph relation confignebula: {address:{graph:["192.168.8.128:9669"]meta:["192.168.8.128:49377"]}user: rootpswd: nebulaspace: sst# parameters for SST import, not requiredpath:{local:"/tmp"remote:"/sst"hdfs.namenode: "hdfs://192.168.8.128:9000"}# nebula client connection parametersconnection {# socket connect & execute timeout, unit: millisecondtimeout: 30000}error: {# max number of failures, if the number of failures is bigger than max, then exit the application.max: 32# failed import job will be recorded in output pathoutput: /tmp/errors}# use google's RateLimiter to limit the requests send to NebulaGraphrate: {# the stable throughput of RateLimiterlimit: 1024# Acquires a permit from RateLimiter, unit: MILLISECONDS# if it can't be obtained within the specified timeout, then give up the request.timeout: 1000}}# Processing tags# There are tag config examples for different dataSources.tags: [# HDFS csv# Import mode is sst, just change type.sink to client if you want to use client import mode.{name: playertype: {source: csvsink: sst}path: "file:///root/player.csv"# if your csv file has no header, then use _c0,_c1,_c2,.. to indicate fieldsfields: [_c1, _c2]nebula.fields: [name, age]vertex: {field:_c0}separator: ","header: falsebatch: 256partition: 32}]
}

本文中如有任何错误或疏漏,欢迎去 GitHub:https://github.com/vesoft-inc/nebula issue 区向我们提 issue 或者前往官方论坛:https://discuss.nebula-graph.com.cn/ 的 建议反馈 分类下提建议

无依赖单机尝鲜 Nebula Exchange 的 SST 导入相关推荐

  1. Nebula Exchange 从Hive导入 NoSuchMethodError

    从Hive导入guava版本冲突,重新打包exchange 环境 nebula 版本:3.2.0 hadoop 3.1.1 spark 2.4.3 hive 3.1.0 scala 2.11.12 e ...

  2. 跟我极速尝鲜 Spring Boot 2.3

    Spring Boot 2.3 已经发布一个月了,这两天才想起来尝一尝鲜儿.除了常规的升级外,很大部分的升级是针对 Docker 的,让你不得不相信,Docker 容器化微服务已然大势所趋.还没有用过 ...

  3. Taro 小程序开发大型实战(六):尝鲜微信小程序云(上篇)

    欢迎继续阅读<Taro 小程序开发大型实战>系列,前情回顾: 熟悉的 React,熟悉的 Hooks[1]:我们用 React 和 Hooks 实现了一个非常简单的添加帖子的原型 多页面跳 ...

  4. 通用流量录制回放工具 jvm-sandbox-repeater 尝鲜 (二)——repeater-console 使用

    本文作者陈恒捷是TesterHome社区主编,第十届MTSC大会上海站-开源专场出品人.先后在PP助手.PPmoney.荔枝等公司从事测试效能提升相关工作,在测试技术及效率提升方面有丰富的经验积累. ...

  5. K3s初探:Rancher架构师带你尝鲜史上最轻量Kubernetes发行版

    发布不到两天,GitHub上Star数已近3000,这个业界大热的.史上最轻量的开源Kubernetes发行版,你试过了没? Rancher资深架构师来教你走出尝鲜第一步!使用教程在此! 前 言 昨天 ...

  6. 前端每周清单第 49 期:Webpack 4 Beta 尝鲜,React Windowing 与 setState 分析

    前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点:分为新闻热点.开发教程.工程实践.深度阅读.开源项目.巅峰人生等栏目.欢迎关注[前端之巅]微信公众号(ID: fron ...

  7. vue 时间插件_Vue3 插件开发详解尝鲜版「值得收藏」

    作者:lishuai 转发链接:https://segmentfault.com/a/1190000022757326 前言 vue3.0-beta 版本已经发布了一段时间了,正式版本据说在年中发布( ...

  8. python wasm_Python-pywasm-美味尝鲜

    Pywasm: Python 爱上 Wasm, 美味尝鲜! pywasm 是一个使用纯 Python 实现的 WebAssembly 解释器. 您可以使用如下命令来安装它: $ pip3 instal ...

  9. 基于 Blazui 的 Blazor 后台管理模板 BlazAdmin 正式尝鲜

    简介 BlazAdmin 是一个基于Blazui的后台管理模板,无JS,无TS,非 Silverlight,非 WebForm,一个标签即可使用. 我将在下一篇文章讨论 Blazor 服务器端渲染与客 ...

最新文章

  1. jQuery学习- 内容选择器
  2. 排序算法(插入、快速、归并)java实现
  3. 读javascript高级程序设计11-事件
  4. 如何把某个网站的SSL Server certificate链导入到ABAP Netweaver系统里
  5. Java 7 Update 21安全改进的详细信息
  6. 【Linux】Linux简介以及 与UNIX区别
  7. 如何设置mysql远程访问
  8. python selenium爬虫需要账号和密码登陆的网页_如何使用selenium和requests组合实现登录页面...
  9. 史上最全的微服务知识科普
  10. 绝佳的ASR学习方案:这是一套开源的中文语音识别系统
  11. Oracle→简介、用户、数据字典、表空间及其文件
  12. 微信开放平台认证资料填报
  13. 巧用CSS,愚人节极客式恶搞
  14. 深度学习、目标检测相关博客链接
  15. 关于惠普暗影精灵2 pro用一段时间之后,插上电源充不了电的问题
  16. 日历控件CalendarView
  17. 内网渗透思路10之SPN拿下域控
  18. kali下载gnuplot步骤
  19. 2014年计算机求职总结--准备篇 (顺便也带点自己在美国准备的总结吧)
  20. 百慕大永中为何有权继续开发集成Office?

热门文章

  1. 毫米波雷达的系统设计细节(1) - 从雷达方程到雷达威力图
  2. 数据结构与算法——概念
  3. Windows10安装开源Mujoco
  4. 海盗云商php,海盗云商(2.2.1.160429)前台无限制注入(无需登录,无视GPC)
  5. JS-写一个函数,返回参数的平方和
  6. 122.Linux系统和Shell命令行简介,走上数据分析之路
  7. 未來用工新趨勢_未来人工智能,有什么新的发展趋势?
  8. 使用WASAPI捕获声卡音频
  9. 北京计算机非全日制研究生哪个学校最好考,这所211,因校名被隐藏得很好,考上北京二环“有车有房”不是梦...
  10. java oval 入门_java开源验证框架OVAL-Go语言中文社区