范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

使用Nginx构建前端日志统计服务(打点采集)服务

  工作中经常会遇到需要"数据支撑"决策的时候,那么可曾想过这些数据从何而来呢?如果业务涉及 Web 服务,那么这些数据的来源之一便是服务器上各种服务器的请求数据,如果我们将专门用于统计的数据进行服务器区分,有一些服务器专注于接收"统计类型"的请求,那么产生的这些日志便是"打点日志"。
  本文将介绍如何在容器中使用 Nginx 简单搭建一个支持前端使用的统计(打点采集)服务,避免引入过多的技术栈,徒增维护成本。  写在前面
  不知你是否想过一个问题,当一个页面中的打点事件比较多的时候,页面打开的瞬间将同时发起无数请求,此刻非宽带环境下用户体验将不复存在,打点服务器也将面临来自友军的业务 DDoS 行为。
  所以这几年中,不断有公司将数据统计方案由 GET 切换为 POST 方案,结合自研定制的 SDK,对客户端的数据统计进行进行"打包合并",并进行有一定频率的增量日志上报,极大的解决了前端性能问题、以及降低了服务器的压力。
  五年前,我曾分享过如何构建易于扩展的前端统计脚本,感兴趣可以进行关联阅读。  POST 请求在 Nginx 环境下的问题
  看到这个小节的标题,你或许会感到迷惑,日常对 Nginx 进行 POST 交互司空见惯,会有什么问题呢?
  我们不妨做一个小实验,使用容器启动一个 Nginx 服务:  docker run --rm -it -p 3000:80 nginx:1.19.3-alpine
  然后使用   curl   模拟日常业务中的 POST 请求: curl -d "{"key1":"value1", "key2":"value2"}" -X POST http://localhost:3000
  你将看到下面的返回结果:   405 Not Allowed  

405 Not Allowed


nginx/1.19.3
  按图索骥,查看 Nginx 模块 modules/ngx_http_stub_status_module.c 和 http/ngx_http_special_response.c 的源码可以看到下面的实现:static ngx_int_t ngx_http_stub_status_handler(ngx_http_request_t *r) { size_t size; ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; ngx_atomic_int_t ap, hn, ac, rq, rd, wr, wa; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } ... } ... static char ngx_http_error_405_page[] = "" CRLF "405 Not Allowed" CRLF "" CRLF "

405 Not Allowed

