首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

spring cloud 学习(6) - zuul 微服务网关

微服务架构体系中,通常一个业务系统会有很多的微服务,比如:OrderService、ProductService、UserService...,为了让调用更简单,一般会在这些服务前端再封装一层,类似下面这样: 前面这一层俗称为“网关层”,其存在意义在于,将"1对N"问题 转换成了"1对1”问题,同时在请求到达真正的微服务之前,可以做一些预处理,比如:来源合法性检测,权限校验,反爬虫之类... 传统方式下,最土的办法,网关层可以人肉封装,类似以下示例代码: LoginResult login(...){ //TODO 预处理... return userService.login();//调用用户服务的登录方法 } Product queryProduct(...){ //TODO 预处理... return productService.queryProduct();//调用产品服务的查询方法 } Order submitOrder(...){ //TODO 预处理... return orderService.submitOrder();//调用订单服务的查询方法 } 这样做,当然能跑起来,但是维护量大,以后各个微服务增加了新方法,都需要在网关层手动增加相应的方法封装,而spring cloud 中的zuul很好的解决了这一问题,示意图如下: Zuul做为网关层,自身也是一个微服务,跟其它服务Service-1,Service-2, ... Service-N一样,都注册在eureka server上,可以相互发现,zuul能感知到哪些服务在线,同时通过配置路由规则(后面会给出示例),可以将请求自动转发到指定的后端微服务上,对于一些公用的预处理(比如:权限认证,token合法性校验,灰度验证时部分流量引导之类),可以放在所谓的过滤器(ZuulFilter)里处理,这样后端服务以后新增了服务,zuul层几乎不用修改。 使用步骤: 一、添加zuul依赖的jar包 compile 'org.springframework.cloud:spring-cloud-starter-zuul' 二、application.yml里配置路由 zuul: routes: api-a: path: /api-user/** service-id: service-provider sensitive-headers: api-b: path: /api-order/** service-id: service-consumer 解释一下:上面这段配置表示,/api-user/开头的url请求,将转发到service-provider这个微服务上,/api-order/开头的url请求,将转发到service-consumer这个微服务上。 三、熔断处理 如果网关后面的微服务挂了,zuul还允许定义一个fallback类,用于熔断处理,参考下面的代码: package com.cnblogs.yjmyzz.spring.cloud.study.gateway; import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpResponse; import org.springframework.stereotype.Component; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; /** * Created by yangjunming on 2017/7/14. */ @Component public class ServiceConsumerFallbackProvider implements ZuulFallbackProvider { @Override public String getRoute() { return "service-consumer"; } @Override public ClientHttpResponse fallbackResponse() { return new ClientHttpResponse() { @Override public HttpStatus getStatusCode() throws IOException { return HttpStatus.OK; } @Override public int getRawStatusCode() throws IOException { return this.getStatusCode().value(); } @Override public String getStatusText() throws IOException { return this.getStatusCode().getReasonPhrase(); } @Override public void close() { } @Override public InputStream getBody() throws IOException { return new ByteArrayInputStream("Service-Consumer不可用".getBytes()); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); MediaType mt = new MediaType("application", "json", Charset.forName("UTF-8")); headers.setContentType(mt); return headers; } }; } } 开发人员只要在getRoute这个方法里指定要处理的微服务实例,然后重写fallbackResponse即可。 此时,如果观察/health端点,也可以看到hystrix处于融断开启状态 四、ZuulFilter过滤器 过滤器是一个很有用的机制,下面分几种经典场景演示下: 4.1、token校验/安全认证 网关直接暴露在公网上时,终端要调用某个服务,通常会把登录后的token传过来,网关层对token进行有效性验证,如果token无效(或没传token),提示重新登录或直接拒绝。另外,网关后面的微服务,如果设置了spring security中的basic Auth(即:不允许匿名访问,必须提供用户名、密码),也可以在Filter中处理。参考下面的代码: package com.cnblogs.yjmyzz.spring.cloud.study.gateway; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import org.apache.commons.codec.binary.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; /** * Created by yangjunming on 2017/7/13. */ @Component public class AccessFilter extends ZuulFilter { private static Logger logger = LoggerFactory.getLogger(AccessFilter.class); @Override public String filterType() { return FilterConstants.PRE_TYPE; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); Object token = request.getParameter("token"); //校验token if (token == null) { logger.info("token为空,禁止访问!"); ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(401); return null; } else { //TODO 根据token获取相应的登录信息,进行校验(略) } //添加Basic Auth认证信息 ctx.addZuulRequestHeader("Authorization", "Basic " + getBase64Credentials("app01", "*****")); return null; } private String getBase64Credentials(String username, String password) { String plainCreds = username + ":" + password; byte[] plainCredsBytes = plainCreds.getBytes(); byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes); return new String(base64CredsBytes); } } Filter一共有4种类型,其常量值在org.springframework.cloud.netflix.zuul.filters.support.FilterConstants 中定义 // Zuul Filter TYPE constants ----------------------------------- /** * {@link ZuulFilter#filterType()} error type. */ String ERROR_TYPE = "error"; /** * {@link ZuulFilter#filterType()} post type. */ String POST_TYPE = "post"; /** * {@link ZuulFilter#filterType()} pre type. */ String PRE_TYPE = "pre"; /** * {@link ZuulFilter#filterType()} route type. */ String ROUTE_TYPE = "route"; 安全校验,一般放在请求真正处理之前,所以上面的示例filterType指定为pre,剩下的只要在shouldFilter()、run()方法中重写自己的逻辑即可。 4.2 动态修改请求参数 zuulFilter可以拦截所有请求参数,并对其进行修改,比如:终端发过来的数据,出于安全要求,可能是经过加密处理的,需要在网关层进行参数解密,再传递到后面的服务;再比如:用户传过来的token值,需要转换成userId/userName这些信息,再传递到背后的微服务。参考下面的run方法: public Object run() { try { RequestContext context = getCurrentContext(); InputStream in = (InputStream) context.get("requestEntity"); if (in == null) { in = context.getRequest().getInputStream(); } String body = StreamUtils.copyToString(in, Charset.forName("UTF-8")); body = "动态增加一段内容到body中: " + body; byte[] bytes = body.getBytes("UTF-8"); context.setRequest(new HttpServletRequestWrapper(getCurrentContext().getRequest()) { @Override public ServletInputStream getInputStream() throws IOException { return new ServletInputStreamWrapper(bytes); } @Override public int getContentLength() { return bytes.length; } @Override public long getContentLengthLong() { return bytes.length; } }); } catch (IOException e) { rethrowRuntimeException(e); } return null; } 更多filter的示例,可以参考官网:https://github.com/spring-cloud-samples/sample-zuul-filters 4.3 灰度发布(Gated Launch/Gray Release) 大型分布式系统中,灰度发布是保证线上系统安全生产的重要手段,一般的做法为:从集群中指定一台(或某几台)机器,每次做新版本发布前,先只发布这些机器上,先观察一下是否正常,如果稳定运行后,再发布到其它机器。这种策略(相当于按部分节点来灰度),大多数情况下可以满足要求,但是有一些特定场景,可能不太适用。 比如:笔者所在的“美味不用等”公司,主要B端用户为各餐饮品牌的商家,多数情况下,如果新上了一个功能,希望找一些规模较小的餐厅做试点,先看看上线后的运行情况,如果运行良好,再推广到其它商家。 再比如:后端服务有N多个版本在同时运行,比如V1、V2,现在新加了一个V3版本(这在手机app应用中很常见),希望只有部分升级了app的用户访问最新的V3版本服务,其它用户仍然访问旧版本,待系统稳定后,再大规模提示用户升级。 对于这些看上去需求各异的灰度需求,

