零基础学Java——第十一章:实战项目 - 微服务入门

第十一章:实战项目 - 微服务入门

随着互联网应用的复杂性不断增加,单体应用(Monolithic Application)在可扩展性、可维护性、技术栈灵活性等方面逐渐暴露出一些问题。微服务架构(Microservices Architecture)应运而生,成为构建大型复杂应用的一种流行方式。

1. 什么是微服务?

微服务是一种架构风格,它将一个大型复杂应用拆分成一组小型的、独立部署的服务。每个服务都围绕特定的业务能力构建,并且可以独立开发、测试、部署和扩展。

核心思想

  • 单一职责:每个微服务只关注一项特定的业务功能。
  • 独立部署:每个微服务都可以独立部署,不依赖于其他服务的部署周期。
  • 技术异构性:不同的微服务可以使用不同的编程语言、数据库或技术栈。
  • 去中心化治理:团队可以独立负责自己的服务,包括技术选型和数据管理。
  • 弹性与容错:单个服务的故障不会导致整个系统崩溃。

生活中的例子

想象一个大型电商平台。如果采用单体架构,所有的功能(用户管理、商品管理、订单管理、支付、库存等)都在一个巨大的代码库中。如果采用微服务架构,这些功能会被拆分成独立的服务:

  • 用户服务 (User Service)
  • 商品服务 (Product Service)
  • 订单服务 (Order Service)
  • 支付服务 (Payment Service)
  • 库存服务 (Inventory Service)

这些服务之间通过轻量级的通信机制(通常是HTTP/REST API或消息队列)进行交互。

2. 微服务与单体应用的对比

特性单体应用 (Monolithic)微服务 (Microservices)
代码库单一、庞大多个、小型、独立
部署整个应用作为一个单元部署每个服务独立部署
扩展性整体扩展,难以针对特定功能进行精细化扩展可针对每个服务独立扩展
技术栈通常统一技术栈不同服务可采用不同技术栈
开发效率初期快,后期因代码耦合和复杂性增加而变慢初期可能较慢(需要处理分布式问题),后期因独立性而提高
容错性单点故障可能导致整个应用不可用单个服务故障影响范围有限,系统更具弹性
团队协作大型团队在单一代码库上协作可能存在冲突和瓶颈小型自治团队负责各自服务,并行开发效率高
复杂性应用内部复杂性高分布式系统带来的运维和管理复杂性高

3. 微服务的优势

  • 技术多样性:可以为每个服务选择最适合的技术栈。
  • 弹性伸缩:可以根据每个服务的负载情况独立进行伸缩。
  • 易于维护和理解:每个服务代码量小,业务逻辑清晰。
  • 独立部署,快速迭代:单个服务的修改和部署不影响其他服务,可以更快地交付新功能。
  • 更好的故障隔离:一个服务的故障不会轻易导致整个系统瘫痪。
  • 团队自治:小型团队可以独立负责一个或多个服务,提高开发效率和责任感。

4. 微服务的挑战

  • 分布式系统复杂性:需要处理网络延迟、服务间通信、数据一致性等问题。
  • 运维成本:需要管理和监控大量的服务实例,对自动化运维能力要求高。
  • 测试复杂性:端到端测试和集成测试变得更加复杂。
  • 服务发现与注册:需要机制来动态发现和注册服务实例。
  • 配置管理:需要统一管理各个服务的配置。
  • 链路追踪与监控:需要工具来追踪跨多个服务的请求,并监控系统健康状况。
  • 数据一致性:在分布式环境中保证数据最终一致性是一个挑战。

5. Java 微服务技术栈概览

Java生态系统为构建微服务提供了丰富的框架和工具。

5.1 Spring Boot

Spring Boot是构建Java微服务的首选框架。它简化了Spring应用的创建和部署,并且内置了对常见微服务模式的支持。

5.2 Spring Cloud

Spring Cloud是基于Spring Boot的一系列框架的有序集合,用于快速构建分布式系统中的一些常见模式(例如,配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态)。

