Java 互联网微服务架构实战:从零构建高可用分布式系统

11 阅读6分钟

在互联网高并发、海量数据的时代,单体应用已难以满足业务快速迭代和弹性伸缩的需求。微服务架构凭借其服务拆分、独立部署、技术异构等优势,成为 Java 互联网开发的主流范式。然而,从零搭建一套完整的微服务基础设施绝非易事——服务注册发现、配置管理、API 网关、熔断降级、链路追踪、容器化部署……每个环节都充满挑战。

本文将带你从零构建一个生产级 Java 微服务系统,采用 Spring Boot 3 + Spring Cloud 2023 生态,涵盖 Nacos(服务注册+配置中心)、Spring Cloud Gateway(网关)、OpenFeign(声明式调用)、Sentinel(熔断限流)、Zipkin(链路追踪)、Docker 容器化 等核心组件。全部代码(含配置文件和 Java 类)总计超过 2500 字符,并提供完整的启动脚本和测试用例,助你快速掌握互联网微服务开发的全链路技能。


1. 系统架构全景图

组件技术选型职责
服务注册/配置中心Nacos 2.3服务发现、动态配置管理
API 网关Spring Cloud Gateway 4.1路由转发、鉴权、限流
服务提供者Spring Boot 3.2 + MyBatis-Plus业务服务(订单/用户)
服务消费者OpenFeign + LoadBalancer声明式远程调用
熔断限流Sentinel 1.8流量控制、熔断降级
链路追踪Micrometer + Zipkin分布式调用链监控
部署Docker + Docker Compose容器化一键启动

我们将实现 用户服务(user-service)  和 订单服务(order-service) ,订单服务通过 Feign 调用用户服务,并演示配置动态刷新、熔断降级和网关路由。


2. 环境准备与项目初始化

2.1 基础环境

  • JDK 17+
  • Maven 3.9+
  • Docker & Docker Compose(用于 Nacos、Sentinel、Zipkin)
  • IDE(IntelliJ IDEA 或 VS Code)

2.2 父工程 POM(版本管理)

创建 microservice-parent,pom.xml 核心依赖管理(约 200 字符):

xml

<properties>
    <java.version>17</java.version>
    <spring-boot.version>3.2.5</spring-boot.version>
    <spring-cloud.version>2023.0.1</spring-cloud.version>
    <alibaba-cloud.version>2023.0.1.0</alibaba-cloud.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.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>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>${alibaba-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

2.3 启动基础设施(Docker Compose)

创建 docker-compose.yml 启动 Nacos、Sentinel、Zipkin(约 150 字符):

yaml

version: '3'
services:
  nacos:
    image: nacos/nacos-server:v2.3.0
    container_name: nacos
    ports:
      - "8848:8848"
    environment:
      MODE: standalone
  sentinel:
    image: bladex/sentinel-dashboard:1.8.6
    container_name: sentinel
    ports:
      - "8858:8858"
  zipkin:
    image: openzipkin/zipkin:latest
    container_name: zipkin
    ports:
      - "9411:9411"

运行:docker-compose up -d。


3. 服务注册与配置中心(Nacos)

3.1 用户服务(user-service)核心代码

(1)pom.xml 依赖(约 100 字符)

xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

(2)bootstrap.yml 配置(约 120 字符)

yaml

spring:
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
      config:
        server-addr: localhost:8848
        file-extension: yaml
        refresh-enabled: true
server:
  port: 8081
management:
  endpoints:
    web:
      exposure:
        include: health,info,refresh

(3)用户实体与 Controller(约 250 字符)

java

package com.demo.user.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Long id;
    private String username;
    private String email;
}

// Controller
package com.demo.user.controller;

import com.demo.user.entity.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/users")
@RefreshScope  // 支持配置动态刷新
public class UserController {

    @Value("${user.default.role:guest}")
    private String defaultRole;

    // 模拟数据库
    private static final Map<Long, User> userMap = new HashMap<>();
    static {
        userMap.put(1L, new User(1L, "张三", "zhangsan@demo.com"));
        userMap.put(2L, new User(2L, "李四", "lisi@demo.com"));
    }

    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        User user = userMap.get(id);
        if (user == null) {
            throw new RuntimeException("用户不存在: " + id);
        }
        return user;
    }

    @GetMapping("/role")
    public String getDefaultRole() {
        return "当前默认角色: " + defaultRole;
    }

    @PostMapping("/add")
    public User addUser(@RequestBody User user) {
        user.setId(System.currentTimeMillis());
        userMap.put(user.getId(), user);
        return user;
    }
}

(4)启动类

java

package com.demo.user;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

3.2 订单服务(order-service)与 Feign 调用

(1)依赖(增加 OpenFeign 和 Sentinel)

xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

(2)Feign 客户端(含熔断降级)(约 200 字符)

java

package com.demo.order.client;

import com.demo.order.fallback.UserFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import com.demo.order.entity.User;

@FeignClient(name = "user-service", fallback = UserFallback.class)
public interface UserClient {
    @GetMapping("/api/users/{id}")
    User getUser(@PathVariable("id") Long id);
}

// 熔断实现
package com.demo.order.fallback;

import com.demo.order.client.UserClient;
import com.demo.order.entity.User;
import org.springframework.stereotype.Component;

@Component
public class UserFallback implements UserClient {
    @Override
    public User getUser(Long id) {
        return new User(id, "降级用户", "fallback@demo.com");
    }
}

(3)订单实体与 Controller(约 200 字符)

java

package com.demo.order.entity;

import lombok.Data;

@Data
public class Order {
    private Long id;
    private Long userId;
    private String product;
    private Integer quantity;
    private User userInfo; // 冗余用户信息
}

// Controller
package com.demo.order.controller;

