俗话说,活到老,学到老。我们总是在学习中不断进步。微策略软件技术公司秉承的就是这个原则,浓厚的技术氛围,实用的技术分享,在这里你可以享受到各种各样的属于技术分享的盛宴。每周四,笔者所在的RESTful API和Architect组都有大组内的技术分享和读书会活动,分享的豆瓣高分技术书包括但不限于:《设计数据密集型应用Designing data-intensive applications》,《重构改善既有代码的设计》,《大话设计模式》…… 受此氛围的影响,笔者将自己学习的微服务技术知识整理成篇,与大家进行分享。至于为什么分享微服务相关的技术,很简单一个字“火”呀,如果要在诸多热门云计算技术中找出一个最火的,那非微服务莫属。
什么是微服务
>>>>
微服务 (Microservices) 是一种软件架构风格,它是以专注于单一责任与功能的小型功能区块 (Small Building Blocks) 为基础,利用模块化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关 (Language-Independent/Language agnostic) 的 API 集相互通信。
微服务的起源是由 Peter Rodgers 博士于 2005 年度云计算博览会提出的微 Web 服务 (Micro-Web-Service) 开始,Juval Löwy 则是与他有类似的前导想法,将类别变成细粒服务 (granular services),以作为 Microsoft 下一阶段的软件架构,其核心想法是让服务是由类似 Unix 管道的访问方式使用,而且复杂的服务背后是使用简单 URI 来开放接口,任何服务,任何细粒都能被开放 (exposed)。这个设计在 HP 的实验室被实现,具有改变复杂软件系统的强大力量。
2014年,Martin Fowler 与 James Lewis 共同提出了微服务的概念,定义了微服务是由以单一应用程序构成的小服务,自己拥有自己的行程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 HTTP API 通信。同时服务会使用最小规模的集中管理 (例如 Docker) 能力,服务可以用不同的编程语言与数据库等组件实现。
>>>>
简单的理解:
微服务架构的系统是一个分布式的系统,按业务进行划分为独立的服务单元,解决单体系统的不足,同时也满足越来越复杂的业务需求。
>>>>
每个服务独立存在,所以可以单独部署,不用每次发布某个功能都经历一次全服务发布。
遵循单一功能原则,服务之间可以通过RESTFUL或者RPC调用,功能解藕
“细粒度” 的高可扩展性,每个服务都可以单独扩展,单独负载均衡
去中心化,尽可能地实现 “自服务”
有利于简化单独的开发测试以及部署,对开发团队友好
>>>>
微服务缺点
服务的可用性和维护性高度依赖于服务治理,如果治理得不好将会是灾难
某些服务可能造成性能瓶颈,某些服务的宕机可能导致很多服务受影响
服务配置繁琐
Spring Cloud构建微服务的优势
>>>>
微服务框架对比
功能点/服务框架 |
Netflix/SpringCloud |
Motan |
gRPC |
Thrift |
Dubbo/Dubbox |
功能定位 |
完整的微服务框架 |
RPC框架但整合了ZK或者Consul,实现集群环境的基本服务注册/发现 |
RPC框架 |
RPC框架 |
服务框架 |
是否支持Rest |
是,Ribbon支持多种可插拔的序列化选择 |
否 |
否 |
否 |
否 |
是否支持RPC |
否 |
是(Hession2) |
是 |
是 |
是 |
是否支持多语言 |
是 |
否 |
是 |
是 |
否 |
服务注册/发现 |
是(Eureka) Eureka服务注册表,Karyon服务端框架支持服务自注册和健康检查 |
是(zookeeper/consul) |
否 |
否 |
是 |
负载均衡 |
是(服务器zuul+客户端Ribbon) zuul-服务,动态路由, 云端负载均衡, Eureka(针对中间层服务) |
是(客户端) |
否 |
否 |
是(客户端) |
配置服务 |
NetflixArchaius SpringCloudConfigServer集中配置 |
是(zookeeper提供) |
否 |
否 |
否 |
服务调用链监控 |
是(zuul) Zuul提供边缘服务,API网关 |
否 |
否 |
否 |
否 |
高可用/容错 |
是(服务器Hystrix+客户端Ribbon) |
是(客户端) |
否 |
否 |
是(客户端) |
典型应用案例 |
Netflix |
Sina |
|||
社区活跃程度 |
高 |
一般 |
高 |
一般 |
2012年停止维护,2017年7月以后开始维护 |
学习难度 |
中等 |
低 |
高 |
高 |
低 |
文档丰富度 |
高 |
一般 |
一般 |
一般 |
高 |
其他 |
SpringCloudBus为我们的应用程序带来了更多管理端点 |
支持降级 |
Netflix内部在开发集成gRPC |
IDL定义 |
实践的公司比较多 |
Spring Cloud提供构建微服务的解决方案
微服务条目 |
Spring CloudT提供与集成的技术 |
服务开发 |
Spring Boot, Spring, Spring MVC |
服务配置与管理 |
Netflix公司的Archaius |
服务注册与发现 |
Eureka、Zookeeper |
服务调用 |
REST |
服务熔断器 |
Hystrix |
负载均衡 |
Ribbon |
服务接口调用(客户端调用服务的简化工具) |
Feign |
消息队列 |
Kafka、RabbitMQ、ActiveMQ等 |
服务配置中心管理 |
SpringCloudConfig |
服务路由(API网关) |
Zuul |
服务监控 |
Hystrix-Dashboard |
全链路追踪 |
Zipkin+Sleuth |
服务部署 |
Docker、OpenStack、Kubernetes等 |
数据流操作开发包 |
SpringCloud Stream(封装与Redis,Rabbit,Kafka等发送接收消息) |
事件消息总线 |
SpringCloud Bus |
服务注册与发现
>>>>
服务注册与发现架构
>>>>
Application Service 就相当于本书中的服务提供者(用户微服务),Application Client就相当于本书中的服务消费者(电影微服务);
Make Remote Call,可以简单理解为调用RESTful的接口;
us-east-1c、us-east-1d等是zone,它们都属于us-east-1这个region;
Eureka包含两个组件:Eureka Server 和 Eureka Client。
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client是一个Java客户端,用于简化与Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。
在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
Eureka Server之间将会通过复制的方式完成数据的同步。
Eureka还提供了客户端缓存的机制,即使所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。
综上,Eureka通过心跳检测、健康检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。
>>>>
1. 引入第三方依赖
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server
2. 配置文件application.properties
server.port = 6868
# 是否需要将当前应用注册到注册中心
eureka.client.registerWithEureka = false
# 是否需要从注册中心获取注册信息
eureka.client.fetchRegistry = false
# 配置eurekaserver的url地址
eureka.client.serviceUrl.defaultZone = http://127.0.0.1:${server.port}/eureka
3. 在SpringBoot启动类中使用eureka注解’@EnableEurekaServer’
4. 启动eureka server,访问eureka server主页http://localhost:6868/
>>>>
笔者做了一个简单的eureka的演示项目:
https://github.com/wanghuixia/SpringCloudMicroserviceQuicklyStart
负载均衡
Spring Cloud继承了Netflix的Ribbon, 因此可以使用Ribbon来实现负债均衡。
>>>>
1) RoundRobinRule: 轮询
2) RandomRule: 随机
3) AvailabilityFilteringRule: 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问
4) WeightedResponseTimeRule: 根据平均响应时间计算所有服务的权重,响应时间越快的服务权重越大被选中的概率越高,刚启动时如果信息不足,则使用RoundRobinRule策略,等统计信息足够,会切换到WeightedResponseTimeRule
5) RetryRule:会先按照RoundRobinRule的策略获取服务,如果获取服务失败则在制定的时间内会进行重试,获取可用的服务
6) BestAvailableRule: 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
7) ZoneAvoidanceRule: 复合判断server所在区域的性能和server的可用性选择服务器,在没有zone的情况下,类似于轮询
>>>>
https://github.com/Netflix/ribbon/tree/master/ribbon-loadbalancer/src/main/java/com/netflix/loadbalancer
>>>>
1. 继承ribbon提供的接口
“AbstractLoadBalanceRule”
2. 简单一个自定义的负载均衡策略:
public class CustomLoadBalancer extends AbstractLoadBalancerRule {
private int total = 0;
private int index = 0;
/**
* Randomly choose from all living servers
*/
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
if (Thread.interrupted()) {
return null;
}
List upList = lb.getReachableServers() ;
List allList = lb.getAllServers() ;
int serverCount = allList.size();
if (serverCount == 0) {
/*
* No servers. End regardless of pass, because subsequent passes
* only get more restrictive.
*/
return null;
}
//custom load balance rule
if (total >= 4) {
total = 0;
index++;
if (index >= upList.size()) {
index = 0;
}
}
total++;//count
server = upList.get(index);
if (server == null) {
/*
* The only time this should happen is if the server list were
* somehow trimmed. This is a transient condition. Retry after
* yielding.
*/
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
// Shouldn't actually happen.. but must be transient or a bug.
server = null;
Thread.yield();
}
return server;
}
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount);
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
>>>>
笔者做了一个简单的ribbon的演示项目:
https://github.com/wanghuixia/SpringCloudMicroserviceQuicklyStart
了解更多微策略最新动态,行业资讯以及程序员日常
请长按二维码关注微我们的公众号