proxy.go 源码阅读
package main
import (
"net"
"time"
)
func initProxy() {
pLog.Infof("Proxying %s -> %s\n", pConfig.Bind, pConfig.Backend) //输出服务地址 后端服务地址列表
server, err := net.Listen("tcp", pConfig.Bind) //建立tcp连接
if err != nil {
pLog.Fatal(err)
}
waitQueue := make(chan net.Conn, pConfig.WaitQueueLen) //建立连接队列 队列默认等待队列长度---channel net.Conn ==控制最大排队队列
availPools := make(chan bool, pConfig.MaxConn) //建立最大连接数--channel bool=== 控制最大连接数
for i := 0; i < pConfig.MaxConn; i++ { //
availPools <- true
}
go loop(waitQueue, availPools)
for {
connection, err := server.Accept() //等待获取下一次连接
if err != nil {
pLog.Error(err)
} else {
pLog.Infof("Received connection from %s.\n", connection.RemoteAddr())
waitQueue <- connection
}
}
}
func loop(waitQueue chan net.Conn, availPools chan bool) {
for connection := range waitQueue { //循环等待队列中 排队等待需要处理的数据--连接
<-availPools //从通道中 连接池中取出一个
go func(connection net.Conn) {
handleConnection(connection)
availPools <- true //使用结束放回连接池中 目的控制连接数量 通道阻塞特性
pLog.Infof("Closed connection from %s.\n", connection.RemoteAddr())
}(connection)
}
}
func handleConnection(connection net.Conn) {
defer connection.Close()
bksvr, ok := getBackendSvr(connection)
if !ok {
return
}
remote, err := net.Dial("tcp", bksvr.svrStr)
if err != nil {
pLog.Error(err)
bksvr.failTimes++
return
}
//等待双向连接完成
complete := make(chan bool, 2)
oneSide := make(chan bool, 1)
otherSide := make(chan bool, 1)
go pass(connection, remote, complete, oneSide, otherSide)
go pass(remote, connection, complete, otherSide, oneSide)
<-complete
<-complete
remote.Close()
}
// copy Content two-way
func pass(from net.Conn, to net.Conn, complete chan bool, oneSide chan bool, otherSide chan bool) {
var err error
var read int
bytes := make([]byte, 256)
for {
select {
case <-otherSide:
complete <- true
return
default:
from.SetReadDeadline(time.Now().Add(time.Duration(pConfig.Timeout) * time.Second))
read, err = from.Read(bytes)
if err != nil {
complete <- true
oneSide <- true
return
}
to.SetWriteDeadline(time.Now().Add(time.Duration(pConfig.Timeout) * time.Second))
_, err = to.Write(bytes[:read])
if err != nil {
complete <- true
oneSide <- true
return
}
}
}
}
proxy.go 源码阅读的更多相关文章
- CI框架源码阅读笔记3 全局函数Common.php
从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...
- Bean实例化(Spring源码阅读)-我们到底能走多远系列(33)
我们到底能走多远系列(33) 扯淡: 各位: 命运就算颠沛流离 命运就算曲折离奇 命运就算恐吓着你做人没趣味 别流泪 心酸 更不应舍弃 ... 主题: Spring源码阅读还在继 ...
- 【 js 基础 】【 源码学习 】backbone 源码阅读(一)
最近看完了 backbone.js 的源码,这里对于源码的细节就不再赘述了,大家可以 star 我的源码阅读项目(https://github.com/JiayiLi/source-code-stud ...
- 【JDK1.8】JDK1.8集合源码阅读——IdentityHashMap
一.前言 今天我们来看一下本次集合源码阅读里的最后一个Map--IdentityHashMap.这个Map之所以放在最后是因为它用到的情况最少,也相较于其他的map来说比较特殊.就笔者来说,到目前为止 ...
- Spring源码阅读笔记
前言 作为一个Java开发者,工作了几年后,越发觉力有点不从心了,技术的世界实在是太过于辽阔了,接触的东西越多,越感到前所未有的恐慌. 每天捣鼓这个捣鼓那个,结果回过头来,才发现这个也不通,那个也不精 ...
- Rpc框架dubbo-client(v2.6.3) 源码阅读(二)
接上一篇 dubbo-server 之后,再来看一下 dubbo-client 是如何工作的. dubbo提供者服务示例, 其结构是这样的!dubbo://192.168.11.6:20880/com ...
- 【Dubbo源码阅读系列】之远程服务调用(上)
今天打算来讲一讲 Dubbo 服务远程调用.笔者在开始看 Dubbo 远程服务相关源码的时候,看的有点迷糊.后来慢慢明白 Dubbo 远程服务的调用的本质就是动态代理模式的一种实现.本地消费者无须知道 ...
- 【Dubbo源码阅读系列】服务暴露之远程暴露
引言 什么叫 远程暴露 ?试着想象着这么一种场景:假设我们新增了一台服务器 A,专门用于发送短信提示给指定用户.那么问题来了,我们的 Message 服务上线之后,应该如何告知调用方服务器,服务器 A ...
- 【Dubbo源码阅读系列】服务暴露之本地暴露
在上一篇文章中我们介绍 Dubbo 自定义标签解析相关内容,其中我们自定义的 XML 标签 <dubbo:service /> 会被解析为 ServiceBean 对象(传送门:Dubbo ...
随机推荐
- 抛开rails使用ActiveRecord连接数据库
今天是大年三十,明天就正式进入羊年鸟,给所有程序猿(媛)同人拜个年吧!祝大家身体健康,事业有成,财源广进哦! 话归正题,以前都是在rails中使用数据库,或者在rails的console中使用:我们如 ...
- Xshell 链接 Could not connect to '192.168.80.129' (port 22): Connection failed
在使用Xshell链接虚拟机VM里面的Linux的时候.链接失败,报 Could not connect to ): Connection failed 解决步骤: 1.重启VM.Linux.Xshe ...
- db2 查新索引 主键 sql
1.查询主键 select * from sysibm.syskeycoluse where tbname='...' 2.查询索引 select * from sysibm.indexs where ...
- Kali Linux 工具使用中文说明书
From: https://www.hackfun.org/kali-tools/kali-tools-zh.html 英文版地址:http://tools.kali.org/ 信息收集 accche ...
- android开发过程中遇到的坑
在android的学习过程中,会有很多坑,我会把我遇到的,一一列下来,方便后来者查阅! 1:android-support-v4.jar and android-support-v7-appcompa ...
- Scala编程入门---数组操作之Array.ArrayBuffer以及遍历数组
在Scala中,Array代表的含义与Java类似,也是长度不可改变的数组.此外,由于Scala与java都是运行在JVM中,双方可以互相调用,因此Scala数组底层实际上是java数组.列如字符串数 ...
- 架构之Nginx(负载均衡/反向代理)
Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器 ,也是一个 IMAP/POP3/SMTP 代理 服务器 . Nginx 是由 Igor Sys ...
- dubbo+zookeeper+springboot构建服务
本次和大家分享的是dubbo框架应用的初略配置和zookeeper注册中心的使用:说到注册中心现在我使用过的只有两种:zookeeper和Eureka,zk我结合dubbo来使用,而Eureka结合s ...
- 洛谷 P1691 解题报告
P1691 有重复元素的排列问题 题目描述 设\(R={r_1,r_2,--,r_n}\)是要进行排列的\(n\)个元素.其中元素\(r_1,r_2,--,r_n\)可能相同.使设计一个算法,列出\( ...
- Java动态代理(一)
好久没有动笔了,最近想巩固一下自己的基础知识,最近听到一同事问为什么JDK动态代理不能代理类,一听感觉懵逼呀!自己好像也不能很好的描述出来,所以想用2篇文章来复习一下动态代理知识: 一.什么是静态代理 ...