字节跳动C++云原生二面(65min)

Posted MangataTS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字节跳动C++云原生二面(65min)相关的知识,希望对你有一定的参考价值。

字节跳动C++云原生二面(65min)

面试问题

HTTP1.0 、1.1和2.0 的区别和差异是什么

  • 《HTTP1.0和1.1的区别》
  • HTTP1.1 默认开启长连接(keep-alive) 而HTTP1.0需要添加参数,在一定程度上减少了建立和关闭连接的消耗和延迟
  • HTTP1.0中存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能。HTTP1.1支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器,则返回100,客户端接收到100才开始把请求body发送到服务器;如果返回401,客户端就可以不用发送请求body了节约了带宽。
  • HTTP1.0中认为每台服务器只有一个唯一的IP地址,因此请求头中的URL中并没有传递主机名,因此HTTP1.0没有host域,但是HTTP1.1的请求消息必须有host域(host域其实就是一个记录IP和域名的文件,可以加快解析速度)
  • 在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
  • 在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
  • 《HTTP1.1和2.0的区别》
  • HTTP2.0使用多路复用的技术,做到同一个连接并发处理多个请求,并且并发请求的数量也比HTTP1.1大了好几个数量级,要比HTTP1.1多建几个TCP连接的开销更小
  • HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快。
  • 支持服务器推送 ,为了改善延迟,HTTP2.0引入了server push,它允许服务端推送资源给浏览器,在 浏览器明确地请求之前 ,免得客户端再次创建连接发送请求到服务器端获取。这样客户端可以直接从本地加载这些资源,不用再通过网络。
  • HTTP2.0采用二进制格式传输数据

WebSocket 也是基于Http协议的对吧

WebSocket在建立连接的时候是使用的HTTP协议,建立连接之后就是自己的WebSocket协议了

HTTPS有用到过吗,HTTPS在数据传输的过程中是对称加密还是非对称加密

HTTPS 在内容传输的加密上使用的是对称加密,非对称加密只作用在证书验证阶段

整体过程分为:证书验证数据传输 阶段

证书验证的时候会拿公钥做什么事情

会将公钥去加密由一个权威服务器生成的一个随机数字,然后再发送给服务器端,服务器端通过私钥解密随机数,然后服务器通过客户端传入的随机数进行构造对称加密算法,对返回结果内容进行对称加密后传输给客户端

为什么数据传输是用的对称加密

  • 非对称加密的加解密效率是非常低的,而 http 的应用场景中通常端与端之间存在大量的交互,非对称加密的效率是无法接受的
  • 在 HTTPS 的场景中只有服务端保存了私钥,一对公私钥只能实现单向的加解密,所以 HTTPS 中内容传输加密采取的是对称加密,而不是非对称加密。

孤儿进程和僵尸进程简单介绍一下

  • 僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。(也就是子进程的退出状态不被收集)。
  • 父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程就叫做孤儿进程。
    Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程。
    Pid==1,init进程(初始化进程)

孤儿进程和僵尸线程怎么去避免呢

  • 《僵尸进程处理》
  • 其实在子进程退出的时候内核会发送SIGCHLD信号给父进程,我们可以捕捉SIGCHLD信号,然后在信号函数中回收子进程,即调用wait

线程之间是怎么同步的,一般有哪些方式

  • 信号量:为控制一个具有有限数量用户资源而设计
  • 互斥量:为协调共同对一个共享资源的单独访问而设计的
  • 读写锁
  • 条件变量
  • 文件互斥

详情参考此文:https://zhuanlan.zhihu.com/p/514079587

进程什么时候是在内核态什么时候是在用户态,怎么做一个切换的

从用户态到内核态的转变,需要通过系统调用来完成。比如,当我们查看文件内容时,就需要多次系统调用来完成:首先调用 open() 打开文件,然后调用 read() 读取文件内容,并调用 write() 将内容写到标准输出,最后再调用 close() 关闭文件。

系统调用会将CPU从用户态切换到核心态,以便 CPU 访问受到保护的内核内存。

系统调用的过程会发生 CPU 上下文的切换,CPU 寄存器里原来用户态的指令位置,需要先保存起来。接着,为了执行内核态代码,CPU 寄存器需要更新为内核态指令的新位置。最后才是跳转到内核态运行内核任务。

而系统调用结束后,CPU 寄存器需要恢复原来保存的用户态,然后再切换到用户空间,继续运行进程。所以,一次系统调用的过程,其实是发生了两次 CPU 上下文切换。

