---
title: "LoadBalance、服务发现与节点选择"
---

服务发现回答“有哪些实例”，负载均衡回答“本次选哪一个”。在 Solon 中，`LoadBalance` 是一个很小的适配接口，Nami 和 HTTP 工具都可以通过它获得上游地址。

### 1、 读取服务名对应的节点

```java
import org.noear.solon.core.LoadBalance;

LoadBalance balance = LoadBalance.get("userapi");
String server = balance.getServer();
```

带分组：

```java
LoadBalance balance = LoadBalance.get("demo", "userapi");
String server = balance.getServer();
```

当前源码中：

- `get(String service)` 等价于空 group。
- `getServer()` 默认调用 `getServer(0)`。
- `getServer(int port)` 是接口必须实现的方法。
- 找不到底层负载器时，包装器可能返回 `null`；调用前要做好配置和空值检查。

### 2、 `parse` 的两类输入

```java
LoadBalance.parse("userapi");
LoadBalance.parse("lb://userapi");
LoadBalance.parse("http://localhost:9001");
```

源码会把不含 `://` 的字符串当服务名；`lb://` 表示从负载均衡器取得节点；普通 `http://` 则包装成固定 server。不要把任意业务 URL 当成服务名。

### 3、 自定义负载均衡器

最小实现：

```java
import org.noear.solon.core.LoadBalance;

public class MyLoadBalance implements LoadBalance {
    @Override
    public String getServer(int port) {
        if (port > 0) {
            return "http://127.0.0.1:" + port;
        }
        return "http://127.0.0.1:9001";
    }
}
```

如果要按轮询、权重或健康状态选择多个地址，应在实现内部维护节点列表和策略；不要在 `getServer` 中每次无条件返回同一个地址却把它称为负载均衡。

### 4、 工厂接入

一般不这么做，避免破坏 Solon Cloud Discovery/LoadBalance 插件的接入

```java
public class MyLoadBalanceFactory implements LoadBalance.Factory {
    @Override
    public LoadBalance create(String group, String service) {
        if ("demo".equals(group) && "userapi".equals(service)) {
            return new MyLoadBalance();
        }
        return null;
    }
}
```

`Factory` 的签名是 `create(String group, String service)`。未匹配的服务应返回 `null`，让其他工厂或默认机制处理；不要返回一个错误实例导致所有未知服务都指向错误地址。具体注册方式取决于应用容器，可作为 Solon Bean 注册。

### 5、 与 Nami 配合

```java
UserService service = Nami.builder()
    .name("userapi")
    .group("demo")
    .path("/rpc/v1/user")
    .create(UserService.class);
```

普通项目优先使用 Solon Cloud 的 Discovery/LoadBalance 插件。只有需要特殊节点来源、灰度规则或自定义权重时，才实现自己的 `LoadBalance.Factory`。

### 6、不要混淆三层配置

```text
solon.app.name       → 当前应用注册名
NamiClient.name      → 要调用的服务名/负载名称
@Mapping             → 服务的 HTTP 路径
```

三者可以文字相同，但语义不同。排查多实例调用时按“服务名 → group → 节点 URL → path”逐项打印和核对。