• 关于

    多变量控制未响应

    的搜索结果

问题

Nginx性能为什么如此吊

小柒2012 2019-12-01 21:20:47 15038 浏览量 回答数 3

问题

最大限度利用 JavaScript 和 Ajax 性能:报错

kun坤 2020-06-05 22:56:50 0 浏览量 回答数 1

回答

新地址 24题 Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成 Spring 及其他技术,而不需要到处找示例代码和依赖包。如你想使用 Spring JPA 访问数据库,只要加入 spring-boot-starter-data-jpa 启动器依赖就能使用了。Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖。 23题 Spring Boot 的核心配置文件是application(.yml 或者 .properties) 和 bootstrap(.yml 或者 .properties) 配置文件。boostrap 由父 ApplicationContext 加载,比 applicaton 优先加载,boostrap 里面的属性不能被覆盖。application 配置文件主要用于 Spring Boot 项目的自动化配置。bootstrap 配置文件的应用场景:使用 Spring Cloud Config 配置中心时,这时需要在 bootstrap 配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息;一些固定的不能被覆盖的属性;一些加密/解密的场景。 22题 优点:快速构建项目;对主流开发框架的无配置集成;starters自动依赖与版本控制;大量的自动配置,简化开发,也可修改默认值;无需配置XML,无代码生成,开箱即用;项目可独立运行,无须外部依赖Servlet容器;提供运行时的应用监控;与云计算的天然集成。缺点:集成度较高,使用过程中不太容易了解底层。 21题 Spring Boot的初衷就是为了简化spring的配置,使得开发中集成新功能时更快,简化或减少相关的配置文件。Spring Boot其实是一个整合很多可插拔的组件(框架),内嵌了使用工具(比如内嵌了Tomcat、Jetty等),方便开发人员快速搭建和开发的一个框架。 20题 当程序创建对象、数组等引用类型实体时,系统会在堆内存中为之分配一块内存区,对象就保存在内存区中,不需要显式的去释放一个对象的内存,而是由虚拟机自行执行。在JVM 中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,标记那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。 19题 HashMap线程不安全,HashTable线程安全。HashMap允许有一个key为null,多个value为null;而HashTable不允许key和vale为null。继承类不一样,HashMap继承的是AbstractMap,HashTable继承的是Dictionary。初始容量不一样。使用的hashcode不一样。内部遍历方式的实现不一样。 18题 作用:内容可见性和禁止指令重排。内存可见性:某线程对 volatile 变量的修改,对其他线程都是可见的,即获取 volatile 变量的值都是最新的;禁止指令重排:重排序在单线程下一定能保证结果的正确性,但是在多线程环境下,可能发生重排序影响结果,若用volatile修饰共享变量,在编译时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。使用:当一个线程需要立刻读取到另外一个线程修改的变量值的时候,我们就可以使用volatile。区别:volatile是变量修饰符,而synchronized则作用于一段代码或者方法;volatile只是在线程内存和main memory(主内存)间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。显然synchronized要比volatile消耗更多资源;synchronized 关键字可以保证变量原子性和可见性,volatile 不能保证原子性。 17题 非公平主要表现在获取锁的行为上,并非是按照申请锁的时间前后给等待线程分配锁的 ,每当锁被释放后 ,任何一个线程都有机会竞争到锁,这样做的目的是为了提高执行性能 ,缺点是可能会产生线程饥饿现象 。 16题 如果线程遇到了 IO 阻塞,无能为力,因为IO是操作系统实现的,Java代码并没有办法直接接触到操作系统。如果线程因为调用 wait()、sleep()、或者 join()方法而导致的阻塞,可以中断线程,并且通过抛出 InterruptedException 来唤醒它。 15题 原子操作就是无法被别的线程打断的操作。要么不执行,要么就执行成功。在Java中可以通过锁和循环CAS的方式来实现原子操作。从JDK 1.5开始提供了java.util.concurrent.atomic包,这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。 14题 wait()是Object类的方法,所以每一个对象能使用wait()方法。sleep()是Thread类中的静态方法。sleep不会释放锁,但会让出cpu,sleep会在指定的休眠时间后自动唤醒。wait则会释放锁,让出系统资源,并且加入wait set中,wait不会自动唤醒,而需要notify()或者notifyAll()唤醒。sleep和wait都可以被中断,使用sleep需要捕获异常。wait与notify、notifyAll只能在同步代码块中使用,而sleep可以在任何地方使用。 13题 Synchronized 是由 JVM 实现的一种实现互斥同步的一种方式,查看编译后的字节码,会发现被 Synchronized 修饰过的程序块,在编译前后被编译器生成了monitorenter 和 monitorexit 两个字节码指令。在虚拟机执行到 monitorenter 指令时,首先要尝试获取对象的锁:如果这个对象没有锁定,或者当前线程已经拥有了这个对象的锁,把锁的计数器+1;当执行 monitorexit 指令时将锁计数器-1;当计数器为0时,锁就被释放了。如果获取对象失败了,那当前线程就要阻塞等待,直到对象锁被另外一个线程释放为止。Java 中 Synchronize 通过在对象头设置标记,达到了获取锁和释放锁的目的。 12题 Mybatis 通过动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这 4 种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler 的 invoke()方法,只会拦截那些你指定需要拦截的方法。 实现方法:1.编写Intercepror接口的实现类;2.设置插件的签名,告诉mybatis拦截哪个对象的哪个方法;3.最后将插件注册到全局配置文件中。 11题 Mybatis可以映射枚举类,不单可以映射枚举类,Mybatis可以映射任何对象到表的一列上。映射方式为自定义一个TypeHandler,实现TypeHandler的setParameter()和getResult()接口方法。TypeHandler 有两个作用,一是完成从 javaType至jdbcType 的转换,二是完成jdbcType至javaType的转换,体现为 setParameter()和getResult()两个方法,分别代表设置sql问号占位符参数和获取列查询结果。 10题 Mybatis使用RowBounds对象进行分页,也可以直接编写sql实现分页,也可以使用Mybatis的分页插件。分页插件的原理:使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。举例:select * from student,拦截 sql 后重写为:select t.* from(select * from student)t limit 0,10。 9题 resultType和resultMap都是表示数据库表与pojo之间的映射规则的。类的名字和数据库相同时,可以直接设置resultType 参数为Pojo类。若不同或者有关联查询,需要设置resultMap将结果名字和Pojo名字进行转换。在项目中我们定义的resultMap多了property和column属性,实际也就是分别配置Pojo类的属性和对应的表字段之间的映射关系,多了这个映射关系以后,方便维护。 8题 之所以说Mybatis半自动化,是因为SQL语句需要用户自定义,SQL的解析、执行等工作由Mybatis执行。区别:Hibernate属于全自动 ORM 映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而 Mybatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以它是半自动ORM映射工具。 7题 MyBatis 的缓存分为一级缓存和二级缓存。一级缓存是SqlSession级别的缓存,默认就有,在操作数据库时需要构造 sqlSession对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据,不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。二级缓存是mapper级别的缓存,默认是不打开的,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession去操作数据库得到数据会存在二级缓存区域,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。 6题 RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。用于方法上是为了细化映射,即根据特定的HTTP请求方法(GET、POST 方法等)、HTTP请求中是否携带特定参数等条件,将请求映射到匹配的方法上。 5题 1、前置通知(before advice):在目标方法调用之前执行; 2、后置通知(after returning advice):在目标方法调用之后执行,一旦目标方法产生异常不会执行; 3、最终通知(after(finally) advice):在目标调用方法之后执行,无论目标方法是否产生异常,都会执行; 4、异常通知(after throwing advice):在目标方法产生异常时执行; 5、环绕通知(around advice):在目标方法执行之前和执行之后都会执行,可以写一些非核心的业务逻辑,一般用来替代前置通知和后置通知。 4题 1、通过构造器或工厂方法创建Bean实例;2、为Bean的属性设置值和对其他Bean的引用;3、将Bean实例传递给Bean后置处理器的postProcessBeforeInitialization方法;4、调用Bean的初始方法(init-method);5、将bean实例传递给bean后置处理器的postProcessAfterInitialization方法;6、bean可以使用了;7、当容器关闭时,调用Bean的销毁方法(destroy-method) 3题 在TransactionDefinition接口中定义了五个表示隔离级别的常量: ISOLATION_DEFAULT:使用后端数据库默认的隔离级别,Mysql默认采用的REPEATABLE_READ隔离级别;Oracle默认采用的READ_COMMITTED隔离级别。 ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。 ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生 ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。 ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。 2 题 自动装配提供五种不同的模式供Spring容器用来自动装配beans之间的依赖注入: 1.默认的方式是不进行自动装配,通过手工设置ref 属性来进行装配bean。 2.byName:通过参数名自动装配,之后容器试图匹配、装配和该bean的属性具有相同名字的bean。 3.byType:按照参数的数据类型进行自动装配,之后容器试图匹配和装配和该bean的属性类型一样的bean。如果存在多个相同类型的bean对象,会出错。 4.constructor:使用构造方法完成对象注入,其实也是根据构造方法的参数类型进行对象查找,相当于采用byType的方式。 5.autodetect:如果找到默认的构造函数,则通过 constructor的方式自动装配,否则使用 byType的方式自动装配。在Spring3.0以后的版本此模式已被废弃,已经不再合法了。 1 题 循环依赖只会存在在单例实例中,多例循环依赖直接报错。Spring先用构造器实例化Bean对象,然后将实例化结束的对象放到一个Map中,并且Spring提供获取这个未设置属性的实例化对象的引用方法。当Spring实例化了A类、B类后,紧接着会去设置对象的属性,此时发现A类依赖B类,就会去Map中取出已经存在的单例B类对象,以此类推。因为所持有的都是引用,所以A类一改变B类也会跟着改变。从而解决循环依赖问题。

