标签:eth lse ice 提供者 代理 obj -- 用户信息 cell
为了提供并发量,有时同一个服务提供者可以部署多个(商品服务)。这个客户端在调用时要根据一定的负责均衡策略完成负载调用。
实际生产就是同一种服务多部署几台服务器,开发时就是用端口来区分。
1) 拷贝一份8001
2) 修改主类-改名
3) 改8002yml,端口
4) 服务提供者
1)常见的负载均衡技术
Ribbon feign
2)常见的负载均衡
轮休
可用性检查
权重
内置负载均衡规则类 |
规则描述 |
RoundRobinRule(默认) |
简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。 |
AvailabilityFilteringRule |
对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 注意:可以通过修改配置loadbalancer.<clientName>.connectionFailureCountThreshold来修改连接失败多少次之后被设置为短路状态。默认是3次。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上线,可以由客户端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置。
|
WeightedResponseTimeRule |
为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 |
|
|
|
|
|
随机选择一个可用的服务器。 |
Retry |
重试机制的选择逻辑 |
3)ribbon
a. 配置层添加@LoadBAlanced注解
/** * RestTemplate调用远程接口 * @author Lenovo */ @Configuration public class BaseConfig { @Bean @LoadBalanced //开启负载均衡 public RestTemplate restTemplate() { return new RestTemplate(); } }
b. controller层代码
@RestController @RequestMapping("/order") public class OrderController { @Autowired private RestTemplate restTemplate; /** * 通过服务名完成调用 */ private final String URL_PREFIX = "http://PRODUCT-SERVICE/product/"; /** * 暴露通过id远程查询product的接口 * @param id * @return */ @GetMapping("/product/{id}") public Product getProductById(@PathVariable("id") Long id){ /** * 缺点:要拼接的地址很长 */ String url = URL_PREFIX + id; //以接口的方式进行调用 return restTemplate.getForObject(url,Product.class); } }
2) feign
a. 主类配置扫描client
/** * 如果你的client就在该类的子子孙孙包,否则必须指定包名 * 加了它以后,就会扫描加了@FeignClient这个注解的接口,并且为这些接口产生代理对象 * 并且把这些代理对象纳入spring管理,我们要使用时直接获取就可以完成远程调用 * */ @EnableFeignClients
b. client代码
@FeignClient(value = "PRODUCT-SERVICE") //里面所有的方法都要调用PRODUCT-SERVCIE这个服务 @RequestMapping("/product") public interface ProductClient { /** * 回掉托底 */ @GetMapping("/{id}") public Product getProductById(@PathVariable(name = "id") Long id); }
c. controller层代码。(注解注入client调用接口)
@RestController @RequestMapping("/order") public class OrderController { @Autowired private ProductClient productClient; /** * 暴露通过id远程查询product的接口 * @param id * @return */ @GetMapping("/product/{id}") public Product getProductById(@PathVariable("id") Long id){ return productClient.getProductById(id); } }
微服务架构储器服务健壮的框架
解决微服务架构的雪崩现象
资源隔离(限流):包括线程池隔离和信号量隔离,限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其他服务调用。
熔断:当失败率达到阀值自动触发降级(如因网络故障/超时造成的失败率高),熔断器触发的快速失败会进行快速恢复。
降级机制:超时降级、资源不足时(线程或信号量)降级,降级后可以配合降级接口返回托底数据。
缓存:提供了请求缓存、请求合并实现。
1)导入依赖
<!--断路器--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
2)主类添加@EnableHystrix注解
@EnableHystrix //开启hystrix 熔断和降级才会生效
3)controller层代码
@RestController @RequestMapping("/product") public class ProductController { @Autowired private ProductService productService; /** * 根据id查询单条数据 * @param id * @return */ @GetMapping("/{id}") @HystrixCommand(fallbackMethod = "findOneFallback") public Product findOne(@PathVariable(name = "id") Long id) { //如果传入的id=2,报一个错让他熔断,其他的正常访问 if (id.intValue() == 2){ throw new RuntimeException("报错了!"); } Product product = productService.findOne(id); //为了查看是那个服务(端口运行得) product.setName(product.getName() + "-8003"); return product; } private Product findOneFallback(Long id) { return new Product(id, "已经熔断啦..."); } }
feign熔断机制是封装hystrix
1)托底关键代码
/** * 这个工程类要给我们配一个ProductClient的托底类 * @author Lenovo */ @Component public class ProductClientFallbackFactory implements FallbackFactory<ProductClient> { /** * 里面就是返回托底类,里面要为每个方法都有一个托底方法 * @param throwable * @return */ @Override public ProductClient create(Throwable throwable) { return new ProductClient() { @Override public Product getProductById(Long id) { return new Product(id, "feign的托底方法"); } }; } }
2)修改ProductClient@FeignClient注释
指定托底方法
@FeignClient(value = "PRODUCT-SERVICE", fallbackFactory = ProductClientFallbackFactory.class)
为外部访问提供统一的入口,并且我们可以通过过滤完成过度,并且封装负载均衡ribbon,封装了熔断hystrix
1)基本配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency>
yml配置
server:
port: 4399
spring:
application:
name: ZUUL-GATEWAY
eureka:
client:
service-url:
defaultZone: http://eureka-7001.com:7001/eureka, http://eureka-7002.com:7002/eureka
instance:
instance-id: gateway-4399.com
prefer-ip-address: false
主类添加@EnableZuulProxy注解
@EnableZuulProxy //启用zuul代理
2)路由访问加固(不用服务名,映射路径)
zuul:
routes:
myUser.serviceId: product-service # 服务名
myUser.path: /dyier/** # 把dyier打头的所有请求都转发给product-service服务
ignored-services: "*" #所有服务都不允许以服务名来访问
prefix: "/services" #加一个统一前缀
3)拦截器实现登陆
filter代码
@Component public class LoginFilter extends ZuulFilter { /** * 过滤器类型 * - pre:请求在被路由之前执行 * - routing:在路由请求时调用 * - post:在routing和errror过滤器之后调用 * - error:处理请求时发生错误调用 * @return */ @Override public String filterType() { return "pre"; } /** * 设置优先级,值越小越优先 * @return */ @Override public int filterOrder() { return 1; } /** * 是否执行本过滤器 * @return */ @Override public boolean shouldFilter() { return true; } /** * 过滤的逻辑 * @return * @throws ZuulException */ @Override public Object run() throws ZuulException { //获取上下文 RequestContext currentContext = RequestContext.getCurrentContext(); //获取请求 HttpServletRequest request = currentContext.getRequest(); //从请求头中获取token String token = request.getHeader("token"); //判断是否登陆 if (null == token || "".equals(token)) { //校验失败 currentContext.setSendZuulResponse(false); //返回一个状态码401。也可以重定向 currentContext.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED); } // 校验通过,可以考虑把用户信息放入上下文,继续向后执行 return null; } }
4)配置超时管理
zuul:
retryable: true
ribbon:
ConnectTimeout: 250 # 连接超时时间(ms)
ReadTimeout: 2000 # 通信超时时间(ms)
OkToRetryOnAllOperations: true # 是否对所有操作重试
MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数
MaxAutoRetries: 1 # 同一实例的重试次数
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMillisecond: 3000 # 熔断超时时长:3000ms
实现配置文件统一管理(application.yml)
1)准备github配置文件
2)configserver(服务端):通过它读取配置文件
application.yml
server:
port: 1299
eureka:
client:
service-url:
defaultZone: http://eureka-7001.com:7001/eureka,http://eureka-7002.com:7002/eureka # 集群
instance:
prefer-ip-address: true
spring:
application:
name: SPRING-CLOUD-CONFIG-SERVER
cloud:
config:
server:
git:
uri: 仓库地址
username: 账号
password: 密码
3)configclient(客户端):真正读取配置文件的地方
bootstrop.yml
spring:
cloud:
config:
name: application-user #github上面名称
profile: dev #环境
label: master #分支
uri: http://127.0.0.1:1299 #配置服务器
eureka:
client:
service-url:
defaultZone: http://eureka-7001.com:7001/eureka, http://eureka-7002.com:7002/eureka # 集群
instance:
prefer-ip-address: true #显示客户端真实ip
标签:eth lse ice 提供者 代理 obj -- 用户信息 cell
原文地址:https://www.cnblogs.com/dyier/p/12297302.html