Windows 的端口代理配置(端口映射)

在调试本地程序,或者需要把 WSL 的服务暴露出去,使用端口映射会更加方便。 Windows 的端口映射命令格式如下: ❯ netsh interface portproxy The following commands are available: Commands in this context: show - Displays information. add - Adds a configuration entry to a table. delete - Deletes a configuration entry from a table. dump - Displays a configuration script. reset - Resets portproxy configuration state. set - Sets configuration information. portproxy:端口代理,它是在强大的网络管理工具 netsh 中,命令本身比较简单,主要就是端口代理的增删改查。 01 查看映射(show) show 可以查看已存在的端口转发规则,没有给定参数会输出以下帮助信息: ❯ netsh interface portproxy show The following commands are available: Commands in this context: show all - Shows all port proxy parameters....

May 14, 2023 · 3 min · 592 words · Spring

GBK 和 Unicode 之间的转换问题——“锟斤拷”的由来

GBK 和 Unicode 之间的转换问题 1. GBK 被解密为 UTF-8 正常的 GBK 字节流,以为是 UTF-8,所以用 UTF-8 去解码: 输出特点:一堆的黑色菱形+问号 输出示例:�Ҳ����� @Test public void test() throws UnsupportedEncodingException { String str = "我不是锟斤拷"; byte[] buff = str.getBytes("GBK"); // 这里只要不抛异常,数据一定不会被破坏 String str1 = new String(buff, "UTF-8"); } 2. UTF-8 被解密为 GBK 正常的 UTF-8 字节流,以为是 GBK,所以用 GBK 去解码: 输出示例:鎴戜笉鏄敓鏂ゆ嫹 @Test public void test() throws UnsupportedEncodingException { String str = "我不是锟斤拷"; byte[] buff = str.getBytes("UTF-8"); // 这里只要不抛异常,数据一定不会被破坏 String str1 = new String(buff, "GBK"); // 这里破坏了 } 3....

May 25, 2022 · 1 min · 141 words · Spring

Redis 的缓存穿透、缓存击穿和缓存雪崩问题

从第一个缓存框架 Memcached 诞生以来,缓存就广泛地存在于互联网应用中。如果你的应用流量很小,那么使用缓存可能并不需要做多余的考虑。但如果你的应用流量达到了成百上千万,那么你就不得不考虑深层次的缓存问题:缓存穿透、缓存击穿与缓存雪崩。 缓存穿透 缓存穿透是指查询一个一定不存在的数据,因为这个数据不存在,所以永远不会被缓存,所以每次请求都会去请求数据库。 例如我们请求一个 UserID 为 -1 的用户数据,因为该用户不存在,所以该请求每次都会去读取数据库。在这种情况下,如果某些心怀不轨的人利用这个存在的漏洞去伪造大量的请求,那么很可能导致DB承受不了那么大的流量就挂掉了。 对于缓存穿透,有几种解决方案,一种是事前预防,一种是事后预防。 事前预防 事前预防其实就是对所有请求都进行参数校验,把绝大多数非法的请求抵挡在最外层。在我们举的这个例子中,那么就是做参数校验,对于 UserID 小于 0 的请求全部拒绝。但即使我们做了全面的参数校验,还是可能存在漏网之鱼,会出现一些我们没想到的情况。 例如我们的 UserID 是递增的,那么如果有人请求一个 UserID 很大的用户信息(例如:1000000),而我们的 UserID 最大也就 10000。这个时候,你不可能限制 UserID 大于 1 万的就是非法的,或者说大于 10 万就是非法的,所以该用户ID肯定可以通过参数校验。但该用户确实不存在,所以每次请求都会去请求数据库。 其实上面只是我所能想到的一种情况,我们没想到的情况肯定还有很多。对于这些情况,我们能做的就是事后预防。 事后预防 事后预防说的就是当查询到一个空的结果时,我们仍然将这个空的结果进行缓存,但是设置一个很短的过期时间(例如一分钟),但是这种办法还是没办法预防非常多的非法值。 另外一个比较有效的办法是,将这个字段里在数据库中的所有值存在布隆过滤器中。当一个查询请求过来时,先经过布隆过滤器进行查,如果判断请求查询值存在,则继续查数据库。如果判断请求查询不存在,直接丢弃。 通过上面这两种处理方式,我们基本可以解决缓存穿透的问题。事前预防解决 80% 的非法请求,剩下的 20% 非法请求则使用 Redis 转移风险。 缓存击穿 如果你的应用中有一些访问量很高的热点数据,我们一般会将其放在缓存中以提高访问速度。另外,为了保持时效性,我们通常还会设置一个过期时间。但是对于这些访问量很高的KEY,我们需要考虑一个问题:当热点KEY在失效的瞬间,海量的请求会不会产生大量的数据库请求,从而导致数据库崩溃? 例如我们有一个业务 KEY,该 KEY 的并发请求量为 10000。当该 KEY 失效的时候,就会有 1 万个线程会去请求数据库更新缓存。这个时候如果没有采取适当的措施,那么数据库很可能崩溃。 其实上面这个问题就是缓存击穿的问题,它发生在缓存 KEY 的过期瞬间。对于这种情况,现在常用的解决方式有这么两种:互斥锁、永远不过期。 互斥锁 互斥锁指的是在缓存 KEY 过期去更新的时候,先让程序去获取锁,只有获取到锁的线程才有资格去更新缓存 KEY。其他没有获取到锁的线程则休眠片刻之后再次去获取最新的缓存数据。通过这种方式,同一时刻永远只有一个线程会去读取数据库,这样也就避免了海量数据库请求对于数据库的冲击。 而对于上面说到的锁,我们可以使用缓存提供的一些原则操作来完成。例如对于 redis 缓存来说,我们可以使用其 SETNX 命令来完成。 public String get(key) { String value = redis....

December 27, 2021 · 1 min · 200 words · 陈树义

curl 于 wget 的区别(下载文件)

01 curl 和 wget 的区别 wget 是个专职的下载利器,简单,专一,极致; curl 可以下载,但是长项不在于下载,而在于模拟提交 web 数据,POST/GET 请求,调试网页,等等。 02 具体使用(下载) 下载文件 curl -O http://man.linuxde.net/text.iso # O大写,不用O只是打印内容不会下载 wget http://www.linuxde.net/text.iso # 不用参数,直接下载文件 下载文件并重命名 curl -o rename.iso http://man.linuxde.net/text.iso # o小写 wget -O rename.zip http://www.linuxde.net/text.iso # O大写 断点续传 curl -O -C - http://man.linuxde.net/text.iso # O大写;C大写,- 表示不指定续传的偏移量,默认从本地文件计算 wget -c http://www.linuxde.net/text.iso # c小写 限速下载 curl --limit-rate 50k -O http://man.linuxde.net/text.iso wget --limit-rate=50k http://www.linuxde.net/text.iso 显示响应头部信息 curl -I http://man.linuxde.net/text.iso wget --server-response http://www.linuxde.net/test.iso wget 利器 → 打包下载网站 wget --mirror -p --convert-links -P /var/www/html http://man....

May 11, 2021 · 1 min · 83 words · Spring

Java 8 Functional 函数式接口

01 函数式接口 1.1 什么是函数式接口 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。 函数式接口可以被隐式转换为 Lambda 表达式。 Lambda 是一个匿名函数,返回一个实现了接口的对象。方法引用实际上也可认为是 Lambda 表达式(简化版)。 1.2 自定义函数式接口 如果要实现自己的函数式接口,步骤很简单。 首先,定义一个接口,并声明一个抽象方法。然后给接口添加注解 @FunctionalInterface,该接口即为函数式接口: @FunctionalInterface interface Converter<T, R> { R convert(T from); } 使用同样也很简单,创建一个 Lambda 表达式(要实现的方法)并赋值给该接口的一个变量,然后直接调用定义的那个抽象方法: // 创建一个函数:字符串转整型 Converter<String, Integer> converter = (from) -> Ingeter.valueOf(from); converter.convert("123") // 123 02 Java(8)提供的函数式接口 2.1 Converter<T, R>,如上 2.2 Predicate 作用:断言,判断是与非。 调用方式:predicate.test(OBJ)。 示例: Predicate<String> predicate = (s) -> s.length() > 0; predicate.test("foo"); // true predicate.negate().test("foo"); // false 2.3 Function<T, R> 作用:接口一个参数,返回一个结果,可以链式调用。...

November 24, 2020 · 2 min · 259 words · Spring

MySQL 去重之 distinct

在使用 MySQL 时,有时需要查询出某个字段不重复的记录,这时可以使用 MySQL 提供的 distinct 这个关键字来过滤重复的记录[1] 。 语法格式: select distinct expression[,expression...] from tables [where conditions]; 01 distinct 的用法 例如,我们有表如下: mysql> select * from user; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | taylor | pass123 | | 2 | spring | pass456 | | 3 | Yahto | taf23 | | 4 | Lillie | flowwer | | 5 | Lia | wherend | | 6 | Lia2 | wherend | | 7 | Lia3 | wherend | | 8 | Lia4 | wherend | +----+----------+----------+ 1....

August 22, 2020 · 3 min · 435 words · Spring

GO 语言快速入门

00 Go 环境配置 首先,下载 Golang 安装包,地址:https://go.dev/dl/。 接着,将 Golang 安装包解压到指定路径。 然后,把 Go 安装路径配置到环境变量。有如下两个环境变量: GOROOT:可选,主要是将 $GOROOT/bin 配置到环境变量中以便直接使用 go 命令及其工具等 GOPATH:Go 1.11 之后引入 Go Modules,不再完全依赖 GOPATH 了 Go 1.11 之前,go get 下载的包会被存放在 $GOPATH/src 目录下,与项目无关 Go 1.11 之后(使用了 Go Modules),依赖包会被存放在项目的 go.mod 指定的缓存目录中,默认情况下是 $GOPATH/pkg/mod 01 Go 基础 1.1 变量 类型:放在变量名后面 变量声明:var NAME TYPE 简单变量声明:NAME := VALUE(只允许在函数内部使用,且不能用于声明静态变量) 数据类型 bool string // 不出初始化,则默认空字符串:"" int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr byte // alias for uint8 rune // alias for int32 // represents a Unicode code point float32 float64 complex64 complex128 // 复数 var x complex128 = complex(1, 2) // 1+2i var y complex128 = complex(3, 4) // 3+4i fmt....

August 16, 2020 · 10 min · 1920 words · Spring

Learning programming is different from learning a programming language

We are all programmers, and we are all learners. It’s surprising to see how many people(learners) who are bashing their head against the walls thinking they are learning to program. You might be learning a programming language instead of programming itself Don’t feel surprised to know that computer science does not study computers. Instead, it’s the study of automated problem solving using computers. Problem-solving is computer science, not programming. That’s why many computer science students seem not to understand why they learn algorithm or mathematics....

March 20, 2019 · 5 min · 891 words · zooboole

Docker 之 Linux CGroup

基本概念 Linux CGroup 全称 Linux Control Group, 是 Linux 内核的一个功能,用来限制,控制与分离一个进程组群的资源(如 CPU、内存、磁盘输入输出等)。 主要提供了如下功能: Resource limitation: 限制资源使用,比如内存使用上限以及文件系统的缓存限制。 Priority control : 优先级控制,比如:CPU 利用和磁盘 IO 吞吐。 Accounting: 一些审计或一些统计,主要目的是为了计费。 Control: 挂起进程,恢复执行进程。 一些基本的资源子系统: Block IO(blkio):限制块设备(磁盘、SSD、USB 等)的 IO 速率 CPU Set(cpuset):限制任务能运行在哪些 CPU 核上 CPU Accounting(cpuacct):生成 cgroup 中任务使用 CPU 的报告 CPU (CPU):限制调度器分配的 CPU 时间 Devices (devices):允许或者拒绝 cgroup 中任务对设备的访问 Freezer (freezer):挂起或者重启 cgroup 中的任务 Memory (memory):限制 cgroup 中任务使用内存的量,并生成任务当前内存的使用情况报告 Network Classifier(net_cls):为 cgroup 中的报文设置上特定的 classid 标志,这样 tc 等工具就能根据标记对网络进行配置 Network Priority (net_prio):对每个网络接口设置报文的优先级 perf_event:识别任务的 cgroup 成员,可以用来做性能分析 CPU 限制 创建 cgroup 首先,直接在 cgroup 对应的子资源目录下, 用 mkdir 创建一个目录,就会自动包含必要文件...

February 28, 2019 · 2 min · 282 words · Spring
Hello, hugo~

Hello, hugo!

01 Hugo 安装配置 1.1 安装 Hugo(Windows) 安装文档:Install Hugo on Windows . 使用 scoop 安装,搜索 hugo 安装包如下: > scoop search hugo Results from local buckets... Name Version Source Binaries ---- ------- ------ -------- hugo-extended 0.129.0 main hugo 0.129.0 main 推荐安装扩展版的 hugo: > scoop install hugo-extended 1.2 创建项目 文档:Create Site . 首先,使用 hugo 创建项目: # 可以使用 --format yaml/json 设置配置文件格式,默认 toml > hugo new site my-site > cd my-site 然后,下载主题并配置: # 下载主题,可以使用其他方式,只要把主题放到 themes 目录下即可 > git submodule add https://github....

September 15, 2017 · 2 min · 235 words · Spring