工作常见问题汇总

  1. 在服务无法启动得时候,需要首先考虑得问题就是:jar包冲突的问题,这个时候jar包冲突得话,会在一些类无法自动的导入进去。
  2. 凡是报错due to a StackOverflowError. Possible root causes include a too low就是因为jar包的相互依赖出现的问题,这个其实就是jar包冲突 。
  3. 再hibernate的映射文件配置的时候,不能将映射文件放入到依赖的jar包当中,因为无法扫描到。
  4. eureka如何保证他的高可用呢?其实就是相互注册服务,因为自己的服务在自己的注册中心是可以见的,那么只需要注册上另外机器的服务即可。
  5. 在注册中心服务端,需要添加注释为:@EnableEurekaServer,标志此工程是一个enreka server,负责提供注册中心。
  6. 在客户端,需要去将自己服务端注册到注册中心,那么需要注释:@EnableDiscoveryClient,标志此工程需要去发现服务。
  7. Ribbon是一个基于客户端的负载均衡器。而nginx是基于服务器端的负载均衡器。
  8. 服务器端负载均衡:例如Nginx,通过Nginx进行负载均衡,先发送请求,然后通过负载均衡算法,在多个服务器之间选择一个进行访问;即在服务器端再进行负载均衡算法分配。客户端负载均衡:例如spring cloud中的ribbon,客户端会有一个服务器地址列表,在发送请求前通过负载均衡算法选择一个服务器,然后进行访问,这是客户端负载均衡;即在客户端就进行负载均衡算法分配。
  9. Ribbon其实就是通过restTemplate来实现远程调用的,底层使用的是okhttp,负载均衡就是依靠注释@LoadBalanced实现的。
  10. 远程接口的调用要是能够像调用本地的服务一样调用那该多好,所以就有了feign+ribbon。使用的方式为:
  11. @FeignClient(value = "MANAGER_CMS")
    public interface TestFeign {
    
        // 通过feign远程调用接口(可见feign也是集成了spring mvc)
        @GetMapping("/cms/page/get/{id}")
        public CmsPage getCmsPageById(@PathVariable("id") String id);
    }

    调用者:

  12. @EnableFeignClients // 标识FeignClient,开启后会扫描所有FeignClient的bean
    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class TestController {
    
        @Autowired
        TestFeign testFeign; // 其实就是个代理对象
    
        @Test
        public void findTeachplanList(){
            // 开始远程调用
            CmsPage sssss = testFeign.getCmsPageById("sssss");
        }
    }

     

  13. ES的数据节点和主节点,数据节点就是专存储数据,主节点就是专门进行管理分节点,不存储数据。

  14. ES的索引如何与数据库同步呢?可以使用Logstach来进行完成,但是logstach有个问题就是无法实现数据库删除的时候,索引库也跟着删除,这个时候就需要手动得编写删除程序。

  15. HLS的工作方式是:将视频拆分成若干ts格式的小文件,通过m3u8格式的索引文件对这些ts小文件建立索引。一般 10秒一个ts文件,播放器连接m3u8文件播放,当快进时通过m3u8即可找到对应的索引文件,并去下载对应的ts文件,从而实现快进、快退以近实时的方式播放视频。 IOS、Android设备、及各大浏览器都支持HLS协议。

  16. 如何利用java程序调用第三方的应用程序呢?可以使用runtime类或者process builder来操作。

  17. 用户认证和授权?认证可以是本地认证、单点登录认证、第三方认证。

  18. 报错:Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

报错的原因:在应该使用save的方法,但是使用了update方法。

原因分析:使用的是hibernate的saveOrUpdate方法保存实例。saveOrUpdate方法要求ID为null时才执行SAVE,在其它情况下执行UPDATE。在保存实例的时候是新增,但你的ID不为null,所以使用的是UPDATE,但是数据库里没有主键相关的值,所以出现异常。

  1. 多线程出现HibernateException: Could not obtain transaction-synchronized Session for current thread

报错原因:无法获取到当前线程的同步事务session.

原因分析:

通过查阅资料可以发现,解决办法有:用openSession方法取代getCureentSession().或者将用到的方法配置上事务。

那么背后的真正原因是什么呢?为什么上述的方式就可以解决问题呢?

我们需要回归母体,回归起点,那就是查看getCureentSession的源码:

if (TransactionSynchronizationManager.isSynchronizationActive()) {
                session = this.sessionFactory.openSession();
                if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
                    session.setFlushMode(FlushMode.MANUAL);
                }

                SessionHolder sessionHolder = new SessionHolder(session);
                TransactionSynchronizationManager.registerSynchronization(new SpringSessionSynchronization(sessionHolder, this.sessionFactory, true));
                TransactionSynchronizationManager.bindResource(this.sessionFactory, sessionHolder);
                sessionHolder.setSynchronizedWithTransaction(true);
                return session;
            } else {
                throw new HibernateException("Could not obtain transaction-synchronized Session for current thread");
            }

