proxy.go
package main
import (
"net"
"time"
)
// 初始化代理服务
func initProxy() {
Log.Infof("Proxying %s -> %s\n", Config.Bind, Config.Backend)
server, err := net.Listen("tcp", Config.Bind)
if err != nil {
Log.Fatal(err)
}
// 等待的队列长度
waitQueue := make(chan net.Conn, Config.WaitQueueLen)
// 最大并发连接
connPools := make(chan bool, Config.MaxConn)
for i := 0; i < Config.MaxConn; i++ {
connPools <- true
}
// 等待连接处理
go waitConn(waitQueue, connPools)
// 接收连接并抛给管道处理
for {
conn, err := server.Accept()
if err != nil {
Log.Error(err)
continue
}
Log.Infof("Received connection from %s.\n", conn.RemoteAddr())
waitQueue <- conn
}
}
// 连接数控制
func waitConn(waitQueue chan net.Conn, connPools chan bool) {
for conn := range waitQueue {
// 接收一个链接,连接池释放一个
<-connPools
go func(conn net.Conn) {
handleConn(conn)
// 链接处理完毕,增加
connPools <- true
Log.Infof("Closed connection from %s.\n", conn.RemoteAddr())
}(conn)
}
}
// 处理连接
func handleConn(conn net.Conn) {
defer conn.Close()
// 根据链接哈希选择机器
proxySvr, ok := getBackendSvr(conn)
if !ok {
return
}
// 链接远程代理服务器
remote, err := net.Dial("tcp", proxySvr.identify)
if err != nil {
Log.Error(err)
proxySvr.failTimes++
return
}
// 等待双向连接完成
complete := make(chan bool, 2)
oneSwitch := make(chan bool, 1)
otherSwitch := make(chan bool, 1)
// 将当前客户端链接发送的数据发送给远程被代理的服务器
go transaction(conn, remote, complete, oneSwitch, otherSwitch)
// 将远程服务返回的数据返回给客户端
go transaction(remote, conn, complete, otherSwitch, oneSwitch)
<-complete
<-complete
remote.Close()
}
// 数据交换传输(从from读数据,再写入to)
func transaction(from, to net.Conn, complete, oneSwitch, otherSwitch chan bool) {
var err error
var read int
bytes := make([]byte, 1024)
for {
select {
case <-otherSwitch:
complete <- true
return
default:
timeOutSec := time.Duration(Config.Timeout) * time.Second
// 设置超时时间
from.SetReadDeadline(time.Now().Add(timeOutSec))
read, err = from.Read(bytes)
if err != nil {
complete <- true
oneSwitch <- true
return
}
// 设置超时时间
to.SetWriteDeadline(time.Now().Add(timeOutSec))
_, err = to.Write(bytes[:read])
if err != nil {
complete <- true
oneSwitch <- true
return
}
}
}
}
proxy.go的更多相关文章
- 实现代理设置proxy
用户在哪些情况下是需要设置网络代理呢? 1. 内网上不了外网,需要连接能上外网的内网电脑做代理,就能上外网:多个电脑共享上外网,就要用代理: 2.有些网页被封,通过国外的代理就能看到这被封的网站:3. ...
- Could not create SSL connection through proxy serve-svn
RA layer request failedsvn: Unable to connect to a repository at URL xxxxxx 最后:Could not create SSL ...
- could not initialize proxy - no Session
这是一个精典的问题:因为我们在hibernate里面load一个对象出来时,用到的是代理对象,也就是说当我们在执行load方法时并没有发sql语句,而是返回一个proxy对象.只有当们具体用到哪个ge ...
- ABP源码分析三十七:ABP.Web.Api Script Proxy API
ABP提供Script Proxy WebApi为所有的Dynamic WebApi生成访问这些WebApi的JQuery代理,AngularJs代理以及TypeScriptor代理.这些个代理就是j ...
- Java设计模式之代理模式(Proxy)
前言: 最近在研究Retrofit开源框架的时候,其主要核心代码是通过注解标示参数,动态代理模式实现具体接口,反射机制进行参数解析,最终实现发送请求.其实之前在学习Xutils源码的时候,Xutils ...
- 设计模式(十三)代理模式(Proxy Pattern)
一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访问到这些对象,如果直接访问对象给系统带来不必要的复杂性,这时候可以在客户端和目标对象之间增加一层中间层,让代 ...
- 设计模式-代理模式(Proxy Model)
文 / vincentzh 原文连接:http://www.cnblogs.com/vincentzh/p/5988145.html 目录 1.写在前面 2.概述 3.目的 4.结构组成 5.实现 5 ...
- 神秘代理-Proxy
前言: 代理模式作为常见的设计模式之一,在项目开发中不可或缺.本文就尝试着揭开代理的神秘面纱,也欢迎各路人批评指正! 1.如何实现代理: [假设有个关于汽车移动(move)的计时需求]设计:Movea ...
- 12,13 Proxy和Reflect
Proxy和Reflect Proxy(代理) Proxy用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种"元编程"(meta programming),即对编程 ...
- nova instance出错:"message": "Proxy error: 502 Read from server failed
执行 $ nova resize instance1 时候出错: {, "details": " File \"/opt/stack/nova/nova/com ...
随机推荐
- C#基础随手笔记之基础操作优化
对数据的查询,删除等基本操作是任何编程语言都会涉及到的基础,因此,研究了一下C#中比较常用的数据操作类型,并顺手做个笔记. List查询时,若是处理比较大的数据则使用HashSet<T>类 ...
- XSS攻击过滤处理
关于XSS攻击 XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中. XSS漏洞的危害 网络钓鱼,包括盗取各类用户账号: 窃取用户cooki ...
- 初步认识thymeleaf:简单表达式和标签(一)
初步认识Thymeleaf:简单表达式和标签.(一) 本文只适用于不会Java对HTML语言有基础的程序员们,是浏览了各大博客后收集整理,重新编辑的一篇文章,希望能对大家有所帮助.最后本文如果有哪 ...
- Construct Binary Tree from Inorder and Postorder Traversal(根据中序遍历和后序遍历构建二叉树)
根据中序和后续遍历构建二叉树. /** * Definition for a binary tree node. * public class TreeNode { * int val; * Tree ...
- /usr/lib/uwsgi/plugins/python_plugin.so: cannot open shared object file: No such file or directory
Django uwsgi部署方式下产生这个Bug,后来发现把uwsgi配置ini文件里面的 #plugins = python 把上面这句配置语句注释掉,uwsgi就可以运行了,当然,是正常可用运行状 ...
- 学习JavaScript最佳实践方法
首先要说明的是,咱现在不是高手,最多还是一个半桶水,算是入了JS的门. 谈不上经验,都是一些教训. 这个时候有人要说,“靠,你丫半桶水,凭啥教我们”.您先别急着骂,先听我说. 你叫一个大学生去教小学数 ...
- 深入理解css3中的线性渐变
css3中的线性渐变 线性渐变公式: background-image: linear-gradient( [ <angle> | <side-or-corner> ]?, & ...
- C程序员眼里的Python
注释 Phython的注释和C语言非常不同,第一种 #开头的注释,类似于C的//开头,而"""对 包围注释,类似于C的/* */,以及xml类的<!-- -- ...
- Android 开发知识体系
知识体系 1.Unix/Linux平台技术:基本命令,Linux下的开发环境 2.企业级数据库技术:SQL语言.SQL语句调优.Oracle数据库技术 3.Java 语言核心技术:Java语言基础.J ...
- Oracle数据库逻辑迁移之数据泵的注意事项
环境:数据迁移,版本 11.2.0.4 -> 12.2.0.1 思考: 对于DBA而言,常用物理方式的迁移,物理迁移的优势不必多说,使用这种方式不必担心对象前后不一致的情况,而这往往也解决了不懂 ...