分类 唠嗑 下的文章

剑指题解


互联网人题解神器,神器在手,offer我有

随手刷题 | 无广告绿色免费 | 个性推荐 | 每日自动推送 | 多维度丰富领域知识

项目的起源是一个 github 仓库,名为前端知识每日 3+1,正是这个优秀的题库项目才有了我们团队开发聚合题库的想法。在我们国内程序员圈子,大多数小伙伴为了更好的技术发展和 offer,都通过训练题来提高自己的眼界,其中不乏包括算法/业务/软技能的题目,但是因为我们的环境和侧重点不一样,所以我们接触的项目和题目都不一样,而市面上很少有一个项目能做到,涵盖不同圈子的聚合题库。 《剑指题解》项目就是一个优秀的互联网行业聚合题库神器。


开源免费不易,请关注我们的公众号以及开源仓库

沈昊Seho/InternetQuestionBank<br/>
Github 点 star, 拉取代码时请选择最新分支
Dcloud 插件市场支持我们

目录

特点

  1. 汇聚优秀的开源题目,以技术社区为主线展开的刷题 APP
  2. 根据用户的喜好,去推送相关的最新题目,不会再刷到 “牛头不对马嘴”无用的题目
  3. 我们绑定了服务号,每日定时推送给用户最新的题目,让你能在每天清晨就开启活力新一天
  4. 刷题 APP 无广告,无硬性推广,一切盈利皆在赞助/官网流量
  5. 我们还有很多有意思的待开发 feature,比如大佬带萌新模式,还将开启校园/企业的通道,让每一个学生/员工都能每时每刻提高自己
  6. 剑指题解开源项目,从原型图到小程序,UI 图,UML,API 文档,第三方 API 对接说明书,使用说明都将免费开源,欢迎各位同僚二开,让这个行业变得更好,我们将用心地辅助你们解决在技术上的难题。

技术栈

关于技术栈的选型可以参考我们的语雀文档
周边物料的开源,还需要感谢 mockPlus 以及语雀:

<img class="imgIcon" src="http://static.yinzhuoei.com/typecho/2021/01/17/69752764374919.png" width="10%">


<img class="imgIcon" src="http://static.yinzhuoei.com/typecho/2021/01/17/697832282748067.jpg" width="20%"></img>

UML

由于此部分在开发新 feature 的工作中可能会进行变更或者本就有实质性的错误,欢迎向我们反馈错误,我们将感激不尽。

类图

拉取任务

更多

更多相关资料请移步
out/doc或者语雀-UML

设计概览



设计源文件请移步:点击查看-为了您的体验,请务必下载最新版本的设计图
原型图在线预览: 点击查看, 如果失效请联系我们

API

《剑指题解》团队在 API 层面,开源的内容非常有限制,因为涉及到多位合作伙伴的题库授权,所以如果您要使用聚合题库 API 请联系我们商议,如果您是学习者,那么在语雀中的 API 文档会帮助到您,在这里我们将简单介绍。

uniapp 的云函数开发,我们是第一次接触,所以在此之前我们做了很多调研,在下文也提到了关于 explain.js 这个框架的作用,我们也是非常感谢 uniapp 开源社区有这样创作质量的第一批的 unicloud 框架开发者,在咨询了官方人员之后,我们了解到如果要使用 ts 来开发,需要把 ts 编译成 js 来放在云函数目录,所以我们选择了以下的技术栈,开发者可以很爽的使用 ts 来开发 unicloud 云函数:

  • esbuild-node-tsc
  • nodemon

esbuild-node-tsc 这个工具是基于 esbuild 的,利用其特性,我们可以比 ts 官方提出的 tsc 编译工具更快,快几十倍到上百倍,这也是得益于 esbuild 的使用 go 语言直接编译的特性。

nodemon 可以帮助我们监听目录文件,一旦改变就执行打包 ts 命令直接将编译好的 js 放在指定目录
所以我们把 explain.js 的配置也相应的改变,我们在 services 目录中存储的是我们 ts 文件,在 dist 中存储的是我们编译好的 js 文件,而 dist 目录就是 explain 需要的:

config.init({
  baseDir: __dirname,
  serviceDir: "/dist/",
});

需要注意的事情是:
由于云函数大小限制,我们需要把相关依赖全部安装到全局,包括 typescript

读写职责分离

