java + restlet = strange performance behaviour - java

I have a strange behaviour with a restlet server and I can't understand what's happening!
I have a service that make basic string concatenation with datas from a mySQL database.
My code is :
private static void testWS() throws Exception {
Client client = new Client(Protocol.HTTP);
for (String id : listIds) {
long startTime = System.nanoTime();
Request request = new Request(Method.GET, REST_SERVICE + id);
Response response = client.handle(request);
long endTime = System.nanoTime();
System.out.println("Duration of WS call:" + ((endTime - startTime) / 1000000) + " ms");
}
}
When I run this batch I have something like this:
Duration of WS call:128 ms
Duration of WS call:1015 ms
Duration of WS call:1069 ms
But when this same batch runs on two different computer at the same time, I have for both batch something like this:
Duration of WS call:90 ms
Duration of WS call:92 ms
Duration of WS call:81 ms
The response is 10 x faster when two programs are querying the server instead of one !
Real example: Same batch running on two different computer:
+-----------------------------+----------------------------+
| Batch 1 | Batch 2 |
+-----------------------------+----------------------------+
| Duration of WS call:128 ms | | Start of Batch1
| Duration of WS call:1015 ms | |
| Duration of WS call:1010 ms | |
| Duration of WS call:1012 ms | |
| Duration of WS call:1031 ms | |
| Duration of WS call:1036 ms | |
| Duration of WS call:834 ms | |
| Duration of WS call:90 ms | Duration of WS call:75 ms | Start of Batch2
| Duration of WS call:92 ms | Duration of WS call:82 ms |
| Duration of WS call:81 ms | Duration of WS call:85 ms |
| Duration of WS call:89 ms | Duration of WS call:82 ms |
| Duration of WS call:146 ms | Duration of WS call:90 ms |
| Duration of WS call:92 ms | Duration of WS call:85 ms |
| Duration of WS call:85 ms | Duration of WS call:76 ms |
| Duration of WS call:28 ms | Duration of WS call:96 ms |
| Duration of WS call:165 ms | Duration of WS call:88 ms |
| Duration of WS call:78 ms | Duration of WS call:84 ms |
| Duration of WS call:85 ms | Duration of WS call:63 ms |
| Duration of WS call:103 ms | Duration of WS call:37 ms |
| Duration of WS call:129 ms | Duration of WS call:74 ms |
| Duration of WS call:73 ms | Duration of WS call:140 ms | Batch2 manually stopped
| Duration of WS call:1058 ms | |
| Duration of WS call:1016 ms | |
| Duration of WS call:1006 ms | |
| Duration of WS call:1020 ms | |
| Duration of WS call:1055 ms | |
| Duration of WS call:958 ms | |
| Duration of WS call:1003 ms | | End of Batch1
+-----------------------------+----------------------------+
Is there an explanation for this ?
Thanks in advance.

I was using the default HTTP server in org.restlet.jar wich seems to produce strange results. Since I switch to Jetty everything works as expected (average response time is 50-70 ms)

Related

Join two entries rows ( Start time and End time) as a single row in Talend

