帮你快速学习spring cloud相关技术栈

服务注册与发现:Eureka、Zookeeper、Consul

负载均衡服务调用:Ribbon

Hystrix断路器

Gateway网关

Config分布式配置中心

Bus消息总线

Stream消息驱动

Sleuth分布式请求链路跟踪

 壹、零基础

一、微服务架构零基础理论入门

SpringCloud=分布式微服务架构的一站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶。

二、从2.2.x和H版开始说起

springboot版本选择:

git源码地址:https://github.com/spring-projects/spring-boot/releases/

SpringBoot2.0新特性:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release

springcloud版本选择:

git源码地址:https://github.com/spring-projects/spring-cloud

官网:https://spring.io/projects/spring-cloud

官网看cloud版本

springcloud和springboot之间依赖关系:https://spring.io/projects/spring-cloud#overview

三、关于Cloud各种组件的停更/升级/替换

服务注册中序:Eureka(挂)。zookeeper。Consul。Nacos(百万级推荐)。

服务调用1:Ribbon。LoadBalancer。

服务调用2:Feign(挂)。OpenFeign。

服务降级:Hystrix(挂)。resilience4j。sentienl(推荐)。

服务网关:Zuul(挂)。Zuul2(未出)。gateway(推荐)。

服务配置:Config(挂)。Nacos(推荐)。

服务总线:Bus(挂)。Nacos(推荐)。

参考资料:

1. Spring Cloud:https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/

2. Spring Cloud中文文档:https://www.bookstack.cn/read/spring-cloud-docs/docs-index.md

3. Spring Boot:https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/

四、微服务架构编码构建

4.1 引入依赖


  
  
  1. <!-- 统一管理jar包版本 -- >
  2. <properties >
  3. <project.build.sourceEncoding >UTF- 8 < /project.build.sourceEncoding >
  4. <maven.compiler. source > 1.8 < /maven.compiler. source >
  5. <maven.compiler.target > 1.8 < /maven.compiler.target >
  6. <junit.version > 4.12 < /junit.version >
  7. <log 4j.version > 1.2.17 < /log 4j.version >
  8. <lombok.version > 1.16.18 < /lombok.version >
  9. <mysql.version > 5.1.47 < /mysql.version >
  10. <druid.version > 1.1.16 < /druid.version >
  11. <mybatis.spring.boot.version > 1.3.0 < /mybatis.spring.boot.version >
  12. < /properties >

  
  
  1. <!-- 子模块继承之后,提供作用:锁定版本 +子modlue不用写groupId和version -- >
  2. <dependencyManagement >
  3. <dependencies >
  4. <!--spring boot 2.2.2-- >
  5. <dependency >
  6. <groupId >org.springframework.boot < /groupId >
  7. <artifactId >spring-boot-dependencies < /artifactId >
  8. <version > 2.2.2. RELEASE < /version >
  9. < type >pom < / type >
  10. <scope >import < /scope >
  11. < /dependency >
  12. <!--spring cloud Hoxton.SR 1-- >
  13. <dependency >
  14. <groupId >org.springframework.cloud < /groupId >
  15. <artifactId >spring-cloud-dependencies < /artifactId >
  16. <version >Hoxton.SR 1 < /version >
  17. < type >pom < / type >
  18. <scope >import < /scope >
  19. < /dependency >
  20. <!--spring cloud alibaba 2.1.0. RELEASE-- >
  21. <dependency >
  22. <groupId >com.alibaba.cloud < /groupId >
  23. <artifactId >spring-cloud-alibaba-dependencies < /artifactId >
  24. <version > 2.1.0. RELEASE < /version >
  25. < type >pom < / type >
  26. <scope >import < /scope >
  27. < /dependency >
  28. <dependency >
  29. <groupId >mysql < /groupId >
  30. <artifactId >mysql-connector-java < /artifactId >
  31. <version >${mysql.version} < /version >
  32. < /dependency >
  33. <dependency >
  34. <groupId >com.alibaba < /groupId >
  35. <artifactId >druid < /artifactId >
  36. <version >${druid.version} < /version >
  37. < /dependency >
  38. <dependency >
  39. <groupId >org.mybatis.spring.boot < /groupId >
  40. <artifactId >mybatis-spring-boot-starter < /artifactId >
  41. <version >${mybatis.spring.boot.version} < /version >
  42. < /dependency >
  43. <dependency >
  44. <groupId >junit < /groupId >
  45. <artifactId >junit < /artifactId >
  46. <version >${junit.version} < /version >
  47. < /dependency >
  48. <dependency >
  49. <groupId >log 4j < /groupId >
  50. <artifactId >log 4j < /artifactId >
  51. <version >${log 4j.version} < /version >
  52. < /dependency >
  53. <dependency >
  54. <groupId >org.projectlombok < /groupId >
  55. <artifactId >lombok < /artifactId >
  56. <version >${lombok.version} < /version >
  57. < optional > true < / optional >
  58. < /dependency >
  59. < /dependencies >
  60. < /dependencyManagement >

  
  
  1. <build >
  2. <plugins >
  3. <plugin >
  4. <groupId >org.springframework.boot < /groupId >
  5. <artifactId >spring-boot-maven-plugin < /artifactId >
  6. <version > 2.2.1. RELEASE < /version >
  7. < configuration >
  8. <fork > true < /fork >
  9. <addResources > true < /addResources >
  10. < / configuration >
  11. < /plugin >
  12. < /plugins >
  13. < /build >

