protobuf best practice

枚举定义

取值跳过 0

0 是默认值,在 Protobuf 3 中移除了 optional 和 required 关键词,在序列化时没有标记字段是否设置,这会在某些场景带来一些问题。

  • 序列化时跳过为默认值的字段
    • 转换为 Json 时会缺少字段
  • 无法区分未设置和设置为默认值
    • 这两种情况在某些场景下表示完全不同的含义,比如我们用一个字段存储特征,那么这个特征值是默认值和特征不存在是两种情况,不能混为一谈

Python 机器学习 基于 Pytorch 和 Scikit-Learn - 第一章

机器学习

机器学习,是人工智能的一个分支,赋予计算机从数据中学习的能力。机器学习算法从数据中获取知识来进行预测。

学习类型

常见的机器学习类型有三种。

  • 监督学习。从有标签的数据学习知识,并预测无标签的数据。
    • 分类任务,标签是离散值。
      • 二分类任务。
      • 多分类任务。
    • 回归任务,标签是连续值。
  • 无监督学习。无须知道结果变量或奖励函数便能探索数据的规律。
    • 聚类,挖掘数据结构性信息或数据间关系。
    • 降维。用于降噪、数据可视化。
  • 强化学习。学习一系列使总奖励最大化的动作,奖励可以在动作后立即获得,也可以延迟获得。

机器学习系统路线图

image-20241028192141774

  1. 数据预处理,让数据可用
  2. 训练和选择预测模型
  3. 使用未见过的数据对模型进行评估

wireguard

WireGuard

使用步骤

  • 使用 wg genkeywg pubkey 在每个节点创建公钥和私钥
  • 配置
    • 主中继服务器(main relay server)
      • [Interface]
        • 确保在定义服务器可接收的路由地址时,指定整个 VPN 网络的 CIDR 范围
          • Address = 192.0.2.1/24
      • [Peer]
        • 为每个需要加入到 VPN 网络的客户端创建一个 [Peer],使用对应的公钥(public key)
    • 客户端节点(client node)
      • [Interface]
        • 指定单个 IP,不中继流量
          • Address = 192.0.2.3/32
      • [Peer]
        • 为每个可以公开访问的 Peer 创建一个 [Peer]
        • 在定义作为跳板服务器(Bounce Server)的远程对等体时,确保为整个VPN子网指定一个CIDR范围
          • AllowedIPs = 192.0.2.1/24
        • 确保为不中继流量且仅充当简单客户端的远程对等点指定单独的 IP
          • AllowedIPs = 192.0.2.3/32
    • 启动中继节点
      • wg-quick up /full/path/to/wg0.conf
    • 启动客户端节点
      • wg-quick up /full/path/to/wg0.conf

准备

Ubuntu

1
2
3
4
5
6
7
8
$ sudo vim /etc/sysctl.conf
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
$ sudo sysctl -p
$ sudo ufw allow 51820/udp
# 重启 ufw
$ sudo ufw disable
$ sudo ufw enable

配置

字段

  • AllowedIPs : 路由目的网络
1
2
3
4
5
6
7
8
9
# 安装
apt install wireguard -y

# 添加网络接口
ip link add dev wg0 type wireguard
ip address add dev wg0 10.0.2.1/24

# 生成密钥
wg genkey | tee server-private.key | wg pubkey | tee server-public.key

命令

跳板服务器开启中继和转发

1
2
3
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.proxy_arp = 1" >> /etc/sysctl.conf
sudo sysctl -p /etc/sysctl.conf

生成公钥、私钥

1
2
3
4
5
# generate private key
wg genkey > example.key

# generate public key
wg pubkey < example.key > example.key.pub

启停

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
wg-quick up /full/path/to/wg0.conf
wg-quick down /full/path/to/wg0.conf
# Note: you must specify the absolute path to wg0.conf, relative paths won't work

# start/stop VPN network interface
ip link set wg0 up
ip link set wg0 down

# register/unregister VPN network interface
ip link add dev wg0 type wireguard
ip link delete dev wg0

# register/unregister local VPN address
ip address add dev wg0 192.0.2.3/32
ip address delete dev wg0 192.0.2.3/32

# register/unregister VPN route
ip route add 192.0.2.3/32 dev wg0
ip route delete 192.0.2.3/32 dev wg0

