文章851
标签121
分类10

PHP ERROR Maximum function nesting level..

 Uncaught Error: Maximum function nesting level of '256' reached, aborting!

未出错:“256”的最大函数嵌套级别已达到,中止!

今天改写redis 重连 出现的问题
因为在程序中写了个调用自身重连方法。redis-server 断开一段时间后,测试程序出现抛错。

记录一下这个报错 百度搜索了解到最深调用层级默认应该是256 了解下

Windows 7 无法远程登录 Windows 服务器:缺失加密 Oracle 修正

在使用 Windows 7 远程登录 Windows Server 时,可能会遇到连接失败的情况,尤其是在服务器启用了更严格的安全策略时。本文将介绍导致这一问题的原因以及如何通过缺失加密 Oracle 修正来解决。

问题背景

Windows 7 默认使用较旧的加密协议(如 RC4),而许多最新的 Windows Server 版本(如 Windows Server 2016 和 2019)可能已经禁用这些不安全的加密算法。这就导致 Windows 7 客户端与这些服务器之间的远程桌面连接失败,并出现类似“无法连接到远程计算机”的错误信息。

解决方案概述

要解决此问题,可以通过以下步骤进行修复:

  1. 安装更新:确保 Windows 7 安装了最新的安全更新。
  2. 修改注册表:添加或修改注册表项,以允许使用更安全的加密协议。
  3. 启用加密 Oracle 修正:通过组策略或注册表启用加密 Oracle 修正,允许旧版客户端与新服务器建立连接。

步骤详细说明

步骤 1:安装更新

确保 Windows 7 系统已安装最新的服务包和安全更新。你可以通过以下步骤进行检查和安装:

  1. 打开 控制面板
  2. 点击 Windows Update
  3. 检查更新并安装所有可用的更新。

步骤 2:修改注册表

接下来,需要修改注册表以允许使用更安全的加密协议。请按照以下步骤操作:

  1. Win + R 键,输入 regedit,并按 Enter 以打开注册表编辑器。
  2. 导航到以下路径:

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp
  3. 找到 MinEncryptionLevel 键,双击并将其值设置为 1(表示 Low,允许使用 RC4 加密)。如果该键不存在,可以右键点击右侧窗格,选择 新建 > DWORD (32 位),命名为 MinEncryptionLevel,并设置值。

步骤 3:启用加密 Oracle 修正

这一步是解决问题的关键。需启用加密 Oracle 修正,以允许 Windows 7 客户端与 Windows Server 建立连接。

  1. 在注册表编辑器中,导航到以下路径:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
  2. 右键点击右侧窗格,选择 新建 > DWORD (32 位),命名为 EnableOracleRemediation,并将其值设置为 1
  3. 如果 System 下没有 Policies 文件夹,请先创建它。

步骤 4:重启计算机

完成上述修改后,重启 Windows 7 计算机以使更改生效。

其他注意事项

  • 安全性:启用较低的加密标准可能会降低系统安全性,因此在生产环境中应谨慎使用。建议尽快升级到较新的操作系统版本,如 Windows 10 或 Windows 11,以获得更好的安全性和支持。
  • 组策略:如果你的计算机加入了域,可能需要通过组策略进行相应的设置。

总结

通过上述步骤,可以解决 Windows 7 客户端无法远程登录 Windows Server 的问题,特别是在启用了更严格的安全策略的情况下。确保系统及时更新并考虑安全性,以提升整体使用体验。

参考资料

Nginx 中 `$request_uri` 参数与哈希负载均衡

在 Nginx 的负载均衡配置中,使用请求相关变量可以实现更灵活的流量管理。其中,$request_uri 是一个非常重要的变量,可以用于哈希负载均衡。本文将深入探讨 $request_uri 的用法及其在负载均衡中的应用。

什么是 $request_uri

$request_uri 是 Nginx 提供的一个内置变量,它包含了客户端请求的完整 URI,包括查询参数。这使得该变量在负载均衡时非常有用,因为它可以帮助我们基于请求的路径和参数将流量分配到不同的后端服务器。

$request_uri 的结构

  • 示例请求: GET /path/to/resource?param=value HTTP/1.1
  • 对应的 $request_uri: /path/to/resource?param=value

哈希负载均衡

哈希负载均衡根据请求的某一部分(如 URI、IP 地址等)计算出一个哈希值,从而确定请求应该被转发到哪个后端服务器。这种方式可以确保同一请求总是被转发到同一台服务器,从而保持会话的一致性。

使用 $request_uri 的哈希负载均衡配置示例

以下是一个使用 $request_uri 进行哈希负载均衡的 Nginx 配置示例:

http {
    upstream backend {
        # 根据请求 URI 进行哈希负载均衡
        hash $request_uri consistent;
        
        server backend1.example.com;
        server backend2.example.com;
        server backend3.example.com;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://backend;
        }
    }
}

解析配置

  • upstream backend: 定义一个后端服务器组 backend
  • hash $request_uri consistent;: 使用 $request_uri 进行哈希负载均衡,并使用一致性哈希算法。这确保了相同的请求总是被转发到同一台服务器。
  • server backend1.example.com;: 定义后端服务器。

为什么使用哈希负载均衡?

  1. 会话保持: 对于需要会话保持的应用(如购物车、用户登录状态等),哈希负载均衡能够确保同一用户的请求被转发到同一台服务器。
  2. 负载均衡: 根据请求 URI 分配流量,可以有效地避免某些特定请求对单台服务器造成过大负载。
  3. 灵活性: 可以根据实际需求选择哈希的对象(如 IP、URI 等),提供更多灵活性。

