[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RGNq6ueY-1603278766654)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1584929037174.png)]
配置文件
server: port: 8761 eureka: instance: hostname: eureka-server #eureka实例的主机名字 client: register-with-eureka: false #不把自己注册到 eureka fetch-registry: false #不从eureka上获取服务的注册信息 service-url: defaultZone: http://localhost:8761/eureka/在启动类上添加注解
@EnableEurekaServer //启动注册中心[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qilRvHXc-1603278766658)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1584929138810.png)]
配置文件
server: port: 8002 spring: application: name: provider-ticket eureka: instance: prefer-ip-address: true #注册服务时使用ip地址 client: service-url: defaultZone: http://localhost:8761/eureka/[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HhK6zVEo-1603278766661)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1584929282691.png)]
配置文件
spring: application: name: consumer-user server: port: 8200 eureka: instance: prefer-ip-address: true #注册服务时使用ip地址 client: service-url: defaultZone: http://localhost:8761/eureka/启动类添加 获取服务注解 开启负载均衡
@EnableDiscoveryClient //开启获取服务 @SpringBootApplication public class ConsumerUserApplication { public static void main(String[] args) { SpringApplication.run(ConsumerUserApplication.class, args); } @LoadBalanced //使用负载均衡 @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } }开始获取服务
@RestController public class UserController { @Autowired RestTemplate template; @GetMapping("/buy") public String buyTicket(String name){ //第一个参数为注册中心的服务名 , 第二个参数返回值类型; String s = template.getForObject("http://PROVIDER-TICKET/ticket",String.class); return name+"购买了"+s; } }Spring --> SpringMvc --> Tomcat 简化配置值
舍弃笨重的xml 改用 yml 或properties产品独立运行
产品可独立运行,打成jar包,内置了tomcat 或其他servlet容器,契合微服务的理念;强大的场景启动器
每一个特定场景需求都封装成了有个starter,只需要导入这个启动器就有了这个场景所需的一切,其中包括针对这个场景的自动化配置,依赖信息;重要的组成部分
starter 启动器 @Enablexxx 注解 功能启用 yml 或 propertires 配置文件 主启动类读取spring.factories文件
SpringBoot启动时会读取spring-boot-autoconfigure-2.2.5.RELEASE.jar包下的ME TA-INF/spring.factories文件。读取 org.springframework.boot.autoconfigure.EnableAutoConfiguration属性的值加载自动配置类。加载XxxProperties类
根据自动配置类中指定的XxxPropertes类设置自动配置的属性值,开发者也可以根据XxxProperties类中指定的属性在yml 配置文件中修改自动配置。.根据@ConditionalXxx注解决定加载哪些组件
SpringBoot通过@ConditionalXxx注解指定特定组件加入IOC容器时所需要具备的特定条件。这个组件会在满足条件时加入 I0C容器。出现认证问题,应该是设置了认证密码,输入密码既可以啦
注意密码是字符串形式!
cdm 命令
//密码 auth "yourpassword" //查询所有的 keys keys * //查询指定 key的值 get key[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ka3ibEb2-1603278766665)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1585097293833.png)]
创建boot 项目
建议使用boot 项目
openfeign 提供远程业务接口
调用者:
//远程调用的接口方法 //要求 方法完全一致 (修饰符,参数,方法名,返回值) //请求方式 ,请求路径完全一致 //使用的注解完全一致 import com.sl.commons.pojo.Employee; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; // 表示当前接口和一个 provider的服务对应 @FeignClient("provider") public interface EmployeeRemoteService { //远程调用的接口方法 //要求 方法完全一致 (修饰符,参数,方法名,返回值) //请求方式 ,请求路径完全一致 //使用的注解完全一致 @RequestMapping("/provider/get/employee/remote") public Employee getEmployeeRemote(); }创建boot 项目 (web)
启动类 2.0版本之下的需要添加注解 其下任意一个即可
@EnableEurekaClient
只能是获取 Eureka注册中心提供的服务;
@EnableDiscoveryClient
可以获取任意注册中写 的服务
注意点:
//远程调用的接口方法 //要求 方法完全一致 (修饰符,参数,方法名,返回值) //请求方式 ,请求路径完全一致 //使用的注解完全一致
@RestController public class EmployeeController { @RequestMapping("/provider/get/employee/remote") public Employee getEmployeeRemote(){ System.out.println("1000"); return new Employee(555,"provider:",555.55); }创建 boot项目 (web)
扫描Feign提供的远程接口
@EnableFeignClients("com.sl.commons")ribbon
负载均衡:的实现过程被隐藏 在远程调用微服务是开启;
spring-cloud-starter-netflix-ribbon集群:一模一样的业务的集合,来自于同一个注册中兴,端口不一样,服务名一样;
@RequestParam(“id”) String id
@RequestBody Student stu
作为项目的统一返回值
ResultEntity
package com.sl.commons.util; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * 项目统一使用 这个类型作为Ajax 请求 或远程 * 方法条用返回响应的数据格式 * @param <T> */ @Data @AllArgsConstructor @NoArgsConstructor public class ResultEntity<T> { public static final String SUCCESS = "SUCCESS"; //成功 public static final String FAILED = "FAILED"; //失败 public static final String NO_MESSAGE = "NO_MESSAGE"; //无消息 public static final String NO_DATA = "NO_DATA"; //无数据 private String resulr; private String message; private T data; /** * 操作成功,无需返回数据 * @return */ public static ResultEntity<String> successWithoutData(){ return new ResultEntity<String>(SUCCESS,NO_MESSAGE,NO_DATA); } /** * 操作成功 ,需要返回数据 * @param data * @param <E> * @return */ public static <E> ResultEntity<E> successWithoutData(E data){ return new ResultEntity<>(SUCCESS,NO_MESSAGE,data); } /** * 操作失败 ,返回错误信息 * @param message * @param <E> * @return */ public static <E> ResultEntity<E> failed(String message){ return new ResultEntity<>(SUCCESS,message,null); } }实现 FallbackFactory
package com.sl.commons.factory; import com.sl.commons.api.EmployeeRemoteService; import com.sl.commons.pojo.Employee; import com.sl.commons.util.ResultEntity; import feign.hystrix.FallbackFactory; import org.springframework.stereotype.Component; import java.util.List; /** * 实现 Conumer 服务降级的功能 * 实现 FallbackFactory 这个借口是 要传入 @FeignClient注解标记的接口类型; * 实现create 方法 返回 @FeignClient注解标记的接口类型的对象 当 provide调用失败时 会执行这个对象对应的方法 */ @Component public class MyFallBackFactiry implements FallbackFactory<EmployeeRemoteService> { @Override public EmployeeRemoteService create(Throwable throwable) { return new EmployeeRemoteService() { @Override public Employee getEmployeeRemote() { return null; } @Override public List<Employee> getEList(String key) { return null; } @Override public ResultEntity<Employee> breaker(String signal) { return ResultEntity.failed(throwable.getMessage()+"降级使用"); } }; } }注解
@FeignClient(value = “provider”,fallbackFactory = MyFallBackFactiry.class)
package com.sl.commons.api; import com.sl.commons.factory.MyFallBackFactiry; import com.sl.commons.pojo.Employee; import com.sl.commons.util.ResultEntity; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import java.util.List; // 表示当前接口和一个 provider的服务对应 //fallbackFactory 指定 provider 不可使用时 提供备用的 工厂对象 @FeignClient(value = "provider",fallbackFactory = MyFallBackFactiry.class) public interface EmployeeRemoteService { //远程调用的接口方法 //要求 方法完全一致 (修饰符,参数,方法名,返回值) //请求方式 ,请求路径完全一致 //使用的注解完全一致 @RequestMapping("/provider/get/employee/remote") public Employee getEmployeeRemote(); @RequestMapping("/provider/get/empList/remote") List<Employee> getEList(@RequestParam("key") String key); @RequestMapping("/provider/get/emp/circuit/breaker") public ResultEntity<Employee> breaker(@RequestParam("signal") String signal)throws InterruptedException; }@HystrixCommand 指定方法出现问题时调用备份方法
// @HystrixCommand 指定方法出现问题时调用备份方法; @HystrixCommand(fallbackMethod = "breaker2") @RequestMapping("/provider/get/emp/circuit/breaker") public ResultEntity<Employee> breaker(@RequestParam("signal") String signal) throws InterruptedException { if ("quick-bang".equals(signal)) { throw new RuntimeException(); } if ("slow-bang".equals(signal)) { Thread.sleep(5000); } return ResultEntity.successWithoutData(new Employee(555,"provider3",555.55)); } public ResultEntity<Employee> breaker2(@RequestParam("signal") String signal){ String message = "方法出现问题"+signal+"/n执行备用方法"; return ResultEntity.failed(message); }@EnableHystrixDashboard
http://localhost:9000/hystrix
完成一整套的服务 ;才能有该服务的监控;
http://localhost:8001/actuator/hystrix.stream
创建新的 Sprinboot项目
http://localhost:9000/ consumer/feign/get/fallback
zuul网关 微服务名字 目标具体的微服务
配置为zuul ,从zuul 进入调用服务 必须按照 zuul 定义的规则来进行访问服务
http://localhost:9000/ sl/zuul-empfeign/get/fallback
MyZuulFilter
package com.sl.zuul.config; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @Component public class MyZuulFilter extends ZuulFilter { Logger logger = LoggerFactory.getLogger(MyZuulFilter.class); @Override public String filterType() { //返回当前过滤器的类型,并决定当前过滤器在什么时候执行 //pre 表示 在目标微服务之前执行 String filterType = "pre"; return filterType; } @Override public int filterOrder() { return 0; } //判断当前请求是否过滤 //如果过滤 执行 run方法 //不过滤 直接放行 //shouldFilter 返回 true 调用 run 方法 false 放行 @Override public boolean shouldFilter() { //获取 RequestContext 对象 //threadLocal; 本地化; // 你在上游通过threadLocal.set(T value) 存 // 你在下游 通过threadLocal.get() 方法取 ,因为是同一条河(同一线程)所以可以取; RequestContext currentContext = RequestContext.getCurrentContext(); //获取 Request 对象 HttpServletRequest request = currentContext.getRequest(); String signal = request.getParameter("signal"); return "hello".equals(signal); } @Override public Object run() throws ZuulException { logger.info("当前请求要过滤,执行了 run() 方法"); //当前实现会忽略这个返回值 , 所以返回null,不做特殊处理; return null; } }