写在前面

在dubbo之服务本地暴露 文章中,我们分析了当scope="local"时使用injvm协议的本地服务注册,本文一起来看下实际业务中最常使用的方式,即远端服务暴露,相比于本地暴露,主要是多做如下的几件事:

1:启动通信服务器,绑定服务端口,准备接收服务消费者端的远程请求。
2:注册服务端口信息到注册中心,供服务消费者获取服务调用信息。

下面我们就开始吧!

在dubbo之服务本地暴露 文章基础上从doExportUrlsFor1Protocol,具体参考1.1:doExportUrlsFor1Protocol

1:远程暴漏

时序图如下:

在这里插入图片描述

1.1:doExportUrlsFor1Protocol

源码如下:

// com.alibaba.dubbo.config.ServiceConfig.doExportUrlsFor1Protocol
class FakeCls {private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {// *** 构造需要暴漏的url,如: dubbo://192.168.2.107:20826/dongshi.daddy.service.scoperemote.ScopeRemoteService?anyhost=true&application=dongshidaddy-provider&bean.name=dongshi.daddy.service.scoperemote.ScopeRemoteService&bind.ip=192.168.2.107&bind.port=20826&dubbo=2.0.2&generic=false&interface=dongshi.daddy.service.scoperemote.ScopeRemoteService&methods=sayHi&owner=dongshidaddy&pid=63200&side=provider&timestamp=1643363026148*** //String scope = url.getParameter(Constants.SCOPE_KEY);// 以下只处理非scope="none"的情况if (!Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {// scope="local",或者是没有配置scope,此时scope=null,这里会为trueif (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {// 省略本地暴漏逻辑}// scope="remote",或者是没有配置scope,此时scope=null,这里会为trueif (!Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope)) {if (logger.isInfoEnabled()) {logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);}if (registryURLs != null && !registryURLs.isEmpty()) {// 如:registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=dongshidaddy-provider&dubbo=2.0.2&owner=dongshidaddy&pid=63200&registry=zookeeper&timestamp=1643362790535// 将需要暴漏的服务的url,暴漏到所有的注册中心地址上for (URL registryURL : registryURLs) {// 不清楚做什么用的,先忽略!url = url.addParameterIfAbsent(Constants.DYNAMIC_KEY, registryURL.getParameter(Constants.DYNAMIC_KEY));// 获取监控中心url,监控中心其实也是一个服务提供者,用来统计服务调用信息,次数,耗时等URL monitorUrl = loadMonitor(registryURL);if (monitorUrl != null) {// monitor,添加monitor监控中心地址,其实也是一个服务提供者url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString());}if (logger.isInfoEnabled()) {logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);}// 服务提供者使用,用来启用使用定制的代理类生成invokerString proxy = url.getParameter(Constants.PROXY_KEY);if (StringUtils.isNotEmpty(proxy)) {registryURL = registryURL.addParameter(Constants.PROXY_KEY, proxy);}// 2022-01-31 17:39:34// 通过ProxyFactory生成Invoker// registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()):添加要暴漏的服务地址到注册中心地址// ,key:export 添加后:registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=dongshidaddy-provider&dubbo=2.0.2&export=dubbo://192.168.2.107:20826/dongshi.daddy.service.monitor.DubboMonitorService...// 返回的invoker,当调用该其invoke方法时,内部会调用对应的服务实现类,即ref的具体方法// 参数ref:具体的服务实现类,即最终被调用的类。 interfaceClass:服务接口Class。registryURL:注册中心地址Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));// 创建封装Invoker和ServiceConfig的DelegateProviderMetaDataInvoker对象DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);// 2022-01-31 15:01:03Exporter<?> exporter = protocol.export(wrapperInvoker);// private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();// 添加到exporters集合中,Exporter用于获取invoker,以及取消暴漏等exporters.add(exporter);}} else {// 注册地址是N/A的情况,此时因为没有配置注册中心地址,所以不会向注册中心注册,但是依然监听端口,暴漏服务,一般用于消费者端直连的场景// 服务消费者端想要直连的话需要设置url属性,如下可能配置:/*<dubbo:reference id="providerService"interface="dongshi.daddy.service.ProviderService"url="dubbo://192.168.10.119:20880/dongshi.daddy.service.ProviderService"/>*/// 这里和正常向注册中心注册的方式,差别在第四个参数,这里传入的是null,注册的话传入的是注册中心的url地址Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);Exporter<?> exporter = protocol.export(wrapperInvoker);exporters.add(exporter);}}}this.urls.add(url);}
}

2022-01-31 15:01:03处是完成服务的暴漏,在dubbo之服务本地暴露 一文中我们知道Protocol是使用了Wrapper 的自适应扩展类 ,因此在调用真正的Protocol实现类之前,会先调用自动生成的Adaptive类,以及所有的Wrapper类,如下debug图:

在这里插入图片描述

以上调用顺序的原因是,保证服务启动后在向注册中心注册服务启动信息,如下伪代码

class RegistryProtocol {void export() {// 使用DubboProtocol暴漏服务,即启动netty,监听服务端口new DubboProtocol().export();// 完成服务启动后,将服务信息注册到注册中心registerServerInfo();}
}

详细的我们在2:Protocol一起看下。

2:Protocol

2.1:ProtocolFilterWrapper

源码如下:

class FakeCls {public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {// 当是注册中心地址暴漏时为true,即registry://为true,否则为false,此时是正常的服务暴漏,需要添加Filter链if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {// 2022-01-31 16:30:07return protocol.export(invoker);}// 添加Filter链,生成新的Invoker,然后再暴漏return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));}}

2022-01-31 16:30:07处是使用RegistryProtocol暴漏服务,因此这个方法主要做了如下的两件事:

1:注册服务到注册中心启动本地接收远程调用服务->注册服务信息到注册中心
2:暴漏服务

具体参考2.2:RegistryProtocol

2.2:RegistryProtocol

源码如下:

class FakeCls {public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {// 2022-01-31 16:58:42// 暴漏服务,即启动本地相应的服务端口,准备接收来自网络的请求调用,注意此时服务还没有注册到注册中心final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);// 2022-02-06 16:46:37 URL registryUrl = getRegistryUrl(originInvoker);// 获得注册中心对象,该对象封装了注册和取消注册的相关操作,如zk就是在指定的节点建立相关的子节点final Registry registry = getRegistry(originInvoker);// 获取服务提供者地址,如dubbo://192.168.64.1:20826/dongshi.daddy.service.monitor.DubboMonitorService?...final URL registeredProviderUrl = getRegisteredProviderUrl(originInvoker);// 是否注册,正常为trueboolean register = registeredProviderUrl.getParameter("register", true);// 2022-02-07 11:16:00ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registeredProviderUrl);// 注册服务地址到注册中心if (register) {// 2022-02-07 13:05:06// 注册服务地址到注册中心register(registryUrl, registeredProviderUrl);// 设置已经注册ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true);}// 容错相关配置final URL overrideSubscribeUrl = getSubscribedOverrideUrl(registeredProviderUrl);final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker);overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);// 保证返回一个新的Exporter,Exporter在取消暴露时会用到return new DestroyableExporter<T>(exporter, originInvoker, overrideSubscribeUrl, registeredProviderUrl);}
}

2022-01-31 16:58:42处是暴漏服务具体参考2.2.1:doLocalExport2022-02-06 16:46:37处是获取注册中心的地址,因为需要将服务注册到注册中心了,所以这里开始获取注册中心地址,具体参考2.2.2:getRegistryUrl2022-02-07 11:16:00处是向本地注册表中注册服务,具体参考4:ProviderConsumerRegTable2022-02-07 13:05:06处是注册服务地址到注册中心,具体参考2.2.3:register

2.2.1:doLocalExport

该方法只是本地启动服务,而不会向注册中心注册服务。
源码如下:

class FakeCls {private <T> ExporterChangeableWrapper<T> doLocalExport(final Invoker<T> originInvoker) {// 2022-01-31 17:33:00String key = getCacheKey(originInvoker);// private final Map<String, ExporterChangeableWrapper<?>> bounds = new ConcurrentHashMap<String, ExporterChangeableWrapper<?>>(); 从bounds缓存中获取ExporterChangeableWrapper<T> exporter = (ExporterChangeableWrapper<T>) bounds.get(key);if (exporter == null) {// 上🔒synchronized (bounds) {// 2022-02-01 11:31:59exporter = (ExporterChangeableWrapper<T>) bounds.get(key);// 缓存中依然没有if (exporter == null) {// 封装InvokerDelegete对象,主要是增加了getInvoker方法,如下:/*public Invoker<T> getInvoker() {// 递归获取,可能存在invoker属性是InvokerDelegte的情况if (invoker instanceof InvokerDelegete) {return ((InvokerDelegete<T>) invoker).getInvoker();} else {return invoker;}}*/// getProviderUrl(originInvoker):获取服务暴漏地址,如dubbo://192.168.2.107:20826/dongshi.daddy.service.monitor.DubboMonitorService...final Invoker<?> invokerDelegete = new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker));// 2022-02-01 17:11:26exporter = new ExporterChangeableWrapper<T>((Exporter<T>) protocol.export(invokerDelegete), originInvoker);bounds.put(key, exporter);}}}return exporter;}
}

2022-01-31 17:33:00处是获取bounds的缓存key,具体参考2.2.1.1:getCacheKey2022-02-01 11:31:59处是执行DCL检查 ,防止进入同步的条件发生改变。2022-02-01 17:11:26处的protocol.export(invokerDelegete)我们来分析下,其中protocol是Protocol$Adaptive,在dubbo之服务本地暴露 文章中我们分析了Protocol$Adaptive动态生成的代码如下:

public class Protocol$Adaptive implements com.alibaba.dubbo.rpc.Protocol {public void destroy() {throw new UnsupportedOperationException("method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");}public int getDefaultPort() {throw new UnsupportedOperationException("method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");}public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws com.alibaba.dubbo.rpc.RpcException {if (arg1 == null) throw new IllegalArgumentException("url == null");com.alibaba.dubbo.common.URL url = arg1;String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());if (extName == null)throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);return extension.refer(arg0, arg1);}public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");if (arg0.getUrl() == null)throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");com.alibaba.dubbo.common.URL url = arg0.getUrl();String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());if (extName == null)throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);return extension.export(arg0);}
}

