跳到主要内容

· 阅读需 44 分钟
Dylan Li

概述

Spring Cloud Alibaba 衍生自 Spring Cloud Community, 其已经通过 Spring 认证并被收录在 官方网站 中。根据阿里的介绍,这套微服务解决方案中包括了一部分开源组件和一部分阿里云商业化产品。这次我们要上手的将只包含开源部分,对于一些未提供的能力,比如网关服务,将结合 Spring Cloud Community 提供补充,上手过程中会基于本人目前的经验,对其中相关知识点做出简单总结。

围绕开源生态,探究如何将这套微服务方案落地到生产中,是本篇的核心目的。作为初探篇,将着重于应用代码侧的接入,很多设计是结合现有比较常见的开发生产习惯决定的。对于其中的各类中间件环境如何实现 HA,本篇将暂不探讨,有兴趣的可以从本篇末尾获得查看官方建议的链接。

主要功能

  • 流控与服务降级(Flow Control and service degradation):默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
  • 服务注册与发现(Service registration and discovery):适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 负载均衡的支持。
  • 分布式配置管理(Distributed configuration):支持分布式系统中的外部化配置,配置更改时自动刷新。
  • 事件驱动(Event-driven):基于分布式消息实现构建高性能事件驱动的微服务体系。
  • 分布式事务(Distributed Transaction):高效并且对业务零侵入地解决分布式事务问题。
  • 微服务网关(Microservices Gateway):为整套内部微服务链路提供一个可靠且高性能的对外网关,并配套流控、路由、鉴权等能力。
  • 服务间远程过程调用(Remote Procedure Call):提供可靠方便的RPC框架,实现各个系统间就像在调用本地程序一样地调用远程服务。

· 阅读需 4 分钟
Dylan Li

在使用 Elastic Stack v7.4 实现统一的日志系统时,我们希望在 Filebeat 增加像 hostip 这样的参数来将宿主机的 IP 带到日志采集流中。比如这样配置:

- type: log
enabled: true
paths:
- /path/to/your/logs/your-serviceid.log
name: "your-serviceid-log"
multiline.pattern: '^[[:space:]]|^Caused by:|^<|^{|^}'
multiline.negate: false
multiline.match: after
ignore_older: 24h
fields_under_root: true
fields:
serviceid: your-serviceid
hostip: your-hostip

your-hostip 替换为当前宿主机的 IP,然后启动 filebeat 服务即可实现最初的目的。但是这样静态配置的方式还不够优雅,如果每台宿主机的配置文件中存在多组上述配置,在每一组配置中都去手动指定 IP 将会成一个繁琐而无味的工作。

换种思路,如果我们在 /etc/profile 文件中添加 HOST_IP 环境变量,并将值设置为宿主机的 IP,然后尝试重启获取一下,效果如何,我们将配置变更一下:

- type: log
enabled: true
paths:
- /path/to/your/logs/your-serviceid.log
name: "your-serviceid-log"
multiline.pattern: '^[[:space:]]|^Caused by:|^<|^{|^}'
multiline.negate: false
multiline.match: after
ignore_older: 24h
fields_under_root: true
fields:
serviceid: your-serviceid
hostip: "${HOST_IP}"

令人失落的是,我们发现使用这种方案会导致 filebeat 进程无法重启,原因出在它是通过 systemd 启动的,默认情况下系统的环境变量只有通过 pam 方式登录的用户才能读取到,但是 systemd 是不会进行登录的,所以就不能直接读取到系统的环境变量。该如何解决呢?

· 阅读需 6 分钟
Dylan Li

原生 JVM 进程的优雅退出 - ShutdownHook

下面一段代码是最常用的一种优雅关闭实现,使用 Runtime.getRuntime().addShutdownHook() 可以向 JVM Runtime 注册一条 Hook Thread 实例,用于执行我们的优雅关闭逻辑, 值得注意的是,这个 Thread 实例并不会立刻被调度执行。 当我们从 OS 层面向 JVM 进程传递某些 Signal(信号)后,这个 Hook 线程才会被运行。


public class ShutdownHookExample {

private static volatile boolean running = true;

public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Shutdown Hook is activated");
//close resources...
//change running signal to false.
running = false;
}
}));
System.out.println("The Java Virtual Machine is running!");
while (running) {
//jvm is running.
}
//when running signal is false, main thread will println this line.
System.out.println("The Java Virtual Machine shut down gracefully");
}
}

那么前面所说的 Signal 到底是什么呢?

· 阅读需 10 分钟
Dylan Li

正则表达式常常被认为是一种现用现取的工具,开发者会忽视其潜在的场景和应用。实际上,几乎所有的开发语言均对其进行了差异化的实现,基于这一点,它被广泛应用于数据校验、 数据处理等场景。 从某种意义上说,正则表达式已经不是一种现用现取的工具,而是每个开发者必须要具备的一项基础素质。

应用场景

在开发API时判断请求参数中的手机号是否合法,使用数据爬虫爬取网页中某个标签下的数据,对敏感数据进行检测与处理,采集日志时根据格式提取关键信息等,这些场景都需要使用正则表达式来提高 处理的效率。概括来说主要分为两方面:字符串格式校验字符串提取

字符串格式校验

一次性判断一整个字符串是否符合某种格式。比如用^[0-9]+$来校验字符串是否只包含数字,用^[a-zA-Z0-9]+@gmail\.com$来校验是否是谷歌邮箱等。

字符串提取

根据某种格式从一段字符串中提取出符合要求的字串。比如使用[a-z]+hey, welcome to 中国里提取出所有的英文单词:hey、welcome和to。