Golang开发相关我爱编程

作为后端, 面试官可能会问你的问题

2018-03-22  本文已影响108人  bysir

1. 基础

浏览器请求一个域名的流程

  1. 浏览器通过udp向dns服务器请求得到ip地址
  2. 如果是https协议, 浏览器会向web服务器请求得到它的数字证书并验证其是否受信任, 具体看后面-[https认证流程].
  3. 浏览器通过tcp/ip协议发送http协议的数据包
  4. 服务器向浏览器相应数据

衍生出以下知识点

https认证流程
  1. 浏览器访问https网站, 发送随机数R1, 支持的加密算法类型, 协议版本, 压缩算法等
  2. 服务器返回随机数R2, 选定加密算法类型, 协议版本, 以及服务的证书.
  3. 浏览器验证数字证书是否有效, 若无效会给用户提示, 如何验证看下一个问题-[数字证书信任链]
  4. 浏览器生成随机数R3, 用刚刚得到的公钥加密并发送给服务器, 服务器用私钥解密后得到这个密码. 现在双方都拥有R1, R2, R3这三个随机数, 用这个三个数再次生成一个秘钥用于通信, 我们称这个秘钥为会话秘钥.
  5. 浏览器和服务器使用这个秘钥对通讯数据进行对称加密.

Q: 为什么使用对称加密?
A: 对称加密效率高, 只要密码不是固定的安全性也有保障.

数字证书信任链

如何定义一个证书是受信任的?
只要CA是受信任的那么他签发的证书也是受信任的.

那么问题就变成了如何证明这个证书是由它所说的CA签发的.

通常,证书会包含 证书的公钥(pk),证书名,签发者(CA),签发者签名(sign)

在验证证书的时候会使用CA的公钥来验签sign, 如果正确那就能说明这个证书是由CA签发的.

那么CA又怎么证明自己是受信任的呢? CA也是一个证书, 同理向上证明CA的CA是受信任的即可, 那么就有一个问题是根(Root)如何证明自己是受信任的呢? 答案是Root不需要证明, 一般来说它会内置到操作系统里, 是绝对可信的.

dns解析流程

dns服务器与浏览器通信使用UDP协议. 由于dns通信的数据量不大, 要求速度较快, 即用即丢, 对时序以及正确性没太大要求, 用UDP正合适. TCP就有点消耗服务器性能了.

  1. 浏览器向dns服务器发送报文请求xxx域名的ip地址, 报文见下注
  2. dns服务器向浏览器发送报文通知id地址.

emm 怎么感觉说了当没说... 好吧, 本来就不复杂.

举例说明一个消息队列的消息生命周期

主要考点: 怎么确保一个消息送到了.

TCP握手与挥手流程

建立TCP需要与服务器握手三次,你先告诉服务器你要给服务器发东西(SYN),服务器应答你并告诉你它也要给你发东西(SYN、ACK),然后你应答服务器(ACK),总共来回了3次,称为3次握手。

关闭TCP需要与服务器进行四次通信,你先告诉服务器你要关闭了(FIN),服务器应答你说好,我收到你的请求了(ACK),然后服务器会继续传输还没传输完的数据,完成之后告诉你说我也要关了(FIN),然后你回应(ACK),称为4次挥手。

那为什么在关闭的时候不像建立的时候服务器将(ACK和FIN)一起发送给客户端? 原因是在这个ACK和FIN之间服务器可能还要发送一些没有发送完的数据给客户端,而建立的时候没有数据传输也就不需要分开。

redis数据结构有哪些

string(字符串), hash(哈希表), list(列表), set(集合), zset(有序集合)

其中可以排序的数据结构有: list, set, zset

string

命令: SET / GET

redis最基础的数据类型, 可以存储任何数据.
一个键最大能存储512MB

hash

命令: HMSET / HGET

hash是一个键值对集合, 也称键值对. 一般用来存储一个对象.
一个hash表可以存储 2^32 -1 个键值对

list

