# spring-cloud-demo **Repository Path**: beyond-prototype/spring-cloud-demo ## Basic Information - **Project Name**: spring-cloud-demo - **Description**: spring-cloud-demo - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2018-06-30 - **Last Updated**: 2022-08-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # spring-cloud-demo #### Description spring-cloud-demo #### Software Architecture Software architecture description #### Installation 1. Derby Database 10.14 set DERBY_HOME to the floder where Derby database is installed e.g. /home/xwp/derby-10.14.2.0 2. Maven 3.3.9 3. JDK1.8 #### Instructions #### 1. start Derby database server ``` bash xwp@ubuntu:~/cngit/spring-cloud-demo$ java -jar $DERBY_HOME/lib/derbyrun.jar server start ``` #### 2. create database and tables ``` bash xwp@ubuntu:~/cngit/spring-cloud-demo$ java -jar $DERBY_HOME/lib/derbyrun.jar ij ``` ``` bash ij version 10.14 ij> connect 'jdbc:derby://localhost:1527/derby_database;create=true;user=derby;password=derby;'; ij> run '/home/xwp/cngit/spring-cloud-demo/spring-cloud-auth-server/oauth2_db.sql'; ``` #### 3. build the applications ``` bash xwp@ubuntu:~/cngit/spring-cloud-demo$ mvn dependency:tree xwp@ubuntu:~/cngit/spring-cloud-demo$ mvn clean package ``` ```bash [INFO] spring-cloud-demo 1.0-SNAPSHOT ..................... SUCCESS [ 1.192 s] [INFO] spring-cloud-service-customer ...................... SUCCESS [ 2.033 s] [INFO] spring-cloud-auth-server ........................... SUCCESS [ 0.973 s] [INFO] spring-cloud-server ................................ SUCCESS [ 0.393 s] [INFO] spring-cloud-service-registry ...................... SUCCESS [ 0.398 s] [INFO] spring-cloud-zuul 1.0-SNAPSHOT ..................... SUCCESS [ 0.682 s] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ ``` #### deploy eureka server (service-registry) ```bash xwp@ubuntu:~$ cd /home/xwp/cngit/spring-cloud-demo java -jar $DERBY_HOME/lib/derbyrun.jar server start > /dev/null 2>&1 & java -Dserver.port=8763 -jar delivery/spring-cloud-service-registry-1.0-SNAPSHOT.jar > /dev/null 2>&1 & java -Dserver.port=9999 -jar delivery/spring-cloud-auth-server-1.0-SNAPSHOT.jar > /dev/null 2>&1 & java -Dserver.port=9020 -Ddemo.sleepInMilliseconds=2000 -Ddemo.alwaysException=true -jar delivery/spring-cloud-service-account-1.0-SNAPSHOT.jar > /dev/null 2>&1 & java -Dserver.port=9021 -Ddemo.sleepInMilliseconds=4000 -Ddemo.alwaysException=false -jar delivery/spring-cloud-service-account-1.0-SNAPSHOT.jar > /dev/null 2>&1 & java -Dserver.port=9022 -Ddemo.sleepInMilliseconds=500 -Ddemo.alwaysException=true -jar delivery/spring-cloud-service-account-1.0-SNAPSHOT.jar > /dev/null 2>&1 & java -Dserver.port=9010 -jar delivery/spring-cloud-service-customer-1.0-SNAPSHOT.jar > /dev/null 2>&1 & java -Dserver.port=9011 -jar delivery/spring-cloud-service-customer-1.0-SNAPSHOT.jar > /dev/null 2>&1 & java -Dserver.port=9000 -jar delivery/spring-cloud-zuul-1.0-SNAPSHOT.jar > /dev/null 2>&1 & java -Dserver.port=9090 -jar delivery/spring-cloud-dashboard-1.0-SNAPSHOT.jar > /dev/null 2>&1 & java -Dserver.port=9100 -jar delivery/spring-cloud-turbine-1.0-SNAPSHOT.jar > /dev/null 2>&1 & ``` http://localhost:9010/customer/pao/accounts?region=China #### deploy zuul gateway cd /home/xwp/cngit/spring-cloud-demo/spring-cloud-zuul mvn spring-boot:run ### Canary testing deploy customer-service for cd /home/xwp/cngit/spring-cloud-demo/spring-cloud-service-customer note: assume maven repository is /home/tools/maven/repository/, please change according to your local development environment cd /home/tools/maven/repository/demo/spring-cloud-service-customer/1.0-SNAPSHOT java -jar -Dspring.application.name=customer-service -Dserver.port=8093 -Dmanagement.port=58093 -DluckyWord=Canary-Instance -Deureka.instance.metadata-map.gated-launch=true spring-cloud-service-customer-1.0-SNAPSHOT.jar #### Testing (username=user,password=abcd) 1) Canary testing, put the below URL in browser http://localhost:9000/customer/greeting?name=Pao®ion=China Expected result: Hello Pao:) [China] Welcome to customer service : Canary-Instance 2) Timeout testing & hytrix testing http://localhost:9000/customer/greeting?name=Pao®ion=US Expected result: customer-service is unavailable 3) Normal case http://localhost:9000/customer/greeting?name=Pao®ion=UA Expected result: Hello Pao:) [UA] Welcome to customer service : Greeting from Config Server @@ ## Ribbon - load balance ## Account-Service ### 1. define account-service application configuration /spring-cloud-service-account/src/main/resources/application.yml ``` yml server: port: 9020 spring: application: name: account-service demo: region: UK ``` ### 2. define account-service configuration class ```java @ConfigurationProperties(prefix="demo") @Getter @Setter public class Configuration { private String region; } ``` ### 3. define the account-service Application @EnableConfigurationProperties(Configuration.class) ```java @SpringBootApplication @RestController @EnableConfigurationProperties(Configuration.class) public class Application { @Autowired private Configuration configuration; @RequestMapping("/") public String home() { return "Account-Service [region]: " + configuration.getRegion(); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` ### 4. define the AccountServiceController ```java @RestController @RequestMapping("/account") public class AccountServiceController { Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private Configuration configuration; @RequestMapping(value="/list/{name}") public ResponseEntity getAccountsByCustomerName(@PathVariable String name) { List accounts = new ArrayList(); accounts.add(new Account("1",10000D, configuration.getRegion())); return ResponseEntity.ok(accounts); } @RequestMapping(value="/list") public ResponseEntity getAccountsByCustomerName(@RequestParam String name,@RequestParam String region) throws Exception{ logger.info("account service is called.....region:{}",region); //simulate exception if("UK".equals(region)){ throw new Exception("Unsupported region :" + region); } else if("US".equals(region)){ try{ Thread.sleep(5000L); }catch(InterruptedException e){ logger.info("Wake up from sleep: " + region); } } else if("UA".equals(region)){ try{ Thread.sleep(1000L); }catch(InterruptedException e){ logger.info("Wake up from sleep: " + region); } } return getAccountsByCustomerName(name); } } @Data class Account{ String id; Double balance; String region; public Account(String id, Double balance,String region) { this.id = id; this.balance = balance; this.region = region; } } ``` ### 5. Run multiple instances for load balance #### 5.1 UK instance on port 9020 ``` bash xwp@ubuntu:~/cngit/spring-cloud-demo$ nohup java -Dserver.port=9020 -Ddemo.region=UK -jar delivery/spring-cloud-service-account-1.0-SNAPSHOT.jar > /dev/null 2>&1 & ``` You can access it using URL: http://localhost:9020/account/list?name=Pao®ion=China ``` json [ { "id": "1", "balance": 10000, "region": "UK" } ... ] ``` #### 5.2 CN instance on port 9021 ```bash xwp@ubuntu:~/cngit/spring-cloud-demo$ nohup java -Dserver.port=9021 -Ddemo.region=CN -jar delivery/spring-cloud-service-account-1.0-SNAPSHOT.jar > /dev/null 2>&1 & ``` You can access it using URL: http://localhost:9021/account/list?name=Pao®ion=China ``` json [ { "id": "1", "balance": 10000, "region": "CN" } ... ] ``` ### Customer Service (spring-cloud-service-customer) Customer Service will call Account Service using Ribbon load balancing #### 1. Add dependency to pom.xml ``` xml org.springframework.cloud spring-cloud-starter-ribbon ``` #### 2. Add account-service ribbon client in application.yml /spring-cloud-service-customer/src/main/resources/application.yml ```yml account-service: ribbon: eureka: enable: false listOfServers: localhost:9020,localhost:9021 ServerListRefreshInterval: 15000 ``` The object that needs to access the account-service should enable @RibbonClient annotation @RibbonClient(name = "account-service") The account service can be accessed by VIP URL below URL: http://account-service/account/list?name=Pao®ion=China #### 3. Define CustomerServiceApplication Create RestTemplate using @LoadBalanced ``` java @SpringBootApplicatione @EnableConfigurationProperties(CustomerServiceConfiguration.class) public class CustomerServiceApplication { @Autowired private CustomerServiceConfiguration configuration; @LoadBalanced @Bean RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(CustomerServiceApplication.class, args); } ``` #### 4. define CustomerServiceController ```java @RestController @RequestMapping("/customer") @RibbonClient(name = "account-service") public class CustomerServiceController { Logger logger = LoggerFactory.getLogger(getClass()); @Autowired RestTemplate restTemplate; @RequestMapping(value="/{name}/accounts") public ResponseEntity getAccounts(@PathVariable String name,@RequestParam String region) { logger.info("******customer service - getAccounts is called.....region:{}",region); List accounts = this.restTemplate.getForObject("http://account-service/account/list?name={name}®ion={region}", ArrayList.class,name,region); return ResponseEntity.ok(accounts); } } ``` @RibbonClient(name = "account-service") this.restTemplate.getForObject("http://account-service/account/list?name=Pao®ion=China", ArrayList.class); ```bash xwp@ubuntu:~/cngit/spring-cloud-demo$ nohup java -jar delivery/spring-cloud-service-customer-1.0-SNAPSHOT.jar > /dev/null 2>&1 & ``` #### 5. Access customer service to get accounts ```bash xwp@ubuntu:~/cngit/spring-cloud-demo$ nohup java -Dserver.port=9010 -Ddemo.region=CN -jar delivery/spring-cloud-service-customer-1.0-SNAPSHOT.jar > /dev/null 2>&1 & ``` http://localhost:9010/customer/pao/accounts?region=China 1) response from CN account-service instance ```json [ { "id": "1", "balance": 10000, "region": "CN" } ... ] ``` 2) response from UK account-service instance ```json [ { "id": "1", "balance": 10000, "region": "UK" } ... ] ``` ### SSL (HTTPS) #### 1. Create SSL cert ``` bash xwp@ubuntu:~/cngit/spring-cloud-demo$ keytool -genkeypair -alias spring-cloud-demo -keyalg RSA -keystore ./spring-cloud-demo.key Enter keystore password: changeit Re-enter new password: What is your first and last name? [Pao]: Pao Xu What is the name of your organizational unit? [demo]: org-unit What is the name of your organization? [demo-org]: org What is the name of your City or Locality? [guangzhou]: guangzhou What is the name of your State or Province? [guangdong]: guangdong What is the two-letter country code for this unit? [CN]: CN Is CN=Pao Xu, OU=org-unit, O=org, L=guangzhou, ST=guangdong, C=CN correct? [no]: yes Enter key password for (RETURN if same as keystore password): changeit Re-enter new password: Warning: The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore ./spring-cloud-demo.key -destkeystore ./spring-cloud-demo.key -deststoretype pkcs12". ``` #### 2. place spring-cloud-demo.key to project root folder spring-cloud-service-customer/spring-cloud-demo.key #### 3. Update application.yml spring-cloud-service-customer/src/main/resources/application.yml ``` yml server: port: 8443 ssl: key-store: spring-cloud-demo.key key-store-type: JKS key-alias: spring-cloud-demo key-store-password: changeit ``` #### 4. Define HTTP Connector (optional) Redirect request from http port (8080) to https port 8443 ``` java @Bean public Connector httpConnector(){ Connector connector=new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setScheme("http"); connector.setPort(8080); connector.setSecure(false); connector.setRedirectPort(8443); return connector; } ``` #### Test in browser https://localhost:8443/customer/greeting?name=Pao®ion=UA ```html Hello Pao:) [UA] Welcome to customer service : Greeting from Config Server @@ ``` #### Reference https://curl.haxx.se/docs/sslcerts.html