For high-QPS, high-traffic services such as image services, calling services through a VPC direct connection significantly improves performance and reduces latency. However, this method does not provide load balancing across multiple service instances. If you already use Nacos in your microservices architecture, you can integrate it with EAS to manage service access and enable client-side load balancing. This topic explains how to call an EAS service by associating it with a Nacos instance.
Nacos integration does not currently support intelligent routing for LLMs.
How it works
After you configure a VPC for an EAS service, the system assigns a VPC IP address to each pod of the service.
EAS registers the pods of the inference service with the associated Nacos instance.
The client subscribes to service registration events from Nacos.
Nacos pushes changes to the EAS service's IP address list to the client.
The client uses an SDK to select an instance. The SDK includes a built-in weighted round-robin (WRR) load balancing algorithm.
The client uses the IP address and port returned by the SDK to call the service.
Configuration methods
Console configuration
On the deployment configuration page, in the Network Information section, configure the VPC and enable Service Discovery Nacos.
Configure the VPC. To associate with Nacos, you must configure a VPC, vSwitch, and security group for the EAS service. If you have not created them, see Create and manage a VPC and Manage security groups.
The Nacos instance must be in the same VPC and vSwitch as the EAS service.
Ensure that the vSwitch's CIDR block has enough available IP addresses.
ImportantNetwork access between the client (such as an ECS instance) and the EAS service instances is controlled by security group rules.
By default, instances within the same basic security group can communicate with each other over the internal network. You can configure the EAS service to use the same security group as the client ECS instance that needs to access it.
If the client and the EAS service use different security groups, you must add rules to allow communication between them. For more information, see Enable internal communication between instances in different security groups of a classic network.
Enable Service Discovery Nacos and select a Nacos instance from the dialog box that appears. If you do not have one, Create an MSE registry instance first.
You can associate multiple Nacos instances with a single service for disaster recovery. The service is registered with all associated instances.
JSON configuration
The following JSON parameters are required to associate a Nacos instance. For more information about each parameter, see Configure in the console.
Parameter | Description | ||
cloud | networking | vpc_id | The IDs of the VPC, vSwitch, and security group for the EAS service. |
vswitch_id | |||
security_group_id | |||
networking | nacos | nacos_id | The ID of the Nacos instance that you created. |
Example configuration:
{
"cloud": {
"networking": {
"security_group_id": "sg-*****",
"vpc_id": "vpc-***",
"vswitch_id": "vsw-****"
}
},
"networking": {
"nacos": [
{
"nacos_id": "mse_regserverless_cn-****"
}
]
}
}Verify service registration
After the service is deployed, EAS registers it with the associated Nacos instance. The registration information is as follows:
cluster: Defaults to the
DEFAULTcluster.namespace: The default public namespace.
serviceName: Your service name.
groupName: A system-generated value:
pai-eas.
Verify that the service information is correct:

Verify that the number of instances and their status are correct:

