During website development, you have probably already experienced following situation:
Make significant changes to website CSS
Deploy changed CSS to webserver / app server
Verify changed resource by navigating to website an pressing “Reload”
Everything looks allright, you pack your bags and head home
And the story continues… You arrive home and you realize, that your CSS is not refreshed. What happened
wrong? You start to investigate. Then you realize, that the resource was cached by your browser and
doesn’t change on a simple page request, because you are using a long resource expiration.
Handling resource cache expiration
What if you just decrease duration of cache expiration? You will not use never, but browser clients will
redownload your resources every day.
This change shuld be very straight forward. Depending on your technology stack, you just provide
correct configuration. In nginx, one day resource expiration would look like this:
location ~* \.(css)$ {
expires 1d;
}
As you can see, it is not very flexible. Either you must always conform to a common filename pattern,
or you will always have to enumerate all your resources by hand. What if you want to see changed resources
in that instant without too much hassle?
Append URL query parameter to your resource
By adding a changing query parameter to your resource’s URL you solve these 2 issues,
which were present with previous solution:
Resources expire at fixed interval and browser is force to reload them even if they didn’t change
Cache expiry configuration changes between different technology stacks
Let’s put it to the test. Create a website and add a <link> to your CSS in the <head> section.
If you look into this website sources, you will see following stylesheet declaration:
Notice the 201405190923 parameter in the end. It’s the date and time of last build.
Every frontend technology handles resource output differently, but all have one thing in common:
Stylesheet resource is linked to the website by a URL. Guess what? You should have full control
over this URL in all frontend stacks.
By defining a variable, which changes only from build to build, you have fine grained control
over stylesheet resources expiration, which now expire as you please and you can distribute them with “Never”
expiry policy.
Recently, we had an error in our production system. Replication on MySQL Slave failed.
It was not caused by a bug, but by an unexpected Slave server restart of the whole machine.
After checking SHOW SLAVE STATUS\G we got scared, that Master’s binlog is also corrupt,
which happened not so long ago - MySQL Bug #7022.
Fortunately, Master’s binlog was intact, so we moved back to Slave, to solve the problem (removed MySQL noise for brevity):
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
...
Slave_IO_Running: Yes
Slave_SQL_Running: No
...
Last_Errno: 1594
Last_Error: Relay log read failure: Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log), the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's MySQL code. If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE
...
Executed_Gtid_Set: 3aabcfda-591d-11e3-81f1-0050569a4585:1-14351185
Auto_Position: 1
1 row in set (0.00 sec)
You can see from the output, that we are using GTID replication,
which is available since MySQL 5.6. Transactions 1-14351185 were executed successfully, but the 14351186 got corrupt.
We tried to skip it by
committing an empty GTID transaction,
but that did not help.
What to do next? At this point I wanted to start crying, because multiple sites and tutorials suggest to
perform a clean mysqldump of Master, which will be copied to Slave.
That is “the correct” way of solving replication problems.
However, shutting down a site, just to perform a ~700GB database dump is not fun at all.
MySQL 5.6 replication variables
Browsing through the net reveals a small number of pages, which mention this secret GTID_PURGED variable.
I didn’t comprehend the meaning of this variable at first (straight from dev.mysql.com):
The set of all transactions that have been purged from the binary log.
But after some digging, it has definitely its place inside MySQL.
By changing the GTID_PURGED on Slave, we can inform the server about missing binary logs on Master, so Slave
starts replication from the next available transaction identifier. This way, we don’t have to perform a full
Master Slave backup. Just make sure, that binlogs, which you want to synchronize
are still present on Master.
Work your magic GTID_PURGED!
1.
Reset available replication information on Slave, so Slave forgets its own binlogs and Master’s relay logs.
mysql> RESET SLAVE;
mysql> RESET MASTER;
2.
Issue a command to reconfigure replication by pointing Slave to Master (which was cleared in previous step):
3.
We are ready to instruct Slave with information about deleted binlogs on Master, so Slave will not replicate them and
they will be skipped.
_The reason, why we want to skip some transactions, is because they were already replicated to Slave before._
mysql> SET global GTID_PURGED="3aabcfda-591d-11e3-81f1-0050569a4585:1-14351185";
4.
We are done with preparations. All, that is left to be done is to start the replication:
mysql> START SLAVE;
5.
And check if both Slave replication threads are doing their work without errors:
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
...
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...
Seconds_Behind_Master: 157717
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
...
Retrieved_Gtid_Set: 3aabcfda-591d-11e3-81f1-0050569a4585:14351185-14805026
Executed_Gtid_Set: 3aabcfda-591d-11e3-81f1-0050569a4585:1-14351185
Auto_Position: 1
1 row in set (0.00 sec)
MySQL is a great database, which solves problems it is meant to solve. New replication functionality
(GTID) however has it quirks when compared to the “old”
replication by master log coordinates.
Hopefully, this post will help others when solving similar problems with bringing replication back to life after Slave failure.
How do you make your Java EE application configurable? Do you use Maven profiles? Properties file? Environment properties?
If you have developed with JBoss 7 before, you have probably already heard about JBoss 7 System Properties.
They are usually specified in configuration file of mode specific directory, for example standalone, they are
persistent (live through server restarts) and can be configured, most usually via jboss-cli.
One of the great things about Java EE application development is its flexibility. Why not use this flexibility to
inject these properties into runtime?
In following lines you will see:
how to inject JBoss system properties into runtime
First, we need to define, how would our default access pattern look. Let’s leverage the @Inject annotation with a
custom @Qualifier:
@Inject@SystemProperty("example.foo")Stringfoo;
Now, let’s define the @SystemProperty annotation:
@Qualifier@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.PARAMETER,ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})public@interfaceSystemProperty{/**
* Full name of the system property, for example "user.home"
*/@NonbindingStringvalue();}
Note, that we do not define default "" next to our value(), since the property name should be always defined.
Therefore we automatically disallow usage of empty system property @SystemProperty().
And how will the System property get from JBoss to our little @SystemProperty annotated variable?
Let’s define a provider, who uses the @Produces annotation and provides our application with
concrete system properties:
publicclassSystemPropertyProvider{^@Produces@SystemProperty("")StringfindProperty(InjectionPointip){SystemPropertyannotation=ip.getAnnotated().getAnnotation(SystemProperty.class);Stringname=annotation.value();Stringfound=System.getProperty(name);if(found==null){thrownewIllegalStateException("System property '"+name+"' is not defined!");}returnfound;}}
Demonstration
After we have defined our deliver mechanism, we probably want to use our new @SystemProperty annotation.
Let’s define an example REST resource:
Deploy to JBoss 7 and hit http://localhost:8080/inject-jboss-system-properties/example.
But what happened? We are getting an exception:
java.lang.IllegalStateException: System property 'example.foo' is not defined!
sk.blahunka.jbossinject.properties.SystemPropertyProvider.findProperty(SystemPropertyProvider.java:15)
We forgot about our properties, to define them, we will use the good old jboss-cli.
On windows, fire up the jboss-cli.bat executable and type in:
connect
/system-property=example.foo:add(value="Special Foo Value")
/system-property=example.bar:add(value="Why is Foo so special?")
Then hit refresh in your browser and voila, our properties were injected: