单体架构

  1. 简单方便,高度耦合,扩展性差,适合小型项目。例如:学生管理系统

分布式架构

  1. 根据业务对功能经行拆分 每个业务功能独立开发
  2. 优点: 降低耦合 有利于服务的升级和拓展
  3. 缺点:服务调用关系复杂
  4. 松耦合,扩展性好,但架构复杂,难度大。适合大型互联网项目,例如:京东、淘宝

什么是微服务?

  1. 微服务是一种经过良好设计的分布式架构方案
  2. 架构特点
  3. - 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责
  4. - 自治:团队独立、技术独立、数据独立,独立部署和交付
  5. - 面向服务:服务提供统一标准的接口,与语言和技术无关
  6. - 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题
  7. ①优点:拆分粒度更小、服务更独立、耦合度更低
  8. ②缺点:架构非常复杂,运维、监控、部署难度提高

如何实现服务间调用的?

  1. 在服务的启动类中,注册RestTemplate实例:
  2. 修改模块中的service层类中的方法:

什么是SpringCloud?

  1. SpringCloud是目前国内使用最广泛的微服务框架。官网地址:https://spring.io/projects/spring-cloud。

注册中心高可用

eureka注册中心

  1. 1. 创建eureka-secvice服务模块
  2. 2. 引入SpringCloudeureka提供依赖
  3. <dependency>
  4. <groupId>org.springframework.cloud</groupId>
  5. <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
  6. </dependency>
  7. 3. cureka-scrvice模块编写启动类
  8. @SpringBootApplication //此类为启动类
  9. @EnableEurekaServer //eureka注册中心启动 注解
  10. 4. 编写application.yml配置文件
  11. server:
  12. port: 10086
  13. spring:
  14. application:
  15. name: eureka-server
  16. eureka:
  17. client:
  18. service-url:
  19. defaultZone: http://127.0.0.1:10086/eureka
  20. 5. 启动服务
  21. 浏览器访问:http://127.0.0.1:10086

服务注册
  1. 1. 添加依赖
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  5. </dependency>
  6. 2. 添加application.yml配置文件
  7. spring:
  8. application:
  9. name: userservice(注册服务的模块名)
  10. eureka:
  11. client:
  12. service-url:
  13. defaultZone: http://127.0.0.1:10086/eureka
  14. 3. 查看eureka-server管理页面:

服务发现
  1. 1. 引入依赖
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  5. </dependency>
  6. 2. 添加application.yml配置文件
  7. spring:
  8. application:
  9. name: orderservice
  10. eureka:
  11. client:
  12. service-url:
  13. defaultZone: http://127.0.0.1:10086/eureka
  14. 3. 服务拉取和负载均衡
  15. 最后,我们要去eureka-server中拉取user-service服务的实例列表,并且实现负载均衡。
  16. 不过这些动作不用我们去做,只需要添加一些注解即可。
  17. order-serviceOrderApplication中,给RestTemplate这个Bean添加一个@LoadBalanced注解:
  18. 修改order-service服务中的cn.itcast.order.service包下的OrderService类中的queryOrderById方法。修改访问的url路径,用服务名代替ip、端口:

Ribbon负载均衡

  1. SpringCloud底层其实是利用了一个名为Ribbon的组件,来实现负载均衡功能的。

负载均衡策略

负载均衡的规则都定义在IRule接口中,而IRule有很多不同的实现类 不同规则的含义如下:

内置负载均衡规则类 规则描述
RoundRobinRule 简单轮询服务列表来选择服务器。
AvailabilityFilteringRule 对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit属性进行配置。
WeightedResponseTimeRule 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。
BestAvailableRule 忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule 随机选择一个可用的服务器。
RetryRule 重试机制的选择逻辑

默认的实现就是ZoneAvoidanceRule,是一种轮询方案

自定义负载均衡策略
  1. 两种方式
  2. 1.代码方式
  3. @Bean
  4. public IRule randomRule(){
  5. return new RandomRule(); //负载均衡策略 随机选择一个可用的服务器。
  6. }
  7. 2.application配置文件方式
  8. userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
  9. ribbon:
  10. NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
  11. # 负载均衡规则

Nacos注册中心

服务注册到nacos注册中心
  1. 1. 引入依赖
  2. 1.1在父工程的pom文件中的<dependencyManagement>中引入依赖:
  3. <dependency>
  4. <groupId>com.alibaba.cloud</groupId>
  5. <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  6. <version>2.2.6.RELEASE</version>
  7. <type>pom</type>
  8. <scope>import</scope>
  9. </dependency>
  10. 1.2然后在user-serviceorder-service中的pom文件中引入nacos-discovery依赖:
  11. <dependency>
  12. <groupId>com.alibaba.cloud</groupId>
  13. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  14. </dependency>
  15. 2. application配置nacos地址
  16. spring:
  17. cloud:
  18. nacos:
  19. server-addr: localhost:8848
  20. 3. 重启微服务 登录nacos管理页面
  21. 注意:不要忘了注释掉eureka的依赖和配置。