我们注意export方法中的代码String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());,根据协议来获取目标扩展名称,此时debug可以看到结果如下:

在这里插入图片描述

结果是dubbo,再考虑Wrapper 的情况,因此最终的调用顺序是ProtocolAdaptive->ProtocolListenerWrapper->PotocolFilterWrapper->DubboProtocol,具体调用过程参考3:DubboProtocol

2.2.1.1:getCacheKey

源码如下:

class FakeCls {private String getCacheKey(final Invoker<?> originInvoker) {// 2022-01-31 17:38:19// 获取服务提供者地址URL providerUrl = getProviderUrl(originInvoker);// 删除dynamic,enabled,然后转成字符串作为缓存键,结果如:// dubbo://192.168.2.107:20826/dongshi.daddy.service.monitor.DubboMonitorService...String key = providerUrl.removeParameters("dynamic", "enabled").toFullString();return key;}
}

2022-01-31 17:38:19处是获取服务提供者的URL,源码如下:

class FakeCls {private URL getProviderUrl(final Invoker<?> origininvoker) {// 值在2022-01-31 17:39:34处已经设置,所以这里可以直接获取// 如:registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?...&export=// 获取的结果是:dubbo%3A%2F%2F192.168.2.107%3A20826%2Fdongshi.daddy.service.monitor.DubboMonitorServiceString export = origininvoker.getUrl().getParameterAndDecoded(Constants.EXPORT_KEY);// 这里必须有export,不然抛出java.lang.IllegalArgumentException异常if (export == null || export.length() == 0) {throw new IllegalArgumentException("The registry export url is null! registry: " + origininvoker.getUrl());}// 转成com.alibaba.dubbo.common.URL对象URL providerUrl = URL.valueOf(export);return providerUrl;}}

2.2.2:getRegistryUrl

源码如下:

class FakeCls {// com.alibaba.dubbo.registry.integration.RegistryProtocol.getRegistryUrlprivate URL getRegistryUrl(Invoker<?> originInvoker) {// 直接获取注册中心地址,如:registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?...URL registryUrl = originInvoker.getUrl();// 如果是"public static final String REGISTRY_PROTOCOL = "registry";"协议,即registry://if (Constants.REGISTRY_PROTOCOL.equals(registryUrl.getProtocol())) {// 获取registry参数的值作为新的协议名称,如我本地使用zk,是registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?...&registry=zookeeper...// 结果就是zookeeperString protocol = registryUrl.getParameter(Constants.REGISTRY_KEY, Constants.DEFAULT_DIRECTORY);// 使用zookeeper作为新的协议名称,registry://127.0.0.1:2181... -> zookeeper://127.0.0.1:2181...registryUrl = registryUrl.setProtocol(protocol).removeParameter(Constants.REGISTRY_KEY);}// 结果如:zookeeper://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?...return registryUrl;}
}

2.2.3:register

源码如下:

class FakeCls {// com.alibaba.dubbo.registry.integration.RegistryProtocol.registerpublic void register(URL registryUrl, URL registedProviderUrl) {// 2022-02-07 14:17:03Registry registry = registryFactory.getRegistry(registryUrl);// 2022-02-07 15:51:34// 使用zk作为注册中心的话,这里获取的是com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryregistry.register(registedProviderUrl);}
}

2022-02-07 14:17:03处是通过RegistryFactory获取Registry,其中RegistryFactory是一个自适应 的扩展接口,registryFactory是自动生成的自适应扩展类RegistryFactory$Adaptive。
RegistryFactory源码如下:

@SPI("dubbo")
public interface RegistryFactory {@Adaptive({"protocol"})Registry getRegistry(URL url);
}

自动生成代码如下:

package com.alibaba.dubbo.registry;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class RegistryFactory$Adaptive implements com.alibaba.dubbo.registry.RegistryFactory {public com.alibaba.dubbo.registry.Registry getRegistry(com.alibaba.dubbo.common.URL arg0) {if (arg0 == null) throw new IllegalArgumentException("url == null");com.alibaba.dubbo.common.URL url = arg0;String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.registry.RegistryFactory) name from url(" + url.toString() + ") use keys([protocol])");com.alibaba.dubbo.registry.RegistryFactory extension = (com.alibaba.dubbo.registry.RegistryFactory)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.registry.RegistryFactory.class).getExtension(extName);return extension.getRegistry(arg0);}
}

执行代码String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );,获取的结果是extName=zookeeper,那么对应的是哪个扩展类呢,可以从META-INF\dubbo\internal\com.alibaba.dubbo.registry.RegistryFactory文件找到答案,内容如下:

dubbo=com.alibaba.dubbo.registry.dubbo.DubboRegistryFactory
multicast=com.alibaba.dubbo.registry.multicast.MulticastRegistryFactory
zookeeper=com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryFactory
redis=com.alibaba.dubbo.registry.redis.RedisRegistryFactory

最终获取到的扩展类就是ZookeeperRegistryFactory,会调用其getRegistry,因为该方法是在其父类AbstractRegistryFactory中定义的,因此最终调用的方法如下:

class FakeCls {// com.alibaba.dubbo.registry.support.AbstractRegistryFactory.getRegistrypublic Registry getRegistry(URL url) {// 1:设置路径为com.alibaba.dubbo.registry.RegistryService// 2:设置参数interface=com.alibaba.dubbo.registry.RegistryService// 3:删除参数exporturl = url.setPath(RegistryService.class.getName()).addParameter(Constants.INTERFACE_KEY, RegistryService.class.getName()).removeParameters(Constants.EXPORT_KEY, Constants.REFER_KEY);// 缓存键,如zookeeper://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryServiceString key = url.toServiceString();LOCK.lock();try {// 缓存获取Registry registry = REGISTRIES.get(key);// 缓存有,直接returnif (registry != null) {return registry;}// 2022-02-07 14:58:54registry = createRegistry(url);// 不能拿不到if (registry == null) {throw new IllegalStateException("Can not create registry " + url);}// 放入缓存REGISTRIES.put(key, registry);return registry;} finally {LOCK.unlock();}}
}

2022-02-07 14:58:54处是创建Registry,具体参考2.2.4:createRegistry2022-02-07 15:51:34处是通过对应注册中心的Registry注册服务提供者的url,具体参考2.2.5:注册服务地址到注册中心

2.2.4:createRegistry

源码如下:

class FakeCls {// com.alibaba.dubbo.registry.support.AbstractRegistryFactory.createRegistryprotected abstract Registry createRegistry(URL url);
}

我们发现这是一个抽象的模板方法,具体调用的是com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryFactory.createRegistry,源码如下:

class FakeCls {// com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryFactory.createRegistrypublic Registry createRegistry(URL url) {// 直接new ZookeeperRegistry返回return new ZookeeperRegistry(url, zookeeperTransporter);}
}

ZookeeperRegistry构造函数如下:

class FakeCls {// com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry.ZookeeperRegistrypublic ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {super(url);if (url.isAnyHost()) {throw new IllegalStateException("registry address == null");}// dubboString group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);// /dubboif (!group.startsWith(Constants.PATH_SEPARATOR)) {group = Constants.PATH_SEPARATOR + group;}this.root = group;// 获取操作zk的客户端对象zkClient = zookeeperTransporter.connect(url);// 增加状态变化监听器zkClient.addStateListener(new StateListener() {@Overridepublic void stateChanged(int state) {if (state == RECONNECTED) {try {recover();} catch (Exception e) {logger.error(e.getMessage(), e);}}}});}
}

2.2.5:注册服务地址到注册中心

我们这里以ZookeeperRegistry为例来说明,源码如下:

class FakeCls {// com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry.doRegisterprotected void doRegister(URL url) {try {// toUrlPath(url):要创建的zk路径,如/dubbo/dongshi.daddy.service.monitor.DubboMonitorService/providers/dubbo...version%3D0.0.11// 执行后,对应的路径在zk就建立完毕,服务信息注册到注册中心,消费者可以通过注册中心获取服务提供者的信息了zkClient.create(toUrlPath(url), url.getParameter(Constants.DYNAMIC_KEY, true));} catch (Throwable e) {throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);}}
}

3:DubboProtocol

源码如下:

class FakeCls {public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {// 获取url对象,如dubbo://192.168.2.107:20826/dongshi.daddy.service.monitor.DubboMonitorService...URL url = invoker.getUrl();// 2022-02-01 18:58:33String key = serviceKey(url);// exporterMap->new ConcurrentHashMap<String, Exporter<?>>();存储暴漏(本地启动服务)的服务DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);//zs 放到map中exporterMap.put(key, exporter);/*** 暂时忽略开始 ***/Boolean isStubSupportEvent = url.getParameter(Constants.STUB_EVENT_KEY, Constants.DEFAULT_STUB_EVENT);Boolean isCallbackservice = url.getParameter(Constants.IS_CALLBACK_SERVICE, false);if (isStubSupportEvent && !isCallbackservice) {String stubServiceMethods = url.getParameter(Constants.STUB_EVENT_METHODS_KEY);if (stubServiceMethods == null || stubServiceMethods.length() == 0) {if (logger.isWarnEnabled()) {logger.warn(new IllegalStateException("consumer [" + url.getParameter(Constants.INTERFACE_KEY) +"], has set stubproxy support event ,but no stub methods founded."));}} else {stubServiceMethodsMap.put(url.getServiceKey(), stubServiceMethods);}}/*** 暂时忽略结束 ***/// 2022-02-02 10:10:53openServer(url);// 初始化序列器optimizeSerialization(url);return exporter;}
}

2022-02-01 18:58:33处是生成服务的唯一标识,具体参考3.1:serviceKey2022-02-02 10:10:53处是启动服务器,具体参考3.2:openServer

3.1:serviceKey

源码如下:

class FakeCls {protected static String serviceKey(URL url) {// 获取要绑定的端口,public static final String BIND_PORT_KEY = "bind.port";// dubbo://192.168.2.107:20826/dongshi.daddy.service.monitor.DubboMonitorService,结果是20826int port = url.getParameter(Constants.BIND_PORT_KEY, url.getPort());// port:20826,// url.getPath(): dongshi.daddy.service.monitor.DubboMonitorService// url.getParameter(Constants.VERSION_KEY):如<dubbo:service ... version="0.0.11"/>,值为0.0.11// url.getParameter(Constants.GROUP_KEY): 如<dubbo:service ... group="xxxx"/>,值为xxxx// 2022-02-01 19:51:29return serviceKey(port, url.getPath(), url.getParameter(Constants.VERSION_KEY),url.getParameter(Constants.GROUP_KEY));}
}

2022-02-01 19:51:29处最终调用到方法com.alibaba.dubbo.rpc.support.ProtocolUtils.serviceKey(int, java.lang.String, java.lang.String, java.lang.String)源码如下:

class FakeCls {// com.alibaba.dubbo.rpc.support.ProtocolUtils.serviceKey(int, java.lang.String, java.lang.String, java.lang.String)public static String serviceKey(int port, String serviceName, String serviceVersion, String serviceGroup) {StringBuilder buf = new StringBuilder();// 组名称/if (serviceGroup != null && serviceGroup.length() > 0) {buf.append(serviceGroup);buf.append("/");}// 组名称/服务名称buf.append(serviceName);// 组名称/服务名称:版本号if (serviceVersion != null && serviceVersion.length() > 0 && !"0.0.0".equals(serviceVersion)) {buf.append(":");buf.append(serviceVersion);}// 组名称/服务名称:版本号:端口号buf.append(":");buf.append(port);// 结果如:xxxx/dongshi.daddy.service.monitor.DubboMonitorService:0.0.11:20826return buf.toString();}
}

3.2:openServer

源码如下:

class FakeCls {private void openServer(URL url) {// 使用地址作为唯一标识,如192.168.2.107:20826String key = url.getAddress();// url正常无该值,而默认值是true,所以这里可以认为是trueboolean isServer = url.getParameter(Constants.IS_SERVER_KEY, true);if (isServer) {// ExchangeServer代表了服务器,是Server接口的子接口// Map<String, ExchangeServer> serverMap = new ConcurrentHashMap<String, ExchangeServer>();// key;host:port value:ExchangeServerExchangeServer server = serverMap.get(key);if (server == null) {// 2022-02-05 20:26:00serverMap.put(key, createServer(url));// 当存在多个service时会有不为空的情况} else {// 因为间接继承了com.alibaba.dubbo.common.Resetable接口,所以这里可以重置相关属性server.reset(url);}}}
}

2022-02-05 20:26:00处是利用URL创建Server并添加到serverMap中,具体参考3.3:createServer

3.3:createServer

源码如下:

class FakeCls {private ExchangeServer createServer(URL url) {// public static final String CHANNEL_READONLYEVENT_SENT_KEY = "channel.readonly.sent";// server关闭时发送READONLY事件 // dubbo://192.168.2.107:20826/dongshi.daddy.service.monitor.DubboMonitorService?...&channel.readonly.sent=true&...url = url.addParameterIfAbsent(Constants.CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString());// public static final int DEFAULT_HEARTBEAT = 60 * 1000;// public static final String HEARTBEAT_KEY = "heartbeat";// 启用心跳,默认心跳时长一分钟// dubbo://192.168.2.107:20826/dongshi.daddy.service.monitor.DubboMonitorService?...&heartbeat=60000&...url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT));// public static final String SERVER_KEY = "server";// public static final String DEFAULT_REMOTING_SERVER = "netty";// 检验是否有对应名称的Transporter Dubbo SPI扩展类,Transporter是用于操作netty,mina等框架的接口String str = url.getParameter(Constants.SERVER_KEY, Constants.DEFAULT_REMOTING_SERVER);// 保证对应的扩展类存在if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str))throw new RpcException("Unsupported server type: " + str + ", url: " + url);// 使用dubbo codec编解码,即DubboCountCodecurl = url.addParameter(Constants.CODEC_KEY, DubboCodec.NAME);ExchangeServer server;try {// 2022-02-06 12:45:27server = Exchangers.bind(url, requestHandler);} catch (RemotingException e) {throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e);}// 检验client扩展类必须存在str = url.getParameter(Constants.CLIENT_KEY);if (str != null && str.length() > 0) {Set<String> supportedTypes = ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions();if (!supportedTypes.contains(str)) {throw new RpcException("Unsupported client type: " + str);}}return server;}
}

2022-02-06 12:45:27处Exchangers是Exchanger的门面类 ,用来封装底层系统的细节,简化用户的使用,最后返回的是ExchangeServer,这是Server的一个子接口,定义如下:

public interface ExchangeServer extends Server {Collection<ExchangeChannel> getExchangeChannels();ExchangeChannel getExchangeChannel(InetSocketAddress remoteAddress);
}

bind方法执行输出的日志如下:

[2022-02-0613:06:28][INFO ][jpm-AbstractServer-<init>(65)]- [DUBBO] Start NettyServer bind /0.0.0.0:20826, export /192.168.2.107:20826, dubbo version: 2.6.6, current host: 192.168.2.107

可以看出来是启动了netty服务,并暴漏服务端口了。

4:ProviderConsumerRegTable

该类是用于进行本地服务消费者和服务提供者注册的支持类(工具类),为了了服务提供者和服务消费者的Invoker,主要用于进行QOS(quality of service),如上下线,统计等,相关代码如下:

public class ProviderConsumerRegTable {/*** 服务提供者Invoker集合* key:服务提供者URL*/public static ConcurrentHashMap<String, Set<ProviderInvokerWrapper>> providerInvokers = new ConcurrentHashMap<String, Set<ProviderInvokerWrapper>>();/*** 服务消费者Invoker集合* key:服务消费者URL*/public static ConcurrentHashMap<String, Set<ConsumerInvokerWrapper>> consumerInvokers = new ConcurrentHashMap<String, Set<ConsumerInvokerWrapper>>();// .... 省略方法
}

4.1:ProviderInvokerWrapper

provider invoker的wrapper类,主要是增加了一些额外的辅助运维属性,比如标记是否注册的属性isReg,当进行下线操作后就可以修改为false,代表已经下线,主要属性如下:

class FakeCls {/*** Invoker 对象*/private Invoker<T> invoker;/*** 原始 URL*/private URL originUrl;/*** 注册中心 URL*/private URL registryUrl;/*** 服务提供者 URL*/private URL providerUrl;/*** 是否注册*/private volatile boolean isReg;
}

4.2:ConsumerInvokerWrapper

consumer invoker的wrapper类,主要是增加了一些额外的属性,如下:

class FakeCls {/*** Invoker 对象*/private Invoker<T> invoker;/*** 原始 URL*/private URL originUrl;/*** 注册中心 URL*/private URL registryUrl;/*** 消费者 URL*/private URL consumerUrl;/*** 注册中心 Directory*/private RegistryDirectory registryDirectory;
}
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 智慧农业接入复合式树莓派网关(二)