import com.demo.order.client.UserClient;
import com.demo.order.entity.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/api/orders")
public class OrderController {

    @Autowired
    private UserClient userClient;

    private static List<Order> orderDB = new ArrayList<>();

    @PostMapping("/create")
    public Order createOrder(@RequestBody Order order) {
        // 调用用户服务获取用户信息
        order.setUserInfo(userClient.getUser(order.getUserId()));
        order.setId(System.currentTimeMillis());
        orderDB.add(order);
        return order;
    }

    @GetMapping("/{id}")
    public Order getOrder(@PathVariable Long id) {
        return orderDB.stream()
                .filter(o -> o.getId().equals(id))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("订单不存在"));
    }

    @GetMapping("/user/{userId}")
    public List<Order> listByUser(@PathVariable Long userId) {
        return orderDB.stream()
                .filter(o -> o.getUserId().equals(userId))
                .toList();
    }
}

(4)启动类(启用 Feign 和 Sentinel)

java

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

3.3 Nacos 动态配置演示

在 Nacos 控制台(http://localhost:8848/nacos)创建 Data ID user-service.yaml,Group DEFAULT_GROUP,内容:

yaml

user:
  default:
    role: admin

发布后,调用 GET /api/users/role 会立即返回“当前默认角色: admin”,无需重启服务,证明配置动态刷新生效。


4. API 网关(Spring Cloud Gateway)

4.1 网关服务 gateway-service 依赖

xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

4.2 路由配置(代码块,约 180 字符)

yaml

# application.yml
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      routes:
        - id: user-route
          uri: lb://user-service   # 负载均衡
          predicates:
            - Path=/api/users/**
        - id: order-route
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
      # 全局熔断(配合 Sentinel)
      default-filters:
        - name: Hystrix
          args:
            name: fallback
            fallbackUri: forward:/fallback

4.3 熔断降级处理器(约 120 字符)

java

package com.demo.gateway.handler;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
public class FallbackController {
    @GetMapping("/fallback")
    public Mono<String> fallback() {
        return Mono.just("服务暂时不可用,请稍后再试");
    }
}

5. 熔断限流(Sentinel)集成

在订单服务的 application.yml 中配置 Sentinel Dashboard:

yaml

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8858
        port: 8719

在 Controller 中使用 @SentinelResource 注解(约 150 字符):

java

@GetMapping("/hot")
@SentinelResource(value = "hotResource", blockHandler = "handleBlock")
public String hotMethod(@RequestParam String param) {
    return "热点数据: " + param;
}

public String handleBlock(String param, BlockException ex) {
    return "请求被限流,请降低频率";
}

配置流控规则(在 Sentinel 控制台):为 hotResource 设置 QPS 阈值=1,快速访问会触发降级。


6. 链路追踪(Zipkin + Micrometer)

6.1 依赖引入(每个服务添加)

xml

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
    <groupId>io.zipkin.reporter2</groupId>
    <artifactId>zipkin-reporter-brave</artifactId>
</dependency>

6.2 配置(约 60 字符)

yaml

spring:
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      probability: 1.0

启动后,访问网关触发的调用链可在 Zipkin UI(http://localhost:9411)查看。


7. 服务容器化(Dockerfile 与编排)

7.1 每个服务的 Dockerfile(约 100 字符)

dockerfile

FROM openjdk:17-jdk-alpine
WORKDIR /app
COPY target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
EXPOSE 8080

7.2 Docker Compose 整合所有服务(约 180 字符)

yaml

version: '3'
services:
  nacos: # 同上
  sentinel: # 同上
  zipkin: # 同上
  user-service:
    build: ./user-service
    ports:
      - "8081:8081"
    depends_on:
      - nacos
    environment:
      SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR: nacos:8848
  order-service:
    build: ./order-service
    ports:
      - "8082:8082"
    depends_on:
      - nacos
    environment:
      SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR: nacos:8848
  gateway-service:
    build: ./gateway-service
    ports:
      - "8080:8080"
    depends_on:
      - nacos
      - user-service
      - order-service

8. 单元测试与集成测试(代码块)

使用 @SpringBootTest 和 MockMvc 测试订单创建流程(约 200 字符):

java

@SpringBootTest
@AutoConfigureMockMvc
public class OrderIntegrationTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testCreateOrder() throws Exception {
        String orderJson = "{"userId":1,"product":"笔记本电脑","quantity":2}";
        mockMvc.perform(post("/api/orders/create")
                .contentType(MediaType.APPLICATION_JSON)
                .content(orderJson))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.userInfo.username").value("张三"));
    }
}

9. 生产级优化与监控

  • 日志聚合:使用 ELK 或 Loki 收集微服务日志。
  • 健康检查:为每个服务配置 /actuator/health,K8s 探针依赖。
  • 配置加密:使用 Jasypt 对敏感配置(数据库密码)加密。
  • 灰度发布:通过 Nacos 的权重路由或 Gateway 的 Weight 谓词实现。
  • 性能调优:调整 Tomcat 线程池、Feign 连接超时、Sentinel 规则持久化。

10. 总结与扩展

本文完整构建了一个基于 Spring Cloud Alibaba 的 Java 互联网微服务系统,涵盖了 Nacos 注册与配置、Feign 远程调用、Sentinel 熔断限流、Gateway 路由转发、Zipkin 链路追踪、Docker 容器化 等关键组件。全部代码(含 YAML 和 Java)总计超过 2600 字符,可直接作为新项目的脚手架。

通过这个实战,你可以深入理解微服务架构的核心原理,并掌握各组件在实际开发中的用法。未来可进一步扩展:集成 Spring Security OAuth2 实现认证授权、引入 Seata 处理分布式事务、使用 Kubernetes 进行编排调度。