" CRLF ; #define NGX_HTTP_OFF_4XX (NGX_HTTP_LAST_3XX - 301 + NGX_HTTP_OFF_3XX) ... ngx_string(ngx_http_error_405_page), ngx_string(ngx_http_error_406_page), ...   没错,默认情况下,NGINX 并不支持记录 POST 请求,会根据 RFC7231 展示错误码405。所以一般情况下,我们会借助 Lua /Java / PHP / Go / Node 等动态语言进行辅助解析。   那么如何来解决这个问题呢?能否单纯的使用性能好、又轻量的 Nginx 来完成对 POST 请求的支持,而不借助外力吗? 让 Nginx "原生"支持 POST 请求   为了更清晰的展示配置,我们接下来使用 compose 来启动 Nginx 进行实验,在编写脚本之前,我们需要先获取配置文件,使用下面的命令行将指定版本的 Nginx 的配置文件保存到当前目录中。 docker run --rm -it nginx:1.19.3-alpine cat /etc/nginx/conf.d/default.conf > default.conf   默认的配置文件内容如下: server { listen 80; server_name localhost; #charset koi8-r; #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ .php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ .php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache"s document root # concurs with nginx"s one # #location ~ /.ht { # deny all; #} }   稍作精简,我们会得到一个更简单的配置文件,并在其中添加一行 error_page 405 =200 $uri; :server { listen 80; server_name localhost; charset utf-8; location / { return 200 "soulteary"; } error_page 405 =200 $uri; }   将本小节开始部分的命令改写为 docker-compose.yml 并添加 volumes ,把刚刚导出的配置文件映射到容器内,方便使用后续使用 compose 启动容器进行验证。version: "3" services: ngx: image: nginx:1.19.3-alpine restart: always ports: - 3000:80 volumes: - ./default.conf/:/etc/nginx/conf.d/default.conf   使用 docker-compose up 启动服务,然后使用前面的 curl 模拟 POST 验证请求是否正常。curl -d "{"key1":"value1", "key2":"value2"}" -H "Content-Type: application/json" -H "origin:gray.baai.ac.cn" -X POST http://localhost:3000 soulteary   执行完毕,除了得到 "soulteary" 这个字符串返回之外, Nginx 日志记录也会多一条看起来正常的记录: ngx_1 | 192.168.16.1 - - [31/Oct/2020:14:24:48 +0000] "POST / HTTP/1.1" 200 0 "-" "curl/7.64.1" "-"   但是,如果你细心的话,你会发现日志中并未包含我们发送的数据,那么这个问题该如何解决呢? 解决 Nginx 日志中丢失的 POST 数据   这个问题其实是老生常谈,默认 Nginx 服务器记录日志格式并不包含 POST Body(性能考虑),并且在没有 proxy_pass 的情况下,是不会解析 POST Body的。   先执行下面的命令: docker run --rm -it nginx:1.19.3-alpine cat /etc/nginx/nginx.conf   可以看到默认的 log_format 配置规则中确实并没有任何关于 POST Body 中的数据。user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main "$remote_addr - $remote_user [$time_local] "$request" " "$status $body_bytes_sent "$http_referer" " ""$http_user_agent" "$http_x_forwarded_for""; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; }   所以解决这个问题的方案也不难,新增一个日志格式,添加 POST Body 变量( request_body ),然后添加一个 proxy_pass 路径,激活 Nginx 解析 POST Body 的处理逻辑。   考虑到维护问题,我们前文中的配置文件与这个配置进行合并,并定义一个名为 /internal-api-path 的路径:user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main "$remote_addr - $remote_user [$time_local] "$request" " "$status $body_bytes_sent "$http_referer" " ""$http_user_agent" "$http_x_forwarded_for" $request_body"; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; charset utf-8; location / { proxy_pass http://127.0.0.1/internal-api-path; } location /internal-api-path { # access_log off; default_type application/json; return 200 "{"code": 0, data:"soulteary"}"; } error_page 405 =200 $uri; } }   将新配置文件保存为 nginx.conf 后,调整 compose 中的 volumes 配置信息,再次使用 docker-compose up 启动服务。volumes: - ./nginx.conf/:/etc/nginx/nginx.conf   再次使用 curl 模拟之前的 POST 请求,会看到 Nginx 日志多了两条记录,第一条记录中包含了我们所需要的 POST 数据:192.168.192.1 - - [31/Oct/2020:15:05:48 +0000] "POST / HTTP/1.1" 200 29 "-" "curl/7.64.1" "-" {"key1":"value1", "key2":"value2"} 127.0.0.1 - - [31/Oct/2020:15:05:48 +0000] "POST /internal-api-path HTTP/1.0" 200 29 "-" "curl/7.64.1" "-" -   但是这里不完美的地方还有很多: 服务器可以正常接收 GET 请求,我们在日志处理的时候需要进行大量"抛弃动作",并且在暂存的时候,磁盘空间也存在不必要的浪费。 用于激活 Nginx POST Body 解析能力的路径可以被随意调用,产生无意义日志,同样存在上面的问题。 更关键的,日志中的数据看起来还需要额外加工处理,进行转码,解析效率会有不必要的性能损耗。   接下来我们来继续解决这些问题。 改进 Nginx 配置,优化日志记录   首先,在日志格式中添加 escape=json 参数,要求 Nginx 解析日志请求中的 JSON 数据:log_format main escape=json "$remote_addr - $remote_user [$time_local] "$request" " "$status $body_bytes_sent "$http_referer" " ""$http_user_agent" "$http_x_forwarded_for" $request_body";   然后,在不需要记录日志的路径中,添加 access_log off; 指令,避免不必要的日志进行记录。location /internal-api-path { access_log off; default_type application/json; return 200 "{"code": 0, data:"soulteary"}"; }   接着使用 Nginx map 指令,和 Nginx 中的条件判断,过滤非 POST 请求的日志记录,以及拒绝处理非 POST 请求。map $request_method $loggable { default 0; POST 1; } ... server { location / { if ( $request_method !~ ^POST$ ) { return 405; } access_log /var/log/nginx/access.log main if=$loggable; proxy_pass http://127.0.0.1/internal-api-path; } ... }   再次使用 curl 请求,会看到日志已经能够正常解析,不会出现两条日志了。192.168.224.1 - [31/Oct/2020:15:19:59 +0000] "POST / HTTP/1.1" 200 29 "" "curl/7.64.1" "" {"key1":"value1", "key2":"value2"}   同时,也不会再记录任何非 POST 请求,使用 POST 请求的时候,会提示 405 错误状态。   这个时候,你或许会好奇,为什么这个 405 和前文中不同,不会被重定向为 200 呢?这是因为这个 405 是我们根据触发条件"手动设置"的,而非 Nginx 逻辑运行过程中判断出新的结果。   当前的 Nginx 配置如下: user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main escape=json "$remote_addr - $remote_user [$time_local] "$request" " "$status $body_bytes_sent "$http_referer" " ""$http_user_agent" "$http_x_forwarded_for" $request_body"; sendfile on; keepalive_timeout 65; map $request_method $loggable { default 0; POST 1; } server { listen 80; server_name localhost; charset utf-8; location / { if ( $request_method !~ ^POST$ ) { return 405; } access_log /var/log/nginx/access.log main if=$loggable; proxy_pass http://127.0.0.1/internal-api-path; } location /internal-api-path { access_log off; default_type application/json; return 200 "{"code": 0, "data":"soulteary"}"; } error_page 405 =200 $uri; } }   但是到这里就真的结束了吗? 模拟前端客户端常见跨域请求   我们打开熟悉的"百度",在控制台中输入下面的代码,模拟一次常见的业务跨域请求。 async function testCorsPost(url = "", data = {}) { const response = await fetch(url, { method: "POST", mode: "cors", cache: "no-cache", credentials: "same-origin", headers: { "Content-Type": "application/json" }, redirect: "follow", referrerPolicy: "no-referrer", body: JSON.stringify(data) }); return response.json(); } testCorsPost("http://localhost:3000", { hello: "soulteary" }).then(data => console.log(data));   代码执行完毕后,你会看到一个经典的提示信息: Access to fetch at "http://localhost:3000/" from origin "https://www.baidu.com" has been blocked by CORS policy: Response to preflight request doesn"t pass access control check: No "Access-Control-Allow-Origin" header is present on the requested resource. If an opaque response serves your needs, set the request"s mode to "no-cors" to fetch the resource with CORS disabled. POST http://localhost:3000/ net::ERR_FAILED   观察 Network 网络面板,会看到有两条失败的新请求: Request URL: http://localhost:3000/ Request Method: OPTIONS Status Code: 405 Not Allowed Request URL: http://localhost:3000/ Request Method: POST 没有响应结果   让我们继续调整配置,解决这个常见的问题吧。 使用 Nginx 解决前端跨域问题   我们首先调整之前的过滤规则,允许 OPTIONS 请求的处理。if ( $request_method !~ ^(POST|OPTIONS)$ ) { return 405; }   跨域请求是前端常见场景,许多人会偷懒使用 " * "来解决问题,但是 Chrome 等现代浏览器在新版本中有些场景不能使用这样宽松的规则,而且为了业务安全,一般情况,我们会在服务端设置允许进行跨域请求的域名白名单,参考上文中的方式,我们可以很容易的定义出类似下面的 Nginx map 配置,来谢绝所有前端非授权跨域请求:map $http_origin $corsHost { default 0; "~(.*).soulteary.com" 1; "~(.*).baidu.com" 1; } server { ... location / { ... if ( $corsHost = 0 ) { return 405; } ... } }   这里有一个 trick 的地方,Nginx 的路由内的规则编写,并不完全类似级编程语言一样,可以顺序执行,是具备"优先级/覆盖"关系的,所以为了能够让前端正常调用接口进行数据提交,这里需要这样书写规则,存在四行代码冗余。 if ( $corsHost = 0 ) { return 405; } if ( $corsHost = 1 ) { # 不需要 Cookie add_header "Access-Control-Allow-Credentials" "false"; add_header "Access-Control-Allow-Headers" "Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Mx-ReqToken,X-Requested-With,Date,Pragma"; add_header "Access-Control-Allow-Methods" "POST,OPTIONS"; add_header "Access-Control-Allow-Origin" "$http_origin"; } # OPTION 请求返回 204 ,并去掉 BODY响应,因 NGINX 限制,需要重复上面的前四行配置 if ($request_method = "OPTIONS") { add_header "Access-Control-Allow-Credentials" "false"; add_header "Access-Control-Allow-Headers" "Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Mx-ReqToken,X-Requested-With,Date,Pragma"; add_header "Access-Control-Allow-Methods" "POST,OPTIONS"; add_header "Access-Control-Allow-Origin" "$http_origin"; add_header "Access-Control-Max-Age" 1728000; add_header "Content-Type" "text/plain charset=UTF-8"; add_header "Content-Length" 0; return 204; }   再次在网页中执行前面的 JavaScript 代码,会发现请求已经可以正常执行了,前端数据会返回: {code: 0, data: "soulteary"}   而 Nginx 日志,则会多一条符合预期的记录: 172.20.0.1 - [31/Oct/2020:15:49:17 +0000] "POST / HTTP/1.1" 200 31 "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36" "" {"hello":"soulteary"}   而使用 curl 执行之前的命令,继续模拟纯接口调用,则会发现出现了 405 错误响应,这是因为我们的请求中不包含 origin 请求头,无法表明我们的来源身份,在请求中使用 -H 参数补全这个数据,即可拿到符合预期的返回:curl -d "{"key1":"value1", "key2":"value2"}" -H "Content-Type: application/json" -H "origin:www.baidu.com" -X POST http://localhost:3000/ {"code": 0, "data":"soulteary"} 相对完整的 Nginx 配置   到现在为止,我们基本实现一般的采集功能,满足基本诉求的 Nginx 配置信息如下: user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main escape=json "$remote_addr - $remote_user [$time_local] "$request" " "$status $body_bytes_sent "$http_referer" " ""$http_user_agent" "$http_x_forwarded_for" $request_body"; sendfile on; keepalive_timeout 65; map $request_method $loggable { default 0; POST 1; } map $http_origin $corsHost { default 0; "~(.*).soulteary.com" 1; "~(.*).baidu.com" 1; } server { listen 80; server_name localhost; charset utf-8; location / { if ( $request_method !~ ^(POST|OPTIONS)$ ) { return 405; } access_log /var/log/nginx/access.log main if=$loggable; if ( $corsHost = 0 ) { return 405; } if ( $corsHost = 1 ) { # 不需要 Cookie add_header "Access-Control-Allow-Credentials" "false"; add_header "Access-Control-Allow-Headers" "Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Mx-ReqToken,X-Requested-With,Date,Pragma"; add_header "Access-Control-Allow-Methods" "POST,OPTIONS"; add_header "Access-Control-Allow-Origin" "$http_origin"; } # OPTION 请求返回 204 ,并去掉 BODY响应,因 NGINX 限制,需要重复上面的前四行配置 if ($request_method = "OPTIONS") { add_header "Access-Control-Allow-Credentials" "false"; add_header "Access-Control-Allow-Headers" "Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Mx-ReqToken,X-Requested-With,Date,Pragma"; add_header "Access-Control-Allow-Methods" "POST,OPTIONS"; add_header "Access-Control-Allow-Origin" "$http_origin"; add_header "Access-Control-Max-Age" 1728000; add_header "Content-Type" "text/plain charset=UTF-8"; add_header "Content-Length" 0; return 204; } proxy_pass http://127.0.0.1/internal-api-path; } location /internal-api-path { access_log off; default_type application/json; return 200 "{"code": 0, "data":"soulteary"}"; } error_page 405 =200 $uri; } }   如果我们结合容器使用,只需要在其中添加一段额外的路由定义,单独用于健康检查,就能够实现一个简单稳定的采集服务。继续对接后续的数据转存、处理程序。 location /health { access_log off; return 200; }   而 compose 配置文件,相比较之前,不过多了几行健康检查定义罢了: version: "3" services: ngx: image: nginx:1.19.3-alpine restart: always ports: - 3000:80 volumes: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - ./nginx.conf:/etc/nginx/nginx.conf healthcheck: test: wget --spider localhost/health || exit 1 interval: 5s timeout: 10s retries: 3   结合 Traefik ,可以轻松进行实例的水平扩展,处理更多的请求。感兴趣可以翻阅我之前的文章。 最后   本文仅介绍了数据采集的皮毛,更多的内容或许后续有时间会细细道来。要给我家毛孩子付猫粮尾款啦,先写到这里吧。