    五、产品创建 ​ 需要在涂鸦 IoT 开发平台创建产品&#xff0c;获取授权信息&#xff0c;然后将产品和授权相关信息写入到代码中&#xff0c;实现接入涂鸦云&#xff0c;详细步骤如下&#xff1a; 1、网关设备的创建 登录涂鸦 IoT 工作台后&#xff0c;单击 创建产品 并选择 …...

    2024/4/20 5:56:42
  2. 生成订单30分钟未支付,则自动取消,该怎么实现

    在开发中&#xff0c;往往会遇到一些关于延时任务的需求。例如 生成订单30分钟未支付&#xff0c;则自动取消 生成订单60秒后,给用户发短信 对上述的任务&#xff0c;我们给一个专业的名字来形容&#xff0c;那就是延时任务。那么这里就会产生一个问题&#xff0c;这个延时任…...

    2024/4/26 22:35:40
  3. node_modules\node-sass: Command failed报错问题处理

    前言&#xff1a; 运行小程序代码时出现这个报错&#xff0c;百度了好久终于解决&#xff0c;整理一下以作纪念。 报错&#xff1a; error G:\Codes\XXX\node_modules\node-sass: Command failed. Exit code: 1 Command: node scripts/build.js Arguments: Directory: G:\Cod…...

