Skip to content
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

Acesslog dateformat enhancemnet #3090

Closed

Conversation

khanimteyaz
Copy link
Contributor

What is the purpose of the change

AcceLogFilter message creation and last and current check was performing by each time simple date formate object creation. In this version of code I have use the ThreadLocal for each thread wise to create simple date format object instead of each call

#3026

In this PR

  1. I have moved the access log creation and writing to file into a single thread and reusing a single instance of SimpleDateFormat
  2. Refactored code to separate our and group related task in separate method and have enhance the readability by using
    - Method naming
    - Reducing big methods to small.

This PR is a resurrection of old PR

  1. 3027 (Simple date format each time new object creation removed #3027) PR
  2. 3080 (Simple date format each time new object creation removed #3080)
    Sorry for the inconvenience

Brief changelog

XXXXX

Verifying this change

Runnig UT and verifying generated access log.

Follow this checklist to help us incorporate your contribution quickly and easily:

  • Make sure there is a [GITHUB_issue] (AccessLogFilter simple date format reduce instance creation #3026) field for the change (usually before you start working on it). Trivial changes like typos do not require a GITHUB issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue.
  • Format the pull request title like [Dubbo-XXX] Fix UnknownException when host config not exist #XXX. Each commit in the pull request should have a meaningful subject line and body.
  • Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
  • Write necessary unit-test to verify your logic correction, more mock a little better when cross module dependency exist. If the new feature or significant change is committed, please remember to add integration-test in test module.
  • Run mvn clean install -DskipTests=false & mvn clean test-compile failsafe:integration-test to make sure unit-test and integration-test pass.
  • If this contribution is large, please follow the Software Donation Guide.

@codecov-io
Copy link

codecov-io commented Dec 28, 2018

Codecov Report

Merging #3090 into master will increase coverage by 0.21%.
The diff coverage is 85.4%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #3090      +/-   ##
============================================
+ Coverage      63.5%   63.72%   +0.21%     
  Complexity       75       75              
============================================
  Files           653      654       +1     
  Lines         28251    28256       +5     
  Branches       4816     4781      -35     
============================================
+ Hits          17942    18005      +63     
+ Misses         8040     7997      -43     
+ Partials       2269     2254      -15
Impacted Files Coverage Δ Complexity Δ
...n/java/org/apache/dubbo/common/utils/DateUtil.java 100% <100%> (ø) 0 <0> (?)
...a/org/apache/dubbo/rpc/filter/AccessLogFilter.java 83.33% <80.95%> (+12.22%) 0 <0> (ø) ⬇️
...va/org/apache/dubbo/rpc/support/AccessLogData.java 88.73% <88.73%> (ø) 0 <0> (?)
.../remoting/transport/netty4/NettyClientHandler.java 75% <0%> (-11.12%) 0% <0%> (ø)
...bo/rpc/cluster/support/FailbackClusterInvoker.java 67.21% <0%> (-8.2%) 0% <0%> (ø)
...ng/zookeeper/zkclient/ZkclientZookeeperClient.java 55% <0%> (-7.75%) 0% <0%> (ø)
...ava/org/apache/dubbo/rpc/cluster/Configurator.java 92.3% <0%> (-7.7%) 0% <0%> (ø)
...onfig/spring/extension/SpringExtensionFactory.java 78.04% <0%> (-7.32%) 0% <0%> (ø)
...apache/dubbo/remoting/transport/AbstractCodec.java 76.92% <0%> (-3.85%) 0% <0%> (ø)
...dubbo/remoting/exchange/support/DefaultFuture.java 71.81% <0%> (-3.36%) 0% <0%> (ø)
... and 99 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 09cbf8f...154b560. Read the comment docs.

@khanimteyaz
Copy link
Contributor Author

@carryxyh could you please review this.

@beiwei30
Copy link
Member

I didn't look into the change closely, but it looks like we are now moving the date formatter into one single thread to avoid contention completely, which I believe it is the right direction as I pointed out in the old pull request :)

Copy link
Member

@zonghaishang zonghaishang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not thread safe

@khanimteyaz
Copy link
Contributor Author

khanimteyaz commented Dec 30, 2018

@zonghaishang
Whole log parsing and writing is happening in a single thread environment , irrespective of invokes. Would you provide more details so that I can fix it if I can ?

@khanimteyaz
Copy link
Contributor Author

@zonghaishang could you please provide the details about the thread safety so that I can work on this?

@beiwei30 Is there something to incorporate which you feel here?

Copy link
Member

@carryxyh carryxyh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can make the log queue static.
What do u think?

}
if (logSet.size() < LOG_MAX_BUFFER) {
logSet.add(logmessage);
private static final InternalThreadLocal<SimpleDateFormat> INLINE_MESSAGE_DATE_FORMATTER = new InternalThreadLocal<SimpleDateFormat>() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this filed is never used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. I will remove it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


private volatile ScheduledFuture<?> logFuture = null;
private final ConcurrentMap<String, Set<AccessLogData>> logQueue = new ConcurrentHashMap<String, Set<AccessLogData>>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this field be static?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it make sense now to make it static as it is now bound to single thread.

In addition to this, I was thinking (correct me If I am wrong), instead of defining the logQueue as a member of this class, we can it get through a factory (although factory will supply single queue only), so that in future even if we have change it based on our defined we don't have to touch this class. May be we can do this as part of separate PR. What do you say?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emmm...
What is this factory produce? Maybe I haven't get your point~ Can u give more details?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it provide the storage object which its consumer object,

e.g.

Store store= InMemoryQueueStorageFactory.getInstance().getStore();
store.add(accessLog);

something like above. The above example what I hvae given may not be very intuitive itself for explaination, but for high level understanding it might help. If you want I might create a sample branch to demonestrate in more detail way by having some implementation. What do you say?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally think that it is not necessary, because it will make the code more complicated. I think that the current structure is relatively simple, haha.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😄

} catch (Exception e) {
logger.error(e.getMessage(), e);
private void log(String accessLog, AccessLogData accessLogData) {
Set<AccessLogData> logSet = logQueue.get(accessLog);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use computeIfAbsent to optimize this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@khanimteyaz
Copy link
Contributor Author

@carryxyh I have made the changes, would you plz review it.

@carryxyh
Copy link
Member

carryxyh commented Jan 4, 2019

@khanimteyaz
nice work!
I will take a look.

@khanimteyaz
Copy link
Contributor Author

@zonghaishang would you care to provide some detail on the thread safety, so that I can incorporate them? FYI I have provided the comment in previous section about the implementation.

@khanimteyaz
Copy link
Contributor Author

I have updated with comment, would you review my pr?

@carryxyh
Copy link
Member

@zonghaishang
Hi, yiji, would u pls check this pr again?

@khanimteyaz
Let's wait for his feedback. Seems like yiji is very busy recently. :)

@jasonjoo2010
Copy link
Contributor

Why not introducing FastDateFormat?

I think it's more simple and make sense.

@carryxyh
Copy link
Member

@jasonjoo2010
Is the class thread-safe?

@jasonjoo2010
Copy link
Contributor

@jasonjoo2010
Is the class thread-safe?

Yes, it's thread-safe by implemented no sharing data and also including instances cache.

Generally we can just call FastDataFormat.getInstance("yyyyMMdd") as same as new SimpleDateFormat("yyyyMMdd").

@carryxyh
Copy link
Member

@khanimteyaz
Would pls check whether 'FastDataFormat' is better?
:)

Thx for your suggestion. @jasonjoo2010

@jasonjoo2010
Copy link
Contributor

@khanimteyaz
Would pls check whether 'FastDataFormat' is better?
:)

Thx for your suggestion. @jasonjoo2010

But it's in commons-lang or commons-lang3 library maybe we need introduce a new library to project. It's the only point.

@lixiaojiee
Copy link
Contributor

lixiaojiee commented Jan 11, 2019

SimpleDateFormat is not thread-safe, which is why we have to create new objects every time before. I did some research. Java8 currently has a thread-safe date tool called LocalDateTime. After reviewing @jasonjoo2010 's recommendation, I did some testing and found that FastDateFormat performs much better than the other two. Therefore, I also recommend FastDateFormat, but I prefer to bring it into the dubbo-commom package as a common date tool for other modules to reuse.You can refer to the data in the table below. The first column is the number of samples, and the following data is the average time corresponding to each sample in ms.

  SimpleDateFormat FastDateFormat LocalDateTime
10 3 1 77
100 10 4 83
1000 54 26 137
10000 170 52 168
100000 470 153 341
1000000 1827 501 1024
10000000 11591 3473 6228

Note : For environmental reasons, the above data are for reference only

@carryxyh
Copy link
Member

Do we copy code into dubbo?
Seems like we can depend on common-langs package.

CrazyHZM and others added 27 commits January 18, 2019 21:40
Release resource after use in ConfigParserTest
add javadoc for registry and optimize code
* code optimization
* useless import
* optimization
* optimize log output

* Separate logs for reconnect and close

* remove reconnect exception log
* modify some log describe

* use java8 lambda expression
* fix telnet trace times is always 1

* use StringUtils determine if the string is empty

* Fix 3105 , make invoke command with Json string parameter without "class" key

* Fix 3105 ,Keep the class key to support overloaded methods

* optimize InvokerTelnetHandlerTest
* upgrade junit to junit5

* modify test

* 批量修改upgrade_junt_to_junit5

* 删除多余的文件

* fi test case

* Disabled soem test case temporarily

* upgrade junit to junit5 and batch modify test case

* copy some code from jupiter5.4.0.M1 for some issues

* 修改rat福泽

* update rat path

* revert case

* add junit-platform-surefire-provider to maven-surefire-plugin

* update dependency

* fix coverage issue (#1)

* use jupiter 5.4.0-M1 and remove junit5 source code
…backService method issue. (apache#3199)

* Optimize the code: fix url to null, NullPointerException, change private variable to camel mode.
* Optimize the code: exportOrUnexportCallbackService method camel mode.
* Optimize the code: fix method:encodeInvocationArgument private callbackStatus is camel writing.
* Optimize the code: fix name issue
* Exporter is a noun, we should use a verb here, like Export.
* The generics that can be inferred automatically are also deleted.
* refactor telnet invoke command

* add select command for telnet

* fix test case
* wrong event setting

* modify event seeting

* modify
* Code optimization, call the util method

* mofidy

* modify *

* import package
* qos heart question fix apache#3165

* modify

* judge if it's a IdleStateEvent

* add UT

* modify
* modify some typos

* fix some other addionalParameterKeys and paramter typos
* must shutdown thread pool when no in use
@khanimteyaz khanimteyaz deleted the acesslog-dateformat-enhancemnet branch January 18, 2019 19:01
@khanimteyaz khanimteyaz mentioned this pull request Jan 18, 2019
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.