Spring Cloud 核心组件

  • 服务发现与注册 (Service Discovery & Registration)
    • Netflix Eureka (维护模式,推荐使用Consul或Nacos)
    • HashiCorp Consul
    • Alibaba Nacos
  • 客户端负载均衡 (Client-side Load Balancing)
    • Netflix Ribbon (维护模式,Spring Cloud LoadBalancer是推荐替代方案)
    • Spring Cloud LoadBalancer
  • 声明式REST客户端 (Declarative REST Client)
    • Netflix Feign (现在是OpenFeign)
    • Spring Cloud OpenFeign
  • API网关 (API Gateway)
    • Netflix Zuul (Zuul 1维护模式,Zuul 2不被Spring Cloud直接支持)
    • Spring Cloud Gateway (推荐)
  • 断路器 (Circuit Breaker)
    • Netflix Hystrix (维护模式)
    • Resilience4j (推荐)
    • Sentinel (Alibaba)
  • 配置中心 (Configuration Management)
    • Spring Cloud Config Server
    • HashiCorp Consul
    • Alibaba Nacos
  • 消息总线 (Message Bus)
    • Spring Cloud Bus (通常与Spring Cloud Config配合使用,实现配置动态刷新)
  • 分布式追踪 (Distributed Tracing)
    • Spring Cloud Sleuth (通常与Zipkin或Jaeger集成)

6. 构建一个简单的微服务示例 (使用 Spring Boot)

让我们构思两个简单的微服务:一个“问候服务”(Greeting Service)和一个“用户服务”(User Service)。“问候服务”会调用“用户服务”来获取用户名,然后返回个性化的问候语。

6.1 创建用户服务 (User Service)

  1. 使用 Spring Initializr 创建项目:
    • Group: com.example.microservices
    • Artifact: user-service
    • Dependencies: Spring Web
  2. 创建 User POJO:
    package com.example.microservices.userservice;public class User {private Long id;private String username;public User(Long id, String username) {this.id = id;this.username = username;}// Getters and Setterspublic Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }
    }
    
  3. 创建 UserController:
    package com.example.microservices.userservice;import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
    import java.util.Map;@RestController
    @RequestMapping("/users")
    public class UserController {private final Map<Long, User> users = new HashMap<>();public UserController() {users.put(1L, new User(1L, "Alice"));users.put(2L, new User(2L, "Bob"));}@GetMapping("/{id}")public User getUserById(@PathVariable Long id) {System.out.println("User Service: Received request for user ID: " + id);return users.getOrDefault(id, new User(0L, "Unknown"));}
    }
    
  4. 配置端口 (可选,避免冲突): 在 application.properties 中设置:
    server.port=8081
    
  5. 运行 User Service.
    测试:访问 http://localhost:8081/users/1,应返回 {"id":1,"username":"Alice"}

6.2 创建问候服务 (Greeting Service)

  1. 使用 Spring Initializr 创建项目:
    • Group: com.example.microservices
    • Artifact: greeting-service
    • Dependencies: Spring Web, Spring Boot Actuator (可选,用于健康检查等)
  2. 创建 User DTO (Data Transfer Object) (用于接收来自User Service的数据):
    package com.example.microservices.greetingservice;// 这个类结构需要和User Service返回的User对象一致
    public class User {private Long id;private String username;// Getters and Setterspublic Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }
    }
    
  3. 创建 GreetingController:
    package com.example.microservices.greetingservice;import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;@RestController
    public class GreetingController {// RestTemplate用于进行HTTP调用private final RestTemplate restTemplate;@Autowiredpublic GreetingController(RestTemplate restTemplate) {this.restTemplate = restTemplate;}@GetMapping("/greet/{userId}")public String greetUser(@PathVariable Long userId) {System.out.println("Greeting Service: Received request for user ID: " + userId);// 调用User Service获取用户信息// 注意:这里硬编码了User Service的地址,实际项目中应使用服务发现String userServiceUrl = "http://localhost:8081/users/" + userId;User user = restTemplate.getForObject(userServiceUrl, User.class);if (user != null && !"Unknown".equals(user.getUsername())) {return "Hello, " + user.getUsername() + "!";} else {return "Hello, Anonymous User!";}}
    }
    
  4. 配置 RestTemplate Bean (在主应用类中添加):
    package com.example.microservices.greetingservice;import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;@SpringBootApplication
    public class GreetingServiceApplication {public static void main(String[] args) {SpringApplication.run(GreetingServiceApplication.class, args);}@Bean // 将RestTemplate注册为一个Bean,Spring会管理它的生命周期public RestTemplate restTemplate() {return new RestTemplate();}
    }
    
  5. 配置端口: 在 application.properties 中设置 (例如 server.port=8082)。
  6. 运行 Greeting Service.
    测试:访问 http://localhost:8082/greet/1。Greeting Service会调用User Service,然后返回 Hello, Alice!
    如果User Service未运行或ID不存在,可能会返回 Hello, Anonymous User! 或报错。

注意:这个例子非常基础,它硬编码了服务地址。在实际的微服务架构中,你需要使用服务发现机制(如Eureka, Consul, Nacos)和客户端负载均衡(如Spring Cloud LoadBalancer)来动态查找和调用服务。