I have Data coming from a MS SQL Database, it is concerning the the working hours of employees.
The problem is that, the start time and the end time are stored as 2 different entries, so when the employee comes, he scans his badge and this is considered arrival time, and when he leaves, he scans his badge again and this is considered departure time.
There is one column that helps to make the difference between the start and the end time (CodeNr column : B1 = StartTime, B2 = EndTime)
so this is how my Table looks like
Now i need this data as a single entry, in Talend oder from the Database,
so that should looks like
What to use in order to achieve this please (specially in Talend and when to complicate than in MS SQL)?
CREATE TABLE EmployeeWorkLoad(
EmployeeNr bigint,
Year int,
Month int,
Day int,
Hour int,
Minute int,
CodeNr char(2)
)
Insert into [EmployeeWorkLoad] ( [EmployeeNr],[Year],[Month] ,[Day],[Hour], [Minute] ,[CodeNr]) Values (1,2020,1,4,8,30,'B1'),
(1,2020,1,4,16,45,'B2'),
(1,2020,1,6,8,15,'B1'),
(1,2020,1,6,16,45,'B2'),
(2,2020,3,2,8,10,'B1'),
(2,2020,3,2,16,5,'B2')
GO
6 rows affected
WITH CTE AS (
select EmployeeNr,Year,Month,Day,
MAX(CASE WHEN CodeNr='B1' THEN Hour END) AS StartHour,
MAX(CASE WHEN CodeNr = 'B1' THEN Minute END) AS StartMinute,
MAX(CASE WHEN CodeNr = 'B2' THEN Hour END) AS EndHour,
MAX(CASE WHEN CodeNr = 'B2' THEN Minute END) AS EndMinute
from EmployeeWorkLoad
group by EmployeeNr,Year,Month,Day )
SELECT * , ABS(EndHour-StartHour) AS DutationHour
,ABS(IIF(EndMinute <StartMinute, EndMinute+60, EndMinute)- StartMinute) AS DurationMinute
FROM
CTE
GO
EmployeeNr | Year | Month | Day | StartHour | StartMinute | EndHour | EndMinute | DutationHour | DurationMinute
---------: | ---: | ----: | --: | --------: | ----------: | ------: | --------: | -----------: | -------------:
1 | 2020 | 1 | 4 | 8 | 30 | 16 | 45 | 8 | 15
1 | 2020 | 1 | 6 | 8 | 15 | 16 | 45 | 8 | 30
2 | 2020 | 3 | 2 | 8 | 10 | 16 | 5 | 8 | 55
db<>fiddle here

Java - Problem with the logger on console

i'm developing the Connect4 game in Java and i'm having problem with the Logger. I don't know why prints in different place ad between other kind of prints.
public void setPlacement(Move lastMove){
Logger.getGlobal().info("Player" + lastMove.getPlayerIndex() + " placed a checker in position : " + lastMove.toString());
display();
}
The method display() just prints the grid of the game. Here's the output of the above method :
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| - | - | - | - | - | - | - |
| - | - | - | - | - | - | - |
| - ago 01, 2019 6:10:24 PM it.unicam.cs.pa.connectFour.GameViewsetPlacement
INFO: Player1 placed a checker in position : column 4, row 5
| - | - | - | - | - | - |
| - | - | - | - | - | - | - |
| - | O | O | O | - | - | - |
| O | X | X | X | - | - | - |
*****************************
Can someone explain me why the logger acts like this?
The response to this question concerning System::out and System::err may help you. Specifically, your console is displaying two streams of output at the same time, with no ordering guarantees between messages sent to different streams.
One way to enable Loggers to write to a standard output stream is to create your own StreamHandler and configure your Logger to send input to the handler instead. You may also have to disable parent handlers to avoid duplicate output. You may also want to ensure that output is proactively sent to the desired output stream, as so:
Handler h = new StreamHandler(System.out, formatter)
{
public void publish(LogRecord record)
{
if(record == null)
return;
super.publish(record);
super.flush();
}
};

Single job execution across multiple servers

