nginx的请求转发算法,如何配置根据权重转发
负载均衡策略:内置策略:轮询(默认)、加权轮询(处理1次连接则权重减1重新排序,所有机器down后重置所有机器的状态)、IP hash(经过20次hash仍找不到可用的机器时退化成轮询)、least_conn(把请求转发给连接数较少的后端服务器);扩展策略:fair(根据服务器响应时间判断负载,选出负载最轻的机器)、url_hash(按url的hash结果分配请求,每个请求的url会指向后端固定的某个服务器)、一致性hash;upstream配置参数:ip_hash、least_conn、weight(加权轮询的权重)、backup(标记备份服务器,主服务器挂掉才会处理请求)、down(标记服务器永久停机)、max_fails/fail_timeout/fail_time(fail_timeout时间内失败了max_fails次则认为服务器停机,停机时间为fail_time,默认10s);
zookeeper的实现机制,有缓存,如何存储注册服务的
Zookeeper是分布式协调服务,主要提供文件系统和通知机制2个功能;文件系统:提供多层级节点空间的树状结构,每个节点都可以存数据(包括目录),由于数据存放于内存,所有不能存储大量数据,单节点1M;节点znode类型:持久节点、持久有序节点、临时节点、临时有序节点;临时节点会话断开自动删除;有序通过父节点生成自增整数;通知机制watcher:通过观察者模式实现轻量级的通知机制,客户端注册某个znode节点的watcher、服务端处理watcher、客户端回调watcher;watcher是一次性的,触发后删除,避免节点频繁变更的性能问题;
服务提供者在启动的时候,会在ZooKeeper上注册服务,就是在ZooKeeper的service/version/ipport目录/providers节点下创建一个子节点,并写入自己的URL地址;服务消费者在启动的时候,会向ZooKeeper注册中心订阅自己的服务,就是读取并订阅ZooKeeper上对应服务名目录/providers节点下的所有子节点,并解析出所有提供者的URL地址来作为该服务地址列表,并在以服务名命名的目录/consumers节点下创建一个临时节点,并写入自己的URL地址;
zookeeper的事务,结点,服务提供方挂了如何告知消费方
客户端会随机连接到zookeeper集群中的一个节点,如果是读请求就直接从当前节点中读取数据,如果是写请求那么请求会被转发给leader提交事务,然后leader会广播事务,只要有超过半数节点写入成功,那么写请求就会被提交(类似2PC事务);所有事务请求必须由一个全局唯一的服务器来协调处理,这个服务器就是Leader服务器,其他的服务器就是follower;
注册中心集群挂掉之后消费者和生产者之前还能继续通信,因为消费者在启动时会从zk拉取注册的生产者的地址接口等数据缓存在本地,每次调用时按照本地存储的地址进行调用,集群挂掉之后只是不能同步最新的服务列表;
ZK提供心跳检测功能,会定时向服务提供者发送心跳请求,若长期没响应,服务中心会任务服务提供者挂掉而将其剔除;服务消费者会监听相应的路径,一旦发生变化,ZK会通知服务消费者更新服务列表;
如何用zk实现分布式锁,与redis分布式锁有和优缺点
利用Zookeeper创建临时有序节点来实现分布式锁;判断节点序号最小则加锁成功,否则注册Watcher事件等待前面节点(序号小的获取到锁的)通知则获取到锁;通过客户端加锁时将主机和线程信息写入锁中,下一次再来加锁时直接和序列最小的节点对比实现可重入,ZK自动删除会话断开的临时节点实现锁超时;ZK集群解决单点问题;通过curator框架可实现ZK分布式锁;
区别:Redis分布式锁需要自己不断去尝试获取锁,比较消耗性能;ZK分布式锁获取不到锁时注册监听器即可,不需要不断主动尝试获取锁,性能开销较小;Redis获取锁的客户端挂了之后只能等待超时释放,ZK只要客户端挂了会自动删除临时节点来释放锁;Redis锁是数值操作,ZK需要操作文件节点,总的来说Redis性能高些;
ZK 5台服务器如何选出leader(选举算法)
ZK集群是Master/Slave模式,通过ZAB(ZooKeeperAtomicBroadcast)原子广播协议进行选主,有两种基本的模式:崩溃恢复和消息广播,框架启动、Leader异常时进入崩溃恢复,已选举新Leader并且半数机器和leader完成同步后进入消息广播模式;
选举过程:每个服务器发起投票包括SID服务器ID和ZXID事务ID,第一次会先投自己,然后每个服务器收到所有投票并开始处理,优先选举ZXID和SID较大的服务器为Leader,每个服务器根据ZXID和SID决定是否更新自己的投票,再统计投票结果,超半数接受的SID即为Leader,最后更新服务器状态:LOOKING(选举中)、FOLLOWING(跟随者)、LEADING(领导者);当Leader挂掉之后,其他所有服务器进入LOOKING状态,重复上述过程选举新的Leader;
Zookeeper watch机制原理
通知机制watcher:客户端注册某个znode节点的watcher(将watcher封装到请求中)、服务端处理watcher(解析请求中的watcher放入注册管理器,后续请求解析时判断是否有watcher,有则通过TCP发送通知)、客户端回调watcher(线程接收事件处理);watcher是一次性的,触发后删除,避免节点频繁变更的性能问题;轻量,不传实体只传boolean;
Junit用法,before,beforeClass,after, afterClass的执行顺序
@BeforeClass、@AfterClass必须设置在public静态方法之上,表示在class加载之前执行,只会执行一次;@Before、@After则会再每次方法调用之前/之后执行;一个单元测试类执行顺序:@BeforeClass、@Before、@Test、@After、@AfterClass;一个单元测试方法执行顺序:@Before、@Test、@After;
Tomcat的各种配置,如何配置docBase
server.xml包括顶级组件server:1个Tomcat实例;容器组件:service:关联多个connector和1个engine;engine:通过connector接收请求,处理请求,转发请求到对应的host;host:虚拟主机;context:应用程序,docbase指定webapp本地文件路径,path指定访问URL;连接器组件connector:指定端口接收请求;被嵌套类组件:Valve:阀门,发送到webapp前拦截请求,实现如日志、IP控制等;realm:关联一个用户认证库,实现认证和授权,包括UserDatabaseRealm使用JNDI自定义、MemoryRealm使用tomcat-users.xml、JDBCRealm使用JDBC链接数据库;
简单讲讲Tomcat结构,以及其类加载器流程,线程模型等
Tomcat核心组件是Connector和Container,Connector通过Socket接收请求并将Socket请求封装成HttpRequest传给Container;Container封装和管理Servlet和处理请求并返回HttpResponse给Connector;Connector将HttpResponse转换成Socket返回给客户端;Container包括engine、host、context、wrapper4种,engine+Connector组成service并基于server对外提供服务;
类加载流程:4种类加载器,Bootstrap引导类加载器加载JVM启动类和扩展类;System系统类加载器加载Tomcat启动类如tomcat-juli.jar;webapp应用类加载器加载每个Web应用的WEB-INF/classes和WEB-INF/lib;Common通用类加载器加载通用类如servlet.jar;
线程模型:4种线程模型,BIO:阻塞IO,每个请求创建一个线程;NIO:同步非阻塞,8.0版本默认;APR:JNI形式调用动态链接库处理请求,需安装APR库;AIO:异步非阻塞,8.0版本后支持;
Tomcat如何调优,涉及哪些参数
优化:安全优化:普通用户启动、SHUTDOWN端口禁telnet、禁用AJP连接、删除多余的Root目录避免漏洞;性能优化:禁止DNS查询(Connector配置enableLookups=false)、JVM调优(catalina.sh增加JAVA_OPTS)、使用线程池(定义线程池Executor在Connector中使用)、使用NIO(Connector中配置protocol:bio/nio/nio2/apr);
是否用过maven instal、 maven test
mvn clean:删除target目录;mvn install:编译项目,并将项目打包发布到本地;mvn test:编译项目并运行测试代码;
Mongodb和Hbase的区别
1、HBase依赖于HDFS和ZK;MongoDB直接存储在本地磁盘中,不依赖其他三方组件;2、HBase基于列存储,按照列族将数据存储在不同的文件中;MongoDB基于文档存储,整个文档都存储在一个文件中;3、HBase一个region只有一个HRegionServer对外提供服务(没有负载均衡的概念);MongoDB的shards(类似于region)支持负载均衡(主从结构,通过日志进行同步)4、HBase根据文件的大小来控制region的分裂;MongoDB根据负载来决定shards的分裂;
git rebase
rebase通过合并多个commit解决分支树分叉,让分支树呈现线性的commit记录,可用于多个分支的合并;
Mybatis如何映射表结构
实体类属性名和表字段名相同时MyBatis会自动映射,否则可通过Select as别名、或者在XML中通过resultMap配置映射关系、或者通过注解@Result、@Column配置映射;
Mybatis的底层实现原理
Mybatis是半ORM框架,需要自己写SQL,内部封装了JDBC来连接数据库,所以数据库兼容性较好,可通过XML和注解完成映射和配置;通过Mapper接口的全限定名和接口方法定位到XML的SQL,将每个select/update等语句解析成MapperStatement对象,使用JDK动态代理为Mapper接口生成代理对象,调用对应的MapperStatement执行SQL;通过反射和SQL列名和对象属性映射创建对象并赋值完成查询结果的封装;
了解几种消息中间件产品?各产品的优缺点介绍
ActiveMQ、RabbitMQ、RocketMQ、Kafka、Redis;吞吐量:RocketMQ、Kafka高于ActiveMQ、RabbitMQ;延迟:RabbitMQ基于erlang实现,延迟最低;可用性:RocketMQ、Kafka实现了分布式,可用于高于ActiveMQ、RabbitMQ只实现了主从;消息可靠性:ActiveMQ低概率丢失数据;RabbitMQ管理界面较丰富;RocketMQ是阿里实现,社区活跃度没有其他3个高;只有RocketMQ 支持事务消息即保证消息的生产和发送的原子性;
消息中间件如何保证消息的一致性和如何进行消息的重试机制?
数据一致性指消息发送成功后即使leader挂了也能读取到该消息;Kafka是通过ISR机制保证的,Kafka中每个Topic有多个分区,每个分区有多个副本,不同副本保存在不同的broker,每个分区维护自己的ISR列表即与leader保持数据同步的副本列表,写入消息时会先发送给leader,leader再同步的把消息同步给ISR内的多个副本后再提交,再异步的把消息同步给ISR外的副本,所以即使leader挂了之后也可以从新的leader上消费消息;
Kafka重试机制比较简单,通过配置重试次数支持在特定异常时重试;自己可以通过新建Topic,将需要重试的消息写入Topic,再通过定时任务来处理实现完善的重试机制;RocketMQ通过重试队列(失败的消息加入)和死信队列(失败了指定次数的消息加入)实现了完善的重试机制,包括生产端和消费端两类重试机制,主要通过重试次数、重试时间、超时重试、异常重试控制;通过消息ID解决幂等性;
消息队列的使用场景
异步处理,应用解耦,流量削锋,消息通讯,日志收集;
如何保证消息的有序性
Kafka中对同一个分区的消息的生产和消费是有序的,可以通过将需要保序的消息设置Key来发送到同一个分区;另外消费端多线程处理(不是从分区消费)消息时,可通过对key进行hash将需要保序的消息维护到内部的多个队列里面,一个线程消费一个队列;
MQ系统的数据如何保证不丢失
发送消息不丢失:Kafka通过ack机制保证,每次发送都会有确认反馈机制,有3个状态:0:不等broker确认、1:leader确认,异步同步、-1:leader和ISR所有副本都确认;
消费消息不丢失:Kafka通过offset commit机制保证,Kafka在单独的Topic中保存了每次消费的offset,消费者重启时会从上次的offset处开始消费,commit时机也可以程序控制;
Broker消息不丢失:1个Topic多个分区,1个分区多个副本,不同副本保存在不同broker,每个分区维护自己的ISR(与leader保持同步的副本列表,定期消息同步,不同步则剔除),写入消息时先给leader,leader再同步的把消息同步给ISR内的多个副本,再提交,再异步的把消息同步给ISR外的副本;
Kafka吞吐量高的原因
partiton机制:1个Topic有多个partiton,partiton分布在不同节点且存储在本地文件夹且可在不同磁盘,1个partiton有多个segment,1个segment有1个数据和索引文件,从节点、磁盘、文件上都可并发,同时1个partiton只有1个消费者线程,避免竞争;ISR机制:可用性和一致性的动态平衡,动态复制,避免慢节点拖慢整体性能;顺序写磁盘:新消息顺序写入文件,读消息通过offset顺序读,删消息删整个segment文件,避免磁盘随机写;支持多磁盘:broker数据存储支持配置多个磁盘路径,不同分区数据尽量写到不同路径;零拷贝:用mmap作为文件读写方式的,直接把它传给sendfile,通过transferTo和transferFrom使用零拷贝读写文件;批处理:同一主题和分区的多条消息合并传输,并支持数据压缩;高效的序列化:可自定义使用更高效的序列化方式;
Kafka主从同步怎么实现
Kafka中同一个Topic可以被分配成多个Partition,每个Partition的可以有一个或者多个Replicas,即会有一个Leader以及0到多个Follower,在consumer读取数据的时候,只会从Leader上读取数据,Follower只是在Leader宕机的时候来替代Leader,主从同步有两种方式:同步复制和异步复制,Kafka采用的是中间策略ISR(In Sync Replicas),每个分区维护自己的ISR列表(与leader保持同步的副本列表,定期消息同步,不同步则剔除),写入消息时先给leader,leader再同步的把消息同步给ISR内的多个副本后再提交,再异步的把消息同步给ISR外的副本;
利用mq怎么实现最终一致性
在服务生产方和服务消费方中间加一层MQ,服务生产方保证消息发送成功,MQ保证消息不会丢失,服务消费方保证消息消费成功,每个服务保证自己的本地事务,如果生产方挂了可以直接回滚,MQ或消费方挂了由于消息还在所以可以再次消费从而保证最终一致性;另外RocketMQ支持事务消息,即保证消息生产和发送成功的原子性,可以更方便的解决上述问题,通过预先发送半消息及多次和MQ的确认交互实现;
使用Kafka有没有遇到什么问题,怎么解决的
问题一:消息的顺序问题,发送消息时通过指定key让同类消息发送到同一个分区解决;问题二:消息挤压多的问题,通过增加Topic分区和水平扩容消费者服务解决;问题三:消费不到消息,经常挂的问题,是Windows部署低版本的Bug,通过升级版本使用Linux部署解决;
MQ有可能发生重复消费,如何避免,如何做到幂等
MQ为了保证消息必达可能重复发送消息,首先需要MQ服务器内部生成唯一的和业务无关的消息ID:inner-msg-id来去重,重复的消息不持久化;然后消息发送的业务方发送消息时需要带上和业务相关的biz-id,消费方根据biz-id去重,通过MQ服务器和业务服务共同的处理达到幂等性;
MQ的消息延迟了怎么处理,消息可以设置过期时间么,过期了你们一般怎么处理
Kakfa处理消息延迟:1、根据业务逻辑调整max.poll.records与max.poll.interval.ms之间的平衡点,避免出现消费者被频繁踢出消费组导致重平衡; 2、消费线程逻辑轻量化;3、增加分区数和消费节点;ActiveMQ、Rabbitmq发送消息时可以设置消息过期时间,过期的消息可以设置自动删除或者单独写程序补偿发送;
netty的线程模型,netty如何基于reactor模型上实现的
Reactor线程模型:所有线程都是NIO线程,单线程模型:1个Reactor线程(完成所有IO操作包括接收、分发和处理),实现:ServerBootstrap().group(NioEventLoopGroup);多线程模型:1个Reactor线程(负责接收)+多个Acceptor线程(线程池,负责处理),实现:ServerBootstrap().group(NioEventLoopGroup(1),NioEventLoopGroup);主从模型:1个主Reactor线程(负责接收,只负责接入认证、握手等,然后重新注册到从Reactor)+多个从Reactor线程(线程池)+多个Acceptor线程(线程池,负责处理),实现:ServerBootstrap().group(NioEventLoopGroup,NioEventLoopGroup);
Netty的HashWheelTimer的用法,实现原理,是否出现过调用不够准时,怎么解决
HashedWheelTimer底层数据结构是DelayedQueue,加上时间轮的算法来实现;新建HashedWheelTimer实例的时候可以传入几个参数:时间长度(类似手表一圈的长度)、刻度数(类似手表的刻度,越大精度越细);添加一个任务时会根据任务得到一个hash值,并根据时间轮长度和刻度得到一个商值round(圈数)和模index(刻度),比如时间长度24小时,刻度为12,延迟时间为32小时,那么round=1,index=8。时间轮从开启之时起每24/12个时间走一个指针,即index+1,第一圈round=0。当走到第7个指针时,此时index=7,此时刚才的任务并不能执行,因为刚才的任务round=1,必须要等到下一轮index=7的时候才能执行;
时间轮对时间精度要求不高,内存占用较大,效率比延迟队列高;
Netty的心跳处理在弱网下怎么办
Netty实现心跳机制的关键就是利用IdleStateHandler来产生对应的idle 事件,一般是客户端负责发送心跳的PING消息, 当服务器收到客户端的 PING 消息时会发送一个 PONG 消息作为回复,一个 PING-PONG消息对就是一个心跳交互;客户端在监测到与服务器端的连接断开后,或者一开始就无法连接的情况下,使用指定的重连策略进行重连操作,直到重新建立连接或重试次数耗尽,对于如何监测连接是否断开,则是通过重写ChannelInboundHandler#channelInactive来实现,但连接不可用,该方法会被触发,所以只需要在该方法做好重连工作即可;
Netty的通讯协议是什么样的
通讯协议指的是把Netty通讯管道中的二进制流转换为对象、把对象转换成二进制流的过程,转换过程追根究底还是ChannelInboundHandler(二进制转对象)、ChannelOutboundHandler(对象转二进制)的实现类在进行处理,通过自定义编解码可以实现自己的通信协议,从而实现各种服务器如Http、FTP等;
为什么选择Netty
1、API 使用简单,开发门槛低;2、功能强大,预置了多种编解码功能,支持多种主流协议; 3、定制能力强,可以通过 ChannelHandler对通信框架进行灵活的扩展; 4、性能高,通过与其它业界主流的 NIO 框架对比,Netty 的综合性能最优; 5、成熟、稳定,社区活跃,版本迭代周期短,发现的BUG可以被及时修复,同时,更多的新功能会被加入; 6、经历了大规模的商业应用考验,质量已经得到验证,在互联网、大数据、网络游戏、企业应用、电信软件等众多行业得到成功商用,证明了它可以完全满足不同行业的商业应用;
ElasticSearch了解多少,以及一些调优手段
ElasticSearch是分布式搜索和处理平台,基于Lucene,可实现近实时查询;核心概念有索引:文档的集合,类似数据库;索引中的逻辑分类即类型,类似表;分片:一个索引被切成多块存在不同的服务器即分片,类似水平分表;包括主分片(默认5)和复制分片(默认1);一个分片包括多个segment;文档:索引和搜索的原子单位,JSON表示,由多个域(包含一个名字和多个值)组成;节点:集群通过名字标识,节点通过节点名字加入;分为主节点(管理所有变更)、数据节点(存储数据和倒排索引)、协调节点(处理客户端请求);使用:配置(集群和节点名称、数据和日志路径、改大操作系统默认文件描述符)、使用(提供内置RestAPI:_doc、_search等);
优化:1、冷热数据分离,冷数据存储机械硬盘,热数据可存储SSD提高效率;2、根据业务场景、通道、节点数通过合理规划索引数和分片数,分片大小不超过30G,一个索引不要创建多个Type;3、按照日期规划索引,可以方便的删除历史数据;使用别名管理索引;4、定时在后台空闲时对索引使用force_merge合并段来释放空间;5、根据是否需要精确查询、是否需要检索等设置合理的Mapping(类似表结构字段);6、仅针对需要分词的字段,合理的设置分词器;7、查询的优化,禁用wildcard,禁用批量terms,数据量大时先基于时间筛选,设置合理的路由机制;8、写入优化:写入前设置副本为0和关闭刷新,写入后恢复副本数和刷新间隔;9、采用批量请求并调整合适的提交大小;10、部署优化:磁盘容量留出足够的buffer,不要和其他耗内存的服务同机部署,内存CPU不要太小;
ElasticSearch的倒排索引是什么
倒排索引相反于一篇文章包含了哪些词,它从词出发记载了这个词在哪些文档中出现过,由词典和倒排表两部分组成;ES利用倒排索引对文档进行分词并维护一张分词字典、出现频率、出现的文档ID的表,提高了检索效率O(1);倒排索引的底层实现是基于FST(有限状态转换器)数据结构,FST有两个优点:空间占用小,重复利用了单词,压缩了存储空间;查询速度快;
ElasticSearch是如何实现master选举的
ES采用了多数派的思想选举Master,每个节点都可以成为候选主节点,只有候选主节点(master:true)的节点才能成为主节点;集群启动时或者Master挂掉时会进入Master选举流程,先确定候选主节点数是否达到多数节点,再优先选择节点id较小的节点为主节点;
详细描述一下Elasticsearch索引文档的过程
索引文档理解为文档写入ES并创建索引的过程,文档写入包含单文档写入和批量bulk写入;写文档过程:协调节点处理请求计算新文档加入哪个主分片;主分片完成后再请求副分片;过程:内存+操作日志translog(用于故障恢复)、文件系统缓存生成segment(每隔1秒生成1个)、写磁盘(fsync操作,文件系统缓存所有segment落盘并清空translog)、合并segment(1秒1个太多而优化);
详细描述一下Elasticsearch搜索的过程
查询文档包括查询和获取两个阶段,先查询需要查询哪些文档和segment(协调节点广播查询请求到所有相关分片,整合所有节点的响应并排序),再根据segment获取内容返回;
Elasticsearch在部署时,对Linux的设置有哪些优化方法?
关闭缓存Swap;设置最大文件句柄数;磁盘存储raid方式,存储有条件使用RAID10,增加单节点性能以及避免单节点存储故障;线程池+队列大小根据业务需要做调整
网友评论