This commit is contained in:
crusader 2017-08-23 18:19:21 +09:00
commit ac11ea7d95
15 changed files with 499 additions and 0 deletions

68
.gitignore vendored Normal file
View File

@ -0,0 +1,68 @@
# Created by .ignore support plugin (hsz.mobi)
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Go template
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
.idea/
*.iml
vendor/
glide.lock
.DS_Store
dist/
debug

32
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,32 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"type": "go",
"request": "launch",
"mode": "debug",
"remotePath": "",
"port": 2345,
"host": "127.0.0.1",
"program": "${workspaceRoot}/main.go",
"env": {},
"args": [],
"showLog": true
},
{
"name": "File Debug",
"type": "go",
"request": "launch",
"mode": "debug",
"remotePath": "",
"port": 2345,
"host": "127.0.0.1",
"program": "${fileDirname}",
"env": {},
"args": [],
"showLog": true
}
]
}

11
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,11 @@
// Place your settings in this file to overwrite default and user settings.
{
// Specifies Lint tool name.
"go.lintTool": "gometalinter",
// Flags to pass to Lint tool (e.g. ["-min_confidence=.8"])
"go.lintFlags": [
"--config=${workspaceRoot}/golint.json"
]
}

6
backend/client.go Normal file
View File

@ -0,0 +1,6 @@
package backend
type PooledClient interface {
Exec(target string, method string, params []string) (string, error)
Close()
}

28
backend/options.go Normal file
View File

@ -0,0 +1,28 @@
package backend
import (
"google.golang.org/grpc"
)
type Options struct {
// Dial is an application supplied function for creating and configuring a
// grpc connection.
//
// The grpc.ClientConn returned from Dial
Dial func() (*grpc.ClientConn, error)
// NewClient is an application supplied function for creating and configuring a
// client.
//
// The client returned from NewClient
NewClient func(*grpc.ClientConn) (interface{}, error)
Exec func(client interface{}, target string, method string, params []string) (string, error)
// Initial number of clients in the pool.
InitCapacity int
// Maximum number of clients allocated by the pool at a given time.
// When zero, there is no limit on the number of clients in the pool.
MaxCapacity int
}

144
backend/pool.go Normal file
View File

@ -0,0 +1,144 @@
package backend
import (
"fmt"
"sync"
"google.golang.org/grpc"
)
type Pool interface {
// Get gets a client. The application must close the returned client.
// This method always returns a valid client so that applications can defer
// error handling to the first use of the client. If there is an error
// getting an underlying client, then the client Err, Do, Send, Flush
// and Receive methods return that error.
Get() (PooledClient, error)
// Capacity returns the number of maximum clients in the pool.
Capacity() int
// Available returns the number of avaliable clients in the pool.
Available() int
// Destroy releases the resources used by the pool.
Destroy()
}
type pool struct {
dial func() (*grpc.ClientConn, error)
newClient func(*grpc.ClientConn) (interface{}, error)
exec func(client interface{}, target string, method string, params []string) (string, error)
initCapacity int
maxCapacity int
conn *grpc.ClientConn
mtx sync.Mutex
clients chan PooledClient
}
func NewPool(o Options) (Pool, error) {
if o.Dial == nil {
return nil, fmt.Errorf("invalid Dial settings")
}
if o.NewClient == nil {
return nil, fmt.Errorf("invalid NewClient settings")
}
if o.InitCapacity < 0 || o.MaxCapacity < 0 {
return nil, fmt.Errorf("invalid capacity settings")
}
p := &pool{
dial: o.Dial,
newClient: o.NewClient,
exec: o.Exec,
initCapacity: o.InitCapacity,
maxCapacity: o.MaxCapacity,
clients: make(chan PooledClient, o.InitCapacity),
}
var err error
p.conn, err = p.dial()
if nil != err {
return nil, err
}
for i := 0; i < p.initCapacity; i++ {
pc, err := p.create()
if err != nil {
p.conn.Close()
return nil, err
}
p.clients <- pc
}
return p, nil
}
func (p *pool) Capacity() int {
return cap(p.clients)
}
func (p *pool) Available() int {
return len(p.clients)
}
func (p *pool) Get() (PooledClient, error) {
if p.clients == nil {
// pool aleardy destroyed, returns new client
return p.create()
}
for {
select {
case c := <-p.clients:
return c, nil
default:
return p.create()
}
}
}
func (p *pool) Destroy() {
p.mtx.Lock()
defer p.mtx.Unlock()
if p.clients == nil {
// pool aleardy destroyed
return
}
close(p.clients)
p.clients = nil
p.conn.Close()
}
func (p *pool) create() (PooledClient, error) {
c, err := p.newClient(p.conn)
if err != nil {
return nil, err
}
pc := &pooledClient{
p: p,
c: c,
}
return pc, nil
}
type pooledClient struct {
p *pool
c interface{}
}
func (pc *pooledClient) Exec(target string, method string, params []string) (string, error) {
return pc.p.exec(pc.c, target, method, params)
}
func (pc *pooledClient) Close() {
select {
case pc.p.clients <- pc:
return
default:
// pool is full, close passed connection
return
}
}

11
glide.yaml Normal file
View File

@ -0,0 +1,11 @@
package: git.loafle.net/overflow/overflow_server_app
import:
- package: github.com/valyala/fasthttp
version: v20160617
- package: github.com/buaazp/fasthttprouter
version: v0.1.1
- package: google.golang.org/grpc
version: v1.5.2
- package: git.loafle.net/overflow/overflow_api_server
subpackages:
- golang