读写职责分离模式(CQRS)是一种把查询(Queries) 数据和和更新(Commands) 数据通过使用各自独立的接口分开的模式。
Uniapp 的 Unicloud 很好,其中的 jql 也是大开眼界,确实统一了前端开发操作数据库的体验,让我们前端开发操作数据库非常友好,但是我们使用 CQRS 将这些原本封装的很好的 API 不予以使用。

  • 前端使用 jql 去读取想要的数据
  • 写入操作就交给云函数去执行

如图,前端读取一个列表数据

const db = uniCloud.database();
const databaseName = "testInit";
// 获取测试数据列表
export function getTestList() {
  return new Promise((resolve) => {
    db.collection(databaseName)
      .get()
      .then((res) => {
        // res 为数据库查询结果
        resolve(res);
      })
      .catch((err) => {
        // err.message 错误信息
        // err.code 错误码
      });
  });
}

我们将这样的文件抽出了一个一个查询模块,每一个模块对应了一个数据表(这里是 testInit)封装在了 API 这个文件夹中。

Vue 页面将这样去调用,这样我们在 API 查询层将做好数据的处理,确保 Vue 拿到的是可以直接渲染的干净数据。

import { getTestList } from "../../api/test";
const data = getTestList();

我们写入操作将通过云函数直接调用,唯一设计不同的地方在于,我们将云函数这个概念改变了,应该是模块化,我们把一个一个函数变成了模块。

在我们的初步技术调研过程中,由于 Uni 官方并没有提供给用户云函数开发框架,但是我们在插件市场中找到了一款名为 explain 的开发框架,它可以迅速的帮助我们实现 restapi 风格的单路由云函数,这款框架我们不多做介绍,文档在这里:explain.js 快速开发 uni 云函数的框架

// 注册用户根据手机号
  addUserByPhone() {
    return handleMustRequireParam(
        [{
            key: "username",
            value: "用户名",
          },
          {
            key: "password",
            value: "密码",
          },
        ],
        this.event.params
      )
      .then(async () => {
        const {
          username,
          password
        } = this.event.params;
        if (!/^1[3456789]\d{9}$/.test(username)) {
          return appErrorMessage("用户名格式不正确");
        } else if (password === "" || password.length < 6) {
          return appErrorMessage("密码格式不正确");
        } else {
          // 校验手机号
          return await uniID.register({
            username,
            password,
          });
        }
      })
      .catch((err) => {
        return err;
      });
  }

那么我们如果要调用 testPrint 这个模块中的增加操作

uniCloud.callFunction({
  name: "application",
  data: {
    route: "api/user",
    method: "POST",
    params: {
      username: "18291563764",
      password: "sas",
    },
  },
});

贡献者

感谢为《剑指题解》这个优秀项目贡献自己一份力的小伙伴们:

如果您想加入到我们的贡献者队列中,请联系我们,这里还有相关贡献者的介绍,希望对您有帮助

核心维护者

相关开源物料

题库合作伙伴

QQ 群和钉钉群欢迎大家加入


许可

Apache License © 剑指题解
如果您在其他有关我们的文档见到了与之不符合的协议内容,请联系我们,这可能是我们的历史遗留的代码问题。

Nginx是一款高性能服务器,最近这几年非常火,以轻量且高并发,高性能著称,那么此笔记将不会从0开始讲解API,而是会从各种问题入手,通过问题学习nginx。


特点:

  1. IO多路复用
  2. 高性能
  3. 高并发
  4. 占用系统资源少

Untitled.png

Nginx作为一个WEB服务器,有着大好的未来,市场份额非常给力,同时也是份额上升速度最快的web服务器。

Untitled.png

Nginx作为前端来说,需要学习什么?我们只需要学习Nginx在应用部署,反向代理,处理资源的进程,亦或者是搭建网站的基础知识,如果你还没有一个blog,那么就从现在开始学习nginx并且搭建你的第一个网站吧。


反向代理与正向代理

Untitled.png

我们在平时上外网的时候,比如谷歌,youtube,twitter,Ins等,如果使用我们内地网络,是访问不成功的,只有在香港台湾或者境外才能访问到类似的外网。那我们需要通过内地网络去访问外网只能通过一个proxy代理去做一个请求的转发,我们的内地网络请求在到达外网地址之前,会经过一层代理,这个代理会去请求外网,请求成功之后会把页面呈现给我们的客户端。

在这个过程中,外网服务器不知道我们的内地网络是谁,只知道代理地址,所以对于外网服务器来说,请求的真实客户端是看不到的。那么这个过程就叫做 正向代理,proxy代理的是客户端。

Untitled.png

