存档2019年12月5日

Zuul 服务网关

常用网关方案

Nginx+Lua
Kong(商业)
Tyk(go开发)
Spring Cloud Zuul

Zuul 4种过滤器

前置Pre 限流(google的令牌桶,spring-cloud-zuul-ratelimit),鉴权,参数校验
路由 Route
后置Post 统计,日志
错误Error

将多个Zuul节点注册到Eureka Server实现高可用

Nginx和Zuul混搭

配制

#自定义路由
#自定义路由
zuul:
  routes:
    myProduct:
#      路由到 /myProduct/** ->> /product
      path: /myProduct/**
      serviceId: product
#      敏感头过滤,设置传递参数带cookie
      sensitiveHeaders:
#      简单写法
#  product: /myProduct/**
  #  禁止路由外部访问
  ignored-patterns:
    - /product/product/listForOrder
    - /myProduct/product/listForOrder
#    - /**/product/listForOrder

#所有路由规则地址
management:
  #打开/actuator监控端口 /actuator/routes路由列表 /actuator/routes/details路由详情
  endpoints:
    web:
      exposure:
        include: '*'
  #打开health
  endpoint:
    health:
      show-details: ALWAYS
  #关闭权限认证 默认访问需权限
  security:
    enabled: false

跨域解决
1. 在Nginx中解决
1. 在被调用的类或方法上增加注解@CrossOrigin
1. 在ZULL中使用CorsConfig配制文件增加CorsFilter过滤器

@Configuration
public class CorsConfig {

    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration config = new CorsConfiguration();
        //是否支持Cookie跨域
        config.setAllowCredentials(true);
        //允许的原始域,你自己的域名 http:www.a.com
        config.setAllowedOrigins(Arrays.asList("*"));
        //允许的头
        config.setAllowedHeaders(Arrays.asList("*"));
        //允许的方法GET POST ....
        config.setAllowedMethods(Arrays.asList("*"));
        //缓存时间,在这时间内的同一请求不再进行跨域检查
        config.setMaxAge(300L);
        //将配制文件注册
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

ERROR:com.netflix.zuul.exception.ZuulException: Hystrix Readed time out

这个错误是应为zuul的默认超时时间比较小,我们配置下zuul的超时时间,因zuul启用了ribbon的负载均衡,还需要设置ribbon的超时时间,注意ribbon的超时时间要小于zuul超时时间 。

zuul:
  host:
    connect-timeout-millis: 15000 #HTTP连接超时要比Hystrix的大
    socket-timeout-millis: 60000   #socket超时

Redis

https://redis.io/

hub.docker.com

https://hub.docker.com/_/redis/

docker run -itd --name redis -p 6379:6379 -v /home/redis/data:/data --restart always redis:5.0.7
<dependency>
            <groupId> org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

spring:
 redis:
  host: localhost
  port: 6379

类型 简介 特性 场景
String(字符串) 二进制安全 可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M
Hash(字典) 键值对集合,即编程语言中的Map类型 适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去) 存储、读取、修改用户属性
List(列表) 链表(双向链表) 增删快,提供了操作某一段元素的API 1,最新消息排行等功能(比如朋友圈的时间线) 2,消息队列
Set(集合) 哈希表实现,元素不重复 1、添加、删除,查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作 1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐
Sorted Set(有序集合) 将Set中的元素增加一个权重参数score,元素按score有序排列 数据插入集合时,已经进行天然排序 1、排行榜 2、带权重的消息队列

Spring Cloud Stream

支持RabbitMQ,Kaflka,简化消息中间件的使用

添加依赖

支持RabbitMQ
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
支持Kaflka
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-kaflka</artifactId>
</dependency>

定义接口

/**
 * 功能描述: 定义Spring Cloud Stream接口
 */
public interface StreamClient {

    String INPUT = "myMessage";

    String INPUT2 = "myMessage2";

    @Input(StreamClient.INPUT)
    SubscribableChannel input();

    @Output(StreamClient.INPUT)
    MessageChannel output();

    @Input(StreamClient.INPUT2)
    SubscribableChannel input2();

    @Output(StreamClient.INPUT2)
    MessageChannel output2();
}

发送stream消息

@Api(tags = "发送Spring Cloud Stream信息到MQ")
@RestController
public class SendMessageController {

    @Autowired
    private StreamClient streamClient;

//    @GetMapping("/sendMessage")
//    public void process() {
//        String message = "now " + new Date();
//        streamClient.output().send(MessageBuilder.withPayload(message).build());
//    }

    /**
     * 发送 orderDTO对象
     */
    @ApiOperation("发送 orderDTO对象")
    @GetMapping("/sendMessage")
    public void process() {
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setOrderId("123456");
        streamClient.output().send(MessageBuilder.withPayload(orderDTO).build());
    }
}

接收stream消息

 * 功能描述:接收Spring Cloud Stream消息
 */
@Component
@EnableBinding(StreamClient.class)
@Slf4j
public class StreamReceiver {

//    @StreamListener(value = StreamClient.INPUT)
//    public void process(Object message) {
//        log.info("StreamReceiver: {}", message);
//    }

    /**
     * myMessage 接收orderDTO对象 消息,myMessage2发送一条返回消息
     * @param message
     */
    @StreamListener(value = StreamClient.INPUT)
    @SendTo(StreamClient.INPUT2)
    public String process(OrderDTO message) {
        log.info("StreamReceiver: {}", message);
        return "received.";
    }

    /**
     * myMessage2接收返回消息
     * @param message
     */
    @StreamListener(value = StreamClient.INPUT2)
    public void process2(String message) {
        log.info("StreamReceiver2: {}", message);
    }
}