注意

  • 如果一个节点在 NAT 内,在配置远端 Peer 时需要配置 PersistentKeepalive ,这样远端 Peer 才能访问当前 Node
1
2
3
4
5
[Peer]
Endpoint = <ip:port>
PublicKey = <public-key>
AllowedIPs = 10.0.10.1/24
PersistentKeepalive = 25

其他

预设

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# vpn 网络
10.110.10.1/24
# 示例 client 地址
10.110.10.100/24
# 网络接口
ens18
# server 地址
192.168.6.192

# server 端密钥对
PUBLICKEY = HsNTZwNRji31XuNAhx+eMOD8y7CZEeoPEUzZWZXpqg0=
PRIVATEKEY = UHIqicenzBJQ6gnsSHqrvZbEEbjz6NJfl1qc4UgpMm8=

# client 端密钥对
PUBLICKey = KLL6tm7wiU/ouenCktUwThss5Jw9Xr79C+3u3QRnYCQ=
PRIVATEKEY = oNLv6Ntj5iHulThhcCtZ0jYtRV0CTsC4d6rJkWo21FY=

配置模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[Interface]
## Address : A private IP address for wg0 interface.
Address = 10.110.10.1/24

## Specify the listening port of WireGuard, I like port 33333, you can change it.
ListenPort = 51820

## A privatekey of the server ( cat /etc/wireguard/server-private.key)
PrivateKey = {private-key-of-server}

## The PostUp will run when the WireGuard Server starts the virtual VPN tunnel.
## The PostDown rules run when the WireGuard Server stops the virtual VPN tunnel.
## Specify the command that allows traffic to leave the server and give the VPN clients access to the Internet.
## Replace enp1s0 = Your-Network-Interface-Name

PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o {Your-Network-Interface-Name} -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o {Your-Network-Interface-Name} -j MASQUERADE
1
2
3
4
5
6
7
[Interface]
Address = 10.110.10.1/24
ListenPort = 51820
PrivateKey = UHIqicenzBJQ6gnsSHqrvZbEEbjz6NJfl1qc4UgpMm8=

PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ens18 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ens18 -j MASQUERADE

服务

1
2
3
4
5
6
systemctl start wg-quick@wg0
systemctl enable wg-quick@wg0
systemctl status wg-quick@wg0.service

# 查看状态
wg show wg0

客户端配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 重新生成密钥和公钥
[Interface]
PrivateKey = PrivateKey_of_the_Client
Address = IP_UNDER_VPN

[Peer]
###Public of the WireGuard VPN Server
PublicKey = PublicKey_of_the_Server

### IP and Port of the WireGuard VPN Server
Endpoint = IP_of_the_Sever:Port_VPN_of_the_Server

### Allow all traffic
AllowedIPs = 0.0.0.0/0
1
2
3
4
5
6
7
8
9
# 重新生成密钥和公钥
[Interface]
PrivateKey = oNLv6Ntj5iHulThhcCtZ0jYtRV0CTsC4d6rJkWo21FY=
Address = 10.110.10.100/24

[Peer]
PublicKey = HsNTZwNRji31XuNAhx+eMOD8y7CZEeoPEUzZWZXpqg0=
Endpoint = 192.168.6.192:51820
AllowedIPs = 0.0.0.0/0

服务端添加 Peer

1
2
3
4
wg set wg0 peer {client-public-key} allowed-ips 10.110.10.100

# 示例
wg set wg0 peer KLL6tm7wiU/ouenCktUwThss5Jw9Xr79C+3u3QRnYCQ= allowed-ips 10.110.10.100

访问 Local Network

1
2
3
4
5
6
7
8
9
10
PostUp = ufw route allow in on wg0 out on eth0
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = ip6tables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PostUp = ip6tables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PreDown = ufw route delete allow in on wg0 out on eth0
PreDown = iptables -D FORWARD -i wg0 -j ACCEPT
PreDown = ip6tables -D FORWARD -i wg0 -j ACCEPT
PreDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
PreDown = ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

注意以下配置

1
2
3
4
5
6
7
8
$ sudo vim /etc/sysctl.conf
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
$ sudo sysctl -p
$ sudo ufw allow 51820/udp
# 重启 ufw
$ sudo ufw disable
$ sudo ufw enable

