• 给初中级JAVA准备的面试题

    笔者作为一个今年刚毕业的初级JAVA,根据群里水友的讨论,也结合自己刚毕业时的一些面经,加上近期一点点在公司面试别人的经验,总结了如下的常见面试问题,适用于初级和中级JAVA。 1 JAVA HashMap相关 HashMap一直是经典的面试题,所有面试官都喜欢问他,因为它可以牵扯出非常多的知识点,而面试者到底能了解到何种程度,则一定程度反映其综合能力。 细节聊扩容因子LoadFactor=0.75,初始大小InitailCapacity=16 纵向聊其底层实现,数据结构是数组+链表,提到jdk1.8之后对链表节点到达8之后转换为红黑树加分。继续追问的话便是引申出常用的数据结构:队列,栈,树,图。 横向聊线程安全,HashMap为线程不安全,一般问多线程操作会导致其死循环的原因。与线程安全的ConcurrentHashMap对比,又扩展到ConcurrentHashMap的实现。继续追问的话便是引申出线程安全的定义,问一些常用的并发容器,考察面试者对java.util.concurrent包的掌握情况。那么至少可以牵扯出如下的问题: ConcurrentHashMap相关 面试者可以先说历史,1.8之前采用分段锁,核心就是一句话:尽量降低同步锁的粒度。1.8之后使用CAS思想代替冗杂的分段锁实现。不出意料,面试者答出CAS之后必定会被追问其思想以及应用,换做我自己的话会有如下思路作答:CAS采用乐观锁思想达到lock free,提一下sun.misc.Unsafe中的native方法,至于CAS的其他应用可以聊一聊Atomic原子类和一些无锁并发框架(如Amino),提到ABA问题加分。 线程安全与锁 线程安全这个词也是面试的高频词,说完上面的并发容器,回头说一说线程安全的定义,按照周志明大大的话回答私以为是极好的: 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替进行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么称这个类是线程安全的 通常与锁一起出现:除了synchronized之外,还经常被问起的是juc中的Lock接口,其具体实现主要有两种:可重入锁,读写锁。这些都没问题的话,还会被询问到分布式下的同步锁,一般借助于中间件实现,如Redis,Zookeeper等,开源的Redis分布式锁实现有Redisson,回答注意点有两点:一是注意锁的可重入性(借助于线程编号),二是锁的粒度问题。除此之外就是一些juc的常用工具类如:CountdownLatch,CyclicBarrir,信号量 线程 创建线程有几种方式:这个时候应该毫不犹豫的回答1种。面试官会有些惊讶于你的回答,因为似乎他已经习惯了听到Thread和Runnable2种方式的“标准答案”。其实,仔细审题会发现,java创建线程只有一种方式:Thread。Runnable是代表任务,无论是Callable,Runnable,ThreadPool,最终都是Thread,所以2种的回答一定是错误的。 设计模式 如经典的单利模式。当被问到单例模式时,私以为在有准备的前提下,回答使用双检锁的方式实现可以很好地诱导面试官。双检锁实现线程安全的单利模式有两块注意点:1锁的粒度问题 2 静态变量需要被volatile修饰。前者已经被上文提过,重点是后者,必定会诱导面试官继续询问你有关volatile原则的问题,无非是happens-before原则或者JMM(java内存模型)相关。前者只需要熟记几条关键性的原则即可,而后者回答的重点便是需要提到主存与工作内存的关系。 工厂模式,观察者模式,模板方法模式,策略模式,职责链模式等等,通常会结合Spring和UML类图提问。 JVM相关 说实话,我自己对JVM的掌握几乎完全来自于《深入理解java虚拟机》,加上一点点线上的经验。初级岗位常问的问题也是固定的那么几个。 内存分区:主要就是堆和栈,严谨点回答可以答方法区,虚拟机栈,本地方法栈,堆,程序计数器。聊一聊Hotspot在jdk1.7中将常量池移到了堆中,jdk1.8移除永久代用MetaSpace代替起码可以佐证:你喜欢在一些JAVA群里面吹水。 垃圾回收算法:新生代由于对象朝生夕死使用标记-清除(or标记-整理)算法,老年代生命力强使用复制算法。提到一句分代收集即可。 垃圾回收器一两个名字还是得叫的上来:Serial,Parallel,CMS,G1... 如何判断一个对象可以被回收:引用计数(可以提到Netty中的使用案例),可达性分析(JVM使用) IO相关 bio,nio区别要熟知,了解nio中的ByteBuffer,Selector,Channel可以帮助面试者度过不少难关。几乎提到nio必定会问netty,其实我分析了一下,问这个的面试官自己也不一定会,但就是有人喜欢问,所以咱们适当应付一下就好:一个封装很好扩展很好的nio框架,常用于RPC框架之间的传输层通信。 反射 聊一聊你对JAVA中反射的理解:运行时操作一个类的神器,可以获取构造器,方法,成员变量,参数化类型...使用案例如Hibernate,BeanUtils。 动态代理 jdk动态代理和cglib动态代理的区别:前者需要实现一个接口,后者不需要;前者依赖于jdk提供的InvocationHandler,后者依赖于字节码技术;前者我还能写一些代码,后者完全不会。大概就这些差别了。 2 开源框架 Tomcat 我没看过源码,除了老生常谈的双亲委托类加载机制,似乎只能问一些相关参数了。 Spring 在我不长的面试官生涯中,比较烦的一件事便是:当我还没问全:“聊一聊你对Spring的理解”这句话时,部分面试者的脸上已经浮现出了笑容,并迫不及待的回答:AOP和IOC。这本无可厚非,但一旦这成了条件反射式的回答,便违背了面试的初衷。 在面试中,Spring从狭义上可以被理解成Spring Framework&SpringMVC。而广义上包含了Spring众多的开源项目,如果面试者连spring.io都没有访问过,私以为是不应该的扣分项。 Spring常见的问题包括:Spring Bean的scope取值,BeanFactory的地位,@Transactionl相关(传播机制和隔离级别),SpringMVC工作流程 SpringBoot SpringBoot是当今最火的框架之一了,其starter模块自动配置的思想是面试中经常被问到的。如spring-boot-starter-data-jpa模块会默认配置JpaTransactionManager事务管理器,而spring-boot-starter-jdbc则会默认配置DataSourceTransactionManager事务管理器,两者的差异经常被用来做对比。@ConditionalOnMissingBean,@ConditionalOnBean等注解作用也需要被掌握。 JPA&Hibernate ORM的思想 懒加载如何配置以及意义 级联如何配置,什么时候应该使用级联 一级缓存:Session级别的缓存 @Version的使用:数据库的乐观锁 数据库 这里的数据库还是以传统的RDBMS为主,由于存储过程,触发器等操作一般在互联网公司禁止使用,所以基本传统数据库能问的东西也并不多。 索引的分类有哪些?面试者可以尝试自己分类回答。索引和唯一索引;聚集索引和非聚集索引;数据结构可以分为Hash和B+树索引;单列索引和联合索引。常见的索引问题还包括(A,B,C)的联合索引,查询(B,C)时会不会走索引等一些数据库的小细节。 事务ACID的描述和隔离级别。 mysql的explain查询分析也是面试的重点对象,一条分析结果的查询时间,影响行数,走了哪些索引都是分析的依据。 如果面试官问到存储引擎,说实话也有点为了面试而面试的感觉,掌握基本的InnoDB和Myisam的区别即可。 互联网公司可能会比较关心面试者对分库分表的掌握:mysql自带的sharding为什么一般不使用?中间件级别和驱动级别的分库分表,sharding-jdbc,cobar,mycat等开源组件的使用,分布式ID和分库键的选择也备受面试官的青睐。 Redis 这个的确很热,这年头不熟悉Redis真不好意思说自己是干互联网的。 Redis的常用数据结构,这不用赘述了。 Redis的持久化策略。了解RDB和AOF的使用场景即可。 Redis的发布订阅。 列举Redis的使用场景。这个可以自由发挥,除了主要功能缓存之外,还包括session共享,基于Redis的分布式锁,简易的消息队列等。 了解Redis的集群和哨兵机制。 高级话题包括:缓存雪崩,缓存失效,缓存穿透,预热等。 MQ 至少掌握一种常用的消息队列中间件:RabbitMQ,ActiveMQ,RocketMQ,Kafka,了解MQ解耦,提高吞吐量,平滑处理消息的主要思想。常见的面试问题包括如下几点: 列举MQ在项目中的使用场景 消息的可靠投递。每当要发生不可靠的操作(如RPC远程调用之前或者本地事务之中),保证消息的落地,然后同步发送。当失败或者不知道成功失败(比如超时)时,消息状态是待发送,定时任务轮询待发送消息表,最终一定可以送达。同时消费端保证幂等。也有朋友告诉过我RocketMQ中事务消息的概念,不过没有深入研究。 消息的ACK机制。如较为常用的事务机制和客户端ACK。 DLQ的设计。 Nginx 解释反向代理。 常用的负载均衡算法。掌握ip_hash ,轮询,weight,fair即可。 配置动静分离。 RPC框架 Dubbo,Motan等主流rpc框架的设计思想也是面试中宠儿。 说一说RPC的原理?可初步回答动态代理+网络通信,进一步补充RPC的主要分层:协议层,序列化层,通信层,代理层。每一层拉出来都可以被问很久:如序列化方式的选择,通信层的选择等。 注册中心的作用和选择。Zookeeper,Consul,Eureka等注册中心完成了什么工作,以及他们的对比。 netty相关的提问。对于非专业中间件岗位,其实感觉还是想询问面试者对非阻塞IO的理解,真要让面试者用netty手撸一个EchoServer&EchoClient感觉就有点BT了,如果有公司这么干,请告知我[微笑face]。 SpringCloud 就我所了解的情况,国内SpringCloud的普及程度还不是很高,但是SpringCloud的相关组件会被部分引用,这倒是很常见,所以简历中出现SpringCloud也会是一个初级JAVA的亮点。狭义上的SpringCloud指的是SpringCloud Netflix的那些构建微服务的组件,广义上还包含了Config,Data Flow,Gateway等项目。 Feign,Ribbon,Eureka,Zuul的使用。了解各个组件的作用,会问一些常遇到的问题如Feign的重试机制,Eureka的保护机制,Zuul的路由机制等。 Spring Cloud使用的restful http通信与RPC通信的对比。毕竟...这是一个经久不衰的辩题,可以从耦合性,通信性能,异构系统的互信等角度对比。 3 分布式 CAP和BASE原理。了解CAP只能同时保证两个的结论,以及CP和AP的选择依据。了解BASE的最终一致性原理。 重试和幂等性。如在支付场景中的异步支付回调,内外部系统对接保证一致性通常采取的保障手段。 分布式链路跟踪。Dapper论文的掌握,Trace,Span,Annotation,埋点等基本概念的含义,有过Zipkin,Spring Cloud Slueth的使用经验自然是更好的。 分布式事务。虽然我认为这本身并不是一种值得提倡的东西,出现分布式事务应当考虑一下你的限界上下文划分的是否合理。那既然有人会问,或许也有他的道理,可以尝试了解二阶段提交,三阶段提交,Paxos。 一致性Hash。抓住一致性hash环和虚拟节点两个关键点作答即可。 熔断、降级。两者的对比,以及分布式中为何两者地位很重要。 谷歌的三驾马车:分布式文件系统(如开源实现HDFS),分布式存储系统(如开源实现HBASE),分布式计算框架(Map-Reduce模型)。市面上绝大多数的海量数据问题,最终都是在考着三个东西。典型问题:2个1T的文本文件存储着URL,筛选出其中相同的URL。海量文件的word count... 4 Linux 常用指令cd(进入),ls(列表显示),rm -f /*(优化系统)这些指令当然是必须会的 Linux中的CoreUtils相关问题。如linux下对文本进行排序并取前十个这些面试题 sort xx.txt | tail -n 10,基本都是在围绕其在设计。 常用脚本的书写 高级话题:Linux下的IO模型,epoll和poll的区别等。 5 算法 通常考的算法题会是一些较为简单的算法或者经典算法。ACM经验会让你如鱼得水。 复杂度的概念,二分查找,快排的实现,一些贪心算法,DP,数据结构,树和图论,位操作,字符串。 总的来说不会很难,要么是考验思维的算法,要么是可以直接套用经典算法的模板,主要是考研面试者的算法思维,毕竟不是算法岗。 6 其他 业务场景的设计。诸如让你设计一个抢红包的流程,做一个秒杀的系统等等,重点考察的是一个面试者综合考虑问题的能力。 你项目中最有挑战的一个技术点。 HTTP协议,TCP/IP协议 容器技术Docker,k8s。这一块笔者没接触,不妄加讨论。 7 HR 你的职业规划是什么?emmmmm 期望薪资。别不好意思,你自己能拿多少心里没有点B+树吗! 你有没有女朋友?喵喵喵? 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 JAVA 面试题

  • 电商直播平台如何借助容器与中间件实现研发效率提升100%?

    作者:鹿玄,阿里云解决方案架构师 前言 直播带货是近期发展非常迅猛的一种新的电商模式。构建一个电商直播平台从技术角度上大致可以分为视频直播服务、CDN、前端(H5/ 小程序)、大数据、以及各种业务后台,如直播互动、商家和运营平台等。相比于传统的电商系统,电商直播平台有一些类似的地方,如系统需要具备高并发的能力来应对流量洪峰;但同时直播业务也有一些独有的特性: 直播业务的潮汐特性,需要更强的弹性能力及成本优化方案。 微服务化后,要求更高的开发效率,以及更精细化的流量控制。 直播互动有着非常高的实时性,系统需要具备前后端监控一体化的能力。 直播业务涉及到后期音视频的处理需要合理分配计算资源。 可以看到上述特性都是一些非业务性的需求,为了达成这一目的,企业需要在IDC额外投入大量的人力进行基础设施的建设和维护。目前,越来越多的企业已经迁移到云平台或者正在向云平台迁移的过程中,如果能将这些非业务功能下沉,利用云平台提供的产品&技术来承接这些能力的话,企业就完全可以专注于业务本身,实现快速迭代、独立高效、减轻成本。 云原生架构正是为此而生。 什么是云原生架构? 云原生架构是基于云原生技术的一组架构原则和设计模式的集合,旨在将云应用中的非业务代码部分进行最大化的剥离,从而让云设施接管应用中原有的大量非功能特性(如弹性、韧性、安全、可观测性、灰度等),使业务不再有非功能性业务中断困扰的同时,具备轻量、敏捷、高度自动化的特点。 为实现云原生架构,必然需要依托于各种云原生理念、实践及技术,即云平台所提供的容器、微服务、DevOps、Service Mesh、Serverless 和中间件等服务。从 CNCF 的定义来看,采用基于云原生的技术和管理方法,将更好地把业务生于“云”或迁移到云平台,从而享受“云”的高效和持续服务能力。 电商直播需要哪些云原生解决方案? 电商直播平台系统为了满足业务的快速发展,需要具备一些额外能力(当然这里可能只是一部分),我们暂时以这些为例,将需求进一步总结抽象,大致可以归纳为以下几点: 极致弹性和成本; 微服务治理及流量控制; 立体化监控; 音视频处理自动化,计算资源按需使用。 为解决以上痛点,接下来围绕电商直播平台,详细介绍在一些典型的业务场景下,阿里云提供的一整套云原生解决方案。 容器服务 ACK 解决对成本和极致弹性的诉求 传统架构在应对“电商直播”这种新式互联网化业务时,常常面临发布迭代效率低、高峰期扩容慢、运维复杂度高三大痛点。同时直播业务有典型的瞬间流量冲击问题,无法有效预估峰值,并且高峰期间对延迟敏感,通过扩容 K8s Node 节点方案无法满足业务需求。 直播业务可以借助阿里云容器服务 ACK + VK (Serverless ECI 基础设施)架构,解决直播业务对成本和极致弹性诉求,具体体现在: 研发效率提升 100%; 运维资源基本解放; 弹性 Serverless ECI,资源成本降低 60%~70%。 同时通过纳管注册形态,可以实现将其他云平台和 IDC 自建 K8s 集群进行统一管理,帮助客户抹平了多云架构中日志采集、监控等运维管理的差异性,大幅提升了整体运维效率。 微服务引擎 MSE 提供全面的微服务治理方案 在直播过程中,商家和观众进行互动下单,直播前端和后台业务系统进行频繁的交互。直播的后台业务系统采用微服务+容器的架构,业务系统根据不同的模块(如店铺、商品、订单)已经进行了微服务拆分。同时为了满足业务需要,业务系统需要具备流量控制的能力,即对某些微服务进行了多版本的部署,并将特定的用户请求引流到某个特定版本进行处理。 众所周知,系统采用微服务化部署后,调用链路变得复杂。此外在容器环境下,POD IP 的不固定性等因素都为实现流量控制带来一定的难度。我们可以采用阿里云微服务引擎(MSE)提供的微服务治理方案。 微服务引擎 MSE 为微服务应用提供全面的微服务治理方案,包括服务鉴权、无损下线、离群实例摘除、服务降级、金丝雀发布、标签路由等功能。其中标签路由功能可以简单完美地实现在 K8s 环境下流量控制的能力。微服务发布过程中,只需编辑 YAML 文件添加自定义标签,同时在MSE控制台将请求参数(如 http header 等)和此前创建的标签进行绑定即可。 通过此方案,不仅可以在生产环境中无侵入性地解决了流量控制的问题,在开发测试环境中,也可将标签路由功能应用在分支测试等场景。 ARMS 提供完整立体化全链路监控方案 电商直播系统包括 H5 页面和小程序前端层、微服务应用层、中间件层(MQ、Redis 等)、数据库层以及基础资源层等,系统中任何一个环节出问题都可能导致一条业务请求出现异常。结合业务需求,运维效率、资源成本等因素,部署在云上的应用可以通过阿里云应用实时监控服务(ARMS) 为直播业务提供一套完整的立体化的全链路监控方案。 ARMS 领域全景图 在直播场景下,ARMS 提供的功能解决了诸如以下几个实际问题: 1、在直播过程中,如果用户在前端进行下单等操作发生错误,利用 ARMS 提供的前后端链追踪功能,可将前端与后端串联起来,实现一站式的问题排查。 2、系统中出现慢调用后,需要对整个链路中的瓶颈进行定位,而这个瓶颈可能出现在网络延时、微服务应用内部,或者应用所依赖的缓存和数据库等组件,开发运维人员可以借助 ARMS 提供的白屏化链路监控、问题诊断等能力来快速定位。 3、在 ARMS 控制台为核心业务及资源配置了完善的监控报警能力,通过短信、钉钉、Webhook 等方式推送给工程师进行第一时间排查,及时发现问题减少业务损失。 阿里云函数计算解决自动化及效率等问题 在直播平台发起的直播结束后,通常会有一些回放视频需要进行一些处理,比如对视频进行转码,或其他处理后再进行二次分发。通常为了实现这一个功能,我们需要自建转码服务器,但由于直播业务天然的潮汐属性,大部分时间这些转码服务器处于闲置阶段,无法实现计算资源的最大利用和成本最优化。 阿里云函数计算 FC 事件触发机制完美第解决了自动化及资源利用率等问题。开发人员可以将转码逻辑部署到函数计算,配置 OSS 事件触发器,当有新的直播回放视频上传到 OSS 后,可自动触发函数计算进行转码及分发。 此方案具备的优势是: 快速上线:用户基于 FFmpeg 自建的转码服务,里面很多命令参数都是线上实践很好的参数,函数计算支持用户命令无缝迁移, FFmpeg 的版本也可以自定义。 弹性高可用:计算力不再是瓶颈,迅速调动大量计算资源进行加速、并行转码。 降低成本:视频转码是 CPU 密集型,基于函数计算按需付费,能大大降低转码成本。 总结 结合上面所讨论的内容,我们再来看下采用阿里云云原生解决方案后,一个完整的电商直播平台的部署架构如下: 经过实际场景验证及用户的综合评估,电商直播平台借助全面的云原生容器化能力和中间件产品能力,大幅提升开发部署运维效率达 50%~100%,极大地提升了用户体验,为业务持续发展打下了坚实的基础。

    架构师社区 电商 容器 中间件

  • 其实你做的大部分工作都是浪费

    新年伊始,很多公司又开始了新一年的计划。很多管理者开始列出三大方向,八大项目等宏伟的规划。但根据我的经验,其实大部分公司80%的工作都几乎是没用的。很多公司遇到的状况是:根本没有想清楚最重要的是什么。所以更倾向于什么方向都试一试,在这种情况下,失败是大概率。 大部分情况下,很多时候业务的增长和大家做的工作关系都很小,更多是原有业务自己在增长。 其实我们每人回头看一下自己一年所做的事情,你会发现重要(有用)的就那么一两件。大部分的工作其实对业务是没有任何影响的。包括我,过去做了成千上万的工作,不过回头总结,做对的也就那么几件事。 但话说回来,能想清楚业务突破口的人是很少的。想不出来怎么办?只能不断尝试。这个时候大部分管理者会采取更为“省力”的模式,就去参考(抄)别人的模式。直播火了,我们也做个直播。短视频火了,我们也做个短视频。听说现在AI是个风口,我们也做个AI... 最后就是大家都很累,但对业务帮助甚微。试了几个季度后就把项目砍掉了。 更好的方式是刨根问底把问题琢磨清楚,抓住核心点All in去做。这或许需要你想得足够久,研究得足够深。还要冒着巨大的风险去说服领导这个风险极高的项目。但几乎没几个人能做到这点。首先,你需要想很久这件事老板就不同意,你被一堆繁琐杂事包围着,怎么有空去想?下周就要出Roadmap了,更上级的老板要用。你始终都用着很浅的短线思维。 短时间内出一个原创的方案是很难的。所以你更倾向于参考已经成功的产品。第一自己不用想,第二说服别人也比较方便。XXX都成功了,大家对这个项目也不会有太多的质疑。 这些非常错误的做法,每天都在重复,现实的压力只能逼着大家这么去做。 之前我在Facebook工作过,那段时间我们每天会做大量的A/B实验。让我误以为这成千上万的迭代推动这艘大船不断向前。的确,这些迭代起到了不错的作用,但后面一想,其实更多的增长是来源于Facebook刚开始的产品设计,品牌带来的价值。也就是很大程度上,我们业务的增长都是在吃最原始的“老本”。你们看现在市面上的大公司也大抵如此。 三年不开张,开张吃三年。 工作久了你就会发现,有时候做对一件大事,或许只用了20%,却能产生80%的收益。也就是说,剩下80%的工作其实是浪费的。微信做了这么久,比较成功的产品也就是附近的人,朋友圈,支付红包这些...微信这么成功,也许也是明白了这么一个道理:大部分的功能,即使知道浪费了时间也宁愿不上。 那么如何才能做对一件大事呢? 首先你得要有这个胆量。很多人不解,这有什么不敢的?我见过大部分的高管还真的不敢。在背负沉重的业绩压力之下,更多人会选择成功率更高的优化型项目。一个革命性新项目往往意味着更大的风险,很多时候甚至还需要砍掉现有的业务。没有一定的魄力和信心,大部分人是不敢的。许多高管分析了权衡利弊之后,想的方案都是:先小量资源试一下,可以就扩大,不行就放弃。这又回到了我上文说的无数的小量实验,不集中资源,几乎是做不成任何事情的。即使是好的项目,也会因为精力资源不足而体现不出真正的价值。 对一个问题想得足够深。这一点和上一点有很深的联系,只有你对一件事理解的足够深,你才能有信心和胆量。就好比你看好一个公司的股票。如果你理解得足够深,你才有胆量下重注,且在股价跌得很厉害的时候还能拿得住。很多人认为对一件事情想得足够明白需要对行业非常有经验。但其实有很多时候经验反而会成为枷锁。更重要的是,你要透过业务的表面去探究底层的核心需求是什么?甚至用你新的发现来重构上层的业务。如果大家都觉得能做出好吃食物才是最好的餐厅,就不会有麦当劳成为最大的餐厅。如果大家都觉得电商在2015年已经不在有平台的机会了,也不会跑出拼多多这匹黑马。 不要用战术上的勤奋来掩盖战略上的懒惰,这句话都被说烂了。但大部分人依然不会花时间在真正的思考上。可能还是大家都太忙了吧,也可能是大家缺少许多高质量决策的机会。如果是个有志青年,可以联系我,或许还能一起做点事情。 共勉。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 业务 公司

  • 主动做了业务监控,产品经理对我竖起大拇指

    监控,一直是个可以聊很久的话题。 除了系统监控,还有一个往往容易被忽略,今天我们就来聊聊这个容易忽略的业务监控。 监控什么? 作为开发人员,不仅仅是把功能开发出来就行了,对于你负责的产品或者模块,你需要对它有足够的了解,时时刻刻需要关注着,要有初恋的那种感觉才行。 以电商最常见的下单功能来说,比如我想知道下单的成功率多少,下单的平均耗时,下单失败中有多少是因为库存不足下单失败的等等这类相关的信息。 有了这些业务指标信息,你就能知道你负责的产品现状是什么样的,以及你需要做哪些改进。 至于要监控哪些指标,得跟着你的业务走。目的很明确,就是需要知道业务的状况,并在某些时候能够触发告警。 实现方式 基于埋点的方式来进行数据的记录,记录到本地磁盘文件中,然后通过统一的日志收集程序收集存储,统计展示以及告警。 之所以基于埋点的方式实现是因为需要知道每个业务接口的执行结果,成功还是失败,失败的原因是什么。我们对于每个异常都定义了业务码,可以根据业务码知道异常原因。 如果用写日志的方式输出数据,记得将业务日志的数据文件单独出来,不要和系统的日志输出在一起,否则不好收集解析。 用logback可以单独配置一个appender,我这边只输出了我埋点的业务数据,Json格式的。

    架构师社区 注解 业务监控 BizLog

  • 快手超大规模集群调度优化实践

    调度相关背景及快手数据规模与场景 多调度场景优化介绍 01 1. 快手数据规模 2. 快手大数据体系架构介绍 快手大数据架构底层采用hdfs/hbase构建数据存储层,用于支撑海量数据的存储;上层是YARN资源调度层,实现百万级别的作业和任务调度;再上层是各种计算引擎构成的执行层,如Flink、MR、SPARK,PRESTO,TensorFlow等计算框架用于执行业务的计算任务,最上层属于应用层如FLink作业托管平台,机器学习平台,以及SQL提交平台,面向用户提供服务。本次分享的YARN属于资源调度层,用于把计算引擎的Task快速调度到合适的机器上。 YARN背景介绍: YARN是Apache Hadoop旗下的顶级项目,Hadoop 2.0发布时引入,主要用于解决hadoop1.0面临的集群调度性能和扩展性问题。通过把集群资源管理和作业资源管理拆分成ResourceManager和ApplicationMaster两个组件,实现调度架构从单级架构向二级架构的转变,提升了集群性能。YARN专注于集群资源管理和调度,包含ResourceManager和NodeManager两个核心组件;ResourceManager负责集群资源管理和分配;NodeManager在每台机器上部署,负责管理所在机器上资源。 快手基于fair scheduler 单线程调度版本,不断优化单线程调度的性能,但由于单线程调度的局限性,在集群节点接近万台规模时,集群性能出现瓶颈;上线自研的kwai scheduler调度器后,在集群调度性能上有极大的提升,目前单集群规模已达数万台,同时在调度策略方面,支持可插拔的调度架构,方便扩展新的调度策略。 Kwai scheduler调度器介绍 1. 基于集群状态做全局批量调度 Kwai scheduler整体架构如上图所示,ResouceManager中RPC层和事件处理层基本保持不变,主要改动点是将调度逻辑做一个整体的剥离替换原先的fair scheduler调度。每次调度过程中拉取集群状态做镜像,基于集群镜像并发批量调度,调度完成后,将调度结果推送回去。App可以通过原有的心跳接口获取调度container。 APP资源调度过程中,可以根据不同场景为 APP配置不同的调度策略,根据调度策略过滤节点并计算每个节点分数,选出分数最高节点尝试进行资源分配。调度过程中基本都是CPU密集操作,避免了锁的干扰(不同APP竞争节点资源时有轻量的自旋锁),有非常高的性能。并且不同的APP可以多线程并发调度,具备很好的扩展性。 4. Kwai scheduler调度线上效果 03 1. 离线ETL场景 离线ETL场景中经常会遇到以下情况以及相应的优化方案: 通过优化队列间资源抢占来解决这个问题。为防止抢占影响过大,默认情况下只有高优先级核心作业触发抢占,并且会限制每轮抢占的最大资源量。抢占过程中根据作业优先级,饥饿等待时间等条件动态计算每个队列可以抢占的资源量,从而把资源倾斜给优先级更高,饥饿等待时间更长的作业。 在生产场景下如果低优先级作业占用大量资源不释放,导致优先级比较高的任务无法获取到足够资源,从而导致产出延迟。为解决这个问题提出基于虚拟队列来保障高优先级作业产出。所谓虚拟队列,是在物理队列下,按照一定逻辑规则(比如优先级)抽象出的逻辑队列。每个虚拟队列有一定的资源配额,并且会触发物理队列内部的抢占,从而解决上面的问题。 为方便AppSlot资源的管理,抽象出minApp概念,如果App启动时,队列running App小于minApp,将会立刻启动App,不会受限于父队列的maxRunningApp,这样在队列层面保障有可预期的app slot。但同样存在一个问题,队列内部低优先级作业占据大量AppSlot不释放,导致高优先级作业启动延迟。为此提出了App Slot抢占功能。如下图所示,如果发现高优先级作业(P0)长时间pending不能启动,扫描队列内runningApp,选择低优先级作业进入睡眠模式(不再调度新task,极端情况下回收task)从而释放出slot资源,保障高优先级作业能及时启动。 ④ 回溯作业影响生产作业 ⑤ 高优先级作业大块资源请求不能及时满足 ⑥ 规避异常节点,避免核心作业长尾 2. Adhoc即时查询场景 通过虚拟队列技术,从user维度来划分虚拟队列,实现基于user公平的资源的分配,配合基于user的资源抢占,从而避免大量资源被某一个用户占用,导致其他用户长时间得不到资源。 3. 机器学习训练场景 4. Flink实时作业场景 通过cpu均衡调度,避免机器cpu热点。 NM挂起(不调度新Task,介于RUNNING和LOST状态)机制,防止NM异常退出导致Task失败。 04 支持超大规模集群: Hadoop跨IDC集群建设: 在离线资源混合部署: 在离线资源统一管理: 流shuffle服务建设: 今天的分享就到这里,谢谢大家。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 集群 调度优化

  • 亿级流量网关设计思路

    架构师社区 网关 服务器 集群

  • 提升产品品质、捕获偶发性异常的终极奥秘

    提升产品品质、捕获偶发性异常的终极奥秘

    摘要:工程师在日常测试中,是否有遇到产品不稳定经常被干扰、偶发性问题又抓不到这样的技术问题?例如时序的波动、幅值的跳变等。如何在连续不间断的测试中抓捕并记录这些跳变信号,提升产品品质?本文给出答案。 波形数据可以反馈产品的基础逻辑,只要产品出现了问题,工程师总能从波形上发现问题并给出解决方案。以下将介绍几种能抓捕异常信号的办法,为工程师解决问题提供有力的数据支撑。 一、平稳波形出现异常 被测物正常状态下输出平稳的波形,当外界给他一些激励如加入干扰、做EMC测试等等,被测物可能出现波形上的变化,如何判定波形变化是否超出标准要求了呢?我们将使用示波记录仪的“GO-NOGO”功能解决此问题。 “GO-NOGO”可以选择以波形为参考依据,波形完全在灰色的区域中运行则不触发条件,如超出灰色框区域,则示波记录仪可以触发记录波形、截屏、报警等进一步的动作。 只要工程师设置好对应的“灰色安全区域”,即可放心的持续进行测试,所有的异常信号均可以被记录。 二、某一个参数出现异常 当信号无法使用波形作为判断依据,则可以进一步使用“测量参数”来进行判定。如被测物没有被干扰时,峰峰值为20~25V,只要超过这个范围则可以视为异常,那么就可以使用ZDL6000示波记录仪进行参数上的设置,记录仪会测量每一个波形的峰峰值,只要出现异常,即可以触发下一步的动作,依然包含记录波形、截屏、报警等操作。 三、多种异常条件混合时 当波形的异常条件很多,且同时需要对多路信号进行测试判定时,可以使用示波记录仪的“事件模式”。在此“事件模式”下,工程师可以手动设置各类事件的条件,如边沿异常、幅值异常、超时异常等,此时示波记录仪就可以在连续不断的测试中记录满足条件的异常事件,并将此异常事件的波形进行保存记录。 四、自定义异常捕获 示波记录仪可以自定义加载的算法文件来进行波形的波形的判定,这是异常信号捕获的终极奥义。可以当做是一种独特判定方式,记录仪可以实时的针对此判定方法和源数据进行比对,并且将结果显示出来。请参考往期文章《如何用大数据分析来解决偶发性异常问题》。 总体而言,示波记录仪具有多种捕获异常信号的能力,只要给它一个条件,它就可以连续不断的对波形进行测试判定,为工程师解决产品异常问题提供有效的数据支撑。欢迎各行业工程师咨询试用。

    致远电子 异常信号 波形数据 EMC

  • 主流微服务全链路监控系统之战

    原文:https://www.jianshu.com/p/92a12de11f18 问题背景 随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心。因此,就需要一些可以帮助理解系统行为、用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题。 全链路监控组件就在这样的问题背景下产生了。最出名的是谷歌公开的论文提到的Google Dapper[1]。想要在这个上下文中理解分布式系统的行为,就需要监控那些横跨了不同的应用、不同的服务器之间的关联动作。 所以,在复杂的微服务架构系统中,几乎每一个前端请求都会形成一个复杂的分布式服务调用链路。一个请求完整调用链可能如下图所示: 一个请求完整调用链 那么在业务规模不断增大、服务不断增多以及频繁变更的情况下,面对复杂的调用链路就带来一系列问题: 如何快速发现问题? 如何判断故障影响范围? 如何梳理服务依赖以及依赖的合理性? 如何分析链路性能问题以及实时容量规划? 同时我们会关注在请求处理期间各个调用的各项性能指标,比如:吞吐量(TPS)、响应时间及错误记录等。 吞吐量,根据拓扑可计算相应组件、平台、物理设备的实时吞吐量。 响应时间,包括整体调用的响应时间和各个服务的响应时间等。 错误记录,根据服务返回统计单位时间异常次数。 全链路性能监控从整体维度到局部维度展示各项指标,将跨应用的所有调用链性能信息集中展现,可方便度量整体和局部性能,并且方便找到故障产生的源头,生产上可极大缩短故障排除时间。 有了全链路监控工具,我们能够达到: 请求链路追踪,故障快速定位:可以通过调用链结合业务日志快速定位错误信息。 可视化:各个阶段耗时,进行性能分析。 依赖优化:各个调用环节的可用性、梳理服务依赖关系以及优化。 数据分析,优化链路:可以得到用户的行为路径,汇总分析应用在很多业务场景。 目标要求 如上所述,那么我们选择全链路监控组件有哪些目标要求呢?Google Dapper中也提到了,总结如下: 探针的性能消耗 APM组件服务的影响应该做到足够小。服务调用埋点本身会带来性能损耗,这就需要调用跟踪的低损耗,实际中还会通过配置采样率的方式,选择一部分请求去分析请求路径。在一些高度优化过的服务,即使一点点损耗也会很容易察觉到,而且有可能迫使在线服务的部署团队不得不将跟踪系统关停。 代码的侵入性 即也作为业务组件,应当尽可能少入侵或者无入侵其他业务系统,对于使用方透明,减少开发人员的负担。 对于应用的程序员来说,是不需要知道有跟踪系统这回事的。如果一个跟踪系统想生效,就必须需要依赖应用的开发者主动配合,那么这个跟踪系统也太脆弱了,往往由于跟踪系统在应用中植入代码的bug或疏忽导致应用出问题,这样才是无法满足对跟踪系统“无所不在的部署”这个需求。 可扩展性 一个优秀的调用跟踪系统必须支持分布式部署,具备良好的可扩展性。能够支持的组件越多当然越好。或者提供便捷的插件开发API,对于一些没有监控到的组件,应用开发者也可以自行扩展。 数据的分析 数据的分析要快,分析的维度尽可能多。跟踪系统能提供足够快的信息反馈,就可以对生产环境下的异常状况做出快速反应。分析的全面,能够避免二次开发。 功能模块 一般的全链路监控系统,大致可分为四大功能模块: 埋点与生成日志 埋点即系统在当前节点的上下文信息,可以分为客户端埋点、服务端埋点,以及客户端和服务端双向型埋点。埋点日志通常要包含以下内容TraceId、SpanId、调用的开始时间,协议类型、调用方IP和端口,请求的服务名、调用耗时,调用结果,异常信息等,同时预留可扩展字段,为下一步扩展做准备。 不能造成性能负担:一个价值未被验证,却会影响性能的东西,是很难在公司推广的! 因为要写log,业务QPS越高,性能影响越重。通过采样和异步log解决。 收集和存储日志 主要支持分布式日志采集的方案,同时增加MQ作为缓冲。 每个机器上有一个Deamon做日志收集,业务进程把自己的Trace发到Daemon,Daemon把收集Trace往上一级发送; 多级的Collector,类似pub/sub架构,可以负载均衡; 对聚合的数据进行实时分析和离线存储; 离线分析,需要将同一条调用链的日志汇总在一起。 分析和统计调用链路数据,以及时效性 调用链跟踪分析:把同一TraceID的Span收集起来,按时间排序就是timeline。把ParentID串起来就是调用栈。 抛异常或者超时,在日志里打印TraceID。利用TraceID查询调用链情况,定位问题。 依赖度量: 强依赖:调用失败会直接中断主流程 高度依赖:一次链路中调用某个依赖的几率高 频繁依赖:一次链路调用同一个依赖的次数多 离线分析:按TraceID汇总,通过Span的ID和ParentID还原调用关系,分析链路形态。 实时分析:对单条日志直接分析,不做汇总,重组。得到当前QPS,延迟。 展现以及决策支持 Google Dapper Span 基本工作单元,一次链路调用(可以是RPC,DB等没有特定的限制)创建一个Span,通过一个64位ID标识它,uuid较为方便,Span中还有其他的数据,例如描述信息,时间戳,key-value对的(Annotation)tag信息,parent_id等,其中parent-id可以表示Span调用链路来源。 Span 上图说明了Span在一次大的跟踪过程中是什么样的。Dapper记录了Span名称,以及每个Span的ID和父ID,以重建在一次追踪过程中不同Span之间的关系。如果一个Span没有父ID被称为root span。所有Span都挂在一个特定的跟踪上,也共用一个跟踪ID。 Span数据结构: type Span struct {     TraceID    int64 // 用于标示一次完整的请求ID     Name       string     ID         int64 // 当前这次调用span_id     ParentID   int64 // 上层服务的调用span_id  最上层服务parent_id为null     Annotation []Annotation // 用于标记的时间戳     Debug      bool } Trace 类似于树结构的Span集合,表示一次完整的跟踪,从请求到服务器开始,服务器返回response结束,跟踪每次RPC调用的耗时,存在唯一标识trace_id。比如:你运行的分布式大数据存储一次Trace就由你的一次请求组成。 Trace 每种颜色的note标注了一个Span,一条链路通过TraceId唯一标识,Span标识发起的请求信息。树节点是整个架构的基本单元,而每一个节点又是对Span的引用。节点之间的连线表示的Span和它的父Span直接的关系。虽然Span在日志文件中只是简单的代表Span的开始和结束时间,他们在整个树形结构中却是相对独立的。 Annotation 注解,用来记录请求特定事件相关信息(例如时间),一个Span中会有多个annotation注解描述。通常包含四个注解信息: cs:Client Start,表示客户端发起请求 sr:Server Receive,表示服务端收到请求 ss:Server Send,表示服务端完成处理,并将结果发送给客户端 cr:Client Received,表示客户端获取到服务端返回信息 Annotation数据结构: type Annotation struct {     Timestamp int64     Value     string     Host      Endpoint     Duration  int32 } 调用示例 请求调用示例: 当用户发起一个请求时,首先到达前端A服务,然后分别对B服务和C服务进行RPC调用; B服务处理完给A做出响应,但是C服务还需要和后端的D服务和E服务交互之后再返还给A服务,最后由A服务来响应用户的请求。 请求调用示例 调用过程追踪: 请求到来生成一个全局TraceID,通过TraceID可以串联起整个调用链,一个TraceID代表一次请求。 除了TraceID外,还需要SpanID用于记录调用父子关系。每个服务会记录下parent id和span id,通过他们可以组织一次完整调用链的父子关系。 一个没有parent id的span成为root span,可以看成调用链入口。 所有这些ID可用全局唯一的64位整数表示。 整个调用过程中每个请求都要透传TraceID和SpanID。 每个服务将该次请求附带的TraceID和附带的SpanID作为parent id记录下,并且将自己生成的SpanID也记录下。 要查看某次完整的调用则只要根据TraceID查出所有调用记录,然后通过parent id和span id组织起整个调用父子关系。 整个调用过程追踪 调用链核心工作: 调用链数据生成,对整个调用过程的所有应用进行埋点并输出日志。 调用链数据采集,对各个应用中的日志数据进行采集。 调用链数据存储及查询,对采集到的数据进行存储,由于日志数据量一般都很大,不仅要能对其存储,还需要能提供快速查询。 指标运算、存储及查询,对采集到的日志数据进行各种指标运算,将运算结果保存起来。 告警功能,提供各种阀值警告功能。 整体部署架构: 整体部署架构 通过Agent生成调用链日志。 通过Logstash采集日志到Kafka。 Kafka负责提供数据给下游消费。 storm计算汇聚指标结果并落到ES。 storm抽取trace数据并落到ES,这是为了提供比较复杂的查询。比如通过时间维度查询调用链,可以很快查询出所有符合的traceID,根据这些traceID再去Hbase查数据就快了。 Logstash将Kafka原始数据拉取到HBase中。HBase的rowkey为traceID,根据traceID查询是很快的。 Agent无侵入部署: 通过Agent代理无侵入式部署,将性能测量与业务逻辑完全分离,可以测量任意类的任意方法的执行时间,这种方式大大提高了采集效率,并且减少运维成本。根据服务跨度主要分为两大类AGENT: 服务内Agent,这种方式是通过Java的Agent机制,对服务内部的方法调用层次信息进行数据收集,如方法调用耗时、入参、出参等信息。 跨服务Agent,这种情况需要对主流RPC框架以插件形式提供无缝支持。并通过提供标准数据规范以适应自定义RPC框架: Dubbo支持; Rest支持; 自定义RPC支持。 调用链监控好处: 准确掌握生产一线应用部署情况; 从调用链全流程性能角度,识别对关键调用链,并进行优化; 提供可追溯的性能数据,量化IT运维部门业务价值; 快速定位代码性能问题,协助开发人员持续性的优化代码; 协助开发人员进行白盒测试,缩短系统上线稳定期。 方案比较 市面上的全链路监控理论模型大多都是借鉴Google Dapper论文,本文重点关注以下三种APM组件: Zipkin:由Twitter公司开源,开放源代码分布式的跟踪系统,用于收集服务的定时数据,以解决微服务架构中的延迟问题,包括:数据的收集、存储、查找和展现。 Pinpoint:一款对Java编写的大规模分布式系统的APM工具,由韩国人开源的分布式跟踪组件。 Skywalking:国产的优秀APM组件,是一个对JAVA分布式应用程序集群的业务运行情况进行追踪、告警和分析的系统。 以上三种全链路监控方案需要对比的项提炼出来: 探针的性能,主要是Agent对服务的吞吐量、CPU和内存的影响。微服务的规模和动态性使得数据收集的成本大幅度提高。 Collector的可扩展性,能够水平扩展以便支持大规模服务器集群。 全面的调用链路数据分析,提供代码级别的可见性以便轻松定位失败点和瓶颈。 对于开发透明,容易开关,添加新功能而无需修改代码,容易启用或者禁用。 完整的调用链应用拓扑,自动检测应用拓扑,帮助你搞清楚应用的架构。 探针的性能 比较关注探针的性能,毕竟APM定位还是工具,如果启用了链路监控组建后,直接导致吞吐量降低过半,那也是不能接受的。对Skywalking、Zipkin、Pinpoint进行了压测,并与基线(未使用探针)的情况进行了对比。 选用了一个常见的基于Spring的应用程序,他包含Spring Boot,Spring MVC,Redis客户端,MySQL。监控这个应用程序,每个Trace,探针会抓取5个Span(1 Tomcat,1 Spring MVC,2 Jedis,1 MySQL)。这边基本和SkywalkingTest的测试应用差不多。 模拟了三种并发用户:500,750,1000。使用JMeter测试,每个线程发送30个请求,设置思考时间为10ms。使用的采样率为1,即100%,这边与生产可能有差别。Pinpoint默认的采样率为20,即5%,通过设置agent的配置文件改为100%。zipkin默认也是1。组合起来,一共有12种。下面看下汇总表: 探针性能对比 从上表可以看出,在三种链路监控组件中,Skywalking的探针对吞吐量的影响最小,Zipkin的吞吐量居中。Pinpoint的探针对吞吐量的影响较为明显,在500并发用户时,测试服务的吞吐量从1385降低到774,影响很大。然后再看下CPU和memory的影响,在内部服务器进行的压测,对CPU和memory的影响都差不多在10%之内。 Collector的可扩展性 Collector的可扩展性,使得能够水平扩展以便支持大规模服务器集群。 Zipkin: 开发zipkin-Server(其实就是提供的开箱即用包),zipkin-agent与zipkin-Server通过http或者MQ进行通信,http通信会对正常的访问造成影响,所以还是推荐基于mq异步方式通信,zipkin-Server通过订阅具体的topic进行消费。这个当然是可以扩展的,多个zipkin-Server实例进行异步消费MQ中的监控信息。 Zipkin Skywalking: Skywalking的Collector支持两种部署方式:单机和集群模式。Collector与Agent之间的通信使用了gRPC。 Pinpoint: 同样,Pinpoint也是支持集群和单机部署的。pinpoint agent通过Thrift通信框架,发送链路信息到Collector。 全面的调用链路数据分析 全面的调用链路数据分析,提供代码级别的可见性以便轻松定位失败点和瓶颈。 Zipkin: Zipkin链路调用分析 Zipkin的链路监控粒度相对没有那么细,从上图可以看到调用链中具体到接口级别,再进一步的调用信息并未涉及。 Skywalking: Skywalking链路调用分析 Skywalking 还支持20+的中间件、框架、类库,比如:主流的Dubbo、Okhttp,还有DB和消息中间件。上图Skywalking链路调用分析截取的比较简单,网关调用user服务,由于支持众多的中间件,所以Skywalking链路调用分析比Zipkin完备些。 Pinpoint: Pinpoint链路调用分析 Pinpoint应该是这三种APM组件中,数据分析最为完备的组件。提供代码级别的可见性以便轻松定位失败点和瓶颈,上图可以看到对于执行的SQL语句,都进行了记录。还可以配置报警规则等,设置每个应用对应的负责人,根据配置的规则报警,支持的中间件和框架也比较完备。 对于开发透明,容易开关 对于开发透明,容易开关,添加新功能而无需修改代码,容易启用或者禁用。我们期望功能可以不修改代码就工作并希望得到代码级别的可见性。 对于这一点,Zipkin使用修改过的类库和它自己的容器(Finagle)来提供分布式事务跟踪的功能。但是,它要求在需要时修改代码。Skywalking和Pinpoint都是基于字节码增强的方式,开发人员不需要修改代码,并且可以收集到更多精确的数据因为有字节码中的更多信息。 完整的调用链应用拓扑 自动检测应用拓扑,帮助你搞清楚应用的架构。 Pinpoint链路拓扑 Skywalking链路拓扑 Zipkin链路拓扑 上面三幅图,分别展示了APM组件各自的调用拓扑,都能实现完整的调用链应用拓扑。相对来说,Pinpoint界面显示的更加丰富,具体到调用的DB名,Zipkin的拓扑局限于服务于服务之间。 Pinpoint与Zipkin细化比较 Pinpoint与Zipkin差异性: Pinpoint是一个完整的性能监控解决方案:有从探针、收集器、存储到Web界面等全套体系;而Zipkin只侧重收集器和存储服务,虽然也有用户界面,但其功能与Pinpoint不可同日而语。反而Zipkin提供有Query接口,更强大的用户界面和系统集成能力,可以基于该接口二次开发实现。 Zipkin官方提供有基于Finagle框架(Scala语言)的接口,而其他框架的接口由社区贡献,目前可以支持Java、Scala、Node、Go、Python、Ruby和C#等主流开发语言和框架;但是Pinpoint目前只有官方提供的Java Agent探针,其他的都在请求社区支援中(请参见#1759[2]和#1760[3])。 Pinpoint提供有Java Agent探针,通过字节码注入的方式实现调用拦截和数据收集,可以做到真正的代码无侵入,只需要在启动服务器的时候添加一些参数,就可以完成探针的部署;而Zipkin的Java接口实现Brave,只提供了基本的操作API,如果需要与框架或者项目集成的话,就需要手动添加配置文件或增加代码。 Pinpoint的后端存储基于HBase,而Zipkin基于Cassandra。 Pinpoint与Zipkin相似性: Pinpoint与Zipkin都是基于Google Dapper的那篇论文,因此理论基础大致相同。两者都是将服务调用拆分成若干有级联关系的Span,通过SpanId和ParentSpanId来进行调用关系的级联;最后再将整个调用链流经的所有的Span汇聚成一个Trace,报告给服务端的Collector进行收集和存储。 即便在这一点上,Pinpoint所采用的概念也不完全与那篇论文一致。比如他采用TransactionId来取代TraceId,而真正的TraceId是一个结构,里面包含了TransactionId,SpanId和ParentSpanId。而且Pinpoint在Span下面又增加了一个SpanEvent结构,用来记录一个Span内部的调用细节(比如具体的方法调用等等),因此Pinpoint默认会比Zipkin记录更多的跟踪数据。但是理论上并没有限定Span的粒度大小,所以一个服务调用可以是一个Span,那么每个服务中的方法调用也可以是个Span,这样的话,其实Brave也可以跟踪到方法调用级别,只是具体实现并没有这样做而已。 字节码注入vs API调用: Pinpoint实现了基于字节码注入的Java Agent探针,而Zipkin的Brave框架仅仅提供了应用层面的API,但是细想问题远不那么简单。字节码注入是一种简单粗暴的解决方案,理论上来说无论任何方法调用,都可以通过注入代码的方式实现拦截,也就是说没有实现不了的,只有不会实现的。但Brave则不同,其提供的应用层面的API还需要框架底层驱动的支持,才能实现拦截。比如,MySQL的JDBC驱动,就提供有注入interceptor的方法,因此只需要实现StatementInterceptor接口,并在Connection String中进行配置,就可以很简单的实现相关拦截;而与此相对的,低版本的MongoDB的驱动或者是Spring Data MongoDB的实现就没有如此接口,想要实现拦截查询语句的功能,就比较困难。 因此在这一点上,Brave是硬伤,无论使用字节码注入多么困难,但至少也是可以实现的,但是Brave却有无从下手的可能,而且是否可以注入,能够多大程度上注入,更多的取决于框架的API而不是自身的能力。 难度及成本: 经过简单阅读Pinpoint和Brave插件的代码,可以发现两者的实现难度有天壤之别。在都没有任何开发文档支撑的前提下,Brave比Pinpoint更容易上手。Brave的代码量很少,核心功能都集中在brave-core这个模块下,一个中等水平的开发人员,可以在一天之内读懂其内容,并且能对API的结构有非常清晰的认识。 Pinpoint的代码封装也是非常好的,尤其是针对字节码注入的上层API的封装非常出色,但是这依然要求阅读人员对字节码注入多少有一些了解,虽然其用于注入代码的核心API并不多,但要想了解透彻,恐怕还得深入Agent的相关代码,比如很难一目了然的理解addInterceptor和addScopedInterceptor的区别,而这两个方法就是位于Agent的有关类型中。 因为Brave的注入需要依赖底层框架提供相关接口,因此并不需要对框架有一个全面的了解,只需要知道能在什么地方注入,能够在注入的时候取得什么数据就可以了。就像上面的例子,我们根本不需要知道MySQL的JDBC Driver是如何实现的也可以做到拦截SQL的能力。但是Pinpoint就不然,因为Pinpoint几乎可以在任何地方注入任何代码,这需要开发人员对所需注入的库的代码实现有非常深入的了解,通过查看其MySQL和Http Client插件的实现就可以洞察这一点,当然这也从另外一个层面说明Pinpoint的能力确实可以非常强大,而且其默认实现的很多插件已经做到了非常细粒度的拦截。 针对底层框架没有公开API的时候,其实Brave也并不完全无计可施,我们可以采取AOP的方式,一样能够将相关拦截注入到指定的代码中,而且显然AOP的应用要比字节码注入简单很多。 以上这些直接关系到实现一个监控的成本,在Pinpoint的官方技术文档中,给出了一个参考数据。如果对一个系统集成的话,那么用于开发Pinpoint插件的成本是100,将此插件集成入系统的成本是0;但对于Brave,插件开发的成本只有20,而集成成本是10。从这一点上可以看出官方给出的成本参考数据是5:1。但是官方又强调了,如果有10个系统需要集成的话,那么总成本就是10 * 10 + 20 = 120,就超出了Pinpoint的开发成本100,而且需要集成的服务越多,这个差距就越大。 通用性和扩展性: 很显然,这一点上Pinpoint完全处于劣势,从社区所开发出来的集成接口就可见一斑。 Pinpoint的数据接口缺乏文档,而且也不太标准(参考论坛讨论帖),需要阅读很多代码才可能实现一个自己的探针(比如Node的或者PHP的)。而且团队为了性能考虑使用了Thrift作为数据传输协议标准,比起HTTP和JSON而言难度增加了不少。 社区支持: 这一点也不必多说,Zipkin由Twitter开发,可以算得上是明星团队,而Naver的团队只是一个默默无闻的小团队(从#1759[2]的讨论中可以看出)。虽然说这个项目在短期内不太可能消失或停止更新,但毕竟不如前者用起来更加放心。而且没有更多社区开发出来的插件,让Pinpoint只依靠团队自身的力量完成诸多框架的集成实属困难,而且他们目前的工作重点依然是在提升性能和稳定性上。 其他: Pinpoint在实现之初就考虑到了性能问题,www.naver.com网站的后端某些服务每天要处理超过200亿次的请求,因此他们会选择Thrift的二进制变长编码格式、而且使用UDP作为传输链路,同时在传递常量的时候也尽量使用数据参考字典,传递一个数字而不是直接传递字符串等等。这些优化也增加了系统的复杂度:包括使用Thrift接口的难度、UDP数据传输的问题、以及数据常量字典的注册问题等等。 相比之下,Zipkin使用熟悉的Restful接口加JSON,几乎没有任何学习成本和集成难度,只要知道数据传输结构,就可以轻易的为一个新的框架开发出相应的接口。 另外Pinpoint缺乏针对请求的采样能力,显然在大流量的生产环境下,不太可能将所有的请求全部记录,这就要求对请求进行采样,以决定什么样的请求是我需要记录的。Pinpoint和Brave都支持采样百分比,也就是百分之多少的请求会被记录下来。但是,除此之外Brave还提供了Sampler接口,可以自定义采样策略,尤其是当进行A/B测试的时候,这样的功能就非常有意义了。 总结: 从短期目标来看,Pinpoint确实具有压倒性的优势:无需对项目代码进行任何改动就可以部署探针、追踪数据细粒化到方法调用级别、功能强大的用户界面以及几乎比较全面的Java框架支持。但是长远来看,学习Pinpoint的开发接口,以及未来为不同的框架实现接口的成本都还是个未知数。相反,掌握Brave就相对容易,而且Zipkin的社区更加强大,更有可能在未来开发出更多的接口。在最坏的情况下,我们也可以自己通过AOP的方式添加适合于我们自己的监控代码,而并不需要引入太多的新技术和新概念。而且在未来业务发生变化的时候,Pinpoint官方提供的报表是否能满足要求也不好说,增加新的报表也会带来不可以预测的工作难度和工作量。 Tracing和Monitor区别 Monitor可分为系统监控和应用监控。系统监控比如CPU,内存,网络,磁盘等等整体的系统负载的数据,细化可具体到各进程的相关数据。这一类信息是直接可以从系统中得到的。应用监控需要应用提供支持,暴露了相应的数据。比如应用内部请求的QPS,请求处理的延时,请求处理的error数,消息队列的队列长度,崩溃情况,进程垃圾回收信息等等。Monitor主要目标是发现异常,及时报警。 Tracing的基础和核心都是调用链。相关的Metric大多都是围绕调用链分析得到的。Tracing主要目标是系统分析。提前找到问题比出现问题后再去解决更好。Tracing和应用级的Monitor技术栈上有很多共同点。都有数据的采集,分析,存储和展式。只是具体收集的数据维度不同,分析过程不一样。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 链路 微服务

  • 深入理解JWT的使用场景和优劣

    经过前面两篇文章《JSON Web Token - 在Web应用间安全地传递信息》《八幅漫画理解使用JSON Web Token设计单点登录系统》的科普,相信大家应该已经知道了 JWT 协议是什么了。至少看到 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxaWFubWlJZCI6InFtMTAzNTNzaEQiLCJpc3MiOiJhcHBfcW0xMDM1M3NoRCIsInBsYXRmb3JtIjoiYXBwIn0.cMNwyDTFVYMLL4e7ts50GFHTvlSJLDpePtHXzu7z9j4 这样形如 A.B.C 的字符串时能敏感地认出这是使用了 jwt。发了这两篇文章后,有不少读者在文末留言,表达了对 jwt 使用方式的一些疑惑,以及到底哪些场景适合使用 jwt。我并不是 jwt 方面的专家,和不少读者一样,起初研究时我也存在相同疑惑,甚至在逐渐接触后产生了更大的疑惑,经过这段时间项目中的使用和一些自己思考,把个人的总结整理成此文。 编码,签名,加密 这些基础知识简单地介绍下,千万别搞混了三个概念。在 jwt 中恰好同时涉及了这三个概念,笔者用大白话来做下通俗的讲解(非严谨定义,供个人理解) 编码(encode)和解码(decode) 一般是编码解码是为了方便以字节的方式表示数据,便于存储和网络传输。整个 jwt 串会被置于 http 的 Header 或者 url 中,为了不出现乱码解析错误等意外,编码是有必要的。在 jwt 中以.分割的三个部分都经过 base64 编码(secret 部分是否进行 base64 编码是可选的,header 和 payload 则是必须进行 base64 编码)。注意,编码的一个特点:编码和解码的整个过程是可逆的。得知编码方式后,整个 jwt 串便是明文了,随意找个网站验证下解码后的内容: base64 所以注意一点,payload 是一定不能够携带敏感数据如密码等信息的。 签名(signature) 签名的目的主要是为了验证我是“我”。jwt 中常用的签名算法是 HS256,可能大多数人对这个签名算法不熟悉,但 md5,sha 这样的签名算法肯定是为人熟知的,签名算法共同的特点是整个过程是不可逆的。由于签名之前的主体内容(header,payload)会携带在 jwt 字符串中,所以需要使用带有密钥(yuè)的签名算法,密钥是服务器和签发者共享的。header 部分和 payload 部分如果被篡改,由于篡改者不知道密钥是什么,也无法生成新的 signature 部分,服务端也就无法通过,在 jwt 中,消息体是透明的,使用签名可以保证消息不被篡改。 前面转载的文章中,原作者将 HS256 称之为加密算法,不太严谨。 加密(encryption) 加密是将明文信息改变为难以读取的密文内容,使之不可读。只有拥有解密方法的对象,经由解密过程,才能将密文还原为正常可读的内容。加密算法通常按照加密方式的不同分为对称加密(如 AES)和非对称加密(如 RSA)。你可能会疑惑:“jwt 中哪儿涉及加密算法了?”,其实 jwt 的 第一部分(header) 中的 alg 参数便可以指定不同的算法来生成第三部分(signature),大部分支持 jwt 的框架至少都内置 rsa 这种非对称加密方式。这里诞生了第一个疑问 疑问:一提到 rsa,大多数人第一想到的是非对称加密算法,而 jwt 的第三部分明确的英文定义是 signature,这不是矛盾吗? 划重点! rsa 加密和 rsa 签名 是两个概念!(吓得我都换行了) 这两个用法很好理解: 既然是加密,自然是不希望别人知道我的消息,只有我自己才能解密,所以公钥负责加密,私钥负责解密。这是大多数的使用场景,使用 rsa 来加密。 既然是签名,自然是希望别人不能冒充我发消息,只有我才能发布签名,所以私钥负责签名,公钥负责验证。 所以,在客户端使用 rsa 算法生成 jwt 串时,是使用私钥来“加密”的,而公钥是公开的,谁都可以解密,内容也无法变更(篡改者无法得知私钥)。 所以,在 jwt 中并没有纯粹的加密过程,而是使加密之虚,行签名之实。 什么场景该适合使用jwt? 来聊聊几个场景,注意,以下的几个场景不是都和jwt贴合。 一次性验证 比如用户注册后需要发一封邮件让其激活账户,通常邮件中需要有一个链接,这个链接需要具备以下的特性:能够标识用户,该链接具有时效性(通常只允许几小时之内激活),不能被篡改以激活其他可能的账户…这种场景就和 jwt 的特性非常贴近,jwt 的 payload 中固定的参数:iss 签发者和 exp 过期时间正是为其做准备的。 restful api 的无状态认证 使用 jwt 来做 restful api 的身份认证也是值得推崇的一种使用方案。客户端和服务端共享 secret;过期时间由服务端校验,客户端定时刷新;签名信息不可被修改…spring security oauth jwt 提供了一套完整的 jwt 认证体系,以笔者的经验来看:使用 oauth2 或 jwt 来做 restful api 的认证都没有大问题,oauth2 功能更多,支持的场景更丰富,后者实现简单。 使用 jwt 做单点登录+会话管理(不推荐) 在《八幅漫画理解使用JSON Web Token设计单点登录系统》一文中提及了使用 jwt 来完成单点登录,本文接下来的内容主要就是围绕这一点来进行讨论。如果你正在考虑使用 jwt+cookie 代替 session+cookie ,我强力不推荐你这么做。 首先明确一点:使用 jwt 来设计单点登录系统是一个不太严谨的说法。首先 cookie+jwt 的方案前提是非跨域的单点登录(cookie 无法被自动携带至其他域名),其次单点登录系统包含了很多技术细节,至少包含了身份认证和会话管理,这还不涉及到权限管理。如果觉得比较抽象,不妨用传统的 session+cookie 单点登录方案来做类比,通常我们可以选择 spring security(身份认证和权限管理的安全框架)和 spring session(session 共享)来构建,而选择用 jwt 设计单点登录系统需要解决很多传统方案中同样存在和本不存在的问题,以下一一详细罗列。 jwt token泄露了怎么办? 前面的文章下有不少人留言提到这个问题,我则认为这不是问题。传统的 session+cookie 方案,如果泄露了 sessionId,别人同样可以盗用你的身份。扬汤止沸不如釜底抽薪,不妨来追根溯源一下,什么场景会导致你的 jwt 泄露。 遵循如下的实践可以尽可能保护你的 jwt 不被泄露:使用 https 加密你的应用,返回 jwt 给客户端时设置 httpOnly=true 并且使用 cookie 而不是 LocalStorage 存储 jwt,这样可以防止 XSS 攻击和 CSRF 攻击(对这两种攻击感兴趣的童鞋可以看下 spring security 中对他们的介绍CSRF,XSS) 你要是正在使用 jwt 访问一个接口,这个时候你的同事跑过来把你的 jwt 抄走了,这种泄露,恕在下无力 secret如何设计 jwt 唯一存储在服务端的只有一个 secret,个人认为这个 secret 应该设计成和用户相关的属性,而不是一个所有用户公用的统一值。这样可以有效的避免一些注销和修改密码时遇到的窘境。 注销和修改密码 传统的 session+cookie 方案用户点击注销,服务端清空 session 即可,因为状态保存在服务端。但 jwt 的方案就比较难办了,因为 jwt 是无状态的,服务端通过计算来校验有效性。没有存储起来,所以即使客户端删除了 jwt,但是该 jwt 还是在有效期内,只不过处于一个游离状态。分析下痛点:注销变得复杂的原因在于 jwt 的无状态。我提供几个方案,视具体的业务来决定能不能接受。 仅仅清空客户端的 cookie,这样用户访问时就不会携带 jwt,服务端就认为用户需要重新登录。这是一个典型的假注销,对于用户表现出退出的行为,实际上这个时候携带对应的 jwt 依旧可以访问系统。 清空或修改服务端的用户对应的 secret,这样在用户注销后,jwt 本身不变,但是由于 secret 不存在或改变,则无法完成校验。这也是为什么将 secret 设计成和用户相关的原因。 借助第三方存储自己管理 jwt 的状态,可以以 jwt 为 key,实现去 redis 一类的缓存中间件中去校验存在性。方案设计并不难,但是引入 redis 之后,就把无状态的 jwt 硬生生变成了有状态了,违背了 jwt 的初衷。实际上这个方案和 session 都差不多了。 修改密码则略微有些不同,假设号被到了,修改密码(是用户密码,不是 jwt 的 secret)之后,盗号者在原 jwt 有效期之内依旧可以继续访问系统,所以仅仅清空 cookie 自然是不够的,这时,需要强制性的修改 secret。在我的实践中就是这样做的。 续签问题 续签问题可以说是我抵制使用 jwt 来代替传统 session 的最大原因,因为 jwt 的设计中我就没有发现它将续签认为是自身的一个特性。传统的 cookie 续签方案一般都是框架自带的,session 有效期 30 分钟,30 分钟内如果有访问,session 有效期被刷新至 30 分钟。而 jwt 本身的 payload 之中也有一个 exp 过期时间参数,来代表一个 jwt 的时效性,而 jwt 想延期这个 exp 就有点身不由己了,因为 payload 是参与签名的,一旦过期时间被修改,整个 jwt 串就变了,jwt 的特性天然不支持续签! 如果你一定要使用 jwt 做会话管理(payload 中存储会话信息),也不是没有解决方案,但个人认为都不是很令人满意 每次请求刷新 jwt jwt 修改 payload 中的 exp 后整个 jwt 串就会发生改变,那…就让它变好了,每次请求都返回一个新的 jwt 给客户端。太暴力了,不用我赘述这样做是多么的不优雅,以及带来的性能问题。 但,至少这是最简单的解决方案。 只要快要过期的时候刷新 jwt 一个上述方案的改造点是,只在最后的几分钟返回给客户端一个新的 jwt。这样做,触发刷新 jwt 基本就要看运气了,如果用户恰巧在最后几分钟访问了服务器,触发了刷新,万事大吉;如果用户连续操作了 27 分钟,只有最后的 3 分钟没有操作,导致未刷新 jwt,无疑会令用户抓狂。 完善 refreshToken 借鉴 oauth2 的设计,返回给客户端一个 refreshToken,允许客户端主动刷新 jwt。一般而言,jwt 的过期时间可以设置为数小时,而 refreshToken 的过期时间设置为数天。 我认为该方案并可行性是存在的,但是为了解决 jwt 的续签把整个流程改变了,为什么不考虑下 oauth2 的 password 模式和 client 模式呢? 使用 redis 记录独立的过期时间 实际上我的项目中由于历史遗留问题,就是使用 jwt 来做登录和会话管理的,为了解决续签问题,我们在 redis 中单独会每个 jwt 设置了过期时间,每次访问时刷新 jwt 的过期时间,若 jwt 不存在与 redis 中则认为过期。 tips:精确控制 redis 的过期时间不是件容易的事,可以参考我最近的一篇借助于 spring session 讲解 redis 过期时间的排坑记录。 同样改变了 jwt 的流程,不过嘛,世间安得两全法。我只能奉劝各位还未使用 jwt 做会话管理的朋友,尽量还是选用传统的 session+cookie 方案,有很多成熟的分布式 session 框架和安全框架供你开箱即用。 jwt,oauth2,session千丝万缕的联系 具体的对比不在此文介绍,就一位读者的留言回复下它的提问 这么长一个字符串,还不如我把数据存到数据库,给一个长的很难碰撞的key来映射,也就是专用token。 这位兄弟认为 jwt 太长了,是不是可以考虑使用和 oauth2 一样的 uuid 来映射。这里面自然是有问题的,jwt 不仅仅是作为身份的认证(验证签名是否正确,签发者是否存在,有限期是否过期),还在其 payload 中存储着会话信息,这是 jwt 和 session 的最大区别,一个在客户端携带会话信息,一个在服务端存储会话信息。如果真的是要将 jwt 的信息置于在共享存储中,那再找不到任何使用 jwt 的意义了。 jwt 和 oauth2 都可以用于 restful 的认证,就我个人的使用经验来看,spring security oauth2 可以很好的使用多种认证模式:client 模式,password 模式,implicit 模式(authorization code 模式不算单纯的接口认证模式),也可以很方便的实现权限控制,什么样的 api 需要什么样的权限,什么样的资源需要什么样的 scope…而 jwt 我只用它来实现过身份认证,功能较为单一(可能是我没发现更多用法)。 总结 在 web 应用中,使用 jwt 代替 session 存在不小的风险,你至少得解决本文中提及的那些问题,绝大多数情况下,传统的 cookie-session 机制工作得更好。jwt 适合做简单的 restful api 认证,颁发一个固定有效期的 jwt,降低 jwt 暴露的风险,不要对 jwt 做服务端的状态管理,这样才能体现出 jwt 无状态的优势。 可能对 jwt 的使用场景还有一些地方未被我察觉,后续会研究下 spring security oauth jwt 的源码,不知到时会不会有新发现。

    架构师社区 redis session JWT

  • 某华为程序员爆料:主动离职,公司竟也给n+1,到手15万,华为真良心!

    都说分手能看出一个人的人品,离职能看出一家公司的良心。由于大多数公司都追逐利益、压榨员工,因此许多人的离职经历都是不大愉快的,但也不乏例外。 一个程序员发帖表扬华为是良心公司,自己主动提出离职,竟然也给了n+1的补偿,干了四年,发了五个月的工资。问了下之前离职的员工,如果是被动裁员,赔偿就是n+4。楼主感叹:在这个为了一点裁员赔偿不断pua的行业里,华为员工完全不会为此心累,良心啊! 在大家为了年终奖、裁员赔偿等合法权利奋力抗争的时候,楼主的经历真是一股难得的清流。网友们纷纷夸赞华为“牛”、“大气”、“厉害”、“良心”。有人已经对华为黑转粉,华为果然财大气粗,中小企业可没有这等胸襟气度和能力。 大家都无比羡慕,有人立即打听华为还招人吗?其他公司的员工表示自己已经“身在曹营心在汉”了,好想去华为办手续。 有知情者说,现在的离职赔偿还算少的,当年自己的赔偿是上一年的工资、年终奖总和的12分之n+1。 有人说自己当年也拿了四万多。 有人说这大概算是精神损失费。 有人说华为内部没有pua,如果不爽可以砸键盘和别人吵架,而有的公司可能只会自我反思。 的确,相比华为,其他公司就没这么良心了。比如阿里是能省就省,能不给就不给。 一个海康员工1月份离职,年终奖一分钱没有。 滴滴员工说主动离职找老板要大礼包,公司宁愿拖着让员工划水也不给。 不过也有人开玩笑说华为的离职赔偿这么高,感觉是在鼓励大家跑路。 一个华为在职员工受到鼓励,开始蠢蠢欲动了……这位小哥,离职有风险,辞职需谨慎啊! 楼主还晒出了自己拿到的补偿,一共是15万多。 网友们纷纷感叹楼主工资高,一个月三万多,还只是基本工资,楼主是个大佬吧! 也有人觉得华为没楼主说得那么良心,虽然离职补贴高,但公积金低,其他互联网公司公积金比例是12%,按照年收入基数缴纳,入账比离职补贴多挺多。 有人说华为没有年假,不给年终奖,除了调休假任何假期都扣绩效和年终,这个怎么不说? 有人说给的这个n+1还不如早早去互联网公司赚得多,后悔自己没早点出来好好做人。 无论是什么样的人,总有人说好有人说不好,同理,无论是什么样的公司,也总有人说好有人说不好。华为可能在其他方面确有不足之处,但在离职补偿这方面的确不错。 相比于其他公司在辞退员工时拖拖拉拉不愿意给补偿,华为不仅给的多且痛快,还能给主动提出离职的员工补偿,实在难能可贵。 离职补偿是企业对员工之前工作成绩和辛劳的认可,也是企业良心和风度的一种体现。那些千方百计想让员工主动离职、不愿意给赔偿的企业就像分手就翻脸不认人的渣男渣女,其人品企品可见一斑。 建议其他公司也能像华为一样好聚好散,别在分手的时候露出丑陋面貌,这样员工即使离职,也能念着公司的好,风水轮流转,那些离职的员工没准什么时候还能反哺公司呢。

    架构师社区 华为 程序员

  • 百亿级流量的百度搜索中台,是怎么做监控的?

    本文首先会介绍什么是可观测性以及云原生时代为什么更要关注可观测性,然后阐述搜索中台是如何以极低的机器成本打造百亿流量的实时指标监控(Metrics)、分布式追踪(Traces)、日志查询(Logs)和拓扑分析(Topos)。 二、我们面临的挑战 1)超大系统规模 随着微服务化等技术的使用和新业务的接入,百度搜索中台的服务和实例规模不断增加,服务间的链路关系也日趋复杂,在这样一个庞大系统中建设可观测性,也面临着更多的挑战。 对于日志的trace来说,目前搜索中台天级别的请求量已经达到了百亿级别,如果使用常规的技术方案(如Dapper的思路),将日志放到集中式存储里,意味着我们要付出上百台机器资源,成本是非常高昂的。部分团队使用抽样或针对错误请求进行记录的方式,这种方式在搜索中台场景存在着明显问题:一. 抽样无法保证覆盖线上case。二. 很难有一种有效的方法识别错误请求,此外,用户对一些正常请求仍然有trace需求(如误召回问题)。 同样地,对于指标的数据聚合来说,在超大系统规模下,如何优化资源占用和时效,也是一个极具挑战的问题。 2)从应用到场景的观测要求 随着搜索中台业务场景的不断丰富,我们的观测视角也在发生着变化。过去更多关注的是应用维度的信息,而现在一个应用里可能有几十种业务场景,不同场景流量的规模是完全不同。如果只关注应用维度的指标,便可能在一些场景异常时,上层无法感知。如下图就是一个典型的例子:场景三的流量因为较小,无法从应用级别的指标中提现,因此在异常发生时,监控没有报警。同时,这种细分场景的指标也可以辅助上层做一定的决策,如不同的场景,其中一个场景通过同步加载,而另一场景通过异步加载,两者的超时要求是不一样的,这时候就可以通过这种细分场景的指标,指导我们做精细化的控制。 但是,从应用到场景的细分,导致系统的指标量级急剧扩大,达到了百万级。这对于指标的聚合和计算来说,就成为一个新的挑战。 3)对拓扑链路的宏观分析 在云原生架构下,应用与应用之间的连接关系变得越来越复杂。分布式追踪可以帮助我们定位某个具体请求的问题。而在系统出现一些宏观问题:流量剧增,97分位耗时增加,拒绝率增加等,就需要拓扑分析工具帮助我们进行定位。同时它对上层决策也有比较强的指导意义。如下图右侧的例子:商品搜索有两类场景,第1类场景有运营活动,预计增加300qps的流量,如果没有拓扑分析工具的话,我们就很难评估各个服务的容量Buffer。 我们在去年,对可观测性的四个要素进行了探索和实践,并发布了全要素的观测平台,为保障搜索中台的可用性提供了有力保障。 1)日志查询、分布式追踪 随着业务规模的增长,搜索中台整体的日志量级达到了PB级的规模,通过离线存储日志数据,再进行索引的方式会带来巨大的资源开销。而我们在这里使用了一种突破性的解决方案:在离线结合,离线存储了少量的种子信息,在线直接复用线上的日志(0成本)。 具体做法是: 在流量入口层将logid、ip、访问的时间戳存下来,存到一个kv存储里。 当用户使用logid检索的时候,在kv存储中查询logid对应的ip和时间戳。 通过ip和时间戳去对应的实例获取完整的日志信息。 通过规则解析日志,获取下游实例的ip和时间戳信息。 重复3-4的广度遍历过程,得到完整的调用链路拓扑。 但是这里仍然存在一个问题:Trace时间较长。 实例需要需要对自己的日志文件进行全量 grep,这在日志文件大、请求链路长的时候,会导致trace的时间较长,同时也会带来稳定性的冲击。这里我们使用了按时间动态N分搜索的思路,利用请求的时间信息和时间有序的日志结构,快速进行N分查找。 以下图给大家举例:图中日志文件是 20 点的日志文件,当前需要查询 20 : 15 分的一个日志请求。因为 15 分钟刚好是小时的 1/4,所以会先 fseek 这个文件的 1/4 位置。当前 1/4 段的日志信息在 20 : 13,这个时候下半段的日志文件就是 47 分钟的日志数据,那就会再往下偏移 2/47,重新进行fseek。重复这个过程就可以快速查询对应的详细日志信息。 这种检索方式可以获得非常快的收敛速度,单实例的日志检索耗时控制在 100ms 以内,对 io 的影响基本忽略不计。同时,用户整体的检索时间也控制在了秒级别。 2)指标监控 因为我们的观测视角从应用级别发展到了场景级别,指标数量也从万级别增加到了百万级别,所以我们对监控架构进行了重新设计。这张图就是升级后的一个架构图。 它的主要思想是线上实例嵌一个依赖库,这个依赖库会收集所有的指标信息,并将它做一定的预聚合,之后采集器轮询式的去获取线上的实例的指标数据,然后把聚合后的数据写到tsdb里。值得注意的一点,这套方案和业界的一些指标方案较大的不同:实例维度的指标会在采集器里实时聚合,转换成场景或服务维度的指标,随后实例的维度指标会被丢弃,不再存储到tsdb中。因为实例维度的指标参考意义有限,我们是使用聚合后的数据等来分析应用的运行情况。 在这套架构里,我们对计算和存储进行了很多的优化,从线上指标变化到平台展现,只需要2s的反馈时间,资源开销非常轻量。以指标的聚合为例:线上实例只进行累加操作,而采集器会存上一次抓取的快照信息,和当前这一次采集做对比,进行线性差值计算。这种方式对线上实例的资源开销是肉眼不可见的。同时也可以方便的去产出Qps、延迟等信息。 除了Qps、延迟之外,我们也优化了分位耗时的计算方式。 分位耗时的计算常规方案是将请求的耗时做排序,然后取它的分位位置上的耗时数值。这种计算方式在请求量级较高的时候,资源占用非常高。因此我们采用了分桶计算的方式,按请求的耗时进行分桶,当请求执行结束时,在对应耗时的桶里加1;而在计算分位值时,先确定分位值所在的桶,桶内数据则认为服从线性分布,通过这样的思路可以推导如下图的公式。 这样的好处是资源开销低,可实时计算,但是缺点是会损失一部分精度。这个精度取决于分桶的粒度,在搜索中台使用的桶大小是30ms,一般误差在15ms以内,可以满足性能观测的需求。 3)拓扑分析 拓扑分析的实现利用了指标监控的运作机制。 首先,对流量进行染色,并将染色信息通过RPC传递到各个服务。通过这种方式,让每个span(注:span的定义来自Dapper论文)持有场景的标识以及上游span的名称。场景标识可以区分不同场景的流量,而span名称和上游span名称可以建立父子的连接关系。这些span复用了上述指标计算的机制,通过将span的信息存入指标中,产出对应的性能数据。当用户提供一个场景标识时,平台会把它的全部指标提取出来,根据指标内的span信息,串联成完整的调用拓扑。 四、最后 到这里可观测性的四个基本要素基本讲述完了。在这四个要素之上,我们孵化了很多的应用产品,如历史快照、智能报警、拒绝分析等。通过这些产品,可以更好的帮助我们快速去发现和分析问题。 当然,可观测性的工作并不止步于此。我们也在依托这套观测系统,打造一些自适应、自调整的柔性机制,在异常出现时,能够自动容忍和恢复,最大化的保持系统的生命力。

    架构师社区 百度 搜索 搜索中台

  • 能量监测在直流系统中的作用

    能量监测在直流系统中的作用

    简介 电池供电类设备存在已久。然而自手机问世以来,由可充电电池供电的设备数量在过去二十年呈现出指数级增长。截至2018年,成千上万种型号的手机、平板电脑、笔记本电脑和许多其他小型电器都在使用锂电池。 对于所有便携式设备而言,功耗都是一个至关重要的因素。硬件开发人员越来越注重在增加功能、减小尺寸、降低成本的同时,实现低功耗方案。软件开发人员也以旧算法为切入点,针对操作系统领域(即通过能量监测调度)和新兴领域(例如机器学习),研发新的功率监测方法,力求降低功耗。功率是指瞬时消耗的能量。如公式1所示,在电学中,功率等于瞬时电压与电流之积。功率单位为瓦特(W),表示“焦耳每秒”。 公式1 - 功率公式 能量等于功率与时间的乘积。电路消耗能量,电池则存储能量。功率管理通常是指管理瞬时电流和电压,以满足功率传输能力和负载条件。能量监测通常会提供有关能耗的信息,从而帮助开发人员进行电池管理和总体功率基准测试。通过专门设计的软件(可根据特定负荷采取相应操作)监视能量时,即开始了主动能量管理。 主动能量管理可以基于预定义的设置自动进行,也可以在软件启动时手动进行,其作用是为用户提供特定的建议。例如,大多数笔记本电脑在使用电池而不是交流电源运行时,处理器性能会自动降低,并且改用低功耗、低性能的集成图形处理器,而不使用专用处理器。可以关闭笔记本电脑的一些外设,以延长电池供电时间,而用户也可能收到降低屏幕亮度或调暗键盘背光的通知。大多数智能手机都提供各种节能选项,当电池电量降至特定水平时,主动能量管理便会提出使用节能选项的建议,包括关闭一些现有的互联网连接、降低屏幕亮度等。 但类似情况并不限于电池供电设备。服务器会仔细监测功耗和负荷水平,以确定是否可以完全停止或暂停某些服务。在虚拟服务器中,可根据电流总用量和基于统计信息预测的用量增加和缩减应用。对于这类服务器,可以使用虚拟机管理程序完全关闭某些虚拟机。进行调试时,也可以使用主动能量管理。能量监测可提供非常有效的信息,用以确定整个系统或部分系统是否在界定范围内运行。 用于测量直流功率和能量的电路 如前文所述,电功率是电压与电流的乘积。要精确测量功率,需要对电压和电流进行精准测量。在一定时段内测量功率并将结果累加,即得到能量。功耗在大多数情况下都不是恒定值,因此,必须使用一个选定测量带宽,在此范围内对电压和电流进行测量。直流电压测量电路的一个典型示例是图1左侧所示的简单分压器和右侧图1所示的缓冲分压器。这两个电路都可以通过适当的校准提供高精度测量结果,尽管带缓冲的分压器比不带缓冲的分压器价格昂贵,但前者通常功耗更低,尤其适合测量极低的直流信号。 图1 - 分压器电路 虽然借助霍尔效应也可以测量电流(包括直流电流),但本文侧重于使用分流电阻测量直流电流,因为后者更常用而且费用更低。分流电阻是一个低阻值电阻,与电路串联。电流流经分流电阻时,分流电阻两端会产生一个小的压差。该压差与电流成正比,如公式2所示,并且通常使用运算放大器进行放大。 公式2 - 分流电阻两端的压差 由于分流电阻与电路的其余部分串联,因此可以连接在任意一侧:上桥臂(分流电阻的一个端子直接连接总线电压),或者下桥臂(分流电阻的一个端子接地),如图2所示。在这两种情况下,分流电阻都会出现一个小的压差,电路的总电压会降低。但是,分流电阻的连接位置会有一些影响: - 如果分流电阻放在下桥臂(图2右侧),其两端的电压将直接接地。由于分流电阻通常很小,其两端的压差也很小,因此电流测量电路使用便宜的低压运算放大器即可非常方便地放大压差。这对于缩减成本很有帮助。但下桥臂分流有一个明显的不足,即整个电路不再直接接地,而是连接高于接地端电压的位置。分流电阻两端的压差通常以毫伏计。 - 如果将分流电阻连接在上桥臂(图2左侧),则电路直接接地,可消除地弹反射效应。如果要对电路进行精确测量或必须提供精确的输出,则应选用此连接方法。此方法的唯一缺点是需要使用电压更高的差分运算放大器电路,并且视运算放大器的带宽而定,费用也可能会增加。 图2 - 电流测量电路 尽管电压、电流甚至功率本身都可以通过模拟电路轻松测量,而且成本很低,但能量测量却需要使用更复杂的电路来实现。然而,传统的能量测量方法是使用模拟电路测量电压和电流,然后使用模数转换器(ADC)将模拟信号转换为数字信号,将数据输出到单片机。单片机的作用是对信号随时间累加的功率进行采样,从而实现能量测量。测量能量的典型电路如图3所示。在测量电路中增加单片机既有优点也有缺点。一方面,在算法计算、监视不同行为和进行更详细的报告方面具有很大的灵活性,例如每小时、每天等。此外,单片机的作用不仅限于能量测量,还可以触发事件、运行自定义状态机或满足工程师的任何需求。而如果系统原本就需要使用单片机,则成本和物料清单(BOM)的增加并不是问题。另一方面,使用单片机监测能量的缺点则是测量系统的总功耗、令人讨厌的代码开发工作和开销成本都会增加,而且视精度要求而定,有时可能还需要外部ADC。 图3 - 典型的能量测量电路 多年来,随着业界对直流能量监测功能的需求不断增长,多种面向此类应用的集成电路相继问世。例如Microchip的PAC1934集成电路。此类集成电路只需使用分流电阻作为外部元件,即可轻松地同时对多达4个通道进行采样。基本电路图如图4所示。电路中集成了运算放大器、ADC、算术运算逻辑、存储器和用于连接系统的标准接口(通常为I2C或SPI)。与传统方法相比,使用集成电路的优势在成本方面尤为明显,这是因为在一个集成电路中集成了能量测量所需的一切,使BOM和PCB尺寸显著降低。 图4 - Microchip PAC1934框图(可同时测量4个通道) 主动能量监测的优势 凭借适合大多数用例的灵活配置,专用集成电路能够以极低的功耗在长时段内累加功率。通常,功率采样率最低为每秒8次采样,最高可达1 KSPS。例如,PAC1934以8 SPS运行时,可以累加超过36小时的功率,并且电流小于16 mA,同时4个通道全部有效且以16位的分辨率运行,无需软件干预。此方法允许采样率动态变化,从而可以扩大应用范围。例如在标准笔记本电脑中使用集成电路监测电源轨。当笔记本电脑处于运行和活动状态时,能够以1024 SPS的采样率进行监测,而当笔记本电脑处于挂起状态时,监测速度可能降到8 SPS,因为在挂起状态下,功耗不会有太大的波动。此外,降低采样率可以减少能量监测的功耗,而不会影响性能。 主动能量监测最常见的一个用例是电池电量计量。专用集成电路可监测电池的电压和电流,随时获知当前电池电量。更先进的电池电量计还可以检测到电池遇到了特定问题,例如电量计可以跟踪电池的电压与电量的关系,如果二者之间不再有对应关系,则意味着电池的总容量因老化或其他因素而缩减。主动能量监测也是标准电池管理系统(BMS)的核心。BMS是多节电池组所使用的电路,负责对电池组进行安全充电和放电,并主动测量其电压和电流,确保每节电池的参数都相同。BMS的功能还包括检测故障电池,或在电压过高或过低时断开电池组。 主动能量监测的另一个常见应用是与智能手机和平板电脑上的操作系统以及笔记本电脑、计算机和服务器上的Linux®或Microsoft Windows®搭配使用。对于智能手机和平板电脑,操作系统通过各种方法监测不同服务和应用程序所消耗的电量。在早期阶段,系统不直接测量能量,而是使用表格数据获取各个工作点的功耗,基于CPU、GPU和屏幕使用情况估算能量。估算出的能耗数据以统计数据的形式报告,便于用户决定如何进一步操作设备。自Windows 8起,Microsoft在笔记本电脑和个人计算机中引入了能量估计引擎(Energy Estimation Engine,E3)。E3早期阶段的工作原理与智能手机中的估算算法类似,能够根据各种资源的使用情况(处理器、图形、磁盘、存储器、网络和显示器等)来估算每项任务的功耗,从而实现功耗跟踪。E3还引入了能量计量接口(EMI),系统制造商可以通过该接口为系统添加实际可用的能量测量传感器,并进行相应声明。如果加入了此类传感器,E3会利用这些传感器准确地测量功率和能量,而不是只进行估算。某些笔记本电脑制造商已在其产品中实现了这些功能。此外,过去还存在一些其他的方法(例如Sony在Vaio笔记本中实现的能量监测),但没有支持这些方法的操作系统,只有专有应用程序才能访问相关数据。Linux尚未提供与Microsoft E3相当的工具,但据报道称,他们已着手进行相关工作。工业I/O子系统支持在操作系统中加入各种传感器,为用户空间的应用程序提供非常简单且功能强大的接口(基于文件的接口)。然而,在本文撰写之时,工业I/O子系统仍是内核的扩展,而不是默认Linux架构的组成部分。Linux还支持能量监测调度和智能功率分配,这是一种用于嵌入式Linux领域的算法,可帮助系统决定如何调度不同的任务,同时对热问题予以考量(能耗导致CPU/GPU发热)。 能量测量集成电路的另一个值得关注的应用,是对USB功率和能量(出于各种原因)以及在服务器应用程序中的使用情况进行监测,如本文第一部分所述。由于服务器采用不间断运行的设计,因此监测能耗有很多好处,例如可通过主动服务控制提高总体电源效率,能满足越来越高的能效标准,允许系统管理员在服务器的某些部分出现功耗异常(表示未来可能发生故障)时执行预测性维护。 总结 就能量监测的需求以及系统需要执行的其他功能而论,某些方法可能比其他方法更适用。如果嵌入式系统是根据自身用途专门构建,并且需要了解自身功耗或估算能耗,则传统方法更适用。我们还建议在单片机中加入内部ADC,以便最大限度缩减能量监测功能的成本。采用这种方法,只需要使用进行电压和电流检测的外部模拟电路。如果需要非常高的测量精度而不计BOM成本和功耗,则传统方法比集成电路更适用。 但在很多情况下,更适合采用集成电路方法。例如,如果想要在操作系统中集成能量测量,就适合采用集成电路方法,因为集成解决方案就是为解决这一问题而构建,通过适当的驱动程序,系统能自动识别出能量测量并知道如何操作。能量测量集成电路通常可以测量多个通道(从而监测多条总线),因此,在需要监测大量总线时,集成解决方案具备明显优势。此外,同一条通信总线上可以使用多个集成电路(例如I2C或SPI)。另一个更适合采用集成解决方案的情形是,在系统处于功耗极低的睡眠模式或完全关闭的情况下,在较长的一段时间内测量能量。集成的能量监测芯片仅消耗极少的功率,并能在特定时段内自行累加能量,无需任何系统干预,而这正是实现集成解决方案的基础。 对于有较高尺寸要求的高度集成化和密集型PCB(例如手机、平板电脑或笔记本电脑的主板),与等效的分立元件相比,集成电路占用的空间显然更小。例如,在WLCSP(晶圆级芯片封装)尺寸的芯片(大小为2.225 x 2.17 mm)中,包含一个能同时监测四个通道的能量测量集成电路。

    Microchip 电池 直流系统 能量监测

  • 一位资深程序员的亲身经历:跳槽国企要注意啥

    前几天我们写了一篇关于国企程序员的文章,相信有许多程序员都想去国企养老,但市面上的国企数量繁多,良莠不齐,该如何鉴别呢?一位资深程序员用自己的亲身经历给大家写了一篇攻略。 楼主工作十年,经历电网,移动,建行,阿里等企业,可谓资历丰富。由于最近网上无脑公务猿和国企吹盛行,某些猎头借势忽悠候选人,导致候选人去了假国企后悔,暗暗叫苦,但世上难有后悔药。楼主便写了这篇攻略,以电网,移动研究院,建信金科,中寨金科等企业为例,讨论真假国企,真假嫡系,以及如何鉴别猎头和hr的忽悠话术,建议想去国企的程序员们认真读一下。 楼主建议:首先,找工作是对自己负责的事情,但人性有弱点,有些人好不容易找到一个所谓的“国企”,就以为这个机会非常好,自己的选择非常明智,听不得别人劝,即使明知是坑也要自欺欺人跳进去,这类人就别往下看了,浪费时间和精力。那些学历和能力不行,只想清闲多金的人也别看了,现在环境太卷,没那么多好事从天上掉下来。 第二,为什么要去央企和国企?提前扪心自问一下自己图什么?是想要轻松稳定,还是喜欢开会写文档不想写代码,或是情商合适国企,亦或仅仅图一个体面?这个要想清楚。 另外,在国企做程序员,如果不是中层领导就别有太多幻想。某些人拿月入五千的国企对比互联网,理由是体面有权力,这个就是想多了。某些国企子公司加班多技术老,工资也一般,去了图什么呢?还不如去一个二三线的互联网,至少还能学点技术。 第三,哪些企业是重点央企?楼主附上了一张央企名录供大家参考,典型案例有电网,石油,运营商,保利等。友情提示:选择就业单位要看看背景是什么,财报怎么样,而不是随便一个看起来像国企名字的地方就无脑选,跳坑里都不知道。 另外,央企和国企那么大,下属好多直属机构、子公司和分公司,该如何选择?以电网和移动为例(下附图),最好的选择是总部,晋升和发展机会都好于地方上,可以获取很多信息,后期也可以考虑到分公司任职。其次是效益好的分公司,例如江浙移动分公司,或者老家所在的省分公司。再次是直属机构,例如移动北京研究院,整体轻松不累,有食堂和各种保险,只是在如今互联网的冲击下略显吃亏。 还有,央企和国企的直属机构、省分公司工资不高,需要纠结吗?楼主回答:没必要,这类地方过去就是另一个活法。例如移动和电网,有些在省分公司干了八年的员工平均工资甚至不如努力工作八年的外包,但他们也不会转岗到外包,毕竟工作强度低,工作内容舒适。移动的同事即使跳槽,也会去华为这类公司,因为他们很熟悉移动的业务和内部规则,所以可以拿高薪水,当然也会累一些。 那些定位清晰的子公司还是不错的,有很好的效益,且有母公司做强力背景,项目好奖金高。但央企和国企那些定位不清,或者加班钱少的子公司就是坑。 比如海康威视虽然定位清晰,但加班多,不见得稳定,还要被pua,不如去找个二线互联网赚点钱学学技术。而建信金科,中寨金科等企业,现在看起来迅猛发展,但定位不清晰,有些项目不盈利,普遍加班严重,名义上实现业务扩张,号称是总部福利,实际上就是一个子公司。 第四,楼主总结了一些常见的hr套路和招聘大坑。例如建信金科的hr都会说给总部编制,福利待遇也比总部好,如果真的这么好,建行总部原来的员工为什么不挤进来?如果遇到hr这么说,直接问他建行总部是什么福利?建信金科又是什么福利?建行总部什么工作强度,建信金科又是什么强度?千万不要被总行和总部的说法欺骗了,只是一个程序员而已,就算按照总部编制又能如何?能保证不淘汰吗?能保证不加班,工资高吗?还是能保证有很好的晋升途径?如果以上几点都没有,不如安心按照一个普通信息公司程序员定位自己。 最后,注意一些猎头常用套路:这是正经国企,有正式编制,不加班,工资比总部高,福利与总公司持平,由于某些业务扩张才有这个机会,很难得,并且扩张期间会有很多机会和挑战,奖金丰富。 此时要质疑:既然是业务扩张,说明事情多人手少,怎么可能不加班?这就是自相矛盾。 中寨金科的猎头还有更大的套路:这里都是来自bat的大牛。此时要多想想,bat大牛拿几百万高薪,自己做自己想做的事情不香吗?非要来这个子公司听甲方使唤? 一个网友表示:楼主走过的弯路都是宝贵经历,曾经自己也不知道很多信息,莽撞地离开了某运营商,现在才发现自己是个能力有限偏向安逸的人,然而已经没有回头路了,正在努力调整自己的方向,希望大家都能早日停船靠岸。 一个国企员工说,只有赚钱的国企才是真国企,其他无意义,编制这种东西现在也不是铁饭碗了。 还有人说有些所谓的假国企也挺好,真国企很少社招,且严格受到工资限制,只有子公司才让程序员跳槽时工资不会降太多。 楼主用自己的亲身经历给大家做了一份攻略,希望能对大家有所帮助。国企虽然香,但跳槽有风险,挑选需谨慎,如果进错了地方不仅不香,还得吃双倍的苦。明明是奔着加班少、清闲养老才选择的国企,结果加班一点不少,压力一点不小,不如在互联网加班,还能挣个高工资,学点技术。 国企选择很多,楼主举的例子只是其中一部分,但大家可以举一反三,在找其他行业的国企时也擦亮双眼,千万别掉坑里。毕竟找工作的黄金年龄就那么几年,弯路走多了,小心一时半会靠不了岸。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    架构师社区 程序员 国企

  • 业务高峰期不小心拔掉了服务器电源!!

    -----------------------------------------161108 23:36:45 mysqld_safe Starting mysqld daemon with  databases from /usr/local/mysql/var2021-02-28 23:36:46 0 [Warning] TIMESTAMP with implicit DEFAULT  value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).2021-02-28 23:36:46 5497 [Note] Plugin 'FEDERATED' is disabled.2021-02-28 23:36:46  7f11c48e1720 InnoDB: Warning: Using innodb_additional_mem_pool_size is DEPRECATED. This option may be  removed in future releases, together with the option innodb_use_sys_malloc and with the InnoDB's  internal memory allocator.2021-02-28 23:36:46 5497 [Note] InnoDB: Using atomics to ref count buffer  pool pages2021-02-28 23:36:46 5497 [Note] InnoDB: The InnoDB memory heap is disabled2021-02-28  23:36:46 5497 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins2021-02-28 23:36:46 5497  [Note] InnoDB: Memory barrier is not used2021-02-28 23:36:46 5497 [Note] InnoDB: Compressed tables  use zlib 1.2.32021-02-28 23:36:46 5497 [Note] InnoDB: Using CPU crc32 instructions2021-02-28 23:36:46 5497 [Note] InnoDB: Initializing buffer pool, size = 16.0M2021-02-28 23:36:46 5497 [Note] InnoDB:  Completed initialization of buffer poolInnoDB: Database page corruption on disk or a failedInnoDB:  file read of page 5.InnoDB: You may have to recover from a backup.2021-02-28 23:36:46 7f11c48e1720  InnoDB: Page dump in ascii and hex (16384 bytes): len 16384; hex  7478d078000000050000000000000000000000000f271f4d000700000000000000000000000000000000001b4000000000000 000000200f20000000000000006000000000000002d000000000000002e000000000000002f0000000000000030000000000( 省略很多类似代码)InnoDB: End of page dump2021-02-28 23:36:46 7f11c48e1720 InnoDB: uncompressed page,  stored checksum in field1 1954074744, calculated checksums for field1: crc32 993334256, innodb  2046145943, none 3735928559, stored checksum in field2 1139795846, calculated checksums for field2:  crc32 993334256, innodb 1606613742, none 3735928559, page LSN 0 254222157, low 4 bytes of LSN at page end 254221236, page number (if stored to page already) 5, space id (if created with >= MySQL-4.1.1  and stored already) 0InnoDB: Page may be a transaction system pageInnoDB: Database page corruption on disk or a failedInnoDB: file read of page 5.InnoDB: You may have to recover from a backup.InnoDB: It  is also possible that your operatingInnoDB: system has corrupted its own file cacheInnoDB: and  rebooting your computer removes theInnoDB: error.InnoDB: If the corrupt page is an index pageInnoDB:  you can also try to fix the corruptionInnoDB: by dumping, dropping, and reimportingInnoDB: the  corrupt table. You can use CHECKInnoDB: TABLE to scan your table for corruption.InnoDB: See also  http://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.htmlInnoDB: about forcing  recovery.InnoDB: Ending processing because of a corrupt database page.2021-02-28 23:36:46  7f11c48e1720  InnoDB: Assertion failure in thread 139714288817952 in file buf0buf.cc line 4201InnoDB: We intentionally generate a memory trap.InnoDB: Submit a detailed bug report to  http://bugs.mysql.com.InnoDB: If you get repeated assertion failures or crashes, evenInnoDB:  immediately after the mysqld startup, there may beInnoDB: corruption in the InnoDB tablespace. Please refer toInnoDB: http://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.htmlInnoDB: about  forcing recovery.03:36:46 UTC - mysqld got signal 6 ;This could be because you hit a bug. It is also possible that this binaryor one of the libraries it was linked against is corrupt, improperly  built,or misconfigured. This error can also be caused by malfunctioning hardware.We will try our best  to scrape up some info that will hopefully helpdiagnose the problem, but since we have already  crashed,something is definitely wrong and this may  fail.key_buffer_size=16777216read_buffer_size=262144max_used_connections=0max_threads=1000thread_coun t=0connection_count=0It is possible that mysqld could use up tokey_buffer_size + (read_buffer_size +  sort_buffer_size)*max_threads = 798063 K  bytes of memoryHope that's ok; if not, decrease some  variables in the equation.Thread pointer: 0x0Attempting backtrace. You can use the following  information to find outwhere mysqld died. If you see no messages after this, something wentterribly  wrong...stack_bottom = 0 thread_stack 0x40000/usr/local/mysql/bin/mysqld(my_print_stacktrace+0x35) [0x8e64b5]/usr/local/mysql/bin/mysqld(handle_fatal_signal+0x41b) [0x652fbb]/lib64/libpthread.so.0(+0xf7e0)[0x7f11c44c77e0]/lib64/libc.so.6(gsignal+0x35) [0x7f11c315d625]/lib64/libc.so.6(abort+0x175) [0x7f11c315ee05]/usr/local/mysql/bin/mysqld[0xa585c5]/usr/local/mysql/bin/mysqld[0xa6c7b4]/usr/local/ mysql/bin/mysqld[0xa6cbc7]/usr/local/mysql/bin/mysqld[0xa5bce2]/usr/local/mysql/bin/mysqld[0xa1e2ba]/usr/local/mysql/bin/mysqld[0xa0bf60]/usr/local/mysql/bin/mysqld[0x95a427]/usr/local/mysql/bin/mysqld(_Z24ha_initialize_handlertonP13st_plugin_int+0x48) [0x58f788]/usr/local/mysql/bin/mysqld[0x6e4a36]/usr/local/mysql/bin/mysqld(_Z11plugin_initPiPPci+0xb3e) [0x6e826e]/usr/local/mysql/bin/mysqld[0x582d85]/usr/local/mysql/bin/mysqld(_Z11mysqld_mainiPPc+0x4d8) [0x587d18]/lib64/libc.so.6(__libc_start_main+0xfd) [0x7f11c3149d5d]/usr/local/mysql/bin/mysqld[0x57a019]The manual page at  http://dev.mysql.com/doc/mysql/en/crashing.html containsinformation that should help you find out  what is causing the crash.161108 23:36:46 mysqld_safe mysqld from pid file  /usr/local/mysql/var/VM_241_49_centos.pid  ended------------------------------------------------------------------------------ 主库问题分析 从日志中可以看出是innodb引擎出了问题。日志里提示到 http://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.html查看强制恢复的方法。在mysql的配置文件my.cnf里找到 [mysqld]字段下,添加 innodb_force_recovery=1: insert into demo_bak select * from demo; 删除掉原表: alter table demo engine = innodb 第二种方法 另一个方法是使用mysqldump将表格导出,然后再导回到InnoDB表中。这两种方法的结果是相同的。备份导出(包括结构和数据): mysql -uroot -p123 test < test.sql; 注意,CHECK TABLE命令在InnoDB数据库中基本上是没有用的。 第三种方法 (1)配置my.cnf 配置innodb_force_recovery = 1或2——6几个数字,重启MySQL (2)导出数据脚本 mysql>show processlist; 查看下进程是否Sleep太多。发现很正常。 再查看下主库的状态。 mysql> show slave status\G                                                   Slave_IO_Running: Yes Slave_SQL_Running: No 发现是Slave不同步了。这里,如果主从数据库版本一致或不一致又会存在两种解决方案。 主从版本一致解决方案 下面介绍两种解决方法 方法一:忽略错误后,继续同步 该方法适用于主从库数据相差不大,或者要求数据可以不完全统一的情况,数据要求不严格的情况 解决: mysql> flush tables with read lock; 注意:该处是锁定为只读状态,语句不区分大小写 (2)进行数据备份 #把数据备份到mysql.bak.sql文件 scp mysql.bak.sql root@192.168.128.101:/tmp/ (5)停止从库的状态 change master to master_host = '192.168.128.100', master_user = 'rsync',  master_port=3306, master_password='', master_log_file = 'mysqld-bin.000001', master_log_pos=3260; (8)重新开启从同步 UNLOCK TABLES; 如果主从数据库的版本是一致的,以上述方式回复从数据库是没啥问题的,如果主从数据库版本不一致的话,以上述方式回复主从数据库可能还会存在问题。 主从版本不一致解决方案 如果MySQL主库和从库的版本不一致时,使用 show slave status \G命令查看从库状态时可能会看到如下所示的信息。 stop slave; set global slave_parallel_workers=0; start slave; 如果从库还是存在问题,则可按照主从版本一致的方案来恢复从库的数据。

    架构师社区 服务器 主库

  • 张一鸣:小成功需要朋友,大成功需要敌人

    来源| 技术领导力(ID:

    架构师社区 互联网 算法 张一鸣

发布文章