当前位置: 首页 > news >正文

淘宝网站怎么做链接地址网站开发自学流程

淘宝网站怎么做链接地址,网站开发自学流程,最美珠海app下载,招商网站平台一、SpringCloud初阶篇 1、从面试题开始 1.1什么是微服务#xff1f; 1.2微服务之间是如何独立通讯的#xff1f; 1.3SpringCloud和Dubbo有哪些区别#xff1f; 1.4通信机制#xff1a;Dubbo是通过RPC远程过程调用#xff0c;微服务Cloud是基于rest调用 1.5SpringBo…一、SpringCloud初阶篇 1、从面试题开始 1.1什么是微服务 1.2微服务之间是如何独立通讯的 1.3SpringCloud和Dubbo有哪些区别 1.4通信机制Dubbo是通过RPC远程过程调用微服务Cloud是基于rest调用 1.5SpringBoot和SpringCloud请你谈谈对他们的理解 SpringBoot专注于快速方便的开发单个个体微服务。 SpringCloud是关注全局的微服务协调整理治理框架他将SpringBoot开发的一个个单体微服务整合并管理起来为各个微服务之间提供配置管理、服务发现、断路器、路由、微代理、事件总线、全局所、决策竞选、分布式会话等等集成服务 SpringBoot可以离开SpringCloud独立使用开发项目但是SpringCloud离不开SpringBoot属于依赖的关系。 总结SpringBoot专注于快速、方便的开发单个微服务个体SpringCloud关注与全局的微服务治理框架。 1.6什么是服务熔断什么是服务降级 1.7微服务的优缺点分别是什么说下你在项目开发中碰到坑 1.8你所知道的微服务技术栈有哪些请列举一二 1.9Eureka和Zookeeper都可以提供服务注册与发现的功能请说说两个的区别 2、微服务概述 2.1 是什么 微服务架构是一种架构模式或者说是一种架构风格他提倡将单一应用程序划分成一组小的服务每个服务运行在其独立的自己的进程中服务之间互相协调、互相配合为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通Double是通过RPC远程通常是基于HTTP的RESTful API。每个服务都围绕着具体业务进行构建并且能够被独立地部署到生产环境、类生产环境等。另外应尽量避免统一的、集中式的服务管理机制对具体的一个服务而言应根据业务上下文选择合适的语言、工具对其进行构建可以有一个非常轻量级的集中式管理来协调这些服务可以使用不同的语言来编写服务也可以拥有自己独立的数据库。 通俗的讲 微服务化的核心就是将传统的一站式应用根据业务拆分成一个一个的服务彻底地去耦合每一个微服务提供单个业务功能的服务一个无服务做一件事从技术角度看就是一种小而独立的处理过程类似进程概念能够单独启动或销毁拥有自己独立的数据库。 2.2微服务与微服务架构 微服务 微服务是一种软件开发方法他将一个大型应用程序分解为许多小型、独立的服务。每个服务负责解决特定的问题或执行特定的工能。这些服务可以单独部署、维护和更新而不影响其他服务。它具有可伸缩性、可维护性、可组合性等特点。通常采用轻量级通信机制如HTTP REST API 或消息队列进行通信。 微服务架构 微服务架构是一种架构模式它基于微服务的原则来设计和实现大型应用程序。在微服务架构中应用程序有多个独立的服务组成这些服务可以按照业务功能、领域或团队进行划分。每个服务可以独立地开发、部署和扩展他们通过轻量级协议进行通信和协作。 2.3微服务优缺点 优点 模块化微服务架构将一个大的应用分为多个小的服务每个服务都专注于完成一项任务这种模块化使得微服务更容易理解和维护。 灵活性微服务架构使用REST API与服务之间进行交互和通信这使得微服务之间的协作更加灵活可以根据需求选择不同的编程语言和框架来编写服务。 持续部署微服务架构允许持续部署独立的服务这样就可以更加频繁地发布新功能同时也更容易进行灰度发布。 隔离性微服务之间通过REST API相互隔离这样即使其中一个服务发生故障也不会影响其他服务。 缺点 复杂性由于系统被分解成许多微服务在开发和测试阶段容易发生依赖冲突这会增加项目的复杂性 运维难度微服务架构使得技术栈更加庞大复杂运维工程师需要监控更多的服务这增加了运维的难度 通信开销微服务之间通过网络进行通信这必然带来一定的性能开销特别是高并发场景下会更加明显 数据一致性微服务架构下不同的服务有各自的数据库这可能导致数据一致性问题需要借助分布式事务来解决 重复开发微服务架构可能会有许多重复的业务逻辑在不同的服务中实现这增加了开发工作量 2.4微服务技术栈有哪些 微服务条目落地技术服务发现用于服务注册和发现比较常用的有 Eureka、Consul、Zookeeper等服务调用用于服务之间的调用常用的有REST、RPC、gRPC等。其中RPC框架有Dubbo、Thrift、SpringCloud OpenFeign等。负载均衡用于服务调用的负载均衡常用的有Ribbon、Nginx等服务网关用于同一 entrance常用的有Zull、Gateway配置中心用于集中管理配置常用的有Spring Cloud Config、Apollo、Archaius、阿里的Diamond熔断和降级用于保护服务不被过载常用的有 Hystrix、Resilience4j、Envoy服务监控用于服务监控常用的有 SpringBoot Admin、Prometheus、Zipkin分布式消息队列用于服务解耦和异步通信常用的有RabbitMQ、Kafka、RocketMQAPI文档用于同一管理API文档常用的有Swagger、SpringFox分布式日志用于同一管理日志常用的有ELK持续集成用于自动化构建和部署常用的有 Jenkins、GitLab CI容器化部署用于快速高效的部署和扩展常用的有 Docker、Kubernetes 2.5为什么选择SpringCloud作为微服务架构 SpringCloud是Spring旗下的项目与SpringBoot、SpringData等其他Spring项目完美整合开发体验好。SpringCloud项目涵盖了微服务开发中的各个方面如服务注册与发现Eureka、Consul、负载均衡Ribbon、熔断器Hystrix、配置中心Config、API网关Zuul等组件丰富使用方便。SpringCloud项目基于Netflix的开源项目进行二次开发和封装具有Netflix丰富的经验社区活跃发展迅速各个组件不断更新迭代SpringCloud与Docker、Kubernetes等容器技术相结合可以更容易部署和运维微服务应用SpringCloud提供了一套完整的微服务解决方案从开发到部署forming了一条令服务简化了微服务架构落地的难度 3、SpringCloud入门概述 3.1是什么 SpringCloud基于SpringBoot提供了一套微服务解决方案包括服务注册与发现配置中心全链路监控服务网关负载均衡熔断器等组件除了基于Netflix的开源组件做高度抽象封装之外还有一些选型中立的开源组件。 SpringCloud利用SpringBoot的开发遍历性巧妙地简化了分布式系统基础设施的开发SpringCloud为开发人员提供了快速构建分布式系统的一些工具包括**配置管理、服务发现、断路器、路由、微代理、时间总线、全局锁、决策竞选、分布式会话**等等它们都可以用SpringBoot的开发风格做到一建启动和部署。 一句话就是SpringCloud分布式微服务架构下的一站式解决方案是各个微服务架构落地技术的集合体俗称微服务全家桶。 3.2能干嘛 3.3去哪下 官方网址 参考书 API说明 SpringCloud中国社区 SpringCloud中文网 4、Rest微服务构建案例工程模块 4.1RestTemplate RestTemplate是Spring中的一个HTTP客户端用于简化RESTful Web Service的调用。他提供了一组易于使用的方法可以发送HTTP请求并处理HTTP响应。使用RestTemplate可以使用HTTP协议发送GET、POST、PUT、DELETE等请求并将响应映射为Java对象。 RestTemplate提供了多种方法来发送HTTP请求例如 getForEntity()和getForObject()方法用于发送HTTP GET请求并将响应映射为Java对象。postForEntity()和postForObject()方法用于发送HTTP POST请求并将请求体和响应映射为java对象put() 和 delete() 方法用于发送HTTP PUT和DELETE请求。 RestTemplate还提供了一些其他的方法例如 exchange()方法用于发送任意类型的HTTP请求并允许自定义请求头和请求体execute()方法用于发送任意类型的HTTP请求并允许自定义请求头、请求体和响应处理器 RestTemplate官网 使用restTemplate访问restful接口非常简单URLrequsetMap,ResponseBean.class这三个参数分别代表REST请求地址、请求参数、HTTP响应转换被转换成的对象类型 5、Eureka服务注册与发现 5.1 概念 Eureka是Netflix的一个子模块也是核心模块之一现在已经成为了SpringCloud等微服务核心组件之一。Eureka的核心原则是基于REST的架构和AP可用性和分区容错性设计理念。Eureka通过心跳机制来检测服务实例的存活状态并通过注册中心来管理服务实例的注册和发现。当一个服务实例出现故障或者下线时Eureka会自动将其从注册中心中删除并通知其他的服务实例重新选择可用的服务实例来进行负载均衡。 5.2 原理 5.2.1Eureka的基本架构 Eureka主要有两个组件组成Eureka Server 和 Eureka Client。Eureka Server是服务注册中心用于管理服务实例的注册和发现而Eureka Client 是服务提供者或服务消费者用于向Eureka Server注册自己并从Eureka Server获取可用的服务实例信息。 Eureka Server原理 Eureka Server采用了AP设计理念即可用性和分区容错性。在Eureka Server中有两个重要的组件Registry 和 Peer Registry服务注册表用于存储服务实例的注册信息包括服务名、IP地址、端口号、健康状态等。Peer服务注册中心的集群节点用于实现服务注册中心的高可用性。 Eureka Server 在启动时会像Peer结点发送心跳请求已加入到服务注册中心的集群中。当服务实例启动时它会向Eureka Server发送注册请求Eureka Server会将服务实例的注册信息存储到Registry中。当服务实例出现故障或下线时它会向Eureka Server发送取消注册请求Eureka Server会将服务实例的注册信息从Registry中删除。 Eureka Client原理 Eureka Client 是服务提供或服务消费者它用于向Eureka Server注册自己并从Eureka Server获取可用的服务实例信息。在Eureka Client中有两个重要的组件DiscoveryClient 和 Heartbeat。 DiscovertClient服务发现客户端用于从Eureka Server获取可用的服务实例信息。Heartbeat心跳机制用于定期向Eureka Server 发送心跳请求以保证服务实例的健康状态。 当服务实例启动时它会向Eureka Server发送注册请求Eureka Server会将服务实例的注册信息存储到Registry中。同时服务实例会定期向Eureka Server发送心跳请求以保证自己的健康状态。当服务实例出现故障或下线时它会向Eureka Server发送取消注册请求Eureka Server会将服务实例的注册信息从Registry中删除。 当服务消费者需要调用某个服务时它会向Eureka Server发送查询请求以获取可用的服务实例列表。Eureka Client会从获取到的服务实例列表中选择一个可用的服务实例并通过负载均衡算法进行负载均衡。如果选择的服务实例出现故障或下线Eureka Client会从服务实例列表中选择另一个可用的服务实例。 5.2.2 三大角色 Eureka Server 为客户端提供服务注册和发现Service Provides 作为服务提供方向Eureka Server注册自己提供的服务。Service Consumers 作为服务消费方从Eureka Server获取服务列表然后去调用服务。 Eureka Server:提供服务注册和发现的功能。客户端向Eureka Server注册自己提供的服务,然后也从Eureka Server获取其他服务的信息。 Service Provider:就是提供各种服务的微服务。Service Provider在启动时,会向Eureka Server注册自己,告知Eureka我提供了什么服务。 Service Consumer:服务消费者。需要调用其他服务的微服务。服务消费者在启动时,也会从Eureka Server获取所有已注册的服务,然后根据需要去调用服务。 5.3 构建步骤 5.3.1 服务注册中心 pom.xml 文件 !-- Eureka Server服务端 -- dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-eureka-server/artifactId /dependencyapplication.yml 文件 server:port: 7001eureka:instance:hostname: localhost # Eureka服务端的实例名称client: # false表示不向注册中心注册自己register-with-eureka: false # false表示自己端就是注册中心我的职责是维护服务实例并不需要检索服务service-url:defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # Eureka 客户端的默认注册中心地址,设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址 主启动类 SpringBootApplication EnableEurekaServer // 启用 Eureka Server 的功能接收其他微服务注册进来。 public class EurekaServer7001_App {public static void main(String[] args) {SpringApplication.run(EurekaServer7001_App.class,args);} }启动服务后浏览器访问localhost:7001 如果出现下图则说明成功 5.3.2 将已有服务注册进Eureka注册中心 pom.xml 文件 !-- 将微服务provider侧注册进eureka -- dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-eureka/artifactId /dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-config/artifactId /dependencyapplication.yml 文件 eureka:client: # 客户端注册进eureka服务列表内service-url:defaultZone: http://localhost:7001/eureka主启动类 SpringBootApplication EnableEurekaClient // 启用 Eureka Client 的功能。本服务启动后会自动注册进Eureka服务中 public class DeptProvider8001_App {public static void main(String[] args) {SpringApplication.run(DeptProvider8001_App.class,args);} }启动服务端再启动客户端浏览器发送localhost:7007请求如下图 可以看到有一个服务注册进来了而这个服务的名称正是注册的微服务的应用名称即对外暴露的微服务名称。 5.3.3 Actuator与注册微服务信息完善 配置服务实例信息 在客户端pom文件中加入一下配置 eureka: instance:instance-id: microservicecloud-dept8001 # 自定义服务名名称信息prefer-ip-address: true # 访问路径可以显示IP地址其他实例配置 instanceId服务实例的唯一标识符通常由主机名、IP地址、端口号等组成hostName服务市里的主机名appname服务实例所属的应用名称ip-address服务实例的IP地址secure-port服务实例的安全端口号initial-status服务实例的状态UP(运行中)、DOWN(不可用)、STARTING(正在启动)、OUT_OF_SERVICE(服务停机) Info 元数据信息 在客户端pom文件中加入以下配置 !-- actuator用于监控和管理Spring Boot应用的端点(endpoint)和健康检查(health check)功能 -- dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId /dependency父工程pom文件中加入以下配置 buildfinalNamemicroservicecloud/finalName!-- 指定Maven构建过程中需要处理的资源目录 --resourcesresourcedirectorysrc/main/resources/directory!-- 对资源进行过滤处理 --filteringtrue/filtering/resource/resources!-- 指定Maven构建过程中需要使用的插件 --pluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-resources-plugin/artifactId!-- 指定插件的配置信息 --configuration!-- 指定占位符的分隔符 --delimiters!-- 指定具体的分隔符。此处指定了 $ 作为占位符的分隔符 --delimit$/delimit/delimiters/configuration/plugin/plugins /build在客户端的yml文件中加入以下配置 info: # 指定应用程序的元数据。app.name: atpl-microservicecloud # 指定应用程序的名称可以用来标识应用程序在整个系统中的作用company.name: www.atpl.com # 指定应用程序所属的公司名称build.artifactId: ${project.artifactId} # 指定应用程序的构件ID通常是Maven项目中的artifactIdbuild.version: ${project.version} #指定应用程序的版本号通常是Maven项目中的version访问在上一小节图中左下角出现的IP地址(192.168.1.16:8001/info) 可以看到应用的元数据。 5.3.4 服务发现 对于注册进Eureka的服务可以通过服务发现来获得该服务的信息。 只需要在服务主启动类上加上EnableDiscoveryClient注解即可开启服务发现功能。 在8001的服务端的DeptController类中加入以下方法 /*** 服务发现获取当期应用程序的注册信息** return*/ GetMapping(/discoveryServer) public Object discoveryClientList() {ListString list discoveryClient.getServices();logger.info(-----微服务个数------ list);ListServiceInstance instances discoveryClient.getInstances(MICROSERVICECLOUD-DEPT);if (instances.size() 0 instances ! null) {for (ServiceInstance instance : instances) {logger.info(----服务实例信息---- 【 IP instance.getHost() , 端口号 instance.getPort() , URI instance.getUri() , 服务ID instance.getServiceId(), 元数据instance.getMetadata() 】);}}return this.discoveryClient; }启动8001浏览器访问http://localhost:8001/dept/discoveryServer 可以获得当前应用服务注册信息 也可以通过8001的客户端80 进行访问在客户端的DeptConsumerController类中加入以下代码 /*** 获取当前应用程序的注册信息** return*/ RequestMapping(/discovery) public Object disCoveryServer() {return restTemplate.getForObject(REST_URL_PRIFIX /dept/discoveryServer, Object.class); }启动80微服务浏览器发送http://localhost/dept/consumer/discovery 请求 都可以获得服务的注册信息。 5.4 介绍Eureka的自我保护机制 上图中出现 ’EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.‘意思是Eureka可能会声明已经不存在的实例刷新数小于阈值时为了安全起见不会剔除过期的实例。 Eureka的自我保护机制是为了防止误杀服务。当注册中心发生故障服务不能够正常的发送心跳请求但是服务运行正常默认情况下Eureka会将超过90s未发送心跳请求的服务进行移除。这样做明显不合理所以Eureka提供了一个自我保护模式。自我保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护一旦进入保护模式Eureka Server将会尝试保护其服务注册表中的信息不再删除服务注册表中的数据也就是不会注销任何微服务 。 首先说一下Eureka的默认阈值为85%90秒 比如目前有10个微服务只有8个有心跳反应时8/1080%85%Eureka就会开启保护机制过期的实例不会立马剔除。并且出这个紧急警告在搭建Eureka Server时比如我们搭建了2个Eureka Server并且禁止自注册Eureka Server自身算一个服务那么其中任意一个Eureka只能获得一个心跳1/250%。那么也会出现这个警告。 这种情况如果未禁止自注册的话是不会出现的因为本机不会有什么网络问题肯定是百分百。 博主这里测过只有当我开启7台及以上的Eureka Server服务(关闭Eureka Server自注册)的时候才不会出这个警告。 因为 5/6≈83.3%85% 6/7≈85.7%85%。 那么当不想有这个红色警告是本机自测可以关闭Eureka保护配置。生产环境下不要关。 在application.yml文件中配置 server:enable-self-preservation: false #关闭注册中心的自我保护机制保证不可用服务被及时提出eviction-interval-timer-in-ms: 2000 #用于驱逐移除的间隔计时器测试浏览器访问localhost:7001很明显说自我保护已经关闭。 客户端服务配置文件application.yml eureka:instance:prefer-ip-address: trueinstance-id: provider8001#Eureka服务端在收到最后一次心跳后等待时间上限默认为90秒超时将服务提出这里值为2意思是如果在2秒内没有收到心跳注册中心将认为该服务实例已过期可能会将该实例从注册表中清除lease-expiration-duration-in-seconds: 2 #Eureka客户端向服务端发送心跳的时间间隔默认30秒,意思是每个1秒发送心跳以保持自己的活跃状态lease-renewal-interval-in-seconds: 1 假设客户端服务宕机看一下测试结果可以看到客户端实例已经被清除掉 5.5 Eureka集群配置 5.5.1 简单说下什么是集群 集群是由多台计算机组成的一个整体他们作为一个整体向用户提供一组网络资源这些单个的计算机系统就是集群的结点node。集群提供了一下关键的特性 可扩展性集群的性能不限于单一的服务实体新的服务实体可以动态地加入到集群中而不会影响到进群的新能。高可用性在集群中如果某个节点出现故障其他节点可以接管其工作从而保证了整个系统的可用性。数据共享在集群中多个节点可以共享同一份数据这样可以避免数据冗余和重复存储。 简单理解集群注册原理 互相注册相互守望。 5.2.2 搭建 修改hosts文件 在原来的基础上创建7002、7003服务注册中心。 在7001、7002、7003的application.yml文件中配置服务注册中心的信息 7001 eureka:instance:hostname: eureka7001.com # Eureka服务端的实例名称client: # false表示不向注册中心注册自己register-with-eureka: false # false表示自己端就是注册中心我的职责是维护服务实例并不需要检索服务service-url:defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/7002 eureka:instance:hostname: eureka7002.com # Eureka服务端的实例名称client: # false表示不向注册中心注册自己register-with-eureka: false # false表示自己端就是注册中心我的职责是维护服务实例并不需要检索服务service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/7003 eureka:instance:hostname: eureka7003.com # Eureka服务端的实例名称client: # false表示不向注册中心注册自己register-with-eureka: false # false表示自己端就是注册中心我的职责是维护服务实例并不需要检索服务service-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/即在三个Eureka服务中心都要相互注册另外两个服务为服务注册中心集群节点 启动三个Eureka服务他们就可以相互注册另外两个为集群节点新城服务注册中心集群 其他微服务在注册时只需要注册到集群中的任意一个节点即可Eureka会同步服务信息。 6、Ribbon负载均衡 官网地址 6.1 概念 ​ Ribbon是Netflix的开源项目他提供了一组云中间件开发组件主要用于通过HTTP和TCP协议进行服务之间的调用、负载均衡以及故障处理。 ​ Ribbon主要包括一下几个核心功能 负载均衡Ribbon是一个客户端负载均衡器它可以根据某种规则如简单轮询、随机连接等在服务器实例结合中选择一个运行实例。在微服务架构中由于服务实例在动态变化因此需要一种机制实时更新服务器实例的变化情况Ribbon就能满足这样的需求。服务调用Ribbon提供了一套完整的HTTP和TCP客户端行为封装。他通过与SpringCloud的整合使用注解的方式就可以实现一个HTTP客户端的创建并发送HTTP请求非常方便。故障处理在一个分布式系统中服务可能因为各种原因调用失败Ribbon提供了多种故障处理策略包括重试、回退等。 6.2 负载均衡器Load Balancer简称LB ​ 在微服务分布式架构中Load Balancer负载均衡器是一种将用户的请求平摊的分发到多个服务实例上从而达到系统的高可用性HA的技术。Load Balancer可以根据不同的负载均衡策略来选择服务实例例如轮询、随机、最小连接数。常见的负载均衡有软件Nginx、LVS硬件F5。 6.2.1 集中式Load Balancer(LB) 集中式LB是指在服务器群集前服务的消费方和提供方之间设置一个独立的LB设备负责接收用户请求,然后根据负载均衡算法将请求转发给后端的不同服务器。在集中式Load Balancer架构中用户只需要知道Load Balancer的地址然后将请求发送到改地址即可而无需关心后端服务实例的具体地址。常见的集中式负载均衡器有硬件F5软件Nginx。 优点部署简单、支持各种负载均衡算法 缺点LB设备单点故障、性能和扩展能力受LB设备限制 6.2.3 进程内Load Balancer(LB) 进程内LB是一种在应用程序内部实现的负载均衡机制不依赖外部独立的负载均衡设备负载均衡逻辑内置在应用进程内。应用进程之间通过进程内通信来实现请求的负载分发如RPC调用、消息队列等。 Ribbon就是一个进程内LB 优点去中心化、避免了集中式负载均衡的单点故障问题、很容易通过增加应用进程实例来进行扩展 缺点由于负载均衡在进程内增加了应用的复杂度需要处理RPC或队列、增加了开发难度、无法做全局优化 6.3 Ribbon的配置 修改80客户端微服务模块 pom文件中加入Ribbon相关以来坐标 !-- Ribbon相关 -- dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-eureka/artifactId /dependency dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-ribbon/artifactId /dependency dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-config/artifactId /dependency在application.yml文件中加入以下内容 eureka:client:register-with-eureka: falseservice-url:defaultZone: http://erureka7001.com:7001,http://eureka7002.com:7002,http://eureka7003.com:7003在ConfigBean中的restTemplate方法上加上LoadBalanced 注解如下 Bean LoadBalanced // 表示这个RestTemplate对象开启了负载均衡功能 public RestTemplate restTemplate(){return new RestTemplate(); }启动类加上EnableEurekaClient注解 SpringBootApplication EnableEurekaClient // 开启Eureka客户端 public class DeptConsumer80_APP {public static void main(String[] args) {SpringApplication.run(DeptConsumer80_APP.class,args);} }修改DeptConsumerController类 在这之前客户端能够访问服务提供端都是绕过了Eureka。什么意思呢如下面代码所示访问路径是写死的。 RequestMapping(/dept/consumer) RestController public class DeptConsumerController {/*** 服务提供端的IP*/public static final String REST_URL_PRIFIX http://localhost:8001;// .... }修改后 RequestMapping(/dept/consumer) RestController public class DeptConsumerController {/*** 服务提供端的IP*///public static final String REST_URL_PRIFIX http://localhost:8001;// 使用微服务的名字public static final String REST_URL_PRIFIX http://MICROSERVICECLOUD-DEPT;}先启动三个Eureka服务端注册中心7001/7002/7003再启动8001微服务将8001注册进注册中心然后在启动80微服务80微服务在yml文件中设置了本身不注册进注册中心然后在浏览器发送请求进行测试。 浏览器输入http://localhost/dept/consumer/get/list出现下图即表示成功。 Ribbon和Eureka整合后Consumer可以直接调用服务而不用在关心地址和端口号 关键之处是 使用Ribbon的过程大致如下 首先使用Ribbon的客户端会获取服务端列表。这个列表可以来自与Eureka等服务注册中心或直接在配置文件中指定。然后Ribbon从这个列表中按照某种策略选择一个地址。例如它可以使用Round-Robin轮询策略。最后Ribbon的客户端会向这个地址发送HTTP请求。 6.4 LoadBalanced注解 在SpringCloud中LoadBalanced是一个重要的注解它用于实现客户端负载均衡。这个注解通常与RestTemplate 或 WebClient 一起使用。下面是一些详细的解释。 解释 LoadBalanced注解的主要用途是提供一种简单的方式来将负载均衡策略应用到指定的服务消费者。换句话说它允许消费者在多个服务提供者实例之间分配请求而不需要明确知道他们的存在。 工作原理 当你在RestTemplate或WebClient bean上使用LoadBalanced注解时SpringCloud会创建一个特殊的代理该代理将拦截所有的HTTP(S)请求。这个代理会使用Ribbon或其他的客户端负载均衡器来选择一个服务实例并将请求重定向到这个实例。 案例 下面是一个使用LoadBalanced的简单实例 Configuration public class MyConfiguration {LoadBalancedBeanpublic RestTemplate restTemplate() {return new RestTemplate();} }在上面的代码中LoadBalanced注解用于一个新创建的RestTemplate bean。现在当你使用这个RestTemplate发送一个HTTP请求时请求会被发送到通过Ribbon选择的服务实例。例如你可以将请求发送到‘my-service’而不需要知道具体的URL String response restTemplate.getForObject(http://my-service/some-endpoint, String.class);在这种情况下Ribbon会从Eureka或其他服务发现系统中获取‘my-service’的所有实例并选择一个来发送请求。 注意在新的SpringCloud版本中RestTemplate已经被弃用推荐使用WebClient。 6.5 负载均衡案例 架构说明 扩展微服务工程 参考微服务提供者dept-8001创建dept-8002/dept-8003微服务 新建数据库sringCloud02、springcloud03各微服务分别连接自己的数据库。这里只是简单的创建两个库来模拟主从同步读写分离。 #建库脚本 CREATE DATABASE springcloud01 CREATE DATABASE springcloud02 CREATE DATABASE springcloud03 #建表脚本需要在三个库中都执行一下 CREATE TABLE dept (deptNo int(11) NOT NULL AUTO_INCREMENT,deptName varchar(255) DEFAULT NULL,dbSource varchar(255) DEFAULT NULL,PRIMARY KEY (deptNo) ) ENGINEInnoDB AUTO_INCREMENT14 DEFAULT CHARSETutf8; #插入数据脚本只需要改一下‘springcloud03’ INSERT INTO dept ( deptName, dbSource) VALUES ( 张三, springcloud03); INSERT INTO dept ( deptName, dbSource) VALUES ( 李四, springcloud03); INSERT INTO dept ( deptName, dbSource) VALUES ( 王五, springcloud03); INSERT INTO dept ( deptName, dbSource) VALUES ( 赵六, springcloud03);修改8002/8003各自YML文件 8003也是同样的方式修改。 启动3个eureka集群 启动3个dept微服务进行自测 分别自测三个微服务提供端 发送8001的请求 发送8002的请求 发送8003的请求 启动客户端80通过注册中心进行访问。 可以看到每次点击刷新按钮都会获取到不同的相应数据。这就是Ribbon的负载均衡轮询算法。 6.6 Ribbon核心组件IRule 根据特定算法从服务列表中选取一个要访问的服务。 默认情况下会使用轮询算法分发请求即依次向可用服务实例发送请求。 通过实现Rule接口可以自定义请求路由规则。主要有以下几种 RoundRobinRule轮询【默认】轮询所有可用服务实例依次向每个实例发送请求。RandomRule随机规则随机选择一个可用服务实例发送请求。WeightedResponseTimeRule加权响应时间规则按服务实例的权重分配请求。权重大的实例处理更多请求。AvailabilityFilterRule可用性筛选规则先过滤掉当前不可用的服务实例然后根据轮询、随机等策略分发请求。BestAvailableRule最佳可用规则选择一个最少活跃的服务实例发送请求分散负载均衡压力。RetryRule重试规则首先使用某个IRule路由如果请求失败则会重新请求如果再次失败则结合断路器进行处理。ZoneAvoidanceRule区域回避规则考虑服务实例所在区域的性能和访问性尽量避免高延迟的区域。 所以通过实现自定义的IRule我们可以按照自己的需求实现复杂的请求路由策略。 IRule很重要的一点是它决定着服务调用的稳定性和性能。选择一个合适的路由策略可以有效地分散负载提高吞度量和成功率。 6.6.1 更换Ribbon负载均衡算法 ConfigBean.java配置类中定义算法 /*** 更换算法*/Beanpublic IRule myRule(){// 随机算法return new RandomRule();}重启80服务发送请求 可以看到每次刷新所请求的服务是随机的。 特别地重试规则 /*** 更换算法*/Beanpublic IRule myRule(){// 随机算法//return new RandomRule();// 重试算法return new RetryRule();}重启80 服务此时我们将8001服务提供短down掉来模拟服务挂掉的场景。如果没有down掉的服务的话会按照某个算法一般是轮询来分发请求 发送80客户端请求 可以看到不在去找8002的服务实例了。 其他的分发算法不在一一演示。有兴趣的伙伴可以自己测试一下来加深印象 只需要按这个格式去定义就行了。 6.6.2 自定义Ribbon负载均衡策略 现在需求是不使用Ribbon提供的负载均衡算法需要开发人员自定义。 在开始前先了解一下RibbonClient注解该注解是用于自定义Ribbon客户端配置。在启动该微服务的时候就能去加载我们的自定义的Ribbon配置类从而是配置生效 RibbonClient(name serviceName, configuration MyClientConfig.class)nameRibbon客户端名称即服务名称用于标识这个Ribbon客户端。configuration自定义的Ribbon配置类。 案例1使用最少连接算法实现自定义Ribbon负载均衡策略 算法实现 public class CustomRule extends AbstractLoadBalancerRule {// 声明一个map类型的成员变量用来存放每个服务器的连接数private ConcurrentHashMapServer, AtomicInteger connectionCountMap;//public CustomRule() {connectionCountMap new ConcurrentHashMap();}Overridepublic void initWithNiwsConfig(IClientConfig clientConfig) {// 不需要额外的配置留空}Overridepublic Server choose(Object key) {// 获取所有可用服务器列表ListServer servers getLoadBalancer().getAllServers();// 存储连接数最少的服务器Server leastConnectionsServer null;// 初始化整形最大值记录当前最少连接数int leastConnections Integer.MAX_VALUE;// 遍历服务器列表for (Server server : servers) {// 根据服务器从connectionCountMap中获取对应的连接数。AtomicInteger connections connectionCountMap.get(server);// 连接数为空if (connections null) {// 初始化连接数为0connections new AtomicInteger(0);// 将服务其和对应的连接数存入map中connectionCountMap.put(server, connections);}// 获取当前服务器的连接数int currentConnections connections.get();// 如果当前连接数小于最小连接数if (currentConnections leastConnections) {// 更新最小连接数为当前连接数leastConnections currentConnections;// 更新连接数最小的服务器为当前服务器leastConnectionsServer server;}}// 如果当前连接数最小的服务器不为空if (leastConnectionsServer ! null) {// 将连接数最少的服务器连接数加一connectionCountMap.get(leastConnectionsServer).incrementAndGet();}// 返回连接数最小的服务器return leastConnectionsServer;} }案例2使用随机规则只不过要求每个服务被调用5次 public class RewritePolling extends AbstractLoadBalancerRule {private int total 0; // 记录已调用次数private int currentIndex 0; // 当前选择的服务实例索引Overridepublic Server choose(Object key) {// 获取负载均衡器ILoadBalancer lb getLoadBalancer();if (lb null) {return null;}Server server null;while (server null) {// 检查线程是否被中断if (Thread.interrupted()) {return null;}// 获取可到达的服务实例列表ListServer upList lb.getReachableServers();// 获取所有的服务实例列表ListServer allList lb.getAllServers();// 服务实例总数int serverCount allList.size();if (serverCount 0) {return null;}// Github源码不是每个服务调用5次//int index chooseRandomInt(serverCount);//server upList.get(index);if (total 5) {// 选择当前索引对应的服务实例server upList.get(currentIndex);// 让调用次数加一total;} else {// 调用次数大于了5次后将调用次数置为0total 0;// 调用下一个服务实例currentIndex;// 当索引超出范围时重新从头开始选择if(currentIndex upList.size()){currentIndex 0;}}if (server null) {// 放弃当前线程的CPU时间片让其他线程执行Thread.yield();continue;}// 检查服务实例是否存活if (server.isAlive()) {return (server);}server null;Thread.yield();}return server;}Overridepublic void initWithNiwsConfig(IClientConfig clientConfig) {// 初始化操作} }将自定义算法应用到负载均衡器中 Bean public IRule ribbonRule(){// 最少连接算法//return new CustomRule(); // 随机算法每个服务被调用5次return new RewritePolling(); }主启动类上加上RibbonClient注解 RibbonClient(nameMICROSERVICECLOUD-DEPT,configuration ConfigBean.class) // 加载自定义Ribbon客户端配置 public class DeptConsumer80_APP {public static void main(String[] args) {SpringApplication.run(DeptConsumer80_APP.class,args);} }注意点RibbonClient注解和负载均衡规则类需要位于不同的包中主要有以下两个原因 在Spring初始化阶段RibbonClient所在的类会优先初始化。它用来配置Ribbon客户端指定负载均衡规则类。如果RibbonClient和负载均衡规则类位于同一包中在Spring初始化阶段会产生循环依赖。RibbonClient 初始化时需要加载负载均衡规则类但是负载均衡规则类还没有初始化。 所以为了避免初始化顺序问题和循环依赖RibbonClient所在类的包不能与负载均衡规则类所在的包相同。 简单来说就是 RibbonClient负责配置ribbon客户端以及制定负载均衡规则。负载均衡规则类实现负载均衡算法逻辑。 7、Feign负载均衡 官方地址 源码地址 7.1 概念 ​ Feign是一个声明式的Web服务客户端使用Feign能让编写Web服务客户端更加简单他的使用方法是定义一个接口然后在上面添加注解同时也支持JAX-RS标准的注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。 说白了就是Feign是一个Web服务客户端是的编写Web服务客户端变得非常容易。 只需创建一个接口然后在上面添加注解即可。 7.2 为什么使用Feign ​ 开发中由于对服务依赖的调用可能不止一处往往一个接口会被多处调用所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以Feign在此基础上做了进一步封装由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下我们只需要创建一个接口并使用注解的方式来配置它以前是Dao接口上面标注Mapper注解现在是一个微服务接口上面标注一个Feign注解即可即可完成对服务提供方的接口绑定简化了使用SpringCloud Ribbon时自动封装服务调用客户端的开发量。 ​ Feign继承了Ribbon ​ 利用Ribbon维护了注册中心的服务列表信息并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是通过Feign只需要定义服务绑定接口且以声明式的方法优雅而简单的实现了服务调用。 ​ Feign通过接口的方法调用Rest服务之前是Ribbon RestTemplate该请求发送给Eureka注册中心通过Feign直接找到服务接口由于在进行服务调用的时候融合了Ribbon技术所以也支持负载均衡。 7.3 Feign的特点 简化HTTP客户端的创建Feign可以自动创建并绑定接口到HTTP请求这大大简化了HTTP客户端的创建和使用。集成Ribbon和HystrixFeign可以与Neflix的其他开源项目Ribbon客户端负载均衡器和Hystrix断路器结合使用从而提供负载均衡和容错能力。支持插件化和可扩展Feign支持插件化开发者可以通过实现特定的接口或者注解来扩展Feign的功能。使用注解来定义HTTP请求Feign使用注解来定义HTTP请求这使得代码更加清晰和易于理解。SpringCloud中的一部分Feign是SpringCloud的一部分 7.4 搭建 导入依赖坐标 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-feign/artifactId /dependency定义接口 RequestMapping(/dept) FeignClient(value MICROSERVICECLOUD-DEPT) public interface DeptClientService {PostMapping(/add)boolean add(Dept dept);GetMapping(/get/{id})Dept get(PathVariable(id) Long id);GetMapping(/get/list)ListDept list(); }客户端通过接口调用 RestController public class DeptConsumerController {public static final Logger logger LoggerFactory.getLogger(DeptConsumerController.class);AutowiredDeptClientService deptClientService;PostMapping(/add)public boolean add(RequestBody Dept dept){boolean flag deptClientService.add(dept);if(flag){logger.info(增加成功);}return flag;}GetMapping(/get/{id})public Dept get(PathVariable(id) Long id){return deptClientService.get(id);}GetMapping(/get/list)public ListDept list(){return deptClientService.list();} }测试POSTMAN发送请求http://localhost/get/list 为什么接口上加了FeignClien注解就可以访问到远程的服务了呢 本案例中FeignClient(value MICROSERVICECLOUD-DEPT)表示DeptClientService接口是一个Feign客户端代理接口他将用于访问名为“MICROSERVICECLOUD-DEPT”的远程服务。通过该注解Feign将根据接口定义自动创建一个代理类实现用于与远程服务进行通信。我这里调用的是DeptClientService接口中list()方法Feign将自动将请求发送到MICROSERVICECLOUD-DEPT/dept/get/list 路径上. 那么接口是如何找到远程服务的呢 这是因为主启动类上标注了EnableFeignClients(basePackages {com.atpl.springcloud})该注解需要制定basePackages参数用于指定要扫描的包路径即扫描有FeignClient注解的接口并为其生成代理实现。 8、Hystrix断路器 官网地址 8.1 概念 Hystrix断路器是一种用于构建韧性和弹性分布式系统的开源库。它最初由Netflix开发并广泛应用于微服务架构中以帮助应对服务间的故障和延迟。 Hystrix的主要目的是防止级联故障。在分布式系统中一个服务的失败或延迟可能会导致对其依赖的其他服务也出现问题从而引发级联故障。Hystrix通过实施断路器模式来解决这个问题。断路器模式允许在服务出现故障或延迟时通过断路器的故障监控向调用方返回一个快速失败并提供备用的响应而不是一直等待或继续尝试请求。 8.2 工作原理 当一个服务的请求频率达到一定的阈值时Hystrix会监视该服务的状态。如果服务的错误率超过预设的阈值时Hystrix会打开断路器将请求转发到备用的服务或返回预设的默认响应。在一段时间内Hystrix会定期尝试发出一些试探性请求到原始服务已检查其是否恢复正常。如果试探性请求成功Hystrix会关闭断路器继续将请求转发到原始服务。如果试探性请求失败Hystrix会继续保持断路器打开状态并延迟一段时间后再次尝试试探性请求。 Hystrix还提供了其他功能包括请求缓存、请求合并、线程池隔离和实时的监控和指标收集。这些功能使得开发人员能够更好地理解和管理服务之间的依赖关系并在故障发生时提供更好的容错能力。 8.3 服务熔断 熔断机制是应对雪崩效应的一种微服务链路保护机制。 当扇出链路的某个微服务不可用或者响应时间太长时会进行服务的降级进而熔断该结点微服务的调用快速返回“错误”的响应信息并返回一个事先定义好的备选响应或错误结果 FallBack。当检测到该结点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务调用的状况当失败的调用到一定阈值缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是HystrixCommand。 HystrixCommand注解解释 该注解由Hystrix提供用于实现服务的容错和隔离。**当使用该注解时Hystrix会将被注解的方法封装在一个独立的线程池中并未该方法设置一个超时时间。**如果该方法执行时或发生异常Hystrix会自动触发服务降级从而保证系统的可用性和稳定性。此外HystrixCommand 还支持实现服务熔断、请求缓存等功能。 EnableCircuitBreaker注解解释 该注解由SpringCloud提供用于断路器功能通过监控和控制对远程服务的调用来实现容错和故障恢复的机制。该注解主要开启断路器功能会自动为使用断路器模式的Bean创建代理断路器代理会监控这些方法的调用情况。如果调用远程服务出现故障或超市断路器会阻止对该服务的进一步调用。然后通过故障恢复的机制调用备用服务或者返回预先定义的错误消息。 GetMapping(/get/{id})// 一旦调用服务方法失败并抛出了错误信息后会自动调用HystrixCommand标注的fallBackMethod调用类中指定的方法 HystrixCommand(fallbackMethod processHystrix_Get) public Dept get(PathVariable Long id) {Dept dept deptService.get(id);if (dept null) {// 抛出自定义的异常throw new CustomException(dept is null);}return dept; }// 服务熔断后处理方法 (fallback方法) public Dept processHystrix_Get(PathVariable Long id) {// 处理服务异常或超时情况下的逻辑return new Dept().setDeptNo(id).setDeptName(); }注意 标记了HystrixCommand注解的额方法与fallback方法的返回值类型与参数列表不一定保持一致。需要遵守一些要求 返回值类型fallback方法的返回值类型应该与标记了HystrixCommand方法的返回值类型兼容。比如标记了HystrixCommand方法返回一个String类型那么fallback方法也要返回一个String类型或其子类。 8.4 服务降级 ​ 服务降级是一种应对系统故障、资源不足或异常情况下的策略旨在保证系统的可用性和稳定性。当系统出现故障、性能下降或资源紧张时服务降级通过临时屏蔽某些功能或切换到备用方案来减少对系统的负载确保核心功能的正常运行并提供用户友好的响应。 服务降级的主要目标是在面对异常情况时保持系统的可用性避免因单个组件的故障而导致整个系统的崩溃。 fallback方法与业务逻辑方法在一起或者有很多方法都需要服务熔断那么每个方法都要加上HystrixCommand注解这是一种高耦合的表现。 优化所有要加HystrixCommand的方法都是来源于接口中那么将接口进行熔断岂不是每个方法发不用再一一的添加HystrixCommand。 实现 /*** author cpl* 服务降级处理* 将其从业务逻辑中拆分出来降低耦合*/ Component public class DeptClientServiceFallBackFactory implements FallbackFactoryDeptClientService {Overridepublic DeptClientService create(Throwable cause) {return new DeptClientService() {Overridepublic Dept get(Long id) {return new Dept().setDeptNo(id).setDeptName();}};} }DeptClientService接口 FeignClient(value MICROSERVICECLOUD-DEPT,fallbackFactory DeptClientServiceFallBackFactory.class) public interface DeptClientService {GetMapping(/get/{id})Dept get(PathVariable(id) Long id); }# 启用feign客户端熔断器 feign:hystrix:enabled: true这样就将fallback方法与业务逻辑分离开从而也实现服务降级。可以发现服务降级是在客户端实现的。另外客户端服务降级及时服务关闭也能看到提示信息而不会挂起耗死服务器。 8.5 服务降级与服务熔断的区别 概念 服务熔断Circuit Breaking是一种用于处理故障的模式它旨在防止故障在整个系统中扩散。当服务发生故障或超过一定阈值时熔断器会打开并快速拒绝后续的请求从而减轻对故障服务的压力。服务熔断的核心目标是保护系统免受不可用服务的影响提高系统的容错性。一旦熔断器打开可以采取一些措施如返回缓存数据、返回默认值或使用备用服务等。 服务降级Fallback是一种在服务不可用或性能下降时提供有限但可用功能的策略。当服务发生故障、性能下降或超过一定的响应时间时可以通过服务降级来返回预先定义的默认值、缓存数据或备用结果。服务降级的目标是确保调用方在面对异常情况时仍能够获得响应而不会因为服务不可用而导致整个系统的不可用。服务降级可以在单个服务内部实现也可以由调用方在失败时采取备用策略。 区别 目的服务熔断的目标是防止故障在整个系统中扩散保护系统免受不可用服务的影响服务降级的目标识在服务不可用或性能下降时提供有限但可用的功能确保调用方仍能够获得相应。 触发条件服务熔断触发条件通常是错误率超过阈值或请求失败次数超过阈值服务降级触发条件通常是服务不可用、性能下降或超过一定的响应时间。 动作服务通断打开后可以采取一些措施如返回缓存数据、返回默认值或使用备用服务等服务降级时可以返回预先定义的默认值、缓存数据或备用结果。 范围服务熔断通常是在服务间的通信层面进行以防止故障在整个系统中扩散服务降级可以在单个服务内部实现也可以有调用方在失败时采用备用策略。 8.6 服务监控 pom文件新增依赖 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-hystrix/artifactId /dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-hystrix-dashboard/artifactId /dependency主启动类新增注解EnablebHystrixDashboard application.yml server:port: 9001浏览器输入http://localhost:9001/hystrix出现如下界面 监控测试 浏览器输入http://localhost/8001/hystrix.stream 此界面会一直刷新。 也可以通过Dashboard界面测试 Delay控制服务器上轮询监控信息的延迟时间默认2000毫秒可通过配置改属性降低客户端的网络和CPU的消耗。 Title该参数对应了头部标题Hystrix Stream之后的内容默认会使用具体监控实例的URL可以通过配置该信息来展示更合适的标题。 点击Monitor Stream后跳转到如下界面 9、Zuul路由网关 9.1 概念 ​ Zull是Netflix开源的一个基于JVM的边缘服务网关用于在微服务架构中提供动态路由、过滤器、负载均衡、安全性能等功能。他作为应用程序的前置网关接收所有的客户端请求并将请求路由到适当的微服务实例。 注意Zull服务最终还是会注册进Eureka 提供代理路由过滤三大功能 9.2 主要功能 路由RoutingZull可以根据配置将请求路由到不同的微服务实例或后端服务。他支持基于RUL路径、主机名、请求参数等条件进行灵活的路由规则配置。过滤器FilteringZull的过滤器机制可以在请求进入和响应返回时进行预处理和后处理。通过变细自定义的过滤器可以实现身份验证、请求转换、日志记录、请求限流等工能。负载均衡Load BalancingZull集成了负载均衡功能可以根据配置将请求均匀的分发到多个微服务实例以提高系统的可伸缩性和可用性。安全性SecurityZull可以通过与认证和授权服务进程实现对请求的安全验证和访问控制。可以拦截请求畸形身份验证确保只有经过验证的请求才能访问后端服务。监控和日志Monitoring and LoggingZull支持继承监控和日志系统可以记录请求的状态、响应事件等指标帮助开发人员进行故障排查和性能优化。 9.3 路由的基本配置 导入依赖 dependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-eureka/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-zuul/artifactId/dependency /dependencies主启动类加上 EnableZuulProxyapplication.yml server:port: 9527spring:application:name: microservicecloud-zull-gateway # 微服务实例名称eureka:client:service-url:defaultZone: http://eureka7001:7001.com/eureak,http://eureka7002:7002/eureka,http://eureka7003:7003/eurekainstance: # 配置Zull的实例instance-id: gateway-9527.com # Zull实例唯一标识符prefer-ip-address: true # 是否优先使用Ip地址进行路由值为ture时会优先使用服务实例的IP地址进行访问 访问Eureka的注册中界面 测试zull 普通访问 通过网关访问 9.5 路由的访问映射规则 application.yml文件中 zuul:routes:agent.serviceId: microservicecloud-dept # 指定agent路由规则将转发到的服务的服务IDagent.path: /agent/** # 路径匹配规则,指定匹配该路由规则的请求路径 (配置服务的匿名),本例中所有以/agent/开头的路径都会匹配该规则。ignored-services: microservicecloud-dept # 忽略的服务如果要忽略多个可以使用 * 号prefix: /atpl # 前缀配置指定了Zuul路由的前缀路径。本例中Zuul将会将所有的路由请求的路径加上“/atpl”前缀可以看到上图中请求路径中是使用的路由规则所以能访问到。 然而下图中由于配置了 ignored-services: microservicecloud-dept所以访问路径中含有microservicecloud-dept则该请求将会被忽略不会进行路由转发。 使用prefix: /atpl配置了前缀 访问原来的路径 访问带有前缀的路径 10、SpringCloud Config分布式配置中心 10.1 服务端 分布式系统面临的—配置问题 ​ 微服务意味着要将单体应用中的业务拆分成一个个子服务每个服务的粒度相对较小因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行所以一套集中式的、动态的配置管理设施是必不可少的。SpringCloud提供了ConfigServer来解决这个问题。每个服务都有一个application.yml文件那么上百个服务呢岂不悲剧了 10.1.1 是什么 SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。 10.1.2 怎么玩 SpringCloud Config分为服务端和客户端两部分。 服务端也称为分布式配置中心他是一个独立的微服务应用用来连接配置服务器并为客户端提供获取配置信息加密/解密信息等访问接口。 客户端则是通过指定的配置中心来管理应用资源以及与业务相关的配置内容并在启动的时候从配置中心获取和加载配置信息配置服务器默认采用git来存储配置信息这样就有助于对环境配置进行版本管理并且可以通过git客户端工具来方便的管理和访问配置内容。 10.1.3 能干嘛 集中化配置管理SpringCloud Config 提供了一个集中化的配置存储库可以将应用程序的配置信息存储在版本控制系统如Git或其他后端存储中。通过集中管理配置可以实现配置的版本控制、审计和变更历史记录。配置文件的外部化SpringCloud Config 允许将应用程序的配置文件从代码中分离出来已实现配置与代码的解耦。配置文件可以根据环境、应用程序实例等进行不同的配置而无需重新打包和部署应用程序。动态刷新配置SpringCloud Config 支持配置的动态刷新即在应用程序运行时可以重新加载配置信息而无需重启应用程序。进而避免重新部署应用程序或重启服务的操作。多环境支持SpringCloud Config支持多环境配置可以为不同的环境开发、测试、生产提供不同的配置信息。通过使用不同的配置文件或配置文件的目录结构轻松管理和区分不同环境的配置。安全性和权限控制SpringCloud Config 支持对配置信息进行安全性管理和权限控制。可以通过身份验证和授权机制限制对配置信息的访问权限确保配置的机密性和完整性。 10.1.4 Config服务端与Github的通信 SpringCloud Config 与 GitHub整合步骤 在GitHub上新建一个仓库用于存储配置文件。可以按照应用程序、环境或其他自定义方式组织配置文件。 在本地创建本地仓库并克隆GitHub上的microservicecloud-config仓库 然后再此文件夹中新建application.yml文件要保存成UTF-8的格式要保存成UTF-8的格式 spring:profiles:active:- dev --- spring:profiles: devapplication:name: microservicecloud-config-dev --- spring:profiles: testapplication:name: microservicecloud-config-test --- spring:profiles: prodapplication:name: microservicecloud-config-prod #编码格式保存为UTF-8将文件推到远程的GitHub从库中 远程库 创建SpringCloud Config 微服务如下 application.yml文件 server:port: 3344spring:application:name: microservicecloud-config # 应用程序名用于从SpringCloud Config 服务器获取配置cloud:config:server:git:uri: https://github.com/pinlu-0/microservicecloud-config.git # 指定远程GitHub存储库的URIusername: #GitHub用户名password: #Github密码default-label: main # 分支主启动类 SpringBootApplication /*** 开启配置服务器的功能*/ EnableConfigServer public class Config_App_3344 {public static void main(String[] args) {SpringApplication.run(Config_App_3344.class);} }pom文件 !-- SpringCloud Config 依赖-- dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-config-server/artifactId /dependency启动配置中心服务http://localhost:3344/application-dev.yml 但是这种是通过https的形式访问的远程库 使用SSH秘钥远程访问比较坑下面介绍怎么使用SSH远程访问 首先生成秘钥并添加到GitHub中 #生成秘钥 ssh-keygen -t rsa -b 4096 -C youremailexample.com#测试SSH连接,如果出现如下信息则表示成功 ssh -T gitgithub.comHi USERNAME! Youve successfully authenticated, but GitHub does notprovide shell access.按道理应该是可以访问了的但是出现了报错大概意思是github不支持RSA秘钥它认为这种算法的秘钥不安全。 所以使用 ssh-keygen -t ed25519 -C “yourmailexample.com” 命令生成秘钥但是呢这种生成的秘钥是 OPENSSH类型的而com.jcraft.jsch不兼容OPENSSH所以。做在这只是简单试了一下应为可能需要更换版本比较麻烦也没有深入解决。后续可能会解决 10.1.5访问方式 10.2 客户端 10.2.1 单机版 配置客户端 pom文件 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-config/artifactId /dependency测试类 RestController public class ConfigClientController {Value(${spring.application.name})private String applicationName;Value(${eureka.client.service-url.defaultZone})private String eurekaServers;Value(${server.port})private String port;RequestMapping(/config)public String getConfig() {String str applicationName: applicationName \n eurekaServers: eurekaServers \n port: port ;System.out.println(******str: str);return applicationName: applicationName \n eurekaServers: eurekaServers \n port: port ;} }bootstrap.yml文件 spring:cloud:config:name: microservicecloud-config-client #profile: testlabel: masteruri: http://config-3344.com:3344 # 指定配置服务端的URI测试启动服务端启动客户端。 测试访问服务端http://localhost:3344/microservicecloud-config-client-dev.yml 测试访问客户端http://localhost:8201/config,可能回报以下错误原因是服务端不能够访问到数据可以单独测试一下服务端是否能访问到数据。 Could not resolve placeholder eureka.client.service-url.defaultZone in value ${eureka.client.service-url.defaultZone}浏览器打印数据 控制台打印数据 通过修改bootstrap.pom文件测试8201端口 现在我们做一个通过Eureka服务一个Dept客户端访问的服务将两个微服务的配置统一由github获得实体统一配置分布式管理完成多环境的变更。 10.2.2 访问注册中心版 新建配置版Eureka注册中心 bootstrap.yml内容 spring:cloud:config:name: microservicecloud-config-eureka-client # 需要从github上读取的资源名称profile: devlabel: masteruri: http://config-3344.com:3344 # 服务端地址服务端存放在配置中心GitHub上的文件microservicecloud-config-eureka-client spring:profiles:active:- dev --- server:port: 7001 spring:profiles: devapplication:name: microservicecloud-config-eureka-clienteureka:instance:hostname: eureka7001.comclient:register-with-eureka: false # 当前的Eureka-server自己不注册到服务列表中fetch-registry: false # 不通过Eureka获取注册信息service-url:defaultZone: http://eureka7001.com:7001/eureka/ --- server:port: 7001 spring:profiles: testapplication:name: microservicecloud-config-eureka-clienteureka:instance:hostname: eureka7001.com # 冒号后面必须有空格client:register-with-eureka: false # 当前的Eureka-server自己不注册到服务列表中fetch-registry: false # 不通过Eureka获取注册信息service-url:defaultZone: http://eureka7001.com:7001/eureka/新建配置客户端可参考之前的 bootstrap.yml内容 spring:cloud:config:name: microservicecloud-config-dept-client # 需要从github上读取的资源名称profile: devlabel: masteruri: http://config-3344.com:3344 # config服务端的访问地址客户端存放在配置中心GitHub的文件内容microservicecloud-config-dept-client spring:profiles:active:- dev --- server:port: 8001 spring:profiles: devapplication:name: microservicecloud-config-dept-clientdatasource:type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型driver-class-name: com.mysql.jdbc.Driver # mysql驱动包url: jdbc:mysql://localhost:3306/springcloud01 # 数据库名称username: rootpassword: rootdbcp2:min-idle: 5 # 数据库连接池的最小维持连接数initial-size: 5 # 初始化连接数max-total: 5 # 最大连接数max-wait-millis: 200 mybatis:config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径type-aliases-package: com.atpl.springcloud.entities # 所有Entity别名类所在包mapper-locations:- classpath:mybatis/mapper/**/*.xmleureka:client: # 客户端注册进eureka服务列表内service-url:defaultZone: http://eureka7001.com:7001/eureka/# 单机版 defaultZone: http://localhost:7001/eurekainstance:instance-id: dept-8001.com # 自定义服务名名称信息prefer-ip-address: true info: # 指定应用程序的元数据app.name: atpl-microservicecloud # 指定应用程序的名称可以用来标识应用程序在整个系统中的作用company.name: www.atpl.com # 指定应用程序所属的公司名称build.artifactId: ${project.artifactId} # 指定应用程序的构件ID通常是Maven项目中的artifactIdbuild.version: ${project.version} #指定应用程序的版本号通常是Maven项目中的version---server:port: 8001 spring:profiles: testapplication:name: microservicecloud-config-dept-clientdatasource:type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型driver-class-name: com.mysql.jdbc.Driver # mysql驱动包url: jdbc:mysql://localhost:3306/springcloud02 # 数据库名称username: rootpassword: rootdbcp2:min-idle: 5 # 数据库连接池的最小维持连接数initial-size: 5 # 初始化连接数max-total: 5 # 最大连接数max-wait-millis: 200 mybatis:config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径type-aliases-package: com.atpl.springcloud.entities # 所有Entity别名类所在包mapper-locations:- classpath:mybatis/mapper/**/*.xmleureka:client: # 客户端注册进eureka服务列表内service-url:defaultZone: http://eureka7001.com:7001/eureka/# 单机版 defaultZone: http://localhost:7001/eurekainstance:instance-id: dept-8001.com # 自定义服务名名称信息prefer-ip-address: true info: # 指定应用程序的元数据app.name: atpl-microservicecloud # 指定应用程序的名称可以用来标识应用程序在整个系统中的作用company.name: www.atpl.com # 指定应用程序所属的公司名称build.artifactId: ${project.artifactId} # 指定应用程序的构件ID通常是Maven项目中的artifactIdbuild.version: ${project.version} #指定应用程序的版本号通常是Maven项目中的version测试优先启动3344他启动的过程bootstrap.yml会优先加载会去GitHub上获取配置信息然后启动7001服务注册中心在启动8001客户端。 浏览器发送请求http://localhost:8001/dept/get/list http://eureka7001.com:7001/ 11、补充知识点 11.1 Maven的几个命令的用处 mvn clean清除项目中的构建产物例如target目录和生成的jar、war等文件。mvn compile编译项目中的Java源文件。mvn test运行项目中的测试用例。mvn package生成项目的可部署的打包文件例如jar、war等。mvn install将项目的打包文件安装到本地Maven仓库中以便其他项目可以使用该依赖。mvn deploy将项目的打包文件部署到远程Maven仓库中以便其他项目可以使用该依赖。mvn dependency:tree打印项目依赖树显示项目中所有的依赖关系。mvn help:describe列出Maven命令的详细信息和用法。11.2 分布式数据库中的CAP原理CAPBASE 11.2.1 传统的ACID分别是什么 ACID是传统关系型数据库Transaction处理的四个基本属性: A : 原子性 事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。C : 一致性 事务必须使数据库从一个一致性状态变换到另一个一致性状态。I : 独立性 事务的隔离性有多种级别,最常见的是READ-COMMITTED隔离级别,即一个事务内的更新在提交之前对其他事务是不可见的。D : 持久性 已提交的事务对数据库的修改应该永久保存在数据库中。 11.2.2 CAP CAP 是分布式系统设计中需要考虑的三个指标: C 强一致性所有节点访问同一份最新的数据副本A 可用性非故障节点在合理的时间内返回合理的响应P 分区容错性系统还能正常工作即使发生网络分区 根据CAP定理这三个指标不可能同时满足最多只能同时满足其中两个即3进2要么AP要么CP要么CA不可能三者兼得。P一定是占有的因为网络可能出现延迟丢包等问题。 CAP 理论的核心思想是:一个分布式系统不可能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition Tolerance)这三项属性。 在分布式系统设计中不同系统可以根据业务需求在AP和CP之间做不同的权衡 追求一致性和分区容错的系统,通常需要牺牲可用性,比如采用单主模式的数据库集群。追求可用性和分区容错的系统,通常需要牺牲一致性,实现异步复制和事件最终一致性,比如NoSQL数据库。追求一致性和可用性的系统,通常需要牺牲分区容错,采用单实例或者传统集群,比如Core Banking系统。 下面列举出一些场景使用的CAP组合 对强一致性要求高的场景,如金融账务处理,应选择 CP。可以采用主备模式,牺牲系统可用性来保证一致性。对高可用性要求高的场景,如电商网站,应选择 AP。可以使用 NoSQL 数据库,通过副本和异步复制实现高可用。对网络分区故障敏感的场景,如分布式游戏,应选择 CP。要求系统在分区故障时牺牲可用性而不破坏一致性。对实时性要求较高的场景,如即时通信,可选择 AP,通过快速响应保证可用性和实时性。对临时不一致性可以容忍的场景,如非关键流量分析,可选择 AP,牺牲强一致来获得系统可用性。基础设施类服务,如 DNS,注册中心等,需要选择 CP,确保服务地址等元数据一致性。数据处理类系统,对一致性要求较低,可选择 AP,用重复计算等方式容忍短暂不一致。 11.2.3 经典CAP图 11.2.4 BASE 是什么 11.2.5 分布式集群简介 11.2.6 Eureka比Zookeeper好在哪里 Zookeeper与Eureka都是分布式系统中的重要协调组件主要区别如下 用途不同 Zookeeper是一个协调服务提供分布式锁、集群管理、元数据存储等功能。 Eureka是一个服务注册中心用于服务发现与注册。 数据存储方式不同 Zookeeper采用属性结构存储数据支持嵌套适合保存配置、状态等复杂信息。 Eureka采用扁平的Key-Value结构主要存储服务实例信息。 节点角色不同 Zookeeper节点通过Leader选举产生节点角色对等。 Eureka各节点地位平等可独立对外提供服务。 一致性保证不同 Zookeeper通过ZAB协议保证一致性。 Eureka为了可用性保证最终一致性。 容错机制不同 Zookeeper通过Leader选举恢复可用性。 Eureka通过自我保护机制防止网络分区网络中的某些节点因为网络故障而无法与其他节点通信是的误删。 语言不同 Zookeeper使用Java语言实现。 Eureka使用Java和Scala语言实现。 总体来说说Zookeeper偏向于强一致性Eureka偏向于高可用性。 11.3 Mapper注解与MapperScan注解 这两个注解标注的位置不一样Mapper注解标注在Mapper接口上表示该接口为Mapper接口Mybatis会自动扫描并注册该接口。 而MapperScan是标注在主启动类上的注解它是扫描某个包下所有的Mapper接口。这种适用于某个包下有很多Mapper接口。 11.4 application.yml与bootstrap.yml的区别 首先application.yml与bootstrap.yml都是SpringBoot应用程序中常用的配置文件用于配置应用程序的属性和设置。 application.yml是主要的配置文件定义程序的**一般(用户级别)**属性和设置。bootstrap.yml是在应用程序启动阶段加载的配置文件用于配置一些系统级别的属性和配置。它优先于application.yml加载主要配置一些在程序启动前需要提前配置的属性 SpringCloud在程序初始化过程中创建了一个‘Bootstrap Context’ 上下文,它充当了Spring应用的‘Application Context’的父上下文。初始化的时候‘Bootstrap Context’负责从外部资源加载配置属性并解析配置。这两个上下文共享一个从外部获取的‘Environment’环境。‘Bootstrap’ 属性有高优先级默认情况下他们不会被本地配置覆盖。‘Bootstrap Context’和‘Application Context’有着不同的约定。 所以新增了一个‘bootstrap.yml’文件保证’Bootstrap Context’和’Application Context’配置的分离。 二、SpringCloud高阶篇 1. 前言 高阶篇的技术与初阶篇技术用较新版本的SpringBoot与SpringCloud 下图是SpringCloud与SpringBoot的版本映射关系 具体版本浏览器输入https://start.spring.io/actuator/info ,会返回一个JSON数据来显示版本信息。 {git: {branch: 53acf2ef792d1b167c889ab4f19501c7acf730b5,commit: {id: 53acf2e,time: 2023-08-29T07:26:28Z}},build: {version: 0.0.1-SNAPSHOT,artifact: start-site,versions: {spring-boot: 3.1.3,initializr: 0.20.1-SNAPSHOT},name: start.spring.io website,time: 2023-08-29T07:27:38.085Z,group: io.spring.start},bom-ranges: {codecentric-spring-boot-admin: {2.6.8: Spring Boot 2.6.0 and 2.7.0-M1,2.7.4: Spring Boot 2.7.0-M1 and 3.0.0-M1,3.0.4: Spring Boot 3.0.0-M1 and 3.1.0-M1,3.1.5: Spring Boot 3.1.0-M1 and 3.2.0-M1},hilla: {2.1.4: Spring Boot 3.1.0-M1 and 3.2.0-M1},sentry: {6.28.0: Spring Boot 2.7.0 and 3.2.0-M1},solace-spring-boot: {1.2.2: Spring Boot 2.6.0 and 3.0.0-M1,2.0.0: Spring Boot 3.0.0-M1},solace-spring-cloud: {2.3.2: Spring Boot 2.6.0 and 3.0.0-M1,3.0.0: Spring Boot 3.0.0-M1},spring-cloud: {2021.0.8: Spring Boot 2.6.0 and 3.0.0,2022.0.4: Spring Boot 3.0.0 and 3.2.0-M1,2023.0.0-M1: Spring Boot 3.2.0-M1 and 3.2.0-SNAPSHOT,2023.0.0-SNAPSHOT: Spring Boot 3.2.0-SNAPSHOT},spring-cloud-azure: {4.11.0: Spring Boot 2.6.0 and 3.0.0-M1,5.5.0: Spring Boot 3.0.0-M1 and 3.2.0-M1},spring-cloud-gcp: {3.6.3: Spring Boot 2.6.0 and 3.0.0-M1,4.7.2: Spring Boot 3.0.0-M1 and 3.2.0-M1},spring-cloud-services: {3.4.0: Spring Boot 2.6.0 and 2.7.0-M1,3.5.0: Spring Boot 2.7.0-M1 and 3.0.0-M1,4.0.3: Spring Boot 3.0.0 and 3.2.0-M1},spring-modulith: {1.0.0: Spring Boot 3.1.0 and 3.2.0-M1},spring-shell: {2.1.12: Spring Boot 2.7.0 and 3.0.0-M1,3.0.7: Spring Boot 3.0.0 and 3.1.0-M1,3.1.3: Spring Boot 3.1.0 and 3.2.0-M1,3.2.0-M1: Spring Boot 3.2.0-M1},vaadin: {23.2.15: Spring Boot 2.6.0 and 2.7.0-M1,23.3.21: Spring Boot 2.7.0-M1 and 3.0.0-M1,24.0.13: Spring Boot 3.0.0-M1 and 3.1.0-M1,24.1.7: Spring Boot 3.1.0-M1 and 3.2.0-M1},wavefront: {2.2.2: Spring Boot 2.6.0 and 2.7.0-M1,2.3.4: Spring Boot 2.7.0-M1 and 3.0.0-M1,3.0.1: Spring Boot 3.0.0-M1 and 3.1.0-M1}},dependency-ranges: {okta: {2.1.6: Spring Boot 2.6.0 and 3.0.0-M1,3.0.5: Spring Boot 3.0.0-M1 and 3.2.0-M1},mybatis: {2.2.2: Spring Boot 2.6.0 and 2.7.0-M1,2.3.1: Spring Boot 2.7.0-M1 and 3.0.0-M1,3.0.2: Spring Boot 3.0.0-M1},pulsar: {0.2.0: Spring Boot 3.0.0 and 3.2.0-M1},pulsar-reactive: {0.2.0: Spring Boot 3.0.0 and 3.2.0-M1},camel: {3.14.9: Spring Boot 2.6.0 and 2.7.0-M1,3.20.6: Spring Boot 2.7.0.M1 and 3.0.0-M1,4.0.0: Spring Boot 3.0.0-M1 and 3.2.0-M1},picocli: {4.7.4: Spring Boot 2.6.0 and 3.1.0-M1}} }2. 高阶篇技术选型: 开发工具IntelliJ IDEA 2023.1.3 SpringCloudHoxton.SR1 SpringBoot2.2.2.RELEASE SpringCloud Alibaba 2.1.0.RELEASE Java Java8 Maven3.5及以上 MySQL5.7及以上 3. 实战 在实战过程中出现的BUG或者坑都会在’‘知识拓展’小节说明 3.1 搭建父工程 IDEA字符编码统一为UTF-8 创建一个Maven项目 pom.xml文件 project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.atpl.springcloud/groupIdartifactIdspringcloud02/artifactIdversion1.0-SNAPSHOT/versionpackagingpom/packagingpropertiesproject.build.sourceEncodingUTF-8/project.build.sourceEncodingmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetjunit.version4.12/junit.versionlog4j.version1.2.17/log4j.versionlombok.version1.16.18/lombok.versionmysql.version5.1.47/mysql.versiondruid.version1.1.16/druid.versionmybatis.spring.boot.version1.3.0/mybatis.spring.boot.version/properties!-- dependencyManagement集中管理依赖的版本号当其他子模块引入想用的依赖时不需要在指定版本号 --dependencyManagement!-- 注意dependencyManagement里的依赖可能下载不下来需要将下载不下来的依赖放到改标签外下载好在放到该标签里也可以不处理在子工程需要使用相同的依赖时会自动下载--dependencies!--spring boot 2.2.2--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-dependencies/artifactIdversion2.2.2.RELEASE/versiontypepom/typescopeimport/scope/dependency!--spring cloud Hoxton.SR1--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversionHoxton.SR1/versiontypepom/typescopeimport/scope/dependency!--spring cloud alibaba 2.1.0.RELEASE--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion2.1.0.RELEASE/versiontypepom/typescopeimport/scope/dependency!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion${mysql.version}/version/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion${druid.version}/version/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion${mybatis.spring.boot.version}/version/dependencydependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion${junit.version}/version/dependencydependencygroupIdlog4j/groupIdartifactIdlog4j/artifactIdversion${log4j.version}/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion${lombok.version}/versionoptionaltrue/optional/dependency/dependencies/dependencyManagementbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId!-- 该插件的版本与SpringBoot的版本对应 --version2.2.2.RELEASE/versionconfigurationforktrue/forkaddResourcestrue/addResources/configuration/plugin/plugins/build /project3.2 REST微服务工程构建 3.2.1 创建8001模块工程 pom.xml文件 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdcom.atpl.springcloud/groupIdartifactIdspringcloud02/artifactIdversion1.0-SNAPSHOT/version/parentartifactIdcloud-provider-payment8001/artifactIdpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/propertiesdependencies!--包含了sleuthzipkin--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-zipkin/artifactId/dependency!--eureka-client--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!-- 引入自己定义的api通用包可以使用Payment支付Entity --!--dependencygroupIdcom.atguigu.springcloud/groupIdartifactIdcloud-api-commons/artifactIdversion${project.version}/version/dependency--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactId/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactIdversion1.1.10/version/dependency!--mysql-connector-java--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependency!--jdbc--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdscoperuntime/scopeoptionaltrue/optional/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependencies /project3.2.2 创建逆向工程模块 pom文件 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdcom.atpl.springcloud/groupIdartifactIdspringcloud02/artifactIdversion1.0-SNAPSHOT/version/parentartifactIdgenerator/artifactIdpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/propertiesdependencies!-- 依赖 MyBatis 核心包 --dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.4/version/dependency/dependencies!-- 控制 Maven 在构建过程中相关配置 --build!-- 构建过程中用到的插件 --plugins!-- 具体插件逆向工程的操作是以构建过程中插件形式出现的 --plugingroupIdorg.mybatis.generator/groupIdartifactIdmybatis-generator-maven-plugin/artifactIdversion1.3.0/version!-- 插件的依赖 --dependencies!-- 逆向工程的核心依赖 --dependencygroupIdorg.mybatis.generator/groupIdartifactIdmybatis-generator-core/artifactIdversion1.3.5/version/dependency!-- 数据库连接池 --dependencygroupIdcom.mchange/groupIdartifactIdc3p0/artifactIdversion0.9.2/version/dependency!-- MySQL 驱动 --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.47/version/dependency/dependencies/plugin/plugins/build /projectgeneratorConfig.xml文件 ?xml version1.0 encodingUTF-8? !DOCTYPE generatorConfigurationPUBLIC -//mybatis.org//DTD MyBatis Generator Configuration 1.0//ENhttp://mybatis.org/dtd/mybatis-generator-config_1_0.dtd generatorConfiguration!-- mybatis-generator:generate --context idatcplTables targetRuntimeMyBatis3commentGenerator!-- 是否去除自动生成的注释 true:是;false:否 --property namesuppressAllComments valuetrue//commentGenerator!--数据库连接的信息驱动类、连接地址、用户名、密码 --jdbcConnection driverClasscom.mysql.jdbc.Driver connectionURLjdbc:mysql://localhost:3306/springcloud02userIdroot passwordroot/jdbcConnection!-- 默认 false把 JDBC DECIMAL 和 NUMERIC 类型解析为 Integer为 true 时把JDBC DECIMAL和 NUMERIC 类型解析为 java.math.BigDecimal --javaTypeResolverproperty nameforceBigDecimals valuefalse//javaTypeResolver!-- targetProject:生成 Entity 类的路径 --javaModelGenerator targetProject.\src\main\javatargetPackagecom.plcao.springcloud.entities!-- enableSubPackages:是否让 schema 作为包的后缀 --property nameenableSubPackages valuefalse/!-- 从数据库返回的值被清理前后的空格 --property nametrimStrings valuetrue//javaModelGenerator!-- targetProject:XxxMapper.xml 映射文件生成的路径 --sqlMapGenerator targetProject.\src\main\resources targetPackagemapper!-- enableSubPackages:是否让 schema 作为包的后缀 --property nameenableSubPackages valuefalse//sqlMapGenerator!-- targetPackageMapper 接口生成的位置 --javaClientGenerator typeXMLMAPPER targetProject.\src\main\java targetPackagecom.plcao.springcloud.dao!-- enableSubPackages:是否让 schema 作为包的后缀 --property nameenableSubPackages valuefalse//javaClientGenerator!-- 数据库表名字和我们的 entity 类对应的映射指定 --!--table tableNameinner_account_type_cert domainObjectNameAccountTypeCert/--!--table tableNamet_account_type domainObjectNameAccountType/--table tableNamepayment domainObjectNamePayment/table/context /generatorConfiguration3.2.3 开启热部署 父工程pom文件加入 buildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId!-- 该插件的版本与SpringBoot的版本对应 --version2.2.2.RELEASE/versionconfigurationforktrue/forkaddResourcestrue/addResources/configuration/plugin/plugins /build要使用热部署的工程pom文件 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdscoperuntime/scopeoptionaltrue/optional /dependency设置IDEA 然后在要开启热部署的工程的pom文件中ctrlshiftalt/ 选中如下图 3.2.4 创建80模块工程 pom文件 dependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdscoperuntime/scopeoptionaltrue/optional/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency /dependencies该工程需要访问8001服务需要使用到RestTemplate。 介绍RestTemplate RestTemplate是Spring提供的一个类用于进行HTTP通信和访问RESTful Web服务。 创建配置类 Configuration public class ApplicationContextConf {Beanpublic RestTemplate getRestTemplate(){return new RestTemplate();}}客户端访问8001 RestController Slf4j public class OrderController {private static final String PAYMENT_URI http://127.0.0.1:8001;AutowiredRestTemplate restTemplate;GetMapping(/consumer/get/{id})public CommonResultPayment getPaymentById(PathVariable(id) Long id){return restTemplate.getForObject(PAYMENT_URI/get/payment/id,CommonResult.class);}GetMapping(/consumer/insert)public CommonResultPayment insertPayment(RequestBody Payment payment){return restTemplate.postForObject(PAYMENT_URI/insert/payment,payment ,CommonResult.class);} }测试POSTMAN发送请求后可以得到响应请求的响应。 3.2.5 重构项目 80模块和8001模块都有重复的代码将其提取成公共部分 创建cloud-api-common模块 pom文件 dependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdscoperuntime/scopeoptionaltrue/optional/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion5.1.0/version/dependency/dependencies使用maven命令将该模块进行install然后在需要用到的模块的pom文件中引入该模块。 即现在80和8001的pom文件都要加上 dependencygroupIdcom.atpl.springcloud/groupIdartifactIdcloud-api-common/artifactIdversion1.0-SNAPSHOT/version/dependency进行复测结果显示跟重构前一样。 3.2.6 创建7001服务注册中心工程 pom文件 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdcom.atpl.springcloud/groupIdartifactIdspringcloud02/artifactIdversion1.0-SNAPSHOT/version/parentartifactIdcloud-eureka-server7001/artifactIdpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/propertiesdependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-server/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdscoperuntime/scopeoptionaltrue/optional/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependency/dependencies/projectapplication.yml文件 server:port: 7001 eureka:instance:hostname: eureka7001.com #服务端实例名称 eureka7001.com已在hosts文件中配置映射了client:fetch-registry: false #自己就是服务中心不需要检索服务register-with-eureka: false #不想注册中心注册自己service-url:defaultZone: http://eureka7001.com:7001/eureka/主启动类 修改8001、80模块工程的主启动类 启动7001工程再启动80、8001工程浏览器访问http://localhost:7001如下图所示说明80、8001已经注册进注册中心。 3.2.7 搭建服务集群和服务提供集群 创建7002、7003服务注册工程与7001类似配置文件需要修改一下 7001application.yml server:port: 7001 eureka:instance:hostname: eureka7001.com #服务端实例名称client:fetch-registry: false #自己就是服务中心不需要检索服务register-with-eureka: false #不想注册中心注册自己service-url:defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/7002application.yml server:port: 7002 eureka:instance:hostname: eureka7002.comclient:fetch-registry: falseregister-with-eureka: falseservice-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/7003application.yml server:port: 7003 eureka:instance:hostname: eureka7003.comclient:register-with-eureka: falsefetch-registry: falseservice-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/创建8002服务提供工程与8001类似区别端口号即可 server:port: 8002 spring:application:name: cloud-payment-service #服务名称datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: org.gjt.mm.mysql.Driverurl: jdbc:mysql://127.0.0.1:3306/springcloud02?useUnicodetruecharacterEncodingutf-8useSSLfalseusername: rootpassword: root mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.plcao.springcloud.entities #实体类所在包配置别名eureka:client:service-url:defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eurekainstance: prefer-ip-address: trueinstance-id: provider8002启动7001、7002、7003、80、8001浏览器访问eureka7001.com:7001、eureka7002.com:7002、eureka7003.com:7003如下图所示 上图中有两处标识红色是没有配置虽然不影响程序但是在实际开发中数不允许出现主街名称的一般都是ip 微服务信息完善 instance: prefer-ip-address: trueinstance-id: provider8002 #访问路径可以看见ip地址修改ApplicationContextConf.java 修改80客户端的Controller 因为服务提供搭建了集群客户端不应该是再把访问的服务提供的端口写死而是写成服务提供的实例名称但是服务集群中有多个服务提供客户端不知道具体访问哪个所以需要开启RestTemplate的负载均衡。 3.2.8 服务发现 DiscorveryClient 这里只简单测试一下详细内容请看后续章节。在这里只拿8001服务做测试。 DiscoveryClient注解可以将服务注册到服务发现组建中它允许服务实例注册自己并提供有关其位置和可用性信息以便其他服务可以动态地发现和调用他们。 该注解通常用于服务提供者它会告诉SpringCloud将当前服务注册到服务发现组件中。 主启动类上加上注解DiscoveryClient 业务逻辑 启动服务浏览器访问http://localhost:8001/payment/discovery,可以看到控制台打印信息 到这Eureka基本已经都涉及到了但是Eureka官网已经停更了。下文将选用Zookeeper作为注册中心技术。 Zookeeper相关教程连接 3.2.9 新建8004微服务模块 使用Zookeeper作为服务注册中心 4. 知识拓展 4.1 Maven相关知识 pom文件中的dependencyManagement dependencies dependency 的区别 Maven使用dependencyManagement 元素集中管理项目中的依赖版本号。通常会在项目的最顶层的父工程POM文件中看到。它允许您在一个地方定义依赖项及其版本然后在项目的其他模块中引用这些依赖项而无需在每个模块中重复定义版本号。通过使用 dependencyManagement您可以确保项目中的所有模块使用相同的依赖版本从而提供了更好的一致性和可维护性。 Maven会沿着父子增次向上走指导找到一个拥有dependencyManagement 元素的项目然后他就会使用这个元素中指定的版本号。 例如在父工程中 dependencyManagementdependenciesdependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.47/version/dependency// ...然后在子工程中 dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId /dependency如果不在子工程中声明以来是不会从父项目中继承下来的只有在子项目中写了该依赖并没有指定具体版本才会从父项目中继承该项并且version和scope都读取自父pom。也就是说只要子工程不指定版本号子工程就会与父工程的版本号保持一致。如果子工程的某个依赖需要用到别的版本只需要声明版本即可。 注意dependencyManagement 标签里知识声明依赖并不是引入以来因此子工程需要显式的声明需要的依赖。 例如要导入的新以来在本地库没有那么该依赖在dependencyManagement 标签中就会爆红只需要将该依赖拿到dependencyManagement 标签外引入后再放进改标签即可。 跳过单元测试 locations: classpath:mapper/*.xml type-aliases-package: com.plcao.springcloud.entities #实体类所在包配置别名 eureka: client: service-url: defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka instance: prefer-ip-address: true instance-id: provider8002 启动7001、7002、7003、80、8001浏览器访问eureka7001.com:7001、eureka7002.com:7002、eureka7003.com:7003如下图所示[外链图片转存中...(img-RedL8PVB-1701690304462)]上图中有两处标识红色是没有配置虽然不影响程序但是在实际开发中数不允许出现主街名称的一般都是ip微服务信息完善yml instance: prefer-ip-address: trueinstance-id: provider8002 #访问路径可以看见ip地址修改ApplicationContextConf.java [外链图片转存中…(img-VEa0dDhU-1701690304463)] 修改80客户端的Controller [外链图片转存中…(img-B46Murwm-1701690304464)] 因为服务提供搭建了集群客户端不应该是再把访问的服务提供的端口写死而是写成服务提供的实例名称但是服务集群中有多个服务提供客户端不知道具体访问哪个所以需要开启RestTemplate的负载均衡。 3.2.8 服务发现 DiscorveryClient 这里只简单测试一下详细内容请看后续章节。在这里只拿8001服务做测试。 DiscoveryClient注解可以将服务注册到服务发现组建中它允许服务实例注册自己并提供有关其位置和可用性信息以便其他服务可以动态地发现和调用他们。 该注解通常用于服务提供者它会告诉SpringCloud将当前服务注册到服务发现组件中。 主启动类上加上注解DiscoveryClient [外链图片转存中…(img-YwW8bwN9-1701690304465)] 业务逻辑 [外链图片转存中…(img-CSDPsf1P-1701690304466)] 启动服务浏览器访问http://localhost:8001/payment/discovery,可以看到控制台打印信息 [外链图片转存中…(img-BYhlgALo-1701690304467)] 到这Eureka基本已经都涉及到了但是Eureka官网已经停更了。下文将选用Zookeeper作为注册中心技术。 Zookeeper相关教程连接 3.2.9 新建8004微服务模块 使用Zookeeper作为服务注册中心 4. 知识拓展 4.1 Maven相关知识 pom文件中的dependencyManagement dependencies dependency 的区别 Maven使用dependencyManagement 元素集中管理项目中的依赖版本号。通常会在项目的最顶层的父工程POM文件中看到。它允许您在一个地方定义依赖项及其版本然后在项目的其他模块中引用这些依赖项而无需在每个模块中重复定义版本号。通过使用 dependencyManagement您可以确保项目中的所有模块使用相同的依赖版本从而提供了更好的一致性和可维护性。 Maven会沿着父子增次向上走指导找到一个拥有dependencyManagement 元素的项目然后他就会使用这个元素中指定的版本号。 例如在父工程中 dependencyManagementdependenciesdependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.47/version/dependency// ...然后在子工程中 dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId /dependency如果不在子工程中声明以来是不会从父项目中继承下来的只有在子项目中写了该依赖并没有指定具体版本才会从父项目中继承该项并且version和scope都读取自父pom。也就是说只要子工程不指定版本号子工程就会与父工程的版本号保持一致。如果子工程的某个依赖需要用到别的版本只需要声明版本即可。 注意dependencyManagement 标签里知识声明依赖并不是引入以来因此子工程需要显式的声明需要的依赖。 例如要导入的新以来在本地库没有那么该依赖在dependencyManagement 标签中就会爆红只需要将该依赖拿到dependencyManagement 标签外引入后再放进改标签即可。 跳过单元测试 [外链图片转存中…(img-eEOpjgLN-1701690304469)]
http://www.pierceye.com/news/374255/

