Thursday, October 21, 2021

V2EX - 技术

V2EX - 技术


求指路淘宝爬虫姿势

Posted: 21 Oct 2021 06:29 AM PDT

现在有个需求,需要爬某品类下不同商家的大量商品详情及图片,总量约十万级别,预算比较充足,请问现在有靠谱的方法吗,是不是会面临比较大的政策风险 = =

求指路,感激不尽

请推荐书籍 - 描述 GUI 开发的原理与思想的书

Posted: 21 Oct 2021 06:28 AM PDT

学过 Android 、Flutter 、Web,发现有些共性,都是需要 先测量,布局再绘制。 而且 GUI 程序肯定也有异步处理,不然 耗时任务会卡住 GUI 。

后来想 GUI 开发也发展了很多年,从老早前的 windows 软件、QT 、J2ME 、诺基亚,很多语言都有自己的 GUI 开发库,比如 Python 有 Tkinter 、Kivy 、PySide 、wxPython 等等。

所以, 想请教下有没有 这样一本书,描述了 GUI 开发的共性、原理的,能让人能一通百通的。

b 站的 1024 解迷题有大佬做吗?

Posted: 21 Oct 2021 06:26 AM PDT

地址: https://security.bilibili.com/sec1024/
不会做,看到有个第 6 题跟第 5 题 url 地址一样的,是写错了还是说是某种提示??😂

有無方式可以完整復刻系統分區?

Posted: 21 Oct 2021 06:25 AM PDT

需求描述:
自用工作筆記本原先的系統分區是在一個機械硬碟上的。由於後期需要性能升級,所以就想把它遷移到一塊 SSD 上。
但是因為軟體的關係,是無法通過重灌系統的方式得到與原來相似的使用方式的。因此就在想有沒有合適的方式,可以直接將系統分區復刻到 SSD 。(在提問之前也找過數款 windows 上的工具,它們要麼收費很貴,要麼就是根本達不到所需目的)

具體目的:
將系統分區原封不懂從一塊 500G 的機械硬碟遷移到另一塊同樣的大小的 SSD 。完成後可以直接打開使用。(不在乎操作複雜程度和所需時間)