可见是在判断TransactionSynchronizationManager.isSynchronizationActive()不成立的情况下才会抛出的这个异常。那么继续追踪isSynchronizationActive方法。

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

其含义就是:返回当前线程副本中的线程局部变量,如果当前线程没有变量,它首先通过调用initialValue方法初始化值。而在spring的事务实现中需要判断当前线程中的事务是否同步,而没有事务的时候,那个判断是否同步的方法会因为get返回初始的null值而返回false,最终导致throw一个Could not obtain transaction-synchronized Session for current thread的异常.

19、Auth2的密码授权模式:通过用户名和密码达到获取授权码,然后获取令牌。

20、JWT令牌与传统的授权不同的地方:JWT令牌是不需要再通过http请求去认证系统获取令牌检验,而是可以通过自身完成检测。(因为再返回的JWT令牌已经携带了加密的方式,那么这个时候就可以自己来完成检测)

21、keyTool:可以用来进行密钥(私钥或者公钥)生成的工具,文件的后缀为xx.keystore

22、再spring中如何获取response:

HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();

23、再申请令牌得时候,spring security会调用loadUserByUsername的方法,去获取UserDetails对象,该对象包含了用户的真正账号和密码。

24、MD5加密的话,只要密码相同,那么生成的结果皆相同。然而BCrypt加密能够做到每次加密的结果不一样。BCrypt比通过MD5加盐的方式更高级。
25、在令牌中,是可以解析出用户的权限的。

26、在授权方法的时候,是授权的controller层的方法进行授权控制。

27、细粒度授权也是权限范围授权,不同的用户拥有的权限相同,但是能够操作的范围不一样。

28、如果更新支付表失败则抛出异常,不再执行远程调用,此设想没有问题。

29、如果更新支付表成功,网络远程调用超时会拉长本地数据库事务时间,影响数据库的性能。

30、如果更新支付表成功,远程调用添加选课成功,最后更新支付表失败,此时出现操作不一致

31、只要是多个系统协同完成一个事务的过程,并不强调多个系统访问了不同的数据库,也就是即使在同一个数据库,还是存在分布式事务问题。

32、CAP理论:软件中存在分布式事务还是很多的,CAP理论就是一致性、可用性、分区容错性。节点越多,一致性越差,可用性越高。在现实的开发中,AP是用到最多的,强调可用性和分区容忍性,追求数据的最终一致性。

33、现在的分布式事务的解决办法就是:2PC两阶段提交,适用于关系型数据库。+,并不适用于现在的分布式系统。TTC事务补偿机制,try、confirm、cancel,在每个try里面都需要进行接口开发,开发成本太高。消息队列实现最终一致性,开发成本比较低,但是需要频繁的操作数据库,会对数据库的性能造成影响,异步调用。

34、Spring task中的fixedDelay,意思就是在任务结束后的多少秒后才开始执行。

35、finedRate 在任务执行后间隔多少秒后才开始执行。

36、Cron表达式:秒  分钟  小时   月中的天  月   周中的天 。每日的10点执行:0 0 10 * * *  月中的天和周中的天执只能一个存在

37、在spring task的定时任务是串行的,如果需要并行的话,那么是需要进行相关配置的,配置如下:需要一个类实现asyncConfigurer。

38、在处理问题之前需要将原来的数据进行备份。

39、上线发生数据改动,格式和之前不兼容,回滚也不正常,如何处理?

答:首先备份数据,通过备份的数据来进行恢复。

40、不分层就是all in one的架构,所有代码都在一起。

41、硬盘类型RAID0是支持分条,RAID1支持备份,RAID01支持分条和备份。

42、DNS将网站的域名转为对应的ip信息。

43、Linux查看域名对应的ip,nslookup www.baoidu.com

44、linux查看ip对应的区域:whois 192.168.1.129

45、HttpDNS可以直接去访问服务,不需要进行域名解析。

46、CDN内容分发网络,CDN其实就是个内容管理集群,每个CDN就是一个保存资源得服务器,供其他的服务器进行访问。内容的由来可以是主动的pull和被动的push技术获取。

47、一个可视化数据结构的网站推荐:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

48、可以使用断言方式来校验参数非空:

Object obj = null;
Assert.notNull(obj,"obj is not null");

49、AspectJ的语法:就是使用@aspectJ来声明切面。在spring中只是使用两种aop技术,一种是jdk和cglib。这个可以在类aopproxy类里看出来。

50、jvm获取锁的优先级:先尝试获取偏向锁、再尝试获取轻量级锁、再尝试获取自旋锁、最后再去获取普通锁。

51、再同步块很长,自旋时间很长,得不偿失。同步块比较短,自旋时间很短,减少线程切换的时间,提高效率。

52、ByteBuffer.allocate()与ByteBuffer.allocateDirect()方法的区别:前者的内存开销是再JVM上的,后者是再JVM之外的系统内存上。前者优点就是分配内存不耗时间,后者耗时间。数据进入到内存的时候不需要赋值数据到JVM,而是直接再内存中使用,减少复制数据的时间消耗。

你可能感兴趣的:(工作常见问题汇总)