android系统定制开发微服务入门:Ribbon与Nacos

文章目录

android系统定制开发微服务入门:与Nacos

一、Ribbon概论

android系统定制开发在有提到过Eurkaandroid系统定制开发具有负载均衡的作用

android系统定制开发负载均衡其实是用一个名为Ribbonandroid系统定制开发的组件实现的

那么Ribbon是什么?

先给Ribbonandroid系统定制开发来个简单的自我介绍,Ribbon是Netflixandroid系统定制开发发布的开源项目,android系统定制开发主要功能是提供客户端android系统定制开发的软件负载均衡算法和服务调用。也就是说Ribbonandroid系统定制开发会自动帮我们基于某种android系统定制开发规则去选择某种服务


二、Ribbon实现原理

我们使用RestTemplate对象只需要访问一个带有对象名称的路径,也就是http://userservice/user/XX,就可以访问到相对应的接口,这其中离不开LoadBalancerInterceptor的帮助,它会去RestTemplate的请求进行拦截,然后从Eureka中获取服务id与端口号,随后利用负载均衡算法得到真实的服务地址信息,替换服务id。

在LoadBalancerInterceptor这个类中,会有一个intercept方法,其拦截了用户的HttpRequest请求,通过调用以下api

  • request.getURI():获取请求uri,也就是 http://user-service/user/8
  • originalUri.getHost():获取uri路径的主机名,其实就是服务id,user-service
  • this.loadBalancer.execute():处理服务id,和用户请求。

获取到了url、主机名、和服务的id,再将这些信息作为参数传到LoadBalancerClient(this.loadBalancer)的execute的方法中

而在LoadBalancerClient的execute方法中可以通过服务id获取到服务列表,并获取合适的服务的端口号,其实现的主要api如下

  • getLoadBalancer(serviceId):根据服务id获取ILoadBalancer,而ILoadBalancer会拿着服务id去eureka中获取服务列表并保存起来。
  • getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个。也就是127.0.0.1:8080

从这里可以知道,负载均衡的实现是在getServer方法中实现的

继续跟进

可以发现这里返回一个rule,那我们就再跟进看看这个rule到底是什么

可以发现,前面传过来的default对应的是RoundRobinRule对象

查询相关资料可以知道,RoundRobinRule对应的是一个轮询的规则,所以这里采用的默认负载均衡规则是轮询

Ribbon的主要流程如下


三、常用的

内置负载均衡规则类规则描述
RoundRobinRule简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
AvailabilityFilteringRule对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit属性进行配置。
WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。
BestAvailableRule忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule随机选择一个可用的服务器。
RetryRule重试机制的选择逻辑

既然有那么多负载均衡策略,那就说明我们可以自己自定义指定某个负载均衡策略

首先,先在OrderApplication类中,定义一个IRule

@Beanpublic IRule randomRule(){	return new RandomRule();}
  • 1
  • 2
  • 3
  • 4

然后再yml文件进行配置

userservice:  ribbon:    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 
  • 1
  • 2
  • 3

四、饥饿加载

Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。

而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

ribbon:  eager-load:    enabled: true    clients: userservice
  • 1
  • 2
  • 3
  • 4

五、注册中心

1、Nacos简介

Nacos与Eureka一样,都是一个注册中心,但是Nacos是阿里巴巴的产品,也是SpringCloud的一个组件。与Eureka相比,Nacos的功能更加丰富,同时在国内也更受欢迎


2、将服务注册到nacos

  • 父工程引入依赖

    <dependency>	<groupId>com.alibaba.cloud</groupId>	<artifactId>spring-cloud-alibaba-dependencies</artifactId>	<version>2.2.6.RELEASE</version>	<type>pom</type>	<scope>import</scope></dependency>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 在子工程引入nacos客服端依赖包

    <!--nacos客户端依赖包--><dependency>	<groupId>com.alibaba.cloud</groupId>	<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
    • 1
    • 2
    • 3
    • 4
    • 5
  • 在对应工程的yml文件配置nacos地址

    spring:  application:    name: orderservice  #orderservice的服务名称  cloud:    nacos:      server-addr: localhost:8848 #nacos地址
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

