认识微服务
微服务是分布式架构的一种实现方式,是一种良好的架构设计方案,它包含以下几个特点:
- 单一职责:拆分粒度小,每个服务对应一个功能业务,避免重复开发。
- 面向服务:对外暴露业务接口。
- 自治:团队独立、技术独立、数据独立、部署独立。
- 隔离性强:服务在调用中需要做好隔离、容错、降级、避免出现级联问题。
缺点也很明显,更加复杂的架构设计,运维,监控业务是否宕机,部署成本和难度大大增加。
微服务结构主要分为服务网关、服务集群、注册中心和配置中心。
服务集群很好理解,就是我们针对业务实现的请求集群,里面包含了很多的业务逻辑实现,方便用户使用服务,和负载均衡的实现。
服务网关用于对用户访问服务集群的路由设置,用于分发指定路由。
注册中心用于注册服务集群中不同地点分区的服务端的业务暴露接口的地址,以便于不同业务的整合。
配置中心用于管理整个项目的配置信息,方便后期维护管理。
Dubbo | SpringCloud | SpringCloudAlibaba | |
---|---|---|---|
注册中心 | zookeeper、Redis | Eureka、Consul | Nacos、Eureka |
服务远程调用 | Dubbo协议 | Feign(http协议) | Dubbo、Feign |
配置中心 | 无 | SpringCloudConfig | SpringCloudConfig ,Nacos |
服务网关 | 无 | SpringCloudGateway、Zuul | SpringCloudGateway、Zuul |
服务监控和防护 | dubbo-admin,功能弱 | Hystix | Sentinel |
微服务远程调用
微服务的远程调用其实和我们以前实现的前后端分离的数据访问情况一致,我们只需要发送一个Http请求到服务端,即可获取到对应的数据信息。这里我们需要使用Spring给我提供的RestTemplate类,我们先将RestTemplate类注入Spring容器,接着我们就可以通过自动注入获取到RestTemplate实例,然后通过提供对应业务的url,以及我们需要的实体字节码类,我们就可以获取到想要的数据了。
http请求做远程调用和语言无关,只需要知道对方的ip、端口号、接口路径、请求参数即可获得需要的数据信息。
注册中心Eureka
首先针对注册中心,我们需要了解一个小的知识点,消费者和提供者,这里的消费者就是服务的使用方,提供者顾名思义就是服务的承办方。
比如如果服务A需要服务B的一个业务,那么服务A就是消费者,服务B就是提供者,当然也会出现连续调用的情况,服务A调用服务B,服务B调用服务C,这时,相对于不同的服务,服务B就有拥有不同的身份。
那么在实际应用中,消费者如何获取提供者的地址信息,以及如果有很多个提供者,消费者如何进行业务选择,当出现服务宕机,消费者如何才能知道哪个服务是可以获取到数据的。
这些内容就需要我们的Eureka来进行实现与解决了。首先,服务提供者和消费者都会将自己的信息发送到注册中心去,通过注册中心保存自己的服务接口等信息,这时候党消费者若要调用远程服务的某个功能,就会去注册中心中查询需要的信息,注册中心就可以把数据返回给消费者。
同时服务提供者会以30s的时间间隔向注册中心发送心跳续约,如果注册中心超时没有收到提供者的续约申请,就会从自己的信息注册表中删除对应提供者的信息,这样消费者在访问的时候就无法获取到宕机的业务的数据,也就不会产生失败的情况。针对于业务的选择,消费者可以设置负载均衡算法来进行适当的任务分配,即可保证不发生业务的混乱。
Eureka简单搭建流程
非常简单的三步走:
- 建立项目,引入eureka-server依赖
- 在启动类上添加@EnableEurekaServer注解
- 在application.yml中配置eureka地址信息,同时不要忘记注册自己,在搭建多集群的时候需要互相注册以便信息通信。
以上的在注册中心的搭建,接下来我们要对消费者和提供者进行注册:
- 在消费者A服务中引入spring-cloud-starter-netflix-eureka-client依赖
- 在application.yml文件中注册本服务(包含服务名称与eureka地址)
- 在提供者A服务中同样引入spring-cloud-starter-netflix-eureka-client依赖
- 在application.yml文件中注册本服务(包含服务名称与eureka地址)
现在我们就可以通过服务名称来代替原来的ip进行服务拉取了。与此同时,我们要对消费者A中设置负载均衡注解@LoadBalanced标记在我们注入的RestTemplate上方。
Ribbon负载均衡
这里我们就如下图所示了,不再详细描述。
很明显这里的IRule就是我们的负载均衡策略,我们通过查看这个接口的实现类就可以发现有哪些负载均衡的算法了。
这里每种算法我们就不一一叙述,有兴趣的可以查阅官方文档,对每一种算法进行详细的了解。
如果我们要使用不同的负载均衡算法,这里提供两种方案,第一个就是代码的形式,我们在启动类中设置我们希望的负载均衡算法的实现类,我们可以直接new一个IRule的实现类即可。
第二个就是配置文件的方式配置,我们在application.yml文件中配置如下设置:
userservice:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalance.RandomRule # 负载均衡规则
Nacos注册中心
我们使用Nacos的主要原因我感觉应该就是,它是中文的!!!
安装很简单,网上也有很多教程,这里我们就不再叙述。
主要是我们要将服务注册到Nacos中:
- 首先在父工程中添加spring-cloud-alibaba的管理依赖
- 注释掉原来的eureka依赖
- 在我们需要的服务中同时添加nacos客户端的依赖spring-cloud-starter-alibaba-nacos-discovery
- 注销服务中application.yml文件中的eureka地址,添加nacos地址
spring:
cloud:
nacos:
server-addr: localhost:8848
Nacos服务分级存储模型
nacos分级存储模型
- 一级是服务,例如userservice服务名称
- 二级是集群,例如上海,杭州
- 三级是实例,例如杭州机场某一台部署了userservice的服务器
设置实例的集群属性:修改application.yml文件,添加spring.cloud.nacos.discovery.cluster-name属性即可。
同时在消费者端设置负载均衡IRule为NacosRule,这个规则优先会寻找和自己同集群的服务:
userservice:
ribbon:
NFLoadBalanceRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
NacosRule负载均衡策略
- 优先选择同集群服务实例列表
- 本地集群找不到提供者,才会去其他集群寻找,并且提出警告
- 确定了可用实例列表后,再采用随机负载均衡挑选实例
权重负载均衡
实际部署中会出现这种场景:
- 服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求
Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高。在Nacos控制台中我们就可以修改对应的权限比重,权重设置小,访问的频率就会大大降低。
实例权重控制
- Nacos控制台可以设置实例的权重值,0~1之间
- 同集群内的多个实例,权重越高被访问的频率越高
- 权重设置为0则完全不会被访问
环境隔离
为了保护服务存储和数据存储,nacos注册中心设计了一个名为namespace的定义,用来做最外层的隔离。
在nacos的控制台中我们可以创建命名空间,而要在命名空间内分配对应的服务,需要我们向代码中添加命名空间的ID,这样我们重启服务就可以在新的命名空间内部看到服务了。
Eureka和Nacos的对比
Eureka在服务提供者中只有一种心跳检测,就是服务提供者向注册中心定始发送的心跳数据。而Nacos则是针对于服务提供者的不同属性,区分为了临时实例和非临时实例。临时实例中,需要服务提供者自己定时去向注册中心发送心跳数据。非临时实例中,则是注册中心主动向服务提供者询问状态。临时实例如果状态不正常就会被注册中心删除,而非临时实例则会保留。
同时在消费者层面,Eureka是定始向服务器发起询问,从而更新自己的缓存池。Nacos则是主动向消费者push自己的状态列表,可以更快的更新实时变化的数据信息。