restTemplate存在问题?
- 在consumer中,我们把url地址硬编码到了代码中,不方便后期维护
- consumer需要记忆user-service的地址,如果出现变更,可能得不到通知,地址将失效
- consumer不清楚user-service的状态,服务宕机也不知道
- user-service只有1台服务,不具备高可用性
- 即便user-service形成集群,consumer还需自己实现负载均衡
其实上面说的问题,概括一下就是分布式服务必然要面临的问题:
- 服务管理
- 如何自动注册和发现
- 如何实现状态监管
- 如何实现动态路由
- 服务如何实现负载均衡
- 服务如何解决容灾问题
- 服务如何实现统一配置
Eureka注册中心
基本架构

- Eureka本身也是一个微服务,就是服务注册中心(可以是一个集群),对外暴露自己的地址
- 服务生产者向Eureka注册自己地址及服务
- 服务消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新
- 心跳(续约):提供者定期向注册中心汇报自己的状态
案例基本步骤
SpringCloud版本Finchley.SR1;
在子工程中建立一个微服务
1.引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

2.编写启动类
除了常规的启动注解外,还需要添加一个
@EnableEurekaServer表名其Eureka服务身份

3.在yaml文件中指定好eureka的端口
tips:
Eureka也是一个服务,所以自身也可能挂,所以自身也是client,集群内部也会相互注册。如果仅有一个Eureka服务,自己给自己regiest。 
3.1 参数类型是一个map,key表示zone,value表示地址,地址后面要加上/eureka
3.2 本服务类型需要命一个名字 配置在spring-application-name
4 服务方注册服务
4.1在其他需要注册的服务中,引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-start-netflix-eureka-client</artifactId>
</dependency>
4.2 在启动类中添加注册的注解
推荐用@EnableDiscoveryClient这个注解,因为EnableEurekaClient的兼容性受限制只有Eureka注册中心支持。
4.3 配置
服务名及eureka的url

5 调用方调用服务
5.1 引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
5.2启动类中加注解进行注册
@EnableDiscoveryClient
无论是服务提供方还是消费,都是Eureka的客户端。

5.3 配置
配置与服务提供一致。
5.4 调用服务
使用DiscoveryClient对象,获取服务实例。返回类型是一个list。之后再讨论负载均衡的问题。

根据restTemplate参数规则拼接url
6 高级功能
6.1 EurekaServer可以有多个同时存在形成集群,然后相互注册,
A中有BC ,B中有AC,C中有AB。
同一份代码两份实例,端口不同。

实例启动之后,Eureka中的所有被注册的服务会共享。
服务的客户端,需要在配置的eurekaserver-url中写入两份value。
如果服务本身不想注册自己,配置register-with-eureka:false

其他重要参数
- renew(心跳),lease-renewal-interval-in-seconds=30 默认
- 过期时长,lease-expiration-duration-in-seconds=90 默认
- 修改显示实例格式 instance-id:${hostname} + ${spring.application.name} + ${server.port} 默认
- 失效剔除时长 eviction-interval-timer-in-ms:60000 默认,单位ms
- 自我保护 意思是如果心跳丢包率超过15%,可能是网络等原因,进入自我保护状态,暂时会关闭失效剔除。
eureka:
server:
enable-self-preservation: false # 关闭自我保护模式(缺省为打开)
eviction-interval-timer-in-ms: 1000 # 扫描失效服务的间隔时间(缺省为60*1000ms)
负载均衡器 Ribbon
基本策略
- 随机
- 轮询
- 哈希
案例
1. 启动第二台UserServer,修改其端口号防止冲突

2. 引入依赖
调用服务的主体 引入Ribbon依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
- 复杂的方法:调用的时候使用RibbonLoadBalancerClient类的实例 choose默认逻辑是轮询。
获得instance之后再拼接url

- 简单的方法
在启动类中加入注解@LoadBalanced
加在RestTemplate身上
Ribbon内置的拦截器会拦截RestTemplate请求 解析出真实的访问url,默认逻辑是轮询。


改变策略,需要手动配置,没有编译器提示,根是服务名
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule```

默认轮询挺好的
重试机制
因为Eureka的服务列表不是实时更新,所以可能导致拉取出的服务有问题,因此Spring Cloud 整合了Spring Retry 来增强RestTemplate的重试能力,当一次服务调用失败后,不会立即抛出一次,而是再次重试另一个服务。
只需要两步
1.引入依赖
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
2.配置:
spring:
cloud:
loadbalancer:
retry:
enabled: true # 开启Spring Cloud的重试功能
user-service:
ribbon:
ConnectTimeout: 250 # Ribbon的连接超时时间
ReadTimeout: 1000 # Ribbon的数据读取超时时间
OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
MaxAutoRetries: 1 # 对当前实例的重试次数
本文指出restTemplate存在硬编码、服务管理不便等问题,介绍了Eureka注册中心的基本架构、案例步骤及高级功能,包括服务注册、发现、集群配置等。还阐述了负载均衡器Ribbon的基本策略、使用案例,以及Spring Cloud整合Spring Retry增强RestTemplate重试能力的方法。

3657

被折叠的 条评论
为什么被折叠?



