常见面试题

1、什么是微服务?
2、微服务之间是如何独立通讯的?
3、spingcloud与Dubbo有哪些区别?
4、springboot和springcloud,谈谈对他们的理解
5、什么是服务熔断?什么是服务降级?
6、微服务的优缺点分别是什么?说下你在项目中遇到的坑
7、你知道的微服务的技术栈有哪些?
8、eureka和zookeeper都可以提供服务注册与发现的功能,请说说他们的区别

image.png

1、概述

1、服务拆分后,服务众多,客户端该如何访问?
2、众多服务之间该如何通信?http、rpc
3、众多服务该如何治理?
4、服务挂了怎么办?

解决方案:
1、Spring Cloud NetFlix 一站式解决方案
api网关:zuul组件
feign—-httpclient—-http通信,同步,阻塞
服务注册发现:Eureka
熔断机制:Hystrix
2、Apache Dubbo Zookeeper 半自动,需要整合别人的
API:没有。整合第三方,或自己实现
Dubbo
Zookeeper
没有:借助Hystrix
3、Spring Cloud Alibaba 一站式解决方案!成本更低,更加简便

image.png

2、cloud与boot的版本选择

参考:https://spring.io/projects/spring-cloud#overwrite
更加详细的版本范围参考:start.spring.io/actuator/info
本次学习springcloud的版本选择为:
pringcloud: Hoxton.SR1
springboot: 2.2.2.RELEASE
springcloud alibaba: 2.1.0.RELEASE
java: java8
maven: 3.5及以上
mysql: 5.7及以上
springcloud此时最新的稳定发布版为:Hoxton.SR1
springboot此时最新的稳定发布版为:2.2.4.RELEASE

springboot为什么不选择最新的2.2.4.RELEASE?
查看springcloud此稳定版本文档发现推荐使用springboot的版本为:2.2.2.RELEASE

image.png
订单-支付工程融合进以上技术

3、项目初始化cloud2022

1、创建父工程

1、创建mave项目选择maven-archetype-site框架
2、设置字符集编码为utf-8 File Encoding
3、设置注解生效 Compliler===》Annotation Processors
4、设置java编译版本为java8 Compliler===》java Complicer

2、父工程pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>com.guang.springcloud</groupId>
  6. <artifactId>cloud2022</artifactId>
  7. <version>1.0-SNAPSHOT</version>
  8. <packaging>pom</packaging>
  9. <!-- 统一管理jar包版本 -->
  10. <properties>
  11. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  12. <maven.compiler.source>1.8</maven.compiler.source>
  13. <maven.compiler.target>1.8</maven.compiler.target>
  14. <junit.version>4.12</junit.version>
  15. <log4j.version>1.2.17</log4j.version>
  16. <lombok.version>1.16.18</lombok.version>
  17. <mysql.version>5.1.47</mysql.version>
  18. <druid.version>1.1.16</druid.version>
  19. <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
  20. </properties>
  21. <!-- 子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version -->
  22. <dependencyManagement>
  23. <dependencies>
  24. <!--spring boot 2.2.2-->
  25. <dependency>
  26. <groupId>org.springframework.boot</groupId>
  27. <artifactId>spring-boot-dependencies</artifactId>
  28. <version>2.2.2.RELEASE</version>
  29. <type>pom</type>
  30. <scope>import</scope>
  31. </dependency>
  32. <!--spring cloud Hoxton.SR1-->
  33. <dependency>
  34. <groupId>org.springframework.cloud</groupId>
  35. <artifactId>spring-cloud-dependencies</artifactId>
  36. <version>Hoxton.SR1</version>
  37. <type>pom</type>
  38. <scope>import</scope>
  39. </dependency>
  40. <!--spring cloud alibaba 2.1.0.RELEASE-->
  41. <dependency>
  42. <groupId>com.alibaba.cloud</groupId>
  43. <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  44. <version>2.1.0.RELEASE</version>
  45. <type>pom</type>
  46. <scope>import</scope>
  47. </dependency>
  48. <dependency>
  49. <groupId>mysql</groupId>
  50. <artifactId>mysql-connector-java</artifactId>
  51. <version>${mysql.version}</version>
  52. </dependency>
  53. <dependency>
  54. <groupId>com.alibaba</groupId>
  55. <artifactId>druid</artifactId>
  56. <version>${druid.version}</version>
  57. </dependency>
  58. <dependency>
  59. <groupId>org.mybatis.spring.boot</groupId>
  60. <artifactId>mybatis-spring-boot-starter</artifactId>
  61. <version>${mybatis.spring.boot.version}</version>
  62. </dependency>
  63. <dependency>
  64. <groupId>junit</groupId>
  65. <artifactId>junit</artifactId>
  66. <version>${junit.version}</version>
  67. </dependency>
  68. <dependency>
  69. <groupId>log4j</groupId>
  70. <artifactId>log4j</artifactId>
  71. <version>${log4j.version}</version>
  72. </dependency>
  73. <dependency>
  74. <groupId>org.projectlombok</groupId>
  75. <artifactId>lombok</artifactId>
  76. <version>${lombok.version}</version>
  77. <optional>true</optional>
  78. </dependency>
  79. </dependencies>
  80. </dependencyManagement>
  81. <build>
  82. <plugins>
  83. <plugin>
  84. <groupId>org.springframework.boot</groupId>
  85. <artifactId>spring-boot-maven-plugin</artifactId>
  86. <configuration>
  87. <fork>true</fork>
  88. <addResources>true</addResources>
  89. </configuration>
  90. </plugin>
  91. </plugins>
  92. </build>
  93. </project>

maven跳过单元测试:点击闪电即可

4、支付模块的构建cloud-provider-payment8001

1、创建子模块cloud-provider-payment8001

