4 Star 5 Fork 4

Plato/Service-Box-go

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
service_route.go 3.79 KB
一键复制 编辑 原始数据 按行查看 历史
CloudGuan 提交于 2023-06-30 08:38 . !15ISSUE: Customize the call context
package http_proxy
import (
"encoding/json"
"net/http"
"sync/atomic"
"time"
)
const (
requestWaiting = iota
requestFinished
)
type (
//serviceRoute rpc 映射http方法路由代理
serviceRoute struct {
hp *HttpProxy //http proxy 指针
serviceUuid uint64 //服务uid
methodId uint32 //方法id
service string //方法名
method string //函数名
timeout time.Duration //超时时间
}
requestInfo struct {
id uint32 // call id
status int32 // 请求状态
uid uint64 // 服务uid
mid uint32 // 方法uid
service string // 服务名字
method string // 方法id
body []byte // 请求包体
context []byte // 上下文context
done chan *responseInfo // 回包等待
}
responseInfo struct {
status int // http response 状态
err error
body string
}
)
func makeHttpCall(uuid uint64, methodId uint32, service string, method string) *requestInfo {
return &requestInfo{
uid: uuid,
status: requestWaiting,
mid: methodId,
service: service,
method: method,
done: make(chan *responseInfo, 1),
}
}
func (s *serviceRoute) onRequest(c *Context) {
// http proxy 状态检查
if s.hp == nil {
c.JSON(http.StatusInternalServerError, Response{
"error": "The HTTP proxy currently in use is invalid",
})
return
}
// 检查http proxy 的状态, 如果不是可以服务状态,暂停服务
if !s.hp.IsResolved() {
c.JSON(http.StatusInternalServerError, Response{
"error": "The HTTP proxy currently in use is invalid",
})
return
}
// 组装rpc调用头部信息
call := makeHttpCall(s.serviceUuid, s.methodId, s.service, s.method)
// 获取context
rpcCtx := c.GetRpcContext()
if rpcCtx != nil {
var err error
call.context, err = json.Marshal(rpcCtx)
if err != nil {
c.JSON(http.StatusInternalServerError, Response{
"error": err.Error(),
})
return
}
}
// 获取 body
var err error
call.body, err = c.GetRawData()
if call.body == nil || err != nil {
c.JSON(http.StatusBadRequest, Response{
"message": "Invalid parameters",
"err": err,
})
return
}
// 检查body的长度, 长度为0, 时候需要拦截,否则会崩溃
if len(call.body) == 0 {
c.JSON(http.StatusBadRequest, Response{
"message": "Invalid parameters length",
})
return
}
// 发送到主协程
s.hp.onRequest(call)
// 启动定时器
timer := time.NewTimer(s.timeout * time.Millisecond)
// 总是清理定时器
defer timer.Stop()
// 阻塞等待调用返回
select {
case resp, ok := <-call.done:
if !ok {
c.JSON(http.StatusBadRequest, Response{
"error": "Service unavailable",
})
return
}
if resp == nil {
//管道关闭
c.JSON(http.StatusInternalServerError, Response{
"error": "Service unavailable",
})
return
}
if resp.err == nil {
c.Header("Content-Type", "application/json")
c.String(resp.status, resp.body)
return
} else {
c.JSON(resp.status, Response{
"error": resp.err.Error(),
})
return
}
case <-timer.C:
c.JSON(http.StatusNotFound, Response{
"error": "Request response timeout",
})
// 关闭请求
call.finish()
s.hp.opt.logger.Warn("request /%s/%s time out", call.service, call.method)
return
}
}
func (req *requestInfo) isFinished() bool {
return atomic.LoadInt32(&req.status) == requestFinished
}
func (req *requestInfo) finish() {
// 检查避免重复关闭
if atomic.LoadInt32(&req.status) == requestFinished {
return
}
// 结束请求监听,回收资源
atomic.StoreInt32(&req.status, requestFinished)
close(req.done)
}
func (req *requestInfo) doRet(resp *responseInfo) {
if atomic.LoadInt32(&req.status) != requestWaiting {
return
}
req.done <- resp
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/dennis-kk/service-box-go.git
git@gitee.com:dennis-kk/service-box-go.git
dennis-kk
service-box-go
Service-Box-go
v0.5.14

搜索帮助