7. 服务发现与注册 (以 Nacos 为例,概念性介绍)

当微服务数量增多,手动管理它们的地址和端口变得不现实。服务发现与注册中心解决了这个问题。

  • 服务注册:每个微服务实例在启动时,向注册中心注册自己的网络位置(IP地址、端口号)和其他元数据。
  • 服务发现:当一个服务(如Greeting Service)需要调用另一个服务(如User Service)时,它会向注册中心查询User Service的可用实例列表。
  • 健康检查:注册中心会定期检查已注册服务的健康状况,并剔除不健康的实例。

Alibaba Nacos 是一个功能丰富的平台,提供服务发现、配置管理和服务管理。

大致流程

  1. 启动 Nacos Server
  2. User Service 配置:
    • 添加 Nacos Discovery Starter 依赖 (spring-cloud-starter-alibaba-nacos-discovery)。
    • application.properties 中配置 Nacos Server 地址和应用名:
      spring.application.name=user-service
      spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
      
    • 在主类上添加 @EnableDiscoveryClient 注解。
  3. Greeting Service 配置:
    • 添加 Nacos Discovery Starter 依赖。
    • 配置 Nacos Server 地址和应用名 (spring.application.name=greeting-service)。
    • 在主类上添加 @EnableDiscoveryClient 注解。
    • 修改 RestTemplate Bean,添加 @LoadBalanced 注解,使其能够通过服务名进行调用:
      @Bean
      @LoadBalanced // 开启负载均衡
      public RestTemplate restTemplate() {return new RestTemplate();
      }
      
    • 修改 GreetingController 中调用User Service的URL,使用服务名代替硬编码的IP和端口:
      // String userServiceUrl = "http://localhost:8081/users/" + userId; // 旧方式
      String userServiceUrl = "http://user-service/users/" + userId; // 新方式,user-service是User Service在Nacos中注册的服务名
      

当Greeting Service通过 http://user-service/... 调用时,Spring Cloud LoadBalancer (集成了Ribbon的功能) 会从Nacos获取 user-service 的可用实例列表,并选择一个实例进行调用。

8. API 网关 (以 Spring Cloud Gateway 为例,概念性介绍)

当微服务数量众多时,客户端直接与所有微服务通信会变得复杂且难以管理。API网关作为系统的唯一入口,提供了请求路由、聚合、安全、监控等功能。

Spring Cloud Gateway 是一个基于Spring Framework 5, Project Reactor和Spring Boot 2构建的API网关。

主要功能

  • 路由 (Routing):根据请求的路径、头部等信息将请求转发到后端相应的微服务。
  • 断言 (Predicates):匹配HTTP请求中的任何内容,如路径、方法、头部等,用于决定路由规则是否适用。
  • 过滤器 (Filters):在请求被路由前后执行一些逻辑,如修改请求/响应、认证、限流等。