DependencyManagement和Dependencies的区别:

<DependencyManagement>是父类定义的坐标版本号,用在父工程,类似于规范将全工程的版本统一,只负责定义,而不负责引入实现。真正引入依赖的是子类<dependencies>定义的版本号。如果子类没指定版本号,默认是用父类的。如果子类指定了版本号,则版本号用子类指定的(如果不在子项目中声明依赖,不会从父项目中继承。只要在子项目中写了该依赖项,并且没有指定具体的版本,才会从父项目中继承该项,并且version和scope都读取自父pom)。

maven中跳过单元测试:

4.2 支付模块构建

1.建module:右键项目新建Module

2.改POM


  
  
  1. <dependencies >
  2. <dependency >
  3. <groupId >org.springframework.boot < /groupId >
  4. <artifactId >spring-boot-starter-web < /artifactId >
  5. < /dependency >
  6. <dependency >
  7. <groupId >org.springframework.boot < /groupId >
  8. <artifactId >spring-boot-starter-actuator < /artifactId >
  9. < /dependency >
  10. <dependency >
  11. <groupId >org.mybatis.spring.boot < /groupId >
  12. <artifactId >mybatis-spring-boot-starter < /artifactId >
  13. < /dependency >
  14. <dependency >
  15. <groupId >com.alibaba < /groupId >
  16. <artifactId >druid-spring-boot-starter < /artifactId >
  17. <version > 1.1.10 < /version >
  18. < /dependency >
  19. <!--mysql-connector-java-- >
  20. <dependency >
  21. <groupId >mysql < /groupId >
  22. <artifactId >mysql-connector-java < /artifactId >
  23. < /dependency >
  24. <!--jdbc-- >
  25. <dependency >
  26. <groupId >org.springframework.boot < /groupId >
  27. <artifactId >spring-boot-starter-jdbc < /artifactId >
  28. < /dependency >
  29. <dependency >
  30. <groupId >org.springframework.boot < /groupId >
  31. <artifactId >spring-boot-devtools < /artifactId >
  32. <scope >runtime < /scope >
  33. < optional > true < / optional >
  34. < /dependency >
  35. <dependency >
  36. <groupId >org.projectlombok < /groupId >
  37. <artifactId >lombok < /artifactId >
  38. < optional > true < / optional >
  39. < /dependency >
  40. <dependency >
  41. <groupId >org.springframework.boot < /groupId >
  42. <artifactId >spring-boot-starter-test < /artifactId >
  43. <scope > test < /scope >
  44. < /dependency >
  45. < /dependencies >

3. 写YML

