SpringCloud学习笔记
作者:互联网
1、SpringCloud基础学习
1、模块之间的调用
1、模块之间的调用使用RestTemplate类,将这个类交由Spring容器管理
RestTemplate:提供多种便捷访问远程http服务的方法,简单的restful服务模板
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
2、测试
-
生产者Controller
@RestController
@RequestMapping("/dept")
public class DeptController {
@Autowired
private DeptService deptService;
@GetMapping("/list")
public String list(){
return deptService.getDeptList().toString();
}
@PostMapping("/add")
public boolean add(@RequestBody Dept dept){
return deptService.addDept(dept);
}
} -
消费者Controller
@Controller
@RequestMapping("/consumer")
public class DeptConsumerController {
private static final String REST_URL_PREFIX = "http://localhost:8001";
@Autowired
private RestTemplate restTemplate;
// 消费者不应该有Service,而是通过RestTemplate调用生产者的接口
@GetMapping("/depts")
@ResponseBody
public String getDepts(){
String listStr = restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", String.class);
return listStr;
}
@GetMapping("/add")
@ResponseBody
public String addDepts(){
Dept dept = new Dept();
dept.setName("总经办").setDatasource("test");
Boolean isSuccess = restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
return String.valueOf(isSuccess);
}
}
2、Eureka服务注册与发现
==注意==:本次父工程用的SpringBoot和SpringCloud的依赖版本如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Eureka包含两大组件:EurekaServer 和 EurekaClient
EurekaServer提供服务注册服务:每个服务启动后在EurekaServer进行注册,EurekaServer服务注册表会储存所有服务节点的信息,这些节点信息会在服务界面中直观的看到
EurekaClient是一个java客户端,用于简化与EurekaServer的交互,客户端也具备一个内置的、使用轮询(roud-robin)负载算法的负载均衡器。在启动应用后会EurekaServer发送心跳(默认为30秒)。如果EurekaServer在多个心跳周期内没有接到某个节点的心跳,EurekaServer会从注册表中把这个服务移除(默认90秒)
1、EurekaServer 配置
1、导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
2、eureka配置文件配置
server:
port: 7001
eureka:
instance:
hostname: localhost # eureka服务端的实例名称
client:
register-with-eureka: false # 是否向eureka注册中心注册自己
fetch-registry: false # 如果为false,则表示自己为注册中心
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # 注册中心的交互地址
3、在主配置类上开启自动启用eureka服务
@SpringBootApplication
@EnableEurekaServer
public class SpringCloudEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudEurekaApplication.class,args);
}
}
2、EurekaClient注册服务
1、导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2、配置文件配置
server:
port: 8001
eureka:
client:
serviceUrl:
defaultZone: http://localhost:7001/eureka/
instance:
# 自定义服务名称
instance-id: dept-provider8001
# 访问路径是否显示ip
prefer-ip-address: true
3、主配置类上加上@EnableEurekaServer注解
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication7001.class,args);
}
}
4、服务信息完善
-
加入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency> -
application.yml配置添加
info:
app.name: springcloud
app.company: www.myspringcloud.com
3、Eureka自我保护机制
在自我保护模式中,Eureka Server会保护注册表中的服务信息,不再注销任何服务实例。当他收到的心跳数重新恢复到阈值以上时,该Eureka Server节点就会自动退出自我保护机制。它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的实例。一句话讲解:好死不如赖活着。
可以通过 server.enable-self-preservation = false禁用掉自我保护机制,但不推荐禁用
4、服务发现:
1、主配置类上加上@EnableDiscoveryClient注解
@EnableDiscoveryClient
public class DeptProvider8001Application {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001Application.class,args);
}
}
2、使用DiscoveryClient类
@Autowired
private DiscoveryClient client;
@GetMapping("/servers")
public Object servers(){
List<String> services = client.getServices();
System.out.println(services);
List<ServiceInstance> instances = client.getInstances("SPRINGCLOUD-PROVIDER");
instances.forEach(i -> {
System.out.println(i.getServiceId() + "\t" + i.getHost() + "\t" + i.getPort());
});
return this.client;
}
5、Eureka搭建集群
项目端口为7001、7002、7003的为Eureka Server
项目端口为8001的为要注册的服务
1、项目7001配置
server:
port: 7001
eureka:
instance:
# eureka服务实例名称
hostname: eureka7001
client:
register-with-eureka: false # 不向注册中心注册自己
fetch-registry: false # 表示自己就是注册中心
service-url:
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
2、项目7002配置
server:
port: 7002
eureka:
instance:
# eureka服务实例名称
hostname: eureka7002
client:
register-with-eureka: false # 不向注册中心注册自己
fetch-registry: false # 表示自己就是注册中心
service-url:
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
3、项目7003配置
server:
port: 7003
eureka:
instance:
# eureka服务实例名称
hostname: eureka7003
client:
register-with-eureka: false # 不向注册中心注册自己
fetch-registry: false # 表示自己就是注册中心
service-url:
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
4、项目8001配置
eureka:
client:
serviceUrl:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
# 自定义服务名称
instance-id: dept-provider8001
# 访问路径是否显示ip
prefer-ip-address: true
3、Ribbon负载均衡
1、Ribbon的简单使用
客户端的负载均衡,查找到可用服务实例列表,把每个请求在服务列表中轮询
1、导入jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
2、RestTemplate加上@LoadBalanced注解
@Configuration
public class ConfigBean {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
2、Ribbon的负载均衡算法
要使用其它的算法,则在config的配置类将IRule的实现类注入到bean容器即可,默认的是使用轮询RoundRobinRule
3、自定义RIbbon负载均衡算法
1、在主配置类上加上@RibbonClient(name = "服务名",configuration = 自定义算法类.class)
注意: 自定的Ribbon算法类不能放在@ComponentScan注解扫描的包及其子包下,也就是说不能放在主配置类所在的包下及其子包下
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "服务名",configuration = MySelfRule.class)
public class DeptConsumerApplication80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerApplication80.class,args);
}
}
2、MySelfRule.java
@Configuration
public class MySelfRule {
@Bean
public IRule myRule(){
return new MyRandomRule();
}
}
3、MyRandomRule.java
根据RandomRule.java实现的算法修改成自定义算法:每台服务在被调用5次后轮询下一台服务
public class MyRandomRule extends AbstractLoadBalancerRule {
// 服务被调用的次数
private int total = 0;
// 当前服务list的下标
private int currentIndex = 0;
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
if (Thread.interrupted()) {
return null;
}
// 可用的服务列表
List<Server> upList = lb.getReachableServers();
// 所有服务列表
List<Server> allList = lb.getAllServers();
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
// 是否被掉用5次
if (total < 5){
server = upList.get(currentIndex);
total ++;
} else {
total = 0;
currentIndex ++;
// 轮询到最后一台服务,则从头开始轮询
if (currentIndex >= allList.size()){
currentIndex = 0;
}
}
if (server == null) {
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
server = null;
Thread.yield();
}
return server;
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
// TODO Auto-generated method stub
}
}
4、Feign负载均衡
什么是Feign?
Feign是一个声明式的Web服务客户端,使得编写Web服务客户端变得非常容易
使用方法:==只需要创建一个接口,在上面添加注解即可==
Feign继承了Ribbon,所以默认也是轮询实现客户端的负载均衡。而与Ribbon不同的是,==通过Feign只需要定义服务绑定接口且以声明式的方法==,优雅而简单的实现服务调用
1、导入jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、在接口上使用@FeignClient(value = "服务名称")注解绑定服务名称
@FeignClient(value = "服务名称")
public interface DeptClientService {
@GetMapping("/对应服务接口url")
public String list();
@GetMapping("/对应服务接口url")
public String get(@PathVariable("deptNo") Integer deptNo);
@PostMapping("/对应服务接口url")
public boolean add(@RequestBody Dept dept);
}
3、在主启动类上加@EnableFeignClients(basePackages = {"@FeignClient标注接口所在的包"})扫描到我们的FeignClient接口到容器
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"@FeignClient所在的包"})
public class DeptConsumerFeignApplication {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerFeignApplication.class,args);
}
}
总结:Feign相当于Ribbon + RestTemplate
5、Hystrix断路器
微服务面临的问题:当服务与服务之间的调用中,某个服务在不可用的情况下,可能会造成请求超时、延时,但有大量的请求的时候就可能会造成服务资源紧张,从而导致服务雪崩。==而Hystrix作为断路器可以向调用方返回一个符合预期、可处理的备选响应(FallBack),而不是长时间等待或抛出调用方法处理异常。==这样保证了线程不会被长时间、不必要的占用,从而避免故障在分布式系统中的蔓延,乃至雪崩。
1、服务熔断
1、导入jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、主启动类上加上@EnableCircuitBreaker注解,开启对hystrix的支持
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
// 启动对hystrix熔断器的支持
@EnableCircuitBreaker
public class DeptProviderHystrixApplication8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProviderHystrixApplication8001.class,args);
}
}
3、在调用方法上加上@HystrixCommand(fallbackMethod = "当方法抛出异常时要调用的接口")
@GetMapping("/get/{deptNo}")
// 报错时调用/hystrixGet接口
@HystrixCommand(fallbackMethod = "hystrixGet")
public String get(@PathVariable("deptNo") Integer deptNo) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Dept dept = service.get(deptNo);
// 如果结果为空,则抛出异常
if (null == dept){
throw new RuntimeException("该部门Id" + deptNo + "没有对应的信息");
}
String deptJson = objectMapper.writeValueAsString(dept);
return deptJson;
}
@GetMapping("/hystrixGet")
public String hystrixGet(@PathVariable("deptNo") Integer deptNo){
return "没有找到部门信息";
}
2、服务降级
在我们的服务不可用的时候,会调用我们Feign接口实现类的方法
1、创建我们Feign接口的处理类DeptClientServiceFallbackFactory
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {
@Override
public DeptClientService create(Throwable cause) {
return new DeptClientService() {
/**
* 获取所有部门
* @return
*/
@Override
public String list() {
return "系统错误!";
}
/**
* 根据部门id获取部门
* @param deptNo
* @return
*/
@Override
public String get(Integer deptNo) {
return "系统错误!";
}
/**
* 添加一个部门
* @param dept
* @return
*/
@Override
public boolean add(Dept dept) {
return false;
}
};
}
}
2、接口的@FeignClient(value = "服务名称",fallbackFactory = DeptClientServiceFallbackFactory.class)指定我们的处理类
//@FeignClient(value = "SPRINGCLOUD-PROVIDER")
@FeignClient(value = "SPRINGCLOUD-PROVIDER",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
@GetMapping("/list")
public String list();
@GetMapping("/get/{deptNo}")
public String get(@PathVariable("deptNo") Integer deptNo);
@PostMapping("/add")
public boolean add(@RequestBody Dept dept);
}
3、在application.yml配置文件中加上配置
feign:
hystrix:
enabled: true # 开启熔断机制
==注意:在Feign接口的实现类上别忘记加上@Component注解==
6、服务监控Hystrix Dashboard
Hystrix提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求成功,多少失败等。
1、监控服务模块(端口9001)
1、添加依赖
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--hystrix dashboard-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
2、主启动类上添加@EnableHystrixDashboard注解开启服务监控支持
@SpringBootApplication
@EnableHystrixDashboard
public class DeptHystrixDashboardApplication9001 {
public static void main(String[] args) {
SpringApplication.run(DeptHystrixDashboardApplication9001.class,args);
}
}
2、被监控服务模块(端口8001)
1、添加依赖
<!--actuator监控信息完善-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、主启动类添加@EnableCircuitBreaker开启熔断功能
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
// 启动对hystrix熔断器的支持
@EnableCircuitBreaker
public class DeptProviderHystrixApplication8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProviderHystrixApplication8001.class,args);
}
}
3、application.yml配置文件配置(通过“/actuator/hystrix.stream”访问不到时)
# hystrix dashboard服务监控访问路径
management:
endpoints:
web:
exposure:
include: "*"
7、Zuul网关
两个主要功能:路由和过滤
路由:将外部请求转发到具体的微服务实例上,实现了外部统一访问的统一入口
过滤:对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础
注意: Zuul服务最终会注册到Eureka
提供 = 代理 + 路由 + 过滤三大功能
1、网关模块(端口:9527)导入依赖
<!-- eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--zuul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
2、主配置类上添加@EnableZuulProxy注解
@SpringBootApplication
@EnableZuulProxy
public class DeptZuulGatewayApplication9527 {
public static void main(String[] args) {
SpringApplication.run(DeptZuulGatewayApplication9527.class,args);
}
}
3、application.yml配置路由
zuul:
prefix: /springcloud # 所有的请求前缀都要加上才能访问
routes:
mydept: # 面向服务的路由配置,此名称可以自定义
service-id: springcloud-provider
path: /mydept/**
ignored-services: springcloud-provider # 不能再通过原有的服务名访问
# 所有的原有服务名都不能访问
# ignored-services: "*"
注意:网关模块也需要注册到eureka,配好路由后访问接口通过:http://localhost:9527/zuul前缀/服务映射名/接口路径
8、Config配置中心
微服务要将单体应用拆分成许多的子服务,因此系统会出现大量的服务,每个服务又都需要必要的配置信息才能运行,后期要修改配置,维护起来也不方便。所以一套集中式,动态配置管理设施必不可少。SpringCloud提供了Config Server来解决这个问题。
1、Config服务端(端口:3344)
1、导入依赖
<!--springcloud config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
2、主配置类上加上@EnableConfigServer注解
@SpringBootApplication
@EnableConfigServer
public class SpringCloudConfigApplication3344 {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConfigApplication3344.class,args);
}
}
3、application.yml配置文件
server:
port: 3344
spring:
application:
name: springcloud-config
cloud:
config:
server:
git:
uri: "远程仓库地址"
username: "用户名"
password: "密码"
default-label: "默认分支"
4、配置读取规则
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
{application}: 配置文件的名称
{profile}: 配置文件的版本,例如我们开发中的 dev:开发环境版本 test:测试环境版本 release:发布环境版本
.yml和.properties: 用于区分两种配置文件
{label}: 表示 git 分支,默认是 master 分支
示例:http://localhost:3344/application/dev/master
http://localhost:3344/application-dev.yml
http://localhost:3344/master/application-dev.yml
http://localhost:3344/application-dev.properties
http://localhost:3344/master/application-dev.properties
2、Config客户端(通过Config服务端读取远程配置,动态获取端口启动项目)
1、导入依赖
<!--springcloud config客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--必须要-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、创建bootstrap.yml,进行如下配置
spring:
cloud:
config:
name: application # 从远程仓库读取的配置文件名,注意:没有.yml后缀
profile: dev # 配置文件版本
label: master # 分支名
uri: localhost:3344 # config配置中心服务端地址
==注意:application.yml:用户级别配置文件==
==bootstrap.yml:系统级别配置文件,优先级大于application.yml==
标签:服务,String,SpringCloud,笔记,public,学习,eureka,class,cloud 来源: https://www.cnblogs.com/zhouqiangshuo/p/16511967.html