常见问题

无法访问远端内网

首先,客户端配置远端地址段。

1
2
3
4
5
6
[Peer]
Endpoint = {remote_ip:port}
PublicKey = {public_key}
AllowedIPs = 10.0.20.0/24 # wireguard 组网地址
AllowedIPs = 192.168.6.0/24 # 远端内网地址
AllowedIPs = 192.168.1.0/24 # 远端内网地址

其次,配置远端服务器网络 forward。

1
2
3
4
5
$ sudo vim /etc/sysctl.conf
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
$ sudo sysctl -p
$ sudo ufw allow 51820/udp

参考

参考 参考二

端口连通性判断

1
2
$ nc -z -v -u 127.0.0.1 51820
Connection to 127.0.0.1 port 51820 [udp/*] succeeded!

Debug

1
$ sudo wg show 

postgresql - startup

命令

登录

1
2
# login
$ psql -U postgres # 指定用户,无密码

用户操作

1
CREATE USER root WITH CREATEDB CREATEUSER PASSWORD 'root';

role 操作

1
2
3
4
CREATE ROLE root WITH LOGIN CREATEDB CREATEROLE SUPERUSER PASSWORD 'root';

# 查看
SELECT * FROM pg_roles;

数据库操作

1
CREATE DATABASE dolphinscheduler;

docker compose

Docker Compose

Docker Compose是一个用于定义和运行多个容器化应用的工具。它允许你通过一个单独的配置文件(通常是YAML格式)来定义和管理多个Docker容器,以便这些容器能够协同工作。

Docker Compose的主要功能包括:

  1. 定义服务:使用Compose文件可以指定多个相关联的服务,每个服务都在单独的容器中运行。例如,你可以定义一个Web服务、一个数据库服务和一个消息队列服务。
  2. 配置网络和卷:Compose文件允许你定义容器之间的网络连接,以及将本地文件系统的目录与容器内的卷进行映射。
  3. 管理环境变量:Compose文件支持设置和管理环境变量,这对于配置应用程序和容器之间的交互非常有用。
  4. 批量启动和停止:使用Compose命令可以方便地一次启动或停止整个应用程序,而不需要分别管理每个容器。

对比 Dockerfile

相比之下,Dockerfile是用于构建Docker镜像的文本文件。它包含了描述如何构建镜像的指令和配置,例如基础镜像选择、安装软件包、配置环境等。通过执行Dockerfile中的指令,可以自动化地构建出一个可重复部署的镜像。

Dockerfile和Docker Compose的主要区别在于其关注点和使用场景:

  • Dockerfile:适用于单个容器或一个独立的服务。它用于定义镜像的构建过程,使其可在任何支持Docker的环境中部署。
  • Docker Compose:适用于多个相关容器组成的应用程序。它用于定义、配置和管理多个容器之间的交互,并提供了一种简化的方式来启动、停止和管理整个应用程序的多个服务。

通常情况下,你可以使用Dockerfile构建出应用程序所需的镜像,然后使用Docker Compose来定义和管理各个容器的协同工作,以搭建和运行复杂的多容器应用程序。

安装

1
$ sudo apt install docker-compose-plugin

命令

1
2
3
4
5
6
7
8
# 启动
$ docker compose up -d
# 停止
$ docker dompose stop

# 删除
# !!! 注意, 是删除
$ docker compose down

启动指定 service

1
$ docker compose up -d services...

Nvidia GPU

安装驱动(ubuntu)

1
2
$ sudo ubuntu-drivers list                # 可安装驱动列表, 多版本
$ sudo ubuntu-drivers install nvidia:535 # 安装指定版本

安装工具(ubuntu)

安装文档参考这里Installing the NVIDIA Container Toolkit

1
2
3
4
5
6
$ curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
$ sudo apt-get update
$ sudo apt-get install -y nvidia-container-toolkit

配置 Docker

1
2
$ sudo nvidia-ctk runtime configure --runtime=docker
$ sudo systemctl restart docker # 重启 docker

Docker Compose 添加配置

1
2
3
4
5
6
7
8
9
10
11
12
...
services:
{service-name}:
image: ...
...
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]