Why Nacos Beats Eureka: Hands‑On Guide to Service Discovery, Config Center & Cluster
This article explains Nacos' advantages over Eureka, compares its Raft‑based consistency, details the Spring Cloud Alibaba suite, walks through Nacos architecture, installation, standalone and cluster modes, and provides practical examples of using Nacos as both a service registry and a configuration center in microservice projects.
1. Nacos Advantages
问题,既然有了Eureka ,为啥还要用Nacos?Nacos serves as a core service registration and discovery center for microservices, offering a new choice beyond Eureka and Consul. It is ready to use out of the box, easy to get started, and has shown no major pitfalls so far.
1.1 Comparison with Eureka
1. Eureka 2.0 is closed source. 2. According to the official website, Nacos registers more instances than Eureka. 3. Nacos uses the Raft protocol, giving its cluster consistency far higher than Eureka's.
Raft, a distributed consistency protocol published in 2013, has become popular due to its relative simplicity and ease of implementation compared with other algorithms.
Raft Data Consistency Strategy The Raft protocol heavily relies on a Leader node to ensure cluster data consistency. Client data first reaches the Leader, which marks it as uncommitted, then replicates it to all Followers. After receiving acknowledgments from a majority of Followers, the Leader marks the data as committed and notifies the client, finally informing all Followers of the committed state.
1.2 Comparison with Spring Cloud Config
Three Major Advantages
Spring Cloud Config typically uses Git; dynamic changes still require Spring Cloud Bus to propagate changes to all clients.
Spring Cloud Config does not provide a visual interface.
Nacos Config uses long connections for updates, notifying providers instantly and outperforming Spring Cloud Config by a large margin.
2. Spring Cloud Alibaba Suite
The current Spring Cloud Alibaba suite mainly includes three components:
Nacos: a dynamic service discovery, configuration management, and service management platform for building cloud‑native applications.
Sentinel: protects service stability from traffic control, circuit breaking, and system load perspectives.
AliCloud OSS: Alibaba Cloud Object Storage Service, a massive, secure, low‑cost, highly reliable cloud storage solution.
Comparison between Spring Cloud Alibaba and Spring Cloud Netflix Suites
By examining component functionalities, the correspondence is roughly:
Nacos = Eureka/Consul + Config + Admin
Sentinel = Hystrix + Dashboard + Turbine
Dubbo = Ribbon + Feign
RocketMQ = RabbitMQ
Schedulerx = Quartz
AliCloud OSS, AliCloud SLS are unique; tracing (Sleuth, Zipkin) may be integrated into Sentinel.
3. Nacos Architecture and Installation
3.1 Nacos Architecture
The diagram shows that Nacos integrates service registration, discovery, configuration, and management functions, essentially a combination of Eureka/Consul + Config + Admin.
Besides Spring Cloud integration, Nacos can also be integrated with plain Spring and Spring Boot.
In this tutorial we focus only on Spring Cloud integration.
3.2 Download and Install Nacos Server
Before using Nacos, download it and start the Nacos Server.
Installation reference tutorial: https://www.cnblogs.com/crazymakercircle/p/11992539.html
4. Running Nacos Server
4.1 Two Modes
Nacos Server can run in two modes:
standalone
cluster
4.2 Standalone Mode
This mode is typically used for demos and tests; no configuration changes are needed. Execute the following command: sh bin/startup.sh -m standalone On Windows: cmd bin/startup.cmd -m standalone Then open http://cdh1:8848/nacos/index.html to see the console.
Default username and password are nacos nacos.
4.3 Cluster Mode
For production environments, use cluster mode.
Cluster mode requires MySQL and modifications to two configuration files:
conf/cluster.conf
conf/application.propertiesIn cluster.conf list the IPs of the machines that will run Nacos Server:
192.168.100.155
192.168.100.156In application.properties add MySQL settings:
db.num=1
db.url.0=jdbc:mysql://localhost:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=rootCreate a database named nacos_config and import the tables from conf/nacos-mysql.sql.
4.4 Where Does Nacos Server Store Configuration Data?
问题来了: Nacos Server 的配置数据是存在哪里呢?Without any custom configuration, Nacos stores data in two possible locations:
Memory
Local database
After restarting the server, the previously added nacos.properties configuration persists, indicating it is not stored in memory.
Inspecting NACOS_PATH/data reveals a derby-data directory where the configuration data is stored.
Derby is a Java‑written open‑source database from the Apache project.
If you switch the data source to MySQL, it works as well, but MySQL 8.0 is not supported.
Note: MySQL 8.0 is not supported.
Key points:
standalone uses Derby even if MySQL is configured; cluster mode automatically uses MySQL and will error if MySQL is not configured.Example cluster.conf:
#it is ip
#example
10.10.109.214
11.16.128.34
11.16.128.36After completing the configuration, start Nacos Server to see the effect.
5. Practical Example 1: Using Nacos as a Service Registry
Project Structure
The demo project has the following directory layout:
5.1 How to Use Nacos Client Component
First, import the Spring Cloud Alibaba BOM
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/>
</parent>
<properties>
<spring-cloud.version>Finchley.SR2</spring-cloud.version>
<spring-cloud-alibaba.version>0.2.0.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>Version incompatibilities may arise; for example, Spring Boot 2.0.6.RELEASE throws
java.lang.NoClassDefFoundError: org/springframework/core/env/EnvironmentCapable.
5.2 Demo Module Structure
The service registry and discovery are provided by Nacos Server; we only need to register services.
Two services are simulated: provider and consumer.
alibaba
├── service-provider-demo
│ ├── pom.xml
│ └── src
└── service-consumer-demo
├── pom.xml
└── src5.3 Provider Microservice
step1: Add dependencies to the provider and consumer pom files
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>step2: Main class
package com.crazymaker.cloud.nacos.demo.starter;
import com.crazymaker.springcloud.standard.context.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.List;
@EnableSwagger2
@SpringBootApplication
@EnableDiscoveryClient
@Slf4j
public class ServiceProviderApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(ServiceProviderApplication.class, args);
Environment env = applicationContext.getEnvironment();
String port = env.getProperty("server.port");
String path = env.getProperty("server.servlet.context-path");
System.out.println("
--------------------------------------
\t" +
"Application is running! Access URLs:
\t" +
"Local: \t\thttp://localhost:" + port + path + "/index.html
\t" +
"swagger-ui: \thttp://localhost:" + port + path + "/swagger-ui.html
\t" +
"----------------------------------------------------------");
}
}step3: Rest service interface
package com.crazymaker.cloud.nacos.demo.controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/echo")
public class EchoController {
// Echo service
@RequestMapping(value = "/{string}", method = RequestMethod.GET)
public String echo(@PathVariable String string) {
return "echo: " + string;
}
}step4: Configuration file
spring:
application:
name: service-provider-demo
cloud:
nacos:
discovery:
server-addr: ${NACOS_SERVER:cdh1:8848}
server:
port: 18080step5: After starting, access via Swagger UI
5.4 Consumer Microservice Demonstrating RPC Remote Call
In NacosConsumerApplication integrate RestTemplate and Ribbon.
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}Consumer controller class
package com.crazymaker.cloud.nacos.demo.consumer.controller;
import com.crazymaker.cloud.nacos.demo.consumer.client.EchoClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/echo")
@Api(tags = "Service - Consumer")
public class EchoConsumerController {
@Resource
EchoClient echoClient;
@ApiOperation(value = "Consume echo service interface")
@RequestMapping(value = "/{string}", method = RequestMethod.GET)
public String echoRemoteEcho(@PathVariable String string) {
return "provider echo is:" + echoClient.echo(string);
}
}Consumer configuration file
spring:
application:
name: sevice-consumer-demo
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
server:
port: 18081Swagger UI for consumer
Remote echo API results:
5.5 Demo URLs
Provider:
http://localhost:18080/provider/swagger-ui.html#/Echo_%E6%BC%94%E7%A4%BAConsumer:
http://localhost:18081/consumer/swagger-ui.html#/服务-消费者/echoRemoteEchoUsingGETNacos console:
http://cdh1:8848/nacos/index.html#/serviceManagement?dataId=&group=&appName=&namespace=5.6 Nacos Console
The console displays the list of registered services and their details.
6. Practical Example 2: Using Nacos as a Configuration Center
6.1 Basic Concepts
1. Profile
Java projects often have multiple profiles (dev, test, pre‑prod, prod) each represented by a separate properties or YAML file. The active profile is selected via spring.profiles.active.
spring:
application:
name: sharding-jdbc-provider
jpa:
hibernate:
ddl-auto: none
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
show-sql: true
profiles:
active: sharding-db-tableNacos Config moves these files into a unified configuration center, enabling real‑time updates.
2. Data ID
Each profile corresponds to a Data ID in Nacos. The naming format is ${prefix}-${spring.profiles.active}.${file-extension}.
Prefix defaults to spring.application.name but can be set via spring.cloud.nacos.config.prefix. spring.profiles.active provides the environment name.
File extension is configurable via spring.cloud.nacos.config.file-extension.
3. Group
The default group is DEFAULT_GROUP; it can be changed with spring.cloud.nacos.config.group to avoid name collisions.
After configuration, use @RefreshScope and @Value as with Spring Cloud Config.
6.2 Add Configuration via Nacos Console
Create two Data IDs: nacos-config-demo-dev.yaml for the development environment. nacos-config-demo-test.yaml for the test environment.
Both are created through the Nacos configuration UI (screenshots omitted).
6.3 Use Nacos Config Client Component
1. Add dependency
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${nacos.version}</version>
</dependency>2. Main class
package com.crazymaker.cloud.nacos.demo.consumer.starter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@EnableSwagger2
@EnableDiscoveryClient
@Slf4j
@SpringBootApplication(
scanBasePackages = {
"com.crazymaker.cloud.nacos.demo",
"com.crazymaker.springcloud.standard"
},
exclude = {SecurityAutoConfiguration.class,
// exclude DB auto‑configuration
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class,
// exclude Redis auto‑configuration
RedisAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class})
@EnableFeignClients(basePackages = {"com.crazymaker.cloud.nacos.demo.consumer.client"})
public class ConfigDomeProviderApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = null;
try {
applicationContext = SpringApplication.run(ConfigDomeProviderApplication.class, args);
System.out.println("Server startup done.");
} catch (Exception e) {
log.error("服务启动报错", e);
return;
}
Environment env = applicationContext.getEnvironment();
String port = env.getProperty("server.port");
String path = env.getProperty("server.servlet.context-path");
System.out.println("
----------------------------------------------------------
\t" +
"Application is running! Access URLs:
\t" +
"Local: \t\thttp://localhost:" + port + path + "/index.html
\t" +
"swagger-ui: \thttp://localhost:" + port + path + "/swagger-ui.html
\t" +
"----------------------------------------------------------");
}
}3. Controller to read configuration
package com.crazymaker.cloud.nacos.demo.config.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/config")
@Api(tags = "Nacos Configuration Center Demo")
public class ConfigGetController {
@Value("${foo.bar:empty}")
private String bar;
@Value("${spring.datasource.username:empty}")
private String dbusername;
@ApiOperation(value = "Get configuration value of bar")
@RequestMapping(value = "/bar", method = RequestMethod.GET)
public String getBar() {
return "bar is :" + bar;
}
@ApiOperation(value = "Get DB username from configuration")
@RequestMapping(value = "/dbusername", method = RequestMethod.GET)
public String getDbusername() {
return "db username is :" + dbusername;
}
}4. bootstrap.yml
spring:
application:
name: nacos-config-demo-provider
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: ${NACOS_SERVER:cdh1:8848}
config:
server-addr: ${NACOS_SERVER:cdh1:8848}
prefix: nacos-config-demo
group: DEFAULT_GROUP
file-extension: yaml
server:
port: 18083
servlet:
context-path: /config6.4 Test Result
Start the application and open Swagger UI at http://localhost:18083/config/swagger-ui.html#.
The API returns the expected configuration values:
6.5 Mapping Configuration Files
Use config.prefix to map the main configuration file.
Use spring.cloud.nacos.config.ext-config to map additional files, e.g.:
spring:
application:
name: nacos-config-demo-provider
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: ${NACOS_SERVER:cdh1:8848}
config:
server-addr: ${NACOS_SERVER:cdh1:8848}
prefix: nacos-config-demo
group: DEFAULT_GROUP
file-extension: yaml
ext-config:
- data-id: crazymaker-db-dev.yml
group: DEFAULT_GROUP
refresh: true
- data-id: crazymaker-redis-dev.yml
group: DEFAULT_GROUP
refresh: true
- data-id: crazymaker-common-dev.yml
group: DEFAULT_GROUP
refresh: true
- data-id: some.properties
group: DEFAULT_GROUP
refresh: trueAfter starting, the application can retrieve values from these additional Data IDs.
7. Configuration Isolation
Real‑world applications often require isolation across environments, projects, and modules.
Development, test, pre‑production, and production environments need separation.
Different projects need isolation.
Within the same project, different modules need isolation.
Three mechanisms provided by Nacos achieve isolation:
Server address: spring.cloud.nacos.config.server-addr Namespace (use the namespace ID, not the name): spring.cloud.nacos.config.namespace Group:
spring.cloud.nacos.config.group8. Nacos Cluster Setup
In cluster mode, an external database (MySQL) is required for shared data.
Cluster deployment can be fronted by Nginx for load balancing:
IP Planning
For a quick local test, copy the Nacos package into three directories (e.g., nacos, nacos1, nacos2) and modify the ports.
Edit conf/application.properties to use MySQL:
# Specify MySQL as the data source
spring.datasource.platform=mysql
# Database instance count
db.num=1
db.url.0=jdbc:mysql://localhost:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456Change server.port for the additional instances (e.g., 8847 and 8846).
Initialize the database using conf/nacos-mysql.sql.
Rename conf/cluster.conf.example to conf/cluster.conf and list the three nodes:
127.0.0.1:8848
127.0.0.1:8847
127.0.0.1:8846Start each instance with ./startup.sh; the default mode is cluster.
Cluster Usage
Nacos cluster can be accessed in four ways:
Direct IP: http://ip1:port/openAPI VIP (high availability): http://VIP:port/openAPI Domain name: http://nacos.com:port/openAPI Reverse proxy:
http://proxy:port/openAPIReverse proxy example using Nginx:
upstream nacos_server {
server 127.0.0.1:8848;
server 127.0.0.1:8847;
server 127.0.0.1:8846;
}
server {
listen 8648;
server_name localhost;
location / {
proxy_pass http://nacos_server;
index index.html index.htm;
}
}Accessing the cluster via the proxy (e.g., http://localhost:8648/nacos/#/clusterManagement) shows the cluster management UI.
Even if one Nacos node is killed, the service continues to operate, demonstrating high availability.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