反向代理是相反的,代理的是服务端,对于客户端而言,访问的服务器仅仅是多个真实服务器的一个代理而已,所以对于客户端用户而言,真实服务器的信息是不可见的。这样的过程也就是反向代理,proxy代理的是服务端

Nginx如何去做反向代理?

server{
        listen 80;
        server_name nginx.yinzhuoei.com;
        location / {
               proxy_pass http://yinzhuoei.com;
        }
}

其他的proxy配置:

proxy_set_header :在将客户端请求发送给后端服务器之前,更改来自客户端的请求头信息。
proxy_connect_timeout:配置Nginx与后端代理服务器尝试建立连接的超时时间。
proxy_read_timeout : 配置Nginx向后端服务器组发出read请求后,等待相应的超时时间。
proxy_send_timeout:配置Nginx向后端服务器组发出write请求后,等待相应的超时时间。
proxy_redirect :用于修改后端服务器返回的响应头中的Location和Refresh。

解决跨域

通过反向代理解决跨域:

server
{
   listen 3003;
   server_name localhost;
      ##  = /表示精确匹配路径为/的url
   location = / {
       proxy_pass http://localhost:5500;
   }
   ##  若 proxy_pass最后为/ 如http://localhost:3000/;匹配/no/son,则真实匹配为http://localhost:3000/son
   location /no {
       proxy_pass http://localhost:3000;
   }
   ##  /ok/表示精确匹配以ok开头的url,/ok2是匹配不到的,/ok/son则可以
   location /ok/ {
       proxy_pass http://localhost:3000;
   }
}

加header头允许跨域:

server
{
    listen 3002;
    server_name localhost;
    location /ok {
        proxy_pass http://localhost:3000;

        #   指定允许跨域的方法,*代表所有
        add_header Access-Control-Allow-Methods *;

        #   预检命令的缓存,如果不缓存每次会发送两次请求
        add_header Access-Control-Max-Age 3600;
        #   带cookie请求需要加上这个字段,并设置为true
        add_header Access-Control-Allow-Credentials true;

        #   表示允许这个域跨域调用(客户端发送请求的域名和端口) 
        #   $http_origin动态获取请求客户端请求的域   不用*的原因是带cookie的请求不支持*号
        add_header Access-Control-Allow-Origin $http_origin;

        #   表示请求头的字段 动态获取
        add_header Access-Control-Allow-Headers 
        $http_access_control_request_headers;

        #   OPTIONS预检命令,预检命令通过时才发送请求
        #   检查请求的类型是不是预检命令
        if ($request_method = OPTIONS){
            return 200;
        }
    }
}

Master&Woker模式

Nginx启动之后,启动了80端口进行服务监听,那么进程中就存在一个Mater主进程和多个Woker进程;

Untitled.png

Master进程的作用就是:读取&验证nginx.conf配置文件并且管理多个woker进程;接受外部信号;监控Woker,如果Woker挂掉,将自动重启Woker;

Woker进程的作用就是:多个Woker会拦截所有的请求并做出处理;每一个woker进程维护一个线程;woker的个数和CPU有关,从nginx.conf配置woker个数,配置几个就是几个,但是要避免配置过多,要充分利用CPU;

一个请求到响应的流程:

  1. Nginx启动,Matster进程根据nginx.conf初始化;初始化监听socket;fork出多个woker进程;
  2. 发起请求
  3. woker进程们一起竞争,胜出者通过三次握手,建立socket连接,处理请求。

如何做热部署呢?

热部署就和前端热部署一样的性质,即修改配置文件,不需要重启服务器就可以使用最新的配置。

nginx -s reload

通过这样的一个命令即可热部署,无需重启,随时改随时用。

一般情况下,我们做热部署可以有几个方案,比如前端,webpack的本地开发工具,webpack-dev-server,即本地启动一个服务,开启一个websocket,当我们的文件改动,就重新加载这个css/js。

而nginx也是同样的方式么?我们的主进程master去发布一个修改请求,然后woker去订阅这个消息,实现类似这样的热部署?

其实不然,nginx使用的是如下的方案,当master监听到配置文件的更改,会创建一批新的woker去执行新的请求,老的woker进程会在任务处理完毕之后,再由master杀掉进程。


如何做到高并发?

Nginx采用多进程+异步非阻塞方式(IO多路复用):

关于异步和同步,我需要做一些概念上的整理;

同步和异步指的是消息的通信机制,我们做web开发是最能理解同步异步的区别的,因为我们天天和接口打交道;

