Skip to content

Commit

Permalink
add http2 listener for grpc proxy (#315)
Browse files Browse the repository at this point in the history
* split listener service interface

* split listener service interface

* update

* update

* update

* update

* add integration test

* add integration test

* update

* fix golangci-lint

* update

* fix reviewdog

* fix reviewdog

* fix reviewdog

* update for comment

* rename to NetworkFilterChain

* update

Co-authored-by: Mark4z <36187602+mark4z@users.noreply.github.com>
Co-authored-by: Xin.Zh <dragoncharlie@foxmail.com>
  • Loading branch information
3 people authored Jan 3, 2022
1 parent c3fa875 commit 7946f64
Show file tree
Hide file tree
Showing 60 changed files with 1,557 additions and 341 deletions.
6 changes: 1 addition & 5 deletions docs/sample/dubbo/dubbo-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,12 @@
static_resources:
listeners:
- name: "net/http"
protocol_type: "HTTP"
address:
socket_address:
protocol_type: "HTTP"
address: "0.0.0.0"
port: 8881
filter_chains:
- filter_chain_match:
domains:
- api.dubbo.com
- api.pixiu.com
filters:
- name: dgp.filter.httpconnectionmanager
config:
Expand Down
6 changes: 1 addition & 5 deletions docs/sample/http/http-grpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,12 @@
static_resources:
listeners:
- name: "net/http"
protocol_type: "HTTP"
address:
socket_address:
protocol_type: "HTTP"
address: "0.0.0.0"
port: 8881
filter_chains:
- filter_chain_match:
domains:
- api.dubbo.com
- api.pixiu.com
filters:
- name: dgp.filter.httpconnectionmanager
config:
Expand Down
6 changes: 1 addition & 5 deletions docs/sample/http/http-http.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,12 @@
static_resources:
listeners:
- name: "net/http"
protocol_type: "HTTP"
address:
socket_address:
protocol_type: "HTTP"
address: "0.0.0.0"
port: 8888
filter_chains:
- filter_chain_match:
domains:
- api.dubbo.com
- api.pixiu.com
filters:
- name: dgp.filter.httpconnectionmanager
config:
Expand Down
6 changes: 1 addition & 5 deletions docs/user/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,12 @@ This document mainly describes the pixiu config abstraction, there is a example
static_resources:
listeners:
- name: "net/http"
protocol_type: "HTTP"
address:
socket_address:
protocol_type: "HTTP"
address: "0.0.0.0"
port: 8888
filter_chains:
- filter_chain_match:
domains:
- api.dubbo.com
- api.pixiu.com
filters:
- name: dgp.filter.httpconnectionmanager
config:
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/dubbogo/dubbo-go-pixiu-filter v0.1.4
github.com/dubbogo/go-zookeeper v1.0.3
github.com/dubbogo/gost v1.11.19
github.com/emirpasic/gods v1.12.0
github.com/emirpasic/gods v1.12.0 // indirect
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
github.com/gin-gonic/gin v1.7.4
github.com/go-playground/assert/v2 v2.0.1
Expand All @@ -22,6 +22,7 @@ require (
github.com/goinggo/mapstructure v0.0.0-20140717182941-194205d9b4a9
github.com/golang-jwt/jwt/v4 v4.1.0
github.com/golang/protobuf v1.5.2
github.com/gorilla/mux v1.7.3 // indirect
github.com/jhump/protoreflect v1.9.0
github.com/mercari/grpc-http-proxy v0.1.2
github.com/mitchellh/mapstructure v1.4.2
Expand All @@ -45,6 +46,7 @@ require (
go.opentelemetry.io/otel/trace v1.0.0-RC2
go.uber.org/zap v1.19.1
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
golang.org/x/net v0.0.0-20211105192438-b53810dc28af
google.golang.org/grpc v1.42.0
google.golang.org/protobuf v1.27.1
gopkg.in/yaml.v2 v2.4.0
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORR
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
Expand Down
1 change: 1 addition & 0 deletions pkg/common/constant/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package constant

const (
HTTPConnectManagerFilter = "dgp.filter.httpconnectionmanager"
GRPCConnectManagerFilter = "dgp.filter.grpcconnectionmanager"

HTTPAuthorityFilter = "dgp.filter.http.authority"
HTTPProxyFilter = "dgp.filter.http.httpproxy"
Expand Down
5 changes: 3 additions & 2 deletions pkg/common/extension/filter/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package filter

import (
"fmt"
stdHttp "net/http"
)

import (
Expand Down Expand Up @@ -83,8 +84,8 @@ type (

// NetworkFilter describe network filter
NetworkFilter interface {
// OnData handle the http context from worker
OnData(hc *http.HttpContext) error
// ServeHTTP handle request and response
ServeHTTP(w stdHttp.ResponseWriter, r *stdHttp.Request)
}
)

Expand Down
34 changes: 34 additions & 0 deletions pkg/common/grpc/RoundTripper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package grpc

import (
"net/http"
)

import (
"golang.org/x/net/http2"
)

type HttpForwarder struct {
transport *http2.Transport
}

func (hf *HttpForwarder) Forward(r *http.Request) (*http.Response, error) {
return hf.transport.RoundTrip(r)
}
143 changes: 143 additions & 0 deletions pkg/common/grpc/manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package grpc

import (
"context"
"crypto/tls"
"encoding/json"
"io/ioutil"
"net"
stdHttp "net/http"
)

import (
"golang.org/x/net/http2"
)

import (
"github.com/apache/dubbo-go-pixiu/pkg/common/constant"
router2 "github.com/apache/dubbo-go-pixiu/pkg/common/router"
"github.com/apache/dubbo-go-pixiu/pkg/context/http"
pch "github.com/apache/dubbo-go-pixiu/pkg/context/http"
"github.com/apache/dubbo-go-pixiu/pkg/logger"
"github.com/apache/dubbo-go-pixiu/pkg/model"
"github.com/apache/dubbo-go-pixiu/pkg/server"
)

// GrpcConnectionManager network filter for grpc
type GrpcConnectionManager struct {
config *model.GRPCConnectionManagerConfig
routerCoordinator *router2.RouterCoordinator
}

// CreateGrpcConnectionManager create grpc connection manager
func CreateGrpcConnectionManager(hcmc *model.GRPCConnectionManagerConfig, bs *model.Bootstrap) *GrpcConnectionManager {
hcm := &GrpcConnectionManager{config: hcmc}
hcm.routerCoordinator = router2.CreateRouterCoordinator(&hcmc.RouteConfig)
return hcm
}

// OnData receive data from listener
func (gcm *GrpcConnectionManager) OnData(hc *pch.HttpContext) error {
panic("grpc connection manager OnData function shouldn't be called")
}

// ServeHTTP handle request and response
func (gcm *GrpcConnectionManager) ServeHTTP(w stdHttp.ResponseWriter, r *stdHttp.Request) {

ra, err := gcm.routerCoordinator.RouteByPathAndName(r.RequestURI, r.Method)
if err != nil {
logger.Info("GrpcConnectionManager can't find route %v", err)
w.WriteHeader(stdHttp.StatusNotFound)
if _, err := w.Write(constant.Default404Body); err != nil {
logger.Warnf("WriteWithStatus error %v", err)
}
}

logger.Debugf("[dubbo-go-pixiu] client choose endpoint from cluster :%v", ra.Cluster)

clusterName := ra.Cluster
clusterManager := server.GetClusterManager()
endpoint := clusterManager.PickEndpoint(clusterName)
if endpoint == nil {
bt, _ := json.Marshal(http.ErrResponse{Message: "cluster not found endpoint"})
w.WriteHeader(stdHttp.StatusServiceUnavailable)
w.Write(bt)
return
}

newReq := r.Clone(context.Background())
newReq.URL.Scheme = "http"
newReq.URL.Host = endpoint.Address.GetAddress()

// todo: need cache?
forwarder := gcm.newHttpForwarder()
res, err := forwarder.Forward(newReq)

if err != nil {
logger.Info("GrpcConnectionManager forward request error %v", err)
bt, _ := json.Marshal(http.ErrResponse{Message: "pixiu forward error"})
w.WriteHeader(stdHttp.StatusServiceUnavailable)
w.Write(bt)
return
}

if err := gcm.response(w, res); err != nil {
logger.Info("GrpcConnectionManager response error %v", err)
}
}

func (gcm *GrpcConnectionManager) response(w stdHttp.ResponseWriter, res *stdHttp.Response) error {
defer res.Body.Close()

copyHeader(w.Header(), res.Header)
w.WriteHeader(res.StatusCode)

bytes, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
w.Write(bytes)

for k, vv := range res.Trailer {
k = stdHttp.TrailerPrefix + k
for _, v := range vv {
w.Header().Add(k, v)
}
}
return nil
}

func (gcm *GrpcConnectionManager) newHttpForwarder() *HttpForwarder {
transport := &http2.Transport{
DialTLS: func(network, addr string, _ *tls.Config) (net.Conn, error) {
return net.Dial(network, addr)
},
AllowHTTP: true,
}
return &HttpForwarder{transport: transport}
}

func copyHeader(dst, src stdHttp.Header) {
for k, vv := range src {
for _, v := range vv {
dst.Add(k, v)
}
}
}
Loading

0 comments on commit 7946f64

Please sign in to comment.