??xml version="1.0" encoding="utf-8" standalone="yes"?>BlogJava-年阿宾http://www.qpkxbc.shop/stevenjohn/那些青春的岁?/description>zh-cnSat, 24 Aug 2019 08:45:17 GMTSat, 24 Aug 2019 08:45:17 GMT60如何用消息系l避免分布式事务Q?/title><link>http://www.qpkxbc.shop/stevenjohn/archive/2018/01/04/433004.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Wed, 03 Jan 2018 16:01:00 GMT</pubDate><guid>http://www.qpkxbc.shop/stevenjohn/archive/2018/01/04/433004.html</guid><wfw:comment>http://www.qpkxbc.shop/stevenjohn/comments/433004.html</wfw:comment><comments>http://www.qpkxbc.shop/stevenjohn/archive/2018/01/04/433004.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.qpkxbc.shop/stevenjohn/comments/commentRss/433004.html</wfw:commentRss><trackback:ping>http://www.qpkxbc.shop/stevenjohn/services/trackbacks/433004.html</trackback:ping><description><![CDATA[     摘要: 前阵子从支付宝{?万块钱到余额宝,q是日常生活的一件普通小事,但作Z联网研发人员的职业病Q我思考支付宝扣除1万之后,如果pȝ挂掉怎么办,q时余额宝̎户ƈ没有增加1万,数据׃出现不一致状况了。上q场景在各个cd的系l中都能扑ֈ怼影子Q比如在电商pȝ中,当有用户下单后,除了在订单表插入一条记录外Q对应商品表的这个商品数量必d1吧,怎么保证Q!在搜索广告系l中Q当用户点击某广告后Q除了在点击...  <a href='http://www.qpkxbc.shop/stevenjohn/archive/2018/01/04/433004.html'>阅读全文</a><img src ="http://www.qpkxbc.shop/stevenjohn/aggbug/433004.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.qpkxbc.shop/stevenjohn/" target="_blank">abin</a> 2018-01-04 00:01 <a href="http://www.qpkxbc.shop/stevenjohn/archive/2018/01/04/433004.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>微服务优点缺?/title><link>http://www.qpkxbc.shop/stevenjohn/archive/2017/12/31/432996.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sun, 31 Dec 2017 08:41:00 GMT</pubDate><guid>http://www.qpkxbc.shop/stevenjohn/archive/2017/12/31/432996.html</guid><wfw:comment>http://www.qpkxbc.shop/stevenjohn/comments/432996.html</wfw:comment><comments>http://www.qpkxbc.shop/stevenjohn/archive/2017/12/31/432996.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.qpkxbc.shop/stevenjohn/comments/commentRss/432996.html</wfw:commentRss><trackback:ping>http://www.qpkxbc.shop/stevenjohn/services/trackbacks/432996.html</trackback:ping><description><![CDATA[<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"><span style="font-size: 16px; color: #454545; background-color: #ffffff;">微服务架构采用Scale CubeҎ设计应用架构Q将应用服务按功能拆分成一l相互协作的服务。每个服务负责一l特定、相关的功能。每个服务可以有自己独立的数据库Q从而保证与其他服务解耦?/span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"><span style="font-weight: bold;">微服务优?/span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;">1?span style="font-family: SimHei, STHeiti; color: #666666; background-color: #ffffff;">通过分解巨大单体式应用ؓ多个服务Ҏ解决了复杂性问题,</span><span style="font-size: 16px; color: #454545; background-color: #ffffff;">每个微服务相对较?/span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;">2、每个单体应用不局限于固定的技术栈Q?span style="font-family: SimHei, STHeiti; color: #666666; background-color: #ffffff;">开发者可以自由选择开发技术,提供API服务?/span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;">3?span style="font-family: SimHei, STHeiti; color: #666666; background-color: #ffffff;">每个微服务独立的开发,部v</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;">4、单一职责功能Q?span style="font-family: Arial; background-color: #ffffff;">每个服务都很单,只关注于一个业务功?/span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;">5?span style="font-size: 16px; color: #454545; background-color: #ffffff;">易于规模化开发,多个开发团队可以ƈ行开发,每个团队负责一Ҏ?/span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"><span style="font-size: 16px; color: #454545; background-color: #ffffff;">6、改善故障隔R一个服务宕Z会媄响其他的服务</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"><span style="font-weight: bold;">微服务缺点:</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"><span style="font-size: 16px; color: #454545; background-color: #ffffff;">1.开发者需要应对创建分布式pȝ所产生的额外的复杂因素</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"><span style="font-size: 16px; color: #454545; background-color: #ffffff;">l  目前的IDE主要面对的是单体工程E序Q无法显C支持分布式应用的开?/span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"><span style="font-size: 16px; color: #454545; background-color: #ffffff;">l  试工作更加困难</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"><span style="font-size: 16px; color: #454545; background-color: #ffffff;">l  需要采用服务间的通讯机制</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"><span style="font-size: 16px; color: #454545; background-color: #ffffff;">l  很难在不采用分布式事务的情况下跨服务实现功能</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"><span style="font-size: 16px; color: #454545; background-color: #ffffff;">l  跨服务实现要求功能要求团队之间的紧密协作</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"><span style="font-size: 16px; color: #454545; background-color: #ffffff;">2.部v复杂</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"><span style="font-size: 16px; color: #454545; background-color: #ffffff;">3.内存占用量更?/span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75;"></div><img src ="http://www.qpkxbc.shop/stevenjohn/aggbug/432996.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.qpkxbc.shop/stevenjohn/" target="_blank">abin</a> 2017-12-31 16:41 <a href="http://www.qpkxbc.shop/stevenjohn/archive/2017/12/31/432996.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDK 源码?HashMap ?hash Ҏ原理是什么?http://www.qpkxbc.shop/stevenjohn/archive/2017/12/24/432975.htmlabinabinSun, 24 Dec 2017 14:38:00 GMThttp://www.qpkxbc.shop/stevenjohn/archive/2017/12/24/432975.htmlhttp://www.qpkxbc.shop/stevenjohn/comments/432975.htmlhttp://www.qpkxbc.shop/stevenjohn/archive/2017/12/24/432975.html#Feedback0http://www.qpkxbc.shop/stevenjohn/comments/commentRss/432975.htmlhttp://www.qpkxbc.shop/stevenjohn/services/trackbacks/432975.htmlJDK ?HashMap 中用了一?hash Ҏ来做 bit shiftingQ在注释中说明是Z防止一些实现比较差的hashCode() ҎQ请问原理是什么?JDK 的源码参见:GrepCode: java.util.HashMap (.java)
/**
 * Applies a supplemental hash function to a given hashCode, which
 * defends against poor quality hash functions.  This is critical
 * because HashMap uses power-of-two length hash tables, that
 * otherwise encounter collisions for hashCodes that do not differ
 * in lower bits. Note: Null keys always map to hash 0, thus index 0.
 */
static int hash(int h) {
    // This function ensures that hashCodes that differ only by
    // constant multiples at each bit position have a bounded
    // number of collisions (approximately 8 at default load factor).
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}
PSQ网上看见有作者本原理需要参见圣l《计机E序设计艺术》的 Vol.3 里头的介l,不过木有看过书Q求达h介绍





q段代码?#8220;扰动函数”?br />题主贴的是Java 7的HashMap的源码,Java 8中这步已l简化了Q只做一?6位右位移异或混合Q而不是四ơ,但原理是不变的。下面以Java 8的源码ؓ例解释,