1)所谓同步指的就是发起一个请求/调用,在没有得到结果之前就不会返回,一旦得到结果就立即返回;

2)所谓异步指的就是发起一个请求/调用,调用者不会主动去care被调用者,而被调用者拿到结果之后会通知调用者

而阻塞非阻塞指的是程序在等待调用结果时的状态

1)阻塞调用指的就是,结果返回之前当前线程被挂起,调用线程在返回之后才返回;那么挂起的这个线程是会被阻塞的;

2)非阻塞调用指的就是,不能立刻得到结果之前,线程是不会被挂起的,仍然可以做其他事情;那么非阻塞调用如何知道得到结果了呢,需要定时去check的;

关于阻塞IO和非阻塞IO等我总结完了再说哈,还有关于Nginx的IO多路复用Epoll模型,这个是延申知识了,我也需要学习整理哈,现在还不清楚这一块的东西。

Nginx后续章节过段时间发,中间要发几篇shadowDom和剑指题解的文章,大家耐心等待...


学习资料如下:

nginx如何做到高并发?
8分钟带你深入浅出搞懂Nginx
理解同步异步&阻塞非阻塞

微信截图_20210331210548.png

微信截图_20201212173122.png
最近一直在调研unicloud云函数开发,所以一直想给js加入类型推导,这篇文章就记录一下我是如何开发TS版本的云函数的吧。

  1. 确定使用TS还是Flow.js

Flow.js在基本语法上和TS很相像,我认为它是一个针对老项目的类型推导方案,因为只需要安装简单的包和给文件加入Flow的标识就可以给对应的文件提供类型推导的功能,所以针对目前我所做的这个业务来讲,不存在老项目,所以既然是新项目就不如直接上TS。

在云函数开发过程中,我们在插件市场选择了一款非常简洁已拓展的explain框架,这个框架目前已经支持单路由和restfulAPI还有基本的过滤拦截器,那么目前这个框架没有做TS的解决方案,我就斗胆替作者大大想一个曲线救国的方案,而且这个方案有以下特点:

  1. TS的编译速度比官方提供的TSC编译要快几十倍到上百倍
  2. 支持重新加载打包
  3. 云函数项目0依赖就可以玩转这套方案

uni官方的云函数大小限制是10M,所以我们不能把依赖都安装在项目中,需要我们全局安装:

npm i -g typescript esbuild-node-tsc nodemon
  1. esbuild-node-tsc是基于esbuild的ts编译器,大名鼎鼎的esbuild由于其出色的编译特性,能够让我们在大型项目中编译ts速度更快。
  2. nodemon帮助我们在文件变更时重新编译ts

2个插件的玩法很多,尤其是nodemon,在我们这个解决方案中我们只需要简单的配置几个文件就可以把我们的项目跑起来了。

微信图片_20201212171411.png

我们的云函数目录是这样的,这是搭配了前面提到的explain.js,在etsc.config.js中我们可以配置一下,输出的js版本规范以及目录和是否进行压缩:

module.exports = {
  outDir: "./dist",
  esbuild: {
    minify: true,
    target: "es2015",
  },
  assets: {
    baseDir: "services",
    filePatterns: ["**/*.json"],
  },
};

在services目录中编写完ts文件之后,esbuild-node-tsc会把js文件放到dist目录之下,我们现在只需要更改explain.js默认配置:

config.init({
  baseDir: __dirname,
  serviceDir: "/dist/"
});

这样explain会从dist下找文件而不是从services文件下找

我们在这个根目录下运行编译命令即可

etsc

这个时候我们运行这个函数就会发现,它已经达到了我们的目标了:

  1. 开发使用了ts
  2. 可以正常的跑通和上传云函数

但是我们需要services下的文件一变更就编译放到dist下,我们就需要nodemon帮助我们做这个事情(nodemon.json):

{
    "watch": ["services"],
    "ext": "ts,js,json",
    "exec": "etsc",
    "legacyWatch": true
  }

监听services目录,包括文件名为ts,js,json,执行命令etsc

然后我们再把这个运行nodemon的命令放到package.json中:

"scripts": {
    "dev": "nodemon"
  },

这样我们就可以启动nodemon这个监听服务,可以很爽的使用ts来开发云函数啦~~
微信截图_20201212172316.png

微信截图_20210331210548.png

超低价PDD打造无限极简桌面攻略

如题所见,这篇文章可不是软文,我们武林中人不能不讲武德的

1758.jpg