通过cmd指令打开nacos,先定位到nacos的bin目录,输入以下指令(window指令)打开启动nacos

startup.cmd -m standalone
  • 1

启动之后登录地址http://127.0.0.1:8848/nacos即可

登录账号和密码默认为nacos

在这就能看到我们已经成功将服务注册了


3、服务分级存储模型

上面的示例都是将服务布置在一个集群(机房),但是如果当机房出现天灾人祸的话,这个服务的实例就会都全军覆没,因此为了解决这个问题,可以将一个服务的实例布置在多个集群,以防万一

但是这里需要注意的是,服务的调用一般应该尽可能选择本地的服务,一般不跨集群调用,因为这样的话延迟会比较高

只有当本地集群不可以访问的时候,再访问其他集群


(1)、配置集群

在需要配置集群的服务的yml文件配置以下属性

spring:  application:    name: orderservice  #orderservice的服务名称  cloud:    nacos:      server-addr: localhost:8848      discovery:        cluster-name: HZ
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这当中的cluster-name为集群名称,可以自己自定义

注意:如果是自己本机测试的话,不可以修改集群之后一次性打开一个服务的所有实例,应当先打开一个实例,再改变集群名称,再运行另外一个实例


(2)、配置集群的负载均衡策略

首先安装上面那样配置集群,接着修改使用该集群的服务的yml配置文件

这里order-service服务使用了user-service服务,所以再order-service服务设置

userservice:  ribbon:    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
  • 1
  • 2
  • 3

这里的默认情况下NacosRule是同集群内随机挑选,不会考虑机器的性能问题

但是有些机器比较旧,有些比较新,因此我们一般都是希望服务多调用机器新的服务,小频率调用机器旧的集群。

在nacos中,其为我们提供了权重配置来控制访问频率,权重越大则访问频率越高

在nacos控制台中,打开服务服务列表——》点击详情,就可以看到某个服务的所有实例

点击编辑即可修改权重,权重大小为0-1,支持小数

注意:当权重修改为0的时候,该服务实例不再被调用


4、环境隔离

环境隔离是基于环境隔离的,也就是说,在开发中我们会遇到很多不同的环境,对于这些不同的环境,不同的服务之间是不能访问的,因此我们需要对其进行隔离

Nacos提供了namespace来实现环境隔离功能。

  • nacos中可以有多个namespace
  • namespace下可以有group、service等
  • 不同namespace之间相互隔离,例如不同namespace的服务互相不可见


(1)、创建namespace

在nacos控制台的命名管理,里面新建一个命名空间

下面两个是必填的,第一项不用填,会自动生成

新建完毕之后,就可以得到这样的一串命名空间ID


(2)、配置namespace

使用上述的命名空间id在需要配置的文件的yml配置namespace

这里是在order-service的yml文件配置

spring:  cloud:    nacos:      server-addr: localhost:8848      discovery:        cluster-name: HZ        namespace: 86be35cb-2a01-451f-9978-b6c45e72fb76 # 命名空间,填ID
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

重启服务,即可得到两个环境中有不同的服务


六、Nacos与Eureka的不同

Nacos的服务实例分为两种l类型:

  • 临时实例:如果实例宕机超过一定时间,会从服务列表剔除,默认的类型。

  • 非临时实例:如果实例宕机,不会从服务列表剔除,也可以叫永久实例。

配置一个服务实例为永久实例:

spring:  cloud:    nacos:      discovery:        ephemeral: false # 设置为非临时实例
  • 1
  • 2
  • 3
  • 4
  • 5

Nacos和Eureka整体结构类似,服务注册、服务拉取、心跳等待,但是也存在一些差异:

  • Nacos与eureka的共同点

    • 都支持服务注册和服务拉取
    • 都支持服务提供者心跳方式做健康检测
  • Nacos与Eureka的区别

    • Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
    • 临时实例心跳不正常会被剔除,非临时实例则不会被剔除
    • Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
    • Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式

