当前位置: 首页 > news >正文

SpringBoot项目架构实战之“网关zuul搭建“

第三章 网关zuul搭建


前言:

1、主要功能

        zuul主要提供动态路由(内置ribbon实现)和过滤(可以做统一鉴权过滤器、灰度发布过滤器、黑白名单IP过滤器、服务限流过滤器(可以配合Sentinel实现))功能;

2、和Spring Cloud GateWay的区别

        属于两个不同开源组织提供的网关解决方案。spring cloud GateWay使用非阻塞API,内置限流过滤器,支持长连接(比如 websockets),在高并发和后端服务响应慢的场景下比Zuul1的表现要好;zuul无内置限流过滤器,但是可以与Sentinel(是阿里开源的一款高性能的限流框架)集成使用。


一、创建zuul服务module

参考第二章eureka的创建

二、配置文件

1、pom文件配置

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hq</groupId><artifactId>taxi-online</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>taxi-online-zuul</artifactId><name>taxi-online-zuul</name><description>personal test for zuul</description><url>org.apache</url><packaging>jar</packaging><dependencies><!-- zuul --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-zuul</artifactId></dependency><!-- eureka-client --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency></dependencies>
</project>

2、application.yml文件配置

#服务端口
server:port: 9100
#服务名  
spring:application:name: taxi-online-zuul
#服务注册    
eureka:client:service-url:defaultZone: http://localhost:9001/eureka/,http://localhost:9002/eureka/enabled: true # 是否启用Eureka clientinstance:hostname: localhostinstance-id: taxi-online-zuul # 实例id

3、启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
public class StartSpringCloudZuul {public static void main(String[] args) {SpringApplication.run(StartSpringCloudZuul.class,args);}
}

三、zuul功能

1、动态路由

2、统一鉴权

3、过滤器

4、灰度发布

5、限流

四、底层源码

1、启动原理

类似注册中心:

1)boot启动类

boot启动类上添加@EnableZuulProxy注解;

2)EnableZuulProxy注解

EnableZuulProxy注解中导入ZuulProxyMarkerConfiguration配置类

@EnableCircuitBreaker
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {}
3)ZuulProxyMarkerConfiguration配置类

ZuulProxyMarkerConfiguration配置类往容器添加了一个空的Marker对象,这个对象是作为容器是否添加ZuulProxyAutoConfiguration类的条件,因为ZuulProxyAutoConfiguration类上面加了@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)的注解

@Configuration(proxyBeanMethods = false)
public class ZuulProxyMarkerConfiguration {@Beanpublic Marker zuulProxyMarkerBean() {return new Marker();}class Marker {}}
4)spring.factories文件

zuul包下面的spring.factories文件指定了两个引入类,只要导包就会被引进去(由SpringFactoriesLoader 进行读取)--见下方截图。如果没有这个文件,boot的自动扫描不会扫描这些外部包的类。这两个引入类被注入容器的条件分别是:

@ConditionalOnBean(ZuulServerMarkerConfiguration.Marker.class)

@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)

,分别可以通过在启动类上添加下面注解来引入相应的Marker类:

@EnableZuulProxy

@EnableZuulServer。


@EnableZuulServer、@EnableZuulProxy两个注解的区别:
@EnableZuulServer - 普通Zuul Server,只支持基本的route与filter功能.
@EnableZuulProxy - 普通Zuul Server+服务发现与熔断等功能的增强版,具有反向代理功能。
@EnableZuulProxy简单理解为@EnableZuulServer的增强版,当Zuul与Eureka、Ribbon等组件配合使用时,我们使用@EnableZuulProxy。所以我们做SpringCloud微服务系统一般都是使用@EnableZuulProxy。

5)ZuulServerAutoConfiguration配置类

ZuulServerAutoConfiguration配置类(源码见下方)主要做的事情有:

1、往容器注入了ZuulServlet,该类是zuul的核心类。

2、往容器注入了 一些前置过滤器和后置过滤器。

3、注入ZuulFilterInitializer类并初始化,初始化逻辑中将所有过滤器交给FilterRegistry类进行管理。FilterRegistry类源码如下:

