Commit c4890f04 authored by AlexStocks's avatar AlexStocks

Add: dev script and conf files

parent 6b2ba37d
......@@ -10,6 +10,10 @@
## develop history ##
---
- 2018/06/24
> improvement
* delete this, using name abbreviation instead.
- 2018/03/17
> improvement
* use getty 0.8.2
......
......@@ -40,99 +40,99 @@ type EchoClient struct {
gettyClient getty.Client
}
func (this *EchoClient) isAvailable() bool {
if this.selectSession() == nil {
func (c *EchoClient) isAvailable() bool {
if c.selectSession() == nil {
return false
}
return true
}
func (this *EchoClient) close() {
client.lock.Lock()
if client.gettyClient != nil {
for _, s := range this.sessions {
func (c *EchoClient) close() {
c.lock.Lock()
defer c.lock.Unlock()
if c.gettyClient != nil {
for _, s := range c.sessions {
log.Info("close client session{%s, last active:%s, request number:%d}",
s.session.Stat(), s.session.GetActive().String(), s.reqNum)
s.session.Close()
}
client.gettyClient.Close()
client.gettyClient = nil
client.sessions = client.sessions[:0]
c.gettyClient.Close()
c.gettyClient = nil
c.sessions = c.sessions[:0]
}
client.lock.Unlock()
}
func (this *EchoClient) selectSession() getty.Session {
func (c *EchoClient) selectSession() getty.Session {
// get route server session
this.lock.RLock()
defer this.lock.RUnlock()
count := len(this.sessions)
c.lock.RLock()
defer c.lock.RUnlock()
count := len(c.sessions)
if count == 0 {
log.Info("client session array is nil...")
return nil
}
return this.sessions[rand.Int31n(int32(count))].session
return c.sessions[rand.Int31n(int32(count))].session
}
func (this *EchoClient) addSession(session getty.Session) {
func (c *EchoClient) addSession(session getty.Session) {
log.Debug("add session{%s}", session.Stat())
if session == nil {
return
}
this.lock.Lock()
this.sessions = append(this.sessions, &clientEchoSession{session: session})
this.lock.Unlock()
c.lock.Lock()
c.sessions = append(c.sessions, &clientEchoSession{session: session})
c.lock.Unlock()
}
func (this *EchoClient) removeSession(session getty.Session) {
func (c *EchoClient) removeSession(session getty.Session) {
if session == nil {
return
}
this.lock.Lock()
c.lock.Lock()
for i, s := range this.sessions {
for i, s := range c.sessions {
if s.session == session {
this.sessions = append(this.sessions[:i], this.sessions[i+1:]...)
c.sessions = append(c.sessions[:i], c.sessions[i+1:]...)
log.Debug("delete session{%s}, its index{%d}", session.Stat(), i)
break
}
}
log.Info("after remove session{%s}, left session number:%d", session.Stat(), len(this.sessions))
log.Info("after remove session{%s}, left session number:%d", session.Stat(), len(c.sessions))
this.lock.Unlock()
c.lock.Unlock()
}
func (this *EchoClient) updateSession(session getty.Session) {
func (c *EchoClient) updateSession(session getty.Session) {
if session == nil {
return
}
this.lock.Lock()
c.lock.Lock()
for i, s := range this.sessions {
for i, s := range c.sessions {
if s.session == session {
this.sessions[i].reqNum++
c.sessions[i].reqNum++
break
}
}
this.lock.Unlock()
c.lock.Unlock()
}
func (this *EchoClient) getClientEchoSession(session getty.Session) (clientEchoSession, error) {
func (c *EchoClient) getClientEchoSession(session getty.Session) (clientEchoSession, error) {
var (
err error
echoSession clientEchoSession
)
this.lock.Lock()
c.lock.Lock()
err = errSessionNotExist
for _, s := range this.sessions {
for _, s := range c.sessions {
if s.session == session {
echoSession = *s
err = nil
......@@ -140,12 +140,12 @@ func (this *EchoClient) getClientEchoSession(session getty.Session) (clientEchoS
}
}
this.lock.Unlock()
c.lock.Unlock()
return echoSession, err
}
func (this *EchoClient) heartbeat(session getty.Session) {
func (c *EchoClient) heartbeat(session getty.Session) {
var pkg EchoPackage
pkg.H.Magic = echoPkgMagic
pkg.H.LogID = (uint32)(src.Int63())
......@@ -159,6 +159,6 @@ func (this *EchoClient) heartbeat(session getty.Session) {
log.Warn("session.WritePkg(session{%s}, pkg{%s}) = error{%v}", session.Stat(), pkg, err)
session.Close()
this.removeSession(session)
c.removeSession(session)
}
}
......@@ -22,8 +22,8 @@ import (
)
const (
APP_CONF_FILE string = "APP_CONF_FILE"
APP_LOG_CONF_FILE string = "APP_LOG_CONF_FILE"
APP_CONF_FILE = "APP_CONF_FILE"
APP_LOG_CONF_FILE = "APP_LOG_CONF_FILE"
)
var (
......@@ -139,7 +139,7 @@ func initConf() {
panic(fmt.Sprintf("time.ParseDuration(WaitTimeout{%#v}) = error{%v}", conf.GettySessionParam.WaitTimeout, err))
return
}
// gxlog.Info("config{%#v}\n", conf)
// gxlog.CInfo("config{%#v}\n", conf)
// log
confFile = os.Getenv(APP_LOG_CONF_FILE)
......
......@@ -87,29 +87,29 @@ type EchoPackage struct {
B string
}
func (this EchoPackage) String() string {
func (p EchoPackage) String() string {
return fmt.Sprintf("log id:%d, sequence:%d, command:%s, echo string:%s",
this.H.LogID, this.H.Sequence, (echoCommand(this.H.Command)).String(), this.B)
p.H.LogID, p.H.Sequence, (echoCommand(p.H.Command)).String(), p.B)
}
func (this EchoPackage) Marshal() (*bytes.Buffer, error) {
func (p EchoPackage) Marshal() (*bytes.Buffer, error) {
var (
err error
buf *bytes.Buffer
)
buf = &bytes.Buffer{}
err = binary.Write(buf, binary.LittleEndian, this.H)
err = binary.Write(buf, binary.LittleEndian, p.H)
if err != nil {
return nil, err
}
buf.WriteByte((byte)(len(this.B)))
buf.WriteString(this.B)
buf.WriteByte((byte)(len(p.B)))
buf.WriteString(p.B)
return buf, nil
}
func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
func (p *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
var (
err error
len byte
......@@ -120,18 +120,18 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
}
// header
err = binary.Read(buf, binary.LittleEndian, &(this.H))
err = binary.Read(buf, binary.LittleEndian, &(p.H))
if err != nil {
return 0, err
}
if this.H.Magic != echoPkgMagic {
log.Error("@this.H.Magic{%x}, right magic{%x}", this.H.Magic, echoPkgMagic)
if p.H.Magic != echoPkgMagic {
log.Error("@p.H.Magic{%x}, right magic{%x}", p.H.Magic, echoPkgMagic)
return 0, ErrIllegalMagic
}
if buf.Len() < (int)(this.H.Len) {
if buf.Len() < (int)(p.H.Len) {
return 0, ErrNotEnoughStream
}
if maxEchoStringLen < this.H.Len-1 {
if maxEchoStringLen < p.H.Len-1 {
return 0, ErrTooLargePackage
}
......@@ -139,7 +139,7 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
if err != nil {
return 0, nil
}
this.B = (string)(buf.Next((int)(len)))
p.B = (string)(buf.Next((int)(len)))
return (int)(this.H.Len) + echoPkgHeaderLen, nil
return (int)(p.H.Len) + echoPkgHeaderLen, nil
}
......@@ -32,30 +32,29 @@ type clientEchoSession struct {
reqNum int32
}
type EchoMessageHandler struct {
}
type EchoMessageHandler struct{}
func newEchoMessageHandler() *EchoMessageHandler {
return &EchoMessageHandler{}
}
func (this *EchoMessageHandler) OnOpen(session getty.Session) error {
func (h *EchoMessageHandler) OnOpen(session getty.Session) error {
client.addSession(session)
return nil
}
func (this *EchoMessageHandler) OnError(session getty.Session, err error) {
func (h *EchoMessageHandler) OnError(session getty.Session, err error) {
log.Info("session{%s} got error{%v}, will be closed.", session.Stat(), err)
client.removeSession(session)
}
func (this *EchoMessageHandler) OnClose(session getty.Session) {
func (h *EchoMessageHandler) OnClose(session getty.Session) {
log.Info("session{%s} is closing......", session.Stat())
client.removeSession(session)
}
func (this *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}) {
func (h *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}) {
p, ok := pkg.(*EchoPackage)
if !ok {
log.Error("illegal packge{%#v}", pkg)
......@@ -66,7 +65,7 @@ func (this *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}
client.updateSession(session)
}
func (this *EchoMessageHandler) OnCron(session getty.Session) {
func (h *EchoMessageHandler) OnCron(session getty.Session) {
clientEchoSession, err := client.getClientEchoSession(session)
if err != nil {
log.Error("client.getClientSession(session{%s}) = error{%#v}", session.Stat(), err)
......
......@@ -20,14 +20,13 @@ import (
log "github.com/AlexStocks/log4go"
)
type EchoPackageHandler struct {
}
type EchoPackageHandler struct{}
func NewEchoPackageHandler() *EchoPackageHandler {
return &EchoPackageHandler{}
}
func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
func (h *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
var (
err error
len int
......@@ -48,7 +47,7 @@ func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}
return &pkg, len, nil
}
func (this *EchoPackageHandler) Write(ss getty.Session, pkg interface{}) error {
func (h *EchoPackageHandler) Write(ss getty.Session, pkg interface{}) error {
var (
ok bool
err error
......
......@@ -10,5 +10,5 @@
package main
var (
Version = "0.8.2"
Version = "0.8.4"
)
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=linux
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=darwin
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=windows
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
# toml configure file
# toml中key的首字母可以小写,但是对应的golang中的struct成员首字母必须大写
AppName = "ECHO-CLIENT"
# host
LocalHost = "127.0.0.1"
# server
# ServerHost = "192.168.8.3"
ServerHost = "127.0.0.1"
ServerPort = 10000
ProfilePort = 10080
# connection pool
# 连接池连接数目
ConnectionNum = 2
# session
# client与server之间连接的心跳周期
HeartbeatPeriod = "10s"
# client与server之间连接的超时时间
SessionTimeout = "20s"
# client
# client echo request string
EchoString = "Hello, getty!"
# 发送echo请求次数
EchoTimes = 10000
# app fail fast
FailFastTimeout = "3s"
# tcp
[GettySessionParam]
CompressEncoding = true
TcpNoDelay = true
TcpKeepAlive = true
KeepAlivePeriod = "120s"
TcpRBufSize = 262144
TcpWBufSize = 65536
PkgRQSize = 512
PkgWQSize = 256
TcpReadTimeout = "1s"
TcpWriteTimeout = "5s"
WaitTimeout = "1s"
MaxMsgLen = 128
SessionName = "echo-client"
<logging>
<filter enabled="true">
<tag>stdout</tag>
<type>console</type>
<!-- level is (:?FINEST|FINE|DEBUG|TRACE|INFO|WARNING|ERROR) -->
<level>DEBUG</level>
</filter>
<filter enabled="false">
<tag>debug_file</tag>
<type>file</type>
<level>DEBUG</level>
<property name="filename">logs/debug.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>info_file</tag>
<type>file</type>
<level>INFO</level>
<property name="filename">logs/info.log</property>
<!--
%T - Time (15:04:05 MST)
%t - Time (15:04)
%D - Date (2006/01/02)
%d - Date (01/02/06)
%L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT)
%S - Source
%M - Message
It ignores unknown format strings (and removes them)
Recommended: "[%D %T] [%L] (%S) %M"
-->
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>warn_file</tag>
<type>file</type>
<level>WARNING</level>
<property name="filename">logs/warn.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>error_file</tag>
<type>file</type>
<level>ERROR</level>
<property name="filename">logs/error.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
</logging>
......@@ -22,8 +22,8 @@ import (
)
const (
APP_CONF_FILE string = "APP_CONF_FILE"
APP_LOG_CONF_FILE string = "APP_LOG_CONF_FILE"
APP_CONF_FILE = "APP_CONF_FILE"
APP_LOG_CONF_FILE = "APP_LOG_CONF_FILE"
)
var (
......
......@@ -87,29 +87,29 @@ type EchoPackage struct {
B string
}
func (this EchoPackage) String() string {
func (p EchoPackage) String() string {
return fmt.Sprintf("log id:%d, sequence:%d, command:%s, echo string:%s",
this.H.LogID, this.H.Sequence, (echoCommand(this.H.Command)).String(), this.B)
p.H.LogID, p.H.Sequence, (echoCommand(p.H.Command)).String(), p.B)
}
func (this EchoPackage) Marshal() (*bytes.Buffer, error) {
func (p EchoPackage) Marshal() (*bytes.Buffer, error) {
var (
err error
buf *bytes.Buffer
)
buf = &bytes.Buffer{}
err = binary.Write(buf, binary.LittleEndian, this.H)
err = binary.Write(buf, binary.LittleEndian, p.H)
if err != nil {
return nil, err
}
buf.WriteByte((byte)(len(this.B)))
buf.WriteString(this.B)
buf.WriteByte((byte)(len(p.B)))
buf.WriteString(p.B)
return buf, nil
}
func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
func (p *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
var (
err error
len byte
......@@ -120,19 +120,19 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
}
// header
err = binary.Read(buf, binary.LittleEndian, &(this.H))
err = binary.Read(buf, binary.LittleEndian, &(p.H))
if err != nil {
return 0, err
}
if this.H.Magic != echoPkgMagic {
log.Error("@this.H.Magic{%x}, right magic{%x}", this.H.Magic, echoPkgMagic)
if p.H.Magic != echoPkgMagic {
log.Error("@p.H.Magic{%x}, right magic{%x}", p.H.Magic, echoPkgMagic)
return 0, ErrIllegalMagic
}
if buf.Len() < (int)(this.H.Len) {
if buf.Len() < (int)(p.H.Len) {
return 0, ErrNotEnoughStream
}
// 防止恶意客户端把这个字段设置过大导致服务端死等或者服务端在准备对应的缓冲区时内存崩溃
if maxEchoStringLen < this.H.Len-1 {
if maxEchoStringLen < p.H.Len-1 {
return 0, ErrTooLargePackage
}
......@@ -140,7 +140,7 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
if err != nil {
return 0, nil
}
this.B = (string)(buf.Next((int)(len)))
p.B = (string)(buf.Next((int)(len)))
return (int)(this.H.Len) + echoPkgHeaderLen, nil
return (int)(p.H.Len) + echoPkgHeaderLen, nil
}
......@@ -38,7 +38,7 @@ type PackageHandler interface {
type HeartbeatHandler struct{}
func (this *HeartbeatHandler) Handle(session getty.Session, pkg *EchoPackage) error {
func (h *HeartbeatHandler) Handle(session getty.Session, pkg *EchoPackage) error {
log.Debug("get echo heartbeat package{%s}", pkg)
var rspPkg EchoPackage
......@@ -55,7 +55,7 @@ func (this *HeartbeatHandler) Handle(session getty.Session, pkg *EchoPackage) er
type MessageHandler struct{}
func (this *MessageHandler) Handle(session getty.Session, pkg *EchoPackage) error {
func (h *MessageHandler) Handle(session getty.Session, pkg *EchoPackage) error {
log.Debug("get echo package{%s}", pkg)
// write echo message handle logic here.
return session.WritePkg(pkg, WritePkgTimeout)
......@@ -86,83 +86,83 @@ func newEchoMessageHandler() *EchoMessageHandler {
return &EchoMessageHandler{sessionMap: make(map[getty.Session]*clientEchoSession), handlers: handlers}
}
func (this *EchoMessageHandler) OnOpen(session getty.Session) error {
func (h *EchoMessageHandler) OnOpen(session getty.Session) error {
var (
err error
)
this.rwlock.RLock()
if conf.SessionNumber < len(this.sessionMap) {
h.rwlock.RLock()
if conf.SessionNumber < len(h.sessionMap) {
err = errTooManySessions
}
this.rwlock.RUnlock()
h.rwlock.RUnlock()
if err != nil {
return err
}
log.Info("got session:%s", session.Stat())
this.rwlock.Lock()
this.sessionMap[session] = &clientEchoSession{session: session}
this.rwlock.Unlock()
h.rwlock.Lock()
h.sessionMap[session] = &clientEchoSession{session: session}
h.rwlock.Unlock()
return nil
}
func (this *EchoMessageHandler) OnError(session getty.Session, err error) {
func (h *EchoMessageHandler) OnError(session getty.Session, err error) {
log.Info("session{%s} got error{%v}, will be closed.", session.Stat(), err)
this.rwlock.Lock()
delete(this.sessionMap, session)
this.rwlock.Unlock()
h.rwlock.Lock()
delete(h.sessionMap, session)
h.rwlock.Unlock()
}
func (this *EchoMessageHandler) OnClose(session getty.Session) {
func (h *EchoMessageHandler) OnClose(session getty.Session) {
log.Info("session{%s} is closing......", session.Stat())
this.rwlock.Lock()
delete(this.sessionMap, session)
this.rwlock.Unlock()
h.rwlock.Lock()
delete(h.sessionMap, session)
h.rwlock.Unlock()
}
func (this *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}) {
func (h *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}) {
p, ok := pkg.(*EchoPackage)
if !ok {
log.Error("illegal packge{%#v}", pkg)
return
}
handler, ok := this.handlers[p.H.Command]
handler, ok := h.handlers[p.H.Command]
if !ok {
log.Error("illegal command{%d}", p.H.Command)
return
}
err := handler.Handle(session, p)
if err != nil {
this.rwlock.Lock()
if _, ok := this.sessionMap[session]; ok {
this.sessionMap[session].active = time.Now()
this.sessionMap[session].reqNum++
h.rwlock.Lock()
if _, ok := h.sessionMap[session]; ok {
h.sessionMap[session].active = time.Now()
h.sessionMap[session].reqNum++
}
this.rwlock.Unlock()
h.rwlock.Unlock()
}
}
func (this *EchoMessageHandler) OnCron(session getty.Session) {
func (h *EchoMessageHandler) OnCron(session getty.Session) {
var (
flag bool
active time.Time
)
this.rwlock.RLock()
if _, ok := this.sessionMap[session]; ok {
h.rwlock.RLock()
if _, ok := h.sessionMap[session]; ok {
active = session.GetActive()
if conf.sessionTimeout.Nanoseconds() < time.Since(active).Nanoseconds() {
flag = true
log.Warn("session{%s} timeout{%s}, reqNum{%d}",
session.Stat(), time.Since(active).String(), this.sessionMap[session].reqNum)
session.Stat(), time.Since(active).String(), h.sessionMap[session].reqNum)
}
}
this.rwlock.RUnlock()
h.rwlock.RUnlock()
if flag {
this.rwlock.Lock()
delete(this.sessionMap, session)
this.rwlock.Unlock()
h.rwlock.Lock()
delete(h.sessionMap, session)
h.rwlock.Unlock()
session.Close()
}
}
......@@ -27,7 +27,7 @@ func NewEchoPackageHandler() *EchoPackageHandler {
return &EchoPackageHandler{}
}
func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
func (h *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
var (
err error
len int
......@@ -48,7 +48,7 @@ func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}
return &pkg, len, nil
}
func (this *EchoPackageHandler) Write(ss getty.Session, pkg interface{}) error {
func (h *EchoPackageHandler) Write(ss getty.Session, pkg interface{}) error {
var (
ok bool
err error
......
......@@ -10,5 +10,5 @@
package main
var (
Version = "0.8.2"
Version = "0.8.4"
)
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=linux
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=darwin
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=windows
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
# toml configure file
# toml中key的首字母可以小写,但是对应的golang中的struct成员首字母必须大写
AppName = "ECHO-SERVER"
Host = "127.0.0.1"
# Host = "192.168.35.1"
# Host = "192.168.8.3"
Ports = ["10000", "20000"]
ProfilePort = 10086
# session
# client与server之间连接的超时时间
SessionTimeout = "20s"
SessionNumber = 700
# app
FailFastTimeout = "3s"
# tcp
[GettySessionParam]
CompressEncoding = true
TcpNoDelay = true
TcpKeepAlive = true
KeepAlivePeriod = "120s"
TcpRBufSize = 262144
TcpWBufSize = 524288
PkgRQSize = 1024
PkgWQSize = 512
TcpReadTimeout = "1s"
TcpWriteTimeout = "5s"
WaitTimeout = "1s"
MaxMsgLen = 128
SessionName = "echo-server"
<logging>
<filter enabled="true">
<tag>stdout</tag>
<type>console</type>
<!-- level is (:?FINEST|FINE|DEBUG|TRACE|INFO|WARNING|ERROR) -->
<level>DEBUG</level>
</filter>
<filter enabled="false">
<tag>debug_file</tag>
<type>file</type>
<level>DEBUG</level>
<property name="filename">logs/debug.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>info_file</tag>
<type>file</type>
<level>INFO</level>
<property name="filename">logs/info.log</property>
<!--
%T - Time (15:04:05 MST)
%t - Time (15:04)
%D - Date (2006/01/02)
%d - Date (01/02/06)
%L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT)
%S - Source
%M - Message
It ignores unknown format strings (and removes them)
Recommended: "[%D %T] [%L] (%S) %M"
-->
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>warn_file</tag>
<type>file</type>
<level>WARNING</level>
<property name="filename">logs/warn.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>error_file</tag>
<type>file</type>
<level>ERROR</level>
<property name="filename">logs/error.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
</logging>
......@@ -10,6 +10,10 @@
## develop history ##
---
- 2018/06/24
> improvement
* delete this, using name abbreviation instead.
- 2018/03/17
> improvement
* set the timeout parameter of WritePkg 0 to send out package asap.
......
......@@ -42,100 +42,100 @@ type EchoClient struct {
serverAddr net.UDPAddr
}
func (this *EchoClient) isAvailable() bool {
if this.selectSession() == nil {
func (c *EchoClient) isAvailable() bool {
if c.selectSession() == nil {
return false
}
return true
}
func (this *EchoClient) close() {
this.lock.Lock()
if this.gettyClient != nil {
for _, s := range this.sessions {
func (c *EchoClient) close() {
c.lock.Lock()
defer c.lock.Unlock()
if c.gettyClient != nil {
for _, s := range c.sessions {
log.Info("close client session{%s, last active:%s, request number:%d}",
s.session.Stat(), s.session.GetActive().String(), s.reqNum)
s.session.Close()
}
this.gettyClient.Close()
this.gettyClient = nil
this.sessions = this.sessions[:0]
c.gettyClient.Close()
c.gettyClient = nil
c.sessions = c.sessions[:0]
}
this.lock.Unlock()
}
func (this *EchoClient) selectSession() getty.Session {
func (c *EchoClient) selectSession() getty.Session {
// get route server session
this.lock.RLock()
defer this.lock.RUnlock()
count := len(this.sessions)
c.lock.RLock()
defer c.lock.RUnlock()
count := len(c.sessions)
if count == 0 {
log.Info("client session array is nil...")
return nil
}
return this.sessions[rand.Int31n(int32(count))].session
return c.sessions[rand.Int31n(int32(count))].session
}
func (this *EchoClient) addSession(session getty.Session) {
func (c *EchoClient) addSession(session getty.Session) {
log.Debug("add session{%s}", session.Stat())
if session == nil {
return
}
this.lock.Lock()
this.sessions = append(this.sessions, &clientEchoSession{session: session})
log.Debug("after add session{%s}, session number:%d", session.Stat(), len(this.sessions))
this.lock.Unlock()
c.lock.Lock()
c.sessions = append(c.sessions, &clientEchoSession{session: session})
log.Debug("after add session{%s}, session number:%d", session.Stat(), len(c.sessions))
c.lock.Unlock()
}
func (this *EchoClient) removeSession(session getty.Session) {
func (c *EchoClient) removeSession(session getty.Session) {
if session == nil {
return
}
this.lock.Lock()
c.lock.Lock()
for i, s := range this.sessions {
for i, s := range c.sessions {
if s.session == session {
this.sessions = append(this.sessions[:i], this.sessions[i+1:]...)
c.sessions = append(c.sessions[:i], c.sessions[i+1:]...)
log.Debug("delete session{%s}, its index{%d}", session.Stat(), i)
break
}
}
log.Info("after remove session{%s}, left session number:%d", session.Stat(), len(this.sessions))
log.Info("after remove session{%s}, left session number:%d", session.Stat(), len(c.sessions))
this.lock.Unlock()
c.lock.Unlock()
}
func (this *EchoClient) updateSession(session getty.Session) {
func (c *EchoClient) updateSession(session getty.Session) {
if session == nil {
return
}
this.lock.Lock()
c.lock.Lock()
for i, s := range this.sessions {
for i, s := range c.sessions {
if s.session == session {
this.sessions[i].reqNum++
c.sessions[i].reqNum++
break
}
}
this.lock.Unlock()
c.lock.Unlock()
}
func (this *EchoClient) getClientEchoSession(session getty.Session) (clientEchoSession, error) {
func (c *EchoClient) getClientEchoSession(session getty.Session) (clientEchoSession, error) {
var (
err error
echoSession clientEchoSession
)
this.lock.Lock()
c.lock.Lock()
err = errSessionNotExist
for _, s := range this.sessions {
for _, s := range c.sessions {
if s.session == session {
echoSession = *s
err = nil
......@@ -143,12 +143,12 @@ func (this *EchoClient) getClientEchoSession(session getty.Session) (clientEchoS
}
}
this.lock.Unlock()
c.lock.Unlock()
return echoSession, err
}
func (this *EchoClient) heartbeat(session getty.Session) {
func (c *EchoClient) heartbeat(session getty.Session) {
var (
err error
pkg EchoPackage
......@@ -164,14 +164,14 @@ func (this *EchoClient) heartbeat(session getty.Session) {
pkg.H.Len = (uint16)(len(pkg.B) + 1)
ctx.Pkg = &pkg
ctx.PeerAddr = &(this.serverAddr)
ctx.PeerAddr = &(c.serverAddr)
//if err := session.WritePkg(ctx, WritePkgTimeout); err != nil {
if err = session.WritePkg(ctx, WritePkgASAP); err != nil {
log.Warn("session.WritePkg(session{%s}, context{%#v}) = error{%v}", session.Stat(), ctx, err)
session.Close()
this.removeSession(session)
c.removeSession(session)
}
log.Debug("session.WritePkg(session{%s}, context{%#v})", session.Stat(), ctx)
}
......@@ -22,8 +22,8 @@ import (
)
const (
APP_CONF_FILE string = "APP_CONF_FILE"
APP_LOG_CONF_FILE string = "APP_LOG_CONF_FILE"
APP_CONF_FILE = "APP_CONF_FILE"
APP_LOG_CONF_FILE = "APP_LOG_CONF_FILE"
)
var (
......
......@@ -87,29 +87,29 @@ type EchoPackage struct {
B string
}
func (this EchoPackage) String() string {
func (p EchoPackage) String() string {
return fmt.Sprintf("log id:%d, sequence:%d, command:%s, echo string:%s",
this.H.LogID, this.H.Sequence, (echoCommand(this.H.Command)).String(), this.B)
p.H.LogID, p.H.Sequence, (echoCommand(p.H.Command)).String(), p.B)
}
func (this EchoPackage) Marshal() (*bytes.Buffer, error) {
func (p EchoPackage) Marshal() (*bytes.Buffer, error) {
var (
err error
buf *bytes.Buffer
)
buf = &bytes.Buffer{}
err = binary.Write(buf, binary.LittleEndian, this.H)
err = binary.Write(buf, binary.LittleEndian, p.H)
if err != nil {
return nil, err
}
buf.WriteByte((byte)(len(this.B)))
buf.WriteString(this.B)
buf.WriteByte((byte)(len(p.B)))
buf.WriteString(p.B)
return buf, nil
}
func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
func (p *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
var (
err error
len byte
......@@ -120,18 +120,18 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
}
// header
err = binary.Read(buf, binary.LittleEndian, &(this.H))
err = binary.Read(buf, binary.LittleEndian, &(p.H))
if err != nil {
return 0, err
}
if this.H.Magic != echoPkgMagic {
log.Error("@this.H.Magic{%x}, right magic{%x}", this.H.Magic, echoPkgMagic)
if p.H.Magic != echoPkgMagic {
log.Error("@p.H.Magic{%x}, right magic{%x}", p.H.Magic, echoPkgMagic)
return 0, ErrIllegalMagic
}
if buf.Len() < (int)(this.H.Len) {
if buf.Len() < (int)(p.H.Len) {
return 0, ErrNotEnoughStream
}
if maxEchoStringLen < this.H.Len-1 {
if maxEchoStringLen < p.H.Len-1 {
return 0, ErrTooLargePackage
}
......@@ -139,11 +139,11 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
if err != nil {
return 0, nil
}
this.B = (string)(buf.Next((int)(len)))
//if strings.HasPrefix(this.B, "Hello, getty!") {
// gxlog.CError("idx:%d, body:%s", idx, this.B)
p.B = (string)(buf.Next((int)(len)))
//if strings.HasPrefix(p.B, "Hello, getty!") {
// gxlog.CError("idx:%d, body:%s", idx, p.B)
// idx++
//}
return (int)(this.H.Len) + echoPkgHeaderLen, nil
return (int)(p.H.Len) + echoPkgHeaderLen, nil
}
......@@ -41,23 +41,23 @@ func newEchoMessageHandler(client *EchoClient) *EchoMessageHandler {
return &EchoMessageHandler{client: client}
}
func (this *EchoMessageHandler) OnOpen(session getty.Session) error {
this.client.addSession(session)
func (h *EchoMessageHandler) OnOpen(session getty.Session) error {
h.client.addSession(session)
return nil
}
func (this *EchoMessageHandler) OnError(session getty.Session, err error) {
func (h *EchoMessageHandler) OnError(session getty.Session, err error) {
log.Info("session{%s} got error{%v}, will be closed.", session.Stat(), err)
this.client.removeSession(session)
h.client.removeSession(session)
}
func (this *EchoMessageHandler) OnClose(session getty.Session) {
func (h *EchoMessageHandler) OnClose(session getty.Session) {
log.Info("session{%s} is closing......", session.Stat())
this.client.removeSession(session)
h.client.removeSession(session)
}
func (this *EchoMessageHandler) OnMessage(session getty.Session, udpCtx interface{}) {
func (h *EchoMessageHandler) OnMessage(session getty.Session, udpCtx interface{}) {
ctx, ok := udpCtx.(getty.UDPContext)
if !ok {
log.Error("illegal UDPContext{%#v}", udpCtx)
......@@ -70,13 +70,12 @@ func (this *EchoMessageHandler) OnMessage(session getty.Session, udpCtx interfac
}
log.Debug("get echo package{%s}", p)
gxlog.CError("session:%s, get echo package{%s}", session.Stat(), p)
this.client.updateSession(session)
h.client.updateSession(session)
}
func (this *EchoMessageHandler) OnCron(session getty.Session) {
clientEchoSession, err := this.client.getClientEchoSession(session)
func (h *EchoMessageHandler) OnCron(session getty.Session) {
clientEchoSession, err := h.client.getClientEchoSession(session)
if err != nil {
log.Error("client.getClientSession(session{%s}) = error{%#v}", session.Stat(), err)
return
......@@ -85,11 +84,11 @@ func (this *EchoMessageHandler) OnCron(session getty.Session) {
log.Warn("session{%s} timeout{%s}, reqNum{%d}",
session.Stat(), time.Since(session.GetActive()).String(), clientEchoSession.reqNum)
// UDP_ENDPOINT session should be long live.
if this.client != &unconnectedClient {
this.client.removeSession(session)
if h.client != &unconnectedClient {
h.client.removeSession(session)
}
return
}
this.client.heartbeat(session)
h.client.heartbeat(session)
}
......@@ -27,7 +27,7 @@ func NewEchoPackageHandler() *EchoPackageHandler {
return &EchoPackageHandler{}
}
func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
func (h *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
var (
err error
len int
......@@ -48,7 +48,7 @@ func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}
return &pkg, len, nil
}
func (this *EchoPackageHandler) Write(ss getty.Session, udpCtx interface{}) error {
func (h *EchoPackageHandler) Write(ss getty.Session, udpCtx interface{}) error {
var (
ok bool
err error
......
......@@ -10,5 +10,5 @@
package main
var (
Version = "0.8.2"
Version = "0.8.4"
)
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=linux
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=darwin
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=windows
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
# toml configure file
# toml中key的首字母可以小写,但是对应的golang中的struct成员首字母必须大写
AppName = "ECHO-CLIENT"
# host
LocalHost = "127.0.0.1"
# server
# ServerHost = "192.168.8.3"
ServerHost = "127.0.0.1"
ServerPort = 10000
ProfilePort = 10080
# connection pool
# 连接池连接数目
ConnectionNum = 2
# session
# client与server之间连接的心跳周期
HeartbeatPeriod = "10s"
# client与server之间连接的超时时间
SessionTimeout = "20s"
# client
# client echo request string
EchoString = "Hello, getty!"
# 发送echo请求次数
EchoTimes = 100000
# app fail fast
FailFastTimeout = "3s"
# tcp
[GettySessionParam]
CompressEncoding = true
UdpRBufSize = 262144
UdpWBufSize = 65536
PkgRQSize = 512
PkgWQSize = 256
UdpReadTimeout = "10s"
UdpWriteTimeout = "5s"
WaitTimeout = "1s"
MaxMsgLen = 128
SessionName = "echo-client"
<logging>
<filter enabled="true">
<tag>stdout</tag>
<type>console</type>
<!-- level is (:?FINEST|FINE|DEBUG|TRACE|INFO|WARNING|ERROR) -->
<level>DEBUG</level>
</filter>
<filter enabled="true">
<tag>debug_file</tag>
<type>file</type>
<level>DEBUG</level>
<property name="filename">logs/debug.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>info_file</tag>
<type>file</type>
<level>INFO</level>
<property name="filename">logs/info.log</property>
<!--
%T - Time (15:04:05 MST)
%t - Time (15:04)
%D - Date (2006/01/02)
%d - Date (01/02/06)
%L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT)
%S - Source
%M - Message
It ignores unknown format strings (and removes them)
Recommended: "[%D %T] [%L] (%S) %M"
-->
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>warn_file</tag>
<type>file</type>
<level>WARNING</level>
<property name="filename">logs/warn.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>error_file</tag>
<type>file</type>
<level>ERROR</level>
<property name="filename">logs/error.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
</logging>
......@@ -22,8 +22,8 @@ import (
)
const (
APP_CONF_FILE string = "APP_CONF_FILE"
APP_LOG_CONF_FILE string = "APP_LOG_CONF_FILE"
APP_CONF_FILE = "APP_CONF_FILE"
APP_LOG_CONF_FILE = "APP_LOG_CONF_FILE"
)
var (
......
......@@ -87,29 +87,29 @@ type EchoPackage struct {
B string
}
func (this EchoPackage) String() string {
func (p EchoPackage) String() string {
return fmt.Sprintf("log id:%d, sequence:%d, command:%s, echo string:%s",
this.H.LogID, this.H.Sequence, (echoCommand(this.H.Command)).String(), this.B)
p.H.LogID, p.H.Sequence, (echoCommand(p.H.Command)).String(), p.B)
}
func (this EchoPackage) Marshal() (*bytes.Buffer, error) {
func (p EchoPackage) Marshal() (*bytes.Buffer, error) {
var (
err error
buf *bytes.Buffer
)
buf = &bytes.Buffer{}
err = binary.Write(buf, binary.LittleEndian, this.H)
err = binary.Write(buf, binary.LittleEndian, p.H)
if err != nil {
return nil, err
}
buf.WriteByte((byte)(len(this.B)))
buf.WriteString(this.B)
buf.WriteByte((byte)(len(p.B)))
buf.WriteString(p.B)
return buf, nil
}
func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
func (p *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
var (
err error
len byte
......@@ -120,19 +120,19 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
}
// header
err = binary.Read(buf, binary.LittleEndian, &(this.H))
err = binary.Read(buf, binary.LittleEndian, &(p.H))
if err != nil {
return 0, err
}
if this.H.Magic != echoPkgMagic {
log.Error("@this.H.Magic{%x}, right magic{%x}", this.H.Magic, echoPkgMagic)
if p.H.Magic != echoPkgMagic {
log.Error("@p.H.Magic{%x}, right magic{%x}", p.H.Magic, echoPkgMagic)
return 0, ErrIllegalMagic
}
if buf.Len() < (int)(this.H.Len) {
if buf.Len() < (int)(p.H.Len) {
return 0, ErrNotEnoughStream
}
// 防止恶意客户端把这个字段设置过大导致服务端死等或者服务端在准备对应的缓冲区时内存崩溃
if maxEchoStringLen < this.H.Len-1 {
if maxEchoStringLen < p.H.Len-1 {
return 0, ErrTooLargePackage
}
......@@ -140,7 +140,7 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
if err != nil {
return 0, nil
}
this.B = (string)(buf.Next((int)(len)))
p.B = (string)(buf.Next((int)(len)))
return (int)(this.H.Len) + echoPkgHeaderLen, nil
return (int)(p.H.Len) + echoPkgHeaderLen, nil
}
......@@ -40,7 +40,7 @@ type PackageHandler interface {
type HeartbeatHandler struct{}
func (this *HeartbeatHandler) Handle(session getty.Session, ctx getty.UDPContext) error {
func (h *HeartbeatHandler) Handle(session getty.Session, ctx getty.UDPContext) error {
var (
ok bool
pkg *EchoPackage
......@@ -66,7 +66,7 @@ func (this *HeartbeatHandler) Handle(session getty.Session, ctx getty.UDPContext
type MessageHandler struct{}
func (this *MessageHandler) Handle(session getty.Session, ctx getty.UDPContext) error {
func (h *MessageHandler) Handle(session getty.Session, ctx getty.UDPContext) error {
log.Debug("get echo ctx{%#v}", ctx)
// write echo message handle logic here.
// return session.WritePkg(ctx, WritePkgTimeout)
......@@ -98,42 +98,42 @@ func newEchoMessageHandler() *EchoMessageHandler {
return &EchoMessageHandler{sessionMap: make(map[getty.Session]*clientEchoSession), handlers: handlers}
}
func (this *EchoMessageHandler) OnOpen(session getty.Session) error {
func (h *EchoMessageHandler) OnOpen(session getty.Session) error {
var (
err error
)
this.rwlock.RLock()
if conf.SessionNumber < len(this.sessionMap) {
h.rwlock.RLock()
if conf.SessionNumber < len(h.sessionMap) {
err = errTooManySessions
}
this.rwlock.RUnlock()
h.rwlock.RUnlock()
if err != nil {
return err
}
log.Info("got session:%s", session.Stat())
this.rwlock.Lock()
this.sessionMap[session] = &clientEchoSession{session: session}
this.rwlock.Unlock()
h.rwlock.Lock()
h.sessionMap[session] = &clientEchoSession{session: session}
h.rwlock.Unlock()
return nil
}
func (this *EchoMessageHandler) OnError(session getty.Session, err error) {
func (h *EchoMessageHandler) OnError(session getty.Session, err error) {
log.Info("session{%s} got error{%v}, will be closed.", session.Stat(), err)
this.rwlock.Lock()
delete(this.sessionMap, session)
this.rwlock.Unlock()
h.rwlock.Lock()
delete(h.sessionMap, session)
h.rwlock.Unlock()
}
func (this *EchoMessageHandler) OnClose(session getty.Session) {
func (h *EchoMessageHandler) OnClose(session getty.Session) {
log.Info("session{%s} is closing......", session.Stat())
this.rwlock.Lock()
delete(this.sessionMap, session)
this.rwlock.Unlock()
h.rwlock.Lock()
delete(h.sessionMap, session)
h.rwlock.Unlock()
}
func (this *EchoMessageHandler) OnMessage(session getty.Session, udpCtx interface{}) {
func (h *EchoMessageHandler) OnMessage(session getty.Session, udpCtx interface{}) {
ctx, ok := udpCtx.(getty.UDPContext)
if !ok {
log.Error("illegal UDPContext{%#v}", udpCtx)
......@@ -146,42 +146,42 @@ func (this *EchoMessageHandler) OnMessage(session getty.Session, udpCtx interfac
return
}
handler, ok := this.handlers[p.H.Command]
handler, ok := h.handlers[p.H.Command]
if !ok {
log.Error("illegal command{%d}", p.H.Command)
return
}
err := handler.Handle(session, ctx)
if err != nil {
this.rwlock.Lock()
if _, ok := this.sessionMap[session]; ok {
this.sessionMap[session].active = time.Now()
this.sessionMap[session].reqNum++
h.rwlock.Lock()
if _, ok := h.sessionMap[session]; ok {
h.sessionMap[session].active = time.Now()
h.sessionMap[session].reqNum++
}
this.rwlock.Unlock()
h.rwlock.Unlock()
}
}
func (this *EchoMessageHandler) OnCron(session getty.Session) {
func (h *EchoMessageHandler) OnCron(session getty.Session) {
var (
//flag bool
active time.Time
)
this.rwlock.RLock()
if _, ok := this.sessionMap[session]; ok {
h.rwlock.RLock()
if _, ok := h.sessionMap[session]; ok {
active = session.GetActive()
if conf.sessionTimeout.Nanoseconds() < time.Since(active).Nanoseconds() {
//flag = true
log.Error("session{%s} timeout{%s}, reqNum{%d}",
session.Stat(), time.Since(active).String(), this.sessionMap[session].reqNum)
session.Stat(), time.Since(active).String(), h.sessionMap[session].reqNum)
}
}
this.rwlock.RUnlock()
h.rwlock.RUnlock()
// udp session是根据本地udp socket fd生成的,如果关闭则连同socket也一同关闭了
//if flag {
// this.rwlock.Lock()
// delete(this.sessionMap, session)
// this.rwlock.Unlock()
// h.rwlock.Lock()
// delete(h.sessionMap, session)
// h.rwlock.Unlock()
// session.Close()
//}
}
......@@ -28,7 +28,7 @@ func NewEchoPackageHandler() *EchoPackageHandler {
return &EchoPackageHandler{}
}
func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
func (h *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
var (
err error
len int
......@@ -49,7 +49,7 @@ func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}
return &pkg, len, nil
}
func (this *EchoPackageHandler) Write(ss getty.Session, udpCtx interface{}) error {
func (h *EchoPackageHandler) Write(ss getty.Session, udpCtx interface{}) error {
var (
ok bool
err error
......
......@@ -10,5 +10,5 @@
package main
var (
Version = "0.8.2"
Version = "0.8.4"
)
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=linux
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=darwin
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=windows
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
# toml configure file
# toml中key的首字母可以小写,但是对应的golang中的struct成员首字母必须大写
AppName = "ECHO-SERVER"
Host = "127.0.0.1"
# Host = "192.168.35.1"
# Host = "192.168.8.3"
# Ports = ["10000", "20000"]
Ports = ["10000"]
ProfilePort = 10086
# session
# client与server之间连接的超时时间
SessionTimeout = "20s"
SessionNumber = 700
# app
FailFastTimeout = "3s"
# tcp
[GettySessionParam]
CompressEncoding = true
UdpRBufSize = 262144
UdpWBufSize = 524288
PkgRQSize = 1024
PkgWQSize = 512
UdpReadTimeout = "10s"
UdpWriteTimeout = "5s"
WaitTimeout = "1s"
MaxMsgLen = 128
SessionName = "echo-server"
<logging>
<filter enabled="true">
<tag>stdout</tag>
<type>console</type>
<!-- level is (:?FINEST|FINE|DEBUG|TRACE|INFO|WARNING|ERROR) -->
<level>DEBUG</level>
</filter>
<filter enabled="false">
<tag>debug_file</tag>
<type>file</type>
<level>DEBUG</level>
<property name="filename">logs/debug.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>info_file</tag>
<type>file</type>
<level>INFO</level>
<property name="filename">logs/info.log</property>
<!--
%T - Time (15:04:05 MST)
%t - Time (15:04)
%D - Date (2006/01/02)
%d - Date (01/02/06)
%L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT)
%S - Source
%M - Message
It ignores unknown format strings (and removes them)
Recommended: "[%D %T] [%L] (%S) %M"
-->
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>warn_file</tag>
<type>file</type>
<level>WARNING</level>
<property name="filename">logs/warn.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>error_file</tag>
<type>file</type>
<level>ERROR</level>
<property name="filename">logs/error.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
</logging>
......@@ -10,6 +10,10 @@
## develop history ##
---
- 2018/06/24
> improvement
* delete this, using name abbreviation instead.
- 2018/03/17
> improvement
* use getty 0.8.2
......
......@@ -39,99 +39,99 @@ type EchoClient struct {
gettyClient getty.Client
}
func (this *EchoClient) isAvailable() bool {
if this.selectSession() == nil {
func (c *EchoClient) isAvailable() bool {
if c.selectSession() == nil {
return false
}
return true
}
func (this *EchoClient) close() {
client.lock.Lock()
if client.gettyClient != nil {
for _, s := range this.sessions {
func (c *EchoClient) close() {
c.lock.Lock()
defer c.lock.Unlock()
if c.gettyClient != nil {
for _, s := range c.sessions {
log.Info("close client session{%s, last active:%s, request number:%d}",
s.session.Stat(), s.session.GetActive().String(), s.reqNum)
s.session.Close()
}
client.gettyClient.Close()
client.gettyClient = nil
client.sessions = client.sessions[:0]
c.gettyClient.Close()
c.gettyClient = nil
c.sessions = c.sessions[:0]
}
client.lock.Unlock()
}
func (this *EchoClient) selectSession() getty.Session {
func (c *EchoClient) selectSession() getty.Session {
// get route server session
this.lock.RLock()
defer this.lock.RUnlock()
count := len(this.sessions)
c.lock.RLock()
defer c.lock.RUnlock()
count := len(c.sessions)
if count == 0 {
log.Debug("client session array is nil...")
log.Info("client session array is nil...")
return nil
}
return this.sessions[rand.Int31n(int32(count))].session
return c.sessions[rand.Int31n(int32(count))].session
}
func (this *EchoClient) addSession(session getty.Session) {
func (c *EchoClient) addSession(session getty.Session) {
log.Debug("add session{%s}", session.Stat())
if session == nil {
return
}
this.lock.Lock()
this.sessions = append(this.sessions, &clientEchoSession{session: session})
this.lock.Unlock()
c.lock.Lock()
c.sessions = append(c.sessions, &clientEchoSession{session: session})
c.lock.Unlock()
}
func (this *EchoClient) removeSession(session getty.Session) {
func (c *EchoClient) removeSession(session getty.Session) {
if session == nil {
return
}
this.lock.Lock()
c.lock.Lock()
for i, s := range this.sessions {
for i, s := range c.sessions {
if s.session == session {
this.sessions = append(this.sessions[:i], this.sessions[i+1:]...)
c.sessions = append(c.sessions[:i], c.sessions[i+1:]...)
log.Debug("delete session{%s}, its index{%d}", session.Stat(), i)
break
}
}
log.Info("after remove session{%s}, left session number:%d", session.Stat(), len(this.sessions))
log.Info("after remove session{%s}, left session number:%d", session.Stat(), len(c.sessions))
this.lock.Unlock()
c.lock.Unlock()
}
func (this *EchoClient) updateSession(session getty.Session) {
func (c *EchoClient) updateSession(session getty.Session) {
if session == nil {
return
}
this.lock.Lock()
c.lock.Lock()
for i, s := range this.sessions {
for i, s := range c.sessions {
if s.session == session {
this.sessions[i].reqNum++
c.sessions[i].reqNum++
break
}
}
this.lock.Unlock()
c.lock.Unlock()
}
func (this *EchoClient) getClientEchoSession(session getty.Session) (clientEchoSession, error) {
func (c *EchoClient) getClientEchoSession(session getty.Session) (clientEchoSession, error) {
var (
err error
echoSession clientEchoSession
)
this.lock.Lock()
c.lock.Lock()
err = errSessionNotExist
for _, s := range this.sessions {
for _, s := range c.sessions {
if s.session == session {
echoSession = *s
err = nil
......@@ -139,7 +139,7 @@ func (this *EchoClient) getClientEchoSession(session getty.Session) (clientEchoS
}
}
this.lock.Unlock()
c.lock.Unlock()
return echoSession, err
}
......@@ -23,8 +23,8 @@ import (
)
const (
APP_CONF_FILE string = "APP_CONF_FILE"
APP_LOG_CONF_FILE string = "APP_LOG_CONF_FILE"
APP_CONF_FILE = "APP_CONF_FILE"
APP_LOG_CONF_FILE = "APP_LOG_CONF_FILE"
)
var (
......
......@@ -82,29 +82,29 @@ type EchoPackage struct {
B string
}
func (this EchoPackage) String() string {
func (p EchoPackage) String() string {
return fmt.Sprintf("log id:%d, sequence:%d, command:%s, echo string:%s",
this.H.LogID, this.H.Sequence, (echoCommand(this.H.Command)).String(), this.B)
p.H.LogID, p.H.Sequence, (echoCommand(p.H.Command)).String(), p.B)
}
func (this EchoPackage) Marshal() (*bytes.Buffer, error) {
func (p EchoPackage) Marshal() (*bytes.Buffer, error) {
var (
err error
buf *bytes.Buffer
)
buf = &bytes.Buffer{}
err = binary.Write(buf, binary.LittleEndian, this.H)
err = binary.Write(buf, binary.LittleEndian, p.H)
if err != nil {
return nil, err
}
buf.WriteByte((byte)(len(this.B)))
buf.WriteString(this.B)
buf.WriteByte((byte)(len(p.B)))
buf.WriteString(p.B)
return buf, nil
}
func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
func (p *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
var (
err error
len byte
......@@ -115,18 +115,18 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
}
// header
err = binary.Read(buf, binary.LittleEndian, &(this.H))
err = binary.Read(buf, binary.LittleEndian, &(p.H))
if err != nil {
return 0, err
}
if this.H.Magic != echoPkgMagic {
log.Error("@this.H.Magic{%x}, right magic{%x}", this.H.Magic, echoPkgMagic)
if p.H.Magic != echoPkgMagic {
log.Error("@p.H.Magic{%x}, right magic{%x}", p.H.Magic, echoPkgMagic)
return 0, ErrIllegalMagic
}
if buf.Len() < (int)(this.H.Len) {
if buf.Len() < (int)(p.H.Len) {
return 0, ErrNotEnoughStream
}
if maxEchoStringLen < this.H.Len-1 {
if maxEchoStringLen < p.H.Len-1 {
return 0, ErrTooLargePackage
}
......@@ -134,7 +134,7 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
if err != nil {
return 0, nil
}
this.B = (string)(buf.Next((int)(len)))
p.B = (string)(buf.Next((int)(len)))
return (int)(this.H.Len) + echoPkgHeaderLen, nil
return (int)(p.H.Len) + echoPkgHeaderLen, nil
}
......@@ -39,23 +39,23 @@ func newEchoMessageHandler() *EchoMessageHandler {
return &EchoMessageHandler{}
}
func (this *EchoMessageHandler) OnOpen(session getty.Session) error {
func (h *EchoMessageHandler) OnOpen(session getty.Session) error {
client.addSession(session)
return nil
}
func (this *EchoMessageHandler) OnError(session getty.Session, err error) {
func (h *EchoMessageHandler) OnError(session getty.Session, err error) {
log.Info("session{%s} got error{%v}, will be closed.", session.Stat(), err)
client.removeSession(session)
}
func (this *EchoMessageHandler) OnClose(session getty.Session) {
func (h *EchoMessageHandler) OnClose(session getty.Session) {
log.Info("session{%s} is closing......", session.Stat())
client.removeSession(session)
}
func (this *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}) {
func (h *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}) {
p, ok := pkg.(*EchoPackage)
if !ok {
log.Error("illegal packge{%#v}", pkg)
......@@ -66,7 +66,7 @@ func (this *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}
client.updateSession(session)
}
func (this *EchoMessageHandler) OnCron(session getty.Session) {
func (h *EchoMessageHandler) OnCron(session getty.Session) {
clientEchoSession, err := client.getClientEchoSession(session)
if err != nil {
log.Error("client.getClientSession(session{%s}) = error{%#v}", session.Stat(), err)
......
......@@ -20,14 +20,13 @@ import (
log "github.com/AlexStocks/log4go"
)
type EchoPackageHandler struct {
}
type EchoPackageHandler struct{}
func NewEchoPackageHandler() *EchoPackageHandler {
return &EchoPackageHandler{}
}
func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
func (h *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
var (
err error
len int
......@@ -48,7 +47,7 @@ func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}
return &pkg, len, nil
}
func (this *EchoPackageHandler) Write(ss getty.Session, pkg interface{}) error {
func (h *EchoPackageHandler) Write(ss getty.Session, pkg interface{}) error {
var (
ok bool
err error
......
......@@ -10,5 +10,5 @@
package main
var (
Version = "0.8.2"
Version = "0.8.4"
)
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=linux
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=darwin
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=windows
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
-----BEGIN CERTIFICATE-----
MIICHjCCAYegAwIBAgIQKpKqamBqmZ0hfp8sYb4uNDANBgkqhkiG9w0BAQsFADAS
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
iQKBgQC5Nxsk6WjeaYazRYiGxHZ5G3FXSlSjV7lZeebItdEPzO8kVPIGCSTy/M5X
Nnpp3uVDFXQub0/O5t9Y6wcuqpUGMOV+XL7MZqSZlodXm0XhNYzCAjZ+URNjTHGP
NXIqdDEG5Ba8SXMOfY6H97+QxugZoAMFZ+N83ggr12IYNO/FbQIDAQABo3MwcTAO
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
AwEB/zA5BgNVHREEMjAwgglsb2NhbGhvc3SCC2V4YW1wbGUuY29thwR/AAABhxAA
AAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4GBAE5dr9q7ORmKZ7yZqeSL
305armc13A7UxffUajeJFujpl2jOqnb5PuKJ7fn5HQKGB0qSq3IHsFua2WONXcTW
Vn4gS0k50IaDpW+yl+ArIo0QwbjPIAcFysX10p9dVO7A1uEpHbRDzefem6r9uVGk
i7dOLEoC8hkfk6nJsNEIEqu6
-----END CERTIFICATE-----
# toml configure file
# toml中key的首字母可以小写,但是对应的golang中的struct成员首字母必须大写
AppName = "ECHO-CLIENT"
# host
LocalHost = "127.0.0.1"
# server
# ServerHost = "127.0.0.1"
# ServerHost = "192.168.8.3"
ServerHost = "localhost"
ServerPort = 10000
ServerPath = "/echo"
ProfilePort = 10080
# connection pool
# 连接池连接数目
ConnectionNum = 2
# session
# client与server之间连接的心跳周期
HeartbeatPeriod = "10s"
# client与server之间连接的超时时间
SessionTimeout = "20s"
# client
# client echo request string
# EchoString = "Hello, getty!"
# for compress test
EchoString = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
# 发送echo请求次数
EchoTimes = 10
# app fail fast
FailFastTimeout = "3s"
# tcp
[GettySessionParam]
CompressEncoding = true
TcpNoDelay = true
TcpKeepAlive = true
TcpRBufSize = 262144
TcpWBufSize = 65536
PkgRQSize = 512
PkgWQSize = 256
TcpReadTimeout = "1s"
TcpWriteTimeout = "5s"
WaitTimeout = "1s"
MaxMsgLen = 128
SessionName = "echo-client"
<logging>
<filter enabled="true">
<tag>stdout</tag>
<type>console</type>
<!-- level is (:?FINEST|FINE|DEBUG|TRACE|INFO|WARNING|ERROR) -->
<level>INFO</level>
</filter>
<filter enabled="false">
<tag>debug_file</tag>
<type>file</type>
<level>DEBUG</level>
<property name="filename">logs/debug.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>info_file</tag>
<type>file</type>
<level>INFO</level>
<property name="filename">logs/info.log</property>
<!--
%T - Time (15:04:05 MST)
%t - Time (15:04)
%D - Date (2006/01/02)
%d - Date (01/02/06)
%L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT)
%S - Source
%M - Message
It ignores unknown format strings (and removes them)
Recommended: "[%D %T] [%L] (%S) %M"
-->
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>warn_file</tag>
<type>file</type>
<level>WARNING</level>
<property name="filename">logs/warn.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>error_file</tag>
<type>file</type>
<level>ERROR</level>
<property name="filename">logs/error.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
</logging>
......@@ -23,8 +23,8 @@ import (
)
const (
APP_CONF_FILE string = "APP_CONF_FILE"
APP_LOG_CONF_FILE string = "APP_LOG_CONF_FILE"
APP_CONF_FILE = "APP_CONF_FILE"
APP_LOG_CONF_FILE = "APP_LOG_CONF_FILE"
)
var (
......
......@@ -82,29 +82,29 @@ type EchoPackage struct {
B string
}
func (this EchoPackage) String() string {
func (p EchoPackage) String() string {
return fmt.Sprintf("log id:%d, sequence:%d, command:%s, echo string:%s",
this.H.LogID, this.H.Sequence, (echoCommand(this.H.Command)).String(), this.B)
p.H.LogID, p.H.Sequence, (echoCommand(p.H.Command)).String(), p.B)
}
func (this EchoPackage) Marshal() (*bytes.Buffer, error) {
func (p EchoPackage) Marshal() (*bytes.Buffer, error) {
var (
err error
buf *bytes.Buffer
)
buf = &bytes.Buffer{}
err = binary.Write(buf, binary.LittleEndian, this.H)
err = binary.Write(buf, binary.LittleEndian, p.H)
if err != nil {
return nil, err
}
buf.WriteByte((byte)(len(this.B)))
buf.WriteString(this.B)
buf.WriteByte((byte)(len(p.B)))
buf.WriteString(p.B)
return buf, nil
}
func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
func (p *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
var (
err error
len byte
......@@ -115,19 +115,19 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
}
// header
err = binary.Read(buf, binary.LittleEndian, &(this.H))
err = binary.Read(buf, binary.LittleEndian, &(p.H))
if err != nil {
return 0, err
}
if this.H.Magic != echoPkgMagic {
log.Error("@this.H.Magic{%x}, right magic{%x}", this.H.Magic, echoPkgMagic)
if p.H.Magic != echoPkgMagic {
log.Error("@p.H.Magic{%x}, right magic{%x}", p.H.Magic, echoPkgMagic)
return 0, ErrIllegalMagic
}
if buf.Len() < (int)(this.H.Len) {
if buf.Len() < (int)(p.H.Len) {
return 0, ErrNotEnoughStream
}
// 防止恶意客户端把这个字段设置过大导致服务端死等或者服务端在准备对应的缓冲区时内存崩溃
if maxEchoStringLen < this.H.Len-1 {
if maxEchoStringLen < p.H.Len-1 {
return 0, ErrTooLargePackage
}
......@@ -135,7 +135,7 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
if err != nil {
return 0, nil
}
this.B = (string)(buf.Next((int)(len)))
p.B = (string)(buf.Next((int)(len)))
return (int)(this.H.Len) + echoPkgHeaderLen, nil
return (int)(p.H.Len) + echoPkgHeaderLen, nil
}
......@@ -34,7 +34,7 @@ type PackageHandler interface {
type MessageHandler struct{}
func (this *MessageHandler) Handle(session getty.Session, pkg *EchoPackage) error {
func (h *MessageHandler) Handle(session getty.Session, pkg *EchoPackage) error {
log.Debug("get echo package{%s}", pkg)
// write echo message handle logic here.
return session.WritePkg(pkg, conf.GettySessionParam.waitTimeout)
......@@ -63,84 +63,84 @@ func newEchoMessageHandler() *EchoMessageHandler {
return &EchoMessageHandler{sessionMap: make(map[getty.Session]*clientEchoSession), handlers: handlers}
}
func (this *EchoMessageHandler) OnOpen(session getty.Session) error {
func (h *EchoMessageHandler) OnOpen(session getty.Session) error {
var (
err error
)
this.rwlock.RLock()
if conf.SessionNumber < len(this.sessionMap) {
h.rwlock.RLock()
if conf.SessionNumber < len(h.sessionMap) {
err = errTooManySessions
}
this.rwlock.RUnlock()
h.rwlock.RUnlock()
if err != nil {
return err
}
log.Info("got session:%s", session.Stat())
this.rwlock.Lock()
this.sessionMap[session] = &clientEchoSession{session: session}
this.rwlock.Unlock()
h.rwlock.Lock()
h.sessionMap[session] = &clientEchoSession{session: session}
h.rwlock.Unlock()
return nil
}
func (this *EchoMessageHandler) OnError(session getty.Session, err error) {
func (h *EchoMessageHandler) OnError(session getty.Session, err error) {
log.Info("session{%s} got error{%v}, will be closed.", session.Stat(), err)
this.rwlock.Lock()
delete(this.sessionMap, session)
this.rwlock.Unlock()
h.rwlock.Lock()
delete(h.sessionMap, session)
h.rwlock.Unlock()
}
func (this *EchoMessageHandler) OnClose(session getty.Session) {
func (h *EchoMessageHandler) OnClose(session getty.Session) {
log.Info("session{%s} is closing......", session.Stat())
this.rwlock.Lock()
delete(this.sessionMap, session)
this.rwlock.Unlock()
h.rwlock.Lock()
delete(h.sessionMap, session)
h.rwlock.Unlock()
}
func (this *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}) {
func (h *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}) {
p, ok := pkg.(*EchoPackage)
if !ok {
log.Error("illegal packge{%#v}, %s", pkg, string(pkg.([]byte)))
return
}
handler, ok := this.handlers[p.H.Command]
handler, ok := h.handlers[p.H.Command]
if !ok {
log.Error("illegal command{%d}", p.H.Command)
return
}
err := handler.Handle(session, p)
if err != nil {
this.rwlock.Lock()
if _, ok := this.sessionMap[session]; ok {
this.sessionMap[session].reqNum++
h.rwlock.Lock()
if _, ok := h.sessionMap[session]; ok {
h.sessionMap[session].reqNum++
}
this.rwlock.Unlock()
h.rwlock.Unlock()
}
}
func (this *EchoMessageHandler) OnCron(session getty.Session) {
func (h *EchoMessageHandler) OnCron(session getty.Session) {
var (
flag bool
active time.Time
)
this.rwlock.RLock()
if _, ok := this.sessionMap[session]; ok {
h.rwlock.RLock()
if _, ok := h.sessionMap[session]; ok {
active = session.GetActive()
if conf.sessionTimeout.Nanoseconds() < time.Since(active).Nanoseconds() {
flag = true
log.Warn("session{%s} timeout{%s}, reqNum{%d}",
session.Stat(), time.Since(active).String(), this.sessionMap[session].reqNum)
session.Stat(), time.Since(active).String(), h.sessionMap[session].reqNum)
}
}
this.rwlock.RUnlock()
h.rwlock.RUnlock()
if flag {
this.rwlock.Lock()
delete(this.sessionMap, session)
this.rwlock.Unlock()
h.rwlock.Lock()
delete(h.sessionMap, session)
h.rwlock.Unlock()
session.Close()
}
}
......@@ -28,7 +28,7 @@ func NewEchoPackageHandler() *EchoPackageHandler {
return &EchoPackageHandler{}
}
func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
func (h *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
// log.Debug("get client package:%s", gxstrings.String(data))
var (
err error
......@@ -52,7 +52,7 @@ func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}
// return data, len(data), nil
}
func (this *EchoPackageHandler) Write(ss getty.Session, pkg interface{}) error {
func (h *EchoPackageHandler) Write(ss getty.Session, pkg interface{}) error {
var (
ok bool
err error
......
......@@ -10,5 +10,5 @@
package main
var (
Version = "0.8.2"
Version = "0.8.4"
)
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=linux
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=darwin
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=windows
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
# toml configure file
# toml中key的首字母可以小写,但是对应的golang中的struct成员首字母必须大写
AppName = "ECHO-SERVER"
# Host = "0.0.0.0"
# Host = "127.0.0.1"
# Host = "192.168.35.1"
Host = "localhost"
Ports = ["10000", "20000"]
Paths = ["/echo", "/echo"]
ProfilePort = 10086
# session
# client与server之间连接的心跳周期
HeartbeatPeriod = "10s"
# client与server之间连接的超时时间
SessionTimeout = "20s"
# client与server之间连接的最大连接数
SessionNumber = 700
# app
FailFastTimeout = "3s"
# tcp
[GettySessionParam]
CompressEncoding = true
TcpNoDelay = true
TcpKeepAlive = true
TcpRBufSize = 262144
TcpWBufSize = 524288
PkgRQSize = 1024
PkgWQSize = 512
TcpReadTimeout = "1s"
TcpWriteTimeout = "5s"
WaitTimeout = "1s"
MaxMsgLen = 128
SessionName = "echo-server"
<logging>
<filter enabled="true">
<tag>stdout</tag>
<type>console</type>
<!-- level is (:?FINEST|FINE|DEBUG|TRACE|INFO|WARNING|ERROR) -->
<level>DEBUG</level>
</filter>
<filter enabled="true">
<tag>debug_file</tag>
<type>file</type>
<level>DEBUG</level>
<property name="filename">logs/debug.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>info_file</tag>
<type>file</type>
<level>INFO</level>
<property name="filename">logs/info.log</property>
<!--
%T - Time (15:04:05 MST)
%t - Time (15:04)
%D - Date (2006/01/02)
%d - Date (01/02/06)
%L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT)
%S - Source
%M - Message
It ignores unknown format strings (and removes them)
Recommended: "[%D %T] [%L] (%S) %M"
-->
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>warn_file</tag>
<type>file</type>
<level>WARNING</level>
<property name="filename">logs/warn.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>error_file</tag>
<type>file</type>
<level>ERROR</level>
<property name="filename">logs/error.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
</logging>
......@@ -10,6 +10,10 @@
## develop history ##
---
- 2018/06/24
> improvement
* delete this, using name abbreviation instead.
- 2018/03/17
> improvement
* use getty 0.8.2
......
......@@ -39,99 +39,99 @@ type EchoClient struct {
gettyClient getty.Client
}
func (this *EchoClient) isAvailable() bool {
if this.selectSession() == nil {
func (c *EchoClient) isAvailable() bool {
if c.selectSession() == nil {
return false
}
return true
}
func (this *EchoClient) close() {
client.lock.Lock()
if client.gettyClient != nil {
for _, s := range this.sessions {
func (c *EchoClient) close() {
c.lock.Lock()
defer c.lock.Unlock()
if c.gettyClient != nil {
for _, s := range c.sessions {
log.Info("close client session{%s, last active:%s, request number:%d}",
s.session.Stat(), s.session.GetActive().String(), s.reqNum)
s.session.Close()
}
client.gettyClient.Close()
client.gettyClient = nil
client.sessions = client.sessions[:0]
c.gettyClient.Close()
c.gettyClient = nil
c.sessions = c.sessions[:0]
}
client.lock.Unlock()
}
func (this *EchoClient) selectSession() getty.Session {
func (c *EchoClient) selectSession() getty.Session {
// get route server session
this.lock.RLock()
defer this.lock.RUnlock()
count := len(this.sessions)
c.lock.RLock()
defer c.lock.RUnlock()
count := len(c.sessions)
if count == 0 {
log.Debug("client session array is nil...")
log.Info("client session array is nil...")
return nil
}
return this.sessions[rand.Int31n(int32(count))].session
return c.sessions[rand.Int31n(int32(count))].session
}
func (this *EchoClient) addSession(session getty.Session) {
func (c *EchoClient) addSession(session getty.Session) {
log.Debug("add session{%s}", session.Stat())
if session == nil {
return
}
this.lock.Lock()
this.sessions = append(this.sessions, &clientEchoSession{session: session})
this.lock.Unlock()
c.lock.Lock()
c.sessions = append(c.sessions, &clientEchoSession{session: session})
c.lock.Unlock()
}
func (this *EchoClient) removeSession(session getty.Session) {
func (c *EchoClient) removeSession(session getty.Session) {
if session == nil {
return
}
this.lock.Lock()
c.lock.Lock()
for i, s := range this.sessions {
for i, s := range c.sessions {
if s.session == session {
this.sessions = append(this.sessions[:i], this.sessions[i+1:]...)
c.sessions = append(c.sessions[:i], c.sessions[i+1:]...)
log.Debug("delete session{%s}, its index{%d}", session.Stat(), i)
break
}
}
log.Info("after remove session{%s}, left session number:%d", session.Stat(), len(this.sessions))
log.Info("after remove session{%s}, left session number:%d", session.Stat(), len(c.sessions))
this.lock.Unlock()
c.lock.Unlock()
}
func (this *EchoClient) updateSession(session getty.Session) {
func (c *EchoClient) updateSession(session getty.Session) {
if session == nil {
return
}
this.lock.Lock()
c.lock.Lock()
for i, s := range this.sessions {
for i, s := range c.sessions {
if s.session == session {
this.sessions[i].reqNum++
c.sessions[i].reqNum++
break
}
}
this.lock.Unlock()
c.lock.Unlock()
}
func (this *EchoClient) getClientEchoSession(session getty.Session) (clientEchoSession, error) {
func (c *EchoClient) getClientEchoSession(session getty.Session) (clientEchoSession, error) {
var (
err error
echoSession clientEchoSession
)
this.lock.Lock()
c.lock.Lock()
err = errSessionNotExist
for _, s := range this.sessions {
for _, s := range c.sessions {
if s.session == session {
echoSession = *s
err = nil
......@@ -139,7 +139,7 @@ func (this *EchoClient) getClientEchoSession(session getty.Session) (clientEchoS
}
}
this.lock.Unlock()
c.lock.Unlock()
return echoSession, err
}
......@@ -23,8 +23,8 @@ import (
)
const (
APP_CONF_FILE string = "APP_CONF_FILE"
APP_LOG_CONF_FILE string = "APP_LOG_CONF_FILE"
APP_CONF_FILE = "APP_CONF_FILE"
APP_LOG_CONF_FILE = "APP_LOG_CONF_FILE"
)
var (
......
......@@ -82,29 +82,29 @@ type EchoPackage struct {
B string
}
func (this EchoPackage) String() string {
func (p EchoPackage) String() string {
return fmt.Sprintf("log id:%d, sequence:%d, command:%s, echo string:%s",
this.H.LogID, this.H.Sequence, (echoCommand(this.H.Command)).String(), this.B)
p.H.LogID, p.H.Sequence, (echoCommand(p.H.Command)).String(), p.B)
}
func (this EchoPackage) Marshal() (*bytes.Buffer, error) {
func (p EchoPackage) Marshal() (*bytes.Buffer, error) {
var (
err error
buf *bytes.Buffer
)
buf = &bytes.Buffer{}
err = binary.Write(buf, binary.LittleEndian, this.H)
err = binary.Write(buf, binary.LittleEndian, p.H)
if err != nil {
return nil, err
}
buf.WriteByte((byte)(len(this.B)))
buf.WriteString(this.B)
buf.WriteByte((byte)(len(p.B)))
buf.WriteString(p.B)
return buf, nil
}
func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
func (p *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
var (
err error
len byte
......@@ -115,18 +115,18 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
}
// header
err = binary.Read(buf, binary.LittleEndian, &(this.H))
err = binary.Read(buf, binary.LittleEndian, &(p.H))
if err != nil {
return 0, err
}
if this.H.Magic != echoPkgMagic {
log.Error("@this.H.Magic{%x}, right magic{%x}", this.H.Magic, echoPkgMagic)
if p.H.Magic != echoPkgMagic {
log.Error("@p.H.Magic{%x}, right magic{%x}", p.H.Magic, echoPkgMagic)
return 0, ErrIllegalMagic
}
if buf.Len() < (int)(this.H.Len) {
if buf.Len() < (int)(p.H.Len) {
return 0, ErrNotEnoughStream
}
if maxEchoStringLen < this.H.Len-1 {
if maxEchoStringLen < p.H.Len-1 {
return 0, ErrTooLargePackage
}
......@@ -134,7 +134,7 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
if err != nil {
return 0, nil
}
this.B = (string)(buf.Next((int)(len)))
p.B = (string)(buf.Next((int)(len)))
return (int)(this.H.Len) + echoPkgHeaderLen, nil
return (int)(p.H.Len) + echoPkgHeaderLen, nil
}
......@@ -39,23 +39,23 @@ func newEchoMessageHandler() *EchoMessageHandler {
return &EchoMessageHandler{}
}
func (this *EchoMessageHandler) OnOpen(session getty.Session) error {
func (h *EchoMessageHandler) OnOpen(session getty.Session) error {
client.addSession(session)
return nil
}
func (this *EchoMessageHandler) OnError(session getty.Session, err error) {
func (h *EchoMessageHandler) OnError(session getty.Session, err error) {
log.Info("session{%s} got error{%v}, will be closed.", session.Stat(), err)
client.removeSession(session)
}
func (this *EchoMessageHandler) OnClose(session getty.Session) {
func (h *EchoMessageHandler) OnClose(session getty.Session) {
log.Info("session{%s} is closing......", session.Stat())
client.removeSession(session)
}
func (this *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}) {
func (h *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}) {
p, ok := pkg.(*EchoPackage)
if !ok {
log.Error("illegal packge{%#v}", pkg)
......@@ -66,7 +66,7 @@ func (this *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}
client.updateSession(session)
}
func (this *EchoMessageHandler) OnCron(session getty.Session) {
func (h *EchoMessageHandler) OnCron(session getty.Session) {
clientEchoSession, err := client.getClientEchoSession(session)
if err != nil {
log.Error("client.getClientSession(session{%s}) = error{%#v}", session.Stat(), err)
......
......@@ -20,14 +20,13 @@ import (
log "github.com/AlexStocks/log4go"
)
type EchoPackageHandler struct {
}
type EchoPackageHandler struct{}
func NewEchoPackageHandler() *EchoPackageHandler {
return &EchoPackageHandler{}
}
func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
func (h *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
var (
err error
len int
......@@ -48,7 +47,7 @@ func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}
return &pkg, len, nil
}
func (this *EchoPackageHandler) Write(ss getty.Session, pkg interface{}) error {
func (h *EchoPackageHandler) Write(ss getty.Session, pkg interface{}) error {
var (
ok bool
err error
......
......@@ -10,5 +10,5 @@
package main
var (
Version = "0.8.2"
Version = "0.8.4"
)
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=linux
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=darwin
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=windows
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
-----BEGIN CERTIFICATE-----
MIICHjCCAYegAwIBAgIQKpKqamBqmZ0hfp8sYb4uNDANBgkqhkiG9w0BAQsFADAS
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
iQKBgQC5Nxsk6WjeaYazRYiGxHZ5G3FXSlSjV7lZeebItdEPzO8kVPIGCSTy/M5X
Nnpp3uVDFXQub0/O5t9Y6wcuqpUGMOV+XL7MZqSZlodXm0XhNYzCAjZ+URNjTHGP
NXIqdDEG5Ba8SXMOfY6H97+QxugZoAMFZ+N83ggr12IYNO/FbQIDAQABo3MwcTAO
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
AwEB/zA5BgNVHREEMjAwgglsb2NhbGhvc3SCC2V4YW1wbGUuY29thwR/AAABhxAA
AAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4GBAE5dr9q7ORmKZ7yZqeSL
305armc13A7UxffUajeJFujpl2jOqnb5PuKJ7fn5HQKGB0qSq3IHsFua2WONXcTW
Vn4gS0k50IaDpW+yl+ArIo0QwbjPIAcFysX10p9dVO7A1uEpHbRDzefem6r9uVGk
i7dOLEoC8hkfk6nJsNEIEqu6
-----END CERTIFICATE-----
# toml configure file
# toml中key的首字母可以小写,但是对应的golang中的struct成员首字母必须大写
AppName = "ECHO-CLIENT"
# host
LocalHost = "127.0.0.1"
# server
WSSEnable = true
# ServerHost = "127.0.0.1"
# ServerHost = "192.168.8.3"
ServerHost = "localhost"
ServerPort = 10000
ServerPath = "/echo"
ProfilePort = 10080
# cert
CertFile = "./conf/cert/client.crt"
# connection pool
# 连接池连接数目
ConnectionNum = 2
# session
# client与server之间连接的心跳周期
HeartbeatPeriod = "10s"
# client与server之间连接的超时时间
SessionTimeout = "20s"
# client
# client echo request string
# EchoString = "Hello, getty!"
# for compress test
EchoString = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
# 发送echo请求次数
EchoTimes = 10
# app fail fast
FailFastTimeout = "3s"
# tcp
[GettySessionParam]
CompressEncoding = true
TcpNoDelay = true
TcpKeepAlive = true
TcpRBufSize = 262144
TcpWBufSize = 65536
PkgRQSize = 512
PkgWQSize = 256
TcpReadTimeout = "1s"
TcpWriteTimeout = "5s"
WaitTimeout = "1s"
MaxMsgLen = 128
SessionName = "echo-client"
<logging>
<filter enabled="true">
<tag>stdout</tag>
<type>console</type>
<!-- level is (:?FINEST|FINE|DEBUG|TRACE|INFO|WARNING|ERROR) -->
<level>INFO</level>
</filter>
<filter enabled="false">
<tag>debug_file</tag>
<type>file</type>
<level>DEBUG</level>
<property name="filename">logs/debug.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>info_file</tag>
<type>file</type>
<level>INFO</level>
<property name="filename">logs/info.log</property>
<!--
%T - Time (15:04:05 MST)
%t - Time (15:04)
%D - Date (2006/01/02)
%d - Date (01/02/06)
%L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT)
%S - Source
%M - Message
It ignores unknown format strings (and removes them)
Recommended: "[%D %T] [%L] (%S) %M"
-->
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>warn_file</tag>
<type>file</type>
<level>WARNING</level>
<property name="filename">logs/warn.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>error_file</tag>
<type>file</type>
<level>ERROR</level>
<property name="filename">logs/error.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
</logging>
......@@ -23,8 +23,8 @@ import (
)
const (
APP_CONF_FILE string = "APP_CONF_FILE"
APP_LOG_CONF_FILE string = "APP_LOG_CONF_FILE"
APP_CONF_FILE = "APP_CONF_FILE"
APP_LOG_CONF_FILE = "APP_LOG_CONF_FILE"
)
var (
......
......@@ -82,29 +82,29 @@ type EchoPackage struct {
B string
}
func (this EchoPackage) String() string {
func (p EchoPackage) String() string {
return fmt.Sprintf("log id:%d, sequence:%d, command:%s, echo string:%s",
this.H.LogID, this.H.Sequence, (echoCommand(this.H.Command)).String(), this.B)
p.H.LogID, p.H.Sequence, (echoCommand(p.H.Command)).String(), p.B)
}
func (this EchoPackage) Marshal() (*bytes.Buffer, error) {
func (p EchoPackage) Marshal() (*bytes.Buffer, error) {
var (
err error
buf *bytes.Buffer
)
buf = &bytes.Buffer{}
err = binary.Write(buf, binary.LittleEndian, this.H)
err = binary.Write(buf, binary.LittleEndian, p.H)
if err != nil {
return nil, err
}
buf.WriteByte((byte)(len(this.B)))
buf.WriteString(this.B)
buf.WriteByte((byte)(len(p.B)))
buf.WriteString(p.B)
return buf, nil
}
func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
func (p *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
var (
err error
len byte
......@@ -115,19 +115,19 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
}
// header
err = binary.Read(buf, binary.LittleEndian, &(this.H))
err = binary.Read(buf, binary.LittleEndian, &(p.H))
if err != nil {
return 0, err
}
if this.H.Magic != echoPkgMagic {
log.Error("@this.H.Magic{%x}, right magic{%x}", this.H.Magic, echoPkgMagic)
if p.H.Magic != echoPkgMagic {
log.Error("@p.H.Magic{%x}, right magic{%x}", p.H.Magic, echoPkgMagic)
return 0, ErrIllegalMagic
}
if buf.Len() < (int)(this.H.Len) {
if buf.Len() < (int)(p.H.Len) {
return 0, ErrNotEnoughStream
}
// 防止恶意客户端把这个字段设置过大导致服务端死等或者服务端在准备对应的缓冲区时内存崩溃
if maxEchoStringLen < this.H.Len-1 {
if maxEchoStringLen < p.H.Len-1 {
return 0, ErrTooLargePackage
}
......@@ -135,7 +135,7 @@ func (this *EchoPackage) Unmarshal(buf *bytes.Buffer) (int, error) {
if err != nil {
return 0, nil
}
this.B = (string)(buf.Next((int)(len)))
p.B = (string)(buf.Next((int)(len)))
return (int)(this.H.Len) + echoPkgHeaderLen, nil
return (int)(p.H.Len) + echoPkgHeaderLen, nil
}
......@@ -34,7 +34,7 @@ type PackageHandler interface {
type MessageHandler struct{}
func (this *MessageHandler) Handle(session getty.Session, pkg *EchoPackage) error {
func (h *MessageHandler) Handle(session getty.Session, pkg *EchoPackage) error {
log.Debug("get echo package{%s}", pkg)
// write echo message handle logic here.
return session.WritePkg(pkg, conf.GettySessionParam.waitTimeout)
......@@ -63,84 +63,84 @@ func newEchoMessageHandler() *EchoMessageHandler {
return &EchoMessageHandler{sessionMap: make(map[getty.Session]*clientEchoSession), handlers: handlers}
}
func (this *EchoMessageHandler) OnOpen(session getty.Session) error {
func (h *EchoMessageHandler) OnOpen(session getty.Session) error {
var (
err error
)
this.rwlock.RLock()
if conf.SessionNumber < len(this.sessionMap) {
h.rwlock.RLock()
if conf.SessionNumber < len(h.sessionMap) {
err = errTooManySessions
}
this.rwlock.RUnlock()
h.rwlock.RUnlock()
if err != nil {
return err
}
log.Info("got session:%s", session.Stat())
this.rwlock.Lock()
this.sessionMap[session] = &clientEchoSession{session: session}
this.rwlock.Unlock()
h.rwlock.Lock()
h.sessionMap[session] = &clientEchoSession{session: session}
h.rwlock.Unlock()
return nil
}
func (this *EchoMessageHandler) OnError(session getty.Session, err error) {
func (h *EchoMessageHandler) OnError(session getty.Session, err error) {
log.Info("session{%s} got error{%v}, will be closed.", session.Stat(), err)
this.rwlock.Lock()
delete(this.sessionMap, session)
this.rwlock.Unlock()
h.rwlock.Lock()
delete(h.sessionMap, session)
h.rwlock.Unlock()
}
func (this *EchoMessageHandler) OnClose(session getty.Session) {
func (h *EchoMessageHandler) OnClose(session getty.Session) {
log.Info("session{%s} is closing......", session.Stat())
this.rwlock.Lock()
delete(this.sessionMap, session)
this.rwlock.Unlock()
h.rwlock.Lock()
delete(h.sessionMap, session)
h.rwlock.Unlock()
}
func (this *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}) {
func (h *EchoMessageHandler) OnMessage(session getty.Session, pkg interface{}) {
p, ok := pkg.(*EchoPackage)
if !ok {
log.Error("illegal packge{%#v}, %s", pkg, string(pkg.([]byte)))
return
}
handler, ok := this.handlers[p.H.Command]
handler, ok := h.handlers[p.H.Command]
if !ok {
log.Error("illegal command{%d}", p.H.Command)
return
}
err := handler.Handle(session, p)
if err != nil {
this.rwlock.Lock()
if _, ok := this.sessionMap[session]; ok {
this.sessionMap[session].reqNum++
h.rwlock.Lock()
if _, ok := h.sessionMap[session]; ok {
h.sessionMap[session].reqNum++
}
this.rwlock.Unlock()
h.rwlock.Unlock()
}
}
func (this *EchoMessageHandler) OnCron(session getty.Session) {
func (h *EchoMessageHandler) OnCron(session getty.Session) {
var (
flag bool
active time.Time
)
this.rwlock.RLock()
if _, ok := this.sessionMap[session]; ok {
h.rwlock.RLock()
if _, ok := h.sessionMap[session]; ok {
active = session.GetActive()
if conf.sessionTimeout.Nanoseconds() < time.Since(active).Nanoseconds() {
flag = true
log.Warn("session{%s} timeout{%s}, reqNum{%d}",
session.Stat(), time.Since(active).String(), this.sessionMap[session].reqNum)
session.Stat(), time.Since(active).String(), h.sessionMap[session].reqNum)
}
}
this.rwlock.RUnlock()
h.rwlock.RUnlock()
if flag {
this.rwlock.Lock()
delete(this.sessionMap, session)
this.rwlock.Unlock()
h.rwlock.Lock()
delete(h.sessionMap, session)
h.rwlock.Unlock()
session.Close()
}
}
......@@ -28,7 +28,7 @@ func NewEchoPackageHandler() *EchoPackageHandler {
return &EchoPackageHandler{}
}
func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
func (h *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}, int, error) {
// log.Debug("get client package:%s", gxstrings.String(data))
var (
err error
......@@ -52,7 +52,7 @@ func (this *EchoPackageHandler) Read(ss getty.Session, data []byte) (interface{}
// return data, len(data), nil
}
func (this *EchoPackageHandler) Write(ss getty.Session, pkg interface{}) error {
func (h *EchoPackageHandler) Write(ss getty.Session, pkg interface{}) error {
var (
ok bool
err error
......
......@@ -10,5 +10,5 @@
package main
var (
Version = "0.8.2"
Version = "0.8.4"
)
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=linux
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=darwin
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for dev env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : dev.sh
# ******************************************************
set -e
export GOOS=windows
export GOARCH=amd64
export PROFILE="dev"
export PROJECT_HOME=`pwd`
if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then
. ${PROJECT_HOME}/assembly/common/app.properties
fi
if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then
sh ${PROJECT_HOME}/assembly/common/build.sh
fi
#!/usr/bin/env bash
openssl genrsa -out server.key 2048
openssl req -new -x509 -key server.key -out server.crt
-----BEGIN CERTIFICATE-----
MIICHjCCAYegAwIBAgIQKpKqamBqmZ0hfp8sYb4uNDANBgkqhkiG9w0BAQsFADAS
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
iQKBgQC5Nxsk6WjeaYazRYiGxHZ5G3FXSlSjV7lZeebItdEPzO8kVPIGCSTy/M5X
Nnpp3uVDFXQub0/O5t9Y6wcuqpUGMOV+XL7MZqSZlodXm0XhNYzCAjZ+URNjTHGP
NXIqdDEG5Ba8SXMOfY6H97+QxugZoAMFZ+N83ggr12IYNO/FbQIDAQABo3MwcTAO
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
AwEB/zA5BgNVHREEMjAwgglsb2NhbGhvc3SCC2V4YW1wbGUuY29thwR/AAABhxAA
AAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4GBAE5dr9q7ORmKZ7yZqeSL
305armc13A7UxffUajeJFujpl2jOqnb5PuKJ7fn5HQKGB0qSq3IHsFua2WONXcTW
Vn4gS0k50IaDpW+yl+ArIo0QwbjPIAcFysX10p9dVO7A1uEpHbRDzefem6r9uVGk
i7dOLEoC8hkfk6nJsNEIEqu6
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQC5Nxsk6WjeaYazRYiGxHZ5G3FXSlSjV7lZeebItdEPzO8kVPIG
CSTy/M5XNnpp3uVDFXQub0/O5t9Y6wcuqpUGMOV+XL7MZqSZlodXm0XhNYzCAjZ+
URNjTHGPNXIqdDEG5Ba8SXMOfY6H97+QxugZoAMFZ+N83ggr12IYNO/FbQIDAQAB
AoGBAJgvuXQY/fxSxUWkysvBvn9Al17cSrN0r23gBkvBaakMASvfSIbBGMU4COwM
bYV0ivkWNcK539/oQHk1lU85Bv0K9V9wtuFrYW0mN3TU6jnl6eEnzW5oy0Z9TwyY
wuGQOSXGr/aDVu8Wr7eOmSvn6j8rWO2dSMHCllJnSBoqQ1aZAkEA5YQspoMhUaq+
kC53GTgMhotnmK3fWfWKrlLf0spsaNl99W3+plwqxnJbye+5uEutRR1PWSWCCKq5
bN9veOXViwJBAM6WS5aeKO/JX09O0Ang9Y0+atMKO0YjX6fNFE2UJ5Ewzyr4DMZK
TmBpyzm4x/GhV9ukqcDcd3dNlUOtgRqY3+cCQQDCGmssk1+dUpqBE1rT8CvfqYv+
eqWWzerwDNSPz3OppK4630Bqby4Z0GNCP8RAUXgDKIuPqAH11HSm17vNcgqLAkA8
8FCzyUvCD+CxgEoV3+oPFA5m2mnJsr2QvgnzKHTTe1ZhEnKSO3ELN6nfCQbR3AoS
nGwGnAIRiy0wnYmr0tSZAkEAsWFm/D7sTQhX4Qnh15ZDdUn1WSWjBZevUtJnQcpx
TjihZq2sd3uK/XrzG+w7B+cPZlrZtQ94sDSVQwWl/sxB4A==
-----END RSA PRIVATE KEY-----
# toml configure file
# toml中key的首字母可以小写,但是对应的golang中的struct成员首字母必须大写
AppName = "ECHO-SERVER"
# Host = "0.0.0.0"
# Host = "127.0.0.1"
# Host = "192.168.35.1"
Host = "localhost"
Ports = ["10000", "20000"]
Paths = ["/echo", "/echo"]
ProfilePort = 10086
# session
# client与server之间连接的心跳周期
HeartbeatPeriod = "10s"
# client与server之间连接的超时时间
SessionTimeout = "20s"
# client与server之间连接的最大连接数
SessionNumber = 700
# app
FailFastTimeout = "3s"
# cert
CertFile = "./conf/cert/server.crt"
KeyFile = "./conf/cert/server.key"
# CACert = "./conf/cert/ca.crt"
# tcp
[GettySessionParam]
CompressEncoding = true
TcpNoDelay = true
TcpKeepAlive = true
TcpRBufSize = 262144
TcpWBufSize = 524288
PkgRQSize = 1024
PkgWQSize = 512
TcpReadTimeout = "1s"
TcpWriteTimeout = "5s"
WaitTimeout = "1s"
MaxMsgLen = 128
SessionName = "echo-server"
<logging>
<filter enabled="true">
<tag>stdout</tag>
<type>console</type>
<!-- level is (:?FINEST|FINE|DEBUG|TRACE|INFO|WARNING|ERROR) -->
<level>DEBUG</level>
</filter>
<filter enabled="true">
<tag>debug_file</tag>
<type>file</type>
<level>DEBUG</level>
<property name="filename">logs/debug.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>info_file</tag>
<type>file</type>
<level>INFO</level>
<property name="filename">logs/info.log</property>
<!--
%T - Time (15:04:05 MST)
%t - Time (15:04)
%D - Date (2006/01/02)
%d - Date (01/02/06)
%L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT)
%S - Source
%M - Message
It ignores unknown format strings (and removes them)
Recommended: "[%D %T] [%L] (%S) %M"
-->
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>warn_file</tag>
<type>file</type>
<level>WARNING</level>
<property name="filename">logs/warn.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter enabled="true">
<tag>error_file</tag>
<type>file</type>
<level>ERROR</level>
<property name="filename">logs/error.log</property>
<property name="format">[%D %T] [%L] [%S] %M</property>
<property name="rotate">true</property> <!-- true enables log rotation, otherwise append -->
<property name="maxsize">0M</property> <!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property name="maxlines">0K</property> <!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property name="daily">true</property> <!-- Automatically rotates when a log message is written after midnight -->
</filter>
</logging>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment