前言哈喽各位 CSDN 的技术伙伴们最近博主在学习微服务相关内容踩了不少拆分和治理的坑也整理了一套从核心思想到落地实操的完整流程。不管你是刚接触微服务的新手还是正在项目中面临拆分难题的开发者这篇文章都会从「是什么 - 为什么 - 怎么做」三个维度把微服务的拆分逻辑、工程结构、服务注册发现等关键知识点讲透还附带 Nacos、OpenFeign 的具体配置代码直接复制就能用话不多说咱们正文开始微服务的拆分与治理从思想到落地一、微服务核心思想1.1 什么是微服务微服务架构是服务化指导思想下的一套最佳实践架构方案。微服务化就是把这个单体项目拆分为多个独立的项目1.2 使用微服务的好处粒度小每个模块仅负责自己单独的功能登录功能、用户管理功能团队自治每个模块都会有一个几人或十几人的小团队去管理服务自治测试以及部署的时候每个模块可以单独部署拥有自己的数据库使用微服务可以极大地优化项目打包构建时间还可以有效减轻数据库的访问压力二、服务拆分2.1 SpringCloud官网Spring Cloud 官方网站为https://spring.io/projects/spring-cloud。注springboot3.0.x以上需要使用2022.0.x的版本2.2 拆分思想与原则2.2.1 如何拆分从拆分目标上来说高内聚每个微服务职责单一包含的业务关联性高低耦合每个微服务之间尽量独立尽可能减少对其他微服务模块或项目的影响从拆分维度上来说横向拆分抽取公共服务提高复用性登录以及订单功能的风控纵向拆分按照业务模块拆分分布式2.2.2工程结构种类独立project每块业务逻辑都是一个独立的项目有多少个微服务就需要new多少个项目最后再把这一堆项目扔到一个统一的目录里面去做一个松散的管理。maven聚合每块业务逻辑都是一个独立的模块有多少个微服务就需要new多少个模块统一交给一个maven项目做一个聚合型管理。适用于中小型项目2.3 maven聚合形式的拆分2.3.1拆分流程前提有一个完善的、可以正常工作的单体项目方法创建一个maven包不是spring项目起名为xxx-service复制单体架构项目的maven内容根据需求修改为一个适合的足够该微服务使用的pom文件复制单体架构项目里面的yml文件修改为一个新的端口号修改数据库配置写好三层架构、domain包等以及resource里面的mapper内容从单体架构中对应的包里面复制即可2.3.2远程调用有些微服务在拆分的时候由于原先在单体项目中作为一个模块它会调用其他其他模块的service方法来完成相关功能但是现在由于各服务之间相互隔离无法调用。它们虽然端口号不同但是都在同一个网络下可以通过网络沟通解决方法使用RestTemplate不推荐请求方式繁琐路径写死使用OpenFeign服务治理内容三、服务治理3.1 服务注册通常情况下大型项目为了解决高并发下的服务器卡顿缓解服务器压力这些易引发高并发的模块会被使用多个docker容器进行部署管理服务治理下的三个角色服务提供者暴露服务接口便于其他服务调用服务消费者调用其他服务的接口注册中心记录并监控各个微服务实例的状态并推送服务变更信息注册中心原理与nginx的负载均衡的原理相似相当于有一个中间商做代理对于该服务所访问的一些其他服务这个代理能根据需要给出几个合适的服务然后通过随机、轮询、哈希、加权随机等形式来处理挨个试直到找到首个可以满足要求的服务把对应的ip地址给了这个访问服务让它拿着这个ip地址对指定服务进行远程调用进而访问到指定服务的指定接口并获取到返回的数据所有服务都是会定期向注册中心发送注册服务信息的让中间商知道自己还活着信息内容包括 IP、端口、服务名、健康检查路径等在服务运行过程中可能某个服务因为某些原因突然挂掉了没有继续发服务信息服务中心就会认为该服务已经出现故障就会从注册中心中将该服务剔除心跳机制剔除挂掉的服务之后注册中心还会告知调用者对应的哪一个服务已经挂掉了不能再访问了推送变更如果这个服务复活了或者又引进来了新的服务注册中心又会有新的变动时刻告知调用者对应服务的最新状态注册中心种类EurekaAP 模型高可用优先客户端拉取服务列表心跳默认 30 秒剔除默认 90 秒。ConsulCP 模型强一致性优先支持多数据中心内置健康检查。Nacos同时支持 AP/CP 模型兼容 Dubbo、Spring Cloud国内使用广泛。注册中心的搭建下载nacos数据库脚本使用官方脚本nacos/distribution/conf/mysql-schema.sql at master · alibaba/nacos创建专用网络保证各个微服务、数据库以及nacos在同一网络下。使用docker创建nacos专属mysql容器加载脚本生成nacos数据库创建nacos的docker容器docker run -d \ -p 8848:8848 -p 9848:9848 -p 9849:9849 \ --name nacos \ --network hmall-spring-cloud \ # 与MySQL容器在同一网络 -e MODEstandalone \ # 单机模式 -e SPRING_DATASOURCE_PLATFORMmysql \ # 指定使用mysql数据库 -e MYSQL_SERVICE_HOSTnacos-mysql \ # 创建的nacos的mysql容器名 -e MYSQL_SERVICE_PORT3306 \ #mysql默认端口 -e MYSQL_SERVICE_DB_NAMEnacos \ # 创建的nacos的mysql容器中存放nacos数据的数据库 -e MYSQL_SERVICE_USERroot \ # 数据库用户名 -e MYSQL_SERVICE_PASSWORD159357 \ # 密码 -e MYSQL_DATABASE_NUM1 \ # 数据库实例数量单机为1 nacos/nacos-server:2.1.0注nacos个人开发推荐使用2.1.0以下版本新版配置繁琐。使用时去掉注释5. 使用ip地址:8848/nacos访问私网用户名密码nacos在maven聚合项目中进行服务注册引入 nacos discovery 依赖!--nacos 服务注册发现-- dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId /dependency配置 Nacos 地址spring: application: name: xxx-service # 服务名称 cloud: nacos: server-addr: xxxxxxxxxx:8848 # nacos地址这个注册需要对所有微服务模块做3.2 服务发现使用OpenFeignOpenFeign内部已经内置了服务发现功能实践方案根据项目的工程结构进行合理选择对于独立project把原来的被调用的微服务再拆成三个模块xxx-dto放实体类xxx-api放httpclient接口xxx-biz放业务逻辑代码优点项目耦合度更低httpClient接口由负责该微服务部分的团队编写该团队对该接口的熟悉度更高缺点项目结构更加复杂对于maven聚合创建一个新的包里面放所有微服务想要暴露的客户端优点代码简洁且通用性更强缺点代码耦合度更高在maven聚合项目中进行服务发现创建xxx-api包下设三个包client、config、dtoclient包中是需要被共享使用的接口xxxClientconfig里面放可能用到的配置文件dto里面放共用的dto类client类的编写示例FeignClient(value item-service) //value后面是被调用服务名称 public interface ItemClient { GetMapping(/items) ListItemDTO queryItemByIds(RequestParam(ids) CollectionLong ids); }修改xxx-api的pom文件把openfeign和负载均衡的依赖引入hm-api的pom文件中!--OpenFeign-- dependency groupIdorg.springframework.cloud/groupId artifactIdspring-cloud-starter-openfeign/artifactId /dependency !--负载均衡-- dependency groupIdorg.springframework.cloud/groupId artifactIdspring-cloud-starter-loadbalancer/artifactId /dependency由于openfeign的底层使用的是loadbalancer,所以必须引入负载均衡依赖对于调用者引入OKHttp的依赖!--ok-http-- dependency groupIdio.github.openfeign/groupId artifactIdfeign-okhttp/artifactId /dependency开启okhttp提供的连接池功能feign: okhttp: enabled: true # 开启OKHttp连接池支持并引入xxx-api包通过依赖传递可以让调用者获得相关依赖5. 给cart-service的启动类上的注解EnableFeignClients添加扫描com.hmall.api.client不然识别不到6. 业务逻辑中就可以直接改用xxxClient进行调用示例ListItemDTO items itemClient.queryItemByIds(List.of(1,2,3));注编写过程中如果发现dto冲突需要删除本服务下的dto然后使用引入的xxx-api包中共享的dto类补充OpenFeign日志输出四种级别NONE不打印任何日志默认级别生产环境推荐BASIC仅打印请求方法、URL、响应状态码、执行耗时最轻量化生产排查基本问题可用HEADERS在 BASIC 基础上额外打印请求 / 响应的头信息FULL打印请求 / 响应的头、请求体、响应体、状态码、耗时等所有细节开发调试专用信息最完整在hm-api中创建配置类DefaultFeignConfig声明一个类型为 Logger.Level 的 Bean在其中定义日志级别public class DefaultFeignConfig { Bean public Logger.Level feignLogLevel(){ return Logger.Level.FULL; } }Configuration注解可加可不加加上之后所有FeignClient都会使用这个级别的日志不加则需要显示指定使用2. 在 FeignClient 注解中声明,让这个Bean生效局部不加Configuration对于每一个FeignClient需要显示指定FeignClient(value item-service, configuration DefaultFeignConfig.class)全局加Configuration无需声明全局生效3. 配置yml文件中的logging部分# yml配置推荐 logging: level: # 格式logging.level.【Feign客户端接口的全类名】 debug com.xxx.feign.UserFeignClient: debug # 局部生效仅指定接口打印日志 # 或全局生效匹配所有Feign客户端包路径根据自己项目调整 com.xxx.feign: debug结尾技术交流与总结以上就是微服务拆分与治理的核心内容啦从思想到落地每一步都附了实操代码希望能帮大家少走弯路 如果在实操过程中遇到 Nacos 启动失败、Feign 调用超时、依赖冲突等问题或者有更好的拆分思路欢迎在评论区留言交流觉得文章有用的话别忘了点赞 收藏 关注呀后续还会更新微服务、JVM、多线程等更多内容咱们下期见