Calling from a client
Go
package main
import (
"fmt"
"github.com/nacos-group/nacos-sdk-go/v2/clients"
"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client"
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
"github.com/nacos-group/nacos-sdk-go/v2/model"
"github.com/nacos-group/nacos-sdk-go/v2/util"
"github.com/nacos-group/nacos-sdk-go/v2/vo"
"strconv"
"testing"
"time"
)
var Clients = make(map[string]NacosClientManager)
type NacosClientManager struct {
userId string
endPoint string
client naming_client.INamingClient
}
func NewAndGetNacosClient(userId string, endPoint string) (*NacosClientManager, error) {
key := generateKey(userId, endPoint)
client, exists := Clients[key]
if exists {
return &client, nil
}
client, exists = Clients[key]
if exists {
return &client, nil
}
newClient, err := clients.NewNamingClient(
vo.NacosClientParam{
ClientConfig: constant.NewClientConfig(
constant.WithNamespaceId(""),
constant.WithTimeoutMs(5000),
constant.WithNotLoadCacheAtStart(true),
constant.WithLogDir("/tmp/nacos/log"),
constant.WithCacheDir("/tmp/nacos/cache"),
constant.WithLogLevel("debug"),
),
ServerConfigs: []constant.ServerConfig{
*constant.NewServerConfig(endPoint, 8848, constant.WithContextPath("/nacos")),
},
},
)
if err != nil {
return nil, err
}
nacosClient := NacosClientManager{
userId: userId,
endPoint: endPoint,
client: newClient,
}
Clients[key] = nacosClient
return &nacosClient, nil
}
func (p *NacosClientManager) SelectOneHealthyInstance(param vo.SelectOneHealthInstanceParam) (*model.Instance, error) {
instance, err := p.client.SelectOneHealthyInstance(param)
if err != nil {
return nil, fmt.Errorf("SelectOneHealthyInstance failed: %v", err)
}
fmt.Printf("SelectOneHealthyInstance success, param: %+v\n", param)
return instance, nil
}
func (p *NacosClientManager) Subscribe(service string, group string) error {
subscribeParam := &vo.SubscribeParam{
ServiceName: service,
GroupName: group,
SubscribeCallback: func(services []model.Instance, err error) {
fmt.Printf("callback return services:%s \n\n", util.ToJsonString(services))
},
}
return p.client.Subscribe(subscribeParam)
}
func generateKey(userId string, endPoint string) string {
return userId + fmt.Sprintf("-%s", endPoint)
}
func Test(t *testing.T) {
nacosClient, err := NewAndGetNacosClient("yourAliyunUid", "yourNacosEndpoint")
if err != nil {
panic(err)
}
nacosClient.Subscribe("your_service", "pai-eas")
params := vo.SelectOneHealthInstanceParam{
ServiceName: "your_service",
GroupName: "pai-eas",
}
instance, err := nacosClient.SelectOneHealthyInstance(params)
fmt.Println(instance)
// Replace the host with the IP address and port from your invocation information in the console.
url := fmt.Sprintf("http://%s:%s/api/predict/xxxxxxx", instance.Ip, strconv.FormatUint(instance.Port, 10))
fmt.Println(url)
// TODO: Invoke the service by using the URL.
} Python
The official Nacos Python SDK lacks a built-in load balancing algorithm, so you must implement your own, such as weighted round-robin.
Install dependencies
pip install nacos-sdk-pythonCall the service
# -*- coding: utf8 -*-
import nacos
# Nacos server configuration
SERVER_ADDRESSES = "yourNacosEndpoint"
NAMESPACE = "" # Use default namespace if empty
SERVICE_NAME = "your_service"
GROUP_NAME = "pai-eas"
# Create Nacos client
client = nacos.NacosClient(SERVER_ADDRESSES, namespace=NAMESPACE)
def callback(args):
print(args)
if __name__ == '__main__':
# Correctly pass the callback function as a list
client.add_config_watchers(SERVICE_NAME, "pai-eas", [callback])
# Fetch and print naming instance details
b = client.list_naming_instance(SERVICE_NAME, None, None, GROUP_NAME, True)
print(b)
if b"hosts":
print("ip", b["hosts"][0]["ip"])
ip = b["hosts"][0]["ip"]
port = b["hosts"][0]["port"]
# Replace the host with the IP address and port from your invocation information in the console.
url = f"http://{ip}:{port}/api/predict/xxxxxxx"
print(url)
# TODO: Invoke the service by using the URL. Java
Add the Maven dependency
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>2.3.2</version>
</dependency>Call the service
package test;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.AbstractEventListener;
import com.alibaba.nacos.api.naming.listener.Event;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import com.alibaba.nacos.api.naming.pojo.Instance;
public class NacosTest {
public static void main(String[] args) {
try {
String serverAddr = "yourNacosEndpoint:8848";
NamingService namingService = NacosFactory.createNamingService(serverAddr);
ExecutorService executorService = Executors.newFixedThreadPool(1);
EventListener serviceListener = new AbstractEventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
System.out.println(((NamingEvent) event).getServiceName());
System.out.println(((NamingEvent) event).getGroupName());
}
}
@Override
public Executor getExecutor() {
return executorService;
}
};
namingService.subscribe("your_service", "pai-eas", serviceListener);
Instance instance = namingService.selectOneHealthyInstance("your_service", "pai-eas");
System.out.println(instance.getIp());
System.out.println(instance.getPort());
// Replace the host with the IP address and port from your invocation information in the console.
String url = String.format("http://%s:%d/api/predict/xxxxxxx", instance.getIp(), instance.getPort());
System.out.println(url);
// TODO: Invoke the service by using the URL.
} catch (NacosException e) {
e.printStackTrace();
}
}
}