    2024/4/27 15:29:14
  4. 中国碳化硅单晶片行业发展前景预测与投资战略规划分析报告2022~2028年

    中国碳化硅单晶片行业发展前景预测与投资战略规划分析报告2022&#xff5e;2028年 第一章 碳化硅单晶片、外延片、器件产业概述 1 1.1 碳化硅单晶片、外延片、器件定义 1 1.1.1 碳化硅概述 1 1.1.2 碳化硅晶体结构介绍 2 1.1.3 碳化硅单晶片定义 4 1.1.4 碳化硅外延片定义 5 1.…...

    2024/4/27 16:33:05
  5. draft

    // 经过六年的努力&#xff0c;小明终于被一所知名中学录取。 优秀的小明总是对一些奇奇怪怪的事情感兴趣&#xff0c;这次他想知道谁在这所新学校拥有的朋友最多&#xff0c; 由于大家都才刚报到&#xff0c;所以小明只知道大家两两之间是否是朋友关系。 输入 的第一行有两个整…...

    2024/4/27 17:43:44
  6. eMMC--基本架构

    eMMC--基本架构1. eMMC是什么1.1 个人理解1.2 eMMC 的整体架构2. 各组成部分2.1 NAND Flash2.2 Flash Controller2.3 标准接口参考&#xff1a;eMMC官方协议黑猫带你学eMMC协议第1篇&#xff1a;全网最全emmc协议中文详讲&#xff0c;这份学习框架图&#xff0c;你值得拥有&…...

