Spring cloud是一个基于Spring Boot实现的服务治理工具包,在微服务架构中用于管理和协调服务的。
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
以下是主要组成部分:
使用微服务架构就可以解决单体项目缺点
我们开发服务的时候,这个服务由多个项目组成,各个项目会根据自身所提供功能的不同具有一个明确的边界。在编译时,这些项目将被打包成为一个个JAR包,并最终合并在一起形成一个WAR包。将该WAR包上传到Web容器中,解压该WAR包,并重新启动服务器。这种将所有的代码及功能都包含在一个WAR包中的项目组织方式被称为Monolith
在项目很小的情况下这种单体应用比较简单,但是随着项目越变越大,代码越来越多。就会存在以下缺点。
①编译难,部署难,测试难
代码量变多,即使更改一行代码,也需花大量时间编译,部署前要编译打包,解压等所以部署难,部署完了还要测试所以测试难。
②技术选择难
在变得越来越大的同时,我们的应用所使用的技术也会变得越来越多。这些技术有些是不兼容的,就比如在一个项目中大范围地混合使用C++和Java几乎是不可能的事情。在这种情况下,我们就需要抛弃对某些不兼容技术的使用,而选择一种不是那么适合的技术来实现特定的功能。
③扩展难
按照Monolith组织的代码将只产生一个包含了所有功能的WAR包,因此在对服务的容量进行扩展的时候,我们只能选择重复地部署这些WAR包来扩展服务能力,而不是仅仅扩展出现系统瓶颈的组成:
是这种扩展方式极大地浪费了资源。就以上图所展示的情况为例:在一个服务中,某个组成的负载已经达到了90%,也就是到了不得不对服务能力进行扩容的时候了。而同一服务的其它三个组成的负载还没有到其处理能力的20%。由于Monolith服务中的各个组成是打包在同一个WAR包中的,因此通过添加一个额外的服务实例虽然可以将需要扩容的组成的负载降低到了45%,但是也使得其它各组成的利用率更为低下。
单体应用中多个模块的负载不均衡,我们扩容高负载的时候,也把低负载的模块也扩容,极大浪费了资源.
简单来说:微服务就是把一个单体项目,拆分为多个微服务,每个微服务可以独立技术选型,独立开发,独立部署,独立运维.并且多个服务相互协调,相互配合,最终完成用户的价值.
微服务架构更加适用于大型项目,虽然刚开始成本高,但是随着项目开展成本会变得越来越低。并且微服务只是一种架构思想,具体可以通过springboot快速开发一个单一服务,但是多个服务协调管理,就需要服务治理框架springcloud等。springcloud是基于springboot
在将应用分解的同时,规避了原本复杂度无止境的积累。每一个微服务专注于单一功能,并通过定义良好的接口清晰表述服务边界。由于体积小、复杂 度低,每个微服务可由一个小规模开发团队完全掌控,易于保持高可维护性和开 发效率。
由于微服务具备独立的运行进程,所以每个微服务也可以独立部署。当某个微服务发生变更时无需编译、部署整个应用。由微服务组成的应用相当于具备一系列可并行的发布流程,使得发布更加高效,同时降低对生产环境所造成的风险,最终缩短应用交付周期。
微服务架构下,技术选型是去中心化的。每个团队可以根据自身服务的需求和行业发展的现状,自由选择最适合的技术栈。由于每个微服务相对简单,故需要对技术栈进行升级时所面临的风险就较低,甚至完全重构一个微服务也是可行的。
当某一组建发生故障时,在单一进程的传统架构下,故障很有可能在进程内扩散,形成应用全局性的不可用。在微服务架构下,故障会被隔离在单个服务中。若设计良好,其他服务可通过重试、平稳退化等机制实现应用层面的容错。
单块架构应用也可以实现横向扩展,就是将整个应用完整的复制到不同的节点。当应用的不同组件在扩展需求上存在差异时,微服务架构便体现出其灵活性,因为每个服务可以根据实际需求独立进行扩展。
中小型项目(功能相对较少) crm 物流 库存管理等中小型项目(功能相对较少) crm 物流 库存管理等
大型项目(功能比较多) 商城 erp等大型项目(功能比较多) 商城 erp等
以maven多模块化的方法搭建
在idea上创建一个普通的maven项目
UTF-8
UTF-8
1.8
Finchley.SR1
2.0.5.RELEASE
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.boot
spring-boot-dependencies
${springboot.version}
pom
import
由于Spring Cloud为服务治理做了一层抽象接口,所以在Spring Cloud应用中可以支持多种不同的服务治理框架,比如:Netflix Eureka、Consul、Zookeeper。在Spring Cloud服务治理抽象层的作用下,我们可以无缝地切换服务治理实现,并且不影响任何其他的服务注册、服务发现、服务调用等逻辑。
Eureka是netflix的一个子模块,也是核心模块之一,Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册与发现对于微服务架构来说是非常重要的,有了服务发现和注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务,而不需要修改服务调用的配置文件了,功能类似于dubbo的注册中心,比如zookeeper。
Eureka采用了C-S的设计架构。Eureka Server作为服务注册功能的服务器,它是服务注册时中心。
而系统中的其他微服务,使用eureka的客户端连接到eureka server并维持心跳连接。这样系统的维护人员就可以通过eureka server来监控系统中各个微服务是否正常运行。SpringCloud的一些其他模块就可以通过eureka server来发现系统中的其他微服务,并执行相关的逻辑。
三大角色:
Eureka server提供服务注册和发现
Eureka Server提供服务注册服务。各个服务提供者节点启动后,会在Eureka Server中进行注册,这样Eureka server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到
Service Provider服务提供方将自身服务注册到Eureka,从而使服务消费方能够找到。
Service Consumer服务消费方从Eureka获取注册服务列表,从而能够消费服务。
Eureka client是一个java客户端,用于简化eureka server的交互,在应用启动后,将会向Eureka Server发送心跳。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表把这个服务节点移除。
在父maven项目下创建子模块
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
resources资源目录下
server:
#端口
port: 7001
eureka:
instance:
#服务注册中心实例的主机名
hostname: localhost
prefer-ip-address: true #显示ip地址
server:
#关闭自我保护机制,防止失效的服务也被一直访问 (开发环境)
enable-self-preservation: false
#该配置可以修改检查失效服务的时间,每隔5s检查失效服务,默认该配置是 60s (开发环境)
eviction-interval-timer-in-ms: 3000
client:
#是否向服务注册中心注册自己
registerWithEureka: false
#是否检索服务
fetchRegistry: false
#服务注册中心的配置内容,指定服务注册中心的位置
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机配置
@SpringBootApplication默认扫描启动类所在的当前包
如果需要指定扫描,需要添加属性@SpringBootApplication(scanBasePackages = “cn.ykf”)
@SpringBootApplication
@EnableEurekaServer ////表示是Eureka的服务端
public class Eureka_RunApp {
public static void main(String[] args) {
SpringApplication.run(Eureka_RunApp.class, args);
}
}
创建子模块
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
resource资源目录下
server:
port: 8001
# 注册服务名称
spring:
application:
name: springcloud-demo-ehr #不要使用下划线
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka #告诉服务提供者要把服务注册到哪儿
instance:
#eureka服务器在接收到最后一个心跳之后等待的时间,然后才能从列表中删除此实例 默认90s(开发环境)
lease-expiration-duration-in-seconds: 2
#eureka客户端需要向eureka服务器发送心跳的频率 默认30s (开发环境)
lease-renewal-interval-in-seconds: 1
@SpringBootApplication默认扫描启动类所在的当前包
如果需要指定扫描,需要添加属性@SpringBootApplication(scanBasePackages = “cn.ykf”)
@SpringBootApplication
@EnableEurekaClient //表示是eureka的客户端
public class UserProviderApplication_8001 {
public static void main(String[] args) {
SpringApplication.run(UserProviderApplication_8001.class);
}
}
需要新建一个model层的User类(略)
@RestController
public class UserController {
@RequestMapping("/getEmp/{id}")
public Object getEmp(@PathVariable("id") Integer id){
User user = new User();
user.setId(id);
user.setName("ykf");
return user;
}
}
1、首先启动注册中心
2、启动服务提供者
3、浏览器地址输入localhost:7001
发现注册中心,有了服务提供者注册应用,即注册成功
4、浏览器地址输入http://localhost:8001/getEmp/1
创建子模块
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
resource资源目录下
server:
port: 9001
# 注册服务名称
spring:
application:
name: springcloud-demo-crm #不要使用下划线
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka #告诉服务提供者要把服务注册到哪儿
#defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka #告诉服务提供者要把服务注册到哪儿,多个用逗号隔开
instance:
#eureka服务器在接收到最后一个心跳之后等待的时间,然后才能从列表中删除此实例 默认90s(开发环境)
lease-expiration-duration-in-seconds: 2
#eureka客户端需要向eureka服务器发送心跳的频率 默认30s (开发环境)
lease-renewal-interval-in-seconds: 1
prefer-ip-address: true # 显示ip地址
@SpringBootApplication //默认扫描当前包
@EnableDiscoveryClient
public class Crm_RunApp {
public static void main(String[] args) {
SpringApplication.run(Crm_RunApp.class, args);
}
}
创建一个类,配置RestTemplate ,必须放在spring可以扫描到的地方
@Configuration //相当于xml的beans标签
public class CfgBean {
@Bean//相当于xml中的bean标签,id为方法名
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
@RestController
public class UserController {
//注入restTemplate
@Autowired
RestTemplate restTemplate;
//restful风格
@RequestMapping("/getEmp/{id}")
public Object getEmp(@PathVariable("id") Integer id){
//调用远程服务 http请求
String url = "http:/http://localhost:8001/getEmp/"+id;
User user = restTemplate.getForObject(url, User.class);
return user;
}
}
输入路径:http://localhost:9001/getEmp/1
通过springboot实现服务提供者,然后再服务消费者以restTemplate以restful的方式完成服务调用。