2、改pom

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>cloud2020</artifactId>
  7. <groupId>com.atguigu.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-provider-payment8001</artifactId>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-starter-web</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-actuator</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.mybatis.spring.boot</groupId>
  23. <artifactId>mybatis-spring-boot-starter</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>com.alibaba</groupId>
  27. <artifactId>druid-spring-boot-starter</artifactId>
  28. <version>1.1.10</version>
  29. </dependency>
  30. <!--mysql-connector-java-->
  31. <dependency>
  32. <groupId>mysql</groupId>
  33. <artifactId>mysql-connector-java</artifactId>
  34. </dependency>
  35. <!--jdbc-->
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-starter-jdbc</artifactId>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.springframework.boot</groupId>
  42. <artifactId>spring-boot-devtools</artifactId>
  43. <scope>runtime</scope>
  44. <optional>true</optional>
  45. </dependency>
  46. <dependency>
  47. <groupId>org.projectlombok</groupId>
  48. <artifactId>lombok</artifactId>
  49. <optional>true</optional>
  50. </dependency>
  51. <dependency>
  52. <groupId>org.springframework.boot</groupId>
  53. <artifactId>spring-boot-starter-test</artifactId>
  54. <scope>test</scope>
  55. </dependency>
  56. </dependencies>
  57. </project>