在cloud-provider-payment8001的resources下创建application.yml文件,注意要变成绿色树叶:


  
  
  1. server:
  2. port: 8081
  3. spring:
  4. application:
  5. name: cloud-payment-service
  6. datasource:
  7. type: com.alibaba.druid.pool.DruidDataSource
  8. driver-class-name: com.mysql.jdbc.Driver
  9. url: jdbc:mysql: / /localhost: 3306 /db 2019?useUnicode = true &characterEncoding =utf- 8 &usrSSL = false
  10. username: root
  11. password: 111111
  12. mybatis:
  13. mapper-locations: classpath:mapper / *.xml #在mapper包下创建.xml配置文件
  14. type-aliases-package: com.atguigu.springcloud.entities #entities下创建实体类

4. 主启动

在src/main/java/com/atguigu/springcloud包下创建PaymentMain8001类,加上@SpringBootApplication作为主启动类:


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

5. 业务类

5.1 建表SQL


  
  
  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 AUTO_INCREMENT = 1 DEFAULT CHARSET =utf 8

5.2 entities实体类

在java/com/atguigu/springcloud下创建entities包,在其下创建Payment类:

主实体Payment代码:


  
  
  1. public class Payment implements Serializable {
  2. private Long id;
  3. private String serial;
  4. public Long getId( ) { return id;}
  5. public void setId( Long id) { this. id = id;}
  6. public String getSerial( ) { return serial;}
  7. public void setSerial( String serial) { this. serial = serial;}
  8. public Payment( Long id, String serial) { this. id = id; this. serial = serial;}
  9. public Payment() {}
  10. }

Json封装体CommonResult

在entities包下创建CommonResult类:


  
  
  1. public class CommonResult<T> {
  2. private Integer code;
  3. private String message;
  4. private T data;
  5. public CommonResult( Integer code, String message){ this(code,message, null);}
  6. public CommonResult( Integer code, String message, T data) { this. code = code; this. message = message; this. data = data;}
  7. public CommonResult() {}
  8. public Integer getCode( ) { return code;}
  9. public void setCode( Integer code) { this. code = code;}
  10. public String getMessage( ) { return message;}
  11. public void setMessage( String message) { this. message = message;}
  12. public T getData( ) { return data;}
  13. public void setData( T data) { this. data = data;}
  14. }

1. @Data是一个Lombok注解,用于自动生成Java类的常见方法,如getter、setter、toString、equals和hashCode方法。

2. this(code, message, null)表示调用当前类的另一个构造函数CommonResult(Integer code, String message, Object data),并传递参数codemessagenull。

3. @AllArgsConstructor是Lombok注解之一,用于自动生成一个包含所有参数的构造函数。

5.3 dao

创建dao包,在其下创建PaymentDao接口,记得写@Mapper注解:


  
  
  1. @Mapper
  2. public interface PaymentDao {
  3. public int create(Payment payment);
  4. public Payment getPaymentById( @Param( "id") Long id);
  5. }

mybatis的映射文件:

在resources下创建mapper包,创建PaymentMapper.xml映射文件:

1. parameterType是用来指定传入SQL语句的参数类型。

2. resultMap用来指定查询结果映射到哪个Java对象上。

3. column是数据库字段,property是java对象属性。

4.keyProperty:用于指定自动生成的主键值要被设置到Java实体类的哪个属性上。