优秀的个人博客,低调大师

自然语言理解-从规则到深度学习

1. 引言 自然语言理解是人工智能的核心难题之一,也是目前智能语音交互和人机对话的核心难题。维基百科有如下描述[1]: Natural language understanding (NLU) is a subtopic of natural language processing in artificial intelligence that deals with machine reading comprehension. NLU is considered an AI-hard problem. 对于AI-hard的解释如下: In the field of artificial intelligence, the most difficult problems are informally known as AI-complete

优秀的个人博客,低调大师

《Scala机器学习》一一3.2 理解Spark的架构

3.2 理解Spark的架构并行化是将工作负载划分为在不同线程或不同节点上执行的子任务。下面介绍Spark实现并行化的原理,以及它如何管理子任务的执行和子任务之间的通信。3.2.1 任务调度Spark工作负载的划分由弹性分布式数据集(Resilient Distributed Dataset,RDD)的分区数决定,这是Spark的基本抽象和管道结构。RDD是一种可并行操作的、不可变元素的分区集合。具体细节可能取决于Spark的运行模式,图3-2为Spark任务/资源调度的示意图。 图3-2 通用的Spark任务调度示意图。尽管在图中没有明确标识,Spark Context通常会在端口4040上打开一个HTTP UI(并发情形将打开4041、4042等),在任务执行期间会一直这样。Spark Master UI的端口通常是8080(虽

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册