    2024/4/27 17:47:48
  7. kali中安装ksubdomain工具

    1. linux下需要安装libpcap-dev&#xff1b;所以首先布置好安装工具所需的环境。 sudo apt-get install libpcap-dev libnids-dev libnet1-dev 2.安装go包 apt install gccgo-go 3.下载ksubdomain:GitHub - knownsec/ksubdomain: 无状态子域名爆破工具 4.解压并cd ksubdomai…...

    2024/4/27 18:37:09
  8. react项目国际化

    react项目国际化 这里使用的react-intl 1、安装react-intl npm install react-intl --save 或者 cnpm install react-intl --save 2、引入 在需要国际化的文件引入react-intl 需要全局国际化就在app.js文件中引入 import React, { Component } from "react"; …...

    2024/4/27 16:05:47
  9. Cobalt Strike特征修改

    在红蓝对抗以及hvv等等情况下&#xff0c;我们都会用到 Cobalt Strike&#xff0c;那么它也是安全公司重点关注的对象&#xff0c;跟msf类似&#xff0c;但CS操作相对比MSF使用简单&#xff0c;同时也有一个强大的插件库。那么&#xff0c;这么红的工具&#xff0c;特征方面安全…...

    2024/4/27 21:01:14
  10. vue组件通讯方式