54
main.go Normal file
View File

@ -0,0 +1,54 @@
package main
import (
"context"
"git.loafle.net/overflow/overflow_server_app/backend"
"git.loafle.net/overflow/overflow_server_app/module/member"
"git.loafle.net/overflow/overflow_server_app/server"
grpcAPI "git.loafle.net/overflow/overflow_api_server/golang"
"github.com/valyala/fasthttp"
"google.golang.org/grpc"
)
func main() {
s := server.New()
grpcPool, err := backend.NewPool(backend.Options{
Dial: func() (*grpc.ClientConn, error) {
return grpc.Dial("192.168.1.101:50006", grpc.WithInsecure())
},
NewClient: func(conn *grpc.ClientConn) (interface{}, error) {
return grpcAPI.NewOverflowApiServerClient(conn), nil
},
Exec: func(client interface{}, target string, method string, params []string) (string, error) {
ctx := context.Background()
c := client.(grpcAPI.OverflowApiServerClient)
si := &grpcAPI.ServerInput{
Target: target,
Method: method,
Params: params,
}
so, err := c.Exec(ctx, si)
if nil != err {
return "", err
}
return so.Result, nil
},
})
if nil != err {
}
s.SetContextValue("grpc", grpcPool)
s.Route("POST", "/account/signin", member.SignIn)
s.Route("POST", "/account/signup", member.SignUp)
s.Route("POST", "/account/forgot_password", member.ForgotPassword)
s.Route("POST", "/account/check_email", member.CheckEmail)
fasthttp.ListenAndServe(":19080", s.Handler)
}

View File

@ -0,0 +1,16 @@
package member
import (
"fmt"
"git.loafle.net/overflow/overflow_server_app/server"
"github.com/valyala/fasthttp"
)
func CheckEmail(sctx *server.ServerContext, ctx *fasthttp.RequestCtx) {
msg := sctx.Value("key1")
fmt.Fprintf(ctx, "Welcome!!!!: %s \n", msg)
}

View File

@ -0,0 +1,16 @@
package member
import (
"fmt"
"git.loafle.net/overflow/overflow_server_app/server"
"github.com/valyala/fasthttp"
)
func ForgotPassword(sctx *server.ServerContext, ctx *fasthttp.RequestCtx) {
msg := sctx.Value("key1")
fmt.Fprintf(ctx, "Welcome!!!!: %s \n", msg)
}

29
module/member/signin.go Normal file
View File

@ -0,0 +1,29 @@
package member
import (
"fmt"
"git.loafle.net/overflow/overflow_server_app/backend"
"git.loafle.net/overflow/overflow_server_app/server"
"github.com/valyala/fasthttp"
)
func SignIn(sctx *server.ServerContext, ctx *fasthttp.RequestCtx) {
grpcPool := sctx.Value("grpc").(backend.Pool)
c, err := grpcPool.Get()
if nil != err {
}
signinId := string(ctx.FormValue("signinId"))
signinPw := string(ctx.FormValue("signinPw"))
params := []string{signinId, signinPw}
r, err := c.Exec("MemberService", "signin", params)
fmt.Fprintf(ctx, "Welcome!!!!: %s\n", r)
}

16
module/member/signup.go Normal file
View File

@ -0,0 +1,16 @@
package member
import (
"fmt"
"git.loafle.net/overflow/overflow_server_app/server"
"github.com/valyala/fasthttp"
)
func SignUp(sctx *server.ServerContext, ctx *fasthttp.RequestCtx) {
msg := sctx.Value("key1")
fmt.Fprintf(ctx, "Welcome!: %s \n", msg)
}

19
server/context.go Normal file
View File

@ -0,0 +1,19 @@
package server
type ServerContext struct {
values map[interface{}]interface{}
}
func (c *ServerContext) Value(key interface{}) interface{} {
if nil == c.values {
return nil
}
return c.values[key]
}
func (c *ServerContext) setValue(key interface{}, value interface{}) {
if nil == c.values {
c.values = make(map[interface{}]interface{}, 1)
}
c.values[key] = value
}

5
server/handler.go Normal file
View File

@ -0,0 +1,5 @@
package server
import "github.com/valyala/fasthttp"
type RequestHandler func(sctx *ServerContext, ctx *fasthttp.RequestCtx)

44
server/server.go Normal file
View File

@ -0,0 +1,44 @@
package server
import (
"github.com/buaazp/fasthttprouter"
"github.com/valyala/fasthttp"
)
type Server interface {
Handler(ctx *fasthttp.RequestCtx)
Route(method, path string, handler RequestHandler)
SetContextValue(key interface{}, value interface{})
}
type server struct {
ctx *ServerContext
router *fasthttprouter.Router
}
func New() Server {
s := &server{}
s.router = fasthttprouter.New()
s.ctx = &ServerContext{}
return s
}
func (s *server) SetContextValue(key interface{}, value interface{}) {
s.ctx.setValue(key, value)
}
func (s *server) Handler(ctx *fasthttp.RequestCtx) {
s.router.Handler(ctx)
}
func (s *server) Route(method, path string, handler RequestHandler) {
s.router.Handle(method, path, s.wrapHandler(handler))
}
func (s *server) wrapHandler(handler RequestHandler) fasthttp.RequestHandler {
return fasthttp.RequestHandler(func(ctx *fasthttp.RequestCtx) {
handler(s.ctx, ctx)
})
}