/*** @author mhawthorne*/
public class FilterRegistry {private static final FilterRegistry INSTANCE = new FilterRegistry();public static final FilterRegistry instance() {return INSTANCE;}private final ConcurrentHashMap<String, ZuulFilter> filters = new ConcurrentHashMap<String, ZuulFilter>();private FilterRegistry() {}public ZuulFilter remove(String key) {return this.filters.remove(key);}public ZuulFilter get(String key) {return this.filters.get(key);}public void put(String key, ZuulFilter filter) {this.filters.putIfAbsent(key, filter);}public int size() {return this.filters.size();}public Collection<ZuulFilter> getAllFilters() {return this.filters.values();}}

ZuulServerAutoConfiguration源码如下(有删减):

/*** @author Spencer Gibb* @author Dave Syer* @author Biju Kunjummen*/
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties({ ZuulProperties.class })
@ConditionalOnClass({ ZuulServlet.class, ZuulServletFilter.class })
@ConditionalOnBean(ZuulServerMarkerConfiguration.Marker.class)
// Make sure to get the ServerProperties from the same place as a normal web app would
// FIXME @Import(ServerPropertiesAutoConfiguration.class)
public class ZuulServerAutoConfiguration {@Bean@ConditionalOnMissingBean(name = "zuulServlet")@ConditionalOnProperty(name = "zuul.use-filter", havingValue = "false",matchIfMissing = true)public ServletRegistrationBean zuulServlet() {ServletRegistrationBean<ZuulServlet> servlet = new ServletRegistrationBean<>(new ZuulServlet(), this.zuulProperties.getServletPattern());// The whole point of exposing this servlet is to provide a route that doesn't// buffer requests.servlet.addInitParameter("buffer-requests", "false");return servlet;}// pre filters@Beanpublic ServletDetectionFilter servletDetectionFilter() {return new ServletDetectionFilter();}@Bean@ConditionalOnMissingBeanpublic FormBodyWrapperFilter formBodyWrapperFilter() {return new FormBodyWrapperFilter();}@Bean@ConditionalOnMissingBeanpublic DebugFilter debugFilter() {return new DebugFilter();}@Bean@ConditionalOnMissingBeanpublic Servlet30WrapperFilter servlet30WrapperFilter() {return new Servlet30WrapperFilter();}// post filters@Beanpublic SendResponseFilter sendResponseFilter(ZuulProperties properties) {return new SendResponseFilter(zuulProperties);}@Beanpublic SendErrorFilter sendErrorFilter() {return new SendErrorFilter();}@Beanpublic SendForwardFilter sendForwardFilter() {return new SendForwardFilter();}//@Configuration(proxyBeanMethods = false)protected static class ZuulFilterConfiguration {@Autowiredprivate Map<String, ZuulFilter> filters;@Beanpublic ZuulFilterInitializer zuulFilterInitializer(CounterFactory counterFactory,TracerFactory tracerFactory) {FilterLoader filterLoader = FilterLoader.getInstance();FilterRegistry filterRegistry = FilterRegistry.instance();return new ZuulFilterInitializer(this.filters, counterFactory, tracerFactory,filterLoader, filterRegistry);}}
}
6)ZuulProxyAutoConfiguration配置类

继承了ZuulServerAutoConfiguration类,是ZuulServerAutoConfiguration的增强版,在ZuulServerAutoConfiguration的基础上增加eureka、ribbon、hystrix等功能。源码如下:

/*** @author Spencer Gibb* @author Dave Syer* @author Biju Kunjummen*/
@Configuration(proxyBeanMethods = false)
@Import({ RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration.class,RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration.class,RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class,HttpClientConfiguration.class })
@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)
public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration {// pre filters@Bean@ConditionalOnMissingBean(PreDecorationFilter.class)public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator,ProxyRequestHelper proxyRequestHelper) {return new PreDecorationFilter(routeLocator,this.server.getServlet().getContextPath(), this.zuulProperties,proxyRequestHelper);}// route filters@Bean@ConditionalOnMissingBean(RibbonRoutingFilter.class)public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper,RibbonCommandFactory<?> ribbonCommandFactory) {RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, ribbonCommandFactory,this.requestCustomizers);return filter;}@Bean@ConditionalOnMissingBean({ SimpleHostRoutingFilter.class,CloseableHttpClient.class })public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper,ZuulProperties zuulProperties,ApacheHttpClientConnectionManagerFactory connectionManagerFactory,ApacheHttpClientFactory httpClientFactory) {return new SimpleHostRoutingFilter(helper, zuulProperties,connectionManagerFactory, httpClientFactory);}@Bean@ConditionalOnMissingBean({ SimpleHostRoutingFilter.class })public SimpleHostRoutingFilter simpleHostRoutingFilter2(ProxyRequestHelper helper,ZuulProperties zuulProperties, CloseableHttpClient httpClient) {return new SimpleHostRoutingFilter(helper, zuulProperties, httpClient);}@Bean@ConditionalOnMissingBean(ServiceRouteMapper.class)public ServiceRouteMapper serviceRouteMapper() {return new SimpleServiceRouteMapper();}@Configuration(proxyBeanMethods = false)@ConditionalOnMissingClass("org.springframework.boot.actuate.health.Health")protected static class NoActuatorConfiguration {@Beanpublic ProxyRequestHelper proxyRequestHelper(ZuulProperties zuulProperties) {ProxyRequestHelper helper = new ProxyRequestHelper(zuulProperties);return helper;}}@Configuration(proxyBeanMethods = false)@ConditionalOnClass(Health.class)protected static class EndpointConfiguration {@Autowired(required = false)private HttpTraceRepository traces;@Bean@ConditionalOnAvailableEndpointpublic RoutesEndpoint routesEndpoint(RouteLocator routeLocator) {return new RoutesEndpoint(routeLocator);}@ConditionalOnAvailableEndpoint@Beanpublic FiltersEndpoint filtersEndpoint() {FilterRegistry filterRegistry = FilterRegistry.instance();return new FiltersEndpoint(filterRegistry);}@Beanpublic ProxyRequestHelper proxyRequestHelper(ZuulProperties zuulProperties) {TraceProxyRequestHelper helper = new TraceProxyRequestHelper(zuulProperties);if (this.traces != null) {helper.setTraces(this.traces);}return helper;}}}

2、核心类ZuulServlet

1)作用

调度不同阶段的filters,处理异常。所有的Request都要经过ZuulServlet的处理。三个核心的方法preRoute(),route(), postRoute(),zuul对request处理逻辑都在这三个方法里。源码如下:

public class ZuulServlet extends HttpServlet {private static final long serialVersionUID = -3374242278843351500L;private ZuulRunner zuulRunner;@Overridepublic void init(ServletConfig config) throws ServletException {super.init(config);String bufferReqsStr = config.getInitParameter("buffer-requests");boolean bufferReqs = bufferReqsStr != null && bufferReqsStr.equals("true") ? true : false;zuulRunner = new ZuulRunner(bufferReqs);}@Overridepublic void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {try {init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);// Marks this request as having passed through the "Zuul engine", as opposed to servlets// explicitly bound in web.xml, for which requests will not have the same data attachedRequestContext context = RequestContext.getCurrentContext();context.setZuulEngineRan();try {preRoute();} catch (ZuulException e) {error(e);postRoute();return;}try {route();} catch (ZuulException e) {error(e);postRoute();return;}try {postRoute();} catch (ZuulException e) {error(e);return;}} catch (Throwable e) {error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));} finally {RequestContext.getCurrentContext().unset();}}/*** executes "post" ZuulFilters** @throws ZuulException*/void postRoute() throws ZuulException {zuulRunner.postRoute();}/*** executes "route" filters** @throws ZuulException*/void route() throws ZuulException {zuulRunner.route();}/*** executes "pre" filters** @throws ZuulException*/void preRoute() throws ZuulException {zuulRunner.preRoute();}/*** initializes request** @param servletRequest* @param servletResponse*/void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {zuulRunner.init(servletRequest, servletResponse);}/*** sets error context info and executes "error" filters** @param e*/void error(ZuulException e) {RequestContext.getCurrentContext().setThrowable(e);zuulRunner.error();}
}
2)调用链路:

以preRoute()为例:

1、ZuulServlet——》ZuulRunner,源码见四-2-1);

2、ZuulRunner——》FilterProcessor,源码如下:

public void preRoute() throws ZuulException {FilterProcessor.getInstance().preRoute();}

3、FilterProcessor调自己的runFilters方法,涉及调用其他类:

FilterProcessor——》FilterLoader,源码见下方4

实际执行过滤器逻辑是在调用自己processZuulFilter方法中的下方的代码逻辑。

ZuulFilterResult result = filter.runFilter();(runFilter里面调用了子类的run方法)

public void preRoute() throws ZuulException {try {runFilters("pre");} catch (ZuulException e) {throw e;} catch (Throwable e) {throw new ZuulException(e, 500, "UNCAUGHT_EXCEPTION_IN_PRE_FILTER_" + e.getClass().getName());}}/*** runs all filters of the filterType sType/ Use this method within filters to run custom filters by type** @param sType the filterType.* @return* @throws Throwable throws up an arbitrary exception*/public Object runFilters(String sType) throws Throwable {if (RequestContext.getCurrentContext().debugRouting()) {Debug.addRoutingDebug("Invoking {" + sType + "} type filters");}boolean bResult = false;List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType);if (list != null) {for (int i = 0; i < list.size(); i++) {ZuulFilter zuulFilter = list.get(i);Object result = processZuulFilter(zuulFilter);if (result != null && result instanceof Boolean) {bResult |= ((Boolean) result);}}}return bResult;}public Object processZuulFilter(ZuulFilter filter) throws ZuulException {RequestContext ctx = RequestContext.getCurrentContext();boolean bDebug = ctx.debugRouting();final String metricPrefix = "zuul.filter-";long execTime = 0;String filterName = "";try {long ltime = System.currentTimeMillis();filterName = filter.getClass().getSimpleName();RequestContext copy = null;Object o = null;Throwable t = null;if (bDebug) {Debug.addRoutingDebug("Filter " + filter.filterType() + " " + filter.filterOrder() + " " + filterName);copy = ctx.copy();}ZuulFilterResult result = filter.runFilter();ExecutionStatus s = result.getStatus();execTime = System.currentTimeMillis() - ltime;switch (s) {case FAILED:t = result.getException();ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);break;case SUCCESS:o = result.getResult();ctx.addFilterExecutionSummary(filterName, ExecutionStatus.SUCCESS.name(), execTime);if (bDebug) {Debug.addRoutingDebug("Filter {" + filterName + " TYPE:" + filter.filterType() + " ORDER:" + filter.filterOrder() + "} Execution time = " + execTime + "ms");Debug.compareContextState(filterName, copy);}break;default:break;}if (t != null) throw t;usageNotifier.notify(filter, s);return o;} catch (Throwable e) {if (bDebug) {Debug.addRoutingDebug("Running Filter failed " + filterName + " type:" + filter.filterType() + " order:" + filter.filterOrder() + " " + e.getMessage());}usageNotifier.notify(filter, ExecutionStatus.FAILED);if (e instanceof ZuulException) {throw (ZuulException) e;} else {ZuulException ex = new ZuulException(e, "Filter threw Exception", 500, filter.filterType() + ":" + filterName);ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);throw ex;}}}