I have setup where multiple servers run a #Schedule which run a spring batch job that sends out emails to users. I want to make sure that only one instance of this job is ran across multiple servers.
Based on this question
I have implemented some logic to see if its possible to solve this using only spring batch.
To run a job I created a helper class JobRunner with the following methods:
public void run(Job job) {
try {
jobLauncher.run(job, new JobParameters());
} catch (JobExecutionAlreadyRunningException e) {
// Check if job is inactive and stop it if so.
stopIfInactive(job);
} catch (JobExecutionException e) {
...
}
}
The stopIfInactive method:
private void stopIfInactive(Job job) {
for (JobExecution execution : jobExplorer.findRunningJobExecutions(job.getName())) {
Date createTime = execution.getCreateTime();
DateTime now = DateTime.now();
// Get running seconds for more info.
int seconds = Seconds
.secondsBetween(new DateTime(createTime), now)
.getSeconds();
LOGGER.debug("Job '{}' already has an execution with id: {} with age of {}s",
job.getName(), execution.getId(), seconds);
// If job start time exceeds the execution window, stop the job.
if (createTime.before(now.minusMillis(EXECUTION_DEAD_MILLIS)
.toDate())) {
LOGGER.warn("Execution with id: {} is inactive, stopping",
execution.getId());
execution.setExitStatus(new ExitStatus(BatchStatus.FAILED.name(),
String.format("Stopped due to being inactive for %d seconds", seconds)));
execution.setStatus(BatchStatus.FAILED);
execution.setEndTime(now.toDate());
jobRepository.update(execution);
}
}
}
And then the jobs are ran by the following on all servers:
#Scheduled(cron = "${email.cron}")
public void sendEmails() {
jobRunner.run(emailJob);
}
Is this a valid solution for a multiple server setup? If not, what are the alternatives?
EDIT 1
I've did a bit more testing - setup two applications which run a #Schedule every 5 seconds that initiates a job using the helper class I created. It seems that my solution does not resolve the problem. Here is the data from batch_job_execution table that is used by spring batch:
job_execution_id | version | job_instance_id | create_time | start_time | end_time | status | exit_code | exit_message | last_updated | job_configuration_location
------------------+---------+-----------------+-------------------------+-------------------------+-------------------------+-----------+-----------+--------------+-------------------------+----------------------------
1007 | 2 | 2 | 2016-08-25 14:43:15.024 | 2016-08-25 14:43:15.028 | 2016-08-25 14:43:16.84 | COMPLETED | COMPLETED | | 2016-08-25 14:43:16.84 |
1006 | 1 | 2 | 2016-08-25 14:43:15.021 | 2016-08-25 14:43:15.025 | | STARTED | UNKNOWN | | 2016-08-25 14:43:15.025 |
1005 | 2 | 2 | 2016-08-25 14:43:10.326 | 2016-08-25 14:43:10.329 | 2016-08-25 14:43:12.047 | COMPLETED | COMPLETED | | 2016-08-25 14:43:12.047 |
1004 | 2 | 2 | 2016-08-25 14:43:10.317 | 2016-08-25 14:43:10.319 | 2016-08-25 14:43:12.03 | COMPLETED | COMPLETED | | 2016-08-25 14:43:12.03 |
1003 | 2 | 2 | 2016-08-25 14:43:05.017 | 2016-08-25 14:43:05.02 | 2016-08-25 14:43:06.819 | COMPLETED | COMPLETED | | 2016-08-25 14:43:06.819 |
1002 | 2 | 2 | 2016-08-25 14:43:05.016 | 2016-08-25 14:43:05.018 | 2016-08-25 14:43:06.811 | COMPLETED | COMPLETED | | 2016-08-25 14:43:06.811 |
1001 | 2 | 2 | 2016-08-25 14:43:00.038 | 2016-08-25 14:43:00.042 | 2016-08-25 14:43:01.944 | COMPLETED | COMPLETED | | 2016-08-25 14:43:01.944 |
1000 | 2 | 2 | 2016-08-25 14:43:00.038 | 2016-08-25 14:43:00.041 | 2016-08-25 14:43:01.922 | COMPLETED | COMPLETED | | 2016-08-25 14:43:01.922 |
999 | 2 | 2 | 2016-08-25 14:42:55.02 | 2016-08-25 14:42:55.024 | 2016-08-25 14:42:57.603 | COMPLETED | COMPLETED | | 2016-08-25 14:42:57.603 |
998 | 2 | 2 | 2016-08-25 14:42:55.02 | 2016-08-25 14:42:55.023 | 2016-08-25 14:42:57.559 | COMPLETED | COMPLETED | | 2016-08-25 14:42:57.559 |
(10 rows)
I also tried the method provided by #Palcente, I've got similar results.
Spring Integration's latest release added some functionality around distributed locks. This is really what you'd want to use to make sure that only one server fires the job (only the server that obtains the lock should launch the job). You can read more about Spring Integration's locking capabilities in the documentation here: http://projects.spring.io/spring-integration/

How to answer all SIP Calls automatically in Java

I want automatically answer all sip calls.
When I respond with trying or ringing, the transaction is in a proceeding state,
but when I send the OK response, the transaction is in a terminated state.
This is my code:
public void processRequest(RequestEvent requestReceivedEvent)
{
Address contactAddress = myAddressFactory.createAddress("sip:" + myIP + ":" + myPort);
myContactHeader = myHeaderFactory.createContactHeader(contactAddress);
Request req = requestReceivedEvent.getRequest();
myGUI.display("<<< " + req.toString());
String method = req.getMethod(); //bad request type.
FromHeader from = (FromHeader) req.getHeader("From");
Response response = null;
try
{ //Reply with OK
response = myMessageFactory.createResponse(200, req);
ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
toHeader.setTag("888"); //Identifier, specific to your application
ServerTransaction st = mySipProvider.getNewServerTransaction(req);
response.addHeader(myContactHeader);
st.sendResponse(response);
System.out.println("Ok response: " + st.getState());
}
catch (Exception e)
{
e.printStackTrace();
}
}
Thanks in advance.
INVITE server transactions to go terminated state after 200 OK. It's normal. Your call is answered and you shouldn't worry about it.
(see diagram of state machine from RFC)
|INVITE
|pass INV to TU
INVITE V send 100 if TU won't in 200ms
send response+-----------+
+--------| |--------+101-199 from TU
| | Proceeding| |send response
+------->| |<-------+
| | Transport Err.
| | Inform TU
| |--------------->+
+-----------+ |
300-699 from TU | |2xx from TU |
send response | |send response |
| +------------------>+
| |
INVITE V Timer G fires |
send response+-----------+ send response |
+--------| |--------+ |
| | Completed | | |
+------->| |<-------+ |
+-----------+ |
| | |
ACK | | |
- | +------------------>+
| Timer H fires |
V or Transport Err.|
+-----------+ Inform TU |
| | |
| Confirmed | |
| | |
+-----------+ |
| |
|Timer I fires |
|- |
| |
V |
+-----------+ |
| | |
| Terminated|<---------------+
| |
+-----------+
Figure 7: INVITE server transaction

Connection to the DataBase lost after X seconds of inactivity

I have this error after 20-30 minutes of inactivity
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 2.383.932 milliseconds ago.
The last packet sent successfully to the server was 21.351 milliseconds ago.
I have checked Data Base options,but they are ok
mysql> show session variables like '%timeout%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| slave_net_timeout | 3600 |
| table_lock_wait_timeout | 50 |
| wait_timeout | 28800 |
+----------------------------+-------+
10 rows in set (0.00 sec)
mysql> show global variables like '%timeoout%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| slave_net_timeout | 3600 |
| table_lock_wait_timeout | 50 |
| wait_timeout | 28800 |
+----------------------------+-------+
10 rows in set (0.00 sec)
Connection class:
public class ConnectionDB {
Connection con;
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://XXXXXXXXXX:3306/";
String nomeutente = "XXXXXXX";
String password = "XXXXXXXX";
String nomedatabase = "XXXXXX";
public Boolean ok = false;
public Connection connect(){
try {
Class.forName(driver);
con = DriverManager.getConnection(url+nomedatabase,nomeutente,password);
ok = true;
return con;
} catch (ClassNotFoundException | SQLException e) {
new ErrorLog();
e.printStackTrace();
ok = false;
return null;
}
}
}

Categories