正反向代理 集群搭建

代理

正向代理

通过正向代理服务地址 由正向代理服务器访问外部网络 由内部到外部访问

反向代理

将外部网络请求通过反向代理 中转给局域网的服务器 由外部到内部中转


upstream

  • server ip:端口或者unix套接字 修饰符
    修饰符
    weight 权重 默认为1 权重就越大 负载的概率越大
    backup 备份 非备份机down或者忙的时候 请求备份机
    down 停止使用
    max_fails 最大失败次数 默认为1 超过最大次数时 返回proxy_next_upstream定义的错误
    fail_timeout 最大失败次数后 暂停的时间

  • ip_hash 按照ip一致性hash分配

  • keepalive 设置每个worker进程与后端服务器(upstream中的server)保持连接的最大数量
    一个连接池缓存的最大数目
    这些保持的连接会被放入缓存 淘汰算法lru 淘汰最老的

upstream backend{
     ip_hash;
     ##连接池缓存连接最大数目 
     keepalive=2000;
    server 127.0.0.1:81 down; 
    server 127.0.0.1:82 weight=2; 
    server 127.0.0.1:83 max_fails=0  fail_timeout=1s; 
    server 127.0.0.1:84 backup; 
}

proxy

  • proxy_connect_timeout
    默认时间为60s 与upstream的server连接超时时间

  • proxy_buffers
    proxy_buffers 4 64k;
    缓冲区数目和每个缓冲区的大小

  • proxy_set_header X-Real-IP $remote_addr;
    设置响应的头部
    在php里$_SERVER[‘HTTP_X_REAL_IP’]

  • proxy_next_upstream
    什么时候 被转接到下一个upstream的server
    proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header non_idempotent;

  • proxy_pass 连接方式 ip:端口 域名 或者套接字都可以的

###结尾有/ 表示绝对路径 没有相对路径
location /baidu {
		proxy_pass http://www.baidu.com/   #有斜杠
	 }
###访问http://www.baidu.com
location /baidu{
		proxy_pass http://www.baidu.com
	 }
###访问http://www.baidu.com/baidu

proxy_pass 192.168.1.78:80
#unix套接字连接方式
proxy_pass unix:/dev/shm/php-cgi.sock;
#连接upstream方式
proxy_pass http://backend;

location  /{
	proxy_connect_timeout 75s;
	proxy_buffers   4 64k;
	proxy_next_upstream  error timeout invalid_header non_idempotent;
	proxy_set_header X-Real-IP $remote_addr; 
    proxy_pass http://myproject;  
 }	

分配策略

  • 一致性hash
    上面的ip_hash 就是按照ip进行一致性hash分配
    做过优化 解决 hash虚拟节点分布不均的问题
    平均散列到1到2147483647之间
namespace helper\assign;
defined('IN')||exit;

class hashAssign
{
    //节点(包含虚拟节点)
    protected $_positionToTarget = array();
    //主机节点
    protected $_targetToPositions = array();
    //排序
    protected $_positionToTargetSorted = false;
	protected $targetNum=1;
	protected $replicas=1;	
	protected $HashList=array();
    public  function init($init=array())
    {
		$this->targetNum = isset($init[0])?$init[0]:10;
        $this->replicas = isset($init[1])?$init[1]:100;
		if(($this->replicas%$this->targetNum)!=0){
			throw new \Exception('虚拟节点数必须是物理节点数的整数倍');
		}
		$chu=intval($this->replicas/$this->targetNum);
		$this->HashList=$this->getHashList($this->replicas);
		for ($i = 0; $i < $this->replicas; $i ++) {
			$target=intval($i/$chu);
            $position = $this->HashList[$i];
            $this->_positionToTarget[$position] = $target;
			$this->_targetToPositions[$target][$i] = $position;
        }
		$this->_positionToTargetSorted = false;
    }
	
	public function move($atarget=0,$starget=1,$replicasStart=10,$replicasEnd=100)
    {
		if (!isset($this->_targetToPositions[$starget])) {
            throw new \Exception('物理节点 '.$starget.' 不存在.');
        }
        if (isset($this->_targetToPositions[$atarget])) {
            throw new \Exception('物理节点 '.$atarget.' 已经存在.');
        }
        $this->_targetToPositions[$atarget] = array();
		for($i = $replicasStart; $i <= $replicasEnd; $i++) {
			$position = $this->HashList[$i];
			if(!isset($this->_targetToPositions[$starget][$i])){
				 throw new \Exception('虚拟节点 '.$starget.'-'.$i.' 不存在.');
			}
			unset($this->_targetToPositions[$starget][$i]);
			$this->_positionToTarget[$position] = $atarget;
            $this->_targetToPositions[$atarget][$i] = $position;
        }
		
        $this->_positionToTargetSorted = false;
    }
	
    private function hash($hash)
    {
        return abs(crc32($hash));
    }
	
	private function getHashList($replicas=10)
    {
	$HashList=array();
	$max=2147483647;
	$num=intval($max/$replicas)+1;
	for($i=0;$i<$replicas-1;$i++){
		$HashList[$i]=$num*($i+1);
	}
	$HashList[]=2147483647;
	return $HashList;
    }

    public function lookup($resource)
    {
        $targets = $this->lookupList($resource, 1);

        if (empty($targets)){
			throw new \Exception('No targets exist');
		}
            
        return $targets[0];
    }

    public function lookupList($resource,$requestedCount=1)
    {
        if(empty($this->_positionToTarget)){return array();}   
        $resourcePosition = $this->hash($resource);
        $this->_sortPositionTargets();
        return $this->find($this->_positionToTarget, $resourcePosition, $requestedCount);
    }

    protected function _sortPositionTargets()
    {
        if (!$this->_positionToTargetSorted) {
            ksort($this->_positionToTarget, SORT_REGULAR);
            $this->_positionToTargetSorted = true;
        }
    }
	
	private function find($node,$resourcePosition,$requestedCount)
    {
        $results = array();
        $collect = false;
        foreach ($node as $key => $value) {
            if (! $collect && $key > $resourcePosition) {
                $collect = true;
            }
            if ($collect && ! in_array($value, $results)) {
                $results[] = $value;
            }
            if (count($results) == $requestedCount) {
                return $results;
            }
        }
        foreach ($node as $key => $value) {
            if (! in_array($value, $results)) {
                $results[] = $value;
            }
            if (count($results) == $requestedCount) {
                return $results;
            }
        }
        return $results;
    }
	
}
  • 加权轮询策略
namespace helper\assign;
defined('IN')||exit;
class weightAssign
{
	public $default_sign='default';
    public function setHost($hosts)
    {
       return $this->host=$hosts;
    }
	
	public function getHostIndex($sign='')
    {
        $weight_sum = 0;
        foreach ($this->host as $v) {
            if (! isset($v['sign'])) {
                $v['sign'] = $this->default_sign;
            }
            if ($v['sign'] != $sign) {
                continue;
            }
            if (! isset($v['weight'])) {
                $v['weight'] = 1;
            }
            $weight_sum += $v['weight'];
        }
        $roll = mt_rand(1, $weight_sum);
        $tmp = 0;
        foreach ($this->host as $k => $v) {
            if (! isset($v['sign'])) {
                $v['sign'] = $this->default_sign;
            }
            if ($v['sign'] != $sign) {
                continue;
            }
            if (! isset($v['weight'])) {
                $v['weight'] = 1;
            }
            $tmp += $v['weight'];
            if ($tmp >= $roll) {
                return $k;
            }
        }
    }
	
}

猜你喜欢

转载自blog.csdn.net/qq_38984126/article/details/83272794
今日推荐