4、FilterLoader——》filterRegistry,通过filterRegistry拿到所有的过滤器并筛选返回符合要求类型的集合并按优先级排序,放入缓存。

 /*** Returns a list of filters by the filterType specified** @param filterType* @return a List<ZuulFilter>*/public List<ZuulFilter> getFiltersByType(String filterType) {List<ZuulFilter> list = hashFiltersByType.get(filterType);if (list != null) return list;list = new ArrayList<ZuulFilter>();Collection<ZuulFilter> filters = filterRegistry.getAllFilters();for (Iterator<ZuulFilter> iterator = filters.iterator(); iterator.hasNext(); ) {ZuulFilter filter = iterator.next();if (filter.filterType().equals(filterType)) {list.add(filter);}}Collections.sort(list); // sort by priorityhashFiltersByType.putIfAbsent(filterType, list);return list;}

5、FilterRegistry调用自己的getAllFilters方法返回所有的过滤器

private final ConcurrentHashMap<String, ZuulFilter> filters = new ConcurrentHashMap<String, ZuulFilter>();
public Collection<ZuulFilter> getAllFilters() {return this.filters.values();}

3、顶级抽象父类ZuulFilter

所有的过滤器都应继承该抽象类,重写shouldFilter、filterType、filterOrder、run方法。

shouldFilter:该过滤器是否生效  返回true:有效;false:无效

filterType:指定过滤器类型,FilterConstants包含下面图中几种类型:filterOrder:在过滤器链中的顺序,返回值越小越靠前;

run:过滤器的逻辑。

public abstract class ZuulFilter implements IZuulFilter, Comparable<ZuulFilter> {abstract boolean shouldFilter();abstract Object run() throws ZuulException;abstract public String filterType();/*** filterOrder() must also be defined for a filter. Filters may have the same  filterOrder if precedence is not* important for a filter. filterOrders do not need to be sequential.** @return the int order of a filter*/abstract public int filterOrder();public int compareTo(ZuulFilter filter) {return Integer.compare(this.filterOrder(), filter.filterOrder());}
}

4、过滤器热加载

参考下方博客:

zuul 1.x 源码解析 (结合本人过去2年工作经历整理,超详细)_zuulproxyautoconfiguration.predecorationfilter-CSDN博客文章浏览阅读428次,点赞6次,收藏4次。zuul 1.x 源码解析,全程断点调试,超详细(结合本人过去2年工作经历,花了1周时间整理并记录)_zuulproxyautoconfiguration.predecorationfilterhttps://blog.csdn.net/qq_22270363/article/details/132052278

相关文章:

SpringBoot项目架构实战之“网关zuul搭建“

第三章 网关zuul搭建 前言&#xff1a; 1、主要功能 zuul主要提供动态路由&#xff08;内置ribbon实现&#xff09;和过滤&#xff08;可以做统一鉴权过滤器、灰度发布过滤器、黑白名单IP过滤器、服务限流过滤器&#xff08;可以配合Sentinel实现&#xff09;&#xff09;功能…...

发挥储能系统领域优势,海博思创坚定不移推动能源消费革命

随着新发展理念的深入贯彻&#xff0c;我国正全面落实“双碳”目标任务&#xff0c;通过积极转变能源消费方式&#xff0c;大幅提升能源利用效率&#xff0c;实现了以年均约3.3%的能源消费增长支撑了年均超过6%的国民经济增长。这一成就的背后&#xff0c;是我国能源结构的持续…...

matlab R2016b安装cplex12.6,测试时cplex出现出现内部错误的解决方法

问题场景 网上搜索matlabyalmipcplex的安装教程&#xff0c;跟着步骤操作即可&#xff0c;假如都安装好了&#xff0c;在matlab中测试安装是否成功&#xff0c;出现以下问题&#xff1a; 1、matlab中设置路径中添加了yalmip和cplex路径&#xff0c;在命令窗口中输入yalmiptest…...

C#中的Dictionary

Dictionary<TKey, TValue> 是一个泛型集合&#xff0c;它存储键值对&#xff08;key-value pairs&#xff09;&#xff0c;其中每个键&#xff08;key&#xff09;都是唯一的。这个集合类提供了快速的数据插入和检索功能&#xff0c;因为它是基于哈希表实现的。 注意 ke…...

VSCode中多行文本的快速前后缩进

快捷键 VSCode提供了一组快捷键&#xff0c;用于快速调整选中文本行的缩进。 增加缩进&#xff08;向前缩进&#xff09;&#xff1a;在Windows和Linux上按 Tab 键&#xff0c;在Mac上按 ⇧⇥&#xff08;Shift Tab&#xff09;。减少缩进&#xff08;向后缩进&#xff09;&…...

C# 8.0 新语法的学习和使用

C# 8.0 是微软在 2019 年 9 月 23 日随 .NET Core 3.0 一同发布的一个重要版本更新&#xff0c;带来了许多新的语言特性和改进。本文将详细介绍 C# 8.0 的新语法&#xff0c;并通过实际应用案例展示这些新特性的使用方法。 目录 1. 可空引用类型 2. 异步流 3. 默认接口方…...

数据结构——约瑟夫环C语言链表实现

约瑟夫环问题由古罗马史学家约瑟夫&#xff08;Josephus&#xff09;提出&#xff0c;他参加并记录了公元66—70年犹太人反抗罗马的起义。在城市沦陷之后&#xff0c;他和40名死硬的将士在附近的一个洞穴中避难。起义者表示“宁为玉碎不为瓦全”&#xff0c;约瑟夫则想“留得青…...

【MyBatis】——入门基础知识必会内容

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大二学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…...

react父调用子的方法,子调用父的方法

父调用子的方法 // 子组件 import React, { useRef, useEffect } from react;const ChildComponent ({ childMethodRef }) > {const childMethod useRef(null);useEffect(() > {childMethodRef.current childMethod;}, []);const someMethod () > {console.log(子…...

C#知识|账号管理系统:UI层-添加账号窗体设计思路及流程。

哈喽,你好啊,我是雷工! 前边练习过详情页窗体的设计思路及流程: 《C#知识|上位机UI设计-详情窗体设计思路及流程(实例)》 本节练习添加账号窗体的UI设计,以下为学习笔记。 01 效果展示 02 添加窗体 在UI层添加Windows窗体,设置名称为:FrmAddAcount.cs 设置窗体属…...

【机器学习】初学者经典案例(随记)

&#x1f388;边走、边悟&#x1f388;迟早会好 一、概念 机器学习是一种利用数据来改进模型性能的计算方法&#xff0c;属于人工智能的一个分支。它旨在让计算机系统通过经验自动改进&#xff0c;而不需要明确编程。 类型 监督学习&#xff1a;使用带标签的数据进行训练&…...

进阶版智能家居系统Demo[C#]:整合AI和自动化

引言 在基础智能家居系统的基础上&#xff0c;我们将引入更多高级功能&#xff0c;包括AI驱动的自动化控制、数据分析和预测。这些进阶功能将使智能家居系统更加智能和高效。 目录 高级智能家居功能概述使用C#和AI实现智能家居自动化实现智能照明系统的高级功能 自动调节亮度…...

IC后端设计中的shrink系数设置方法

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 在一些成熟的工艺节点通过shrink的方式(光照过程中缩小特征尺寸比例)得到了半节点,比如40nm从45nm shrink得到,28nm从32nm shrink得到,由于半节点的性能更优异,成本又低,漏电等不利因素也可以…...

在NVIDIA Jetson平台离线部署大模型

在NVIDIA Jetson平台离线部署大模型&#xff0c;开启离线具身智能新纪元。 本项目提供一种将LMDeploy移植到NVIDIA Jetson系列边缘计算卡的方法&#xff0c;并在Jetson计算卡上运行InternLM系列大模型&#xff0c;为离线具身智能提供可能。 最新新闻&#x1f389; [2024/3/1…...

51单片机嵌入式开发:8、 STC89C52RC 操作LCD1602原理

STC89C52RC 操作LCD1602原理 1 LCD1602概述1.1 LCD1602介绍1.2 LCD1602引脚说明1.3 LCD1602指令介绍 2 LCD1602外围电路2.1 LCD1602接线方法2.2 LCD1602电路原理 3 LCD1602软件操作3.1 LCD1602显示3.2 LCD1602 protues仿真 4 总结 1 LCD1602概述 1.1 LCD1602介绍 LCD1602是一种…...

数字化时代的供应链管理综合解决方案

目录 引言背景与意义供应链管理综合解决方案的目标 &#x1f4c4;供应链管理系统主要功能系统优势 &#x1f4c4;物流管理系统主要功能系统优势 &#x1f4c4;订单管理系统主要功能应用场景 &#x1f4c4;仓储管理系统系统亮点主要功能系统优势 &#x1f4c4;商城管理系统主要功…...

CentOS 安装 annie/lux,以及 annie/lux 的使用

annie 介绍 如果第一次听到 annie 想必都会觉得陌生&#xff0c;annie 被大家称为视频下载神器&#xff0c;annie 作者介绍说可以下载抖音、哔哩哔哩、优酷、爱奇艺、芒果TV、YouTube、Tumblr、Vimeo 等平台的视频。 githup&#xff1a;https://github.com/pingf/annie 支持…...

拥抱UniHttp,规范Http接口对接之旅

前言 如果你项目里还在用传统的编程式Http客户端比如HttpClient、Okhttp去直接对接第三方Http接口&#xff0c; 那么你项目一定充斥着大量的对接逻辑和代码&#xff0c; 并且针对不同的对接渠道方需要每次封装一次调用的简化&#xff0c; 一旦封装不好系统将会变得难以维护&am…...

Python 给存入 Redis 的键值对设置过期时间

Redis 是一种内存中的数据存储系统&#xff0c;与许多传统数据库相比&#xff0c;它具有一些优势&#xff0c;其中之一就是可以设置数据的过期时间。通过 Redis 的过期时间设置&#xff0c;可以为存储在 Redis 中的数据设置一个特定的生存时间。一旦数据到达过期时间&#xff0…...

在linux中安装docker

文章目录 1、安装依赖2、安装docker的下载源3、安装docker4、设置Docker服务开机自启 1、安装依赖 sudo yum install -y yum-utils2、安装docker的下载源 sudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repohttps://download.do…...

【JVM-04】线上CPU100%

【JVM-04】线上CPU100% 1. 如何排查2. 再举一个例子 1. 如何排查 ⼀般CPU100%疯狂GC&#xff0c;都是死循环的锅&#xff0c;那怎么排查呢&#xff1f;先进服务器&#xff0c;⽤top -c 命令找出当前进程的运⾏列表按⼀下 P 可以按照CPU使⽤率进⾏排序显示Java进程 PID 为 2609…...

try catch 解决大问题

项目开发中遇到一个棘手的bug&#xff0c;react前端项目独自运行时一切正常&#xff0c;但是把项目集成到使用wujie的大平台微前端项目中之后&#xff0c;突然有个地方无故报错&#xff0c;导致程序运行停止&#xff0c;后续的方法不再执行。报错如下&#xff1a; DOMExceptio…...

手动解析Collection

即将被解析的json {"collection": {"templates": [{"data": [{"name": "plantCode","value": "MSHG_KFXHS02"}, {"name": "details","value": [{"plantMedicament…...

list模拟实现【C++】

文章目录 全部的实现代码放在了文章末尾准备工作包含头文件定义命名空间类的成员变量为什么节点类是用struct而不是class呢&#xff1f;为什么要写get_head_node? 迭代器迭代器在list类里的实例化和重命名普通迭代器operator->()的作用是什么&#xff1f; const迭代器反向迭…...

nginx正向代理、反向代理、负载均衡

nginx.conf nginx首要处理静态页面 反向代理 动态请求 全局模块 work processes 1; 设置成服务器内核数的两倍&#xff08;一般不不超过8个超过8个反而会降低性能一般4个 1-2个也可以&#xff09; netstat -antp | grep 80 查端口号 *1、events块&#xff1a;* 配置影响ngi…...

matlab 有倾斜的椭圆函数图像绘制

matlab 有倾斜的椭圆函数图像绘制 有倾斜的椭圆函数图像绘制xy交叉项引入斜线负向斜线成分正向斜线成分 x^2 y^2 xy 1 &#xff08;负向&#xff09;绘制结果 x^2 y^2 - xy 1 &#xff08;正向&#xff09;绘制结果 有倾斜的椭圆函数图像绘制 为了确定椭圆的长轴和短轴的…...

PTK是如何加密WLAN单播数据帧的?

1. References WLAN 4-Way Handshake如何生成PTK&#xff1f;-CSDN博客 2. 概述 在Wi-Fi网络中&#xff0c;单播、组播和广播帧的加密算法是由AP决定的。其中单播帧的加密使用PTK密钥&#xff0c;其PTK的密钥结构如下图所示&#xff1a; PTK的组成如上图所示&#xff0c;由K…...

Django之登录权限系统

本文参考链接django之auth模块&#xff08;用户认证&#xff09; - chchcharlie、 - 博客园 (cnblogs.com) 执行完迁移命令&#xff0c;会自动生成admin表,迁移命令如下&#xff1a; python manage.py makemigrations python manage.py migrate 相关模块 from django.contrib …...

rust way step 1

install rust CARGO_HOME D:\rust\.cargo RUSTUP_HOME D:\rust\.rustup [dependencies] ferris-says "0.2" vscode 安装rust 插件 use ferris_says::say; // from the previous step use std::io::{stdout, BufWriter};fn main() {let stdout stdout();let m…...

视觉语言模型导论:这篇论文能成为你进军VLM的第一步

近些年&#xff0c;语言建模领域进展非凡。Llama 或 ChatGPT 等许多大型语言模型&#xff08;LLM&#xff09;有能力解决多种不同的任务&#xff0c;它们也正在成为越来越常用的工具。 这些模型之前基本都局限于文本输入&#xff0c;但现在也正在具备处理视觉输入的能力。如果…...

有什么做服装的网站好/长春网站快速排名提升

需求1&#xff1a;跑大sql内存不够用 虽然知道怎么改&#xff0c;但是对这几个配置一直是模糊不清晰&#xff0c;所以特意在下面写下&#xff0c;我所知道的。 需求2&#xff1a;Eclipse崩溃&#xff0c;错误提示&#xff1a; MyEclipse has detected that less than 5% of the…...

这几年做哪个网站致富/互联网平台推广是什么意思

//学习继承Descriptionauthor huoyudate 2020年2月10日下午9:34:01param args一、继承性的好处减少了代码的冗余&#xff0c;提高了代码的复用性便于功能的扩展为之后多态的使用提供了前提二、继承的格式 class A extends B{}A:子类、派生类 subclassB&#xff1a;父类、起类、…...

电商网站怎么做支付/成人电脑速成培训班

你好&#xff0c;我感觉你这写错了&#xff0c;首先第一步要对close做差分&#xff0c;然后通过这个差分与0的大小关系来进一步计算&#xff0c;我感觉你代码里没有这个判断(我是门外汉&#xff0c;我也不清楚&#xff0c;希望可以帮到你)def rsi(price,period6):import pandas…...

工业园企业建设网站公司/如何进行市场推广

前几天在弄struts和spring整合的时候&#xff0c;把action交给spring来管理。但是调试的时候出了点问题。 问题是: 我页面有一个grid和一个表单&#xff0c;点击grid的edit链接&#xff0c;会去数据库查询数据,然后放到from上来&#xff0c;同时有一个Link&#xff0c;是add功能…...

南京网站制作工具/seo主要做什么

Flowable 6.6.0 用户指南相关文档下载 BPMN用户指南 第一部分 - 中文PDF精编版BPMN用户指南 第二部分 - 中文PDF精编版BPMN用户指南 第三部分 - 中文PDF精编版应用程序指南 - 中文PDF精编版应用程序指南 - 中英对照PDF精编版应用程序指南 - Eclipse设计器中文PDF精编版表单用户…...

语文建设编辑部官方网站/无锡seo

影响ABAP程序的运行效率主要是在程序中大量数据的取得&#xff0c;如果取数不得方法&#xff0c;很影响报表的运行效率&#xff0c;所有优化ABAP程序主要是优化数据取数的方法。下面这几点可以有效的提高取数的效率&#xff0c;从而来提高程序的运行效率。①选择最有效率的表名…...