首页 文章 精选 留言 我的

精选列表

搜索[cloud],共10000篇文章
优秀的个人博客,低调大师

Spring Cloud 应用在 Kubernetes 上的最佳实践 — 高可用(混沌工程)

作者 | 穹谷 导读:从上篇开始,我们进入到了高可用的章节,上篇提到的熔断能力,是历年保障大促当天晚上整个系统不被洪峰流量打垮的法宝。本文将重点介绍为什么我们要做混沌工程以及如何使用 ChaoBlade 工具和 AHAS 平台快速实施混沌工程。 前言 从上篇开始,我们进入到了高可用的章节,上篇提到的熔断能力,是历年保障大促当天晚上整个系统不被洪峰流量打垮的法宝,本篇介绍的措施与熔断有不一样的地方,一个是线上洪峰来临时的保护措施,它更多的是流量低峰或者在专门的演练环境中,针对可能遇见的各类故障,采取演练的手段,来窥探对业务的影响;它的主要目的是让我们自己更加了解自己业务系统的薄弱环节,以便来对症下药增强系统的高可用能力。 为什么需要混沌工程? 任何一个系统都会有未曾可知的故障出现,拿现代工艺已经很好的磁盘来说,有统计数据的磁盘最低的年故障率都可达到 0.39% 。即便是这么底层基础设施,也会有这么高的不确定性。 尤其当下大部分的服务形态都是分布式架构,在分布式系统架构下,服务间的依赖日益复杂,更很难评估单个服务故障对整个系统的影响;并且请求链路长,监控告警的不完善导致发现问题、定位问题难度增大;同时业务和技术迭代快,如何持续保障系统的稳定性和高可用性受到很大的挑战。 1. 云原生系统挑战更大 谈到云原生,可以说云原生是一个理念,主要包含的技术有云设施、容器、微服务、服务网格、Serverless 等技术。云设施指公有云、专有云和混合云等,是云原生系统的基础设施,基础实施的故障可能对整个上层业务系统造成很大影响,所以说云设施的稳定性是非常重要的。 容器服务的挑战可以分两大类:一类是面向 K8s 服务提供商,服务是否稳定;另一类是面向用户,配置的扩缩容规则是否有效,实现的 CRD 是否正确,容器编排是否合理等问题。 分布式服务的挑战主要是复杂性,单个服务的故障很难判断对整个系统的影响;service mesh,sidecar 的服务路由、负载均衡等功能的有效性,还有 sidecar 容器本身的可用性。 一些新兴的部署模式的挑战如 serverless,现在基本上都是函数加事件的形式,资源调度是否有效,而且 serverless 服务提供商屏蔽了一些中间件,你能掌控的是函数这些服务,那么你可以通过混沌工程去验证你函数调用的一些配置,比如超时配置、相关的一些降级策略等这些是否合理。 以上技术都有相同的共性,比如弹性可扩展、松耦合、容错性高、还有一些易于管理,便于观察这些特性。所以说在云原生时代,通过混沌工程可以更有效的推进系统的“云原生”化。 2. 每个职位都需要懂混沌工程 混沌工程是一种思想,它让系统中的每个参与者都学会去考虑一件事情:如果所依赖的某服务中断了服务该怎么办?对于以下四类人群而言,意义尤显突出: 对于架构师来说,可以验证系统架构的容错能力,我们需要面向失败设计的系统,混沌工程的思想就是践行这一原则的方式; 对于开发和运维,可以提高故障的应急效率,实现故障告警、定位、恢复的有效和高效性; 对于测试来说,可以弥补传统测试方法留下的空白,之前的测试方法基本上是从用户的角度去做,而混沌工程是从系统的角度进行测试,降低故障复发率; 对于产品和设计,通过混沌事件查看产品的表现,提升客户使用体验。所以说混沌工程面向的不仅仅是开发、测试,拥有最好的客户体验是每个人的目标,所以实施混沌工程,可以提早发现生产环境上的问题,并且可以以战养战,提升故障应急效率和可以使用体验,逐渐建设高可用的韧性系统。 混沌工程实操 在一次完整的演练流程中,需要先做好计划,对相关的演练计划有一个行为预期;演练相关计划的同时,我们推荐的最佳实践是需要配合有业务的自动化测试,每演练一次需要全方位的跑完自动化测试用例,这样才能全面的了解真正的业务产生时对业务造成的影响: 在上面的图中描述了一次完整的故障演练需要经过的步骤,其中最重要的一步的实践是如何“执行预制混沌实验”?因为这一步需要一个专业的工具,在业内目前最流行的工具是 Netflix 的 Chaos Monkey 和阿里巴巴开源的 ChaosBlade,我们接下来主要是介绍如何使用 ChaosBlade 来完成一次演练。 1. 使用 ChaosBlade 去做 ChaosBlade 是阿里巴巴一款遵循混沌实验模型的混沌实验执行工具,具有场景丰富度高,简单易用等特点,而且扩展场景也特别方便,开源不久就被加入到 CNCF Landspace 中,成为主流的一款混沌工具。目前包含的场景有基础资源、应用服务、容器服务、云资源等。ChaosBlade 下载解压即用,可以通过执行 blade 命令来执行云原生下微服务的演练场景,下面是模拟 Kubernetes 下微服务中数据库调用延迟故障。 2. 使用 AHAS 故障演练平台去做 AHAS 故障演练平台是阿里云对外部用户开放的云产品,使用方式可参考官方文档。其底层的故障注入能力大部分来源于 ChaosBlade 实现,另一部分使用自身小程序扩展实现。AHAS 相比于 ChaosBlade,除了简单易用的白屏操作之外,还实现了上层的演练编排、权限控制、场景管理等,而且还针对微服务新增应用维度演练,简化演练成本,优化演练体验。 结尾 混沌工程是一种主动防御的稳定性手段,体现的是反脆弱的思想,实施混沌工程不能只是把故障制造出来,需要有明确的驱动目标。我们要选择合适的工具和平台,控制演练风险,实现常态化演练。 阿里巴巴内部从最早引入混沌工程解决微服务的依赖问题,到业务服务、云服务稳态验证,进一步升级到公共云、专有云的业务连续性保障,以及在验证云原生系统的稳定性等方面积累了比较丰富的场景和实践经验;这一些经验沉淀我们都通过开源产品以及云产品 AHAS 一一对外输出。 相关文章推荐: 《SpringCloud 应用在 Kubernetes 上的最佳实践 —— 开发篇》 《SpringCloud 应用在 Kubernetes 上的最佳实践 — 部署篇(开发部署)》 《SpringCloud 应用在 Kubernetes 上的最佳实践 — 部署篇(工具部署)》 《SpringCloud 应用在 Kubernetes 上的最佳实践 — 线上发布(可灰度)》 《SpringCloud 应用在 Kubernetes 上的最佳实践 — 诊断(线上联调)》 《SpringCloud 应用在 Kubernetes 上的最佳实践 — 线上发布(可监控)》 《SpringCloud 应用在 Kubernetes 上的最佳实践 — 线上发布(可回滚)》 《SpringCloud 应用在 Kubernetes 上的最佳实践 — 线上发布(优雅上下线)》 《SpringCloud 应用在 Kubernetes 上的最佳实践 — 高可用(熔断)》 “阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

