下载Docker版gitlab
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
下载镜像
创建容器
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
- 随着业务的发展,开发变得越来越复杂。
- 修改、新增某个功能,需要对整个系统进行测试、重新部署。
- 一个模块出现问题,很可能导致整个系统崩溃。
- 多个开发团队同时对数据进行管理,容易产生安全漏洞。
- 各个模块使用同一种技术进行开发,各个模块很难根据实际情况选择更合适的技术框架,局限性很大。
- 模块内容过于复杂,如果员工离职,可能需要很长时间才能完成工作交接。
分布式、集群
集群:一台服务器无法负荷高并发的数据访问量,那么就设置十台服务器一起分担压力,十台不行就设置一百台(物理层面)。很多人干同一件事情,来分摊压力。
分布式:将一个复杂问题拆分成若干个简单的小问题,将一个大型的项目架构拆分成若干个微服务来协同完成。(软件设计层面)。将一个庞大的工作拆分成若干个小步骤,分别由不同的人完成这些小步骤,最终将所有的结果进行整合实现大的需求。
- 服务治理Eureka的核心又三部分组成:服务提供者、服务消费者、注册中心。
- 在分布式系统架构中,每个微服务在启动时,将自己的信息存储在注册中心,叫做服务注册。
- 服务消费者从注册中心获取服务提供者的网络信息,通过该信息调用服务,叫做服务发现。
Spring Cloud 的服务治理使用 Eureka 来实现,Eureka 是 Netflix 开源的基于 REST 的服务治理解决方案,Spring Cloud 集成了 Eureka,提供服务注册和服务发现的功能,可以和基于 Spring Boot 搭建的微服务应用轻松完成整合,开箱即用,Spring Cloud Eureka。
Spring Cloud Eureka
- Eureka Server,注册中心
- Eureka Client,所有要进行注册的微服务通过 Eureka Client 连接到 Eureka Server,完成注册。
Eureka Server代码实现
- 创建父工程,pom.xml(aispringcloud)
<!-- 引入 Spring Boot 的依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.7.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- 引入 Spring Cloud 的依赖,管理 Spring Cloud 各组件 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<!--springboot 2.0-->
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- =======================================================================================
- 在父工程下创建 Module,pom.xml (eurekaserver)
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 创建配置文件 application.yml,添加 Eureka Server 相关配置。
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
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
:注册中心的访问地址。
- 创建启动类
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class,args);
}
}
注解说明:
@SpringBootApplication
:声明该类是 Spring Boot 服务的入口。
@EnableEurekaServer
:声明该类是一个 Eureka Server 微服务,提供服务注册和服务发现功能,即注册中心。
============================================================================================
Eureka Client代码实现
- 创建 Module ,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
创建配置文件 application.yml,添加 Eureka Client 相关配置
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.service-url.defaultZone
:注册中心的访问地址。
eureka.instance.prefer-ip-address
:是否将当前服务的 IP 注册到 Eureka Server。
- 创建启动类
package com.northwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//服务的提供者
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args);
}
}
RestTemplate 的使用
- 什么是 RestTemplate?
RestTemplate 是 Spring 框架提供的基于 REST 的服务组件,底层是对 HTTP 请求及响应进行了封装,提供了很多访问 RETS 服务的方法,可以简化代码开发。
- 如何使用 RestTemplate?
微服务之间的交互
1、创建 Maven 工程,pom.xml。
2、创建实体类 (和服务提供者中的实体类一致)
package com.southwind.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private long id;
private String name;
private int age;
}
https://blog.csdn.net/chenyang1010/article/details/83834443(可能产生的问题)
3、Controller
package com.northwind.controller;
import com.northwind.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Collection;
@RestController // 使用了服务提供者中的方法, 这是一个服务消费者
@RequestMapping("/rest")
public class RestTemplateController {
@Autowired
private RestTemplate restTemplate; //用来连接另一个微服务的
@GetMapping("/findAll")
public Collection<Student> findAll(){
// 服务提供者地址 想拿的是集合,则写集合类型
return restTemplate.getForEntity("http://localhost:8010/student/findAll",Collection.class).getBody();
}
@GetMapping("/findAll2")
public Collection<Student> findAll2(){
return restTemplate.getForObject("http://localhost:8010/student/findAll",Collection.class);
}
@GetMapping("/findById/{id}")
public Student findById(@PathVariable("id") long id){
return restTemplate.getForEntity("http://localhost:8010/student/findById/{id}",Student.class,id).getBody();
}
@GetMapping("/findById2/{id}")
public Student findById2(@PathVariable("id") long id){
return restTemplate.getForObject("http://localhost:8010/student/findById/{id}",Student.class,id);
}
@PostMapping("/save")
public void save(@RequestBody Student student){
restTemplate.postForEntity("http://localhost:8010/student/save",student,null).getBody();
}
@PostMapping("/save2")
public void save2(@RequestBody Student student){
restTemplate.postForObject("http://localhost:8010/student/save",student,null);
}
@PutMapping("/update")
public void update(@RequestBody Student student){
restTemplate.put("http://localhost:8010/student/update",student);
}
@DeleteMapping("/deleteById/{id}")
public void deleteById(@PathVariable("id") long id){
restTemplate.delete("http://localhost:8010/student/deleteById/{id}",id);
}
}
4、启动类
package com.northwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class RestTemplateApplication {
public static void main(String[] args) {
SpringApplication.run(RestTemplateApplication.class,args);
}
// 注入restTemplate 用来调用提供者中的方法
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
=========================================================================================
服务消费者 consumer
- 创建 Maven 工程,pom.xml
<!--和服务提供者差不多-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 创建配置文件 application.yml
server:
port: 8020
spring:
application:
name: consumer
eureka:
client:
service-url:
#注册中心访问地址
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
- 创建启动类
package com.northwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
// 注入restTemplate
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- Controller
package com.northwind.controller;
import com.northwind.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Collection;
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate; //用来连接另一个微服务的
@GetMapping("/findAll")
public Collection<Student> findAll(){
// 服务提供者地址 想拿的是集合,则写集合类型
return restTemplate.getForEntity("http://localhost:8010/student/findAll",Collection.class).getBody();
}
@GetMapping("/findAll2")
public Collection<Student> findAll2(){
return restTemplate.getForObject("http://localhost:8010/student/findAll",Collection.class);
}
@GetMapping("/findById/{id}")
public Student findById(@PathVariable("id") long id){
//参数
return restTemplate.getForEntity("http://localhost:8010/student/findById/{id}",Student.class,id).getBody();
}
@GetMapping("/findById2/{id}")
public Student findById2(@PathVariable("id") long id){
return restTemplate.getForObject("http://localhost:8010/student/findById/{id}",Student.class,id);
}
@PostMapping("/save")
public void save(@RequestBody Student student){ // 没有返回值
restTemplate.postForEntity("http://localhost:8010/student/save",student,null).getBody();
}
@PostMapping("/save2")
public void save2(@RequestBody Student student){
restTemplate.postForObject("http://localhost:8010/student/save",student,null);
}
@PutMapping("/update")
public void update(@RequestBody Student student){
restTemplate.put("http://localhost:8010/student/update",student);
}
@DeleteMapping("/deleteById/{id}")
public void deleteById(@PathVariable("id") long id){
restTemplate.delete("http://localhost:8010/student/deleteById/{id}",id);
}
}
上一节中resttemplate服务没有在注册中心注册,不能算一个消费者,而这一节consumer通过yml注册了,所以属于消费者。
=============================================================
服务网关
Spring Cloud 集成了 Zuul 组件,实现服务网关。
- 什么是 Zuul?
Zuul 是 Netflix 提供的一个开源的 API 网关服务器,是客户端和网站后端所有请求的中间层,对外开放一个 API,将所有请求导入统一的入口,屏蔽了服务端的具体实现逻辑,Zuul 可以实现反向代理的功能,在网关内部实现动态路由、身份认证、IP 过滤、数据监控等。
- 创建 Maven 工程,pom.xml
<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>
- 创建配置文件 application.yml
server:
port: 8030
spring:
application:
name: gateway
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
zuul:
routes:
# 映射到提供者
provider: /p/**
p映射到provider端口。
通过网关访问。
属性说明:
zuul.routes.provider
:给服务提供者 provider 设置映射
- 创建启动类
package com.northwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@EnableZuulProxy
@EnableAutoConfiguration
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 的代码。
启动注册中心后,再启动两个提供者,端口分别为8010,和8011.
通过zuul网关访问时,交替进入两个提供者端口。p映射的是provider提供者端口。
实现了负载均衡。
===================================================================================
Ribbon 负载均衡
- 什么是 Ribbon?
Spring Cloud Ribbon 是一个负载均衡解决方案,Ribbon 是 Netflix 发布的负载均衡器,Spring Cloud Ribbon 是基于 Netflix Ribbon 实现的,是一个用于对 HTTP 请求进行控制的负载均衡客户端。
在注册中心对 Ribbon 进行注册之后,Ribbon 就可以基于某种负载均衡算法,如轮询、随机、加权轮询、加权随机等自动帮助服务消费者调用接口,开发者也可以根据具体需求自定义 Ribbon 负载均衡算法。实际开发中,Spring Cloud Ribbon 需要结合 Spring Cloud Eureka 来使用,Eureka Server 提供所有可以调用的服务提供者列表,Ribbon 基于特定的负载均衡算法从这些服务提供者中选择要调用的具体实例。
- 创建 Module,pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 创建配置文件 application.yml
server:
port: 8040
spring:
application:
name: ribbon
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
- 创建启动类
package com.northwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class RibbonApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonApplication.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
@LoadBalanced
:声明一个基于 Ribbon 的负载均衡。
- Controller
package com.northwind.controller;
import com.northwind.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Collection;
@RestController
@RequestMapping("/ribbon")
public class RibbonController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/findAll")
public Collection<Student> findAll(){
//localhost:8010/在注册中心已经完成注册名字是provider
return restTemplate.getForObject("http://provider/student/findAll",Collection.class);
}
@GetMapping("/index")
public String index(){
return restTemplate.getForObject("http://provider/student/index",String.class);
}
}
可以通过提供者在注册中心的注册名,直接找到提供者。
启动注册中心 ->启动两个提供者->再启动ribbon,实现负载均衡。
访问效果:
负载均衡:
交替进入两个提供者,实现负载均衡。
============================================================================
Feign声明式接口调用
- 什么是 Feign?
与 Ribbon 一样,Feign 也是由 Netflix 提供的,Feign 是一个声明式、模版化的 Web Service 客户端,它简化了开发者编写 Web 服务客户端的操作,开发者可以通过简单的接口和注解来调用 HTTP API,Spring Cloud Feign,它整合了 Ribbon 和 Hystrix,具有可插拔、基于注解、负载均衡、服务熔断等一系列便捷功能。
相比较于 Ribbon + RestTemplate 的方式,Feign 大大简化了代码的开发,Feign 支持多种注解,包括 Feign 注解、JAX-RS 注解、Spring MVC 注解等,Spring Cloud 对 Feing 进行了优化,整合了 Ribbon 和 Eureka,从而让 Feign 的使用更加方便。
- Ribbon 和 Feign 的区别
Ribbon 是一个通用的 HTTP 客户端工具,Feign 是基于 Ribbon 实现的。
- Feign 的tedian
1、Feign 是一个声明式的 Web Service 客户端。
2、支持 Feign 注解、Spring MVC 注解、JAX-RS 注解。
3、Feign 基于 Ribbon 实现,使用起来更加简单。
4、Feign 集成了 Hystrix,具备服务熔断的功能。
- 创建 Module,pom.xml
<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-openfeign</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
- 创建配置文件 application.yml
server:
port: 8050
spring:
application:
name: feign
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
- 创建启动类
package com.northwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class FeignApplication {
public static void main(String[] args) {
SpringApplication.run(FeignApplication.class,args);
}
}
- 创建声明式接口
package com.northwind.feign;
import com.northwind.entity.Student;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Collection;
@FeignClient(value = "provider")//访问的微服务名称
public interface FeignProviderClient {
@GetMapping("/student/findAll")
public Collection<Student> findAll();
@GetMapping("/student/index")
public String index();
}
- Controller(可以访问feign包下的接口FeignProviderClient)
package com.northwind.controller;
import com.northwind.entity.Student;
import com.northwind.feign.FeignProviderClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
@RestController
@RequestMapping("/feign")
public class FeignController {
@Autowired
private FeignProviderClient feignProviderClient;
@GetMapping("/findAll")
public Collection<Student> findAll(){
return feignProviderClient.findAll(); //调用接口中的方法
}
@GetMapping("/index")
public String index(){
return feignProviderClient.index();
}
}
访问时按照url路径解析先进入controller,调用接口的方法,进入接口中,接口中有对应的微服务(如provider)。
实现负载均衡
ribbon和feign都能实现负载均衡,feign还有熔断机制。
- 服务熔断,application.yml 添加熔断机制。
server:
port: 8050
spring:
application:
name: feign
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
feign.hystrix.enabled
:是否开启熔断器。
- 创建 FeignProviderClient 接口的实现类 FeignError,定义容错处理逻辑,通过
@Component
注解将 FeignError 实例注入 IoC 容器中。
package com.northwind.feign.impl;
import com.northwind.entity.Student;
import com.northwind.feign.FeignProviderClient;
import org.springframework.stereotype.Component;
import java.util.Collection;
@Component
public class FeignError implements FeignProviderClient {
@Override
public Collection<Student> findAll() {
return null;
}
@Override
public String index() {
return "服务器维护中...........";
}
}
- 在 FeignProviderClient 定义处通过
@FeignClient
的 fallback 属性设置映射。
如果能进入provider提供者微服务中,则正常进入,否则启动容错机制。
将提供者微服务关闭,无法进入"provider"中,启动容错机制,进入FeignProviderClient接口实现类中。