By embedding I meant this:

type ServiceQProperties struct {
    ...
    sync.Mutex
}

which allows you to call p.Lock() instead of p.REMutex.Lock(). It’s just a 
personal preference that I was happy about when I learned about it.

One thought here is you could make it a *sync.Mutex and not use a pointer 
in these function arguments. Maps vars are pointers so you are doing a 
double dereference when accessing RequestErrorLog. This avoids (*sqp) but 
there may be extra memory used and work done to copy the entire struct var 
as an argument. If you get into performance details I would look at pprof 
or package testing benchmarking to decide if it matters, but I try to 
choose cleanest code first.

Thanks for sharing your verification approach.

I haven’t gotten far enough into network services to have much to say about 
the features although maybe I will in the future. I was curious about this:

The buffered requests are forwarded in FIFO order when the service is 
> available next.


wouldn’t you want to do these concurrently if possible?

Matt

On Friday, May 18, 2018 at 11:50:56 AM UTC-5, Ankit Gupta wrote:
>
> Hi Matt,
>
> First of all, thanks so much for the review.
>
> I will revisit the package structure and take care of err handling in a 
> more idiomatic way. Few points - 
>
> - The mutex is embedded in model.ServiceQProperties. Here is the 
> definition in model.balancer_properties.go - 
>
> type ServiceQProperties struct {
>         ...
>         REMutex                 sync.Mutex
> }
>
> This is used in two places - error logging to service map in 
> service_error.go and reading in select_service.go.
>
> - I validated 3 things (all tests were done on a cluster of aws t2 medium 
> linux machines) -  
>
> a) Program should reduce probability of selection of errored nodes - this 
> was done by continously bringing 1 to n-1 services down/up and noting the 
> trend of requests sent to each node after every state change. As an 
> example, for a 3 node cluster with 1 node down for 2 mins, the probability 
> of selection of that node reduced (from 33%) by around 1-2% on each 
> subsequent hit.
>
> b) For performance testing, I used apache bench for issuing large number 
> of concurrent requests/issuing requests within a time frame and 
> benchmarking against nginx. There was a 10% difference on average that is 
> attributed to the fact that I preprocess (parse/store) all requests before 
> forwarding and that the code is not the most optimzed version right now.
>
> c) For deferred queue functionality, I specifically wanted to test 
> scenarios where both active and deferred requests are to be sent out 
> simultaneously and if user defined concurrency limits are still valid.
>
> Let me know if I should provide more details on a specific feature.
>
> Thanks,
> Ankit
>
> On Friday, May 18, 2018 at 8:21:12 PM UTC+5:30, matthe...@gmail.com wrote:
>>
>> Hi Ankit, thanks for the Apache license and for sharing here. Here’s a 
>> code review.
>>
>> These are my unfiltered opinions and I hope that they are useful.
>>
>> Without looking at any code yet, the packages might not be idiomatic. 
>> Packages should contain specific behavior that can be decoupled from the 
>> application. These concepts could be represented as files and symbols in 
>> package main.
>>
>> SQP_K_LISTENER_PORT might be more regularly represented as 
>> SQPKListenerPort.
>>
>> In config_manager_test.go you could embed model.ServiceQProperties and 
>> error in type Properties for better readability.
>>
>> The newlines in the functions don’t help readability.
>>
>> Instead of this:
>>
>> if sqp, err := getProperties(getPropertyFilePath()); err == nil {
>> …
>> } else {
>>     fmt.Fprintf(os.Stderr…
>>
>> this may be more readable:
>>
>> // or if …; err != nil {
>> sqp, err := getProperties(getPropertyFilePath())
>> if err != nil {
>>     fmt.Fprintf(os.Stderr…
>>     return
>> }
>> // regular functionality
>>
>> Generally “err == nil” shouldn’t be in the code.
>>
>> In getListener a similar improvement could be made to avoid the 
>> unnecessary indentation:
>>
>> if sqp.SSLEnabled == false {
>>     return …
>> }
>> // longer behavior
>>
>> In TestWorkAssignment the sqp could be simpler:
>>
>> sqp := model.ServiceQProperty{
>>     ListenerPort: “5252”,
>>     Proto:        “http”,
>>     …
>>
>> More if improvement in algorithm.ChooseServiceIndex:
>>
>> if retry != 0 {
>>     return …
>> }
>> // longer behavior
>>
>> The else after “if sumErr == 0” is unnecessary.
>>
>> The mutex could be embedded in model.ServiceQProperties.
>>
>> How did you validate this program?
>>
>> Thanks,
>> Matt
>>
>> On Friday, May 18, 2018 at 2:34:20 AM UTC-5, Ankit Gupta wrote:
>>>
>>> Hello gophers,
>>>
>>> I recently built a small HTTP load balancer with capabilities built 
>>> around error feedback - https://github.com/gptankit/serviceq
>>> Provides two primary functionalities - deferred request queue and 
>>> probabilitically reducing errored nodes selection.
>>>
>>> I am using channel as a in-memory data structure for storing deferred 
>>> requests. Would love some feedback on this approach and on the project in 
>>> general.
>>>
>>>
>>>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to