游客ih62co2qqq5ww 2020-03-03 18:05:36 0 浏览量 回答数 0

阿里云试用中心,为您提供0门槛上云实践机会!

0元试用32+款产品,最高免费12个月!拨打95187-1,咨询专业上云建议!

回答

详细解答可以参考官方帮助文档 PostObject使用HTML表单上传文件到指定bucket。 Post作为Put的替代品,使得基于浏览器上传文件到bucket成为可能。Post Object的消息实体通过多重表单格式(multipart/form-data)编码,在Put Object操作中参数通过HTTP请求头传递,在Post操作中参数则作为消息实体中的表单域传递。 Post object 请求语法 POST / HTTP/1.1 Host: BucketName.oss-cn-hangzhou.aliyuncs.com User-Agent: browser_data Content-Length:ContentLength Content-Type: multipart/form-data; boundary=9431149156168 --9431149156168 Content-Disposition: form-data; name="key" key --9431149156168 Content-Disposition: form-data; name="success_action_redirect" success_redirect --9431149156168 Content-Disposition: form-data; name="Content-Disposition" attachment;filename=oss_download.jpg --9431149156168 Content-Disposition: form-data; name="x-oss-meta-uuid" myuuid --9431149156168 Content-Disposition: form-data; name="x-oss-meta-tag" mytag --9431149156168 Content-Disposition: form-data; name="OSSAccessKeyId" access-key-id --9431149156168 Content-Disposition: form-data; name="policy" encoded_policy --9431149156168 Content-Disposition: form-data; name="Signature" signature --9431149156168 Content-Disposition: form-data; name="file"; filename="MyFilename.jpg" Content-Type: image/jpeg file_content --9431149156168 Content-Disposition: form-data; name="submit" Upload to OSS --9431149156168-- 表单域 名称 类型 描述 必须 OSSAccessKeyId 字符串 Bucket 拥有者的Access Key Id。 默认值:无 限制:当bucket非public-read-write或者提供了policy(或Signature)表单域时,必须提供该表单域。 有条件的 policy 字符串 policy规定了请求的表单域的合法性。不包含policy表单域的请求被认为是匿名请求,并且只能访问public-read-write的bucket。更详细描述请参考下文 Post Policy。 默认值:无 限制:当bucket非public-read-write或者提供了OSSAccessKeyId(或Signature)表单域时,必须提供该表单域。 有条件的 Signature 字符串 根据Access Key Secret和policy计算的签名信息,OSS验证该签名信息从而验证该Post请求的合法性。更详细描述请参考下文 Post Signature。 默认值:无 限制:当bucket非public-read-write或者提供了OSSAccessKeyId(或policy)表单域时,必须提供该表单域。 有条件的 Cache-Control, Content-Type, Content-Disposition, Content-Encoding, Expires 字符串 REST请求头,更多的信息见Put Object。 默认值:无 可选 file 字符串 文件或文本内容,必须是表单中的最后一个域。浏览器会自动根据文件类型来设置Content-Type,会覆盖用户的设置。 OSS一次只能上传一个文件。 默认值:无 必须 key 字符串 上传文件的object名称。 如果名称包含路径,如a/b/c/b.jpg, 则OSS会自动创建相应的文件夹。 默认值:无 必须 success_action_redirect 字符串 上传成功后客户端跳转到的URL,如果未指定该表单域,返回结果由success_action_status表单域指定。如果上传失败,OSS返回错误码,并不进行跳转。 默认值:无 可选 success_action_status 字符串 未指定success_action_redirect表单域时,该表单域指定了上传成功后返回给客户端的状态码。 接受值为200, 201, 204(默认)。 如果该域的值为200或者204,OSS返回一个空文档和相应的状态码。 如果该域的值设置为201,OSS返回一个XML文件和201状态码。 如果其值未设置或者设置成一个非法值,OSS返回一个空文档和204状态码。 默认值:无 x-oss-meta-* 字符串 用户指定的user meta值。 OSS不会检查或者使用该值。 默认值:无 可选 x-oss-server-side-encryption 字符串 指定OSS创建object时的服务器端加密编码算法。 合法值:AES256 可选 x-oss-object-acl 字符串 指定oss创建object时的访问权限。 合法值:public-read,private,public-read-write 可选 x-oss-security-token 字符串 若本次访问是使用STS临时授权方式,则需要指定该项为SecurityToken的值,同时OSSAccessKeyId需要使用与之配对的临时AccessKeyId,计算签名时,与使用普通AccessKeyId签名方式一致。 默认值:无 可选 响应Header 名称 类型 描述 x-oss-server-side-encryption 字符串 如果请求指定了x-oss-server-side-encryption熵编码,则响应Header中包含了该头部,指明了所使用的加密算法。 响应元素(Response Elements) 名称 类型 描述 PostResponse 容器 保持Post请求结果的容器。 子节点:Bucket, ETag, Key, Location Bucket 字符串 Bucket名称。 父节点:PostResponse ETag 字符串 ETag (entity tag) 在每个Object生成的时候被创建,Post请求创建的Object,ETag值是该Object内容的uuid,可以用于检查该Object内容是否发生变化。 父节点:PostResponse Location 字符串 新创建Object的URL。 父节点:PostResponse 细节分析 进行Post操作要求对bucket有写权限,如果bucket为public-read-write,可以不上传签名信息,否则要求对该操作进行签名验证。与Put操作不同,Post操作使用AccessKeySecret对policy进行签名计算出签名字符串作为Signature表单域的值,OSS会验证该值从而判断签名的合法性。 无论bucket是否为public-read-write,一旦上传OSSAccessKeyId, policy, Signature表单域中的任意一个,则另两个表单域为必选项,缺失时OSS会返回错误码:InvalidArgument。 post操作提交表单编码必须为“multipart/form-data”,即header中Content-Type为multipart/form-data;boundary=xxxxxx 这样的形式,boundary为边界字符串。 提交表单的URL为bucket域名即可,不需要在URL中指定object。即请求行是POST / HTTP/1.1,不能写成POST /ObjectName HTTP/1.1。 policy规定了该次Post请求中表单域的合法值,OSS会根据policy判断请求的合法性,如果不合法会返回错误码:AccessDenied。在检查policy合法性时,policy中不涉及的表单域不进行检查。 表单和policy必须使用UTF-8编码,policy为经过UTF-8编码和base64编码的JSON。 Post请求中可以包含额外的表单域,OSS会根据policy对这些表单域检查合法性。 如果用户上传了Content-MD5请求头,OSS会计算body的Content-MD5并检查一致性,如果不一致,将返回InvalidDigest错误码。 如果POST请求中包含Header签名信息或URL签名信息,OSS不会对它们做检查。 如果请求中携带以x-oss-meta-为前缀的表单域,则视为user meta,比如x-oss-meta-location。一个Object可以有多个类似的参数,但所有的user meta总大小不能超过8k。 Post请求的body总长度不允许超过5G。若文件长度过大,会返回错误码:EntityTooLarge。 如果上传指定了x-oss-server-side-encryption Header请求域,则必须设置其值为AES256,否则会返回400和错误码:InvalidEncryptionAlgorithmError。指定该Header后,在响应头中也会返回该Header,OSS会对上传的Object进行加密编码存储,当这个Object被下载时,响应头中会包含x-oss-server-side-encryption,值被设置成该Object的加密算法。 表单域为大小写不敏感的,但是表单域的值为大小写敏感的。 示例 请求示例:POST / HTTP/1.1 Host: oss-example.oss-cn-hangzhou.aliyuncs.com Content-Length: 344606 Content-Type: multipart/form-data; boundary=9431149156168 --9431149156168 Content-Disposition: form-data; name="key" /user/a/objectName.txt --9431149156168 Content-Disposition: form-data; name="success_action_status" 200 --9431149156168 Content-Disposition: form-data; name="Content-Disposition" content_disposition --9431149156168 Content-Disposition: form-data; name="x-oss-meta-uuid" uuid --9431149156168 Content-Disposition: form-data; name="x-oss-meta-tag" metadata --9431149156168 Content-Disposition: form-data; name="OSSAccessKeyId" 44CF9590006BF252F707 --9431149156168 Content-Disposition: form-data; name="policy" eyJleHBpcmF0aW9uIjoiMjAxMy0xMi0wMVQxMjowMDowMFoiLCJjb25kaXRpb25zIjpbWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDAsIDEwNDg1NzYwXSx7ImJ1Y2tldCI6ImFoYWhhIn0sIHsiQSI6ICJhIn0seyJrZXkiOiAiQUJDIn1dfQ== --9431149156168 Content-Disposition: form-data; name="Signature" kZoYNv66bsmc10+dcGKw5x2PRrk= --9431149156168 Content-Disposition: form-data; name="file"; filename="MyFilename.txt" Content-Type: text/plain abcdefg --9431149156168 Content-Disposition: form-data; name="submit" Upload to OSS --9431149156168-- 返回示例:HTTP/1.1 200 OK x-oss-request-id: 61d2042d-1b68-6708-5906-33d81921362e Date: Fri, 24 Feb 2014 06:03:28 GMT ETag: 5B3C1A2E053D763E1B002CC607C5A0FE Connection: keep-alive Content-Length: 0 Server: AliyunOSS Post Policy Post请求的policy表单域用于验证请求的合法性。 policy为一段经过UTF-8和base64编码的JSON文本,声明了Post请求必须满足的条件。虽然对于public-read-write的bucket上传时,post表单域为可选项,我们强烈建议使用该域来限制Post请求。 policy示例 { "expiration": "2014-12-01T12:00:00.000Z", "conditions": [ {"bucket": "johnsmith" }, ["starts-with", "$key", "user/eric/"] ] } Post policy中必须包含expiration和condtions。 Expiration Expiration项指定了policy的过期时间,以ISO8601 GMT时间表示。例如”2014-12-01T12:00:00.000Z”指定了Post请求必须发生在2014年12月1日12点之前。 Conditions Conditions是一个列表,可以用于指定Post请求的表单域的合法值。注意:表单域对应的值在检查policy之后进行扩展,因此,policy中设置的表单域的合法值应当对应于扩展之前的表单域的值。Policy中支持的conditions项见下表: 名称 描述 content-length-range 上传文件的最小和最大允许大小。 该condition支持contion-length-range匹配方式。 Cache-Control, Content-Type, Content-Disposition, Content-Encoding, Expires HTTP请求头。 该condition支持精确匹配和starts-with匹配方式。 key 上传文件的object名称。 该condition支持精确匹配和starts-with匹配方式。 success_action_redirect 上传成功后的跳转URL地址。 该condition支持精确匹配和starts-with匹配方式。 success_action_status 未指定success_action_redirect时,上传成功后的返回状态码。 该condition支持精确匹配和starts-with匹配方式。 x-oss-meta-* 用户指定的user meta。 该condition支持精确匹配和starts-with匹配方式。 如果Post请求中包含其他的表单域,可以将这些额外的表单域加入到policy的conditions中,conditions不涉及的表单域将不会进行合法性检查。 Conditions匹配方式 Conditions匹配方式 描述 精确匹配 表单域的值必须精确匹配conditions中声明的值。如指定key表单域的值必须为a: {“key”: “a”} 同样可以写为: [“eq”, “$key”, “a”] Starts With 表单域的值必须以指定值开始。例如指定key的值必须以/user/user1开始: [“starts-with”, “$key”, “/user/user1”] 指定文件大小 指定所允许上传的文件最大大小和最小大小,例如允许的文件大小为1到10字节: [“content-length-range”, 1, 10] 转义字符 于在 Post policy 中 $ 表示变量,所以如果要描述 $,需要使用转义字符\$。除此之外,JSON 将对一些字符进行转义。下图描述了 Post policy 的 JSON 中需要进行转义的字符。 转义字符 描述 \/ 斜杠 \ 反斜杠 \” 双引号 \$ 美元符 \b 空格 \f 换页 \n 换行 \r 回车 \t 水平制表符 \uxxxx Unicode 字符 Post Signature 对于验证的Post请求,HTML表单中必须包含policy和Signature信息。policy控制请求中那些值是允许的。计算Signature的具体流程为: 创建一个 UTF-8 编码的 policy。 将 policy 进行 base64 编码,其值即为 policy 表单域该填入的值,将该值作为将要签名的字符串。 使用 AccessKeySecret 对要签名的字符串进行签名,签名方法与Head中签名的计算方法相同(将要签名的字符串替换为 policy 即可),请参见在Header中包含签名。 示例 Demo Web 端表单直传 OSS 示例 Demo,请参见JavaScript客户端签名直传。

