Spring Cloud Distributed Deployment Guide: Deploy Microservices with Nacos, MySQL, and Gateway

Technical Specifications at a Glance

Parameter Details
Tech Stack Spring Cloud, Spring Boot, Nacos, MySQL, Gateway
Runtime Language Java
Deployment Environment Linux (CentOS/Ubuntu)
Communication Protocols HTTP, TCP/IP
Registry Port 8848
Database Port 3306
Gateway Port 8080
Service Ports 10030 (Product), 10040 (Order)
GitHub Stars Not provided in the source
Core Dependencies JDK 17, MySQL, Nacos, Spring Cloud Gateway

This deployment path provides a practical Spring Cloud distributed architecture

The real value of the original material is not the installation commands. It provides a minimum viable production deployment path: centralized database storage, centralized service registration with Nacos, horizontal scaling through multiple business service instances, and a unified traffic entry through Gateway.

This architecture solves several limitations of single-node deployments: hard-coded service addresses, poor scalability, fragmented entry points, and unstable cross-host communication. For beginners, it also marks the first step from running services in a local IDE to deploying them in a real server environment.

A recommended four-server deployment topology

Server Deployed Components Purpose
Server 1 MySQL + Nacos Provides data storage and service registration
Server 2 Product Service 1 + Order Service 1 First group of business instances
Server 3 Product Service 2 + Order Service 2 Second group of business instances for Load Balancing
Server 4 Gateway Unified entry point and route forwarding

This topology is not the only valid option, but it works especially well for learning and validation environments. If resources are limited, you can compress it into a single-server or two-server setup, although that reduces the distributed effect.

MySQL must support cross-server access first

Once you deploy microservices across multiple hosts, several service instances will run on different machines. That means the database cannot listen only on the local loopback address. The most critical step in the original content is to create a remote-access user and update MySQL’s bind address.

CREATE USER 'bite'@'%' IDENTIFIED BY '[email protected]'; -- Create a user that can log in remotely
GRANT ALL ON *.* TO 'bite'@'%'; -- Grant access to all databases and tables
FLUSH PRIVILEGES; -- Apply privilege changes immediately

This SQL allows MySQL access from any source IP, which is suitable for validating connectivity in a learning environment.

sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
# Change bind-address from 127.0.0.1 to 0.0.0.0 to allow external connections
sudo systemctl restart mysql

After this step, the database can actually serve microservice instances across multiple nodes.

A remote connection test helps expose the real problem boundary

mysql -h<Server-IP> -P3306 -ubite [email protected]
# If you enter the MySQL shell successfully, the account, network, and port are all working correctly

This command helps you quickly determine whether the problem lies in database configuration, network policy, or account permissions.

Nacos acts as the central hub for service registration and configuration

In this architecture, Nacos acts as both the service registry and the configuration center. All Product services, Order services, and the Gateway must be able to access the same Nacos node. Otherwise, service discovery will fail.

Deployment itself is straightforward. The key constraints are these: the server must have JDK 1.8+ or JDK 17 installed, and the firewall or security group must allow port 8848. If you can access `http://

:8848/nacos`, that only confirms that the console is reachable. It does not guarantee that business services are registered successfully. ### Successful service registration depends on both network reachability and the correct registered IP In cross-server deployments, many projects fail not because the JAR cannot start, but because the service registers the wrong private IP into Nacos. When the Gateway or another instance retrieves that address, the call still fails in practice. “`bash nohup java -jar product-service-1.0-SNAPSHOT.jar \ –spring.cloud.nacos.discovery.ip= \ > logs/product.log & nohup java -jar order-service-1.0-SNAPSHOT.jar \ –spring.cloud.nacos.discovery.ip= \ > logs/order.log & “` The key point in these commands is not `nohup`. It is the explicit `spring.cloud.nacos.discovery.ip` setting, which prevents the instance from registering the wrong private network address. ## Multi-instance deployment determines whether Load Balancing actually works Product Service and Order Service should usually each run at least two instances on different nodes. That way, when Gateway forwards requests by service name, the underlying system can apply round-robin or another load-balancing strategy. The original content uses port 10030 for Product Service and 10040 for Order Service. After deployment, you should validate each instance endpoint directly before going through the Gateway. Otherwise, it becomes difficult to isolate the source of the problem. “`bash curl http://:10030/product/1001 curl http://:10040/order/1 # If JSON is returned, the application process, port listener, and controller route are all working correctly “` This step confirms that an individual business instance is healthy and serves as a required prerequisite before Gateway integration testing. ## Gateway provides a unified entry point and service routing In production deployments, Gateway hides backend instance details and allows clients to maintain only one entry address. It can also support authentication, rate limiting, canary releases, and other capabilities later. “`bash nohup java -jar gateway-1.0-SNAPSHOT.jar \ –server.port=8080 \ > logs/gateway.log & “` This command starts the unified entry service and exposes port 8080 by default. ### Successful access through the Gateway proves that the full request chain is working “`bash curl http://:8080/product/1001 curl http://:8080/order/1 # If business data is returned, the Gateway, registry, and backend instances are working together correctly “` This step validates the complete call path: client → Gateway → Nacos → business instance → database, not just the availability of one isolated service. ## You must identify these common failure points before production First, if MySQL does not allow remote access, services will fail to start because database connections cannot be established. Second, Nacos may be reachable while services are still not registered correctly, which commonly happens when the registered IP is wrong. Third, if the security group does not allow 3306, 8848, 8080, 10030, and 10040, services may appear to start successfully but remain unreachable from outside. Fourth, if the log directory does not exist in advance or permissions are insufficient, `nohup` output may fail, which makes troubleshooting harder. Fifth, if you test the Gateway before testing individual instances, you can easily misdiagnose the issue. For that reason, always follow this validation order: database → Nacos → single instance → Gateway. ### A minimal troubleshooting checklist “`bash ss -lntp | grep -E ‘3306|8848|8080|10030|10040’ # Check port listeners curl http://:8848/nacos/ # Check registry reachability tail -f logs/product.log # View service startup logs in real time “` Use these commands to quickly locate issues across network connectivity, process state, and application logs. ## This guide works well as a microservices deployment template If you are moving a local Spring Cloud project to cloud servers, this approach is valuable because the path is clear, the component set is minimal, and the validation points are explicit. Although it is a learning-oriented deployment model, it already covers the essential structure for service discovery, unified ingress, and multi-instance scaling. As the system evolves, you can extend it with Docker, Kubernetes, configuration isolation, health checks, monitoring and alerting, and CI/CD pipelines, allowing the platform to move from simply being deployable to being sustainably operable. ## FAQ ### Why does the service start successfully but remain inaccessible through the Gateway? The most common reason is that the service registered the wrong private IP in Nacos. In cross-public-network deployments, you should explicitly set `spring.cloud.nacos.discovery.ip` to the address that other nodes can actually reach. ### Why can I open the Nacos console, but service-to-service calls still fail? A reachable console only means port 8848 is open. It does not mean the instance registration data is correct. You still need to verify instance status, registered IP, service port, and the security group configuration on the target service host. ### Can this deployment approach be used directly in production? It can serve as a production prototype, but you still need to add high-availability design elements such as MySQL primary-replica replication, a Nacos cluster, multiple Gateway replicas, environment-based configuration isolation, centralized log collection, and monitoring and alerting. **Core Summary:** This article reconstructs the standard process for moving Spring Cloud microservices from local development to multi-server deployment. It covers MySQL remote authorization, Nacos service registration, multi-instance deployment for Product and Order services, unified ingress through Gateway, and the most important troubleshooting points. It works well as both an introduction to distributed deployment and a practical deployment template.