2026年4月

后续大概了解了一下,我觉得色温灯的需求不高,目前我的想法是
1 、 网关 M2 , 智能开关,不需要妙控屏幕里
2 、 中央空调的 VRF 控制器 是肯定要的
3 、 传感器,目前的想法是: 主卫一个,次卫外面有个设计小灯(我想路过让他自动亮起
4 、 能介入 homkit 的智能门铃 (昨天看视频,门铃可以自动投放到电视机上,感觉还不错


有几个问题想问问:

1 、妙控屏是否必须呢? 智能开关一般要多少个? 三个房间,主卫,次卫,这是 5 个? 客餐厅各一个? 一个 7 个吗
2 、色温灯的场景到底有没有必要
3 、智能门锁是否有必要? 我昨天看视频讲解说是,门锁可以链接 tsl 自动开空调,我觉得这也不错
4 、如果后续洗衣机啊,扫地机器人接入的话,是不是只要机器支持就可以?
5 、新风系统有必要接入吗? 还有什么厨房的一些报警系统?

感谢各位大佬

前几天随手发了一个骑摩托车的视频,没想到引起了轩然大波,视频被推流到了广东广西等地方,观众大多也都是外卖骑手,评论区基本一边倒

举例来说:

我在北京发视频说:这条路60巡航很舒服

A:60 太慢了,我这边都是 80 起步

B:你这属于危险驾驶,必须 40 (配图小区内道路)

C:不会骑车就别骑

D:我电动车都比你快

后续我又发了个视频解释为什么,但还是有人在自说自话

这波视频流量不错,但是给我带了相当大的压力,周六那天都干失眠了

身处内地某省会城市。身为技术人员,不善交际,没有圈子。
一方面,年级大了,有找对象的需求。
二方面,读了些没用的书,有交流的需求。

对于需求一,试过一些 APP 和平台,要么没回应,要么好像是约 P 的。
对于需求二,没用的书读多了,好像是注定是孤独的。参加几次线下的一些读书会,来的人要么是来凑热闹的,要么跟自己不在一个频道。

Tomcat 是 Java Web 开发的基石。我们天天使用它,但你是否思考过它内部是如何工作的?为了打破这个“黑盒”,最好的方式就是动手实现一个极度精简的核心。本项目 “TinyTomcat” 的目标,就是用大约 300 行纯 Java 代码,实现一个能够解析 HTTP 请求、路由到对应处理逻辑并返回响应的微型服务器。通过这个过程,你将透彻理解 Tomcat 处理请求的本质:监听端口、解析协议、调度响应。

所以,我们的目标是:

  1. 监听一个端口(比如8080),接受HTTP请求。
  2. 解析HTTP请求,至少能解析请求的URL和方法(GET、POST等)。
  3. 根据请求的URL,找到对应的处理逻辑(类似于Servlet),并返回响应。
  4. 响应基本的HTTP格式,包括状态行、头部和响应体。

核心设计思路

一个基础的 HTTP 服务器,无论规模大小,其核心流程都可以抽象为下图所示的步骤:

graph TD
    A[客户端请求] --> B(ServerSocket 接受连接)
    B --> C[读取并解析 HTTP 请求行/头]
    C --> D{请求路径是 '/' ?}
    D -->|是| E[返回欢迎首页]
    D -->|是 Servlet 路径| F[调用对应 Servlet.service]
    D -->|是文件路径| G[查找并发送静态文件]
    D -->|都不是| H[返回 404 错误]
    E --> I[构建 HTTP 响应]
    F --> I
    G --> I
    H --> I
    I --> J[发送响应给客户端]

基于这个流程,我们设计出五个核心类,共同完成了上图的闭环:

  1. SimpleTomcat (服务器引擎):这是大脑,负责启动、监听端口,并协调所有工作。
  2. SimpleRequest (请求解析器):这是翻译官,将原始的、文本格式的 HTTP 请求解析成程序容易理解的 Java 对象。
  3. SimpleResponse (响应构建器):这是包装工,负责将我们的处理结果,包装成符合 HTTP 协议格式的字节流。
  4. SimpleServlet (处理接口):这是业务合同,定义了所有动态处理器(Servlet)必须遵守的规范。
  5. HelloServlet (业务实现):这是我们的一个具体业务逻辑例子。

构建服务器引擎 (SimpleTomcat.java)

这个类是程序的起点,也是调度中心。其核心逻辑在 start()handleClient方法中。

  • 多线程处理。我们使用 ExecutorService线程池来处理每一个客户端连接 (Socket),这是服务器能同时服务多个请求的基础,避免了单线程阻塞。
  • 路由分发。在 handleClient方法中,我们读取请求的第一行(如 GET /hello HTTP/1.1),解析出请求路径,然后根据一个预设的“路由表” (servletMapping) 来决定将这个请求派发给谁处理。这模仿了 Tomcat 中 web.xml或注解配置的 Servlet 映射机制。
  • 区分动态与静态。我们的路由逻辑区分了三种情况:访问根路径返回欢迎页、访问注册的 Servlet 路径则动态处理、其他路径则尝试查找静态文件
import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;
import java.time.*;
import java.time.format.*;

/**
 * Mini版 Tomcat - 核心服务器
 * 功能:监听端口、解析HTTP、路由请求
 */
public class SimpleTomcat {
    private int port = 8080;
    private String webRoot = ".";
    private ServerSocket serverSocket;
    private ExecutorService threadPool;
    private boolean running = false;
    
    // Servlet映射表:路径 -> Servlet实例
    private Map<String, SimpleServlet> servletMapping = new ConcurrentHashMap<>();
    // 静态文件后缀映射
    private static final Map<String, String> CONTENT_TYPES = Map.of(
        ".html", "text/html; charset=utf-8",
        ".txt", "text/plain; charset=utf-8",
        ".js", "application/javascript",
        ".css", "text/css",
        ".json", "application/json",
        ".png", "image/png",
        ".jpg", "image/jpeg",
        ".jpeg", "image/jpeg",
        ".gif", "image/gif"
    );
    
    public SimpleTomcat(int port, String webRoot) {
        this.port = port;
        this.webRoot = webRoot;
        this.threadPool = Executors.newFixedThreadPool(20);
    }
    
    public void start() throws IOException {
        serverSocket = new ServerSocket(port);
        running = true;
        System.out.printf("🚀 SimpleTomcat 启动在 http://localhost:%d\n", port);
        System.out.printf("📁 静态文件目录: %s\n", new File(webRoot).getAbsolutePath());
        
        // 注册默认处理器
        registerDefaultServlets();
        
        while (running) {
            Socket client = serverSocket.accept();
            threadPool.submit(() -> handleClient(client));
        }
    }
    
    public void stop() {
        running = false;
        try {
            if (serverSocket != null) serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        threadPool.shutdown();
    }
    
    // 注册Servlet
    public void addServlet(String path, SimpleServlet servlet) {
        servletMapping.put(path, servlet);
        System.out.printf("📋 注册Servlet: %s -> %s\n", path, servlet.getClass().getSimpleName());
    }
    
    private void registerDefaultServlets() {
        addServlet("/hello", new HelloServlet());
        addServlet("/time", (req, res) -> {
            res.setContentType("text/plain; charset=utf-8");
            res.getWriter().write("当前时间: " + Instant.now().toString());
        });
    }
    
    private void handleClient(Socket client) {
        try (client;
             BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
             OutputStream out = client.getOutputStream()) {
            
            // 读取请求行
            String requestLine = in.readLine();
            if (requestLine == null) return;
            
            String[] parts = requestLine.split(" ");
            if (parts.length < 3) return;
            
            String method = parts[0];
            String path = parts[1];
            
            // 创建请求/响应对象
            SimpleRequest request = new SimpleRequest(method, path, in);
            SimpleResponse response = new SimpleResponse(out);
            
            // 记录访问日志
            logRequest(client.getInetAddress().getHostAddress(), method, path);
            
            // 路由处理
            if (path.equals("/")) {
                serveWelcomePage(response);
            } else if (servletMapping.containsKey(path)) {
                // 动态Servlet处理
                servletMapping.get(path).service(request, response);
            } else if (path.equals("/favicon.ico")) {
                serveFavicon(response);
            } else {
                // 静态文件服务
                serveStaticFile(path, response);
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private void serveWelcomePage(SimpleResponse res) throws IOException {
        res.setContentType("text/html; charset=utf-8");
        PrintWriter writer = res.getWriter();
        writer.println("<!DOCTYPE html>");
        writer.println("<html><head><title>MiniTomcat</title>");
        writer.println("<style>");
        writer.println("body { font-family: Arial; margin: 40px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; }");
        writer.println(".container { max-width: 800px; margin: 0 auto; padding: 20px; background: rgba(255,255,255,0.1); border-radius: 10px; }");
        writer.println("h1 { text-align: center; font-size: 2.5em; margin-bottom: 30px; }");
        writer.println(".card { background: rgba(255,255,255,0.2); padding: 20px; border-radius: 8px; margin: 15px 0; }");
        writer.println("a { color: #ffd700; text-decoration: none; padding: 8px 15px; background: rgba(0,0,0,0.3); border-radius: 5px; }");
        writer.println("a:hover { background: rgba(0,0,0,0.5); }");
        writer.println("</style></head><body>");
        writer.println("<div class='container'>");
        writer.println("<h1>🚀 SimpleTomcat 已启动!</h1>");
        writer.println("<div class='card'><h3>📡 测试链接</h3>");
        writer.println("<p><a href='/hello'>/hello - 问候Servlet</a></p>");
        writer.println("<p><a href='/time'>/time - 时间Servlet</a></p>");
        writer.println("<p><a href='/index.html'>/index.html - 静态文件</a></p>");
        writer.println("</div>");
        writer.println("<div class='card'><h3>📁 服务器信息</h3>");
        writer.println("<p><strong>服务器时间:</strong>" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "</p>");
        writer.println("<p><strong>工作目录:</strong>" + new File(webRoot).getAbsolutePath() + "</p>");
        writer.println("<p><strong>已注册Servlet:</strong>" + servletMapping.size() + "个</p>");
        writer.println("</div></div></body></html>");
    }
    
    private void serveStaticFile(String path, SimpleResponse res) throws IOException {
        File file = new File(webRoot + path);
        if (!file.exists() || file.isDirectory()) {
            serve404(res, "文件未找到: " + path);
            return;
        }
        
        // 设置Content-Type
        String contentType = "application/octet-stream";
        for (Map.Entry<String, String> entry : CONTENT_TYPES.entrySet()) {
            if (path.endsWith(entry.getKey())) {
                contentType = entry.getValue();
                break;
            }
        }
        res.setContentType(contentType);
        res.setContentLength(file.length());
        
        // 发送文件
        Files.copy(file.toPath(), res.getOutputStream());
    }
    
    private void serve404(SimpleResponse res, String message) throws IOException {
        res.setStatus(404, "Not Found");
        res.setContentType("text/html; charset=utf-8");
        PrintWriter writer = res.getWriter();
        writer.println("<html><head><title>404 Not Found</title></head>");
        writer.println("<body><h1>404 找不到页面</h1><p>" + message + "</p>");
        writer.println("<p><a href='/'>返回首页</a></p></body></html>");
    }
    
    private void serveFavicon(SimpleResponse res) throws IOException {
        res.setStatus(204, "No Content"); // 不返回favicon
    }
    
    private void logRequest(String ip, String method, String path) {
        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"));
        System.out.printf("[%s] %s %s %s\n", time, ip, method, path);
    }
    
    public static void main(String[] args) throws IOException {
        int port = args.length > 0 ? Integer.parseInt(args[0]) : 8080;
        String webRoot = args.length > 1 ? args[1] : ".";
        
        SimpleTomcat tomcat = new SimpleTomcat(port, webRoot);
        Runtime.getRuntime().addShutdownHook(new Thread(tomcat::stop));
        tomcat.start();
    }
}

解析 HTTP 请求 (SimpleRequest.java)

HTTP 请求本质上是按特定格式组织的文本。SimpleRequest类的任务就是解析它。

  • 解析请求行。构造函数中,通过 requestLine.split(" ")可以得到方法、路径和协议版本
  • 解析查询参数。在 parseQueryString方法中,我们处理 URL 中 ?后面的部分(如 name=Bob&age=25),将其拆解成键值对,存入 params映射,这样 Servlet 中就能通过 getParameter("name")获取值。
  • 解析请求头。通过循环读取输入流直到空行,将 HeaderName: HeaderValue这样的行解析后存入 headers映射。虽然我们的迷你版没有用到所有头部信息,但这种设计为后续扩展(如处理 Cookie、Session)留出了空间。
import java.io.*;
import java.util.*;

/**
 * 请求对象
 */
public class SimpleRequest {
    private final String method;
    private final String path;
    private final Map<String, String> headers = new HashMap<>();
    private final Map<String, String> params = new HashMap<>();
    
    public SimpleRequest(String method, String path, BufferedReader in) throws IOException {
        this.method = method;
        this.path = path;
        
        // 解析查询参数
        int qIndex = path.indexOf('?');
        if (qIndex > 0) {
            parseQueryString(path.substring(qIndex + 1));
        }
        
        // 解析请求头
        String line;
        while ((line = in.readLine()) != null && !line.isEmpty()) {
            int colon = line.indexOf(':');
            if (colon > 0) {
                headers.put(
                    line.substring(0, colon).trim().toLowerCase(),
                    line.substring(colon + 1).trim()
                );
            }
        }
    }
    
    private void parseQueryString(String query) {
        for (String pair : query.split("&")) {
            String[] kv = pair.split("=", 2);
            if (kv.length == 2) {
                params.put(kv[0], kv[1]);
            }
        }
    }
    
    public String getMethod() { return method; }
    public String getPath() { 
        int qIndex = path.indexOf('?');
        return qIndex > 0 ? path.substring(0, qIndex) : path;
    }
    public String getParameter(String name) { return params.get(name); }
    public String getHeader(String name) { return headers.get(name.toLowerCase()); }
    
    public String toString() {
        return method + " " + path;
    }
}

构建 HTTP 响应 (SimpleResponse.java)

与解析请求相对,我们需要构建一个格式正确的 HTTP 响应。HTTP 响应由状态行、响应头和响应体三部分组成。

  • 延迟发送头。我们设置了 headersSent标志位。这是因为在业务代码(Servlet)中,可能会先设置状态、内容类型等头部信息,再输出响应体。getWriter()getOutputStream()方法会在第一次被调用时,自动将所有已设置的头部信息发送出去(sendHeaders方法),这是一个巧妙的设计,确保了头部先于身体发送。
  • 头部格式。在 sendHeaders方法中,我们严格按照 HTTP/1.1 200 OK\r\nHeader: Value\r\n\r\n的格式拼接字符串。注意最后的空行 \r\n\r\n,它是分隔头部和身体的关键标记。
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 响应对象
 */
public class SimpleResponse {
    private final OutputStream output;
    private PrintWriter writer;
    private int status = 200;
    private String statusText = "OK";
    private final Map<String, String> headers = new HashMap<>();
    private boolean headersSent = false;
    
    public SimpleResponse(OutputStream output) {
        this.output = output;
        headers.put("Server", "SimpleTomcat/1.0");
        headers.put("Date", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US)
            .format(new Date()));
    }
    
    public void setStatus(int status, String text) {
        this.status = status;
        this.statusText = text;
    }
    
    public void setContentType(String type) {
        headers.put("Content-Type", type);
    }
    
    public void setContentLength(long length) {
        headers.put("Content-Length", String.valueOf(length));
    }
    
    public PrintWriter getWriter() throws IOException {
        sendHeaders();
        if (writer == null) {
            writer = new PrintWriter(new OutputStreamWriter(output, "UTF-8"), true);
        }
        return writer;
    }
    
    public OutputStream getOutputStream() throws IOException {
        sendHeaders();
        return output;
    }
    
    private void sendHeaders() throws IOException {
        if (headersSent) return;
        headersSent = true;
        
        StringBuilder sb = new StringBuilder();
        sb.append("HTTP/1.1 ").append(status).append(" ").append(statusText).append("\r\n");
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            sb.append(entry.getKey()).append(": ").append(entry.getValue()).append("\r\n");
        }
        sb.append("\r\n");
        output.write(sb.toString().getBytes("ISO-8859-1"));
    }
}

定义处理契约 (SimpleServlet.java)

为了支持灵活的动态处理,我们定义了极简的 SimpleServlet接口。它只有一个 service方法,接受请求和响应对象。这模仿了标准 Servlet 的 service方法,是设计模式中策略模式​ 的体现。我们可以为不同路径(如 /hello, /time)注册不同的实现类,服务器引擎无需关心具体逻辑,只需调用其 service方法即可

import java.io.IOException;

/**
 * 极简Servlet接口
 */
@FunctionalInterface
public interface SimpleServlet {
    void service(SimpleRequest request, SimpleResponse response) throws IOException;
}

实现业务逻辑 (HelloServlet.java)

HelloServlet是我们契约的一个具体实现。实现的步骤是:

  1. 从 SimpleRequest对象中获取用户参数(req.getParameter("name"))。
  2. 通过 SimpleResponse对象设置内容类型。
  3. 通过 res.getWriter()获得输出流,生成动态的 HTML 内容。

这个 Servlet 就像一个简单的控制器(Controller),它处理业务(组合问候语和当前时间),并渲染视图(生成 HTML 页面)。

import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 示例Servlet
 */
public class HelloServlet implements SimpleServlet {
    @Override
    public void service(SimpleRequest req, SimpleResponse res) throws IOException {
        String name = req.getParameter("name");
        if (name == null || name.trim().isEmpty()) {
            name = "朋友";
        }
        
        res.setContentType("text/html; charset=utf-8");
        PrintWriter writer = res.getWriter();
        
        writer.println("<!DOCTYPE html>");
        writer.println("<html><head><title>问候页面</title>");
        writer.println("<style>");
        writer.println("body { font-family: Arial, sans-serif; text-align: center; margin: 100px; background: linear-gradient(45deg, #f093fb 0%, #f5576c 100%); color: white; }");
        writer.println(".greeting { font-size: 3em; margin: 20px; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); }");
        writer.println(".time { font-size: 1.2em; opacity: 0.9; }");
        writer.println("input, button { padding: 10px; font-size: 16px; margin: 10px; border: none; border-radius: 5px; }");
        writer.println("</style></head><body>");
        writer.println("<div class='greeting'>👋 你好, " + name + "!</div>");
        writer.println("<div class='time'>" + LocalDateTime.now().format(
            DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss")) + "</div>");
        writer.println("<form method='GET'>");
        writer.println("<input type='text' name='name' placeholder='输入你的名字' value='" + name + "'>");
        writer.println("<button type='submit'>重新问候</button>");
        writer.println("</form>");
        writer.println("<p><a href='/' style='color:white;'>🏠 返回首页</a></p>");
        writer.println("</body></html>");
    }
}

总结

我们这个 TinyTomcat 虽然简单,但基本已经有了Tomcat的的核心骨架。真正的 Tomcat 正是在此基础上,在各个维度进行了史诗级的增强:

  • 性能与并发:使用 NIO/AIO 连接器、更精细的线程池、缓存机制。
  • 配置与可扩展性:通过 server.xml, web.xml, 注解等方式进行复杂配置,支持 Valve、Filter 等扩展链。
  • 安全:实现安全管理器、 Realm 域认证。
  • 生命周期与容器:实现完整的 Lifecycle接口,管理 Server、Service、Engine、Host、Context、Wrapper 等层次化容器。
  • 协议支持:支持 HTTP/1.1、HTTP/2,甚至 AJP 协议。
  • 会话管理:实现复杂而强大的 Session 创建、跟踪、持久化机制。
  • 异步处理:支持 Servlet 3.0+ 的异步 I/O 处理。

接下来,我将会继续从源码角度介绍 Tomcat 的核心设计,可以持续关注

作者 | Tina

采访嘉宾 | 沈浪、茹炳晟、吴娟、方汉

编辑 | 蔡芳芳

 

“我不明白,AI 的发展为什么不是让我们能 5 点下班,而是让更多人被裁员,其他人继续工作到 10 点。”

 

“两年前,我们工作的节奏还可以,但 AI 到来之后,这个状态不存在了。节奏一下子被拉快了,因为管理层觉得 AI 可以极大提升效率,以前还能按正常周期推进的事情,现在都默认你应该更快给结果。”

 

“现在我们内部的考核,其实已经慢慢往 AI 那边偏了。最直接的就是代码量,我们有一个排行榜,谁发了多少行代码,一刷就能看到。组里有个别人几乎全靠 AI 在写,代码量和 PR 数量一下子拉得特别高,慢慢大家就都被拿去跟这种人对标。慢慢就有点变味了,一开始是比代码量,后来开始比谁用 AI 用得多,再往后连 Token 都开始被看。这些东西其实没有写进绩效,但你心里都清楚,什么是会被看到的。”

 

从这三个程序员的讲述里,能明显感觉到,行业里的气氛在变,大家都在被迫提速。

 

与此同时,业界也不断传出各种收紧人力的消息,真假交织。国外亚马逊、Meta 在调整岗位结构,国内也不断传出网易等大厂压缩外包、用 AI 接手基础工作的消息,连“裁员一定要快”都成了热梗。

 

AI 的发展,开始和一种残酷的判断绑在了一起:既然有些活已经明显变快,那人是不是可以少一点?于是,越来越多人心里开始冒出一丝不安:当效率被不断量化、不断比较之后,下一个被算掉的,会不会就是自己?

 

提效这阵风,没人能站在风外

 

过去一年,大家讨论 AI,已经从“要不要用(adoption)”转向“到底能不能提速(speed)”,感觉像是“成熟度”的潘多拉魔盒一下子被打开了。毕竟,AI 在软件开发里的角色变化太快了,从最早的代码补全,到对话式生成,再到 agent,甚至多智能体协同,它介入研发流程的深度已经和以前很不一样了。

 

也正因为变化太快,市场上越来越多人开始把这类能力看得近乎神乎其神,甚至开始有意无意地传播一种更浮躁而激进的想法:AI 时代的软件工程已经和过去完全不同了,好像原来那套工程实践都可以被抛开,不需要懂 Kubernetes,不需要理解系统架构,只要会用模型,就够了。Agent 也仿佛成了什么都能包办的“万能外包”。而其中的代表 Claude Code,不知不觉间已经成了部分人的“技术信仰”。

 

对不少企业负责人来说,这确实是一个疯狂又不可思议的时期。

 

尤其是对于那些本来就只有二三十人的小公司,或者现在很流行的 OPC、“一人公司”来说,大模型带来的提效几乎是一眼就能看到的,很多活就是比过去纯靠人手写快得多。也正因为这样,这类公司的负责人最容易被那些炫技产品打动,尤其是 Design to Code 这种从 Figma 直接生成前端代码的演示。

 

这种效率上的提升,同样也吸引了互联网企业。

 

互联网公司最后还是要看数字。比如腾讯就在去年底发过一组数据:九成员工使用编程助手,将编码时间缩短了 40%,整体提升 20%。

 

快手则把生产力提升的北极星指标直接放在了“需求交付周期”上。按照他们向 InfoQ 提供的最新数据,L1 阶段的团队,AI 主要还是代码补全工具,提升通常在 15% 到 25% 之间;而到了 L2、L3 阶段,AI 开始更深地进入交付过程,甚至能自主完成更多任务,人主要做需求定义和质量审核,提效幅度会更大一些。“我们标杆团队,L2/L3 需求占比超过 20% 的,交付周期下降了 58%。”

 

昆仑万维 CEO 方汉也对 InfoQ 提到,公司使用 AI 后,“项目平均交付时间大幅缩短了”。他在接受《中国企业家》采访时也进一步披露了背后的投入和效果:公司已经不再把 AI 支出看作 Token 补贴,而是纳入统一的 IT 采购。按他的说法,公司现在每个月消耗的 Token 大概在 10000 亿到 12000 亿之间,分摊到员工身上,大约是每人每月 700 元。按 2024 年底约 1500 名研发技术人员来算,公司一个月在 Token 上的支出大约是 105 万元,一年最少 1200 万元。

 

方汉认为这笔投入“太值了”。因为每月百万元左右的投入,差不多相当于 20 个员工的成本。更重要的是,实施一个月后,研发速度提升了 50% 以上,尤其是架构师和 Team Leader 这类岗位,提升最明显,几乎能达到 3 到 5 倍。

 

金融行业要求稳、安全、合规,AI 落地没法一蹴而就。

 

神州信息做的是银行核心软件系统。跟互联网公司不一样,金融领域对技术方案的引入持更为审慎的态度:不关心这技术有多“炫酷”,而是能否与现有技术体系实现无缝衔接。具体来说,这涵盖代码质量的可控性、复杂任务的拆解能力、功能需求的完整覆盖、需求定位的精准程度,以及与既有系统架构、开发规范和工程流程的适配程度。简言之,评判标准不仅是“能否生成代码”,更是“能否在现有系统内生成符合工程质量要求的代码”。

 

所以 2025 年之前,神州信息试过用 AI 做文档补全、代码-文档一致性治理这些事,但那时模型能力和工具都跟不上,试下来效果不怎么样,内部结论是“还不能用在生产上”。

 

到 2025 年前后,情况变了。大模型强了,配套工具也更完善了,神州信息又重新开始系统性地验证 AI 能力,逐步确认了 AI 技术已初步具备进入银行软件这类高可靠性要求场景的条件。

 

那金融行业到底有没有提效?具体到一些单点环节,提效已经很明显了。以测试用例编写为例:此前单个功能模块的测试用例编写工作通常需要 5 人团队耗时一个月完成;引入 AI 辅助后,该流程已转变为 1 人审核 AI 生成结果的轻量化模式,且 AI 在异常场景覆盖方面往往表现出更优的全面性。在文档维护场景中,以往需要投入 10 人月方能完成的文档补全工作,如今借助 AI 从代码逆向生成设计文档的方式,可在 3 至 5 人月内完成,效率提升幅度达 50%以上。

 

AI 时代的“效率悖论”:明明让人变快了,但提效却断在中间

 

这轮“提效”风里,AI 真把人变快了,对此现在已经没人怀疑了。但一线开发者感受到的却是另一回事。

 

有开发者对 InfoQ 形容,AI 出现之前,开发这件事其实是有节奏的。写代码、调试、验证,一步一步往前走。可到了 2025 年中,随着 AI 编程工具大规模普及,周围几乎已经没人再老老实实一行行手写代码了。AI 写代码当然更快,但人并没有因此轻松下来,反而比以前更忙了。因为“老板也懂了 AI 能提效”,预期被迅速抬高,很多原本按正常周期推进的事情,一下子都被要求更快交付结果。

 

问题不在“快”,而在快的那一段,只发生在局部。需求还要对齐,测试还要走,联调、上线、问题处理,一样都没少,甚至因为 AI 的引入,多了一层新的复杂性。于是就出现一种很别扭的状态:编码提速了,但整体节奏没跟上,被压掉的时间,最后还是得靠人自己补上。

 

从企业披露的数据里也能看到这种“错位”:编码这一段确实更快了,但整体提效大多仍然停留在 15%~25%。

 

腾讯研究院特约研究员茹炳晟,对这种落差并不意外。在他看来,很多人都把“编码提速”看得太重了。

 

在企业级研发里,真正写代码的时间,通常只占 20%~30%。剩下的大头,都在沟通、对齐、评审、测试和各种临时事务上。AI 提升的,主要是这 20%~30% 的环节,自然很难直接拉动全局。“局部的提升,我认为很容易做到。”茹炳晟说,“难的是把效率真正拉通到端到端的全流程。这对推动改进的人要求很高:你要看得清瓶颈在哪,敢不敢动流程,也要有能力做取舍。”

 

按他的判断,至少在大型软件系统里,目前还没有看到特别显著的整体提升,尤其是那些大型、复杂、历史包袱重、同时质量要求又极高的系统,比如银行核心交易系统、工业软件等。

 

这类系统往往一个产品就有五六百人参与维护,多的甚至达到上千人。在这样的规模下,AI 可以带来局部提速,但还很难撬动整体交付效率。

 

也正是在这种“局部快、整体不动”的结构里,快手研发效能负责人沈浪说,他们花了一年多才摸到一个关键判断:AI 工具、个人提效和组织提效,从来不是一回事,他们自己一开始也踩过这个坑。AI 代码率上去了,看起来很不错,但回头看整体交付周期,改善其实有限。

 

因为大公司里,从个人提效到组织提效之间常常隔着两道鸿沟:第一个是从个人到团队,你个人写代码是快了,但代码评审还得排队,测试环境也得等,这些卡点会一点点把效率吃回去;第二个是从团队到组织,就算团队交付更快了,只要需求、测试、发布这些流程还是瓶颈,整个组织的交付周期照样快不起来。(延伸阅读:“3年、1万人,快手技术团队首次系统披露AI研发范式升级历程”、“生成率从8%到60%:快手智能测试用例生成系统的四阶进化”)

 

更麻烦的是,有些速度其实是“借”来的。茹炳晟提到,现在行业里一个很大的误区,就是太喜欢用交付速度来衡量 AI 的价值。短期看当然会更快,功能先跑通,代码先交上去,效果立刻就能看到。但这种快,往往是把代价往后挪了。

 

AI 生成的代码,未必符合原有的架构风格,也可能把本来不该重复实现的东西又写了一遍。眼前看是提速了,后面却可能留下维护税和技术债。这些账不会当场爆出来,但会一直跟着代码和系统走,到了后续维护、变更、扩展的时候,影响才会越来越明显。

 

什么样的企业,敢把提效直接置换成裁员?

 

这也是为什么,那种小型、轻量的软件开发看起来 AI 提效效果最“炸”。

 

尤其是那种由三五十人以下小团队负责的一个 IT 系统、一个小应用,系统不复杂,协作链条也短,大模型一接进去,很容易就跑出“一个人顶一个小团队”的效果。

 

问题是,这类项目很多活得不久。可能做一年就结束了,维护压力、技术债、架构混乱这些真正的后遗症,还没来得及爆发,项目先没了。老板看到的就只剩下一件事:人可以再少一点,活照样能干完。

 

AI 被拿来当裁员依据,往往就是从这里开始的:没做过大型复杂项目的人,最容易把 AI 神化;把软件工程误读成“写代码”的人,则最容易把小应用里的局部提效,错当成所有团队都该接受的裁员信号。

 

但金融企业不是这样。

 

金融行业系统本身非常复杂,AI 在代码生成环节的起效远没有外界想的那么高。像复杂账务、事务一致性、7×24 小时银行机制支撑这类代码,靠的是人长期积累下来的经验。AI 在简单查询和增删改查上当然快,但一碰到这些复杂场景,提效自然就放缓了——天花板就在那里。

 

除此之外,合规判断、数据安全边界、监管问责时的责任承担,最终还是得由人来扛。知识传递一旦断档,系统稳定性就会受影响。所以银行不会像小企业那样,一看到 AI 快了就急着裁人。所以有金融行业技术负责人认为:把 AI 省出来的人力直接砍掉,那是危险的误判。

 

怎么衡量开发者的生产力

 

AI 的出现,首先放大了组织之间的差异。沈浪打了个比方:AI 像一面透镜,基础扎实的组织,长板被放得更长;本来就有问题的组织,短板也暴露得更彻底。与此同时,AI 也把个人之间的差异拉得更开了。资深工程师对需求理解深、任务拆解能力强、能识别 AI 幻觉,AI 就成了判断力的放大器;初级工程师执行速度快了,但判断失误也跟着快了。这放大了不同层级工程师之间的差距。

 

这种差异一旦被看见,人就忍不住要比。程序员之间开始暗暗较劲,你用了多少 token,我写了多少行代码。有些是隐形的,同事间嘴上不说心里有数;有些干脆摆到明面上,成了榜单。比如 Meta 内部,有人搭了个叫 Claudeonomics 的排行榜,8.5 万名员工比谁烧的 token 多,前三名能拿徽章、头衔,甚至有人专门让 AI Agent 跑几小时任务就为了刷数据。

 

还有那个更古老的指标——代码行数,虽然老掉牙,但从来没人真的忘了它。当 AI 把“写代码”这件事变得廉价之后,衡量一个开发者的生产力到底该看什么,成了一个更棘手的问题。

 

“同时推进 5 个项目,现在平均一天能产出 3.7 万行代码......我最近一直在试着让软件工程师接受一件事:你们一直奉为圭臬的那句‘代码行数没意义’,到了 agentic engineering 时代,可能没那么对了。再过 5 年,你们大概不会相信自己当年真这么想过。”

 

这其实是一个老问题。

 

几十年来,怎么衡量开发者的生产力,在软件行业里争议不断。十年前,Martin Fowler 甚至认为,开发者的生产力是无法真正被衡量的。

 

后来《Accelerate》问世,把软件交付拆成了几百个可测量的指标——部署频率、变更前置时间、平均恢复时间等等,行业总算有了一套相对成体系的参照系。

 

沈浪观察到,这套框架其实一直在变。十年里,从 DORA 到 GSM 到 SPACE 到 DevEx 到 DX Core 4,表面上是度量方法在进步,背后则是“开发者是什么”这个定义在变。DORA 时代,开发者是生产线上的工人,看产出速度;SPACE 时代,开发者是有情感、需协作的多维个体;到了 AI 时代,开发者变成了与 AI 协同的决策者。

 

如今 AI 来了之后,情况也变得更复杂了。写代码这件事也变得前所未有地快,组织自然想用新的尺子去量“AI 时代的生产力”。问题在于,这套尺子很快就走偏了——最典型的例子,就是代码行数这个早该被淘汰的指标,堂而皇之地杀了回来。

 

代码行数之所以重新流行,原因很简单:它最容易测量,结果也最显眼。你不需要复杂的遥测系统,也不需要成熟的指标框架,只要统计一下就行。然而,低投入的改动可能写出很多行代码,高投入的改动却可能只有寥寥几行——这个指标天然就不稳定。到了 AI 时代,问题只会更严重。同样一个程序,AI 生成的代码,本就倾向于写得更“膨胀”,行数更大。

 

但现实就是这么离谱,代码行数这个噪音极大的指标,正和 Meta 的 token 排行榜一样,成为衡量“谁更努力”的显性标尺。那么如果不看代码行数,不看 token 消耗量,那到底该看什么?

 

旧尺子量新世界:尺子没变,刻度变了

 

讽刺的是,DORA 和 SPACE 这类传统框架并没有被冲垮,反而在 AI 时代站得更稳了。

 

茹炳晟认为,软件研发的本质问题没有变。人月神话里那些关于复杂度、一致性、协作、沟通的属性,并没有因为大语言模型的出现而发生任何的改变,所以度量体系的底层逻辑也就不该变。

 

不过,他也指出,DORA 和 SPACE 的核心虽然有效,但标杆需要重新校正。其中,DORA 的四个指标——部署频率、变更前置时间、变更失败率、平均恢复时间——依然是稳定的核心选项。但基准变了。以前追求每日部署,现在 AI 让每小时部署都成为可能,原来的绝对值失去了意义。更合理的做法是:同一个团队,对比引入 AI 前后的变化——能不能在不牺牲稳定性和质量的前提下,把业务价值交付的节奏提上去。

 

SPACE 框架的维度——满意度、绩效、活动、沟通协作、效率——同样重要,但内涵发生了根本变化。以前衡量人,现在衡量人与 AI 的协同。满意度不再只看开发者对工具满不满意,更要看他是否信任 AI 的输出、是否对代码有掌控感;效率不再是“代码写得快不快”,而是认知负担有没有减轻;沟通协作从人与人的交互,扩展到人跟 AI 的交互、甚至 Agent 与 Agent 的交互。因此,可以引入一些新指标:比如完成一个任务需要与 AI 交互多少次,需求清晰与不清晰时分别调用 AI 多少次,生成内容被采纳与被驳回的比例。

 

代码行数不是完全没用,它可以作为过程指标,比如观察开发者的活跃度或 AI 使用频次。真正该看的,是 AI 代码采纳率、单位 token 产出,以及认知负担——高职级工程师原本并行 1.7 个项目,AI 帮忙后能升到 2.5 甚至 2.8。

 

快手也遵循了同样的逻辑。沈浪说,他们没有抛弃 DORA,而是在它之上加了一层 AI 维度:保留交付周期和变更失败率作为质量锚点,把人均产出从“代码行”换成“交付需求数”,新增 AI 代码率(逐行比对)、L2/L3 需求占比、研发 NPS。并且摒弃了最容易被刷也更危险的的 PR 数量和提交频率。

 

具体到代码行,正确的用法是衡量 AI 工具覆盖深度——AI 生成代码行占总代码行的比例。但用它衡量个人生产力就是错误用法。快手改用“人均有效代码行”:只算进入生产环境、通过质量门控的净增有效代码。这个数字从 134 行提升到 213 行每人天,涨幅 59%。

 

怎么给 Agent 算时薪,怎么给人算成本

 

前文提到的 Meta 排行榜,排名第一的人一个月烧掉 2810 亿 token,折合数百万美元。公司 30 天总消耗甚至突破了 60 万亿 token。另一个例子,Sigrid Jin,25 岁,去年 Anthropic 的榜一大哥,一年在 Claude Code 上烧掉 250 亿 token,约 17.5 万美元。

 

很多企业都是不设限的鼓励大家使用。方汉的原话是:“token 数大多数情况比人力便宜,如果考虑开发速度的提升,就更加正向了,限制开发者合理支出没有任何意义。”

 

方汉的观点代表了很多互联网公司的做法。而在对信息安全有严格要求的金融行业,神州信息则展现了另一种逻辑。

 

神州信息软件工艺创新部负责人提到,出于信息安全和监管合规要求,金融行业在应用 AI 时,普遍更倾向于私有化部署,而不是直接依赖公有云。通常的做法是自建 GPU 算力集群,并将大模型部署在本地,以支撑实际业务需求。在这样的前提下,GPU 算力虽然是 AI 应用中的一项主要成本,但放到企业整体技术投入中看,该项支出占比相对有限,"属于可接受的范围"。

 

也正因为如此,神州信息一直支持内部开发者使用 AI 工具。相比单纯控制资源消耗,他们更看重把 AI 真正用起来。神州信息软件工艺创新部负责人表示:“我们鼓励开发者积极探索 AI 能力的边界,用好了就是最有力的证明。”

 

但不管怎么用,token 烧掉的都是真金白银。大厂工程师薪酬很高,但他消耗的 token 成本,占薪酬的比例可能非常低。你甚至会觉得,跟他靠这些 token 多做出来的事情相比,这点钱几乎可以忽略。所以大厂可以“不计代价”。小公司则完全不一样。 员工薪酬绝对值没那么高,如果某个人的 token 消耗可能都快赶上他一半工资了,那么对公司来说,token 成本是真实刺痛的成本,不能忽略。

 

更根本的变化在于:过去算“人工小时”,现在算“token 成本”。今年 3 月阿里蔡崇信还表示,智能体本质上就是虚拟白领,是一种知识型员工。既是员工,就该算时薪——过去给人算时薪,现在也该给 Agent 算一算:它到底是不是一支高效、回报率高的劳动力?

 

沈浪提醒,Agent 模式不能跟 L1、L2 混用同一套指标。

 

L1 辅助形式,如 IDE 代码补全,效率单位是“人的产出”,消耗低、转化率高,基本上直接变成代码。L2 协同模式,如代码审查辅助和单测生成,中等消耗,转化率也不错,效率单位变成“团队的交付”。L3 自主模式,Agentic 任务执行消耗最高,但产出价值也最高,只是失败率也相应更高。随意问答探索价值最低,很难量化。

 

一个开发者几分钟内就可能消耗数千美元,在 Agentic 模式下尤其常见。企业如果没有预算管理机制,很容易出现“效率提升了,但成本也失控了”的局面。

 

另一方面,当生产力的最小单位从“人”变成了“人 + Agent 组合”,单评估“人”肯定不够,所以,目前快手探索的框架是把输入侧和输出侧分开来看。输入侧,人贡献的是需求定义、架构判断、质量审核的时间,Agent 消耗的是 Token、执行时间、工具调用次数。输出侧,看的是交付的需求数量、需求质量(一次通过率、线上 Bug 率)和交付周期。综合 ROI 就是输出价值除以人力成本加 Agent 成本。

 

另外在场景上,标准化、可验证的活——CRUD 代码、单测生成、写文档——ROI 高。模糊、要人拍脑袋的活——复杂业务逻辑、架构决策、安全审查——用 AI 可能省下来的时间还不够验证错没错,ROI 低。

 

最终价值是把 token 消耗和工程产出绑在一起。用掉多少 token,除以省下来的工程师工时,得到一个“token 效率比”。再折算成成本对比,看 ROI 是否为正。同时按场景和级别设预算,超了告警——不截断,但得让人心里有数。

 

写在最后

今年 2 月,谷歌将 AI 使用情况正式通过 GRAD 系统与员工绩效挂钩。同月,亚马逊被曝用内部系统 Clarity 追踪员工 AI 调用次数——AI 用得够不够,直接决定你能不能晋升。微软更早一步,将 AI 工具使用纳入全员绩效考核。国外三大厂殊途同归:AI 不再是可选项,而是考核的一部分。

 

国内也不遑多让。昆仑万维从普通开发到技术线 CTO,无一豁免,AI 编程能力直接纳入绩效考核,开发效率要提升至少 50%,并与末位淘汰绑定。

 

但我们也该明白,提效有天花板。复杂软件的地位,不会被动摇。那些动辄几百人维护的大型系统,靠的不是 Token 堆砌,是经验沉淀、是背责制度、是对稳定性的敬畏。

 

AI 省出来的人效,目的是承接更多项目、覆盖更多场景,而不是把做事的人变少。

 

未来,当 Token 计价器不断滚动、上下文成本不断雪球化,人类这种“看起来更慢”的大脑,会不会反而变成一种高端奢侈品?一个工程师可以花 5 个小时认真看复杂架构、深入思考问题,而不会像 AI 那样不断累积惊人的计算费用。在企业预算里,这种“慢速的人脑”,反而可能成为终极的固定成本资产。人的价值,恰恰藏在那些算不出 Token 的地方。

⚠️回帖抽一箱黄盖汾酒 [6 瓶装]

⚠️开户送五常大米,推荐朋友有红包

⚠️大笑脸低佣开户推荐:
银河证券:ETF 万 0.5 免 5 [ETF,LOF ,etf 费率低,适合 etf ,打新,纳指,宽基玩家。新手必备]
广发证券:ETF 万 0.5 免 5 [ETF,LOF ,etf 费率低,适合 etf ,打新,纳指,宽基玩家。新手必备]
东北证券: 万 0.741 免 5 [国企券商,股票 etf 费率都很低]
国泰海通: 万 0.8 免 5 [头部龙头券商,费率最优惠,大客户专享,综合费率最低]

⚠️大笑脸联系方式和最新具体券商表格清单,随时更新 www.daxiaolian.com

18 年买的混动车,电池只有 7 度,目前里程 11 万公里,新车充满电,表显 60 公里,现在只有 48 公里,正好打八折。

一万度电大概能跑 6 万公里,电费 3500 元,用油大概 5 毛一公里,节省 26500 元,平均一年节省 4800 元。

目前没啥大问题,本来想换新车的,现在还是先开到报废吧,我估摸着这电池撑不了太久了。

新注册小程序,填了邮箱,主体(企业资质)信息,管理员信息,管理员微信扫码后,提交就报 [涉嫌违规] 。页面可以提交申诉,因为不知道为啥违规,申诉原因也不知道要填什么,提交后 3 工作日就返回申诉失败。

找到腾讯工作的好友内部咨询微信客服,给到的答复是:自查

我于是找公司财务查,确认公司工商信息,续存状态,财税,法人征信,都是正常,企查查返会结果也是 0 风险。

把这个信息委托好友回复给内部微信客服,给到的答复还是:自查

于是想到是不是公司服务号在去年 7 月曾收到一次 [涉嫌诱导用户点击广告] 的违规记录,这也是仅有的一条违规记录。是不是这个违规记录引起的呢?如果是,我应该如何做?把这个疑问再次委托好友回复给内部微信客服,给到的答复依然是:自查

没辙了。
请教各位 V 友,有 V 友遇到申请小程序直接被告知 [涉嫌违规] 的吗?有解决的经验恳请分享一下。

谢谢

做数字化相关工作,最容易遇到的一种情况就是,大家都在聊架构,但说的根本不是一回事。

老板聊的是业务怎么跑得更顺,产品在说功能怎么设计,技术在讨论系统怎么搭,数据团队关心的是数据怎么流、怎么管、怎么用。结果同样都叫架构,开会时听着像在同频,落到执行层面却经常对不上。

所以这篇文章,我想把几类最常见、也最容易混的架构放在一起讲清楚, 尤其是很多团队经常提到、但又容易讲得很虚的数据架构。

一、业务架构

业务架构说白了,解决的是企业到底在做什么,核心流程怎么跑,关键角色怎么协同。

它关注的不是代码,也不是数据库,而是业务本身的组织方式。 比如客户从线索到成交,中间经过哪些环节,哪些部门参与,哪些动作是关键节点,哪些指标最值得盯。

业务架构通常会落到这些内容上:

  • 核心业务域怎么划分
  • 端到端流程怎么设计
  • 部门和角色如何协同
  • 哪些环节是关键控制点
  • 业务目标靠什么指标衡量

业务架构清不清楚,决定了后面产品、系统、数据会不会越做越乱。因为如果连业务主链路都没理顺,后面不管系统搭得多复杂,最后都容易变成局部优化。

二、产品架构

如果说业务架构是在讲做什么,那产品架构就是在讲要做成什么样。

它更偏产品视角,核心任务是把业务需求沉淀成可以被用户使用的功能能力。 比如一个销售管理产品,客户管理、商机管理、合同管理、回款管理这些模块怎么分,哪些能力是基础能力,哪些是扩展能力,页面与功能之间怎么组织,这些都属于产品架构的范畴。

产品架构更强调两个问题:能力边界清不清楚?模块组合合不合理?

这一步做得好,后续研发、测试、实施都会更顺。做不好,就很容易出现功能堆砌、模块打架、后期难维护的问题。

三、应用架构

产品里规划好的能力,最终还得有系统来承接,这就是应用架构在解决的事情。

应用架构关注的是企业里有哪些应用系统,这些系统分别干什么,彼此之间怎么配合。 比如 CRM 管客户,ERP 管供应链,OA 管审批,BI 做分析,营销系统做投放自动化。系统之间不是简单并列,而是有明确的职责边界和协作关系。

应用架构看起来离业务远一点,实际上它直接影响日常工作的顺畅程度。系统职责划分不清,常见后果就是重复建设、数据割裂、流程绕路。

四、技术架构

再往下一层,就是技术架构。

技术架构解决的是系统底层如何实现,包括服务怎么拆、接口怎么设计、中间件怎么选、数据库怎么部署、系统怎么保证稳定性和扩展性。 它更偏工程实现,是研发团队最熟悉的一层。

技术架构一般会涉及这些问题:

  • 单体还是微服务
  • 实时还是离线处理
  • 数据库如何分层分库
  • 缓存、消息队列、调度怎么配
  • 安全、容灾、监控怎么做

很多人会把技术架构和数据架构混在一起,其实两者重点不同。技术架构更关心系统怎么建,数据架构更关心数据怎么跑。一个偏底座,一个偏血液循环。

五、数据架构

如果说前面几类架构更多是在回答职责和分工,那数据架构回答的就是数据这条线到底怎么跑通。

为什么数据架构重要。因为企业现在的问题通常不是没数据,而是数据很多,却分散、混乱、不一致。业务系统里有一份,报表里有一份,数据仓库里又有一份,最后同一个指标开会时能报出三个版本。这种情况,本质上就不是报表问题,而是数据架构没搭好。

一个相对完整的数据架构,包含下面几个环节。

1.数据来源

先看数据源。企业里的数据一般来自业务系统、日志系统、第三方平台、Excel 文件、API 接口,来源越多,后面整合的难度越高。数据架构第一步,就是把数据入口梳理清楚,知道数据来自哪里,更新频率是什么,质量怎么样。

2.数据流转

有了数据源之后,核心问题就是流转链路。数据要不要同步,多久同步一次,是批量抽取还是实时采集,要不要做清洗转换,怎么进入ODS、DW、ADS这些层。很多企业的数据问题,其实就出在这一步,链路不清晰,口径自然也很难统一。

3.数据储存

数据进来之后,不是随便找个库放进去就算完事。要不要分层,怎么建主题域,明细层、汇总层、应用层怎么划分,历史数据保留多久,冷热数据怎么处理,这些都属于数据架构里非常实际的问题。

数据存储结构设计得好,后面的分析效率会高很多。设计得差,后面每做一次需求都像临时救火。

4.数据管理

真正成熟的数据架构,不会只停留在采集和存储,还会把治理一起纳进来。比如主数据怎么统一,指标口径怎么管理,数据质量怎么监控,权限怎么分配,元数据怎么维护。这部分往往不显山不露水,但缺了它,数据平台越大,后面越容易乱。

5.数据应用

最后才是应用层。报表、看板、经营分析、用户画像、风控模型、推荐算法,本质上都是数据消费方式。数据架构不是为了把数据堆起来,而是为了让数据能被真正使用,支持业务判断和决策。

所以你会发现,数据架构不是单纯画一张图,而是把数据的来源、链路、存储、治理、应用整套机制串起来。它既连接业务,也连接技术,是数字化建设里非常关键的一层。

六、项目架构

前面讲的业务架构、产品架构、应用架构、技术架构和数据架构,更多是在解决应该怎么设计的问题,而项目架构解决的,是这件事到底怎么一步一步落地。

说得直白一点,项目架构管的不是某一个系统,也不是某一块数据,而是整个项目怎么拆、怎么排、怎么协同、怎么推进。比如先做什么,后做什么,哪些事情可以并行,哪些必须等前一步完成,哪些角色要参与,哪些节点要验收,这些都属于项目架构要考虑的内容。

它通常会关注这几个点:项目范围的界定、阶段计划的安排、人员分工的划分、里程碑的设定、风险和依赖的管理。

很多项目不是技术不行,也不是方案不对,而是推进过程中节奏乱了,前后顺序没捋清,最后导致交付拖延、沟通反复、问题堆积。项目架构的意义,就是把一件复杂的事拆成能执行、能协作、能交付的路径,让大家知道现在在哪一步,下一步该干什么。

七、总结

想要区分这些架构,其实核心是需要分清它们各自解决的问题:业务架构负责的是业务怎么跑,产品架构负责能力怎么设计,应用架构负责系统怎么分工,技术架构负责底层怎么实现,数据架构负责数据怎么流通,项目架构负责事情怎么一步步落地。

我建议大家平时做数字化工作的时候,先把最贴近自己业务的那部分吃透,再搭着数据架构一起理解。因为真正到了项目里,很多问题并不是某一类架构单独出了问题,而是几层之间没有衔接好。等你把这些关系理顺了,再去看系统建设、数据治理、数仓规划和项目实施,思路会清楚很多,很多原本绕来绕去的地方,也会慢慢变得顺手。

新闻稿(英文) https://www.apple.com/newsroom/2026/04/tim-cook-to-become-apple-executive-chairman-john-ternus-to-become-apple-ceo/

来自 Tim 的一封信

致 Apple 的社区:
过去 15 年来,我几乎每个早晨都以同样的方式开启这一天。我会打开邮箱,阅读前一天收到的来自全球 Apple 用户的来信。

你们与我分享生活中的点滴,告诉我 Apple 如何走进了你们的生活 ——比如某位用户的母亲被 Apple Watch 救下的那一刻,或是在难以攀登的山巅上拍下的那张完美的自拍照。你们感谢 Mac 如何改变了工作中的可能性,有时也会对我提出建议,因为某个你们珍视的功能没有如预期般正常工作。

在每一封这样的邮件中,我都能感受到我们共同人性中那颗跳动的心。我感到一种日益加深的责任感,驱使我们更加努力、走得更远。但最重要的是,我感受到一种无法用言语表达的感激——感激我竟然能成为在邮件的另一端,作为一家以超越言语能描述的方式来激发想象、让大家的生活更丰富的公司的领导者。这是何等的殊荣与幸运。

今天,我们宣布我将迈出在 Apple 旅程中的下一步。在接下来的几个月里,我将过渡到一个新的角色,于九月份卸任 CEO 一职,成为 Apple 的 Executive Chairman 。将有一位新人接任我心中世界上最好的工作。这位领导者就是 John Ternus —— 一位杰出的工程师和思想家。他在过去 25 年里,致力于打造我们的用户深爱的 Apple 产品,注重每一个细节,专注于每一个让产品变得更美妙、更大胆、更美丽、更有意义的可能。他是这个职位的最佳人选。

John 深谙 Apple 的初心与使命,珍视我们所坚守的价值,更牵挂每一位用户。他拥有非凡的正直来领导公司的品格和心性。我无比自豪地称他为 Apple 的下一任 CEO 。在他的领导下,这家公司将达到令人难以置信的新高度,而在未来产品与服务所带来的每一次喜悦和发现中,你们都会感受到他的影响。我迫不及待地希望你们像我一样了解他。

这不是告别。但在这个过渡的时刻,我想借此机会说一声谢谢。这一次,不是代表公司——尽管公司内部对你们的感激之情如泉涌般满溢——而仅仅是代表我自己,Tim 。一个来自不同时代、乡村之地长大的人,在这些神奇的时刻,成为了这家世界上最伟大公司的 CEO 。感谢你们给予我的信任和善意。感谢你们在街头和我们的店里向我打招呼。感谢你们在我们发布新产品或服务时与我一同欢呼。最要感谢的是,你们相信我能领导这家始终把你们放在工作中心的公司。每一天,我们起床后都在思考,能做些什么让你们的生活变得更好一点。而每一天,你们都让我的生活成为了我所能期望的最好模样。

谢谢你们。



📰 今日新闻精选:

  • 2025 年我国人均阅读纸质书 4.81 本,较 2024 年增加 0.02 本;人均每天接触手机超 109 分钟,比 2024 年增加 0.78 分钟
  • 湖南试点学生运动能力达标:对应年级学生须达相应运动等级
  • 一季度全社会用电量同比增长 5.2%,专家称:第二产业成用电量增长主要拉动力
  • 餐饮业指数连续下行,中国烹饪协会:平台大额补贴正在破坏行业生态
  • 机构预测国内油价 21 日 24 时或迎年内首降,加满一箱 92 号汽油预计将少花约 20 元
  • 近 70 款车集体降价,覆盖新能源与燃油车,平均降价金额达 3.7 万元,最高降幅直逼 17 万
  • 中国脑机接口迈向临床应用:“北脑一号” 已完成 10 例人体植入,安全工作时长超过 45000 小时
  • 爱奇艺宣布超 100 位艺人同意入驻 AI 艺人库,CEO 称将提高演员拍摄效率,张若昀等多名艺人均否认签约 AI 授权
  • 运 - 20B 首次海外任务,赴韩国接迎第十三批志愿军烈士遗骸回国
  • 五一假期赴日航班量接近腰斩,每天取消超 40 班;往返韩国计划航班量位列第一,同比增长 11.1%
  • 日本国会周围 3.6 万人集会抗议高市修宪企图,中方表态:敦促日方汲取历史教训
  • 日媒:日本东部附近海域地震调整至 7.7 级,海啸预警已解除,日气象厅提醒:未来一周有同等规模地震风险
  • 美媒:最新民调显示特朗普支持率已跌至新低,63% 表示不认可,其中 50% 表示强烈不认可
  • 美方扣押一艘中国驶来伊朗货船,伊朗誓言将报复,中方表示:对美方强制截停有关船只表示关切
  • 美媒:伊朗已决定继续与美国进行谈判;万斯及美国代表团将抵达巴基斯坦;特朗普称如未能达成协议 “几无可能” 再延长停火

📅 今日信息:

  • 公历:2026-04-21 星期二 金牛座
  • 农历:二〇二六年三月初五
  • 下一节气:2026-05-05,立夏
  • 今年进度:30.41%(已过 111 天,剩余 253 天)

🌟 历史上的今天

  • 1998 年:迪士尼动画电影《花木兰》在美国首映,改编自中国民间故事,展现了勇气与自我认同的主题。
  • 1960 年:巴西首都从里约热内卢迁至巴西利亚,这座现代主义城市由建筑师奥斯卡·尼迈耶设计,成为城市规划的典范。

语-一个工具箱

软著已经在申请了,现在在内测完善功能,主要就是一些自己平时用的小工具。

  • 小冰箱:管理冰箱内的食物,支持自定义分类(当然可以用于记录其他物品),查看过期时间,记录数量等等;
  • 记书摘:一个普通的书籍书摘记录程序,特色是从一个 iosAPP 抄来的时间线布局;
  • 票夹子:一个用于在 12306 停止提供报销凭证后,用于收藏火车票的工具。

软件支持安卓 14 以上,如果哪位大佬有谷歌 play 账号,欢迎参与(留下你的邮箱,或者发邮件申请 [email protected] )内测计划,这对我很重要。

有没有《关于约会的一切》《完美陌生人》这一类的电影推荐,这两部是同一个制作班底,很喜欢这种在很小的场景范围拍出深度的爱情电影,小巧精致。

当时可以听到一点水被打到的声音,感觉应该是风扇和水有接触了,但是没有自己断电,我就长按电源键关机了。后面观察了一下左边转轴有点水雾,应该是风扇吹上去的,麻了。

关机吹了一会儿,从键盘里面吹出来一点水,每次吹出来一点我就擦掉,一擦就按到键盘就开机,我真的是服了。

但是现在开机了一点事都没有,键盘测试了也是每个键都可以用,还需要担心吗?😭

😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭

因为个人用的是 Java 的自研 agent ,官方又没提供 java 相关的 sdk 。因此顺手根据官方 npm 包和文档封装了一下,欢迎使用。
二合一的 SDK:

  1. 基于 WebSocket 长连接协议的企业微信 AI Bot Java SDK
  2. 基于二维码登录、长轮询、CDN 协议封装的微信 ClawBOT Java SDK

具体见:
https://github.com/CloudSen/wx-aibot-java-sdk

https://gitee.com/CloudSen/wx-aibot-java-sdk

做了套边缘计算数据采集方案,想和你聊聊后续方向, 请指教一下

https://github.com/anviod/edgex

在工厂和工业现场待久了,总能遇到一些让人头疼的事:车间里设备种类多,协议又杂,数据采集常常不稳定,要么延迟高,要么经常断。我做边缘计算的,每天跟着现场工程师跑,看他们调设备、查故障,慢慢就想:能不能做套更靠谱的采集方案?

于是我们花了一些时间,搞出了这套南向采集优化方案。它没什么花里胡哨的概念,就是想解决实际问题:

  • 不管是 Modbus 、BACnet 还是 OPC UA 、S7 ,一套系统就能管起来,不用再为不同设备单独配方案。
  • 设备状态好的时候多采点数据,网络不稳定时就少发点请求,让系统自己适应现场情况。
  • 哪个点位老出问题,系统会自动放缓采集频率,等它恢复了再正常采,省得一直发无效请求占资源。
  • 同一总线上的设备一起不间断轮询采集,减少来回通信的等待次数,效率更高。
  • 数据在边缘侧先处理一下,不用全往云端发,响应更快,流量也省。

没搞什么复杂的技术名词,就是把现场遇到的问题一个个解决:网络抖动了,就根据响应时间自动调超时;传大数据慢了,就自动找最合适的传输单元;设备坏了要换,新设备接上配置相同的 IP 就能自动同步配置,不用人手动搞。

现在这套方案已经在几个工厂试过了,工程师反馈说延迟降了,稳定性高了,维护起来也省心。做这个的初衷,就是想让搞工业物联网的朋友们少点麻烦,多点踏实。

如果你也在为设备数据采集发愁,欢迎聊聊,说不定能帮上忙。也想听听你的场景,一起把这套方案做得更实用。

说出来真的很糟心,今天儿子两周岁,我和老婆上午带儿子出去户外游乐场玩,中午外面吃自助餐,下午比较热就在家里,请儿子吃糖水,晚上吃蛋糕,反正让儿子过了个开心的生日


但是等了一天,儿子的爷爷奶奶和姑姑,一点表示都没有,连条信息都没有,说实话真得有点寒心,儿子姑姑就不说了,但是连爷爷奶奶也这样,其实并不是想要他们什么,发个 200 红包对于我可有可无,而且我每个月还给二老打 2000 生活费,但是这样做真的让人寒心

所以以后儿子跟他们不亲,那真的是自找的,自己唯一的孙子都不关心,疼爱止于表面话上,没有一点实际行动,不亲近也是正常的