//Java 8中的散列g化函数staticfinalinthash(Objectkey){inth;return(key==null)?0:(h=key.hashCode())^(h>>>16);//key.hashCode()为哈希算法,q回初始哈希值}
大家都知道上面代码里的key.hashCode()函数调用的是key键值类型自带的哈希函数Q返回int型散列倹{理Z散列值是一个int型,如果直接拿散列gZ标访问HashMapLl的话,考虑?q制32位带W号的int表D围从-2147483648?147483648。前后加h大概40亿的映射I间。只要哈希函数映得比较均匀松散Q一般应用是很难出现撞的。但问题是一?0争K度的数组Q内存是放不下的。你惻IHashMap扩容之前的数l初始大才16。所以这个散列值是不能直接拿来用的。用之前q要先做Ҏl的长度取模q算Q得到的余数才能用来讉K数组下标。源码中模运是在这个indexFor( )函数里完成的?br />
bucketIndex = indexFor(hash, table.length);indexFor的代码也很简单,是把散列值和数组长度做一??操作Q?br />
static int indexFor(int h, int length) {        return h & (length-1);}Z说一下,q也正好解释了ؓ什么HashMap的数l长度要?的整ơ幂。因P数组长度-1Q正好相当于一?#8220;低位掩码”?#8220;?#8221;操作的结果就是散列值的高位全部归零Q只保留低位|用来做数l下标访问。以初始长度16ZQ?6-1=15?q制表示?0000000 00000000 00001111。和某散列值做“?#8221;操作如下Q结果就是截取了最低的四位倹{?br />10100101 11000100 00100101& 00000000 00000000 00001111---------------------------------- 00000000 00000000 00000101    //高位全部归零Q只保留末四?br />但这时候问题就来了Q这样就我的散列值分布再松散Q要是只取最后几位的话,撞也会很严重。更要命的是如果散列本n做得不好Q分布上成等差数列的漏洞Q恰好最后几个低位呈现规律性重复,无比蛋疹{这时?#8220;扰动函数”的h值就体现出来了,说到q里大家应该猜出来了。看下面q个图,


右位U?6位,正好?2bit的一半,自己的高半区和低半区做异或,是Z混合原始哈希码的高位和低位,以此来加大低位的随机性。而且混合后的低位掺杂了高位的部分特征Q这样高位的信息也被变相保留下来。最后我们来看一下PeterLawley的一专栏文章《An introduction to optimising a hashing strategy》里的的一个实验:他随机选取?52个字W串Q在他们散列值完全没有冲H的前提下,对它们做低位掩码Q取数组下标?br />

l果昄Q当HashMap数组长度?12的时候,也就是用掩码取低9位的时候,在没有扰动函数的情况下,发生?03ơ碰撞,接近30%。而在使用了扰动函C后只?2ơ碰撞。碰撞减了近10%。看来扰动函数确实还是有功效的。但明显Java 8觉得扰动做一ơ就够了Q做4ơ的话,多了可能辚w效用也不大,所谓ؓ了效率考虑改成一ơ了?br />------------------------------------------------------








https://www.zhihu.com/question/20733617





abin 2017-12-24 22:38 发表评论
]]>
GoLang之方法与接口http://www.qpkxbc.shop/stevenjohn/archive/2017/08/03/432720.htmlabinabinThu, 03 Aug 2017 03:34:00 GMThttp://www.qpkxbc.shop/stevenjohn/archive/2017/08/03/432720.htmlhttp://www.qpkxbc.shop/stevenjohn/comments/432720.htmlhttp://www.qpkxbc.shop/stevenjohn/archive/2017/08/03/432720.html#Feedback0http://www.qpkxbc.shop/stevenjohn/comments/commentRss/432720.htmlhttp://www.qpkxbc.shop/stevenjohn/services/trackbacks/432720.htmlGo语言没有沿袭传统面向对象~程中的诸多概念Q比如ѝ虚函数、构造函数和析构函数、隐藏的this指针{?/p>

 

Ҏ

