-
Notifications
You must be signed in to change notification settings - Fork 492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support grpc protocol proxy #793
support grpc protocol proxy #793
Conversation
2.use emptypb instead of anypb
Codecov ReportBase: 75.89% // Head: 73.14% // Decreases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## main #793 +/- ##
==========================================
- Coverage 75.89% 73.14% -2.75%
==========================================
Files 115 130 +15
Lines 13464 14969 +1505
==========================================
+ Hits 10218 10949 +731
- Misses 2674 3400 +726
- Partials 572 620 +48
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
2.corrected according to review comments
Would you mind linking an issue or concluding your change on the PR description rather than leaving it empty? |
yeah, I will supply the description of my change as soon as possible. |
pkg/protocols/grpcprot/request.go
Outdated
// GetFirstInHeader returns the first value for a given key. | ||
// k is converted to lowercase before searching in md. | ||
func (r *Request) GetFirstInHeader(k string) string { | ||
v := r.header.md.Get(k) | ||
if v == nil { | ||
return "" | ||
} | ||
return v[0] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the name of this function is a little confusing, if it is hard to find a good name, I propose removing it and using r.RawHeader().Get(k)
directly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the value structure in the grpc header is []string, so sometimes it will be necessary to obtain the first one, for reference
scg . it will be better to use r.RawHeader().GetFirst(k)
return lb.Servers[hash.Sum32()%uint32(len(lb.Servers))] | ||
} | ||
|
||
type forwardLoadBalancer struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why use the word forward
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
behavior like a forward proxy
// Explicitly *do not Close* c2sErrChan and c2sErrChan, otherwise the select below will not terminate. | ||
// Channels do not have to be closed, it is just a control flow mechanism, see | ||
// https://groups.google.com/forum/#!msg/golang-nuts/pZwdYRGxCIk/qpbHxRRPJdUJ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is better to close the channels in the goroutine created by sp.forwardE2E
, just before it exit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
closing the channel is not always a good option in this scenario. because the client indicates that it will not continue to send datato server on the ClientStream after called ClientStream.CloseSend
, the server can take a long time to handle business before return IO.EOF or continue to send data in one direction, and the client can also continue processing , so C2S and S2C are not always sync. In this scenario, select in for loop
will always select the closed channel and take a lot of CPU
|
||
// RequestMatcherSpec describe RequestMatcher | ||
type RequestMatcherSpec struct { | ||
Policy string `yaml:"policy" jsonschema:"omitempty,enum=,enum=general,enum=ipHash,enum=headerHash,enum=random"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
This PR is for the proxy that easegress can support the gRPC protocol.
The simple process is shown in the figure above, which can forward the traffic on the gRPC client side to the downstream gRPC server according to the configured pipeline rules. It should be reminded that gRPC stream is a full-duplex protocol, so the traffic can also be pushed from the server side to the client side, the above picture is more to show the process of proxy, but not to emphasise the characteristics of full-duplex.
The main modification is the addition of the following modules:
TrafficGate
interface, managed by the Supervisor. It manages the life cycle of the runtimegrpc.server
listener and listen for events to manage the server's life cycle, such as restart/shutdown/hot update, etc.grpc.UnknownServiceHandler
interface to process all traffic entering theruntime
, and implements the same route capability as object/httpserver/muxgRPC.Server
does not support tunnelling, it adopts the method of parsing headersprotocols.Request
, wrappergrpc.ServerStream
protocols.Response
, wrapperstatus.Status
metadata.md
, used bygrpc.InComingContext/OutgoingContext
Header
grpc.Codec
instead ofencoding.Codec
, becauseencoding.Codec
would change the header: useencoding.Codec
, then header's content-type=application/grpc -> content-type=application/grpc+encoding.Codec.Name()