微服务实践四: 配置管理

微服务实践四: 配置管理

配置涵盖程序运行的环境,程序依赖的基础资源地址,程序的行为等。

需求

  • 根据环境读取配置
  • 方便更新配置
  • 基础数据格式为listmap等,常见的配置格式是JSONYAMLXML
Read more

微服务实践三: 服务编排

物理机部署

传统发布流程(以Java spring boot为例)

  • 编译jar包
  • 分发到服务器A,B,C
  • 服务启动,监听到指定端口
  • 配置负载均衡到已启动服务端口
  • 服务发布成功

关于服务更新,为了实现滚动更新,可以让LB绑定的服务逐渐更新

传统更新流程

  • 编译jar包
  • 分发到服务器A,B,C
  • 将服务器A从LB上解绑,更新服务器A上的服务
  • 启动服务,通过健康检查和QA之后,将服务器A绑定到LB上
  • 继续更新服务器B和C
  • 服务完全更新成功

拓容流程

  • 新增机器节点
  • 启动jar包
  • 将新节点注册到LB上

特点

  • 单机端口有限,同一个服务如果在同一个服务器更新,需要不同的端口
  • 动态更新LB
  • 拓容成本高

服务化部署(这里以kubernetes为例)

k8s发布流程

  • 构建docker镜像
  • 创建deployment和service,可以限制服务的CPU、Memory等资源,k8s寻找空闲节点启动服务
  • 更新iptables将物理机上指定端口路由到VIP(虚拟服务IP)
  • 绑定物理机端口到LB

k8s更新流程

  • 构建docker镜像
  • 更新deployment和service,k8s更新某个pod
  • 轮流更新pod,直到所有pod更新完成

k8s拓容

  • 寻找空闲节点启动服务,直到达到指定数量

特点

  • 几乎无物理端口限制(k8s需要物理端口作为转发,默认为30000+,数量有限)
  • 服务间通信,可以使用serviceName或者服务的VIP进行访问,内网访问更方便
  • 虚拟化物理机资源,隔离物理资源的细节,资源控制如拓容、服务资源限制方便

Kubernetes vs Docker swarm

  • 稳定性上,k8s上基于iptables的网络路由比docker swarm的网络更加稳定
  • 配置性上,k8s比docker swarm要复杂,swarm采用manager-worker架构,由manager调度worker,docker 1.12以上对于swarm原生支持,方便启动集群,不过k8s在新版本之后也越来越易于配置
  • 管理系统上,swarm比k8s的UI界面更友好,操作性更强

微服务架构下的应用

  • 外部访问可以暴露gateway到LB上,外部通过访问LB进行访问
  • 使用k8s或者swarm,服务间通信可以使用serviceName进行访问,也可以利用容器的IP,使用服务注册进行服务查询
  • 自动拓容,当检测到服务的CPU和内存利用率升高,通过水平拓展,增加服务节点;服务压力减少后,逐渐减少服务节点数量

微服务实践二: 服务容错与降级

保证系统能稳定地运行在生产环境是第一要务,就算是服务质量下降,只要仍在工作,那就是万幸。

常见服务问题

  1. 服务超时
    依赖的第三方服务因为某种不可抗力超时了?数据库慢查询拖垮了整个数据库?

  2. 服务错误
    某个服务挂了?

  3. 服务负载高
    突然陡增的访问量?

解决方法

  1. 限时
    针对服务超时,可以通过超时控制保证接口的返回,可以通过设置超时时间为1s,尽快返回结果,因为大多数情况下,接口超时一方面影响用户体验,一方面可能是由于后端依赖出现了问题,如负载过高,机器故障等。某个互联网公司曾经说,当系统故障时,fail fast。

  2. fallback
    有些情况下,即使服务出错,对用户而言,也希望是透明的,无感的,设置一些fallback,做一些服务降级,保证用户的体验,即使这个服务实际上是挂掉的,返回内容是空的或者是旧的,在此故障期间,程序员能赶紧修复,对用户几乎没有造成不良体验。

  3. 电路熔断
    这里的电路熔断是对于后端服务的保护,当错误、超时、负载上升到一定的高度,那么负载再高下去,对后端来说肯定是无法承受,好像和电路熔断一样,这三个因素超过了阈值,客户端就可以停止对后端服务的调用,这个保护的措施,帮助了运维人员能迅速通过增加机器和优化系统,帮助系统度过难关。

工具

Hystrix能保护客户端,服务降级,它的dashboard上有一句标语,defend your app,确实,当后端程序能对异常,超时,错误等进行处理,那么客户端能获得的数据能更加稳定统一,同时它也是对后端服务的保护,hystrix有上述的电路熔断机制和用户可以自定义fallback,对服务限时等功能。

hystrix运行流程可见How it works
How-it-works

以构建一个对内部RPC调用的HystrixCommand为例:

  1. 构建一个HystrixCommand用于RPC调用,设置超时时间为1s,fallback为返回空数据
  2. 如果缓存打开,结果优先从缓存中获取
  3. 如果电路被熔断,尝试fallback
  4. 如果并发量超过限制,尝试fallback
  5. 不然,运行实际的RPC调用,如果调用失败或者超时,尝试fallback

根据实际情况设置

hystrix的超时时间,fallback,并发量都可以根据需要封装的指令进行设置,可以说非常灵活,根据自己的具体业务进行合适的设置,能优化用户体验。

例如:文章列表API依赖的服务超时,可以通过服务降级拉取缓存中的旧数据进行返回,虽然即时性稍逊,但是起码用户能读到几分钟前的文章,在此期间,赶紧修复问题。

