Spring Cloud 的学习是一个比较漫长的旅程。
参考博客资料:https://www.kuangstudy.com/bbs/1374942542566551554
学习网站:
通过 springcloud, 我们可以实现的功能大致有:
什么是微服务?
微服务(Microservice Architecture) 是近几年流行的一种架构思想,关于它的概念很难一言以蔽之。
究竟什么是微服务呢?我们在此引用ThoughtWorks 公司的首席科学家 Martin Fowler 于2014年提出的一段话:
原文:https://martinfowler.com/articles/microservices.html
汉化:https://www.cnblogs.com/liuning8023/p/4493156.html
再来从技术维度角度理解下:
优点
缺点
微服务技术条目 | 落地技术 |
---|---|
服务开发 | SpringBoot、Spring、SpringMVC等 |
服务配置与管理 | Netfix公司的Archaius、阿里的Diamond等 |
服务注册与发现 | Eureka、Consul、Zookeeper等 |
服务调用 | Rest、PRC、gRPC |
服务熔断器 | Hystrix、Envoy等 |
负载均衡 | Ribbon、Nginx等 |
服务接口调用(客户端调用服务的简化工具) | Fegin等 |
消息队列 | Kafka、RabbitMQ、ActiveMQ等 |
服务配置中心管理 | SpringCloudConfig、Chef等 |
服务路由(API网关) | Zuul、Nacos等 |
服务监控 | Zabbix、Nagios、Metrics、Specatator等 |
全链路追踪 | Zipkin、Brave、Dapper等 |
数据流操作开发包 | SpringCloud Stream(封装与Redis,Rabbit,Kafka等发送接收消息) |
时间消息总栈 | SpringCloud Bus |
服务部署 | Docker、OpenStack、Kubernetes等 |
功能点/服务框架 | Netflix/SpringCloud | Motan | gRPC | Thri t | Dubbo/DubboX |
---|---|---|---|---|---|
功能定位 | 完整的微服务框架 | RPC框架,但整合了ZK或Consul,实现集群环境的基本服务注册发现 | RPC框架 | RPC框架 | 服务框架 |
支持Rest | 是,Ribbon支持多种可拔插的序列号选择 | 否 | 否 | 否 | 否 |
支持RPC | 否 | 是(Hession2) | 是 | 是 | 是 |
支持多语言 | 是(Rest形式) | 否 | 是 | 是 | 否 |
负载均衡 | 是(服务端zuul+客户端Ribbon),zuul-服务,动态路由,云端负载均衡Eureka(针对中间层服务器) | 是(客户端) | 否 | 否 | 是(客户端) |
配置服务 | Netfix Archaius,Spring Cloud Config Server 集中配置 | 是(Zookeeper提供) | 否 | 否 | 否 |
服务调用链监控 | 是(zuul),zuul提供边缘服务,API网关 | 否 | 否 | 否 | 否 |
高可用/容错 | 是(服务端Hystrix+客户端Ribbon) | 是(客户端) | 否 | 否 | 是(客户端) |
典型应用案例 | Netflix | Sina | |||
社区活跃程度 | 高 | 一般 | 高 | 一般 | 2017年后重新开始维护,之前中断了5年 |
学习难度 | 中等 | 低 | 高 | 高 | 低 |
文档丰富程度 | 高 | 一般 | 一般 | 一般 | 高 |
其他 | Spring Cloud Bus为我们的应用程序带来了更多管理端点 | 支持降级 | Netflix内部在开发集成gRPC | IDL定义 | 实践的公司比较多 |
Spring官网:https://spring.io/
这是官网的模块流程图:
SpringCloud 是基于 SpringBoot 的一套微服务解决方案,巧妙地简化了分布式系统基础设施的开发,为开发人员提供了快速构建分布式系统的一些工具,包括配置管理,服务发现,断路器,路由,微代理,事件总线,全局锁,决策竞选,分布式会话等等,他们都可以用 SpringBoot 的开发风格做到一键启动和部署。
Spring Cloud 是分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶。
Dubbo 和 SpringCloud对比:
可以看一下社区活跃度:
https://github.com/dubbo
https://github.com/spring-cloud
对比结果:
Dubbo | SpringCloud | |
---|---|---|
服务注册中心 | Zookeeper | Spring Cloud Netfilx Eureka |
服务调用方式 | RPC | REST API |
服务监控 | Dubbo-monitor | Spring Boot Admin |
断路器 | 不完善 | Spring Cloud Netfilx Hystrix |
服务网关 | 无 | Spring Cloud Netfilx Zuul |
分布式配置 | 无 | Spring Cloud Config |
服务跟踪 | 无 | Spring Cloud Sleuth |
消息总栈 | 无 | Spring Cloud Bus |
数据流 | 无 | Spring Cloud Stream |
批量任务 | 无 | Spring Cloud Task |
最大区别:Spring Cloud 抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式
严格来说,这两种方式各有优劣。虽然从一定程度上来说,后者牺牲了服务调用的性能,但也避免了上面提到的原生RPC带来的问题。而且REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这个优点在当下强调快速演化的微服务环境下,显得更加合适。
总结:二者解决的问题域不一样:Dubbo的定位是一款RPC框架,而SpringCloud的目标是微服务架构下的一站式解决方案。
官网:http://projects.spring.io/spring-cloud/
SpringCloud没有采用数字编号的方式命名版本号,而是采用了伦敦地铁站的名称,同时根据字母表的顺序来对应版本时间顺序,比如最早的Realse版本:Angel,第二个Realse版本:Brixto,然后是Camden、Dalston、Edgware,Hoxton最新的是 SR12 GA通用稳定版。
学习网站:
1. `一个简单的Maven模块结构是这样的:` 2. `` 3. `-- app-parent: 一个父项目(app-parent)聚合了很多子项目(app-util\app-dao\app-web...)` 4. ` |-- pom.xml` 5. ` |` 6. ` |-- app-core` 7. ` ||---- pom.xml` 8. ` |` 9. ` |-- app-web` 10. ` ||---- pom.xml` 11. ` ......`
<modules> <module>springcloud-api</module> <module>springcloud-provider-dept-8001</module> <module>springcloud-consumer-dept-80</module> </modules> <!--打包方式 pom--> <packaging>pom</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <junit.version>4.12</junit.version> <log4j.version>1.2.17</log4j.version> <lombok.version>1.16.18</lombok.version> </properties> <dependencyManagement> <dependencies> <!--spring cloud--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR11</version> <type>pom</type> <scope>import</scope> </dependency> <!--兼容的springboot版本--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.8</version> <type>pom</type> <scope>import</scope> </dependency> <!-- mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.21</version> </dependency> <!--druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.6</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency> <!--日志测试~--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> </dependencies> </dependencyManagement>
父工程为springcloud,其下有多个子mudule,如
springcloud-consumer-dept-80(服务提供者)访问 springcloud-provider-dept-8001(服务消费者) 下的 controller 使用 Restful 方式
服务提供者配置
springcloud-provider-dept-8001 为服务提供者,端口为8001,xml配置如下:
<dependencies> <!--我们需要拿到实体类,所以要配置api module--> <dependency> <groupId>com.lin</groupId> <artifactId>springcloud-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <!--spring-web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--热部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies>
注意上文的 xml, springcloud-provider-dept-8001 的 dao 接口调用 springcloud-api 模块下的 pojo,可使用在 springcloud-provider-dept-8001 的 pom 文件导入 springcloud-api 模块依赖的方式:
<!--引入springcloud-api模块--> <dependency> <groupId>com.lin</groupId> <artifactId>springcloud-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
配置 application.yml:
server: port: 8001 #mybatis mybatis: # 全类名 type-aliases-package: com.lin.springcloud.pojo mapper-locations: classpath:mybatis/mapper/*.xml # 驼峰命名 configuration: map-underscore-to-camel-case: true #spring spring: application: name: spring-cloud-provider-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/spring_cloud_demo01?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 username: root password: 123456
编写 DeptProviderController:
/** * 提供者,提供Restful服务 */ @RequestMapping("/dept") @RestController public class DeptProviderController { @Autowired private DeptService deptService; @PostMapping("/add") public boolean addDept(@RequestBody Dept dept) { return deptService.addDept(dept); } @GetMapping("/queryById/{id}") public Dept queryById(@PathVariable("id") Long id) { return deptService.queryById(id); } }
服务消费者配置
springcloud-consumer-dept-80 为服务消费者,端口为80,pom.xml 配置同服务提供者一样,这里忽略。
编写 DeptConsumerController,调用 DeptProviderController的接口:
/** * 消费者 */ @RequestMapping("/consumer") @RestController public class DeptConsumerController { //提供多种便捷访问远程http服务的方法,简单的Restful服务模板 @Autowired private RestTemplate restTemplate; private static final String REST_URL_PREFIX = "http://localhost:8001"; @GetMapping("/add") public Boolean get(Dept dept) { return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class); } @GetMapping("/queryById/{id}") public Dept get(@PathVariable("id") Long id) { return restTemplate.getForObject(REST_URL_PREFIX + "/dept/queryById/" + id, Dept.class); } }
需要装配 RestTemplate,编写 ConfigBean:
/** * 装配Bean */ @Configuration public class ConfigBean { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
配置完毕,启动 springcloud-provider-dept-8001、springcloud-consumer-dept-80,访问服务消费者端口:
http://localhost/consumer/queryById/1 , 成功访问:
Eureka基本的架构
三大角色
01、springcloud-eureka-7001 模块建立
02、pom.xml 配置:
<!--eureka--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <version>2.2.8.RELEASE</version> </dependency>
03、application.yml 配置:
server: port: 7001 # eureka eureka: instance: hostname: localhost # eureka服务端的实例名称 client: register-with-eureka: false # 表示是否向eureka注册中心注册自己 fetch-registry: false # false则表示自己为注册中心 service-url: # 监控页面 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
查看源码,可以知道 Eureka 的默认端口和访问路径:
04、启动类添加 @EnableEurekaServer 注解:
@SpringBootApplication @EnableEurekaServer //eureka的启动类,可以接受别人注册进来 public class EurekaServer_7001Application { public static void main(String[] args) { SpringApplication.run(EurekaServer_7001Application.class, args); } }
启动成功后访问 http://localhost:7001/ 得到以下页面:
调整之前创建的springlouc-provider-dept-8001
01、导入 eureka 依赖:
<!--eureka--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.2.8.RELEASE</version> </dependency>
02、application 添加 eureka 配置:
#eureka 配置服务注册中心地址 eureka: client: service-url: defaultZone: http://localhost:7001/eureka/
03、启动类添加 @EnableEurekaClient 注解:
@SpringBootApplication //Eureka客户端注解,在服务启动后自动向注册中心注册服务 @EnableEurekaClient public class DeptProvider_8001Application { public static void main(String[] args) { SpringApplication.run(DeptProvider_8001Application.class, args); } }
启动成功后,同样访问 http://localhost:7001/,可以发现服务已经注册进来了:
可以对注册进来的服务重命名,yml 修改配置:
#eureka 配置服务注册中心地址 eureka: client: service-url: defaultZone: http://localhost:7001/eureka/ instance: instance-id: spring-cloud-provider-dept8001 #修改eureka上的描述信息
如果此时停掉springcloud-provider-dept-8001,有可能需要等待 30s, 监控会开启保护机制:
配置关于服务加载的监控信息
spring-cloud-provider-dept-8001 的 pom.xml 中添加依赖:
<!--actuator,完善监控信息--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
application.yml 添加 info配置, info 信息自定义:
# actuator info配置 info: user.name: linxiansheng email: 20271@qq.com
刷新监控页,点击 spring-cloud-provider-dept8001,跳转新页面,返回数据:
某时刻某一个微服务不可用,eureka不会立即清理,依旧会对该微服务的信息进行保存!
详细内容可以参考下这篇博客内容:https://blog.csdn.net/wudiyong22/article/details/80827594
springcloud-provider-dept-8001 即 eureka 客户端,相应 DeptProviderController 添加代码:
//注册进来的微服务,获取一些信息 @Autowired private DiscoveryClient discoveryClient; @GetMapping("/discovery") public Object discovery() { //得到微服务列表的清单 List<String> services = discoveryClient.getServices(); System.out.println("discovery=>services:" + services); //得到一个具体的微服务信息,通过具体的微服务id:spring.application.name List<ServiceInstance> instances = discoveryClient.getInstances("SPRING-CLOUD-PROVIDER-DEPT"); for (ServiceInstance instance : instances) { System.out.println( instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri() + "\t" + instance.getServiceId() ); } return this.discoveryClient; }
启动类添加注解 @EnableDiscoveryClient 注解:
@SpringBootApplication //Eureka客户端注解,在服务启动后自动向注册中心注册服务 @EnableEurekaClient //服务发现 @EnableDiscoveryClient public class DeptProvider_8001Application { public static void main(String[] args) { SpringApplication.run(DeptProvider_8001Application.class, args); } }
结果如下图:
控制台:
7001下注册7002、7003;7002下注册7001、7003等等。
新建 springcloud-eureka-7002、springcloud-eureka-7003 模块
集群后的服务调用示例如下:
1、初始化
1.为 pom.xml 添加依赖 (与 springcloud-eureka-7001 相同)
<dependencies> <!--eureka--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <version>2.2.8.RELEASE</version> </dependency> <!--热部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies>
2.application.yml 配置(与 springcloud-eureka-7001 相同)
server: port: 7002 # eureka eureka: instance: hostname: localhost # eureka服务端的实例名称 client: register-with-eureka: false # 表示是否向eureka注册中心注册自己 fetch-registry: false # false则表示自己为注册中心 service-url: # 监控页面 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
3.主启动类(与 springcloud-eureka-7001 相同)
@SpringBootApplication @EnableEurekaServer //eureka的启动类,可以接受别人注册进来 public class EurekaServer_7002Application { public static void main(String[] args) { SpringApplication.run(EurekaServer_7002Application.class, args); } }
2、集群成员相互关联
配置一些自定义本机名字,找到本机hosts文件并打开,
在hosts文件最后加上,要访问的本机名称,默认是localhost。
在集群中使 springcloud-eureka-7001 关联 springcloud-eureka-7002、springcloud-eureka-7003
完整的 springcloud-eureka-7001下的 application.yml 如下:
server: port: 7001 # eureka eureka: instance: hostname: eureka7001.com # eureka服务端的实例名称 client: register-with-eureka: false # 表示是否向eureka注册中心注册自己 fetch-registry: false # false则表示自己为注册中心 service-url: # 监控页面 # defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # 单机 defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ #集群,7001关联7002、7003
springcloud-eureka-7002、springcloud-eureka-7003 配置方式同理可得。
修改 springcloud-provider-dept-8001下的 yml 配置文件,修改 Eureka 配置:配置服务注册中心地址
#eureka 配置服务注册中心地址 eureka: client: service-url: # 注册中心地址7001、7002、7003 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: spring-cloud-provider-dept8001 #修改eureka上的描述信息
这样模拟集群就搭建好了,就可以把一个项目挂载到三个服务器上了
RDBMS (MySQL\Oracle\sqlServer) ===> ACID
NoSQL (Redis\MongoDB) ===> CAP
著名的CAP理论指出,一个分布式系统不可能同时满足C (一致性) 、A (可用性) 、P (容错性),由于分区容错性P再分布式系统中是必须要保证的,因此我们只能再A和C之间进行权衡。
Zookeeper 保证的是 CP
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接收服务直接down 掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但 zookeeper 会出现这样一种情况,当 master 节点因为网络故障与其他节点失去联系时,剩余节点会重新进行 leader 选举。问题在于,选举 leader的时间太长,30-120s,且选举期间整个 zookeeper 集群是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因为网络问题使得 zookeeper 集群失去 master 节点是较大概率发生的事件,虽然服务最终能够恢复,但是,漫长的选举时间导致注册长期不可用,是不可容忍的。
Eureka 保证的是 AP
Eureka 看明白了这一点,因此在设计时就优先保证可用性。Eureka 各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而 Eureka 的客户端在向某个 Eureka 注册时,如果发现连接失败,则会自动切换至其他节点,只要有一台 Eureka 还在,就能保住注册服务的可用性,只不过查到的信息可能不是最新的,除此之外,Eureka 还有之中自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么 Eureka 就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像 zookeeper 那样使整个注册服务瘫痪
Ribbon是什么?
负载均衡简单分类:
在上文中,springcloud-consumer-dept-80 作为消费方,这里也作为 eureka 的客户端进行 Ribbon 的配置。
eureka 已经集成了 Ribbon,因此不需要再额外导入 Ribbon 的包:
<!--eureka--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.2.8.RELEASE</version> </dependency>
application.yml 配置:
#eureka 配置服务注册中心地址 eureka: client: service-url: #注册中心地址7001、7002、7003 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ #不向注册中心注册自己 register-with-eureka: false instance: instance-id: spring-cloud-provider-dept8001 #修改eureka上的描述信息
启动类 添加 @EnableEurekaClient 注解,表示为 eureka 的客户端:
@SpringBootApplication @EnableEurekaClient public class DeptConsumer_80Application { public static void main(String[] args) { SpringApplication.run(DeptConsumer_80Application.class, args); } }
ConfigBean.java 配置 Ribbon 负载均衡实现 RestTemplate:
/** * 装配Bean */ @Configuration public class ConfigBean { @Bean //Ribbon 客户端负载均衡 @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
修改 DeptConsumerController :
// private static final String REST_URL_PREFIX = "http://localhost:8001"; //Ribbon负载均衡,请求地址是一个变量,应该通过注册中心的服务名来访问 private static final String REST_URL_PREFIX = "http://SPRING-CLOUD-PROVIDER-DEPT";
流程图如下:
1.新建两个服务提供者Moudle:springcloud-provider-dept-8003、springcloud-provider-dept-8002
2.参照 springcloud-provider-dept-8001 依次为另外两个 Moudle 添加 pom.xml 依赖 、resourece 下的 mybatis 和 application.yml 配置,Java代码。
注意三个服务的名称要一致:
#spring spring: application: name: spring-cloud-provider-dept #3个服务名称一致
以及 eureka 上服务的描述信息需要修改:
#eureka 配置服务注册中心地址 eureka: client: service-url: # 注册中心地址7001、7002、7003 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: spring-cloud-provider-dept8003 #修改eureka上的描述信息
3.启动所有服务测试(根据自身电脑配置决定启动服务的个数),访问 http://localhost:7001/ 查看结果
测试访问http://localhost/consumer/dept/queryById/1 这时候随机访问的是服务提供者 8001:
再次访问,访问的是服务提供者 8002:
第三次访问,访问的则是服务提供者 8003:
以上这种每次访问 http://localhost/consumer/queryById/1 随机访问集群中某个服务提供者,这种情况叫做轮询,轮询算法在SpringCloud中可以自定义。
如何切换规则呢?
在springcloud-provider-dept-80模块下的ConfigBean中进行配置,切换使用不同的规则
@Configuration public class ConfigBean { @Bean //Ribbon 客户端负载均衡 @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } /** * * 负载均衡策略 * @return */ @Bean public IRule myRule() { return new RandomRule();//使用随机策略 //return new RoundRobinRule();//使用轮询策略 //return new AvailabilityFilteringRule();//使用轮询策略 //return new RetryRule();//使用轮询策略 } }
关于自定义规则请参考官方文档:https://www.springcloud.cc/spring-cloud-dalston.html#_customizing_the_ribbon_client
Feign 是声明式 Web Service 客户端,它让微服务之间的调用变得更简单,类似 controller 调用 service。SpringCloud 集成了 Ribbon 和 Eureka,可以使用 Feigin 提供负载均衡的 http 客户端。
只需要创建一个接口,然后添加注解即可~
Feign,主要是社区版,大家都习惯面向接口编程。这个是很多开发人员的规范。调用微服务访问两种方法:
Feign能干什么?
Feign 旨在使编写 Java Http 客户端变得更容易
前面在使用 Ribbon + RestTemplate 时,利用 RestTemplate 对 http 请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一个客户端类来包装这些依赖服务的调用。所以,Feign 在此基础上做了进一步的封装,由他来帮助我们定义和实现依赖服务接口的定义,在 Feign 的实现下,我们只需要创建一个接口并使用注解的方式来配置它 (类似以前 Dao 接口上标注 Mapper 注解,现在是一个微服务接口上面标注一个 Feign 注解),即可完成对服务提供方的接口绑定,简化了使用 Spring Cloud Ribbon 时,自动封装服务调用客户端的开发量。
利用 Ribbon 维护了 MicroServiceCloud-Dept 的服务列表信息,并且通过轮询实现了客户端的负载均衡,而与 Ribbon 不同的是,通过 Feign 只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。
1、创建 springcloud-consumer-dept-feign 模块
拷贝 springcloud-consumer-dept-80 模块下的 pom.xml,resource,以及 java 代码到 springcloud-consumer-feign 模块,并添加 feign 依赖:
<!--feign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.2.8.RELEASE</version> </dependency>
修改 DeptConsumerController :
@RequestMapping("/consumer") @RestController public class DeptConsumerController { //调用feign服务 @Autowired private DeptClientService deptClientService; @GetMapping("/add") public Boolean get(Dept dept) { return deptClientService.addDept(dept); } @GetMapping("/queryById/{id}") public Dept get(@PathVariable("id") Long id) { return deptClientService.queryById(id); } }
启动类配置如下:
@SpringBootApplication @EnableEurekaClient //feign客户端注解,并指定要扫描的包以及配置接口DeptClientService @EnableFeignClients(basePackages = {"com.lin.springcloud"}) public class FeignDeptConsumer_80Application { public static void main(String[] args) { SpringApplication.run(FeignDeptConsumer_80Application.class, args); } }
2、改造 springcloud-api 模块
1、pom.xml 同样添加 feign 依赖:
<!--feign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.2.8.RELEASE</version> </dependency>
2、新建 service 包,并新建 DeptClientService.java 接口:
@Component //微服务客户端注解,value:指定微服务的名字,这样就可以使Feign客户端直接找到对应的微服务 @FeignClient(value = "SPRING-CLOUD-PROVIDER-DEPT") public interface DeptClientService { @PostMapping("/dept/add") boolean addDept(Dept dept); @GetMapping("/dept/queryById/{id}") Dept queryById(@PathVariable("id") Long id); }
配置完成,启动 springcloud-dept-consumer-dept-feign ,访问接口成功:
分布式系统面临的问题
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免失败!
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出”,如果扇出的链路上某个微服务的调用响应时间过长,或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几十秒内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以达到单个依赖关系的失败而不影响整个应用程序或系统运行。
Hystrix 是一个应用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix 能够保证在一个依赖出问题的情况下,不会导致整个体系服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控 (类似熔断保险丝) ,向调用方返回一个服务预期的,可处理的备选响应 (FallBack) ,而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
官网资料:https://github.com/Netflix/Hystrix/wiki
当一切正常时,请求流可以如下所示:
当许多后端系统中有一个潜在阻塞服务时,它可以阻止整个用户请求:
随着大容量通信量的增加,单个后端依赖项的潜在性会导致所有服务器上的所有资源在几秒钟内饱和。
应用程序中通过网络或客户端库可能导致网络请求的每个点都是潜在故障的来源。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,从而备份队列、线程和其他系统资源,从而导致更多跨系统的级联故障。
当您使用 Hystrix 包装每个底层依赖项时,如上图所示的架构将更改为类似于下图。每个依赖项彼此隔离,限制在发生延迟时它可以饱和的资源,并覆盖在回退逻辑中,该逻辑决定在依赖项中发生任何类型的故障时做出什么响应:
什么是服务熔断?
熔断机制是赌赢雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。检测到该节点微服务调用响应正常后恢复调用链路。在 SpringCloud 框架里熔断机制通过 Hystrix 实现。Hystrix 会监控微服务间调用的状况,当失败的调用到一定阀值缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是:@HystrixCommand
。
服务熔断解决如下问题:
案例演示
新建 springcloud-provider-dept-hystrix-8001 模块并拷贝 springcloud-provider-dept–8001 内的 pom.xml、resource 和 Java 代码进行初始化并调整。
导入 hystrix 依赖:
<!--hystrix--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>2.2.8.RELEASE</version> </dependency>
application.yml 配置:
server: port: 8001 #mybatis mybatis: # 全类名 type-aliases-package: com.lin.springcloud.pojo mapper-locations: classpath:mybatis/mapper/*.xml # 驼峰命名 configuration: map-underscore-to-camel-case: true #spring spring: application: name: spring-cloud-provider-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/spring_cloud_demo01?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 username: root password: 123456 #eureka 配置服务注册中心地址 eureka: client: service-url: # 注册中心地址7001、7002、7003 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: spring-cloud-provider-dept-hystrix-8001 #修改eureka上的描述信息 # actuator info配置 info: user.name: linxiansheng email: 20271@qq.com
修改 Controller :
/** * 提供者,提供Restful服务 */ @RequestMapping("/dept") @RestController public class DeptProviderController { @Autowired private DeptService deptService; /** * 根据id查询 * 如果根据id查询出现异常,则走hystrixGet这段备选代码 * @param id * @return */ @GetMapping("/queryById/{id}") @HystrixCommand(fallbackMethod = "hystrixGet") public Dept queryById(@PathVariable("id") Long id) { Dept dept = deptService.queryById(id); if (dept == null) { throw new RuntimeException("id=>" + id + "不存在该部门"); } return dept; } //备选方法 public Dept hystrixGet(@PathVariable("id") Long id) { return new Dept().setId(id). setName("id=>" + id + "没有对应的部门") .setDbSource("no this database in MySQL"); } }
启动类添加对熔断的支持注解 @EnableHystrix
@SpringBootApplication//Eureka客户端注解,在服务启动后自动向注册中心注册服务@EnableEurekaClient//服务发现@EnableDiscoveryClient//对服务熔断的支持@EnableHystrixpublic class DeptProviderHystrix_8001Application { public static void main(String[] args) { SpringApplication.run(DeptProviderHystrix_8001Application.class, args); }}
测试:
使用熔断后,当访问一个不存在的id时,前台页展示数据如下:
说明服务熔断成功了。
什么是服务降级?
服务降级是指 当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理,或换种简单的方式处理,从而释放服务器资源以保证核心业务正常运作或高效运作。说白了,就是尽可能的把系统资源让给优先级高的服务。
资源有限,而请求是无限的。如果在并发高峰期,不做服务降级处理,一方面肯定会影响整体服务的性能,严重的话可能会导致宕机某些重要的服务不可用。所以,一般在高峰期,为了保证核心功能服务的可用性,都要对某些服务降级处理。比如当双11活动时,把交易无关的服务统统降级,如查看蚂蚁深林,查看历史订单等等。
服务降级主要用于什么场景呢?当整个微服务架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时,为了保证重要或基本的服务能正常运行,可以将一些 不重要 或 不紧急 的服务或任务进行服务的 延迟使用 或 暂停使用。
降级的方式可以根据业务来,可以延迟服务,比如延迟给用户增加积分,只是放到一个缓存中,等服务平稳之后再执行 ;或者在粒度范围内关闭服务,比如关闭相关文章的推荐。
服务降级需要考虑的问题
自动降级分类
1)超时降级:主要配置好超时时间和超时重试次数和机制,并使用异步机制探测回复情况。
2)失败次数降级:主要是一些不稳定的api,当失败调用次数达到一定阀值自动降级,同样要使用异步机制探测回复情况。
3)故障降级:比如要调用的远程服务挂掉了(网络故障、DNS故障、http服务返回错误的状态码、rpc服务抛出异常),则可以直接降级。降级后的处理方案有:默认值(比如库存服务挂了,返回默认现货)、兜底数据(比如广告挂了,返回提前准备好的一些静态页面)、缓存(之前暂存的一些缓存数据)。
4)限流降级:秒杀或者抢购一些限购商品时,此时可能会因为访问量太大而导致系统崩溃,此时会使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级;降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)。
案例演示
在 springcloud-api 模块下的 service 包中新建降级配置类 DeptClientServiceFallBackFactory.java
/** * 服务降级 */ @Component public class DeptClientServiceFallbackFactory implements FallbackFactory { @Override public DeptClientService create(Throwable throwable) { return new DeptClientService() { @Override public boolean addDept(Dept dept) { return false; } @Override public Dept queryById(Long id) { return new Dept().setId(id) .setName("id=>" + id + "客户端提供了降级的信息,服务已经被关闭") .setDbSource("没有数据"); } }; } }
在 DeptClientService 中指定降级配置类 DeptClientServiceFallBackFactory
@Component //微服务客户端注解,value:指定微服务的名字,这样就可以使Feign客户端直接找到对应的微服务 //fallbackFactory指定降级配置类 @FeignClient(value = "SPRING-CLOUD-PROVIDER-DEPT", fallbackFactory = DeptClientServiceFallbackFactory.class) public interface DeptClientService { @PostMapping("/dept/add") boolean addDept(Dept dept); @GetMapping("/dept/queryById/{id}") Dept queryById(@PathVariable("id") Long id); }
在 springcloud-consumer-dept-feign 模块中开启降级:
server: port: 80 #eureka 配置服务注册中心地址 eureka: client: service-url: #注册中心地址7001、7002、7003 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ #不向注册中心注册自己 register-with-eureka: false instance: instance-id: spring-cloud-provider-feign-dept80 #修改eureka上的描述信息 #开启feign.hystrix,支持服务降级 feign: hystrix: enabled: true
熔断,降级,限流:
限流:限制并发的请求访问量,超过阈值则拒绝;
降级:服务分优先级,牺牲非核心服务(不可用),保证核心服务稳定;从整体负荷考虑;
熔断:依赖的下游服务故障触发熔断,避免引发本系统崩溃;系统自动执行和恢复.
新建 springcloud-consumer-hystrix-dashboard 模块
添加依赖
<dependencies> <!--hystrix-dashboard--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> <version>2.2.8.RELEASE</version> </dependency> <!--实体类--> <dependency> <groupId>com.lin</groupId> <artifactId>springcloud-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--spring-web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--热部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!--eureka--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.2.8.RELEASE</version> </dependency> </dependencies>
配置 application.yml:
server: port: 9001 #eureka 配置服务注册中心地址 eureka: client: service-url: #注册中心地址7001、7002、7003 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ #不向注册中心注册自己 register-with-eureka: false hystrix: dashboard: proxy-stream-allow-list: "*"
启动类:
@SpringBootApplication//开启流量监控@EnableHystrixDashboardpublic class DeptConsumerDashboard_9001Application { public static void main(String[] args) { SpringApplication.run(DeptConsumerDashboard_9001Application.class); }}
接下来配置 springcloud-provider-dept-hystrix-8001 模块,pom.xml 增加依赖:
<!--hystrix-dashboard--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> <version>2.2.8.RELEASE</version> </dependency>
启动类添加如下代码,添加监控:
@SpringBootApplication //Eureka客户端注解,在服务启动后自动向注册中心注册服务 @EnableEurekaClient //服务发现 @EnableDiscoveryClient //对服务熔断的支持 @EnableHystrix public class DeptProviderHystrix_8001Application { public static void main(String[] args) { SpringApplication.run(DeptProviderHystrix_8001Application.class, args); } //增加一个servlet @Bean public ServletRegistrationBean hystrixMetricsStreamServlet() { ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet()); //访问该页面就是监控页面 registrationBean.addUrlMappings("/actuator/hystrix.stream"); return registrationBean; } }
访问:http://localhost:9001/hystrix
进入监控页面:
效果如图:
参数说明:
官方文档:https://www.springcloud.cc/spring-cloud-dalston.html#_router_and_filter_zuul
Zuul 包含了对请求的路由(用来跳转的)和过滤两个最主要功能:
其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础。Zuul 和 Eureka 进行整合,将 Zuul 自身注册为 Eureka 服务治理下的应用,同时从 Eureka 中获得其他服务的消息,也即以后的访问微服务都是通过 Zuul跳转后获得。
注意:Zuul 服务最终还是会注册进 Eureka。
新建 springcloud-zuul 模块,并导入依赖
<dependencies> <!--zuul--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> <version>2.2.8.RELEASE</version> </dependency> <!--hystrix-dashboard--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> <version>2.2.8.RELEASE</version> </dependency> <!--实体类--> <dependency> <groupId>com.lin</groupId> <artifactId>springcloud-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--spring-web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--热部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!--eureka--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.2.8.RELEASE</version> </dependency> </dependencies>
application.yml
server: port: 9527 spring: application: name: spring-cloud-zuul #eureka 配置服务注册中心地址 eureka: client: service-url: #注册中心地址7001、7002、7003 defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: zuul9527.com prefer-ip-address: true # actuator info配置 info: user.name: linxiansheng email: 20271@qq.com #zuul zuul: #配置路由 #原本访问路由为: http://localhost:9527/spring-cloud-provider-dept/dept/queryById/1 #设置完后访问路由为:http://localhost:9527/mydept/dept/queryById/1 routes: mydept.serviceId: spring-cloud-provider-dept mydept.path: /mydept/** # 设置忽略的服务,这里隐藏所有的服务 ignored-services: "*"
启动类:
@SpringBootApplication //// 开启Zuul @EnableZuulProxy public class Zuul_9527Application { public static void main(String[] args) { SpringApplication.run(Zuul_9527Application.class, args); } }
测试,可以看到 zuul 网关已经被注册进来了:
经过 Zuul 路由网关配置后,访问的路由为:http://localhost:9527/mydept/dept/queryById/1
可以看到,微服务名称被替换并隐藏,换成了我们自定义的微服务名称 mydept,这样就做到了对路由访问的加密处理!
分布式系统面临的–配置文件问题
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务,由于每个服务都需要必要的配置信息才能运行,所以一套集中式的,动态的配置管理设施是必不可少的。spring cloud提供了configServer来解决这个问题,我们每一个微服务自己带着一个application.yml,那上百个的配置文件修改起来,令人头疼!
什么是SpringCloud config分布式配置中心?
spring cloud config 为微服务架构中的微服务提供集中化的外部支持,配置服务器为各个不同微服务应用的所有环节提供了一个中心化的外部配置。
spring cloud config 分为服务端和客户端两部分。
服务端也称为 分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密,解密信息等访问接口。
客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用 git 来存储配置信息,这样就有助于对环境配置进行版本管理。并且可用通过git 客户端工具来方便的管理和访问配置内容。
spring cloud config 分布式配置中心能干嘛?
新建 springcloud-config-server-3344 模块,添加依赖
<dependencies> <!--config--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> <version>2.2.8.RELEASE</version> </dependency> <!--spring-web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
application.yml:
server: port: 3344 spring: application: name: spring-cloud-config-server #连接远程仓库 cloud: config: server: git: #https,不是ssh uri: https://gitee.com/xiaoshengstudy/spring-cloud-config-demo.git
启动类:
@SpringBootApplication //开启 config server @EnableConfigServer public class ConfigServer_3344Application { public static void main(String[] args) { SpringApplication.run(ConfigServer_3344Application.class, args); } }
将本地 git 仓库 springcloud-config-demo 文件夹下新建的 application.yml 提交到码云仓库:
springcloud-config-demo 的 application.yml 配置如下:
spring: profiles: active: dev --- spring: profiles: dev application: name: spring-cloud-config-dev --- spring: profiles: test application: name: spring-cloud-config-test
HTTP 服务具有以下格式的资源:
/{application}/{profile}[/{label}] /{application}-{profile}.yml /{label}/{application}-{profile}.yml /{application}-{profile}.properties /{label}/{application}-{profile}.properties
测试访问 http://localhost:3344/application-dev.yml
成功访问配置文件。
将本地 git 仓库 springcloud-config 文件夹下新建的 config-client.yml 提交到码云仓库:
config-client.yml:
spring: profiles: active: dev --- server: port: 8201 #spring 配置 spring: profiles: dev application: name: spring-cloud-provider-dept #eureka 配置服务注册中心地址 eureka: client: service-url: #注册中心地址7001、7002、7003 defaultZone: http://eureka7001.com:7001/eureka/ --- server: port: 8202 #spring 配置 spring: profiles: test application: name: spring-cloud-provider-dept #eureka 配置服务注册中心地址 eureka: client: service-url: # 注册中心地址7001、7002、7003 defaultZone: http://eureka7001.com:7001/eureka/
新建一个 springcloud-config-client-3355 模块,并导入依赖:
<dependencies> <!-- config-client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-client</artifactId> <version>2.2.8.RELEASE</version> </dependency> <!--spring-web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
resources 下创建 application.yml 和 bootstrap.yml 配置文件
bootstrap.yml 是系统级别的配置
#系统级别的配置,用于查找远程资源 spring: cloud: config: #需要从git上读取的资源名称,不用后缀 name: config-client profile: dev label: master uri: http://localhost:3344
application.yml 是用户级别的配置
#用户级别的配置 spring: application: name: spring-cloud-config-clietn-3355
创建 controller 包下的 ConfigClientController.java 用于测试:
@RestController public class ConfigClientController { @Value("${spring.application.name}") private String applicationName; @Value("${eureka.client.service-url.defaultZone}") private String eurekaServer; @Value("${server.port}") private String port; @GetMapping("/config") public String getConfig() { return "applicationName: " + applicationName + "eurekaServer: " + eurekaServer + "port: " + port; } }
启动类:
@SpringBootApplication public class ConfigClient_3355Application { public static void main(String[] args) { SpringApplication.run(ConfigClient_3355Application.class, args); } }
启动服务端ConfigServer_3344Application
再启动客户端 ConfigClient_3355Application
访问:http://localhost:8201/config/
成功读取服务端的配置文件。
spring-cloud-config-demo 新建 config-eureka.yml 并提交到码云仓库:
代码如下:
spring: profiles: active: dev --- server: port: 7001 # spring spring: profiles: dev application: name: spring-cloud-config-eureka # eureka eureka: instance: hostname: eureka7001.com # eureka服务端的实例名称 client: register-with-eureka: false # 表示是否向eureka注册中心注册自己 fetch-registry: false # false则表示自己为注册中心 service-url: # 监控页面 defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ --- server: port: 7001 # spring spring: profiles: test application: name: spring-cloud-config-eureka # eureka eureka: instance: hostname: eureka7001.com # eureka服务端的实例名称 client: register-with-eureka: false # 表示是否向eureka注册中心注册自己 fetch-registry: false # false则表示自己为注册中心 service-url: # 监控页面 defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
新建 springcloud-config-eureka-7001 模块,并将原来的 springcloud-eureka-7001 模块下的内容拷贝的该模块。
1、清空该模块的 application.yml 配置,并新建 bootstrap.yml 连接远程配置:
#系统级别的配置,用于查找远程资源 spring: cloud: config: #需要从git上读取的资源名称,不用后缀 name: config-eureka profile: dev label: master uri: http://localhost:3344
2、在 pom.xml 中添加 spring cloud config 依赖:
<dependencies> <!-- config-client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-client</artifactId> <version>2.2.8.RELEASE</version> </dependency> <!--eureka--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <version>2.2.8.RELEASE</version> </dependency> <!--热部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies>
3、启动类:
@SpringBootApplication @EnableEurekaServer //eureka的启动类,可以接受别人注册进来 public class ConfigEurekaServer_7001Application { public static void main(String[] args) { SpringApplication.run(ConfigEurekaServer_7001Application.class, args); } }
4、测试
第一步:启动 ConfigServer_3344Application,并访问 http://localhost:3344/master/config-eureka-dev.yml 测试:
第二步:启动ConfigEurekaServer_7001Application,访问 http://localhost:7001/ 测试:
说明访问远程配置成功。
到这里 spring cloud 的搭建及基础模块的功能演示到这里结束了,积跬步,行千里。