服务架构种类和各个的优缺点
微服务架构说明
SpringCloud说明
Eureka说明
负载均衡
一、服务架构种类和各个的优缺点
1.种类:单体架构、分布式架构
2.单体架构:一般适用于小型的,访问数据量小,用户群体不多的项目
【例如:学生管理系统、小超市、小公司等】
- 优点:架构简单,部署成本低
- 缺点:高度耦合【维护困难,升级困难】;技术栈受限;扩展性差
3.分布式架构:大型的,用户群体大,访问数据量大的项目
【例如:京东、淘宝】
- 优点:降低耦合;扩展性好;技术栈不受限
- 缺点:服务调用关系复杂;部署成本高;
二、微服务架构说明
1.概述:一种良好的分布式架构方案【将复杂的业务拆分成一个个微小的服务】
- 分布式:各司其职【例如:门童,服务员】
- 集群:一群人干相同的事情【公司里的各部门】
2.优点:高内聚、低耦合【因为是分布式,必然可以降低耦合度】
3.特征:
- 单一职责:拆分粒度小,每一个服务都对应唯一的业务能力
- 自治:团队独立、技术独立、数据独立、独立部署和交付
- 面向服务:服务提供统一标准的接口,与语言和技术无关
- 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题
三、SpringCloud说明
面试:SpringCloud是微服务分布式架构的一站式解决方案,集成了各种优秀微服务功能组件【注册中心、配置中心、服务集群、安全网关】
加强版:SpringCloudAlibaba(国货之光)
接下来就开始学习springcloud的五大组件!!!
3.1注册中心:Eureka
Eureka是属于SpringCloud的功能组件:注册中心的一种实现技术。它只是其中一种,其功能并没有Nacos完美【Nacos后面再详说!!!】,因为Eureka依赖于SpringCloud,但是Nacos依赖于SpringCloudAlibaba
概念:【就上图而言——服务提供者:order-service 服务消费者:user-service】
【1】服务注册:一个微服务既可以是服务的提供者,也可是服务的消费者,对于eureka注册中心来说,所有的微服务都是客户端,而它自己本身才是服务端。所以,所有的微服务都需要将自己的信息注册到eureka-server,这个就叫服务注册
eureka-server中保存的注册信息【服务列表】:服务名称到服务实例地址列表的映射关系【服务名称+ip+端口】,对于注册中心来说:一个服务就是一个实例!
【2】服务拉取:服务消费者根据服务名称,从注册中心拉取实例地址列表,这个就叫做服务拉取 or 服务发现
【3】心跳:防止一些服务出现宕机,排除服务故障的一种措施。每个服务每个一段时间(默认30s)要向注册中心发起请求,注册中心收到请求后才能确定对应的服务是没有问题,如果无法接受到,超过30s就会将该服务的注册信息抹除,这样就无法被拉取!
问题1:order-service如何得知user-service实例地址?
获取地址信息的流程如下:
-
user-service服务实例启动后,将自己的信息注册到eureka-server(Eureka服务端)。这个叫服务注册
-
eureka-server保存服务名称到服务实例地址列表的映射关系
-
order-service根据服务名称,拉取实例地址列表。这个叫服务发现或服务拉取
问题2:order-service如何从多个user-service实例中选择具体的实例?
-
order-service从实例列表中利用负载均衡算法选中一个实例地址
-
向该实例地址发起远程调用
问题3:order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?
-
user-service会每隔一段时间(默认30秒)向eureka-server发起请求,报告自己状态,称为心跳
-
当超过一定时间没有发送心跳时,eureka-server会认为微服务实例故障,将该实例从服务列表中剔除
-
order-service拉取服务时,就能将故障实例排除了
3.2面试的时候要学会画上面那个图,并且组织语言简要说明!!!
- 搭建注册中心
- 将服务都注册都注册到eureka上
- 拉取服务列表,通过负载均衡策略选择具体服务进行调用
3.3搭建注册中心
【1】在父工程下创建一个eureka-server的子模块
【2】引入 注册中心服务端 的依赖,eureka依赖于springcloud
注意:这里和下面第6步的区别,这里注入服务端,下面是注入客户端
<!--eureka注册中心依赖于springcloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
【3】在该模块的启动类上加一个注解:@EnableEurekaServer,开启eureka的注册中心的功能
【4】编写application.yml配置文件
server: #注册中心自己也是一个服务,设置服务端口
port: 10086
spring:
application:
name: eureka-server #注册中心是springcloud的组件之一,为注册中心服务端取名
eureka:
#【所有服务对于注册中心来说都是客户端,这个就是注册中心对它的客户端的配置】
client:#配置客户端
service-url:
#所有服务向【注册中心】注册信息的默认地址
defaultZone: http://127.0.0.1:10086/eureka
# 注册中心自己也是一个服务,不需要注册自己【只有将信息注册到注册中心的 服务 才是客户端】
register-with-eureka: false
#不拉取本注册中心:eureka服务中的服务信息【上面都配置没有注册,何来的拉取呢】
fetch-registry: false
【5】启动服务,访问: http://127.0.0.1:10086
【6】服务注册——所有服务 向注册中心里 注册信息
6.1在user-service,order-service服务模块中 引入 注册中心客户端 的依赖【所有微服务对于注册中心来说都是客户端】
<!--引入eureka注册中心客户端的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
6.2 编写application.yml配置文件
#注册中心eureka 配置
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
instance: # 所有注册的服务都是一个实例【名称+ip+port】
ip-address: 127.0.0.1 # 配置服务器ip地址
prefer-ip-address: true # 更倾向于使用ip,而不是host名
instance-id: ${eureka.instance.ip-address}:${server.port} # 自定义实例的id
6.3开启多个服务实例【开启多个服务提供者:userservice】
【7】服务发现——服务消费者从注册中心拉取服务提供者
7.1 同6.1。上面的6.1已经说过了,所有的微服务对于注册中心来说都是客户端,所以即使是服务消费者也要导入 注册中心客户端的依赖!
7.2 编写application.yml配置文件【和服务提供者差不多,不需要配置ip信息,因为它是要拉取别人的注册信息的。】
#eureka注册中心 配置
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka #根据服务提供者的配置确定
#以下这些是不同于上面user-service的配置,
#因为作为服务消费者,完全没必要配置的像服务提供者那样的详细信息
/*
instance: # 所有注册的服务都是一个实例【名称+ip+port】
ip-address: 127.0.0.1 # 配置服务器ip地址
prefer-ip-address: true # 更倾向于使用ip,而不是host名
instance-id: ${eureka.instance.ip-address}:${server.port} # 自定义实例的id
*/
#饥饿加载【懒加载】
ribbon:
eager-load:
enabled: true
clients: userservice
7.3开始拉取
【1】在服务消费者的启动类中配置RestTemplate的Bean,并加上@LoadBalanced注解(负载均衡)
@Bean
@LoadBalanced//负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
【2】修改拉取服务中的url,用服务名来替换ip和端口
四、负载均衡
远离流程图:
负载均衡=负载均衡策略
我们之前搭建注册中心时,仅仅 通过一个注解@EnableEurekaServer,开启了负载均衡。底层涉及的反射如上图!
4.1面试时要学会画出上面的大致流程图,并且组织语言做出以下简略说明!
-
拦截我们的RestTemplate请求http://userservice/user/1
-
RibbonLoadBalancerClient会从请求url中获取服务名称,也就是user-service
-
DynamicServerListLoadBalancer根据user-service到eureka拉取服务列表
-
eureka返回列表,localhost:8081、localhost:8082
-
IRule利用内置负载均衡规则,从列表中选择一个,例如localhost:8081
-
RibbonLoadBalancerClient修改请求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,发起真实请求
4.2负载均衡策略
总共有以下几种,不需要强制记忆!【只记三个:轮询、Zone(就近原则)、随机】
要明白下面几点:
【1】负载均衡策略,一般不会改变,就是默认的轮询:RounDRobinRule【下表的第一个】
【2】随机的负载均衡会有安全隐患:里面的算法涉及一个while的判空循环,可能会出现死循环
【3】ZoneAvoidanceRule:是一种遵守”就近“原则的轮询!
4.3如何自定义配置负载均衡?【如果不配置,就是默认的轮询!】
在服务消费者的启动类中定义一个新的Rule,返回的对象就是负载均衡类的对象【遵循上表】
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
//order 远程拉取 user 【调用RestTemplate 才能实现远程拉取】
@Bean
@LoadBalanced//负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
//自定义负载均衡——随机
@Bean
public IRule randomRule(){
return new RandomRule();
}
}