相关文章:

  • 小企业网站建设多少钱软件免费下载的网站大全
  • 免费承接网站建设公司网站备案资料
  • 深圳微信网站制作免费加盟一件代发货源网站
  • 青岛外贸网站建站公司东莞市专业的网页设计制作报价
  • 长沙网站设计工作室wordpress手机分享插件下载地址
  • 网站开发用什么图片格式最好网站数据库搬家
  • 宜宾建设网站企业所得税税负率
  • 广州网站二级等保上海企业网站模板
  • 做任务赚话费的网站网站直播间 是怎么做的
  • 合肥住房城乡建设部的网站传媒公司是干嘛的
  • 网站建设公司盈利深圳保障性住房在哪里申请
  • 网站建设(信科网络)谷歌推广怎么开户
  • 活动策划网站有哪些温州网页设计美工
  • 网站描述代码怎么写做正规小说网站
  • 无锡外贸网站制作公司php网站开发薪资 深圳
  • 做卡盟网站赚钱吗为企业制定网络营销方案
  • lol视频网站模板网站定制案例
  • 海兴县网站建设郑州嵌入式培训机构
  • 网站建设怎么记账韩国 电商网站
  • 公司介绍网站怎么做的网站建设的广告语
  • 茂名网站建设托管阿里云 wordpress主机名
  • 投票活动网站怎么做郑州营销型网站制作教程
  • 如何做一个导航网站凡科建设网站怎么保存
  • 哪个网站能叫我做直播回放广州十大猎头公司排名
  • 四川网站建设那家好百度爱采购竞价
  • 怎么做提卡密网站万游wordpress 验证
  • 威宁住房和城乡建设局网站网站介绍怎么写
  • 百度站长平台快速收录wordpress hook机制
  • 衡水提供网站设计公司哪家专业网站维护简单吗
  • 域名购买后 怎么创建网站网站内部优化是什么