resultMap映射属性,用于防止命名不规范造成错误:


  
  
  1. <?xml version = "1.0" encoding = "UTF-8" ? >
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  5. <mapper namespace = "com.atguigu.springcloud.dao.PaymentDao" >
  6. <insert id = "create" parameterType = "Payment" useGeneratedKeys = "true" keyProperty = "id" >
  7. insert into payment(serial) values(#{serial});
  8. < /insert >
  9. <resultMap id = "BaseResultMap" type = "com.atguigu.springcloud.entities.Payment" >
  10. <id column = "id" property = "id" jdbcType = "BIGINT" / >
  11. <id column = "serial" property = "serial" jdbcType = "VARCHAR" / >
  12. < /resultMap >
  13. < select id = "getPaymentById" parameterType = "Long" resultMap = "BaseResultMap" >
  14. select * from payment where id =#{id};
  15. < / select >
  16. < /mapper >

5.4 service

在springcloud下创建service包,创建PaymentService接口:


  
  
  1. public interface PaymentService{
  2. public int create(Payment payment);
  3. public Payment getPatmentById( @Param( "id") Long id);
  4. }

1. @Param注解的作用是给方法参数起别名,@Param注解的作用是给方法参数起别名。@Param("id")表示给方法参数id起别名为"id"。这样在SQL映射文件中可以使用#{id}来引用这个参数。

创建PaymentServiceImpl实现类,记得写@Service注解

1. @Resource注解是用来标记一个需要依赖注入的对象。可以根据名称进行依赖注入,也可以根据类型进行依赖注入。


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

5.5 controller

在springcloud下创建controller包,然后创建PaymentController类:

1. @GetMapping注解用于将HTTP的GET请求映射到相应的处理方法上。

2. @PathVariable注解用于将URL路径中的变量值绑定到方法参数上。


  
  
  1. @RestController
  2. public class PaymentController {
  3. @Resource
  4. private PaymentService paymentService;
  5. @PostMapping(value="/payment/create")
  6. public CommonResult create(Payment payment){
  7. System. out.println(payment.getSerial());
  8. int result = paymentService.create(payment);
  9. if(result> 0){
  10. return new CommonResult( 200, "插入数据库成功",result);
  11. } else{
  12. return new CommonResult( 444, "插入数据库失败", null);
  13. }
  14. }
  15. @GetMapping(value="/payment/get/{id}")
  16. public CommonResult getPaymentById( @PathVariable("id") Long id)
  17. {
  18. Payment payment = paymentService.getPatmentById(id);
  19. if(payment != null){
  20. return new CommonResult( 200, "查询成功",payment);
  21. } else{
  22. return new CommonResult( 444, "没有对应记录,查询ID:"+id, null);
  23. }
  24. }
  25. }

5.6 测试

启动启动类,在地址栏输入localhost:8001/payment/get/31

浏览器不适合发post请求,因此去postman发请求,id是自增的,只需要发送serial即可:

4.3 热部署

Devtools热部署,代码改动,自动重启。

第1步:在cloud-provider-payment8001添加依赖


  
  
  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步:父工程cloud2020添加插件


  
  
  1. <build >
  2. <plugins >
  3. <plugin >
  4. <groupId >org.springframework.boot < /groupId >
  5. <artifactId >spring-boot-maven-plugin < /artifactId >
  6. <version > 2.2.1. RELEASE < /version >
  7. < configuration >
  8. <fork > true < /fork >
  9. <addResources > true < /addResources >
  10. < / configuration >
  11. < /plugin >
  12. < /plugins >
  13. < /build >

第3步:开启自动编译权限 

第4步:更新值,开启热注册

输入快捷键:ctrl + shift + alt + /

 

第5步:重启

(失败)测试:同样是PaymentMain8001启动,然后进入到cloud-provider-payment8001下的controller,更改CommonResult为CommonResult<Payment>,会实时刷新(失败)。

4.4 消费者订单模块

1. 建module

名字:Cloud-consumer-order80,src下有main和test,main下有java和resource

2. 改pom

web、acuator是图形化的监控展现,要先加mybatis的驱动运行,之后可以删除mybatis驱动,不然.yml会变不成绿叶:


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

3. 写YML

在resources下建application.yml,设置端口80


  
  
  1. server:
  2. port: 81

4. 主启动

在java下创建com.atguigu.springcloud.OrderMain80类


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

5. 业务类

5.1 entities复制payment8001的

RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集。

5.2 创建springcloud下的config包,在包下创建ApplicationContextConfig类:


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

5.3 在controller包下创建OrderController类:


  
  
  1. @RestController
  2. @Slf4j
  3. public class OrderController{
  4. public static final String PAYMENT_URL = "http://localhost:8081";
  5. @Resource
  6. private RestTemplate restTemplate;
  7. @PostMapping("/consumer/payment/create")
  8. public CommonResult<Payment> create(Payment payment){
  9. return restTemplate.postForObject(PAYMENT_URL+ "/payment/create",payment,CommonResult. class);
  10. }
  11. @GetMapping("/consumer/payment/get/{id}")
  12. public CommonResult<Payment> getPayment( @PathVariable("id") Long id){
  13. return restTemplate.getForObject(PAYMENT_URL+ "/payment/get/"+id,CommonResult. class);
  14. }
  15. }

  

但此时调用create方法会出现插入值为空的情况,记得要在cloud-provider-payment8001的controller下的PaymentController类中加入@RequestBody注解:

@RequestBody注解用于将HTTP请求的请求体部分映射到方法的参数上。

新版的Dashboard叫作services

4.5 重构

新建一个cloud-api-commons模块,作为通用封装类:

在模块下引入依赖:


  
  
  1. <dependencies >
  2. <dependency >
  3. <groupId >org.springframework.boot < /groupId >
  4. <artifactId >spring-boot-devtools < /artifactId >
  5. <scope >runtime < /scope >
  6. < optional > true < / optional >
  7. < /dependency >
  8. <dependency >
  9. <groupId >org.projectlombok < /groupId >
  10. <artifactId >lombok < /artifactId >
  11. < optional > true < / optional >
  12. < /dependency >
  13. <dependency >
  14. <groupId >cn.hutool < /groupId >
  15. <artifactId >hutool-all < /artifactId >
  16. <version > 5.1.0 < /version >
  17. < /dependency >
  18. <dependencies >

在模块的java目录下建com.atguigu.springcloud.entities包,直接将entities粘贴在下面:

点击右边的Maven,选择刷新出现cloud-api-commons,进入Lifecycle点击clean点击install即可。

删除掉原先的entities包

将下面依赖粘贴在删掉entities包的模块之下:


  
  
  1. <dependency >
  2. <groupId >com.atguigu.springcloud < /groupId >
  3. <artifactId >cloud-api-commons < /artifactId >
  4. <version >${project.version} < /version >
  5. < /dependency >

贰、初级

五、Eureka服务注册与发现

7001、7002模拟的是Eureka服务器,81模拟消费者,8081和8082模拟生产者。

5.1 基础知识

5.2 服务端安装

1. 建module

ArtifactId:cloud-eureka-server7001,com.atguigu.springcloud

2. 改POM


  
  
  1. <dependencies >
  2. <!--eureka-server-- >
  3. <dependency >
  4. <groupId >org.springframework.cloud < /groupId >
  5. <artifactId >spring-cloud-starter-netflix-eureka-server < /artifactId >
  6. < /deoendency >
  7. <dependency >
  8. <groupId >org.atguigu.springcloud < /groupId >
  9. <artifactId >cloud-api-common < /artifactId >
  10. <version >${project.version} < /version >
  11. < /dependency >
  12. <dependency >
  13. <groupId >org.springframework.boot < /groupId >
  14. <artifactId >spring-boot-starter-web < /artifactId >
  15. < /dependency >
  16. <dependency >
  17. <groupId >org.springframework.boot < /groupId >
  18. <artifactId >spring-boot-starter-actuator < /artifactId >
  19. < /dependency >
  20. <dependency >
  21. <groupId >org.springframework.boot < /groupId >
  22. <artifactId >spring-boot-devtools < /artifactId >
  23. <scope >runtime < /scope >
  24. < optional > true < / optional >
  25. < /dependency >
  26. <dependency >
  27. <groupId >org.projectlombok < /groupId >
  28. <artifactId >lombok < /artifactId >
  29. < optional > true < / optional >
  30. < /dependency >
  31. <dependency >
  32. <groupId >org.springframework.boot < /groupId >
  33. <artifactId >spring-boot-starter-test < /artifactId >
  34. <scope > test < /scope >
  35. < /dependency >
  36. < /dependencies >

3. 写YML

在resources下创建application.yml


  
  
  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. 主启动

创建EurekaMain7001作为启动类:


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

如果成功输入localhost:7001后出现下面字样: 

5.3 支付微服务8081入驻进eurekaServer

在8081的Pom中引入:


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

在application.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

在启动类添加注解:@EnableEurekaClient

如果成功,Instances区域会出现CLOUD-PAYMENT-SERVICE这一新的Instances:

5.4 订单微服务81入驻进eurekaServer

在Pom中加入如下代码:


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

在YML中加入如下代码:


  
  
  1. eureka:
  2. client:
  3. register-with-eureka: true
  4. fetchRegistry: true
  5. service-url:
  6. defaultZone: http: / /localhost: 7001 /eureka

 在启动类中加入如下代码:@EnableEurekaClient

如果成功出现如下2个:

register-with-eureka为false表示不让入驻,为true表示让入驻。

5.5 集群原理说明

Eureka Server:服务注册,将服务信息注册进服务中心。服务发现,从注册中心上获取服务信息。实质,存key服务名 取 value调用地址。

先启动eureka注册中心。启动服务提供者payment支付服务。支付服务启动后会把自身信息(如服务地址以别名方式注册进eureka)。消费者order服务在需要调用接口时,使用服务别名去注册中心获取实际的RPC远程调用地址。消费者或者调用地址后,底层实际是利用HttpClient技术实现远程调用。消费者获取服务地址后会缓存在本地jvm内存中,默认每隔30秒更新一次服务调用地址。

Eureka具有高可用特点,可搭建Eureka注册中心集群,实现负载均衡+容错故障。避免单点故障。互相注册,相互守望。

5.6 集群环境构建

建Module:cloud-eureka-server7002

Pom:直接复制7001

YML:建application.yml

主启动类:EurekaMain7002,用7001的注解

修改配置:C:\Windows\System32\drivers\etc路径下的hosts文件。

修改7001的.yml,修改hostname和defaultZone:


  
  
  1. server:
  2. port: 7001
  3. eureka:
  4. instance:
  5. hostname: eureka 7001.com #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 7002.com: 7002 /eureka /

修改7002的.yml文件:


  
  
  1. server:
  2. port: 7002
  3. eureka:
  4. instance:
  5. hostname: eureka 7002.com #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 7001.com: 7001 /eureka /

输入eureka7002.com:7002==127.0.0.1:7002和eureka7001.com:7001==127.0.0.1能见到eureka首页:

输入

locahost:7002能指向7001,locahost:7001能指向7002算是成功:

5.7 订单支付两微服务注册进Eureka集群

YML:在8081的eureka下添加:

defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
  
  

 YML:在81的eureka下添加:


  
  
  1. eureka:
  2. client:
  3. register-with-eureka: true
  4. fetchRegistry: true
  5. service-url:
  6. defaultZone: http: / /eureka 7001.com: 7001 /eureka,http: / /eureka 7002.com: 7002 /eureka

启动:

先要启动EurekaServer,7001/7002服务 

再启动服务提供者provider,8081

再启动消费者,81

输入http://localhost:81/consumer/payment/get/31,如果查询成功即可

测试:

eureka7001.com:7001可以看到81和8081注册进入

eureka7002.com:7002同样也可以看到

5.8 支付微服务集群配置

建Module:创建cloud-provider-payment8082

改Pom:把8081粘贴入8082

写YML:把8081的粘贴入8082,改一个端口号

主启动:建PaymentMain8082把8081的启动类复制过来,把resource下的mapper包粘贴到8082,把com包直接粘贴到8082。

改controller:修改8001和8002加入如下内容:


  
  
  1. @Value("${server.port}")
  2. private String serverPort;

  
  
  1. return new CommonResult( 200, "插入数据库成功,serverPort" +serverPort,result);
  2. return new CommonResult( 200, "查询成功,serverPort" +serverPort,payment);

启动顺序:7001、7002、8081、8082、81

测试:eureka7001.com:7001,eureka7002.com:7002,localhost:81/consumer/payment/get/31

发现bug:订单服务访问地址是写死的。

此时会报错,因为IDEA不知道是这个地址下的哪台服务器提供服务。

使用@LoadBalanced注解赋予RestTemplate负载均衡的能力,注解写在config包的ApplicationContextConfig下:

此时访问localhost:81/consumer/payment/get/31,端口号会在8081和8082之间来回切换:

5.9 actuator微服务信息完善

加上instance: instance-id和prefer-ip-address: true(访问路径显示ip地址)

5.10 服务发现Discovery

在8081的controller的PaymentController类上修改:


  
  
  1. @Slf 4j
  2. @RestController
  3. public class PaymentController {
  4. @Resource
  5. private DiscoveryClient discoveryClient;
  6. @GetMapping( value = "/payment/discovery")
  7. public Object discovery()
  8. {
  9. List < String > services = discoveryClient.getServices();
  10. for( String element : services){
  11. log.info( "*****element: " +element);
  12. }
  13. List <ServiceInstance > instances = discoveryClient.getInstances( "CLOUD-PAYMENT-SERVICE");
  14. for(ServiceInstance instance : instances){
  15. log.info(instance.getServiceId() + "\t" +instance.getHost() + "\t" +instance.getPort() + "\t" +instance.getUri());
  16. }
  17. return instances;
  18. }
  19. }

5. 11 Eureka自我保护理论知识

概括:某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存。

为了防止EurekaClient可以正常运行,但是与EurekaServer网络不通情况下,EurekaServer不会立刻将EurekaClient服务器剔除。

5.12 禁止自我保护

在7001的yml文件中的eureka下,加下列代码:


  
  
  1. server:
  2. #关闭自我保护机制,保证不可用服务被及时踢除
  3. enable- self-preservation: false
  4. eviction-interval-timer-in-ms: 2000

测试:先看8081是否存在,关闭8081,看卡是否立刻删除。

Eureka停更说明

六、Zookeeper服务注册与发现

6.1 Zookeeper的安装

下载zookeeper-3.4.9,下面是安装地址

https://archive.apache.org/dist/zookeeper/
  
  

在Linux虚拟机中,创建/opt/module目录,把zookeeper的gz压缩包放到该目录下。

然后解压该压缩包到该目录:

tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/module/
  
  

然后修改配置:

将/opt/module/zookeeper-3.4.10/conf这个路径下的zoo.sample.cfg修改为zoo.cfg:

mv zoo_sample.cfg zoo.cfg
  
  

在/opt/module/zookeeper-3.4.10目录创建zkData文件夹:

mkdir zkData
  
  

打开zoo.cfg文件,修改dataDir路径:

vim zoo.cfg
  
  

修改如下内容:

dataDir=/opt/module/zookeeper-3.4.10/zkData
  
  

启动Zookeeper服务

输入:sudo /opt/module/zookeeper-3.4.9/bin/zkServer.sh start

进入Zookeeper

输入:sudo /opt/module/zookeeper-3.4.9/bin/zkCli.sh

退出Zookeeper 

输入:quit

关闭Zookeeper服务:

sudo /opt/module/zookeeper-3.4.9/bin/zkServer.sh stop

6.2 项目环境配置

在/opt/module/zookeeper-3.4.9/bin目录下输入:

sudo systemctl stop firewalld 关闭防火墙。

sudo systemctl status firewalld检查防火墙是否关闭。

确保虚拟机能和windows ping通

建module:cloud-provider-payment8004

pom:


  
  
  1. <dependency >
  2. <groupId >org.springframework.boot < /groupId >
  3. <artifactId >spring-boot-starter-web < /artifactId >
  4. < /dependency >
  5. <dependency >
  6. <groupId >org.springframework.boot < /groupId >
  7. <artifactId >spring-boot-starter-actuator < /artifactId >
  8. < /dependency >
  9. <dependency >
  10. <groupId >org.springframework.boot < /groupId >
  11. <artifactId >spring-boot-devtools < /artifactId >
  12. <scope >runtime < /scope >
  13. < optional > true < / optional >
  14. < /dependency >
  15. <dependency >
  16. <groupId >org.projectlombok < /groupId >
  17. <artifactId >lombok < /artifactId >
  18. < optional > true < / optional >
  19. < /dependency >

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

YML: 


  
  
  1. server:
  2. port: 8004
  3. #服务别名 — — — — 注册zookeeper到注册中心名称
  4. spring:
  5. application:
  6. name: cloud-provider-payment
  7. cloud:
  8. zookeeper:
  9. connect- string: 192.168. 182.157: 2181

启动类:

com.atguigu.springcloud.PaymentMain8004 


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

服务类:

springcloud下建controller包,PaymentController


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

然后启动Zookeeper服务,进入zookeeper

输入:sudo /opt/module/zookeeper-3.4.9/bin/zkServer.sh start

输入:sudo /opt/module/zookeeper-3.4.9/bin/zkCli.sh

输入:get /zookeeper

版本冲突问题:


  
  
  1. <dependency >
  2. <!--添加zookeeper 3.4.9版本-- >
  3. <groupId >org.apache.zookeeper < /groupId >
  4. <artifactId >zookeeper < /artifactId >
  5. <version > 3.4.9 < /version >
  6. <!--先排除自带的zookeeper 3.5.3-- >
  7. <exclusions >
  8. <exclusion >
  9. <groupId >org.apache.zookeeper < /groupId >
  10. <artifactId >zookeeper < /artifactId >
  11. < /exclusion >
  12. < /exclusions >
  13. < /dependency >

然后点击启动。

测试localhost:8004/payment/zk,如果每次刷新后面一串数字会变则成功:

把json串赋值到tool.lu/json看得到信息则成功:

6.3 临时还是持久节点

用的是临时的,关闭8004一段时间,zookeeper会踢掉。重新启动,流水号会改变。

6.4 订单服务注册进zookeeper

module:cloud-consumerzk-order81。

POM:复制8004,见上节。

YML:


  
  
  1. server:
  2. port: 81
  3. #服务别名 — — — — 注册zookeeper到注册中心名称
  4. spring:
  5. application:
  6. name: cloud-consumer- order
  7. cloud:
  8. #注册到zookeeper地址
  9. zookeeper:
  10. connect- string= 192.168. 182.157: 2181

启动类:


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

config:


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

controller:


  
  
  1. @RestController
  2. @Slf4j
  3. public class OrderZKController {
  4. public static final String INVOKE_URL= "http://cloud-provider-payment";
  5. @Resource
  6. private RestTemplate restTemplate;
  7. @GetMapping(value= "/consumer/payment/zk")
  8. public String paymentInfo( ){
  9. String result = restTemplate. getForObject( INVOKE_URL+ "/payment/zk", String. class);
  10. return result;
  11. }
  12. }

测试:

七、Consul服务注册与发现

7.1 Consul简介

7.2 安装并运行Consul

下载地址:

https://developer.hashicorp.com/consul/downloads
  
  

 

点击地址栏,输入cmd,输入consul --version,再输入consul agent -dev

输入http://localhost:8500会进入界面,看到勾勾:

7.3 服务提供者注册进Consul

module:cloud-providerconsul-payment8006

pom:


  
  
  1. <dependency >
  2.       <groupId >org.springframework.cloud < /groupId >
  3.       <artifactId >spring-cloud-starter-consul-discovery < /artifactId >
  4. < /dependency >
  5. <dependency >
  6. <groupId >org.springframework.boot < /groupId >
  7. <artifactId >spring-boot-starter-web < /artifactId >
  8. < /dependency >
  9. <dependency >
  10. <groupId >org.springframework.boot < /groupId >
  11. <artifactId >spring-boot-starter-actuator < /artifactId >
  12. < /dependency >
  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 >

yml:


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

启动类:


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

业务类:复制8004,稍加修改


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

测试类:启动

7.4 服务消费者注册进Consul

module: cloud-consumerconsul-order81

pom:


  
  
  1. <dependency >
  2. <groupId >org.springframework.cloud < /groupId >
  3. <artifactId >spring-cloud-starter-consul-discovery < /artifactId >
  4. < /dependency >
  5. <dependency >
  6. <groupId >org.springframework.boot < /groupId >
  7. <artifactId >spring-boot-starter-web < /artifactId >
  8. < /dependency >
  9. <dependency >
  10. <groupId >org.springframework.boot < /groupId >
  11. <artifactId >spring-boot-starter-actuator < /artifactId >
  12. < /dependency >
  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 >org.springframework.boot < /groupId >
  26. <artifactId >spring-boot-starter-test < /artifactId >
  27.     <scope > test < /scope >
  28. < /dependency >

yml:


  
  
  1. server:
  2. port: 81
  3. spring:
  4. application:
  5. name: cloud-consumer-order
  6. #consul注册中心地址
  7. cloud:
  8. consul:
  9. host: localhost
  10. port: 8500
  11. discovery:
  12. service- name: ${spring.application.name}

主启动类:


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

配置Bean:


  
  
  1. @Configuration
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值