命令: LPUSH / LPOP / BLPOP / LRANGE

list是字符串列表, 按照插入的顺序排序, 可以指定从哪个方向添加获取取出元素.
一个list可以存储 2^32 -1 个元素

set

命令: SADD / SMEMBERS / SCARD

与list不同的是set的元素不能重复

set是string类型的无序集合, 有诸多高级命令, 常用的有

一个set可以存储 2^32 -1 个元素

zset

命令: ZADD / ZRANGE / ZCOUNT / ZREM / ZREMRANGEBYLEX

zset是set的排序版, 元素根据score来排序, 如ZADD命令:
ZADD key score1 member1 [score2 member2]

ZADD boom 1 C4 2 NTN

排序就是C4在前NTN在后.

与set同样 元素不能重复, 但是score可以重复.

由于排序特性与Redis的高效, zset经常用到需要实时排名的场景, 比如游戏中的土豪玩家充钱排行.

如何使用redis实现一个分布式锁

在多个服务器上要实现同步锁稍微有点复杂, 需要借助第三方程序实现. redis是很好的选择.

方案1: string数据类型+自旋

容易想到的实现是:

func lock() {while (GET key != '') ; SET key 1 EX expire}
func unlock() {DEL key}

可以看到当第一个调用者得到锁之后, 第二个调用者在得不到锁的情况下会进入自旋状态, 直到第一个调用者unlock或者超时之后才能得到锁.

这个方案的问题是:

方案2: list数据类型+BLPOP

用BLPOP解决自旋引起的性能消耗, 用list保证同时只拿得到一个锁.
而BLPOP自带参数timeout能更简单的解决死锁问题.

func init () {if (LLEN key == 0){LPUSH key 1}}
func lock() {BLPOP key }
func unlock() { LPUSH key 1}

lock在list中取出一个key, 如果没有元素则阻塞. 为了防止一开始list中没有值需要执行init初始化.
init会在list中插入一个元素, 为保证只有一个锁需要先判断这个list的长度.

细心的朋友可能会发现一个问题, init中会出现并发问题.

这个方案要注意的问题是lock之后一定要调用unlock, 不然之后的lock都会有问题.

emm... 感觉这个方案还是有问题

方案3: baidu+google

作者放弃了自己实现, 于是百度找到方案, 方案通过

ping的原理, 使用的协议

mysql 读写锁

什么情况下mysql的写操作是并发安全的

mysql 几种引擎的区别

mysql 几种事务的区别

短连接原理及实现

解释线程/进程

什么是并发模型, 有哪些?

常见的GC算法

基本

高级

高级方式是对基本算法的融合

总结

任何GC算法都是跟踪回收和计数回收两种思路的结合.

go使用的GC算法

2. 算法

常见的排序算法有哪些, 如何选用合适的算法?

3. Golang

goroutine与线程/进程区别

slice/array的区别

slice的底层是array, 结构如下

struct slice {
  cap int
  len int
  ptr *[]T
}

其中ptr指向的就是底层的数组.

append在什么情况下会扩容, 如何扩容, 扩容会发生什么

当slice的cap不能再存放这么多元素的时候就会扩容, 扩张后的容量是原cap的两倍.

注: 好像不会一直是两倍, 在大于1024长度的时候会优化, 比如只增长1/4*1024. 到底是不是这样请google吧, 我暂时也没找到资料.

扩容的时候原slice指向的array会被释放, 并重新new了一个array存放元素, 所以append返回的slice有时候(没扩容)是原地址, 有时候(扩容后)不是原地址, 这点需要注意~

实现消费者/生产者模型

多个生产者+多个消费者模型使用GO很好实现, 就是使用多个goroutine和一个chan.

func main(){
  c:=make(chan int,10)
  
}
chan由谁关闭?

对比 Actor 和 CSP 模型

4. Js

现代框架如Vue, React与JQuery的区别

Vue响应式数据的实现原理

Vuex设计思路

未完待续

上一篇 下一篇

猜你喜欢

热点阅读