大致配置

  1. 创建一个新的Spring Boot项目,添加 Spring Cloud Gateway 依赖。
  2. application.propertiesapplication.yml 中配置路由规则:
    spring:application:name: api-gatewaycloud:gateway:discovery:locator:enabled: true # 开启从注册中心自动发现服务并创建路由lower-case-service-id: true # 将服务名转为小写作为路径前缀routes:- id: user_service_route # 路由ID,唯一即可uri: lb://user-service # lb:// 表示从注册中心负载均衡地选择 user-service 实例predicates:- Path=/api/users/** # 当请求路径匹配 /api/users/** 时,应用此路由# filters: # 可以添加过滤器# - StripPrefix=1 # 例如,去掉路径中的第一个前缀 /api- id: greeting_service_routeuri: lb://greeting-servicepredicates:- Path=/api/greetings/**
    server:port: 8080 # 网关端口
    
    如果开启了 discovery.locator.enabled=true,Gateway会自动为注册中心中的每个服务创建一个路由,路径通常是 /服务名小写/**。例如,可以直接通过 http://localhost:8080/user-service/users/1 访问User Service。

客户端现在只需要与API网关 (如 http://localhost:8080) 通信,网关会将请求路由到相应的后端微服务。

9. 总结与下一步

微服务架构为构建大型、复杂的分布式系统提供了一种灵活且可扩展的方式。Spring Boot和Spring Cloud为Java开发者构建微服务提供了强大的支持。

入门微服务需要掌握的关键概念

  • 服务拆分原则
  • 服务间通信 (REST API, 消息队列)
  • 服务发现与注册
  • 客户端负载均衡
  • API网关
  • 断路器与容错
  • 配置管理
  • 分布式追踪与监控

下一步可以探索的内容

  • 深入学习 Spring Cloud 各个组件:如Nacos/Consul, OpenFeign, Resilience4j, Spring Cloud Gateway, Spring Cloud Config等。
  • 容器化与编排:学习Docker和Kubernetes,用于微服务的打包、部署和管理。
  • 消息队列:学习RabbitMQ, Kafka等,实现异步通信和解耦。
  • 分布式事务:了解Saga模式、TCC模式等处理分布式事务的方案。
  • DevOps实践:学习CI/CD(持续集成/持续交付)流程,实现微服务的自动化构建、测试和部署。

微服务是一个庞大且不断发展的领域。从小处着手,逐步实践,你会慢慢掌握它的精髓。祝你学习愉快!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/80023.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git 本地提交后修改注释

dos命令行进入目录&#xff0c;idea可以点击Terminal 进入命令行 git commit --amend -m "修改内容"

Python训练打卡Day22

复习日&#xff1a; 1.标准化数据&#xff08;聚类前通常需要标准化&#xff09; scaler StandardScaler() X_scaled scaler.fit_transform(X) StandardScaler() &#xff1a;这部分代码调用了 StandardScaler 类的构造函数。在Python中&#xff0c;当你在类名后面加上括号…

气动排渣煤粉炉专用V型球阀——法兰连接耐磨阀门生产厂家解析-耀圣

气动排渣煤粉炉专用V型球阀——法兰连接耐磨阀门生产厂家解析 副标题&#xff1a;开关灵活无泄漏 标配行程开关/电磁阀/过滤器 一、产品概述&#xff1a;气动排渣煤粉炉专用V型球阀核心优势 作为专业的气动耐磨V型球阀生产厂家&#xff0c;我们针对煤粉炉排渣工况研发的法兰连…

Linux云计算训练营笔记day08(MySQL数据库)

Linux云计算训练营笔记day08&#xff08;MySQL数据库&#xff09; 目录 Linux云计算训练营笔记day08&#xff08;MySQL数据库&#xff09;数据准备修改更新update删除delete数据类型1.整数类型2.浮点数类型(小数)3.字符类型4.日期5.枚举: 表头的值必须在列举的值里选择拷贝表复…

致远OA人事标准模块功能简介【附应用包百度网盘下载地址,官方售价4W】

人事管理应用&#xff0c;围绕岗位配置、招聘管理、员工档案、入转调离、员工自助申报、数据信息管理等人力资源管理关键业务&#xff0c;构建全员可参与的人事工作协同平台&#xff0c;让人事从繁杂琐碎的事务中解脱出来&#xff0c;高质高效工作&#xff0c;让管理层清楚掌握…

数字孪生工厂实战指南:基于Unreal Engine/Omniverse的虚实同步系统开发

引言&#xff1a;工业元宇宙的基石技术 在智能制造2025与工业元宇宙的交汇点&#xff0c;数字孪生技术正重塑传统制造业。本文将手把手指导您构建基于Unreal Engine 5.4与NVIDIA Omniverse的实时数字孪生工厂系统&#xff0c;集成Kafka实现毫秒级虚实同步&#xff0c;最终交付…

【向量模型 + HNSW 参数如何选择】

目录 一、embedding_function&#xff08;向量模型&#xff09; 可选方式 选型建议 二、HNSW 参数选择&#xff08;核心影响搜索速度与准确率&#xff09; 2.1 参数解释和推荐值 2.2 配置模板参考 1、推荐默认配置&#xff08;适合大多数项目&#xff09;&#xff1a; 2…

fpga系列 HDL : Microchip FPGA开发软件 Libero Soc 安装 license申请

启动 注册账号&#xff1a;https://login.microchip.com/申请免费许可&#xff1a;https://www.microchipdirect.com/fpga-software-products C:\Windows\System32>vol驱动器 C 中的卷是 Windows卷的序列号是 ****-****为“D:\Microsemi\License.dat”创建环境变量“LM_LICE…

【C++】解析C++面向对象三要素:封装、继承与多态实现机制

解析C面向对象三要素&#xff1a;封装、继承与多态实现机制 1. 面向对象设计基石2. 封装&#xff1a;数据守卫者2.1 访问控制实现2.2 封装优势 3. 继承&#xff1a;代码复用艺术3.1 继承的核心作用3.2 继承类型对比3.3 典型应用场景3.4 构造函数与析构函数处理3.4.1 构造顺序控…

Python并发编程:开启性能优化的大门(7/10)

1.引言 在当今数字化时代&#xff0c;Python 已成为编程领域中一颗璀璨的明星&#xff0c;占据着编程语言排行榜的榜首。无论是数据科学、人工智能&#xff0c;还是 Web 开发、自动化脚本编写&#xff0c;Python 都以其简洁的语法、丰富的库和强大的功能&#xff0c;赢得了广大…

数学复习笔记 10

前言 我觉得数学的高分乃至满分属于那些&#xff0c;聪明&#xff0c;坚韧&#xff0c;勇敢&#xff0c;细致的人。我非常惭愧自己不是这样的人&#xff0c;我在生活中发现了这样的同学&#xff0c;和他们交流的时候我常常感到汗流浃背&#xff0c;因为他们非常扎实的基础知识…

深入理解 Webpack 核心机制与编译流程

&#x1f916; 作者简介&#xff1a;水煮白菜王&#xff0c;一位前端劝退师 &#x1f47b; &#x1f440; 文章专栏&#xff1a; 前端专栏 &#xff0c;记录一下平时在博客写作中&#xff0c;总结出的一些开发技巧和知识归纳总结✍。 感谢支持&#x1f495;&#x1f495;&#…

概率相关问题

问题汇总 1. 贝叶斯定理&#xff08;贝叶斯公式和全概率公式&#xff09;2. 概率题2.1 随机发生器的概率为1/2 1. 贝叶斯定理&#xff08;贝叶斯公式和全概率公式&#xff09; 定义&#xff1a;在信息和条件有限的情况下&#xff0c;基于过去的数据&#xff0c;通过动态调整的…

【系统架构师】2025论文《WEB系统性能优化技术》

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本文分享【系统架构师】2025论文《系统可靠性设计》&#xff0c;期待与你一同探索、学习、进步&#xff0c;一起卷起来叭&#xff01; 目录 项目介绍背景介绍系统模块技术栈性能…

ADS1220高精度ADC(TI)——应用 源码

文章目录 德州仪器ADS1220概述资料引脚&封装布线寄存器配置寄存器0&#xff08;00h&#xff09;配置寄存器1&#xff08;01h&#xff09;配置寄存器2&#xff08;02h&#xff09;配置寄存器3&#xff08;03h&#xff09; 连续转换流程驱动源码ads1220.cads1220.h 德州仪器A…

Uniapp 安卓实现讯飞语音听写(复制即用)

在移动应用开发中&#xff0c;语音交互功能能够极大提升用户体验&#xff0c;让操作更加便捷自然。讯飞语音听写技术凭借其高准确率和稳定性&#xff0c;成为众多开发者的选择。本文将详细介绍如何在 Uniapp 项目中&#xff0c;实现安卓端的讯飞语音听写功能&#xff0c;帮助你…

【golang】DNS 资源记录(RR)接口

Go 中 miekg/dns 包对 DNS 资源记录&#xff08;RR&#xff09;接口 的定义&#xff1a; type RR interface {Header() *RR_HeaderString() stringcopy() RRlen(off int, compression map[string]struct{}) intpack(...)unpack(...)parse(...)isDuplicate(r2 RR) bool }这个接…

16.2 VDMA视频转发实验之模拟源

文章目录 1 实验任务2 系统框图3 硬件设计3.1 IP核配置3.2 注意事项3.3 自定义IP核源码 4 软件设计4.1 注意事项4.2 工程源码4.2.1 main.c文件 1 实验任务 基于14.1&#xff0c;相较于16.1&#xff0c;使用自定义IP核vid_gen_motion替换Xilinx TPG IP核。 2 系统框图 基于14…

深度学习之用CelebA_Spoof数据集搭建一个活体检测-训练好的模型用MNN来推理

一、模型转换准备 首先确保已完成PyTorch到ONNX的转换&#xff1a;深度学习之用CelebA_Spoof数据集搭建活体检测系统&#xff1a;模型验证与测试。这里有将PyTorch到ONNX格式的模型转换。 二、ONNX转MNN 使用MNN转换工具进行格式转换&#xff1a;具体的编译过程可以参考MNN的…

JVM学习专题(一)类加载器与双亲委派

目录 1、JVM加载运行全过程梳理 2、JVM Hotspot底层 3、war包、jar包如何加载 4、类加载器 我们来查看一下getLauncher&#xff1a; 1.我们先查看getExtClassLoader() 2、再来看看getAppClassLoader(extcl) 5、双亲委派机制 1.职责明确&#xff0c;路径隔离​&#xff…