Clay 的技术空间

用进废退 | 艺不压身

大纲

服务雪崩效应

服务雪崩概述

微服务之间进行 RPC 或者 HTTP 调用时,一般都会设置 调用超时失败重试 等机制来确保服务的成功执行,这看上去很美好,但如果不考虑服务的熔断和限流,它就是造成服务雪崩的元凶。假设有两个访问量比较大的服务 A 和 B,这两个服务分别依赖 C 和 D,其中 C 和 D 服务都依赖 E 服务(如下图),这就是所谓的 扇出。A 和 B 不断地调用 C 和 D,处理客户请求和返回需要的数据;当 E 服务不能提供服务的时候,C 和 D 的 超时重试机制 会被执行;由于新的请求不断的产生,会导致 C 和 D 对 E 服务的调用大量的积压,产生大量的调用等待和重试调用,会慢慢耗尽 C 和 D 的系统资源(CPU 或者内存等),然后 C 和 D 服务跟着也挂掉。A 和 B 服务会重复 C 和 D 的遭遇,导致系统资源耗尽,然后服务也挂掉了,最终整个服务都不可访问,造成了服务雪崩。

阅读全文 »

大纲

OpenFeign 介绍

Feign 的概述

在使用 Spring Cloud 开发微服务应用时,各个服务提供者都是以 HTTP 接口的形式对外提供服务,因此在服务消费者调用服务提供者时,底层通过 HTTP Client 的方式访问。此时可以使用 JDK 原生的 URLConnection、Apache 的 HTTP Client、Netty 的异步 HTTP Client 或者 Spring 的 RestTemplate 去实现服务间的调用。但是最方便、最优雅的方式是通过 Feign 进行服务间的调用。Feign 是由 Netflix 开发的一个声明式的 Web 服务客户端,它的出现使开发 Web 服务客户端变得很简单。Feign 同时也是一款声明式、模板化的 HTTP 客户端。更多介绍可参考:Feign 项目

OpenFeign 的概述

Spring Cloud OpenFeign 对 Feign 进行了二次封装,使得在 Spring Cloud 中使用 Feign 的时候,可以做到使用 HTTP 请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程访问,更感知不到在访问 HTTP 请求。Spring Cloud OpenFeign 增强了 Feign 的功能,使 Feign 有限支持 Spring MVC 的注解,如 @RequestMapping 等。OpenFeign 的 @FeignClient 注解可以解析 Spring MVC 的 @RequestMapping 注解下的接口,并通过 AOP 中的动态代理来产生实现类,在实现类中做负载均衡并调用其他服务,同时默认集成了 Ribbon 与 Hystrix。OpenFeign 基本上就是当前微服务之间调用的事实标准。更多介绍可参考:Spring Cloud OpenFeign 项目Spring Cloud OpenFeign 官方文档Spring Cloud OpenFeign 官方中文教程

阅读全文 »

Spring Boot 配置

邮件发送失败问题

在本地开发环境测试,Spring Boot 能够正常发送邮件,但部署到阿里云 ECS 服务器以后,一直没有收到邮件,部分关键日志信息如下:

1
2
3
4
5
6
7
8
org.springframework.mail.MailSendException: Mail server connection failed; nested exception is com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.163.com, 25; timeout -1;
nested exception is:
java.net.ConnectException: 连接超时 (Connection timed out). Failed messages: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.163.com, 25; timeout -1;
nested exception is:
java.net.ConnectException: 连接超时 (Connection timed out)
at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:447)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:322)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:311)

从现有情况看,跟程序运行环境有关,查看相关资料,发现在阿里云 ECS 服务器上,默认禁用了 25 端口,所以在通过 25 端口去连接邮件服务器时,无法连上,就报超时了。官方建议使用 465 端口,而 456 端口是 SSL 协议的,所以不仅要换端口,还需要进行 SSL 协议替换。下面是在 application.properties 进行的邮件发送相关配置,经过这样配置后,在阿里 ECS 上就能够正常发送邮件了

阅读全文 »

大纲

Ribbon 介绍

Ribbon 是什么

Ribbon 是 Netflix 公司开发的一个负载均衡组件,诞生于 2013 年 1 月,一直是 Netflix 活跃度较高的项目,由 Pivotal 公司将其整合进 Spring Cloud 生态。Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,通过 Spring Cloud 的封装,可以轻松地将面向服务的 REST 模板请求自动转换成客户端负载均衡的服务调用。 此外,Ribbon 拥有丰富的负载均衡策略、重试机制、支持多协议的异步与响应式模型、容错、缓存与批次处理等功能。Ribbon 虽然只是一个工具类框架,它不像服务注册中心、配置中心、API 网关那样需要独立部署,但是它几乎存在于每一个 Spring Cloud 构建的微服务和基础设施中。 因为微服务间的调用,API 网关的请求转发等内容实际上都是通过 Ribbon 来实现的,Feign、Zuul 已经集成了 Ribbon,更多介绍可参考:Ribbon 项目Ribbon 官方英文文档Spring Cloud Ribbon 官方中文文档

Ribbon 与负载均衡

负载均衡(Load Balance),即利用特定方式将流量分摊到多个操作单元上的一种手段,它对系统吞吐量与系统处理能力有着质的提升,当今极少企业没有用到负载均衡器或是负载均衡策略。常见的负载均衡实现有 Nginx 与 LVS,且不管它们的使用方式,工作在什么层次,本质还是对流量的疏导。业界对于负载均衡有不少分类,最常见的有软负载与硬负载,代表产品是 Nginx 与 F5;还有一组分类最能体现出 Ribbon 与传统负载均衡的差别,那就是集中式负载均衡与进程内负载均衡。集中式负载均衡指位于因特网与服务提供者之间,并负责把网络请求转发到各个提供单位,这时候 Nginx 与 F5 就可以归为一类,也可以称是服务端负载均衡。进程内负载均衡是指从一个实例库选取一个实例进行流量导入,在微服务的范畴内,实例库一般存储在 Zookeeper、Eureka、Consul、etcd 这样的注册中心,而此时的负载均衡器就是类似 Ribbon 的 IPC(Inter-Process Communication,进程间通信)组件,因此进程内负载均衡也叫做客户端负载均衡。

阅读全文 »

BigDecimal 的概述

Java 在 java.math 包中提供了 API 类 BigDecimal,用于对超过 16 位有效位的数进行精确的运算。双精度浮点型变量 double 可以处理 16 位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。在一般情况下,对于那些不需要准确计算精度的数字,可以直接使用 Float 和 Double 处理,但是 Double.valueOf(String)Float.valueOf(String) 会丢失精度。所以在开发中,如果需要高精度的计算结果,则必须使用 BigDecimal 类来操作数据。BigDecimal 所创建的是对象,因此不能使用传统的 -×÷ 等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是 BigDecimal 的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。

阅读全文 »

错误与异常

在 Java 中所有的错误 (Error) 和异常 (Exception) 都继承了同一个父类 Throwable,它们的关系如下:

  • Error (错误):是指程序无法处理的错误,表示应用程序运行时遇到比较严重的问题。大多数错误与开发者执行的操作无关,而表示在代码运行时 JVM 出现了的问题。
  • Exception (异常):是指在程序运行时由于程序处理逻辑上的错误而导致程序中断的一种指令流。通俗地说,就是代码存在逻辑错误(Bug)。
  • 上述两者的区别:错误无法被处理,异常可以被程序自身捕获并处理
阅读全文 »