首页 文章 精选 留言 我的

精选列表

搜索[面试],共4915篇文章
优秀的个人博客,低调大师

这10道springboot常见面试题你需要了解下

1、什么是Spring Boot? 多年来,随着新功能的增加,spring变得越来越复杂。只需访问https://spring.io/projects页面,我们就会看到可以在我们的应用程序中使用的所有Spring项目的不同功能。 如果必须启动一个新的Spring项目,我们必须添加构建路径或添加Maven依赖关系,配置应用程序服务器,添加spring配置。 因此,开始一个新的spring项目需要很多努力,因为我们现在必须从头开始做所有事情。 Spring Boot是解决这个问题的方法。Spring Boot已经建立在现有spring框架之上。使用spring启动,我们避免了之前我们必须做的所有样板代码和配置。 因此,Spring Boot可以帮助我们以最少的工作量,更加健壮地使用现有的Spring功能。 2、Spring Boot有哪些优点? 减少开发,测试时间和努力。 使用JavaConfig有助于避免使用XML。 避免大量的Maven导入和各种版本冲突。 提供意见发展方法。 通过提供默认值快速开始开发。 没有单独的Web服务器需要。这意味着你不再需要启动Tomcat,Glassfish或其他任何东西。 需要更少的配置 因为没有web.xml文件。只需添加用@ Configuration注释的类,然后添加用@Bean注释的方法,Spring将自动加载对象并像以前一样对其进行管理。您甚至可以将@Autowired添加到bean方法中,以使Spring自动装入需要的依赖关系中。 基于环境的配置 使用这些属性,您可以将您正在使用的环境传递到应用程序:-Dspring.profiles.active = {enviornment}。在加载主应用程序属性文件后,Spring将在(application{environment} .properties)中加载后续的应用程序属性文件。 3、什么是JavaConfig? Spring JavaConfig是Spring社区的产品,它提供了配置Spring IoC容器的纯Java方法。因此它有助于避免使用XML配置。使用JavaConfig的优点在于: 面向对象的配置。由于配置被定义为JavaConfig中的类,因此用户可以充分利用Java中的面向对象功能。一个配置类可以继承另一个,重写它的@Bean方法等。 减少或消除XML配置。基于依赖注入原则的外化配置的好处已被证明。但是,许多开发人员不希望在XML和Java之间来回切换。 JavaConfig为开发人员提供了一种纯Java方法来配置与XML配置概念相似的Spring容器。 从技术角度来讲,只使用JavaConfig配置类来配置容器是可行的,但实际上很多人认为将JavaConfig与XML混合匹配是理想的。 类型安全和重构友好。JavaConfig提供了一种类型安全的方法来配置Spring容器。由于Java 5.0对泛型的支持,现在可以按类型而不是按名称检索bean,不需要任何强制转换或基于字符串的查找。 4、如何重新加载Spring Boot上的更改,而无需重新启动服务器? 这可以使用DEV工具来实现。通过这种依赖关系,您可以节省任何更改,嵌入式tomcat将重新启动。 Spring Boot有一个开发工具(DevTools)模块,它有助于提高开发人员的生产力。Java开发人员面临的一个主要挑战是将文件更改自动部署到服务器并自动重启服务器。 开发人员可以重新加载Spring Boot上的更改,而无需重新启动服务器。这将消除每次手动部署更改的需要。Spring Boot在发布它的第一个版本时没有这个功能。 这是开发人员最需要的功能。DevTools模块完全满足开发人员的需求。该模块将在生产环境中被禁用。它还提供H2数据库控制台以更好地测试应用程序。 5、Spring Boot中的监视器是什么? Spring boot actuator是spring启动框架中的重要功能之一。Spring boot监视器可帮助您访问生产环境中正在运行的应用程序的当前状态。 有几个指标必须在生产环境中进行检查和监控。即使一些外部应用程序可能正在使用这些服务来向相关人员触发警报消息。监视器模块公开了一组可直接作为HTTP URL访问的REST端点来检查状态。 6、如何在Spring Boot中禁用Actuator端点安全性? 默认情况下,所有敏感的HTTP端点都是安全的,只有具有ACTUATOR角色的用户才能访问它们。 安全性是使用标准的HttpServletRequest.isUserInRole方法实施的。 我们可以使用management.security.enabled = false 来禁用安全性。只有在执行机构端点在防火墙后访问时,才建议禁用安全性。 如何在自定义端口上运行Spring Boot应用程序? 为了在自定义端口上运行Spring Boot应用程序,您可以在application.properties中指定端口。 server.port = 8090 7、什么是YAML? YAML是一种人类可读的数据序列化语言。它通常用于配置文件。 与属性文件相比,如果我们想要在配置文件中添加复杂的属性,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。 8、如何实现Spring Boot应用程序的安全性? 为了实现Spring Boot的安全性,我们使用 spring-boot-starter-security依赖项,并且必须添加安全配置。它只需要很少的代码。配置类将必须扩展WebSecurityConfigurerAdapter并覆盖其方法。 9、如何集成Spring Boot和ActiveMQ? 对于集成Spring Boot和ActiveMQ,我们使用spring-boot-starter-activemq 依赖关系。 它只需要很少的配置,并且不需要样板代码。 10、如何使用Spring Boot实现分页和排序? 使用Spring Boot实现分页非常简单。使用Spring Data-JPA可以实现将可分页的org.springframework.data.domain.Pageable传递给存储库方法。