优秀的个人博客,低调大师

Spring Cloud服务提供者与服务消费者怎么运作的?

在微服务中最基本最基本的两个角色是服务提供者与服务消费者。 之前所有代码都在同一个框架的时候,比如Controller调用Service的,直接注入Service bean即可进行调用了。现在做成微服务之后,那么我们就需要有一个工程专门提供相应的服务功能,对应的有相应的工程消费这个功能,这就是服务提供者和服务消费者最基本的概念。 目录大纲: (1)服务提供者与服务消费者概念(2)编码思路(3)服务提供者编码(4)服务消费者编码(5)存在问题 接下来看下具体的内容: (1)服务提供者与服务消费者概念 服务提供者:服务的被调用方(即,为其他服务提供服务的服务); 服务消费者:服务的调用方(即,依赖其他服务的服务); (2)编码思路 这里我们使用最基本的方式实现服务提供者和服务消费者。 (1)两个项目,一个服务提供者,一个是服务消费者; (2)服务提供者从内存数据库H2中查询数据,Controller进行调用获取; (3)服务消费者调用服务提供者的Controller进行获取数据,然后返回给浏览器。 (3)服务提供者编码 新建工程 新建一个提供用户信息的工程,取名为:microservie-provider-user 在pom.xml添加依赖包 Xml代码 <projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.kfit</groupId> <artifactId>ms-provider-user</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>ms-provider-user</name> <url>http://maven.apache.org</url> <!--springbootparent节点,引入这个之后,在下面和springboot相关的就不需要引入版本了;--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.1.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!--web支持:1、webmvc;2、restful;3、jackjson支持;4、aop........--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--内存数据库h2--> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <!--springdatajpa--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> </dependencies> </project> 在src/main/resources下新建schema.sql添加建表语句 创建了一张User表: Sql代码 droptableuserifexists; createtableuser( idbigintgeneratedbydefaultasidentity, usernamevarchar(40), namevarchar(20), ageint(3), balancedecimal(10,2), primarykey(id) ); 在src/main/resources/新建data.sql插入数据 在User表插入几条数据进行测试: Sql代码 insertintouser(id,username,name,age,balance)values(1,'user1','张三',20,100.00); insertintouser(id,username,name,age,balance)values(2,'user2','李四',20,100.00); insertintouser(id,username,name,age,balance)values(3,'user3','王五',20,100.00); insertintouser(id,username,name,age,balance)values(4,'user4','赵六',20,100.00); 创建实体类User Java代码 @JsonIgnoreProperties({"hibernateLazyInitializer","handler"}) @Entity publicclassUserimplementsSerializable{ privatestaticfinallongserialVersionUID=1L; @Id@GeneratedValue privatelongid;//主键. privateStringusername;//用户名. privateStringname;//姓名 privateintage;//年龄. privateBigDecimalbalance;//余额. } 为什么要加@JsonIgnoreProperties呢? 问题在于,使用load方法,您只需要一个代理,而不是真正的对象。代理对象没有已经加载的属性,所以当序列化发生时,没有要序列化的属性。使用get方法,您实际上可以获得真正的对象,这个对象实际上可以被序列化。 具体可以参考文章:https://my.oschina.net/lieefu/blog/680098 创建Dao类UserRepository Java代码 publicinterfaceUserRepositoryextendsJpaRepository<User,Long>{ } 创建Service类UserService Java代码 @Service publicclassUserService{ @Autowired privateUserRepositoryuserRepository; publicUsergetById(longid){ returnuserRepository.getOne(id); } } 创建Controller类UserController Java代码 @RestController publicclassUserController{ @Autowired privateUserServiceuserService; @GetMapping("/user/{id}") publicUsergetById(@PathVariablelongid){ Useruser=userService.getById(id); System.out.println(user); returnuser; } } 在src/main/resources新建application.properties 主要是配置端口号和jpa配置: Properties代码 server.port=7900 spring.jpa.generate-ddl=false spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=none spring.datasource.platform=h2 spring.datasource.schema=classpath:schema.sql spring.datasource.data=classpath:data.sql logging.level.root=INFO logging.level.org.hibernate=INFO 编写启动类 Java代码 @SpringBootApplication publicclassApp{ publicstaticvoidmain(String[]args){ SpringApplication.run(App.class,args); } } 启动App测试 启动访问:http://127.0.0.1:7900/user/1可以在浏览器中看到返回信息: {"id":1,"username":"user1","name":"张三","age":20,"balance":100.00} 到此服务提供者就编写完毕了,这个代码没有什么特别之处,和我们常规代码编写是一样的!。 (4)服务消费者编码 新建工程 新建一个服务消费者项目,取名为:microservice-consumer-movice 在pom.xml添加依赖包 Xml代码 <projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.kfit</groupId> <artifactId>ms-consumer-movice</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>ms-consumer-movice</name> <url>http://maven.apache.org</url> <!--springbootparent节点,引入这个之后,在下面和springboot相关的就不需要引入版本了;--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!--web支持:1、webmvc;2、restful;3、jackjson支持;4、aop........--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project> 新建实体类User Java代码 publicclassUserimplementsSerializable{ privatestaticfinallongserialVersionUID=1L; privatelongid;//主键. privateStringusername;//用户名. privateStringname;//姓名 privateintage;//年龄. privateBigDecimalbalance;//余额. } 新建Controller类MoviceController Java代码 @RestController publicclassMoviceController{ @Autowired privateRestTemplaterestTemplate; @GetMapping("/user/{id}") publicUsergetById(longid){ Stringurl="http://127.0.0.1:7900/user/"+id; returnrestTemplate.getForObject(url,User.class); } } 在src/main/resources新建application.properties 这里只配置了端口号: server.port=7901 新建启动类App.java Java代码 @SpringBootApplication publicclassApp{ @Bean publicRestTemplaterestTemplate(){ returnnewRestTemplate(); } publicstaticvoidmain(String[]args){ SpringApplication.run(App.class,args); } } 这里将RestTemplate进行初始化,交给Spring进行管理。 启动测试 启动访问:http://127.0.0.1:7901/user/2,返回给浏览器信息: {"id":2,"username":"user2","name":"李四","age":20,"balance":100.00} (5)存在问题 该例子简单易理解,但是存在很多的问题,比如: (1)请求地址(http://127.0.0.1:7900/user/)硬编码了; (2)当有多个提供者节点的时候,怎么进行负载,基本想法可以在提供者和消费者中间加一个反向代理,但是服务太多的时候不利于管理。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

用户登录
用户注册