簡介
通過上一節我們已經通過docker-compose在swarm中部署了有三個例項的高可用eureka服務註冊中心,本節我們討論一下,怎麼在建立一個spring cloud生產者,並用docker部署,並且把服務註冊到上一節的eureka叢集中。
一、建立服務提供者模組(microservice-provider-user)
程式碼結構如下
二、pom.xml檔案內容
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>microservice-consumer-movie</artifactId>
<groupId>com.jacky</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../microservice-consumer-movie/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>microservice-provider-user</artifactId>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--spring boot使用jpa需要引入的包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<executions>
<!--設定在執行maven 的install時構建映象-->
<execution>
<id>build-image</id>
<phase>install</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<!--安裝了docker的主機,並且開啟了api remote介面設定-->
<dockerHost>http://192.168.6.130:5678</dockerHost>
<pushImage>true</pushImage><!--設定上傳映象到私有倉庫,需要docker設定指定私有倉庫地址-->
<!--映象名稱-->
<imageName>${docker.repostory}/${docker.image.prefix}/${project.artifactId}:${project.version}</imageName>
<!--映象的基礎版本-->
<baseImage>java:openjdk-8-jdk-alpine</baseImage>
<!--映象啟動引數-->
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
</project>
複製程式碼
三、配置檔案:application.yml
server:
port: 7900
spring:
datasource:
url: jdbc:mysql://192.168.6.131:53306/sping-cloud-demo?useUnicode=true&characterEncoding=UTF-8
username: root
password: admin
schema: classpath:schema.sql
data: classpath:data.sql
jpa:
hibernate:
ddl-auto: none #每次啟動時不根據實體自動構建資料庫結構
naming:
strategy: org.hibernate.cfg.ImprovedNamingStrategy #實體和表的對映策略
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect #資料庫方言
show-sql: true
application:
name: microservice-provider-user #虛擬IP名稱 virtual Ip
#zipkin:
#base-url: http://127.0.0.1:7788
#日誌配置開始
logging:
level:
root: INFO
org.hibernate: INFO
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
com.itmuch: DEBUG
#日誌配置結束
#eureka配置開始
eureka:
client:
healthcheck:
enabled: true # 開啟健康檢查(需要spring-boot-starter-actuator依賴)
serviceUrl:
defaultZone: http://jacky:admin@peer1:8761/eureka/,http://jacky:admin@peer2:8762/eureka/,http://jacky:admin@peer3:8763/eureka/
instance:
prefer-ip-address: true # 開啟健康檢查(需要spring-boot-starter-actuator依賴)
lease-expiration-duration-in-seconds: 90 #續約到期時間(單位 S)預設是90S
lease-renewal-interval-in-seconds: 30 # 續約更新時間間隔(預設30秒)
instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
metadata-map:
zone: ABC # eureka可以理解的後設資料
lilizhou: BBC # 不會影響客戶端行為
#eureka配置結束
複製程式碼
四、使用者建表語句(schema.sql)
DROP TABLE IF EXISTS user;
create table user(
id INT NOT NULL AUTO_INCREMENT,
username varchar(40),
name varchar(20),
age int(3),
balance decimal(10,2),
primary key(id)
);
複製程式碼
五、測試資料(data.sql)
insert into user(id,username, name, age, balance) values(1,'user1', '張三', 20, 100.00);
insert into user(id,username, name, age, balance) values(2,'user2', '李四', 20, 100.00);
insert into user(id,username, name, age, balance) values(3,'user3', '王五', 20, 100.00);
insert into user(id,username, name, age, balance) values(4,'user4', '馬六', 20, 100.00);
複製程式碼
六、實體類(User.java)
package com.jacky.cloud.entity;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
public User(Long id, String username) {
super();
this.id = id;
this.username = username;
}
public User() {
super();
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String username;
@Column
private String name;
@Column
private Short age;
@Column
private BigDecimal balance;
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Short getAge() {
return this.age;
}
public void setAge(Short age) {
this.age = age;
}
public BigDecimal getBalance() {
return this.balance;
}
public void setBalance(BigDecimal balance) {
this.balance = balance;
}
}
複製程式碼
七、jpa-Repository類
package com.jacky.cloud.repository;
import com.jacky.cloud.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
複製程式碼
八、編寫UserController.java
package com.jacky.cloud.controller;
import java.util.ArrayList;
import java.util.List;
import com.jacky.cloud.entity.User;
import com.jacky.cloud.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.google.common.collect.Lists;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@Autowired
private EurekaClient eurekaClient;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/simple/{id}")
public User findById(@PathVariable Long id) {
return this.userRepository.findOne(id);
}
@GetMapping("/eureka-instance")
public String serviceUrl() {
InstanceInfo instance = this.eurekaClient.getNextServerFromEureka("MICROSERVICE-PROVIDER-USER", false);
return instance.getHomePageUrl();
}
@GetMapping("/instance-info")
public ServiceInstance showInfo() {
ServiceInstance localServiceInstance = this.discoveryClient.getLocalServiceInstance();
return localServiceInstance;
}
@PostMapping("/user")
public User postUser(@RequestBody User user) {
return user;
}
// 該請求不會成功
@GetMapping("/get-user")
public User getUser(User user) {
return user;
}
@GetMapping("list-all")
public List<User> listAll() {
ArrayList<User> list = Lists.newArrayList();
User user = new User(1L, "zhangsan");
User user2 = new User(2L, "zhangsan");
User user3 = new User(3L, "zhangsan");
list.add(user);
list.add(user2);
list.add(user3);
return list;
}
}
複製程式碼
九、修改docker-compose.yml檔案
version: "3"
services:
peer1: # 預設情況下,其他服務可以使用服務名稱連線到該服務。因此,對於eurekaService1的節點,它需要連線http://eurekaService2/3:951X/eureka/,因此需要配置該服務的名稱是eurekaService1。
image: 192.168.6.132:5000/jacky/microservice-discovery-eureka-ha:1.0-SNAPSHOT
deploy:
replicas: 1 #定義 replicated 模式的服務的複本數量
update_config:
parallelism: 1 #每次更新複本數量
delay: 2s #每次更新間隔
restart_policy:
condition: on-failure #定義服務的重啟條件
networks:
- eureka-net
ports:
- "8761:8761"
environment:
- spring.profiles.active=peer1
peer2: # 高可用eureka註冊節點2
image: 192.168.6.132:5000/jacky/microservice-discovery-eureka-ha:1.0-SNAPSHOT
deploy:
replicas: 1 #定義 replicated 模式的服務的複本數量
update_config:
parallelism: 1 #每次更新複本數量
delay: 2s #每次更新間隔
restart_policy:
condition: on-failure #定義服務的重啟條件
networks:
- eureka-net
ports:
- "8762:8762"
environment:
- spring.profiles.active=peer2
peer3: # 高可用eureka註冊節點3
image: 192.168.6.132:5000/jacky/microservice-discovery-eureka-ha:1.0-SNAPSHOT
deploy:
replicas: 1 #定義 replicated 模式的服務的複本數量
update_config:
parallelism: 1 #每次更新複本數量
delay: 2s #每次更新間隔
restart_policy:
condition: on-failure #定義服務的重啟條件
networks:
- eureka-net
ports:
- "8763:8763"
environment:
- spring.profiles.active=peer3
userService:
image: 192.168.6.132:5000/jacky/microservice-provider-user:1.0-SNAPSHOT
deploy:
replicas: 1 #定義 replicated 模式的服務的複本數量
update_config:
parallelism: 1 #每次更新複本數量
delay: 2s #每次更新間隔
restart_policy:
condition: on-failure #如果某個例項失敗,立即重啟容器
networks:
- eureka-net
ports:
- "7900:7900"
networks:
eureka-net: #網路名稱
driver: overlay
複製程式碼
十、父專案引入microservice-provider-user模組
十一、啟動類(MicroserviceSimpleProviderUserApplication.java)
package com.jacky.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class MicroserviceSimpleProviderUserApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceSimpleProviderUserApplication.class, args);
}
}
複製程式碼
十二、打包
然後在docker中就可以看到打包成功的映象
十三、利用docker-compose啟動服務提供者映象
把docker-compose.yml上傳到linux中,然後
[root@node1 docker-compose]# docker stack deploy -c docker-compose.yml eureka
複製程式碼
注意:這樣執行不會影響到原來執行的eureka叢集服務,覺得這點docker做的很人性化
十四、測試
喜歡本文的朋友,歡迎關注,本人的微信公眾號,“咖啡牧羊人”