注意:系统调用过程中,并不会涉及到虚拟内存等进程用户态的资源,也不会切换进程。

系统调用过程通常称为特权模式切换,而不是进程上下文切换。

详情参考此文:https://www.cnblogs.com/tsaiccj/p/15762258.html

死锁你是怎么理解的,什么情况会产生死锁

读写锁这一块你有用过吗,简单介绍一下

平常项目里面也没涉及到读写锁对吧

爬虫这一块,爬数据的时候是并发做爬取的吗,讲一下你的思路,还有你的数据是存储在哪里的?

这个项目是你单独去做的吗?看你投入了一年的时间,当时是出于什么考虑来做这一块呢?你在做的过程中有碰到过比较大的难点吗,比如真正去做一些实现的时候遇到过什么棘手的吗

刚才提到你自学了 python ,你来介绍一下Python中的闭包

你自己比较擅长哪个语言呢

你对云原生感兴趣,那么Golang有尝试去做过一些学习吗

数据库这一块你了解的多吗,比如像mysql,包括像一些关联查询,一些高级的SQL语句什么的,还有索引什么的

比如数据量比较大的情况,比如说你朋友发现我某一个SQL执行的时候比较慢,你觉得如果他执行比较慢的,可能有哪些原因?你怎么去排查定位呢?

索引的回表的操作一般在什么情况发生

volatile这样的关键字的作用是干什么的

你平常和同学做项目的合作过程中你是怎么去写作的,怎么分工的或者是做一个拆解的,谁去做这个事儿

因为你涉及到一些比如参加一些比赛的话,比赛是有人去主导,比如说一些比如参会,你们是主动自己去参加的吗

如果你过来实习的话,比如说给你一个比如说任务或者一个方向,但这一块相对来说又自己比较陌生,你一般会怎么去做?

你有关注哪些云原生的方向或者项目吗?K8s这一块的话有了解过吗?

代码

想了2min,给了一个 N 3 N^3 N3 的思路,先预处理前缀和面积,然后枚举正方形的左上角,以及边长

实现后,面试官问我能不能用动态规划做,当时感觉是可以的,然后想了10min,用 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示 ( i , j ) (i,j) (i,j) 点作为正方形的右下角的点的最大正方形的长度 ,发现规律如果左上角三个正方形的面积相等,而面积相等就等价于边长相等就恰巧是我们的 d p dp dp 状态,那么就能合成更大的一个正方形

d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + 1 dp[i][j] = dp[i-1][j-1] + 1 dp[i][j]=dp[i1][j1]+1

如果不相等的话,那么就是从三个正方形中选一个最小的加一来合成

d p [ i ] [ j ] = m i n ( d p [ i − 1 ] [ j − 1 ] , m i n ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) ) + 1 dp[i][j] = min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1])) + 1 dp[i][j]=min(dp[i1][j1],min(dp[i1][j],dp[i][j1]))+1

当时脑子有点昏,不相等我就直接让他等于 1 1 1 了,面试官说有事,我的思路没问题,细节还需要注意下,然后就run了,现在想来真就差一点

#include<bits/stdc++.h>
using namespace std;
#define N 500
int dp[N][N];
int n,m;
vector<char> matrix[N];
int main()

    cin>>n>>m;
    for(int i = 0;i < n; ++i) 
		for(int j = 0;j < m; ++j) 
            cin>>matrix[i][j];
    
    memset(dp,0,sizeof dp);
    int ans = 0;
    for(int i = 0;i < n; ++i) 
        for(int j = 0;j < m; ++j) 
            if(matrix[i][j] == '1') 
                if(dp[i][j] == dp[i][j+1] && dp[i][j] == dp[i+1][j] && dp[i][j+1] == dp[i+1][j])
                    dp[i + 1][j + 1] = dp[i][j] + 1;
                else
                    dp[i + 1][j + 1] = min(dp[i][j],min(dp[i+1][j],dp[i][j+1])) + 1;
            

            ans = max(ans,dp[i+1][j+1]);
        
    
    pritnf("%d\\n",ans);
    
    return 0;

以上是关于字节跳动C++云原生二面(65min)的主要内容,如果未能解决你的问题,请参考以下文章

第三十八期字节跳动后台开发二面凉经

字节跳动Java后端开发一二面,心态爆炸

揭秘字节跳动云原生Spark History 服务 UIService

成都精灵云C++ 二面(hr面,30min)

成都精灵云C++ 二面(hr面,30min)

字节跳动云原生:机器学习平台建设实践