1.springcloud是什么?
2.springcloud有什么用?
3.springcloud怎么用?
4.注意:写在上面,如果应用启动有报错,那么很大可能是包的问题,请更改依赖的版本。
springcloud是一个微服务的框架,是能快速构建分布式系统的工具。它是很多组件的集合体。
里面的功能分别有:注册配置管理、服务发现、智能路由、负载均衡、熔断器、控制总线、集群等功能。
主要的组件有:netflix下的,
Eureka(找到了):注册中心,注意服务提供者和服务消费者都要注册到这里;同时,为了集群,
Eureka本身也要相互注册,形成一个集群。
Ribbon:负载均衡,是指每台服务器处理的请求,都是平均的。默认使用的算法是轮询算法
(核心思想是定义一个自增变量,再用变量模于提供服务的个数,余数就是哪台服务器)
Hystisx:熔断器,是为了解决雪崩可能,引入该技术,就是服务调用者不会因为服务提供者宕机,
而对自己造成影响,从而影响整个集群。
Feign:服务调用
Zuul:服务网关
4.Eureka注册中心,实现原理和使用步骤:
Eureka架构中的三个核心角色:
- 服务注册中心
Eureka的服务端应用,提供服务注册和发现功能,就是刚刚我们建立的eureka-demo
- 服务提供者
提供服务的应用,可以是SpringBoot应用,也可以是其它任意技术实现,只要对外提供的是Rest风格服务即可。
本例中就是我们实现的user-service
- 服务消费者
消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。本例中就是我们实现的consumer-demo
如果要想实现高可用的Eureka Server,那么服务注册中心就要进行相互注册、集群,服务同步
1.实现原理:
把服务提供者和服务调用者都注册到Eureka注册中心,之后这2类注册者(这2类都是web应用)都要renew到注册中心:,
默认是每30秒向注册中心Eureka发送信息,告知自己的状态,以表示它们都是在线,可访问的;默认是超过90秒,如果注册中心Eureka都没有收到它们发送的信息,
那么注册中心Eureka就会把它不在线类,就从注册列表中剔除它。
而服务调用者每次调用服务提供者的服务时,都要到注册中心Eureka主动拉取服务列表,然后再从拉取的服务列表中,通过负载均衡处理,
向服务提供者调用服务
2.使用步骤:
1.先创建提供EurekaServer的项目,该项目也是通过maven生成springboot项目
2.导入Eureka-server依赖和spring-cloud-dependencies依赖2个依赖
<!-- Eureka服务端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
3.然后在启动类中添加注解@EnableEurekaServer ,声明该应用是一个EurekaServer
@SpringBootApplication
@EnableEurekaServer // 声明这个应用是一个EurekaServer
public class EurekaDemoApplication {...} 4.如要集群,那么EurekaServer也要相互注册,所以yml文件中一定要指定服务名和注册的地址(其实如果不集群,这些内容要设置为false)
yml配置内容如下:
server:
port: 10086 # 端口
spring:
application:
name: eureka-server # 应用名称,会在Eureka中显示
eureka:
client:
register-with-eureka: false # 是否注册自己的信息到EurekaServer,默认是true
fetch-registry: false # 是否拉取其它服务的信息,默认是true
service-url: # EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址。
defaultZone: http://127.0.0.1:端口/eureka =========================================================================================================
1.然后给web应用的服务提供者和服务调用者都提供依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency> 2.然后在各自的启动类上添加注解:@EnableDiscoveryClient,表示开启Eureka客户端功能
@SpringBootApplication
@EnableDiscoveryClient
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class);
}
} 3.然后注册到Eureka注册中心,yml文件中注册,先指定启动端口,和应用名,注册地址,
如果需要连数据库,那么还要配置数据库4大参数
server:
port: 8080 \端口 spring: \数据库4大参数
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/heima
username: root
password: 123456 application:
name: user \应用名 eureka:
client:
service-url: \注册地址
defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka ================================================================================================
4.如果服务消费者需要访问服务,那么还需要2步骤,
1.在访问服务的启动类上增加一个bean对象 @Bean \作用是返回一个http的客户端类的实例,目的是为了通过http请求,来访问服务,这里默认使用是jdk的URLConnection类
public RestTemplate restTemplate() {
return new RestTemplate();
} 2.使用urlConnection,在使用的地方还需要自动注入一个discoveryClient类,目的是去注册中心根据服务id拉取服务列表
@Autowired
RestTemplate restTemplate; @Autowired
DiscoveryClient discoveryClient;
@RequestMapping("/test/{id}")
public User test(@PathVariable int id) {
List<ServiceInstance> instances = discoveryClient.getInstances("user");
ServiceInstance instance = instances.get(0);
String url = "http://" + instance.getHost()+ ":" + instance.getPort()+ "/user/"+ id;
User object = restTemplate.getForObject(url, User.class);
return object;
} 5.Ribbon,负载均衡,作用是把请求平均分发给每个服务器处理,使得每个服务器都能充分的得到运用,同时又减轻了压力
因为Eureka中已经集成了Ribbon,所以我们无需引入新的依赖。直接修改代码: 1.使用步骤:在服务消费者中使用
1.在restTemplate的bean上添加注解@LoadBalanced(负载均衡),该注解是使用拦截器的思想,
就是在restTemplate调用方法时,对其方法进行拦截,然后再对方法中的参数url进行解析,
获取服务的id,再使用Ribbon中的算法去平均的获取服务的实例,然后再把url中的服务id给替换掉,
然后再放行restTemplate的方法。(就是对restTemplate的方法进行拦击,然后解析url中的服务id,得到服务的实例,再把url中的服务id给替换掉,最后放行方法) @Bean //把该返回值交给spring容器进行管理
@LoadBalanced //对该bean的方法进行拦截,然后处理方法的参数url,然后再放行方法
public RestTemplate restTemplate() {
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
} 2.使用 ,在服务消费者中使用
@Autowired
private RestTemplate restTemplate;
String url = "http://userid/user/"+id (restfull风格) //到时,会去解析userid,获得服务的实例,再用实例的ip+端口替换掉userid
restTemplate.getForObject(url,User.class); //根据url发送请求,User.class 是指定请求后返回来的数据类型(注意,这里它会自动把json字符串反序列为对象) 2.springcloud的重试机制:它是指当访问某个服务超时后,它会尝试去访问下一个的服务实例,如果还是不行,就会再换一个服务实例服务,如果不行,则返回失败。
就是说一次请求服务失败,它可以配置该请求去尝试访问该服务的其他实例,直到该服务的全部实例都不行,则返回失败。这个功能需要配置 注意:一定要注意,重试机制是针对于服务消费者来说的,就是这些依赖和配置都是加在服务消费者身上的,
因为只有服务请求者才有资格决定,我要不要继续请求,我要请求到什么程度。(服务提供者和其他人都是不能决定的) 1.要引入spring retry依赖,就是重试包
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency> 2.在服务消费者的yml配置文件中加上下面这几个配置。
ribbon:
# 同一实例最大重试次数,不包括首次调用
MaxAutoRetries: 1
# 重试其他实例的最大重试次数,不包括首次所选的server
MaxAutoRetriesNextServer: 2
# 是否所有操作都进行重试
OkToRetryOnAllOperations: true ConnectTimeout: 250 # Ribbon的连接超时时间
ReadTimeout: 1000 # Ribbon的数据读取超时时间 3.代码测试方式,改写RestTemplate的返回值bean
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
simpleClientHttpRequestFactory.setConnectTimeout(6000);
simpleClientHttpRequestFactory.setReadTimeout(6000);
return new RestTemplate(simpleClientHttpRequestFactory);
}6.Hystrix,熔断器。就是容错管理工具,作用是通过线程隔离、服务降级等方式,对有延迟和有故障的服务提供更强的容错能力,
避免整个系统出现雪崩情况(因为一个tomcat的并发能力是200)
线程隔离:是指一个tomcat中的所有线程是按需分发给tomcat的每个服务,比如这个
服务降级:就好比是平常市场买鱼,都会给你杀鱼去鳞;等过年时,市场就不会提供杀鱼的服务了。这就是服务降级。 1.工作机制:熔断器原理很简单,就像家里电路的熔断器一样,如果电路发生短路,就能立刻熔断电路,避免火灾。
同样,在分布式系统中应用这一模式后,服务调用方可以自己进行判断某些服务反应慢或者超时时,会主动熔断。
但是这里的熔断器还会自动重连,就是等情况好转时。 2.使用步骤:
1.在服务消费端添加依赖(就是服务请求者添加依赖)Hystrix,
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency> 2.再在服务消费者端的启动类上面,开启熔断器(这个跟ribbon的重试机制配置方式一样)注解@EnabelHystrix,是使用注解@EnableHystrix开启熔断机制
@SpringBootApplication
@EnableDiscoverClient
@EnableHystrix
public class Consumer{....} 3.再在服务消费者的方法上加上注解@HystrixCommand(fallbackMethod="方法名") // fallbacke回退策略,fallbackeMethod回退方法。
该注解@HystrixCommand是熔断指令,表示请求的内容有延迟时,马上终止,然后去执行方法中fallbackMethod中的方法。 注意,该回退方法上的参数列表必须与上面的方法的参数列表一致,且方法的返回类型也必须一致
(它这样做到目的是,把回退方法中的返回值给返回到客户端,所以2者的返回类型必须一致,这样才可以返回出去)。 如下: @RequestMapping("/{id}")
@HystrixCommand(fallbackMethod = "cnm")
public User user(@PathVariable Long id) {
String url = "http://user/user/" + id;
User user = restTemplate.getForObject(url, User.class);
System.out.println(user);
return user;
}
// 覆写fallbackMethod中指定的方法,注意,此方法的返回值,参数必须与原方法一致
public User cnm(Long id) {
System.out.println("傻屌!!"+id);
User user = new User();
user.setId(id);
user.setCreated(new Date());
user.setPassword("傻屌");
user.setPhone("傻屌");
user.setUsername("傻屌");
return user; }
4.修改服务提供者的方法,使得服务出现延迟或故障。
@GetMapping("{id}")
public User queryById(@PathVariable("id") Long id) throws InterruptedException { Thread.sleep(120000L); //对方法进行延迟
return this.userService.queryById(id);
} 3.在配置熔断器机制的条件下,ribbon的重试机制也要生效了,那么熔断器的熔断时间一定要比ribbon重试机制的时间长,重试才会有用,在服务消费者的yml中加上配置:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMillisecond: 6000 # 设置hystrix的超时时间为6000ms7.Feign功能(伪装),是对rest的请求进行隐藏,伪装成类似SpringMvc的Controller一样。就是不用自己不用再去拼接eiurl,连接参数等,这些操作都交给Feign去做
简单来说,Feign的功能就是简化代码量,但是功能又跟之前一样。
注意:下面这些操作步骤都是在服务的消费者中编写的。 1.简化请求时的代码量:步骤,
1.先在服务的消费者(请求者)中加入依赖Feign依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency> 2.Feign的客户端(接口模式,就是在只写接口,不写实现,实现由Feain去生成) 接口名上添加注解@FeignClient("服务id")
@FeignClient("user")
public interface UserFeign{
@RequestMapping("/user/me/{id}") //这里完全可以采用springmvc1的注解进行请求
User getById(@PathVariable Long id);
} @FeignClient,会声明这是一个Feign客户端,它会通过动态代理,自动生成实现类,和mybatis的mapper注解类似
其中方法上的请求路径,Feign会根据该值生成url 3.然后在Controller层调用Feign的客户端中的方法,其实,可以把Feign的客户端的这个接口理解为就是一个实现代码块而已,
注意@FeignClient注解不能和@Controller注解同时一起用
@Controller
public class Test{
@AutoWired
UserFeign userFeign @RequestMapping("/test/{id}")
public User getById(long id){
User user = userFeign.getById(id);
return user
}
} 4.在服务的消费者的启动类上开启Feign功能,用注解@EnableFeignClients开启。
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableFeignClients // 开启Feign功能
public class UserConsumerDemoApplication {.....} 5.因为Feign本身已经集成类Ribbon依赖和自动配置,使用不需要引入额外的依赖,也不再需要使用RestTemplate对象。
(也不需要引入重试机制包retry依赖) 2.Feign中重试机制配置:分为全局配置,就是服务消费者针对所有的请求的服务提供者都有效;局部配置,就是针对某一个服务。
全局配置:
ribbon:
ConnectTimeout: 250 # Ribbon的连接超时时间
ReadTimeout: 1000 # Ribbon的数据读取超时时间
OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
MaxAutoRetries: 1 # 对当前实例的重试次数 局部配置:
user-service: //服务名(或者服务的id)
ribbon:
ConnectTimeout: 250 # 连接超时时间(ms)
ReadTimeout: 1000 # 通信超时时间(ms)
OkToRetryOnAllOperations: true # 是否对所有操作重试
MaxAutoRetriesNextServer: 1 # 同一服务不同实例的重试次数
MaxAutoRetries: 1 # 同一实例的重试次数 3.Feign中结合Hystrix使用,使用步骤:
1.首先要定义一个类,这个类要实现上面的FeignClient的接口,然后重写其方法,在方法体中增加回退的代码(注意是在重写的方法里面写的,所以方法名、参数列表和返回值必须一致),如下:
@Component //注意,这必须要加Component注解,因为这个类和方法是spring自动加载和要调用
public Class Ht implements UserFeign{ public User getById(Long id){
sout("cnm");
return new User();
} }
2.要在@FeignClient的接口上,添加属性fallback
@FeignClient(value="user", fallback=Ht.class)
public interface UserFeign{
@RequestMapping("/user/me/{id}") //这里完全可以采用springmvc1的注解进行请求
User getById(@PathVariable Long id);
}
3.在yml中开启熔断器功能:
feign:
hystrix:
enabled: true # 开启Feign的熔断功能