一. 应用架构
1.单体架构
单体架构:所有业务代码,写在一个项目中
优点:
- 易于开发 :架构简单,技术成本低
- 易于测试 :所有功能在一个项目,方便测试
- 易于部署 :一个Tomcat就可以实现部署,简单方便
缺点:
- 代码臃肿
- 业务复杂
- 并发处理差
2.分布式与SOA
分布式与SOA:按照业务拆分成多个子系统,使用多个服务器部署
优点:
- 解决并发和代码臃肿
- 把业务服务化(把功能暴露处理,直接调用),业务调用更加方便,功能重组
缺点:
- 运维成本高
- 技术成本高
- 硬件成本高
3.微服务
微服务:基于SOA/分布式 , 系统拆分成多个服务,每个服务的独立的负责一部分功能,有自己的数据库,服务之间项目调用
优点:
- 解决高并发
- 解决代码臃肿
- 单个服务业务简单,扩展性强,对敏捷开发支持友好
缺点:
- 运维成本高
- 技术成本高
- 硬件成本高
- 服务调用网络开销
- 事务处理麻烦
4.集群
集群:指的是把应用进行复制多个相同的应用一起工作提高作业能力,多个应用做的是相同的事情
作用:处理高并发,高可用
5.负载均衡
负载均衡:把请求分发到服务应用集群,做了集群的地方一定要做负载均衡
算法:算法:随机,轮询等
二:SpringCloud
1.SpringCloud基本概念
SpringCloud基本概念:Spring Cloud是一系列框架的有序集合。简化了分布式系统基础设施的开发,都可以用Spring Boot的开发风格做到一键启动和部署。通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。有了SpringCloud之后,让微服务架构的落地变得更简单。
2.SpringCloud常用组件
Netflix Eureka
当我们的微服务过多的时候,管理服务的通信地址是一个非常麻烦的事情,Eureka就是用来管理微服务的通信地址清单的,有了Eureka之后我们通过服务的名字就能实现服务的调用。
Netflix Ribbon\Feign : 客户端负载均衡
Ribbon和Feign都是客户端负载均衡器,它的作用是在服务发生调用的时候帮我们将请求按照某种规则分发到多个目标服务器上,简单理解就是用来解决微服务之间的通信问题。
Netflix Hystrix :断路器
微服务的调用是非常复杂的,有的时候一个请求需要很多的微服务共同完成,那么一旦某个服务发生故障,导致整个调用链上的微服务全都出现异常,甚至导致整个微服务架构瘫痪。Hystrix就是用来解决微服务故障,保护微服务安全的组件。
Netflix Zuul : 服务网关
zuul作为服务网关,我们可以把它看作是微服务的大门,所有的请求都需要经过zuul之后才能到达目标服务,根据这一特性,我们可以把微服务公共的是事情交给zuul统一处理,如:用户鉴权,请求监控等。
Spring Cloud Config :分布式配置
微服务架构中的服务实例非常的多,服务的配置文件分散在每个服务中,每次修改服务的配置文件和重新服务实例都是一个很麻烦的工作,Spring Cloud Config作为分布式配置管理中心就是用来统一的管理服务的配置文件。
Spring Cloud Bus : 消息总线
消息总线是在微服务中给各个微服务广播消息的一个组件,我们使用消息总线构建一个消息中心,其他微服务来接入到消息中心,当消息总线发起消息,接入的微服务都可以收到消息从而进行消费。
Spring Cloud sleuth :微服务链路追踪
当我们的应用采用微服务架构之后,后台可能有几十个甚至几百个服务在支撑,一个请求请求可能需要多次的服务调用最后才能完成,链路追踪的作用就是来监控维护之间的调用关系,让程序员方便直观的感受到一个请求经历了哪些微服务,以及服务的请求时间,是否有异常等。
三:Eureka注册中心
1.Eureka的工作原理
1.1服务注册
客户端启动向服务端注册(服务名,IP,端口等),服务端维护一个服务注册表
1.2服务发现
客户端30s/次拉取注册表缓存到本地,服务调用的时候,去注册表中根据服务名查找服务实例,拿到通信地址,发起HTTP请求
1.3服务续约
客户端30s/次向服务端发送心跳续约请求,报告自己的健康状态,超过3次续约失败,会被剔除
1.4服务下线
微服务(EurekaClient)关闭服务前向注册中心发送下线请求,注册中心(EurekaServer)接受到下线请求负责将该服务实例从注册列表剔除
2.EurekaServer实战
1.导入依赖
<!--spring-cloud-starter-netflix-eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
2.启动类
/**
* 注册中心启动类
*
* @EnableEurekaServer : 开启EurekaServer服务端
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication1010 {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication1010.class);
}
}
3.yml配置
server:
port: 1010 #端口
eureka:
instance:
hostname: localhost #主机
client: #客户端配置
registerWithEureka: false #EurekaServer自己不要注册到EurekaServer自己 ,只有EurekaClient才注册
fetchRegistry: false #EurekaServer不要拉取服务的通信地址列表 ,只有EurekaClient才拉取地址列表
serviceUrl: #注册中心的注册地址
defaultZone: http://localhost:1010/eureka/ #http://${eureka.instance.hostname}:${server.port}/eureka/
server:
enable-self-preservation: false #关闭自我保护警告
3.EurekaClient(user,order服务)
1.导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.启动类
/**
* 用户的启动类
*
* @EnableEurekaClient: 标记该应用是 Eureka客户端
*/
@SpringBootApplication
@EnableEurekaClient
public class UserServerApplication1030 {
public static void main(String[] args) {
SpringApplication.run(UserServerApplication1030.class);
}
}
/**
* 订单的启动类
*
* @EnableEurekaClient: 标记该应用是 Eureka客户端
*/
@SpringBootApplication
@EnableEurekaClient
public class OrderServerApplication1020 {
public static void main(String[] args) {
SpringApplication.run(OrderServerApplication1020.class);
}
//配置一个RestTemplate ,Spring封装的一个机遇Restful风格的http客户端 工具
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
3.yml配置
#注册到EurekaServer
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1010/eureka/
instance:
instance-id: order-server-1020
spring:
application:
name: order-server
server:
port: 1020
#注册到EurekaServer
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1010/eureka/
instance:
instance-id: user-server-1030
spring:
application:
name: user-server
server:
port: 1030
四.RestTemplate服务通信
1.搭建公共的实体类模块
写一个User对象
2.用户服务
编写controller,返回一个User
3.订单服务
编写一个controller,远程调用User
1.定义Bean : RestTemplate
2.注入RestTemplate.getForObject(url , 类型)
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/order/{id}")
public User getById(@PathVariable("id")Long id){
//发送http请求
return restTemplate.getForObject("http://USER-SERVER/user/"+id, User.class);
}
}
五.Ribbon客户端负载均衡
1.用户服务集群
修改端口,修改实例ID, 启动多个
读取端口:@Value("${server.port}") ,用来区分
2.订单整合Ribbon
1.导入Ribbon的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>