简介
微服务: Microservice
使用定义好边界的 小的 独立组件 来做好 一件事情。
Spring Cloud 开发的程序,docker 或其他Pass(平台即是服务,如:Coud Foundry)部署。称作:原生云应用。
@EnableConfigServer
@EnableEurekaServer
@EnableEurekaClient
@EnableZuulProxy
@FeignClient RestTemplate
@EnableCircuitBreaker 断路器
@HystrixCommand 指定后备方法
@Enable Hystrix Dashboard
实战
pom
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.wisely</groupId>
<artifactId>ch12</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<name>Cloud Native App</name>
<modules> 指名子项目
<module>config</module> 为person 和 some 提供配置
<module>discovery</module> eureka server
<module>ui</module> 网关, feign 消费 person。Ribbon消费 some服务
<module>person</module> 提供保存的 rest服务
<module>some</module> 返回一串制服馆
<module>monitor</module> 断路器
</modules>
<parent> 公共的父类
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Angel.SR3</version> 最新是 H版本 sr3
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> web支持
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId> 监控支持
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> 测试支持
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> 插件支持
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId> docker支持
<version>0.2.9</version>
<configuration>
<skipDockerBuild>true</skipDockerBuild>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
eureka
<?xml version="1.0" encoding="UTF-8"?>
<project >
<modelVersion>4.0.0</modelVersion>
<artifactId>discovery</artifactId>
<packaging>jar</packaging>
<name>discovery</name>
<description>Discovery App</description>
<parent>
<groupId>com.wisely</groupId>
<artifactId>ch12</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<start-class>com.wisely.discovery.DiscoveryApplication</start-class>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId> 啥用?
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId> server
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<imageName>${project.name}:${project.version}</imageName>
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
<skipDockerBuild>false</skipDockerBuild>
<resources>
<resource>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
</project>
@EnableEurekaServer //1
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false #不需要注册到其他微服务
fetch-registry: false #不需要拉取配置
配置中心
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
@SpringBootApplication
@EnableConfigServer //1 开启配置中心
@EnableEurekaClient //2 是个客户端
bootstrap.yml
bootstrap.yml负责从外部加在属性配置,优先级更高
spring:
application:
name: config #1 在eureka上名字是 config
profiles:
active: native #2 使用本地配置,默认的是git
eureka:
instance:
non-secure-port: ${server.port:8888} #3 非ssl端口,如果有就使用。默认8888
metadata-map:
instanceId: ${spring.application.name}:${random.value} #4 配置在eureka server上实例ID
client:
service-url:
defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ #5 server地址
application.yml
spring:
cloud:
config:
server:
native:
search-locations: classpath:/config #1
server:
port: 8888
配置其他项目
src/main/resources/config/person.yml
spring:
jpa:
database: HSQL
person-docker.yml
spring:
jpa:
database: POSTGRESQL
datasource:
platform: postgres
url: jdbc:postgresql://postgres:5432/postgres
username: postgres
password: postgres
driver-class-name: org.postgresql.Driver
some.yml
my:
message: Message from Development
some-docker.yml
my:
message: Message from Production
应用名+profile.yml
服务模块 1
开发环境用 hsqldb,生产环境用 postgreSQL
PostgreSQL是一种特性非常齐全的自由软件的对象-关系型数据库管理系统(ORDBMS)
HSQLDB(HyperSQL DataBase)是一个开放源代码的JAVA数据库,其具有标准的SQL语法和JAVA接口
xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId> config 客户端
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId> eureka客户端
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> jsp
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId> hsqldb
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901-1.jdbc4</version>
</dependency>
</dependencies>
代码
@SpringBootApplication
@EnableEurekaClient
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
private String name;
}
public interface PersonRepository extends JpaRepository<Person, Long>{
}
@RestController
public class PersonController {
@Autowired
PersonRepository personRepository;
@RequestMapping(value = "/save", method = RequestMethod.POST)
public List<Person> savePerson(@RequestBody String personName) {
Person p = new Person(personName);
personRepository.save(p);
List<Person> people = personRepository.findAll(new PageRequest(0, 10)).getContent();
return people;
}
}
bootstrap.yml
spring:
application:
name: person
cloud:
config:
enabled: true
discovery:
enabled: true
service-id: CONFIG #1
eureka:
instance:
non-secure-port: ${server.port:8082}
client:
service-url:
defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/
开发环境下 使用 配置中心的 person.yml
docker 环境 使用 person-docker.yml
application.yml
server:
port: 8082
spring:
jpa:
hibernate:
ddl-auto: update
服务模块 2
pom.xml
<dependencies>
<artifactId>spring-cloud-starter</artifactId>
<artifactId>spring-cloud-config-client</artifactId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependencies>
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class SomeApplication {
@Value("${my.message}") //1
private String message;
@RequestMapping(value = "/getsome")
public String getsome(){
return message;
}
}
配置文件
application.yml
server:
port: 8083
bootstrap.yml
spring:
application:
name: some
eureka:
instance:
non-secure-port: ${server.port:8083}
其他都和 模块1 一致
开发读取 some.yml,docker读取 some-docker.yml
UI (Ribbon Feign)
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId> start
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId> zuul
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId> config
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId> eureka
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId> feign
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId> ribbon
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId> hystrix
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId> bootstrap
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>angularjs</artifactId> angularjs
<version>1.3.15</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>angular-ui-router</artifactId> angular-ui
<version>0.2.13</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId> jquery
</dependency>
</dependencies>
代码
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients //1 feign
@EnableCircuitBreaker //2 断路器
@EnableZuulProxy //3 网关
public class UiApplication {}
public class Person {
private Long id;
private String name;
}
@FeignClient("person") //指名请求的是 person 服务
public interface PersonService {
@RequestMapping(method = RequestMethod.POST, value = "/save",
produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody List<Person> save(@RequestBody String name);
} # 提供者 和 消费者 都是 json 。 对象服务模块1
使用:
@Service
public class PersonHystrixService {
@Autowired
PersonService personService;
@HystrixCommand(fallbackMethod = "fallbackSave") //1 指定断路器
public List<Person> save(String name) {
return personService.save(name);
}
public List<Person> fallbackSave(String name){
List<Person> list = new ArrayList<>();
Person p = new Person(name+"没有保存成功,Person Service 故障");
list.add(p);
return list;
}
}
服务模块2,直接用 restTemplate请求了。 不需要service
@Service
public class SomeHystrixService {
@Autowired
RestTemplate restTemplate; //1 注入 restTemplate即是 ribbon
@HystrixCommand(fallbackMethod = "fallbackSome") //2 指定回退
public String getSome() {
return restTemplate.getForObject("http://some/getsome", String.class); //发请求
}
public String fallbackSome(){
return "some service模块故障";
}
}
application.yml
server:
port: 80
bootstrap.yml
spring:
application:
name: ui
eureka:
instance:
non-secure-port: ${server.port:80}
client:
service-url:
defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/
@RestController
public class UiController {
@Autowired
private SomeHystrixService someHystrixService;
@Autowired
private PersonHystrixService personHystrixService;
@RequestMapping("/dispatch")
public List<Person> sendMessage(@RequestBody String personName) {
return personHystrixService.save(personName);
}
@RequestMapping(value = "/getsome",produces={MediaType.TEXT_PLAIN_VALUE})
public String getSome(){
return someHystrixService.getSome();
}
}
断路器监控 Monitor (DashBoard)
pom
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>
</dependencies>
代码:
@SpringBootApplication
@EnableEurekaClient 客户端
@EnableHystrixDashboard 断路器
@EnableTurbine
public class MonitorApplication {}
server:
port: 8989
bootstrap.yml
spring:
application:
name: monitor
eureka:
instance:
nonSecurePort: ${server.port:8989}
http://localhost:8098/
http://localhost:8098/#/some
访问:
http://localhost:8989/hystrix.stream
输入:
http://localhost:8098/hystrix.stream 请求地址
Docker 部署
文件编写
src/main/docker/runboot.sh #新建目录
sleep 10
java -Djava.security.egd=file:/dev/./urandom -jar /app/app.jar
src/main/docker/Dockerfile
FROM java:8 #使用 java:8 运行
VOLUME /tmp #挂载点
RUN mkdir /app #创建目录
ADD config-1.0.0-SNAPSHOT.jar /app/app.jar #把项目,添加到 app目录
ADD runboot.sh /app/ #运行这个sh文件
RUN bash -c 'touch /app/app.jar' #创建这个文件
WORKDIR /app
RUN chmod a+x runboot.sh #给这个文件加上执行权限
EXPOSE 8888 #不同的服务需要修改成不同的端口
CMD /app/runboot.sh #执行
docker 的 maven插件
所有的程序都要增加这个
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId> #公司
<artifactId>docker-maven-plugin</artifactId> #插件名
<configuration>
<imageName>${project.name}:${project.version}</imageName> #项目名 版本
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
<skipDockerBuild>false</skipDockerBuild> #docker文件位置。不保持
<resources>
<resource>
<directory>${project.build.directory}</directory> #在项目构建目录
<include>${project.build.finalName}.jar</include> #项目构建的最终名字
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
默认把镜像编译到本地,如果远程服务器。
在本地配置 环境变量 DOCKER_HOST 值为:tcp://localhost:2375
#编译 并且放入docker镜像
mvn clean package docker:build -DshkipTests
Docker Compose
curl -L https://get.daocloud.io/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
其他链接不可用
postgresdb:
image: busybox
volumes:
- /var/lib/postgresql/data
postgres:
name: postgres
image: postgres
hostname: postgres
volumes_from:
- postgresdb
# ports:
# - "5432:5432"
environment:
- POSTGRES_USER=postgres #给容器使用的变量,在容器中使用 ${}使用
- POSTGRES_PASSWORD=postgres
discovery:
image: "discovery:1.0.0-SNAPSHOT"
hostname: discovery
name: discovery
ports:
- "8761:8761" #将我门需要的端口,映射出来
config:
image: "config:1.0.0-SNAPSHOT"
hostname: config
name: config
links:
- discovery #当前容器链接的依赖
environment:
EUREKA_HOST: discovery
EUREKA_PORT: 8761
# ports:
# - "8888:8888"
person:
image: person:1.0.0-SNAPSHOT
hostname: person
links:
- discovery
- config
- postgres
environment:
EUREKA_HOST: discovery
EUREKA_PORT: 8761
SPRING_PROFILES_ACTIVE: docker
# ports:
# - "8082:8082"
some:
image: some:1.0.0-SNAPSHOT
hostname: some
links:
- discovery
- config
environment:
EUREKA_HOST: discovery
EUREKA_PORT: 8761
SPRING_PROFILES_ACTIVE: docker
# ports:
# - "8083:8083"
ui:
image: ui:1.0.0-SNAPSHOT
hostname: ui
links:
- discovery
- config
- person
- some
environment:
EUREKA_HOST: discovery
EUREKA_PORT: 8761
SPRING_PROFILES_ACTIVE: docker
ports:
- "80:80"
monitor:
image: monitor:1.0.0-SNAPSHOT
hostname: monitor
links:
- discovery
- config
- person
- some
- ui
environment:
EUREKA_HOST: discovery
EUREKA_PORT: 8761
SPRING_PROFILES_ACTIVE: docker
# ports:
# - "8989:8989"
docker-compose up -d 哎,我忘记应该放在那里了
JHipster 代码生成器,用来生成基于 spring boot 和 angularJs项目