2019-12-01 23:13:50 0 浏览量 回答数 0

问题

IIS7.5安装配置UrlScan3.1应用防火墙

虎笑 2019-12-01 21:00:19 11275 浏览量 回答数 2

问题

关于Object操作之如何实现PostObject?

青衫无名 2019-12-01 21:50:18 2821 浏览量 回答数 0

回答

概述 本文主要介绍无法远程登录Linux实例的案例和排查方法。 详细信息 本文主要通过如下2个方面解决无法远程登录Linux实例的问题。 常见报错案例 排查方法 常见报错案例 SSH无法远程登录Linux实例的常见案例如下所示,可根据实际报错信息选择不同的方案进行排查和处理。 PAM安全框架 Linux系统环境配置 SSH服务及参数配置 SSH服务关联目录或文件配置 SSH服务密钥配置 PAM安全框架 Linux系统的PAM安全框架可以加载相关安全模块,对云服务器的账户策略、登录策略等进行访问控制。如果相关配置存在异常,或触发了相关策略,就可能会导致SSH登录失败。根据不同报错信息,可参见如下常见案例进行解决。 SSH登录时出现如下错误:pam_listfile(sshd:auth): Refused user root for service sshd SSH登录时出现如下错误:requirement “uid >= 1000” not met by user “root” SSH登录时出现如下错误:Maximum amount of failed attempts was reached SSH登录时出现如下错误:login: Module is unknown Linux系统环境配置 Linux内的系统环境,比如中毒、账户配置、环境变量配置等,如果出现异常,也可能会导致SSH登录失败。根据不同报错信息,可参见如下常见案例进行解决。 SSH登录时出现如下错误:ssh_exchange_identification: read: Connection reset by peer 中毒导致SSH服务运行异常,出现如下错误:fatal: mm_request_send: write: Broken pipe SSH启动时出现如下错误:main process exited, code=exited SSH连接时出现如下错误:pam_limits(sshd:session):could not sent limit for ‘nofile’ SSH连接时出现如下错误:pam_unix(sshdsession) session closed for user SSH连接时出现如下错误:error Could not get shadow infromation for root SSH服务及参数配置 SSH服务的默认配置文件为/etc/ssh/sshd_config。配置文件中的相关参数配置异常,或启用了相关特性或策略,也可能会导致 SSH登录失败。根据不同报错信息,可参见如下常见案例进行解决。 SSH登录时出现如下错误:Disconnected:No supported authentication methods available SSH登录时出现如下错误:User root not allowed because not listed in SSH登录时出现如下错误:Permission denied, please try again SSH登录时出现如下错误:Too many authentication failures for root SSH启动时出现如下错误:error while loading shared libraries SSH启动时出现如下错误:fatal: Cannot bind any address SSH启动时出现如下错误:Bad configuration options 云服务器ECS Linux SSH启用UseDNS导致连接速度变慢 Linux实例中由于SELinux服务开启导致SSH远程连接异常 SSH服务关联目录或文件配置 SSH服务基于安全性考虑,在运行时,会对相关目录或文件的权限配置、属组等进行检查。过高或过低的权限配置,都可能会引发服务运行异常,进而导致客户端登录失败。根据不同报错信息,可参见如下常见案例进行解决。 SSH登录时出现如下错误:No supported key exchange algorithms SSH启动时出现如下错误:must be owned by root and not group or word-writable SSH服务密钥配置 SSH服务采用非对称加密技术,对所传输的数据进行加密。客户端及服务端会交换和校验相关密钥信息的有效性。根据不同报错信息,可参见如下常见案例进行解决。 SSH登录时出现如下错误:Host key verification failed SSH服务的公私钥异常导致无法SSH登录Linux实例 排查方法 若常见报错案例没有解决问题,可以参考如下流程排查问题。 检查CPU负载、带宽及内存使用情况 客户端排查 中间网络 网络检查 端口检查 安全组检查 示例 提示: 以下操作在CentOS 6.5 64位操作系统中进行过测试,在其他Linux发行版中可能存在差异,具体情况请参阅对应Linux发行版的官方文档。 客户端SSH连接Linux实例是运维操作的主要途径。通过管理终端可以用于临时运维操作,或者在客户端SSH登录异常时,用于问题排查和分析。 下图为SSH登录关联因素示意图。由此可见,通过SSH无法远程登录Linux实例时,可能涉及的关联因素较多。 检查CPU负载、带宽及内存使用情况 确认是否存在CPU负载过高的情况,如果存在,则参考本步骤解决问题,如果不存在,则执行下一步步骤。 提示:您无法主动监控系统内部的程序运行状态,但是可以借助云监控进行查看。 登录云监控控制台,依次选择 主机监控 > 进程监控。 查看应用运行情况,排除CPU负载过高的原因,如何查看CPU负载问题,请参见Linux系统ECS实例CPU使用率较高的排查思路。 提示:在某个时间段CPU负载过高可能导致远程连接失败,建议您查询程序或者实例资源是否不满足现有要求。 无法远程连接可能是公网带宽不足导致的,具体排查方法如下。可通过续费ECS实例,然后重启实例解决。详情参见手动续费或者自动续费。 登录ECS管理控制台。 找到该实例, 单击 管理 进入 实例详情 页面,查看网络监控数据。 检查服务器带宽是否为“1k”或“0k”。如果购买实例时没有购买公网带宽,后来升级了公网带宽,续费的时候没有选择续费带宽,带宽就会变成“1k”。 远程连接输入用户密码登录后,不能正常显示桌面直接退出,也没有错误信息。这种情况可能是服务器内存不足导致的,需要查看一下服务器的内存使用情况。具体操作如下。 使用控制台远程连接功能登录到Linux实例。 查看内存使用情况,具体请参考Linux系统的ECS实例中如何查看物理CPU和内存信息,确认内存不足后,请参考Linux服务器内存消耗过高进行处理。 客户端排查 客户端无法正常登录时,先使用不同的SSH客户端基于相同账户信息进行登录测试。如果能正常登录,则判断是客户端配置问题,需要对客户端配置或软件运行情况做排查分析。关于如何使用客户端SSH登录Linux实例,您可以参考远程连接Linux实例。 步骤一:使用管理终端登录实例 无论何种原因导致无法远程连接实例,请先尝试用阿里云提供的远程连接功能进行连接,确认实例还有响应,没有完全宕机,然后再按原因分类进行故障排查。 登录云服务器管理控制台,单击左侧导航栏中的 实例,然后在目标实例右侧单击 远程连接。 在首次连接或忘记连接密码时,单击 修改远程连接密码,修改远程连接的密码。 然后通过远程连接密码连接实例。 步骤二:检查客户端本地网络是否异常 确认是否存在用户本地无法连接外网的故障。 如果存在,则检查网卡驱动,如果存在异常,则重新安装。使用管理终端登录实例,查看/etc/hosts.deny文件,查看是否存在拦截IP,如果存在则删除此IP配置即可。 如果不存在,则执行下一步步骤。 步骤三:重启实例 在确保登录密码正确的情况下,确认之前是否曾重置过密码。检查重置实例密码后是否未重启实例,如果存在实例密码修改记录,但无重启实例记录,则参考以下操作步骤重启实例。 登录ECS管理控制台,单击左侧导航栏中的 实例。 在页面顶部的选择对应的地域,目标实例右侧单击 更多 > 实例状态 > 重启,再单击 确认 即可。 中间网络 中间网络包括网络检查和端口检查。 网络检查 无法正常远程连接Windows实例时,需要先检查网络是否正常。 用其他网络环境中,不同网段或不同运营商)的电脑连接对比测试,判断是本地网络问题还是服务器端的问题。如果是本地网络问题或运营商问题,请联系本地IT人员或运营商解决。如果是网卡驱动存在异常,则重新安装。排除本地网络故障后进行下一步检查。 在客户端使用ping命令测试与实例的网络连通性。 网络异常时,请参考网络异常时如何抓取数据包进行排查。 当出现ping丢包或ping不通时,请参考使用ping命令丢包或不通时的链路测试方法进行排查。 如果出现间歇性丢包,ECS实例的网络一直处于不稳定状态时,请参考使用ping命令测试ECS实例的IP地址间歇性丢包进行解决。 系统内核没有禁ping的情况下,使用ping命令测试ECS服务器,发现网络不通,请参考Linux系统的ECS中没有禁PING却PING不通的解决方法。 端口检查 网络检查正常后,进一步检查端口是否正常。 使用管理终端登录实例,执行如下命令,编辑SSH配置文件。 vi /etc/ssh/sshd_config 找到“#port 22”所在行,检查默认端口22是否被修改,且前面的“#”是否删除,如果没有删除,可以把前面的“#”删除,然后将22改为其它的端口,再保存退出即可。 注:服务监听能使用的端口范围为0到65535,错误配置监听端口会导致远程桌面服务监听失败。 执行如下命令,重启SSH服务。 /etc/init.d/sshd restart 注:也可执行如下命令,重启SSH服务。 service sshd restart 使用Python自带的Web服务器用于临时创建新的监听端口进行测试。 python -m SimpleHTTPServer [$Port] 如果登录方式改变或者ECS安全组规则中未放行修改后的端口号,则参考如下步骤放行修改后的端口。 注:ECS的安全组规则中默认放行22端口。修改了远程桌面的端口后,需要在安全组规则中放行修改后的端口号。 登录ECS管理控制台。 找到该实例,单击 管理 进入 实例详情 页面,切换到 本实例安全组 标签页,单击 配置规则。 在安全组规则页面,单击 添加安全组规则。 在弹出的页面中,端口范围 输入修改后的远程桌面端口号。授权对象 输入客户端的公网IP地址。比如修改后的远程桌面端口号为2222,则 端口范围 应输入“2222/2222”。填写完成后,单击 确定。 通过上一步获取的端口,参考如下命令,进行端口测试,判断端口是否正常。如果端口测试失败,请参考使用ping命令正常但端口不通时的端口可用性探测说明进行排查。 telnet [$IP] [$Port] 注: [$IP]指Linux实例的IP地址。 [$Port]指Linux实例的SSH端口号。 系统显示类似如下,比如执行telnet 192.168.0.1 22命令,正常情况下,系统会返回服务端中SSH的软件版本号。 安全组检查 检查安全组配置,是否允许远程连接的端口。 参考查询安全组规则,查看安全组规则。如果远程连接端口没有进行配置,则参考Linux实例启用SSH服务后设置对应的安全组策略配置。 确认是否存在无法ping通ECS实例,在排除Iptables和网卡IP配置问题且回滚系统后,仍然无法ping通。可能是ECS实例安全组默认的公网规则被删除,则需要重新配置ECS实例的安全组公网规则,具体操作请参见ECS实例安全组默认的公网规则被删除导致无法ping通。如果不存在,则继续下一步骤检查。 示例 如果根据前述问题场景进行排查和处理后,还是无法正常登录。则建议按照如下步骤逐一排查和分析。 使用不同的客户端SSH及管理终端做对比访问测试,判断是否是个别客户端自身配置或软件运行问题所致。 参阅中间网络问题相关说明,测试网络连通性。 参阅管理终端,登录云服务器,在客户端进行访问测试的同时,执行如下命令,查看相关日志。 tailf /var/log/secure 参考如下命令, 比如ssh -v 192.168.0.1 命令,获取Linux环境中详细的SSH登录交互日志。 ssh -v [$IP] 通过管理终端登录Linux实例,参考如下步骤,检查SSH服务运行状态。 执行如下命令,检查服务运行状态。 service sshd status service sshd restart 正常情况下会返回SSH服务的运行状态及进程PID,系统显示类似如下。 [root@centos ~]# service sshd status openssh-daemon (pid 31350) is running... [root@centos ~]# service sshd restart Stopping sshd: [ OK ] Starting sshd: [ OK ] 执行如下命令,检查服务监听状态。 netstat -ano | grep 0.0.0.0:22 正常情况下会返回相应端口监听信息,系统显示类似如下。 tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN off (0.00/0/0) 通过管理终端登录Linux实例,执行如下命令。如果能正常登录,则推断是系统防火墙或外部安全组策略等配置异常,导致客户端登录失败。 ssh 127.0.0.1 若用阿里云提供的远程连接功能仍无法成功连接实例,请尝试重启实例。重启操作会使实例停止工作,从而中断业务,请谨慎执行。 提示:重启实例前,需给实例创建快照,用于数据备份或者制作镜像。创建快照的方法请参见创建快照。 登录ECS管理控制台,单击左侧导航栏中的 实例。 在页面顶部的选择对应的地域,在目标实例右侧单击 更多 > 实例状态 > 重启,再单击 确认 即可。

