pubsub := rdb.Subscribe(ctx, "mychannel1")
// Close the subscription when we are done.
defer pubsub.Close()
// vs unsubscribe from a channel
defer pubsub.Unsubscribe(ctx, "mychannel1")
ch := pubsub.Channel()
for msg := range ch {
fmt.Println(msg.Channel, msg.Payload)
}
If I don't wan't redis pub-sub channel anymore. Which is the recommended way to unsubscribe a receiver/subscription from a channel and why? Do I also need to delete the redis pub-sub channel at the end too?
Close and Unsubscribe are two behaviors.
we should close when service stop, just like close net conn.
Unsubscribe means we no longer subscribe to something even if the service start.
you don't need to delete the channel at the end, GC will ecycle.
Related
I am trying to broadcast the message to channel in redis, but every user have they'r own channel with their user_id.
the way i think can be use is get all active channel and then publish it one by one. because what i know redis can't publish if diferent channel.
but the problem is, in lib go-redis i am using when the user subribe and check the redis with command PUBSUB CAHNNELS there is no channel result. i read on documentation the subribe function not gonna actived thhe channel immidietly. so how can i get the subribe channel ?
is there any solution to solve this ?
i am using golang-redis https://godoc.org/github.com/go-redis/redis
Subscribe each connection to the per user channel and and a channel for broadcasts. To send to all users, publish to the broadcast channel. The subscriber code will look something like this with the go-redis client:
sub := client.Subscribe(userChannel, broadcastChannel)
defer sub.Close()
for {
m, err := sub.ReceiveMessage()
... do something with m
}
where userChannel and broadcastChannel are the names of Redis channels. Use code like this to broadcast:
cmd := client.Publish(broadcastChannel, message)
if cmd.Err() != nil {
// handle error
}
I want to listen for graceful server termination in grpc in my handler. When the server is being stopped gracefully, I want to add some logic in my code to close open ports, files, flush results etc. How can I do that?
How is it different in case of unary and streaming handler?
You can have shutdown hook by listening to the signals something like this
In your main function or where you start your server create channel for signals that you want to listen to
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
// call your cleanup method with this channel as a routine
go cleanup(c)
In your clean up method
func cleanup(c chan os.Signal) {
// Wait for termination
<- c
// Do your cleanups here
}
Create the signal channel and call the cleanup function as a go routine before you start the gRPC server. Whenever the application (gRPC server) stopped or interrupted this channel will get the signal in the cleanup function where you can do the necessary cleanups
For grpc servers u can do this
func waitForGracefulShutdown(srv *grpc.Server) {
fmt.Println("Grpc messaging server started ...")
interruptChan := make(chan os.Signal, 1)
signal.Notify(interruptChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
// Block until we receive our signal.
<-interruptChan
// Create a deadline to wait for.
_, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
srv.GracefulStop()
publisher, messagingError := messaging.GetPublisherInstance()
if messagingError.Error == nil {
publisher.Close()
}
log.Println("Shutting down grpc messaging server.")
os.Exit(0)
}
Currently there's no mechanism to signal a service handler about Graceful stop. Cleanups and other such global functions that must happen upon server exiting wouldn't usually happen inside of a service handler.
That said, if you think your design is better off with such cleanups happening inside of the service handler and a signal from graceful close is critical, we would love to hear more about your use case. Perhaps open an issue on our github repo and we can discuss it there.
Best,
Mak
From Effective Go
Receivers always block until there is data to receive. If the channel is unbuffered, the sender blocks until the receiver has received the value.
But signal.Notify relays signals to an unbuffered channel without blocking. How does this work and is it possible to do with other chan<- types ?
What it means when it says os.Notify will not block is the messages will be dropped were it to block. So while it's true that it doesn't block, it's not true that it will relay the signals if they can't be received immediately. This is done via simple select:
select {
case channel <- message:
// message sent
default:
// message dropped
}
Which is why the documentation for Notify explicitly states that you should use a buffered channel. Also note that buffered channels can also block, not just unbuffered channels; buffered channels only block if the buffer is already full.
select is covered in the tour and the spec.
You can always avoid blocking while (probably) still guaranteeing delivery by using another goroutine:
go func() { channel <- message }()
Of course, this is just using the goroutine scheduler as a substitute buffer for your channel, which may or may not be wise.
Which is why the documentation for Notify explicitly states that you should use a buffered channel
With Go 1.17, the tool vet will also make that clearer:
New warning for calling signal.Notify on unbuffered channels
The vet tool now warns about calls to signal.Notify with incoming signals being sent to an unbuffered channel.
Using an unbuffered channel risks missing signals sent on them as signal.Notify does not block when sending to a channel.
For example:
c := make(chan os.Signal)
// signals are sent on c before the channel is read from.
// This signal may be dropped as c is unbuffered.
signal.Notify(c, os.Interrupt)
Users of signal.Notify should use channels with sufficient buffer space to keep up with the expected signal rate.
So, this doesn't answer directly to the problem since it asks for a unbuffered channel, but if all you want is for it not to block on send, this is what I came up with:
ch := make(chan shared.BlogPost, 1024)
You just put a number larger than expected. If you don't know in advance the maximum capacity, then this solution might not work for you.
Also remember that go allocates the channel eagerly, so be careful with memory usage.
I try to explore go channel, i create channel buffer max 10, with gomaxprocess is 2, but i wonder why this code won't receive message
runtime.GOMAXPROCS(2)
messages := make(chan int, 9)
go func() {
for {
i := <-messages
fmt.Println("Receive data:", i)
}
}()
for i := 0; i <= 9; i++ {
fmt.Println("Send data ", i)
messages <- i
}
Your case works like this, though it may appear to work certain times, but it's not guaranteed to always.
Just to add some context, in an unbuffered channel, the sending go routine is blocked as it tries to send a value and a receive is guaranteed to occur before the sending go routine is awakened (in this case the main), so it may seem like a viable option in such cases. But the sending go routine may still exit before the print statement in the receiving go routine is executed. So basically you need to use a synchronization mechanism such that the sending go routine exits only after the work in the receiver is completed.
Here's how you can use a synchronization mechanism, have annotated it so that you can make better sense out of it. This will work for both buffered and unbuffered channels. Another option is to have the receive in the main thread itself so that it doesn't exit before receive processing is done, this way you won't need a separate synchronization mechanism. Hope this helps.
You created a channel which has 9 buffer space, which means main routine (r1) will not blocked until the 10th element was ready to send to messages.
In your go func() (r2), it most probably starts running when r1 almost finished for r2 is a new routine and system takes time to create stacks etc.
so, r2 doesn't print anything, for r1 is done and program exits while r2 has just begin running.
I'm learning Go and so far very impressed with it. I've read all the online docs at golang.org and am halfway through Chrisnall's "The Go Programming Language Phrasebook". I get the concept of channels and think that they will be extremely useful. However, I must have missed something important along the way, as I can't see the point to one-way channels.
If I'm interpreting them correctly, a read-only channel can only be received on and a write-only channel can only be transmitted on, so why have a channel that you can send to and never receive on? Can they be cast from one "direction" to the other? If so, again, what's the point if there's no actual constraint? Are they nothing more than a hint to client code of the channel's purpose?
A channel can be made read-only to whoever receives it, while the sender still has a two-way channel to which they can write. For example:
func F() <-chan int {
// Create a regular, two-way channel.
c := make(chan int)
go func() {
defer close(c)
// Do stuff
c <- 123
}()
// Returning it, implicitly converts it to read-only,
// as per the function return type.
return c
}
Whoever calls F(), receives a channel from which they can only read.
This is mostly useful to avoid potential misuse of a channel at compile time.
Because read/write-only channels are distinct types, the compiler can use
its existing type-checking mechanisms to ensure the caller does not try to write
stuff into a channel it has no business writing to.
I think the main motivation for read-only channels is to prevent corruption and panics of the channel. Imagine if you could write to the channel returned by time.After. This could mess up a lot of code.
Also, panics can occur if you:
close a channel more than once
write to a closed channel
These operations are compile-time errors for read-only channels, but they can cause nasty race conditions when multiple go-routines can write/close a channel.
One way of getting around this is to never close channels and let them be garbage collected. However, close is not just for cleanup, but it actually has use when the channel is ranged over:
func consumeAll(c <-chan bool) {
for b := range c {
...
}
}
If the channel is never closed, this loop will never end. If multiple go-routines are writing to a channel, then there's a lot of book-keeping that has to go on with deciding which one will close the channel.
Since you cannot close a read-only channel, this makes it easier to write correct code. As #jimt pointed out in his comment, you cannot convert a read-only channel to a writeable channel, so you're guaranteed that only parts of the code with access to the writable version of a channel can close/write to it.
Edit:
As for having multiple readers, this is completely fine, as long as you account for it. This is especially useful when used in a producer/consumer model. For example, say you have a TCP server that just accepts connections and writes them to a queue for worker threads:
func produce(l *net.TCPListener, c chan<- net.Conn) {
for {
conn, _ := l.Accept()
c<-conn
}
}
func consume(c <-chan net.Conn) {
for conn := range c {
// do something with conn
}
}
func main() {
c := make(chan net.Conn, 10)
for i := 0; i < 10; i++ {
go consume(c)
}
addr := net.TCPAddr{net.ParseIP("127.0.0.1"), 3000}
l, _ := net.ListenTCP("tcp", &addr)
produce(l, c)
}
Likely your connection handling will take longer than accepting a new connection, so you want to have lots of consumers with a single producer. Multiple producers is more difficult (because you need to coordinate who closes the channel) but you can add some kind of a semaphore-style channel to the channel send.
Go channels are modelled on Hoare's Communicating Sequential Processes, a process algebra for concurrency that is oriented around event flows between communicating actors (small 'a'). As such, channels have a direction because they have a send end and a receive end, i.e. a producer of events and a consumer of events. A similar model is used in Occam and Limbo also.
This is important - it would be hard to reason about deadlock issues if a channel-end could arbitrarily be re-used as both sender and receiver at different times.