发表于: 2020-07-29 23:43:07
1 1463
今天完成的事情
1. 看书了解 Spring Cloud 的组件及其功能(完成)
2. 学习 Spring Boot 中 yml 配置文件的应用(完成)
3. Eureka server&client demo(完成)
4. Eureka server 集群(完成)
5. Ribbon 负载均衡(完成)
6. RestTemplate 请求接口(完成)
收获
1. 微服务的常见组件及其功能
微服务具备的功能:
a,服务注册于发现
b,服务负载均衡
c,服务容错
d,服务网关
e,服务配置管理
f,链路追踪
g,实时日志
【服务注册与发现】
服务注册:服务向注册中心注册一个服务实例,服务提供者把自己的服务信息告知注册中心。
服务发现:服务消费者需要另一个服务的时候,服务注册中心能够告知所需要消费服务的实例信息(服务名、ip···)
通常一个服务即是服务提供者也是服务消费者,注册中心需要提供服务健康检测,检查服务是否可用。
一个服务注册以后会间隔向注册中心发送心跳信息,证明自己的服务可用。入伙一个服务超过一定时间没有发送心跳信息那么注册中心就会把服务剔除。
【负载均衡】
为了保证服务高可用,通常使用集群部署。为了解决调用哪个服务的问题引入了负载均衡机制。具体的附在均衡策略可以按需配置。
通常注册中心也会集群部署,zookeeper 就是一种能方便的实现集群部署的注册中心,内部的选举机制可以保证注册服务的高可用。
【服务容错】
微服务框架下的服务非常多,互相之间的调用错综复杂,当一个服务因为某种原因不能及时响应的时候可能会导致大量的请求(包括各种重试)堵塞,严重的时候会导致这些服务的资源消耗殆尽。整个系统都瘫痪,这就是雪崩效应。
为了解决分布式系统的雪崩效应问题,分布式系统引入了【熔断机制】,当一个服务在一定时间内的失败次数大于设定的阈值的时候熔断器生效,所有的请求都会执行快速失败,不执行业务逻辑。
一段时间之后熔断器会通过一部分请求来测试服务是否可用,如果可用则执行熔断器失效,服务恢复,否则继续维持熔断状态。
熔断机制非常重要,常见于解决以下问题:
a,资源隔离:某个 api 故障,直接下线,修复后上线。
b,服务降级:大量的请求涌入,关闭一部分服务,维持服务负载不超过上限,避免负载过高整个服务瘫痪。
c,自我修复:由于网络波动可能导致某些服务短时间不可用,此时熔断机制生效,一段时候后恢复。避免这种因素引发雪崩效应。
【服务网关】
微服务都是通过各种 api 进行通信,一部分 api 不应该暴露给外界,那么服务网关就起到了这种隔离作用。
应用场景:
a,api 资源聚合,统一对外暴露。
b,身份认证、权限认证
c,流量监控,大流量的时候实行服务降级
d,监控功能,日志输出,记录请求
常见的网关组件:zuul,nginx···
【服务配置管理】
每个服务都有很多配置文件,数据库的配置、日志输出··· 大量的服务管理起来非常困难。在微服务的架构中需要统一的配置文件管理机制。
常见的配置文件管理组件:spring cloud config、Diamond、Apollo···
【服务链路追踪】
微服务按照业务划分服务单元,互相之间的调用错综复杂,出现问题很难追踪异常服务的位置。因此我们需要一个服务链路追踪使得服务的调用关系以及异常服务点清晰可见。
常见的链路追踪组件:Dapper、Zipkin、Eagleeye
2. spring cloud
spring cloud 是一个微服务框架,依赖于 spring boot。
【服务注册与发现】Eureka。同时也支持 Consul、zookeeper
【熔断组件】Hystrix
【负载均衡】Ribbon。通常与 Eureka、Zuul、RestTemplate、Feign 配合使用。
【路由网关】Zuul。与 Ribbon 配合可以做到负载均衡,智能路由,也可以进行用户角色与权限的判断,统一日志输出。
以上四个组件由 Netfilx 公司开源,统称 Spring Cloud Netfilx
【服务配置】Spring Cloud Config。Server 向指定地点读取配置,client 统一向 server 读取配置。通常与 Spring Cloud Bus 配合刷新 Client 的配置。
【链路追踪】Spring Cloud Sleush,封装了 Dapper、Zipkin 和 Kibana 等组件。
【消息组件】Spring Cloud Stream,可以实现消息的接收与发送。
简单 Spring Cloud 应用的常见配合 Eureka、Zuul、Config、Auth。
3. 初试 Eureka
多模块项目:注册中心、服务提供者、服务消费者
注册中心需要暴露服务注册地址,启动多个注册中心,注册中心之间会同步服务数据。
只需要在配置文件中配置多个 profiles 然后命令行指定 frofiles 启动。
(yaml 配置文件简洁清晰,但是排版一乱就完蛋)
#---
server:
port: 8761
eureka:
instance:
hostname: peer1
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# defaultZone: http://peer2:8762/eureka/
#---
#server:
# port: 8762
#eureka:
# instance:
# hostname: peer2
# client:
# register-with-eureka: false
# fetch-registry: false
# service-url:
# defaultZone: http://peer1:8761/eureka/
#spring:
# profiles: peer2
这里只配置了两个注册中心,如果是三个或者更多那么 dafaultZone里面填写其他注册中心的地址就好了,用逗号分割。
配置一个 Client 只指向一台 Eureka Server 的时候我们会发现另一台注册中心也会记录到 Client 的信息,这是因为注册中心集群之间同步了服务信息。
当然我们也可以在一个 Client 里面配置多个 Eureka Server,同样使用逗号分割就可以了。
4. Ribbon & Eureka & RestTemplate 负载均衡
RestTemplate 来自 spring web 依赖(我以前都没有用过···)是一个访问第三方 Restful API 的网络请求框架。和其他的 Spring Template (RedisTemplate、JdbcTemplate) 一样致力于将复杂的任务提供一个简单的方法。(长见识,以前从没把这几个 template 想到一块去)
常用 RestTemplate 来消费 Restful 接口(标红的部分是用来处理中文乱码的)。
@GetMapping("/rest")
public String rest(@RequestParam String link){
logger.info("profiles:{} port:{}", profiles, port);
RestTemplate restTemplate= new RestTemplate();
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate.getForObject(link, String.class);
}
上图展示了 RestTemplate 向目标地址发出了一个 get 请求,并且把结果序列化成一个 String 对象。
RestTemplate 还可以把请求到的 xml、jaon 序列化为自定义对象(有了这个感觉不用 RMI 也能做一个土制 rpc 框架了,而且还语言无关。不就是远程调用么,传什么不是传)
结合 RestTemplate 与 Ribbon 实现负载均衡。
a,从注册中心获取服务实例的数据
RestTemplate Bean 上面加一个 @LoadBlanced 注解
@Bean
@LoadBalanced
RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}
加上这个注解之后再使用 RestTemplate 的时候 url 里面就不能写域名了,需要通过【服务名】的方式访问,否则 Ribbon 不知道需要做负载均衡的是什么服务。
@Autowired
private RestTemplate restTemplate;
public String hi(String name) {
String url = "http://eureka-client/hi/";
return restTemplate.getForObject(url + name, String.class);
}
测试了以下貌似这个负载均衡是平均分配的,我部署了两个 Eureka Client,每次刷新都切换了。
然后 @LoadBalanced 这个注解是在 Spring Cloud commons 这个包里面的,但是我还没找到它的处理类和 Ribbon 依赖包之间的关系,不知道怎么实现的,用的什么策略。
太菜了
b,调用者维护服务实例数据
这种方式可以关闭 Eureka Server,在消费者配置文件中配置好 Eureka Client 的地址,直接使用 Ribbon 来做负载均衡。
ribbon:
eureka:
enabled: false
eureka-client:
ribbon:
listOfServers: peer1:8762, peer1:8763
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
server:
port: 8769
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/hi")
public String ribbon(@RequestParam String name) {
ServiceInstance instance = loadBalancerClient.choose("eureka-client");String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/hi/" + name;
RestTemplate restTemplate = new RestTemplate();
return restTemplate.getForObject(url, String.class);
}
还有一种调用方式是 url 里面直接写上配置文件中的服务名,http://eureka-client/hi/name 的方式访问。
这种的话就需要把 RestTemplate 改成 Bean 注入,加上 @LoadBalanced 注解。
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}
@Autowired
private RestTemplate restTemplate;
@GetMapping("/testRibbon")
public String testRibbon() {
ServiceInstance instance = loadBalancerClient.choose("eureka-client");
return instance.getHost() + ":" + instance.getPort();
}
@GetMapping("/hi")
public String ribbon(@RequestParam String name) {
String url = "http://eureka-client/hi/" + name;
return restTemplate.getForObject(url, String.class);
}
配置文件不用改,照样访问。Eureka Server 可以关了,没有关系。
明天的计划
1. Feign 消费者客户端
2. Feign 负载均衡
3. Hystrix 熔断器
评论