Más contenido relacionado La actualidad más candente (20) Similar a Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか (20) Más de Yoshitaka Kawashima (15) Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか8. NullPointerExceptionの典型例
HttpSession session = request.getSession();
User user = session.getAttribute("user");
if (user.isAdmin()) {
// ...
}
ここでNullPointerException発生
引数なしでgetSessionを呼ぶのでセッションがない
場合は空のものが作られる
空のSessionの場合、userはnullになる。
9. Guard against null
HttpSession session = request.getSession(false);
if (session == null) {
response.sendRedirect(LOGIN_URL);
return;
}
User user = session.getAttribute("user");
if (user == null) {
response.sendRedirect(LOGIN_URL);
return;
}
if (user.isAdmin()) {
// ...
}
nullガード戦法
Java有史以来、最も多く使われている戦術だが、
ガードの漏れが検出しにくく、実際それが本番障害の
原因としてたびたび登場している
11. Optionalの意義
User user = Optional
.ofNullable(request.getSession(false))
.map(session -> session.getAttribute("user"))
.orElse(new AnonymousUser());
if (user.isAdmin()) {
// ...
}
Operation中にnullが出現しうる一連の操作を、
Optionalで包みこむこと
14. Default method
●
インタフェースに実装が持てるようになった
●
インスタンス変数は当然ながら持てない
default void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}
17. Mixin using default methods
public interface Traceable {
Logger LOG = LoggerFactory
.getLogger(Traceable.class);
default void writeLog() {
LOG.info(toString());
}
}
こういうインタフェースを用意して、implementsすれば、
writeLogメソッドが使えるようになる。
19. private Map<String, Object> extensions;
@Override
public void setExtension(String name, Object extension) {
if (extensions == null) {
extensions = new HashMap<>();
}
extensions.put(name, extension);
}
@Override
public Object getExtension(String name) {
if (extensions == null) {
extensions = new HashMap<>();
}
return extensions.get(name);
}
It's not beautiful, but pragmatic.
実装をこんな感じにすれば、データを持つMixinが実現可能
30. Enkanフレームワークの擬似REPL
enkan> /middleware app list
ANY defaultCharset (enkan.middleware.DefaultCharsetMiddleware
NONE serviceUnavailable (enkan.middleware.ServiceUnavailableM
ANY stacktrace (enkan.middleware.StacktraceMiddleware@545872d
enkan> /middleware app predicate serviceUnavailable ANY
enkan> /middleware app list
ANY defaultCharset (enkan.middleware.DefaultCharsetMiddleware
ANY serviceUnavailable (enkan.middleware.ServiceUnavailableMi
ANY stacktrace (enkan.middleware.StacktraceMiddleware@545872d
REPL上からMiddlewareの適用条件を操作できる
https://enkan.github.io/
33. Try Artifact
JShellの中で、Mavenの依存関係を動的に解決し、その
機能を試してみることができる。
-> /resolve org.apache.commons:commons-lang3:jar:3.4
| Path /home/kawasima/.m2/repository/org/apache/commons/commons-
lang3/3.4/commons-lang3-3.4.jar added to classpath
->
org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric(10)
| Expression value is: "peXXUYGin6"
| assigned to temporary variable $1 of type String
https://github.com/kawasima/try-artifact
現段階でのJShellカスタマイズ事例
40. SO_REUSEPORT in Jetty
class ReusePortAvailableConnector extends ServerConnector {
public ReusePortAvailableConnector(@Name("server") Server server) {
super(server);
}
@Override
public void open() throws IOException {
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.setOption(StandardSocketOptions.SO_REUSEPORT, true);
InetSocketAddress bindAddress = getHost() == null ? new
InetSocketAddress(getPort()) : new InetSocketAddress(getHost(), getPort());
serverChannel.socket().setReuseAddress(getReuseAddress());
serverChannel.socket().bind(bindAddress, getAcceptQueueSize());
serverChannel.configureBlocking(true);
addBean(serverChannel);
try {
Field acceptChannel = ServerConnector.class
.getDeclaredField("_acceptChannel");
acceptChannel.setAccessible(true);
acceptChannel.set(this, serverChannel);
} catch (Exception ex) {
throw new IOException(ex);
41. Falchion container
● JVMプロセスのコンテナ
● Anotherプロセスが起動するのを待ってから、古い
JVMプロセスをKillできる。
● SO_REUSEPORTとの組合せで、リクエストをロストす
ることなく、論理的なアプリケーションの再起動が
可能になる。
https://github.com/kawasima/falchion
experimental
42. Falchion Container
Falchion container architecture
JVM real process
WebApplication
JVM pool
JVM virtual process
JVM virtual process
JVM real process
WebApplication
Listen the same port
46. JVM auto tuning
● JVMのパラメータを少しづつ変えながら、性能の変
化を計測する。
●
最適なものを選択
– Full GC countを最小に
– 1回あたりのFull GC Timeが最長のものが一番短く
(Full GC Timeのマクシミン)
JVMコンテナの活用可能性
56. ルールの実装例
public class DiscountInMorningOrEvening implements DiscountRule {
private RulePeriod morning = new RulePeriod(6, 9);
private RulePeriod evening = new RulePeriod(17, 20);
@Override
public boolean isApplicable(HighwayDrive drive) {
return ((!morning.isHoliday(drive) && morning.isIn(drive))
|| (!evening.isHoliday(drive) && evening.isIn(drive)))
&& drive.getRouteType() == RouteType.RURAL;
}
@Override
public long discountPercentage(HighwayDrive drive) {
int count = drive.getDriver().getCountPerMonth();
if (count >= 10) {
return 50;
} else if (count >= 5){
return 30;
} else {
return 0;
}
57. YAGNI has come to Java
運用の大変さ(のイメージ)から、過剰設計になりがち
だったJavaの世界も、今必要なものだけを設計し作れ
ばよい時代に