[{"content":"","date":"2025-12-20","externalUrl":null,"permalink":"/categories/go%E8%AF%AD%E8%A8%80/","section":"文章分类","summary":"","title":"Go语言","type":"categories"},{"content":"","date":"2025-12-20","externalUrl":null,"permalink":"/categories/k8s/","section":"文章分类","summary":"","title":"K8s","type":"categories"},{"content":"","date":"2025-12-20","externalUrl":null,"permalink":"/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/","section":"文章分类","summary":"","title":"数据库","type":"categories"},{"content":"","date":"2025-12-20","externalUrl":null,"permalink":"/categories/","section":"文章分类","summary":"","title":"文章分类","type":"categories"},{"content":"","date":"2025-12-20","externalUrl":null,"permalink":"/posts/","section":"文章归档","summary":"","title":"文章归档","type":"posts"},{"content":"本文介绍一种简单、稳定、可直接部署的 PostgreSQL 16 在 Kubernetes 中的部署方式，适合：\n单机 K8s / k3s 开发、测试、内部业务环境 仅 集群内部访问 的数据库场景 特点一句话总结：少配置、不踩坑、一次就能跑起来。\n一、方案说明 # 本方案具备以下特点：\n使用 StatefulSet（保证数据库身份稳定） 使用 hostPath 持久化数据（简单直观） 使用 initContainer 修复权限（避免常见 init-perms BackOff） PostgreSQL 监听所有地址 pg_hba.conf 完全放开（仅建议集群内使用） 通过 ClusterIP Service 访问，不暴露公网 二、部署结构 # Namespace: flash ├── Secret (数据库名 / 用户 / 密码) ├── ConfigMap (postgresql.conf / pg_hba.conf) ├── StatefulSet (PostgreSQL 16) └── Service (ClusterIP) 数据库访问地址：\npostgresql.flash.svc:5432 三、完整部署 YAML # 将下面内容保存为 postgresql-open.yaml，直接部署即可。\napiVersion: v1 kind: Secret metadata: name: postgresql-secret namespace: flash type: Opaque stringData: POSTGRES_DB: eladmin POSTGRES_USER: postgres POSTGRES_PASSWORD: \u0026#34;ChangeMe123\u0026#34; --- apiVersion: v1 kind: ConfigMap metadata: name: postgresql-config namespace: flash data: postgresql.conf: | listen_addresses = \u0026#39;*\u0026#39; port = 5432 pg_hba.conf: | local all all trust host all all 0.0.0.0/0 md5 host all all ::/0 md5 --- apiVersion: v1 kind: Service metadata: name: postgresql namespace: flash spec: type: ClusterIP selector: app: postgresql ports: - port: 5432 targetPort: 5432 --- apiVersion: apps/v1 kind: StatefulSet metadata: name: postgresql namespace: flash spec: serviceName: postgresql replicas: 1 selector: matchLabels: app: postgresql template: metadata: labels: app: postgresql spec: securityContext: fsGroup: 999 initContainers: - name: init-perms image: busybox:1.36 securityContext: runAsUser: 0 command: [\u0026#34;/bin/sh\u0026#34;,\u0026#34;-c\u0026#34;] args: - mkdir -p /var/lib/postgresql/data \u0026amp;\u0026amp; chown -R 999:999 /var/lib/postgresql/data volumeMounts: - name: pg-data mountPath: /var/lib/postgresql/data containers: - name: postgresql image: postgres:16 securityContext: runAsUser: 999 envFrom: - secretRef: name: postgresql-secret env: - name: PGDATA value: /var/lib/postgresql/data/pgdata ports: - containerPort: 5432 args: - \u0026#34;-c\u0026#34; - \u0026#34;config_file=/etc/postgresql/postgresql.conf\u0026#34; - \u0026#34;-c\u0026#34; - \u0026#34;hba_file=/etc/postgresql/pg_hba.conf\u0026#34; volumeMounts: - name: pg-data mountPath: /var/lib/postgresql/data - name: pg-config mountPath: /etc/postgresql/postgresql.conf subPath: postgresql.conf - name: pg-config mountPath: /etc/postgresql/pg_hba.conf subPath: pg_hba.conf volumes: - name: pg-data hostPath: path: /data/postgresql type: DirectoryOrCreate - name: pg-config configMap: name: postgresql-config 四、部署与验证 # kubectl apply -f postgresql-open.yaml kubectl -n flash get pods 验证数据库：\nkubectl -n flash exec -it postgresql-0 -- psql -U postgres -d eladmin 五、注意事项 # 仅用于内网 / 集群内部 不要直接暴露到公网 若用于生产，建议改用 PVC + 收紧 pg_hba.conf 补充阅读 # 补充 Kubernetes 部署 PostgreSQL 16 的内网访问边界、存储依赖与恢复验证说明。\n如何理解与使用 # hostPath 将数据留在指定节点，ClusterIP 提供集群内访问入口，两者都不能单独提供备份或账号权限控制。\n验证与边界 # 原例的宽松认证只适合理解受控测试流程；实际部署应按地址和用户收紧 pg_hba.conf，再验证认证失败、数据写入与恢复。节点或容器重建的结果需要分别检查。\n参考：PostgreSQL 16 认证配置（本次补充核对）。\n","date":"2025-12-20","externalUrl":null,"permalink":"/posts/k8s-postgres/","section":"文章归档","summary":"hostPath 将数据留在指定节点，ClusterIP 提供集群内访问入口，两者都不能单独提供备份或账号权限控制。","title":"在 Kubernetes 中部署 PostgreSQL 16（单机版，集群内全放开访问）","type":"posts"},{"content":"记录技术实践，整理解决问题的方法，也留下一些日常思考。\n","date":"2025-12-20","externalUrl":null,"permalink":"/","section":"正能量","summary":"记录技术实践，整理解决问题的方法，也留下一些日常思考。\n","title":"正能量","type":"page"},{"content":"","date":"2025-08-15","externalUrl":null,"permalink":"/categories/java/","section":"文章分类","summary":"","title":"Java","type":"categories"},{"content":"在 Kubernetes 上部署 Redis 是许多应用的基础服务之一。由于 Redis 是一个高性能、内存存储的数据库，因此在部署时，我们需要关注性能、持久化、安全性和高可用性等方面。本文将展示如何基于 Kubernetes 上的 StatefulSet 和 Service 部署 Redis。 特点：\n资源请求和限制 在 Kubernetes 中，合理的资源请求和限制能够有效避免资源浪费，并保障 Redis 服务的稳定性。下面我们根据负载需求进行了优化： 内存和 CPU 请求和限制：减少了内存请求和限制，以更合适地配置单节点 Redis 部署。 资源请求和限制：设置了 CPU 请求和限制，以确保系统能够根据负载进行适当的调度。\nresources: limits: memory: \u0026#34;512Mi\u0026#34; # 优化内存限制 cpu: \u0026#34;500m\u0026#34; # 添加 CPU 限制 requests: memory: \u0026#34;256Mi\u0026#34; # 请求的内存大小 cpu: \u0026#34;250m\u0026#34; # 请求的 CPU 安全性增强 默认情况下，Redis 容器是以 root 用户运行的，这会带来一定的安全隐患。在生产环境中，我们建议避免使用 root 用户，而是使用一个非特权用户来运行 Redis：\nsecurityContext: runAsUser: 1001 # 使用非 root 用户 fsGroup: 1001 # 为 Redis 容器指定文件系统组，提升安全性 此外，我们还可以将 Redis 密码通过 Kubernetes Secret 管理，而不是直接在配置文件中明文存储：\nenvFrom: - secretRef: name: redis-secret # 密码通过 Secrets 引用 健康检查 为了提高 Redis 的可用性，添加 livenessProbe 和 readinessProbe 是非常重要的。这些探针可以帮助 Kubernetes 检测容器是否健康，如果 Redis 容器无法响应请求，Kubernetes 会自动重启该容器：\nlivenessProbe: httpGet: path: /health port: 6379 initialDelaySeconds: 30 periodSeconds: 10 failureThreshold: 3 readinessProbe: httpGet: path: /health port: 6379 initialDelaySeconds: 15 periodSeconds: 5 failureThreshold: 3 外部化 Redis 密码 为了提高安全性，Redis 密码不应直接存储在 YAML 配置文件中。我们将密码存储在 Kubernetes Secret 中，这样可以避免在配置文件中泄露敏感信息。首先，我们创建一个 Secret 来存储密码：\napiVersion: v1 kind: Secret metadata: name: redis-secret namespace: flash type: Opaque data: REDIS_PASSWORD: \u0026lt;base64-encoded-password\u0026gt; # 通过 base64 编码存储密码 然后，在 StatefulSet 配置中，通过 envFrom 引用该 Secret：\nenvFrom: - secretRef: name: redis-secret # 引用 Secret 存储的密码 持久化配置 虽然已经配置了 volumeClaimTemplates 来保证 Redis 的数据持久化，但为了提高 Redis 的性能，建议在容器中指定 Redis 配置文件，并根据需要调整持久化行为，例如 RDB 快照和 AOF 日志设置。\ncommand: - \u0026#34;redis-server\u0026#34; - \u0026#34;/etc/redis/redis.conf\u0026#34; - \u0026#34;--requirepass\u0026#34; - \u0026#34;$(REDIS_PASSWORD)\u0026#34; 完整的优化后配置 将上面的所有优化合并后，我们的最终 Redis 部署配置如下：\napiVersion: apps/v1 kind: StatefulSet metadata: name: redis namespace: flash labels: app: redis spec: serviceName: \u0026#34;redis\u0026#34; replicas: 1 # 单节点 Redis，设置为 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis image: redis:6-alpine ports: - containerPort: 6379 envFrom: - secretRef: name: redis-secret # 密码通过 Secrets 引用 resources: limits: memory: \u0026#34;512Mi\u0026#34; cpu: \u0026#34;500m\u0026#34; requests: memory: \u0026#34;256Mi\u0026#34; cpu: \u0026#34;250m\u0026#34; command: - \u0026#34;redis-server\u0026#34; - \u0026#34;/etc/redis/redis.conf\u0026#34; - \u0026#34;--requirepass\u0026#34; - \u0026#34;$(REDIS_PASSWORD)\u0026#34; volumeMounts: - name: redis-data mountPath: /data securityContext: runAsUser: 1001 # 使用非 root 用户 fsGroup: 1001 # 提升容器安全性 livenessProbe: httpGet: path: /health port: 6379 initialDelaySeconds: 30 periodSeconds: 10 failureThreshold: 3 readinessProbe: httpGet: path: /health port: 6379 initialDelaySeconds: 15 periodSeconds: 5 failureThreshold: 3 volumeClaimTemplates: - metadata: name: redis-data spec: accessModes: [\u0026#34;ReadWriteOnce\u0026#34;] resources: requests: storage: 1Gi --- apiVersion: v1 kind: Service metadata: name: redis namespace: flash spec: selector: app: redis ports: - protocol: TCP port: 6379 targetPort: 6379 type: ClusterIP --- apiVersion: v1 kind: Service metadata: name: redis-external namespace: flash spec: selector: app: redis ports: - protocol: TCP port: 6379 targetPort: 6379 nodePort: 32679 type: NodePort --- apiVersion: v1 kind: Secret metadata: name: redis-secret namespace: flash type: Opaque data: REDIS_PASSWORD: \u0026lt;base64-encoded-password\u0026gt; 结语 在 Kubernetes 上部署 Redis 不仅仅是将其容器化，更多的是通过合适的配置优化，使 Redis 在生产环境中具备高可用性、安全性和良好的性能表现。本文展示了如何优化 Redis 部署，从资源管理到安全性，再到持久化配置，每一步都能提高 Redis 服务的可靠性和效率。\n补充阅读 # 解释 Kubernetes Redis 单节点部署中，资源、用户权限与数据持久化需要怎样配套验证。\n如何理解与使用 # Pod 数量、Service 可达与 Redis 数据持久化分别解决不同问题；运行用户和 fsGroup 要与实际镜像及挂载目录匹配。\n验证与边界 # 测试认证、读写和重建后的数据，再核对存储落在哪个节点。单个 StatefulSet 副本并不是高可用，资源上限也不能直接等同于 Redis 可用数据内存。\n","date":"2025-08-15","externalUrl":null,"permalink":"/posts/k8s-redis/","section":"文章归档","summary":"Pod 数量、Service 可达与 Redis 数据持久化分别解决不同问题；运行用户和 fsGroup 要与实际镜像及挂载目录匹配。","title":"Kubernetes 上的 Redis 部署","type":"posts"},{"content":"","date":"2025-08-15","externalUrl":null,"permalink":"/categories/redis/","section":"文章分类","summary":"","title":"Redis","type":"categories"},{"content":"","date":"2025-08-15","externalUrl":null,"permalink":"/categories/spring/","section":"文章分类","summary":"","title":"Spring","type":"categories"},{"content":"","date":"2025-08-15","externalUrl":null,"permalink":"/categories/%E5%BE%AE%E6%9C%8D%E5%8A%A1/","section":"文章分类","summary":"","title":"微服务","type":"categories"},{"content":" 通过 WireGuard 实现内网资源访问 # 场景描述 # 在企业或家庭网络中，常需要通过公网安全访问内部资源（如NAS、服务器、监控设备等）。WireGuard 凭借其轻量高效的特点，成为理想的VPN解决方案。\n网络拓扑 # 公网客户端 \u0026lt;---\u0026gt; WireGuard Server（公网IP） \u0026lt;---\u0026gt; 内网资源（192.168.88.0/24）\n配置步骤 # 1. 服务端准备 # # Ubuntu/Debian 安装 sudo apt update \u0026amp;\u0026amp; sudo apt install wireguard resolvconf -y # 生成密钥对 umask 077 wg genkey | tee server_private.key | wg pubkey \u0026gt; server_public.key 2. 服务端配置 # /etc/wireguard/wg0.conf\n[Interface] Address = 10.88.88.1/24 ListenPort = 1088 PrivateKey = \u0026lt;SERVER_PRIVATE_KEY\u0026gt; # 替换为生成的私钥 PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE # 客户端配置模板（每个客户端单独创建） [Peer] PublicKey = \u0026lt;CLIENT_PUBLIC_KEY\u0026gt; AllowedIPs = 10.8.0.2/32 # 客户端分配的IP 3. 客户端配置 # # 生成客户端密钥 wg genkey | tee client_private.key | wg pubkey \u0026gt; client_public.key 客户端配置文件\n[Interface] # WireGuard 接口的私钥，注意不要泄露这个私钥 PrivateKey = iF5rewTrFZSwH4iEfMOTC9Y9（不完整的私钥） # 本地客户端的 IP 地址 Address = 10.88.88.24/16 PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE [Peer] # 服务器的公钥 PublicKey = aYRjKVpcXMeSBO/+w3amiJ0stZda0FR1wzJzUlcFmSs= # 服务器的端点（IP 地址和端口） Endpoint = xxxx.com:1088 # 允许的 IP 地址范围 AllowedIPs = 10.88.0.0/16,192.168.88.0/23 PersistentKeepalive = 25 4. 关键网络配置(客户端) # # 启用IP转发 echo \u0026#34;net.ipv4.ip_forward=1\u0026#34; | sudo tee /etc/sysctl.d/99-wireguard.conf sudo sysctl -p # 防火墙规则（UFW示例） sudo ufw allow 51820/udp sudo ufw allow from 10.8.0.0/24 to any port 22 # 示例规则 连接测试 # # 查看连接状态 wg show # 测试内网访问 ping 192.168.88.100 curl http://192.168.88.200:8080 高级配置技巧 # 多客户端管理：使用 wg set 动态添加客户端 移动端支持：使用QR码快速配置（qrencode -t ansiutf8 \u0026lt; client.conf） 安全增强：结合fail2ban防止暴力破解 性能优化：启用内核加速 wg-quick save /etc/wireguard/wg0.conf 故障排查 # 服务端端口是否开放（nc -vzu \u0026lt;公网IP\u0026gt; 51820） 路由是否正确（ip route show table all） 密钥是否配对 MTU设置（可通过ping -s测试） 补充阅读 # 补充 WireGuard 访问内网时的路由、AllowedIPs 与返回路径检查方法。\n如何理解与使用 # 握手成功说明对端能够通信，访问内网还需要目标网段路由、转发与合适的返回路径；先明确哪些地址应该经过隧道。\n验证与边界 # 分别测试隧道地址、内网 IP、实际服务和域名解析，用分层结果定位问题。公私钥及内网网段需要按实际环境配置并保留恢复方式。\n","date":"2025-03-31","externalUrl":null,"permalink":"/posts/wireguard-lan/","section":"文章归档","summary":"握手成功说明对端能够通信，访问内网还需要目标网段路由、转发与合适的返回路径；先明确哪些地址应该经过隧道。","title":"WireGuard 实现内网资源访问","type":"posts"},{"content":"","date":"2025-03-31","externalUrl":null,"permalink":"/categories/%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%BB%E6%9C%BA/","section":"文章分类","summary":"","title":"服务器主机","type":"categories"},{"content":"","date":"2025-03-31","externalUrl":null,"permalink":"/categories/%E8%B7%AF%E7%94%B1%E5%99%A8/","section":"文章分类","summary":"","title":"路由器","type":"categories"},{"content":"","date":"2025-03-19","externalUrl":null,"permalink":"/tags/win10/","section":"标签","summary":"","title":"Win10","type":"tags"},{"content":" 如何在Windows 10企业版LTSC中禁止安装软件 # 前言 # 对于企业环境或需要严格管控的电脑，限制用户安装软件是常见的需求。Windows 10企业版LTSC（长期服务频道）提供了多种原生管控方式，以下是两种有效方法（支持新旧版本系统）。\n方法一：通过本地策略禁止软件安装 # 操作步骤： 1、通过快捷键“win+R”打开运行菜单。在运行窗口中，输入命令secpol.msc，然后点击确定按钮。 2、这时就会打开Windows10的本地安全策略窗口，在窗口中依次点击“安全设置/本地策略/安全选项”菜单项。 3、接下来在右侧的窗口中我们找到“用户帐户控制：标准用户的提升提示行为”设置项。 4、接下来在打开的该设置，我们点击下拉菜单，在弹出菜单中选择“自动拒绝提升请求”菜单项。 5、接下来再找到“用户帐户控制：检测应用程序安装并提示提升”设置项。 6、双击打开该设置，在窗口中我们选择“已禁用”设置项，最后点击确定按钮即可。这样该帐户以后就不能再安装应用软件了。 方法二：通过组策略禁止软件安装 # 1、通过快捷键“win+R”打开运行菜单，输入“gpedit.msc”并点击确定。 2、依次展开“计算机配置”---“管理模板”---“Windows组件”---“Windows Installer”，然后双击打开“禁止用户安装”。 3、选择启用并“隐藏用户安装”，电脑就不会自动下载乱七八糟的软件了。 补充阅读 # 补充 Windows 10 LTSC 限制软件安装的适用对象、策略验证与恢复思路。\n如何理解与使用 # 先区分标准用户与管理员，以及用户账户控制和 Windows Installer 策略；两类设置覆盖的安装路径不同。\n验证与边界 # 用标准用户分别测试需要提权的安装程序与其他允许的应用方式，再检查日志和策略结果。保留原设置，避免将局部限制描述为对所有软件都绝对有效。\n","date":"2025-03-19","externalUrl":null,"permalink":"/posts/windows-block-install/","section":"文章归档","summary":"先区分标准用户与管理员，以及用户账户控制和 Windows Installer 策略；两类设置覆盖的安装路径不同。","title":"Win10 LTSC禁止软件安装方法","type":"posts"},{"content":"","date":"2025-03-19","externalUrl":null,"permalink":"/tags/","section":"标签","summary":"","title":"标签","type":"tags"},{"content":"","date":"2025-03-19","externalUrl":null,"permalink":"/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/","section":"文章分类","summary":"","title":"操作系统","type":"categories"},{"content":"","date":"2025-03-19","externalUrl":null,"permalink":"/tags/%E7%A6%81%E6%AD%A2%E5%AE%89%E8%A3%85/","section":"标签","summary":"","title":"禁止安装","type":"tags"},{"content":" 开发背景 # 在企业IT安全管理中，部分公司会设置5分钟自动锁屏策略。频繁的密码解锁操作虽保障了安全，但影响了工作效率。为此开发本工具，核心特点：\n无需管理员权限 单文件绿色运行 系统托盘常驻 实现代码 # 系统托盘模块 (main.go) # package main import ( _ \u0026#34;embed\u0026#34; \u0026#34;fmt\u0026#34; \u0026#34;github.com/getlantern/systray\u0026#34; \u0026#34;time\u0026#34; ) //go:embed icon.ico // 必须确保存在图标文件 var iconData []byte func main() { PreventSleep() // 启动防锁屏 systray.Run(onReady, onExit) } // 托盘初始化 func onReady() { systray.SetIcon(iconData) // 设置托盘图标 systray.SetTitle(\u0026#34;Anti-Lock\u0026#34;) // 任务栏悬停显示 systray.SetTooltip(\u0026#34;运行中\u0026#34;) // 状态提示 // 创建退出菜单项 quitMenu := systray.AddMenuItem(\u0026#34;退出\u0026#34;, \u0026#34;关闭防锁屏功能\u0026#34;) // 异步监听菜单事件 go func() { \u0026lt;-quitMenu.ClickedCh systray.Quit() }() } func onExit() { fmt.Println(\u0026#34;程序已安全退出\u0026#34;) } 防锁屏核心模块 # package main import ( \u0026#34;syscall\u0026#34; ) const ( ES_CONTINUOUS = 0x80000000 // 持续生效标志 ES_SYSTEM_REQUIRED = 0x00000001 // 阻止系统休眠 ES_DISPLAY_REQUIRED = 0x00000002 // 阻止显示器关闭 ) // PreventSleep 调用Windows API实现防锁屏 func PreventSleep() { kernel32 := syscall.NewLazyDLL(\u0026#34;kernel32.dll\u0026#34;) execStateAPI := kernel32.NewProc(\u0026#34;SetThreadExecutionState\u0026#34;) // 组合控制参数 flags := uintptr(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED) ret, _, _ := execStateAPI.Call(flags) if ret == 0 { panic(\u0026#34;API调用失败\u0026#34;) } } 使用说明 # 准备图标\n将icon.ico图标文件与main.go放在同一目录\n编译命令\ngo build -ldflags=\u0026#34;-s -w -H=windowsgui\u0026#34; -o Sleep.exe 运行效果\n双击运行生成的.exe文件 系统托盘区显示图标 右键点击可退出程序 补充阅读 # 解释 Windows 防休眠 API 示例的能力边界，区分系统休眠、显示器电源与账户锁定策略。\n如何理解与使用 # 系统执行状态请求与企业账户锁定策略不是同一机制；示例不应被理解为能够覆盖所有组策略或安全限制。\n验证与边界 # 测试目标系统上的实际电源行为，并确认退出程序后恢复原来的状态；如涉及组织管理设备，应遵守适用的管理规则。\n","date":"2025-03-13","externalUrl":null,"permalink":"/posts/windows-keep-awake/","section":"文章归档","summary":"系统执行状态请求与企业账户锁定策略不是同一机制；示例不应被理解为能够覆盖所有组策略或安全限制。","title":"Windows防锁屏工具技术实现","type":"posts"},{"content":"","date":"2025-03-13","externalUrl":null,"permalink":"/categories/%E4%BB%A3%E7%A0%81%E7%BC%96%E7%A8%8B/","section":"文章分类","summary":"","title":"代码编程","type":"categories"},{"content":" 声明式锁（基于Spring AOP） # 通过自定义注解和AOP统一管理锁逻辑，类似@Transactional。\n(1) 定义锁注解 # import java.lang.annotation.*; import java.util.concurrent.TimeUnit; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface ConcurrentLock { /** * 锁的Key（支持SpEL表达式，如 #orderId） */ String key() default \u0026#34;\u0026#34;; /** * 获取锁超时时间 */ long timeout() default 5; /** * 时间单位 */ TimeUnit timeUnit() default TimeUnit.SECONDS; } (2) 实现AOP切面 # import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @Aspect @Component public class LockAspect { // 使用可重入锁（实际项目中可替换为分布式锁） private final Lock lock = new ReentrantLock(); // SpEL表达式解析器 private final ExpressionParser parser = new SpelExpressionParser(); @Around(\u0026#34;@annotation(concurrentLock)\u0026#34;) public Object around(ProceedingJoinPoint joinPoint, ConcurrentLock concurrentLock) throws Throwable { String lockKey = resolveLockKey(joinPoint, concurrentLock); try { // 尝试获取锁（带超时） if (lock.tryLock(concurrentLock.timeout(), concurrentLock.timeUnit())) { return joinPoint.proceed(); } else { throw new RuntimeException(\u0026#34;[\u0026#34; + lockKey + \u0026#34;] Acquire lock failed after \u0026#34; + concurrentLock.timeout() + \u0026#34; \u0026#34; + concurrentLock.timeUnit()); } } finally { if (((ReentrantLock) lock).isHeldByCurrentThread()) { lock.unlock(); } } } /** * 解析锁的Key（支持SpEL表达式） */ private String resolveLockKey(ProceedingJoinPoint joinPoint, ConcurrentLock concurrentLock) { // 获取方法参数名和值 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Object[] args = joinPoint.getArgs(); String[] paramNames = signature.getParameterNames(); // 创建评估上下文 StandardEvaluationContext context = new StandardEvaluationContext(); for (int i = 0; i \u0026lt; args.length; i++) { context.setVariable(paramNames[i], args[i]); } // 解析SpEL表达式 Expression expression = parser.parseExpression(concurrentLock.key()); String dynamicKey = expression.getValue(context, String.class); return method.getDeclaringClass().getName() + \u0026#34;:\u0026#34; + method.getName() + \u0026#34;:\u0026#34; + dynamicKey; } } (3) 在Service中使用 # @Service public class OrderService { // 使用SpEL动态生成锁Key @ConcurrentLock(key = \u0026#34;\u0026#39;order:\u0026#39; + #orderId\u0026#34;, timeout = 3) public void processOrder(String orderId, int quantity) { // 需要同步的业务逻辑 System.out.println(\u0026#34;Processing order: \u0026#34; + orderId); } // 静态Key示例 @ConcurrentLock(key = \u0026#34;GLOBAL_CONFIG_LOCK\u0026#34;) public void updateGlobalConfig() { // 全局配置更新 } } 关键实现说明 # SpEL动态Key解析： # 使用StandardEvaluationContext绑定方法参数 支持形如#orderId的表达式，自动替换为实际参数值 示例方法processOrder生成的Key：com.example.OrderService:processOrder:order:123 锁管理增强： # 检查当前线程是否持有锁后再释放（避免IllegalMonitorStateException） 支持自定义超时时间和时间单位 完整的异常处理流程 扩展建议： # // 若要升级为分布式锁，只需替换Lock实现： @Autowired private RedissonClient redissonClient; private Lock getDistributedLock(String lockKey) { return redissonClient.getLock(lockKey); } 性能优化： # 添加@ConditionalOnProperty控制锁功能的开关 添加@Order注解控制切面执行顺序 添加监控埋点记录锁竞争耗时 补充阅读 # 补充 Spring AOP 声明式锁的作用范围，区分单进程并发控制与多实例协调。\n如何理解与使用 # 锁注解和 SpEL 键只定义调用意图，实际互斥范围取决于锁实现和键生成规则；需要检查调用是否经过代理。\n验证与边界 # 验证同键并发、不同键并发、业务异常和超时后的释放。若服务部署多个实例，应明确是否需要共享锁服务，不能直接把本地锁称为分布式锁。\n","date":"2025-03-13","externalUrl":null,"permalink":"/posts/spring-aop-lock/","section":"文章归档","summary":"锁注解和 SpEL 键只定义调用意图，实际互斥范围取决于锁实现和键生成规则；需要检查调用是否经过代理。","title":"Spring自定义Aop实现锁机制","type":"posts"},{"content":"","date":"2024-12-22","externalUrl":null,"permalink":"/tags/linux/","section":"标签","summary":"","title":"Linux","type":"tags"},{"content":" 1.结合rustdesk官方的compose加入api # version: \u0026#39;3\u0026#39; networks: rustdesk-net: external: false services: hbbs: container_name: hbbs ports: - 21115:21115 - 21116:21116 - 21116:21116/udp - 21118:21118 image: rustdesk/rustdesk-server:latest command: hbbs -r 公网IP:21117 -k 你的自定义密钥 volumes: - ./data/hbbs:/root networks: - rustdesk-net depends_on: - hbbr restart: unless-stopped hbbr: container_name: hbbr ports: - 21117:21117 - 21119:21119 image: rustdesk/rustdesk-server:latest command: hbbr -k 你的自定义密钥 volumes: - ./data/hbbr:/root networks: - rustdesk-net restart: unless-stopped rustdesk-api: container_name: rustdesk-api environment: - RUSTDESK_API_RUSTDESK_ID_SERVER=公网IP:21116 - RUSTDESK_API_RUSTDESK_RELAY_SERVER=公网IP:21117 - RUSTDESK_API_RUSTDESK_API_SERVER=http://公网IP:21114 - RUSTDESK_API_RUSTDESK_KEY=你的自定义密钥 ports: - 21114:21114 image: lejianwen/rustdesk-api volumes: - ./data/api:/app/data #将数据库挂载出来方便备份 networks: - rustdesk-net restart: unless-stopped 2.公网访问管理 # http://公网IP:21114 默认账号admin 默认密码admin\n3.最终效果 # 注意： 如果想用https，则自行搭建nginx或者nginx-proxy-manager反向代理到http://公网IP:21114 即可。（推荐走https） 补充阅读 # 说明 RustDesk Compose 中注册、中继与管理组件的分工，以及客户端连接的验收范围。\n如何理解与使用 # 先明确各容器与端口用途，并确认持久化目录保存了需要的密钥和状态；服务端密钥应与客户端使用的值对应。\n验证与边界 # 分别测试注册、直连失败后的中继以及重建后的身份保持。原文管理界面和默认账号属于当时附加组件，不能当作所有官方版本的默认能力。\n","date":"2024-12-22","externalUrl":null,"permalink":"/posts/rustdesk-compose/","section":"文章归档","summary":"先明确各容器与端口用途，并确认持久化目录保存了需要的密钥和状态；服务端密钥应与客户端使用的值对应。","title":"Linux下用docker-compose自建RustDesk远程控制服务器","type":"posts"},{"content":"","date":"2024-12-22","externalUrl":null,"permalink":"/tags/rustdesk/","section":"标签","summary":"","title":"Rustdesk","type":"tags"},{"content":"","date":"2024-12-22","externalUrl":null,"permalink":"/categories/%E5%88%86%E4%BA%AB%E5%8F%91%E7%8E%B0/","section":"文章分类","summary":"","title":"分享发现","type":"categories"},{"content":"","date":"2024-12-22","externalUrl":null,"permalink":"/tags/%E8%BF%9C%E7%A8%8B/","section":"标签","summary":"","title":"远程","type":"tags"},{"content":"","date":"2024-12-22","externalUrl":null,"permalink":"/tags/%E4%B8%AD%E7%BB%A7/","section":"标签","summary":"","title":"中继","type":"tags"},{"content":"","date":"2024-12-22","externalUrl":null,"permalink":"/tags/%E8%87%AA%E5%BB%BAid%E6%9C%8D%E5%8A%A1%E5%99%A8/","section":"标签","summary":"","title":"自建id服务器","type":"tags"},{"content":"","date":"2024-12-12","externalUrl":null,"permalink":"/tags/nacos/","section":"标签","summary":"","title":"Nacos","type":"tags"},{"content":"","date":"2024-12-12","externalUrl":null,"permalink":"/tags/refreshscope/","section":"标签","summary":"","title":"RefreshScope","type":"tags"},{"content":"","date":"2024-12-12","externalUrl":null,"permalink":"/tags/spring/","section":"标签","summary":"","title":"Spring","type":"tags"},{"content":"通过自定义注解 @NacosJsonConfig 自动加载 Nacos 中的 JSON 配置文件，并将其注入到指定的配置类字段中，你可以通过以下步骤实现：\n1. 自定义注解 @NacosJsonConfig # 首先，定义注解 @NacosJsonConfig 来标记需要从 Nacos 中加载 JSON 配置的字段。该注解的两个参数分别是 dataId（配置文件标识）和 group（配置组，默认为 DEFAULT_GROUP）。\nimport java.lang.annotation.*; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface NacosJsonConfig { String dataId(); // Nacos 中的 dataId String group() default \u0026#34;DEFAULT_GROUP\u0026#34;; } 2. 创建自定义处理逻辑 # 接下来，你需要创建一个自定义的处理器，负责在应用启动时从 Nacos 中读取指定的 JSON 配置文件，并将其解析后注入到配置类的字段中。你可以使用 BeanPostProcessor 或 InitializingBean 来实现此功能。\nimport cn.hutool.json.JSONUtil; import com.alibaba.cloud.nacos.NacosConfigManager; import com.alibaba.nacos.api.config.listener.Listener; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; import java.lang.reflect.Field; import java.util.concurrent.Executor; @Slf4j @Component public class NacosJsonConfigProcessor implements BeanPostProcessor { private final NacosConfigManager nacosConfigManager; public NacosJsonConfigProcessor(NacosConfigManager nacosConfigManager) { this.nacosConfigManager = nacosConfigManager; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { Field[] fields = bean.getClass().getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(NacosJsonConfig.class)) { NacosJsonConfig annotation = field.getAnnotation(NacosJsonConfig.class); String dataId = annotation.dataId(); String group = annotation.group(); try { // 加载初始配置并注入 String config = nacosConfigManager.getConfigService().getConfig(dataId, group, 3000); injectConfig(bean, field, config); // 注册监听器，配置更新后重新注入 nacosConfigManager.getConfigService().addListener(dataId, group, new Listener() { @Override public Executor getExecutor() { return null; } @Override public void receiveConfigInfo(String configInfo) { // 配置更新时动态注入 try { log.info(\u0026#34;重新载入配置文件：{}\u0026#34;, dataId); injectConfig(bean, field, configInfo); } catch (Exception e) { log.error(\u0026#34;配置文件载入失败：{}\u0026#34;, e.getMessage(), e); } } }); } catch (Exception e) { throw new BeansException(\u0026#34;Failed to load config from Nacos\u0026#34;, e) { }; } } } return bean; } /** * 注入配置到字段 * * @param bean 目标对象 * @param field 目标字段 * @param config 配置内容 */ private void injectConfig(Object bean, Field field, String config) throws IllegalAccessException { if (config != null) { Object value = null; if (JSONUtil.isTypeJSONArray(config)) { value=JSONUtil.toBean(config, field.getGenericType(),true); }else { value=JSONUtil.toBean(config, field.getType()); } field.setAccessible(true); field.set(bean, value); } } } 3. 配置 Nacos 服务 # 在 application.yml 中配置 Nacos 服务器地址：\nspring: cloud: nacos: config: server-addr: 127.0.0.1:8848 4. 使用自定义注解的配置类 # 在配置类中，通过 @NacosJsonConfig 注解指定需要加载的 Nacos JSON 配置文件的 dataId 和 group。\n@Data @Component public class AppConfig{ @NacosJsonConfig(dataId = \u0026#34;test1.json\u0026#34;) private List\u0026lt;Test1\u0026gt; test1Config; @NacosJsonConfig(dataId = \u0026#34;test2.json\u0026#34;) private List\u0026lt;Test2\u0026gt; test2Config; } 补充阅读 # 解释 Spring Boot 读取 Nacos JSON 配置并自动刷新的生命周期与并发检查点。\n如何理解与使用 # 启动加载和后续监听回调是两个阶段，应确认首次配置缺失、解析失败和更新触发时分别如何处理。\n验证与边界 # 测试合法变更与非法 JSON，确认回调线程中的更新可被业务线程一致读取；配置对象已经变更不代表所有依赖它的缓存或连接都同步刷新。\n","date":"2024-12-12","externalUrl":null,"permalink":"/posts/nacos-config-refresh/","section":"文章归档","summary":"启动加载和后续监听回调是两个阶段，应确认首次配置缺失、解析失败和更新触发时分别如何处理。","title":"Springboot实现读取Nacos中指定的配置文件并实现自动刷新","type":"posts"},{"content":"","date":"2024-12-12","externalUrl":null,"permalink":"/tags/springcloud/","section":"标签","summary":"","title":"Springcloud","type":"tags"},{"content":"","date":"2024-12-12","externalUrl":null,"permalink":"/tags/%E8%87%AA%E5%8A%A8%E5%88%B7%E6%96%B0/","section":"标签","summary":"","title":"自动刷新","type":"tags"},{"content":"","date":"2024-12-12","externalUrl":null,"permalink":"/tags/redis/","section":"标签","summary":"","title":"Redis","type":"tags"},{"content":"","date":"2024-12-12","externalUrl":null,"permalink":"/tags/%E7%A9%BF%E9%80%8F/","section":"标签","summary":"","title":"穿透","type":"tags"},{"content":"","date":"2024-12-12","externalUrl":null,"permalink":"/tags/%E7%BC%93%E5%AD%98/","section":"标签","summary":"","title":"缓存","type":"tags"},{"content":" 缓存穿透 # 缓存穿透说简单点就是大量请求的 key 是不合理的，根本不存在于缓存中，也不存在于数据库中 。这就导致这些请求直接到了数据库上，根本没有经过缓存这一层，对数据库造成了巨大的压力，可能直接就被这么多请求弄宕机了。\n举个例子：某个黑客故意制造一些非法的 key 发起大量请求，导致大量请求落到数据库，结果数据库上也没有查到对应的数据。也就是说这些请求最终都落到了数据库上，对数据库造成了巨大的压力。\n有哪些解决办法？ # 最基本的就是首先做好参数校验，一些不合法的参数请求直接抛出异常信息返回给客户端。比如查询的数据库 id 不能小于 0、传入的邮箱格式不对的时候直接返回错误消息给客户端等等。\n1）缓存无效 key\n如果缓存和数据库都查不到某个 key 的数据就写一个到 Redis 中去并设置过期时间，具体命令如下：SET key value EX 10086 。这种方式可以解决请求的 key 变化不频繁的情况，如果黑客恶意攻击，每次构建不同的请求 key，会导致 Redis 中缓存大量无效的 key 。很明显，这种方案并不能从根本上解决此问题。如果非要用这种方式来解决穿透问题的话，尽量将无效的 key 的过期时间设置短一点比如 1 分钟。\n2）布隆过滤器\n布隆过滤器是一个非常神奇的数据结构，通过它我们可以非常方便地判断一个给定数据是否存在于海量数据中。我们可以把它看作由二进制向量（或者说位数组）和一系列随机映射函数（哈希函数）两部分组成的数据结构。相比于我们平时常用的 List、Map、Set 等数据结构，它占用空间更少并且效率更高，但是缺点是其返回的结果是概率性的，而不是非常准确的。理论情况下添加到集合中的元素越多，误报的可能性就越大。并且，存放在布隆过滤器的数据不容易删除。\nBloom Filter 会使用一个较大的 bit 数组来保存所有的数据，数组中的每个元素都只占用 1 bit ，并且每个元素只能是 0 或者 1（代表 false 或者 true），这也是 Bloom Filter 节省内存的核心所在。这样来算的话，申请一个 100w 个元素的位数组只占用 1000000Bit / 8 = 125000 Byte = 125000/1024 KB ≈ 122KB 的空间。\n缓存击穿 # 缓存击穿中，请求的 key 对应的是 热点数据 ，该数据 存在于数据库中，但不存在于缓存中（通常是因为缓存中的那份数据已经过期） 。这就可能会导致瞬时大量的请求直接打到了数据库上，对数据库造成了巨大的压力，可能直接就被这么多请求弄宕机了。\n举个例子：秒杀进行过程中，缓存中的某个秒杀商品的数据突然过期，这就导致瞬时大量对该商品的请求直接落到数据库上，对数据库造成了巨大的压力。\n有哪些解决办法？ # 设置热点数据永不过期或者过期时间比较长。 针对热点数据提前预热，将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。 请求数据库写数据到缓存之前，先获取互斥锁，保证只有一个请求会落到数据库上，减少数据库的压力。 缓存穿透和缓存击穿有什么区别？ # 缓存穿透中，请求的 key 既不存在于缓存中，也不存在于数据库中。\n缓存击穿中，请求的 key 对应的是 热点数据 ，该数据 存在于数据库中，但不存在于缓存中（通常是因为缓存中的那份数据已经过期） 。\n缓存雪崩 # 实际上，缓存雪崩描述的就是这样一个简单的场景：缓存在同一时间大面积的失效，导致大量的请求都直接落到了数据库上，对数据库造成了巨大的压力。 这就好比雪崩一样，摧枯拉朽之势，数据库的压力可想而知，可能直接就被这么多请求弄宕机了。\n举个例子：数据库中的大量数据在同一时间过期，这个时候突然有大量的请求需要访问这些过期的数据。这就导致大量的请求直接落到数据库上，对数据库造成了巨大的压力。\n有哪些解决办法？ # 针对 Redis 服务不可用的情况：\n采用 Redis 集群，避免单机出现问题整个缓存服务都没办法使用。 限流，避免同时处理大量的请求。 多级缓存，例如本地缓存+Redis 缓存的组合，当 Redis 缓存出现问题时，还可以从本地缓存中获取到部分数据。 针对热点缓存失效的情况： # 设置不同的失效时间比如随机设置缓存的失效时间。 缓存永不失效（不太推荐，实用性太差）。 缓存预热，也就是在程序启动后或运行过程中，主动将热点数据加载到缓存中。 缓存预热如何实现？ # 常见的缓存预热方式有两种：\n使用定时任务，比如 xxl-job，来定时触发缓存预热的逻辑，将数据库中的热点数据查询出来并存入缓存中。 使用消息队列，比如 Kafka，来异步地进行缓存预热，将数据库中的热点数据的主键或者 ID 发送到消息队列中，然后由缓存服务消费消息队列中的数据，根据主键或者 ID 查询数据库并更新缓存。 缓存雪崩和缓存击穿有什么区别？ # 缓存雪崩和缓存击穿比较像，但缓存雪崩导致的原因是缓存中的大量或者所有数据失效，缓存击穿导致的原因主要是某个热点数据不存在与缓存中（通常是因为缓存中的那份数据已经过期）。\n补充阅读 # 用请求来源和失效范围区分缓存穿透、击穿与雪崩，并补充方案选择的验证方法。\n如何理解与使用 # 先判断访问的是不存在的数据、单个热点过期，还是大量键或整个缓存服务失效，再选择参数校验、空值缓存、互斥重建或降级等措施。\n验证与边界 # 记录缓存命中率、后端请求量、重建耗时及错误比例，模拟对应故障验证。引入锁、布隆过滤器或过期扰动后，还需处理误判、失败与恢复路径。\n","date":"2024-12-12","externalUrl":null,"permalink":"/posts/cache-failures/","section":"文章归档","summary":"先判断访问的是不存在的数据、单个热点过期，还是大量键或整个缓存服务失效，再选择参数校验、空值缓存、互斥重建或降级等措施。","title":"缓存穿透，缓存击穿，缓存雪崩出现的原因及解决方案","type":"posts"},{"content":"","date":"2024-12-12","externalUrl":null,"permalink":"/tags/%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF/","section":"标签","summary":"","title":"缓存击穿","type":"tags"},{"content":"","date":"2024-12-12","externalUrl":null,"permalink":"/tags/%E9%9B%AA%E5%B4%A9/","section":"标签","summary":"","title":"雪崩","type":"tags"},{"content":" 购买和部署 # 下载alpine镜像(也可以用其它系统，但是得低于1GB 开通oss对象储存，创建 Bucket,地区选择 华北6 (乌兰察布) 进入刚上传的Bucket，上传文件，点扫描文件，把刚下载的文件上传，再点击分享，此时链接已复制至剪贴板 进入ecs的镜像，地区选择华北6(乌兰察布) 点击右上角导入镜像，下一步，镜像文件URL这里直接粘贴刚刚复制的链接，镜像名称随意，操作系统类型linux,操作系统版本others linux,系统架构64位，接着勾选云盘配置，配置云盘属性，大小选择1G，随后创建。\n地区选择华北6(乌兰察布)、架构共享型、突发性能实例 t6：ecs.t6-c4m1.arge、镜像选自定义镜像、刷新，选择你刚刚创建的、系统盘选essd云盘，然后手动输入1G、带宽计费模式选CDT(每月免费20G出站流量)、带宽选80MBPS、随后创建密钥对，下载私钥，选择刚刚创建的密钥 右下角购买时间改成五年，确认下单，支付后点续费，再续费四年，刚好差不多用完300元券，获得9年的阿里云 （非学生 自费300元9年服务器） 创建完成后删除OSS中自己上传的文件与镜像中创建的自定义镜像，防止扣费\n使用 # 使用xshell或putty连接到你的ecs，用户名alpine，密钥为你刚才下载的私钥 alpine使用了doas代替sudo，进入root：soas -s 初始化系统:doas setup-alpine\n更新源 # sed -i \u0026#39;s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g\u0026#39; /etc/apk/repositories 补充阅读 # 保留早期阿里云 ECS 购买与导入镜像记录，补充活动价格与初始化过程的核对方法。\n如何理解与使用 # 九年成本、代金券和流量规则来自当时条件，不能作为当前可购买方案。重新操作应先核对地域、实例与计费选项。\n验证与边界 # 镜像导入和实例创建分别验证，登录后核对系统版本与磁盘容量；Alpine 提权命令应核对为 doas，原文的 soas 是笔误。\n","date":"2024-12-11","externalUrl":null,"permalink":"/posts/aliyun-ecs-notes/","section":"文章归档","summary":"九年成本、代金券和流量规则来自当时条件，不能作为当前可购买方案。重新操作应先核对地域、实例与计费选项。","title":"Aliyun九年ECS","type":"posts"},{"content":"","date":"2024-12-11","externalUrl":null,"permalink":"/categories/linux/","section":"文章分类","summary":"","title":"Linux","type":"categories"},{"content":"","date":"2024-11-19","externalUrl":null,"permalink":"/tags/k3s/","section":"标签","summary":"","title":"K3s","type":"tags"},{"content":" 配置镜像加速 # # 添加配置 $ cat \u0026gt;\u0026gt; /etc/rancher/k3s/registries.yaml \u0026lt;\u0026lt;EOF mirrors: \u0026#34;docker.io\u0026#34;: endpoint: - \u0026#34;https://fogjl973.mirror.aliyuncs.com\u0026#34; - \u0026#34;https://registry-1.docker.io\u0026#34; EOF # 重启服务 $ sudo systemctl restart k3s # 是否生效 $ sudo crictl info | grep -A 2 \u0026#34;endpoint\u0026#34; 国内安装： # curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn INSTALL_K3S_EXEC=\u0026#34;--tls-san 1.1.1.1(改成你的公网IP)\u0026#34; INSTALL_K3S_EXEC=\u0026#34;--docker\u0026#34; sh - 在安装 k3s 之前，你可以创建一个名为 config.yaml 的文件，其中包含与 CLI 标志相匹配的字段。该文件位于：/etc/rancher/k3s/config.yaml，K3s 在启动后会加载这个文件中的配置选项。\nwrite-kubeconfig-mode: 644 token: \u0026#34;secret\u0026#34; node-ip: 10.0.10.22 cluster-cidr: 10.42.0.0/16 service-cidr: 10.43.0.0/16 安装纪要 # 1、开启服务\nsystemctl start k3s 2、查看当前集群镜像\ncrictl images list 3、查看当前集群容器状态\ncrictl ps 4、查看当前集群所有服务\nkubectl get services --all-namespaces 5、查看当前集群某个命名空间的服务\nkubectl get services -n default 6、查看集群所有pod\nkubectl get pods --all-namespaces 7、查看集群某个命名空间pod\nkubectl get pods -n default 8、查看pod所在节点\nkubectl get pods --all-namespaces -o wide 9、设置镜像加速\n# 添加镜像库，无认证 vim /etc/rancher/k3s/registries.yaml mirrors: cr.l5d.io: endpoint: - \u0026#34;https://l5d.m.daocloud.io\u0026#34; docker.elastic.co: endpoint: - \u0026#34;https://elastic.m.daocloud.io\u0026#34; docker.io: endpoint: - \u0026#34;https://docker.m.daocloud.io\u0026#34; gcr.io: endpoint: - \u0026#34;https://gcr.m.daocloud.io\u0026#34; ghcr.io: endpoint: - \u0026#34;https://ghcr.m.daocloud.io\u0026#34; k8s.gcr.io: endpoint: - \u0026#34;https://k8s-gcr.m.daocloud.io\u0026#34; registry.k8s.io: endpoint: - \u0026#34;https://k8s.m.daocloud.io\u0026#34; mcr.microsoft.com: endpoint: - \u0026#34;https://mcr.m.daocloud.io\u0026#34; nvcr.io: endpoint: - \u0026#34;https://nvcr.m.daocloud.io\u0026#34; quay.io: endpoint: - \u0026#34;https://quay.m.daocloud.io\u0026#34; registry.jujucharms.com: endpoint: - \u0026#34;https://jujucharms.m.daocloud.io\u0026#34; rocks.canonical.com: endpoint: - \u0026#34;https://rocks-canonical.m.daocloud.io\u0026#34; 10、安装指定连接IP(把示例IP改成机器外网IP即可)\n通常错误：Unable to connect to the server: x509: certificate signed by unknown authority\n/etc/rancher/k3s/config.yaml write-kubeconfig-mode: \u0026#34;0644\u0026#34; tls-san: - \u0026#34;111.111.111.111\u0026#34; 11、释放80和443端口\nk3s默认会安装traefik来替代k8s的ingress来代理流量，此时默认情况会占据系统的 80 和 443 端口。\n因为通过iptables来转发流量所以lsof不会找到该应用，因为接管80/443端口的是service而不是traefik这个pod\n如果不想被占用的话需要修改配置以释放这两个端口。\n在配置中禁用参考配置\n/etc/rancher/k3s/k3s.yaml:\ndisable: - traefik 12、kube-explorer\nkube-explorer 是 K8S 的便携式资源管理器，没有任何依赖 并提供了一个几乎完全无状态的 K8S 资源管理器 # 从发布页面下载二进制文件 # https://github.com/cnrancher/kube-explorer # 运行 # --kubeconfig 可以不配置(自己可以找到) $ ./kube-explorer --kubeconfig=/etc/rancher/k3s/kube.yaml \\ --http-listen-port=9898 \\ --https-listen-port=0 # 打开浏览器访问 http://192.168.100.100:9898 13、K3s环境下如何启用traefik的dashboard\n配置 # 在master机器上添加文件/var/lib/rancher/k3s/server/manifests/traefik-config.yaml，内容如下:\napiVersion: helm.cattle.io/v1 kind: HelmChartConfig metadata: name: traefik namespace: kube-system spec: valuesContent: |- dashboard: enabled: true ports: traefik: expose: true logs: access: enabled: true 添加完成之后，K3s会自动生效，且重启K3s集群也不会被恢复默认设置。\n访问方式 # 直接访问http://{master_node_ip}:9000/dashboard/ 在kube-system命名空间添加一个Ingress，绑定域名，指向traefik服务的9000端口，然后就可以正常在浏览器使用绑定的域名打开了 补充阅读 # 整理 k3s 安装记录的阅读顺序，区分服务配置、客户端凭据和附加组件设置。\n如何理解与使用 # config.yaml 用于服务启动配置，客户端 kubeconfig 用于访问集群，二者不应混为同一文件；修改哪一个取决于实际目标。\n验证与边界 # 先确认服务和节点 Ready，再验证 Pod、Service 与入口流量。镜像加速、证书和 Traefik 等内容应按实际版本逐项检查，避免一次改动多个环节。\n","date":"2024-11-19","externalUrl":null,"permalink":"/posts/k3s-install/","section":"文章归档","summary":"config.yaml 用于服务启动配置，客户端 kubeconfig 用于访问集群，二者不应混为同一文件；修改哪一个取决于实际目标。","title":"k3s安装部署记录","type":"posts"},{"content":"","date":"2024-11-19","externalUrl":null,"permalink":"/tags/k8s/","section":"标签","summary":"","title":"K8s","type":"tags"},{"content":"","date":"2024-11-19","externalUrl":null,"permalink":"/tags/%E5%AE%B9%E5%99%A8/","section":"标签","summary":"","title":"容器","type":"tags"},{"content":"","date":"2024-11-11","externalUrl":null,"permalink":"/tags/adguardhome/","section":"标签","summary":"","title":"Adguardhome","type":"tags"},{"content":"因家里部署了K3S，借助K8S的安全，在K8S部署adguardhome过滤广告。由于我家里的K3S只有单机，故部署脚本如下：\n在单机 Kubernetes 环境中，可以将 AdGuard 配置调整为使用本地存储，以便数据可以在容器重启或主机重启后仍然保留。以下是改进的 YAML 配置，添加了对本地存储的支持。\nadguard-deployment-local.yaml # apiVersion: apps/v1 kind: Deployment metadata: name: adguard namespace: mmgg spec: replicas: 1 selector: matchLabels: app: adguard strategy: type: Recreate template: metadata: labels: app: adguard spec: hostNetwork: true dnsPolicy: ClusterFirstWithHostNet containers: - name: adguard image: adguard/adguardhome:latest ports: - name: web containerPort: 3000 - name: web2 containerPort: 3100 - name: dns containerPort: 53 protocol: UDP - name: dns-tcp containerPort: 53 protocol: TCP volumeMounts: - name: adguard-config mountPath: /opt/adguardhome/work - name: adguard-data mountPath: /opt/adguardhome/conf resources: requests: memory: \u0026#34;256Mi\u0026#34; cpu: \u0026#34;100m\u0026#34; limits: memory: \u0026#34;512Mi\u0026#34; cpu: \u0026#34;500m\u0026#34; volumes: - name: adguard-config hostPath: path: /root/adguard/work type: DirectoryOrCreate - name: adguard-data hostPath: path: /root/adguard/conf type: DirectoryOrCreate 主要特点 # 使用 hostPath 实现本地存储： 配置文件和数据存储路径分别为 /root/adguard/work 和 /root/adguard/conf。 Kubernetes 将这两个路径映射到容器中的 /opt/adguardhome/work 和 /opt/adguardhome/conf。 type: DirectoryOrCreate：如果目录不存在，会自动创建。 资源限制： 为 AdGuard 设置了合理的 CPU 和内存请求与限制，以确保单机环境稳定。 添加 hostNetwork: true。 Pod 会共享宿主机的 IP 地址，并使用宿主机的网络接口。 设置 dnsPolicy: ClusterFirstWithHostNet，以确保 Pod 能解析集群内的 DNS。 部署与测试 # 应用配置：\nkubectl apply -f adguard-deployment-local.yaml 检查本地存储内容：\n配置和数据将保存在 /root/adguard/work 和 /root/adguard/conf 中。 可以直接检查这些目录来确认文件是否正确存储。 注意事项 # 权限问题： 确保 Kubernetes 节点的 /root/adguard 目录有合适的权限，容器内用户可以读写。 由于是共享宿主主机的IP来暴露服务，故重启策略需要改成删除重建 Recreate ，而不是滚动更新 补充阅读 # 补充 Kubernetes AdGuard Home 部署的 DNS 端口、节点网络与持久化验证方法。\n如何理解与使用 # 使用宿主网络时，应确认目标节点上相关端口没有冲突，并保证配置目录与运行用户权限相符。\n验证与边界 # 测试 DNS 查询和管理界面两个入口，再重建 Pod 检查配置保留。调整 DNS 服务前应保留可用的解析回退路径。\n","date":"2024-11-11","externalUrl":null,"permalink":"/posts/k8s-adguard/","section":"文章归档","summary":"使用宿主网络时，应确认目标节点上相关端口没有冲突，并保证配置目录与运行用户权限相符。","title":"K8S部署adguardhome","type":"posts"},{"content":"","date":"2024-11-11","externalUrl":null,"permalink":"/tags/%E8%BF%87%E6%BB%A4%E5%B9%BF%E5%91%8A/","section":"标签","summary":"","title":"过滤广告","type":"tags"},{"content":"","date":"2024-11-11","externalUrl":null,"permalink":"/categories/%E5%AE%B9%E5%99%A8/","section":"文章分类","summary":"","title":"容器","type":"categories"},{"content":" 配置文件nacos-config.yaml # 使用的是外部 mysql 数据库，所以没有使用官方提供的 mysql 和存储方案。\n--- apiVersion: v1 data: MODE: cluster MYSQL_SERVICE_DB_NAME: nacos_db MYSQL_SERVICE_HOST: 172.16.0.163 MYSQL_SERVICE_PASSWORD: MySQL密码 MYSQL_SERVICE_PORT: \u0026#39;3306\u0026#39; MYSQL_SERVICE_USER: nacos NACOS_APPLICATION_PORT: \u0026#39;8848\u0026#39; NACOS_AUTH_ENABLE: \u0026#39;true\u0026#39; NACOS_AUTH_IDENTITY_KEY: nacosAuthKey NACOS_AUTH_IDENTITY_VALUE: nacosSecurtyValue NACOS_AUTH_TOKEN: YjI5YTIwNDkwMGUxZmY5NjNlZTU5ZWFjMjlhZTc4OTU4YTVjNjUxOQ== #这里的token需要base64编码，且长度不低于32个字符，一般用个字符做sha1然后base64 NACOS_AUTH_TOKEN_EXPIRE_SECONDS: \u0026#39;18000\u0026#39; NACOS_REPLICAS: \u0026#39;3\u0026#39; NACOS_SERVERS: \u0026gt;- nacos-0.nacos-headless.default.svc.cluster.local:8848 nacos-1.nacos-headless.default.svc.cluster.local:8848 nacos-2.nacos-headless.default.svc.cluster.local:8848 NACOS_SERVER_PORT: \u0026#39;8848\u0026#39; PREFER_HOST_MODE: hostname SPRING_DATASOURCE_PLATFORM: mysql kind: ConfigMap metadata: name: nacos-server-config namespace: default 部署文件nacos-deploy.yaml # ###使用自建数据库；使用Ingress发布配置后台### --- apiVersion: v1 kind: Service metadata: name: nacos-headless labels: app: nacos-headless spec: type: ClusterIP clusterIP: None ports: - port: 8848 name: server targetPort: 8848 - port: 9848 name: client-rpc targetPort: 9848 - port: 9849 name: raft-rpc targetPort: 9849 ## 兼容1.4.x版本的选举端口 - port: 7848 name: old-raft-rpc targetPort: 7848 selector: app: nacos --- apiVersion: apps/v1 kind: StatefulSet metadata: name: nacos spec: serviceName: nacos-headless replicas: 3 template: metadata: labels: app: nacos annotations: pod.alpha.kubernetes.io/initialized: \u0026#34;true\u0026#34; spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: \u0026#34;app\u0026#34; operator: In values: - nacos topologyKey: \u0026#34;kubernetes.io/hostname\u0026#34; containers: - name: nacos imagePullPolicy: Always image: registry.cn-shenzhen.aliyuncs.com/mmgg/nacos-server:v2.3.2 resources: requests: memory: \u0026#34;2Gi\u0026#34; cpu: \u0026#34;500m\u0026#34; ports: - containerPort: 8848 name: client - containerPort: 9848 name: client-rpc - containerPort: 9849 name: raft-rpc - containerPort: 7848 name: old-raft-rpc envFrom: - configMapRef: name: nacos-server-config selector: matchLabels: app: nacos --- # ------------------- App Ingress ------------------- # apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nacos-headless spec: rules: - host: nacos.k8s.znl.net http: paths: - path: /nacos pathType: Prefix backend: service: name: nacos-headless port: name: server 补充阅读 # 说明 Kubernetes 三节点 Nacos 配置中，外部 MySQL、节点发现与持久化依赖。\n如何理解与使用 # 节点数只是部署形态，先确认实例如何互相发现、连接哪套数据库、各端口承担什么功能。示例地址与认证参数需要按真实环境替换。\n验证与边界 # 验证每个节点健康、实例之间的成员状态与客户端访问，再检查节点重建后的配置数据。三个 Pod 都运行并不自动证明集群功能完整。\n","date":"2024-10-14","externalUrl":null,"permalink":"/posts/k8s-nacos/","section":"文章归档","summary":"节点数只是部署形态，先确认实例如何互相发现、连接哪套数据库、各端口承担什么功能。示例地址与认证参数需要按真实环境替换。","title":"k8s部署3节点Naocs集群","type":"posts"},{"content":"","date":"2024-10-14","externalUrl":null,"permalink":"/tags/%E9%9B%86%E7%BE%A4/","section":"标签","summary":"","title":"集群","type":"tags"},{"content":"","date":"2024-06-21","externalUrl":null,"permalink":"/tags/oauth2/","section":"标签","summary":"","title":"Oauth2","type":"tags"},{"content":"","date":"2024-06-21","externalUrl":null,"permalink":"/tags/security/","section":"标签","summary":"","title":"Security","type":"tags"},{"content":"记录一下代码： OAuth2ClientTest.java\n@Slf4j @Component public class OAuth2ClientTest implements InitializingBean { @Autowired private ClientRegistrationRepository clientRegistrationRepository; @Autowired private OAuth2AccessTokenResponseClient\u0026lt;OAuth2AuthorizationCodeGrantRequest\u0026gt; accessTokenResponseClient; public OAuth2AccessTokenResponse getAccessToken(String authorizationCode) { ClientRegistration renaultClient = clientRegistrationRepository.findByRegistrationId(\u0026#34;demo\u0026#34;); String code=PKCEUtil.generateCodeVerifier(); Map\u0026lt;String,Object\u0026gt; params= Maps.newHashMap(); //如果用了PKCE，则记得删除client_secret params.put(PkceParameterNames.CODE_CHALLENGE,PKCEUtil.generateCodeChallenge(code)); params.put(PkceParameterNames.CODE_VERIFIER,code); params.put(PkceParameterNames.CODE_CHALLENGE_METHOD,\u0026#34;S256\u0026#34;); OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() .clientId(renaultClient.getClientId()) .authorizationUri(renaultClient.getProviderDetails().getAuthorizationUri()) .redirectUri(renaultClient.getRedirectUri()) .attributes(params) .build(); OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponse.success(authorizationCode) .redirectUri(renaultClient.getRedirectUri()) .build(); OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse); OAuth2AuthorizationCodeGrantRequest grantRequest = new OAuth2AuthorizationCodeGrantRequest(renaultClient, authorizationExchange); log.info(JSONUtil.toJsonStr(grantRequest)); return accessTokenResponseClient.getTokenResponse(grantRequest); } @Override public void afterPropertiesSet() throws Exception { //示例code，实际应该是auth server返回的 getAccessToken(\u0026#34;abc\u0026#34;); } } PKCEUtil.java\npublic class PKCEUtil { private static final SecureRandom SECURE_RANDOM = new SecureRandom(); public static String generateCodeVerifier() { byte[] codeVerifier = new byte[32]; SECURE_RANDOM.nextBytes(codeVerifier); return Base64.encodeBase64URLSafeString(codeVerifier); } public static String generateCodeChallenge(String codeVerifier) { byte[] digest = DigestUtils.sha256(codeVerifier); return Base64.encodeBase64URLSafeString(digest); } } 补充阅读 # 补充 OAuth2 授权码换取令牌流程的上下文，说明重定向地址、PKCE 与错误验证。\n如何理解与使用 # 授权码需要与相应客户端、回调地址及授权上下文匹配，PKCE 的校验值必须来自同一次授权流程。\n验证与边界 # 分别测试正常回调、错误 verifier、重复使用和超时。客户端密钥及令牌应留在可信处理范围，日志不要输出完整凭据。\n","date":"2024-06-21","externalUrl":null,"permalink":"/posts/oauth2-code-token/","section":"文章归档","summary":"授权码需要与相应客户端、回调地址及授权上下文匹配，PKCE 的校验值必须来自同一次授权流程。","title":"Spring OAuth2 Client通过code获取AccessToken","type":"posts"},{"content":"代码如下：\npublic class MachineCodeUtil { public static void main(String[] args) { SystemInfo systemInfo = new SystemInfo(); HardwareAbstractionLayer hal = systemInfo.getHardware(); String cpuSerial = getCpuSerial(hal.getProcessor()); System.out.println(\u0026#34;CPU序列号：\u0026#34; + cpuSerial); String diskSerial = getDiskSerial(systemInfo); System.out.println(\u0026#34;磁盘序列号：\u0026#34; + diskSerial); String motherboardSerial = getMotherboardSerial(hal.getComputerSystem()); System.out.println(\u0026#34;主板序列号：\u0026#34; + motherboardSerial); String memorySerial = getMemorySerial(hal.getMemory()); System.out.println(\u0026#34;内存大小：\u0026#34; + memorySerial); String combinedInfo = cpuSerial + diskSerial + motherboardSerial + memorySerial; String machineCode = SecureUtil.sha256(combinedInfo); System.out.println(\u0026#34;Unique Machine Code: \u0026#34; + machineCode); } /** * CPU序列号 * @param processor * @return */ private static String getCpuSerial(CentralProcessor processor) { return processor.getProcessorIdentifier().getProcessorID(); } /** * 操作系统所在磁盘的驱动器UUID * @param si * @return */ private static String getDiskSerial(SystemInfo si) { String systemDrive = System.getenv(\u0026#34;SystemDrive\u0026#34;) + File.separator; StringBuilder serials = new StringBuilder(); List\u0026lt;OSFileStore\u0026gt; stores = si.getOperatingSystem().getFileSystem().getFileStores(); for (OSFileStore store : stores) { if (systemDrive.equals(store.getMount())) { serials.append(store.getUUID()); break; } } return serials.toString().trim(); } /** * 主板序列号 * @param computerSystem * @return */ private static String getMotherboardSerial(ComputerSystem computerSystem) { return computerSystem.getBaseboard().getSerialNumber(); } /** * 内存总大小 * @param memory * @return */ private static String getMemorySerial(GlobalMemory memory) { return String.valueOf(memory.getTotal()); } } 补充阅读 # 解释 Java 硬件信息生成机器标识的组成，补充稳定性、空值与隐私检查。\n如何理解与使用 # 示例组合处理器、磁盘和主板信息，实际可读取字段受硬件、权限与虚拟化环境影响；有些设备可能缺少序列号。\n验证与边界 # 测试设备重启、硬件更换和虚拟机复制后的结果。硬件指纹不能自动保证全球唯一，也不适合作为秘密凭据，应尽量减少暴露原始标识。\n","date":"2024-06-06","externalUrl":null,"permalink":"/posts/java-machine-id/","section":"文章归档","summary":"示例组合处理器、磁盘和主板信息，实际可读取字段受硬件、权限与虚拟化环境影响；有些设备可能缺少序列号。","title":"Java根据硬件信息生成唯一机器码","type":"posts"},{"content":" 表达式全集 # 字符 描述 \\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如，“n”匹配字符“n”。“\\n”匹配一个换行符。串行“\\\\”匹配“\\”而“\\(”则匹配“(”。 ^ 匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性，^也匹配“\\n”或“\\r”之后的位置。 $ 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性，$也匹配“\\n”或“\\r”之前的位置。 * 匹配前面的子表达式零次或多次。例如，zo*能匹配“z”以及“zoo”。*等价于{0,}。 + 匹配前面的子表达式一次或多次。例如，“zo+”能匹配“zo”以及“zoo”，但不能匹配“z”。+等价于{1,}。 ? 匹配前面的子表达式零次或一次。例如，“do(es)?”可以匹配“does”或“does”中的“do”。?等价于{0,1}。 {n} n是一个非负整数。匹配确定的n次。例如，“o{2}”不能匹配“Bob”中的“o”，但是能匹配“food”中的两个o。 {n,} n是一个非负整数。至少匹配n次。例如，“o{2,}”不能匹配“Bob”中的“o”，但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。 {n,m} m和n均为非负整数，其中n\u0026lt;=m。最少匹配n次且最多匹配m次。例如，“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。 ? 当该字符紧跟在任何一个其他限制符（*,+,?，{n}，{n,}，{n,m}）后面时，匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串，而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如，对于字符串“oooo”，“o+?”将匹配单个“o”，而“o+”将匹配所有“o”。 . 匹配除“\\n”之外的任何单个字符。要匹配包括“\\n”在内的任何字符，请使用像“(.|\\n)”的模式。 (pattern) 匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到，在VBScript中使用SubMatches集合，在JScript中则使用$0…$9属性。要匹配圆括号字符，请使用“\\(”或“\\)”。 (?:pattern) 匹配pattern但不获取匹配结果，也就是说这是一个非获取匹配，不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。 (?=pattern) 正向肯定预查，在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后使用。例如，“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”，但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之后开始。 (?!pattern) 正向否定预查，在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”，但不能匹配“Windows2000”中的“Windows”。预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之后开始 (?\u0026lt;=pattern) 反向肯定预查，与正向肯定预查类拟，只是方向相反。例如，“(?\u0026lt;=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”，但不能匹配“3.1Windows”中的“Windows”。 (?\u0026lt;!pattern) 反向否定预查，与正向否定预查类拟，只是方向相反。例如“(?\u0026lt;!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”，但不能匹配“2000Windows”中的“Windows”。 x|y 匹配x或y。例如，“z|food”能匹配“z”或“food”。“(z|f)ood”则匹配“zood”或“food”。 [xyz] 字符集合。匹配所包含的任意一个字符。例如，“[abc]”可以匹配“plain”中的“a”。 [^xyz] 负值字符集合。匹配未包含的任意字符。例如，“[^abc]”可以匹配“plain”中的“p”。 [a-z] 字符范围。匹配指定范围内的任意字符。例如，“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。 [^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如，“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。 \\b 匹配一个单词边界，也就是指单词和空格间的位置。例如，“er\\b”可以匹配“never”中的“er”，但不能匹配“verb”中的“er”。 \\B 匹配非单词边界。“er\\B”能匹配“verb”中的“er”，但不能匹配“never”中的“er”。 \\cx 匹配由x指明的控制字符。例如，\\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则，将c视为一个原义的“c”字符。 \\d 匹配一个数字字符。等价于[0-9]。 \\D 匹配一个非数字字符。等价于[^0-9]。 \\f 匹配一个换页符。等价于\\x0c和\\cL。 \\n 匹配一个换行符。等价于\\x0a和\\cJ。 \\r 匹配一个回车符。等价于\\x0d和\\cM。 \\s 匹配任何空白字符，包括空格、制表符、换页符等等。等价于[ \\f\\n\\r\\t\\v]。 \\S 匹配任何非空白字符。等价于[^ \\f\\n\\r\\t\\v]。 \\t 匹配一个制表符。等价于\\x09和\\cI。 \\v 匹配一个垂直制表符。等价于\\x0b和\\cK。 \\w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。 \\W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。 \\xn 匹配n，其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如，“\\x41”匹配“A”。“\\x041”则等价于“\\x04\u0026amp;1”。正则表达式中可以使用ASCII编码。. \\num 匹配num，其中num是一个正整数。对所获取的匹配的引用。例如，“(.)\\1”匹配两个连续的相同字符。 \\n 标识一个八进制转义值或一个向后引用。如果\\n之前至少n个获取的子表达式，则n为向后引用。否则，如果n为八进制数字（0-7），则n为一个八进制转义值。 \\nm 标识一个八进制转义值或一个向后引用。如果\\nm之前至少有nm个获得子表达式，则nm为向后引用。如果\\nm之前至少有n个获取，则n为一个后跟文字m的向后引用。如果前面的条件都不满足，若n和m均为八进制数字（0-7），则\\nm将匹配八进制转义值nm。 \\nml 如果n为八进制数字（0-3），且m和l均为八进制数字（0-7），则匹配八进制转义值nml。 \\un 匹配n，其中n是一个用四个十六进制数字表示的Unicode字符。例如，\\u00A9匹配版权符号（©）。 常用正则表达式 # 用户名 /^[a-z0-9_-]{3,16}$/ 密码 /^[a-z0-9_-]{6,18}$/ 十六进制值 /^#?([a-f0-9]{6}|[a-f0-9]{3})$/ 电子邮箱 /^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$/ /^[a-z\\d]+(\\.[a-z\\d]+)*@([\\da-z](-[\\da-z])?)+(\\.{1,2}[a-z]+)+$/ URL /^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$/ IP 地址 /((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)/ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ HTML 标签 /^\u0026lt;([a-z]+)([^\u0026lt;]+)*(?:\u0026gt;(.*)\u0026lt;\\/\\1\u0026gt;|\\s+\\/\u0026gt;)$/ 删除代码\\\\注释 (?\u0026lt;!http:|\\S)//.*$ Unicode编码中的汉字范围 /^[\\u2E80-\\u9FFF]+$/ ","date":"2024-04-29","externalUrl":null,"permalink":"/regexp/","section":"正能量","summary":"保留原有表达式说明和常用匹配示例，按表格查阅正则语法。","title":"正则表达式全集","type":"page"},{"content":"跳过强制使用Microsoft登录的限制：\n方法：使用OOBE命令来安装，自从2022年9月底发布了Windows 11 22H2版本后，全新安装系统时再也无法使用本地账户登录了。以前的做法是断网就可以跳过强制使用Microsoft登录的限制，但新版本会提示要联网才能继续安装。\n在没有网络连接的情况下，“下一步”按钮是灰色不可点击的。这时候，按下 Shift + F10 键打开命令提示符（使用笔记本的朋友如果无法打开命令提示符，可以按 Fn + Shift + F10）。\n出现命令提示符后，输入“oobe\\bypassnro”，然后按回车键。当按下回车键后，计算机会重新启动。\n重新启动后，将回到设置国家区域的界面，然后继续Windows 11的设置过程。这时在网络界面上终于出现了“我没有 Internet 连接”的选项，点击进入。\n接下来，点击“继续进行有限设置”。当看到“输入你的姓名”时，恭喜你学会了一种在安装系统时不使用Microsoft账户登录的技巧。\n补充阅读 # 说明 Windows 11 安装时本地账户处理记录的适用版本与验证范围。\n如何理解与使用 # 原文针对当时的 OOBE 流程；系统构建、发行渠道和安装介质变化后，界面与命令行为都可能不同。\n验证与边界 # 尝试前确认所用版本与恢复方式，安装完成后检查账户类型、网络和更新状态。本篇没有验证所有后续 Windows 版本都能使用旧方法。\n","date":"2024-03-07","externalUrl":null,"permalink":"/posts/windows-local-account/","section":"文章归档","summary":"原文针对当时的 OOBE 流程；系统构建、发行渠道和安装介质变化后，界面与命令行为都可能不同。","title":"Win11 跳过联网登陆","type":"posts"},{"content":" Debian 下载站 # debian官方默认只提供最新的版本下载，有时需要找一些旧的版本的debian，着实费用。下面这个debian iso镜像站可以下载各个版本的debian下载：debian 系统各个版本ISO下载\nhttp://cdimage.debian.org/cdimage/archive/\nLinuxMirrors一键脚本更换Linux系统源 # LinuxMirrors：为您提供快速下载和安装Linux镜像的选择\n开源地址：\nhttps://github.com/SuperManito/LinuxMirrors https://linuxmirrors.cn/\nLinuxMirrors是一个非盈利的开源项目，旨在为计算机相关行业的朋友们提供便利。它提供了各种Linux发行版的软件源镜像，涵盖了Debian、Ubuntu、Kali Linux、Deepin、Red Hat Enterprise Linux、Fedora、CentOS、Rocky Linux、AlmaLinux、OpenCloudOS、openEuler、openSUSE、Arch Linux和Alpine Linux等。使用LinuxMirrors的软件源可以加速软件的下载和更新，让用户能够更快地获取和安装所需的Linux操作系统。\n使用方法：\n中国大陆（默认） # bash \u0026lt;(curl -sSL https://linuxmirrors.cn/main.sh) 开源中国\nbash \u0026lt;(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh) 中国大陆（教育网） # bash \u0026lt;(curl -sSL https://linuxmirrors.cn/main.sh) --edu 开源中国\nbash \u0026lt;(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh) --edu 海外 # bash \u0026lt;(curl -sSL https://linuxmirrors.cn/main.sh) --abroad 开源中国\nbash \u0026lt;(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh) --abroad 补充阅读 # 说明 Linux 下载与换源链接的分类，帮助区分系统安装镜像、旧版本归档和软件仓库。\n如何理解与使用 # 需要重装系统时找安装镜像，需要日常软件更新时配置包仓库，二者不能相互替代。旧版本归档适合复现历史环境。\n验证与边界 # 第三方换源脚本执行前应查看支持范围与修改内容，保留原软件源配置；下载镜像后还应按发布方信息检查完整性。\n","date":"2024-02-08","externalUrl":null,"permalink":"/posts/linux-downloads/","section":"文章归档","summary":"需要重装系统时找安装镜像，需要日常软件更新时配置包仓库，二者不能相互替代。旧版本归档适合复现历史环境。","title":"网址备忘","type":"posts"},{"content":"","date":"2024-01-30","externalUrl":null,"permalink":"/tags/aria/","section":"标签","summary":"","title":"Aria","type":"tags"},{"content":"","date":"2024-01-30","externalUrl":null,"permalink":"/tags/ariang/","section":"标签","summary":"","title":"Ariang","type":"tags"},{"content":"","date":"2024-01-30","externalUrl":null,"permalink":"/tags/bt/","section":"标签","summary":"","title":"Bt","type":"tags"},{"content":"1、拉取AriaNG镜像并运行-\nHOST模式\ndocker run -d \\ --name aria2-pro \\ --restart unless-stopped \\ --log-opt max-size=1m \\ --network host \\ -e PUID=$UID \\ -e PGID=$GID \\ -e RPC_SECRET=\u0026lt;TOKEN\u0026gt; \\ -e RPC_PORT=6800 \\ -e LISTEN_PORT=6888 \\ -v $PWD/aria2-config:/config \\ -v $PWD/aria2-downloads:/downloads \\ p3terx/aria2-pro bridge 模式\ndocker run -d \\ --name aria2-pro \\ --restart unless-stopped \\ --log-opt max-size=1m \\ -e PUID=$UID \\ -e PGID=$GID \\ -e RPC_SECRET=\u0026lt;TOKEN\u0026gt; \\ -e RPC_PORT=6800 \\ -p 6800:6800 \\ -e LISTEN_PORT=6888 \\ -p 6888:6888 \\ -p 6888:6888/udp \\ -v ~/aria2-config:/config \\ -v ~/aria2-downloads:/downloads \\ p3terx/aria2-pro bridge 网络模式下如果需要自定义端口，建议映射到宿主机相同的端口，避免混淆和功能异常。\n2、拉取AriaNg 并运行【可选】\ndocker run -d \\ --name AiraNg \\ --log-opt max-size=1m \\ --restart=always \\ -p 16880:6880 \\ p3terx/ariang:latest 如果你不需要自己的AriaNG，这可以用第三方的，以下是公共的第三方AriaNG地址\nhttps://ariang.js.org/ 【推荐】 3、一键API设置\nAriaNg 提供了一个名为命令行 API 的功能，这使得我们可以通过 URL 请求的方式去一键设置 RPC 信息，而不必每次换浏览器和设备都重复手动设置。最新的 Aria2 一键安装管理脚本 增强版中所生成的 AriaNg 一键直达链接就是使用的这个功能。\nAPI RPC 设置语法：\n/#!/settings/rpc/set/${protocol}/${rpcHost}/${rpcPort}/${rpcInterface}/${secret} ${protocol} 为连接协议. 可以使用http、https、ws或wss。 ${rpcHost} 为 Aria2 RPC 的主机。可以使用 IP 或域名。 ${rpcPort} 为 Aria2 RPC 的端口。 ${rpcInterface} 为 Aria2 RPC 的路径，默认为jsonrpc。 ${secret} 为使用 URL 安全的base64编码后的 RPC 密钥，可选。 举个例子，假设使用 http://ariang.js.org 这个 Ar­i­aNg 页面，连接协议使用 ws，主机 IP 为 233.233.233.233，端口为 6800，RPC 路径使用默认的 jsonrpc，RPC 密钥为 P3TERX。\n在终端中通过 base64 编码 RPC 密钥（或者也可以使用在线编码工具）：\n$ echo -n \u0026#34;P3TERX\u0026#34; | base64 # 输入命令 UDNURVJY # 编码结果 综合以上信息可以如下的链接：\nhttp://ariang.js.org/#!/settings/rpc/set/ws/233.233.233.233/6800/jsonrpc/UDNURVJY\n将配置好的链接保存到浏览器书签，可以方便的同步到不同的设备直接进行访问。\n4、 开源网址\nhttps://p3terx.com/archives/docker-aria2-pro.html\n补充阅读 # 说明 aria2 与 AriaNG 的角色划分，补充 RPC 连接、目录权限与网络模式检查。\n如何理解与使用 # aria2 执行下载任务，AriaNG 提供管理界面；页面能打开不代表它已连接到正确的 RPC 服务。\n验证与边界 # 核对 RPC 地址、密钥、端口映射和下载目录权限，再提交一个有权下载的测试文件。host 与 bridge 模式的网络行为应分别验证。\n","date":"2024-01-30","externalUrl":null,"permalink":"/posts/aria2-ariang/","section":"文章归档","summary":"aria2 执行下载任务，AriaNG 提供管理界面；页面能打开不代表它已连接到正确的 RPC 服务。","title":"Docker安装aria2+AriaNG","type":"posts"},{"content":"","date":"2024-01-30","externalUrl":null,"permalink":"/tags/pt/","section":"标签","summary":"","title":"Pt","type":"tags"},{"content":"","date":"2024-01-30","externalUrl":null,"permalink":"/tags/%E4%B8%8B%E8%BD%BD/","section":"标签","summary":"","title":"下载","type":"tags"},{"content":"","date":"2024-01-02","externalUrl":null,"permalink":"/tags/netstat/","section":"标签","summary":"","title":"Netstat","type":"tags"},{"content":"","date":"2024-01-02","externalUrl":null,"permalink":"/tags/ss/","section":"标签","summary":"","title":"Ss","type":"tags"},{"content":"","date":"2024-01-02","externalUrl":null,"permalink":"/tags/ssh/","section":"标签","summary":"","title":"Ssh","type":"tags"},{"content":"在Linux系统下，你可以使用netstat和ss命令来查看当前的TCP连接。以下是一些相关的命令：\n使用netstat命令： netstat -an | grep tcp 这条命令会列出所有的TCP连接，包括本地地址和端口、远程地址和端口以及连接状态等信息。\n使用ss命令： ss -t 这条命令会列出所有的TCP连接，包括本地地址和端口、远程地址和端口以及连接状态等信息。ss命令相比netstat更为现代化，性能更好。\n注意：在最新的Linux系统中，netstat命令已经被标记为过时（deprecated），推荐使用ss命令来代替。\n如果你想持续监控当前的TCP连接情况，你可以使用watch命令结合ss或netstat。watch命令可以定期执行某个命令并显示结果，提供了一种实时监控的方式。\n以下是使用watch和ss的示例：\nwatch -n 1 \u0026#39;ss -t\u0026#39; 这个命令每隔1秒执行一次ss -t，显示当前的TCP连接信息。\n上述命令将每秒刷新一次当前的TCP连接状态。你可以根据需要调整监控的时间间隔，例如，将-n 1中的数字改为其他秒数。按下Ctrl+C可以停止命令的执行。\n补充阅读 # 解释 ss 连接查看命令的过滤目标与输出含义，区分监听、已建立连接和进程信息。\n如何理解与使用 # 读结果时先确认协议、连接状态及本地和远端地址，过滤条件不同会让同一台机器呈现不同视图。\n验证与边界 # 结合进程信息和服务日志确认连接归属；权限不足可能影响进程显示。没有列出某条连接并不等于过去从未建立过连接。\n","date":"2024-01-02","externalUrl":null,"permalink":"/posts/ss-connections/","section":"文章归档","summary":"读结果时先确认协议、连接状态及本地和远端地址，过滤条件不同会让同一台机器呈现不同视图。","title":"记录一个查看当前TCP和UDP连接的命令ss","type":"posts"},{"content":"","date":"2024-01-02","externalUrl":null,"permalink":"/categories/%E6%9C%AA%E5%88%86%E7%B1%BB/","section":"文章分类","summary":"","title":"未分类","type":"categories"},{"content":"","date":"2023-12-27","externalUrl":null,"permalink":"/tags/ossutil/","section":"标签","summary":"","title":"Ossutil","type":"tags"},{"content":"","date":"2023-12-27","externalUrl":null,"permalink":"/tags/shell/","section":"标签","summary":"","title":"Shell","type":"tags"},{"content":"","date":"2023-12-27","externalUrl":null,"permalink":"/tags/%E5%A4%87%E4%BB%BD/","section":"标签","summary":"","title":"备份","type":"tags"},{"content":"","date":"2023-12-27","externalUrl":null,"permalink":"/tags/%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0/","section":"标签","summary":"","title":"文件上传","type":"tags"},{"content":" 缘由 # 经常要备份linux上的文件，直接复制和下载有时候不是很方便，即使下载下来了，也可能由于一些原因给忘记保存到相对安全的磁盘上。故写一个脚本来实现备份。\n脚本 # #!/bin/bash # 阿里云 OSS 相关配置 ACCESS_KEY=\u0026#34;\u0026lt;YourAccessKey\u0026gt;\u0026#34; SECRET_KEY=\u0026#34;\u0026lt;YourSecretKey\u0026gt;\u0026#34; ENDPOINT=\u0026#34;\u0026lt;YourEndpoint\u0026gt;\u0026#34; BUCKET=\u0026#34;\u0026lt;YourBucket\u0026gt;\u0026#34; # 检查命令行参数 if [ \u0026#34;$#\u0026#34; -ne 2 ]; then echo \u0026#34;Usage: $0 source_file target_file\u0026#34; exit 1 fi # 获取待上传的文件路径和目标文件路径 SOURCE=$1 TARGET=$2 # 检查是否已安装 ossutil if ! command -v ossutil64 \u0026amp;\u0026gt; /dev/null; then echo \u0026#34;ossutil not found, downloading...\u0026#34; # 下载 ossutil64，此处最好替换成自己的ossutil地址，文件去阿里云官网找 wget -O ossutil64 https://demo.znl.net/ossutil64 # 赋予执行权限 chmod +x ossutil64 # 移动到系统路径 sudo mv ossutil64 /usr/local/bin/ossutil64 fi # 使用 ossutil 配置 ossutil64 config --access-key-id $ACCESS_KEY --access-key-secret $SECRET_KEY --endpoint $ENDPOINT # 执行 ossutil 命令 ossutil64 cp -r $SOURCE oss://$BUCKET/$TARGET 使用方式 # bash \u0026lt;(curl -s https://file.znl.net/jiaoben.sh) /path/to/source/file /path/to/target/file 效果 # Succeed: Total num: 1, size: 163,480,502. OK num: 1(upload 1 files). average speed 11756000(byte/s) 13.906585(s) elapsed root@C20230915182797:~/.halo# bash \u0026lt;(curl -s https://demo.znl.net/ossutil.sh) ./file-backup-20231227.zip file/file-backup-20231227.zip cp: overwrite \u0026#34;oss://mmgg/file/file-backup-20231227.zip\u0026#34;(y or N)? y Succeed: Total num: 1, size: 163,480,502. OK num: 1(upload 1 files). average speed 9181000(byte/s) 17.806552(s) elapsed 注意事项 # jiaoben.sh需上传到自己的web服务器上，这样每次只需要按这个命令去执行就可以自动备份了。 OssUtil需要时间同步，如果当前linux机器的时间不正确，可能会有以下错误：\nretry count:9,multipart upload file:file-backup-20231227.zip. Total num: 1, size: 163,480,502. Dealed num: 0, Transfer size: 0. When error happens. average speed 0(byte/s) Total num: 1, size: 163,480,502. Dealed num: 1(Error 1 files), OK size: 0, Progress: 0.000%, Speed: 0.00KB/sError: oss: service returned error: StatusCode=403, ErrorCode=RequestTimeTooSkewed, ErrorMessage=\u0026#34;The difference between the request time and the current time is too large.\u0026#34;, RequestId=658BA4164F7BC43236D9A708, Ec=0002-00000504, File=file-backup-20231227.zip 遇到此情况，请自行通过ntpdate同步时间即可。\n补充阅读 # 补充 ossutil 备份脚本的参数、凭据与恢复验证说明，区分上传成功和备份可用。\n如何理解与使用 # 源文件、目标对象名、端点和 Bucket 共同决定数据放在哪里；示例凭据需要由本机私有配置提供，不能写进公开文章或版本库。\n验证与边界 # 上传后核对对象大小和完整性，并抽样下载恢复。脚本提示成功只能说明该次上传完成，不能替代保留周期与恢复演练。\n","date":"2023-12-27","externalUrl":null,"permalink":"/posts/oss-backup-script/","section":"文章归档","summary":"源文件、目标对象名、端点和 Bucket 共同决定数据放在哪里；示例凭据需要由本机私有配置提供，不能写进公开文章或版本库。","title":"写一个ossutil的工具脚本","type":"posts"},{"content":" 1、下面提供了四个 mirror 地址，您可以去掉其中任意一个地址的注释，以使用该 mirror 地址。 # # Docker中国 mirror # export REGISTRY_MIRROR=\u0026#34;https://registry.docker-cn.com\u0026#34; # 腾讯云 docker hub mirror # export REGISTRY_MIRROR=\u0026#34;https://mirror.ccs.tencentyun.com\u0026#34; # 华为云镜像 # export REGISTRY_MIRROR=\u0026#34;https://05f073ad3c0010ea0f4bc00b7105ec20.mirror.swr.myhuaweicloud.com\u0026#34; # DaoCloud 镜像 # export REGISTRY_MIRROR=\u0026#34;http://f1361db2.m.daocloud.io\u0026#34; # 阿里云 docker hub mirror export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com curl -sSL https://kuboard.cn/install-script/set_mirror.sh | sh -s ${REGISTRY_MIRROR} systemctl restart kubelet # 假设您安装了 kubenetes 2、查看修改结果 # docker info ... Docker Root Dir: /var/lib/docker Debug Mode (client): false Debug Mode (server): false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Registry Mirrors: https://registry.cn-hangzhou.aliyuncs.com Live Restore Enabled: false Product License: Community Engine 补充阅读 # 说明 Docker registry mirror 配置与 Kubernetes 容器运行时的关系。\n如何理解与使用 # 原文使用 Docker 的镜像设置和诊断命令；如果节点实际使用其他运行时，这些配置不一定参与镜像拉取。\n验证与边界 # 先识别节点运行时，再检查对应镜像源配置与一次真实拉取；不能仅通过重启 kubelet 推断所有节点已经切换。\n","date":"2023-12-20","externalUrl":null,"permalink":"/posts/docker-registry-mirror/","section":"文章归档","summary":"原文使用 Docker 的镜像设置和诊断命令；如果节点实际使用其他运行时，这些配置不一定参与镜像拉取。","title":"修改镜像仓库 mirror 地址","type":"posts"},{"content":"默认启动时是spring-boot的字体,可以定制Banner\n1.登录一下网站定制自己的Banner: # http://patorjk.com/software/taag\n2.放入文件resource/banner.txt 中即可 # 建议选择：big,Doh,Doom\n3.效果如下： # 补充阅读 # 补充 Spring Boot 启动 Banner 的配置用途，并说明控制台展示与应用状态的区别。\n如何理解与使用 # Banner 只影响启动时的展示内容，可用于说明项目或版本；它出现并不代表依赖连接、端口监听和业务初始化全部完成。\n验证与边界 # 检查资源文件位置与当前环境的展示设置，再分别观察日志和健康检查，避免把一段启动文字当作服务验收证据。\n","date":"2023-11-07","externalUrl":null,"permalink":"/posts/spring-boot-banner/","section":"文章归档","summary":"Banner 只影响启动时的展示内容，可用于说明项目或版本；它出现并不代表依赖连接、端口监听和业务初始化全部完成。","title":"修改Springboot启动的LOGO","type":"posts"},{"content":"","date":"2023-10-26","externalUrl":null,"permalink":"/tags/configmap/","section":"标签","summary":"","title":"Configmap","type":"tags"},{"content":"在K8S中配置数据库的配置文件\napiVersion: v1 data: mysql.db.name: nacos mysql.host: [mysql连接地址] mysql.password: [mysql密码] mysql.port: \u0026#39;3306\u0026#39; mysql.user: [mysql账号] kind: ConfigMap metadata: name: [配置文件名称] namespace: [命名空间] 补充阅读 # 解释 Kubernetes MySQL 连接配置示例中，ConfigMap、命名空间和敏感字段的处理边界。\n如何理解与使用 # 示例记录配置项的名称与引用方式，需要与应用读取的键完全对应，并确认对象和工作负载处于可访问的命名空间。\n验证与边界 # 数据库密码不宜按普通配置公开保存；应将敏感项独立管理。Kubernetes Secret 也不等于默认加密保险箱，还需结合访问控制与存储保护。\n参考：Kubernetes Secret（本次补充核对）。\n","date":"2023-10-26","externalUrl":null,"permalink":"/posts/k8s-mysql-config/","section":"文章归档","summary":"示例记录配置项的名称与引用方式，需要与应用读取的键完全对应，并确认对象和工作负载处于可访问的命名空间。","title":"k8s中创建MySQL配置文件","type":"posts"},{"content":"","date":"2023-10-19","externalUrl":null,"permalink":"/tags/openfeign/","section":"标签","summary":"","title":"Openfeign","type":"tags"},{"content":" 问题描述 # 在项目使用open feign过程中，我曾经在gateway中去调用其他服务的时候，发现经常性有fallback的情况发生，然后报了503后，就没下文了。。。，很显然是fallback未生效。\n解决方案 # 前提：我使用了Spring Cloud Alibaba全家桶\n添加依赖\n\u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;com.alibaba.cloud\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-cloud-starter-alibaba-sentinel\u0026lt;/artifactId\u0026gt; \u0026lt;/dependency\u0026gt; 修改或者添加bootstrap.yml\nfeign: sentinel: enabled: true 补充阅读 # 说明 Spring Cloud Alibaba 与 Sentinel 场景下 Feign fallback 未触发的检查顺序。\n如何理解与使用 # 原文依赖特定组件组合和版本，先确认引入的依赖、启用配置与客户端 fallback 声明是否一致。\n验证与边界 # 分别模拟连接失败、超时和业务错误观察回调路径；不要假定所有错误都会自动进入同一回退分支，参数名还需与实际版本对应。\n","date":"2023-10-19","externalUrl":null,"permalink":"/posts/feign-fallback/","section":"文章归档","summary":"原文依赖特定组件组合和版本，先确认引入的依赖、启用配置与客户端 fallback 声明是否一致。","title":"Spring Open Feign远程调用后，fallback回调无效的解决方案","type":"posts"},{"content":"","date":"2023-10-19","externalUrl":null,"permalink":"/tags/springcloudalibaba/","section":"标签","summary":"","title":"Springcloudalibaba","type":"tags"},{"content":"","date":"2023-10-19","externalUrl":null,"permalink":"/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/","section":"标签","summary":"","title":"微服务","type":"tags"},{"content":"","date":"2023-10-12","externalUrl":null,"permalink":"/tags/webp/","section":"标签","summary":"","title":"Webp","type":"tags"},{"content":" 简介 # WebP 是一种新型的图片格式，可以为网站上的图片提供卓越的无损和有损压缩。使用 WebP，网站站长和 Web 开发者可以制作更小、更丰富的图片，从而提升网页加载速度。\nWebP 无损图片的大小比 PNG 图片小 26% 。WebP 有损图片比采用等效 SSIM 质量索引的同类 JPEG 图片缩小 25-34% 。\n无损 WebP 支持透明度（也称为 Alpha 通道），费用仅为 22% 的额外字节。在可以接受有损 RGB 压缩的情况下，有损 WebP 也支持透明度，其提供的文件大小通常比 PNG 小 3 倍。\n动画 WebP 图片均支持有损、无损和透明度，与 GIF 和 APNG 相比，这种格式可以减小文件大小。\ncwebp 是 Google 官方的开源命令后工具，支持将 PNG、JPEG 等格式的图片转换为 WebP。\n安装 # 在 Mac 下，可以使用 brew install webp 安装。\n转换 # 转换的方式也很简单，使用默认配置：\ncwebp znl_log.png -o znl_log.webp 可用参数 # https://developers.google.com/speed/webp/docs/cwebp?hl=zh-cn\n批量转换脚本 # #!/bin/bash # 检查参数是否正确 if [ $# -ne 3 ]; then echo \u0026#34;Usage: $0 \u0026lt;input_path\u0026gt; \u0026lt;output_path\u0026gt; \u0026lt;quality\u0026gt;\u0026#34; exit 1 fi # 获取参数 input_path=$1 output_path=$2 quality=$3 # 创建输出目录（如果不存在） mkdir -p $output_path # 查找所有符合条件的图片文件 find $input_path -type f \\( -iname \\*.jpg -o -iname \\*.jpeg -o -iname \\*.png \\) -print0 | while IFS= read -r -d \u0026#39;\u0026#39; file do # 构建输出路径 rel_path=${file#$input_path} out_file=\u0026#34;$output_path$rel_path\u0026#34; out_dir=$(dirname \u0026#34;$out_file\u0026#34;) # 创建目录结构 mkdir -p \u0026#34;$out_dir\u0026#34; # 转换图片 cwebp -q $quality -quiet \u0026#34;$file\u0026#34; -o \u0026#34;$out_file\u0026#34; echo \u0026#34;Converted $file to $out_file\u0026#34; done 脚本使用方式 # 将上述脚本保存为一个 .sh 文件，比如 convert_images.sh。 给脚本文件执行权限：chmod +x convert_images.sh。 运行脚本，指定输入路径、输出路径和质量参数。例如： ./convert_images.sh /path/to/input/images/ /path/to/output/images/ 80 这个脚本会遍历输入路径下的所有图片文件（以.jpg、.jpeg和.png结尾的文件），将它们转换为webp格式，并保持相同的目录结构到输出路径下。\n补充阅读 # 解释批量转换 WebP 脚本的输入范围、输出文件与图片效果验证方法。\n如何理解与使用 # 批处理前明确扫描目录、支持格式和同名文件处理方式；主观清晰度、透明通道与输出体积都需要观察。\n验证与边界 # 先选几张照片、截图和透明图片试转，比较画质和大小后再批量执行。完成后检查原图是否保留，以及网页是否实际引用了新文件。\n","date":"2023-10-12","externalUrl":null,"permalink":"/posts/images-to-webp/","section":"文章归档","summary":"批处理前明确扫描目录、支持格式和同名文件处理方式；主观清晰度、透明通道与输出体积都需要观察。","title":"通过shell脚本批量转换所有图片为webp格式","type":"posts"},{"content":"","date":"2023-10-12","externalUrl":null,"permalink":"/tags/%E5%9B%BE%E7%89%87%E8%BD%AC%E6%8D%A2/","section":"标签","summary":"","title":"图片转换","type":"tags"},{"content":"","date":"2023-10-08","externalUrl":null,"permalink":"/tags/go/","section":"标签","summary":"","title":"Go","type":"tags"},{"content":"","date":"2023-10-08","externalUrl":null,"permalink":"/tags/micro/","section":"标签","summary":"","title":"Micro","type":"tags"},{"content":"","date":"2023-10-08","externalUrl":null,"permalink":"/tags/vim/","section":"标签","summary":"","title":"Vim","type":"tags"},{"content":"","date":"2023-10-08","externalUrl":null,"permalink":"/tags/%E7%BC%96%E8%BE%91%E5%99%A8/","section":"标签","summary":"","title":"编辑器","type":"tags"},{"content":" 简介 # Micro 是一个使用 Go 语言开发的现代的基于终端的开源文本编辑器，它试图摆脱键盘快捷键的痛苦，并提供流行的快捷键以及鼠标支持。\n特性 # Micro 编辑器的一些主要亮点有：\n易于使用和安装。\n不需要依赖或外部文件。\n多光标支持。\n支持通用键盘快捷键（Ctrl-s, Ctrl-c, Ctrl-v, Ctrl-z, ...）。\n智能的默认值。\n拆分和选项卡。\n类似 nano 的菜单，帮助你记住键盘快捷键。\n极好的鼠标支持：这意味着鼠标拖动可以创建一个选择，双击可以按字选择，三击可以按行选择。\n跨平台（它应该能在所有 Go 运行的平台上工作）。\n插件系统（插件是用 Lua 编写的）：micro 有一个内置的插件管理器来自动安装、删除和更新插件。\n内置 diff gutter。\n简单的自动补全。\n撤销持久化。\n自动提示和错误通知。\n超过 130 种语言的语法高亮。\n颜色方案支持：默认情况下，micro 带有 16、256 和真彩色主题。\n支持真彩色（将 MICRO_TRUECOLOR 环境变量设为 1 来启用它）。\n用系统剪贴板进行复制和粘贴。\n小而简单。\n易于配置。\n宏。\n常见的编辑器功能，如撤销/重做、行号、Unicode 支持...\n安装 # Micro 在所有主要发行版的存储库中都可用。在 Ubuntu 中，你可以使用以下命令安装它：\nsudo apt install micro 这将安装 xclip 作为剪贴板功能的依赖项。\n要获得剪贴板支持，你需要安装 xclip 和 xsel 包。在 Ubuntu 和其他基于 Ubuntu 的 Linux 发行版中，你可以使用以下命令来安装它：\nsudo apt install xclip 对于 Mac 系统，同样可以使用 Homebrew 进行安装：\nbrew install micro 如果你使用的是 macOS，则应考虑使用 iTerm2 而不是默认终端 (Terminal.app)。iTerm2 终端具有更好的鼠标支持以及对关键事件的更好处理，为了获得最佳的按键绑定行为，请在 Preferences-\u0026gt;Profiles-\u0026gt;Keys-\u0026gt;Presets... 下选择 xterm 默认值，然后在同一菜单中为 Left Option Key 选择 Esc+，最新版本还支持真彩色。\n使用 # 当安装完成后，我们就可以在终端通过运行 micro path/to/fiename.txt 或 micro 命令来打开一个空缓冲区启动它。 下图是我们总结的 Micro 编辑器的速查表，可以对照来学习 Micro 的使用，还是非常简单的。 开源地址：Git 仓库：https://github.com/zyedidia/micro\n补充阅读 # 补充 micro 文本编辑器记录的使用范围，以及与终端、文件编码和快捷键的配合。\n如何理解与使用 # 这类终端编辑器适合远程修改文本，实际体验受终端按键传递、字体与编码影响；文章中的快捷键应结合自己的终端验证。\n验证与边界 # 先使用副本测试打开、保存、撤销和退出，再处理重要配置。编辑成功还应检查文件权限、换行方式与实际内容。\n","date":"2023-10-08","externalUrl":null,"permalink":"/posts/micro-editor/","section":"文章归档","summary":"这类终端编辑器适合远程修改文本，实际体验受终端按键传递、字体与编码影响；文章中的快捷键应结合自己的终端验证。","title":"分享一款跨平台的文本编辑器micro","type":"posts"},{"content":"","date":"2023-10-08","externalUrl":null,"permalink":"/tags/golang/","section":"标签","summary":"","title":"Golang","type":"tags"},{"content":"","date":"2023-10-08","externalUrl":null,"permalink":"/tags/go%E8%AF%AD%E8%A8%80/","section":"标签","summary":"","title":"Go语言","type":"tags"},{"content":" 在Mac 下编译 Linux 和 Windows 64位可执行程序 # CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go Linux 下编译 Mac 和 Windows 64位可执行程序 # CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go Windows 下编译 Mac 和 Linux 64位可执行程序 # SET CGO_ENABLED=0 SET GOOS=darwin SET GOARCH=amd64 go build main.go SET CGO_ENABLED=0 SET GOOS=linux SET GOARCH=amd64 go build main.go 在Mac和Linux下也可以编写shell文件：\n#!/bin/bash export GOOS=windows export GOARCH=amd64 export CC=x86_64-w64-mingw32-gcc export CXX=x86_64-w64-mingw32-g++ export CGO_ENABLED=1 go build . GOOS：目标平台的操作系统（darwin、freebsd、linux、windows） GOARCH：目标平台的体系架构（386、amd64、arm）\n补充阅读 # 说明 Go 交叉编译时，目标操作系统、架构和本机运行环境的区别。\n如何理解与使用 # 交叉编译需要同时考虑 GOOS 与 GOARCH，产物能否运行还受使用的依赖与系统能力影响。\n验证与边界 # 先确认目标平台，再到对应环境验证启动与关键功能。依赖 CGO 时应额外检查交叉工具链，不能仅以生成文件判定跨平台兼容。\n","date":"2023-10-08","externalUrl":null,"permalink":"/posts/go-cross-compile/","section":"文章归档","summary":"交叉编译需要同时考虑 GOOS 与 GOARCH，产物能否运行还受使用的依赖与系统能力影响。","title":"Go语言编译指定操作系统的可执行文件","type":"posts"},{"content":"","date":"2023-10-08","externalUrl":null,"permalink":"/tags/%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91/","section":"标签","summary":"","title":"交叉编译","type":"tags"},{"content":"","date":"2023-10-06","externalUrl":null,"permalink":"/tags/linux%E5%91%BD%E4%BB%A4/","section":"标签","summary":"","title":"Linux命令","type":"tags"},{"content":"由于经常在linux上进程操作，需要测试服务器的上行带宽，除了主动上传，还可以被动下载，故，需要提供一个大文件来提供给外部下载，为此找到以下几种方式生成大文件。\n使用 dd 命令 # dd 命令用于复制和转换文件，它最常见的用途是创建实时 Linux USB。dd 命令是实际写入硬盘，文件产生的速度取决于硬盘的读写速度，根据文件的大小，该命令将需要一些时间才能完成。同时也可以测试磁盘的写入速度。\ndd if=/dev/zero of=znl.img bs=2G count=1 使用 truncate 命令 # 该命令缩减或扩充指定文件的大小为指定值，参数所指定的文件如果不存在，那么该命令会创建这个文件。\ntruncate -s 1G znl.img 使用 fallocate 命令 # fallocate命令可能是Linux中可以用来创建文件的鲜为人知的命令之一。fallocate用于将块预分配给文件。对于支持fallocate系统调用的文件系统，这可以通过分配块并将其标记为未初始化来快速完成，因此不需要对数据块进行I / O操作。 fallocate 命令是我比较推荐的创建大文件的方法，因为它创建大文件的速度是最快的。\nfallocate -l 1G znl.img 补充阅读 # 比较 Linux 创建大文件时的占用空间与写入成本，帮助理解测试文件的用途。\n如何理解与使用 # 不同命令可能真正写入数据，也可能只预分配或创建稀疏文件；表面文件大小相同，不代表磁盘实际占用相同。\n验证与边界 # 创建后分别核对逻辑大小和磁盘占用，再选择是否适合你的空间或性能测试。测试前确认路径和可用容量，避免在业务分区写满磁盘。\n","date":"2023-10-06","externalUrl":null,"permalink":"/posts/linux-large-file/","section":"文章归档","summary":"不同命令可能真正写入数据，也可能只预分配或创建稀疏文件；表面文件大小相同，不代表磁盘实际占用相同。","title":"Linux下快速创建大文件的4种方法总结","type":"posts"},{"content":"","date":"2023-10-06","externalUrl":null,"permalink":"/tags/%E7%A3%81%E7%9B%98/","section":"标签","summary":"","title":"磁盘","type":"tags"},{"content":"","date":"2023-10-06","externalUrl":null,"permalink":"/tags/%E5%86%85%E5%AD%98/","section":"标签","summary":"","title":"内存","type":"tags"},{"content":"","date":"2023-04-17","externalUrl":null,"permalink":"/tags/cpu/","section":"标签","summary":"","title":"Cpu","type":"tags"},{"content":"","date":"2023-04-17","externalUrl":null,"permalink":"/tags/docker/","section":"标签","summary":"","title":"Docker","type":"tags"},{"content":"遇到过一次CPU和内存占用过高的问题，后面统一设置所有容器的内存和CPU占用，来杜绝宿主卡死的问题：\ndocker container update --memory=\u0026#34;4g\u0026#34; --memory-swap=\u0026#34;4g\u0026#34; --cpus=\u0026#34;.5\u0026#34; $(docker container ls -q) 修改4g为其他数值即可，.5代表cpu使用率最高是50%\n补充阅读 # 解释 Docker 批量更新 CPU 与内存限制的命令范围和数值含义。\n如何理解与使用 # 命令会作用于列出的全部运行中容器，应用前应先确认目标集合。.5 表示约半个逻辑 CPU 的配额，不能笼统理解为整台多核机器的 50%。\n验证与边界 # 逐个核对应用所需资源与当前限制，并观察运行指标。内存限制、交换空间和 JVM 等进程的内部配置属于不同层，不能只改一个数值。\n","date":"2023-04-17","externalUrl":null,"permalink":"/posts/docker-resource-limits/","section":"文章归档","summary":"命令会作用于列出的全部运行中容器，应用前应先确认目标集合。.5 表示约半个逻辑 CPU 的配额，不能笼统理解为整台多核机器的 50%。","title":"更新Docker的内存和CPU的占用","type":"posts"},{"content":"OpenWRT VRRP协议配置： OpenWRT上需要安装keepalived，安装命令：\nopkg update \u0026amp; opkg install keepalived 然后，修改配置文件 /etc/keepalived/keepalived.conf，内容如下（没有就自行新建）：\nglobal_defs { router_id LVS_DEVEL } vrrp_instance VI_1 { interface br-lan #指定连接ROS的接口，默认为LAN接口的桥接 state BACKUP #默认状态是BACKUP，也可以指定为MASTER virtual_router_id 51 #和ROS保持一致即可 priority 110 # 本机优先级为110，主路由，ROS优先级为100 advert_int 1 virtual_ipaddress { 192.168.88.8 # 虚拟网关地址，和ROS保持一致 } } 划重点 # OpenWrt安装后，启动时候会自动执行配置命令，故：每次配置完毕后，一旦重启OpenWrt，配置文件会丢失。解决办法是注释掉以下配置，代码位置：/etc/init.d/keepalived\nreload_service() { #process_config 这行代码是需要注释的 #SIGHUP is used by keepalived to do init.d reload procd_send_signal keepalived } start_service() { procd_open_instance procd_set_param command /usr/sbin/keepalived procd_append_param command -n # don\u0026#39;t daemonize, procd will handle that for us procd_append_param command -f \u0026#34;$KEEPALIVED_CONF\u0026#34; #process_config 这行代码也是需要注释的 # set auto respawn behavior procd_set_param respawn procd_close_instance } 启动 /usr/sbin/keepalived -n -f /etc/keepalived/keepalived.conf(可略，参见下面的附录) 查看服务情况 ps -ef | grep keepalived查看服务状态service keepalived status重载配置文件 service keepalived reload启动服务 service keepalived start停止服务 service keepalived stop\n附录：\n由于keepalived启动时候指定了配置文件，故在/etc/init.d/keepalived文件的首几行可以修改指定配置文件\n#KEEPALIVED_CONF=/tmp/keepalived.conf 这行注释掉，或者改成如下： KEEPALIVED_CONF=/etc/keepalived/keepalived.conf 这样，Openwrt重启后，配置文件就不会丢失且会自动按配置文件/etc/keepalived/keepalived.conf来启动keepalived\n补充阅读 # 补充 OpenWrt keepalived 部署的角色、虚拟地址与故障切换验证思路。\n如何理解与使用 # 先明确哪台是主节点、哪台是备用节点，以及虚拟 IP 所在接口；配置文件相似并不说明两个节点已互相感知。\n验证与边界 # 分别检查正常持有虚拟地址、主节点故障与恢复后的行为，再用实际客户端测试访问。验证应包括切换期间业务可用性，而不只看进程状态。\n","date":"2023-04-03","externalUrl":null,"permalink":"/posts/openwrt-keepalived/","section":"文章归档","summary":"先明确哪台是主节点、哪台是备用节点，以及虚拟 IP 所在接口；配置文件相似并不说明两个节点已互相感知。","title":"openwrt部署keepalived","type":"posts"},{"content":"","date":"2022-10-23","externalUrl":null,"permalink":"/tags/debian/","section":"标签","summary":"","title":"Debian","type":"tags"},{"content":"Debian 全球镜像站\nhttps://www.debian.org/mirror/list.zh-cn.html\n以下代码在shell里面执行后，然后执行apt -y update\n中国大陆\ncat \u0026lt;\u0026lt;EOF \u0026gt; /etc/apt/sources.list deb http://ftp.cn.debian.org/debian/ bullseye main non-free contrib deb-src http://ftp.cn.debian.org/debian/ bullseye main non-free contrib deb http://ftp.cn.debian.org/debian-security/ bullseye-security main deb-src http://ftp.cn.debian.org/debian-security/ bullseye-security main deb http://ftp.cn.debian.org/debian/ bullseye-updates main non-free contrib deb-src http://ftp.cn.debian.org/debian/ bullseye-updates main non-free contrib deb http://ftp.cn.debian.org/debian/ bullseye-backports main non-free contrib deb-src http://ftp.cn.debian.org/debian/ bullseye-backports main non-free contrib EOF 阿里云\ncat \u0026lt;\u0026lt;EOF \u0026gt; /etc/apt/sources.list deb http://mirrors.aliyun.com/debian/ bullseye main non-free contrib deb-src http://mirrors.aliyun.com/debian/ bullseye main non-free contrib deb http://mirrors.aliyun.com/debian-security/ bullseye-security main deb-src http://mirrors.aliyun.com/debian-security/ bullseye-security main deb http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib deb-src http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib deb http://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib deb-src http://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib EOF 香港\ncat \u0026lt;\u0026lt;EOF \u0026gt; /etc/apt/sources.list deb http://ftp.hk.debian.org/debian/ bullseye main non-free contrib deb-src http://ftp.hk.debian.org/debian/ bullseye main non-free contrib deb http://ftp.hk.debian.org/debian-security/ bullseye-security main deb-src http://ftp.hk.debian.org/debian-security/ bullseye-security main deb http://ftp.hk.debian.org/debian/ bullseye-updates main non-free contrib deb-src http://ftp.hk.debian.org/debian/ bullseye-updates main non-free contrib deb http://ftp.hk.debian.org/debian/ bullseye-backports main non-free contrib deb-src http://ftp.hk.debian.org/debian/ bullseye-backports main non-free contrib EOF 美国\ncat \u0026lt;\u0026lt;EOF \u0026gt; /etc/apt/sources.list deb http://ftp.debian.org/debian/ bullseye main non-free contrib deb-src http://ftp.debian.org/debian/ bullseye main non-free contrib deb http://ftp.debian.org/debian-security/ bullseye-security main deb-src http://ftp.debian.org/debian-security/ bullseye-security main deb http://ftp.debian.org/debian/ bullseye-updates main non-free contrib deb-src http://ftp.debian.org/debian/ bullseye-updates main non-free contrib deb http://ftp.debian.org/debian/ bullseye-backports main non-free contrib deb-src http://ftp.debian.org/debian/ bullseye-backports main non-free contrib EOF AWS\ncat \u0026lt;\u0026lt;EOF \u0026gt; /etc/apt/sources.list deb http://cdn-aws.deb.debian.org/debian bullseye main deb-src http://cdn-aws.deb.debian.org/debian bullseye main deb http://security.debian.org/debian-security bullseye-security main deb-src http://security.debian.org/debian-security bullseye-security main deb http://cdn-aws.deb.debian.org/debian bullseye-updates main deb-src http://cdn-aws.deb.debian.org/debian bullseye-updates main deb http://cdn-aws.deb.debian.org/debian bullseye-backports main deb-src http://cdn-aws.deb.debian.org/debian bullseye-backports main EOF 补充阅读 # 解释 Debian 软件源镜像列表的用途，并说明发行版代号与安全更新源的核对方法。\n如何理解与使用 # 软件源条目需要与本机发行版和版本代号匹配；镜像域名可替换，但路径与仓库分类不能随意混用。\n验证与边界 # 修改前保存原列表，更新包索引并检查报错来源。安装镜像、软件包仓库和旧版本归档是不同入口，应根据要下载的内容选择。\n","date":"2022-10-23","externalUrl":null,"permalink":"/posts/debian-mirrors/","section":"文章归档","summary":"软件源条目需要与本机发行版和版本代号匹配；镜像域名可替换，但路径与仓库分类不能随意混用。","title":"Debian 全球镜像站的源","type":"posts"},{"content":"","date":"2022-09-27","externalUrl":null,"permalink":"/tags/mirror/","section":"标签","summary":"","title":"Mirror","type":"tags"},{"content":"# Docker中国 mirror # export REGISTRY_MIRROR=\u0026#34;https://registry.docker-cn.com\u0026#34; # 腾讯云 docker hub mirror # export REGISTRY_MIRROR=\u0026#34;https://mirror.ccs.tencentyun.com\u0026#34; # 华为云镜像 # export REGISTRY_MIRROR=\u0026#34;https://05f073ad3c0010ea0f4bc00b7105ec20.mirror.swr.myhuaweicloud.com\u0026#34; # DaoCloud 镜像 # export REGISTRY_MIRROR=\u0026#34;http://f1361db2.m.daocloud.io\u0026#34; # 阿里云 docker hub mirror export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com curl -sSL https://kuboard.cn/install-script/set_mirror.sh | sh -s ${REGISTRY_MIRROR} 重启并查看结果\nsystemctl restart docker / service docker restart docker info 补充阅读 # 说明 Docker 镜像加速切换脚本的作用位置，区分镜像仓库与通用加速地址。\n如何理解与使用 # 原记录列出的入口对应当时的环境，并非任意 registry 地址都提供 Docker Hub 加速服务。脚本会修改本机配置，需要先了解其具体内容。\n验证与边界 # 保存旧配置，检查合并后的 JSON 和服务启动结果，再测试实际镜像拉取；不要仅看环境变量赋值成功就判断加速已启用。\n","date":"2022-09-27","externalUrl":null,"permalink":"/posts/docker-mirror-switch/","section":"文章归档","summary":"原记录列出的入口对应当时的环境，并非任意 registry 地址都提供 Docker Hub 加速服务。脚本会修改本机配置，需要先了解其具体内容。","title":"修改Docker 镜像仓库 加速的快捷方式","type":"posts"},{"content":"FlatMap就是一种将数据拆分成多条数据的方法。 示意图：\n[a|b|c|d] [e|f|g|h|i] [j|k|l] [m] [n|o|p] ... ↓ ↓ flatmap ( s -\u0026gt; s.split(\u0026#39;|\u0026#39;) ) ↓ ↓ [a][b][c][d][e][f][g][h][i][j][k][l][m][n][o][p]... 补充阅读 # 解释 Java Stream flatMap 的展开思路，并补充与 map 的区别和结果验证方法。\n如何理解与使用 # map 为每个元素产生一个映射结果，flatMap 再把映射得到的多个流展开为一个流。可先用“多组词语合并为词语流”理解原图。\n验证与边界 # 验证时观察结果元素的层级与数量，区分空集合、空流和空引用；展开通常不会自动去重，是否保留顺序取决于上游与后续操作。\n","date":"2022-09-26","externalUrl":null,"permalink":"/posts/java-flatmap/","section":"文章归档","summary":"map 为每个元素产生一个映射结果，flatMap 再把映射得到的多个流展开为一个流。可先用“多组词语合并为词语流”理解原图。","title":"Java FlatMap","type":"posts"},{"content":"","date":"2022-09-19","externalUrl":null,"permalink":"/categories/javascirpt/","section":"文章分类","summary":"","title":"Javascirpt","type":"categories"},{"content":"nginx 反向代理配置文件修改为以下代码即可：\nproxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; proxy_ssl_session_reuse off; proxy_ssl_server_name on; proxy_ssl_name 这里填 ssl 的域名; proxy_ssl_protocols TLSv1.2; proxy_set_header X-Real-IP $remote_addr; 补充阅读 # 补充 Nginx HTTPS 上游 502 配置中，SNI、上游名称与 TLS 参数的不同作用。\n如何理解与使用 # proxy_ssl_name 与握手名称选择有关，转发 HTTP 头属于另一个阶段；应先明确上游证书与访问域名的对应关系。\n验证与边界 # 原文固定 TLS 版本和关闭会话复用不是所有环境的通用必选项。按错误日志逐项验证变更，并把证书验证作为独立配置核对。\n参考：Nginx HTTPS 上游名称（本次补充核对）。\n","date":"2022-09-19","externalUrl":null,"permalink":"/posts/nginx-upstream-sni/","section":"文章归档","summary":"proxy_ssl_name 与握手名称选择有关，转发 HTTP 头属于另一个阶段；应先明确上游证书与访问域名的对应关系。","title":"Nginx 反向代理HTTPS服务出现502错误的解决方案","type":"posts"},{"content":"","date":"2022-09-19","externalUrl":null,"permalink":"/categories/%E5%89%8D%E7%AB%AF/","section":"文章分类","summary":"","title":"前端","type":"categories"},{"content":"","date":"2022-09-18","externalUrl":null,"permalink":"/tags/baota/","section":"标签","summary":"","title":"Baota","type":"tags"},{"content":"","date":"2022-09-18","externalUrl":null,"permalink":"/tags/%E5%AE%9D%E5%A1%94/","section":"标签","summary":"","title":"宝塔","type":"tags"},{"content":"在宝塔面板安装nginx后，创建站点和启用nginx都会提示报错/www/server/nginx/sbin/nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory。 终端中一行命令解决：\nyum -y install lua* 补充阅读 # 解释宝塔 Nginx 缺少 LuaJIT 动态库报错的排查思路，区分依赖名称与实际加载路径。\n如何理解与使用 # 错误发生在程序加载共享库时，应先核对目标库的版本、架构、安装位置及 Nginx 的构建来源。\n验证与边界 # 原文通配符安装只是当时的处理记录，不宜在未确认仓库内容时批量安装。修复后检查二进制可运行、配置语法和服务日志。\n","date":"2022-09-18","externalUrl":null,"permalink":"/posts/baota-nginx-error/","section":"文章归档","summary":"错误发生在程序加载共享库时，应先核对目标库的版本、架构、安装位置及 Nginx 的构建来源。","title":"宝塔面板安装nginx后报错","type":"posts"},{"content":" 将以下代码存成.sh 文件，执行一下即可 # #!/bin/sh echo ======== start clean docker containers logs ======== logs=$(find /var/lib/docker/containers/ -name *-json.log) for log in $logs do echo clean logs : $log cat /dev/null \u0026gt; $log done echo ======== end clean docker containers logs ======== 补充阅读 # 说明 Docker JSON 日志清理脚本的作用范围，补充日志轮转与操作前核对事项。\n如何理解与使用 # 原脚本直接清空容器日志文件，影响的是历史日志，不会清理镜像或业务数据；目录还依赖实际的数据根路径和日志驱动。\n验证与边界 # Docker 官方不建议外部程序直接操作其管理的 JSON 日志。长期应配置大小与数量限制；应先确认保留需求和真实驱动，再选择维护方式。\n参考：Docker JSON File 日志驱动。\n","date":"2022-08-11","externalUrl":null,"permalink":"/posts/docker-log-cleanup/","section":"文章归档","summary":"原脚本直接清空容器日志文件，影响的是历史日志，不会清理镜像或业务数据；目录还依赖实际的数据根路径和日志驱动。","title":"清空 Docker 日志占用的磁盘空间","type":"posts"},{"content":"","date":"2022-08-03","externalUrl":null,"permalink":"/tags/java/","section":"标签","summary":"","title":"Java","type":"tags"},{"content":"","date":"2022-08-03","externalUrl":null,"permalink":"/tags/slf4j/","section":"标签","summary":"","title":"Slf4j","type":"tags"},{"content":"使用 sysout-over-slf4j 进行日志重定向，maven引入 jar 包：\n\u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;uk.org.lidalia\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;sysout-over-slf4j\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;1.0.2\u0026lt;/version\u0026gt; \u0026lt;/dependency\u0026gt; 在 spring 等项目启动时候调用如下方法\nSysOutOverSLF4J.sendSystemOutAndErrToSLF4J(); 补充阅读 # 解释把 System.out 与 System.err 转接到 SLF4J 的用途，以及日志后端的配套关系。\n如何理解与使用 # 这类桥接用于接纳仍直接输出到标准流的旧代码，最终日志位置和级别还由 SLF4J 绑定的后端决定。\n验证与边界 # 启动时分别写入标准输出与错误输出检查结果，并确认没有重复记录或循环桥接。业务新代码可直接使用项目已有日志接口。\n","date":"2022-08-03","externalUrl":null,"permalink":"/posts/stdout-slf4j/","section":"文章归档","summary":"这类桥接用于接纳仍直接输出到标准流的旧代码，最终日志位置和级别还由 SLF4J 绑定的后端决定。","title":"将System.out和 System.err输出到日志文件slf4j","type":"posts"},{"content":"","date":"2022-08-03","externalUrl":null,"permalink":"/tags/%E6%97%A5%E5%BF%97/","section":"标签","summary":"","title":"日志","type":"tags"},{"content":"","date":"2022-07-26","externalUrl":null,"permalink":"/tags/bat/","section":"标签","summary":"","title":"Bat","type":"tags"},{"content":" bat文件内容 # powershell -executionpolicy remotesigned -file \u0026#34;npcap.ps1\u0026#34; 其中npcap.ps1为powershell脚本\nnpcap-0.96.exe是windows的安装文件，此功能的是通过powershell调用安装程序，无窗口化安装npcap # Start-Process \u0026#34;npcap-0.96.exe\u0026#34; -ArgumentList \u0026#34;/S /npf_startup=yes /loopback_support=yes /dlt_null=no /admin_only=no /dot11_support=no /vlan_support=no /winpcap_mode=yes\u0026#34; -wait echo \u0026#34;Npcap has been installed.\u0026#34; pause 补充阅读 # 说明 Windows BAT 调用 PowerShell 脚本时，参数、工作目录与退出状态的传递。\n如何理解与使用 # 批处理负责启动解释器，脚本逻辑由 PowerShell 执行；相对路径和引号跨两个解析层时容易产生差异。\n验证与边界 # 先用含空格的路径和简单参数测试，再检查退出码能否传回调用方。执行策略与脚本来源需要独立确认，不应只以窗口打开作为成功标准。\n","date":"2022-07-26","externalUrl":null,"permalink":"/posts/batch-powershell/","section":"文章归档","summary":"批处理负责启动解释器，脚本逻辑由 PowerShell 执行；相对路径和引号跨两个解析层时容易产生差异。","title":"bat文件调用PowerShell脚本","type":"posts"},{"content":"","date":"2022-07-26","externalUrl":null,"permalink":"/tags/pcap/","section":"标签","summary":"","title":"Pcap","type":"tags"},{"content":"","date":"2022-07-26","externalUrl":null,"permalink":"/tags/powershell/","section":"标签","summary":"","title":"Powershell","type":"tags"},{"content":"","date":"2022-05-05","externalUrl":null,"permalink":"/tags/ethereum/","section":"标签","summary":"","title":"Ethereum","type":"tags"},{"content":"","date":"2022-05-05","externalUrl":null,"permalink":"/tags/web3j/","section":"标签","summary":"","title":"Web3j","type":"tags"},{"content":" 废话不多说，直接贴代码 # public class Web3jUtils { public static boolean isSignatureValid(final String address, final String signature, final String message) { log.info(\u0026#34;isSignatureValid invoked for Address {} with Signature {} and Message {} \u0026#34;, address, signature, message); final String personalMessagePrefix = \u0026#34;\\u0019Ethereum Signed Message:\\n\u0026#34;; boolean match = false; final String prefix = personalMessagePrefix + message.length(); final byte[] msgHash = Hash.sha3((prefix + message).getBytes()); final byte[] signatureBytes = Numeric.hexStringToByteArray(signature); byte v = signatureBytes[64]; if (v \u0026lt; 27) { v += 27; } final Sign.SignatureData sd = new Sign.SignatureData(v, Arrays.copyOfRange(signatureBytes, 0, 32), Arrays.copyOfRange(signatureBytes, 32, 64)); String addressRecovered = null; // Iterate for each possible key to recover for (int i = 0; i \u0026lt; 4; i++) { final BigInteger publicKey = Sign.recoverFromSignature((byte) i, new ECDSASignature( new BigInteger(1, sd.getR()), new BigInteger(1, sd.getS())), msgHash); if (publicKey != null) { addressRecovered = \u0026#34;0x\u0026#34; + Keys.getAddress(publicKey); if (addressRecovered.equals(address)) { match = true; break; } } } return match; } } 补充阅读 # 解释 Web3j 签名验签示例中的消息恢复流程，并补充字符编码和防重放的检查点。\n如何理解与使用 # 原代码恢复公钥并与地址比较，处理的是特定消息签名格式；消息长度应按协议要求的编码字节数计算，中文不能简单按字符串字符数代替。\n验证与边界 # 登录挑战还应绑定域名、随机数和有效期，验签成功本身不能阻止旧签名重放。验证时覆盖中文消息、非法长度、地址格式与重复使用。\n参考：Ethereum 签名数据标准 ERC-191。\n","date":"2022-05-05","externalUrl":null,"permalink":"/posts/web3j-auth/","section":"文章归档","summary":"原代码恢复公钥并与地址比较，处理的是特定消息签名格式；消息长度应按协议要求的编码字节数计算，中文不能简单按字符串字符数代替。","title":"基于Web3j做账号签名认证","type":"posts"},{"content":"","date":"2022-05-05","externalUrl":null,"permalink":"/categories/%E5%8C%BA%E5%9D%97%E9%93%BE/","section":"文章分类","summary":"","title":"区块链","type":"categories"},{"content":"","date":"2022-04-21","externalUrl":null,"permalink":"/tags/eth/","section":"标签","summary":"","title":"Eth","type":"tags"},{"content":"","date":"2022-04-21","externalUrl":null,"permalink":"/tags/%E5%8C%BA%E5%9D%97%E9%93%BE/","section":"标签","summary":"","title":"区块链","type":"tags"},{"content":"","date":"2022-04-21","externalUrl":null,"permalink":"/tags/%E4%BB%A5%E5%A4%AA%E5%9D%8A/","section":"标签","summary":"","title":"以太坊","type":"tags"},{"content":" 官网：OpenEthereum github # 文档： 运行参数 # docker cli # docker run -tid --name parity \\ -v /www/openethereum/chaindata/:/chaindata/ \\ -p 7788:8545 \\ -p 7799:8546 \\ -p 30303:30303 \\ -p 30303:30303/udp \\ openethereum/openethereum:latest --base-path /chaindata/ 或者\ndocker-compose.yml # version: \u0026#34;3\u0026#34; services: openethereum: image: openethereum/openethereum:latest container_name: openethereum restart: unless-stopped ports: - \u0026#34;30303:30303\u0026#34; - \u0026#34;30303:30303/udp\u0026#34; - \u0026#34;127.0.0.1:8545:8545\u0026#34; - \u0026#34;127.0.0.1:8546:8546\u0026#34; user: openethereum volumes: - ./chaindata:/chaindata stop_signal: SIGINT stop_grace_period: 2m command: - --base-path=/chaindata - --jsonrpc-interface=all - --jsonrpc-cors=all - --ws-interface=all - --ws-origins=all - --no-ipc - --scale-verifiers - --num-verifiers=4 - --pruning=fast - --pruning-memory=512 - --cache-size-db=1024 - --cache-size-blocks=128 - --cache-size-queue=512 - --cache-size-state=256 logging: driver: \u0026#34;json-file\u0026#34; options: max-size: \u0026#34;2m\u0026#34; max-file: \u0026#34;10\u0026#34; 创建目录并赋予权限 # mkdir -p chaindata \u0026amp;\u0026amp; chown -R 1000:1000 chaindata 运行脚本 # docker-compose up -d 补充阅读 # 补充 OpenEthereum 节点部署记录的同步、链配置与接口访问检查点。\n如何理解与使用 # 节点启动、与对等节点连接和完成链同步是不同状态；阅读旧配置时先确认链网络、数据目录及客户端版本。\n验证与边界 # 通过所连接网络的链标识与同步状态核对结果，并限制管理接口的暴露范围。历史镜像或参数不代表当前仍是适用的客户端选择。\n","date":"2022-04-21","externalUrl":null,"permalink":"/posts/openethereum-node/","section":"文章归档","summary":"节点启动、与对等节点连接和完成链同步是不同状态；阅读旧配置时先确认链网络、数据目录及客户端版本。","title":"以太坊openethereum节点","type":"posts"},{"content":"","date":"2022-03-21","externalUrl":null,"permalink":"/tags/proxmox-ve/","section":"标签","summary":"","title":"Proxmox VE","type":"tags"},{"content":"Proxmox VE登陆的时候提示没有有效的订阅\nYou do not have a valid subscription for this server. Please visit 。。。\n由于使用的proxmox是免费版社区版的，所以每次都提示这个没有有效的订阅挺烦的！\n网上搜索一把，基本上都是针对6.0或者之前的版本做的修改，已经不适用于7.0，经过自己的摸索已经\n可以完全去掉该提示了，有需要的小朋友拿走不谢：\n第一步：\n第二步：\nenjoy ！！！\n补充阅读 # 说明 Proxmox VE 7.0 订阅提示相关记录的版本范围与使用边界。\n如何理解与使用 # 界面提示是否显示，与节点实际拥有的订阅、仓库权限及支持资格是不同问题；改变前端展示不会创建订阅。\n验证与边界 # 维护时先确认版本和授权状态，优先使用产品提供的订阅管理方式。本次保留旧记录，没有验证界面修改对后续升级的兼容性。\n","date":"2022-03-21","externalUrl":null,"permalink":"/posts/proxmox-subscription/","section":"文章归档","summary":"界面提示是否显示，与节点实际拥有的订阅、仓库权限及支持资格是不同问题；改变前端展示不会创建订阅。","title":"Proxmox VE 7.0 登陆的时候提示没有有效的订阅","type":"posts"},{"content":"","date":"2022-03-21","externalUrl":null,"permalink":"/tags/pve/","section":"标签","summary":"","title":"PVE","type":"tags"},{"content":"location ^~ / { proxy_pass https://www.binance.com/bapi/asset/v1/public/asset-service/product/currency; proxy_set_header Host www.binance.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; add_header X-Cache $upstream_cache_status; proxy_ssl_server_name on; } 关键的一行代码：\nproxy_ssl_server_name on; 补充阅读 # 说明 Nginx 反向代理 HTTPS 时，SNI 与 HTTP Host 头为何需要分别检查。\n如何理解与使用 # 原示例通过 proxy_ssl_server_name 让上游 TLS 握手携带服务器名称；proxy_set_header Host 则作用于之后的 HTTP 请求。\n验证与边界 # 遇到 502 时结合错误日志检查域名解析、连接和 TLS 阶段。SNI 能解决名称选择问题，但不能替代上游证书校验或修复所有 502。\n参考：Nginx HTTPS 上游配置（本次补充核对）。\n","date":"2022-03-11","externalUrl":null,"permalink":"/posts/nginx-https-502/","section":"文章归档","summary":"原示例通过 proxy_ssl_server_name 让上游 TLS 握手携带服务器名称；proxy_set_header Host 则作用于之后的 HTTP 请求。","title":"解决Nginx反向代理https502错误的问题","type":"posts"},{"content":"请注意：环境变量$开头的请自行替换\n\u0026lt;build\u0026gt; \u0026lt;plugins\u0026gt; \u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-boot-maven-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;2.3.10.RELEASE\u0026lt;/version\u0026gt; \u0026lt;/plugin\u0026gt; \u0026lt;!--Maven to Docker--\u0026gt; \u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;com.google.cloud.tools\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;jib-maven-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;${jib.version}\u0026lt;/version\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;from\u0026gt; \u0026lt;image\u0026gt;${project.jib-image}\u0026lt;/image\u0026gt; \u0026lt;/from\u0026gt; \u0026lt;to\u0026gt; \u0026lt;image\u0026gt;${godname}/${project.artifactId}\u0026lt;/image\u0026gt; \u0026lt;tags\u0026gt; \u0026lt;tag\u0026gt;latest\u0026lt;/tag\u0026gt; \u0026lt;/tags\u0026gt; \u0026lt;/to\u0026gt; \u0026lt;outputPaths\u0026gt; \u0026lt;tar\u0026gt;${project.tar}/target/${godname}-${project.artifactId}.tar\u0026lt;/tar\u0026gt; \u0026lt;/outputPaths\u0026gt; \u0026lt;container\u0026gt; \u0026lt;mainClass\u0026gt;net.nice.box.gateway.GatewayApplication\u0026lt;/mainClass\u0026gt; \u0026lt;!--使用当前时间--\u0026gt; \u0026lt;creationTime\u0026gt;USE_CURRENT_TIMESTAMP\u0026lt;/creationTime\u0026gt; \u0026lt;jvmFlags\u0026gt; \u0026lt;!-- \u0026lt;jvmFlag\u0026gt;-Xms512m\u0026lt;/jvmFlag\u0026gt;--\u0026gt; \u0026lt;!-- \u0026lt;jvmFlag\u0026gt;-Xmx2048m\u0026lt;/jvmFlag\u0026gt;--\u0026gt; \u0026lt;jvmFlag\u0026gt;-XX:+UseContainerSupport\u0026lt;/jvmFlag\u0026gt; \u0026lt;jvmFlag\u0026gt;-XX:-UseAdaptiveSizePolicy\u0026lt;/jvmFlag\u0026gt; \u0026lt;jvmFlag\u0026gt;-XX:InitialRAMPercentage=40.0\u0026lt;/jvmFlag\u0026gt; \u0026lt;jvmFlag\u0026gt;-XX:MinRAMPercentage=20.0\u0026lt;/jvmFlag\u0026gt; \u0026lt;jvmFlag\u0026gt;-XX:MaxRAMPercentage=80.0\u0026lt;/jvmFlag\u0026gt; \u0026lt;jvmFlag\u0026gt;-Duser.timezone=GMT+08\u0026lt;/jvmFlag\u0026gt; \u0026lt;jvmFlag\u0026gt;-Duser.timezone=GMT+08\u0026lt;/jvmFlag\u0026gt; \u0026lt;/jvmFlags\u0026gt; \u0026lt;environment\u0026gt; \u0026lt;TZ\u0026gt;Asia/Shanghai\u0026lt;/TZ\u0026gt; \u0026lt;spring.profiles.active\u0026gt;deploy\u0026lt;/spring.profiles.active\u0026gt; \u0026lt;/environment\u0026gt; \u0026lt;/container\u0026gt; \u0026lt;!--如果私有镜像仓库没有启用https，设置allowInsecureRegistries参数为true--\u0026gt; \u0026lt;allowInsecureRegistries\u0026gt;true\u0026lt;/allowInsecureRegistries\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;!--绑定jib:build到 Maven生命周期，例如package--\u0026gt; \u0026lt;executions\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;phase\u0026gt;${project.jib-tar}\u0026lt;/phase\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;buildTar\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;/executions\u0026gt; \u0026lt;/plugin\u0026gt; \u0026lt;/plugins\u0026gt; \u0026lt;/build\u0026gt; 补充阅读 # 解释 Jib 构建配置中的 JVM 内存参数，区分镜像构建参数与容器运行限制。\n如何理解与使用 # jvmFlags 描述应用进程启动选项，容器内存上限则来自运行平台；百分比参数需要结合实际 JVM 和可见内存限额解释。\n验证与边界 # 验证时看最终镜像的启动参数和应用实际堆设置，同时为非堆内存保留空间。Maven 构建成功不能证明运行时不会触发内存不足。\n","date":"2022-03-02","externalUrl":null,"permalink":"/posts/jib-jvm-memory/","section":"文章归档","summary":"jvmFlags 描述应用进程启动选项，容器内存上限则来自运行平台；百分比参数需要结合实际 JVM 和可见内存限额解释。","title":"使用jib-maven-plugin调整Jvm内存大小","type":"posts"},{"content":"version: \u0026#39;3\u0026#39; services: app: image: \u0026#39;jc21/nginx-proxy-manager:latest\u0026#39; restart: unless-stopped ports: - \u0026#39;80:80\u0026#39; - \u0026#39;81:81\u0026#39; - \u0026#39;443:443\u0026#39; volumes: - /root/ng/data:/data - /root/ng/letsencrypt:/etc/letsencrypt networks: - vnet v2ray: image: v2ray/official:latest ports: - \u0026#34;51168:51168\u0026#34; volumes: - /root/ng/v2ray:/etc/v2ray networks: - vnet networks: vnet: driver: bridge YOUR_ADMIN_ACCOUNT 是管理员账号占位符，请使用所部署版本的初始账号。\n访问管理地址：http://ip:81 Email: YOUR_ADMIN_ACCOUNT Password: changeme 官网 # [https://nginxproxymanager.com](https://nginxproxymanager.com \u0026#34;https://nginxproxymanager.com\u0026#34;) 补充阅读 # 解释 Nginx Proxy Manager 的 Compose 配置、管理入口与代理业务验证顺序。\n如何理解与使用 # 管理面板可访问只说明管理服务启动，代理目标、域名解析和 TLS 证书还需要单独配置。\n验证与边界 # 先核对映射端口与持久化目录，再用一个受控目标验证转发。管理员凭据应按所用版本初始化，不能把旧记录中的默认值视为通用事实。\n","date":"2021-12-20","externalUrl":null,"permalink":"/posts/nginx-proxy-manager/","section":"文章归档","summary":"管理面板可访问只说明管理服务启动，代理目标、域名解析和 TLS 证书还需要单独配置。","title":"Docker部署Nginx proxy manager","type":"posts"},{"content":" 创建环境变量文件 # 在docker-compose.yml所在目录下创建.env，并键入以下内容\nELK_VERSION=7.14.2 docker-compose.yml # version: \u0026#34;3\u0026#34; services: elasticsearch: image: elasticsearch:${ELK_VERSION} container_name: elasticsearch-${ELK_VERSION} environment: - TZ=Asia/Shanghai - discovery.type=single-node - bootstrap.memory_lock=true - \u0026#34;ES_JAVA_OPTS=-Xms512m -Xmx512m\u0026#34; ports: - 9200:9200 - 127.0.0.1:9300:9300 volumes: - /etc/localtime:/etc/localtime - /etc/timezone:/etc/timezone # - ./elasticsearch/config/:/usr/share/elasticsearch/config/ - ./elasticsearch/data/:/usr/share/elasticsearch/data/ - ./elasticsearch/logs/:/usr/share/elasticsearch/logs/ - ./elasticsearch/plugins:/usr/share/elasticsearch/plugins networks: - elk-net kibana: image: kibana:${ELK_VERSION} container_name: kibana-${ELK_VERSION} depends_on: - elasticsearch ports: - \u0026#34;5601:5601\u0026#34; volumes: - /etc/localtime:/etc/localtime - /etc/timezone:/etc/timezone - ./kibana/config/:/usr/share/kibana/config/ networks: - elk-net networks: elk-net: driver: bridge 补充阅读 # 补充单节点 Elasticsearch 与 Kibana 的服务关系、版本匹配和数据目录验证方法。\n如何理解与使用 # 这是用于理解两项服务如何联通的单节点示例；容器间地址、认证设置和镜像版本需要配套。\n验证与边界 # 先确认 Elasticsearch 状态，再检查 Kibana 是否成功连接及索引是否可访问；需要保留数据时测试重建容器后的持久化，而不只刷新页面。\n","date":"2021-12-19","externalUrl":null,"permalink":"/posts/elasticsearch-kibana/","section":"文章归档","summary":"这是用于理解两项服务如何联通的单节点示例；容器间地址、认证设置和镜像版本需要配套。","title":"docker-compose部署elasticsearch和kibana单节点","type":"posts"},{"content":" 编辑~/.vimrc,没有就创建一个 # set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936 set termencoding=utf-8 set encoding=utf-8 保存，退出，重新打开即可显示中文。\n补充阅读 # 解释 Vim 中文乱码设置中，文件编码识别、内部编码与终端编码的区别。\n如何理解与使用 # 原文配置尝试按列出的编码顺序读取文件；文件本身的编码与终端如何显示字符需要分别判断。\n验证与边界 # 用已知编码的文件验证，必要时先只读查看；不要在编码识别错误时直接保存覆盖，以免把原文件内容真正改坏。\n","date":"2021-12-17","externalUrl":null,"permalink":"/posts/vim-chinese/","section":"文章归档","summary":"原文配置尝试按列出的编码顺序读取文件；文件本身的编码与终端如何显示字符需要分别判断。","title":"配置Linux中vim中文乱码的问题","type":"posts"},{"content":"今天忽然发现自家的op居然打不开了ui了，但确能ssh登录。咋一看，发现请求返回是403 网上搜索一番，发现是主题原因导致，所以决定命令行修改主题\n修改默认主题还是很简单，修改一下 /etc/config/luci 文件中的主题名字就行了。\n补充阅读 # 说明通过 OpenWrt 命令行切换 LuCI 主题时，安装包与主题配置的对应关系。\n如何理解与使用 # 先确认主题已经安装且与固件匹配，再改对应的界面设置；仅修改主题路径并不会自动下载所需文件。\n验证与边界 # 重新登录或清理相关浏览器缓存后检查展示，同时保留命令行访问，以便主题资源不匹配时恢复原设置。\n","date":"2021-12-17","externalUrl":null,"permalink":"/posts/openwrt-theme/","section":"文章归档","summary":"先确认主题已经安装且与固件匹配，再改对应的界面设置；仅修改主题路径并不会自动下载所需文件。","title":"Openwrt 命令行修改主题","type":"posts"},{"content":"","date":"2021-12-17","externalUrl":null,"permalink":"/tags/caddy/","section":"标签","summary":"","title":"Caddy","type":"tags"},{"content":" docker-compose # docker-compose安装 # 以下示例中的 YOUR_EMAIL_ADDRESS 是邮箱占位符，使用前请替换为自己的地址。\ncurl -L \u0026#34;https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)\u0026#34; -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose docker-compose.yml # version: \u0026#34;3.7\u0026#34; networks: ssr: external: true services: caddy: image: caddy:alpine #restart: unless-stopped ports: - \u0026#34;80:80\u0026#34; - \u0026#34;443:443\u0026#34; volumes: - ./Caddyfile:/etc/caddy/Caddyfile - ./caddy/site:/srv - ./caddy/data:/data - ./caddy/config:/config environment: - ACME_AGREE=true - TZ=Asia/Shanghai networks: - ssr v2ray: image: v2ray/official:latest ports: - \u0026#34;1090:1090\u0026#34; volumes: - ./v2ray:/etc/v2ray networks: - ssr networks: ssr: driver: bridge 创建网络这一步已经取消了 # ~~docker network create ssr ss配置文件config.json # { \u0026#34;inbounds\u0026#34;: [ { \u0026#34;port\u0026#34;: 10900, \u0026#34;protocol\u0026#34;: \u0026#34;vmess\u0026#34;, \u0026#34;settings\u0026#34;: { \u0026#34;clients\u0026#34;: [ { \u0026#34;id\u0026#34;: \u0026#34;b831381d-6324-4d53-ad4f-8cda48b30811\u0026#34;, \u0026#34;alterId\u0026#34;: 64 } ] }, \u0026#34;streamSettings\u0026#34;: { \u0026#34;network\u0026#34;: \u0026#34;ws\u0026#34;, \u0026#34;wsSettings\u0026#34;: { \u0026#34;path\u0026#34;: \u0026#34;/love\u0026#34; } } } ], \u0026#34;outbounds\u0026#34;: [ { \u0026#34;protocol\u0026#34;: \u0026#34;freedom\u0026#34;, \u0026#34;settings\u0026#34;: {} } ] } Caddyfile # domain.name { tls YOUR_EMAIL_ADDRESS reverse_proxy /love v2ray:10900 { header_up Connection {http.request.header.Connection} header_up Upgrade {http.request.header.Upgrade} } } 补充阅读 # 说明 Docker Compose 服务组合示例的网络、端口和持久化目录，帮助看清配置依赖。\n如何理解与使用 # 阅读文件时先列出每个服务的职责、共享网络和挂载目录；需要外部网络或额外配置文件的项目，应先确认这些资源存在。\n验证与边界 # 用实际所用 Compose 版本检查配置，再逐个看服务日志与访问结果。容器处于运行状态不代表服务依赖和认证流程已经就绪。\n","date":"2021-12-17","externalUrl":null,"permalink":"/posts/compose-services/","section":"文章归档","summary":"阅读文件时先列出每个服务的职责、共享网络和挂载目录；需要外部网络或额外配置文件的项目，应先确认这些资源存在。","title":"Docker-compose 一键部署特殊服务","type":"posts"},{"content":"","date":"2021-12-17","externalUrl":null,"permalink":"/tags/websocket/","section":"标签","summary":"","title":"Websocket","type":"tags"},{"content":" Homebrew国内源 # 苹果电脑标准安装脚本：（推荐 优点全面 缺点慢一点）\n/bin/zsh -c \u0026#34;$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)\u0026#34; 苹果电脑极速安装脚本：（优点安装速度快 缺点update功能需要命令修复 ）\n/bin/zsh -c \u0026#34;$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)\u0026#34; speed Linux 标准安装脚本：\nrm Homebrew.sh ; wget https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh ; bash Homebrew.sh 苹果电脑卸载脚本：\n/bin/zsh -c \u0026#34;$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/HomebrewUninstall.sh)\u0026#34; Linux卸载脚本：\nrm HomebrewUninstall.sh ; wget https://gitee.com/cunkai/HomebrewCN/raw/master/HomebrewUninstall.sh ; bash HomebrewUninstall.sh ---Brew介绍\nmacOS 和 Linux 缺失软件包的管理器\n---Homebrew 能干什么?\n使用 Homebrew 安装 Mac（或Linux）没有预装但你需要的东西。\n--Homebrew自身如何使用\n知道软件包具体名称，直接 brew install 软件包名只知道一小部分名称，用 brew search 小部分名称 查询即可 例如brew search chrome就会把带chrome的软件包全部列出\n--Homebrew中的扩展cask如何使用\n假设安装firefox运行：\nbrew install --cask firefox\ncask的图形化软件一般国内没有任何缓冲，下载很慢。\n补充阅读 # 解释 Homebrew 下载慢的不同阶段，说明安装脚本、仓库和二进制包来源的区别。\n如何理解与使用 # 安装器下载、Git 元数据更新和软件包下载可能走不同入口，只更换一个地址不一定解决全部慢的问题。\n验证与边界 # 先记录卡住的具体 URL 与错误，再按实际使用的镜像项目说明调整；执行远端安装或卸载脚本前阅读其内容，修改后分别验证更新与安装。\n","date":"2021-11-21","externalUrl":null,"permalink":"/posts/homebrew-mirrors/","section":"文章归档","summary":"安装器下载、Git 元数据更新和软件包下载可能走不同入口，只更换一个地址不一定解决全部慢的问题。","title":"解决Brew慢的问题","type":"posts"},{"content":" HEU KMS Activator是一款不需要联网也能激活多种版本的Windows和Office的激活工具，使用后对系统无残留，可直接删除，无需额外安装NET 4.0框架。支持win7、8、10、Server2008、Office 201O/2013多个版本的自动续费。一键即可激活Office/Win，激活后180天需要再次激活，不想动手的可以安装自动续费功能。\n时隔三年，“迷你版” KMS 激活工具 HEU KMS Activator 再次更新！此次更新增加了对 Office 2019、Windows 10 激活的支持。\nHEU KMS Activator 是知彼而知己基于MDL论坛的KMS 服务端模拟环境“KMS Server Emulator”而制作的一款简洁高效的 KMS 激活工具。适用于 Windows、Office 及 VL 版本，无需联网即可一键激活，离线全自动激活软件。KMS 服务是微软公司对 Windows 以及 Office 等的批量授权服务，可以利用 KMS 激活局域网中的产品。而这款工具是利用在系统内部搭建 KMS 服务器，因此无论是 Windows 还是 Office 都可轻易进行激活。\n下载地址 1下载地址 2下载地址 3\n网盘下载\n下载地址若无法下载请留言联系站长\n补充阅读 # 补充历史 KMS 工具记录的阅读边界，区分技术介绍与合法的软件授权。\n如何理解与使用 # KMS 是批量授权体系的一部分，使用第三方工具并不会自动取得软件许可证。原文列出的版本和效果描述属于历史记录。\n验证与边界 # 需要激活时应核对组织许可证和厂商的正式方式；本次没有新增下载地址、绕过步骤或激活结果，也没有测试旧工具的可用性。\n","date":"2019-11-02","externalUrl":null,"permalink":"/posts/kms-notes/","section":"文章归档","summary":"KMS 是批量授权体系的一部分，使用第三方工具并不会自动取得软件许可证。原文列出的版本和效果描述属于历史记录。","title":"HEU KMS Activator(离线KMS激活工具)","type":"posts"},{"content":"","date":"2019-11-02","externalUrl":null,"permalink":"/tags/kms/","section":"标签","summary":"","title":"Kms","type":"tags"},{"content":"","date":"2019-11-02","externalUrl":null,"permalink":"/tags/%E6%BF%80%E6%B4%BB/","section":"标签","summary":"","title":"激活","type":"tags"},{"content":"欢迎在这里交流与留言。\n可以在下面分享技术经验、提出问题，或留下对博客的建议。\n","date":"2019-10-30","externalUrl":null,"permalink":"/book/","section":"正能量","summary":"欢迎交流技术实践与日常想法。","title":"留言","type":"page"},{"content":"欢迎来到 正能量。\n这里记录我在软件研发、系统建设和日常生活中的观察与实践。写下一段代码，也尽量说明它解决什么问题；记录一种方法，也交代它成立的条件。\n把具体问题弄清楚，把解决问题的方法留下来。\n我在做什么 # 我是一名从一线开发成长起来的系统架构与工程实践者，拥有近二十年的软件研发和架构经验，曾承担软件总工、研发总监与 CTO 等职责。\n从早年的 Java 研发，到平台架构、技术管理和完整产品交付，我长期关注业务规则如何进入系统，以及系统如何在真实环境中稳定运行。现在的实践也延伸到 Go、云原生、链上链下协同和 AI 协作研发。\n这段经历让我习惯把业务、代码和运行现场放在一起考虑：模块边界是否清楚，数据状态是否一致，异常发生后能否定位，交付之后是否便于维护。具体问题里，往往藏着最有价值的技术判断。\n这里会记录什么 # 开发与架构：Java、Go、框架使用、接口协作与业务建模。从一个代码细节出发，尽量讲清背后的机制与取舍。 系统与运维：Linux、容器、Kubernetes、网络与服务部署。除了配置方法，也关注验证、排障和恢复。 工程与 AI 协作：任务拆解、项目约定、代码审查与交付验证，记录如何让工具真正参与研发流程。 阅读与生活：值得反复思考的观点、工具使用体会，以及技术工作之外的日常片段。 有些文章很短，只为留下一个可靠的查阅入口；有些会展开说明背景、步骤与边界。篇幅由问题决定。\n我习惯怎样解决问题 # 先弄清业务目标、使用条件和现有约束，再讨论模块划分与技术选择。一个方案是否合适，要看它能否解释清楚、验证充分，并支持后续的维护与变化。\n遇到稳定性和性能问题，我会沿着数据与请求的路径寻找证据，关注事务、缓存、消息、重试和状态之间的关系。讨论方案时，也会把失败场景、恢复方式和交付成本放在桌面上。\n这些判断最终需要落实到可检查的结果：代码、测试、真实交互、运行状态和清晰的交接记录。它们也是我持续整理技术笔记的原因。\n与 AI 一起做研发 # 我目前主要使用 Codex，也会结合任务使用其他协作工具。业务目标、架构边界和关键技术取舍由我判断，AI 按明确的上下文与验收条件推进实现，再由我审查、验证和校正。\n这套方式也用于博客写作：把零散笔记整理成文章，把遗漏的上下文补齐，把实践中形成的方法留下来。涉及事实与技术结论时，仍需要核对来源、版本和适用条件。\n工具带来速度，经验帮助判断方向；两者通过具体任务和验证过程连接起来。\n为什么保留这些旧笔记 # 这个博客保留了不少早年写下的记录。它们有当时的技术背景，也有表达不够完整的地方。我会持续补充解释、校正过时说明，让后来读到的人少一些猜测。\n一篇旧文章能再次帮人解决问题，一段经验能让下一次判断更清楚，就是这些记录继续存在的价值。“记录生活点滴”，也包含那些尚未形成完整答案、值得慢慢想明白的问题。\n从这里开始 # 想按时间查找，可以看文章归档；想围绕某个方向阅读，可以浏览分类与标签。习惯订阅更新的话，也可以使用 RSS。\n欢迎在站内留言交流具体问题、不同经验，或文章中需要纠正的地方。\n","date":"2019-10-30","externalUrl":null,"permalink":"/about/","section":"正能量","summary":"一个架构与工程实践者的长期记录：从代码和系统运行，到技术判断、AI 协作与日常思考。","title":"关于正能量","type":"page"},{"content":"","date":"2019-07-09","externalUrl":null,"permalink":"/tags/vps/","section":"标签","summary":"","title":"VPS","type":"tags"},{"content":"","date":"2019-07-09","externalUrl":null,"permalink":"/tags/%E6%90%AC%E7%93%A6%E5%B7%A5/","section":"标签","summary":"","title":"搬瓦工","type":"tags"},{"content":" 2019年2月13日，搬瓦工（bandwagonhost）正式推出助推电子商务企业的企业级VPS服务；接入10Gbps cn2 gia带宽，一起搬瓦工（bandwagonhost）也考虑到中国大陆的联通和移动用户的需求，针对中国联通和中国移动线路，由中国电信提供企业级的专线对接中国联通和中国移动，保证中国大陆的三网都是优化线路。\n搬瓦工cn2怎么样？搬瓦工是一家来自美国的vps销售，老牌、稳定、高性价比代表！属于老少皆宜的美国cn2 vps产品，SSD固态硬盘（高读写速度保证）、G口以上带宽端口（高速、大流量保障），使用上手简单易管理，适合上网、建站等多种用途。近期搬瓦工cn2系列vps再次全线补货，有优质的美国cn2 gt、cn2 gia线路可以选择！最低1核1G内存46.7美元/年，平均3.81美元/月（目前汇率来说大约27元/月），性价比非常高了。\n全场终身优惠6.58%（目前最大优惠力度）：BWH3HYATVBJW，全场通用！\n搬瓦工cn2 gia怎么样？搬瓦工目前所销售的美国cn2 gia vps主打大带宽端口，2.5gbps带宽端口起步，最高提供10gbps带宽端口可以选择，目前美国cn2 gia线路产品当中为数不多提供超大带宽cn2 gia vps产品的商家！最低配置2核1G内存、2.5gbps带宽、年付158.8美元，大约13.23美元/月（目前最新汇率计算是在93元左右/月），适合企业级用户选择！晚高峰高速、稳定保证！！！\n一、搬瓦工官网 点击直达搬瓦工官方网站(大陆访问bwh88.net)\n点击直达搬瓦工官方网站(海外访问bandwagonhost.com)\n下面列举的产品均为商家官网销售原价，购买时请记得使用目前最高6.58%的折扣码购买。\n尘埃落定，北美CN2 GIA全面涨价，cn2 gia网络将面向更加高端的用户！\n美国 cn2 gia、日本软银、荷兰（三网）联通，2.5~10Gbps带宽，市面唯一一家 最高10Gbps带宽，可选：美国 cn2 gia、日本软银、荷兰联通AS9929，企业级高端网络带宽。VPS基于KVM虚拟，SSD raid10阵列，自带一个IPv4，免费支持snapshot快照功能（可以导入、导出）和Backup（备份功能），可以一键更换IP、一键切换机房。年付低至7.6折！\n内存 CPU SSD 流量 带宽 价格 购买 1G 2核 20G 1.0T/月 2.5G $50/季 链接 2G 3核 40G 2.0T/月 2.5G $90/季 链接 4G 4核 80G 3.0T/月 2.5G $57/月 链接 8G 6核 160G 5.0T/月 5.0G $87/月 链接 16G 8核 320G 8.0T/月 10G $160/月 链接 32G 10核 640G 10.0T/月 10G $290/月 链接 64G 12核 1280G 12.0T/月 10G $550/月 链接\n香港机房VPS，1Gbps cn2 gia，市面唯一一家 适合预算高，对速度特别看重的用户，特征：KVM虚拟，1Gbps带宽，纯SSD raid 10，三网直连，cn2 gia网络；每个VPS自带一个IPv4，后台有一键快照（备份VPS，还可以导入导出）功能。到目前为止，这是市面上唯一一家提供“香港”1Gbps cn2 gia带宽的VPS！年付低至7.6折！\n内存 CPU 硬盘 流量 价格 购买 2G 2核 40G 500G/月 $90/月 链接 4G 4核 80G 1.0T/月 $156/月 链接 8G 6核 160G 2.0T/月 $300/月 链接 16G 8核 320G 4.0T/月 $590/月 链接\n搬瓦工的VPS，重点就是高端网络，美国CN2 GIA、日本软银、香港CN2 GIA、荷兰AS9929，其余的完全没有性价比，下方的VPS，不推荐购买，性价比不高，同价格可以在其他商家买到更好的。\n美国 LOS ANGELES – CN2（GT） 适合中等或者偏低预算同时也不放弃一定的速度的用户群。特征：KVM虚拟，纯SSD raid10，自带一个IPv4，免费自动备份+快照（备份VPS，还可以导入导出）。机房直接接入电信CN2 GT和中国联通…\n内存 CPU 硬盘 流量 价格 购买 1G 1核 20G 1T/月 $49.99/年 链接 2G 1核 40G 2T/月 $99.99/年 链接 4G 2核 80G 3T/月 $199.99/年 链接 8G 2核 160G 5T/月 $399.99/年 链接 16G 3核 320G 8T/月 $799.99/年 链接 16G 3核 320G 12T $999.99/年 链接 16G 3核 320G 16T $1299.99/年 链接\nDC_6机房，CN2 GIA系列，10Gbps带宽（有货） CN2 GIA网络，高达10Gbps企业级带宽， KVM虚拟，纯SSD（raid10），自带一个IPv4，自带快照等。本系列VPS为DC 6机房。\n内存 CPU SSD 流量 带宽 价格 购买 1G 2核 20G 1.0T/月 2.5G $50/季 链接 2G 3核 40G 2.0T/月 2.5G $90/季 链接 4G 4核 80G 3.0T/月 2.5G $57/月 链接 8G 6核 160G 5.0T/月 5.0G $87/月 链接 16G 8核 320G 8.0T/月 10G $160/月 链接 32G 10核 640G 10.0T/月 10G $290/月 链接 64G 12核 1280G 12.0T/月 10G $550/月 链接\nDC_9机房，CN2 GIA系列，1Gbps带宽（有货） VPS特征：本系列VPS为DC 9机房，1Gbps cn2 gia带宽，KVM虚拟，SSD raid10，自带一个IPv4，自带snapshot快照等多项功能！\n内存 CPU SSD 流量 价格 购买 1G 2核 20G 1.0T/月 $114/年 链接 2G 3核 40G 2.0T/月 $226/年 链接 4G 4核 80G 3.0T/月 $400/年 链接 8G 6核 160G 5.0T/月 $760/年 链接 16G 8核 320G 8.0T/月 $1440/年 链接\n网络测试：\n美国 cn2 gia：162.244.241.103\\104\\105\\106\\107 日本软银：185.212.59.148\\149\\150\\151\\152 荷兰联通：104.255.65.1、104.255.64.1、104.255.66.1 香港cn2 gia：93.179.124.167\\168\\169\\170\\171\\172\n为什么“我”买到的很慢？\n很多新手，不熟悉搬瓦工，喜欢直接跑到官方网站首页去点击购买，实际上网站首页是没有CN2 GIA系列的产品购买的，你买到的都是常规VPS，在晚高峰都会爆炸得稀烂的！ 如果要买高端CN2 GIA网络的，请直接戳上面给出的链接，点击进入之后你会发现产品名称是带有“CN2 GIA”字样的！\n国内如何选择？\n预算没上限，直接买香港；香港太贵，那就优先CN2 GIA；还扛不住，那就选CN2 GT；速度依次降低，能买贵的，那就不要买便宜的，一分钱一分货！\nCN2 GIA和CN2 GT的区别？\n前者是有独立的回国链路而后者没有，前者是超级VIP，不被QOS，晚高峰不受影响；后者随时被QOS，晚高峰跟随骨干网大爆炸一起卡卡卡卡…\n网络测试：\nDC6（cn2 gia）：162.244.241.102\nDC_9（cn2 gia）：65.49.131.102\nHKHK_1（香港）：69.171.64.175\nDC2（洛杉矶QN）：104.194.76.20\nDC4（洛杉矶MC）：98.142.136.11\nUSNJ（新泽西）：23.252.104.93\nEUNL_3（荷兰）：45.62.120.202\n补充阅读 # 保留早期 BandwagonHost 套餐促销记录，补充线路、资源与价格信息的核对方法。\n如何理解与使用 # 促销码、线路名称、带宽上限与实际可用吞吐是不同信息，原文数字应理解为当时页面记录。\n验证与边界 # 购买前重新核对地区、计费周期、流量和续费条件；性能判断应依赖自己的目标网络与测试时间，不把历史宣传数字当作当前承诺。\n","date":"2019-07-09","externalUrl":null,"permalink":"/posts/bandwagonhost-notes/","section":"文章归档","summary":"促销码、线路名称、带宽上限与实际可用吞吐是不同信息，原文数字应理解为当时页面记录。","title":"搬瓦工/bandwagonhost 促销优惠码,新增10Gbps带宽的cn2 gia线路VPS，移动+联通同步走企业级带宽","type":"posts"},{"content":"","date":"2019-07-09","externalUrl":null,"permalink":"/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/","section":"标签","summary":"","title":"服务器","type":"tags"},{"content":"需要让docker启动时在tcp端口2375上监听api服务\nvi /etc/systemd/system/docker-tcp.socket [Unit]Description=Docker Socket for the API [Socket]ListenStream=2375BindIPv6Only=both Service=docker.service [Install]WantedBy=sockets.target 然后再重启docker服务\nsystemctl enable docker-tcp.socket systemctl stop docker systemctl start docker-tcp.socket systemctl start docker systemctl daemon-reload 补充阅读 # 说明 Docker 2375 端口配置的功能与风险，区分远程管理 API 与容器业务端口。\n如何理解与使用 # 该端口对应 Docker 守护进程管理接口，和向外发布某个容器端口不同；允许连接可能等同于授予宿主机管理能力。\n验证与边界 # 原文保留为配置记录，当前接入应先选 SSH 或带认证的 TLS 通道。验收需要证明访问控制生效，而不仅是端口能连通。\n参考：Docker 管理接口保护（本次补充核对）。\n","date":"2019-06-05","externalUrl":null,"permalink":"/posts/docker-api-port/","section":"文章归档","summary":"该端口对应 Docker 守护进程管理接口，和向外发布某个容器端口不同；允许连接可能等同于授予宿主机管理能力。","title":"Docker 开启2375端口","type":"posts"},{"content":"\u0026lt;pre class=\u0026#34;prism-highlight\u0026#34; prism-language-bash=\u0026#34;\u0026#34;\u0026gt;systemctl stop docker; //每个liunx版本的命令不一样。\n2、创建新的docker目录，执行命令df -h,找一个大的磁盘。我的是放在/home目录下面，我的/home目录大小有50G。 我在 /home目录下面建了 /home/docker目录，执行的命令是：\n\u0026lt;pre class=\u0026#34;prism-highlight\u0026#34; prism-language-bash=\u0026#34;\u0026#34;\u0026gt;mkdir -p /home/docker 3、迁移/var/lib/docker目录下面的文件到 /home/docker下面\n\u0026lt;pre class=\u0026#34;prism-highlight\u0026#34; prism-language-bash=\u0026#34;\u0026#34;\u0026gt;cp -R /var/lib/docker/* /home/docker/ 注意：如果文件内容很多的话，为了确保成功最好是一个文件一个文件的拷贝。如果在拷贝过程中报“设备上没有空间”的错误，就使用mv剪切。\n4、修改docker配置（/etc/systemd/system/docker.service.d/devicemapper.conf）,在文件末添加 --graph=/home/docker\ndevicemapper.conf文件的内容如下：\n\u0026lt;pre class=\u0026#34;prism-highlight\u0026#34; prism-language-bash=\u0026#34;\u0026#34;\u0026gt;[Service] ExecStart= ExecStart=/usr/bin/dockerd --insecure-registry=私服地址 --graph=/home/docker 注意：如果/etc/systemd/system/docker.service.d/devicemapper.conf，这个路径找不到的话，就新建，新建之后加入内容，没有私服地址的话就可以去掉”--insecure-registry=私服地址”。私服地址配置为可选\n5、重载配置，重启docker\n\u0026lt;pre class=\u0026#34;prism-highlight\u0026#34; prism-language-bash=\u0026#34;\u0026#34;\u0026gt;systemctl daemon-reload; systemctl restart docker; systemctl enable docker; 6、启动成功后，确定容器没问题后删除/var/lib/docker/目录中的文件，然后就OK了。\n补充阅读 # 解释 Docker 数据目录迁移的容量、停机一致性和配置切换步骤。\n如何理解与使用 # 先确认真正占用空间的是镜像、容器层、日志还是卷，再决定是否迁移数据根目录；原文 --graph 属于历史写法。\n验证与边界 # 迁移应保存文件属性并避免并发写入，切换后核对实际数据根目录、容器与卷。未验证恢复前应保留原目录，不能因复制遇到空间不足就直接删除源数据。\n","date":"2018-12-26","externalUrl":null,"permalink":"/posts/docker-data-move/","section":"文章归档","summary":"先确认真正占用空间的是镜像、容器层、日志还是卷，再决定是否迁移数据根目录；原文 --graph 属于历史写法。","title":"docker 默认空间不足的问题解决","type":"posts"},{"content":"https://mirrors.tuna.tsinghua.edu.cn/help/docker-ce/\n补充阅读 # 说明 Docker 安装镜像源链接用于解决哪个下载阶段的问题，以及如何验证是否生效。\n如何理解与使用 # 软件包仓库下载慢与运行时拉取容器镜像慢是两个不同问题；先确认失败发生在安装包、仓库元数据还是镜像层下载。\n验证与边界 # 按系统版本与镜像站说明配置，修改后查看实际来源及一次下载结果。镜像站地址与可用性需要现场核对，不保证历史入口一直有效。\n","date":"2018-12-12","externalUrl":null,"permalink":"/posts/docker-mirror-install/","section":"文章归档","summary":"软件包仓库下载慢与运行时拉取容器镜像慢是两个不同问题；先确认失败发生在安装包、仓库元数据还是镜像层下载。","title":"国内无法安装docker或者安装docker慢的解决方案","type":"posts"},{"content":" Enable the remote API on a new socket # Create a file called /etc/systemd/system/docker-tcp.socket to make Docker available on a TCP socket on port 2375.\n[Unit] Description=Docker Socket for the API [Socket] ListenStream=2375 BindIPv6Only=both Service=docker.service [Install] WantedBy=sockets.target Then enable this new socket:\nsystemctl enable docker-tcp.socket systemctl stop docker systemctl start docker-tcp.socket systemctl start docker Test that it's working:\ndocker -H tcp://127.0.0.1:2375 ps 补充阅读 # 解释用 systemd Socket 暴露 Docker API 的旧版配置，并说明远程访问的权限边界。\n如何理解与使用 # 这份配置让 Docker API 接受 TCP 连接，访问者可能获得很高的宿主机控制权限；监听可用不代表认证和传输保护已完成。\n验证与边界 # 不要把无认证的 2375 端口直接暴露到公网。当前使用应按 Docker 官方方式采用 SSH 或双向 TLS 等受控入口，并验证非授权客户端无法连接。\n参考：Docker 管理接口保护（本次补充核对）。\n","date":"2018-12-11","externalUrl":null,"permalink":"/posts/docker-remote-socket/","section":"文章归档","summary":"这份配置让 Docker API 接受 TCP 连接，访问者可能获得很高的宿主机控制权限；监听可用不代表认证和传输保护已完成。","title":"Customizing docker","type":"posts"},{"content":"\u0026lt;pre class=\u0026#34;prism-highlight\u0026#34; prism-language-bash=\u0026#34;\u0026#34;\u0026gt;/ip firewall filter add action=drop chain=input comment=\u0026#34;Drop Invalid connections\u0026#34; connection-state=invalid add action=accept chain=input comment=\u0026#34;Allow Established connections\u0026#34; connection-state=established add action=accept chain=input comment=\u0026#34;Allow ICMP\u0026#34; protocol=icmp add action=drop chain=input comment=\u0026#34;Drop everything else\u0026#34; add action=drop chain=forward comment=\u0026#34;drop invalid connections\u0026#34; connection-state=invalid protocol=tcp add action=accept chain=forward comment=\u0026#34;allow already established connections\u0026#34; connection-state=established add action=accept chain=forward comment=\u0026#34;allow related connections\u0026#34; connection-state=related add action=drop chain=forward src-address=0.0.0.0/8 add action=drop chain=forward dst-address=0.0.0.0/8 add action=drop chain=forward src-address=127.0.0.0/8 add action=drop chain=forward dst-address=127.0.0.0/8 add action=drop chain=forward src-address=224.0.0.0/3 add action=drop chain=forward dst-address=224.0.0.0/3 add action=jump chain=forward jump-target=tcp protocol=tcp add action=jump chain=forward jump-target=udp protocol=udp add action=jump chain=forward jump-target=icmp protocol=icmp add action=drop chain=tcp comment=\u0026#34;deny TFTP\u0026#34; dst-port=69 protocol=tcp add action=drop chain=tcp comment=\u0026#34;deny RPC portmapper\u0026#34; dst-port=111 protocol=tcp add action=drop chain=tcp comment=\u0026#34;deny RPC portmapper\u0026#34; dst-port=135 protocol=tcp add action=drop chain=tcp comment=\u0026#34;deny NBT\u0026#34; dst-port=137-139 protocol=tcp add action=drop chain=tcp comment=\u0026#34;deny cifs\u0026#34; dst-port=445 protocol=tcp add action=drop chain=tcp comment=\u0026#34;deny NFS\u0026#34; dst-port=2049 protocol=tcp add action=drop chain=tcp comment=\u0026#34;deny NetBus\u0026#34; dst-port=12345-12346 protocol=tcp add action=drop chain=tcp comment=\u0026#34;deny NetBus\u0026#34; dst-port=20034 protocol=tcp add action=drop chain=tcp comment=\u0026#34;deny BackOriffice\u0026#34; dst-port=3133 protocol=tcp add action=drop chain=tcp comment=\u0026#34;deny DHCP\u0026#34; dst-port=67-68 protocol=tcp add action=drop chain=udp comment=\u0026#34;deny TFTP\u0026#34; dst-port=69 protocol=udp add action=drop chain=udp comment=\u0026#34;deny PRC portmapper\u0026#34; dst-port=111 protocol=udp add action=drop chain=udp comment=\u0026#34;deny PRC portmapper\u0026#34; dst-port=135 protocol=udp add action=drop chain=udp comment=\u0026#34;deny NBT\u0026#34; dst-port=137-139 protocol=udp add action=drop chain=udp comment=\u0026#34;deny NFS\u0026#34; dst-port=2049 protocol=udp add action=drop chain=udp comment=\u0026#34;deny BackOriffice\u0026#34; dst-port=3133 protocol=udp add action=accept chain=icmp comment=\u0026#34;echo reply\u0026#34; icmp-options=0:0 protocol=icmp add action=accept chain=icmp comment=\u0026#34;net unreachable\u0026#34; icmp-options=3:0 protocol=icmp add action=accept chain=icmp comment=\u0026#34;host unreachable\u0026#34; icmp-options=3:1 protocol=icmp add action=accept chain=icmp comment=\u0026#34;host unreachable fragmentation required\u0026#34; icmp-options=3:4 protocol=icmp add action=accept chain=icmp comment=\u0026#34;allow source quench\u0026#34; icmp-options=4:0 protocol=icmp add action=accept chain=icmp comment=\u0026#34;allow echo request\u0026#34; icmp-options=8:0 protocol=icmp add action=accept chain=icmp comment=\u0026#34;allow time exceed\u0026#34; icmp-options=11:0 protocol=icmp add action=accept chain=icmp comment=\u0026#34;allow parameter bad\u0026#34; icmp-options=12:0 protocol=icmp add action=drop chain=icmp comment=\u0026#34;deny all other types\u0026#34; 补充阅读 # 补充 RouterOS 防火墙脚本的 input、forward 与规则顺序，帮助读懂允许和丢弃条件。\n如何理解与使用 # input 涉及到路由器本身的流量，forward 涉及穿过路由器的流量；同名动作位于不同链时影响不同对象。\n验证与边界 # 执行前确认管理入口与回退通道，逐条检查已有规则和命中顺序；验收要同时覆盖管理访问、内网业务与预期拒绝的连接。\n","date":"2018-11-23","externalUrl":null,"permalink":"/posts/routeros-firewall/","section":"文章归档","summary":"input 涉及到路由器本身的流量，forward 涉及穿过路由器的流量；同名动作位于不同链时影响不同对象。","title":"ROS 6.x下防火墙","type":"posts"},{"content":"\u0026lt;pre class=\u0026#34;prism-highlight\u0026#34; prism-language-bash=\u0026#34;\u0026#34;\u0026gt;/ip firewall mangle add action=mark-connection chain=forward in-interface=pppoe-out1 new-connection-mark=dconn-isp comment=\u0026#34;ISP DOWNSTEAM\u0026#34; add action=mark-packet chain=forward connection-mark=dconn-isp new-packet-mark=dpkt-isp comment=\u0026#34;Packets Total Downsteam\u0026#34; add action=mark-packet chain=forward connection-bytes=0-1000000 new-packet-mark=dpkt-light-isp packet-mark=dpkt-isp passthrough=no comment=\u0026#34;Packets Less Then 1000000\u0026#34; add action=mark-packet chain=forward connection-bytes=1000000-3000000 new-packet-mark=dpkt-fair-isp packet-mark=dpkt-isp passthrough=no comment=\u0026#34;Packets 1000001-3000000\u0026#34; add action=mark-packet chain=forward connection-bytes=3000000-6000000 new-packet-mark=dpkt-weight-isp packet-mark=dpkt-isp passthrough=no comment=\u0026#34;Packets 3000001-6000000\u0026#34; add action=mark-packet chain=forward connection-bytes=6000000-0 new-packet-mark=dpkt-very-isp packet-mark=dpkt-isp passthrough=no comment=\u0026#34;Packets more then 6000000\u0026#34; add action=mark-connection chain=forward new-connection-mark=uconn-isp out-interface=pppoe-out1 comment=\u0026#34;ISP UPSTEAM\u0026#34; add action=mark-packet chain=forward connection-mark=uconn-isp new-packet-mark=upkt-isp comment=\u0026#34;Packets Total Upsteam\u0026#34; \u0026lt;pre class=\u0026#34;prism-highlight\u0026#34; prism-language-bash=\u0026#34;\u0026#34;\u0026gt;/queue tree add max-limit=20M name=Downsteam-ISP packet-mark=dpkt-isp parent=global queue=pcq-download-default add limit-at=1M max-limit=20M name=1.light-isp packet-mark=dpkt-light-isp parent=Downsteam-ISP priority=1 queue=pcq-download-default add limit-at=1M max-limit=10M name=2.fair-isp packet-mark=dpkt-fair-isp parent=Downsteam-ISP priority=2 queue=pcq-download-default add limit-at=1M max-limit=5M name=3.weight-isp packet-mark=dpkt-weight-isp parent=Downsteam-ISP priority=3 queue=pcq-download-default add limit-at=1M max-limit=1M name=4.very-isp packet-mark=dpkt-very-isp parent=Downsteam-ISP priority=4 queue=pcq-download-default add max-limit=20M name=Upsteam-ISP packet-mark=upkt-isp parent=global queue=pcq-upload-default 亲测效果比较佳！另外，如果需要对游戏不限速，需要添加游戏端口到fasttract。fasttract模式下限速无效 至于接口名称，请自行修改。速度值也需要做相应的修改\n补充阅读 # 说明 RouterOS 6.x 队列脚本如何按连接和数据量分类，并解释带宽参数的替换位置。\n如何理解与使用 # 先从连接标记追踪到包标记，再查看 queue tree 的引用关系；接口名和各级限额应按自己的链路设置。\n验证与边界 # 原文“效果较佳”属于当时的个人记录，不代表所有硬件与流量模式的结果。验证时观察分类计数、吞吐和繁忙时延迟，并单独检查排除规则。\n","date":"2018-11-23","externalUrl":null,"permalink":"/posts/routeros-queue-script/","section":"文章归档","summary":"先从连接标记追踪到包标记，再查看 queue tree 的引用关系；接口名和各级限额应按自己的链路设置。","title":"ROS 6.X目前限速比较稳定的一个脚本，来自YouTube","type":"posts"},{"content":" 最近发现linux下改了时区，同步到了硬件，ntpdate cn.pool.ntp.org怎么都没反应，时间还是不对。最后在牛人的blog中搜到了这样的方式。\n\u0026lt;pre class=\u0026#34;prism-highlight\u0026#34; prism-language-bash=\u0026#34;\u0026#34;\u0026gt;yum -y update yum -y install rdate rdate -s cn.pool.ntp.org 补充阅读 # 区分 Linux 时区、系统时间与网络同步，说明旧版 rdate 排查记录的范围。\n如何理解与使用 # 时区改变显示方式，校时改变时钟值，二者需要分别确认；机器时间不对时先记录偏差和现有同步服务。\n验证与边界 # 原文的旧协议与服务器地址不保证当前可用。调整后应持续观察同步状态与偏移，而不仅看一次日期输出是否接近正确时间。\n","date":"2018-11-12","externalUrl":null,"permalink":"/posts/linux-time-sync/","section":"文章归档","summary":"时区改变显示方式，校时改变时钟值，二者需要分别确认；机器时间不对时先记录偏差和现有同步服务。","title":"Linux下时间不同步的问题","type":"posts"},{"content":" yum -y install wget \u0026amp;\u0026amp; wget --no-check-certificate -O shadowsocks-all.sh https://raw.githubusercontent.com/teddysun/shadowsocks_install/master/shadowsocks-all.sh 能看懂的人,都知道是什么意思.\n补充阅读 # 解释历史 Shell 下载命令的组成与执行边界，帮助看懂脚本安装笔记。\n如何理解与使用 # 原命令先安装下载工具，再把远端脚本保存到本地；下载完成本身不代表脚本已执行或服务已配置。\n验证与边界 # 使用此类记录时先核对脚本来源与内容，并区分下载、审阅和执行三个步骤。原文关闭证书校验的参数不宜直接作为日常默认选项。\n","date":"2018-08-01","externalUrl":null,"permalink":"/posts/shell-installer-notes/","section":"文章归档","summary":"原命令先安装下载工具，再把远端脚本保存到本地；下载完成本身不代表脚本已执行或服务已配置。","title":"一行代码行天下","type":"posts"},{"content":" 1.如我博客上篇Nginx安装指南，首先我的执行Nginx路径为：/home/nginx/sbin/nginx； 2.我的Nginx配置文件路径为：/home/nginx/conf/nginx.conf。 下面为nginx服务开机自启动文件，将放在/etc/init.d/目录下，文件名为：nginx。 #!/bin/sh # # nginx - this script starts and stops the nginx daemon # # chkconfig: - 85 15 # description: NGINX is an HTTP(S) server, HTTP(S) reverse \\ # proxy and IMAP/POP3 proxy server # processname: nginx # config: /etc/nginx/nginx.conf # config: /etc/sysconfig/nginx # pidfile: /var/run/nginx.pid # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ \u0026#34;$NETWORKING\u0026#34; = \u0026#34;no\u0026#34; ] \u0026amp;\u0026amp; exit 0 nginx=\u0026#34;/home/nginx/sbin/nginx\u0026#34; prog=$(basename $nginx) NGINX_CONF_FILE=\u0026#34;/home/nginx/conf/nginx.conf\u0026#34; [ -f /etc/sysconfig/nginx ] \u0026amp;\u0026amp; . /etc/sysconfig/nginx lockfile=/var/lock/subsys/nginx make_dirs() { # make required directories user=$nginx -V 2\u0026gt;\u0026amp;1 | grep \u0026#34;configure arguments:\u0026#34; | sed \u0026#39;s/[^*]*--user=\\([^ ]*\\).*/\\1/g\u0026#39; - if [ -z \u0026#34;grep $user /etc/passwd\u0026#34; ]; then useradd -M -s /bin/nologin $user fi options=$nginx -V 2\u0026gt;\u0026amp;1 | grep \u0026#39;configure arguments:\u0026#39; for opt in $options; do if [ echo $opt | grep \u0026#39;.*-temp-path\u0026#39; ]; then value=echo $opt | cut -d \u0026#34;=\u0026#34; -f 2 if [ ! -d \u0026#34;$value\u0026#34; ]; then # echo \u0026#34;creating\u0026#34; $value mkdir -p $value \u0026amp;\u0026amp; chown -R $user $value fi fi done } start() { [ -x $nginx ] || exit 5 [ -f $NGINX_CONF_FILE ] || exit 6 make_dirs echo -n $\u0026#34;Starting $prog: \u0026#34; daemon $nginx -c $NGINX_CONF_FILE retval=$? echo [ $retval -eq 0 ] \u0026amp;\u0026amp; touch $lockfile return $retval } stop() { echo -n $\u0026#34;Stopping $prog: \u0026#34; killproc $prog -QUIT retval=$? echo [ $retval -eq 0 ] \u0026amp;\u0026amp; rm -f $lockfile return $retval } restart() { configtest || return $? stop sleep 1 start } reload() { configtest || return $? echo -n $\u0026#34;Reloading $prog: \u0026#34; killproc $nginx -HUP RETVAL=$? echo } force_reload() { restart } configtest() { $nginx -t -c $NGINX_CONF_FILE } rh_status() { status $prog } rh_status_q() { rh_status \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 } case \u0026#34;$1\u0026#34; in start) rh_status_q \u0026amp;\u0026amp; exit 0 $1 ;; stop) rh_status_q || exit 0 $1 ;; restart|configtest) $1 ;; reload) rh_status_q || exit 7 $1 ;; force-reload) force_reload ;; status) rh_status ;; condrestart|try-restart) rh_status_q || exit 0 ;; *) echo $\u0026#34;Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}\u0026#34; exit 2 esac 最后，别忘记了:chkconfig nginx on 以后可以以下熟悉的命令管理： service nginx status service nginx start service nginx stop service nginx restart 补充阅读 # 解释 Nginx SysV 服务脚本怎样关联二进制、配置路径与开机启动。\n如何理解与使用 # 原文适用于使用 service、chkconfig 的旧式初始化环境；脚本内的执行文件、PID 与配置路径应与实际安装一致。\n验证与边界 # 验证启动、重载、停止和系统重启后的状态，并区分配置语法检查与服务状态。由其他服务管理器托管的环境需要对应的服务定义。\n","date":"2018-01-06","externalUrl":null,"permalink":"/posts/nginx-service/","section":"文章归档","summary":"原文适用于使用 service、chkconfig 的旧式初始化环境；脚本内的执行文件、PID 与配置路径应与实际安装一致。","title":"Linux 下Nginx 设置为服务模式","type":"posts"},{"content":" 找了很多类似的答案，都是扯犊子的，下面的方案完美解决：\n打开终端------\u0026gt;在终端输入 scutil --set HostName \u0026quot;localhost\u0026quot; 在弹出的对话框中输入密码即可，作者的解释是 需要更新hosts文件（具体原因待我日后查明再分享给大家，不懂也不影响大家解决问题）\n另外，修改内存的快捷方式为：\n打开 idea，菜单 –\u0026gt; help –\u0026gt; edit custom vm options，调整参数，重启即可。\n补充阅读 # 补充 IntelliJ IDEA 2017 卡顿处理记录的适用边界，区分主机名问题与 JVM 内存调整。\n如何理解与使用 # 原文记录了两种不同方向：主机名相关环境与自定义 VM 参数。排查时应记录具体卡顿动作，而不是同时修改多项配置。\n验证与边界 # 主机名修改会影响其他依赖本机名称的工具，增加堆内存也不保证所有卡顿消失；保留原设置并比较相同操作下的日志与耗时。\n","date":"2017-12-26","externalUrl":null,"permalink":"/posts/idea-performance/","section":"文章归档","summary":"原文记录了两种不同方向：主机名相关环境与自定义 VM 参数。排查时应记录具体卡顿动作，而不是同时修改多项配置。","title":"关于Idea2017卡顿的问题","type":"posts"},{"content":" 网上找到许多一键安装脚本都不好使,唯独这个,怎么用怎么爽\n\u0026lt;a href=\u0026#34;https://github.com/hwdsl2/setup-ipsec-vpn\u0026#34;\u0026gt;https://github.com/hwdsl2/setup-ipsec-vpn\u0026lt;/a\u0026gt; 补充阅读 # 说明 IPsec VPN 安装脚本链接的用途，以及运行前应核对的系统与网络条件。\n如何理解与使用 # 原文主要保存项目入口，没有记录一套可复现的部署结果；当前使用时应先阅读项目自己的支持范围、端口及配置要求。\n验证与边界 # 先审阅脚本和预期变更，再在合适环境测试。分别确认服务状态、客户端建连及业务访问，不能将脚本退出成功等同于 VPN 可用。\n","date":"2017-12-18","externalUrl":null,"permalink":"/posts/ipsec-vpn-script/","section":"文章归档","summary":"原文主要保存项目入口，没有记录一套可复现的部署结果；当前使用时应先阅读项目自己的支持范围、端口及配置要求。","title":"Linux 下VPN一键安装脚本","type":"posts"},{"content":" 找到java.security\nfind / -name java.security 打开$JAVA_PATH/jre/lib/security/java.security这个文件，找到下面的内容：\nsecurerandom.source=file:/dev/urandom 替换成\nsecurerandom.source=file:/dev/./urandom 补充阅读 # 说明 Tomcat 启动延迟与随机源配置的历史排查思路，避免把单一修改视为通用修复。\n如何理解与使用 # 原文针对旧 JDK 的配置文件位置与随机源行为；处理当前环境时先从启动日志或线程信息定位实际等待点。\n验证与边界 # 如果瓶颈来自 DNS、数据库或其他初始化步骤，改随机源不能解决问题。记录 JDK 版本、修改前后耗时及日志证据，再判断是否相关。\n","date":"2017-11-16","externalUrl":null,"permalink":"/posts/tomcat-startup-delay/","section":"文章归档","summary":"原文针对旧 JDK 的配置文件位置与随机源行为；处理当前环境时先从启动日志或线程信息定位实际等待点。","title":"Linux tomcat 启动延迟5分钟问题解决","type":"posts"},{"content":" #!/bin/bash pro=\u0026#39;tcp\u0026#39; NAT_Host=\u0026#39;Host_A\u0026#39; NAT_Port=8080 Dst_Host=\u0026#39;Host_B\u0026#39; Dst_Port=80 iptables -t nat -A PREROUTING -m $pro -p $pro --dport $NAT_Port -j DNAT --to-destination $Dst_Host:$Dst_Port iptables -t nat -A POSTROUTING -m $pro -p $pro --dport $Dst_Port -d $Dst_Host -j SNAT --to-source $NAT_Host 另存到linux上,修改对应的参数执行一次即可.\n补充阅读 # 解释 iptables 端口映射脚本的参数含义，说明目标转换与返回流量应怎样一起验证。\n如何理解与使用 # Host_A 表示转发端地址，Host_B 表示后端地址，两个端口分别对应入口和后端服务。先画出请求与响应路径再替换参数。\n验证与边界 # 确认 IP 转发、路由和过滤链策略，再检查 NAT 命中计数及后端日志。重复运行追加规则的脚本可能产生重复项，应先查看现有规则。\n","date":"2017-10-08","externalUrl":null,"permalink":"/posts/linux-port-forward/","section":"文章归档","summary":"Host_A 表示转发端地址，Host_B 表示后端地址，两个端口分别对应入口和后端服务。先画出请求与响应路径再替换参数。","title":"Linux 端口映射脚本","type":"posts"},{"content":" 查看系统是否存在mysql,如果存在则删除\nyum list installed | grep mysql 如果存在则执行下面的命令\nyum -y remove mysql-libs.x86_64 当然,如果查出来的是哪个就删除哪个\n然后下载mysql源,当然你可以也可以选择比较新的源,这个目前是mysql5.6\nwget dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm 接下来安装源\nrpm -ivh mysql-community-release-el6-5.noarch.rpm 看看是不是已经安装成功\nyum repolist | grep mysql \u0026lt;p\u0026gt;yum list installed | grep mysql\u0026lt;/p\u0026gt; 接下来安装mysql\nyum -y install mysql-community-server 注意:\n在启动前,建议先配置下/etc/my.conf,在[mysqld]修改和加入\ncharacter-set-server=utf8mb4 datadir=/home/mysqldata socket=/home/mysqldata/mysql.sock 在[client]下加入(如果没有client,需要自行创建)\nsocket=/home/mysqldata/mysql.sock 然后\nservice mysqld start 接下来修改密码,注意默认密码是空\nmysql -u root -p use mysql; update user set password=password(\u0026#39;123456\u0026#39;) where user=\u0026#39;root\u0026#39;; flush privileges; 修改成远程可登陆\nGRANT ALL PRIVILEGES ON TO \u0026#39;root\u0026#39;@\u0026#39;%\u0026#39; IDENTIFIED BY \u0026#39;123123\u0026#39; WITH GRANT OPTION; flush privileges; 完毕!\n补充阅读 # 补充 CentOS 6.9 安装 MySQL 5.6 的历史范围，解释仓库、数据目录和权限配置的关系。\n如何理解与使用 # 这份记录对应旧系统与旧版数据库；原文安装源和账号修改语句不应直接套用到其他主版本。\n验证与边界 # 调整数据目录或卸载依赖包前先确认现有数据和依赖关系。验证启动、连接、字符集和重启持久化，示例弱密码应由真实环境自行替换。\n","date":"2017-09-29","externalUrl":null,"permalink":"/posts/centos-mysql/","section":"文章归档","summary":"这份记录对应旧系统与旧版数据库；原文安装源和账号修改语句不应直接套用到其他主版本。","title":"Centos6.9下通过yum命令安装mysql","type":"posts"},{"content":" wget tar -xzvf redis-3.2.11.tar.gz cd redis-3.2.11/ yum -y install gcc make MALLOC=libc OK,到此就安装结束,记下来配置,vim redis.conf,修改以下几个参数:\n#这个代表后台服务 daemonize yes #这个代表使用保护,如果不需要密码,这个参数需要设置为no,否则无法连接的 protected-mode yes #这个代表连接的密码,不要密码注释就OK requirepass 2017 #注释以下的行,代表可以从其他的地方远程访问redis,根据个人需要修改即可. #bind 127.0.0.1 接下来启动\n./src/redis-server ./redis.conf 补充阅读 # 解释 Redis 源码安装与配置记录，并补充监听地址、认证和保护模式的作用范围。\n如何理解与使用 # 编译成功、进程启动和远程可连接是不同结果；先确认版本与配置文件路径，再按实际部署方式管理服务。\n验证与边界 # 保护模式不等于简单的“开关密码”。使用前按 Redis 安全文档核对网络绑定与认证，避免为连接方便直接暴露服务；测试也应包括未授权访问被拒绝。\n参考：Redis 安全说明（本次补充核对）。\n","date":"2017-09-29","externalUrl":null,"permalink":"/posts/redis-install/","section":"文章归档","summary":"编译成功、进程启动和远程可连接是不同结果；先确认版本与配置文件路径，再按实际部署方式管理服务。","title":"Linux 安装Redis","type":"posts"},{"content":" 最近买了个美国的服务器,使用过程中,发现一些问题,后来经过验证,才发现是时区的问题导致的,现在记录时区修改的方式:\ncp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime hwclock 第一条命令,覆盖本地时间为亚洲上海\n第二条命令,写入到硬件\n补充阅读 # 说明 Linux 修改时区与设置硬件时钟的区别，并纠正原命令说明中的易混点。\n如何理解与使用 # 复制时区文件改变本地时间的解释与显示，并不是一次网络时间同步；应先确认实际需求是时区错误还是时钟本身存在偏差。\n验证与边界 # 单独执行 hwclock 默认是读取硬件时钟，不能视为已经写入。写入操作需要明确方向和相应选项，避免把错误的系统时间同步到硬件。\n参考：hwclock 手册（本次补充核对）。\n","date":"2017-09-24","externalUrl":null,"permalink":"/posts/linux-timezone/","section":"文章归档","summary":"复制时区文件改变本地时间的解释与显示，并不是一次网络时间同步；应先确认实际需求是时区错误还是时钟本身存在偏差。","title":"Linux下修改时区不重启","type":"posts"},{"content":" macOS Sierra 10.12.0\nsudo killall -HUP mDNSResponder OSX 10.11.0\nsudo killall -HUP mDNSResponder OSX 10.10.4\nsudo killall -HUP mDNSResponder OSX 10.10.0 – 10.10.3\nsudo discoveryutil mdnsflushcache OSX 10.9 – 10.8 – 10.7\nsudo killall -HUP mDNSResponder OSX 10.5 – 10.6\nsudo dscacheutil -flushcache Windows\nipconfig /flushdns Linux (depending on what you’re running)\n/etc/init.d/named restart /etc/init.d/nscd restart 补充阅读 # 区分操作系统、应用与递归 DNS 缓存，帮助判断清缓存后为什么结果可能不变。\n如何理解与使用 # 原文按不同旧版系统列出命令，应先确认本机实际使用的解析服务；重启某个服务只影响它管理的缓存。\n验证与边界 # 比较应用访问、系统解析与指定 DNS 服务器查询结果，再结合 TTL 判断更新传播情况。清本地缓存不能立即刷新所有上游缓存。\n","date":"2017-09-23","externalUrl":null,"permalink":"/posts/flush-dns/","section":"文章归档","summary":"原文按不同旧版系统列出命令，应先确认本机实际使用的解析服务；重启某个服务只影响它管理的缓存。","title":"Clear DNS Cache","type":"posts"},{"content":" 不多说，看脚本\nwget -c chmod +x ./speedtest.py ./speedtest.py Ps:\n这个需要安装Python，至于怎么安装，google或者百度都可以查到。\n如果提示无法下载https，请在wget后面加入\n–no-check-certificate 补充阅读 # 说明 Linux 服务器测速笔记的使用前提，以及下载来源与结果解读的注意事项。\n如何理解与使用 # 原文的下载命令缺少具体 URL，不能直接当作完整安装步骤；应先确认测速工具的官方来源与所需运行环境。\n验证与边界 # 单次测速受测试节点、时间和链路影响，适合与同环境多次结果比较。遇到证书错误应先检查证书链、系统时间和下载地址，而非默认关闭校验。\n","date":"2017-09-19","externalUrl":null,"permalink":"/posts/linux-speedtest/","section":"文章归档","summary":"原文的下载命令缺少具体 URL，不能直接当作完整安装步骤；应先确认测速工具的官方来源与所需运行环境。","title":"linux下使用speedtest测试主机网速","type":"posts"},{"content":" 在使用spring框架配置AOP的时候，不管是通过XML配置文件还是注解的方式都需要定义pointcut\u0026quot;切入点\u0026quot;\n例如定义切入点表达式 execution ( com.znle.service.impl...*(..))\nexecution()是最常用的切点函数，其语法如下所示：\n整个表达式可以分为五个部分：\n1、execution(): 表达式主体。\n2、第一个*号：表示返回类型，*号表示所有的类型。\n3、包名：表示需要拦截的包名，后面的两个句点表示当前包和当前包的所有子包，com.znle.service.impl包、子孙包下所有类的方法。\n4、第二个*号：表示类名，*号表示所有的类。\n5、*(..):最后这个星号表示方法名，*号表示所有的方法，后面括弧里面表示方法的参数，两个句点表示任何参数。\nexecution()是最常用的切点函数，其语法如下所示：\nexecution(\u0026lt;修饰符模式\u0026gt;? \u0026lt;返回类型模式\u0026gt; \u0026lt;方法名模式\u0026gt;(\u0026lt;参数模式\u0026gt;) \u0026lt;异常模式\u0026gt;?) 除了返回类型模式、方法名模式和参数模式外，其它项都是可选的。与其直接讲解该方法的使用规则，还不如通过一个个具体的例子进行理解。下面，我们给出各种使用execution()函数实例。\n补充阅读 # 补充 Spring AOP execution 切点表达式的阅读顺序与代理调用边界。\n如何理解与使用 # 从返回类型、包与类、方法名、参数逐段解释表达式，并拿一个希望命中的方法及一个不应命中的方法做对照。\n验证与边界 # 切点匹配只是条件之一，还应确认对象由 Spring 管理、相关切面已启用、调用经过代理；看到注解或表达式并不等于该次调用一定被拦截。\n","date":"2017-09-18","externalUrl":null,"permalink":"/posts/spring-aop/","section":"文章归档","summary":"从返回类型、包与类、方法名、参数逐段解释表达式，并拿一个希望命中的方法及一个不应命中的方法做对照。","title":"Spring AOP 切面","type":"posts"},{"content":" 默认安装的centos-mini版本很多东西都没有.比如docker的源就没有.而docker在centos-extras包,mini是没有的.\n安装之前先执行\nyum search docker 如果提示没有则添加epel\nyum -y install epel-release 官方标准的说法是:\nThe centos-extras repository must be enabled. This repository is enabled by default, but if you have disabled it, you need to re-enable it.\n官方地址:\nhttps://docs.docker.com/engine/installation/linux/docker-ce/centos/#install-using-the-repository\n接下来\nyum -y install docker-io 补充阅读 # 说明 CentOS 旧版 Docker 安装记录中，发行版软件包与官方安装方式的区别。\n如何理解与使用 # 原文 docker-io 与当时的仓库有关，不能据此推断当前系统应安装相同包名。先识别发行版、版本和已有 Docker 安装来源。\n验证与边界 # 完成后同时核对客户端版本、服务端状态及实际容器运行；修改软件仓库前保存原配置，避免多个来源混用造成依赖冲突。\n","date":"2017-09-15","externalUrl":null,"permalink":"/posts/centos-docker/","section":"文章归档","summary":"原文 docker-io 与当时的仓库有关，不能据此推断当前系统应安装相同包名。先识别发行版、版本和已有 Docker 安装来源。","title":"CentOS安装docker","type":"posts"},{"content":" 今天用闲置的HTPC安装了一个Ubuntu Server，由于环境因素，不方便连接有线网，所以通过无线网络的方式上网，以前从来没通过命令行的方式来配置，今天配置一次成功了，现记录如下：\n1、先查看机器是否有安装无线网卡驱动，如果看不到网卡信息，那么接下来的操作都可以忽略了，至于怎么安装无线网卡驱动。\niwconfig 2、在本地目录创建一个密码文件\nwpa_passphrase MMGG.NET apple2099 \u0026gt; wifi.conf 其中：MMGG.NET为无线的SSID，apple2099为无线密码，wifi.conf为创建的文件，存储在当前执行命令的目录，当然也可以修改成其他的目录。\n3、连接无线网络\nUbuntu从16以后貌似已经改成了wlp4s0（也有可能是wlp5s0），通过wpa_supplicant连接\nwpa_supplicant -i wlp4s0 -c wifi.conf -B dhclient wlp4s0 4、ping下百度看看吧。\n补充阅读 # 梳理 Ubuntu Server 16.04 无线联网记录的驱动、认证与地址获取步骤。\n如何理解与使用 # 流程依次解决网卡可识别、连接无线接入点和获得网络地址；原文接口名、SSID 和口令均属于示例环境。\n验证与边界 # 依次检查无线关联、IP 地址、默认路由和 DNS。配置文件可能包含网络凭据，应限制读取范围；不同系统版本的网络管理方式需另行核对。\n","date":"2017-09-15","externalUrl":null,"permalink":"/posts/ubuntu-wifi/","section":"文章归档","summary":"流程依次解决网卡可识别、连接无线接入点和获得网络地址；原文接口名、SSID 和口令均属于示例环境。","title":"Ubuntu 16.04连接无线网络","type":"posts"},{"content":" 需要先修改redis.conf配置文件，修改daemonize的值为yes\n然后执行\n./redis-server ./redis.conf 没有提示表示已经启动成功\n补充阅读 # 解释 Redis 后台启动与配置文件加载的关系，补充实际启动结果的检查方式。\n如何理解与使用 # 原文通过 daemonize 让进程转入后台；需要确认启动命令指向的正是已修改的配置文件，而不是另一个默认配置。\n验证与边界 # 没有终端输出不代表一定启动成功。应检查进程、监听端口、日志和一次符合认证配置的连接；由服务管理器托管时还要遵循对应的前台运行方式。\n","date":"2017-02-22","externalUrl":null,"permalink":"/posts/redis-daemon/","section":"文章归档","summary":"原文通过 daemonize 让进程转入后台；需要确认启动命令指向的正是已修改的配置文件，而不是另一个默认配置。","title":"Redis 后台启动","type":"posts"},{"content":"package com.ygsoft.bxj.api; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.List; import org.apache.commons.io.FileUtils; import com.google.common.collect.Lists; /** * * @author 正能量 * */ public class Test { public static void main(String[] args) throws IOException { getFile(); List\u0026lt;String\u0026gt; list = FileUtils.readLines(new File(\u0026#34;e:/aa.txt\u0026#34;)); List\u0026lt;String\u0026gt; ips = Lists.newArrayList(); for (String string : list) { if (string.matches(\u0026#34;^apnic\\\\|CN\\\\|ipv4\\\\|.+\u0026#34;)) { String[] str = string.split(\u0026#34;\\\\|\u0026#34;); ips.add(str[3] + \u0026#34;/\u0026#34; + toMask(str[4])); } } for (String string : ips) { System.out.println(\u0026#34;/ip firewall address-list add list=chinaips address=\u0026#34; + string); } } private static void getFile() throws IOException { URL url = new URL(\u0026#34;http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest\u0026#34;); FileUtils.copyURLToFile(url, new File(\u0026#34;e:/aa.txt\u0026#34;)); } private static int toMask(String rang) { int r = Integer.parseInt(rang); return (int) (32 - Math.log(r) / Math.log(2)); } } 补充阅读 # 解释通过 APNIC 委派数据解析中国 IPv4 地址段的用途，以及地区登记信息的边界。\n如何理解与使用 # 原题“Apanic”指 APNIC。脚本处理的是地址资源登记数据，读取记录时需要区分地区字段、资源类型、起始地址和数量。\n验证与边界 # 登记地区不等于实时用户所在地，也不能单独用于精确定位。验证时覆盖地址段边界、数据更新时间与非 IPv4 记录，避免简单按字符串拆分后误算。\n","date":"2016-11-01","externalUrl":null,"permalink":"/posts/apnic-china-ip/","section":"文章归档","summary":"原题“Apanic”指 APNIC。脚本处理的是地址资源登记数据，读取记录时需要区分地区字段、资源类型、起始地址和数量。","title":"通过Apanic解析中国IP","type":"posts"},{"content":"location / { root /var/www; index index.html index.htm index.php; if (!-e $request_filename) { rewrite ^/index.php(.*)$ /index.php?s=$1 last; rewrite ^(.*)$ /index.php?s=$1 last; break; } } 用以上的url重写规则就可以了。\n补充阅读 # 说明 ThinkPHP 验证码在 Nginx 环境中的重写排查方向，区分路由与图片生成问题。\n如何理解与使用 # 原文重写规则把请求交给入口脚本，适用于特定年代的路径约定；移植前确认实际入口位置、路径参数和 ThinkPHP 版本。\n验证与边界 # 先看验证码请求是 404、应用报错还是返回了无法识别的图片，再检查重写、会话及相关扩展。重写规则不能解决所有验证码失败。\n","date":"2016-05-30","externalUrl":null,"permalink":"/posts/thinkphp-captcha/","section":"文章归档","summary":"原文重写规则把请求交给入口脚本，适用于特定年代的路径约定；移植前确认实际入口位置、路径参数和 ThinkPHP 版本。","title":"ThinkPHP使用nginx后无法显示验证码的问题","type":"posts"},{"content":" 1.创建用户\ngroupadd sftp\n2.添加用户并设置为sftp组\nuseradd -g sftp -s /sbin/nologin -M sftp （/sbin/nologin为禁止登录shell的用户）\n3.设置用户密码\npasswd sftp\n4.创建用户目录。并设置权限。\ncd /home\nmkdir sftp\nchown root:sftp sftp\nchmod 755 sftp\n5.修改SSH配置\n/etc/ssh/sshd_config\n修改Subsystem\nSubsystem sftp internal-sftp\n6.在sshd_config添加用户配置\nMatch User sftp #限制的用户\nX11Forwarding no\nAllowTcpForwarding no\nForceCommand internal-sftp\nChrootDirectory /home/sftp #用户的根目录\n7.最后重启SSH\n/etc/init.d/ssh restart\nEND # 补充阅读 # 解释 SFTP chroot 目录限制的配置思路，补充目录所有权与可写子目录的区别。\n如何理解与使用 # ChrootDirectory 约束用户看到的根目录；该路径及上级目录的所有权、权限应符合 OpenSSH 要求。需要上传时通常另建用户可写子目录。\n验证与边界 # 使用目标用户验证上传、读取与越界访问，并确认其他用户不受 Match 段影响。修改配置后先做语法检查，再以新连接验收。\n参考：OpenSSH sshd_config（本次补充核对）。\n","date":"2016-05-30","externalUrl":null,"permalink":"/posts/sftp-chroot/","section":"文章归档","summary":"ChrootDirectory 约束用户看到的根目录；该路径及上级目录的所有权、权限应符合 OpenSSH 要求。需要上传时通常另建用户可写子目录。","title":"Linux通过sftp来上传文件，并保证用户在固定的目录下","type":"posts"},{"content":"","date":"2016-04-25","externalUrl":null,"permalink":"/tags/php/","section":"标签","summary":"","title":"Php","type":"tags"},{"content":"做这个的前提是，先自行配置好https环境。\n接下来在首页的位置加上\n\u0026lt;?php switch ($_SERVER[\u0026#34;HTTP_HOST\u0026#34;]) { case \u0026#34;mmgg.net\u0026#34;: header(\u0026#34;location:https://www.mmgg.net\u0026#34;); break; } //http转化为https if ($_SERVER[\u0026#34;HTTPS\u0026#34;] \u0026lt;\u0026gt; \u0026#34;on\u0026#34;) { $xredir=\u0026#34;https://\u0026#34;.$_SERVER[\u0026#34;SERVER_NAME\u0026#34;].$_SERVER[\u0026#34;REQUEST_URI\u0026#34;]; header(\u0026#34;Location: \u0026#34;.$xredir); } ?\u0026gt; 其他语言以此类推。\n当然还可以做302跳转。\n补充阅读 # 解释 PHP 中 HTTP 跳转 HTTPS 的基本流程，以及代理部署时应检查的请求信息。\n如何理解与使用 # 原文的前提是目标域名已有可用 HTTPS；跳转应保留需要的路径和查询参数，并在发送响应头之前避免输出正文。\n验证与边界 # 反向代理终止 TLS 时，应用看到的协议可能不同于用户访问协议，需要按可信代理配置处理，防止循环跳转。分别检查首跳地址、状态码和最终页面。\n","date":"2016-04-25","externalUrl":null,"permalink":"/posts/php-https-redirect/","section":"文章归档","summary":"原文的前提是目标域名已有可用 HTTPS；跳转应保留需要的路径和查询参数，并在发送响应头之前避免输出正文。","title":"php中http到https的自动跳转","type":"posts"},{"content":"原图暂无法获取\n补充阅读 # 说明早期后台界面维护笔记的留存状态，并明确截图缺失时可提供的信息范围。\n如何理解与使用 # 迁移中只保留了原图链接，尚未找到可恢复的界面截图或实现代码，因此本篇是界面演进的资料线索。\n验证与边界 # 后续若补回原图，可记录页面用途、主要区域和当时版本；当前不根据缺失图片推断交互，也不把重绘图当作历史原图。\n","date":"2016-04-21","externalUrl":null,"permalink":"/posts/admin-ui-notes/","section":"文章归档","summary":"迁移中只保留了原图链接，尚未找到可恢复的界面截图或实现代码，因此本篇是界面演进的资料线索。","title":"最新后台界面维护","type":"posts"},{"content":"@Autowired private RequestMappingHandlerMapping handlerMapping; @RequestMapping(\u0026#34;urls\u0026#34;) public void index(Long id, HttpServletRequest request, HttpServletResponse response) throws IOException, ClassNotFoundException { Map\u0026lt;RequestMappingInfo, HandlerMethod\u0026gt; map = handlerMapping.getHandlerMethods(); Iterator\u0026lt;Entry\u0026lt;RequestMappingInfo, HandlerMethod\u0026gt;\u0026gt; iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Entry\u0026lt;RequestMappingInfo, HandlerMethod\u0026gt; entry = iterator.next(); HandlerMethod hm=entry.getValue(); StringBuffer str=new StringBuffer(\u0026#34;请求地址:\u0026#34;+entry.getKey().getPatternsCondition() + \u0026#34;----调用方法:\u0026#34; + hm.getMethod().getName()+\u0026#34;(\u0026#34;); MethodParameter[] mmm=hm.getMethodParameters(); for (MethodParameter methodParameter : mmm) { str.append(methodParameter.getParameterType().getSimpleName()+\u0026#34;,\u0026#34;); } if(str.lastIndexOf(\u0026#34;,\u0026#34;)\u0026gt;0){ str.deleteCharAt(str.length()-1); } str.append(\u0026#34;)\u0026#34;); System.out.println(str); response.setCharacterEncoding(\u0026#34;utf-8\u0026#34;); response.setContentType(\u0026#34;text/html\u0026#34;); response.getWriter().write(str+\u0026#34;\u0026lt;br/\u0026gt;\u0026#34;); } } 补充阅读 # 说明通过 RequestMappingHandlerMapping 查看 Spring MVC 映射的方法与使用范围。\n如何理解与使用 # 示例读取处理器维护的映射信息，可用于理解控制器方法怎样对应到请求路径；它不是一次真实 HTTP 调用的执行轨迹。\n验证与边界 # 调试输出应结合 HTTP 方法、路径条件和实际可达性查看，并限制此类诊断接口的访问范围，避免公开内部管理端点清单。\n","date":"2016-04-20","externalUrl":null,"permalink":"/posts/spring-url-mappings/","section":"文章归档","summary":"示例读取处理器维护的映射信息，可用于理解控制器方法怎样对应到请求路径；它不是一次真实 HTTP 调用的执行轨迹。","title":"Spring MVC 找出所有的URL映射地址","type":"posts"},{"content":"@RequestMapping(value=\u0026#34;/{user:[a-z-]+}.{num:[\\\\d]+}\u0026#34;) public String regularExpression( @PathVariable String user, @PathVariable String num){ System.out.println(\u0026#34;第一个参数: \u0026#34; + user+ \u0026#34;, 第二个参数: \u0026#34; + num); return \u0026#34;\u0026#34;; } 补充阅读 # 解释 Spring MVC 路径变量正则示例，说明 user 与 num 两部分如何从 URL 提取。\n如何理解与使用 # 示例通过路径模式限制变量内容，再用 @PathVariable 接收；阅读时要区分 URL 中的正则语法和 Java 字符串中的转义。\n验证与边界 # 构造合法字符串、非法字符和空值等请求检查匹配结果，同时确认所用 Spring 版本与路径匹配配置，不能只看方法是否成功编译。\n参考：Spring MVC Request Mapping（本次补充核对）。\n","date":"2016-04-20","externalUrl":null,"permalink":"/posts/spring-url-regex/","section":"文章归档","summary":"示例通过路径模式限制变量内容，再用 @PathVariable 接收；阅读时要区分 URL 中的正则语法和 Java 字符串中的转义。","title":"Spring MVC URL的正则表达式","type":"posts"},{"content":" iptables -X\niptables -F\niptables -P INPUT ACCEPT\niptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\niptables -A INPUT -p icmp -j ACCEPT\niptables -A INPUT -p gre -j ACCEPT\niptables -A INPUT -p tcp -m state --state NEW -m multiport --dport 80,25,110,143,22,1723 -j ACCEPT\niptables -A INPUT -i lo -j ACCEPT\niptables -A INPUT -j REJECT --reject-with icmp-host-prohibited\n/etc/init.d/iptables save\nservice iptables restart\n补充阅读 # 解释旧版 iptables 规则清单的顺序、链用途和远程操作前的验证方法。\n如何理解与使用 # 规则按顺序匹配，允许已建立连接、环回和管理入口的规则需要与最终拒绝规则共同阅读；先明确 INPUT 与 FORWARD 对应的不同流量。\n验证与边界 # 原文包含清空规则的操作，适用前应保存当前规则并具备回退通道。验证新连接、已有连接和转发流量，避免只确认当前 SSH 会话未断。\n","date":"2016-04-01","externalUrl":null,"permalink":"/posts/iptables-basics/","section":"文章归档","summary":"规则按顺序匹配，允许已建立连接、环回和管理入口的规则需要与最终拒绝规则共同阅读；先明确 INPUT 与 FORWARD 对应的不同流量。","title":"常用防火墙设置","type":"posts"},{"content":" cd到上级目录，然后输入一条命令即可查询每个子目录所占用的空间大小\ndu -h --max-depth=1\n可以更改--max-depth参数的值，该参数表示查询子目录的层级\n补充阅读 # 解释 du 查看目录占用时的层级和单位，帮助定位 Linux 磁盘空间问题。\n如何理解与使用 # --max-depth=1 用于显示当前层及下一层目录的汇总；运行位置不同，比较对象也不同。du 查看文件占用，df 查看文件系统容量，二者视角不同。\n验证与边界 # 对异常目录继续逐层查看，并注意权限错误、挂载点和已删除但仍被进程占用的文件；不要仅凭一次汇总就直接删除目录。\n","date":"2016-03-17","externalUrl":null,"permalink":"/posts/linux-directory-size/","section":"文章归档","summary":"--max-depth=1 用于显示当前层及下一层目录的汇总；运行位置不同，比较对象也不同。du 查看文件占用，df 查看文件系统容量，二者视角不同。","title":"CentOS查看每个目录所占用空间大小","type":"posts"},{"content":"当您准备Hibernate映射文件中，我们已经看到，映射Java数据类型到关系型数据库的数据类型。声明并在映射文件中使用的类型不是Java数据类型;同时也不是SQL数据库的数据类型。这些类型就是所谓的Hibernate映射类型，它可以从Java转换到SQL数据类型，反之亦然。本章列出了所有的基础上，日期和时间，大对象，以及其他各种内置的映射类型。\nPrimitive types: # Mapping type Java type ANSI SQL Type integer int or java.lang.Integer INTEGER long long or java.lang.Long BIGINT short short or java.lang.Short SMALLINT float float or java.lang.Float FLOAT double double or java.lang.Double DOUBLE big_decimal java.math.BigDecimal NUMERIC character java.lang.String CHAR(1) string java.lang.String VARCHAR byte byte or java.lang.Byte TINYINT boolean boolean or java.lang.Boolean BIT yes/no boolean or java.lang.Boolean CHAR(1) ('Y' or 'N') true/false boolean or java.lang.Boolean CHAR(1) ('T' or 'F') Date and time types: # Mapping type Java type ANSI SQL Type date java.util.Date or java.sql.Date DATE time java.util.Date or java.sql.Time TIME timestamp java.util.Date or java.sql.Timestamp TIMESTAMP calendar java.util.Calendar TIMESTAMP calendar_date java.util.Calendar DATE Binary and large object types: # Mapping type Java type ANSI SQL Type binary byte[] VARBINARY (or BLOB) text java.lang.String CLOB serializable any Java class that implements java.io.Serializable VARBINARY (or BLOB) clob java.sql.Clob CLOB blob java.sql.Blob BLOB JDK-related types: # Mapping type Java type ANSI SQL Type class java.lang.Class VARCHAR locale java.util.Locale VARCHAR timezone java.util.TimeZone VARCHAR currency java.util.Currency VARCHAR 补充阅读 # 说明 Hibernate 映射类型表应怎样用于 Java 属性与数据库列之间的类型检查。\n如何理解与使用 # 表中的名称属于 Hibernate 的映射层，不能直接等同于 Java 类名或任意数据库的实际列类型；还应考虑所用方言和框架版本。\n验证与边界 # 对日期、精度、空值和大字段，分别检查实体声明、生成或已有表结构，以及读写往返结果；历史映射表不应直接替代当前版本文档。\n","date":"2016-01-29","externalUrl":null,"permalink":"/posts/hibernate-types/","section":"文章归档","summary":"表中的名称属于 Hibernate 的映射层，不能直接等同于 Java 类名或任意数据库的实际列类型；还应考虑所用方言和框架版本。","title":"Hibernate - Mapping Types","type":"posts"},{"content":"2013年12月13号，更新为RealVNC 5.1官方原版+注册码，注册密钥如下：\nBQ24G-PDXE4-KKKRS-WBHZE-F5RCA BQ24G-PDXE4-KKKRS-WBHZE-F5RCA 8ZEZH-QPANM-NX3A5-8C4TS-8B97A 7AB4X-3YNXF-C5MRR-59DJG-7HGNA UPL8P-CN2MT-85ERA-N3E3B-GERDA\nRealVNC 5.1官方原版直链下载\n补充阅读 # 保留 RealVNC 5.1 的历史下载与授权笔记，并说明重新安装前的核对事项。\n如何理解与使用 # 这份记录对应旧版产品，下载位置和许可条件可能已变化；原文序列号不代表读者当前获得了授权。\n验证与边界 # 重新使用时核对软件来源、受支持版本与自有许可证，同时确认远程访问权限。本次没有测试或补充激活方式。\n","date":"2015-11-04","externalUrl":null,"permalink":"/posts/realvnc-license-notes/","section":"文章归档","summary":"这份记录对应旧版产品，下载位置和许可条件可能已变化；原文序列号不代表读者当前获得了授权。","title":"RealVNC 5.1官方原版+注册码","type":"posts"},{"content":" package net.mmgg.util; import java.io.File; import java.io.IOException; import java.text.DecimalFormat; import java.text.FieldPosition; import java.text.NumberFormat; import java.util.Random; import java.util.Stack; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;\npublic class Identifier { private static final FieldPosition HELPER_POSITION = new FieldPosition(0); private static final long MAX = 999; private static final long FIX = 1388505600000l; private static long seq = 0; static final char[] array={'q','w','e','r','t','y','u','i','o','p','a','s','d','f','g','h','j','k','l','z','x','c','v','b','n','m','0','1','2','3','4','5','6','7','8','9','Q','W','E','R','T','Y','U','I','O','P','A','S','D','F','G','H','J','K','L','Z','X','C','V','B','N','M'};\npublic static String generate() { synchronized (Identifier.class) { StringBuffer sb = new StringBuffer(\u0026quot;\u0026quot;); long datetime = System.currentTimeMillis() - FIX; sb.append(datetime); NumberFormat nf = new DecimalFormat(\u0026quot;000\u0026quot;); nf.format(seq, sb, HELPER_POSITION); if (seq == MAX) { seq = 0; } else { seq++; } return sb.toString(); } } private static String _10_to_62(long number){ Long rest=number; Stack\u0026lt;Character\u0026gt; stack=new Stack\u0026lt;Character\u0026gt;(); StringBuilder result=new StringBuilder(0); while(rest!=0){ stack.add(array[new Long((rest-(rest/62)*62)).intValue()]); rest=rest/62; } for(;!stack.isEmpty();){ result.append(stack.pop()); } return result.toString();\n} public static String uid() { return _10_to_62(Long.parseLong(generate())); }\npublic static String generateRadix() { return Long.toString(Long.parseLong(generate()), Character.MAX_RADIX); } public static int getRandom(int min, int max) { return new Random().nextInt(Math.abs(max - min)) + min; }\npublic static int get6Number() { return getRandom(100000, 999999); } public static String uuid() { return UUID.randomUUID().toString(); }\npublic static long getIdtoDate(String id) { long longId = Long.parseLong(id, Character.MAX_RADIX); String ids = String.valueOf(longId); ids = ids.substring(0, ids.length() - 3); return Long.parseLong(ids) + FIX; }\n}\n补充阅读 # 补充 Java 唯一 ID 示例的适用范围，区分进程内序列、随机标识与分布式唯一性。\n如何理解与使用 # 读代码时应找出时间、序列和随机部分，并确认计数状态存放在哪里；单进程中的同步并不能自动协调多个进程或多台机器。\n验证与边界 # 验证时覆盖并发、进程重启和时钟变化。数据库唯一约束及冲突处理仍有价值，不能仅凭方法名称包含“唯一”就省略边界检查。\n","date":"2015-10-31","externalUrl":null,"permalink":"/posts/java-unique-id/","section":"文章归档","summary":"读代码时应找出时间、序列和随机部分，并确认计数状态存放在哪里；单进程中的同步并不能自动协调多个进程或多台机器。","title":"Java生成唯一ID","type":"posts"},{"content":" \u0026lt;pre class=\u0026#34;brush:java;toolbar:false\u0026#34;\u0026gt;package net.mmgg.mvc.util; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * 描述：转化日期为人性化方式显示 * 创建人：正能量 * 创建时间：2015年10月21日 下午4:31:40 * 修改人： * 修改时间：2015年10月21日 下午4:31:40 * 修改备注： * @version V3.0 */ public class RelativeDateFormat { public static void main(String[] args) throws ParseException { SimpleDateFormat format = new SimpleDateFormat(\u0026#34;yyyy-MM-dd HH:mm:ss\u0026#34;); Calendar cal=Calendar.getInstance(); cal.setTime(new Date()); for (int i = 0; i \u0026gt; -15000; i--) { cal.add(Calendar.SECOND, i); System.out.print(format.format(cal.getTime())+\u0026#34;=\u0026#34;); System.out.println(format(cal.getTime())); } //System.out.println(format(format.parse(\u0026#34;2015-10-14 00:17:44\u0026#34;))); } public static String format(Date time) throws ParseException{ if(CalendarTime.YEAR.compare(time)){ return CalendarTime.YEAR.format(time); } if(CalendarTime.MONTH.compare(time)){ return CalendarTime.MONTH.format(time); } if(CalendarTime.WEEK_OF_MONTH.compare(time)){ return CalendarTime.WEEK_OF_MONTH.format(time); } if(CalendarTime.DAY_OF_MONTH.compare(time)){ return CalendarTime.DAY_OF_MONTH.format(time); } if(CalendarTime.HOUR.compare(time)){ return CalendarTime.HOUR.format(time); } if(CalendarTime.MINUTE.compare(time)){ return CalendarTime.MINUTE.format(time); } if(CalendarTime.SECOND.compare(time)){ return CalendarTime.SECOND.format(time); } return \u0026#34;刚刚\u0026#34;; } } enum CalendarTime{ YEAR(Calendar.YEAR,\u0026#34;年前\u0026#34;), MONTH(Calendar.MONTH,\u0026#34;个月前\u0026#34;), WEEK_OF_MONTH(Calendar.WEEK_OF_MONTH,\u0026#34;周前\u0026#34;), DAY_OF_MONTH(Calendar.DAY_OF_MONTH,\u0026#34;天前\u0026#34;), HOUR(Calendar.HOUR_OF_DAY,\u0026#34;小时前\u0026#34;), MINUTE(Calendar.MINUTE,\u0026#34;分钟前\u0026#34;), SECOND(Calendar.SECOND,\u0026#34;秒前\u0026#34;); int x; String y; CalendarTime(int x,String y){ this.x=x; this.y=y; } boolean compare(Date date){ Calendar cal=Calendar.getInstance(); cal.setTime(date); Calendar now=Calendar.getInstance(); now.setTime(new Date()); return now.get(this.x)!=cal.get(this.x); } String format(Date date) throws ParseException{ Calendar nowCal=Calendar.getInstance(); nowCal.setTime(new Date()); Calendar dateCal=Calendar.getInstance(); dateCal.setTime(date); String str=(nowCal.get(this.x)-dateCal.get(this.x))+this.y; switch (this) { case YEAR: if(nowCal.get(this.x)==dateCal.get(this.x)+1){ str= \u0026#34;去年\u0026#34;+(dateCal.get(Calendar.MONTH)+1)+\u0026#34;月\u0026#34;; } if(nowCal.get(this.x)==dateCal.get(this.x)+2){ str= \u0026#34;前年\u0026#34;+(dateCal.get(Calendar.MONTH)+1)+\u0026#34;月\u0026#34;; } break; case MONTH: if(nowCal.get(this.x)==dateCal.get(this.x)+1){ str= \u0026#34;上个月\u0026#34;+(dateCal.get(Calendar.DAY_OF_MONTH))+\u0026#34;号\u0026#34;; } break; case WEEK_OF_MONTH: if(nowCal.get(this.x)==dateCal.get(this.x)+1){ str= \u0026#34;上周\u0026#34;+((dateCal.get(Calendar.DAY_OF_WEEK)-1)==0?\u0026#34;日\u0026#34;:(dateCal.get(Calendar.DAY_OF_WEEK)-1)); } break; case DAY_OF_MONTH: if(nowCal.get(this.x)==dateCal.get(this.x)+1){ str= \u0026#34;昨天\u0026#34;+(dateCal.get(Calendar.HOUR_OF_DAY))+\u0026#34;点\u0026#34;; } if(nowCal.get(this.x)==dateCal.get(this.x)+2){ str= \u0026#34;前天\u0026#34;; } break; default: break; } return str; } } 补充阅读 # 解释 Java 相对日期格式化代码的用途，并说明时间差、时区与展示边界。\n如何理解与使用 # 这类格式化把绝对时间转换为“多久以前”等展示文字，原始时间戳仍应保留，用于排序、比较和需要精确时间的场景。\n验证与边界 # 测试同一分钟、跨天、未来时间及空值，并确保输入和当前时间使用同一时间基准；不要把展示文本反过来当作可靠的时间数据。\n","date":"2015-10-22","externalUrl":null,"permalink":"/posts/java-relative-date/","section":"文章归档","summary":"这类格式化把绝对时间转换为“多久以前”等展示文字，原始时间戳仍应保留，用于排序、比较和需要精确时间的场景。","title":"JAVA转化日期为人性化方式显示","type":"posts"},{"content":" 第一步：这是拨号成功后的界面\n原图暂无法获取：blob.png\n第二步：假如vpnserver所在的内网网段为：192.168.8.0/24，则添加一个静态路由从vpnserver网关出去\n原图暂无法获取：blob.png\n第三步：添加目标地址是vpnserver内网的地址伪装，从vpnclient端口出去\n原图暂无法获取：blob.png 原图暂无法获取：blob.png\n补充阅读 # 梳理 RouterOS PPTP 客户端接入远端内网时，静态路由与地址伪装的配置思路。\n如何理解与使用 # 先明确需要访问的远端网段，再确认路由指向隧道出口；是否需要地址伪装取决于远端是否知道客户端网段的返回路由。\n验证与边界 # 原文部分截图已无法恢复，因此这里补充排查顺序而不伪造截图参数。测试目标应包括隧道对端和真实内网服务。\n","date":"2015-10-09","externalUrl":null,"permalink":"/posts/routeros-pptp-route/","section":"文章归档","summary":"先明确需要访问的远端网段，再确认路由指向隧道出口；是否需要地址伪装取决于远端是否知道客户端网段的返回路由。","title":"ROS pptp客户端连接到pptpserver内网","type":"posts"},{"content":" 在这台vpn server上打开转发，并设置\niptables -t nat -A POSTROUTING -o eth0 -s 192.168.10.0/24 -j MASQUERADE 其中：192.168.10.0/24所在的网络为vpn客户端拨号后所在的网络\n补充阅读 # 解释 PPTP 客户端访问服务端内网时，IP 转发和源地址转换各自解决的问题。\n如何理解与使用 # VPN 拨号成功只说明隧道建立，访问远端网段还需要路由和返回路径。原文网段是客户端地址池示例，出口接口应按实际网络填写。\n验证与边界 # 分别验证到 VPN 服务端、远端网关和目标业务的连通性，结合规则计数判断流量走向，避免把所有失败都归因于拨号过程。\n","date":"2015-10-09","externalUrl":null,"permalink":"/posts/pptp-lan-routing/","section":"文章归档","summary":"VPN 拨号成功只说明隧道建立，访问远端网段还需要路由和返回路径。原文网段是客户端地址池示例，出口接口应按实际网络填写。","title":"打通PPTP server所在的内网","type":"posts"},{"content":" ubuntu shell 下默认的脚本解析器是dash, 会使一些bash脚本执行失败. 通过如下方式改回bash:\nsudo dpkg-reconfigure dash 选择NO\n补充阅读 # 说明 Ubuntu 中 /bin/sh 与 Bash 的差异，并解释旧版全局切换方案的影响范围。\n如何理解与使用 # 需要 Bash 特性的脚本应明确使用 Bash 解释器；脚本按 /bin/sh 执行时，不能默认具备所有 Bash 扩展。\n验证与边界 # 原文修改系统默认解释器会影响其他脚本。处理单个脚本兼容问题时，先确认其解释器与实际语法，再决定是否需要系统级调整。\n","date":"2015-08-01","externalUrl":null,"permalink":"/posts/ubuntu-bash/","section":"文章归档","summary":"需要 Bash 特性的脚本应明确使用 Bash 解释器；脚本按 /bin/sh 执行时，不能默认具备所有 Bash 扩展。","title":"Ubuntu修改bash","type":"posts"},{"content":"IDEA 13\n用户名 mmgg.net 注册码 07389-W8AM3-JYGUI-YKT61-INAT7-C9F52 IDEA 14\n用户名 mmgg.net 注册码 05206-3ZORC-KFDNM-W7N4E-MXK3L-GXKK7 补充阅读 # 保留早期 IntelliJ IDEA 授权记录，并说明旧版本信息与当前许可状态的区别。\n如何理解与使用 # 文中属于 IDEA 13、14 年代的历史记录；出现旧序列号并不证明当前有合法授权，也不能推导其对新版本有效。\n验证与边界 # 实际使用时应核对自己的许可证、产品版本与厂商公布的许可方式。本次只补充阅读边界，没有新增激活步骤或验证历史序列号。\n","date":"2015-07-01","externalUrl":null,"permalink":"/posts/idea-license-notes/","section":"文章归档","summary":"文中属于 IDEA 13、14 年代的历史记录；出现旧序列号并不证明当前有合法授权，也不能推导其对新版本有效。","title":"IntelliJ IDEA注册码","type":"posts"},{"content":" 一、安装nginx时必须先安装相应的编译工具\nyum -y install gcc gcc-c++ autoconf automake yum -y install zlib zlib-devel openssl openssl-devel pcre-devel\n建立nginx 组 groupadd -r nginx useradd -s /sbin/nologin -g nginx -r nginx id nginx\nzlib:nginx提供gzip模块，需要zlib库支持 openssl:nginx提供ssl功能 pcre:支持地址重写rewrite功能\n二、tar -zxvf nginx-1.8.0.tar.gz\n三、cd nginx-1.8.0\n四、./configure \\\n--prefix=/nginx-1.8.0 \\\n--user=nginx \\\n--group=nginx \\\n--with-http_ssl_module \\\n--with-http_flv_module \\\n--with-http_gzip_static_module \\\n--with-http_stub_status_module\n五、make \u0026amp;\u0026amp; make install\n小结：centos没有安装make编译器 解决：yum -y install gcc automake autoconf libtool make\n在Ubuntu下遇到库的依赖问题，解决如下：\nsudo apt-get install libssl-dev sudo apt-get install libpcre3 libpcre3-dev\n补充阅读 # 解释 Nginx 源码安装记录中，编译依赖、构建选项与安装目录的作用。\n如何理解与使用 # 原文是指定旧版本的构建笔记，依赖库分别服务于压缩、TLS 和正则等功能；构建参数应与实际需要的模块及路径对应。\n验证与边界 # 安装后确认正在运行的二进制、版本和配置目录一致，再检查语法和监听结果。不要因为编译成功就认为线上实例已切换。\n","date":"2015-06-29","externalUrl":null,"permalink":"/posts/nginx-build/","section":"文章归档","summary":"原文是指定旧版本的构建笔记，依赖库分别服务于压缩、TLS 和正则等功能；构建参数应与实际需要的模块及路径对应。","title":"nginx安装","type":"posts"},{"content":" 下面是参考网络资源总结的一些在Java编程中尽可能要做到的一些地方。\n1. 尽量在合适的场合使用单例 # 使用单例可以减轻加载的负担，缩短加载的时间，提高加载的效率，但并不是所有地方都适用于单例，简单来说，单例主要适用于以下三个方面：\n控制资源的使用，通过线程同步来控制资源的并发访问； 控制实例的产生，以达到节约资源的目的； 控制数据共享，在不建立直接关联的条件下，让多个不相关的进程或线程之间实现通信。 2. 尽量避免随意使用静态变量 # 要知道，当某个对象被定义为stataic变量所引用，那么gc通常是不会回收这个对象所占有的内存，如\npublic class A{ static B b = new B(); } 此时静态变量b的生命周期与A类同步，如果A类不会卸载，那么b对象会常驻内存，直到程序终止。\n3. 尽量避免过多过常的创建Java对象 # 尽量避免在经常调用的方法，循环中new对象，由于系统不仅要花费时间来创建对象，而且还要花时间对这些对象进行垃圾回收和处理，在我们可以控制的范围内，最大限度的重用对象，最好能用基本的数据类型或数组来替代对象。\n4. 尽量使用final修饰符 # 带有final修饰符的类是不可派生的。\n在Java核心API中，有许多应用final的例子，例如java.lang.String。为String类指定final防止了使用者覆盖length()方法。\n另外，如果一个类是final的，则该类所有方法都是final的。Java编译器会寻找机会内联（inline）所有的final方法（这和具体的编译器实现有关）。此举能够使性能平均提高50%。\n5. 尽量使用局部变量 # 调用方法时传递的参数以及在调用中创建的临时变量都保存在栈（Stack）中，速度较快。\n其他变量，如静态变量、实例变量等，都在堆（Heap）中创建，速度较慢。\n6. 尽量处理好包装类型和基本类型两者的使用场所 # 虽然包装类型和基本类型在使用过程中是可以相互转换，但它们两者所产生的内存区域是完全不同的，基本类型数据产生和处理都在栈中处理，包装类型是对象，是在堆中产生实例。\n在集合类对象，有对象方面需要的处理适用包装类型，其他的处理提倡使用基本类型。\n7. 慎用synchronized，尽量减小synchronize的方法 # 都知道，实现同步是要很大的系统开销作为代价的，甚至可能造成死锁，所以尽量避免无谓的同步控制。\nsynchronize方法被调用时，直接会把当前对象锁 了，在方法执行完之前其他线程无法调用当前对象的其他方法。\n所以synchronize的方法尽量小，并且应尽量使用方法同步代替代码块同步。\n8. 尽量使用StringBuilder和StringBuffer进行字符串连接 # 这个就不多讲了。\n9. 尽量不要使用finalize方法 # 实际上，将资源清理放在finalize方法中完成是非常不好的选择，由于GC的工作量很大，尤其是回收Young代内存时，大都会引起应用程序暂停，所以再选择使用finalize方法进行资源清理，会导致GC负担更大，程序运行效率更差。\n10. 尽量使用基本数据类型代替对象 # String str = \u0026#34;hello\u0026#34;; 上面这种方式会创建一个“hello”字符串，而且JVM的字符缓存池还会缓存这个字符串；\nString str = new String(\u0026#34;hello\u0026#34;); 此时程序除创建字符串外，str所引用的String对象底层还包含一个char数组，这个char数组依次存放了h,e,l,l,o\n11. 单线程应尽量使用HashMap、ArrayList # HashTable、Vector等使用了同步机制，降低了性能。\n12. 尽量合理的创建HashMap # 当 你要创建一个比较大的hashMap时，充分利用另一个构造函数 public HashMap(int initialCapacity, float loadFactor) 避免HashMap多次进行了hash重构,扩容是一件很耗费性能的事，在默认中initialCapacity只有16，而loadFactor是 0.75，需要多大的容量，你最好能准确的估计你所需要的最佳大小，同样的Hashtable，Vectors也是一样的道理。\n13. 尽量减少对变量的重复计算 # 如\nfor(int i=0;i\u0026lt;list.size();i++) 应该改为\nfor(int i=0,len=list.size();i\u0026lt;len;i++) 并且在循环中应该避免使用复杂的表达式，在循环中，循环条件会被反复计算，如果不使用复杂表达式，而使循环条件值不变的话，程序将会运行的更快。\n14. 尽量避免不必要的创建 # 如\nA a = new A();if(i==1){list.add(a);} 应该改为\nif(i==1){A a = new A();list.add(a);}\n15. 尽量在finally块中释放资源 # 程序中使用到的资源应当被释放，以避免资源泄漏。\n这最好在finally块中去做。不管程序执行的结果如何，finally块总是会执行的，以确保资源的正确关闭。\n16. 尽量使用移位来代替’a/b’的操作 # ”/”是一个代价很高的操作，使用移位的操作将会更快和更有效\n如\nint num = a / 4;int num = a / 8; 应该改为\nint num = a \u0026gt;\u0026gt; 2;int num = a \u0026gt;\u0026gt; 3; 但注意的是使用移位应添加注释，因为移位操作不直观，比较难理解\n17.尽量使用移位来代替’a*b’的操作 # 同样的，对于’*’操作，使用移位的操作将会更快和更有效\n如\nint num = a * 4;int num = a * 8; 应该改为\nint num = a \u0026lt;\u0026lt; 2;int num = a \u0026lt;\u0026lt; 3;\n18. 尽量确定StringBuffer的容量 # StringBuffer 的构造器会创建一个默认大小（通常是16）的字符数组。在使用中，如果超出这个大小，就会重新分配内存，创建一个更大的数组，并将原先的数组复制过来，再 丢弃旧的数组。\n在大多数情况下，你可以在创建 StringBuffer的时候指定大小，这样就避免了在容量不够的时候自动增长，以提高性能。\n如：\nStringBuffer buffer = new StringBuffer(1000);\n19. 尽量早释放无用对象的引用 # 大部分时，方法局部引用变量所引用的对象 会随着方法结束而变成垃圾，因此，大部分时候程序无需将局部，引用变量显式设为null。\n例如：\nPublic void test(){ Object obj = new Object(); …… Obj=null; } 上面这个就没必要了，随着方法test()的执行完成，程序中obj引用变量的作用域就结束了。\n但是如果是改成下面：\nPublic void test(){ Object obj = new Object(); …… Obj=null; //执行耗时，耗内存操作；或调用耗时，耗内存的方法 …… } 这时候就有必要将obj赋值为null，可以尽早的释放对Object对象的引用。\n20. 尽量避免使用二维数组 # 二维数据占用的内存空间比一维数组多得多，大概10倍以上。\n21. 尽量避免使用split # 除 非是必须的，否则应该避免使用split，split由于支持正则表达式，所以效率比较低，如果是频繁的几十，几百万的调用将会耗费大量资源，如果确实需 要频繁的调用split，可以考虑使用apache的StringUtils.split(string,char)，频繁split的可以缓存结果。\n22. ArrayList \u0026amp; LinkedList # 一 个是线性表，一个是链表，一句话，随机查询尽量使用ArrayList，ArrayList优于LinkedList，LinkedList还要移动指 针，添加删除的操作LinkedList优于ArrayList，ArrayList还要移动数据，不过这是理论性分析，事实未必如此，重要的是理解好2 者得数据结构，对症下药。\n23. 尽量使用System.arraycopy ()代替通过来循环复制数组 # System.arraycopy() 要比通过循环来复制数组快的多\n24. 尽量缓存经常使用的对象 # 尽可能将经常使用的对象进行缓存，可以使用数组，或HashMap的容器来进行缓存，但这种方式可能导致系统占用过多的缓存，性能下降，推荐可以使用一些第三方的开源工具，如EhCache，Oscache进行缓存，他们基本都实现了FIFO/FLU等缓存算法。\n25. 尽量避免非常大的内存分配 # 有时候问题不是由当时的堆状态造成的，而是因为分配失败造成的。分配的内存块都必须是连续的，而随着堆越来越满，找到较大的连续块越来越困难。\n26. 慎用异常 # 当创建一个异常时，需要收集一个栈跟踪(stack track)，这个栈跟踪用于描述异常是在何处创建的。 构建这些栈跟踪时需要为运行时栈做一份快照，正是这一部分开销很大。\n当需要创建一个 Exception 时，JVM 不得不说：先别动，我想就您现在的样子存一份快照，所以暂时停止入栈和出栈操作。 栈跟踪不只包含运行时栈中的一两个元素，而是包含这个栈中的每一个元素。\n如 果您创建一个 Exception ，就得付出代价。好在捕获异常开销不大，因此可以使用 try-catch 将核心内容包起来。 从技术上讲，您甚至可以随意地抛出异常，而不用花费很大的代价。 招致性能损失的并不是 throw 操作——尽管在没有预先创建异常的情况下就抛出异常是有点不寻常。 真正要花代价的是创建异常。\n幸运的是，好的编程习惯已教会我们，不应该不管三七二十一就抛出异常。\n异常是为异常的情况而设计的，使用时也应该牢记这一原则。\n补充阅读 # 把早期 Java 性能建议作为排查清单阅读，并说明为什么优化结果应以实际测量为准。\n如何理解与使用 # 原文汇总了对象、集合和字符串等方面的旧经验，其中固定性能提升比例、堆栈位置等概括不宜直接当作当前 JVM 的保证。\n验证与边界 # 先确定慢在哪里，再围绕同一工作负载测量耗时、分配和 GC；为可读性明显增加复杂度的修改，应有与所用 JDK 相符的验证结果。\n","date":"2015-06-09","externalUrl":null,"permalink":"/posts/java-performance/","section":"文章归档","summary":"原文汇总了对象、集合和字符串等方面的旧经验，其中固定性能提升比例、堆栈位置等概括不宜直接当作当前 JVM 的保证。","title":"26个提升java性能需要注意的地方","type":"posts"},{"content":" 登录前的提示信息：\n系统级别的设置方法（该信息，远程ssh连接的时候并不会显示） 在登录系统输入用户名之前，可以看到上方有WELCOME......之类的信息，这里会显示LINUX发行版本名称，内核版本号，日期，机器信息等等信息，要设置的话，首先打开/etc/issue文件，可以看到里面是这样一段\u0026quot;Welcome to \u0026lt;LINUX 发行版本名称\u0026gt;-kernel 后接各项参数\n后接的参数的各项说明：\n\\r 显示KERNEL内核版本号；\n\\l 显示虚拟控制台号；\n\\d 显示当前日期；\n\\n 显示主机名；\n\\m 显示机器类型，即CPU架构，如i386等；\n了解了参数的意义，就来修改，将上面一段欢迎信息修改如下，可以显示所有必要的信息：\nWelcome to \u0026lt;LINUX 发行版本名称\u0026gt;-kernel \\r (\\l) \\d \\n \\m.\nssh 设置 vi /etc/ssh/sshd_config添加\nBanner /etc/ssh/ssh_login_banner\n把欢迎语或提示信息写入 /etc/ssh/ssh_login_banner(centos6.4)即可，简单的很。\n登录后的提示信息：\n编辑/etc/motd这个文件， 在里面加入自己喜欢的任何欢迎信息，这段信息将会在登录成功后显示！\n补充阅读 # 区分 Linux 本地登录提示、SSH 登录前 Banner 与登录后的 MOTD 信息。\n如何理解与使用 # /etc/issue、SSH 的 Banner 配置和 /etc/motd 处在不同阶段，修改其中一个文件并不意味着所有终端都会显示同样内容。\n验证与边界 # 分别测试本地控制台与新建 SSH 会话，确认提示出现的时机。修改 SSH 配置前检查语法，并保留当前会话以便恢复。\n","date":"2015-05-31","externalUrl":null,"permalink":"/posts/ssh-login-banner/","section":"文章归档","summary":"/etc/issue、SSH 的 Banner 配置和 /etc/motd 处在不同阶段，修改其中一个文件并不意味着所有终端都会显示同样内容。","title":"Linux 终端/ssh登录前后的欢迎信息修改","type":"posts"},{"content":" TCP FLAG 标记 # 基于标记的TCP包匹配经常被用于过滤试图打开新连接的TCP数据包。\nTCP标记和他们的意义如下所列：\nF : FIN - 结束; 结束会话 S : SYN - 同步; 表示开始会话请求 R : RST - 复位;中断一个连接 P : PUSH - 推送; 数据包立即发送 A : ACK - 应答 U : URG - 紧急 E : ECE - 显式拥塞提醒回应 W : CWR - 拥塞窗口减少 示例：\n三次握手Three-way Handshake 一个虚拟连接的建立是通过三次握手来实现的\n(B) --\u0026gt; [SYN] --\u0026gt; (A) 假如有服务器A、客户机B. 当B要和A通信时，B首先向A发一个SYN (Synchronize) 标记的包，告诉A请求建立连接.\n注意: 一个 SYN包就是仅SYN标记设为1的TCP包(参见TCP包头Resources). 只有当A收到B发来的SYN包，才可建立连接，除此之外别无他法。\n(B) \u0026lt;-- [SYN/ACK] \u0026lt;--(A) 接着，A收到后会发一个对SYN包的确认包(SYN/ACK)回去，表示对第一个SYN包的确认，并继续握手操作.\n注意: SYN/ACK包是仅SYN 和 ACK 标记为1的包.\n(B) --\u0026gt; [ACK] --\u0026gt; (A) B收到SYN/ACK 包,B发一个确认包(ACK)，通知A连接已建立。至此，三次握手完成，一个TCP连接完成。\n注意: ACK包就是仅ACK 标记设为1的TCP包.\n特别注意：需要注意的是当三此握手完成、连接建立以后，TCP连接的每个包都会设置ACK位\nPS：这就是为何连接跟踪很重要的原因了. 没有连接跟踪,防火墙将无法判断收到的ACK包是否属于一个已经建立的连接.一般的包过滤(Ipchains)收到ACK包时,会让它通过(这绝对不是个好主意). 而当状态型防火墙收到此种包时，它会先在连接表中查找是否属于哪个已建连接，否则丢弃该包\n四次握手Four-way Handshake 四次握手用来关闭已建立的TCP连接\n(B) --\u0026gt; ACK/FIN --\u0026gt; (A)\n(B) \u0026lt;-- ACK \u0026lt;-- (A)\n(B) \u0026lt;-- ACK/FIN \u0026lt;-- (A)\n(B) --\u0026gt; ACK --\u0026gt; (A)\n注意: 由于TCP连接是双向连接, 因此关闭连接需要在两个方向上做。ACK/FIN 包(ACK 和FIN 标记设为1)通常被认为是FIN(终结)包.然而, 由于连接还没有关闭, FIN包总是打上ACK标记. 没有ACK标记而仅有FIN标记的包不是合法的包，并且通常被认为是恶意的\n连接复位Resetting a connection 四次握手不是关闭TCP连接的唯一方法. 有时,如果主机需要尽快关闭连接(或连接超时,端口或主机不可达),RST (Reset)包将被发送. 注意在，由于RST包不是TCP连接中的必须部分, 可以只发送RST包(即不带ACK标记). 但在正常的TCP连接中RST包可以带ACK确认标记。\n注意：RST包是可以不要收到方确认的\n无效的TCP标记Invalid TCP Flags 到目前为止，你已经看到了 SYN, ACK, FIN, 和RST 标记. 另外，还有PSH (Push) 和URG (Urgent)标记.\n最常见的非法组合是SYN/FIN 包. 注意:由于 SYN包是用来初始化连接的, 它不可能和 FIN和RST标记一起出现. 这也是一个恶意攻击.\n由于现在大多数防火墙已知 SYN/FIN 包, 别的一些组合,例如SYN/FIN/PSH, SYN/FIN/RST, SYN/FIN/RST/PSH。很明显，当网络中出现这种包时，很你的网络肯定受到攻击了。\n别的已知的非法包有FIN (无ACK标记)和\u0026quot;NULL\u0026quot;包。如同早先讨论的，由于ACK/FIN包的出现是为了关闭一个TCP连接，那么正常的FIN包总是带有 ACK 标记。\u0026quot;NULL\u0026quot;包就是没有任何TCP标记的包(URG,ACK,PSH,RST,SYN,FIN都为0)。\n到目前为止，正常的网络活动下，TCP协议栈不可能产生带有上面提到的任何一种标记组合的TCP包。当你发现这些不正常的包时，肯定有人对你的网络不怀好意。\n补充阅读 # 补充 TCP 标志位的阅读场景，帮助把报文标记与连接建立、关闭和异常排查联系起来。\n如何理解与使用 # 阅读抓包时，应把 SYN、ACK、FIN、RST 等标志与连接阶段和报文方向一起看；单个标志位不足以还原整次交互。\n验证与边界 # 排查连接失败时对照客户端和服务端两侧记录，区分未收到响应、主动拒绝和正常关闭，再结合应用日志判断原因。\n","date":"2015-05-22","externalUrl":null,"permalink":"/posts/tcp-flags/","section":"文章归档","summary":"阅读抓包时，应把 SYN、ACK、FIN、RST 等标志与连接阶段和报文方向一起看；单个标志位不足以还原整次交互。","title":"TCP中FLAG","type":"posts"},{"content":" 云服务”现在已经快成了一个家喻户晓的词了。如果你不知道PaaS, IaaS 和SaaS的区别，那么也没啥，因为很多人确实不知道。\n“云”其实是互联网的一个隐喻，“云计算”其实就是使用互联网来接入存储或者运行在远程服务器端的应用，数据，或者服务。\n任何一个使用基于互联网的方法来计算，存储和开发的公司，都可以从技术上叫做从事云的公司。然而，不是所有的云公司都一样。不是所有人都是CTO，所以有时候看到云技术背后的一些词可能会比较头疼。\n云也是分层的 # 任何一个在互联网上提供其服务的公司都可以叫做云计算公司。其实云计算分几层的，分别是Infrastructure（基础设施）-as-a- Service，Platform（平台）-as-a-Service，Software（软件）-as-a-Service。基础设施在最下端，平台在 中间，软件在顶端。别的一些“软”的层可以在这些层上面添加。\n[原图暂无法获取](http://ych.u1city.com/UserFiles/20111122/iaas-paas-saas.jpg)\nIaaS: Infrastructure-as-a-Service（基础设施即服务） # 第一层叫做IaaS，有时候也叫做Hardware-as-a-Service，几年前如果你想在办公室或者公司的网站上运行一些企业应用，你需要去买服务器，或者别的高昂的硬件来控制本地应用，让你的业务运行起来。\n但是现在有IaaS，你可以将硬件外包到别的地方去。IaaS公司会提供场外服务器，存储和网络硬件，你可以租用。节省了维护成本和办公场地，公司可以在任何时候利用这些硬件来运行其应用。\n一些大的IaaS公司包括Amazon, Microsoft, VMWare, Rackspace和Red Hat.不过这些公司又都有自己的专长，比如Amazon和微软给你提供的不只是IaaS，他们还会将其计算能力出租给你来host你的网站。\nPaaS: Platform-as-a-Service（平台即服务） # 第二层就是所谓的PaaS，某些时候也叫做中间件。你公司所有的开发都可以在这一层进行，节省了时间和资源。\nPaaS公司在网上提供各种开发和分发应用的解决方案，比如虚拟服务器和操作系统。这节省了你在硬件上的费用，也让分散的工作室之间的合作变得更加容易。网页应用管理，应用设计，应用虚拟主机，存储，安全以及应用开发协作工具等。\n一些大的PaaS提供者有Google App Engine,Microsoft Azure，Force.com,Heroku，Engine Yard。最近兴起的公司有AppFog, Mendix 和 Standing Cloud\nSaaS: Software-as-a-Service（软件即服务） # 第三层也就是所谓SaaS。这一层是和你的生活每天接触的一层，大多是通过网页浏览器来接入。任何一个远程服务器上的应用都可以通过网络来运行，就是SaaS了。\n你消费的服务完全是从网页如Netflix, MOG, Google Apps, Box.net, Dropbox或者苹果的iCloud那里进入这些分类。尽管这些网页服务是用作商务和娱乐或者两者都有，但这也算是云技术的一部分。\n一些用作商务的SaaS应用包括Citrix的GoToMeeting，Cisco的WebEx，Salesforce的CRM，ADP，Workday和SuccessFactors。\n补充阅读 # 把 IaaS、PaaS、SaaS 的区别对应到资源管理、运行环境和应用使用的责任边界。\n如何理解与使用 # 比较时可问三个问题：谁维护操作系统，谁部署应用，谁负责使用和数据配置。服务商托管越多，用户自行控制的底层细节通常越少。\n验证与边界 # 选型还应记录需要保留的控制能力、迁移成本和实际使用方式；分类名称不能单独说明某个产品的可用性、性能或成本。\n","date":"2015-05-15","externalUrl":null,"permalink":"/posts/cloud-service-models/","section":"文章归档","summary":"比较时可问三个问题：谁维护操作系统，谁部署应用，谁负责使用和数据配置。服务商托管越多，用户自行控制的底层细节通常越少。","title":"什么是IaaS, PaaS和SaaS及其区别","type":"posts"},{"content":" 非线程安全是指多线程操作同一个对象可能会出现问题。而线程安全则是多线程操作同一个对象不会有问题。\n线程安全必须要使用很多synchronized关键字来同步控制，所以必然会导致性能的降低。\n所以在使用的时候，如果是多个线程操作同一个对象，那么使用线程安全的Vector；否则，就使用效率更高的ArrayList。\n非线程安全!=不安全\n有人在使用过程中有一个不正确的观点：我的程序是多线程的，不能使用ArrayList要使用Vector，这样才安全。\n非线程安全并不是多线程环境下就不能使用。注意我上面有说到：多线程操作同一个对象。注意是同一个对象。比如最上面那个模拟，就是在主线程中new的一个ArrayList然后多个线程操作同一个ArrayList对象。\n如果是每个线程中new一个ArrayList，而这个ArrayList只在这一个线程中使用，那么肯定是没问题的。\n补充阅读 # 解释 Java 集合线程安全讨论中，共享对象与单线程对象的区别。\n如何理解与使用 # 关键是多个线程是否访问同一个可变对象，而不只是程序是否使用多线程。线程私有的集合与共享集合需要不同的并发设计。\n验证与边界 # 线程安全不只靠 synchronized，也不能认为换成 Vector 就自动保证“先检查再修改”等复合操作原子性。围绕实际共享状态设计并发测试。\n","date":"2015-05-12","externalUrl":null,"permalink":"/posts/java-thread-safety/","section":"文章归档","summary":"关键是多个线程是否访问同一个可变对象，而不只是程序是否使用多线程。线程私有的集合与共享集合需要不同的并发设计。","title":"Java线程安全和非线程安全","type":"posts"},{"content":" 今天好奇，想在nginx上配置下basic认证。在网上搜索了一大把的资料，照着步骤一步一步的配置，最后发现认证失败！！！\n最后查出的原因是：windows上使用明文，linux和Unix系统则使用Crypt加密\n配置如下：\n修改nginx.conf\nlocation / { auth_basic \u0026#34;MMGG.NET\u0026#34;; auth_basic_user_file htpasswd; } 生成htpasswd文件放到nginx的conf目录，windows下请写全路径，且用/来代替\\\nhtpasswd文件在windows下则直接使用明文，如：admin:admin\n但是在linux下就需要使用Crypt加密，方法如下：\n#!/usr/bin/perl use strict; chomp(my $filename=$ARGV[0]); chomp(my $username=$ARGV[1]); chomp(my $password=$ARGV[2]); if (!$filename || !$username || !$password) { print \u0026#34;USAGE: ./crypt.pl filename username password\\n\\n\u0026#34;; } else { open my $fh, \u0026#34;\u0026gt;\u0026gt;\u0026#34;, $filename or die $!; print $fh $username . \u0026#34;:\u0026#34; . crypt($password, $username) . \u0026#34;\\n\u0026#34;; close $fh or die $!; } 拷贝以上代码另存文件为crypt.pl，然后加权限，chmod +x ./crypt.pl\n最后执行：./crypt htpasswd admin admin\n拷贝当前目录下的htpasswd文件到nginx的conf目录，重启或重载nginx即可。\n补充阅读 # 说明 Nginx Basic Auth 的认证配置、密码文件路径与排错方向。\n如何理解与使用 # auth_basic_user_file 指向认证文件，文件格式及密码摘要应按所用版本文档确认；原文把 Windows 与明文密码简单对应的说法不能作为通用规则。\n验证与边界 # 区分未提供凭据时的 401、错误凭据被拒绝和正确凭据成功三个结果，同时检查工作进程读取文件的权限。认证接口应通过 HTTPS 使用。\n参考：Nginx Basic Auth（本次补充核对）。\n","date":"2015-04-21","externalUrl":null,"permalink":"/posts/nginx-basic-auth/","section":"文章归档","summary":"auth_basic_user_file 指向认证文件，文件格式及密码摘要应按所用版本文档确认；原文把 Windows 与明文密码简单对应的说法不能作为通用规则。","title":"有关nginx的basic auth认证问题","type":"posts"},{"content":" 解决方法：打开nginx主配置文件nginx.conf，找到http{}段，添加 client_max_body_size 20m;\n重载NGINX\n./nginx -s reload\n补充阅读 # 解释 Nginx 413 与 client_max_body_size 的关系，并补充配置范围和上传链路的检查方法。\n如何理解与使用 # client_max_body_size 限制请求体大小，原文 20m 是示例值；应根据实际上传需求设置在生效的 http、server 或 location 范围内。\n验证与边界 # 先检查配置语法，再重载对应实例。若仍失败，核对入口代理和后端应用各自的大小限制；小文件成功、大文件失败能帮助确认限制位置。\n参考：Nginx client_max_body_size（本次补充核对）。\n","date":"2015-04-13","externalUrl":null,"permalink":"/posts/nginx-413/","section":"文章归档","summary":"client_max_body_size 限制请求体大小，原文 20m 是示例值；应根据实际上传需求设置在生效的 http、server 或 location 范围内。","title":"Nginx出现“413 Request Entity Too Large”错误解决方法","type":"posts"},{"content":" 最简单的方法那就是pptpd和ppp全都yum安装，让系统自动判断和找寻ppp和pptp对应版本，很爽的。方法如下:\n加入yum源：\nrpm -Uvh http://poptop.sourceforge.net/yum/stable/rhel6/pptp-release-current.noarch.rpm 然后yum安装pptpd：\nyum install -y pptpd 补充阅读 # 说明 CentOS 旧版 pptpd 安装笔记的范围，以及安装软件包后还需要完成哪些验证。\n如何理解与使用 # 原文记录的是通过软件源安装 pptpd，并非完整的 VPN 部署流程；账号、地址分配、路由和防火墙还需要结合拓扑设置。\n验证与边界 # 先确认仓库与系统版本匹配，再验证拨号、内网访问和上网这三个不同目标。此文保留为旧环境记录，不承诺旧仓库当前仍可直接使用。\n","date":"2015-03-20","externalUrl":null,"permalink":"/posts/centos-pptp/","section":"文章归档","summary":"原文记录的是通过软件源安装 pptpd，并非完整的 VPN 部署流程；账号、地址分配、路由和防火墙还需要结合拓扑设置。","title":"最简单的centos安装pptpd的办法","type":"posts"},{"content":" 以下示例中的 YOUR_EMAIL_ADDRESS 是邮箱占位符，使用前请替换为自己的地址。\n:global mailip :set mailip [:resolve smtp.bbb.net] :global mailuser \u0026#34;YOUR_EMAIL_ADDRESS\u0026#34; :global mailpw \u0026#34;xxx\u0026#34; :global tomail \u0026#34;YOUR_EMAIL_ADDRESS\u0026#34; /tool e-mail set from=YOUR_EMAIL_ADDRESS address=$mailip password=$mailpw user=$mailuser port=25 export file=rosbackup :delay 10 /tool e-mail send file=rosbackup.rsc to=$tomail body=\u0026#34; $[/system clock get date] $[/system clock get time]\u0026#34; subject=\u0026#34;ROS备份 $[/system clock get date] $[/system clock get time] \u0026#34; :log info (\u0026#34;ROS备份文件已发送 \u0026#34; . [/sys cl get time] . \u0026#34; \u0026#34; . [/sys cl get date]) 补充阅读 # 解释 RouterOS 导出配置并邮件备份的流程，区分生成备份、发送和恢复验证。\n如何理解与使用 # 示例先导出 .rsc 文件，再通过邮件发送；需要替换 SMTP 设置、账号占位符和目标地址，并确认设备时间及名称解析正常。\n验证与边界 # 检查邮件附件内容是否完整，同时评估导出是否包含敏感配置。收到附件只能证明传输完成，恢复能力仍需在隔离设备上演练。\n","date":"2015-02-09","externalUrl":null,"permalink":"/posts/routeros-mail-backup/","section":"文章归档","summary":"示例先导出 .rsc 文件，再通过邮件发送；需要替换 SMTP 设置、账号占位符和目标地址，并确认设备时间及名称解析正常。","title":"Ros自动备份到邮件","type":"posts"},{"content":" 你选择使用接口和抽象类的依据是什么？ 接口和抽象类的概念不一样。接口是对动作的抽象，抽象类是对根源的抽象。抽象类表示的是，这个对象是什么；接口表示的是，这个对象能做什么。比如，男人，女人，这两个类（如果是类的话……），他们的抽象类是人。说明，他们都是人。人可以吃东西，狗也可以吃东西，你可以把“吃东西”定义成一个接口，然后让这些类去实现它.所以，在高级语言上，一个类只能继承一个类（抽象类）(正如人不可能同时是生物和非生物)，但是可以实现多个接口(吃饭接口、走路接口)。第一点． 接口是抽象类的变体，接口中所有的方法都是抽象的。而抽象类是声明方法的存在而不去实现它的类。 第二点． 接口可以继承，抽象类不行【抽象类也可以继承抽象类】 第三点． 接口定义方法，不能实现，而抽象类可以实现部分方法【抽象方法不实现，子类实现】。 第四点． 接口中基本数据类型为static 而抽类象不是的。当你关注一个事物的本质的时候，用抽象类；当你关注一个操作的时候，用接口。 接口可以实现也可以继承，抽象类不行 抽象类的功能要远超过接口，但是，定义抽象类的代价高。因为高级语言来说（从实际设计上来说也是）每个类只能继承一个类。在这个类中，你必须继承或编写出其所有子类的所有共性。虽然接口在功能上会弱化许多，但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口。在设计阶段会降低难度的。\n补充阅读 # 比较 Java 接口与抽象类的建模侧重点，并补充旧版语法描述需要注意的变化。\n如何理解与使用 # 接口适合表达可替换的行为契约，抽象类适合共享状态或实现；两者可以共同使用。原文用“能做什么”和“是什么”帮助入门，但不能代替具体设计约束。\n验证与边界 # “接口不能实现方法”是旧式概括；现代 Java 接口支持默认方法等能力。选择时还要考虑兼容性、继承关系和状态共享，而不是仅凭方法能否有实现。\n","date":"2015-01-01","externalUrl":null,"permalink":"/posts/java-interface-abstract/","section":"文章归档","summary":"接口适合表达可替换的行为契约，抽象类适合共享状态或实现；两者可以共同使用。原文用“能做什么”和“是什么”帮助入门，但不能代替具体设计约束。","title":"接口和抽象类","type":"posts"},{"content":" 标记：\n/ip firewall mangle add action=mark-packet chain=postrouting new-packet-mark=QoS_1_Up \\ out-interface=ADSL passthrough=no protocol=icmp add action=mark-packet chain=postrouting dst-port=\\ 8291,20-25,110,1720-1723,3389,3306,3690,15906,35719 new-packet-mark=\\ QoS_2_Up out-interface=ADSL passthrough=no protocol=tcp add action=mark-packet chain=postrouting new-packet-mark=QoS_2_Up \\ out-interface=ADSL passthrough=no protocol=gre add action=mark-packet chain=postrouting dst-port=80,443 new-packet-mark=\\ QoS_3_Up out-interface=ADSL packet-size=0-666 passthrough=no protocol=tcp \\ tcp-flags=syn add action=mark-packet chain=postrouting dst-port=80,443 new-packet-mark=\\ QoS_3_Up out-interface=ADSL packet-size=0-123 passthrough=no protocol=tcp \\ tcp-flags=ack add action=mark-packet chain=postrouting dst-port=53,123 new-packet-mark=\\ QoS_1_Up out-interface=ADSL passthrough=no protocol=udp add action=mark-packet chain=postrouting connection-bytes=0-250000 \\ new-packet-mark=QoS_2_Up out-interface=ADSL passthrough=no protocol=tcp add action=mark-packet chain=postrouting connection-bytes=250000-500000 \\ new-packet-mark=QoS_3_Up out-interface=ADSL passthrough=no protocol=tcp add action=mark-packet chain=postrouting connection-bytes=500000-1000000 \\ new-packet-mark=QoS_4_Up out-interface=ADSL passthrough=no protocol=tcp add action=mark-packet chain=postrouting connection-bytes=1000000-3000000 \\ new-packet-mark=QoS_5_Up out-interface=ADSL passthrough=no protocol=tcp add action=mark-packet chain=postrouting connection-bytes=3000000-6000000 \\ new-packet-mark=QoS_6_Up out-interface=ADSL passthrough=no protocol=tcp add action=mark-packet chain=postrouting connection-bytes=6000000-0 \\ new-packet-mark=QoS_7_Up out-interface=ADSL passthrough=no protocol=tcp add action=mark-packet chain=postrouting new-packet-mark=QoS_3_Up \\ out-interface=ADSL packet-size=0-666 passthrough=no protocol=tcp \\ tcp-flags=syn add action=mark-packet chain=postrouting new-packet-mark=QoS_3_Up \\ out-interface=ADSL packet-size=0-123 passthrough=no protocol=tcp \\ tcp-flags=ack add action=mark-packet chain=postrouting new-packet-mark=QoS_4_Up \\ out-interface=ADSL packet-size=0-50 passthrough=no protocol=udp add action=mark-packet chain=postrouting new-packet-mark=QoS_5_Up \\ out-interface=ADSL packet-size=51-256 passthrough=no protocol=udp add action=mark-packet chain=postrouting new-packet-mark=QoS_6_Up \\ out-interface=ADSL packet-size=256-1024 passthrough=no protocol=udp add action=mark-packet chain=postrouting new-packet-mark=QoS_7_Up \\ out-interface=ADSL passthrough=no protocol=udp add action=mark-packet chain=postrouting new-packet-mark=QoS_8_Up \\ out-interface=ADSL p2p=all-p2p passthrough=no add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_1_Down passthrough=no protocol=icmp add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_2_Down passthrough=no protocol=tcp src-port=\\ 8291,20-25,110,1720-1723,3389,3306,3690,15906,35719 add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_2_Down passthrough=no protocol=gre add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_3_Down packet-size=0-666 passthrough=no protocol=tcp src-port=80,443 \\ tcp-flags=syn add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_3_Down packet-size=0-123 passthrough=no protocol=tcp src-port=80,443 \\ tcp-flags=ack add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_1_Down passthrough=no protocol=udp src-port=53,123 add action=mark-packet chain=prerouting connection-bytes=0-250000 \\ in-interface=ADSL new-packet-mark=QoS_2_Down passthrough=no protocol=tcp add action=mark-packet chain=prerouting connection-bytes=250000-500000 \\ in-interface=ADSL new-packet-mark=QoS_3_Down passthrough=no protocol=tcp add action=mark-packet chain=prerouting connection-bytes=500000-1000000 \\ in-interface=ADSL new-packet-mark=QoS_4_Down passthrough=no protocol=tcp add action=mark-packet chain=prerouting connection-bytes=1000000-3000000 \\ in-interface=ADSL new-packet-mark=QoS_5_Down passthrough=no protocol=tcp add action=mark-packet chain=prerouting connection-bytes=3000000-6000000 \\ in-interface=ADSL new-packet-mark=QoS_6_Down passthrough=no protocol=tcp add action=mark-packet chain=prerouting connection-bytes=6000000-0 \\ in-interface=ADSL new-packet-mark=QoS_7_Down passthrough=no protocol=tcp add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_3_Down packet-size=0-666 passthrough=no protocol=tcp tcp-flags=syn add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_3_Down packet-size=0-123 passthrough=no protocol=tcp tcp-flags=ack add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_4_Down packet-size=0-50 passthrough=no protocol=udp add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_5_Down packet-size=51-256 passthrough=no protocol=udp add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_6_Down packet-size=256-1024 passthrough=no protocol=udp add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_7_Down passthrough=no protocol=udp add action=mark-packet chain=prerouting in-interface=ADSL new-packet-mark=\\ QoS_8_Down p2p=all-p2p passthrough=no 以上脚本，只需要修改\nADSL：外网接口\nqiao：桥接口，或者是内网网卡接口。如果有多个内网网卡，建立放在一个桥内管理，或者采用交换机模式管理。\n（本文属于原创，转载请注明出处：http://www.skydw.com）\n端口\n8291,20-25,110,1720-1723,3389,3306,3690,15906,35719 请修改成你要优先的端口。\nHTB：\n/queue simple add limit-at=128k/1M max-limit=500k/8M name=PCQ queue=\\ pcq-upload-default/pcq-download-default target=192.168.88.0/24 add limit-at=128k/1M max-limit=500k/8M name=queue1 packet-marks=\\ QoS_1_Up,QoS_1_Down parent=PCQ priority=1/1 queue=\\ pcq-upload-default/pcq-download-default target=192.168.88.0/24 add limit-at=128k/1M max-limit=500k/8M name=queue2 packet-marks=\\ QoS_2_Up,QoS_2_Down parent=PCQ priority=2/2 queue=\\ pcq-upload-default/pcq-download-default target=192.168.88.0/24 add limit-at=128k/1M max-limit=500k/8M name=queue3 packet-marks=\\ QoS_3_Up,QoS_3_Down parent=PCQ priority=3/3 queue=\\ pcq-upload-default/pcq-download-default target=192.168.88.0/24 add limit-at=128k/1M max-limit=500k/8M name=queue4 packet-marks=\\ QoS_4_Up,QoS_4_Down parent=PCQ priority=4/4 queue=\\ pcq-upload-default/pcq-download-default target=192.168.88.0/24 add limit-at=128k/1M max-limit=500k/8M name=queue5 packet-marks=\\ QoS_5_Up,QoS_5_Down parent=PCQ priority=5/5 queue=\\ pcq-upload-default/pcq-download-default target=192.168.88.0/24 add limit-at=128k/1M max-limit=500k/8M name=queue6 packet-marks=\\ QoS_6_Up,QoS_6_Down parent=PCQ priority=6/6 queue=\\ pcq-upload-default/pcq-download-default target=192.168.88.0/24 add limit-at=128k/1M max-limit=500k/8M name=queue7 packet-marks=\\ QoS_7_Up,QoS_7_Down parent=PCQ priority=7/7 queue=\\ pcq-upload-default/pcq-download-default target=192.168.88.0/24 add limit-at=128k/1M max-limit=500k/8M name=queue8 packet-marks=\\ QoS_8_Up,QoS_8_Down parent=PCQ queue=\\ pcq-upload-default/pcq-download-default target=192.168.88.0/24 以上脚本，只需修改\n192.168.88.0/24 修改成您自己的网段。（代码为上行512K，下行8M的代码） limit-at=128k/1M //这行的意思是保证上行128K，下行1M。 max-limit=500k/8M //这行的意思是最大上行和下行，这里我取的是最大。 pcq-upload-default/pcq-download-default 这是默认的，不需要做什么修改。 （本文属于原创，转载请注明出处：http://www.znl.net）\n这里多说几句，要做PCQ，一定要在simple queue里做。那些人在queue tree中做，虽然有一点效果，但只是起到了htb的作用，却没有pcq的作用，pcq是基于IP来做的。\n纯属自己理解，勿喷。\nOK！请尽情的享受吧。\n补充阅读 # 补充 RouterOS 6.0 单线 QoS 配置的阅读顺序，说明接口、网段和优先端口的替换位置。\n如何理解与使用 # 先读 mangle 标记，再读队列如何引用标记；ADSL、桥接口与内网网段是这份配置的重要环境参数，不能只替换其中一个。\n验证与边界 # 用真实流量检查各标记是否命中，并在链路繁忙时比较优先业务与普通业务表现。文中端口和带宽属于历史示例，应按当前需求调整。\n","date":"2014-09-18","externalUrl":null,"permalink":"/posts/routeros-qos-v6/","section":"文章归档","summary":"先读 mangle 标记，再读队列如何引用标记；ADSL、桥接口与内网网段是这份配置的重要环境参数，不能只替换其中一个。","title":"Qos 单线(6.0适用)【原创】","type":"posts"},{"content":" 前言:\n众所周知阿里云的云服务器很不错,最近又推出了rds,5块可以用一年.所以搞了一个.遗憾的是,阿里云的RDS通过外网访问还要收费,所以...有了以下方式来偷流量,原理你们都懂的...\n1、 首先应该做的是/etc/sysctl.conf配置文件的 net.ipv4.ip_forward = 1 默认是0\n这样允许iptalbes FORWARD。\nvim /etc/sysctl.conf 找到 net.ipv4.ip_forward 改成 1\n2、之前一直没做成功,后来经过多次尝试总结了,主要是要2条,一条是做目的地址转向,还有一条是做源地址转向.代码如下:\niptables -t nat -F \u0026lt;p\u0026gt;iptables -t nat -A PREROUTING -p tcp --dport 3306 -j DNAT --to-destination 10.146.5.xx:3306\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;iptables -t nat -I POSTROUTING -p tcp -d 10.146.5.xx -j SNAT --to-source 10.163.215.20\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;/etc/init.d/iptables save\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;service iptables restart\u0026lt;/p\u0026gt; 做个笔记而已,大家一定要记得,做了目的地址还要做源地址,否则永远都不会成功.\n补充阅读 # 解释旧版 MySQL 端口转发记录中的 DNAT、SNAT 与返回路径，帮助理解双向流量。\n如何理解与使用 # DNAT 改变请求目标，SNAT 改变源地址；是否需要两者，取决于后端如何把响应送回客户端。原文最后的结论对应当时的网络拓扑，并非所有转发都必须同时设置。\n验证与边界 # 配置前记录现有 NAT 规则、接口和路由，避免原文清空规则的命令影响其他业务。验证时分别检查客户端连接、后端看到的来源和返回流量。\n","date":"2014-08-17","externalUrl":null,"permalink":"/posts/mysql-port-forward/","section":"文章归档","summary":"DNAT 改变请求目标，SNAT 改变源地址；是否需要两者，取决于后端如何把响应送回客户端。原文最后的结论对应当时的网络拓扑，并非所有转发都必须同时设置。","title":"阿里云服务器mysql端口转发","type":"posts"},{"content":" 我这里直接说怎么在终端安装Luci，所以要你的设备能连上互联网，能SSH或者直接TTl终端进去也行；好开始说\n安装Web管理界面LuCY；\n1.打开显示的路由器Linux终端中，输入“opkg update”，开始下载Packages.gz并更新； 2.输入“opkg install luci”，安装LuCY主体，先开始自动下载各种关联库，下载完会自动安装配置。 3.输入“/etc/init.d/uhttpd enable”回车，打开uhttpd服务； 4.输入“/etc/init.d/uhttpd start”回车，让uhttpd自启动； 5.在电脑端的浏览器中输入“xxx.xxx.xxx.xxx”，可访问路由器就表示LuCY安装成功；\n别忘记3、4两步，luci必须依靠uhttpd服务才能访问。\n补充阅读 # 梳理 OpenWrt 安装 LuCI 的软件包、Web 服务启动和浏览器访问三个环节。\n如何理解与使用 # 先确认设备联网、软件源与固件版本匹配，再安装 LuCI 及相应依赖；enable 对应开机启用，start 对应立即启动，两者用途不同。\n验证与边界 # 完成后检查服务状态并从管理网络访问设备地址；包安装成功但网页打不开时，应继续核对监听地址、端口和防火墙，而不是反复安装。\n","date":"2014-08-11","externalUrl":null,"permalink":"/posts/openwrt-luci/","section":"文章归档","summary":"先确认设备联网、软件源与固件版本匹配，再安装 LuCI 及相应依赖；enable 对应开机启用，start 对应立即启动，两者用途不同。","title":"OpenWrt安装LUCI","type":"posts"},{"content":"TCP端口=================================================================\n7 = 回显\n9 = 丢弃\n11 = 在线用户\n13 = 时间服务\n15 = 网络状态\n17 = 每日引用\n18 = 消息发送\n19 = 字符发生器\n20 = ftp数据\n21 = 文件传输\n22 = SSH端口\n23 = 远程终端\n25 = 发送邮件\n31 = Masters Paradise木马\n37 = 时间\n39 = 资源定位协议\n41 = DeepThroat木马\n42 = WINS 主机名服务\n43 = WhoIs服务\n58 = DMSetup木马\n59 = 个人文件服务\n63 = WHOIS端口\n69 = TFTP服务\n70 = 信息检索\n79 = 查询在线用户\n80 = WEB网页\n88 = Kerberros5认证\n101 = 主机名\n102 = ISO\n107 = 远程登录终端\n109 = pop2邮件\n110 = pop3邮件\n111 = SUN远程控制\n113 = 身份验证\n117 = UUPC\n119 = nntp新闻组\n121 = JammerKillah木马\n135 = 本地服务\n138 = 隐形大盗\n139 = 文件共享\n143 = IMAP4邮件\n146 = FC-Infector木马\n158 = 邮件服务\n170 = 打印服务\n179 = BGP\n194 = IRC PORT\n213 = TCP OVER IPX\n220 = IMAP3邮件\n389 = 目录服务\n406 = IMSP PORT\n411 = DC++\n421 = TCP Wrappers\n443 = 安全WEB访问\n445 = SMB(交换服务器消息块)\n456 = Hackers Paradise木马\n464 = Kerberros认证\n512 = 远程执行或卫星通讯\n513 = 远程登录与查询\n514 = SHELL/系统日志\n515 = 打印服务\n517 = Talk\n518 = 网络聊天\n520 = EFS\n525 = 时间服务\n526 = 日期更新\n530 = RPC\n531 = RASmin木马\n532 = 新闻阅读\n533 = 紧急广播\n540 = UUCP\n543 = Kerberos登录\n544 = 远程shell\n550 = who\n554 = RTSP\n555 = Ini-Killer木马\n556 = 远程文件系统\n560 = 远程监控\n561 = 监控\n636 = 安全目录服务\n666 = Attack FTP木马\n749 = Kerberos管理\n750 = Kerberos V4\n911 = Dark Shadow木马\n989 = FTPS\n990 = FTPS\n992 = TelnetS\n993 = IMAPS\n999 = DeepThroat木马\n1001 = Silencer木马\n1010 = Doly木马\n1011 = Doly木马\n1012 = Doly木马\n1015 = Doly木马\n1024 = NetSpy木马\n1042 = Bla木马\n1045 = RASmin木马\n1080 = SOCKS代理\n1090 = Extreme木马\n1095 = Rat木马\n1097 = Rat木马\n1098 = Rat木马\n1099 = Rat木马\n1109 = Kerberos POP\n1167 = 私用电话\n1170 = Psyber Stream Server\n1214 = KAZAA下载\n1234 = Ultors/恶鹰木马\n1243 = Backdoor/SubSeven木马\n1245 = VooDoo Doll木马\n1349 = BO DLL木马\n1352 = Lotus Notes\n1433 = SQL SERVER\n1492 = FTP99CMP木马\n1494 = CITRIX\n1503 = Netmeeting\n1512 = WINS解析\n1524 = IngresLock后门\n1600 = Shivka-Burka木马\n1630 = 网易泡泡\n1701 = L2TP\n1720 = H323\n1723 = PPTP(虚拟专用网)\n1731 = Netmeeting\n1755 = 流媒体服务\n1807 = SpySender木马\n1812 = Radius认证\n1813 = Radius评估\n1863 = MSN聊天\n1981 = ShockRave木马\n1999 = Backdoor木马\n2000 = TransScout-Remote-Explorer木马\n2001 = TransScout木马\n2002 = TransScout/恶鹰木马\n2003 = TransScout木马\n2004 = TransScout木马\n2005 = TransScout木马\n2023 = Ripper木马\n2049 = NFS服务器\n2053 = KNETD\n2115 = Bugs木马\n2140 = Deep Throat木马\n2401 = CVS\n2535 = 恶鹰\n2565 = Striker木马\n2583 = WinCrash木马\n2773 = Backdoor/SubSeven木马\n2774 = SubSeven木马\n2801 = Phineas Phucker木马\n2869 = UPNP(通用即插即用)\n3024 = WinCrash木马\n3050 = InterBase\n3128 = squid代理\n3129 = Masters Paradise木马\n3150 = DeepThroat木马\n3306 = MYSQL\n3389 = 远程桌面\n3544 = MSN语音\n3545 = MSN语音\n3546 = MSN语音\n3547 = MSN语音\n3548 = MSN语音\n3549 = MSN语音\n3550 = MSN语音\n3551 = MSN语音\n3552 = MSN语音\n3553 = MSN语音\n3554 = MSN语音\n3555 = MSN语音\n3556 = MSN语音\n3557 = MSN语音\n3558 = MSN语音\n3559 = MSN语音\n3560 = MSN语音\n3561 = MSN语音\n3562 = MSN语音\n3563 = MSN语音\n3564 = MSN语音\n3565 = MSN语音\n3566 = MSN语音\n3567 = MSN语音\n3568 = MSN语音\n3569 = MSN语音\n3570 = MSN语音\n3571 = MSN语音\n3572 = MSN语音\n3573 = MSN语音\n3574 = MSN语音\n3575 = MSN语音\n3576 = MSN语音\n3577 = MSN语音\n3578 = MSN语音\n3579 = MSN语音\n3700 = Portal of Doom木马\n4080 = WebAdmin\n4081 = WebAdmin+SSL\n4092 = WinCrash木马\n4267 = SubSeven木马\n4443 = AOL MSN\n4567 = File Nail木马\n4590 = ICQ木马\n4661 = 电驴下载\n4662 = 电驴下载\n4663 = 电驴下载\n4664 = 电驴下载\n4665 = 电驴下载\n4666 = 电驴下载\n4899 = Radmin木马\n5000 = Sokets-de木马\n5000 = UPnP(通用即插即用)\n5001 = Back Door Setup木马\n5060 = SIP\n5168 = 高波蠕虫\n5190 = AOL MSN\n5321 = Firehotcker木马\n5333 = NetMonitor木马\n5400 = Blade Runner木马\n5401 = Blade Runner木马\n5402 = Blade Runner木马\n5550 = JAPAN xtcp木马\n5554 = 假警察蠕虫\n5555 = ServeMe木马\n5556 = BO Facil木马\n5557 = BO Facil木马\n5569 = Robo-Hack木马\n5631 = pcAnywhere\n5632 = pcAnywhere\n5742 = WinCrash木马\n5800 = VNC端口\n5801 = VNC端口\n5890 = VNC端口\n5891 = VNC端口\n5892 = VNC端口\n6267 = 广外女生\n6400 = The Thing木马\n6665 = IRC\n6666 = IRC SERVER PORT\n6667 = 小邮差\n6668 = IRC\n6669 = IRC\n6670 = DeepThroat木马\n6711 = SubSeven木马\n6771 = DeepThroat木马\n6776 = BackDoor-G木马\n6881 = BT下载\n6882 = BT下载\n6883 = BT下载\n6884 = BT下载\n6885 = BT下载\n6886 = BT下载\n6887 = BT下载\n6888 = BT下载\n6889 = BT下载\n6890 = BT下载\n6939 = Indoctrination木马\n6969 = GateCrasher/Priority木马\n6970 = GateCrasher木马\n7000 = Remote Grab木马\n7001 = Windows messager\n7070 = RealAudio控制口\n7215 = Backdoor/SubSeven木马\n7300 = 网络精灵木马\n7301 = 网络精灵木马\n7306 = 网络精灵木马\n7307 = 网络精灵木马\n7308 = 网络精灵木马\n7424 = Host Control Trojan\n7467 = Padobot\n7511 = 聪明基因\n7597 = QaZ木马\n7626 = 冰河木马\n7789 = Back Door Setup/ICKiller木马\n8011 = 无赖小子\n8102 = 网络神偷\n8181 = 灾飞\n9408 = 山泉木马\n9535 = 远程管理\n9872 = Portal of Doom木马\n9873 = Portal of Doom木马\n9874 = Portal of Doom木马\n9875 = Portal of Doom木马\n9898 = 假警察蠕虫\n9989 = iNi-Killer木马\n10066 = Ambush Trojan\n10067 = Portal of Doom木马\n10167 = Portal of Doom木马\n10168 = 恶邮差\n10520 = Acid Shivers木马\n10607 = COMA木马\n11000 = Senna Spy木马\n11223 = Progenic木马\n11927 = Win32.Randin\n12076 = GJammer木马\n12223 = Keylogger木马\n12345 = NetBus木马\n12346 = GabanBus木马\n12361 = Whack-a-mole木马\n12362 = Whack-a-mole木马\n12363 = Whack-a-Mole木马\n12631 = WhackJob木马\n13000 = Senna Spy木马\n13223 = PowWow聊天\n14500 = PC Invader木马\n14501 = PC Invader木马\n14502 = PC Invader木马\n14503 = PC Invader木马\n15000 = NetDemon木马\n15382 = SubZero木马\n16484 = Mosucker木马\n16772 = ICQ Revenge木马\n16969 = Priority木马\n17072 = Conducent广告\n17166 = Mosaic木马\n17300 = Kuang2 the virus Trojan\n17449 = Kid Terror Trojan\n17499 = CrazzyNet Trojan\n17500 = CrazzyNet Trojan\n17569 = Infector Trojan\n17593 = Audiodoor Trojan\n17777 = Nephron Trojan\n19191 = 蓝色火焰\n19864 = ICQ Revenge木马\n20001 = Millennium木马\n20002 = Acidkor Trojan\n20005 = Mosucker木马\n20023 = VP Killer Trojan\n20034 = NetBus 2 Pro木马\n20808 = QQ女友\n21544 = GirlFriend木马\n22222 = Proziack木马\n23005 = NetTrash木马\n23006 = NetTrash木马\n23023 = Logged木马\n23032 = Amanda木马\n23432 = Asylum木马\n23444 = 网络公牛\n23456 = Evil FTP木马\n23456 = EvilFTP-UglyFTP木马\n23476 = Donald-Dick木马\n23477 = Donald-Dick木马\n25685 = Moonpie木马\n25686 = Moonpie木马\n25836 = Trojan-Proxy\n25982 = Moonpie木马\n26274 = Delta Source木马\n27184 = Alvgus 2000 Trojan\n29104 = NetTrojan木马\n29891 = The Unexplained木马\n30001 = ErrOr32木马\n30003 = Lamers Death木马\n30029 = AOL木马 30100 = NetSphere木马\n30101 = NetSphere木马\n30102 = NetSphere木马\n30103 = NetSphere 木马\n30103 = NetSphere木马\n30133 = NetSphere木马\n30303 = Sockets de Troie\n30947 = Intruse木马\n31336 = Butt Funnel木马\n31337 = Back-Orifice木马\n31338 = NetSpy DK 木马\n31339 = NetSpy DK 木马\n31666 = BOWhack木马\n31785 = Hack Attack木马\n31787 = Hack Attack木马\n31788 = Hack-A-Tack木马\n31789 = Hack Attack木马\n31791 = Hack Attack木马\n31792 = Hack-A-Tack木马\n32100 = Peanut Brittle木马\n32418 = Acid Battery木马\n33333 = Prosiak木马\n33577 = Son of PsychWard木马\n33777 = Son of PsychWard木马\n33911 = Spirit 2000/2001木马\n34324 = Big Gluck木马\n34555 = Trinoo木马\n35555 = Trinoo木马\n36549 = Trojan-Proxy\n37237 = Mantis Trojan\n40412 = The Spy木马\n40421 = Agent 40421木马\n40422 = Master-Paradise木马\n40423 = Master-Paradise木马\n40425 = Master-Paradise木马\n40426 = Master-Paradise木马\n41337 = Storm木马\n41666 = Remote Boot tool木马\n46147 = Backdoor.sdBot\n47262 = Delta Source木马\n49301 = Online KeyLogger木马\n50130 = Enterprise木马\n50505 = Sockets de Troie木马\n50766 = Fore木马\n51996 = Cafeini木马\n53001 = Remote Windows Shutdown木马\n54283 = Backdoor/SubSeven木马\n54320 = Back-Orifice木马\n54321 = Back-Orifice木马\n55165 = File Manager木马\n57341 = NetRaider木马\n58339 = Butt Funnel木马\n60000 = DeepThroat木马\n60411 = Connection木马\n61348 = Bunker-hill木马\n61466 = Telecommando木马\n61603 = Bunker-hill木马\n63485 = Bunker-hill木马\n65000 = Devil木马\n65390 = Eclypse木马\n65432 = The Traitor木马\n65535 = Rc1木马\nUDP端口**=================================================================**\n31 = Masters Paradise木马\n41 = DeepThroat木马\n53 = 域名解析\n67 = 动态IP服务\n68 = 动态IP客户端\n135 = 本地服务\n137 = NETBIOS名称\n138 = NETBIOS DGM服务\n139 = 文件共享\n146 = FC-Infector木马\n161 = SNMP服务\n162 = SNMP查询\n445 = SMB(交换服务器消息块)\n500 = VPN密钥协商\n666 = Bla木马\n999 = DeepThroat木马\n1027 = 灰鸽子\n1042 = Bla木马\n1561 = MuSka52木马\n1900 = UPNP(通用即插即用)\n2140 = Deep Throat木马\n2989 = Rat木马\n3129 = Masters Paradise木马\n3150 = DeepThroat木马\n3700 = Portal of Doom木马\n4000 = QQ聊天\n4006 = 灰鸽子\n5168 = 高波蠕虫\n6670 = DeepThroat木马\n6771 = DeepThroat木马\n6970 = ReadAudio音频数据\n8000 = QQ聊天\n8099 = VC远程调试\n8225 = 灰鸽子\n9872 = Portal of Doom木马\n9873 = Portal of Doom木马\n9874 = Portal of Doom木马\n9875 = Portal of Doom木马\n10067 = Portal of Doom木马\n10167 = Portal of Doom木马\n22226 = 高波蠕虫\n26274 = Delta Source木马\n31337 = Back-Orifice木马\n31785 = Hack Attack木马\n31787 = Hack Attack木马\n31788 = Hack-A-Tack木马\n31789 = Hack Attack木马\n31791 = Hack Attack木马\n31792 = Hack-A-Tack木马\n34555 = Trin00 DDoS木马\n40422 = Master-Paradise木马\n40423 = Master-Paradise木马\n40425 = Master-Paradise木马\n40426 = Master-Paradise木马\n47262 = Delta Source木马\n54320 = Back-Orifice木马\n54321 = Back-Orifice木马\n60000 = DeepThroat木马\n补充阅读 # 说明常见 TCP、UDP 端口表的查询用途，以及端口编号与实际服务识别之间的区别。\n如何理解与使用 # 端口表适合查找协议线索，但管理员可以更改监听端口，同一端口也可能被其他程序使用；历史恶意软件标签不能单独证明系统感染。\n验证与边界 # 结合监听进程、连接方向、目标地址和服务配置判断实际用途。需要制定防火墙规则时，以当前业务需要为依据，而非整张表批量开放。\n","date":"2014-07-29","externalUrl":null,"permalink":"/posts/network-ports/","section":"文章归档","summary":"端口表适合查找协议线索，但管理员可以更改监听端口，同一端口也可能被其他程序使用；历史恶意软件标签不能单独证明系统感染。","title":"常用端口列表","type":"posts"},{"content":" 1 在根目录下建立root目录\n2 拷贝/etc/skel目录下的.bash_logout和.bashrc和.bash_profile到root目录即可。\n其他的用户也一样，不过要用root用户来拷贝。\n补充阅读 # 解释切换 root 后出现 bash-4.1 提示符时，应怎样检查主目录与 Shell 初始化文件。\n如何理解与使用 # 提示符变化常与用户环境和初始化文件有关，先确认目标账号的主目录及登录方式，再看对应文件是否存在、所有者是否正确。\n验证与边界 # 原文给出从 /etc/skel 补齐配置的思路。复制前保留已有文件，重新开启会话验证，避免覆盖原本自定义的环境设置。\n","date":"2014-07-01","externalUrl":null,"permalink":"/posts/bash-root-prompt/","section":"文章归档","summary":"提示符变化常与用户环境和初始化文件有关，先确认目标账号的主目录及登录方式，再看对应文件是否存在、所有者是否正确。","title":"Linux命令行在su root后突然变成bash-4.1$的办法","type":"posts"},{"content":"210.72.145.44 (国家授时中心服务器IP地址)\n133.100.11.8 日本 福冈大学\ntime-a.nist.gov 129.6.15.28 NIST, Gaithersburg, Maryland\ntime-b.nist.gov 129.6.15.29 NIST, Gaithersburg, Maryland\ntime-a.timefreq.bldrdoc.gov 132.163.4.101 NIST, Boulder, Colorado\ntime-b.timefreq.bldrdoc.gov 132.163.4.102 NIST, Boulder, Colorado\ntime-c.timefreq.bldrdoc.gov 132.163.4.103 NIST, Boulder, Colorado\nutcnist.colorado.edu 128.138.140.44 University of Colorado, Boulder\ntime.nist.gov 192.43.244.18 NCAR, Boulder, Colorado\ntime-nw.nist.gov 131.107.1.10 Microsoft, Redmond, Washington\nnist1.symmetricom.com 69.25.96.13 Symmetricom, San Jose, California\nnist1-dc.glassey.com 216.200.93.8 Abovenet, Virginia\nnist1-ny.glassey.com 208.184.49.9 Abovenet, New York City\nnist1-sj.glassey.com 207.126.98.204 Abovenet, San Jose, California\nnist1.aol-ca.truetime.com 207.200.81.113 TrueTime, AOL facility, Sunnyvale, California\nnist1.aol-va.truetime.com 64.236.96.53 TrueTime, AOL facility, Virginia\n————————————————————————————————————\nntp.sjtu.edu.cn 202.120.2.101 (上海交通大学网络中心NTP服务器地址）\ns1a.time.edu.cn 北京邮电大学\ns1b.time.edu.cn 清华大学\ns1c.time.edu.cn 北京大学\ns1d.time.edu.cn 东南大学\ns1e.time.edu.cn 清华大学\ns2a.time.edu.cn 清华大学\ns2b.time.edu.cn 清华大学\ns2c.time.edu.cn 北京邮电大学\ns2d.time.edu.cn 西南地区网络中心\ns2e.time.edu.cn 西北地区网络中心\ns2f.time.edu.cn 东北地区网络中心\ns2g.time.edu.cn 华东南地区网络中心\ns2h.time.edu.cn 四川大学网络管理中心\ns2j.time.edu.cn 大连理工大学网络中心\ns2k.time.edu.cn CERNET桂林主节点\ns2m.time.edu.cn 北京大学\n补充阅读 # 整理历史 NTP 地址清单的用途，并说明域名、IP、时区与时间同步的区别。\n如何理解与使用 # NTP 用来校准时钟，时区决定时间如何显示；把时区改为上海并不代表机器已与时间源同步。清单中的固定 IP 应视为历史资料。\n验证与边界 # 使用前核对服务提供者当前公布的时间源与访问规则，并检查客户端同步状态、偏移量和网络可达性，不以一次域名解析作为同步成功依据。\n","date":"2014-07-01","externalUrl":null,"permalink":"/posts/ntp-servers/","section":"文章归档","summary":"NTP 用来校准时钟，时区决定时间如何显示；把时区改为上海并不代表机器已与时间源同步。清单中的固定 IP 应视为历史资料。","title":"常用NTP服务器地址及IP","type":"posts"},{"content":"09 @echo off\nset svnlook=\u0026quot;E:\\Program Files (x86)\\VisualSVN Server\\bin\\svnlook.exe\u0026quot;\nsetlocal\nset REPOS=%1\nset TXN=%2\nrem check that logmessage contains at least 10 characters\n%svnlook% log \u0026quot;%REPOS%\u0026quot; -t \u0026quot;%TXN%\u0026quot; | findstr \u0026quot;..........\u0026quot; \u0026gt; nul\nif %errorlevel% gtr 0 goto err\nexit 0\n:err\necho 提交被阻止，请填写关于此次提交的log信息(需大于10个字符[5个汉字])，然后再重新提交! 1\u0026gt;\u0026amp;2\nexit 1\n补充阅读 # 解释 SVN 提交前钩子怎样检查日志长度，以及服务端执行环境需要确认的内容。\n如何理解与使用 # 脚本使用仓库路径和事务参数读取本次提交信息，并以非零退出码阻止不符合要求的提交；它应作为服务端钩子运行。\n验证与边界 # 分别测试空日志、短日志和合格日志，并确认服务账号能运行 svnlook。字符数与字节数可能不同，中文长度条件需要在目标环境实际验证。\n","date":"2014-04-04","externalUrl":null,"permalink":"/posts/svn-hooks/","section":"文章归档","summary":"脚本使用仓库路径和事务参数读取本次提交信息，并以非零退出码阻止不符合要求的提交；它应作为服务端钩子运行。","title":"Svn钩子","type":"posts"},{"content":" 在使用Eclipse编写Java代码时，自动生成的注释信息都是默认是使用的当前登录系统用户名： /**\n@author administrator */ 如果我们想修改成我们自己的名字怎么办呢? 以下介绍的三种方法也可以应用在MyEclipse中 方法一. 修改Eclipse 启动参数 在Eclipse启动时加入启动参数或eclipse.ini中添加一句 -vmargs -Duser.name=Kevin\n方法二. 修改Eclipse代码模板 通过菜单 Window-\u0026gt;Preference -\u0026gt; Java -\u0026gt; Code Style -\u0026gt; Code Templates 在右侧选择Comments,将其中的Types项，然后选右边的\u0026quot;Edit\u0026quot;，进入编辑模式，将 @author ${user} 中的${user}改成你自己的名字即可。\n方法三. 修改操作系统的用户名 控制面板--\u0026gt;计算机管理--\u0026gt;本地用户和组--\u0026gt;用户，使用管理员账户登陆 可以任意修改用户名 ，然后重启电脑，OK 。 注意：XP HOME EDITION 不保证其可用。\n总结：推荐方法一和二，不推荐方法三。\n最好是在建类的时候也加上创建日期如：\n/**\n${tags} @author ${user} @creation ${date} */ 其实是一个很小的问题，不过相信大多数人都遇上过，我反正是遇上好多次了，特别是在Eclipse中使用类的自动注释时，产生的老是是@author Administrator，每次都要手工去改很烦人。每次要么就是一个个手工改注释，要么就是把登陆用户改了\n搜了国内很多地方都没有人知道方法，最后在官网的一个角落里找到了答案\n在Eclipse启动时加入参数 -vmargs -Duser.name=\u0026quot;Phil\u0026quot;\n补充阅读 # 说明 Eclipse 自动注释中用户变量的来源，以及修改模板与启动参数的区别。\n如何理解与使用 # 修改代码模板只改变新生成注释的文字；设置 JVM 的 user.name 则影响进程读取的用户属性。已有源码注释不会自动批量更新。\n验证与边界 # 选择一种方式后新建一个类验证作者信息，并检查团队模板约定。没有必要为了注释展示而修改整个操作系统账号。\n","date":"2014-03-21","externalUrl":null,"permalink":"/posts/eclipse-author/","section":"文章归档","summary":"修改代码模板只改变新生成注释的文字；设置 JVM 的 user.name 则影响进程读取的用户属性。已有源码注释不会自动批量更新。","title":"Eclipse中设置${user}变量","type":"posts"},{"content":" 单线ADSL带宽4M，线路损耗后实际速度3.5M左右，上传350k左右，由于ADSL满速下载、上传速度会变慢，配置ROS最高上传、下载不得超过总带宽90%，QOS配置如下：\n首先分类标记上传、下载数据：\n/ip firewall mangle 小数据 add chain=prerouting action=mark-connection new-connection-mark=Small-conn passthrough=yes protocol=icmp comment=Small add chain=prerouting action=mark-connection new-connection-mark=Small-conn passthrough=yes protocol=udp dst-port=53 add chain=postrouting action=mark-connection new-connection-mark=Small-conn passthrough=yes protocol=udp dst-port=53 add chain=prerouting action=mark-connection new-connection-mark=Small-conn passthrough=yes protocol=udp dst-port=123 add chain=postrouting action=mark-packet new-packet-mark=Small-up passthrough=no out-interface=pppoe-out1 connection-mark=Small-conn add chain=prerouting action=mark-packet new-packet-mark=Small-up passthrough=no in-interface=bridge-local connection-mark=Small-conn add chain=prerouting action=mark-packet new-packet-mark=Small-down passthrough=no in-interface=pppoe-out1 connection-mark=Small-conn SSH及VPN add chain=prerouting action=mark-connection new-connection-mark=SSH-conn passthrough=yes protocol=tcp dst-port=22 comment=SSH add chain=prerouting action=mark-connection new-connection-mark=SSH-conn passthrough=yes protocol=tcp dst-port=23 add chain=prerouting action=mark-packet new-packet-mark=SSH-up passthrough=no in-interface=bridge-local connection-mark=SSH-conn add chain=prerouting action=mark-packet new-packet-mark=SSH-down passthrough=no in-interface=pppoe-out1 connection-mark=SSH-conn 网页数据 add chain=prerouting action=mark-connection new-connection-mark=HTTP-conn passthrough=yes protocol=tcp dst-port=80 comment=HTTP add chain=prerouting action=mark-connection new-connection-mark=HTTP-conn passthrough=yes protocol=tcp dst-port=443 add chain=prerouting action=mark-packet new-packet-mark=HTTP-up passthrough=no in-interface=bridge-local connection-mark=HTTP-conn add chain=prerouting action=mark-packet new-packet-mark=HTTP-down passthrough=no in-interface=pppoe-out1 connection-mark=HTTP-conn 其它 add chain=prerouting action=mark-connection new-connection-mark=Other-conn passthrough=yes comment=Other add chain=prerouting action=mark-packet new-packet-mark=Other-up passthrough=no in-interface=bridge-local connection-mark=Other-conn add chain=prerouting action=mark-packet new-packet-mark=Other-down passthrough=no in-interface=pppoe-out1 connection-mark=Other-conn 新建队列类型为PCQ：\n#pcq-rate为每个了数据流最大速度，0为按数据流数公平分配带宽，pcq-limit为每一数据流队列长度； pcq-total-limit不能小于内网主机数*pcq-limit。 /queue type add name=\u0026#34;Small-down\u0026#34; kind=pcq pcq-rate=0 pcq-limit=50 pcq-classifier=dst-address pcq-total-limit=2000 add name=\u0026#34;Small-up\u0026#34; kind=pcq pcq-rate=50k pcq-limit=50 pcq-classifier=src-address pcq-total-limit=2000 add name=\u0026#34;SSH-down\u0026#34; kind=pcq pcq-rate=0 pcq-limit=50 pcq-classifier=dst-address pcq-total-limit=2000 add name=\u0026#34;SSH-up\u0026#34; kind=pcq pcq-rate=50k pcq-limit=50 pcq-classifier=src-address pcq-total-limit=2000 add name=\u0026#34;HTTP-down\u0026#34; kind=pcq pcq-rate=0 pcq-limit=50 pcq-classifier=dst-address pcq-total-limit=2000 add name=\u0026#34;HTTP-up\u0026#34; kind=pcq pcq-rate=80k pcq-limit=50 pcq-classifier=src-address pcq-total-limit=2000 add name=\u0026#34;Other-down\u0026#34; kind=pcq pcq-rate=0 pcq-limit=50 pcq-classifier=dst-address pcq-total-limit=2000 add name=\u0026#34;Other-up\u0026#34; kind=pcq pcq-rate=30k pcq-limit=50 pcq-classifier=src-address pcq-total-limit=2000 添加队列树调用之前标记的数据包设置优先级，队列类型设置为之前新建的PCQ类型。\n/queue tree add name=\u0026#34;Parent-up\u0026#34; parent=global-out limit-at=330k max-limit=330k add name=\u0026#34;Parent-down\u0026#34; parent=global-in limit-at=3300k max-limit=3300k add name=Small-up parent=Parent-up packet-mark=Small-up limit-at=70k max-limit=150k queue=Small-up priority=1 add name=Small-down parent=Parent-down packet-mark=Small-down limit-at=500k max-limit=1000k queue=Small-down priority=1 add name=SSH-up parent=Parent-up packet-mark=SSH-up limit-at=70k max-limit=200k queue=SSH-up priority=2 add name=SSH-down parent=Parent-down packet-mark=SSH-down limit-at=500k max-limit=1000k queue=SSH-down priority=2 add name=HTTP-up parent=Parent-up packet-mark=HTTP-up limit-at=150k max-limit=200k queue=HTTP-up priority=3 add name=HTTP-down parent=Parent-down packet-mark=HTTP-down limit-at=2000k max-limit=3000k queue=HTTP-down priority=3 add name=Other-up parent=Parent-up packet-mark=Other-up limit-at=20k max-limit=80k queue=Other-up priority=4 add name=Other-down parent=Parent-down packet-mark=Other-down limit-at=200k max-limit=2000k queue=Other-down priority=4 ROS路由设置HTB+PCQ流量控制的一些注意事项：\n1.WAN限制上传，按源地址分组；LAN限制下载，按目标地址分组；\n2.passthrough是否继续向下匹配此链接，选择yes会向下匹配，下面规则如有匹配标记会改变；\n3.在HTB首先满足Limit At，在父级有剩余带宽的前提下才会Max Limit，优先级高的队列优先获得Max Limit；\n4.mark-connection的数据包是双向的，然后通过mark-pack区分上传和下载；\n5.global-in在DNAT后，global-out在SNAT前，分别可匹配目标地址和源地址。\n补充阅读 # 解释 RouterOS 单线 ADSL 的 HTB 与 PCQ 配置中，流量标记和上传下载队列如何配合。\n如何理解与使用 # 原文带宽数字来自当时的单条线路，先测实际上下行，再将接口、网段和队列上限替换成自己的值。PCQ 分类方向需要与实际上传、下载一致。\n验证与边界 # 验证时同时制造上传与下载流量，观察标记和队列计数是否增长，再看交互延迟；只看到测速限速不能证明所有流量都经过预期队列。\n","date":"2013-12-13","externalUrl":null,"permalink":"/posts/routeros-htb-pcq/","section":"文章归档","summary":"原文带宽数字来自当时的单条线路，先测实际上下行，再将接口、网段和队列上限替换成自己的值。PCQ 分类方向需要与实际上传、下载一致。","title":"ROS下单线ADSL使用HTB+PCQ限速","type":"posts"},{"content":"大家都知道国行的9300带有通话录音、来电归属地和信息归属地。其实，9300都有这个功能，只是在香港以及国外通话录音是违法的，所以都和谐掉了。今天教大家小小的改动一下，就让你的港版以及欧水机都能有这个功能。 首先，手机需Root\n再用RE管理器打开system/csc/sales_code.dat\n选择用文本编辑器模式打开，把里面的三个英文字母改为CHN 记得权限，然后保存并重启手机\n你会惊喜的发现国行有的通话录音你也有了，还有归属地显示\n归属地的更新你到时候用WIFI或打开移动数据更新一下即可，若来电不显示联系人，你重新关联一下通讯录就可以了\n希望这个教程能给你带来惊喜，觉得有用的就顶一下噢，您的支持是我最大的动力！\n一些不喜欢刷机 喜欢官方的朋友应该很喜欢的！\n（悲哀啊，看贴的人多，回贴的人少，风气太差了4.1.1-4.1.2测试可用4.0.4请自行测试）\n补充阅读 # 补充三星 Note2、Note3 旧版系统功能修改记录的适用边界与恢复准备。\n如何理解与使用 # 原文针对特定年代的三星系统文件和地区配置，涉及 Root 权限；不能据此推断其他型号、系统版本也具有相同行为。\n验证与边界 # 修改前需要保留原文件与权限信息，并准备恢复方式。通话录音功能是否可用与能否合规使用是两件事，应核对设备所在地的要求。\n","date":"2013-12-09","externalUrl":null,"permalink":"/posts/samsung-call-recording/","section":"文章归档","summary":"原文针对特定年代的三星系统文件和地区配置，涉及 Root 权限；不能据此推断其他型号、系统版本也具有相同行为。","title":"三星Note2 note3非国行机也有通话录音、来电、信息归属地教程","type":"posts"},{"content":"1.热血传奇\nTCP 7300 7500 7200 7400-7401 7204 7006 7099 7201 7100 7491 7440\n2.完美世界国际版\ntcp 29000\n3.地下城勇士\nTCP 10047-48 10010-16 7101-3 10022-23\n10032-37 10051-55 10006 10026-10027 10001\n本地端口 UDP 5063\n4.梦幻西游\nTCP 21388 10156 4188 4588 22788 10116 4088\n5.QQ飞车\nUDP 39311 1764 12721 3133 4550 3620\n121.14.94.76 80\n6.QQ对战平台\nTCP 443\n7.浩方之冰封王座\nUDP 8861 1932 2287 14531 1897 2428 13735\nUDP 1039 1100 1210 1381 1473 1509 1785 18979\nUDP 1140 1371 1510 16434 9865\nTCP 6112\n8.穿越火线\nTCP 28012 10008 7101\nUDP 12152-12157 12061 12071 12121-12125\n12020-12025 12044-12049 12175 12007 12128 12134-12135 12013 12107 12082 12167\n本地2349\n8.JJ斗地主\nTCP 20002-7 22001\n10.魔兽世界\nTCP 3724 1119 8085\n11.QQ炫舞\nTCP 31414\n12.反恐精英OL\nTCP 47611\n来源端口\nUDP 27005 27015\n13.征服\nTCP 5816\n14.街头篮球\nTCP 10011\nUDP 17065\n15.魔域\nTCP 5816 8900\n16.永恒之塔\nTCP 10241 7777\n17.劲舞团\nTCP 25520-21 25511\n18.BFGAME\nTCP 6000 7000\n19.成吉思汗\nTCP 17703-6\n20.三国争霸\nUDP 6660 1610 6600\nTCP 1607\n21.天下贰\nUDP 32824 32404-32407 32424 32299\n22.传奇归来\nTCP 7417 7100\nUDP 12345\n23.魔兽争霸3\n本地端口UDP 2327 2040\nUDP 2191 1845 1998 50801 2111 1590 4377 1925 1561 2191 9628\n24.QQ华夏\nTCP 5130\n25.浩方对战平台\nTCP 1203\nUDP 9000 1511\n26.CS\nUDP 27005-27030\n27.问道\nTCP 9010-9014\n28.天龙八部\nTCP 3731-3735 7449 7237\n29.剑侠情缘3\nTCP 3110-3120\n30.诛仙2\nTCP 29000\n40.起凡游戏平台\nTCP 1607\nUDP 6600 6660 1308 1610\nIP范围125.64.132.11-18 222.73.213.43\n三国争霸\nTCP 2175\nUDP 6631\n41.封神榜\nTCP 8888\n42.神鬼传奇\nTCP 30000-30010\n43.面对面视频游戏中心\nTCP 8000 8018\nUDP 8000-8001\n44.泡泡堂\nTCP 6868 33567\nUDP 9646\n45.传奇世界\nTCP 7203-4 7100 7400\nUDP 7000\n46.魔兽世界台服\nTCP 1080\n47.英雄岛公测版\nTCP 6831-32 6840-6847\n48.热舞派对\nTCP 29000\n49.众神之战先行版online\nTCP 7000\n50.VS竞技平台\nTCP 1759\n51.星尘传说\nTCP 2347\n52.剑侠贰外传\nTCP 6661-6663\n53.fifa online2\nTCP 6217\n54.疯狂赛车\nTCP 9600\n55.寻仙\nUDP 7002 15002-15004 3100\n56.仙剑online\nTCP 15000\n57.光线飞车\nTCP 2181\nUDP 1059\n58.蜀门\nTCP 28880\n59.巴适游戏\nTCP 8001 21800\n59.特种部队\nTCP 27931\nUDP 20096 20059\n60.QQ自由幻想\nTCP 6299\n61.青鹏棋牌\nTCP 8030\n62.QQ音速\nTCP 28008\n63.绿色征途\nTCP 6020 6030\n64.武林群侠传online2\nTCP 6877\n65.兽血沸腾\nTCP 4680\n66.梦幻诛仙：TCP 28993\n补充阅读 # 保留早期网游端口收集清单，说明如何把历史端口信息用于排查而非直接放行。\n如何理解与使用 # 清单按游戏与 TCP、UDP 分类，适合定位当年的连接线索；服务端更新、区域和客户端版本都会影响实际端点。\n验证与边界 # 排查时先用连接信息或抓包确认当前目标与协议，再制定必要的访问规则；不要因清单列出一个范围就认为所有端口都必须开放。\n","date":"2013-12-06","externalUrl":null,"permalink":"/posts/game-ports/","section":"文章归档","summary":"清单按游戏与 TCP、UDP 分类，适合定位当年的连接线索；服务端更新、区域和客户端版本都会影响实际端点。","title":"收集大家常玩的网游端口","type":"posts"},{"content":" CronTrigger # CronTriggers往往比SimpleTrigger更有用，如果您需要基于日历的概念，而非SimpleTrigger完全指定的时间间隔，复发的发射工作的时间表。 CronTrigger，你可以指定触发的时间表如“每星期五中午”，或“每个工作日9:30时”，甚至“每5分钟一班9:00和10:00逢星期一上午，星期三星期五“。 即便如此，SimpleTrigger一样，CronTrigger拥有的startTime指定的时间表时生效，指定的时间表时，应停止（可选）结束时间。\nCron Expressions # cron的表达式被用来配置CronTrigger实例。 cron的表达式是字符串，实际上是由七子表达式，描述个别细节的时间表。这些子表达式是分开的空白，代表：\n1. Seconds 2. Minutes 3. Hours 4. Day-of-Month 5. Month 6. Day-of-Week 7. Year (**可选字段**) 例 \u0026quot;0 0 12 ? * WED\u0026quot; 在每星期三下午12:00 执行,\n个别子表达式可以包含范围, 例如，在前面的例子里(\u0026quot;WED\u0026quot;)可以替换成 \u0026quot;MON-FRI\u0026quot;, \u0026quot;MON, WED, FRI\u0026quot;甚至\u0026quot;MON-WED,SAT\u0026quot;.\n“*” 代表整个时间段.\n每一个字段都有一套可以指定有效值，如\nSeconds (秒) ：可以用数字0－59 表示，\n**Minutes(**分) ：可以用数字0－59 表示，\n**Hours(**时) ：可以用数字0-23表示,\n**Day-of-Month(**天) ：可以用数字1-31 中的任一一个值，但要注意一些特别的月份\n**Month(**月) ：可以用0-11 或用字符串 “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC” 表示\nDay-of-Week(**每周)****：**可以用数字1-7表示（1 ＝ 星期日）或用字符口串“SUN, MON, TUE, WED, THU, FRI and SAT”表示\n“/”：为特别单位，表示为“每”如“0/15”表示每隔15分钟执行一次,“0”表示为从“0”分开始, “3/20”表示表示每隔20分钟执行一次，“3”表示从第3分钟开始执行\n“?”：表示每月的某一天，或第周的某一天\n“L”：用于每月，或每周，表示为每月的最后一天，或每个月的最后星期几如“6L”表示“每月的最后一个星期五”\n“W”：表示为最近工作日，如“15W”放在每月（day-of-month）字段上表示为“到本月15日最近的工作日”\n““#”：是用来指定“的”每月第n个工作日,例 在每周（day-of-week）这个字段中内容为\u0026quot;6#3\u0026quot; or \u0026quot;FRI#3\u0026quot; 则表示“每月第三个星期五”\n1）Cron表达式的格式：秒 分 时 日 月 周 年(可选)。\n字段名 允许的值 允许的特殊字符 秒 0-59 , - / 分 0-59 , - / 小时 0-23 , - / 日 1-31 , - ? / L W C 月 1-12 or JAN-DEC , - / 周几 1-7 or SUN-SAT , - ? / L C # 年 (可选字段) empty, 1970-2099 , - * /\n“?”字符：表示不确定的值\n“,”字符：指定数个值\n“-”字符：指定一个值的范围\n“/”字符：指定一个值的增加幅度。n/m表示从n开始，每次增加m\n“L”字符：用在日表示一个月中的最后一天，用在周表示该月最后一个星期X\n“W”字符：指定离给定日期最近的工作日(周一到周五)\n“#”字符：表示该月第几个周X。6#3表示该月第3个周五\n2）Cron表达式范例：\n每隔5秒执行一次：/5 * ?\n每隔1分钟执行一次：0 /1 ?\n每天23点执行一次：0 0 23 ?\n每天凌晨1点执行一次：0 0 1 ?\n每月1号凌晨1点执行一次：0 0 1 1 * ?\n每月最后一天23点执行一次：0 0 23 L * ?\n每周星期天凌晨1点实行一次：0 0 1 ? * L\n在26分、29分、33分执行一次：0 26,29,33 * ?\n每天的0点、13点、18点、21点都执行一次：0 0 0,13,18,21 ?\n补充阅读 # 解释 Quartz CronTrigger 时间表达式的字段与常见易混点，帮助检查任务触发时间。\n如何理解与使用 # Quartz 表达式从秒开始，与常见的五字段系统 crontab 不同；阅读时应先确认调度器类型，再逐字段解释例子。\n验证与边界 # 原文月份数字范围应按 Quartz 文档核对为 1–12，而不是 0–11。还应确认时区、日期字段约束及下一次触发时间，用实际调度器校验表达式。\n参考：Quartz CronTrigger（本次补充核对）。\n","date":"2013-12-05","externalUrl":null,"permalink":"/posts/quartz-cron/","section":"文章归档","summary":"Quartz 表达式从秒开始，与常见的五字段系统 crontab 不同；阅读时应先确认调度器类型，再逐字段解释例子。","title":"QuartZ Cron表达式","type":"posts"},{"content":" yum -y install xorg-x11-fonts-Type1 yum -y groupinstall \u0026#34;X Window System\u0026#34; #安装Xwindow yum -y groupinstall \u0026#34;Desktop\u0026#34; #安装GNOME桌面 yum -y install @kde-desktop #安装KDE桌面，比GNOME桌面漂亮，但软件包也较大 # yum -y install firefox #安装火狐浏览器（若安装的是GNOME桌面） # yum -y install nautilus-open-terminal #鼠标右键菜单“在终端中打开”（仅GNOME桌面） yum -y groupinstall chinese-support #中文支持 yum -y install dejavu-sans-* dejavu-serif-fonts #比较好看的字体 sed -i \u0026quot;s/^id:3:init/id:5:init/\u0026quot; /etc/inittab #设置开机时默认启用图形界面 reboot #重启若安装以上软件不重启就执行startx命令，可能启动图形界面会失败！\n默认语言设置，可能你还要修改 /etc/sysconfig/i18n ---\u0026gt; LANG=\u0026quot;zh_CN.UTF-8\u0026quot;\n很实用的系统垃圾清理工具BleachBit：http://bleachbit.sourceforge.net/download/linux\n网上看到的安装图形界面的命令是错的。\nGNOME桌面不能用yum groupinstall \u0026quot;GNOME Desktop Environment\u0026quot;安装了，KDE桌面也不能用yum groupinstall 'KDE (K Desktop Environment)'命令安装，都变了（见上文）。\n补充阅读 # 说明 CentOS 6 图形桌面安装记录涉及的组件、启动方式和历史版本范围。\n如何理解与使用 # X Window、桌面环境、浏览器和中文字体各自解决不同问题，安装桌面包并不自动证明显示驱动、字体和输入环境全部正常。\n验证与边界 # 原文针对 CentOS 6 及其当时的软件仓库。操作前先确认版本和仓库可用性；验证应包括登录界面、桌面会话与中文显示，不宜直接套用到不同发行版。\n","date":"2013-11-08","externalUrl":null,"permalink":"/posts/centos-desktop/","section":"文章归档","summary":"X Window、桌面环境、浏览器和中文字体各自解决不同问题，安装桌面包并不自动证明显示驱动、字体和输入环境全部正常。","title":"CentOS6安装图形界面","type":"posts"},{"content":" 分享一个xmanager 4 的序列号 # 101210-450789-147200 分享一个xshell4 的序列号 # 690313-111999-999313\n补充阅读 # 保留早期 Xmanager 与 Xshell 授权记录，并说明版本、安装来源与授权核对的范围。\n如何理解与使用 # 这篇是历史记录，文中型号和序列号不能代表当前产品授权，也不能据此判断使用者拥有许可证。阅读重点是识别当时的软件版本。\n验证与边界 # 重新安装时应从厂商核对安装包与自己的授权条件，避免将旧下载或旧凭据当作当前可用方案；本次没有新增或验证注册码。\n","date":"2013-11-08","externalUrl":null,"permalink":"/posts/xshell-license-notes/","section":"文章归档","summary":"这篇是历史记录，文中型号和序列号不能代表当前产品授权，也不能据此判断使用者拥有许可证。阅读重点是识别当时的软件版本。","title":"分享一个xmanager 4 （xshell）的序列号","type":"posts"},{"content":" iptables -A POSTROUTING -t nat -s 192.168.1.0/24 -j SNAT --to 服务器IP地址\n补充阅读 # 解释 PPTP 客户端已连接但不能上网时，SNAT 与返回路径的排查思路。\n如何理解与使用 # 隧道建立后，客户端流量还需要可用的默认路由、服务器转发和返回路径；原文 SNAT 规则针对指定的客户端网段。\n验证与边界 # 先区分访问内网、访问外部 IP 和解析域名失败，再检查出口地址与 NAT 计数。不要在未确认地址池的情况下直接复制原网段。\n","date":"2013-11-01","externalUrl":null,"permalink":"/posts/pptp-no-internet/","section":"文章归档","summary":"隧道建立后，客户端流量还需要可用的默认路由、服务器转发和返回路径；原文 SNAT 规则针对指定的客户端网段。","title":"解决linux VPN pptpd连接后客户端不能上网的问题","type":"posts"},{"content":" pptpd\nhttp://poptop.sourceforge.net/yum/stable/packages/\n补充阅读 # 说明 CentOS pptpd 软件包链接的历史用途，并区分获取软件包与完整 VPN 部署。\n如何理解与使用 # 原文仅保存包站入口，没有记录目标系统、依赖版本和完整部署参数，因此不能直接作为当前可执行的安装流程。\n验证与边界 # 重新使用时先核对软件包来源与系统兼容性；安装后仍需独立配置认证、路由和访问规则，并验证实际客户端连接。\n","date":"2013-11-01","externalUrl":null,"permalink":"/posts/pptpd-packages/","section":"文章归档","summary":"原文仅保存包站入口，没有记录目标系统、依赖版本和完整部署参数，因此不能直接作为当前可执行的安装流程。","title":"centos pptpd","type":"posts"},{"content":" 安装iptables防火墙\n如果你是CentOS执行：\nyum install iptables 如果你是Debian/Ubuntu执行：\napt-get install iptables centOS设置iptables开机启动\nchkconfig --level 345 iptables on CentOS上可以执行：\nservice iptables save 保存规则。\n需要注意:Debian/Ubuntu上iptables是不会保存规则的。\n需要按如下步骤进行，让网卡关闭是保存iptables规则，启动时加载iptables规则：\n创建/etc/network/if-post-down.d/iptables 文件，添加如下内容：\n#!/bin/bash iptables-save \u0026gt; /etc/iptables.rules 执行：\nchmod +x /etc/network/if-post-down.d/iptables 添加执行权限。\n创建/etc/network/if-pre-up.d/iptables 文件，添加如下内容：\n#!/bin/bash iptables-restore \u0026lt; /etc/iptables.rules 执行：\nchmod +x /etc/network/if-pre-up.d/iptables 添加执行权限。\n清除已有iptables规则\niptables -F iptables -X iptables -Z 开放指定的端口\n#允许本地回环接口(即运行本机访问本机) iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT 允许已建立的或相关连的通行 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 允许所有本机向外的访问 iptables -A OUTPUT -j ACCEPT 允许访问22端口 iptables -A INPUT -p tcp --dport 22 -j ACCEPT 允许访问80端口 iptables -A INPUT -p tcp --dport 80 -j ACCEPT 允许FTP服务的21和20端口 iptables -A INPUT -p tcp --dport 21 -j ACCEPT iptables -A INPUT -p tcp --dport 20 -j ACCEPT 如果有其他端口的话，规则也类似，稍微修改上述语句就行 禁止其他未允许的规则访问 iptables -A INPUT -j REJECT iptables -A FORWARD -j REJECT 屏蔽IP\n#如果只是想屏蔽IP的话“3、开放指定的端口”可以直接跳过。 屏蔽单个IP的命令是 iptables -I INPUT -s 123.45.6.7 -j DROP 封整个段即从123.0.0.1到123.255.255.254的命令 iptables -I INPUT -s 123.0.0.0/8 -j DROP 封IP段即从123.45.0.1到123.45.255.254的命令 iptables -I INPUT -s 124.45.0.0/16 -j DROP 封IP段即从123.45.6.1到123.45.6.254的命令是 iptables -I INPUT -s 123.45.6.0/24 -j DROP 查看已添加的iptables规则\niptables -L -n v：显示详细信息，包括每条规则的匹配包数量和匹配字节数\nx：在 v 的基础上，禁止自动单位换算（K、M） vps侦探\nn：只显示IP地址和端口号，不将ip解析为域名\n删除已添加的iptables规则\n将所有iptables以序号标记显示，执行：\niptables -L -n --line-numbers 比如要删除INPUT里序号为8的规则，执行：\niptables -D INPUT 8 补充阅读 # 补充 Linux iptables 查询与规则阅读的方法，帮助区分规则存在、命中和持久化。\n如何理解与使用 # 查看规则时应同时确认表、链、顺序和默认策略，计数增长才表明测试流量经过相应条件。\n验证与边界 # 修改后验证预期允许与拒绝的连接，并单独确认重启后规则是否保留；命令执行成功并不代表保存机制已经配置。\n","date":"2013-10-31","externalUrl":null,"permalink":"/posts/iptables-reference/","section":"文章归档","summary":"查看规则时应同时确认表、链、顺序和默认策略，计数增长才表明测试流量经过相应条件。","title":"Linux iptables","type":"posts"},{"content":" “常规”标签\n姓 Sn 名 Givename 英文缩写 Initials 显示名称 displayName 描述 Description 办公室 physicalDeliveryOfficeName 电话号码 telephoneNumber 电话号码：其它 otherTelephone 多个以英文分号分隔 电子邮件 Mail 网页 wWWHomePage 网页：其它 url 多个以英文分号分隔\n“地址”标签\n国家/地区 C 如：中国CN，英国GB 省/自治区 St 市/县 L 街道 streetAddress 邮政信箱 postOfficeBox 邮政编码 postalCode\n“帐户”标签\n用户登录名 userPrincipalName 采用“用户名 + @ + 域名”的格式。 用户登录名（以前版本） sAMAccountName 形如：S1 登录时间 logonHours 登录到 userWorkstations 多个以英文逗号分隔 用户帐户控制 userAccountControl (启用：512，禁用：514， 密码永不过期：66048) 帐户过期 accountExpires\n“配置文件”标签\n配置文件路径 profilePath 登录脚本 scriptPath 主文件夹：本地路径 homeDirectory 连接 homeDrive 到 homeDirectory\n“电话”标签 家庭电话 homePhone (若是其它，在前面加other。) 寻呼机 Pager 如：otherhomePhone。 移动电话 mobile 若多个以英文分号分隔。 传真 FacsimileTelephoneNumber IP电话 ipPhone 注释 Info\n“单位”标签 职务 Title 部门 Department 公司 Company\n“隶属于”标签 隶属于 memberOf 用户组的DN不需使用引号， 多个用分号分隔 “拨入”标签 远程访问权限（拨入或VPN） msNPAllowDialin 允许访问 值：TRUE 拒绝访问 值：FALSE 回拨选项 msRADIUSServiceType 由呼叫方设置或回拨到 值：4 总是回拨到 msRADIUSCallbackNumber “环境”、“会话”、“远程控制”、“终端服务配置文件”、“COM+”标签\n属性\n显示名称 属性名称 First Name givenName Last Name sn Initials initials Description description Office physicalDeliveryOfficeName Telephone Number telephoneNumber Telephone: Other otherTelephone E-Mail mail Web Page wwwHomePage Web Page: Other url 帐号属性：\n显示名称 属性名称 UserLogon Name userPrincipalName User logon name (pre-Windows 2000) sAMAccountname Logon Hours logonHours Log On To logonWorkstation Account is locked out userAccountControl User must change password at next logon pwdLastSet User cannot change password N/A Other Account Options userAccountControl Account Expires accountExpires 地址属性\n显示名称 属性名称 Street streetAddress P.O.Box postOfficeBox City l State/Province st Zip/Postal Code postalCode Country/Region c , co , and countryCode 成员属性\n显示名称 属性名称 Member of memberOf Set Primary Group primaryGroupID 组织属性\n显示名称 属性名称 Title title Department department Company company Manager:Name manager Direct Reports directReports 外型属性\n显示名称 属性名称 Profile Path profilePath Logon Script scriptPath Home Folder: Local Path homeDirectory Home Folder: Connect homeDrive Home Folder: To homeDirectory 电话相关属性\n显示名称 属性名称 Home telephoneNumber Home: Other otherTelephone Pager pager Pager: Other pagerOther Mobile mobile Mobile: Other otherMobile Fax facsimileTelephoneNumber Fax: Other otherFacsimileTelephoneNumber IP phone ipPhone IP phone: Other otherIpPhone Notes info 补充阅读 # 说明 LDAP、Active Directory 属性清单应怎样结合对象类型、查询条件与字段实际值使用。\n如何理解与使用 # 同一名称的显示信息、登录标识和唯一标识承担不同作用，不能只凭属性看起来相似就互换。\n验证与边界 # 先在授权范围内查询样本对象，记录字段类型、多值与空值情况；同步业务数据时，还应确认所选标识在重命名和跨域场景中的稳定性。\n","date":"2013-10-30","externalUrl":null,"permalink":"/posts/ldap-attributes/","section":"文章归档","summary":"同一名称的显示信息、登录标识和唯一标识承担不同作用，不能只凭属性看起来相似就互换。","title":"Ldap活动目录常用属性介绍","type":"posts"},{"content":"cls\n@ECHO OFF\nSET NGINX_DIR=%cd%\\nginx-1.5.6\\\ncolor 0a\nTITLE Nginx 管理程序\nGOTO MENU\n:MENU\nCLS\nECHO.\nECHO. * * * * Nginx 管理程序 * * *\nECHO. * *\nECHO. * 1 启动Nginx *\nECHO. * *\nECHO. * 2 关闭Nginx *\nECHO. * *\nECHO. * 3 重载Nginx *\nECHO. * *\nECHO. * 4 重启Nginx *\nECHO. * *\nECHO. * 5 退 出 *\nECHO. * *\nECHO. * * * * * * * * * * * * * * * * * * * * * * * *\nECHO.\nECHO.请输入选择项目的序号：\nset /p ID=\nIF \u0026quot;%id%\u0026quot;==\u0026quot;1\u0026quot; GOTO cmd1\nIF \u0026quot;%id%\u0026quot;==\u0026quot;2\u0026quot; GOTO cmd2\nIF \u0026quot;%id%\u0026quot;==\u0026quot;3\u0026quot; GOTO cmd3\nIF \u0026quot;%id%\u0026quot;==\u0026quot;4\u0026quot; GOTO cmd4\nIF \u0026quot;%id%\u0026quot;==\u0026quot;5\u0026quot; EXIT\nPAUSE\n:cmd1\nECHO.\nECHO.启动Nginx......\nIF NOT EXIST %NGINX_DIR%nginx.exe ECHO %NGINX_DIR%nginx.exe不存在\ncd %NGINX_DIR%\nIF EXIST %NGINX_DIR%nginx.exe start %NGINX_DIR%nginx.exe\nECHO.OK\nPAUSE\nGOTO MENU\n:cmd2\nECHO.\nECHO.关闭Nginx......\ntaskkill /F /IM nginx.exe \u0026gt; nul\nECHO.OK\nPAUSE\nGOTO MENU\n:cmd3\nECHO.\nECHO.重载Nginx......\n%NGINX_DIR%nginx.exe -s reload\nECHO.OK\nPAUSE\nGOTO MENU\n:cmd4\nECHO.\nECHO.重启Nginx......\ntaskkill /F /IM nginx.exe \u0026gt; nul\nECHO.OK\nGOTO cmd1\nGOTO MENU\n补充阅读 # 说明 Windows 批处理菜单怎样管理 Nginx 的启动、停止与重载，以及路径相关的限制。\n如何理解与使用 # 脚本依赖当前目录和固定版本子目录，运行位置、路径空格与多实例都会影响它找到哪个二进制和配置文件。\n验证与边界 # 分别验证菜单各项及返回结果；重载前先做配置检查，停止操作要确认目标进程，避免把其他站点实例一同结束。\n","date":"2013-10-22","externalUrl":null,"permalink":"/posts/nginx-windows/","section":"文章归档","summary":"脚本依赖当前目录和固定版本子目录，运行位置、路径空格与多实例都会影响它找到哪个二进制和配置文件。","title":"Nginx Windows版本启动文件","type":"posts"},{"content":"/* * HashMap对象，实现HashMap功能 * * 接口： * size() 获取HashMap元素个数 * isEmpty() 判断HashMap是否为空 * clear() 删除HashMap所有元素 * put(key, value) 向HashMap中增加元素（key, value) * remove(key) 删除指定KEY的元素，成功返回True，失败返回False * get(key) 获取指定KEY的元素值VALUE，失败返回NULL * element(index) 获取指定索引的元素（使用element.key，element.value获取KEY和VALUE），失败返回NULL * containsKey(key) 判断HashMap中是否含有指定KEY的元素 * containsValue(value) 判断HashMap中是否含有指定VALUE的元素 * values() 获取HashMap中所有VALUE的数组（ARRAY） * keys() 获取HashMap中所有KEY的数组（ARRAY） * * 例子： * var map = new HashMap(); * * map.put(\u0026#34;key\u0026#34;, \u0026#34;value\u0026#34;); * var val = map.get(\u0026#34;key\u0026#34;) * …… * */ function HashMap() { this.elements = new Array(); //获取HashMap元素个数 this.size = function() { return this.elements.length; } //判断HashMap是否为空 this.isEmpty = function() { return (this.elements.length \u0026lt; 1); } //删除HashMap所有元素 this.clear = function() { this.elements = new Array(); } //向HashMap中增加元素（key, value) this.put = function(_key, _value) { this.elements.push( { key : _key, value : _value }); } //删除指定KEY的元素，成功返回True，失败返回False this.remove = function(_key) { var bln = false; try { for (i = 0; i \u0026lt; this.elements.length; i++) { if (this.elements[i].key == _key) { this.elements.splice(i, 1); return true; } } } catch (e) { bln = false; } return bln; } //获取指定KEY的元素值VALUE，失败返回NULL this.get = function(_key) { try { for (i = 0; i \u0026lt; this.elements.length; i++) { if (this.elements[i].key == _key) { return this.elements[i].value; } } } catch (e) { return null; } } //获取指定索引的元素（使用element.key，element.value获取KEY和VALUE），失败返回NULL this.element = function(_index) { if (_index \u0026lt; 0 || _index \u0026gt;= this.elements.length) { return null; } return this.elements[_index]; } //判断HashMap中是否含有指定KEY的元素 this.containsKey = function(_key) { var bln = false; try { for (i = 0; i \u0026lt; this.elements.length; i++) { if (this.elements[i].key == _key) { bln = true; } } } catch (e) { bln = false; } return bln; } //判断HashMap中是否含有指定VALUE的元素 this.containsValue = function(_value) { var bln = false; try { for (i = 0; i \u0026lt; this.elements.length; i++) { if (this.elements[i].value == _value) { bln = true; } } } catch (e) { bln = false; } return bln; } //获取HashMap中所有VALUE的数组（ARRAY） this.values = function() { var arr = new Array(); for (i = 0; i \u0026lt; this.elements.length; i++) { arr.push(this.elements[i].value); } return arr; } //获取HashMap中所有KEY的数组（ARRAY） this.keys = function() { var arr = new Array(); for (i = 0; i \u0026lt; this.elements.length; i++) { arr.push(this.elements[i].key); } return arr; } } 补充阅读 # 解释 JavaScript 旧版自定义 Map 的接口设计，并补充与原生 Map 对照时的检查点。\n如何理解与使用 # 原代码围绕键值存取、删除、枚举和数量等操作封装对象，阅读时先确认重复键覆盖与不存在键的返回约定。\n验证与边界 # 移植前测试键类型、继承属性、迭代顺序及特殊字符串。当前 JavaScript 已有原生 Map，但替换旧实现时仍需核对业务依赖的行为差异。\n","date":"2013-07-16","externalUrl":null,"permalink":"/posts/javascript-map/","section":"文章归档","summary":"原代码围绕键值存取、删除、枚举和数量等操作封装对象，阅读时先确认重复键覆盖与不存在键的返回约定。","title":"Javascript实现类似java中的Map功能","type":"posts"},{"content":"软件开发过程需要经历的几个主要阶段：\n（1）定义。明确软件开发的目的、软件的需求。\n（2）计划。制订软件开发所涉及的各种计划。\n（3）实现。进行设计、编码、文档编写工作，完成所要求的软件特性。\n（4）稳定化。以测试和修复工作为主，确保将提交的软件具有良好的质量。\n（5）部署。安装、提交开发完成的软件，建立可供用户使用的环境。\n常见的软件生命周期模型：\n瀑布模型\n原型模型\n增量模型\n螺旋模型\n瀑布模型：\n在瀑布模型中，包括六个阶段：计划、需求分析、设计、编码、测试、运行维护。这六个阶段自上而下、相互衔接，以固定的次序来进行。模型驱动的一个重要的特征是强调阶段的顺序性和依赖性。下一个阶段必须是以上一个阶段为前提。例如在开始设计工作前，必须完成需求分析过程。瀑布模型要求各个阶段必须有相应的文档为依据，因此瀑布模型是以文档为驱动的。\n原图暂无法获取\n瀑布模型自身存在了一些缺点，比方说：测试人员可能在后期发现大量错误，因此必须返回需求分析、设计或代码中定位问题，而瀑布模型中认为已经完成的各个阶段必须修改，这样以来所花费的代价是很大的。因此很多人认为瀑布模型适合硬件系统的开发。\n原型模型：\n在很多的时候，用户提出了软件需达到的一系列目标，但不能给出详细的输入、输出和处理过程；开发人员不能确定某种算法或合理的解决方案。在这种情况下适合用原型模型。\n其主要思想是：先建立一个能反映用户需求的原型系统，使得用户和开发人员能够对目标系统的概况进行评价和判断，然后对原型进行反复的扩充和改进，最终建立可以满足用户需求的目标系统。\n原图暂无法获取\n开发者和用户得到更加详细的待开发软件的需求，对已经开发的原型进行调整，使之更加符合用户的需求。通过不断的迭代，最终开发出符合需求的软件。\n增量模型：\n增量模型结合了瀑布模型和原型模型的特性。\n原图暂无法获取\n增量模型中，在每个阶段都生成软件的一个可发布版本。这些阶段是交错进行的，这意味着前一个版本还没有发布时，下一个版本的部分工作就已经开始了。\n**增量模型和原型模型有一个很大的差别：在原型中，每个阶段发布一个原型，而在增量模型中是完成一个正式的版本。**在增量模型中，软件版本是在功能上逐步完善的。\n螺旋模型：\n螺旋模型将瀑布模型和原型模型结合起来,并且加入了两种模型都忽略的风险分析。螺旋模型的每一周都包括制定计划、风险分析、实施工程和评审四个阶段。开 发过程没迭代一次，螺旋线就增加一周，软件开发又前进一个层次，系统又生成一个新的版本，而软件开发的时间和成本又有了新的投入，最后得到一个客户满意的软件版本。\n原图暂无法获取\n在螺旋模型中，可软件也同样是以一系列版本的形式进行逐步发布的。螺旋模型和一些传统的过程模型不同，它不是当软件交付的后就结束了，而是贯穿了软件的整个生命周期，在螺旋模型中，可能会包含了增强（升级）项目和产品维护项目。\n补充阅读 # 梳理软件开发阶段与常见生命周期模型，帮助把流程概念对应到实际交付物。\n如何理解与使用 # 可把需求、设计、实现、测试和部署分别对应到需求说明、设计记录、代码、验证结果和上线方案；模型名称本身不能代替这些可检查的结果。\n验证与边界 # 选择瀑布、原型或增量方式时，应先判断需求稳定程度、反馈成本和交付频率。原文中的模型比较作为入门线索，实际项目可组合使用。\n","date":"2013-05-16","externalUrl":null,"permalink":"/posts/software-process/","section":"文章归档","summary":"可把需求、设计、实现、测试和部署分别对应到需求说明、设计记录、代码、验证结果和上线方案；模型名称本身不能代替这些可检查的结果。","title":"软件开发过程","type":"posts"},{"content":" 补充阅读 # 补充 Java 多张图片生成 GIF 的基本思路，说明帧顺序、尺寸和播放时间的检查方法。\n如何理解与使用 # 迁移得到的原文只有标题，没有可恢复的合成代码。按这个主题实现时，需要准备按顺序排列的图片、统一的画布尺寸，以及每一帧的显示时间。\n验证与边界 # 导出后分别检查帧顺序、循环次数、透明区域和文件大小；先用少量图片验证，再扩展数量。这里补充的是实现思路，不代表恢复了当年的具体实现或测试结果。\n","date":"2013-05-14","externalUrl":null,"permalink":"/posts/java-gif/","section":"文章归档","summary":"迁移得到的原文只有标题，没有可恢复的合成代码。按这个主题实现时，需要准备按顺序排列的图片、统一的画布尺寸，以及每一帧的显示时间。","title":"Java图片合并成GIF图片","type":"posts"},{"content":"/* * RandomCodeImage.java * Created on Jun 3, 2008 5:57:28 PM * Copyright (c) IBEX All Rights Reserved. * * This software is the confidential and proprietary information of IBEX. * You shall not disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with IBEX. */ package net.mmgg.commons; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.FontFormatException; import java.awt.GradientPaint; import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; import java.awt.Paint; import java.awt.Point; import java.awt.RenderingHints; import java.awt.Stroke; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Random; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.ImageOutputStream; public class RandomCodeImage { public static ArrayList fonts = null; // 单例模式 private static RandomCodeImage instance = null; // 定义验证码内容 private String codes = null; //乘法口诀常量 private final int MULTIPLY=1;//乘 private final int DIVIDED=2;//除 private final int PLUS=3;//加 private final int SUBTRACT=4;//减 /** * 单例模式 * * @date Jun 13, 2008 9:27:42 AM * @author Fly * @return */ public static RandomCodeImage getInstance() { if (null == instance) { instance = new RandomCodeImage(); } return instance; } /** * 公共构造函数，加载用户自定义字体 * @date Jun 13, 2008 4:31:22 PM * @author Fly * @param fontName 字体名集合 */ public RandomCodeImage(String[] fontName){ if(null!=fonts){ return; } Font font=null; fonts=new ArrayList(); for (int i = 0; i \u0026lt; fontName.length; i++) { font=new Font(fontName[i],Font.PLAIN,14); fonts.add(font); } } /** * 公共构造函数，根据字体文件所在的文件夹，加载用户自定义字体,只支持TTF字体 * @date Jun 13, 2008 5:17:08 PM * @author Fly * @param fontsPath */ public RandomCodeImage(String fontsPath){ if(null!=fonts){ return; } List fontlist=this.readfile(fontsPath, \u0026#34;TTF\u0026#34;); fonts = new ArrayList(); for (Iterator iterator = fontlist.iterator(); iterator.hasNext();) { String object = (String) iterator.next(); File file_ = new File(object); try { Font font_ = Font.createFont(Font.TRUETYPE_FONT, file_); fonts.add(font_); } catch (FontFormatException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } /** * 私有构造函数，加载系统默认字体 * @date Jun 13, 2008 9:27:08 AM * @author Fly */ private RandomCodeImage() { if(null!=fonts){ return; } fonts = new ArrayList(); GraphicsEnvironment.getLocalGraphicsEnvironment().preferLocaleFonts(); String[] names = GraphicsEnvironment.getLocalGraphicsEnvironment() .getAvailableFontFamilyNames(Locale.getDefault()); for (int i = 0; i \u0026lt; names.length; i++) { char c = names[i].charAt(0); if (Character.isLowerCase(c) || Character.isUpperCase(c)) { } else { fonts.add(new Font(names[i],Font.PLAIN,14)); } } } /** * 生成数字和字母验证码 * * @date Jun 13, 2008 9:25:49 AM * @author Fly * @return * @throws Exception */ private BufferedImage getImageOfABC123(){ BufferedImage bi = new BufferedImage(150, 50, BufferedImage.TYPE_INT_RGB); Graphics2D g = bi.createGraphics(); String code = \u0026#34;23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ\u0026#34;; char[] cs = code.toCharArray(); char[] use = new char[5]; g.setColor(this.getBgColor()); g.fillRect(0, 0, 150, 50); codes=\u0026#34;\u0026#34;; java.awt.geom.AffineTransform af=new AffineTransform(); af.setToRotation(Math.PI/2.0); for (int i = 0; i \u0026lt; 5; i++) { //抗锯齿，图片不失真 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); Point p = getPoint(i); int size = getSize(); use[i] = cs[(int) (Math.random() * cs.length)]; g.setPaint(getPaint(p, size)); g.setFont(((Font) fonts.get((int) (Math.random() * fonts.size()))).deriveFont(this.getFace(), this.getSize())); g.drawString(\u0026#34;\u0026#34; + use[i], p.x, p.y); codes += use[i]; } g.setStroke(new BasicStroke(1.5f)); g.setPaint(null); //画干扰线 this.drawLine(g, 2,200,50); //画杂点 this.drawPoint(g, 50,150,50); // 画个边框 //g.setColor(new Color((int) (Math.random() * 0x00FFFFFFF))); //g.drawRect(1, 1, 150 - 2, 50 - 2); g.dispose(); bi.flush(); return bi; } /** * 设置背景颜色 * * @date Jun 13, 2008 9:26:15 AM * @author Fly * @return */ private Color getBgColor() { Random r = new Random(); int x = r.nextInt(256); x = x \u0026gt; 105 ? x : (x + 150); return new Color(x, x, x); } private Stroke getStroke() { BasicStroke bs = new BasicStroke((float) (Math.random() * 3)); return bs; } /** * 文字距离 * * @date Jun 13, 2008 9:26:36 AM * @author Fly * @param index * @return */ private Point getPoint(int index) { return new Point(5 + (index * ((int) (Math.random() * 6) + 24)), 40); } private Paint getPaint(Point p, int size) { GradientPaint gp = new GradientPaint(p.x, p.y, new Color((int) (Math .random() * 200), 0, (int) (Math.random() * 200)), p.x, p.y - size, new Color((int) (Math.random() * 200), (int) (Math .random() * 200), (int) (Math.random() * 200))); return gp; } /** * 字体样式 * * @date Jun 5, 2008 1:44:15 PM * @author Fly * @return */ private int getFace() { if (Math.random() * 10 \u0026gt; 5) { return Font.BOLD; } else { return Font.ITALIC; } } /** * 字体大小 * * @date Jun 5, 2008 1:44:00 PM * @author Fly * @return */ private int getSize() { int[] sizes = new int[20]; for (int i = 0; i \u0026lt; 20; i++) { sizes[i] = 30 + i; } return sizes[(int) (Math.random() * sizes.length)]; } /** * 获取验证码图像，并把图像用流输出 * 生成字母和数字的验证码 * @date Jun 13, 2008 3:19:12 PM * @author Fly * @param imageType 验证码输出的类型，可以是PNG或者JPGE * @param output 输出流 * @return 验证码字符串 * @throws IOException */ public String drawImageOfABC123( OutputStream output) throws IOException { try { this.drawImage(this.getImageOfABC123(), output); } catch (IOException e) { e.printStackTrace(); throw e; } finally{ output.flush(); output.close(); } return codes; } public String drawImageOfABC123( ByteArrayOutputStream output) throws IOException { try { //ImageIO.write(this.getImageOfABC123(), imageType.toUpperCase(), output); this.drawImage(this.getImageOfABC123(), output); } catch (IOException e) { e.printStackTrace(); throw e; }finally{ output.flush(); output.close(); } return codes; } /** * 获取验证码图像，并把图像用流输出 * 生成加减乘除的验证码 * @date Jun 13, 2008 3:20:40 PM * @author Fly * @param imageType 验证码输出的类型，可以是PNG或者JPGE * @param output 输出流 * @return 验证码字符串 * @throws IOException */ public String drawImageOfMultiplicationFormula(OutputStream output) throws IOException{ try { this.drawImage(this.getImageOfMultiplicationFormula(), output); //ImageIO.write(this.getImageOfMultiplicationFormula(), imageType.toUpperCase(), output); } catch (IOException e) { e.printStackTrace(); throw e; }finally{ output.flush(); output.close(); } return codes; } public String drawImageOfMultiplicationFormula(ByteArrayOutputStream output) throws IOException{ try { this.drawImage(this.getImageOfMultiplicationFormula(), output); //ImageIO.write(this.getImageOfMultiplicationFormula(), imageType.toUpperCase(), output); } catch (IOException e) { e.printStackTrace(); throw e; } finally{ output.flush(); output.close(); } return codes; } /** * 获取验证码图像，并把图像用流输出 * 生成中文汉字的验证码 * @date Jun 13, 2008 3:13:15 PM * @author Fly * @param imageType 验证码输出的类型，可以是PNG或者JPGE * @param output 输出流 * @return 验证码字符串 * @throws IOException */ public String drawImageOfChineseChar(OutputStream output) throws IOException{ try { //ImageIO.write(this.getImageOfChineseChar(), imageType.toUpperCase(), output); this.drawImage(this.getImageOfChineseChar(), output); } catch (IOException e) { e.printStackTrace(); throw e; }finally{ output.flush(); output.close(); } return codes; } public String drawImageOfChineseChar(ByteArrayOutputStream output) throws IOException{ try { this.drawImage(this.getImageOfChineseChar(), output); //ImageIO.write(this.getImageOfChineseChar(), imageType.toUpperCase(), output); } catch (IOException e) { e.printStackTrace(); throw e; }finally{ output.flush(); output.close(); } return codes; } /** * 产生清晰的图片 * @Author：正能量 * @date:Oct 22, 2009 9:47:42 AM * @param image * @param output * @throws IOException */ private void drawImage(BufferedImage image,Object output) throws IOException{ //BufferedImage image =this.getImageOfABC123(); //ImageIO.write(this.getImageOfABC123(), imageType.toUpperCase(), output); ImageWriter writer = null; ImageTypeSpecifier type = ImageTypeSpecifier.createFromRenderedImage(image); Iterator\u0026lt;ImageWriter\u0026gt; iter = ImageIO.getImageWriters(type, \u0026#34;JPG\u0026#34;); if (iter.hasNext()) { writer = (ImageWriter) iter.next(); } IIOImage iioImage = new IIOImage(image, null, null); ImageWriteParam param = writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality((float) (1)); ImageOutputStream outputStream = ImageIO.createImageOutputStream(output); writer.setOutput(outputStream); writer.write(null, iioImage, param); } /** * 产生从X到Y的随机数 * * @date Jun 13, 2008 9:59:47 AM * @author Fly * @param x * @param y * @return */ private int getRandom(int x, int y) { return new Random().nextInt(y - x + 1) + x; } /** * 生成乘法口诀类似的加、减、乘、除运算公式 * * @date Jun 13, 2008 10:03:37 AM * @author Fly * @return */ private BufferedImage getImageOfMultiplicationFormula(){ String cds=this.getMultiplication(this.getRandom(1, 4)); int width_; final int height_=50; //根据文字的长度设置图片的宽度 switch (cds.length()) { case 7:width_=160;break; case 8:width_=180;break; case 6:width_=140;break; case 5:width_=120;break; default:width_=150;break; } BufferedImage bi = new BufferedImage(width_, height_,BufferedImage.TYPE_INT_RGB); Graphics2D g = bi.createGraphics(); //抗锯齿，图片不失真 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(this.getBgColor()); g.fillRect(0, 0, width_, height_); for (int i=0;i\u0026lt;cds.length();i++){ g.setColor(new Color((int) (Math.random() * 100), (int) (Math.random() * 100), (int) (Math.random() * 100))); g.setFont(((Font) fonts.get((int) (Math.random() * fonts.size()))).deriveFont(this.getFace(), 25)); g.drawString(String.valueOf(cds.charAt(i)),22*i+5,35); } //画干扰线 this.drawLine(g, 3,200,50); //画杂点 this.drawPoint(g, 30,width_,height_); // 画个边框 //g.setColor(new Color((int) (Math.random() * 0x00FFFFFFF))); //g.drawRect(1, 1, width_ - 2, height_ - 2); g.dispose(); bi.flush(); return bi; } private String getMultiplication(int type) { int a,b,v; String ret=null; if(type\u0026gt;this.DIVIDED){ a=this.getRandom(0, 99); b=this.getRandom(0, 99); }else{ a=this.getRandom(0, 9); b=this.getRandom(0, 9); } //乘以 if(this.MULTIPLY==type){ v=a*b; this.codes=String .valueOf(v); ret=this.getArithmetic(a, b, type); return ret; } //除以 if(this.DIVIDED==type){ //保证除数不为0 b=this.getRandom(1, 9); v=a*b; this.codes=String.valueOf(a); ret=this.getArithmetic(v, b, type); return ret; } //加上 if(this.PLUS==type){ v=a+b; this.codes=String.valueOf(v); ret=this.getArithmetic(a, b, type); return ret; } //减去 if(this.SUBTRACT==type){ v=a+b; this.codes=String.valueOf(a); ret=this.getArithmetic(v, b, type); return ret; } return ret; } private String getArithmetic(int a,int b,int type){ String str=\u0026#34;\u0026#34;; switch (type) { case MULTIPLY: str=a+\u0026#34;×\u0026#34;+b+\u0026#34;＝？\u0026#34;; break; case DIVIDED: str=a+\u0026#34;÷\u0026#34;+b+\u0026#34;＝？\u0026#34;; break; case PLUS: str=a+\u0026#34;＋\u0026#34;+b+\u0026#34;＝？\u0026#34;; break; case SUBTRACT: str=a+\u0026#34;－\u0026#34;+b+\u0026#34;＝？\u0026#34;; break; default: str=a+\u0026#34;×\u0026#34;+b+\u0026#34;＝？\u0026#34;; break; } return str; } /** * 得到随机常用汉字 * 从2500个常用汉字中选 * @date Jun 13, 2008 2:18:53 PM * @author Fly * @return */ private char getRandomChineseChar() { String str=\u0026#34;\\u4e00\\u4e59\\u4e8c\\u5341\\u4e01\\u5382\\u4e03\\u535c\\u4eba\\u5165\\u516b\\u4e5d\\u51e0\\u513f\\u4e86\\u529b\\u4e43\\u5200\\u53c8\\u4e09\\u4e8e\\u5e72\\u4e8f\\u58eb\\u5de5\\u571f\\u624d\\u5bf8\\u4e0b\\u5927\\u4e08\\u4e0e\\u4e07\\u4e0a\\u5c0f\\u53e3\\u5dfe\\u5c71\\u5343\\u4e5e\\u5ddd\\u4ebf\\u4e2a\\u52fa\\u4e45\\u51e1\\u53ca\\u5915\\u4e38\\u4e48\\u5e7f\\u4ea1\\u95e8\\u4e49\\u4e4b\\u5c38\\u5f13\\u5df1\\u5df2\\u5b50\\u536b\\u4e5f\\u5973\\u98de\\u5203\\u4e60\\u53c9\\u9a6c\\u4e61\\u4e30\\u738b\\u4e95\\u5f00\\u592b\\u5929\\u65e0\\u5143\\u4e13\\u4e91\\u624e\\u827a\\u6728\\u4e94\\u652f\\u5385\\u4e0d\\u592a\\u72ac\\u533a\\u5386\\u5c24\\u53cb\\u5339\\u8f66\\u5de8\\u7259\\u5c6f\\u6bd4\\u4e92\\u5207\\u74e6\\u6b62\\u5c11\\u65e5\\u4e2d\\u5188\\u8d1d\\u5185\\u6c34\\u89c1\\u5348\\u725b\\u624b\\u6bdb\\u6c14\\u5347\\u957f\\u4ec1\\u4ec0\\u7247\\u4ec6\\u5316\\u4ec7\\u5e01\\u4ecd\\u4ec5\\u65a4\\u722a\\u53cd\\u4ecb\\u7236\\u4ece\\u4eca\\u51f6\\u5206\\u4e4f\\u516c\\u4ed3\\u6708\\u6c0f\\u52ff\\u6b20\\u98ce\\u4e39\\u5300\\u4e4c\\u51e4\\u52fe\\u6587\\u516d\\u65b9\\u706b\\u4e3a\\u6597\\u5fc6\\u8ba2\\u8ba1\\u6237\\u8ba4\\u5fc3\\u5c3a\\u5f15\\u4e11\\u5df4\\u5b54\\u961f\\u529e\\u4ee5\\u5141\\u4e88\\u529d\\u53cc\\u4e66\\u5e7b\\u7389\\u520a\\u793a\\u672b\\u672a\\u51fb\\u6253\\u5de7\\u6b63\\u6251\\u6252\\u529f\\u6254\\u53bb\\u7518\\u4e16\\u53e4\\u8282\\u672c\\u672f\\u53ef\\u4e19\\u5de6\\u5389\\u53f3\\u77f3\\u5e03\\u9f99\\u5e73\\u706d\\u8f67\\u4e1c\\u5361\\u5317\\u5360\\u4e1a\\u65e7\\u5e05\\u5f52\\u4e14\\u65e6\\u76ee\\u53f6\\u7532\\u7533\\u53ee\\u7535\\u53f7\\u7530\\u7531\\u53f2\\u53ea\\u592e\\u5144\\u53fc\\u53eb\\u53e6\\u53e8\\u53f9\\u56db\\u751f\\u5931\\u79be\\u4e18\\u4ed8\\u4ed7\\u4ee3\\u4ed9\\u4eec\\u4eea\\u767d\\u4ed4\\u4ed6\\u65a5\\u74dc\\u4e4e\\u4e1b\\u4ee4\\u7528\\u7529\\u5370\\u4e50\\u53e5\\u5306\\u518c\\u72af\\u5916\\u5904\\u51ac\\u9e1f\\u52a1\\u5305\\u9965\\u4e3b\\u5e02\\u7acb\\u95ea\\u5170\\u534a\\u6c41\\u6c47\\u5934\\u6c49\\u5b81\\u7a74\\u5b83\\u8ba8\\u5199\\u8ba9\\u793c\\u8bad\\u5fc5\\u8bae\\u8baf\\u8bb0\\u6c38\\u53f8\\u5c3c\\u6c11\\u51fa\\u8fbd\\u5976\\u5974\\u52a0\\u53ec\\u76ae\\u8fb9\\u53d1\\u5b55\\u5723\\u5bf9\\u53f0\\u77db\\u7ea0\\u6bcd\\u5e7c\\u4e1d\\u5f0f\\u5211\\u52a8\\u625b\\u5bfa\\u5409\\u6263\\u8003\\u6258\\u8001\\u6267\\u5de9\\u573e\\u6269\\u626b\\u5730\\u626c\\u573a\\u8033\\u5171\\u8292\\u4e9a\\u829d\\u673d\\u6734\\u673a\\u6743\\u8fc7\\u81e3\\u518d\\u534f\\u897f\\u538b\\u538c\\u5728\\u6709\\u767e\\u5b58\\u800c\\u9875\\u5320\\u5938\\u593a\\u7070\\u8fbe\\u5217\\u6b7b\\u6210\\u5939\\u8f68\\u90aa\\u5212\\u8fc8\\u6bd5\\u81f3\\u6b64\\u8d1e\\u5e08\\u5c18\\u5c16\\u52a3\\u5149\\u5f53\\u65e9\\u5410\\u5413\\u866b\\u66f2\\u56e2\\u540c\\u540a\\u5403\\u56e0\\u5438\\u5417\\u5c7f\\u5e06\\u5c81\\u56de\\u5c82\\u521a\\u5219\\u8089\\u7f51\\u5e74\\u6731\\u5148\\u4e22\\u820c\\u7af9\\u8fc1\\u4e54\\u4f1f\\u4f20\\u4e52\\u4e53\\u4f11\\u4f0d\\u4f0f\\u4f18\\u4f10\\u5ef6\\u4ef6\\u4efb\\u4f24\\u4ef7\\u4efd\\u534e\\u4ef0\\u4eff\\u4f19\\u4f2a\\u81ea\\u8840\\u5411\\u4f3c\\u540e\\u884c\\u821f\\u5168\\u4f1a\\u6740\\u5408\\u5146\\u4f01\\u4f17\\u7237\\u4f1e\\u521b\\u808c\\u6735\\u6742\\u5371\\u65ec\\u65e8\\u8d1f\\u5404\\u540d\\u591a\\u4e89\\u8272\\u58ee\\u51b2\\u51b0\\u5e84\\u5e86\\u4ea6\\u5218\\u9f50\\u4ea4\\u6b21\\u8863\\u4ea7\\u51b3\\u5145\\u5984\\u95ed\\u95ee\\u95ef\\u7f8a\\u5e76\\u5173\\u7c73\\u706f\\u5dde\\u6c57\\u6c61\\u6c5f\\u6c60\\u6c64\\u5fd9\\u5174\\u5b87\\u5b88\\u5b85\\u5b57\\u5b89\\u8bb2\\u519b\\u8bb8\\u8bba\\u519c\\u8bbd\\u8bbe\\u8bbf\\u5bfb\\u90a3\\u8fc5\\u5c3d\\u5bfc\\u5f02\\u5b59\\u9635\\u9633\\u6536\\u9636\\u9634\\u9632\\u5978\\u5982\\u5987\\u597d\\u5979\\u5988\\u620f\\u7fbd\\u89c2\\u6b22\\u4e70\\u7ea2\\u7ea4\\u7ea7\\u7ea6\\u7eaa\\u9a70\\u5de1\\u5bff\\u5f04\\u9ea6\\u5f62\\u8fdb\\u6212\\u541e\\u8fdc\\u8fdd\\u8fd0\\u6276\\u629a\\u575b\\u6280\\u574f\\u6270\\u62d2\\u627e\\u6279\\u626f\\u5740\\u8d70\\u6284\\u575d\\u8d21\\u653b\\u8d64\\u6298\\u6293\\u626e\\u62a2\\u5b5d\\u5747\\u629b\\u6295\\u575f\\u6297\\u5751\\u574a\\u6296\\u62a4\\u58f3\\u5fd7\\u626d\\u5757\\u58f0\\u628a\\u62a5\\u5374\\u52ab\\u82bd\\u82b1\\u82b9\\u82ac\\u82cd\\u82b3\\u4e25\\u82a6\\u52b3\\u514b\\u82cf\\u6746\\u6760\\u675c\\u6750\\u6751\\u674f\\u6781\\u674e\\u6768\\u6c42\\u66f4\\u675f\\u8c46\\u4e24\\u4e3d\\u533b\\u8fb0\\u52b1\\u5426\\u8fd8\\u6b7c\\u6765\\u8fde\\u6b65\\u575a\\u65f1\\u76ef\\u5448\\u65f6\\u5434\\u52a9\\u53bf\\u91cc\\u5446\\u56ed\\u65f7\\u56f4\\u5440\\u5428\\u8db3\\u90ae\\u7537\\u56f0\\u5435\\u4e32\\u5458\\u542c\\u5429\\u5439\\u545c\\u5427\\u543c\\u522b\\u5c97\\u5e10\\u8d22\\u9488\\u9489\\u544a\\u6211\\u4e71\\u5229\\u79c3\\u79c0\\u79c1\\u6bcf\\u5175\\u4f30\\u4f53\\u4f55\\u4f46\\u4f38\\u4f5c\\u4f2f\\u4f36\\u4f63\\u4f4e\\u4f60\\u4f4f\\u4f4d\\u4f34\\u8eab\\u7682\\u4f5b\\u8fd1\\u5f7b\\u5f79\\u8fd4\\u4f59\\u5e0c\\u5750\\u8c37\\u59a5\\u542b\\u90bb\\u5c94\\u809d\\u809a\\u80a0\\u9f9f\\u514d\\u72c2\\u72b9\\u89d2\\u5220\\u6761\\u5375\\u5c9b\\u8fce\\u996d\\u996e\\u7cfb\\u8a00\\u51bb\\u72b6\\u4ea9\\u51b5\\u5e8a\\u5e93\\u7597\\u5e94\\u51b7\\u8fd9\\u5e8f\\u8f9b\\u5f03\\u51b6\\u5fd8\\u95f2\\u95f4\\u95f7\\u5224\\u7076\\u707f\\u5f1f\\u6c6a\\u6c99\\u6c7d\\u6c83\\u6cdb\\u6c9f\\u6ca1\\u6c88\\u6c89\\u6000\\u5fe7\\u5feb\\u5b8c\\u5b8b\\u5b8f\\u7262\\u7a76\\u7a77\\u707e\\u826f\\u8bc1\\u542f\\u8bc4\\u8865\\u521d\\u793e\\u8bc6\\u8bc9\\u8bca\\u8bcd\\u8bd1\\u541b\\u7075\\u5373\\u5c42\\u5c3f\\u5c3e\\u8fdf\\u5c40\\u6539\\u5f20\\u5fcc\\u9645\\u9646\\u963f\\u9648\\u963b\\u9644\\u5999\\u5996\\u59a8\\u52aa\\u5fcd\\u52b2\\u9e21\\u9a71\\u7eaf\\u7eb1\\u7eb3\\u7eb2\\u9a73\\u7eb5\\u7eb7\\u7eb8\\u7eb9\\u7eba\\u9a74\\u7ebd\\u5949\\u73a9\\u73af\\u6b66\\u9752\\u8d23\\u73b0\\u8868\\u89c4\\u62b9\\u62e2\\u62d4\\u62e3\\u62c5\\u5766\\u62bc\\u62bd\\u62d0\\u62d6\\u62cd\\u8005\\u9876\\u62c6\\u62e5\\u62b5\\u62d8\\u52bf\\u62b1\\u5783\\u62c9\\u62e6\\u62cc\\u5e78\\u62db\\u5761\\u62ab\\u62e8\\u62e9\\u62ac\\u5176\\u53d6\\u82e6\\u82e5\\u8302\\u82f9\\u82d7\\u82f1\\u8303\\u76f4\\u8304\\u830e\\u8305\\u6797\\u679d\\u676f\\u67dc\\u6790\\u677f\\u677e\\u67aa\\u6784\\u6770\\u8ff0\\u6795\\u4e27\\u6216\\u753b\\u5367\\u4e8b\\u523a\\u67a3\\u96e8\\u5356\\u77ff\\u7801\\u5395\\u5954\\u5947\\u594b\\u6001\\u6b27\\u5784\\u59bb\\u8f70\\u9877\\u8f6c\\u65a9\\u8f6e\\u8f6f\\u5230\\u975e\\u53d4\\u80af\\u9f7f\\u4e9b\\u864e\\u864f\\u80be\\u8d24\\u5c1a\\u65fa\\u5177\\u679c\\u5473\\u6606\\u56fd\\u660c\\u7545\\u660e\\u6613\\u6602\\u5178\\u56fa\\u5fe0\\u5490\\u547c\\u9e23\\u548f\\u5462\\u5cb8\\u5ca9\\u5e16\\u7f57\\u5e1c\\u5cad\\u51ef\\u8d25\\u8d29\\u8d2d\\u56fe\\u9493\\u5236\\u77e5\\u5782\\u7267\\u7269\\u4e56\\u522e\\u79c6\\u548c\\u5b63\\u59d4\\u4f73\\u4f8d\\u4f9b\\u4f7f\\u4f8b\\u7248\\u4f84\\u4fa6\\u4fa7\\u51ed\\u4fa8\\u4f69\\u8d27\\u4f9d\\u7684\\u8feb\\u8d28\\u6b23\\u5f81\\u5f80\\u722c\\u5f7c\\u5f84\\u6240\\u820d\\u91d1\\u547d\\u65a7\\u7238\\u91c7\\u53d7\\u4e73\\u8d2a\\u5ff5\\u8d2b\\u80a4\\u80ba\\u80a2\\u80bf\\u80c0\\u670b\\u80a1\\u80a5\\u670d\\u80c1\\u5468\\u660f\\u9c7c\\u5154\\u72d0\\u5ffd\\u72d7\\u5907\\u9970\\u9971\\u9972\\u53d8\\u4eac\\u4eab\\u5e97\\u591c\\u5e99\\u5e9c\\u5e95\\u5242\\u90ca\\u5e9f\\u51c0\\u76f2\\u653e\\u523b\\u80b2\\u95f8\\u95f9\\u90d1\\u5238\\u5377\\u5355\\u7092\\u708a\\u7095\\u708e\\u7089\\u6cab\\u6d45\\u6cd5\\u6cc4\\u6cb3\\u6cbe\\u6cea\\u6cb9\\u6cca\\u6cbf\\u6ce1\\u6ce8\\u6cfb\\u6cf3\\u6ce5\\u6cb8\\u6ce2\\u6cfc\\u6cfd\\u6cbb\\u6016\\u6027\\u6015\\u601c\\u602a\\u5b66\\u5b9d\\u5b97\\u5b9a\\u5b9c\\u5ba1\\u5b99\\u5b98\\u7a7a\\u5e18\\u5b9e\\u8bd5\\u90ce\\u8bd7\\u80a9\\u623f\\u8bda\\u886c\\u886b\\u89c6\\u8bdd\\u8bde\\u8be2\\u8be5\\u8be6\\u5efa\\u8083\\u5f55\\u96b6\\u5c45\\u5c4a\\u5237\\u5c48\\u5f26\\u627f\\u5b5f\\u5b64\\u9655\\u964d\\u9650\\u59b9\\u59d1\\u59d0\\u59d3\\u59cb\\u9a7e\\u53c2\\u8270\\u7ebf\\u7ec3\\u7ec4\\u7ec6\\u9a76\\u7ec7\\u7ec8\\u9a7b\\u9a7c\\u7ecd\\u7ecf\\u8d2f\\u594f\\u6625\\u5e2e\\u73cd\\u73bb\\u6bd2\\u578b\\u6302\\u5c01\\u6301\\u9879\\u57ae\\u630e\\u57ce\\u6320\\u653f\\u8d74\\u8d75\\u6321\\u633a\\u62ec\\u62f4\\u62fe\\u6311\\u6307\\u57ab\\u6323\\u6324\\u62fc\\u6316\\u6309\\u6325\\u632a\\u67d0\\u751a\\u9769\\u8350\\u5df7\\u5e26\\u8349\\u8327\\u8336\\u8352\\u832b\\u8361\\u8363\\u6545\\u80e1\\u5357\\u836f\\u6807\\u67af\\u67c4\\u680b\\u76f8\\u67e5\\u67cf\\u67f3\\u67f1\\u67ff\\u680f\\u6811\\u8981\\u54b8\\u5a01\\u6b6a\\u7814\\u7816\\u5398\\u539a\\u780c\\u780d\\u9762\\u8010\\u800d\\u7275\\u6b8b\\u6b83\\u8f7b\\u9e26\\u7686\\u80cc\\u6218\\u70b9\\u4e34\\u89c8\\u7ad6\\u7701\\u524a\\u5c1d\\u662f\\u76fc\\u7728\\u54c4\\u663e\\u54d1\\u5192\\u6620\\u661f\\u6628\\u754f\\u8db4\\u80c3\\u8d35\\u754c\\u8679\\u867e\\u8681\\u601d\\u8682\\u867d\\u54c1\\u54bd\\u9a82\\u54d7\\u54b1\\u54cd\\u54c8\\u54ac\\u54b3\\u54ea\\u70ad\\u5ce1\\u7f5a\\u8d31\\u8d34\\u9aa8\\u949e\\u949f\\u94a2\\u94a5\\u94a9\\u5378\\u7f38\\u62dc\\u770b\\u77e9\\u600e\\u7272\\u9009\\u9002\\u79d2\\u9999\\u79cd\\u79cb\\u79d1\\u91cd\\u590d\\u7aff\\u6bb5\\u4fbf\\u4fe9\\u8d37\\u987a\\u4fee\\u4fdd\\u4fc3\\u4fae\\u4fed\\u4fd7\\u4fd8\\u4fe1\\u7687\\u6cc9\\u9b3c\\u4fb5\\u8ffd\\u4fca\\u76fe\\u5f85\\u5f8b\\u5f88\\u987b\\u53d9\\u5251\\u9003\\u98df\\u76c6\\u80c6\\u80dc\\u80de\\u80d6\\u8109\\u52c9\\u72ed\\u72ee\\u72ec\\u72e1\\u72f1\\u72e0\\u8d38\\u6028\\u6025\\u9976\\u8680\\u997a\\u997c\\u5f2f\\u5c06\\u5956\\u54c0\\u4ead\\u4eae\\u5ea6\\u8ff9\\u5ead\\u75ae\\u75af\\u75ab\\u75a4\\u59ff\\u4eb2\\u97f3\\u5e1d\\u65bd\\u95fb\\u9600\\u9601\\u5dee\\u517b\\u7f8e\\u59dc\\u53db\\u9001\\u7c7b\\u8ff7\\u524d\\u9996\\u9006\\u603b\\u70bc\\u70b8\\u70ae\\u70c2\\u5243\\u6d01\\u6d2a\\u6d12\\u6d47\\u6d4a\\u6d1e\\u6d4b\\u6d17\\u6d3b\\u6d3e\\u6d3d\\u67d3\\u6d4e\\u6d0b\\u6d32\\u6d51\\u6d53\\u6d25\\u6052\\u6062\\u6070\\u607c\\u6068\\u4e3e\\u89c9\\u5ba3\\u5ba4\\u5bab\\u5baa\\u7a81\\u7a7f\\u7a83\\u5ba2\\u51a0\\u8bed\\u6241\\u8884\\u7956\\u795e\\u795d\\u8bef\\u8bf1\\u8bf4\\u8bf5\\u57a6\\u9000\\u65e2\\u5c4b\\u663c\\u8d39\\u9661\\u7709\\u5b69\\u9664\\u9669\\u9662\\u5a03\\u59e5\\u59e8\\u59fb\\u5a07\\u6012\\u67b6\\u8d3a\\u76c8\\u52c7\\u6020\\u67d4\\u5792\\u7ed1\\u7ed2\\u7ed3\\u7ed5\\u9a84\\u7ed8\\u7ed9\\u7edc\\u9a86\\u7edd\\u7ede\\u7edf\\u8015\\u8017\\u8273\\u6cf0\\u73e0\\u73ed\\u7d20\\u8695\\u987d\\u76cf\\u532a\\u635e\\u683d\\u6355\\u632f\\u8f7d\\u8d76\\u8d77\\u76d0\\u634e\\u634f\\u57cb\\u6349\\u6346\\u6350\\u635f\\u90fd\\u54f2\\u901d\\u6361\\u6362\\u633d\\u70ed\\u6050\\u58f6\\u6328\\u803b\\u803d\\u606d\\u83b2\\u83ab\\u8377\\u83b7\\u664b\\u6076\\u771f\\u6846\\u6842\\u6863\\u6850\\u682a\\u6865\\u6843\\u683c\\u6821\\u6838\\u6837\\u6839\\u7d22\\u54e5\\u901f\\u9017\\u6817\\u914d\\u7fc5\\u8fb1\\u5507\\u590f\\u7840\\u7834\\u539f\\u5957\\u9010\\u70c8\\u6b8a\\u987e\\u8f7f\\u8f83\\u987f\\u6bd9\\u81f4\\u67f4\\u684c\\u8651\\u76d1\\u7d27\\u515a\\u6652\\u7720\\u6653\\u9e2d\\u6643\\u664c\\u6655\\u868a\\u54e8\\u54ed\\u6069\\u5524\\u554a\\u5509\\u7f62\\u5cf0\\u5706\\u8d3c\\u8d3f\\u94b1\\u94b3\\u94bb\\u94c1\\u94c3\\u94c5\\u7f3a\\u6c27\\u7279\\u727a\\u9020\\u4e58\\u654c\\u79e4\\u79df\\u79ef\\u79e7\\u79e9\\u79f0\\u79d8\\u900f\\u7b14\\u7b11\\u7b0b\\u503a\\u501f\\u503c\\u501a\\u503e\\u5012\\u5018\\u4ff1\\u5021\\u5019\\u4fef\\u500d\\u5026\\u5065\\u81ed\\u5c04\\u8eac\\u606f\\u5f92\\u5f90\\u8230\\u8231\\u822c\\u822a\\u9014\\u62ff\\u7239\\u7231\\u9882\\u7fc1\\u8106\\u8102\\u80f8\\u80f3\\u810f\\u80f6\\u8111\\u72f8\\u72fc\\u9022\\u7559\\u76b1\\u997f\\u604b\\u6868\\u6d46\\u8870\\u9ad8\\u5e2d\\u51c6\\u5ea7\\u810a\\u75c7\\u75c5\\u75be\\u75bc\\u75b2\\u6548\\u79bb\\u5510\\u8d44\\u51c9\\u7ad9\\u5256\\u7ade\\u90e8\\u65c1\\u65c5\\u755c\\u9605\\u7f9e\\u74f6\\u62f3\\u7c89\\u6599\\u76ca\\u517c\\u70e4\\u70d8\\u70e6\\u70e7\\u70db\\u70df\\u9012\\u6d9b\\u6d59\\u6d9d\\u9152\\u6d89\\u6d88\\u6d69\\u6d77\\u6d82\\u6d74\\u6d6e\\u6d41\\u6da6\\u6d6a\\u6d78\\u6da8\\u70eb\\u6d8c\\u609f\\u6084\\u6094\\u60a6\\u5bb3\\u5bbd\\u5bb6\\u5bb5\\u5bb4\\u5bbe\\u7a84\\u5bb9\\u5bb0\\u6848\\u8bf7\\u6717\\u8bf8\\u8bfb\\u6247\\u889c\\u8896\\u888d\\u88ab\\u7965\\u8bfe\\u8c01\\u8c03\\u51a4\\u8c05\\u8c08\\u8c0a\\u5265\\u6073\\u5c55\\u5267\\u5c51\\u5f31\\u9675\\u9676\\u9677\\u966a\\u5a31\\u5a18\\u901a\\u80fd\\u96be\\u9884\\u6851\\u7ee2\\u7ee3\\u9a8c\\u7ee7\\u7403\\u7406\\u6367\\u5835\\u63cf\\u57df\\u63a9\\u6377\\u6392\\u6389\\u5806\\u63a8\\u6380\\u6388\\u6559\\u638f\\u63a0\\u57f9\\u63a5\\u63a7\\u63a2\\u636e\\u6398\\u804c\\u57fa\\u8457\\u52d2\\u9ec4\\u840c\\u841d\\u83cc\\u83dc\\u8404\\u83ca\\u840d\\u83e0\\u8425\\u68b0\\u68a6\\u68a2\\u6885\\u68c0\\u68b3\\u68af\\u6876\\u6551\\u526f\\u7968\\u621a\\u723d\\u804b\\u88ad\\u76db\\u96ea\\u8f85\\u8f86\\u865a\\u96c0\\u5802\\u5e38\\u5319\\u6668\\u7741\\u772f\\u773c\\u60ac\\u91ce\\u5566\\u665a\\u5544\\u8ddd\\u8dc3\\u7565\\u86c7\\u7d2f\\u5531\\u60a3\\u552f\\u5d16\\u5d2d\\u5d07\\u5708\\u94dc\\u94f2\\u94f6\\u751c\\u68a8\\u7281\\u79fb\\u7b28\\u7b3c\\u7b1b\\u7b26\\u7b2c\\u654f\\u505a\\u888b\\u60a0\\u507f\\u5076\\u5077\\u60a8\\u552e\\u505c\\u504f\\u5047\\u5f97\\u8854\\u76d8\\u8239\\u659c\\u76d2\\u9e3d\\u6089\\u6b32\\u5f69\\u9886\\u811a\\u8116\\u8138\\u8131\\u8c61\\u591f\\u731c\\u732a\\u730e\\u732b\\u731b\\u9985\\u9986\\u51d1\\u51cf\\u6beb\\u9ebb\\u75d2\\u75d5\\u5eca\\u5eb7\\u5eb8\\u9e7f\\u76d7\\u7ae0\\u7adf\\u5546\\u65cf\\u65cb\\u671b\\u7387\\u7740\\u76d6\\u7c98\\u7c97\\u7c92\\u65ad\\u526a\\u517d\\u6e05\\u6dfb\\u6dcb\\u6df9\\u6e20\\u6e10\\u6df7\\u6e14\\u6dd8\\u6db2\\u6de1\\u6df1\\u5a46\\u6881\\u6e17\\u60c5\\u60dc\\u60ed\\u60bc\\u60e7\\u60d5\\u60ca\\u60e8\\u60ef\\u5bc7\\u5bc4\\u5bbf\\u7a91\\u5bc6\\u8c0b\\u8c0e\\u7978\\u8c1c\\u902e\\u6562\\u5c60\\u5f39\\u968f\\u86cb\\u9686\\u9690\\u5a5a\\u5a76\\u9888\\u7ee9\\u7eea\\u7eed\\u9a91\\u7ef3\\u7ef4\\u7ef5\\u7ef8\\u7eff\\u7434\\u6591\\u66ff\\u6b3e\\u582a\\u642d\\u5854\\u8d8a\\u8d81\\u8d8b\\u8d85\\u63d0\\u5824\\u535a\\u63ed\\u559c\\u63d2\\u63ea\\u641c\\u716e\\u63f4\\u88c1\\u6401\\u6402\\u6405\\u63e1\\u63c9\\u65af\\u671f\\u6b3a\\u8054\\u6563\\u60f9\\u846c\\u845b\\u8463\\u8461\\u656c\\u8471\\u843d\\u671d\\u8f9c\\u8475\\u68d2\\u68cb\\u690d\\u68ee\\u6905\\u6912\\u68f5\\u68cd\\u68c9\\u68da\\u68d5\\u60e0\\u60d1\\u903c\\u53a8\\u53a6\\u786c\\u786e\\u96c1\\u6b96\\u88c2\\u96c4\\u6682\\u96c5\\u8f88\\u60b2\\u7d2b\\u8f89\\u655e\\u8d4f\\u638c\\u6674\\u6691\\u6700\\u91cf\\u55b7\\u6676\\u5587\\u9047\\u558a\\u666f\\u8df5\\u8dcc\\u8dd1\\u9057\\u86d9\\u86db\\u8713\\u559d\\u5582\\u5598\\u5589\\u5e45\\u5e3d\\u8d4c\\u8d54\\u9ed1\\u94f8\\u94fa\\u94fe\\u9500\\u9501\\u9504\\u9505\\u9508\\u950b\\u9510\\u77ed\\u667a\\u6bef\\u9e45\\u5269\\u7a0d\\u7a0b\\u7a00\\u7a0e\\u7b50\\u7b49\\u7b51\\u7b56\\u7b5b\\u7b52\\u7b54\\u7b4b\\u7b5d\\u50b2\\u5085\\u724c\\u5821\\u96c6\\u7126\\u508d\\u50a8\\u5965\\u8857\\u60e9\\u5fa1\\u5faa\\u8247\\u8212\\u756a\\u91ca\\u79bd\\u814a\\u813e\\u8154\\u9c81\\u733e\\u7334\\u7136\\u998b\\u88c5\\u86ee\\u5c31\\u75db\\u7ae5\\u9614\\u5584\\u7fa1\\u666e\\u7caa\\u5c0a\\u9053\\u66fe\\u7130\\u6e2f\\u6e56\\u6e23\\u6e7f\\u6e29\\u6e34\\u6ed1\\u6e7e\\u6e21\\u6e38\\u6ecb\\u6e89\\u6124\\u614c\\u60f0\\u6127\\u6109\\u6168\\u5272\\u5bd2\\u5bcc\\u7a9c\\u7a9d\\u7a97\\u904d\\u88d5\\u88e4\\u88d9\\u8c22\\u8c23\\u8c26\\u5c5e\\u5c61\\u5f3a\\u7ca5\\u758f\\u9694\\u9699\\u7d6e\\u5ac2\\u767b\\u7f0e\\u7f13\\u7f16\\u9a97\\u7f18\\u745e\\u9b42\\u8086\\u6444\\u6478\\u586b\\u640f\\u584c\\u9f13\\u6446\\u643a\\u642c\\u6447\\u641e\\u5858\\u644a\\u849c\\u52e4\\u9e4a\\u84dd\\u5893\\u5e55\\u84ec\\u84c4\\u8499\\u84b8\\u732e\\u7981\\u695a\\u60f3\\u69d0\\u6986\\u697c\\u6982\\u8d56\\u916c\\u611f\\u788d\\u7891\\u788e\\u78b0\\u7897\\u788c\\u96f7\\u96f6\\u96fe\\u96f9\\u8f93\\u7763\\u9f84\\u9274\\u775b\\u7761\\u776c\\u9119\\u611a\\u6696\\u76df\\u6b47\\u6697\\u7167\\u8de8\\u8df3\\u8dea\\u8def\\u8ddf\\u9063\\u86fe\\u8702\\u55d3\\u7f6e\\u7f6a\\u7f69\\u9519\\u9521\\u9523\\u9524\\u9526\\u952e\\u952f\\u77ee\\u8f9e\\u7a20\\u6101\\u7b79\\u7b7e\\u7b80\\u6bc1\\u8205\\u9f20\\u50ac\\u50bb\\u50cf\\u8eb2\\u5fae\\u6108\\u9065\\u8170\\u8165\\u8179\\u817e\\u817f\\u89e6\\u89e3\\u9171\\u75f0\\u5ec9\\u65b0\\u97f5\\u610f\\u7cae\\u6570\\u714e\\u5851\\u6148\\u7164\\u714c\\u6ee1\\u6f20\\u6e90\\u6ee4\\u6ee5\\u6ed4\\u6eaa\\u6e9c\\u6eda\\u6ee8\\u7cb1\\u6ee9\\u614e\\u8a89\\u585e\\u8c28\\u798f\\u7fa4\\u6bbf\\u8f9f\\u969c\\u5acc\\u5ac1\\u53e0\\u7f1d\\u7f20\\u9759\\u78a7\\u7483\\u5899\\u6487\\u5609\\u6467\\u622a\\u8a93\\u5883\\u6458\\u6454\\u805a\\u853d\\u6155\\u66ae\\u8511\\u6a21\\u69b4\\u699c\\u69a8\\u6b4c\\u906d\\u9177\\u917f\\u9178\\u78c1\\u613f\\u9700\\u5f0a\\u88f3\\u9897\\u55fd\\u873b\\u8721\\u8747\\u8718\\u8d5a\\u9539\\u953b\\u821e\\u7a33\\u7b97\\u7ba9\\u7ba1\\u50da\\u9f3b\\u9b44\\u8c8c\\u819c\\u818a\\u8180\\u9c9c\\u7591\\u9992\\u88f9\\u6572\\u8c6a\\u818f\\u906e\\u8150\\u7626\\u8fa3\\u7aed\\u7aef\\u65d7\\u7cbe\\u6b49\\u7184\\u7194\\u6f06\\u6f02\\u6f2b\\u6ef4\\u6f14\\u6f0f\\u6162\\u5be8\\u8d5b\\u5bdf\\u871c\\u8c31\\u5ae9\\u7fe0\\u718a\\u51f3\\u9aa1\\u7f29\\u6167\\u6495\\u6492\\u8da3\\u8d9f\\u6491\\u64ad\\u649e\\u64a4\\u589e\\u806a\\u978b\\u8549\\u852c\\u6a2a\\u69fd\\u6a31\\u6a61\\u98d8\\u918b\\u9189\\u9707\\u9709\\u7792\\u9898\\u66b4\\u778e\\u5f71\\u8e22\\u8e0f\\u8e29\\u8e2a\\u8776\\u8774\\u5631\\u58a8\\u9547\\u9760\\u7a3b\\u9ece\\u7a3f\\u7a3c\\u7bb1\\u7bad\\u7bc7\\u50f5\\u8eba\\u50fb\\u5fb7\\u8258\\u819d\\u819b\\u719f\\u6469\\u989c\\u6bc5\\u7cca\\u9075\\u6f5c\\u6f6e\\u61c2\\u989d\\u6170\\u5288\\u64cd\\u71d5\\u85af\\u85aa\\u8584\\u98a0\\u6a58\\u6574\\u878d\\u9192\\u9910\\u5634\\u8e44\\u5668\\u8d60\\u9ed8\\u955c\\u8d5e\\u7bee\\u9080\\u8861\\u81a8\\u96d5\\u78e8\\u51dd\\u8fa8\\u8fa9\\u7cd6\\u7cd5\\u71c3\\u6fa1\\u6fc0\\u61d2\\u58c1\\u907f\\u7f34\\u6234\\u64e6\\u97a0\\u85cf\\u971c\\u971e\\u77a7\\u8e48\\u87ba\\u7a57\\u7e41\\u8fab\\u8d62\\u7cdf\\u7ce0\\u71e5\\u81c2\\u7ffc\\u9aa4\\u97ad\\u8986\\u8e66\\u9570\\u7ffb\\u9e70\\u8b66\\u6500\\u8e72\\u98a4\\u74e3\\u7206\\u7586\\u58e4\\u8000\\u8e81\\u56bc\\u56b7\\u7c4d\\u9b54\\u704c\\u8822\\u9738\\u9732\\u56ca\\u7f50\u0026#34;; return str.charAt(this.getRandom(0, str.length()-1)); } /** * 生成汉字验证码 * * @date Jun 13, 2008 3:14:14 PM * @author Fly * @return */ private BufferedImage getImageOfChineseChar(){ BufferedImage bi = new BufferedImage(150, 50,BufferedImage.TYPE_INT_RGB); Graphics2D g = bi.createGraphics(); g.setColor(this.getBgColor()); g.fillRect(0, 0, 150, 50); codes=\u0026#34;\u0026#34;; for (int i = 0; i \u0026lt; 4; i++) { //抗锯齿，图片不失真 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); String rands=String.valueOf(this.getRandomChineseChar()); g.setColor(new Color((int) (Math.random() * 200), 0, (int) (Math.random() * 200))); g.setFont(((Font) fonts.get((int) (Math.random() * fonts.size()))).deriveFont(this.getFace(), 28)); g.drawString(rands,32*i+10,35); codes+=rands; } //画干扰线 this.drawLine(g, 2,150,50); //画杂点 this.drawPoint(g, 20,150,50); // 画个边框 //g.setColor(new Color((int) (Math.random() * 0x00FFFFFFF))); //g.drawRect(1, 1, 150 - 2, 50 - 2); g.dispose(); bi.flush(); return bi; } /** * 读取文件 * * @date Jun 13, 2008 4:35:09 PM * @author Fly * @param filepath * @param ext * @return * @throws FileNotFoundException * @throws IOException */ private List readfile(String filepath, String ext){ List list = new ArrayList(); try { File file = new File(filepath); //如果不是字体路径那么就是字体文件 if (!file.isDirectory()) { list.add(file.getPath()); } else if (file.isDirectory()) { String[] filelist = file.list(); for (int i = 0; i \u0026lt; filelist.length; i++) { File readfile = new File(filepath + \u0026#34;/\u0026#34; + filelist[i]); if (!readfile.isDirectory()) { int x = filelist[i].lastIndexOf(\u0026#39;.\u0026#39;); if (filelist[i].substring(x + 1).toLowerCase().equals(ext.toLowerCase())) { list.add(readfile.getPath()); } } else if (readfile.isDirectory()) { //不再判断子文件夹 continue; } } } } catch (Exception e) { e.printStackTrace(); } return list; } /** * 在图片画杂点 * @date Sep 12, 2008 4:41:46 PM * @author Fly * @param g * @param num 杂点数目 * @param width 基于原点的最宽位置 * @param height 基于原点的最高位置 */ private void drawPoint(Graphics2D g,int num,int width,int height){ Random random = new Random(); for (int i = 0; i \u0026lt; num; i++) { int x = random.nextInt(width); int y = random.nextInt(height); g.setColor(new Color((int) (Math.random() * 0x00FFFFFFF))); g.setStroke(getStroke()); g.drawLine(x, y, x, y); } } /** * 在图片上画直线 * @date Sep 12, 2008 4:43:10 PM * @author Fly * @param g * @param num 线条数 * @param width 基于原点的最宽位置 * @param height 基于原点的最高位置 */ private void drawLine(Graphics2D g,int num,int width,int height){ for (int i = 0; i \u0026lt; num; i++) { g.setColor(new Color((int) (Math.random() * 0x00FFFFFFF))); g.drawLine((int) (Math.random() * width), (int) (Math.random() * height), (int) (Math.random() * width), (int) (Math.random() * height)); } } public static void main(String[] args) throws IOException { //List ls=null; RandomCodeImage c=new RandomCodeImage(); try { FileOutputStream o=new FileOutputStream(\u0026#34;c:\\\\a.jpg\u0026#34;); FileOutputStream a=new FileOutputStream(\u0026#34;c:\\\\b.jpg\u0026#34;); FileOutputStream d=new FileOutputStream(\u0026#34;c:\\\\c.jpg\u0026#34;); //ImageIO.write(rotateJ2D(c.getImageOfABC123(),30),\u0026#34;JPG\u0026#34;, o); System.out.println(c.drawImageOfABC123(o)); System.out.println(c.drawImageOfChineseChar(a)); System.out.println(c.drawImageOfMultiplicationFormula(d)); } catch (FileNotFoundException e) { e.printStackTrace(); throw e; } //System.out.println(c.getImageOfABC123()); //System.out.println((int)(Math.random()*6+1)); } } 补充阅读 # 理解 Java 图片验证码代码的图像生成用途，并补充接入业务时的校验边界。\n如何理解与使用 # 图片生成只是验证码流程的一部分，接入时还需要把挑战结果与对应会话关联，并明确有效期及使用次数。原代码中的字体、颜色和干扰线影响可读性。\n验证与边界 # 检查图片能否正常输出、刷新后是否生成新挑战，以及错误、过期和重复使用是否被拒绝；图中字符不能作为可公开返回的接口字段。原文件中的版权声明应继续保留。\n","date":"2013-05-14","externalUrl":null,"permalink":"/posts/java-captcha/","section":"文章归档","summary":"图片生成只是验证码流程的一部分，接入时还需要把挑战结果与对应会话关联，并明确有效期及使用次数。原代码中的字体、颜色和干扰线影响可读性。","title":"Java随机验证码","type":"posts"},{"content":" /ip firewall nat add action=dst-nat chain=dstnat comment=ToAddress disabled=no dst-port=80 protocol=tcp src-address-list=src1 to-addresses=192.168.88.1 to-ports=80 /ip firewall mangle add action=add-src-to-address-list address-list=src1 address-list-timeout=3s chain=prerouting comment=TimeOut1 disabled=no dst-port=80 protocol=tcp src-address-list=!src2 add action=add-src-to-address-list address-list=src2 address-list-timeout=3h chain=prerouting comment=TimeOut2 disabled=no dst-port=80 protocol=tcp src-address-list=src1 备注:\n1，192.168.88.1为内网首页强开WEB服务器IP。\n2，强开3秒，强开过的IP在3小时内不会再强开。\n补充阅读 # 阅读 RouterOS HTTP 首次访问跳转脚本，理解地址列表、三秒窗口和三小时重复访问限制。\n如何理解与使用 # 脚本通过地址列表区分新访问与已访问设备，再把匹配的 TCP 80 请求导向示例 Web 服务器；内网地址需要按实际拓扑替换。\n验证与边界 # 这是针对 HTTP 的历史配置，不能据此期待 HTTPS 页面也能透明跳转。验证时分别观察新客户端、三秒后访问和三小时内重复访问的行为。\n","date":"2013-05-14","externalUrl":null,"permalink":"/posts/routeros-redirect/","section":"文章归档","summary":"脚本通过地址列表区分新访问与已访问设备，再把匹配的 TCP 80 请求导向示例 Web 服务器；内网地址需要按实际拓扑替换。","title":"ROS首页强开配置","type":"posts"},{"content":"public static int getRandom(int min, int max) { int r = new Random().nextInt(max - min); return r + min; } 补充阅读 # 说明 Java nextInt 区间随机数示例的上下界、参数约束和适用场景。\n如何理解与使用 # 原代码返回范围是 [min, max)：包含 min，不包含 max。例如 min=3、max=6 时可能得到 3、4、5，得不到 6。\n验证与边界 # 调用前要求 max \u0026gt; min，还要避免 max-min 整数溢出。此写法适合普通模拟或抽样；验证码、密钥等安全用途应单独选择合适的随机源。\n参考：Random（本次补充核对）。\n","date":"2013-05-10","externalUrl":null,"permalink":"/posts/java-random-range/","section":"文章归档","summary":"原代码返回范围是 [min, max)：包含 min，不包含 max。例如 min=3、max=6 时可能得到 3、4、5，得不到 6。","title":"获取min到max的随机数","type":"posts"},{"content":"/** * 四舍五入 * @date 2013-5-10上午11:53:29 * @author Kevin * @param f 参数 * @param rang 保留小数位数 * @return */ private static double round(double f, int rang) { BigDecimal b = new BigDecimal(f); double f1 = b.setScale(rang, BigDecimal.ROUND_HALF_UP).doubleValue(); return f1; } 补充阅读 # 解释 Java 示例怎样用 BigDecimal 保留小数位，并补充浮点输入和舍入方式的注意事项。\n如何理解与使用 # 原方法的 rang 表示小数位数，返回值仍是 double，因此保留两位小数不代表输出时一定显示两个尾随零。展示格式与数值计算需要分开处理。\n验证与边界 # new BigDecimal(double) 会保留二进制浮点近似值；十进制业务输入可优先使用字符串构造或 valueOf。新代码使用 RoundingMode.HALF_UP 表达舍入规则，测试时覆盖负数、边界值与尾随零。\n参考：BigDecimal（本次补充核对）。\n","date":"2013-05-10","externalUrl":null,"permalink":"/posts/java-round/","section":"文章归档","summary":"原方法的 rang 表示小数位数，返回值仍是 double，因此保留两位小数不代表输出时一定显示两个尾随零。展示格式与数值计算需要分开处理。","title":"java四舍五入","type":"posts"},{"content":" 所有的数据都要进队列才能对数据进行控制。如何对数据进行分类，进而进入相应的 队列，从而使HTB对其进行有效的控制，已达到流量控制的作用。稍后，我将首先对分类的方法进行简单的介绍，然后分别通过在RouterOS上设置相应进 入队列的方法对以上的理论加以实践。1、数据分类的方法\n总的来说，队列就是需要将网络上的流量进行分类，从而让设备对相应的队列进行控制。主要有以下几种分类的方法：包长的大小、IP地址、目的端口、此外还有P2P，应用层识别等。\n下面分别对这几种方法做一些说明：\n1）包长的大小：所谓的小包优先\n小包一般是一些控制报文，在上传带宽比较小的时候非常有用，而且包长小的话，同样数目的包比大包要占用的带宽要小很多。一般来说512byte以下的报文为小包，传导的是网络中的控制信息。\n2）IP地址：所谓的VIP优先\n一般来说，一个网络内部可能有几个特殊的IP地址，可能是企业的高管，也可能是小区中缴费多的用户等等，他们理所应当获取较高的优先权。\n3）目的端口：所谓的特殊应用优先\n在 网络环境中，一些通用的服务都有自己固定的端口，比如为大家所熟知HTTP的80端口，pop3的110端口，SMTP的25端口，ftp的21端 口，ssh的22端口，telnet的23端口，dns的53端口，ssl的443端口等等。这就需要看具体的环境中，应用的什么服务比较多了，然后对这 些端口进行配置。\n4）其他：\n都是一些非主流的分类的方法了，因为每个厂商都有自己的识别方法，而且识别率都无法达到100%，因此不对这些方法做何评价。只是对这些技术做一些介绍，典型的有RouterOS的L7识别，Panabit的应用层识别等等。\n2、如何有效的对队列进行管理\n对队列进行管理的时候主要通过两个方面，一种是对队列的带宽进行管理（即流量监管），另一种是对队列的优先级进行管理（即流量整形）。\n对此，我给出以下建议：分类层次应该为包大小——目的端口——IP地址。\n下面说说我给出这种建议的依据：\n1）包长小的包一般在网络中起控制作用，这种包的特点就是实时性要求特别高，占用带宽不高，为了保证上传流量不被过多的占用（有时候FTP上传也是需要占用带宽的），建议其CIR设置在可用上行带宽的一半以下，包长比较大的包可以将其进入一个队列。\n2）下载队列中，可以不用去管大包小包，因为在用户看来，所接受的大包小包的重要程度是同等的。\n3） 前面已经说了，上传和下载是分开的，在1）中也说了上传应该注意的，下面我们来说说下载的。迅雷下载和网页流量，哪个更重要？显然是网页，因此将网页的 80端口优先对于做网络优化的工程师来说是非常必要的。找到更多的对自己有用的端口，并对其进行优化使我们下一步的目标。\n4）几个分类方法之间的配合\n一般来说，小包中有也有各种服务的包，各种服务中，希望哪个IP请求的服务优先被满足？这就需要我们在标记的时候，对这些服务的包进去分类的区分。\n5）PCQ的应用\n如果某种服务下面，所有的IP的优先级都差不多，可以采用PCQ的方式，来让RouterOS根据环境中用户的在线数量去平分带宽。\n需要注意几点：\n1）标记数据包需要通过首先标记连接，再去标记数据包，这样比较准确；\n2）标记的时候应该包含所有的情况，包含时需要根据Passthrough属性的值来确定标记是否终止，标记数据包应该紧接在所标记连接以后；\n3）mangle中，标记的顺序是从上到下的，匹配成功以后还会继续向下匹配，除非Passthrough的值为no；\n4） 将192.168.1.2的包分类标记有两种方法，一种是先标记192.168.1.2所有的数据连接，再标记192.168.1.2中80端口的连接， 再标记其他端口的连接，中间的Passthrough的值全为yes；另一种方法是先标记192.168.1.2中80端口的连接，再去标记其他所有的连 接，中间的Passthrough的值全部为no。显而易见，后者的方法更为科学，更为节省资源；\n5）标记小包的时候，不要尝试着去标记小包的连接，应该是先标记连接以后再根据连接去标记该连接中的大包和小包。\n3、我们来对上面的理论在实际环境中加以实践\n步骤是先标记数据包，然后将这些数据包应用在Queue Tree中。\n/queue type add name=queue_up kind=pcq pcq-classifier=src-address pcq-limit=100 pcq-total-limit=2000 add name=queue_down kind=pcq pcq-classifier=dst-address pcq-limit=100 pcq-total-limit=2000 /ip firewall mangle add chain=prerouting src-address=192.168.1.0/24 protocol=icmp action=mark-connection new-connection-mark=all_icmp_con passthrough=yes add chain=prerouting connection-mark=all_icmp_con action=mark-packet new-packet-mark=all_icmp_pack passthrough=no add chain=prerouting src-address=192.168.1.0/24 protocol=tcp dst-port=80 action=mark-connection new-connection-mark=all_80_con passthrough=yes add chain=prerouting connection-mark=all_80_con action=mark-packet packet-size=0-512 new-packet-mark=all_80_small_pack passthrough=no add chain=prerouting connection-mark=all_80_con action=mark-packet new-packet-mark=all_80_big_pack passthrough=no add chain=prerouting src-address=192.168.1.0/24 action=mark-connection new-connection-mark=all_other_con passthrough=yes add chain=prerouting connection-mark=all_other_con action=mark-packet packet-size=0-512 new-packet-mark=all_other_small_pack passthrough=no add chain=prerouting connection-mark=all_other_con action=mark-packet new-packet-mark=all_other_big_pack passthrough=no /queue tree add name=Down parent=lan add name=icmp_d parent=Down packet-mark=all_icmp_pack priority=1 add name=80_small_d parent=Down packet-mark=all_80_small_pack priority=2 add name=80_big_d parent=Down packet-mark=all_80_big_pack priority=3 add name=other_small_d parent=Down packet-mark=all_other_small_pack priority=4 add name=other_big_d parent=Down packet-mark=all_other_big_pack priority=5 add name=Up parent=wan add name=icmp_u parent=Up packet-mark=all_icmp_pack priority=1 add name=80_small_u parent=Up packet-mark=all_80_small_pack priority=2 add name=80_big_u parent=Up packet-mark=all_80_big_pack priority=3 add name=other_small_u parent=Up packet-mark=all_other_small_pack priority=4 add name=other_big_u parent=Up packet-mark=all_other_big_pack priority=5 补充阅读 # 从流量分类到队列调度，梳理 RouterOS QoS、HTB 和优先级之间的关系。\n如何理解与使用 # 阅读时先区分分类规则与队列策略：前者决定哪些包属于同一组，后者决定这些组怎样分享链路。原文的小包、端口和用户分类是不同维度，可以组合观察。\n验证与边界 # 实际评估应同时看满载时的延迟、丢包和各队列计数；端口命中不等于准确识别应用，原有优先级建议需要结合业务流量验证。\n","date":"2013-01-23","externalUrl":null,"permalink":"/posts/routeros-qos/","section":"文章归档","summary":"阅读时先区分分类规则与队列策略：前者决定哪些包属于同一组，后者决定这些组怎样分享链路。原文的小包、端口和用户分类是不同维度，可以组合观察。","title":"ROS QOS 数据分类/队列（Queue）的理论","type":"posts"}]