Spring Cloud Eureka
- Eureka Server:注册中心
- Eureka Client,所有要进行注册的微服务通过Eureka Client连接到Eureka Server,完成注册。
Eureka Server代码实现
- 创建父工程,pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
<scope>provided</scope>
</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>
- 在父工程下创建Module,pom.xml
<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相关配置。
#当前Eureka Server服务端口。
server:
port: 8761
eureka:
client:
#是否将当前的Eureka Server服务端作为客户进行注册
register-with-eureka: false
#是否获取其他Eureka Server 服务的数据
fetch-registry: false
service-url:
#注册中心的访问地址
defaltZone: http://localhost:8761/eureka/
- 创建启动类
package com.yl.llh;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
//声明该类是Spring Boot服务的入口
@SpringBootApplication
//声明该类是一个Eureka Server 微服务,提供服务注册和服务发现功能,即注册中心。
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class,args);
}
}
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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 阿里fastjson包JSON转换-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
</dependencies>
- 创建配置文件application.yml,添加Eureka Client相关配置
server:
port: 8010
servlet:
context-path: /test
spring:
redis:
# Redis服务器连接端口
port: 6379
# Redis服务器地址
application:
#当前服务注册在Eureka Server上的名称
name: provider
eureka:
client:
service-url:
#注册中心的访问地址
defaultZone: http://localhost:8761/eureka
instance:
#是否将当前服务的ip注册到Eureka Server
prefer-ip-address: true
- 创建启动类
package com.yl.llh;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@EnableCaching
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
- 创建实体类
package com.yl.llh.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;
}
- 创建增删改查接口
package com.yl.llh.repository;
import com.yl.llh.entity.Student;
import java.util.Map;
public interface StudentRepository {
public Map findHash(String redisHash);
public Object findHash(String redisHash, String key);
public void deleteHash(String redisHash);
public void deleteHash(String redisHash, String key);
public void saveOrUpdate(String redisHash, String key, Student student);
}
- 实现接口方法
package com.yl.llh.repository.impl;
import com.yl.llh.entity.Student;
import com.yl.llh.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
import java.util.*;
@Repository
public class StudentRepositoryImpl implements StudentRepository {
@Autowired
private RedisTemplate redisTemplate;
/**
* @PostConstruct 会在servlet初始化时执行,只执行1次
* 作用:让当前方法在构造函数之后,在init方法之前执行
*/
// 这里我用了两种方式往redis里面添加数据
@PostConstruct
public void initData() {
Student stu = new Student();
stu.setId(1L);
stu.setName("llh");
stu.setAge(11);
HashOperations<String, String, Student> hashOps = redisTemplate.opsForHash();
hashOps.put("student", "1", stu);
hashOps.put("student", "2", new Student(2L, "李四", 23));
hashOps.put("student", "3", new Student(3L, "王五", 23));
}
@Override
public Map findHash(String redisHash) {
return redisTemplate.opsForHash().entries(redisHash);
}
@Override
public Object findHash(String redisHash, String key) {
return redisTemplate.opsForHash().get(redisHash, key);
}
@Override
public void deleteHash(String redisHash) {
redisTemplate.delete(redisHash);
}
@Override
public void deleteHash(String redisHash, String key) {
redisTemplate.opsForHash().delete(redisHash, key);
}
@Override
public void saveOrUpdate(String redisHash, String key, Student student) {
HashOperations<String, String, Student> hashOps = redisTemplate.opsForHash();
hashOps.put(redisHash, key, student);
}
}
- Handler
package com.yl.llh.controller;
import com.yl.llh.entity.Student;
import com.yl.llh.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/student")
public class StudentHandler {
@Autowired
private StudentRepository studentRepository;
@PostMapping("/findHash/{redisHash}")
public Map findHash(@PathVariable("redisHash") String redisHash) {
return studentRepository.findHash(redisHash);
}
@GetMapping("/findHash/{redisHash}/{key}")
public Object findHash(@PathVariable("redisHash") String redisHash, @PathVariable("key") String key) {
return studentRepository.findHash(redisHash, key);
}
@DeleteMapping("/deleteHash/{redisHash}/{key}")
public void deleteHash(@PathVariable("redisHash") String redisHash, @PathVariable("key") String key) {
studentRepository.deleteHash(redisHash, key);
}
@DeleteMapping("/deleteHash/{redisHash}")
public void deleteHash(@PathVariable("redisHash") String redisHash) {
studentRepository.deleteHash(redisHash);
}
@PostMapping("/save/{redisHash}/{key}")
public void save2(@PathVariable("redisHash") String redisHash, @PathVariable("key") String key, @RequestBody Student student) {
studentRepository.saveOrUpdate(redisHash, key, student);
}
@PutMapping("/update/{redisHash}/{key}")
public void update2(@PathVariable("redisHash") String redisHash, @PathVariable("key") String key, @RequestBody Student student) {
studentRepository.saveOrUpdate(redisHash, key, student);
}
}
-
创建redis工具类,这两个类好像是对往redis里面存数据时的序列化修改了以下,具体实现我也不太明白,当初没有这俩的时候往reids里面存数据会乱码在网上找了很久,找到了这两个工具类,这篇博客是隔了很久才写的,作者是谁,也找不到了,反正不是我原创
-
RedisUtil
package com.yl.llh.redis; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; @Component public final class RedisUtil { @Resource private RedisTemplate<String, Object> redisTemplate; public Set<String> keys(String keys) { try { return redisTemplate.keys(keys); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 指定缓存失效时间 * * @param key 键 * @param time 时间(秒) * @return */ public boolean expire(String key, long time) { try { if (time > 0) { redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据key 获取过期时间 * * @param key 键 不能为null * @return 时间(秒) 返回0代表为永久有效 */ public long getExpire(String key) { return redisTemplate.getExpire(key, TimeUnit.SECONDS); } /** * 判断key是否存在 * * @param key 键 * @return true 存在 false不存在 */ public boolean hasKey(String key) { try { return redisTemplate.hasKey(key); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除缓存 * * @param key 可以传一个值 或多个 */ @SuppressWarnings("unchecked") public void del(String... key) { if (key != null && key.length > 0) { if (key.length == 1) { redisTemplate.delete(key[0]); } else { redisTemplate.delete(CollectionUtils.arrayToList(key)); } } } /** * 普通缓存获取 * * @param key 键 * @return 值 */ public Object get(String key) { return key == null ? null : redisTemplate.opsForValue().get(key); } /** * 普通缓存放入 * * @param key 键 * @param value 值 * @return true成功 false失败 */ public boolean set(String key, Object value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 普通缓存放入并设置时间 * * @param key 键 * @param value 值 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 * @return true成功 false 失败 */ public boolean set(String key, Object value, long time) { try { if (time > 0) { redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); } else { set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 递增 * * @param key 键 * @param delta 要增加几(大于0) * @return */ public long incr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForValue().increment(key, delta); } /** * 递减 * * @param key 键 * @param delta 要减少几(小于0) * @return */ public long decr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForValue().increment(key, -delta); } /** * HashGet * * @param key 键 不能为null * @param item 项 不能为null * @return 值 */ public Object hget(String key, String item) { return redisTemplate.opsForHash().get(key, item); } /** * 获取hashKey对应的所有键值 * * @param key 键 * @return 对应的多个键值 */ public Map<Object, Object> hmget(String key) { return redisTemplate.opsForHash().entries(key); } /** * HashSet * * @param key 键 * @param map 对应多个键值 * @return true 成功 false 失败 */ public boolean hmset(String key, Map<String, Object> map) { try { redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * HashSet 并设置时间 * * @param key 键 * @param map 对应多个键值 * @param time 时间(秒) * @return true成功 false失败 */ public boolean hmset(String key, Map<String, Object> map, long time) { try { redisTemplate.opsForHash().putAll(key, map); if (time > 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * * @param key 键 * @param item 项 * @param value 值 * @return true 成功 false失败 */ public boolean hset(String key, String item, Object value) { try { redisTemplate.opsForHash().put(key, item, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * * @param key 键 * @param item 项 * @param value 值 * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 * @return true 成功 false失败 */ public boolean hset(String key, String item, Object value, long time) { try { redisTemplate.opsForHash().put(key, item, value); if (time > 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除hash表中的值 * * @param key 键 不能为null * @param item 项 可以使多个 不能为null */ public void hdel(String key, Object... item) { redisTemplate.opsForHash().delete(key, item); } /** * 判断hash表中是否有该项的值 * * @param key 键 不能为null * @param item 项 不能为null * @return true 存在 false不存在 */ public boolean hHasKey(String key, String item) { return redisTemplate.opsForHash().hasKey(key, item); } /** * hash递增 如果不存在,就会创建一个 并把新增后的值返回 * * @param key 键 * @param item 项 * @param by 要增加几(大于0) * @return */ public double hincr(String key, String item, double by) { return redisTemplate.opsForHash().increment(key, item, by); } /** * hash递减 * * @param key 键 * @param item 项 * @param by 要减少记(小于0) * @return */ public double hdecr(String key, String item, double by) { return redisTemplate.opsForHash().increment(key, item, -by); } /** * 根据key获取Set中的所有值 * * @param key 键 * @return */ public Set<Object> sGet(String key) { try { return redisTemplate.opsForSet().members(key); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 根据value从一个set中查询,是否存在 * * @param key 键 * @param value 值 * @return true 存在 false不存在 */ public boolean sHasKey(String key, Object value) { try { return redisTemplate.opsForSet().isMember(key, value); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将数据放入set缓存 * * @param key 键 * @param values 值 可以是多个 * @return 成功个数 */ public long sSet(String key, Object... values) { try { return redisTemplate.opsForSet().add(key, values); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 将set数据放入缓存 * * @param key 键 * @param time 时间(秒) * @param values 值 可以是多个 * @return 成功个数 */ public long sSetAndTime(String key, long time, Object... values) { try { Long count = redisTemplate.opsForSet().add(key, values); if (time > 0) expire(key, time); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 获取set缓存的长度 * * @param key 键 * @return */ public long sGetSetSize(String key) { try { return redisTemplate.opsForSet().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 移除值为value的 * * @param key 键 * @param values 值 可以是多个 * @return 移除的个数 */ public long setRemove(String key, Object... values) { try { Long count = redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } // ===============================list================================= /** * 获取list缓存的内容 * * @param key 键 * @param start 开始 * @param end 结束 0 到 -1代表所有值 * @return */ public List<Object> lGet(String key, long start, long end) { try { return redisTemplate.opsForList().range(key, start, end); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 获取list缓存的长度 * * @param key 键 * @return */ public long lGetListSize(String key) { try { return redisTemplate.opsForList().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 通过索引 获取list中的值 * * @param key 键 * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 * @return */ public Object lGetIndex(String key, long index) { try { return redisTemplate.opsForList().index(key, index); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @return */ public boolean lSet(String key, Object value) { try { redisTemplate.opsForList().rightPush(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, Object value, long time) { try { redisTemplate.opsForList().rightPush(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @return */ public boolean lSet(String key, List<Object> value) { try { redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, List<Object> value, long time) { try { redisTemplate.opsForList().rightPushAll(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据索引修改list中的某条数据 * * @param key 键 * @param index 索引 * @param value 值 * @return */ public boolean lUpdateIndex(String key, long index, Object value) { try { redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 移除N个值为value * * @param key 键 * @param count 移除多少个 * @param value 值 * @return 移除的个数 */ public long lRemove(String key, long count, Object value) { try { Long remove = redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception e) { e.printStackTrace(); return 0; } } }
-
RedisConfig
package com.yl.llh.redis; import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) public class RedisConfig { @Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate<>(); //使用fastjson序列化 FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); // value值的序列化采用fastJsonRedisSerializer template.setValueSerializer(fastJsonRedisSerializer); template.setHashValueSerializer(fastJsonRedisSerializer); // key的序列化采用StringRedisSerializer template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean(StringRedisTemplate.class) public StringRedisTemplate stringRedisTemplate( RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } }
-
Feign
- 什么是Feign
与Ribbon一样,Feign也是有Netfilx提供的,Feign是一个声明式、模板化的Web Service客户端,它简化了开发者编写Web服务客户端的操作,开发者可以通过简单的接口和注解来调用HTTP API,Spring Cloud Feign,它整合了Ribbon和Hystrix,具有可插拔、基于注解、负载均衡、服务熔断等一系列便捷功能。
相比较于Ribbon+RestTemplate的方式,Feign大大简化了代码的开发,Feign支持多中注解,包括Feign注解、JAX-RS注解、Spring MVC注解,Spring Cloud对Feign进行了优化,整合了Ribon和Eureka,从而让Feign的使用更加方便。
- Ribbon和Feign的区别
Ribbon是一个通用的HTTP客户端工具,Feign是基于Ribbon实现的。
- Feign的特点
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>
<dependency>
<groupId>com.yl.llh</groupId>
<artifactId>eurekaclient</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</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
#是否开启熔断器
feign:
hystrix:
enabled: true
- 创建启动类
package com.yl.llh;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication(scanBasePackages = "com.yl.llh")
@EnableFeignClients(basePackages = {"com.yl.llh.feign"})
public class FeignApplication {
public static void main(String[] args) {
SpringApplication.run(FeignApplication.class, args);
}
}
- 创建实体类
package com.yl.llh.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;
}
- 创建声明式接口
package com.yl.llh.feign;
import com.yl.llh.entity.Student;
import com.yl.llh.feign.fallback.FeignProviderClientFallBackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
//当无法访问以下GetMapping,则执行FeignProviderClientFallBackFactory.class,容错机制(文章末尾有介绍),从而避免响应时间过长,抛出异常
@FeignClient(value = "provider", fallbackFactory = FeignProviderClientFallBackFactory.class)
public interface FeignProviderClient {
@PostMapping("/test/student/findHash/{redisHash}")
Map findHash(@PathVariable("redisHash") String redisHash);
@GetMapping("test/student/findHash/{redisHash}/{key}")
Object findHash(@PathVariable("redisHash") String redisHash, @PathVariable("key") String key);
@PostMapping("test/student/save/{redisHash}/{key}")
void save(@PathVariable("redisHash") String redisHash, @PathVariable("key") String key, @RequestBody Student student);
@PutMapping("test/student/update/{redisHash}/{key}")
void update(@PathVariable("redisHash") String redisHash, @PathVariable("key") String key, @RequestBody Student student);
@DeleteMapping("test/student/deleteHash/{redisHash}/{key}")
void deleteHash(@PathVariable("redisHash") String redisHash, @PathVariable("key") String key);
@DeleteMapping("test/student/deleteHash/{redisHash}")
void deleteHash(@PathVariable("redisHash") String redisHash);
}
- 创建FeignProviderClient实现类FeignProviderClientFallBackFactory,定义容错处理逻辑,通过
@Component
注解将FeignProviderClientFallBackFactory实例注入IOC中(我这个没具体写内容,创建实现接口之后,ctrl+i 结束)
package com.yl.llh.feign.fallback;
import com.yl.llh.entity.Student;
import com.yl.llh.feign.FeignProviderClient;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class FeignProviderClientFallBackFactory implements FallbackFactory<FeignProviderClient> {
@Override
public FeignProviderClient create(Throwable throwable) {
return new FeignProviderClient() {
@Override
public Map findHash(String redisHash) {
return null;
}
@Override
public Object findHash(String redisHash, String key) {
return null;
}
@Override
public void save(String redisHash, String key, Student student) {
}
@Override
public void update(String redisHash, String key, Student student) {
}
@Override
public void deleteHash(String redisHash, String key) {
}
@Override
public void deleteHash(String redisHash) {
}
};
}
}
- Handler
package com.yl.llh.controller;
import com.yl.llh.entity.Student;
import com.yl.llh.feign.FeignProviderClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/feign")
public class FeignHandler {
@Autowired
private FeignProviderClient feignProviderClient;
/**
* 通过大key查询数据
* http://localhost:8050/feign/findHash/student
* @param redisHash 大key,相当于哪张表
* @return
*/
@GetMapping("/findHash/{redisHash}")
public Map findHash(@PathVariable("redisHash") String redisHash) {
return feignProviderClient.findHash(redisHash);
}
/**
* 通过小key插叙数据
* http://localhost:8050/feign/findHash/student/3
* @param redisHash
* @param key 小key,某条数据的key
* @return
*/
@GetMapping("/findHash/{redisHash}/{key}")
public Object findHash(@PathVariable("redisHash") String redisHash, @PathVariable("key") String key) {
return feignProviderClient.findHash(redisHash, key);
}
/**
* 删除表中的一条数据
* http://localhost:8050/feign/deleteHash/student/3
* @param redisHash
* @param key
*/
@GetMapping("/deleteHash/{redisHash}/{key}")
public void deleteHash(@PathVariable("redisHash") String redisHash, @PathVariable("key") String key) {
feignProviderClient.deleteHash(redisHash, key);
}
/**
* 删除整个表
* http://localhost:8050/feign/deleteHash/student
* @param redisHash
*/
@GetMapping("/deleteHash/{redisHash}")
public void deleteHash(@PathVariable("redisHash") String redisHash) {
feignProviderClient.deleteHash(redisHash);
}
/**
* 添加一张表并插入一条数据,添加的格式为json格式
* http://localhost:8050/feign/save/student/3
* {
* "name": "星星03",
* "id": 3,
* "age": 44
* }
* @param redisHash
* @param key
* @param student 对象,
*/
@GetMapping("/save/{redisHash}/{key}")
public void save2(@PathVariable("redisHash") String redisHash, @PathVariable("key") String key, @RequestBody Student student) {
feignProviderClient.save(redisHash, key, student);
}
/**
* 更新某张表里的数据,格式为json格式
* http://localhost:8050/feign/update/student/1
* {
* "name": "星星01",
* "id": 1,
* "age": 23
* }
* @param redisHash
* @param key
* @param student
*/
@GetMapping("/update/{redisHash}/{key}")
public void update2(@PathVariable("redisHash") String redisHash, @PathVariable("key") String key, @RequestBody Student student) {
feignProviderClient.update(redisHash, key, student);
}
}
- 容错机制
在不改变各个微服务调用关系的前提下,针对错误情况进行预先处理。
- 设计原则
1、服务隔离机制:指防止某个服务提供者出现问题而影响到整个系统的运行
2、服务降级机制:指服务出现故障时向服务消费者返回fallback的降级处理
3、熔断机制:当服务消费者请求失败率达到某一个特定的数值的时候会迅速启动熔断机制,并对错误进行修复
4、提供实时的监控和报警功能
5、提供实时的配置修改功能