3、application.yml

  1. server:
  2. port: 8001
  3. spring:
  4. application:
  5. name: cloud-payment-service
  6. datasource:
  7. type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
  8. driver-class-name: org.gjt.mm.mysql.Driver # mysql驱动包 com.mysql.jdbc.Driver
  9. url: jdbc:mysql://localhost:3306/db2022?useUnicode=true&characterEncoding=utf-8&useSSL=false
  10. username: root
  11. password: 123456
  12. mybatis:
  13. mapperLocations: classpath:mapper/*.xml
  14. type-aliases-package: com.guang.springcloud.entity # 所有Entity别名类所在包

4、创建主启动类(略)

5、编写业务类

1、创建数据库表

  1. CREATE TABLE `payment` (
  2. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  3. `serial` varchar(200) DEFAULT '',
  4. PRIMARY KEY (`id`)
  5. ) ENGINE=InnoDB DEFAULT CHARSET=utf8

2、PaymentDao

  1. @Mapper
  2. public interface PaymentDao {
  3. int insertPayment(Payment payment);
  4. Payment selectPaymentById(Long id);
  5. }

3、payment-mapper.xml

  1. <mapper namespace="com.guang.springcloud.dao.PaymentDao">
  2. <resultMap id="BaseResultMap" type="com.guang.springcloud.entity.Payment">
  3. <id column="id" property="id" jdbcType="BIGINT"/>
  4. <result column="serial" property="serial" jdbcType="VARCHAR"/>
  5. </resultMap>
  6. <!-- int insertPayment(Payment payment);-->
  7. <insert id="insertPayment" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
  8. insert into payment(serial)values (#{serial});
  9. </insert>
  10. <!-- Payment selectPaymentById(int id);-->
  11. <select id="selectPaymentById" resultType="Payment" resultMap="BaseResultMap">
  12. select id,serial from payment
  13. where id=#{id};
  14. </select>
  15. </mapper>

4、PaymentService

  1. @Service
  2. public class PaymentServiceImpl implements PaymentService {
  3. @Autowired
  4. private PaymentDao paymentDao;
  5. public int insertPayment(Payment payment){
  6. return paymentDao.insertPayment(payment);
  7. }
  8. public Payment selectPaymentById(Long id) {
  9. return paymentDao.selectPaymentById(id);
  10. }
  11. }

5、PaymentController

  1. @RestController
  2. @RequestMapping("/payment")
  3. public class PaymentController {
  4. @Autowired
  5. private PaymentService paymentService;
  6. @PostMapping("/insert")
  7. public CommonResult insertPayment(@RequestBody Payment payment){
  8. if(payment==null){
  9. return new CommonResult(300,"插入数据库失败,参数错误");
  10. }
  11. int result = paymentService.insertPayment(payment);
  12. return new CommonResult(200,"插入数据库成功",result);
  13. }
  14. @GetMapping("/getPayment/{id}")
  15. public CommonResult selectPaymentById(@PathVariable("id") Long id){
  16. Payment payment = paymentService.selectPaymentById(id);
  17. if(payment!=null){
  18. return new CommonResult(200,"查询成功",payment);
  19. }else {
  20. return new CommonResult(300,"查询失败,参数不存在",id);
  21. }
  22. }
  23. }

5、热部署devtools

1、在项目8001中添加依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-devtools</artifactId>
  4. <scope>runtime</scope>
  5. <optional>true</optional>
  6. </dependency>

2、在cloud2022中添加插件

  1. <build>
  2. <finalName>你自己的工程名字</finalName>
  3. <plugins>
  4. <plugin>
  5. <groupId>org.springframework.boot</groupId>
  6. <artifactId>spring-boot-maven-plugin</artifactId>
  7. <configuration>
  8. <fork>true</fork>
  9. <addResources>true</addResources>
  10. </configuration>
  11. </plugin>
  12. </plugins>
  13. </build>

3、修改IDEA配置
settings——》compiler——》将首字母为A、D、B、C四个选项打勾
退出后使用快捷键Ctrl+Alt+Shift+/ 设置
image.png
最后重启IDEA即可

6、消费者模块cloud-consumer-order80

pom.xml

  1. <artifactId>cloud-consumer-order80</artifactId>
  2. <dependencies>
  3. <dependency>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-starter-web</artifactId>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-starter-actuator</artifactId>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-devtools</artifactId>
  14. <scope>runtime</scope>
  15. <optional>true</optional>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.projectlombok</groupId>
  19. <artifactId>lombok</artifactId>
  20. <optional>true</optional>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-test</artifactId>
  25. <scope>test</scope>
  26. </dependency>
  27. </dependencies>

application.yml

  1. server:
  2. port: 80

实体类Payment、CommonResult(略)

配置RestTemplate访问远程URL

  1. @Configuration
  2. public class RestTamplateConfig {
  3. @Bean
  4. public RestTemplate getRestTemplate(){
  5. return new RestTemplate();
  6. }
  7. }

OrderController

  1. @RestController
  2. public class OrderController {
  3. public static final String Payment_URL="http://localhost:8001/payment";
  4. @Autowired
  5. private RestTemplate restTemplate;
  6. @GetMapping("/consumer/payment/insert")
  7. public CommonResult insertPayment(@RequestBody Payment payment){
  8. return restTemplate.postForObject(Payment_URL+"/insert",payment,CommonResult.class);
  9. }
  10. @GetMapping("/consumer/payment/get/{id}")
  11. public CommonResult selectPaymentById(@PathVariable("id")Long id){
  12. return restTemplate.getForObject(Payment_URL+"/get/"+id,CommonResult.class,id);
  13. }
  14. }

7、工程重构-提取公共模块cloud-api-common

pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>cloud2022</artifactId>
  7. <groupId>com.guang.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-api-common</artifactId>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-devtools</artifactId>
  16. <scope>runtime</scope>
  17. <optional>true</optional>
  18. </dependency>
  19. <dependency>
  20. <groupId>org.projectlombok</groupId>
  21. <artifactId>lombok</artifactId>
  22. <optional>true</optional>
  23. </dependency>
  24. <dependency>
  25. <groupId>cn.hutool</groupId>
  26. <artifactId>hutool-all</artifactId>
  27. <version>5.1.0</version>
  28. </dependency>
  29. </dependencies>
  30. </project>

Payment(略)、CommonResult

  1. public class CommonResult<T>
  2. {
  3. private Integer code;
  4. private String message;
  5. private T data;
  6. public CommonResult()
  7. {
  8. }
  9. public CommonResult(Integer code, String message, T data)
  10. {
  11. this.code = code;
  12. this.message = message;
  13. this.data = data;
  14. }
  15. public CommonResult( Integer code,String message) {
  16. this( code, message,null);
  17. }
  18. public CommonResult(T data) {
  19. this(200, "操作成功", data);
  20. }
  21. //setter--getter
  22. public T getData() {
  23. return data;
  24. }
  25. public void setData(T data) {
  26. this.data = data;
  27. }
  28. public String getMessage() {
  29. return message;
  30. }
  31. public void setMessage(String message) {
  32. this.message = message;
  33. }
  34. public Integer getCode() {
  35. return code;
  36. }
  37. public void setCode(Integer code) {
  38. this.code = code;
  39. }
  40. }

maven 进行clean与install操作

80与8001

在pom.xml中引入cloud-api-common的依赖后,删除entity包下的实体类

  1. <dependency>
  2. <groupId>com.guang.springcloud</groupId>
  3. <artifactId>cloud-api-common</artifactId>
  4. <version>1.0-SNAPSHOT</version>
  5. </dependency>

8、服务注册与发现中心

1、Eureka(停更)

1.1 、简介

什么是服务治理  
Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理

在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。

什么是服务注册与发现
Eureka采用了CS的设计架构,Eureka Server 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka的客户端连接到 Eureka Server并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行。
在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息 比如 服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者|服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何rpc远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))
springcloud - 图6
Eureka包含两个组件:Eureka Server和Eureka Client

Eureka Server提供服务注册服务
各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。


EurekaClient通过注册中心进行访问
是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)

1.2、单机版Eureka7001构建

1、创建module==》cloud-eureka-server7001
2、导依赖
以前的老版本(当前使用2018)

org.springframework.cloud
spring-cloud-starter-eureka

现在新版本(当前使用2020.2)

org.springframework.cloud
spring-cloud-starter-netflix-eureka-server

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>cloud2022</artifactId>
  7. <groupId>com.guang.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-eureka-server7001</artifactId>
  12. <dependencies>
  13. <!--eureka-server-->
  14. <dependency>
  15. <groupId>org.springframework.cloud</groupId>
  16. <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
  17. </dependency>
  18. <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
  19. <dependency>
  20. <groupId>com.guang.springcloud</groupId>
  21. <artifactId>cloud-api-common</artifactId>
  22. <version>${project.version}</version>
  23. </dependency>
  24. <!--boot web actuator-->
  25. <dependency>
  26. <groupId>org.springframework.boot</groupId>
  27. <artifactId>spring-boot-starter-web</artifactId>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter-actuator</artifactId>
  32. </dependency>
  33. <!--一般通用配置-->
  34. <dependency>
  35. <groupId>org.springframework.boot</groupId>
  36. <artifactId>spring-boot-devtools</artifactId>
  37. <scope>runtime</scope>
  38. <optional>true</optional>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.projectlombok</groupId>
  42. <artifactId>lombok</artifactId>
  43. </dependency>
  44. <dependency>
  45. <groupId>org.springframework.boot</groupId>
  46. <artifactId>spring-boot-starter-test</artifactId>
  47. <scope>test</scope>
  48. </dependency>
  49. <dependency>
  50. <groupId>junit</groupId>
  51. <artifactId>junit</artifactId>
  52. </dependency>
  53. </dependencies>
  54. </project>

3、配置文件

  1. server:
  2. port: 7001
  3. eureka:
  4. instance:
  5. hostname: localhost #eureka服务端的实例名称
  6. client:
  7. #false表示不向注册中心注册自己。
  8. register-with-eureka: false
  9. #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
  10. fetch-registry: false
  11. service-url:
  12. #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。
  13. defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

4、主启动类

  1. @SpringBootApplication
  2. @EnableEurekaServer
  3. public class EurekaMain7001 {
  4. public static void main(String[] args) {
  5. SpringApplication.run(EurekaMain7001.class,args);
  6. }
  7. }

5、测试
localhost:7001即可

1.3、服务8001进驻单机版eureka

1、改pom

  1. <!--eureka-client-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  5. </dependency>

2、改yml

  1. eureka:
  2. client:
  3. #表示是否将自己注册进EurekaServer默认为true。
  4. register-with-eureka: true
  5. #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
  6. fetchRegistry: true
  7. service-url:
  8. defaultZone: http://localhost:7001/eureka

3、主启动类加上 @EnableEurekaClient
4、测试 localhost:7001 红色字段为eureka的自我保护机制

1.4、服务80进驻单机版Eureka

1、改pom

  1. <!--eureka-client-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  5. </dependency>

2、改yml

  1. spring:
  2. application:
  3. name: cloud-order-service
  4. eureka:
  5. client:
  6. #表示是否将自己注册进EurekaServer默认为true。
  7. register-with-eureka: true
  8. #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
  9. fetchRegistry: true
  10. service-url:
  11. defaultZone: http://localhost:7001/eureka

3、主启动类加上 @EnableEurekaClient

1.5、集群版Eureka概述

问题:微服务RPC远程服务调用最核心的是什么
高可用,试想你的注册中心只有一个only one, 它出故障了那就呵呵( ̄▽ ̄)”了,会导致整个为服务环境不可用

解决办法:搭建Eureka注册中心集群 ,实现负载均衡+故障容错

1.6、集群版Eureka环境搭建

1、创建Module====》cloud-eureka-server7002
2、改pom(参考7001)

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>cloud2022</artifactId>
  7. <groupId>com.guang.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-eureka-server7002</artifactId>
  12. <dependencies>
  13. <!--eureka-server-->
  14. <dependency>
  15. <groupId>org.springframework.cloud</groupId>
  16. <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
  17. </dependency>
  18. <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
  19. <dependency>
  20. <groupId>com.guang.springcloud</groupId>
  21. <artifactId>cloud-api-common</artifactId>
  22. <version>${project.version}</version>
  23. </dependency>
  24. <!--boot web actuator-->
  25. <dependency>
  26. <groupId>org.springframework.boot</groupId>
  27. <artifactId>spring-boot-starter-web</artifactId>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter-actuator</artifactId>
  32. </dependency>
  33. <!--一般通用配置-->
  34. <dependency>
  35. <groupId>org.springframework.boot</groupId>
  36. <artifactId>spring-boot-devtools</artifactId>
  37. <scope>runtime</scope>
  38. <optional>true</optional>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.projectlombok</groupId>
  42. <artifactId>lombok</artifactId>
  43. </dependency>
  44. <dependency>
  45. <groupId>org.springframework.boot</groupId>
  46. <artifactId>spring-boot-starter-test</artifactId>
  47. <scope>test</scope>
  48. </dependency>
  49. <dependency>
  50. <groupId>junit</groupId>
  51. <artifactId>junit</artifactId>
  52. </dependency>
  53. </dependencies>
  54. </project>

3、修改电脑hosts文件
路径:C:\windows\System32\drivers\etc路径下的hosts文件

  1. 127.0.0.1 eureka7001.com
  2. 127.0.0.1 eureka7002.com
  3. 127.0.0.1 eureka7003.com

4、改yml

  1. server:
  2. port: 7002
  3. eureka:
  4. instance:
  5. hostname: eureka7002.com #eureka服务端的实例名称
  6. client:
  7. register-with-eureka: false #false表示不向注册中心注册自己。
  8. fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
  9. service-url:
  10. defaultZone: http://eureka7001.com:7001/eureka/

5、相对应7001的yml文件也需要修改

  1. server:
  2. port: 7001
  3. eureka:
  4. instance:
  5. hostname: eureka7001.com #eureka服务端的实例名称
  6. client:
  7. register-with-eureka: false #false表示不向注册中心注册自己。
  8. fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
  9. service-url:
  10. defaultZone: http://eureka7002.com:7002/eureka/

6、主启动类

  1. @SpringBootApplication
  2. @EnableEurekaServer
  3. public class EurekaMain7002 {
  4. public static void main(String[] args) {
  5. SpringApplication.run(EurekaMain7002.class,args);
  6. }
  7. }

1.7、80与8001进驻集群

8001.yml与80.yml修改eureka的访问路径

  1. # 集群版
  2. defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

1.8、集群版8001

1、创建Module====》cloud-provider-payment
2、改pom(参考8001)

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>cloud2022</artifactId>
  7. <groupId>com.guang.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-provider-payment8002</artifactId>
  12. <dependencies>
  13. <!--eureka-client-->
  14. <dependency>
  15. <groupId>org.springframework.cloud</groupId>
  16. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  17. </dependency>
  18. <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
  19. <groupId>com.atguigu.springcloud</groupId>
  20. <artifactId>cloud-api-common</artifactId>
  21. <version>${project.version}</version>
  22. </dependency>
  23. <dependency>
  24. <groupId>org.springframework.boot</groupId>
  25. <artifactId>spring-boot-starter-web</artifactId>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-starter-actuator</artifactId>
  30. </dependency>
  31. <dependency>
  32. <groupId>org.mybatis.spring.boot</groupId>
  33. <artifactId>mybatis-spring-boot-starter</artifactId>
  34. </dependency>
  35. <dependency>
  36. <groupId>com.alibaba</groupId>
  37. <artifactId>druid-spring-boot-starter</artifactId>
  38. <version>1.1.10</version>
  39. </dependency>
  40. <!--mysql-connector-java-->
  41. <dependency>
  42. <groupId>mysql</groupId>
  43. <artifactId>mysql-connector-java</artifactId>
  44. </dependency>
  45. <!--jdbc-->
  46. <dependency>
  47. <groupId>org.springframework.boot</groupId>
  48. <artifactId>spring-boot-starter-jdbc</artifactId>
  49. </dependency>
  50. <dependency>
  51. <groupId>org.springframework.boot</groupId>
  52. <artifactId>spring-boot-devtools</artifactId>
  53. <scope>runtime</scope>
  54. <optional>true</optional>
  55. </dependency>
  56. <dependency>
  57. <groupId>org.projectlombok</groupId>
  58. <artifactId>lombok</artifactId>
  59. <optional>true</optional>
  60. </dependency>
  61. <dependency>
  62. <groupId>org.springframework.boot</groupId>
  63. <artifactId>spring-boot-starter-test</artifactId>
  64. <scope>test</scope>
  65. </dependency>
  66. </dependencies>
  67. </project>

3、改yml
参考8001 但是端口号得修改为8002

  1. server:
  2. port: 8002
  3. spring:
  4. application:
  5. name: cloud-payment-service
  6. datasource:
  7. type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
  8. driver-class-name: org.gjt.mm.mysql.Driver # mysql驱动包
  9. url: jdbc:mysql://localhost:3306/db2022?useUnicode=true&characterEncoding=utf-8&useSSL=false
  10. username: root
  11. password: 123456
  12. eureka:
  13. client:
  14. #表示是否将自己注册进EurekaServer默认为true。
  15. register-with-eureka: true
  16. #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
  17. fetchRegistry: true
  18. service-url:
  19. defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
  20. #defaultZone: http://localhost:7001/eureka # 单机版
  21. mybatis:
  22. mapperLocations: classpath:mapper/*.xml
  23. type-aliases-package: com.guang.springcloud.entities # 所有Entity别名类所在包

4、主启动类

  1. @SpringBootApplication
  2. @EnableEurekaClient
  3. public class PaymentMain8002 {
  4. public static void main(String[] args) {
  5. SpringApplication.run(PaymentMain8002.class,args);
  6. }
  7. }

5、业务类(直接从8001复制粘贴过来)
但是为了知道从那个服务中获取到的数据,所以在返回结果的数据中加上服务端口号。
注意:服务8001也需要返回其端口号

  1. @Value("${server.port}")
  2. private String serverPort;
  3. CommonResult(200,"插入数据库成功,服务端口:"+serverPort,result);

6、由于80服务的端口是写死的,所以要将其写成对外开放的服务名
在80服务的接口上将访问地址改为对外的服务名

  1. // http://CLOUD-PAYMENT-SERVICE
  2. // public static final String Payment_URL="http://localhost:8001/payment";
  3. public static final String Payment_URL="http://CLOUD-PAYMENT-SERVICE";

7、Restemplate做负载均衡
否则访问服务时,将会值访问8001服务,而不会对8002服务进行访问

  1. @Configuration
  2. public class RestTamplateConfig {
  3. @Bean
  4. @LoadBalanced
  5. public RestTemplate getRestTemplate(){
  6. return new RestTemplate();
  7. }
  8. }

8、测试

1.9、actuator完善微服务信息

问题:
image.png
1、主机名称:服务名称修改
添加:instance的instance-id部分
8002与80也做相应的修改

  1. eureka:
  2. client:
  3. #表示是否将自己注册进EurekaServer默认为true。
  4. register-with-eureka: true
  5. #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
  6. fetchRegistry: true
  7. service-url:
  8. defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
  9. #defaultZone: http://localhost:7001/eureka # 单机版
  10. instance:
  11. instance-id: payment8001

2、设置访问信息有ip显示
添加部分:prefer-ip-address: true
进驻的服务都得修改

  1. eureka:
  2. client:
  3. #表示是否将自己注册进EurekaServer默认为true。
  4. register-with-eureka: true
  5. #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
  6. fetchRegistry: true
  7. service-url:
  8. defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
  9. #defaultZone: http://localhost:7001/eureka # 单机版
  10. instance:
  11. instance-id: payment8001
  12. prefer-ip-address: true #访问路径可以显示IP地址

2.0、服务发现Discovery

1、8001的PaymentController

  1. @Resource
  2. private DiscoveryClient discoveryClient;
  3. @GetMapping("/discovery")
  4. public Object discovery()
  5. {
  6. List<String> services = discoveryClient.getServices();
  7. for (String element : services) {
  8. System.out.println(element);
  9. }
  10. List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
  11. for (ServiceInstance element : instances) {
  12. System.out.println(element.getServiceId() + "\t" + element.getHost() + "\t" + element.getPort() + "\t"
  13. + element.getUri());
  14. }
  15. return this.discoveryClient;
  16. }

2、主启动类
添加注解@EnableDiscoveryClient //服务发现
3、测试

2.1、Eureka自我保护机制

某时刻某个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存。属于CAP里面的AP分支

概述
保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。

为什么会产生Eureka自我保护机制?
为了防止EurekaClient可以正常运行,但是 与 EurekaServer网络不通情况下,EurekaServer不会立刻将EurekaClient服务剔除

什么是自我保护模式?
默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与EurekaServer之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题——当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。

在自我保护模式中,Eureka Server会保护服务注册表中的信息,不再注销任何服务实例。
它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。一句话讲解:好死不如赖活着

综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。

2.2、如何禁止自我保护

以单机版注册中心为例子
1、Eureka7001.yml

  1. eureka:
  2. instance:
  3. hostname: eureka7001.com
  4. client:
  5. register-with-eureka: false
  6. fetch-registry: false
  7. service-url:
  8. #defaultZone: http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
  9. defaultZone: http://eureka7001.com:7001/eureka
  10. server:
  11. #关闭自我保护机制,保证不可用服务被及时踢除,默认为true
  12. enable-self-preservation: false
  13. #设置时间间隔为2秒
  14. eviction-interval-timer-in-ms: 2000

2、payment8001.yml

  1. eureka:
  2. client: #服务提供者provider注册进eureka服务列表内
  3. service-url:
  4. register-with-eureka: true
  5. fetch-registry: true
  6. # cluster version
  7. #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
  8. # singleton version
  9. defaultZone: http://eureka7001.com:7001/eureka
  10. #心跳检测与续约时间
  11. #开发时设置小些,保证服务关闭后注册中心能即使剔除服务
  12. instance:
  13. #Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
  14. lease-renewal-interval-in-seconds: 1
  15. #Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
  16. lease-expiration-duration-in-seconds: 2

3、测试
关闭服务8001后,Eureka会立即将服务删除,不会继续保留

2、ZooKeeper

1、linux系统安装好zookeeper

关闭防火墙

2、创建服务cloud-provider-payment8004

1、改pom

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>cloud2022</artifactId>
  7. <groupId>com.guang.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-provider-payment8004</artifactId>
  12. <dependencies>
  13. <!-- SpringBoot整合Web组件 -->
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-web</artifactId>
  17. </dependency>
  18. <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
  19. <groupId>com.atguigu.springcloud</groupId>
  20. <artifactId>cloud-api-commons</artifactId>
  21. <version>${project.version}</version>
  22. </dependency>
  23. <!-- SpringBoot整合zookeeper客户端 -->
  24. <dependency>
  25. <groupId>org.springframework.cloud</groupId>
  26. <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-devtools</artifactId>
  31. <scope>runtime</scope>
  32. <optional>true</optional>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.projectlombok</groupId>
  36. <artifactId>lombok</artifactId>
  37. <optional>true</optional>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.springframework.boot</groupId>
  41. <artifactId>spring-boot-starter-test</artifactId>
  42. <scope>test</scope>
  43. </dependency>
  44. </dependencies>
  45. </project>

2、改yml

  1. #8004表示注册到zookeeper服务器的支付服务提供者端口号
  2. server:
  3. port: 8004
  4. #服务别名----注册zookeeper到注册中心名称
  5. spring:
  6. application:
  7. name: cloud-provider-payment
  8. cloud:
  9. zookeeper:
  10. connect-string: 192.168.133.128:2181

3、主启动类

  1. @SpringBootApplication
  2. @EnableDiscoveryClient //该注解用于向使用consul或者zookeeper作为注册中心时注册服务
  3. public class PaymentMain8004
  4. {
  5. public static void main(String[] args)
  6. {
  7. SpringApplication.run(PaymentMain8004.class,args);
  8. }
  9. }

4、业务类

  1. @RestController
  2. public class PaymentController
  3. {
  4. @Value("${server.port}")
  5. private String serverPort;
  6. @GetMapping("/payment/zk")
  7. public String paymentzk()
  8. {
  9. return "springcloud with zookeeper: "+serverPort+"\t"+ UUID.randomUUID().toString();
  10. }
  11. }

3、Linux启动zookeeper

4、启动服务8004报错

jar包冲突的问题

5、解决方案

改pom

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>mscloud03</artifactId>
  7. <groupId>com.guang.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-provider-payment8004</artifactId>
  12. <dependencies>
  13. <!-- SpringBoot整合Web组件 -->
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-web</artifactId>
  17. </dependency>
  18. <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
  19. <groupId>com.atguigu.springcloud</groupId>
  20. <artifactId>cloud-api-commons</artifactId>
  21. <version>${project.version}</version>
  22. </dependency>
  23. <!-- SpringBoot整合zookeeper客户端 -->
  24. <dependency>
  25. <groupId>org.springframework.cloud</groupId>
  26. <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
  27. <!--先排除自带的zookeeper3.5.3-->
  28. <exclusions>
  29. <exclusion>
  30. <groupId>org.apache.zookeeper</groupId>
  31. <artifactId>zookeeper</artifactId>
  32. </exclusion>
  33. </exclusions>
  34. </dependency>
  35. <!--添加zookeeper3.4.9版本-->
  36. <dependency>
  37. <groupId>org.apache.zookeeper</groupId>
  38. <artifactId>zookeeper</artifactId>
  39. <version>3.4.9</version>
  40. </dependency>
  41. <dependency>
  42. <groupId>org.springframework.boot</groupId>
  43. <artifactId>spring-boot-devtools</artifactId>
  44. <scope>runtime</scope>
  45. <optional>true</optional>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.projectlombok</groupId>
  49. <artifactId>lombok</artifactId>
  50. <optional>true</optional>
  51. </dependency>
  52. <dependency>
  53. <groupId>org.springframework.boot</groupId>
  54. <artifactId>spring-boot-starter-test</artifactId>
  55. <scope>test</scope>
  56. </dependency>
  57. </dependencies>
  58. </project>

6、测试

linux下查看zookeeper是否存在新的节点
查看节点是否可以获得节点的详细信息
访问路由是否可以得到数据

7、zk节点是临时?持久?

将服务注册进zk后,关闭服务后发现,在一定的时间后zk会将该节点清除。

8、服务80进驻zk

1、创建Module=====》cloud-providerzk-order80
2、改pom

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>mscloud</artifactId>
  7. <groupId>com.guang.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-consumerzk-order81</artifactId>
  12. <dependencies>
  13. <!-- SpringBoot整合Web组件 -->
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-web</artifactId>
  17. </dependency>
  18. <!-- SpringBoot整合zookeeper客户端 -->
  19. <dependency>
  20. <groupId>org.springframework.cloud</groupId>
  21. <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
  22. <!--先排除自带的zookeeper-->
  23. <exclusions>
  24. <exclusion>
  25. <groupId>org.apache.zookeeper</groupId>
  26. <artifactId>zookeeper</artifactId>
  27. </exclusion>
  28. </exclusions>
  29. </dependency>
  30. <!--添加zookeeper3.4.9版本-->
  31. <dependency>
  32. <groupId>org.apache.zookeeper</groupId>
  33. <artifactId>zookeeper</artifactId>
  34. <version>3.4.9</version>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-devtools</artifactId>
  39. <scope>runtime</scope>
  40. <optional>true</optional>
  41. </dependency>
  42. <dependency>
  43. <groupId>org.projectlombok</groupId>
  44. <artifactId>lombok</artifactId>
  45. <optional>true</optional>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.springframework.boot</groupId>
  49. <artifactId>spring-boot-starter-test</artifactId>
  50. <scope>test</scope>
  51. </dependency>
  52. </dependencies>
  53. </project>

3、改yml

  1. server:
  2. port: 80
  3. spring:
  4. application:
  5. name: cloud-consumer-order
  6. cloud:
  7. #注册到zookeeper地址
  8. zookeeper:
  9. connect-string: 192.168.133.128:2181

4、主启动类

  1. @SpringBootApplication
  2. public class OrderZK80
  3. {
  4. public static void main(String[] args)
  5. {
  6. SpringApplication.run(OrderZK80.class,args);
  7. }
  8. }

5、配置RestTamplate

  1. @Configuration
  2. public class ApplicationContextBean
  3. {
  4. @Bean
  5. @LoadBalanced
  6. public RestTemplate getRestTemplate()
  7. {
  8. return new RestTemplate();
  9. }
  10. }

6、controller

  1. @RestController
  2. public class OrderZKController
  3. {
  4. public static final String INVOKE_URL = "http://cloud-provider-payment";
  5. @Autowired
  6. private RestTemplate restTemplate;
  7. @GetMapping("/consumer/payment/zk")
  8. public String paymentInfo()
  9. {
  10. String result = restTemplate.getForObject(INVOKE_URL+"/payment/zk", String.class);
  11. System.out.println("消费者调用支付服务(zookeeper)--->result:" + result);
  12. return result;
  13. }
  14. }

7、测试
查看linux下的zk节点
访问服务8004路由
访问服务80路由

3、Consul

下载地址:https://www.consul.io/downloads.html
中文学习文档:https://www.springcloud.cc/spring-cloud-consul.html

1、简介

Consul 是一套开源的分布式服务发现和配置管理系统,由 HashiCorp 公司用 Go 语言开发。

提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格,总之Consul提供了一种完整的服务网格解决方案。

它具有很多优点。包括: 基于 raft 协议,比较简洁; 支持健康检查, 同时支持 HTTP 和 DNS 协议 支持跨数据中心的 WAN 集群 提供图形界面 跨平台,支持 Linux、Mac、Windows

2、能干嘛

服务发现:提供HTTP和DNS两种发现方式
健康监测:支持等多种方式,HTTP、TCP、Docker、Shell脚本定制化监控
KV存储:key、value的存储方式
多数据中心:Consul支持多数据中心
可视化Web界面

3、下载安装

以windows的consul1.6.1版本为例子
参考官网安装动画、下载安装完成后consul—version 查看版本号
使用consul agent -dev启动consul
测试:http://localhost:8500

4、服务8006进驻consul

1、创建Module====》cloud-providerconsul-payment8006
2、改pom

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>mscloud</artifactId>
  7. <groupId>com.guang.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-providerconsul-payment8006</artifactId>
  12. <dependencies>
  13. <!--SpringCloud consul-server -->
  14. <dependency>
  15. <groupId>org.springframework.cloud</groupId>
  16. <artifactId>spring-cloud-starter-consul-discovery</artifactId>
  17. </dependency>
  18. <!-- SpringBoot整合Web组件 -->
  19. <dependency>
  20. <groupId>org.springframework.boot</groupId>
  21. <artifactId>spring-boot-starter-web</artifactId>
  22. </dependency>
  23. <dependency>
  24. <groupId>org.springframework.boot</groupId>
  25. <artifactId>spring-boot-starter-actuator</artifactId>
  26. </dependency>
  27. <!--日常通用jar包配置-->
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-devtools</artifactId>
  31. <scope>runtime</scope>
  32. <optional>true</optional>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.projectlombok</groupId>
  36. <artifactId>lombok</artifactId>
  37. <optional>true</optional>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.springframework.boot</groupId>
  41. <artifactId>spring-boot-starter-test</artifactId>
  42. <scope>test</scope>
  43. </dependency>
  44. </dependencies>
  45. </project>

3、改yml

  1. ###consul服务端口号
  2. server:
  3. port: 8006
  4. spring:
  5. application:
  6. name: consul-provider-payment
  7. ####consul注册中心地址
  8. cloud:
  9. consul:
  10. host: localhost
  11. port: 8500
  12. discovery:
  13. #hostname: 127.0.0.1
  14. service-name: ${spring.application.name}

4、主启动类

  1. @SpringBootApplication
  2. @EnableDiscoveryClient
  3. public class PaymentMain8006
  4. {
  5. public static void main(String[] args)
  6. {
  7. SpringApplication.run(PaymentMain8006.class,args);
  8. }
  9. }

5、controller

  1. @RestController
  2. public class PaymentController
  3. {
  4. @Value("${server.port}")
  5. private String serverPort;
  6. @GetMapping("/payment/consul")
  7. public String paymentInfo()
  8. {
  9. return "springcloud with consul: "+serverPort+"\t\t"+ UUID.randomUUID().toString();
  10. }
  11. }

6、测试
访问localhost:8006/payment/consul 查看服务是否进驻
查看接口访问路径是否得到返回信息

5、服务80进驻consul

1、新建Module====》cloud-consumerconsul-order80
2、改pom

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>mscloud</artifactId>
  7. <groupId>com.guang.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-consumerconsul-order82</artifactId>
  12. <dependencies>
  13. <!--SpringCloud consul-server -->
  14. <dependency>
  15. <groupId>org.springframework.cloud</groupId>
  16. <artifactId>spring-cloud-starter-consul-discovery</artifactId>
  17. </dependency>
  18. <!-- SpringBoot整合Web组件 -->
  19. <dependency>
  20. <groupId>org.springframework.boot</groupId>
  21. <artifactId>spring-boot-starter-web</artifactId>
  22. </dependency>
  23. <dependency>
  24. <groupId>org.springframework.boot</groupId>
  25. <artifactId>spring-boot-starter-actuator</artifactId>
  26. </dependency>
  27. <!--日常通用jar包配置-->
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-devtools</artifactId>
  31. <scope>runtime</scope>
  32. <optional>true</optional>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.projectlombok</groupId>
  36. <artifactId>lombok</artifactId>
  37. <optional>true</optional>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.springframework.boot</groupId>
  41. <artifactId>spring-boot-starter-test</artifactId>
  42. <scope>test</scope>
  43. </dependency>
  44. </dependencies>
  45. </project>

3、改yml

  1. ###consul服务端口号
  2. server:
  3. port: 80
  4. spring:
  5. application:
  6. name: cloud-consumer-order
  7. ####consul注册中心地址
  8. cloud:
  9. consul:
  10. host: localhost
  11. port: 8500
  12. discovery:
  13. #hostname: 127.0.0.1
  14. service-name: ${spring.application.name}

4、主启动类

  1. @SpringBootApplication
  2. @EnableDiscoveryClient //该注解用于向使用consul或者zookeeper作为注册中心时注册服务
  3. public class OrderConsulMain80
  4. {
  5. public static void main(String[] args)
  6. {
  7. SpringApplication.run(OrderConsulMain80.class,args);
  8. }
  9. }

5、配置RestTamplate

  1. @Configuration
  2. public class ApplicationContextBean
  3. {
  4. @Bean
  5. @LoadBalanced
  6. public RestTemplate getRestTemplate()
  7. {
  8. return new RestTemplate();
  9. }
  10. }

6、controller

  1. @RestController
  2. public class OrderConsulController
  3. {
  4. public static final String INVOKE_URL = "http://cloud-provider-payment"; //consul-provider-payment
  5. @Autowired
  6. private RestTemplate restTemplate;
  7. @GetMapping(value = "/consumer/payment/consul")
  8. public String paymentInfo()
  9. {
  10. String result = restTemplate.getForObject(INVOKE_URL+"/payment/consul", String.class);
  11. System.out.println("消费者调用支付服务(consule)--->result:" + result);
  12. return result;
  13. }
  14. }

7、测试
查看localhost:8006/payment/consul 查看服务是否进驻
查看两个接口路由是否得到返回数据

4、三个注册中心的异同

image.png
image.png
CAP==》关注粒度是数据,而不是整体系统设计的策略。
C:Consistency(强一致性)
A:Availability(可用性)
P:Partition tolerance(分区容错性)

最多只能同时较好的满足两个。
CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,
因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:
CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。
AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。

AP:Eureka
AP架构
当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性。
结论:违背了一致性C的要求,只满足可用性和分区容错,即AP
image.png
CP(Zookeeper/Consul)
CP架构
当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性
结论:违背了可用性A的要求,只满足一致性和分区容错,即CP
image.png

9、负载均衡服务调用-Ribbon

1、Ribbon(维护模式)

1.1简介

官网:https://github.com/Netflix/ribbon/wiki/Getting-Started
未来替换方案:LoadBalance

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法。

1.2能干嘛

负载均衡+RestTemplate

LB(负载均衡)相当于之前RestTemplate的@LoadBalanced

集中式LB
即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;

进程内LB
将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。
Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。

2、Ribbon负载均衡演示

image.png
Ribbon在工作时分成两步
第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server.
第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。
其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。

10、服务接口调用-OpenFeign

11、Hystrix

12、网关

1、zuul路由网关

1.1、概述简介

Zuul是一种提供动态路由、监视、弹性、安全性等功能的边缘服务。
Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器

API网关为微服务架构中的服务提供了统一的访问入口,客户端通过API网关访问相关服务。API网关的定义类似于设计模式中的门面模式,它相当于整个微服务架构中的门面,所有客户端的访问都通过它来进行路由及过滤。它实现了请求路由、负载均衡、校验过滤、服务容错、服务聚合等功能。

image.png
》代理
》路由
》负载均衡
网关为入口,由网关与微服务进行交互,所以网关必须要实现负载均衡的功能;
网关会获取微服务注册中心里面的服务连接地址,再配合一些算法选择其中一个服务地址,进行处理业务。
这个属于客户端侧的负载均衡,由调用方去实现负载均衡逻辑。
image.png

1.2、路由基本配置

功能:路由功能负责将外部请求转发到具体的服务实例上去,是实现统一访问入口的基础
1、新建Module模块cloud-zuul-gateway9527
2、pom

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>mscloud</artifactId>
  7. <groupId>com.atguigu.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-zuul-gateway9527</artifactId>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework.cloud</groupId>
  15. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework.cloud</groupId>
  19. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter-actuator</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.springframework.boot</groupId>
  27. <artifactId>spring-boot-devtools</artifactId>
  28. <scope>runtime</scope>
  29. <optional>true</optional>
  30. </dependency>
  31. <dependency>
  32. <groupId>org.projectlombok</groupId>
  33. <artifactId>lombok</artifactId>
  34. <optional>true</optional>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-starter-test</artifactId>
  39. <scope>test</scope>
  40. </dependency>
  41. </dependencies>
  42. </project>

3、yml

  1. server:
  2. port: 9527
  3. spring:
  4. application:
  5. name: cloud-zuul-gateway
  6. eureka:
  7. client:
  8. service-url:
  9. #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
  10. defaultZone: http://eureka7001.com:7001/eureka
  11. instance:
  12. instance-id: gateway-9527.com
  13. prefer-ip-address: true

4、修改hosts文件
127.0.0.1 myzuul.com
5、主启动类

  1. @SpringBootApplication
  2. @EnableZuulProxy
  3. public class Zuul_9527_StartSpringCloudApp
  4. {
  5. public static void main(String[] args)
  6. {
  7. SpringApplication.run(Zuul_9527_StartSpringCloudApp.class, args);
  8. }
  9. }

6、启动项目
》三个eureka集群
》一个服务提供者microservicecloud-provider-dept-8001
》一个路由
7、测试
不用路由:localhost:8001/paymentInfo
启用路由:
>zuul映射配置+注册中心注册后对外暴露的服务名称+rest调用地址
>myzuul.com:9527/cloud-provider-payment/paymentInfo

1.3、路由访问映射规则