注意事项

  • 单点故障: 如果某台服务器宕机,所有哈希到该服务器的请求都会失败。可以考虑使用健康检查机制来监控服务器状态。
  • 均匀性: 哈希算法可能导致请求分配不均,尤其是当请求 URI 具有高度相似性时。定期监控负载情况,并根据需要调整策略。
  • 性能影响: 哈希计算会增加一定的 CPU 开销,尤其是在高并发场景下。需要根据实际情况进行性能测试和调整。

总结

通过使用 Nginx 的 $request_uri 变量进行哈希负载均衡,可以有效管理流量,提高系统的可用性和性能。了解其工作原理和配置方法,将帮助你在实际应用中更好地实现高可用性架构。

参考资料

Nginx 简单双机热备:`backup` 参数的使用

在现代 Web 应用架构中,高可用性是一个重要的目标。通过使用 Nginx 的双机热备功能,可以确保在主服务器出现故障时,流量能够自动切换到备份服务器。本文将介绍 Nginx 中 backup 参数的使用方法,帮助你实现简单的双机热备。

什么是 backup 参数?

在 Nginx 的负载均衡配置中,backup 参数用于标记一个服务器为备份服务器。备份服务器在主服务器不可用时,才会接收请求。通过这种方式,可以有效提高应用的可用性和容错能力。

基本配置

以下是一个简单的 Nginx 配置示例,展示了如何使用 backup 参数进行双机热备:

http {
    upstream backend {
        server primary.example.com;  # 主服务器
        server backup.example.com backup;  # 备份服务器
    }

    server {
        listen 80;

        location / {
            proxy_pass http://backend;  # 将请求转发到 upstream
        }
    }
}

解析配置

  • upstream backend: 定义一个名为 backend 的上游服务器组。
  • server primary.example.com: 定义主服务器 primary.example.com
  • server backup.example.com backup: 定义备份服务器 backup.example.com,并使用 backup 参数标记为备份。

在这个配置中,只有当 primary.example.com 不可用时,请求才会被转发到 backup.example.com

运行原理

当 Nginx 启动时,它会尝试与定义的所有服务器建立连接。如果主服务器可用,所有请求将被发送到主服务器。只有当主服务器不可用或发生故障时,请求才会被发送到备份服务器。这种机制保证了系统的高可用性。

实际使用场景

1. 应用升级

在进行应用升级时,可以将流量暂时切换到备份服务器,完成升级后再切换回主服务器。

2. 故障恢复

一旦主服务器出现故障,Nginx 会自动将流量切换到备份服务器,确保用户体验不受影响。

3. 负载均衡

在某些情况下,可以将备份服务器用作负载均衡的一部分,虽然在正常情况下不会处理请求,但可以在主服务器负载过高时接手部分流量。

监控和管理

在实际生产环境中,建议使用监控工具(如 Zabbix、Prometheus)监测主服务器的健康状态,以便及时发现并处理故障。此外,可以使用 Nginx 的 http://nginx_status 模块实时监控服务器的状态。

总结

通过 Nginx 的 backup 参数,可以轻松实现双机热备,确保高可用性和业务连续性。配置简单、运行高效,使其成为许多企业 Web 应用架构中的首选方案。

参考资料

PHP 雪花算法收藏

需要注意的 $twepoch 变量一定要在项目初始化时重置为当前最新时间
该方法 存在一定问题使用3年左右 会存在 - 符号

### 雪花算法
class SnowFlake
{
    private static $lastTimestamp = 0;
    private static $lastSequence  = 0;
    private static $sequenceMask  = 4095;

    // 项目初始化时间毫秒戳 
    private static $twepoch       = 1715236393000;

    static function randStr($length)
    {
        return substr(str_shuffle("abcdefghijkmnpqrstuvwxyzABCDEFGHIJKMNPQRSTUVWXYZ23456789"), 0, $length);
    }

    static function randNumStr($length)
    {
        $chars = array(
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        );
        $password = '';
        while (strlen($password) < $length) {
            $password .= $chars[rand(0, 9)];
        }
        return $password;
    }


    /**
     * 生成基于雪花算法的随机编号
     * @return int 分布式ID
     */
    static function snowFlake()
    {
        $timestamp = self::timeGen();

        if (self::$lastTimestamp == $timestamp) {
            self::$lastSequence = (self::$lastSequence + 1) & self::$sequenceMask;
            if (self::$lastSequence == 0) $timestamp = self::tilNextMillis(self::$lastTimestamp);
        } else {
            self::$lastSequence = 0;
        }
        self::$lastTimestamp = $timestamp;

        $snowFlakeId = (($timestamp - self::$twepoch) << 27) | (getmypid() << 12) | self::$lastSequence;

        return (string)$snowFlakeId;
    }

    /**
     * 反向解析雪花算法生成的编号
     * @param int|float $snowFlakeId
     * @return array
     */
    static function unSnowFlake($snowFlakeId)
    {
        $Binary = str_pad(decbin($snowFlakeId), 64, '0', STR_PAD_LEFT);
        return [
            'timestamp'    => bindec(substr($Binary, 0, 41)) + self::$twepoch,
            'dataCenterID' => bindec(substr($Binary, 42, 5)),
            'workerID'     => bindec(substr($Binary, 47, 5)),
            'sequence'     => bindec(substr($Binary, -12)),
        ];
    }

    /**
     * 等待下一毫秒的时间戳
     * @param $lastTimestamp
     * @return float
     */
    private static function tilNextMillis($lastTimestamp)
    {
        $timestamp = self::timeGen();
        while ($timestamp <= $lastTimestamp) {
            $timestamp = self::timeGen();
        }
        return $timestamp;
    }

    /**
     * 获取毫秒级时间戳
     * @return float
     */
    private static function timeGen()
    {
        return (float)sprintf('%.0f', microtime(true) * 1000);
    }
}
">