ADA艾达币值得投资吗?这个币是一匹黑马,以前并没有注意过。也是在市值排名榜中,不知不觉发现它已经排名第六。艾达币和以太坊一样是一个智能合约平台也是同属于公有基础链之一。它的最大发行量是450亿枚,目前的爆料称全新Macmini即将发布性能更强并采用全新设计上周,有消息称苹果将在今年秋天发布经过重新设计的14英寸和16英寸MacBookPro。预计此新款MacBookPro将采用miniLED技术,并搭载苹果自研芯片M1X。此外,其还激光电视为什么不值得买啊?激光电视不是不值得购买,而是当前并不是最佳的购买时机,这里我聊聊我过往买电视的经历,或许你能明白。从液晶和等离子电视之争看激光电视在液晶电视没有完全普及之前,市场上有两种技术的电视三星GalaxyM525G完整规格曝光据外媒GSMArena报道,三星GalaxyM525G手机的完整规格在今日曝光,根据爆料者IshanAgarwal透露,该手机将搭载骁龙778G芯片,采用6。7英寸全高清显示屏。G屏下相机1。08亿像素,外加骁龙888Plus芯片,OPPOFindX4给力十足下半年才刚刚开始很多手机厂商已经开始全面发力,如小米发布了断更已久的小米MIX4,荣耀发布了旗下最高端的荣耀Magic3,vivo的子品牌iQOO开始向高端市场进军发布了iQOO8微信新增重量级功能连续发送暗号才能打开前段时间,微信在安卓iOS双平台更新,终于带来了大家期待了几年的更换铃声功能,提供了更加丰富的个性化选项,甚至还推出了类似彩铃的功能,一时间饱受吐槽的微信竟然备受好评。不知道是不是阿里云回应用户注册信息泄露事件品玩8月23日讯,据第一财经日报报道,阿里云今天对阿里云将用户留存的注册信息泄露给第三方合作伙伴一事进行回应。阿里云表示,根据自查,该投诉事件应为2019年双11前后,阿里云一名电荣耀Magic3上手时隔三年,这就是终极大招?2018年,荣耀首款Magic旗舰正式亮相,不知道你们怎么想,至少在我看来,Magic确实能给我一种极具黑科技和高端范的感觉。但因为种种原因,荣耀Magic迭代到2代之后就一直没有外观大变样,预装鸿蒙OS2爆料称新版华为MatePad11平板即将上市众所周知,上月6日,在华为举办的新品发布会上,官方正式发布了新一代平板电脑华为MatePad11。日前,有数码博主再次爆料,又一款新版华为MatePad11即将上市,根据爆出的海报realme归国刚小米,却从做手机到做生态,抄起了小米作业?文AI财经社陈畅编辑杨洁realme推出了自己AIoT战略下的首款笔记本电脑。这家对于很多人而言还比较陌生的手机品牌,最近开始卖电脑了。realme(中文名真我)作为一家主打智能手Win11系统,应用商店是Win10的怎么办?系统应用商店不对处理方法从Win11公布至今,早已有很多用户升级了Win11系统,并且升级到Win11预览版的最新版本。可是即便那样,用户打开自己电脑上中自带的应用店铺却发觉它并沒有伴随着系统的升级变为W
智能手机正在消失的实用功能,没有这些功能太可惜了随之时代变迁,有很多手机实用的功能正在消失,你最不能接受哪一个功能的消失?红外线遥控功能,该功能可以用手机遥控空调电视机顶盒投影仪等。妈妈再也不用担心我的遥控器找不到了。不过随着红选配置高价格高的三代vivoZ3,还是配置低价格低的vivoU3x这两款手机都已经上市很长时间,不过vivo却对这两款手机保持了持续更新的态势,这是让人有些意外的地方,那么这两款机型是有什么特别值得关注的卖点吗?下面我们来一起来简单分析下。viv共享单车的困境共享经济该何去何从很多人都认为共享单车是2017年诞生。我知道有人会马上反驳,说是2014年。没错,2014年,北大毕业生戴威与4名合伙人共同创立OFO,致力于解决大学校园的出行问题。但这也不是共享3000出头买到一加9,没想到它还真是个宝对于一加9这款手机,本来不在我的选择范围之内,因为当时在网上选机之时看到关于这款机型的很多非议,比如塑料边框不支持光学防抖等等。但是架不住一加9的优惠力度太大,就想试一试反正不满意数据中台到底长什么样子?4张图带你详解数据中台架构数据中台不是一个单纯的系统,而是一套架构一套数据流转模式。数据中台需要采集数据作为原材料进行数据加工数据建模,然后分门别类地储存,再根据实际的业务场景,打造各类数据服务(含数据应用深度长文探讨元宇宙背后的技术支撑交互性3DXRAI及5G我们的世界正变得虚拟Metaverse的功能连接虚拟与现实Metaverse是什么?Metaverse的组成部分Metaverse与交互性3DDecentraland3D虚拟空间S员工涉私德问题百度回应已劝退,lastday为今天文前瓜中午一名媛加笔者微信,让笔者帮忙在朋友圈跟公众号推送几张写真。按民法典第一千零一十条规定,该名媛向笔者展示裸露图片,这已经对本人构成性骚扰事实了。笔者在依法情况下向腾讯做出投新房不想买有线电视,还有什么好的办法?有光纤入户的宽带和一个可任意安装apk软件的机顶盒。我建议你买华为网络机顶盒,是最新款,里面含有电视直播全国各地都有无线数字地面波电视节目,沈阳20个台。2016年以后生产的电视插杨元庆宣布联想入局芯片!你信吗?卖了这么多年电脑,现在才想起来做芯片?科学不是没有国界吗?联想总部在美国也会买不到芯片?一个商人也想做芯片,我看蹭热度才是它的目的。我猜是来搅局的,给美国打击中国芯片产业添砖加瓦!是不是新一代的处理器和主板不支持winpe了?可以试试U盘魔术师全能版。或者看看主板BIOS里面。secureboot可以关闭不。应该是新一代CPU和主板彻底放弃支持legacy模式仅支持全新UEFI模式的原因,legacy是10086为什么那么积极给免费装宽带?有猫腻吗?隔壁老韩感叹枉我一世精明,可是跟移动比,真的算不过,比不过。买的不如卖得精。老韩是老干部,每个月有100元通信补贴,因此移动套餐使用全球通88套餐10G流量,200分钟通话。后来移