主要是自己因为工作后续的需要,需要配置更多的屏幕,所以参考了网上很多大佬的桌面,桌面上动不动mbp,switch,好几千的键盘,4k+的电脑屏幕,千把块的屏幕灯。好家伙把我卖了都没那么多钱,作为程序萌新没那么多钱又想打造一个实用的桌面,你就该看我这个!

完成效果图:

微信图片_20201112221509.jpg


首先我们从价格低到高排序咯,首先就要介绍的笔记本夹架:

来源:淘宝

价格:20-30

推荐星级:五颗星

推荐链接:

淘宝网

评价:不用笔记本的朋友可以用这个架子,这个架子本来是夹餐巾纸的,但是它足够稳固,夹得住,立起来不会伤害电脑,再加上外观清爽,非常好!

O1CN01tFjUIH24Iaj9FfrX6_!!748817368.gif


桌上的老物件:手机/ipad支架是在线下宜家店淘的,这个支架有充电口而且是方便组装的,颜色也是实木风格搭配黑色非常好。

来源:线下宜家

价格:30

推荐星级:4颗星

推荐链接:

SIGFINN 希格芬 手机支架 - 竹子贴面 - IKEA

sigfinn-xi-ge-fen-shou-ji-zhi-jia-zhu-zi-tie-mian__0534722_PE649256_S5.jpg


对于干净的桌面,我就选择了桌下的埋线置物架,首先插板走线都可以从这个架子上走,由于是吸附在桌子下的,所以不会影响到抖腿(滑稽)

来源:拼多多

价格:30+

推荐星级:5颗星(无线桌面非常核心)

推荐链接:

拼多多商城

微信图片_20201112230241.jpg

对于程序员群体来说,在夜晚工作是家常便饭,那么屏幕挂灯就是我们的必备品,因为它不占空间光线可调节等特性,可以让我们眼睛很舒服,屏幕挂灯有多个品牌,既然我们推崇的是性价比,我们就不得不提到小米的屏幕灯啦!对比明基千元的屏幕挂灯,小米这款灯可谓是性价比拉满,不仅有非对称光源还自带无线遥控,非常适合无线桌面呢

来源:小米有品

价格:200

推荐星级:5颗星

推荐链接:

米家显示器挂灯立即购买-小米商城

pms_1590926574.98465077.jpg


对于电脑桌,如果想承受更多的屏幕支架和书籍/空间,那就必须选用1.5m++的桌子,一般的电脑桌都会自带埋线孔,所以电脑桌我就在pdd随便买的,价格基本都是在200元左右,没有必要去选用带储物功能的桌子。

来源:拼多多

价格:200左右(尺寸不一样价格不一样)

推荐星级:3颗星

推荐链接:

拼多多商城
微信图片_20201112231327.jpg


Oh,My god终于到重头戏了,对于显示器支架真的有太多选择了,这里我买了2款,一款是双屏幕的支架和一个显示器壁挂支架,因为老aoc显示器不支持壁挂所以就在同一家店买了壁挂支架,显示器支架非常便宜,100多块就能拿下oh~

来源:淘宝

价格:100+

推荐星级:5颗星

推荐链接:

淘宝网
微信图片_20201112231717.jpg


接着就是我们的最后一个拼多多商品了,这个商品放到最后一个肯定是有原因的,因为真的是pdd购物血泪史,但是结果还是非常好的。因为预算不够所以把4k显示器降低为2k,价格也降低了一半,所以我就抱着试一试的心态购买了pdd的2k显示器,价格只需500出头就可以拿下24寸2k显示器。

收到货之后,发现屏幕窄边框很舒服,屏幕没坏点,该有的接口都有,可是就是开不了机器,店家阿你不讲武德阿,怎么给我一个坏的呢?然后经过和客服的调试发现是电源坏了,然后店家寄了一个电源给我,发现显示器可以开机了。本以为能体验一下捡漏的显示器发现和笔记本连接不上,经过调试发现是HDMI接口有问题,没办法,因为是壁挂的所以影响了二次销售不能退货,只能花70块快递让店家维修,维修之后,开机!完事大吉~

pdd的显示器买的虽然一波三折,但是结局还是好的,也希望给大家一个教训。

来源:拼多多

价格:510

推荐星级:1颗星(抛开退换货就是五颗星,还是值得一试的)

推荐链接:

拼多多商城

微信图片_20201112233131.jpg


Ok!这次打造无线极简桌面的推荐就结束了,还差无线键盘和鼠标这些大家如果为了无线和极简那就挑着自己喜欢的牌子的无线版本就好了噢~