七、Nacos配置管理

Nacos与Eureka不同,Nacos既可以用来做注册中心,也可以用来做配置管理来使用


1、统一配置管理

在实际开发中,我们也许需要部署很多微服务,但是如果当我们需要修改微服务的某个配置文件的时候,就会需要修改很多,这是极其不方便的,因此nacos为我们提供了一个统一的配置管理

也就是当配置发生改变的时候,nacos会通知微服务告诉它配置改变了,应该从nacos将新的配置拉取下来,实现了配置的热更新


2、在nacos添加配置文件

首先,先在nacos控制中心的配置管理中添加配置

这里的Date ID的命名规则是服务名称+开发环境+后缀(userservice-dev.yaml)

Group的话默认分组即可

配置格式一定要勾选YAML

然后配置内容就可以像在本地的yml文件那样配置,到时候微服务拉取配置下来就和本地的yml合并

注意:项目的核心配置,需要热更新的配置才有放到nacos管理的必要。基本不会变更的一些配置还是保存在微服务本地比较好。


3、从nacos中拉取配置

服务从nacos中拉取配置,需要借助一个spring引入的新配置文件——bootstrap.yaml

这个文件的作用就是会在application.yml先读取bootstrap.yml文件,然后读取里面的nacos配置信息,从nacos的地址拉取特定的配置下来

具体实现过程如下:

首先先引入nacos-config依赖

<!--nacos配置管理依赖--><dependency>    <groupId>com.alibaba.cloud</groupId>    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

然后新建一个bootstrap.yml文件,在里面配置相关信息

这里再user-service中添加bootstrap.yml文件

spring:  application:    name: userservice # 服务名称  profiles:    active: dev #开发环境,这里是dev   cloud:    nacos:      server-addr: localhost:8848 # Nacos地址      config:        file-extension: yaml # 文件后缀名
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这里会根据spring.cloud.nacos.server-addr获取nacos地址,再根据

${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}作为文件id,来读取配置。

这样从nacos中拉取配置下来


4、实现配置的热更新

实现配置的热更新有两种方式

  1. 通过@RefreshScope实现热更新
  2. 通过@ConfigurationProperties解决

(1)方式1

在controller中加入@RefreshScope如下所示

@Slf4j@RestController@RequestMapping("/user")@RefreshScopepublic class UserController {    @Autowired    private UserService userService;    // @Value("${pattern.dateformat}")    // private String dataformat;    @GetMapping("prop")    public PatternProperties properties(){        return patternProperties;    }    @GetMapping("now")    public String now(){        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dataformat));    }    /**     * 路径: /user/110     *     * @param id 用户id     * @return 用户     */    @GetMapping("/{id}")    public User queryById(@PathVariable("id") Long id) {        return userService.queryById(id);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

但是这种方法不常用,一般用另外一种方法


(2)方式2

使用@ConfigurationProperties注解代替@Value注解。

@Data@Component@ConfigurationProperties(prefix = "pattern")public class PatternProperties {    private String dateformat;    private String envShareValue;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
@Slf4j@RestController@RequestMapping("/user")public class UserController {    @Autowired    private UserService userService;    @Autowired    private PatternProperties patternProperties;    @GetMapping("prop")    public PatternProperties properties(){        return patternProperties;    }    @GetMapping("now")    public String now(){        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDateformat()));    }    /**     * 路径: /user/110     *     * @param id 用户id     * @return 用户     */    @GetMapping("/{id}")    public User queryById(@PathVariable("id") Long id) {        return userService.queryById(id);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

这样当我们在nacos修改配置文件的时候,即可实现热更新


5、配置共享

配置共享的实现也很简单,在nacos配置一个服务名+后缀的配置,也就是[spring.application.name].yaml,这个不包含任何环境,所以可以用来做环境共享

不管是dev环境还是test环境,都可以读取其中的配置


6、配置共享的优先级

当nacos、服务本地同时出现相同属性时,优先级有高低之分:


网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发