    1. props和$emit 父组件向子组件传递数据是通过prop传递的&#xff0c;子组件传递数据给父组件是通过$emit触发事件来做到的。Vue.component(child,{ data(){ return { mymessage:this.message } }, template…...

    2024/4/27 15:58:42
  11. 本专栏说明

    本专栏将实现一个“All In One Box”的软硬件系统&#xff0c;最终的目的是希望能够通过这个Box满足作为IT人员的“一切控制欲望”。Box将作为载体存放于家庭或者办公环境&#xff0c;作为独立存储或者指令桥梁存在。通过这个Box&#xff0c;我们可以实现以下功能&#xff1a; …...

    2024/4/27 14:14:46
  12. 我的订阅地址

    添加链接描述 https://gitee.com/xhay/ssr/blob/master/Surge.conf...

    2024/4/27 15:09:16
  13. 手机便签上如何记录过去多少天或距离开始还有多少天?

    时间过得是非常快的。为了可以更好地了解某些事情过去了多少天&#xff0c;或者距离某一件事开始还有多少天&#xff0c;很多人会选择使用手机App软件来记录和查看这些事情相应的天数。那手机便签上如何记录过去多少天或距离开始还有多少天&#xff1f; 手机敬业签云便签支持在…...

    2024/4/27 13:48:23
  14. ACM周赛ICPC昆明资格赛

