Breaking Apart the Monolith with Modularity and … Apart the Monolith with Modularity and...
Transcript of Breaking Apart the Monolith with Modularity and … Apart the Monolith with Modularity and...
Breaking Apart the Monolith with Modularity and Microservices CON3127
Neil Griffin Software Architect, Liferay Inc. Specification Lead, JSR 378 Portlet 3.0 Bridge for JavaServer™ Faces 2.2
Michael Han Vice President of Operations, Liferay, Inc.
Presenter: Neil Griffin• Liferay Faces project lead
• Contributing Author, JSF 2.0 Complete Reference
• Specification Lead for JSR 378
• Liferay JCP Representative • JSR 362 (Portlet 3.0) • JSR 372 (JSF 2.3)
Presenter: Michael Han• Vice President of Operations
• Responsible for benchmarking and performance management of Liferay's product lines
• Senior Architect of large-scale distributed systems
Componentized via Independently Deployable Services
Designed for Failure, not against Failure
Services are Independently Scalable
Great! How do I get there?
Microservices
What do we mean when we use the word “modularity”?
Standards for modularity in Java:
JSR 376: JavaTM Platform Module System (Project JigSaw)
(Available with JDK 9)
OSGiTM
Modularity
Several attempts have been made to define a maturity model for modularity, for example:http://enroute.osgi.org/appnotes/modularity-maturity-model.html
This presentation describes three basic levels of modularity for a Java application:
Level 1: Monolithic (No modularity)
Level 2: Composite (Reusable dependencies)
Level 3: Dynamic (OSGi)
Types of Modularity
The simplest way to develop a Java application is to develop a monolith
Single artifact that contains a large compiled codebase
Level 1: Monolithic Application
.war
WEB-INF/classes/CustomerService.classCustomerServiceImpl.classProductService.classProductServiceImpl.classPurchaseService.classPurchaseServiceImpl.class…
Drawbacks:Services are not reusable outside the applicationService API cannot be versioned on its own release scheduleAll classes are loaded into the same servlet context ClassLoaderNo boundaries between the application, Service API and Service Implementation
Demo & Code Review: Monolith
Class.forName( “com.liferay.store.monolith.customer.service.CustomerServiceImpl”)
It works!
In order to overcome the drawbacks of a monolith, develop a composite application
Package services into separate .jar artifacts
Include each .jar as an embedded dependency
Level 2: Composite Applications.jar .jar
.jar .jar
.war
Build tools like Maven or Gradle can help to achieve the goal of having independently versioned artifacts
Each artifact can be on an independent release schedule
Artifacts can be published to an artifact repository like Maven Central
Build ToolsMavenTM
GradleTM
Benefits:Minimal code in WEB-INF/classes
Versioned services can be embedded as dependencies
Drawbacks:All classes are still loaded into the same servlet context ClassLoaderNot designed to anticipate failureStill no boundaries between the application, Service API and Service Implementation
Demo & Code Review: Composite
It still works!
Class.forName( “com.liferay.store.monolith.customer.service.CustomerServiceImpl”)
In order to overcome the drawbacks of a composite application, develop a dynamic modular application
Package services into separate .jar artifacts
Deploy each .jar as an OSGi bundle that runs in its own ClassLoader
Level 3: Dynamic Modularity
bund
le.ja
r
bund
le.ja
r
bund
le.ja
r
bund
le.ja
r
wab.war
OSGi Runtime
OSGi is an open standard that achieves the goal of modularity for Java
Modules are defined as simple .jar artifacts called OSGi bundles
Each bundle runs in its own ClassLoader
Bundles communicate via services that are published in the OSGi service registry
OSGi
OSGi core framework implementations are available in open source
Popular Core Framework Implementations:
Felix (Apache)Equinox (Eclipse)
OSGi Implementations
OSGi bundles are plain old JAR files that contain additional information in META-INF/MANIFEST.MF
OSGi Bundles
OSGi Bundle
Manifest-Version: 1.0 Bundle-SymbolicName: com.liferay.store.customer Export-Package: com.liferay.store.customer.model;version="1.0.0",com.l iferay.store.customer.service;uses:="com.liferay.store.customer.model ";version="1.0.0" Bundle-Name: com.liferay.store.customer Bundle-Version: 1.0.0
The API of an OSGi bundle is defined at the level of Java packages
Bundle API
Manifest-Version: 1.0 Bundle-SymbolicName: com.liferay.store.customer Export-Package: com.liferay.store.customer.model;version="1.0.0",com.l iferay.store.customer.service;uses:="com.liferay.store.customer.model ";version="1.0.0" Bundle-Name: com.liferay.store.customer Bundle-Version: 1.0.0
-exportcontents: \ com.liferay.store.customer.model, \ com.liferay.store.customer.service
bnd.bnd (source)
MANIFEST.MF (generated)
OSGi bundles communicate with each other via services made available by dependency injection
Services are published in the OSGi service registry
OSGi Services
OSGi OSGi @Reference
(dependency injection)(service provider) (service consumer)
Since OSGi bundles are dynamic (can be deployed and un-deployed dynamically), services can come and go at any time
Programing for Failure:
Declarative Services
Service Tracker
Bundle Dynamism
.warThe Servlet Specification requires that the classes for each webapp (servlet context) be loaded into its own ClassLoader
This offers a degree of dynamism:Copy the .war to tomcat/webapps to deployDelete the webapp context to un-deployCopy the .war to tomcat/webapps to re-deploy
Dynamism is a Familiar Concept context-1/
tomcat/webapps/
context-n/
…context-2/
Benefits:Minimal code in WEB-INF/classesVersioned services can be deployed as OSGi bundlesEach bundle runs in a separate ClassLoaderStrict boundaries between the application, Service API, and Service ImplementationModules are dynamic (can come and go at any time)
Demo & Code Review: Dynamic
It doesn’t work!No embedded service
jars! Class.forName( “com.liferay.store.monolith.customer.service.CustomerServiceImpl”)
OSGi: Services and injectable dependencies are discovered by the build-time system and satisfied at deploy time
OSGi Compared to CDI/Spring@Component(immediate = true, service = PurchaseService.class)public class PurchaseServiceImpl implements PurchaseService {
@Referenceprivate CustomerService customerService;
@Referenceprivate ProductService productService;...
}
Spring/CDI: Services and injectable dependencies are discovered and satisfied at deploy time by classpath scanning
bnd-maven-plugin
service implementation
service dependency
service dependency
OSGi runtimes can contain numerous bundles in a single JVM which can be referred to as “In-JVM” microservicesBenefits:
Although you program for failure, it does not have the drawbacks of a distributed systemBundles and service APIs are strictly versionedBundles will NOT be activated at deploy time unless all service dependencies can be satisfiedDirect method invocations and POJOs rather than invoking remote services and processing JSON or XMLLess vulnerable to security attacks since service invocations do not go across the network
Drawbacks:Heavily utilized services can cause a performance impact on other services since they are in the same JVM
Step 1: In-JVM Microservices
Publish services as remote servicesAdd service properties: service.exported.interfaces, service.exported.configsService Consumers have no knowledge whether service is remote or not
See Apache CXF DOSGi and Eclipse ECFhttps://en.wikipedia.org/wiki/Fallacies_of_distributed_computing
Step 2 – Distributed OSGi
Runtime Platform Must ProvideService Fault ToleranceAuto ScalingPlatform Services
Centralized Log ManagementCentralized monitoring
Meso, Kubernetes, CloudFoundry, WeDeploy, etc
Step 3 – Microservices Platform
Case Study: Liferay Digital Enterprise
Liferay Portal 6.2 CE and EEWeb Content Management, Document Management and Collaboration, Workflow and Forms etcProprietary WAR based modular system for extensions
Liferay Portal 7.0 and Digital Enterprise 7.04 Subsystems: WEM, Collaboration, Forms and Workflow, Platform500+ modules (JAR)
Case Study: Liferay DXP
Next StepsImplemented Distributed OSGi Runtime
Integrate Distributed OSGi Runtime into PaaS Platform Wedeploy.com – Liferay’s PaaS PlatformKubernetes, OpenShift, CloudFoundry
major.minor.patch
major = breaking changes
minor = new feature release
patch = bug fixes
Minor & patch versions are guaranteed to be binary backward compatible!
Semantic Versioningcom.mycompany.mybundle-1.0.0.jar
com.mycompany.mybundle-1.0.1.jar
com.mycompany.mybundle-1.1.0.jar
Reporting and enforcement of semantic versioning rules can be accomplished with the help of Bndtools at build-time
Semantic Versioning (Reporting)
mvn bundle:baseline maven-bundle-plugin
Thank You• Liferay and Liferay Faces are trademarks or registered trademarks of Liferay, Inc. • Java Community Process and JCP are service marks of Oracle Corporation in the United States and in other
countries • Java, Java EE, JavaOne, JVM, and JavaServer are trademarks or registered trademarks of Oracle Corporation in
the United States and in other countries • OSGi is a trademark of The OSGi Alliance • Apache Maven is a trademark of The Apache Software Foundation • "Tomcat" is a registered trademark of the Apache Software Foundation. "Apache Tomcat" and the Apache
Tomcat project logo are trademarks of the Apache Software Foundation. • Gradle is a trademark of Gradle, Inc. in the United States and/or other jurisdictions • Payara is a trademark of Payara Services Limited and all its affiliates • Spring Boot is a trademark of Pivotal Software, Inc. in the U.S. and other countries • All other trademarks mentioned herein are the property of their respective owners