refactor!: rename the project from Monitor to MoShiro
Namespaces, assemblies, projects and directories, the solution, binaries, images, systemd units, config paths, environment variables, protocol method names, the media type and the raw chunk magic all move to MoShiro/moshiro. Existing data and deployments are not compatible and must be recreated. Also fix the architecture tests after the solution layout change and make the update tests independent of their order.
This commit is contained in:
1 parent
17b35223aa
commit
83e5120377
309 files changed
+1505
-1499
No files matched your search
@@ -1,4 +1,4 @@
|
||||
# Monitor Probe
|
||||
# MoShiro Probe
|
||||
|
||||
Probe 是网络测量的发起端,通常运行在家宽或其他需要观测的网络出口。它连接 Backend(身份、Agent 列表、状态)和 Agent(测量),执行线路任务,并把本端采集的原始数据交给 Agent 汇总上报。Probe 不提供远程命令或文件管理功能。
|
||||
|
||||
@@ -13,7 +13,7 @@ Backend ──任务──> Agent <──测量会话──> Probe
|
||||
|
||||
Probe 使用面板生成的 `probe.json` 读取自身身份、面板地址(`server`)和本地测试限制。连上面板之后,面板下发要连接的 Agent 列表;Probe 将列表缓存到同目录的 `agents.json`,面板暂时连不上时靠它继续测量。`probe.json` 含私钥,请限制文件访问权限,不要提交到版本控制。
|
||||
|
||||
容器节点的运行方式(podman + systemd)和宿主机更新器见 [`../../docs/deployment.md`](../../docs/deployment.md);Probe 也可以用 OCI 镜像 `registry.oeo.one/monitor/monitor-probe:<version>`,容器默认读取 `/etc/monitor/probe.json`,命名 volume 保存身份配置和缓存,镜像以 UID/GID 1654 运行。
|
||||
容器节点的运行方式(podman + systemd)和宿主机更新器见 [`../../docs/deployment.md`](../../docs/deployment.md);Probe 也可以用 OCI 镜像 `registry.oeo.one/moshiro/moshiro-probe:<version>`,容器默认读取 `/etc/moshiro/probe.json`,命名 volume 保存身份配置和缓存,镜像以 UID/GID 1654 运行。
|
||||
|
||||
## 构建
|
||||
|
||||
@@ -21,33 +21,33 @@ Probe 使用面板生成的 `probe.json` 读取自身身份、面板地址(`se
|
||||
|
||||
```sh
|
||||
cd backend
|
||||
dotnet build probe/src/Monitor.Probe -c Release
|
||||
dotnet build probe/src/MoShiro.Probe -c Release
|
||||
```
|
||||
|
||||
发布 NativeAOT 程序需要对应平台的 C/C++ 工具链;`<RID>` 应与构建环境和目标平台匹配:
|
||||
|
||||
```sh
|
||||
dotnet publish probe/src/Monitor.Probe -c Release -r <RID> -p:PublishAot=true
|
||||
dotnet publish probe/src/MoShiro.Probe -c Release -r <RID> -p:PublishAot=true
|
||||
```
|
||||
|
||||
也可在仓库根目录运行 `bash scripts/publish.sh probe <RID>`,再使用 `scripts/package.sh probe <RID>` 生成部署包。支持平台和安装流程见 [`../../docs/deployment.md`](../../docs/deployment.md)。
|
||||
|
||||
## 配置与运行
|
||||
|
||||
在管理端创建 Probe 并下载一次性身份配置,将文件保存为目标机上的 `/etc/monitor/probe.json`。随后运行:
|
||||
在管理端创建 Probe 并下载一次性身份配置,将文件保存为目标机上的 `/etc/moshiro/probe.json`。随后运行:
|
||||
|
||||
```sh
|
||||
monitor-probe --config /etc/monitor/probe.json
|
||||
moshiro-probe --config /etc/moshiro/probe.json
|
||||
```
|
||||
|
||||
不传 `--config` 时默认读取 `/etc/monitor/probe.json`。配置中的 `limits` 是本地硬上限,Backend 无法远程放宽;路由器等低性能设备可调低测试码率和包速率,避免 Probe 自身成为测量瓶颈。部署时可使用仓库的 `packaging/` 文件和安装脚本。
|
||||
不传 `--config` 时默认读取 `/etc/moshiro/probe.json`。配置中的 `limits` 是本地硬上限,Backend 无法远程放宽;路由器等低性能设备可调低测试码率和包速率,避免 Probe 自身成为测量瓶颈。部署时可使用仓库的 `packaging/` 文件和安装脚本。
|
||||
|
||||
也可使用 OCI 镜像 `registry.oeo.one/monitor/monitor-probe:<version>`,自动选择 Linux amd64 或 arm64 镜像。容器默认读取 `/etc/monitor/probe.json`,并在同一目录维护 `agents.json` 缓存,因此挂载目录必须允许 UID/GID 1654 读写。建议使用宿主网络,并按 ICMP 测量需求添加 `NET_RAW` 能力。
|
||||
也可使用 OCI 镜像 `registry.oeo.one/moshiro/moshiro-probe:<version>`,自动选择 Linux amd64 或 arm64 镜像。容器默认读取 `/etc/moshiro/probe.json`,并在同一目录维护 `agents.json` 缓存,因此挂载目录必须允许 UID/GID 1654 读写。建议使用宿主网络,并按 ICMP 测量需求添加 `NET_RAW` 能力。
|
||||
|
||||
## 设计说明
|
||||
|
||||
- Probe 只执行编译进程序的测量模块。它不落盘测量数据,也不能执行命令或自行更新(更新由宿主机上的更新器完成,Probe 只写清单和请求文件)。
|
||||
- 测量模块由 `backend/shared/Monitor.Measurement/` 与 Agent 共用;Probe 负责发起连接、调度任务和记录本端数据。
|
||||
- 测量模块由 `backend/shared/MoShiro.Measurement/` 与 Agent 共用;Probe 负责发起连接、调度任务和记录本端数据。
|
||||
- 测量模型和协议细节见 [`../../docs/measurement.md`](../../docs/measurement.md) 与 [`../../docs/protocol.md`](../../docs/protocol.md);整体架构见 [`../../docs/architecture.md`](../../docs/architecture.md)。
|
||||
|
||||
Docker 与 rootless/rootful Podman 共用 `packaging/compose/probe/compose.yaml`,配置、身份和缓存放在命名 volume 中,无需宿主配置目录、keep-id 或手动 chown。首次导入和自动更新见部署文档。
|
||||
+13
-13
@@ -6,10 +6,10 @@ using Fleet.Core;
|
||||
using Fleet.Identity;
|
||||
using Fleet.Link;
|
||||
using Fleet.Rpc;
|
||||
using Monitor.Measurement;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Measurement;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Probe;
|
||||
namespace MoShiro.Probe;
|
||||
|
||||
/// <summary>所有连接共用的东西。</summary>
|
||||
public sealed record ConnectionEnv(NodeIdentity Identity, string ProbeId, ProbeLimits Limits, AgentDirectory Directory, MonoClock Clock, TimeProvider Time, INodeLog Log);
|
||||
@@ -154,7 +154,7 @@ public sealed class AgentConnection
|
||||
for (int i = 0; i < rounds; i++)
|
||||
{
|
||||
long sent = _env.Clock.NowUs();
|
||||
Result<ClockResult> reply = await rpc.RequestAsync(MonitorMethods.Clock, new ClockParams { ProbeMonoUs = sent }, MonitorJsonContext.Default.ClockParams, MonitorJsonContext.Default.ClockResult, ct);
|
||||
Result<ClockResult> reply = await rpc.RequestAsync(MoShiroMethods.Clock, new ClockParams { ProbeMonoUs = sent }, MoShiroJsonContext.Default.ClockParams, MoShiroJsonContext.Default.ClockResult, ct);
|
||||
if (reply.TryGet(out ClockResult? value, out _))
|
||||
{
|
||||
clock.Add(sent, value.AgentMonoUs, _env.Clock.NowUs());
|
||||
@@ -189,7 +189,7 @@ public sealed class AgentConnection
|
||||
var result = new StateSyncResult { AppliedVersion = sync.Version };
|
||||
if (sync.Type == LineTaskSet.StateType)
|
||||
{
|
||||
LineTaskSet? set = sync.Doc.Deserialize(MonitorJsonContext.Default.LineTaskSet);
|
||||
LineTaskSet? set = sync.Doc.Deserialize(MoShiroJsonContext.Default.LineTaskSet);
|
||||
if (set is null)
|
||||
{
|
||||
return Result<StateSyncResult>.Fail(FleetErrors.InvalidParams, "line_task_set could not be parsed");
|
||||
@@ -201,18 +201,18 @@ public sealed class AgentConnection
|
||||
return Result<StateSyncResult>.Ok(result);
|
||||
})
|
||||
.On(
|
||||
MonitorMethods.TestPhase,
|
||||
MonitorJsonContext.Default.TestPhaseStartParams,
|
||||
MonitorJsonContext.Default.TestPhaseStartResult,
|
||||
MoShiroMethods.TestPhase,
|
||||
MoShiroJsonContext.Default.TestPhaseStartParams,
|
||||
MoShiroJsonContext.Default.TestPhaseStartResult,
|
||||
(session, start, _) => ValueTask.FromResult(Result<TestPhaseStartResult>.Ok(new TestPhaseStartResult { Accepted = session.StartPhase(start) })))
|
||||
.On(
|
||||
MonitorMethods.TestPhaseEnd,
|
||||
MonitorJsonContext.Default.TestPhaseEndParams,
|
||||
MonitorJsonContext.Default.TestPhaseEndResult,
|
||||
MoShiroMethods.TestPhaseEnd,
|
||||
MoShiroJsonContext.Default.TestPhaseEndParams,
|
||||
MoShiroJsonContext.Default.TestPhaseEndResult,
|
||||
async (session, end, ct) => Result<TestPhaseEndResult>.Ok(new TestPhaseEndResult { Fragments = await session.EndPhaseAsync(end, ct) }))
|
||||
.OnNotify(
|
||||
MonitorMethods.TestAbort,
|
||||
MonitorJsonContext.Default.TestAbortParams,
|
||||
MoShiroMethods.TestAbort,
|
||||
MoShiroJsonContext.Default.TestAbortParams,
|
||||
async (session, abort, _) => await session.AbortAsync(abort.TestId))
|
||||
.OnNotify(
|
||||
FleetMethods.OutboxAck,
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
using System.Text.Json;
|
||||
using Fleet.Core;
|
||||
using Fleet.Hosting;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Probe;
|
||||
namespace MoShiro.Probe;
|
||||
|
||||
/// <summary>
|
||||
/// Probe 要连接的 Agent 列表:由面板作为期望状态(<c>probe_agents</c>)直接下发;面板连不上时用上一次保存的 <c>agents.json</c>。
|
||||
+5
-5
@@ -1,13 +1,13 @@
|
||||
using System.Text.Json;
|
||||
using Fleet.Core;
|
||||
using Fleet.Link;
|
||||
using Monitor.Measurement;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Measurement;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Probe;
|
||||
namespace MoShiro.Probe;
|
||||
|
||||
/// <summary>
|
||||
/// 估计 Agent 单调时钟 − Probe 单调时钟:每次 <c>monitor.clock</c> 往返取中点,在最近 8 次里取往返最短的一次
|
||||
/// 估计 Agent 单调时钟 − Probe 单调时钟:每次 <c>moshiro.clock</c> 往返取中点,在最近 8 次里取往返最短的一次
|
||||
/// (往返越短,对称性假设的误差越小)。Probe 的列块头里带着这个偏移,Backend 据此对齐两端的时间戳。
|
||||
/// </summary>
|
||||
public sealed class ClockEstimator
|
||||
@@ -82,6 +82,6 @@ public sealed class FragmentShipper : IFragmentSink
|
||||
}
|
||||
}
|
||||
|
||||
_outbox.Enqueue(MonitorChannels.ColumnBlock, header.ChunkId.Value, RawChunkCodec.Encode(new RawChunk(header, streams)));
|
||||
_outbox.Enqueue(MoShiroChannels.ColumnBlock, header.ChunkId.Value, RawChunkCodec.Encode(new RawChunk(header, streams)));
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -4,8 +4,8 @@
|
||||
Condition="'$(UseAotAnywhere)' == 'true'" />
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AssemblyName>monitor-probe</AssemblyName>
|
||||
<RootNamespace>Monitor.Probe</RootNamespace>
|
||||
<AssemblyName>moshiro-probe</AssemblyName>
|
||||
<RootNamespace>MoShiro.Probe</RootNamespace>
|
||||
<IsAotCompatible>true</IsAotCompatible>
|
||||
<PublishAot>true</PublishAot>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
@@ -15,10 +15,10 @@
|
||||
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="Monitor.Backend.Tests" />
|
||||
<InternalsVisibleTo Include="MoShiro.Backend.Tests" />
|
||||
<ProjectReference Include="..\..\..\fleet\src\Fleet.Link\Fleet.Link.csproj" />
|
||||
<ProjectReference Include="..\..\..\fleet\src\Fleet.Hosting\Fleet.Hosting.csproj" />
|
||||
<ProjectReference Include="..\..\..\shared\Monitor.Measurement\Monitor.Measurement.csproj" />
|
||||
<ProjectReference Include="..\..\..\shared\MoShiro.Measurement\MoShiro.Measurement.csproj" />
|
||||
</ItemGroup>
|
||||
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
|
||||
<Import Project="Sdk.targets" Sdk="StuDev.AotAnywhere"
|
||||
+10
-10
@@ -4,10 +4,10 @@ using System.Text.Json;
|
||||
using Fleet.Identity;
|
||||
using Fleet.Link;
|
||||
using Fleet.Rpc;
|
||||
using Monitor.Measurement;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Measurement;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Probe;
|
||||
namespace MoShiro.Probe;
|
||||
|
||||
/// <summary>
|
||||
/// Probe 的组装点:到面板的长连接(身份、Agent 列表、状态)+ 每个 Agent 一个测量连接(认证、重连、角色)。没有全局状态,测试可以在同一进程里启动多个。
|
||||
@@ -15,7 +15,7 @@ namespace Monitor.Probe;
|
||||
/// </summary>
|
||||
public sealed class ProbeApp : IDisposable
|
||||
{
|
||||
public const string Version = Monitor.Protocol.BuildInfo.Version;
|
||||
public const string Version = MoShiro.Protocol.BuildInfo.Version;
|
||||
|
||||
private readonly ConnectionEnv _env;
|
||||
private readonly Dictionary<string, Running> _connections = [];
|
||||
@@ -38,25 +38,25 @@ public sealed class ProbeApp : IDisposable
|
||||
Identity = identity,
|
||||
NodeId = new NodeId(file.ProbeId),
|
||||
NodeVersion = Version,
|
||||
Capabilities = [MonitorCapabilities.Base],
|
||||
HeartbeatExtra = () => JsonSerializer.SerializeToElement(new ProbeHeartbeatExtra { Update = update.ReadStatus() }, MonitorJsonContext.Default.ProbeHeartbeatExtra),
|
||||
HelloMeta = () => JsonSerializer.SerializeToElement(new ProbeHelloMeta { Platform = PlatformDetector.Detect() }, MonitorJsonContext.Default.ProbeHelloMeta),
|
||||
Capabilities = [MoShiroCapabilities.Base],
|
||||
HeartbeatExtra = () => JsonSerializer.SerializeToElement(new ProbeHeartbeatExtra { Update = update.ReadStatus() }, MoShiroJsonContext.Default.ProbeHeartbeatExtra),
|
||||
HelloMeta = () => JsonSerializer.SerializeToElement(new ProbeHelloMeta { Platform = PlatformDetector.Detect() }, MoShiroJsonContext.Default.ProbeHelloMeta),
|
||||
};
|
||||
var list = new StateHandler<ProbeAgentList>(
|
||||
ProbeAgentList.StateType,
|
||||
MonitorJsonContext.Default.ProbeAgentList,
|
||||
MoShiroJsonContext.Default.ProbeAgentList,
|
||||
(version, doc, _) =>
|
||||
{
|
||||
directory.Apply(doc);
|
||||
return ValueTask.FromResult(new StateSyncResult { AppliedVersion = version });
|
||||
});
|
||||
var router = new RpcRouter<LinkContext>()
|
||||
.OnNotify(MonitorMethods.UpdateOffer, MonitorJsonContext.Default.UpdateOfferParams, (_, offer, _) =>
|
||||
.OnNotify(MoShiroMethods.UpdateOffer, MoShiroJsonContext.Default.UpdateOfferParams, (_, offer, _) =>
|
||||
{
|
||||
update.WriteOffer(offer);
|
||||
return ValueTask.CompletedTask;
|
||||
})
|
||||
.OnNotify(MonitorMethods.UpdateApply, MonitorJsonContext.Default.UpdateOfferParams, (_, _, _) =>
|
||||
.OnNotify(MoShiroMethods.UpdateApply, MoShiroJsonContext.Default.UpdateOfferParams, (_, _, _) =>
|
||||
{
|
||||
update.RequestApply();
|
||||
return ValueTask.CompletedTask;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Monitor.Probe;
|
||||
namespace MoShiro.Probe;
|
||||
|
||||
/// <summary>
|
||||
/// <c>probe.json</c>:面板 <c>POST /api/admin/probe/identity</c> 生成的文件(只能下载一次)。
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
using Fleet.Core;
|
||||
using Fleet.Hosting;
|
||||
using Monitor.Probe;
|
||||
using MoShiro.Probe;
|
||||
|
||||
TimeProvider time = TimeProvider.System;
|
||||
INodeLog log = new ConsoleNodeLog(time);
|
||||
@@ -11,7 +11,7 @@ if (PlatformCheck.VerifyCrypto() is { } problem)
|
||||
return 1;
|
||||
}
|
||||
|
||||
string configPath = "/etc/monitor/probe.json";
|
||||
string configPath = "/etc/moshiro/probe.json";
|
||||
for (int i = 0; i < args.Length - 1; i++)
|
||||
{
|
||||
if (args[i] == "--config")
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xunit.v3" />
|
||||
<ProjectReference Include="..\..\src\Monitor.Probe\Monitor.Probe.csproj" />
|
||||
<ProjectReference Include="..\..\src\MoShiro.Probe\MoShiro.Probe.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
using Fleet.Core;
|
||||
using Fleet.Hosting;
|
||||
using Monitor.Protocol;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace Monitor.Probe.Tests;
|
||||
namespace MoShiro.Probe.Tests;
|
||||
|
||||
public sealed class ProbeTests
|
||||
{
|
||||
Reference in new issue
Block a user