权重配置

实际部署中会出现这样的场景:

服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求。

但默认情况下NacosRule是同集群内随机挑选,不会考虑机器的性能问题。

因此,Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高。

在nacos控制台,找到user-service的实例列表,点击编辑,即可修改权重:

在弹出的编辑窗口,修改权重:

集群
  1. 修改user-serviceapplication.yml文件,添加集群配置:
  2. spring:
  3. cloud:
  4. nacos:
  5. server-addr: localhost:8848
  6. discovery:
  7. cluster-name: HZ # 集群名称

环境隔离

nacos和eureka的区别?

Nacos的服务实例分为两种l类型:

  • 临时实例:如果实例宕机超过一定时间,会从服务列表剔除,默认的类型。
  • 非临时实例:如果实例宕机,不会从服务列表剔除,也可以叫永久实例。

配置一个服务实例为永久实例:

  1. spring:
  2. cloud:
  3. nacos:
  4. discovery:
  5. ephemeral: false # 设置为非临时实例
  • Nacos与eureka的共同点

    • 都支持服务注册和服务拉取
    • 都支持服务提供者心跳方式做健康检测
  • Nacos与Eureka的区别

    • Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
    • 临时实例心跳不正常会被剔除,非临时实例则不会被剔除
    • Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
    • Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式

微服务、springboot、springcloud有何联系?

Nacos配置中心

从微服务拉取配置

1.引入依赖

  1. 首先,在user-service服务中,引入nacos-config的客户端依赖:
  2. <!--nacos配置管理依赖-->
  3. <dependency>
  4. <groupId>com.alibaba.cloud</groupId>
  5. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  6. </dependency>

2.添加bootstrap.yaml

然后,在user-service中添加一个bootstrap.yaml文件,内容如下:

  1. spring:
  2. application:
  3. name: userservice # 服务名称
  4. profiles:
  5. active: dev #开发环境,这里是dev
  6. cloud:
  7. nacos:
  8. server-addr: localhost:8848 # Nacos地址
  9. config:
  10. file-extension: yaml # 文件后缀名

热更新

方式一

  1. @Value注入的变量所在类上添加注解@RefreshScope

方式二

  1. 使用@ConfigurationProperties注解代替@Value注解。
  2. user-service服务中,添加一个类,读取patterrn.dateformat属性:
  3. UserController中使用这个类代替@Value

Feign的远程调用

替代RestTemplate

1.引入依赖

我们在order-service服务的pom文件中引入feign的依赖:

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-openfeign</artifactId>
  4. </dependency>

2.添加注解

在order-service的启动类添加注解开启Feign的功能:

  1. @EnableFeignClients
  2. Enable 启用
  3. feign
  4. Clients 客户

3.编写Feign客户端

在order-service中新建一个接口

  1. package cn.itcast.order.client;
  2. import cn.itcast.order.pojo.User;
  3. import org.springframework.cloud.openfeign.FeignClient;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.PathVariable;
  6. @FeignClient("userservice")
  7. public interface UserClient {
  8. @GetMapping("/user/{id}")
  9. User findById(@PathVariable("id") Long id);
  10. }

4.测试

修改order-service中的OrderService类中的queryOrderById方法,使用Feign客户端代替RestTemplate:

使用Feign的步骤:

① 引入依赖

② 添加@EnableFeignClients注解

③ 编写FeignClient接口

④ 使用FeignClient中定义的方法代替RestTemplate

自定义配置

Feign可以支持很多的自定义配置,如下表所示:

类型 作用 说明
feign.Logger.Level 修改日志级别 包含四种不同的级别:NONE、BASIC、HEADERS、FULL
feign.codec.Decoder 响应结果的解析器 http远程调用的结果做解析,例如解析json字符串为java对象
feign.codec.Encoder 请求参数编码 将请求参数编码,便于通过http请求发送
feign. Contract 支持的注解格式 默认是SpringMVC的注解
feign. Retryer 失败重试机制 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

日志

1.配置文件

基于配置文件修改feign的日志级别可以针对单个服务:

  1. feign:
  2. client:
  3. config:
  4. userservice: # 针对某个微服务的配置
  5. loggerLevel: FULL # 日志级别

也可以针对所有服务

  1. feign:
  2. client:
  3. config:
  4. userservice: # 针对某个微服务的配置
  5. loggerLevel: FULL # 日志级别

而日志的级别分为四种:

  • NONE:不记录任何日志信息,这是默认值。
  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

2.java代码

也可以基于Java代码来修改日志级别,先声明一个类,然后声明一个Logger.Level的对象:

  1. public class DefaultFeignConfiguration {
  2. @Bean
  3. public Logger.Level feignLogLevel(){
  4. return Logger.Level.BASIC; // 日志级别为BASIC
  5. }
  6. }

如果要全局生效,将其放到启动类的@EnableFeignClients这个注解中:

  1. @EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)

如果是局部生效,则把它放到对应的@FeignClient这个注解中:

  1. @FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)