印象非常深刻的一场面试,十分考验整体架构能力和实操能力。没有八股,全是场景。

场景题:

1.并发请求控制器 请实现一个函数 createRequestPool(limit),用于控制异步请求的并发数量。 要求:

  • createRequestPool(limit) 返回一个函数 add(task),task 是一个返回 Promise 的函数。
  • 最多只能有 limit 个任务同时执行,其余任务需要排队。
  • 当一个任务完成后,应自动开始下一个任务。
  • 所有任务最终都能执行完成。

示例:

function mockTask(id, delay) {
  return () =>
    new Promise((resolve) => {
      setTimeout(() => {
        console.log("done:", id);
        resolve(id);
      }, delay);
    });
}

const pool = createRequestPool(2);

pool.add(mockTask(1, 300));
pool.add(mockTask(2, 200));
pool.add(mockTask(3, 100));
pool.add(mockTask(4, 400));

function createRequestPool(limit: number) {
    // code here
    const queue = [];
    let runningCount = 0;
    
    const add = (task) => {
	    queue.push(task);
	    runNext();
    }
    
    const runNext = () => {
	    // 当有任务在排队,并且有空闲的执行名额时
	    while (queue.length > 0 && runningCount < limit) {
		    const task = queue.shift();
		    
		    if (task) {
			    runningCount++;
			    task().finally(() => {
				    runningCount--;
				    runNext;
			    })
		    }
	    }
    }
}

2.数据表设计 我们计划推出一个网页活动,持续 30 天:

  • 用户可以设定自己的昵称,要求不能与其他用户重复;
  • 用户每天登录可以获得 1 积分,活动期间最多获得 10 次;
  • 用户可以花费1积分进行1次抽奖,奖品为 A / B / C 三种;
  • 需要提供接口查询:
    • 用户积分
    • 用户抽奖记录
    • 某个奖品的前 100 个中奖用户
  • 请完成mysql数据表结构的设计
create table `user` (
	id: string,
	nickname: string,
	points: int,
	login_count: int,
	created_at,
	updated_at,
);

create table `login_records` (
	id: string,
	user_id: string,
	login_data: string,
	created_at,
	// 保证不重复
	UNIQUE KEY `uk_user_data` (`user_id`, `login_data`)
)

create table `lottery_draws` (
	id: string,
	user_id: string,
	prize_type: A | B | C,
	created_at,
)

如何实现单点登录

单点登录 (Single Sign-On, SSO)

目标:让用户只需登录一次,就可以访问所有相互信任的应用系统(分布在不同子域名的项目)。

核心思想:将登录认证的逻辑抽离出来,交给一个独立的、所有应用都信任的中央认证服务 (Central Authentication Service, CAS)

工作流程简述:

假设你有三个应用 app1.yourdomain.comapp2.yourdomain.com 和一个认证中心 auth.yourdomain.com

  1. 首次访问:用户访问 app1.yourdomain.com 的受保护页面。
  2. 检查登录状态app1 发现用户未登录,将用户重定向到认证中心 auth.yourdomain.com,并带上自己的回调地址 (redirect_uri=app1.yourdomain.com/callback)
  3. 用户登录:用户在 auth.yourdomain.com 页面上输入用户名和密码。
  4. 认证成功
    • 认证中心校验成功后,会做两件事:
      a. 在 auth.yourdomain.com 的域下设置一个用于跟踪登录会话的 Cookie(例如 session_id)。
      b. 生成一个一次性的授权码 (code),然后将用户重定向回 app1 的回调地址,并附上这个 code:app1.yourdomain.com/callback?code=xxxx
  5. 获取令牌app1 的后端收到 code 后,会向认证中心发起一个后端请求,用这个 code 换取一个 Access Token
  6. 登录完成app1 验证 Token 有效,并为用户在 app1.yourdomain.com 域下创建自己的会话(或将 Token 存在前端),用户成功登录 app1

如何实现单点登录:

  1. 访问其他应用:现在,用户打开一个新的标签页访问 app2.yourdomain.com
  2. 再次重定向app2 发现用户未登录,同样将用户重定向到 auth.yourdomain.com
  3. 免密认证:此时,认证中心的服务器收到了来自 app2 的请求,它检查浏览器发来的 Cookie,发现了之前登录时设置的 session_id。它知道这个用户已经登录过了!
  4. 直接跳转:认证中心跳过登录页面,直接生成一个新的 code,并把用户重定向回 app2 的回调地址。
  5. 后续流程同步骤 5 和 6,用户无需再次输入密码就自动登录了 app2

鹰角一面

作者

MeorinLime 梦灵

发布日期

2025 - 08 - 08