1934890530796658 2020-03-26 09:52:57 0 浏览量 回答数 0

问题

SSH面试题

琴瑟 2019-12-01 21:46:22 3489 浏览量 回答数 0

回答

92题 一般来说,建立INDEX有以下益处:提高查询效率;建立唯一索引以保证数据的唯一性;设计INDEX避免排序。 缺点,INDEX的维护有以下开销:叶节点的‘分裂’消耗;INSERT、DELETE和UPDATE操作在INDEX上的维护开销;有存储要求;其他日常维护的消耗:对恢复的影响,重组的影响。 需要建立索引的情况:为了建立分区数据库的PATITION INDEX必须建立; 为了保证数据约束性需要而建立的INDEX必须建立; 为了提高查询效率,则考虑建立(是否建立要考虑相关性能及维护开销); 考虑在使用UNION,DISTINCT,GROUP BY,ORDER BY等字句的列上加索引。 91题 作用:加快查询速度。原则:(1) 如果某属性或属性组经常出现在查询条件中,考虑为该属性或属性组建立索引;(2) 如果某个属性常作为最大值和最小值等聚集函数的参数,考虑为该属性建立索引;(3) 如果某属性经常出现在连接操作的连接条件中,考虑为该属性或属性组建立索引。 90题 快照Snapshot是一个文件系统在特定时间里的镜像,对于在线实时数据备份非常有用。快照对于拥有不能停止的应用或具有常打开文件的文件系统的备份非常重要。对于只能提供一个非常短的备份时间而言,快照能保证系统的完整性。 89题 游标用于定位结果集的行,通过判断全局变量@@FETCH_STATUS可以判断是否到了最后,通常此变量不等于0表示出错或到了最后。 88题 事前触发器运行于触发事件发生之前,而事后触发器运行于触发事件发生之后。通常事前触发器可以获取事件之前和新的字段值。语句级触发器可以在语句执行前或后执行,而行级触发在触发器所影响的每一行触发一次。 87题 MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。具体原因为:MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序。因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面。此外可以根据特例的查询或者表结构进行单独的调整。 86题 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。如果需要建立联合索引的话,还需要考虑联合索引中的顺序。此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力。这些都和实际的表结构以及查询方式有关。 85题 存储过程是一组Transact-SQL语句,在一次编译后可以执行多次。因为不必重新编译Transact-SQL语句,所以执行存储过程可以提高性能。触发器是一种特殊类型的存储过程,不由用户直接调用。创建触发器时会对其进行定义,以便在对特定表或列作特定类型的数据修改时执行。 84题 存储过程是用户定义的一系列SQL语句的集合,涉及特定表或其它对象的任务,用户可以调用存储过程,而函数通常是数据库已定义的方法,它接收参数并返回某种类型的值并且不涉及特定用户表。 83题 减少表连接,减少复杂 SQL,拆分成简单SQL。减少排序:非必要不排序,利用索引排序,减少参与排序的记录数。尽量避免 select *。尽量用 join 代替子查询。尽量少使用 or,使用 in 或者 union(union all) 代替。尽量用 union all 代替 union。尽量早的将无用数据过滤:选择更优的索引,先分页再Join…。避免类型转换:索引失效。优先优化高并发的 SQL,而不是执行频率低某些“大”SQL。从全局出发优化,而不是片面调整。尽可能对每一条SQL进行 explain。 82题 如果条件中有or,即使其中有条件带索引也不会使用(要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引)。对于多列索引,不是使用的第一部分,则不会使用索引。like查询是以%开头。如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引。如果mysql估计使用全表扫描要比使用索引快,则不使用索引。例如,使用<>、not in 、not exist,对于这三种情况大多数情况下认为结果集很大,MySQL就有可能不使用索引。 81题 主键不能重复,不能为空,唯一键不能重复,可以为空。建立主键的目的是让外键来引用。一个表最多只有一个主键,但可以有很多唯一键。 80题 空值('')是不占用空间的,判断空字符用=''或者<>''来进行处理。NULL值是未知的,且占用空间,不走索引;判断 NULL 用 IS NULL 或者 is not null ,SQL 语句函数中可以使用 ifnull ()函数来进行处理。无法比较 NULL 和 0;它们是不等价的。无法使用比较运算符来测试 NULL 值,比如 =, <, 或者 <>。NULL 值可以使用 <=> 符号进行比较,该符号与等号作用相似,但对NULL有意义。进行 count ()统计某列的记录数的时候,如果采用的 NULL 值,会被系统自动忽略掉,但是空值是统计到其中。 79题 HEAP表是访问数据速度最快的MySQL表,他使用保存在内存中的散列索引。一旦服务器重启,所有heap表数据丢失。BLOB或TEXT字段是不允许的。只能使用比较运算符=,<,>,=>,= <。HEAP表不支持AUTO_INCREMENT。索引不可为NULL。 78题 如果想输入字符为十六进制数字,可以输入带有单引号的十六进制数字和前缀(X),或者只用(Ox)前缀输入十六进制数字。如果表达式上下文是字符串,则十六进制数字串将自动转换为字符串。 77题 Mysql服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。 76题 在缺省模式下,MYSQL是autocommit模式的,所有的数据库更新操作都会即时提交,所以在缺省情况下,mysql是不支持事务的。但是如果你的MYSQL表类型是使用InnoDB Tables 或 BDB tables的话,你的MYSQL就可以使用事务处理,使用SET AUTOCOMMIT=0就可以使MYSQL允许在非autocommit模式,在非autocommit模式下,你必须使用COMMIT来提交你的更改,或者用ROLLBACK来回滚你的更改。 75题 它会停止递增,任何进一步的插入都将产生错误,因为密钥已被使用。 74题 创建索引的时候尽量使用唯一性大的列来创建索引,由于使用b+tree做为索引,以innodb为例,一个树节点的大小由“innodb_page_size”,为了减少树的高度,同时让一个节点能存放更多的值,索引列尽量在整数类型上创建,如果必须使用字符类型,也应该使用长度较少的字符类型。 73题 当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下: 限定数据的范围: 务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。读/写分离: 经典的数据库拆分方案,主库负责写,从库负责读。垂直分区: 根据数据库里面数据表的相关性进行拆分。简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。水平分区: 保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。水平拆分可以支撑非常大的数据量。 72题 乐观锁失败后会抛出ObjectOptimisticLockingFailureException,那么我们就针对这块考虑一下重试,自定义一个注解,用于做切面。针对注解进行切面,设置最大重试次数n,然后超过n次后就不再重试。 71题 一致性非锁定读讲的是一条记录被加了X锁其他事务仍然可以读而不被阻塞,是通过innodb的行多版本实现的,行多版本并不是实际存储多个版本记录而是通过undo实现(undo日志用来记录数据修改前的版本,回滚时会用到,用来保证事务的原子性)。一致性锁定读讲的是我可以通过SELECT语句显式地给一条记录加X锁从而保证特定应用场景下的数据一致性。 70题 数据库引擎:尤其是mysql数据库只有是InnoDB引擎的时候事物才能生效。 show engines 查看数据库默认引擎;SHOW TABLE STATUS from 数据库名字 where Name='表名' 如下;SHOW TABLE STATUS from rrz where Name='rrz_cust';修改表的引擎alter table table_name engine=innodb。 69题 如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据;如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;同理,哈希索引也没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);哈希索引也不支持多列联合索引的最左匹配规则;B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题。 68题 decimal精度比float高,数据处理比float简单,一般优先考虑,但float存储的数据范围大,所以范围大的数据就只能用它了,但要注意一些处理细节,因为不精确可能会与自己想的不一致,也常有关于float 出错的问题。 67题 datetime、timestamp精确度都是秒,datetime与时区无关,存储的范围广(1001-9999),timestamp与时区有关,存储的范围小(1970-2038)。 66题 Char使用固定长度的空间进行存储,char(4)存储4个字符,根据编码方式的不同占用不同的字节,gbk编码方式,不论是中文还是英文,每个字符占用2个字节的空间,utf8编码方式,每个字符占用3个字节的空间。Varchar保存可变长度的字符串,使用额外的一个或两个字节存储字符串长度,varchar(10),除了需要存储10个字符,还需要1个字节存储长度信息(10),超过255的长度需要2个字节来存储。char和varchar后面如果有空格,char会自动去掉空格后存储,varchar虽然不会去掉空格,但在进行字符串比较时,会去掉空格进行比较。Varbinary保存变长的字符串,后面不会补\0。 65题 首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。 64题 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。如果需要建立联合索引的话,还需要考虑联合索引中的顺序。此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力。这些都和实际的表结构以及查询方式有关。 63题 存储过程是一些预编译的SQL语句。1、更加直白的理解:存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。2、存储过程是一个预编译的代码块,执行效率比较高,一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率,可以一定程度上确保数据安全。 62题 密码散列、盐、用户身份证号等固定长度的字符串应该使用char而不是varchar来存储,这样可以节省空间且提高检索效率。 61题 推荐使用自增ID,不要使用UUID。因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降。总之,在数据量大一些的情况下,用自增主键性能会好一些。 60题 char是一个定长字段,假如申请了char(10)的空间,那么无论实际存储多少内容。该字段都占用10个字符,而varchar是变长的,也就是说申请的只是最大长度,占用的空间为实际字符长度+1,最后一个字符存储使用了多长的空间。在检索效率上来讲,char > varchar,因此在使用中,如果确定某个字段的值的长度,可以使用char,否则应该尽量使用varchar。例如存储用户MD5加密后的密码,则应该使用char。 59题 一. read uncommitted(读取未提交数据) 即便是事务没有commit,但是我们仍然能读到未提交的数据,这是所有隔离级别中最低的一种。 二. read committed(可以读取其他事务提交的数据)---大多数数据库默认的隔离级别 当前会话只能读取到其他事务提交的数据,未提交的数据读不到。 三. repeatable read(可重读)---MySQL默认的隔离级别 当前会话可以重复读,就是每次读取的结果集都相同,而不管其他事务有没有提交。 四. serializable(串行化) 其他会话对该表的写操作将被挂起。可以看到,这是隔离级别中最严格的,但是这样做势必对性能造成影响。所以在实际的选用上,我们要根据当前具体的情况选用合适的。 58题 B+树的高度一般为2-4层,所以查找记录时最多只需要2-4次IO,相对二叉平衡树已经大大降低了。范围查找时,能通过叶子节点的指针获取数据。例如查找大于等于3的数据,当在叶子节点中查到3时,通过3的尾指针便能获取所有数据,而不需要再像二叉树一样再获取到3的父节点。 57题 因为事务在修改页时,要先记 undo,在记 undo 之前要记 undo 的 redo, 然后修改数据页,再记数据页修改的 redo。 Redo(里面包括 undo 的修改) 一定要比数据页先持久化到磁盘。 当事务需要回滚时,因为有 undo,可以把数据页回滚到前镜像的状态,崩溃恢复时,如果 redo log 中事务没有对应的 commit 记录,那么需要用 undo把该事务的修改回滚到事务开始之前。 如果有 commit 记录,就用 redo 前滚到该事务完成时并提交掉。 56题 redo log是物理日志,记录的是"在某个数据页上做了什么修改"。 binlog是逻辑日志,记录的是这个语句的原始逻辑,比如"给ID=2这一行的c字段加1"。 redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。 redo log是循环写的,空间固定会用完:binlog 是可以追加写入的。"追加写"是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。 最开始 MySQL 里并没有 InnoDB 引擎,MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog日志只能用于归档。而InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统,也就是 redo log 来实现 crash-safe 能力。 55题 重做日志(redo log)      作用:确保事务的持久性,防止在发生故障,脏页未写入磁盘。重启数据库会进行redo log执行重做,达到事务一致性。 回滚日志(undo log)  作用:保证数据的原子性,保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。 二进 制日志(binlog)    作用:用于主从复制,实现主从同步;用于数据库的基于时间点的还原。 错误日志(errorlog) 作用:Mysql本身启动,停止,运行期间发生的错误信息。 慢查询日志(slow query log)  作用:记录执行时间过长的sql,时间阈值可以配置,只记录执行成功。 一般查询日志(general log)    作用:记录数据库的操作明细,默认关闭,开启后会降低数据库性能 。 中继日志(relay log) 作用:用于数据库主从同步,将主库发来的bin log保存在本地,然后从库进行回放。 54题 MySQL有三种锁的级别:页级、表级、行级。 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。 死锁: 是指两个或两个以上的进程在执行过程中。因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。 那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。死锁的解决办法:1.查出的线程杀死。2.设置锁的超时时间。3.指定获取锁的顺序。 53题 当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性(脏读,不可重复读,幻读等),可能产生死锁。 乐观锁:乐观锁不是数据库自带的,需要我们自己去实现。 悲观锁:在进行每次操作时都要通过获取锁才能进行对相同数据的操作。 共享锁:加了共享锁的数据对象可以被其他事务读取,但不能修改。 排他锁:当数据对象被加上排它锁时,一个事务必须得到锁才能对该数据对象进行访问,一直到事务结束锁才被释放。 行锁:就是给某一条记录加上锁。 52题 Mysql是关系型数据库,MongoDB是非关系型数据库,数据存储结构的不同。 51题 关系型数据库优点:1.保持数据的一致性(事务处理)。 2.由于以标准化为前提,数据更新的开销很小。 3. 可以进行Join等复杂查询。 缺点:1、为了维护一致性所付出的巨大代价就是其读写性能比较差。 2、固定的表结构。 3、高并发读写需求。 4、海量数据的高效率读写。 非关系型数据库优点:1、无需经过sql层的解析,读写性能很高。 2、基于键值对,数据没有耦合性,容易扩展。 3、存储数据的格式:nosql的存储格式是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,而关系型数据库则只支持基础类型。 缺点:1、不提供sql支持,学习和使用成本较高。 2、无事务处理,附加功能bi和报表等支持也不好。 redis与mongoDB的区别: 性能:TPS方面redis要大于mongodb。 可操作性:mongodb支持丰富的数据表达,索引,redis较少的网络IO次数。 可用性:MongoDB优于Redis。 一致性:redis事务支持比较弱,mongoDB不支持事务。 数据分析:mongoDB内置了数据分析的功能(mapreduce)。 应用场景:redis数据量较小的更性能操作和运算上,MongoDB主要解决海量数据的访问效率问题。 50题 如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。 49题 分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存。如果没有分区,你最多只能使用一台机器的内存。分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。 48题 除了缓存服务器自带的缓存失效策略之外(Redis默认的有6种策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种: 1.定时去清理过期的缓存; 2.当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。 两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!具体用哪种方案,可以根据应用场景来权衡。 47题 Redis提供了两种方式来作消息队列: 一个是使用生产者消费模式模式:会让一个或者多个客户端监听消息队列,一旦消息到达,消费者马上消费,谁先抢到算谁的,如果队列里没有消息,则消费者继续监听 。另一个就是发布订阅者模式:也是一个或多个客户端订阅消息频道,只要发布者发布消息,所有订阅者都能收到消息,订阅者都是平等的。 46题 Redis的数据结构列表(list)可以实现延时队列,可以通过队列和栈来实现。blpop/brpop来替换lpop/rpop,blpop/brpop阻塞读在队列没有数据的时候,会立即进入休眠状态,一旦数据到来,则立刻醒过来。Redis的有序集合(zset)可以用于实现延时队列,消息作为value,时间作为score。Zrem 命令用于移除有序集中的一个或多个成员,不存在的成员将被忽略。当 key 存在但不是有序集类型时,返回一个错误。 45题 1.热点数据缓存:因为Redis 访问速度块、支持的数据类型比较丰富。 2.限时业务:expire 命令设置 key 的生存时间,到时间后自动删除 key。 3.计数器:incrby 命令可以实现原子性的递增。 4.排行榜:借助 SortedSet 进行热点数据的排序。 5.分布式锁:利用 Redis 的 setnx 命令进行。 6.队列机制:有 list push 和 list pop 这样的命令。 44题 一致哈希 是一种特殊的哈希算法。在使用一致哈希算法后,哈希表槽位数(大小)的改变平均只需要对 K/n 个关键字重新映射,其中K是关键字的数量, n是槽位数量。然而在传统的哈希表中,添加或删除一个槽位的几乎需要对所有关键字进行重新映射。 43题 RDB的优点:适合做冷备份;读写服务影响小,reids可以保持高性能;重启和恢复redis进程,更加快速。RDB的缺点:宕机会丢失最近5分钟的数据;文件特别大时可能会暂停数毫秒,或者甚至数秒。 AOF的优点:每个一秒执行fsync操作,最多丢失1秒钟的数据;以append-only模式写入,没有任何磁盘寻址的开销;文件过大时,不会影响客户端读写;适合做灾难性的误删除的紧急恢复。AOF的缺点:AOF日志文件比RDB数据快照文件更大,支持写QPS比RDB支持的写QPS低;比RDB脆弱,容易有bug。 42题 对于Redis而言,命令的原子性指的是:一个操作的不可以再分,操作要么执行,要么不执行。Redis的操作之所以是原子性的,是因为Redis是单线程的。而在程序中执行多个Redis命令并非是原子性的,这也和普通数据库的表现是一样的,可以用incr或者使用Redis的事务,或者使用Redis+Lua的方式实现。对Redis来说,执行get、set以及eval等API,都是一个一个的任务,这些任务都会由Redis的线程去负责执行,任务要么执行成功,要么执行失败,这就是Redis的命令是原子性的原因。 41题 (1)twemproxy,使用方式简单(相对redis只需修改连接端口),对旧项目扩展的首选。(2)codis,目前用的最多的集群方案,基本和twemproxy一致的效果,但它支持在节点数改变情况下,旧节点数据可恢复到新hash节点。(3)redis cluster3.0自带的集群,特点在于他的分布式算法不是一致性hash,而是hash槽的概念,以及自身支持节点设置从节点。(4)在业务代码层实现,起几个毫无关联的redis实例,在代码层,对key进行hash计算,然后去对应的redis实例操作数据。这种方式对hash层代码要求比较高,考虑部分包括,节点失效后的代替算法方案,数据震荡后的自动脚本恢复,实例的监控,等等。 40题 (1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件 (2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次 (3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内 (4) 尽量避免在压力很大的主库上增加从库 (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。 39题 比如订单管理,热数据:3个月内的订单数据,查询实时性较高;温数据:3个月 ~ 12个月前的订单数据,查询频率不高;冷数据:1年前的订单数据,几乎不会查询,只有偶尔的查询需求。热数据使用mysql进行存储,需要分库分表;温数据可以存储在ES中,利用搜索引擎的特性基本上也可以做到比较快的查询;冷数据可以存放到Hive中。从存储形式来说,一般情况冷数据存储在磁带、光盘,热数据一般存放在SSD中,存取速度快,而温数据可以存放在7200转的硬盘。 38题 当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。 37题 分层架构设计,有一条准则:站点层、服务层要做到无数据无状态,这样才能任意的加节点水平扩展,数据和状态尽量存储到后端的数据存储服务,例如数据库服务或者缓存服务。显然进程内缓存违背了这一原则。 36题 更新数据的时候,根据数据的唯一标识,将操作路由之后,发送到一个 jvm 内部队列中。读取数据的时候,如果发现数据不在缓存中,那么将重新读取数据+更新缓存的操作,根据唯一标识路由之后,也发送同一个 jvm 内部队列中。一个队列对应一个工作线程,每个工作线程串行拿到对应的操作,然后一条一条的执行。 35题 redis分布式锁加锁过程:通过setnx向特定的key写入一个随机值,并同时设置失效时间,写值成功既加锁成功;redis分布式锁解锁过程:匹配随机值,删除redis上的特点key数据,要保证获取数据、判断一致以及删除数据三个操作是原子的,为保证原子性一般使用lua脚本实现;在此基础上进一步优化的话,考虑使用心跳检测对锁的有效期进行续期,同时基于redis的发布订阅优雅的实现阻塞式加锁。 34题 volatile-lru:当内存不足以容纳写入数据时,从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。 volatile-ttl:当内存不足以容纳写入数据时,从已设置过期时间的数据集中挑选将要过期的数据淘汰。 volatile-random:当内存不足以容纳写入数据时,从已设置过期时间的数据集中任意选择数据淘汰。 allkeys-lru:当内存不足以容纳写入数据时,从数据集中挑选最近最少使用的数据淘汰。 allkeys-random:当内存不足以容纳写入数据时,从数据集中任意选择数据淘汰。 noeviction:禁止驱逐数据,当内存使用达到阈值的时候,所有引起申请内存的命令会报错。 33题 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。 32题 缓存击穿,一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。如何避免:在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。 31题 缓存雪崩,是指在某一个时间段,缓存集中过期失效。大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。而缓存服务器某个节点宕机或断网,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。如何避免:1.redis高可用,搭建redis集群。2.限流降级,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。3.数据预热,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间。 30题 缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。一些恶意的请求会故意查询不存在的 key,请求量很大,对数据库造成压力,甚至压垮数据库。 如何避免:1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该 key 对应的数据 insert 了之后清理缓存。2:对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap 中,查询时通过该 bitmap 过滤。 29题 1.memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类型。 2.redis 的速度比 memcached 快很多。 3.redis 可以持久化其数据。 4.Redis支持数据的备份,即master-slave模式的数据备份。 5.Redis采用VM机制。 6.value大小:redis最大可以达到1GB,而memcache只有1MB。 28题 Spring Boot 推荐使用 Java 配置而非 XML 配置,但是 Spring Boot 中也可以使用 XML 配置,通过spring提供的@ImportResource来加载xml配置。例如:@ImportResource({"classpath:some-context.xml","classpath:another-context.xml"}) 27题 Spring像一个大家族,有众多衍生产品例如Spring Boot,Spring Security等等,但他们的基础都是Spring的IOC和AOP,IOC提供了依赖注入的容器,而AOP解决了面向切面的编程,然后在此两者的基础上实现了其他衍生产品的高级功能。Spring MVC是基于Servlet的一个MVC框架,主要解决WEB开发的问题,因为 Spring的配置非常复杂,各种xml,properties处理起来比较繁琐。Spring Boot遵循约定优于配置,极大降低了Spring使用门槛,又有着Spring原本灵活强大的功能。总结:Spring MVC和Spring Boot都属于Spring,Spring MVC是基于Spring的一个MVC框架,而Spring Boot是基于Spring的一套快速开发整合包。 26题 YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写。YAML 的配置文件后缀为 .yml,是一种人类可读的数据序列化语言,可以简单表达清单、散列表,标量等数据形态。它通常用于配置文件,与属性文件相比,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。 25题 Spring Boot有3种热部署方式: 1.使用springloaded配置pom.xml文件,使用mvn spring-boot:run启动。 2.使用springloaded本地加载启动,配置jvm参数-javaagent:<jar包地址> -noverify。 3.使用devtools工具包,操作简单,但是每次需要重新部署。 用

游客ih62co2qqq5ww 2020-03-27 23:56:48 0 浏览量 回答数 0

回答

创建一个包含模板间共享布局的模板,通常这样的模板包含: 页面头部、导航栏、脚部、内容展示区域。 Layout.html <!DOCTYPE html> <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <head> <title>Layout page</title> <script src="common-script.js"></script> </head> <body> <header> <h1>My website</h1> </header> <section layout:fragment="content"> <p>Page content goes here</p> </section> <footer> <p>My footer</p> <p layout:fragment="custom-footer">Custom footer here</p> </footer> </body> </html> 注意事项: 1. html标签上附上命名空间 2. section与脚部p标签上使用layout:fragment属性 这些是布局中的插入候选槽点,通过匹配内容模板中片段进行替换。 创建一些内容模板: Content1.html <!DOCTYPE html> <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{Layout}"> <head> <title>Content page 1</title> <script src="content-script.js"></script> </head> <body> <section layout:fragment="content"> <p>This is a paragraph from content page 1</p> </section> <footer> <p layout:fragment="custom-footer">This is some footer content from content page 1</p> </footer> </body> </html> html标签中的layout:decorate说明哪一个布局模板使用这个内容模板进行装饰。内容模板定义自身标题与脚本、content与custom-footer片段。custom-footer片段处于footer元素内部,这其实是不必要的,但是可能会是很方便的,如果想要做内容模板的静态模板,这是一开始使用Thymeleaf的原因之一。 在一个模板内片段名称必须唯一,否则可能会出现片段不匹配,各种各样的可笑事情会接踵而至。 不管如何,一旦告知Thymeleaf处理Content1.html,最终的页面会是这样子: <!DOCTYPE html> <html> <head> <title>Content page 1</title> <script src="common-script.js"></script> <script src="content-script.js"></script> </head> <body> <header> <h1>My website</h1> </header> <section> <p>This is a paragraph from content page 1</p> </section> <footer> <p>My footer</p> <p>This is some footer content from content page 1</p> </footer> </body> </html> 内容模板装饰Layout.html,结果是布局的组合,加上内容模板的片段(两个模板的<head>元素,来自内容模板的<title>元素替换布局文件内的,所有的元素来自布局文件,但是由所有指定的内容模板进行替换) 想了解更多可以如何控制<head>元素合并,参看<head>元素合并一小节。 装饰进程重定向处理从内容模板至布局,将layout:fragment部分从内容模板中挑选出来,因为布局需要它们。正因如此,任何在layout:fragment之外的东西实际从未得到执行,这说明在内容模板中不能这样做: <div th:if="${user.admin}"> <div layout:fragment="content"> ... </div> </div> 如果布局模板想要’内容’片段,那么会得到那个片段,不顾任何所在条件,因为那些条件不会执行。 如果说只想用绝对最小HTML代码量替换装饰器脚部: Content2.html <p layout:decorate="~{Layout}" layout:fragment="custom-footer"> This is some footer text from content page 2. </p> 这就是全部所需的东西!<p>标签同时用作根元素与片段定义,生成一个像这样的页面: <!DOCTYPE html> <html> <head> <title>Layout page</title> <script src="common-script.js"></script> </head> <body> <header> <h1>My website</h1> </header> <section> <p>Page content goes here</p> </section> <footer> <p>My footer</p> <p> This is some footer text from content page 2. </p> </footer> </body> </html> 可以把布局看作母版,会得以填充或者被内容(子模板)覆盖,仅当内容会填充/覆盖父类。以这种方式,布局充当某种’默认’,内容充当这种默认之上的实现。 给布局传送数据 子模板向上给母版布局传送数据,在涉及到布局/装饰过程的任意元素上使用th:with/ data-th-with属性处理器,可以在任何地方layout:decorate/ data-layout-decorate 或者可以发现 layout:fragment/data-layout-fragment, 例如: 孩子/内容模板: <html layout:decorate="your-layout.html" th:with="greeting='Hello!'"> 1 父类/布局模板: <html> ... <p th:text="${greeting}"></p> <!-- You'll end up with "Hello!" in here --> 将来,或许会增加支持使用分片局部变量,很像Thymeleaf用于创建片段签名。 配置标题 鉴于布局方言自动用内容模板中所发现的重载布局<title>,可能会发现自己重复布局中发现的标题部分,尤其是想要创建面包屑或者在页面标题中保留页面名称。layout:title-pattern处理器可以免除重复布局标题的问题,通过使用一些特殊标记以想要标题如何出现的模式。 这是一个例子: Layout.html <!DOCTYPE html> <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <head> <title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">My website</title> </head> ... </html> layout:title-pattern处理器采取简单字符串,识别两种特殊标记:$LAYOUT_TITLE与$CONTENT_TITLE。每种标记在结果页中会被各自相应的标题替换。所以,如果有下面的内容模板: Content.html <!DOCTYPE html> <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="Layout"> <head> <title>My blog</title> </head> ... </html> 结果页会是这样: <!DOCTYPE html> <html> <head> <title>My website - My blog</title> </head> ... </html> 这对<title>元素内的静态/内联文本或者<title>元素上发现使用th:text的动态文本均有效。 上述例子中的模式在布局中指定,所以对所有使用布局的内容模板均适用。如果在内容模板中指定另一种标题模式,那么会覆盖布局中发现的那个,允许细粒度的控制标题的展现形式。 可重用模板 假如发现有一些HTML或者结构经常性地重复,想要做成自己的模板从不同地方插入以便减少代码重复。(模块化Thymeleaf?)这个的例子可能会是一个模态面板,由几个HTML元素与CSS类构成,在网页应用中产生一个新窗口的效果: Modal.html <!DOCTYPE html> <html> <body> <div id="modal-container" class="modal-container" style="display:none;"> <section id="modal" class="modal"> <header> <h1>My Modal</h1> <div id="close-modal" class="modal-close"> <a href="#close">Close</a> </div> </header> <div id="modal-content" class="modal-content"> <p>My modal content</p> </div> </section> </div> </body> </html> 会发现可以将一些东西转换成像头部、ID的变量,以便包含Modal.html的页面可以设定它们自己的名称/ID。继续尽可能泛型化编写模态代码,然而会遇到填充自己的模态框内容的问题,那是开始接触一些限制的地方。 一些页面使用单一消息的模态框,其他想要使用模态框容纳一些更复杂的东西比如接受用户输入的表单。模态框可能性变得无休无止,但是未支持想象,发现自己得不得将这段模态框代码拷贝到每一个模板中,每一次使用场合变化相应内容,重复同样的HTML代码维持同样的外观感受,打破了过程中的DRY原则。 主要妨碍适当重用的事情是无法将HTML元素传递至插入模板中。这正是layout:insert有用的地方。它运作起来完全像th:insert,但是通过指定与实现片段很像内容/布局实例,可以创建一个公共的结构,对插入它的模板使用场合作出响应。 这是一个更新的模态框模板,使用Thymeleaf与layout:fragment属性定义一个可替换的模态框内容部分以变得更加泛型化: Modal2.html Modal2.html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <body layout:fragment="modal(modalId, modalHeader)"> <div th:id="${modalId} + '-container'" class="modal-container" style="display:none;"> <section th:id="${modalId}" class="modal"> <header> <h1 th:text="${modalHeader}">My Modal</h1> <div th:id="'close-' + ${modalId}" class="modal-close"> <a href="#close">Close</a> </div> </header> <div th:id="${modalId} + '-content'" class="modal-content"> <div layout:fragment="modal-content"> <p>My modal content</p> </div> </div> </section> </div> </body> </html> 现在可以插入这个模板,使用layout:insert处理器与无论怎样需要实现modal-content片段,通过在调用模板插入元素内创建同样名称的片段: Content.html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> ... <div layout:insert="Modal2 :: modal(modalId='message', modalHeader='Message')" th:remove="tag"> <p layout:fragment="modal-content">Message goes here!</p> </div> ... </html> 就像内容/布局实例,插入模板layout:fragment会被匹配片段名称的元素替换掉。在这种场合下,Modal2.html的整个modal-content部分会被上述自定义段落替换掉。这是结果: <!DOCTYPE html> <html> ... <div id="message-container" class="modal-container" style="display:none;"> <section id="message" class="modal"> <header> <h1>Message</h1> <div id="close-message" class="modal-close"> <a href="#close">Close</a> </div> </header> <div id="message-content" class="modal-content"> <p>Message goes here!</p> </div> </section> </div> ... </html> 定义在模板内包含Modal2.html的自定义消息作为模态框内容的一部分。在插入模板上下文环境中的片段与用于内容/布局过程中的片段一样工作:如果片段未在模板中定义,那么它不会覆盖插入模板中的内容,使得在可重用版本中创建默认。

景凌凯 2020-04-29 21:11:25 0 浏览量 回答数 0

问题

如何推送高级接口?

猫饭先生 2019-12-01 21:56:00 1106 浏览量 回答数 0

问题

深入理解 Redis 主键失效原理及实现机制:报错

kun坤 2020-06-07 14:14:55 0 浏览量 回答数 1

回答

XSS 攻击有两⼤要素: 攻击者提交恶意代码。浏览器执⾏恶意代码。 针对第⼀个要素:我们是否能够在⽤户输⼊的过程,过滤掉⽤户输⼊的恶意代码呢? 输⼊过滤 在⽤户提交时,由前端过滤输⼊,然后提交到后端。这样做是否可⾏呢? 答案是不可⾏。⼀旦攻击者绕过前端过滤,直接构造请求,就可以提交恶意代码了。 那么,换⼀个过滤时机:后端在写⼊数据库前,对输⼊进⾏过滤,然后把“安全的”内容,返回给前端。这样是否可⾏呢? 我们举⼀个例⼦,⼀个正常的⽤户输⼊了 5 < 7 这个内容,在写⼊数据库前,被转义,变成了 5 < 7 。 问题是:在提交阶段,我们并不确定内容要输出到哪⾥。 这⾥的“并不确定内容要输出到哪⾥”有两层含义: ⽤户的输⼊内容可能同时提供给前端和客户端,⽽⼀旦经过了 escapeHTML() ,客户端显示的内容就变成了乱码(5< 7)。 在前端中,不同的位置所需的编码也不同。 当5 < 7 作为 HTML 拼接⻚⾯时,可以正常显示: <div title="comment">5 < 7</div> 当5 < 7 通过 Ajax 返回,然后赋值给 JavaScript 的变量时,前端得到的字符串就是转义后的字符。这个内容不能直接⽤于 Vue 等模板的展示,也不能直接⽤于内容⻓度计算。不能⽤于标题、alert 等 所以,输⼊侧过滤能够在某些情况下解决特定的 XSS 问题,但会引⼊很⼤的不确定性和乱码问题。在防范 XSS 攻击时应避免此类⽅法 当然,对于明确的输⼊类型,例如数字、URL、电话号码、邮件地址等等内容,进⾏输⼊过滤还是必要的 既然输⼊过滤并⾮完全可靠,我们就要通过“防⽌浏览器执⾏恶意代码”来防范 XSS。这部分分为两类: 防⽌ HTML 中出现注⼊防⽌ JavaScript 执⾏时,执⾏恶意代码 预防存储型和反射型 XSS 攻击 存储型和反射型 XSS 都是在服务端取出恶意代码后,插⼊到响应 HTML ⾥的,攻击者刻意编写的“数据”被内到“代码”中,被浏览器所执⾏。 预防这两种漏洞,有两种常⻅做法: 改成纯前端渲染,把代码和数据分隔开。对 HTML 做充分转义。 纯前端渲染 纯前端渲染的过程: 浏览器先加载⼀个静态 HTML,此 HTML 中不包含任何跟业务相关的数据。然后浏览器执⾏ HTML 中的 JavaScript。JavaScript 通过 Ajax 加载业务数据,调⽤ DOM API 更新到⻚⾯上。 在纯前端渲染中,我们会明确的告诉浏览器:下⾯要设置的内容是⽂本( .innerText ),还是属性( .setAttribute ),还是样式( .style )等等。浏览器不会被轻易的被欺骗,执⾏预期外的代码了。 但纯前端渲染还需注意避免 DOM 型 XSS 漏洞(例如 onload 事件和 href 中的 javascript:xxx 等,请参考下⽂”预防 DOM 型 XSS 攻击“部分)。 在很多内部、管理系统中,采⽤纯前端渲染是⾮常合适的。但对于性能要求⾼,或有 SEO 需求的⻚⾯,我们仍然要⾯ 对拼接 HTML 的问题。 转义 HTML 如果拼接 HTML 是必要的,就需要采⽤合适的转义库,对 HTML 模板各处插⼊点进⾏充分的转义。 常⽤的模板引擎,如 doT.js、ejs、FreeMarker 等,对于 HTML 转义通常只有⼀个规则,就是把 & < > " ' / 这⼏个字符转义掉,确实能起到⼀定的 XSS 防护作⽤,但并不完善: 所以要完善 XSS 防护措施,我们要使⽤更完善更细致的转义策略。 例如 Java ⼯程⾥,常⽤的转义库为 org.owasp.encoder 。以下代码引⽤⾃ org.owasp.encoder 的官⽅说明。 <!-- HTML 标签内⽂字内容 --> <div><%= Encode.forHtml(UNTRUSTED) %></div> <!-- HTML 标签属性值 --> <input value="<%= Encode.forHtml(UNTRUSTED) %>" /> <!-- CSS 属性值 --> <div style="width:<= Encode.forCssString(UNTRUSTED) %>"> <!-- CSS URL --> <div style="background:<= Encode.forCssUrl(UNTRUSTED) %>"> <!-- JavaScript 内联代码块 --> <script> var msg = "<%= Encode.forJavaScript(UNTRUSTED) %>"; alert(msg); </script> <!-- JavaScript 内联代码块内嵌 JSON --> <script> var __INITIAL_STATE__ = JSON.parse('<%= Encoder.forJavaScript(data.to_json) %>'); </script> <!-- HTML 标签内联监听器 --> <button onclick="alert('<%= Encode.forJavaScript(UNTRUSTED) %>');"> click me </button> <!-- URL 参数 --> <a href="/search?value=<%= Encode.forUriComponent(UNTRUSTED) %>&order=1#top"> <!-- URL 路径 --> <a href="/page/<%= Encode.forUriComponent(UNTRUSTED) %>"> <!-- URL. 注意:要根据项⽬情况进⾏过滤,禁⽌掉 "javascript:" 链接、⾮法 scheme 等 --> <a href='<%= urlValidator.isValid(UNTRUSTED) ? Encode.forHtml(UNTRUSTED) : "/404" %>'> link </a> 可⻅,HTML 的编码是⼗分复杂的,在不同的上下⽂⾥要使⽤相应的转义规则。 预防 DOM 型 XSS 攻击 DOM 型 XSS 攻击,实际上就是⽹站前端 JavaScript 代码本身不够严谨,把不可信的数据当作代码执⾏了。 在使⽤ .innerHTML 、 .outerHTML 、 document.write() 时要特别⼩⼼,不要把不可信的数据作为 HTML 插到⻚⾯上,⽽应尽量使⽤ .textContent 、 .setAttribute() 等。 如果⽤ Vue/React 技术栈,并且不使⽤ v-html / dangerouslySetInnerHTML 功能,就在前端 render 阶段避免innerHTML 、 outerHTML 的 XSS 隐患。 DOM 中的内联事件监听器,如 location 、 onclick 、 onerror 、 onload 、 onmouseover 等, 标签的 href 属性,JavaScript 的 eval() 、 setTimeout() 、 setInterval() 等,都能把字符串作为代码运⾏。如果不可信的数据拼接到字符串中传递给这些 API,很容易产⽣安全隐患,请务必避免。 <!-- 内联事件监听器中包含恶意代码 --> ![](https://awps-assets.meituan.net/mit-x/blog-images-bundle-2018b/3e724ce0.data:image/png,) <!-- 链接内包含恶意代码 --> <a href="UNTRUSTED">1</a> <script> // setTimeout()/setInterval() 中调⽤恶意代码 setTimeout("UNTRUSTED") setInterval("UNTRUSTED") // location 调⽤恶意代码 location.href = 'UNTRUSTED' // eval() 中调⽤恶意代码 eval("UNTRUSTED") </script> 如果项⽬中有⽤到这些的话,⼀定要避免在字符串中拼接不可信数据。 其他 XSS 防范措施 虽然在渲染⻚⾯和执⾏ JavaScript 时,通过谨慎的转义可以防⽌ XSS 的发⽣,但完全依靠开发的谨慎仍然是不够的。 以下介绍⼀些通⽤的⽅案,可以降低 XSS 带来的⻛险和后果。 Content Security Policy 严格的 CSP 在 XSS 的防范中可以起到以下的作⽤: 禁⽌加载外域代码,防⽌复杂的攻击逻辑禁⽌外域提交,⽹站被攻击后,⽤户的数据不会泄露到外域禁⽌内联脚本执⾏(规则较严格,⽬前发现 GitHub 使⽤)禁⽌未授权的脚本执⾏(新特性,Google Map 移动版在使⽤)合理使⽤上报可以及时发现 XSS,利于尽快修复问题 输⼊内容⻓度控制 对于不受信任的输⼊,都应该限定⼀个合理的⻓度。虽然⽆法完全防⽌ XSS 发⽣,但可以增加 XSS 攻击的难度。 其他安全措施 HTTP-only Cookie: 禁⽌ JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注⼊后也⽆法窃取此 Cookie。验证码:防⽌脚本冒充⽤户提交危险操作。 过滤 Html 标签能否防⽌ XSS? 请列举不能的情况? ⽤户除了上传 <script>alert('xss');</script> 还可以使⽤图⽚ url 等⽅式来上传脚本进⾏攻击 <table background="javascript:alert(/xss/)"></table> <img src="javascript:alert('xss')"> 还可以使⽤各种⽅式来回避检查, 例如空格, 回⻋, Tab <img src="javas cript: alert('xss')"> 还可以通过各种编码转换 (URL 编码, Unicode 编码, HTML 编码, ESCAPE 等) 来绕过检查 <img%20src=%22javascript:alert('xss');%22> <img src="javascript&#58alert(/xss/)">

前端问答 2019-12-23 12:43:05 0 浏览量 回答数 0

问题

【精品问答】python技术1000问(2)

问问小秘 2019-12-01 22:03:02 68 浏览量 回答数 0

问题

DRDS 错误代码如何解决?

猫饭先生 2019-12-01 21:21:21 7993 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站