Go 语言中同时有函数和方法?span style="color: #ff0000;">Ҏ是一个包含了接受者(receiverQ的函数Qreceiver可以是内|类型或者结构体cd的一个值或者是一个指针。所有给定类型的Ҏ属于该类型的Ҏ集?br />

如下面的q个例子Q定义了一个新cdIntegerQ它和int一P只是为它内置的intcd增加了个新方法Less()

复制代码
type Integer int   func (a Integer) Less(b Integer) bool {     return a < b  }  func main() {     var a Integer = 1       if a.Less(2) {         fmt.Println("less then 2")     }    }
复制代码

可以看出QGo语言在自定义cd的对象中没有C++/Java那种隐藏的this指针Q而是在定义成员方法时昑ּ声明了其所属的对象?/p>

 

method的语法如下:

func (r ReceiverType) funcName(parameters) (results)

当调用methodӞ会将receiver作ؓ函数的第一个参敎ͼ

funcName(r, parameters);

所以,receiver是值类型还是指针类型要看method的作用。如果要修改对象的|需要传递对象的指针?/p>

指针作ؓReceiver会对实例对象的内容发生操?而普通类型作为Receiver仅仅是以副本作ؓ操作对象,q不对原实例对象发生操作?/p>

复制代码
func (a *Ingeger) Add(b Integer) {     *a += b }  func main() {     var a Integer = 1      a.Add(3)     fmt.Println("a =", a)     //  a = 4 }
复制代码

如果AddҎ不用指针,则aq回的结果不变,q是因ؓGo语言函数的参C是基于g递?/p>

注意Q?span style="color: #ff0000;">当方法的接受者是指针Ӟ即用值类型调用那么方法内部也是对指针的操作?/span>

 

之前说过QGo语言没有构造函数的概念Q通常使用一个全局函数来完成。例如:

复制代码
func NewRect(x, y, width, height float64) *Rect {     return &Rect{x, y, width, height} }     func main() {     rect1 := NewRect(1,2,10,20)     fmt.Println(rect1.width) }
复制代码

 

 


匿名l合

Go语言提供了承,但是采用了组合的语法Q我们将其称为匿名组合,例如Q?/span>

复制代码
type Base struct {     name string }  func (base *Base) Set(myname string) {     base.name = myname }  func (base *Base) Get() string {     return base.name }  type Derived struct {     Base     age int  }  func (derived *Derived) Get() (nm string, ag int) {     return derived.name, derived.age }   func main() {     b := &Derived{}      b.Set("sina")     fmt.Println(b.Get()) }
复制代码

例子中,在Basecd定义了get()和set()两个ҎQ而Derivedcdl承了Basec,q改写了Get()ҎQ在Derived对象调用Set()ҎQ会加蝲基类对应的方法;而调用Get()ҎӞ加蝲zcL写的Ҏ?/p>

 

l合的类型和被组合的cd包含同名成员Ӟ 会不会有问题呢?可以参考下面的例子Q?/p>

复制代码
type Base struct {     name string     age int }  func (base *Base) Set(myname string, myage int) {     base.name = myname     base.age = myage }  type Derived struct {     Base     name string }  func main() {     b := &Derived{}      b.Set("sina", 30)     fmt.Println("b.name =",b.name, "\tb.Base.name =", b.Base.name)     fmt.Println("b.age =",b.age, "\tb.Base.age =", b.Base.age) }
复制代码

 

 

 


D义和引用语义

D义和引用语义的差别在于赋|比如

b = a b.Modify()

如果b的修改不会媄响a的|那么此类型属于值类型;如果会媄响a的|那么此类型是引用cd?/span>

Go语言中的大多数类型都ZD义,包括Q?/p>

  • 基本cdQ如byte、int、bool、float32、string{;
  • 复合cdQ如arry、struct、pointer{;

 

C语言中的数组比较特别Q通过函数传递一个数l的时候基于引用语义,但是在结构体定义数组变量的时候基于D义。而在Go语言中,数组和基本类型没有区别,是很Ua的值类型,例如Q?/p>

var a = [3] int{1,2,3} var b = a b[1]++ fmt.Println(a, b)   // [1 2 3] [1 3 3]

从结果看Qb=a赋D句是数组内容的完整复Ӟ要想表达引用Q需要用指针Q?/p>

var a = [3] int{1,2,3} var b = &a    // 引用语义 b[1]++ fmt.Println(a, b)   // [1 3 3] [1 3 3]

 

 


接口

Interface 是一l抽象方法(未具体实现的Ҏ/仅包含方法名参数q回值的ҎQ的集合Q如果实C interface 中的所有方法,卌c?对象实C该接口?/p>

Interface 的声明格式:

type interfaceName interface {       //Ҏ列表   }  

Interface 可以被Q意对象实玎ͼ一个类?对象也可以实现多?interfaceQ?br />interface的变量可以持有Q意实现该interfacecd的对象?/span>

 如下面的例子Q?/p>

复制代码
package main      import "fmt"      type Human struct {         name string         age int         phone string     }      type Student struct {         Human //匿名字段         school string         loan float32     }      type Employee struct {         Human //匿名字段         company string         money float32     }      //Human实现SayHiҎ     func (h Human) SayHi() {         fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)     }      //Human实现SingҎ     func (h Human) Sing(lyrics string) {         fmt.Println("La la la la...", lyrics)     }      //Employee重蝲Human的SayHiҎ     func (e Employee) SayHi() {         fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,             e.company, e.phone)         }      // Interface Men被Human,Student和Employee实现     // 因ؓq三个类型都实现了这两个Ҏ     type Men interface {         SayHi()         Sing(lyrics string)     }      func main() {         mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}         paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}         sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}         tom := Employee{Human{"Tom", 37, "222-444-XXX"}, "Things Ltd.", 5000}          //定义Mencd的变量i         var i Men          //i能存储Student         i = mike             fmt.Println("This is Mike, a Student:")         i.SayHi()         i.Sing("November rain")          //i也能存储Employee         i = tom         fmt.Println("This is tom, an Employee:")         i.SayHi()         i.Sing("Born to be wild")          //定义了slice Men         fmt.Println("Let's use a slice of Men and see what happens")         x := make([]Men, 3)         //q三个都是不同类型的元素Q但是他们实Cinterface同一个接?/span>         x[0], x[1], x[2] = paul, sam, mike          for _, value := range x{             value.SayHi()         }     }
复制代码

 

I接?/h3>

Iinterface(interface{})不包含Q何的methodQ正因ؓ如此Q?span style="background-color: #ffff00;">所有的cd都实CIinterface。空interface对于描述起不CQ何的作用(因ؓ它不包含M的methodQ,但是Iinterface在我们需要存储Q意类型的数值的时候相当有用,因ؓ它可以存储Q意类型的数倹{它有点cM于C语言的void*cd?/span>

复制代码
// 定义a为空接口     var a interface{}     var i int = 5     s := "Hello world"     // a可以存储Lcd的数?/span>     a = i     a = s
复制代码

 

interface的变量里面可以存储Q意类型的数|该类型实CinterfaceQ,那么我们怎么反向知道q个interface变量里面实际保存了的是哪个类型的对象呢?目前常用的有两种ҎQswitch试、Comma-ok断言?/p>

 

switch试如下Q?/p>

复制代码
type Element interface{} type List [] Element  type Person struct {     name string     age int  }  //打印 func (p Person) String() string {     return "(name: " + p.name + " - age: "+strconv.Itoa(p.age)+ " years)" }  func main() {     list := make(List, 3)     list[0] = 1 //an int      list[1] = "Hello" //a string     list[2] = Person{"Dennis", 70}       for index, element := range list{         switch value := element.(type) {             case int:                 fmt.Printf("list[%d] is an int and its value is %d\n", index, value)             case string:                 fmt.Printf("list[%d] is a string and its value is %s\n", index, value)             case Person:                 fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)             default:                 fmt.Println("list[%d] is of a different type", index)         }        }    }
复制代码

 

如果使用Comma-ok断言的话Q?/p>

复制代码
func main() {     list := make(List, 3)     list[0] = 1 // an int     list[1] = "Hello" // a string     list[2] = Person{"Dennis", 70}      for index, element := range list {         if value, ok := element.(int); ok {             fmt.Printf("list[%d] is an int and its value is %d\n", index, value)         } else if value, ok := element.(string); ok {             fmt.Printf("list[%d] is a string and its value is %s\n", index, value)         } else if value, ok := element.(Person); ok {             fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)         } else {             fmt.Printf("list[%d] is of a different type\n", index)         }     } }
复制代码

 

 

嵌入接口

正如structcd可以包含一个匿名字D,interface也可以嵌套另外一个接口?/p>

如果一个interface1作ؓinterface2的一个嵌入字D,那么interface2隐式的包含了interface1里面的method?/p>

 

 

反射

所谓反(reflectQ就是能查程序在q行时的状态?/p>

使用reflect一般分成三步,下面要的讲解一下:要去反射是一个类型的?q些值都实现了空interface)Q首先需要把它{化成reflect对象(reflect.Type或者reflect.ValueQ根据不同的情况调用不同的函?。这两种获取方式如下Q?/p>

 t := reflect.TypeOf(i)    //得到cd的元数据,通过t我们能获取类型定义里面的所有元?/span>  v := reflect.ValueOf(i)   //得到实际的|通过v我们获取存储在里面的|q可以去改变?/span>

 

转化为reflect对象之后我们可以进行一些操作了Q也是reflect对象转化成相应的|例如

tag := t.Elem().Field(0).Tag  //获取定义在struct里面的标{?/span> name := v.Elem().Field(0).String()  //获取存储在第一个字D里面的?/span>

 

获取反射Dq回相应的类型和数?/p>

var x float64 = 3.4 v := reflect.ValueOf(x) fmt.Println("type:", v.Type()) fmt.Println("kind is float64:", v.Kind() == reflect.Float64) fmt.Println("value:", v.Float())

 

最后,反射的话Q那么反的字段必须是可修改的,我们前面学习q传值和传引用,q个里面也是一L道理。反的字段必须是可d的意思是Q如果下面这样写Q那么会发生错误

var x float64 = 3.4 v := reflect.ValueOf(x) v.SetFloat(7.1)

 

如果要修改相应的|必须q样?/p>

var x float64 = 3.4 p := reflect.ValueOf(&x) v := p.Elem() v.SetFloat(7.1)

上面只是对反的单介l,更深入的理解q需要自己在~程中不断的实践?/p>

 

 

参考文档:

http://se77en.cc/2014/05/05/methods-interfaces-and-embedded-types-in-golang/

http://se77en.cc/2014/05/04/choose-whether-to-use-a-value-or-pointer-receiver-on-methods/

 http://www.cnblogs.com/chenny7/p/4497969.html







abin 2017-08-03 11:34 发表评论
]]>
老虞要学GoLang-函数(?http://www.qpkxbc.shop/stevenjohn/archive/2017/08/02/432718.htmlabinabinWed, 02 Aug 2017 08:39:00 GMThttp://www.qpkxbc.shop/stevenjohn/archive/2017/08/02/432718.htmlhttp://www.qpkxbc.shop/stevenjohn/comments/432718.htmlhttp://www.qpkxbc.shop/stevenjohn/archive/2017/08/02/432718.html#Feedback0http://www.qpkxbc.shop/stevenjohn/comments/commentRss/432718.htmlhttp://www.qpkxbc.shop/stevenjohn/services/trackbacks/432718.html不可或缺的函敎ͼ在Go中定义函数的方式如下Q?/p>
func (p myType ) funcName ( a, b int , c string ) ( r , s int ) {     return } 

通过函数定义Q我们可以看到Go中函数和其他语言中的共性和Ҏ?/p>

共?/h3>
  • 关键?#8212;—func
  • Ҏ?#8212;—funcName
  • 入参——— a,b int,b string
  • q回?#8212;— r,s int
  • 函数?#8212;— {}

Ҏ?/h3>

Go中函数的Ҏ是非常LQ给我们带来不一L~程体验?/p>

为特定类型定义函敎ͼ即ؓcd对象定义Ҏ

在Go中通过l函数标明所属类型,来给该类型定义方法,上面?nbsp;p myType 卌C给myType声明了一个方法, p myType 不是必须的。如果没有,则纯_Ҏ一个函敎ͼ通过包名U访问。packageName.funcationName

如:

//定义新的cddoubleQ主要目的是lfloat64cd扩充Ҏ type double float64  //判断a是否{于b func (a double) IsEqual(b double) bool {     var r = a - b     if r == 0.0 {         return true     } else if r < 0.0 {         return r > -0.0001     }     return r < 0.0001 }  //判断a是否{于b func IsEqual(a, b float64) bool {     var r = a - b     if r == 0.0 {         return true     } else if r < 0.0 {         return r > -0.0001     }     return r < 0.0001 }  func main() {     var a double = 1.999999     var b double = 1.9999998     fmt.Println(a.IsEqual(b))     fmt.Println(a.IsEqual(3))     fmt.Println( IsEqual( (float64)(a), (float64)(b) ) )  } 

上述CZ?float64 基本cd扩充了方法IsEqualQ该Ҏ主要是解决精度问题?其方法调用方式ؓQ?nbsp;a.IsEqual(double) Q如果不扩充ҎQ我们只能用函?code style="margin: 0px 2px; padding: 0px 5px; border: 1px solid #eaeaea; background-color: #f8f8f8; border-radius: 3px; white-space: nowrap; font-family: monospace, Monaco;">IsEqual(a, b float64)

入参中,如果q箋的参数类型一_则可以省略连l多个参数的cdQ只保留最后一个类型声明?/h4>

?nbsp;func IsEqual(a, b float64) bool q个Ҏ只保留了一个类型声?此时入参a和b均是float64数据cd?q样也是可以的: func IsEqual(a, b float64, accuracy int) bool

变参Q入参支持变?卛_接受不确定数量的同一cd的参?/h4>

?nbsp;func Sum(args ...int) 参数args是的sliceQ其元素cd为int 。经怋用的fmt.Printf是一个接受Q意个数参数的函数 fmt.Printf(format string, args ...interface{})

支持多返回?/h4>

前面我们定义函数时返回值有两个r,s 。这是非常有用的Q我在写C#代码Ӟ常常Z从已有函C获得更多的信息,需要修改函数签名,使用out ,ref {方式去获得更多q回l果。而现在用Go时则很简单,直接在返回值后面添加返回参数即可?/p>

?在C#中一个字W串转换为intcd旉辑代码

int v=0;  if ( int.TryPase("123456",out v) ) {     //code } 

而在Go中,则可以这样实?逻辑_而明?/p>

if v,isOk :=int.TryPase("123456") ; isOk {     //code } 

同时在Go中很多函数充分利用了多返回?/p>

  • func (file *File) Write(b []byte) (n int, err error)
  • func Sincos(x float64) (sin, cos float64)

那么如果我只需要某一个返回|而不兛_其他q回值的话,我该如何办呢Q?q时可以单的使用W号下划U?#8221;_“ 来忽略不兛_的返回倹{如Q?/p>

_, cos = math.Sincos(3.1415) //只需要cos计算的?

命名q回?/h4>

前面我们说了函数可以有多个返回|q里我还要说的是Q在函数定义时可以给所有的q回值分别命名,q样p在函CL位置l不同返回值复Ӟ而不需要在return语句中才指定q回倹{同时也能增强可L,也提高godoc所生成文档的可L?/p>

如果不支持命名返回|我可能会是这样做?/p>

func ReadFull(r Reader, buf []byte) (int, error) {     var n int     var err error      for len(buf) > 0  {         var nr int         nr, err = r.Read(buf)          n += nr         if err !=nil {             return n,err         }         buf = buf[nr:]     }     return n,err } 

但支持给q回值命名后Q实际上是省略了变量的声明Qreturn时无需写成return n,err 而是直接将D?/p>

func ReadFull(r Reader, buf []byte) (n int, err error) {     for len(buf) > 0 && err == nil {         var nr int         nr, err = r.Read(buf)         n += nr         buf = buf[nr:]     }     return } 

函数也是“?#8221;

和Go中其他东西一P函数也是|q样可以声明一个函数类型的变量Q将函数作ؓ参数传递?/p>

声明函数为值的变量(匿名函数:可赋g变量Q也可直接执?

//赋?fc := func(msg string) {     fmt.Println("you say :", msg) } fmt.Printf("%T \n", fc) fc("hello,my love") //直接执行 func(msg string) {     fmt.Println("say :", msg) }("I love to code") 

输出l果如下Q这里表明fc 的类型ؓQfunc(string)

func(string)  you say : hello,my love say : I love to code 

函C为入参(回调函数Q,能带来便利。如日志处理Qؓ了统一处理Q将信息均通过指定函数去记录日志,且是否记录日志还有开?/p>

func Log(title string, getMsg func() string) {     //如果开启日志记?则记录日?    if true {         fmt.Println(title, ":", getMsg())     } } //---------调用-------------- count := 0 msg := func() string {     count++     return "您没有即使提醒我,已触犯法? } Log("error", msg) Log("warring", msg) Log("info", msg) fmt.Println(count) 

q里输出l果如下Qcount 也发生了变化

error : 您没有即使提醒我,已触犯法?warring : 您没有即使提醒我,已触犯法?info : 您没有即使提醒我,已触犯法?3 

函数也是“cd”

你有没有注意C面示例中?nbsp;fc := func(msg string)... Q既然匿名函数可以赋值给一个变量,同时我们l常q样lint赋?nbsp;value := 2 ,是否我们可以声明func(string) cd 呢,当然是可以的?/p>

//一个记录日志的cdQfunc(string) type saveLog func(msg string)  //字W串转换为int64,如果转换p|调用saveLog func stringToInt(s string, log saveLog) int64 {      if value, err := strconv.ParseInt(s, 0, 0); err != nil {         log(err.Error())         return 0     } else {         return value     } }  //记录日志消息的具体实?func myLog(msg string) {     fmt.Println("Find Error:", msg) }  func main() {     stringToInt("123", myLog) //转换时将调用mylog记录日志     stringToInt("s", myLog) } 

q里我们定义了一个类型,专门用作记录日志的标准接口。在stringToInt函数中如果{换失败则调用我自己定义的接口函数q行日志处理Q至于最l执行的哪个函数Q则无需兛_?/p>

defer 延迟函数

defer 又是一个创斎ͼ它的作用是:延迟执行Q在声明时不会立x行,而是在函数return后时按照后进先出的原则依ơ执行每一个defer。这样带来的好处是,能确保我们定义的函数能百分之百能够被执行刎ͼq样p做很多我们想做的事,如释放资源,清理数据Q记录日志等

q里我们重点来说明下defer的执行顺?/p>

func deferFunc() int {     index := 0      fc := func() {          fmt.Println(index, "匿名函数1")         index++          defer func() {             fmt.Println(index, "匿名函数1-1")             index++         }()     }      defer func() {         fmt.Println(index, "匿名函数2")         index++     }()      defer fc()      return func() int {         fmt.Println(index, "匿名函数3")         index++         return index     }() }  func main() {     deferFunc() } 

q里输出l果如下Q?/p>

0 匿名函数3 1 匿名函数1 2 匿名函数1-1 3 匿名函数2 

有如下结论:

  • defer 是在执行完return 后执?/li>
  • defer 后进先执?/li>

另外Q我们常使用deferd闭IO,在正常打开文g后,qd明一个deferQ这样就不会忘记关闭文gQ也能保证在出现异常{不可预料的情况下也能关闭文件。而不像其他语aQ?code style="margin: 0px 2px; padding: 0px 5px; border: 1px solid #eaeaea; background-color: #f8f8f8; border-radius: 3px; white-space: nowrap; font-family: monospace, Monaco;">try-catch 或?nbsp;using() 方式q行处理?/p>

file , err :=os.Open(file) if err != nil {     return err } defer file.Close()  //dosomething with file 

后箋Q我讨论: 作用域、传值和传指?以及 保留函数init(),main()

本笔C所写代码存储位|:



abin 2017-08-02 16:39 发表评论
]]>
MySQL触发器Trigger实例?http://www.qpkxbc.shop/stevenjohn/archive/2016/08/18/431625.htmlabinabinThu, 18 Aug 2016 09:25:00 GMThttp://www.qpkxbc.shop/stevenjohn/archive/2016/08/18/431625.htmlhttp://www.qpkxbc.shop/stevenjohn/comments/431625.htmlhttp://www.qpkxbc.shop/stevenjohn/archive/2016/08/18/431625.html#Feedback0http://www.qpkxbc.shop/stevenjohn/comments/commentRss/431625.htmlhttp://www.qpkxbc.shop/stevenjohn/services/trackbacks/431625.html
MySQL触发器Trigger实例?/div>
发表?68 天前 ⁄ IT技?/a> ⁄ 暂无评论

以前x的数据存储过E不太懂其中奥妙Q最q遇到跨数据?/a>Q同时对多个表进行CURDQCreate增、Update攏VRead诅RDelete删)Q怎么才能让繁琐的数据CURD同步变得更容易呢Q相信很多h会首先想CMySQL存储q程、触发器Q这U想法确实不错。于是饶有兴地亲自写了CUDQ增、改、删Q触发器的实例,用触发器实现多表数据同步更新?/p>

MySQL触发器Trigger实例? title=

定义Q?何ؓMySQL触发器?

在MySQL Server里面也就是对某一个表的一定的操作Q触发某U条ӞInsert,Update,Delete {)Q从而自动执行的一D늨序。从q种意义上讲触发器是一个特D的存储q程。下面通过MySQL触发器实例,来了解一下触发器的工作过E吧Q?/p>

一、创建MySQL实例数据表:

在mysql的默认的试test数据库下Q创Z个表t_a与t_bQ?/p>



    /*Table structure for table `t_a` */
    DROP TABLE IF EXISTS `t_a`;
    CREATE TABLE `t_a` (
      `id` smallint(1) unsigned NOT NULL AUTO_INCREMENT,
      `username` varchar(20) DEFAULT NULL,
      `groupid` mediumint(8) unsigned NOT NULL DEFAULT '0',
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=16 DEFAULT CHARSET=latin1;
     
    /*Data for the table `t_a` */
    LOCK TABLES `t_a` WRITE;
    UNLOCK TABLES;
     
    /*Table structure for table `t_b` */
    DROP TABLE IF EXISTS `t_b`;
    CREATE TABLE `t_b` (
      `id` smallint(1) unsigned NOT NULL AUTO_INCREMENT,
      `username` varchar(20) DEFAULT NULL,
      `groupid` mediumint(8) unsigned NOT NULL DEFAULT '0',
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=57 DEFAULT CHARSET=latin1;
     
    /*Data for the table `t_b` */
    LOCK TABLES `t_b` WRITE;
    UNLOCK TABLES;

在t_a表上分创Z个CUDQ增、改、删Q?个触发器Q将t_a的表数据与t_b同步实现CUDQ注意创发器每个表同cM件有且仅有一个对应触发器Qؓ什么只能对一个触发器Q不解释啦,看MYSQL的说明帮助文档吧?/p>

二、创建MySQL实例触发器:

在实例数据表t_a上依ơ按照下面步骤创建tr_a_insert、tr_a_update、tr_a_delete三个触发?/p>

1、创建INSERT触发器trigger_a_insertQ?/strong>



    DELIMITER $$
     
    USE `test`$$
     
    --判断数据库中是否存在tr_a_insert触发?br />    DROP TRIGGER /*!50032 IF EXISTS */ `tr_a_insert`$$
    --不存在tr_a_insert触发器,开始创发器
    --Trigger触发条g为insert成功后进行触?br />    CREATE
        /*!50017 DEFINER = 'root'@'localhost' */
        TRIGGER `tr_a_insert` AFTER INSERT ON `t_a`
        FOR EACH ROW BEGIN
            --Trigger触发后,同时对t_b新增同步一条数?br />            INSERT INTO `t_b` SET username = NEW.username, groupid=NEW.groupid;
        END;
    $$
     
    DELIMITER;
2、创建UPDATE触发器trigger_a_updateQ?/strong>


    DELIMITER $$
     
    USE `test`$$
    --判断数据库中是否存在tr_a_update触发?br />    DROP TRIGGER /*!50032 IF EXISTS */ `tr_a_update`$$
    --不存在tr_a_update触发器,开始创发器
    --Trigger触发条g为update成功后进行触?br />    CREATE
        /*!50017 DEFINER = 'root'@'localhost' */
        TRIGGER `tr_a_update` AFTER UPDATE ON `t_a`
        FOR EACH ROW BEGIN
        --Trigger触发后,当t_a表groupid,username数据有更ҎQ对t_b表同步一条更新后的数?br />          IF new.groupid != old.groupid OR old.username != new.username THEN
            UPDATE `t_b` SET groupid=NEW.groupid,username=NEW.username WHEREusername=OLD.username AND groupid=OLD.groupid;
          END IF;
              
        END;
    $$
     
    DELIMITER ;
3、创建DELETE触发器trigger_a_deleteQ?/strong>


    DELIMITER $$
     
    USE `test`$$
    --判断数据库中是否存在tr_a_delete触发?br />    DROP TRIGGER /*!50032 IF EXISTS */ `tr_a_delete`$$
    --不存在tr_a_delete触发器,开始创发器
    --Trigger触发条g为delete成功后进行触?br />    CREATE
        /*!50017 DEFINER = 'root'@'localhost' */
        TRIGGER `tr_a_delete` AFTER DELETE ON `t_a`
        FOR EACH ROW BEGIN
            --t_a表数据删除后Qt_b表关联条件相同的数据也同步删?br />            DELETE FROM `t_b` WHERE username=Old.username AND groupid=OLD.groupid;
        END;
    $$
     
    DELIMITER ;

三、测试MySQL实例触发器:

分别试实现t_a与t_b实现数据同步CUD(增、改、删)3个Triggers

1、测试MySQL的实例tr_a_insert触发器:

在t_a表中新增一条数据,然后分别查询t_a/t_b表的数据是否数据同步Q测试触发器成功标志Qt_a表无论在何种情况下,新增了一条或多条记录集时Q没有t_b表做M数据insert操作Q它同时新增了一L多条记录集?/p>

下面来进行MySQL触发器实例测试:



    --t_a表新增一条记录集
        INSERT INTO `t_a` (username,groupid) VALUES ('sky54.net',123)
       
        --查询t_a?br />        SELECT id,username,groupid FROM `t_a`
       
        --查询t_b?br />        SELECT id,username,groupid FROM `t_b`

2、测试MySQL的实例tr_a_update、tr_a_delete触发器:

q两个MySQL触发器测试原理、步骤与tr_a_insert触发器一LQ先修改/删除一条数据,然后分别查看t_a、t_b表的数据变化情况Q数据变化同步说明Trigger实例成功Q否则需要逐步排查错误原因?/p>

世界上Q何一U事物都其其优点和缺点,优点与缺Ҏ自n一个相对立的面。当然这里不是强?#8220;世界非黑即白”式的“二元?#8221;Q?#8220;存在卛_?#8221;嘛。当?MySQL触发器的优点不说了,说一下不之处,MySQL Trigger没有很好的调试、管理环境,难于在各U系l环境下试Q测试比MySQL存储q程要难Q所以徏议在生成环境下,量用存储过E来代替 MySQL触发器?/p>

本篇l束前再一下,支持触发器的MySQL版本需?.0以上Q?.0以前版本的MySQL升?.0以后版本方可使用触发器哦Q?/p>








http://blog.csdn.net/hireboy/article/details/18079183





abin 2016-08-18 17:25 发表评论
]]>
聊聊高ƈ发系l之限流Ҏ-1http://www.qpkxbc.shop/stevenjohn/archive/2016/06/14/430882.htmlabinabinTue, 14 Jun 2016 05:38:00 GMThttp://www.qpkxbc.shop/stevenjohn/archive/2016/06/14/430882.htmlhttp://www.qpkxbc.shop/stevenjohn/comments/430882.htmlhttp://www.qpkxbc.shop/stevenjohn/archive/2016/06/14/430882.html#Feedback1http://www.qpkxbc.shop/stevenjohn/comments/commentRss/430882.htmlhttp://www.qpkxbc.shop/stevenjohn/services/trackbacks/430882.html阅读全文

abin 2016-06-14 13:38 发表评论
]]>
shadowsocks 安装http://www.qpkxbc.shop/stevenjohn/archive/2016/05/13/430493.htmlabinabinFri, 13 May 2016 14:56:00 GMThttp://www.qpkxbc.shop/stevenjohn/archive/2016/05/13/430493.htmlhttp://www.qpkxbc.shop/stevenjohn/comments/430493.htmlhttp://www.qpkxbc.shop/stevenjohn/archive/2016/05/13/430493.html#Feedback0http://www.qpkxbc.shop/stevenjohn/comments/commentRss/430493.htmlhttp://www.qpkxbc.shop/stevenjohn/services/trackbacks/430493.htmlInstall the Command Line Client

If you prefer command line client, then you can install it on your Linux with the following command.

Debian

sudo apt-get install python-pip sudo pip install shadowsocks

Ubuntu

Yes, you can use the above commands to install shadowsocks client on ubuntu. But it will install it under ~/.local/bin/ directory and it causes loads of trouble. So I suggest using su to become root first and then issue the following two commands.

apt-get install python-pip pip install shadowsocks

Fedora/Centos

sudo yum install python-setuptools   or   sudo dnf install python-setuptools sudo easy_install pip sudo pip install shadowsocks

OpenSUSE

sudo zypper install python-pip sudo pip install shadowsocks

Archlinux

sudo pacman -S python-pip sudo pip install shadowsocks

As you can see the command of installing shadowsocks client is the same to the command of installing shadowsocks server, because the above command will install both the client and the server. You can verify this by looking at the installation script output

Downloading/unpacking shadowsocks Downloading shadowsocks-2.8.2.tar.gz Running setup.py (path:/tmp/pip-build-PQIgUg/shadowsocks/setup.py) egg_info for package shadowsocks  Installing collected packages: shadowsocks Running setup.py install for shadowsocks  Installing sslocal script to /usr/local/bin Installing ssserver script to /usr/local/bin Successfully installed shadowsocks Cleaning up...

sslocal is the client software and ssserver is the server software. On some Linux distros such as ubuntu, the shadowsocks client sslocal is installed under /usr/local/bin. On Others such as Archsslocal is installed under /usr/bin/. Your can use whereis command to find the exact location.

user@debian:~$ whereis sslocal sslocal: /usr/local/bin/sslocal

Create a Configuration File

we will create a configuration file under /etc/

sudo vi /etc/shadowsocks.json

Put the following text in the file. Replace server-ip with your actual IP and set a password.

{
"server":"server-ip",
"server_port":8000,
"local_address": "127.0.0.1",
"local_port":1080,
"password":"your-password",
"timeout":600,
"method":"aes-256-cfb"
}

Save and close the file. Next start the client using command line

sslocal -c /etc/shadowsocks.json

To run in the background

sudo sslocal -c /etc/shadowsocks.json -d start

Auto Start the Client on System Boot

Edit /etc/rc.local file

sudo vi /etc/rc.local

Put the following line above the exit 0 line:

sudo sslocal -c /etc/shadowsocks.json -d start

Save and close the file. Next time you start your computer, shadowsocks client will automatically start and connect to your shadowsocks server.

Check if It Works

After you rebooted your computer, enter the following command in terminal:

sudo systemctl status rc-local.service

If your sslocal command works then you will get this ouput:


● rc-local.service - /etc/rc.local 

Compatibility Loaded: loaded (/etc/systemd/system/rc-local.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2015-11-27 03:19:25 CST; 2min 39s ago
Process: 881 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS)
CGroup: /system.slice/rc-local.service
├─ 887 watch -n 60 su matrix -c ibam
└─1112 /usr/bin/python /usr/local/bin/sslocal -c /etc/shadowsocks....

As you can see from the last line, the sslocal command created a process whose pid is 1112 on my machine. It means shadowsocks client is running smoothly. And of course you can tell your browser to connect through your shadowsocks client to see if everything goes well.

If for some reason your /etc/rc.local script won’t run, then check the following post to find the solution.

How to enable /etc/rc.local with SystemdInstall the Command Line Client

If you prefer command line client, then you can install it on your Linux with the following command.

Debian

sudo apt-get install python-pip
sudo pip install shadowsocks

Ubuntu

Yes, you can use the above commands to install shadowsocks client on ubuntu. But it will install it under ~/.local/bin/ directory and it causes loads of trouble. So I suggest using su to become root first and then issue the following two commands.

apt-get install python-pip
pip install shadowsocks

Fedora/Centos

sudo yum install python-setuptools   or   sudo dnf install python-setuptools
sudo easy_install pip
sudo pip install shadowsocks

OpenSUSE

sudo zypper install python-pip
sudo pip install shadowsocks

Archlinux

sudo pacman -S python-pip
sudo pip install shadowsocks

As you can see the command of installing shadowsocks client is the same to the command of installing shadowsocks server, because the above command will install both the client and the server. You can verify this by looking at the installation script output

Downloading/unpacking shadowsocks
Downloading shadowsocks-2.8.2.tar.gz
Running setup.py (path:/tmp/pip-build-PQIgUg/shadowsocks/setup.py) egg_info for package shadowsocks

Installing collected packages: shadowsocks
Running setup.py install for shadowsocks

Installing sslocal script to /usr/local/bin
Installing ssserver script to /usr/local/bin
Successfully installed shadowsocks
Cleaning up...

sslocal is the client software and ssserver is the server software. On some Linux distros such as ubuntu, the shadowsocks client sslocal is installed under /usr/local/bin. On Others such as Archsslocal is installed under /usr/bin/. Your can use whereis command to find the exact location.

user@debian:~$ whereis sslocal
sslocal: /usr/local/bin/sslocal

Create a Configuration File

we will create a configuration file under /etc/

sudo vi /etc/shadowsocks.json

Put the following text in the file. Replace server-ip with your actual IP and set a password.

{
"server":"server-ip",
"server_port":8000,
"local_address": "127.0.0.1",
"local_port":1080,
"password":"your-password",
"timeout":600,
"method":"aes-256-cfb"
}

Save and close the file. Next start the client using command line

sslocal -c /etc/shadowsocks.json

To run in the background

sudo sslocal -c /etc/shadowsocks.json -d start

Auto Start the Client on System Boot

Edit /etc/rc.local file

sudo vi /etc/rc.local

Put the following line above the exit 0 line:

sudo sslocal -c /etc/shadowsocks.json -d start

Save and close the file. Next time you start your computer, shadowsocks client will automatically start and connect to your shadowsocks server.

Check if It Works

After you rebooted your computer, enter the following command in terminal:

sudo systemctl status rc-local.service

If your sslocal command works then you will get this ouput:

● rc-local.service - /etc/rc.local Compatibility
Loaded: loaded (/etc/systemd/system/rc-local.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2015-11-27 03:19:25 CST; 2min 39s ago
Process: 881 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS)
CGroup: /system.slice/rc-local.service
├─ 887 watch -n 60 su matrix -c ibam
└─1112 /usr/bin/python /usr/local/bin/sslocal -c /etc/shadowsocks....

As you can see from the last line, the sslocal command created a process whose pid is 1112 on my machine. It means shadowsocks client is running smoothly. And of course you can tell your browser to connect through your shadowsocks client to see if everything goes well.

If for some reason your /etc/rc.local script won’t run, then check the following post to find the solution.

How to enable /etc/rc.local with Systemd






abin 2016-05-13 22:56 发表评论
]]>
httpClient Https 单向不验?httpClientq接? http://www.qpkxbc.shop/stevenjohn/archive/2016/04/27/430267.htmlabinabinWed, 27 Apr 2016 11:04:00 GMThttp://www.qpkxbc.shop/stevenjohn/archive/2016/04/27/430267.htmlhttp://www.qpkxbc.shop/stevenjohn/comments/430267.htmlhttp://www.qpkxbc.shop/stevenjohn/archive/2016/04/27/430267.html#Feedback0http://www.qpkxbc.shop/stevenjohn/comments/commentRss/430267.htmlhttp://www.qpkxbc.shop/stevenjohn/services/trackbacks/430267.html废话说Q直接上代码Q以前都是调用别人写好的Q现在有旉自己弄下Q具体功能如下:
1、httpClient+http+U程池:
2、httpClient+https(单向不验证证?+U程池:

https?TOMCAT_HOME%/conf/server.xml里面的配|文?br />
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" 
     maxThreads="150" scheme="https" secure="true" 
     clientAuth="false" keystoreFile="D:/tomcat.keystore" 
     keystorePass="heikaim" sslProtocol="TLS"  executor="tomcatThreadPool"/> 
其中 clientAuth="false"表示不开启证书验证,只是单存的走https



package com.abin.lee.util;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.*;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;

/**
* Created with IntelliJ IDEA.
* User: abin
* Date: 16-4-18
* Time: 上午10:24
* To change this template use File | Settings | File Templates.
*/
public class HttpClientUtil {
private static CloseableHttpClient httpsClient = null;
private static CloseableHttpClient httpClient = null;

static {
httpClient = getHttpClient();
httpsClient = getHttpsClient();
}

public static CloseableHttpClient getHttpClient() {
try {
httpClient = HttpClients.custom()
.setConnectionManager(PoolManager.getHttpPoolInstance())
.setConnectionManagerShared(true)
.setDefaultRequestConfig(requestConfig())
.setRetryHandler(retryHandler())
.build();
} catch (Exception e) {
e.printStackTrace();
}
return httpClient;
}


public static CloseableHttpClient getHttpsClient() {
try {
//Secure Protocol implementation.
SSLContext ctx = SSLContext.getInstance("SSL");
//Implementation of a trust manager for X509 certificates
TrustManager x509TrustManager = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs,
String string) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] xcs,
String string) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{x509TrustManager}, null);
//首先讄全局的标准cookie{略
// RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT).build();
ConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(ctx, hostnameVerifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", connectionSocketFactory).build();
// 讄q接?br /> httpsClient = HttpClients.custom()
.setConnectionManager(PoolsManager.getHttpsPoolInstance(socketFactoryRegistry))
.setConnectionManagerShared(true)
.setDefaultRequestConfig(requestConfig())
.setRetryHandler(retryHandler())
.build();
} catch (Exception e) {
e.printStackTrace();
}
return httpsClient;
}

// 配置h的超时设|?br /> //首先讄全局的标准cookie{略
public static RequestConfig requestConfig(){
RequestConfig requestConfig = RequestConfig.custom()
.setCookieSpec(CookieSpecs.STANDARD_STRICT)
.setConnectionRequestTimeout(20000)
.setConnectTimeout(20000)
.setSocketTimeout(20000)
.build();
return requestConfig;
}

public static HttpRequestRetryHandler retryHandler(){
//h重试处理
HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
public boolean retryRequest(IOException exception,int executionCount, HttpContext context) {
if (executionCount >= 5) {// 如果已经重试?ơ,放?br /> return false;
}
if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了q接Q那么就重试
return true;
}
if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常
return false;
}
if (exception instanceof InterruptedIOException) {// 时
return false;
}
if (exception instanceof UnknownHostException) {// 目标服务器不可达
return false;
}
if (exception instanceof ConnectTimeoutException) {// q接被拒l?br /> return false;
}
if (exception instanceof SSLException) {// ssl握手异常
return false;
}

HttpClientContext clientContext = HttpClientContext.adapt(context);
HttpRequest request = clientContext.getRequest();
// 如果h是幂{的Q就再次试
if (!(request instanceof HttpEntityEnclosingRequest)) {
return true;
}
return false;
}
};
return httpRequestRetryHandler;
}



//创徏HostnameVerifier
//用于解决javax.net.ssl.SSLException: hostname in certificate didn't match: <123.125.97.66> != <123.125.97.241>
static HostnameVerifier hostnameVerifier = new NoopHostnameVerifier(){
@Override
public boolean verify(String s, SSLSession sslSession) {
return super.verify(s, sslSession);
}
};


public static class PoolManager {
public static PoolingHttpClientConnectionManager clientConnectionManager = null;
private static int maxTotal = 200;
private static int defaultMaxPerRoute = 100;

private PoolManager(){
clientConnectionManager.setMaxTotal(maxTotal);
clientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
}

private static class PoolManagerHolder{
public static PoolManager instance = new PoolManager();
}

public static PoolManager getInstance() {
if(null == clientConnectionManager)
clientConnectionManager = new PoolingHttpClientConnectionManager();
return PoolManagerHolder.instance;
}

public static PoolingHttpClientConnectionManager getHttpPoolInstance() {
PoolManager.getInstance();
// System.out.println("getAvailable=" + clientConnectionManager.getTotalStats().getAvailable());
// System.out.println("getLeased=" + clientConnectionManager.getTotalStats().getLeased());
// System.out.println("getMax=" + clientConnectionManager.getTotalStats().getMax());
// System.out.println("getPending="+clientConnectionManager.getTotalStats().getPending());
return PoolManager.clientConnectionManager;
}


}

public static class PoolsManager {
public static PoolingHttpClientConnectionManager clientConnectionManager = null;
private static int maxTotal = 200;
private static int defaultMaxPerRoute = 100;

private PoolsManager(){
clientConnectionManager.setMaxTotal(maxTotal);
clientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
}

private static class PoolsManagerHolder{
public static PoolsManager instance = new PoolsManager();
}

public static PoolsManager getInstance(Registry<ConnectionSocketFactory> socketFactoryRegistry) {
if(null == clientConnectionManager)
clientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
return PoolsManagerHolder.instance;
}

public static PoolingHttpClientConnectionManager getHttpsPoolInstance(Registry<ConnectionSocketFactory> socketFactoryRegistry) {
PoolsManager.getInstance(socketFactoryRegistry);
// System.out.println("getAvailable=" + clientConnectionManager.getTotalStats().getAvailable());
// System.out.println("getLeased=" + clientConnectionManager.getTotalStats().getLeased());
// System.out.println("getMax=" + clientConnectionManager.getTotalStats().getMax());
// System.out.println("getPending="+clientConnectionManager.getTotalStats().getPending());
return PoolsManager.clientConnectionManager;
}

}

public static String httpPost(Map<String, String> request, String httpUrl){
String result = "";
CloseableHttpClient httpClient = getHttpClient();
try {
if(MapUtils.isEmpty(request))
throw new Exception("h参数不能为空");
HttpPost httpPost = new HttpPost(httpUrl);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
for(Iterator<Map.Entry<String, String>> iterator=request.entrySet().iterator(); iterator.hasNext();){
Map.Entry<String, String> entry = iterator.next();
nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
System.out.println("Executing request: " + httpPost.getRequestLine());
CloseableHttpResponse response = httpClient.execute(httpPost);
result = EntityUtils.toString(response.getEntity());
System.out.println("Executing response: "+ result);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}

public static String httpPost(String json, String httpUrl, Map<String, String> headers){
String result = "";
CloseableHttpClient httpClient = getHttpClient();
try {
if(StringUtils.isBlank(json))
throw new Exception("h参数不能为空");
HttpPost httpPost = new HttpPost(httpUrl);
for(Iterator<Map.Entry<String, String>> iterator=headers.entrySet().iterator();iterator.hasNext();){
Map.Entry<String, String> entry = iterator.next();
Header header = new BasicHeader(entry.getKey(), entry.getValue());
httpPost.setHeader(header);
}
httpPost.setEntity(new StringEntity(json, Charset.forName("UTF-8")));
System.out.println("Executing request: " + httpPost.getRequestLine());
CloseableHttpResponse response = httpClient.execute(httpPost);
result = EntityUtils.toString(response.getEntity());
System.out.println("Executing response: "+ result);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}

public static String httpGet(String httpUrl, Map<String, String> headers) {
String result = "";
CloseableHttpClient httpClient = getHttpClient();
try {
HttpGet httpGet = new HttpGet(httpUrl);
System.out.println("Executing request: " + httpGet.getRequestLine());
for(Iterator<Map.Entry<String, String>> iterator=headers.entrySet().iterator();iterator.hasNext();){
Map.Entry<String, String> entry = iterator.next();
Header header = new BasicHeader(entry.getKey(), entry.getValue());
httpGet.setHeader(header);
}
CloseableHttpResponse response = httpClient.execute(httpGet);
result = EntityUtils.toString(response.getEntity());
System.out.println("Executing response: "+ result);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}


public static String httpGet(String httpUrl) {
String result = "";
CloseableHttpClient httpClient = getHttpClient();
try {
HttpGet httpGet = new HttpGet(httpUrl);
System.out.println("Executing request: " + httpGet.getRequestLine());
CloseableHttpResponse response = httpClient.execute(httpGet);
result = EntityUtils.toString(response.getEntity());
System.out.println("Executing response: "+ result);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}





maven依赖Q?br />
  <!--httpclient-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.5.2</version>
        </dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>


abin 2016-04-27 19:04 发表评论
]]>
Redis 代理服务Twemproxy http://www.qpkxbc.shop/stevenjohn/archive/2015/11/03/428041.htmlabinabinTue, 03 Nov 2015 11:30:00 GMThttp://www.qpkxbc.shop/stevenjohn/archive/2015/11/03/428041.htmlhttp://www.qpkxbc.shop/stevenjohn/comments/428041.htmlhttp://www.qpkxbc.shop/stevenjohn/archive/2015/11/03/428041.html#Feedback0http://www.qpkxbc.shop/stevenjohn/comments/commentRss/428041.htmlhttp://www.qpkxbc.shop/stevenjohn/services/trackbacks/428041.html

1、twemproxy explore

      当我们有大量 Redis ?Memcached 的时候,通常只能通过客户端的一些数据分配算法(比如一致性哈希)Q?/span>来实现集存储的Ҏ?/span>虽然Redis 2.6版本已经发布Redis ClusterQ但q不是很成熟适用正式生环境?span style="color:#333333; font-family:Helvetica,Tahoma,Arial,sans-serif; font-size:14px; line-height:25.200000762939453px"> Redis ?Cluster Ҏq没有正式推Z前,我们通过 Proxy 的方式来实现集群存储?/span>

       TwitterQ世界最大的Redis集群之一部v在Twitter用于为用h供时间u数据。Twitter Open Source部门提供了Twemproxy?/span>

     Twemproxy,也叫nutcraker。是一个twtter开源的一个redis和memcache代理服务器?redis作ؓ一个高效的~存服务器,非常h应用价倹{但是当使用比较多的时候,希望可以通过某种方式 l一q?/span>行管理。避免每个应用每个客L理q接的松散性。同时在一定程度上变得可以控制?/p>

      Twemproxy是一个快速的单线E代理程序,支持Memcached ASCII协议和更新的Redis协议Q?/span>

     它全部用C写成Q用Apache 2.0 License授权。项目在Linux上可以工作,而在OSX上无法编译,因ؓ它依赖了epoll API.

      Twemproxy 通过引入一个代理层Q可以将其后端的多台 Redis ?Memcached 实例q行l一理与分配,使应用程序只需要在 Twemproxy 上进行操作,而不用关心后面具体有多少个真实的 Redis ?Memcached 存储?/span> 

2?/span>twemproxyҎ:

    • 支持p|节点自动删除

      • 可以讄重新q接该节点的旉
      • 可以讄q接多少ơ之后删除该节点
      • 该方式适合作ؓcache存储
    • 支持讄HashTag

      • 通过HashTag可以自己讑֮两个KEYhash到同一个实例上厅R?/li>
    • 减少与redis的直接连接数

      • 保持与redis的长q接
      • 可设|代理与后台每个redisq接的数?/li>
    • 自动分片到后端多个redis实例?/p>

      • 多种hash法Q?span style="font-family:Verdana,Arial,Helvetica,sans-serif; font-size:14px; line-height:25px">能够使用不同的策略和散列函数支持一致性hash?/span>
      • 可以讄后端实例的权?/li>
    • 避免单点问题

      • 可以q部v多个代理?client自动选择可用的一?/li>
    • 支持redis pipelining request

           支持h的流式与批处理,降低来回的消?/span>

    • 支持状态监?/p>

      • 可设|状态监控ip和端口,讉Kip和端口可以得C个json格式的状态信息串
      • 可设|监控信息刷新间隔时?/li>
    • 高吞吐量

      • q接复用Q内存复用?/li>
      • 多个连接请求,l成reids pipeliningl一向redish?/li>

     另外可以修改redis的源代码Q抽取出redis中的前半部分Q作Z个中间代理层。最l都是通过linux下的epoll 事g机制提高q发效率Q其中nutcraker本n也是使用epoll的事件机制。ƈ且在性能试上的表现非常?/p>

3、twemproxy问题与不?/span>


Twemproxy ׃其自w原理限Ӟ有一些不之处,如: 
  • 不支持针对多个值的操作Q比如取sets的子交ƈ补等QMGET ?DEL 除外Q?/span>
  • 不支持Redis的事务操?/span>
  • 出错提示q不够完?/span>
  • 也不支持select操作

4、安装与配置 

具体的安装步骤可用查看githubQ?a href="https://github.com/twitter/twemproxy" target="_blank">https://github.com/twitter/twemproxy
Twemproxy 的安装,主要命o如下Q?nbsp;
apt-get install automake  
apt-get install libtool  
git clone git://github.com/twitter/twemproxy.git  
cd twemproxy  
autoreconf -fvi  
./configure --enable-debug=log  
make  
src/nutcracker -h

通过上面的命令就安装好了,然后是具体的配置Q下面是一个典型的配置 
    redis1:  
      listen: 127.0.0.1:6379 #使用哪个端口启动Twemproxy  
      redis: true #是否是Redis的proxy  
      hash: fnv1a_64 #指定具体的hash函数  
      distribution: ketama #具体的hash法  
      auto_eject_hosts: true #是否在结Ҏ法响应的时候时摘除结? 
      timeout: 400 #时旉Q毫U)  
      server_retry_timeout: 2000 #重试的时_毫秒Q? 
      server_failure_limit: 1 #l点故障多少ơ就摘除掉  
      servers: #下面表示所有的Redis节点QIP:端口?权重Q? 
       - 127.0.0.1:6380:1  
       - 127.0.0.1:6381:1  
       - 127.0.0.1:6382:1  
      
    redis2:  
      listen: 0.0.0.0:10000  
      redis: true  
      hash: fnv1a_64  
      distribution: ketama  
      auto_eject_hosts: false  
      timeout: 400  
      servers:  
       - 127.0.0.1:6379:1  
       - 127.0.0.1:6380:1  
       - 127.0.0.1:6381:1  
       - 127.0.0.1:6382:1 

你可以同时开启多?Twemproxy 实例Q它们都可以q行dQ这样你的应用程序就可以完全避免所谓的单点故障?


http://blog.csdn.net/hguisu/article/details/9174459/


abin 2015-11-03 19:30 发表评论
]]>
1һ152ͼ 516Ϸ 11ѡ5ӽʱ ɽʱʱ11ѡ5 12н ͼ ʮһѡ影 ָ 679Ʊ׿ 人齫