spring cloud
spring cloud完全基于spring boot、服务调用方式是基于REST API、整合了各种成熟的产品和框架、同时基于spring boot也使得整体的开发、配置、部署都非常方便
单体应用
单体应用存在的问题
随着业务的发展、开发变得越来越复杂
修改、新增某个功能,需要对整个系统进行测试、重新部署
一个模块出现问题、很可能导致整个系统崩溃
多个开发团队同时对数据进行管理、容易产生安全漏洞
各个模块使用同一种技术进行开发、各个模块很难根据实际情况选择更合适的技术框架、局限性很大
模块内容过于复杂、可能需要很长时间才能完成工作交接
分布式、集群、微服务
分布式
一台服务器无法负荷高并发的数据访问量、那么就设置十台服务器一起分担压力、十台不行就设置一百台(物理层面)、很多人干同一件事情、来分摊压力
集群
将一个复杂问题拆分成若干个简单的小问题、将一个大型的项目架构拆分成若干个微服务来协同完成(软件设计层面)、将一个庞大的工作拆分成若干个小步骤、分别由不同的人完成这些小步骤、最终将所有的结果进行整合实现大的需求
微服务
将应用程序分为多个可独立部署的较小组件
spring cloud核心组件
服务治理 Eureka
spring cloud Eureka
Eureka Server:注册中心
Eureka Client:所有要进行注册的微服务通过 Eureka Client 连接到 Eureka Server、完成注册
核心组成部分
在分布式系统架构中、每个微服务在启动时、将自己的信息存储在注册中心、叫做服务注册
代码示例
父工程 pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| <?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"> <modelVersion>4.0.0</modelVersion>
<groupId>com.dream.xiaobo</groupId> <artifactId>springcloud1</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>eurekaserver</module> </modules>
<parent> <groupId>org.springframework.boot</groupId> <version>2.0.7.RELEASE</version> <artifactId>spring-boot-parent</artifactId> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency>
<dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.0</version> </dependency>
<dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>2.3.0</version> </dependency>
<dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency>
</dependencies>
<dependencyManagement> <dependencies>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.SR2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
</project>
|
子模块 eurekaServer pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?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>springcloud1</artifactId> <groupId>com.dream.xiaobo</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<groupId>com.dream.xiaobo</groupId> <artifactId>eurekaserver</artifactId> <dependencies>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <version>2.0.2.RELEASE</version> </dependency> </dependencies>
</project>
|
子模块 eurekaService application.yml
1 2 3 4 5 6 7 8 9
| server: port: 8761
eureka: client: fetch-registry: false register-with-eureka: true service-url: defaultZone: http://localhost:8761/eureka/
|
属性说明
server.port
:当前 Eureka Server 服务端口
eureka.client.register-with-eureka
:是否将当前的 Eureka Server 服务作为客户端进行注册
eureka.client.fetch-fegistry
:是否获取其他 Eureka Server 服务的数据
eureka.client.service-url.defaultZone
:注册中心的访问地址
启动类
1 2 3 4 5 6 7 8
| @SpringBootApplication @EnableEurekaServer public class EurekaServerAppliaction {
public static void main(String[] args) { SpringApplication.run(EurekaServerAppliaction.class,args); } }
|
@EnableEurekaServer
:声明该类是一个 Eureka Server 微服务、提供服务注册和服务发现功能
服务提供者在注册中心注册相关信息
代码示例
子模块 eurekaClient pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <?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>springcloud1</artifactId> <groupId>com.dream.xiaobo</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>eurekaclient</artifactId>
<dependencies>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.0.2.RELEASE</version> </dependency> </dependencies>
</project>
|
子模块 eurekaClient application.yml
1 2 3 4 5 6 7 8 9 10 11
| server: port: 8010 spring: application: name: provider eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ instance: prefer-ip-address: true
|
spring.application.name
:当前服务注册在Eureka Server上的名称
eureka.client.servic.url.defaultZone
:注册中心的访问地址
eureka.instance.prefer-ip-address
:是否将当前服务的 IP 注册到 Eureka Server
Controlle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| @RestController @RequestMapping(value = "/student") public class StudentController {
@Autowired private StudentServiceImpl studentService;
@GetMapping(value = "/findAll") public Collection<Student> findAll(){
return studentService.findAll(); }
@GetMapping(value = "findById/{id}") public Student findById(@PathVariable Long id){ return studentService.findById(id); }
@DeleteMapping(value = "/deleteById/{id}") public void deleteById(@PathVariable Long id){ studentService.deleteById(id); }
@PutMapping(value = "/updata") public void update(@RequestBody Student student){ studentService.updata(student); }
@PostMapping(value = "/save") public void save(@RequestBody Student student){ studentService.save(student); } }
|
repository
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @Repository public class StudentRepositoryImpl implements StudentRepository {
private static Map<Long,Student> map = null;
static { map = new HashMap<Long, Student>(); map.put(1L,new Student(1L,"xiaobo",21)); map.put(2L,new Student(2L,"xiaowang",21)); map.put(3L,new Student(3L,"wangyibo",21)); }
public Collection<Student> findAll() { return map.values(); }
public Student findById(Long id) { return map.get(id); }
public void deleteById(Long id) { map.remove(id); }
public void saveAndUpdata(Student student) { map.put(student.getId(),student); } }
|
服务消费者从注册中心获取服务提供者的网络信息、通过该信息调用服务、叫做服务发现
代码示例
子模块 conmuser pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?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>springcloud1</artifactId> <groupId>com.dream.xiaobo</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>conmuser</artifactId>
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.0.2.RELEASE</version> </dependency> </dependencies>
</project>
|
application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13
| server: port: 8020
spring: application: name: conmuser
eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ instance: prefer-ip-address: true
|
controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| @RestController @RequestMapping(value = "/student") public class ConmuserController {
@Autowired private RestTemplate restTemplate;
@GetMapping(value = "/findAll") public Collection<Student> findAll(){
return restTemplate.getForEntity("http://localhost:8010/student/findAll",Collection.class).getBody(); }
@GetMapping(value = "/findById/{id}") public Student findById(@PathVariable Long id){
return restTemplate.getForObject("http://localhost:8010/student/findById/{id}",Student.class,id); }
@DeleteMapping(value = "/deleteById/{id}") public void deletedById(@PathVariable("id") Long id){
restTemplate.delete("http://localhost:8010/student/deleteById/{id}",id); }
@PostMapping(value = "/save") public void save(@RequestBody Student student){
restTemplate.postForEntity("http://localhost:8010/student/save",student,null).getBody(); }
@PutMapping(value = "/updata") public void update(@RequestBody Student student){
restTemplate.put("http://localhost:8010/student/updata",student); } }
|
entity
1 2 3 4 5 6 7 8 9 10 11
| @Data @AllArgsConstructor @NoArgsConstructor public class Student {
private Long id;
private String name;
private Integer age; }
|
提供者和消费者是相对的
RestTemplate 是 Spring 框架提供的基于 REST 的服务组件,底层是对 HTTP 请求及响应进行了封装,提供了很多访问 RETS 服务的方法
服务网关 Zuul
Spring Cloud 集成了 Zuul 组件、实现服务网关
Zuul 是 Netflix 提供的一个开源的 API 网关服务器、是客户端和网站后端所有请求的中间层、对外开放一个 API、将所有请求导入统一的入口、屏蔽了服务端的具体实现逻辑、Zuul 可以实现反向代理的功能、在网关内部实现动态路由、身份认证、IP 过滤、数据监控等
代码示例
子模块 zuul pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?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>springcloud1</artifactId> <groupId>com.dream.com.dream.xiaobo.xiaobo</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>zuul</artifactId>
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> <version>2.0.2.RELEASE</version> </dependency> </dependencies>
</project>
|
application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| server: port: 8030
spring: application: name: gateway
eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ zuul: routes: provider: p/**
|
zuul.routes.provider
:给服务提供者 provider 设置映射
启动类
1 2 3 4 5 6 7 8
| @EnableAutoConfiguration @EnableZuulProxy public class ZuulApplication {
public static void main(String[] args) { SpringApplication.run(ZuulApplication.class,args); } }
|
@EnableZuulProxy
:包含了 @EnableZuulServer
、设置该类是网关的启动类
@EnableAutoConfiguration
:可以帮助 Spring Boot 应用将所有符合条件的 @Configuration
配置加载到当前 Spring Boot 创建并使用的 IoC 容器中
Zuul 自带了负载均衡功能,修改 provider 的代码
正确的开始、微小的长进、然后持续、嘿、我是小博、带你一起看我目之所及的世界……