真心請教各位,謝謝大家了。( po 主從事的行業是設計師啦 XD

Google Authenticator 更新了,之前重复的两步校验消失了

Posted: 21 Oct 2021 06:22 AM PDT

如题,不用在手动删了

吐槽一下, win10 真是 bug 十足!

Posted: 21 Oct 2021 06:16 AM PDT

我台式机是 ubuntu,原来的笔记本是联想的,坏了,因为联想那个 5G 投票及吸国内机价格补国外价,不爽,去年底买了台 dell,预装是 win10,但是这个渣渣 bug 10,鼠标右键菜单经常分分钟点不出来!这个时候,就要先点左键,再点右键,重试很多次,才能出来,真是火大! 另外,就是调试程序时,有时候进程在运行,但资源管理器里,进程列表没出来,要等一会才出来,或刷新或作些别的操作才会出来。

为什么没有一种万能且通用的编程语言呢?

Posted: 21 Oct 2021 06:14 AM PDT

Web 开发用 PHP,Java,Node.js

基础设施用 C/C++

网页设计用 HTML,JS,CSS

数据库用 SQL 。

为什么不发明一种万能的编程语言,我只需要学一门语言就能做所有的事情。

这可能吗?

目前 Python 有这种趋势,但还是无法全面覆盖,比如移动端的 App 开发。

WSL 2 拳打 macOS,脚踢 Ubuntu ?

Posted: 21 Oct 2021 05:57 AM PDT

看到很多人说 Windows 11 WSL 2 推出后,开发方面 macOS 已经没有什么优势了?

有没有用过的老哥给说道说道?

[ Java ] 方法里有很多判断需要提前结束,很多重复代码,求大神!

Posted: 21 Oct 2021 05:54 AM PDT

因为几个查询条件耗时久查到结果就提前结束,但是有重复的地方觉得不够优雅 if 判断那一块

    private void prepareBookingOffice(BrChangedEvent brChangedEvent) {         BrGeneralInfoDto brGeneralInfoDto = Optional.ofNullable(brChangedEvent)                 .map(BrChangedEvent::getBrDto)                 .map(BrDto::getGeneralInfo)                 .orElse(BrGeneralInfoDto.builder().build());          if (StringUtils.isNotEmpty(brGeneralInfoDto.getBookingOfficeCode())) {             return;         }          // 耗时         String officeCode = getOfficeCodeByOfficeUnlLocCode(brGeneralInfoDto);         // 重复         if (StringUtils.isNotEmpty(officeCode)) {             brGeneralInfoDto.setBookingOfficeCode(officeCode);             return;         }          // 耗时         officeCode = getOfficeCodeByPor(brChangedEvent);         // 重复         if (StringUtils.isNotEmpty(officeCode)) {             brGeneralInfoDto.setBookingOfficeCode(officeCode);             return;         }          // 耗时         officeCode = getOfficeCodeByFnd(brChangedEvent);         // 重复         if (StringUtils.isNotEmpty(officeCode)) {             brGeneralInfoDto.setBookingOfficeCode(officeCode);             return;         }          // 耗时         officeCode = getOfficeCodeByPol(brChangedEvent);         // 重复         if (StringUtils.isNotEmpty(officeCode)) {             brGeneralInfoDto.setBookingOfficeCode(officeCode);         }     } 

vscode.dev

Posted: 21 Oct 2021 05:50 AM PDT

https://vscode.dev/

微软正式发布了可以在浏览器里使用的 VS Code 。

具体介绍:

https://code.visualstudio.com/blogs/2021/10/20/vscode-dev

WSA 的 IP 地址总是变得不可用,刷个抖音都网络错误

Posted: 21 Oct 2021 05:43 AM PDT

随手下个抖音测试下,没想到这虚拟网卡给我整这出。。

PHP 服务挂了之后是不是就能查看. PHP 文件源码了?

Posted: 21 Oct 2021 05:40 AM PDT

问个小白问题,有这么一个场景,假如我把.php 文件放在网站目录下,和 index.html 同目录,可通过浏览器访问的那种。 比如有一个 test.php 文件,里面有一些 PHP 代码,不渲染任何东西,当服务正常的时候,浏览器显示空白,这是正常情况。但如果 fpm 等相关服务挂掉了,是不是再访问就直接视为普通文本文件返回给浏览器了?这样就能看见源码了?

大家准备 1024 程序员节给自己买点啥?

Posted: 21 Oct 2021 05:33 AM PDT

大家过这个节日,给自己买东西嘛😂

个人准备掏点数码过一下节日,嘻嘻

Language Server for Java ™ 1.0 在 VS Code 上正式发布!

Posted: 21 Oct 2021 05:32 AM PDT

今天,我们很高兴与大家宣布:Language Server for Java™ 的 1.0 版本在 Visual Studio Code 上正式发布了!这是 Java 在 Visual Studio Code 上的一个重要里程碑,也是微软,红帽以及整个社区之间多年合作的结果。在这里我们要感谢所有提出过意见或者做过贡献的用户,谢谢!

发布亮点

当我们开始发布第一个版本时,我们的目标是在 Visual Studio Code 上提供最好的 Java 开发体验。此后,我们一直保持每月 1-2 次的发布周期,经历了多次迭代。在这个 1.0 版本中,我们想重点介绍以下新特色

Java 17 支持

我们会始终尽全力去支持 Java 语言提供的最新技术。在我们的 1.0 版本中,我们的 Java 插件现在正式提供对 Java 17 的支持

性能改进

性能提升也是本次发布的另一个亮点。由于 LSP规范中的新功能,我们能够推迟某些计算,从而在许多场景中为我们带来更好的性能。此外,更好的默认JVM选项可以用于改善更大更复杂项目的用户体验。我们还在很多特定场景做了细微的改进,以提高语言服务器的响应能力。

类继承体系

现在用户可以方便地在 Visual Studio Code 中轻松访问类继承体系!这是我们最近推出的一项功能,并且一直是 Java 社区中最热门的需求之一。

库源代码定位

目前,我们允许用户快速定位某个库的源代码,有时这非常有用。现在,我们已将其支持扩展到普通项目(即没有使用构建工具的项目)。只要库来自 Maven Central repo,我们就可以解析其来源。还支持更高级的配置。

更多代码相关操作

用户体验是我们继续改进的另一个领域。我们在新版本中提供了更多的代码操作来优化用户开发体验

Gradle Kotlin (.kts) 支持

尽管我们已经使用 Groovy 脚本支持 Gradle 项目,但我们不断听到社区需要更好的 Kotlin 支持,所以在新版本中我们对 Kotlin 提供了一些基本的支持。我们希望可以继续扩展这一领域,并在未来为 Kotlin 提供出色的体验

Visual Studio Code 的 Java 之旅

Language Server for Java™ Java扩展包的基础,并提供了 Java 代码编辑、完成、重构、导航等核心体验。在过去的几年里,微软和红帽一直密切合作,不断为这个语言服务器添加新功能。我们还一直在微调语言服务器的性能,并通过修复 Bug 和添加新特性来提高稳定性。

除了主要的 Java 语言支持外,我们还基于语言服务器构建了各种 Java扩展,并扩展了 Visual Studio Code 上的 Java 开发体验,包括项目管理、对 Maven/Gradle 的构建工具支持、更好的测试支持等。这些努力背后的目标是在 Visual Studio Code 上提供最佳的 Java 开发体验。

展望未来

在未来,我们为 Visual Studio Code 上的 Java 语言支持有非常多的计划。其中一些包括:

  • 让用户更容易配置编译器的错误 /警告和代码格式
  • 更智能以及有用的代码自动完成建议
  • 继续提供更多的代码相关操作并最终达到与其它 Java IDE 相同的功能
  • 进一步提升语言服务器的整体性能和启动时间
  • 在插件中直接嵌入 Java Runtime 以改善整体上手体验

Language Server for Java™ 的 1.0 版本是 Java 在 Visual Studio Code 上的重要里程碑,我们还有很长的路要走。微软和红帽将继续在 Java 语言支持方面进行合作和投入,我们致力于提供出色的 Java 开发体验。

与往常一样,您的反馈对我们的产品改进至关重要,因此请不要犹豫尝试我们的产品。您可以点击此链接开始使用 Visual Studio Code 学习 Java,也可以通过此链接获得最新的 Java 插件包。

VMware 虚拟机的 Unity 模式真的太好用了

Posted: 21 Oct 2021 05:18 AM PDT

以前都是用的 Hyper V,今天卸载了 Hyper V 装了 VMware,果然专业的商用软件就是强,Unity 模式可以在宿主机上接近无感地使用虚拟机里面的应用,比如 QQ 微信啥的,非常流畅。

简直比 Sandboxie 还要好用,而且是真正的虚拟机隔离。

为了理解 jvm 对 synchronized 的优化写了个 Java 层的偏向锁 轻量级锁

Posted: 21 Oct 2021 05:04 AM PDT

package code.ss.demo1.jvm;  import java.util.ArrayList; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock;  public class BiasLock {      public static final int SPIN_THRESHOLD_TIMES = 300;      static long a = 0;     static class LockThread extends Thread{         AtomicReference<LockObject> lock = new AtomicReference<>();          public LockThread(Runnable target) {             super(target);         }     }      public static void main(String[] args) throws InterruptedException {         LockObject lockObject = new LockObject();         ArrayList<String> strings = new ArrayList<>();         int size = 30;         Thread[] threads = new Thread[size];          for (int i = 0; i < size; i++) {             threads[i] =             new LockThread(() -> {                 int b = 0;                 while (b <= 10) {                     lock(lockObject);                     a++;                     strings.add(String.valueOf(a));                     unlock(lockObject);                     b++;                 }              });         }         for (Thread thread : threads) {             thread.start();         }          for (Thread thread : threads) {             thread.join();         }         System.out.println("size:" + strings.size());         System.out.println(a);         assert a == (size * 10);     }       static class LockObject {         //0 is not biased,1 is biased         AtomicInteger lockStatus = new AtomicInteger(0);          AtomicInteger baisedThreadId = new AtomicInteger(-1);         ReentrantLock reentrantLock = new ReentrantLock();         AtomicReference<Thread> smallLockReference = new AtomicReference();         AtomicInteger spainThreadCount = new AtomicInteger(0);         AtomicInteger spinCount = new AtomicInteger(0);     }     public static final int BlOCK = 5;     public static final int SPIN_LOCK = 2;     public static final int NO_LOCK = 0;     public static final int LOCK_BAISED = 1;      static public void unlock(LockObject lock) {         int status = lock.lockStatus.get();         if (status == NO_LOCK) {             return;         }         if (status == LOCK_BAISED) {             //解除偏向             int i = lock.baisedThreadId.get();             if (lock.baisedThreadId.compareAndSet(i, -1)) {                 lock.lockStatus.compareAndSet(LOCK_BAISED, NO_LOCK);             }         }         if (status == SPIN_LOCK) {             Thread thread = Thread.currentThread();             lock.smallLockReference.compareAndSet(thread, null);         }         if (status == BlOCK) {             if (lock.smallLockReference.get() == Thread.currentThread()) {                 //spin lock                 lock.smallLockReference.set(null);             }else{                 lock.reentrantLock.unlock();             }         }     }      static public void lock(LockObject lock) {         int status = lock.lockStatus.get();         System.out.println("status:" + status);         if (status == BlOCK) {             lock.reentrantLock.lock();         } else if (status == SPIN_LOCK) {                 raiseSpinLock(lock); //            if (lock.smallLockReference.get() != null) { //                if (lock.smallLockReference.get()  == Thread.currentThread()) { //                    return; //                } //            }else{ //                lock.lockStatus.compareAndSet(SPIN_LOCK, BlOCK); //                lock.reentrantLock.lock(); //            }         } else if (status == NO_LOCK) {             if (lock.baisedThreadId.get() == -1) {                 boolean b = lock.baisedThreadId.compareAndSet(0, Thread.currentThread().hashCode());                 if (b) {                     if (lock.lockStatus.compareAndSet(NO_LOCK, LOCK_BAISED)) {                         return;                     }                 }             }             raiseSpinLock(lock);         } else if (status == LOCK_BAISED) {             //已偏向             if (lock.baisedThreadId.get() == Thread.currentThread().hashCode()) {                 return;             }             lock.lockStatus.set(SPIN_LOCK);             //升级到轻量级锁             raiseSpinLock(lock);          }      }      private static void notify_lock(LockObject lock) { //        LockSupport.unpark();     }      private static void block_lock(LockObject lock) { //        LockSupport.park();     }      private static void raiseSpinLock(LockObject lock) {         while (true) {             int status = lock.lockStatus.get();             if (status == BlOCK) {                 lock.reentrantLock.lock();                 return;             }              if (status <= SPIN_LOCK) {                 if (lock.lockStatus.compareAndSet(status, SPIN_LOCK)) {                     break;                 }             }         }           LockThread c = (LockThread) Thread.currentThread();         c.lock.compareAndSet(null, lock);         int spinCount = 0;         while (true) {             if (spinCount >= SPIN_THRESHOLD_TIMES) {                 lock.lockStatus.set(BlOCK);                 lock.reentrantLock.lock();                 break;             }             int i = lock.spainThreadCount.incrementAndGet();             if (i > 3) {                 System.out.println("// stop spin cause too many thread contend,go to block lock");                 lock.lockStatus.set(BlOCK);                 lock.reentrantLock.lock();                 break;             }             if (lock.smallLockReference.compareAndSet(null, c)) {                 //get lock success                 lock.spainThreadCount.decrementAndGet();                 System.out.println("//spin :" + spinCount);                 break;             } else {                 Thread.yield();                 spinCount++;             }             lock.spinCount.incrementAndGet();         }     }   }  

交流下,理解有问题吗?

怎么让电脑恢复到出厂时预装的系统

Posted: 21 Oct 2021 04:45 AM PDT

入了宏碁的笔记本,出厂预装的 win10 系统个人觉得很好用(比如按下 capslock 或 numlock 会在屏幕上出现一个小提示)
然后后面自己重装了微软官网下的系统,发现各种提示都没有了,触控板也只能单击,无多指手势(装好了驱动)
尝试了恢复出厂设置依旧还是微软官方的系统,有什么办法装回出厂预装的系统吗。

某宝买的成品软路由 漏电,咋办

Posted: 21 Oct 2021 04:36 AM PDT

成品 4415U 软路由外壳是金属的,手心摸上去,是漏电的,麻麻的 还有点疼。用的是笔记本电源。另外一头是三头插头,插在插排上的

主要有 2 个问题:

1.漏电会怎么样?对机器有损坏吗?

2.漏电会导致电费比平时更多吗?

Windows Subsystem for Android 来了

Posted: 21 Oct 2021 04:31 AM PDT

Windows11 一大特性终于来了,可以试用了 https://docs.microsoft.com/en-us/windows/android/wsa/

自从有了 wsa,就可以愉快地刷 tiktok 了

Posted: 21 Oct 2021 04:08 AM PDT


wsa 只要挂个 openvn 就能上了,ios 还得越狱,安卓还得拔卡

搞到一台 2013 年的 Mac Mini 如何发挥余热?

Posted: 21 Oct 2021 03:59 AM PDT

配置的话内存 8G,SSD 256G,13 年的 i5 处理器

这个比树莓派强多了吧,我也没想好怎么用,你们有什么好的使用场景么?

双十一,云服务器有没有作业可以抄

Posted: 21 Oct 2021 03:32 AM PDT

18 年双十一阿里云新用户买了一台服务器
299 三年,单核 2G

今年到期了,不知道有没有其他类似的活动。
学习和搭一些小玩意用,性能不需太高,双核 4G 左右的即可。

一般国外大神分享视频教程的网站有哪些呀?

Posted: 21 Oct 2021 02:57 AM PDT

想深入学一学.Net Core (主要是得开发桌面应用),然而中文环境下的教程都落后太多年了,又恰逢你 Project Union 正在开发中,想看看最新进展。

目前文字资料只有微软的文档以及 GitHub 上的文档,上面的说明总感觉没写完而且略混乱。 Visual Studio 2022 preview 结合这一些插件的使用情况我也不太熟,想看看大神是怎么操作的(那个 build deploy and publish 我真有点分不清)。

我所知的就是 YouTube,但是貌似都不太成体系,而且很多都是宣传的会议过程,就简单介绍一下,其实我也了解了。于是我就陷入瓶颈了....

国内有没有.Net 的大神能分享分享国外的视频教程网站以及.Net 的相关宝贵资料呀。

请教 MYSQL 多表联查数据优化方式

Posted: 21 Oct 2021 02:57 AM PDT

Mariadb 10.1

tbl_product 产品表,有 3k 多个产品; tbl_spu SPU 表,其中 tbl.spu.pid = tbl_product.id;平均一个产品对应 3 个 spu ; tbl_sku SKU 表,其中 tbl_sku.spuID = tbl_spu.id;平均一个 spu 对应 5 个 sku ; tbl_price 价格表,tbl_price.skuID = tbl_sku.id ;价格维度是 日期+skuID ;

当我需要查询 10 条产品 7 日内最低的价格时候,现在伪 SQL 写法:

SELECT  	p.*,min(price) as price  from  	tbl_product p LEFT JOIN      tbl_spu spu ON spu.pid = p.id LEFT JOIN     tbl_sku sku ON sku.spuID = spu.id LEFT JOIN     tbl_price price ON price.skuID = sku.id WHERE      price.bookDate BETWEEN '2021-10-10' AND '2021-10-17' GROUP BY p.id LIMIT 10 

该做的索引都已经做了,但查询执行需要 14 秒左右, 请问类似这种的有没有什么好的方法 /思路 去优化?

想过上 ES,但 ES 太迟内存了, 想上训搜,但是怕结果也是一样,而且多了一个服务要维护,加上之前一个小的项目用过训搜,在索引清空重建的场景下偶尔出现异常,需要清空数据重新导入并进行索引。

如何实时同步 Otter 到 Redis/ES/CK 等存储?

Posted: 21 Oct 2021 02:41 AM PDT

MySQL 配置 Otter 发出消息后,有什么好用的工具,可以配一配就能把数据实时导到 Redis/ES/CK 等其它存储介质? 大家公司怎么实现实时同步数据库到其它存储的?都是重复造轮子吗?

fencing token 还是解决不了 lost update 吧

Posted: 21 Oct 2021 02:29 AM PDT

How to do distributed locking — Martin Kleppmann's blog中,Martin Kleppmann 说以下代码是 broken 的。

// THIS CODE IS BROKEN function writeData(filename, data) {     var lock = lockService.acquireLock(filename);     if (!lock) {         throw 'Failed to acquire lock';     }      try {         var file = storage.readFile(filename);         var updated = updateContents(file, data);         storage.writeFile(filename, updated);     } finally {         lock.release();     } } 

因为 Client 1 会覆盖掉 Client 2 所写的东西,如下图所示:

然后他说可以使用 fencing token 解决 lost update 问题,如下图所示,因为 Client 1 的 fencing token 小于 Storage 中的 token 。

但是如果 Client 1 先存进 Storage 呢? Client 2 最后会覆盖掉 Client 1 所做的改变,这样不是还是存在 lost update 问题吗?因为 Client 2 所做的修改是基于旧的数据,在提交修改时,Client 2 的读已经过时了。

MTK SP Flash Tool 有官方下载地址吗?

Posted: 21 Oct 2021 02:25 AM PDT

如题,网上找到的都是第三方下载的,联发科官方有提供下载吗?

postman 有没有安全风险?

Posted: 21 Oct 2021 02:17 AM PDT

登录后同步咱们的接口,万一 postman 被拖库了,咱们接口是不是都会暴露?或者说 postman 想要看我们的接口,是不是也能看?贼好用而且贼安全的替代品有哪些?大家讨论下。

想必各位果粉还没收到自己带刘海的 Macbook Pro,于是我先想办法在 GNOME 上体验了一下带刘海的 iMac 的感觉

Posted: 21 Oct 2021 02:06 AM PDT

让各位 GNOME 用户开心一下(如果有的话

screenshot

https://github.com/AlynxZhou/gnome-shell-extension-inotch/

又一个农场网站 '程序员的秘密'

Posted: 21 Oct 2021 02:04 AM PDT

这个农场网站搜到好几次了,又是刷流量的垃圾网站 https://www.cxymm.net/

Win11 任务栏满了怎么办?那些一行显示不下的图标不知道去哪了

Posted: 21 Oct 2021 01:59 AM PDT

(首先 LZ 不习惯任务栏图标居中这个设定,已经改成靠左了)
如题,如果图标堆满了,溢出了,那么只会用竖线把最右边能装下的最后一个图标(实际上还有更多的图标装不下了、显示不出来了)隔开来。
https://imgur.com/a/UDYrVpM
那些溢出的、装不下的图标,我好像没发现怎么才能找到它们。以前我记得会出现上下箭头切换翻页按钮,现在没有翻页按钮,各种拖动鼠标滚轮操作也都没用。

换 SIM 卡后信号恢复正常可能是什么原因?

Posted: 21 Oct 2021 01:39 AM PDT

/t/804267

手机插的两张卡都是移动的,但是有一张在家里就完全没信号,外出后有信号可以接听拨打电话,但是不能上网。

更换了 SIM 卡后就恢复正常了。

两张卡都是 nano-SIM 卡,拿到的时候就是三切卡,不是后来大卡剪小卡。

有问题的卡用了十来年。

Linux 配置完 privoxy 代理后 ,容器内的 tinytinyrss 服务无法访问问题 -求助

Posted: 21 Oct 2021 01:33 AM PDT

腾讯云服务器 CentOS7 系统,已安装 ShadowSocks 客户端 并配置代理 privoxy

listen-address 127.0.0.1:8118 forward-socks5t / 127.0.0.1:1080 .

curl www.google.com 调试谷歌已联通

通过 docker-compose 安装完毕 tinytinyrss,但是访问不了

初步分析为 容器内无法联通宿主机的地址

在网上找了很多教程 还是访问不了

比如 使用公网域名地址 比如 配置 docker 默认配置文件

希望那位清楚的大神 给一点其他的方法 对于容器的网络连接不是太熟悉 谢谢了

想抄一个今日头条

Posted: 21 Oct 2021 12:33 AM PDT

想做一个类似头条的资讯社区,做着玩玩。 没找到类似仓库,想请教大家有什么好的开源项目可以参考的么? 内容主要是图文、短视频,首页信息流根据用户标签做推荐。技术栈比较熟悉 spring 那一套。

宙斯盾 DDoS 防护系统“降本增效”的云原生实践

Posted: 21 Oct 2021 12:24 AM PDT

作者

tomdu,腾讯云高级工程师,主要负责宙斯盾安全防护系统管控中心架构设计和后台开发工作。

导语

宙斯盾 DDoS 防护系统作为公司级网络安全产品,为各类业务提供专业可靠的 DDoS/CC 攻击防护。在黑客攻防对抗日益激烈的环境下,DDoS 对抗不仅需要"降本"还需要"增效"。随着云原生的普及,宙斯盾团队持续投入云原生架构改造和优化,以提升系统的处理能力及效率。本文主要介绍宙斯盾防护调度平台上云过程实践与思考。

为什么上云?

云原生作为近年来相当热门的概念,无论在公司内各部门,还是公司外各大同行友商,都受到追捧。云原生涉及技术包括容器、微服务、DevOps 、持续交付等,这些新的技术和理念能带来哪些收益?在我们看来,

资源共享,动态扩缩容——"降本"

以宙斯盾防护调度平台为例,因为以前申请的物理机资源还在服役期,所以当前大部分后台服务还是运行在物理机。申请时会适当预留 buffer (资源消耗跟外部攻击威胁有关,波峰波谷相差可达十倍)。这部分 buffer 虽然作为 backup,但同时大部分时间处于空闲状态,物理机也不便于跨系统、项目共享。在资源上云阶段,CVM 已经对物理机做了虚拟化,一定程度上实现资源共享。随着容器化管理平台的出现,资源控制粒度更细。例如在 TKE 平台上,一个容器分配的资源可以精确到 0.1 核 CPU 、1 MB 内存,根据负载随时扩缩容。同时所有资源作为一个大池子来共享,减少资源浪费。

容器化管理,快速部署——"增效"

要提升迭代速度,除了开发环节,测试、发布、运维都需要做优化。原来物理机部署时,需要运维同学手工或者通过专门的运维发布平台来完成发布,期间还可能因为机器环境的差异出现发布失败或者异常,需要人工处理。现在通过容器化部署,可以保证服务的运行环境一致性,避免"雪花服务器"。同时借助容器管理平台,可以实现一键发布、快速扩缩容,通用的容器容灾策略为服务的稳定性提供了基本保证。

怎么上云?

当前架构

如上图所示,DDoS 防护流程包括攻击检测(发现攻击)和攻击防护(攻击流量清洗及正常流量回源)。

在这个过程中,还需要一个主控"大脑"来协调检测系统和防护系统,以实现全流程的自动化处理——这个"大脑"就是防护调度平台。在检测到 DDoS/CC 攻击时,防护调度平台会自动化决策需要调用的防护设备机房、数量、以及需要下发的防护策略,遇上强对抗时还需要实时调整防护设备上的防护策略,其重要程度可见一斑。

当前防护调度平台整体架构如下图所示。

  • 防护设备:分为 ADS ( Anti-DDoS System )、HTTP CC 、HTTPS CC 三大类,结合多年来团队在 DDoS/CC 攻防对抗上的积累,分别集成了各种协议 /场景下的自研防护算法。防护设备部署在全球各地机房入口,在触发攻击告警后牵引并清洗攻击流量,然后回源。其上部署有管控 agent,负责与后台通信、并管理防护设备。
  • 接入层:多点接入,内网、公网接入。管控 agent 启动后随机选择一个可用接入进行 TCP 连接。
  • 后台服务:多主 /主备部署,向接入注册心跳,所有后台请求通过接入分发、负载均衡,所有 agent 请求通过接入转发。

如果按照当前架构直接部署到 TKE 上,系统是可以运行起来,但是由于机器部署和容器部署的特性不同,直接部署总会有些冲突、别扭的地方。考虑方案时,我们觉得当前架构不适应 TKE 部署的主要地方有:

  • 服务发现:后台服务根据预配置的接入 IP 列表注册心跳,容器化部署后 IP 切换频繁,通过配置的方式加载接入已经不适用。
  • 无状态:容器化部署可以做到根据负载快速扩容,但需要服务做到完全无状态才能达到完全水平扩展。当前多主部署的服务都是无状态的,可以直接迁移,但主备部署的服务则需要改造。
  • 配置管理:当前按机器维度管理,与运行环境相关 /无关的配置混在一起。

同时,借着这次上云的机会,我们也希望对系统架构做一次大的优化,接入公司成熟的公共服务如北极星名字服务、七彩石配置中心、智研,提升研效。

上云架构

基于当前架构,除了把服务做镜像打包、迁移到 TKE 上部署,同时对不适应的地方做改造、优化。改造后的大致架构及流程如下:

  • 服务发现:后台服务全部接入北极星名字服务,向北极星注册实例、定期发送心跳,接入从北极星获取各类服务健康实例来分发请求。
  • 无状态:当前系统存在状态的场景主要有两类。
    • 文件下载:主要是防护设备的策略文件下载,无状态化改造涉及待下载文件在多个文件服务实例间同步。解决方案是选择使用 CFS 来同步文件。
    • 策略分包下发:策略太大时应用层做了分包,同一请求哈希到同一后台策略服务实例。解决方案是请求中带上当前分包状态信息,任一策略服务实例可以处理且结果一致。
  • 配置管理:与运行环境无关的配置,接入七彩石配置中心,保证同一类型部署的实例配置一致。
  • 日志监控:迁移到智研日志汇、监控宝。

两大"拦路虎"

如何平滑迁移

当前物理机环境稳定运行,计划逐步灰度、切量到 TKE 环境,因此会有一段时间是物理机+ TKE 混跑的状态。管控接入、后台服务迁移 TKE,对于防护设备 agent 是透明的。因为防护设备 agent 只会选择一个可用接入建立连接,即 agent 只会连到物理机环境或 TKE 环境,因此后台服务与 agent 交互时,混跑状态下涉及物理机环境和 TKE 环境互访的情况。这种情况 TKE 提供了灵活的配置支持。

在 TKE 上部署服务时,提供了两种网络模块:

  • Global Route:VPC 内私有 IP,无法从集群外访问,不可以注册到 CMDB 。开启随机端口映射后可从集群外访问,并可绑定 CLB 和北极星。
  • ENI IP:公司内可路由 IP,可从集群外访问,可以注册 CMDB 、CLB 和北极星。

在混跑灰度期间,接入部署选择 ENI IP 的方式,物理机后台服务访问 TKE 接入跟访问普通内网服务无异。迁移完成后,后台服务改用 Global Route 的方式,仅允许集群内互访。后台服务间通过原生的 service 访问,对外只通过 CLB 暴露服务。

不断变化的 IP

由于 DDoS 攻防对抗的业务特性,我们长期跟 IP 打交道,对 IP 有一种特殊的情节。在内部交流中,我们发现大家在迁移 TKE 过程中都会遇到一些共性问题。其中,跟 IP 相关的问题就会经常被提及。

在物理机部署环境,机器 IP 是固定的且变化频率较低(几年一次的机器裁撤)。但是在 TKE 环境,重启一次服务,分配到的容器 IP 、节点就可能变了,导致系统中依赖 IP 实现的功能无法很好适应 TKE 环境。

访问鉴权

比较简单的鉴权是基于源 IP 加白,如接口访问、DB 访问。对于接口访问,我们定义了一套基于 JWT 的接口鉴权规范,所有对外接口不再使用源 IP 加白的方式。对于 DB 访问,当前是使用不限源的独立 DB 账号,并对权限做更细的划分(精确到表)。后续 DB 权限支持实时申请,当容器起来以后通过接口申请当前容器所在节点的访问权限。

服务发现

原来的架构中,管控接入层实现了简单的服务注册、服务发现功能,后台服务通过 IP 配置来注册、上报心跳。如果接入层不迁移到 TKE 、继续保持相对固定,那么这套方案还是可行的。但是,接入层迁移到 TKE 后,自身的部署节点也在不断变化,因此需要一个独立与接入、相对固定的服务注册与发现模块。集群内部署的服务可以使用 K8s / TKE 原生的 service,对于物理机和 TKE 混跑的情况则可以考虑北极星名字服务。

服务暴露

这里包含两层含义,一个是该暴露给外部的服务如何保持稳定,另一个是不该暴露给外部的服务如何隐藏起来。

( 1 )暴露服务给外部

在物理机环境,机器裁撤导致服务 IP 变化就是经常出现的问题,通过域名、VIP 都可以解决。在 TKE 上,通过 CLB 来实现。

( 2 )隐藏内部服务

通过 VPC 内私有 IP,就能保证服务无法从集群外访问,实现隔离。

我们系统的最终目标是:所有对外服务通过接入层暴露出去,做好鉴权;内部的后台服务都隐藏起来,保证安全性。

上云效果

防护调度平台上云之后,

(1)在降低成本方面,预计资源使用率可以达到 50%以上。之前为了保证 DDoS 攻击峰值时能正常运行而预留的一大部分资源,闲时放到整个大资源池里共享,忙时动态扩容。

(2)在部署效率方面,部署、扩容耗时从天降到分钟。原来需要运维同学专人专职完成发布,上 TKE 后只需开发同学简单配置即可完成。同时,随着业务场景的快速变化,通过 TKE 满足了我们对高防、网关、第三方云等场景的快速部署和扩容。

随着公司内云上服务越来越丰富,通过上云和接入公共服务,优化宙斯盾防护调度平台的架构,从而提升系统扩展性和迭代效率。 另外,宙斯盾的核心能力是 DDoS 、CC 防护,除了管控上云,我们也正在探索防护能力虚拟化的可能性,为云上各种业务、场景提供灵活、弹性的防护能力。

关于我们

更多关于云原生的案例和知识,可关注同名 [腾讯云原生] 公众号~

福利:

   ①公众号后台回复 [手册] ,可获得《腾讯云原生路线图手册》&《腾讯云原生最佳实践》~     ②公众号后台回复 [系列] ,可获得《 15 个系列 100+篇超实用云原生原创干货合集》,包含 Kubernetes 降本增效、K8s 性能优化实践、最佳实践等系列。 

wsa 分辨率跟窗口大小能调吗

Posted: 21 Oct 2021 12:15 AM PDT

有些应用比如虎扑,怎么拉窗口都不管用,导致里面的字小小的根本看不清。有些就很友好了,比如酷安基本上随便拉,而且字体很大。所以像虎扑这种应用有解吗?

React+异步任务 的疑问

Posted: 20 Oct 2021 11:34 PM PDT

背景:Vue 用户,重学 React 中

先上代码

function App() {   const afterRender = () => {     console.log('after render')    }    // 1.  渲染后回调   // useEffect(afterRender)   // 2.  尝试用异步方式模拟渲染后的回调   queueMicrotask(afterRender)   // Promise.resolve().then(afterRender)   // setTimeout(afterRender, 0)     return (     <div className="App">      <div>something</div>     </div>   ) } 

问题在于:

useEffect 表现正常(废话),

而 2 中的 3 种方法,通过异步方式实现渲染后执行,afterRender 会被调用两次,即控制台打印两次after render

这到底是什么原因?

准备回退 Windows 10 了, Windows 11 过于难以适应

Posted: 20 Oct 2021 10:53 PM PDT

个人感觉: win 11 大大降低了效率, 用了几天, 难以适应, 告辞!

  • (平板上) 屏幕左侧划入: Win 10 是多任务窗口视图, Win 11 强行整个小部件(据说还有 edge webview 后台吃资源呢). 不能改回去, 我又没咋用, 就算要用, 日常操作中, 多任务切窗口动作动作更频繁.

  • (平板上) 屏幕右侧划入: Win 10 是通知中心 + 快捷开关, Win 11 是日历??? 我一个月能点开几次日历? 日程管理都在 outlook 里面, 这日历的日程管理也很弱鸡啊.

  • (平板上) "显示更多" 展开后的菜单项目间距不会增大, 相当小, 新的菜单风格不评价. win 10 在触摸时是自动增加菜单项目间距方便点击的, Win 11 那半成品气息浓厚的菜单设计过于窒息.

  • (平板上) 之前吐槽过了, tabtip 组件 /触屏输入体验越改越糟糕, 唯一喜欢的新功能是可以调整虚拟键盘大小.

  • 任务栏: 多屏时 bug 频出, 图标重叠时有发生.

  • 任务栏: 不能使用小任务栏, 占据过多屏幕纵向空间 (实际倒也不算多). 强行小任务栏会有 bug.

  • 任务栏: 有时应用程序明明只剩一个窗口, 但任务栏图标可能 bug 显示你在此程序开了多个窗口.

  • 开始菜单: 不喜欢现在的开始菜单, 默认不显示所有程序, 找程序不方便, 我觉得 Win 10 21h1 的风格挺好的, 自己贴靠也方便.

  • (平板上) 不知道是不是错觉, ui 元素大小总感觉怪怪的, 偏小的样子, 比如通知中心的快捷操作图标, 不是很适合触摸操作的样子. Win 10 好不好看另说, 图标大大的, 好用一些.

  • 不少重新设计的 UI, 都要多点很多次鼠标, 特别是设置 App, 默认折叠选项, 以前滚动下就能找自己需要的设置项目, 现在, 一个一个的点击展开再看!


好了, 上面的都能勉强适应, 或者使用频率不高, 不太影响, 可以继续使用, 那么:

任务栏不能取消折叠真是要了老命了!!!, 说个今天越用越烦躁的实例: 浏览器开了一些标签页, 又开了个浏览器窗口看 pdf, 开了两个编辑器窗口, 开了一些终端, 结果这些窗口在任务栏上就 3 个图标, 相当难用.

Win+tab 再点要切换的窗口?

alt+tab 凭感觉切换?

鼠标点图标, 再点对应的窗口缩略图?

这些用着都很降低效率, 难道微软的 UX 设计师工作时一个程序只开一个窗口吗?

为什么 Redlock 算法说“It tries to acquire the lock in all the N instances sequentially”

Posted: 20 Oct 2021 09:34 PM PDT

Distributed locks with Redis – Redis - The Redlock algorithm中,它说

It tries to acquire the lock in all the N instances sequentially, using the same key name and random value in all the instances. During step 2, when setting the lock in each instance, the client uses a timeout which is small compared to the total lock auto-release time in order to acquire it. For example if the auto-release time is 10 seconds, the timeout could be in the ~ 5-50 milliseconds range. This prevents the client from remaining blocked for a long time trying to talk with a Redis node which is down: if an instance is not available, we should try to talk with the next instance ASAP.

sequentially 是什么含义?为什么要 sequentially 呢?

然后在Distributed locks with Redis – Redis - Retry on failure中,它又说

When a client is unable to acquire the lock, it should try again after a random delay in order to try to desynchronize multiple clients trying to acquire the lock for the same resource at the same time (this may result in a split brain condition where nobody wins). Also the faster a client tries to acquire the lock in the majority of Redis instances, the smaller the window for a split brain condition (and the need for a retry), so ideally the client should try to send the SET commands to the N instances at the same time using multiplexing.

这不是互相矛盾吗?还是我哪里理解错了?

介绍一个可以在 ubuntu 上编译 uni-app 的 idea 编辑器

Posted: 20 Oct 2021 09:07 PM PDT

我想在 ubuntu 使用 hbuilderx 打包一个 apk,源码是通过 uni 写的,但是官网不支持 Linux,有其他软件推荐吗? 如果推荐我买苹果电脑就算了,话题有点跑偏

Apple Developer Tech Talks 2021

Posted: 20 Oct 2021 08:04 PM PDT

关于 github 访问问题,请大佬来解答

Posted: 20 Oct 2021 07:43 PM PDT

我每天早上到公司第一次可以打开 GitHub,很快。关掉网页,第二次再进就打不开了。然后,就全程梯子才可以访问 GitHub 。这到底是什么原理,难道 qiang 这么智能?

Nodejs+mysql 写接口会有问题不?

Posted: 20 Oct 2021 06:07 PM PDT

两个月前吧,觉得圈内越来越卷了。作为一个入行 5 年的前端,依旧是普通的码农。随着年纪越来越大,房子、车子、孩子的压力也随之到来。

网上看到很多新闻,说程序员 35 岁转行做鸭的也有,程序员 35 岁找不到工作的也有。领着微薄工资的我,陷入了沉思。于是想着,大家都在内卷,你不卷就会被淘汰。

作为老前端,想要继续深入很难,所以准备横向发展。所以想学下后端,一来可以增加编程的知识面,二来学了后端,就可以做点东西出来了。

说干就干!我买了一本掘金小册,是写从零开始实现记账本的全栈课程。缘分呀,刚好我自己也有几年的记账经历,就做记账吧。

很快,两个月过去了,我做出了人生的第一个自己一手打造的微信小程序:文文记账微信小程序。

由于是前端转后端,所以用 nodejs+mysql 的模式写的接口,不知道行不行。有小伙伴用过这种模式的吗?给点意见吧!

多说一句:欢迎大家体验一下我写的微信小程序:微信搜一搜:文文记账,即可找到。另外,我正在招募 100 名种子用户,可以免费成为文文记账的终身 VIP,有兴趣的朋友可以加我微信:wenwenjz_com

想写一个 bat 命令行处理脚本,怎么在执行命令行后的终端继续输入命令

Posted: 20 Oct 2021 04:54 PM PDT

boxie.exe attach ipc:\.\pipe\geth.ipc 执行完后跳转 welcome to XXX

执行完这命令后会跳到另外一个终端,请问怎么在这个终端输入命令 继续执行

执行往后保持 cmd 窗口

No comments:

Post a Comment