微服务实践一: 架构图谱

微服务实践一: 架构图谱

目录

  1. 服务拆分与服务发现
  2. 微服务框架选择
  3. 服务间通信
  4. 服务编排
  5. 配置管理
  6. 服务容错与降级
  7. 监控
    • API监控
    • 服务调用链
    • 服务负载
    • 基础依赖监控
  8. 日志分析

Monolithic vs Microservice

Monolithic Microservice
开发测试 Java类语言项目越大,运行调试需要越多的编译时间,本地调试有较多依赖,况且业务复杂后不易新人上手 只有部分功能的代码,运行更快速,根据业务划分,方便新人上手
部署 更新整个项目 更新一个微服务
生产调试 日志集中,调试方便 日志分散,服务依赖复杂;拓容简便

这两种架构视乎业务的复杂程度和代码量的大小,复杂程度低于一定程度,还是单一应用开发更快速,部署更加容易,因为服务拆分和线上的调试这些都是需要成本,反之,当业务不断增加,代码不断膨胀,服务拆分显得逐渐重要,公共功能能抽出来做成基础服务,各个业务所需的轮子也不需要重新造一遍,反而节省了开发成本,同时对于新人的加入,由于服务职责单一,让新人进来一个一个服务地熟悉,好过于一个大而全的项目。

微服务基础架构

部署架构

处理流程

  1. 浏览器发起下单请求到负载均衡(LB)
  2. 负载均衡派发请求到API gateway
  3. API gateway查询服务发现,找到user服务和store服务,将用户信息和商品ID发送给store服务,
  4. store服务查询MySQL,找到商品信息,生成订单信息,将请求发送给payment服务
  5. payment服务根据用户指定的支付渠道,向第三方服务发起请求,存储订单信息,并返回订单状态
  6. store服务 -> API gateway -> LB
  7. LB返回数据到浏览器

微服务技术

技术图谱

Raspberry 3安装docker

SD卡制作

准备一张4GB或者以上的micro sd卡,下载系统镜像,例如raspbian-jessie-lite.img,并使用刷机工具,如Pi filler将其写入sd卡,当然也可以使用命令行的dd,或者其它工具,要注意的是sd卡必须是fat32格式的文件系统,不然树莓派是无法识别的。

开机启动

先把所有的线材都连上之后,最后再通电,应该很顺利能看到启动的系统。

设置WIFI

1
2
3
4
echo 'network={
ssid="your-ssid"
psk="your-psk"
}' | sudo tee -a /etc/wpa_supplicant/wpa_supplicant.conf

如果你的WIFI设置没有启动

1
sudo ifconfig wlan0 up

设置apt国内镜像

阿里云的镜像还是很快的。

1
echo 'deb http://mirrors.aliyun.com/raspbian/raspbian/ wheezy main non-free contrib\ndeb-src http://mirrors.aliyun.com/raspbian/raspbian/ wheezy main non-free contrib' | sudo tee /etc/apt/sources.list.d/hypriot.list

docker安装

1
2
3
4
5
6
7
ssh pi@raspberrypi.local
sudo apt-get install -y apt-transport-https
wget -q https://packagecloud.io/gpg.key -O - | sudo apt-key add -
echo 'deb https://packagecloud.io/Hypriot/Schatzkiste/debian/ wheezy main' | sudo tee /etc/apt/sources.list.d/hypriot.list
sudo apt-get update
sudo apt-get install -y docker-hypriot
sudo systemctl enable docker

以非root权限运行docker

1
sudo usermod -aG docker `whoami`

如果没有起作用,需要重新登录

参考

Run Docker on a Raspberry Pi 3 with onboard WiFi

xhprof安装记录

选择一个工具分析PHP函数调用的资源耗用明细,以图表化的形式展现,方便优化代码。

安装xhprof

1
$ pecl install xhprof-beta
Read more

Spring data redis的一个bug

前两天上线了一个新功能,导致线上业务的缓存总是无法更新,报错也是非常奇怪,redis.clients.jedis.exceptions.JedisConnectionException: Unknown reply: 5,google到的原因是Spring data redis中的scan操作,它获取了redis的连接之后,在操作没有完全结束之前就把redis连接放回连接池,其它线程从连接池里复用该连接时,会导致数据读取的错误。

bug修复

官方维护人员在 DefaultHashOperations.java 里使用新建redis连接,并等cursor关闭的时候才关闭connection的方式解决该bug。

解决办法

  1. 提升spring data redis版本到1.8,尚未release,可以拉取最新代码,编译成jar包,并配置在local repository
  2. 换个实现方案,尝试用其它数据结构,如hset等

引用

JedisConnection.java

bug地址

MySQL支持emoji

方案1: 应用层支持

MySQL默认的数据库编码是utf8,对于emoji文字是不能直接存储的,要想存储emoji,有许多库支持对emoji的转换,例如将😊转存为:smile:,放在数据库里,在从数据库里取出来的时候,再转换为😊,这是应用层的方案。

方案2: 存储层支持

MySQL编码设置为utf8mb4,直接支持emoji,不需要应用层的改动。

注意事项:
MySQL索引的长度不能大于767字节, utf8 1个字存3byte, utf8mb4存4byte,相对应VARCHAR的字节数分别是255和191,所以要把索引字段的长度限制到191。

1
2
ALTER TABLE <table1> MODIFY COLUMN <col1_indexed> VARCHAR(191);
ALTER TABLE <table1> CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

参考资料

  1. How to support full Unicode in MySQL databases
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×