优秀的个人博客,低调大师

看完这篇 Android ANR 分析,就可以和面试官装逼了!

ANR概述 首先,ANR(Application Not responding)是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。ANR由消息处理机制保证,Android在系统层实现了一套精密的机制来发现ANR,核心原理是消息调度和超时处理。 其次,ANR机制主体实现在系统层。所有与ANR相关的消息,都会经过系统进程(system_server)调度,然后派发到应用进程完成对消息的实际处理,同时,系统进程设计了不同的超时限制来跟踪消息的处理。 一旦应用程序处理消息不当,超时限制就起作用了,它收集一些系统状态,譬如CPU/IO使用情况、进程函数调用栈,并且报告用户有进程无响应了(ANR对话框)。 然后,ANR问题本质是一个性能问题。ANR机制实际上对应用程序主线程的限制,要求主线程在限定的时间内处理完一些最常见的操作(启动服务、处理广播、处理输入), 如果处理超时,则认为主线程已经失去了响应其他操作的能力。主线程中的耗时操作,譬如密集CPU运算、大量IO、复杂界面布局等,都会降低应用程序的响应能力。 哪些场景会造成ANR? 1. 发生ANR时会调用AppNotRespondingDialog.show()方法弹出对话框提示用户,该对话框的依次调用关系如下图所示: 2.AppErrors.appNotResponding(),该方法是最终弹出ANR对话框的唯一入口,调用该方法的场景才会有ANR提示,也可以认为在主线程中执行无论再耗时的任务,只要最终不调用该方法,都不会有ANR提示,也不会有ANR相关日志及报告;通过调用关系可以看出哪些场景会导致ANR,有以下四种场景: (1)Service Timeout:Service在特定的时间内无法处理完成 (2)BroadcastQueue Timeout:BroadcastReceiver在特定时间内无法处理完成 (3)ContentProvider Timeout:内容提供者执行超时 (4)inputDispatching Timeout: 按键或触摸事件在特定时间内无响应。 ANR机制 ANR机制可以分为两部分:ANR监测机制:Android对于不同的ANR类型(Broadcast, Service, InputEvent)都有一套监测机制。ANR报告机制:在监测到ANR以后,需要显示ANR对话框、输出日志(发生ANR时的进程函数调用栈、CPU使用情况等)。 整个ANR机制的代码也是横跨了Android的几个层:App层:应用主线程的处理逻辑;Framework层:ANR机制的核心,主要有AMS、BroadcastQueue、ActiveServices、InputmanagerService、InputMonitor、InputChannel、ProcessCpuTracker等;Native层:InputDispatcher.cpp; Provider超时机制遇到的比较少,暂不做分析;Broadcast目前主要想说两个知识点: 第一:无论是普通广播还是有序广播,最终广播接受者的onreceive都是串行执行的,可以通过Demo进行验证; 第二:通过Demo以及框架添加相关日志,都验证了普通广播也会有ANR监测机制,ANR机制以及问题分析文章认为只有串行广播才有ANR监测机制,后续再会专门讲解Broadcast发送及接收流程,同时也会补充Broadcast ANR监测机制;本文主要以Servie处理超时、输入事件分发超时为例探讨ANR监测机制。 Service超时监测机制 Service运行在应用程序的主线程,如果Service的执行时间超过20秒,则会引发ANR。 当发生Service ANR时,一般可以先排查一下在Service的生命周期函数中(onCreate(), onStartCommand()等)有没有做耗时的操作,譬如复杂的运算、IO操作等。 如果应用程序的代码逻辑查不出问题,就需要深入检查当前系统的状态:CPU的使用情况、系统服务的状态等,判断当时发生ANR进程是否受到系统运行异常的影响。 如何检测Service超时呢?Android是通过设置定时消息实现的。定时消息是由AMS的消息队列处理的(system_server的ActivityManager线程)。 AMS有Service运行的上下文信息,所以在AMS中设置一套超时检测机制也是合情合理的。 我们先抛出两个问题 问题一:Service启动流程? 问题一:如何监测Service超时? 主要通过以上两个问题来说明Service监测机制,在知道Service启动流程之后,通过Service启动流程可以更容易分析Service超时监测机制。 1. Service启动流程如下图所示: (1)ActiveServices.realStartServiceLocked()在通过app.thread的scheduleCreateService()来创建Service对象并调用Service.onCreate()后,接着又调用sendServiceArgsLocked()方法来调用Service的其他方法,如onStartCommand。以上两步均是进程间通信,应用与AMS之间跨进程通信可以参考应用进程与系统进程通信 (2)以上只是列出Service启动流程的关键步骤,具体每个方法主要做哪些工作还需要查看具体的代码,暂时先忽略这些,感兴趣的可以参考Android开发艺术探索等其他相关资料 2. Service超时监测机制 Service超时监测机制可以从Service启动流程中找到。 (1)ActiveServices.realStartServiceLocked()主要工作有 privatefinalvoidrealStartServiceLocked(ServiceRecordr, ProcessRecordapp,booleanexecInFg)throwsRemoteException{ ... //主要是为了设置ANR超时,可以看出在正式启动Service之前开始ANR监测; bumpServiceExecutingLocked(r,execInFg,"create"); //启动过程调用scheduleCreateService方法,最终会调用Service.onCreate方法; app.thread.scheduleCreateService(r,r.serviceInfo, //绑定过程中,这个方法中会调用app.thread.scheduleBindService方法 requestServiceBindingsLocked(r,execInFg); //调动Service的其他方法,如onStartCommand,也是IPC通讯 sendServiceArgsLocked(r,execInFg,true); } (2)bumpServiceExecutingLocked()会调用scheduleServiceTimeoutLocked()方法 voidscheduleServiceTimeoutLocked(ProcessRecordproc){ if(proc.executingServices.size()==0||proc.thread==null){ return; } Messagemsg=mAm.mHandler.obtainMessage( ActivityManagerService.SERVICE_TIMEOUT_MSG); msg.obj=proc; //在serviceDoneExecutingLocked中会remove该SERVICE_TIMEOUT_MSG消息, //当超时后仍没有removeSERVICE_TIMEOUT_MSG消息,则执行ActiveServices.serviceTimeout()方法; mAm.mHandler.sendMessageDelayed(msg, proc.execServicesFg?SERVICE_TIMEOUT:SERVICE_BACKGROUND_TIMEOUT); //前台进程中执行Service,SERVICE_TIMEOUT=20s;后台进程中执行Service,SERVICE_BACKGROUND_TIMEOUT=200s } (3)如果在指定的时间内还没有serviceDoneExecutingLocked()方法将消息remove掉,就会调用ActiveServices. serviceTimeout()方法 voidserviceTimeout(ProcessRecordproc){ ... finallongmaxTime=now- (proc.execServicesFg?SERVICE_TIMEOUT:SERVICE_BACKGROUND_TIMEOUT); ... //寻找运行超时的Service for(inti=proc.executingServices.size()-1;i>=0;i--){ ServiceRecordsr=proc.executingServices.valueAt(i); if(sr.executingStart<maxTime){ timeout=sr; break; } ... } ... //判断执行Service超时的进程是否在最近运行进程列表,如果不在,则忽略这个ANR if(timeout!=null&&mAm.mLruProcesses.contains(proc)){ anrMessage="executingservice"+timeout.shortName; } ... if(anrMessage!=null){ //当存在timeout的service,则执行appNotResponding,报告ANR mAm.appNotResponding(proc,null,null,false,anrMessage); } } (4)Service onCreate超时监测整体流程如下图 在onCreate生命周期开始执行前,启动超时监测,如果在指定的时间onCreate没有执行完毕(该该方法中执行耗时任务),就会调用ActiveServices.serviceTimeout()方法报告ANR;如果在指定的时间内onCreate执行完毕,那么就会调用ActivityManagerService.serviceDoneExecutingLocked()方法移除SERVICE_TIMEOUT_MSG消息,说明Service.onCreate方法没有发生ANR,Service是由AMS调度,利用Handler和Looper,设计了一个TIMEOUT消息交由AMS线程来处理,整个超时机制的实现都是在Java层;以上就是Service超时监测的整体流程。 输入事件超时监测 应用程序可以接收输入事件(按键、触屏、轨迹球等),当5秒内没有处理完毕时,则会引发ANR。 这里先把问题抛出来了: 输入事件经历了一些什么工序才能被派发到应用的界面? 如何检测到输入时间处理超时? 1.Android输入系统简介 Android输入系统总体流程与参与者如下图所示。 简单来说,内核将原始事件写入到设备节点中,InputReader在其线程循环中不断地从EventHub中抽取原始输入事件,进行加工处理后将加工所得的事件放入InputDispatcher的派发发队列中。InputDispatcher则在其线程循环中将派发队列中的事件取出,查找合适的窗口,将事件写入到窗口的事件接收管道中。窗口事件接收线程的Looper从管道中将事件取出,交由窗口事件处理函数进行事件响应。关键流程有:原始输入事件的读取与加工;输入事件的派发;输入事件的发送、接收与反馈。其中输入事件派发是指InputDispatcher不断的从派发队列取出事件、寻找合适的窗口进行发送的过程,输入事件的发送是InputDispatcher通过Connection对象将事件发送给窗口的过程。 InputDispatcher与窗口之间的跨进程通信主要通过InputChannel来完成。在InputDispatcher与窗口通过InputChannel建立连接之后,就可以进行事件的发送、接收与反馈;输入事件的发送和接收主要流程如图所示: 其中,将输入事件注入派发队列后,会唤醒派发线程,派发线程循环由InputDispatcher.dispatchOnce函数完成;InputDispatcher将事件以InputMessage写入InputChannel之后,窗口端的looper被唤醒,进而执行NativeInputReceiver::handleEvent()开始输入事件的接收,从InputEventReceiver开始输入事件被派发到用户界面;以上只是输入事件的大致流程,更详细的流程可以参考相关资料;在了解输入系统的大致流程之后,我们来分析输入事件的超时监测机制。 2.输入事件超时监测 按键事件超时监测整体流程如下图所示 (1)InputDispatcher::dispatchOnceInnerLocked(): 根据事件类型选择不同事件的处理方法:InputDispatcher::dispatchKeyLocked()或者InputDispatcher::dispatchMotionLocked(),我们以按键事件超时监测为例进行说明; (2)findFocusedWindowTargetsLocked()方法会调用checkWindowReadyForMoreInputLocked();该方法检查窗口是否有能力再接收新的输入事件;可能会有一系列的场景阻碍事件的继续派发,相关场景有: 场景1: 窗口处于paused状态,不能处理输入事件 “Waiting because the [targetType] window is paused.” 场景2: 窗口还未向InputDispatcher注册,无法将事件派发到窗口 “Waiting because the [targetType] window’s input channel is not registered with the input dispatcher. The window may be in the process of being removed.” 场景3: 窗口和InputDispatcher的连接已经中断,即InputChannel不能正常工作 “Waiting because the [targetType] window’s input connection is [status]. The window may be in the process of being removed.” 场景4: InputChannel已经饱和,不能再处理新的事件 “Waiting because the [targetType] window’s input channel is full. Outbound queue length: %d. Wait queue length: %d.” 场景5: 对于按键类型(KeyEvent)的输入事件,需要等待上一个事件处理完毕 “Waiting to send key event because the [targetType] window has not finished processing all of the input events that were previously delivered to it. Outbound queue length: %d. Wait queue length: %d.” 场景6: 对于触摸类型(TouchEvent)的输入事件,可以立即派发到当前的窗口,因为TouchEvent都是发生在用户当前可见的窗口。但有一种情况, 如果当前应用由于队列有太多的输入事件等待派发,导致发生了ANR,那TouchEvent事件就需要排队等待派发。 “Waiting to send non-key event because the %s window has not finished processing certain input events that were delivered to it over %0.1fms ago. Wait queue length: %d. Wait queue head age: %0.1fms.” 以上这些场景就是我们常在日志中看到的ANR原因的打印。 (3)其中事件分发5s限制定义在InputDispatcher.cpp;InputDispatcher::handleTargetsNotReadyLocked()方法中如果事件5s之内还没有分发完毕,则调用InputDispatcher::onANRLocked()提示用户应用发生ANR; //默认分发超时间为5s constnsecs_tDEFAULT_INPUT_DISPATCHING_TIMEOUT=5000*1000000LL; int32_tInputDispatcher::handleTargetsNotReadyLocked(nsecs_tcurrentTime, constEventEntry*entry, constsp<InputApplicationHandle>&applicationHandle, constsp<InputWindowHandle>&windowHandle, nsecs_t*nextWakeupTime,constchar*reason){ //1.如果当前没有聚焦窗口,也没有聚焦的应用 if(applicationHandle==NULL&&windowHandle==NULL){ ... }else{ //2.有聚焦窗口或者有聚焦的应用 if(mInputTargetWaitCause!=INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY){ //获取等待的时间值 if(windowHandle!=NULL){ //存在聚焦窗口,DEFAULT_INPUT_DISPATCHING_TIMEOUT事件为5s timeout=windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT); }elseif(applicationHandle!=NULL){ //存在聚焦应用,则获取聚焦应用的分发超时时间 timeout=applicationHandle->getDispatchingTimeout( DEFAULT_INPUT_DISPATCHING_TIMEOUT); }else{ //默认的分发超时时间为5s timeout=DEFAULT_INPUT_DISPATCHING_TIMEOUT; } } } //如果当前时间大于输入目标等待超时时间,即当超时5s时进入ANR处理流程 //currentTime就是系统的当前时间,mInputTargetWaitTimeoutTime是一个全局变量, if(currentTime>=mInputTargetWaitTimeoutTime){ //调用ANR处理流程 onANRLocked(currentTime,applicationHandle,windowHandle, entry->eventTime,mInputTargetWaitStartTime,reason); //返回需要等待处理 returnINPUT_EVENT_INJECTION_PENDING; } } (4)当应用主线程被卡住的事件,再点击该应用其它组件也是无响应,因为事件派发是串行的,上一个事件不处理完毕,不会处理下一个事件。 (5)Activity.onCreate执行耗时操作,不管用户如何操作都不会发生ANR,因为输入事件相关监听机制还没有建立起来;InputChannel通道还没有建立 这时是不会响应输入事件,InputDispatcher还不能事件发送到应用窗口,ANR监听机制也还没有建立,所以此时是不会报告ANR的。 (6)输入事件由InputDispatcher调度,待处理的输入事件都会进入队列中等待,设计了一个等待超时的判断,超时机制的实现在Native层。 以上就是输入事件ANR监测机制;具体逻辑请参考相关源码; ANR报告机制 无论哪种类型的ANR发生以后,最终都会调用 AppErrors.appNotResponding() 方法,所谓“殊途同归”。这个方法的职能就是向用户或开发者报告ANR发生了。 最终的表现形式是:弹出一个对话框,告诉用户当前某个程序无响应;输入一大堆与ANR相关的日志,便于开发者解决问题。 finalvoidappNotResponding(ProcessRecordapp,ActivityRecordactivity, ActivityRecordparent,booleanaboveSystem,finalStringannotation){ ... if(ActivityManagerService.MONITOR_CPU_USAGE){ //1.更新CPU使用信息。ANR的第一次CPU信息采样,采样数据会保存在mProcessStats这个变量中 mService.updateCpuStatsNow(); } //记录ANR到EventLog中 EventLog.writeEvent(EventLogTags.AM_ANR,app.userId,app.pid, app.processName,app.info.flags,annotation); //输出ANR到mainlog. StringBuilderinfo=newStringBuilder(); info.setLength(0); info.append("ANRin").append(app.processName); if(activity!=null&&activity.shortComponentName!=null){ info.append("(").append(activity.shortComponentName).append(")"); } info.append("\n"); info.append("PID:").append(app.pid).append("\n"); if(annotation!=null){ info.append("Reason:").append(annotation).append("\n"); } if(parent!=null&&parent!=activity){ info.append("Parent:").append(parent.shortComponentName).append("\n"); } //3.打印调用栈。具体实现由dumpStackTraces()函数完成 FiletracesFile=ActivityManagerService.dumpStackTraces( true,firstPids, (isSilentANR)?null:processCpuTracker, (isSilentANR)?null:lastPids, nativePids); StringcpuInfo=null; //MONITOR_CPU_USAGE默认为true if(ActivityManagerService.MONITOR_CPU_USAGE){ //4.更新CPU使用信息。ANR的第二次CPU使用信息采样。两次采样的数据分别对应ANR发生前后的CPU使用情况 mService.updateCpuStatsNow(); synchronized(mService.mProcessCpuTracker){ //输出ANR发生前一段时间内各个进程的CPU使用情况 cpuInfo=mService.mProcessCpuTracker.printCurrentState(anrTime); } //输出CPU负载 info.append(processCpuTracker.printCurrentLoad()); info.append(cpuInfo); } //输出ANR发生后一段时间内各个进程的CPU使用率 info.append(processCpuTracker.printCurrentState(anrTime)); //会打印发生ANR的原因,如输入事件导致ANR的不同场景 Slog.e(TAG,info.toString()); if(tracesFile==null){ //Thereisnotracefile,sodump(only)theallegedculprit'sthreadstothelog //发送signal3(SIGNAL_QUIT)来dump栈信息 Process.sendSignal(app.pid,Process.SIGNAL_QUIT); } //将anr信息同时输出到DropBox mService.addErrorToDropBox("anr",app,app.processName,activity,parent,annotation, cpuInfo,tracesFile,null); //BringuptheinfamousAppNotRespondingdialog //5.显示ANR对话框。抛出SHOW_NOT_RESPONDING_MSG消息, //AMS.MainHandler会处理这条消息,显示AppNotRespondingDialog对话框提示用户发生ANR Messagemsg=Message.obtain(); HashMap<String,Object>map=newHashMap<String,Object>(); msg.what=ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG; msg.obj=map; msg.arg1=aboveSystem?1:0; map.put("app",app); if(activity!=null){ map.put("activity",activity); } mService.mUiHandler.sendMessage(msg); } } 除了主体逻辑,发生ANR时还会输出各种类别的日志:event log:通过检索”am_anr”关键字,可以找到发生ANR的应用main log:通过检索”ANR in “关键字,可以找到ANR的信息,日志的上下文会包含CPU的使用情况dropbox:通过检索”anr”类型,可以找到ANR的信息traces:发生ANR时,各进程的函数调用栈信息 至此ANR相关报告已经完成,后续需要分析ANR问题,分析ANR往往是从main log中的CPU使用情况和traces中的函数调用栈开始。所以,更新CPU的使用信息updateCpuStatsNow()方法和打印函数栈dumpStackTraces()方法,是系统报告ANR问题关键所在,具体分析ANR问题请参考相关资料。 总结 1.ANR的监测机制:首先分析Service和输入事件大致工作流程,然后从Service,InputEvent两种不同的ANR监测机制的源码实现开始,分析了Android如何发现各类ANR。在启动服务、输入事件分发时,植入超时检测,用于发现ANR。 2.ANR的报告机制:分析Android如何输出ANR日志。当ANR被发现后,两个很重要的日志输出是:CPU使用情况和进程的函数调用栈,这两类日志是我们解决ANR问题的利器。 3.监测ANR的核心原理是消息调度和超时处理。 4. 只有被ANR监测的场景才会有ANR报告以及ANR提示框。 附录 Android高级技术大纲,以及系统进阶视频; Android高级技术大纲 Android高级进阶视频资料 获取方式; 加Android进阶群;701740775。即可前往免费领取。免费备注一下csdn

优秀的个人博客,低调大师

面试官问你如何解决web高并发这样回答就好了

所谓高并发,就是同一时间有很多流量(通常指用户)访问程序的接口、页面及其他资源,解决高并发就是当流量峰值到来时保证程序的稳定性。 我们一般用QPS(每秒查询数,又叫每秒请求数)来衡量程序的综合性能,数值越高越好,一般需要压测(ab工具)得到数据。 假设我们的一个进程(也可以是线程或者协程)处理一次请求花费了50毫秒(业内达标范围一般是20毫秒至60毫秒),那么1秒钟就可以处理20个请求,一台服务器是可以开很多这样的进程并行去处理请求的,比如开了128个,那么这台机器理论上的QPS=2560。 千万不要小瞧这个数字,当你的QPS真有这么高的时候意味着你的DAU(用户日活)有2560*200=51.2万,业内一般是放大200倍计算,有这样的日活说明做得很不错了。 一台服务器能够达到的最大QPS受很多因素的影响,比如机器参数配置、机房地理位置、CPU性能、内存大小、磁盘性能、带宽大小、程序语言、数据库性能、程序架构等,我们一一细说。 推荐一个交流学习群:614478470 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多 点击:加入 1.机器参数配置 这个很好理解,比如服务器最大可以开启128个进程,你设置了最大只开启100个,这属于服务器调优。 2.机房地理位置 如果你做海外用户,服务器机房应该选择国外的,反之应该选择国内的,因为机房距离用户越近,在传输上的时间损耗就越低。 3.CPU性能 CPU性能越好,处理速度就越快,核心数越多,能够并行开启的进程就越多。 4.内存大小 内存越大,程序就能把更多的数据直接放到内存,从内存读取数据比从磁盘读取数据的速度快很多。 5.磁盘性能 这个不用多说吧,一般固态硬盘的性能比机械硬盘的性能好很多,性能越好读写数据的速度就越快。 6.带宽大小 服务器的带宽一般指流出带宽,单位为Mb/S,比如带宽为8Mb/S即1MB/S,如果提供文件下载服务,可能一个用户的下载行为就把服务器带宽用完了。 一般把图片、视频、css文件、JavaScript脚本等资源放到第三方的CDN去,按流量计费,这样就不占用服务器带宽了。 如果用户规模小,基本上一台服务器就好了,这个时候一般会选按固定带宽大小计费。 如果用户规模很大了,基本上会用到负载均衡器来分流,即把流量按照一定的规则分配到不同的服务器上,负载均衡器一般会按流量来计费。 如果平均一次请求返回的数据大小为50KB,为了达到1000QPS这个指标,需要的带宽峰值=1000*50*8/1024=390.625Mb/S。 我们在设计接口的时候应该尽量减少返回的数据大小,比如user_id就可以简化为uid,像图片、视频、css等文件压缩的目的就是减少数据的大小。 7.程序语言 编译型语言的性能一般好于解释型语言的性能,比如go语言性能就好于php语言性能,当语言短期不会替换时,可以通过堆机器解决高并发问题。 8.数据库性能 一台服务器上部署的数据库总是有一个瓶颈的,比如每秒查询数、每秒写入数。 我们可以通过增加很多从库解决查询(select语句)的瓶颈,称之为多从库模型,需要注意的是主从同步数据可能有延迟,当修改数据后马上需要查询时需要设置强制从主库读取。 我们可以将业务拆分,让某些表存储在一个数据库实例上,另一些表存储在其他数据库实例上,虽然一个数据库实例有自己的瓶颈,但是很多的数据库实例堆积起来性能就会大大改善,多个数据库实例的方案称之为多主库模型,主要是为了解决写入瓶颈(insert语句、update语句、delete语句)。 如果你有多个主库又有多个从库,你就实现了多主多从模型。 如果一个表存储的数据量很大,这个时候就要考虑分表了(一般用中间件实现),比如按时间分表或者按用户分表,当把一个表的所有分表都放在一个数据库实例上都满足不了要求的时候,你应该把某些分表存储在新的数据库实例上,这个时候一个表的数据分布到了不同的数据库实例上,这就是所谓的分布式数据库方案了,你需要处理的事情就很复杂了,比如处理分布式事务。 数据库的并发连接数也是有限制的,我们可以用连接池技术来应对,就是保持一定数量的和数据库的连接不断开的长连接,需要连接数据库的时候就从池子里选择一个连接,用完放回去就好了,这个一般也是用中间件来实现。 好的索引也能提高数据库的性能,有时候比堆多个从库的方案还要好。 如果能够减少数据库的读写,也算间接提高了数据库的性能,比如我们用redis来做缓存,用消息队列异步落库等。 有时候某些数据用数据库来计算需要很长时间,可以取到元数据(最小粒度的数据)用程序来计算,这称之为用内存换时间。 9.程序架构 比如实现同样的功能,初级程序员写的程序需要循环100次,而高级程序员写的程序只需要循环10次,效果肯定不一样。 总结 一般大型项目基本是前后端分离的,从性能方面说就是为了将页面渲染的处理在客户端运行,降低服务器的压力。 从带宽层面考虑,css、图片、视频、JavaScript等文件资源能用CDN的就用CDN,能压缩的就尽量压缩,接口能减小返回数据的大小就尽量减小。 为了解决编程语言的不足或者单台服务器的瓶颈,可以先堆机器应对。 索引、多主多从、分布式数据库、缓存、连接池、消息队列等是从数据库方便考虑如何优化性能。 有时候程序的低耦合性比程序的高性能更重要,不要一味地追求高性能。 推荐一个交流学习群:614478470 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多 点击:加入

优秀的个人博客,低调大师

程序员面试,什么样的 GitHub 才适合放简历上?

为什么 GitHub 可以加分 很多招聘描述上面都会备注 GitHub 加分项,那么为什么它是加分项呢? 社区光环,众所众知,GitHub 是开发者的“同性交友社区”。Google、Facebook、Alibaba 都在通过它来贡献自己的开源项目。如果你留心关注,公司越大 GitHub 的贡献度越高,那么如果你想进入大的互联网公司,是不是也提前融入一下这个氛围?同时对于求知的小伙伴儿想阅读源码没有什么比它来的更直接了。 代码工具,基本上 90% 以上的公司都使用 Git 系工具(GitLab、Gitee、GitHub)做项目源码管理,你的提交记录是最好的证明你的 Git 基本功,要比在简历上写熟练使用 Git 更有说服力。那么一个题外话,如果你也热衷于维护 StackOverflow 账号,写上也是一种加分。 编程习惯, 『Talk is

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。