    文章目录A.kaptreeB.十字路口C.七段的符号D.Xor QueryE.A hard working manF.red bagsA.kaptree Code: // 考点树的深度 难度 ⭐ // 保证树的根为1 // 标程 #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algo…...

    2024/4/27 13:55:41
  15. LeeCode 695. 岛屿的最大面积

    695. 岛屿的最大面积 难度 中等 给你一个大小为 m x n 的二进制矩阵 grid 。 岛屿 是由一些相邻的 1 (代表土地) 构成的组合&#xff0c;这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0&#xff08;代表水&#xff09;包…...

    2024/4/27 20:17:35
  16. 工业人工智能及应用研究现状及展望

    工业人工智能及应用研究现状及展望 人工智能技术与咨询 来源&#xff1a;《自动化学报》&#xff0c;作者李杰等 摘 要 工业4.0 将工业制造流程以及产品质量优化从以前依照经验和观察进行判断转变为以事实为基础,通过分析数据进而挖掘潜在价值的完整智能系统.人工智能技术的…...

    2024/4/26 19:07:23
  17. 今日睡眠质量记录85分

    昨天睡得早&#xff0c;入睡也不晚&#xff0c;早上起来感觉比较精神的&#xff0c;但是一看记录&#xff0c;入睡时间有00&#xff1a;50了&#xff0c;感觉和印象中的不太一样呀。那这个问题出在哪儿呢&#xff1f;...

    2024/4/27 17:35:06
  18. JavaWeb学习——用户注册(14)

    接上篇 目录流程说明基本流程RegisterServlet流程UserMapper流程基本创建流程说明 基本流程 用户填写用户名密码等信息&#xff0c;点击注册按钮&#xff0c;提交到RegisterServlet 在RegisterServlet中使用MyBatis保存数据 保存前&#xff0c;需要判断用户名是否已经存在&am…...

    2024/4/27 18:58:54
  19. jdk8,stream流collect方法:处理集合方法

    jdk8&#xff0c;stream流collect方法&#xff1a;处理集合方法前提需要了解FunctionalInterface&#xff1a;函数式接口&#xff0c;很多方法参数都是函数式接口&#xff0c;需要了解的可以看下这篇文章数据转换1&#xff1a;转List2&#xff1a;转Set3&#xff1a;转Collecti…...

    2024/4/27 17:44:21
  20. Javascript复制内容到剪切版

    有 input 或 textarea 标签时 <input type"text" value"复制我"><button>点击复制</button><script>const btn document.querySelector(button);btn.addEventListener(click, () > {const input document.querySelector(inp…...

    2024/4/27 20:43:17

最新文章

  1. 全栈开发之路——前端篇(1)介绍、框架确定、ide设置与项目创建

    文章目录 前言一、前端框架React和VueReactVue 二、编译器选择和配置1.传统的下载和使用2.你可能遇到的问题1.ERR&#xff01; syscall mkdir2.vue : File C:\nodejs\node_global\vue.ps1 cannot be loaded because running scripts is disabled on3.出现乱码问题 3.运行Vue 三…...

    2024/5/1 23:17:19
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. Harmony鸿蒙南向驱动开发-UART

    UART指异步收发传输器&#xff08;Universal Asynchronous Receiver/Transmitter&#xff09;&#xff0c;是通用串行数据总线&#xff0c;用于异步通信。该总线双向通信&#xff0c;可以实现全双工传输。 两个UART设备的连接示意图如下&#xff0c;UART与其他模块一般用2线&a…...

    2024/4/30 1:11:28
  4. [Flutter]导入singular_flutter_sdk后运行到Android报错

    问题&#xff1a; 接入归因之前&#xff0c;flutter项目一起正常。接入归因之后&#xff0c;iOS正常Android有问题。 dependencies: # Singular归因singular_flutter_sdk: ^1.3.3 针对 Flutter 的 Singular SDK 集成指南 https://support.singular.net/hc/zh-cn/articles/…...

    2024/4/30 20:13:57
  5. RP2040开发笔记

    RP2040 采用合宙的RP2040(板载4MB Flash)&#xff0c; 所有开发资料参考官方&#xff1a;树莓派 Pico 中文站...

    2024/5/1 13:52:14
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/1 17:30:59
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/30 18:14:14
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/30 18:21:48
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/30 9:43:22
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57