客户端,是指发起请求的一方。也就是浏览器,或者指爬虫程序。通过发起请求,来获取想要的网页。服务端,请求的响应端,是 web 服务端。web 服务,是一个虚拟意思上的机器的概念。可以是一个计算机集群,也可以是一个软件或者程序。客户端,通过发送一个请求给服务端,然后进行等待。服务端按照客户端的请求,返回客户端需要的数据。这个过程,我们称之为经典的客户端——服务端模型。
使用 Zookeeper 客户端连接 Zookeeper 服务,我们需要使用 ./zkCli.sh 命令:# 进入 bin 文件夹cd /usr/local/zookeeper/apache-zookeeper-3.6.1-bin/bin/# 连接命令./zkCli.sh # 连接时输出信息Connecting to localhost:2181...# 出现下面这一行时,表示我们连接成功[zk: localhost:2181(CONNECTED) 0] 这里我们就可以使用上一节学习过的命令来操作节点了,我们来测试一下:# 获取根节点的子节点ls /# 输出默认的子节点 zookeeper[zookeeper]# 创建根节点的子节点 imooccreate /imooc# 输出创建成功信息Created /imooc# 创建后再次获取根节点的子节点ls /# 输出两个子节点[imooc, zookeeper]# 我们可以给节点设置数据set /imooc wiki# 然后我们再获取 imooc 节点的数据get /imooc# 输出我们设置的信息wiki# 最后我们测试一下删除命令delete /imooc# 删除后再次获取根节点的子节点ls /# 输出子节点 zookeeper,imooc 节点被删除[zookeeper]# 退出 Zookeeper 客户端命令quit通过上面的学习,我们知道了如何部署单机模式的 Zookeeper 服务,以及如何通过 Zookeeper 客户端连接 Zookeeper 服务端,来对 Znode 节点进行操作。那么 Zookeeper 是如何为我们提供服务的呢,接下来我们就来了解单机模式下的 Zookeeper 的工作流程。
实例:延迟 1 秒钟,每个 15 秒钟往服务端发送一次 hello world。channelFuture.channel().eventLoop().scheduleWithFixedDelay(new Runnable() { public void run() { channelFuture.channel().writeAndFlush("hello world"); } },1,15, TimeUnit.SECONDS);服务端执行结果:channelRead>>>hello world>>>2020-07-26T15:16:08.893exceptionCaught>>>null客户端执行结果:客户端关闭了Process finished with exit code 0代码说明:客户端每隔 15 秒发送一次数据;服务端如果 5 秒之内没有读写事件,则自动断开连接;从时间设置上来看,客户端每次发送数据都是超时了,因此,连接会被断开。
uni-app 的 API 与微信小程序 API 基本一致。掌握微信小程序 API 对后面的开发很有帮助。微信小程序 API 文档:https://developers.weixin.qq.com/miniprogram/dev/api/
http 最常用的协议,用于客户端主动向服务器发送请求,单向传递;ajax HTTP 的扩展版,底层还是 HTTP 协议,只不过客户端是无刷新的;comet 也是基于 HTTP 封装的,使用 HTTP 长连接的方式,原理大致是将 HTTP 的timeout 设置较长,服务器有数据变化时返回数据给客户端,同时断开连接,客户端处理完数据之后重新创建一个 HTTP 长连接,循环上述操作(这只是其中一种实现方式);websocket 这是 HTML5 中的新标准,基于 socket 的方式实现客户端与服务端双向通信,需要浏览器支持 HTML5;Adobe Flash Socket 这个也是使用 socket 的方式,需要浏览器支持 flash 才行,为了兼容老版本的浏览器;ActiveX object 只适用于 IE 浏览器;目前尚没有一种方式能兼容所有的浏览器,只能针对软件的目标客户人群做一定的兼容。sse 服务端单向推送。
客户端实现的功能:在连接准备就绪时 channelActive () 发起登录认证。实例:public class ClientLoginHandler extends ChannelInboundHandlerAdapter { //1.通道激活的时候,发送账号、密码 @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { Map<String,String> map=new HashMap<String,String>(); map.put("username","admin"); map.put("password","1234567"); //对象流序列化Map ByteArrayOutputStream os = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(map); byte[] bytes=os.toByteArray(); //关闭流 oos.close(); os.close(); //发送 ctx.channel().writeAndFlush(Unpooled.copiedBuffer(bytes)); }}代码说明:channelActive 事件是通道建立时触发该事件,并且仅触发一次该事件,通常情况下,在 channelActive 里面实现登录认证;客户端往服务端发送数据的时候需要使用对象流进行序列化,客户端接收服务端响应信息的时候,需要通过对象流进行反序列化;Netty 底层是 ByteBuf 进行传输的(后面章节会详细介绍),最终网络底层传输则是 byte [],因此需要做序列化和反序列化操作。
在 Zookeeper 客户端中,当我们使用 addauth digest mooc:mooc 命令来添加认证用户信息时,Zookeeper 客户端会使用 ClientCnxn 客户端类的 addAuthInfo 方法来封装请求信息,把请求类型包装成权限类请求,封装完毕后发送给服务端。// 添加认证信息,参数一:授权类型,参数二:认证信息的字节数组public void addAuthInfo(String scheme, byte[] auth) { // 判断当前客户端状态 if (this.state.isAlive()) { // 封装认证信息 scheme:digest this.authInfo.add(new ClientCnxn.AuthData(scheme, auth)); // 封装请求头 -4为请求头的xid,100为请求类型:auth this.queuePacket(new RequestHeader(-4, 100), (ReplyHeader)null, new AuthPacket(0, scheme, auth), (Record)null, (AsyncCallback)null, (String)null, (String)null, (Object)null, (WatchRegistration)null); }}简单地介绍了 Zookeeper 客户端处理权限类请求的过程,接下来就是 Zookeeper 服务端的处理过程了。
同样,我们展示了通过 C 语言 Socket API 编写 UDP 客户端和服务器程序的步骤,如下:图中的矩形方框都是 C 函数。对比 TCP 客户端、服务器的建立过程,我们发现 UDP 客户端可以调用 connect 函数,但是并不会去连接服务器,只是和本地接口做绑定;UDP 服务器是没有 listen 和 accept 调用的。对于 UDP 客户端来说,connect 函数的调用是可选的。接下来,我们就探讨一下如何用 Java 语言编写 UDP 客户端和服务器程序。
实例:延迟 1 秒钟,每个 3 秒钟往服务端发送一次 hello world。channelFuture.channel().eventLoop().scheduleWithFixedDelay(new Runnable() { public void run() { channelFuture.channel().writeAndFlush("hello world"); } },1,3, TimeUnit.SECONDS);服务端执行结果:channelRead>>>hello world>>>2020-07-26T15:15:10.889channelRead>>>hello world>>>2020-07-26T15:15:13.892channelRead>>>hello world>>>2020-07-26T15:15:16.893channelRead>>>hello world>>>2020-07-26T15:15:19.894代码说明:客户端每隔 3 秒发送一次数据;服务端如果 5 秒之内没有读写事件,则自动断开;从时间设置上来看,客户端每次发送数据的时间都在超时时间范围之内,因此,连接不会被断开。
注册微信小程序账号,获取到 AppID,我们后面配置的时候会用到。在 HBuilderX 工具栏,点击发行,选择小程序-微信。输入小程序名称和 AppID,单击发行就可以了。这样我们就会获得一个微信小程序的打包文件,接下来我们来发布微信小程序项目,打开微信小程序开发者工具,导入刚刚生成的微信小程序项目的打包文件,在微信小程序开发者工具中先测试一下,项目运行是否正常,项目测试没有问题后,点击右上角>>按钮,上传代码就可以发布微信小程序了,最后等待微信团队审核通过,别人就可以在线上访问到你的项目了。
为了更好地理解编写 TCP 客户端和服务器程序的步骤,下图展示了通过 C 语言 Socket API 编写客户端和服务器程序的过程。图中的矩形方框都是 C 函数,很好的展示了客户端和服务器 Socket 的建立过程。对于 Java 语言来说,只是应用面向对象的思维对上面的过程进行了抽象,下来我们就探讨一下如何编写 Java 客户端和服务器程序。
有的应用并没有明确的前端应用,比如控制台程序或者是服务接口,这种情况下就需要用到客户端凭证式获得凭证了。这种方式下,没有「人」的参与,只有认证服务对后台服务的认证。客户端凭证式
修改客户端的配置文件 application.properties ,以便指定客户端指向的服务端的地址。由于刚刚服务端已经占用了 8080 端口,所以将客户端的端口设置为 8091 。还有一个必要设置是客户端的名称,当我们监控的项目实例比较多时,需要通过客户端名称来区分。实例:# 配置端口server.port=8091# 配置监控管理端地址spring.boot.admin.client.url=http://127.0.0.1:8080# 客户端的名称,用于区分不同的客户端spring.boot.admin.client.instance.name=CLIENT1TIps:此处指定监控管理端地址使用的是 spring.boot.admin.client.url ,我个人认为应使用 spring.boot.admin.server.url 更加合理。当然大家不用纠结于此,此处只是特别提示。
客户端收到服务端的 Cookie 后,该 Cookie 会在接下来的每个请求中被发送至服务器。Cookie 的值被存储在名为 Cookie 的 HTTP 消息头中,并且只包含了 Cookie 的值,其它的选项全部被去除。客户端向服务端发送的 HTTP 请求中设置 Cookie 消息头,一个具体的例子如下:Connection:keep-aliveCookie:user=ZhangSanHost:localhost:8080User-Agent:Mozilla/5.0 AppleWebKit/537.36 Chrome Safari在这个例子中,客户端向服务端发送的 HTTP 消息头中,设置了 ‘Cookie:user=ZhangSan’,服务端接受到字符串 ‘user=ZhangSan’ 作为 Cookie,从而确认此次请求对应的用户。
CAS 客户端是指可以和 CAS 服务端进行安全通讯的业务系统。CAS 通讯支持以下协议:CAS(版本1,2,3)SAML 1.1OpenIDOAuth(1.0,2.0)
我们使用 Zookeeper 的客户端 zkCli 命令行工具来设置节点的 ACL ,使用 zkCli.sh 连接 Zookeeper 服务端后,然后查看节点的 ACL 信息:# 创建 /imooc[zk: localhost:2181(CONNECTED) 1] create /imooc# 创建成功Created /imooc# 查询 /imooc 节点的 ACL 信息[zk: localhost:2181(CONNECTED) 2] getAcl /imooc# 输出 ACL'world,'anyone: cdrwa我们可以发现,imooc 节点的 ACL 信息为默认的 world:anyone:cdrwa.接下来我们使用 Auth 的方式改变该节点的 ACL 设置:# 添加认证用户 mooc,密码为 mooc[zk: localhost:2181(CONNECTED) 3] addauth digest mooc:mooc# 给 /imooc 节点设置 ACL,验证模式为 auth,授权对象为所有认证用户,所以可以不用填写参数,权限信息为所有操作[zk: localhost:2181(CONNECTED) 4] setAcl /imooc auth::cdrwa# 查看 /imooc 节点的 ACL 信息[zk: localhost:2181(CONNECTED) 5] getAcl /imooc# 输出 ACL'digest,'mooc:0xEep90zjLm6hbWMlQ2BGbaQWzI=: cdrwa我们可以看到 imooc 节点的 ACL 信息已经修改成功,密码也被加密了。接下来我们使用 Digest 的方式来设置节点的 ACL :# 给 /imooc 节点设置 ACL,验证模式为 digest# 用户名为 mooc,密码是被加密后的 mooc,加密方式为 BASE64(SHA1(mooc)),权限信息为所有操作[zk: localhost:2181(CONNECTED) 6] [zk: localhost:2181(CONNECTED) 6] setAcl /imooc digest:mooc:0xEep90zjLm6hbWMlQ2BGbaQWzI=:cdrwa# 查看 /imooc 节点的 ACL 信息[zk: localhost:2181(CONNECTED) 7] getAcl /imooc# 输出 ACL'digest,'mooc:0xEep90zjLm6hbWMlQ2BGbaQWzI=: cdrwa我们可以发现,使用 Auth 和 Digest 设置的 ACL 信息是相同的,都是基于 Digest 的授权模式,它们的区别是:Auth 需要在设置 ACL 之前添加认证用户,并且无需手动加密,它的授权范围是所有的使用 addauth digest username:password 命令添加的用户。Digest 不需要提前添加认证用户,但是需要自己完成密码的加密,而且授权范围只有当前设置的用户。Tips: 我们需要注意,当前客户端添加的认证用户只针对当前客户端有效,客户端断开连接后也需要重新进行认证。如果此时客户端断开连接,再重新连接,或者新开一个客户端进行操作,访问节点可能会出现以下错误:[zk: localhost:2181(CONNECTED) 1] get /imooc# 错误 1org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /imooc[zk: localhost:2181(CONNECTED) 2] getAcl /imooc# 错误 2Authentication is not valid : /imooc此时我们需要重新使用 addauth digest username:password 来对新的客户端添加认证用户,才可以访问有 ACL 权限的节点。# 添加认证用户,用户名密码和设置 ACL 时的一致[zk: localhost:2181(CONNECTED) 3] addauth digest mooc:mooc[zk: localhost:2181(CONNECTED) 4] get /imoocnull[zk: localhost:2181(CONNECTED) 5] getAcl /imooc'digest,'mooc:0xEep90zjLm6hbWMlQ2BGbaQWzI=: cdrwaTips: 如果是密码设置错误导致对节点的访问无权限,我们可以在 zoo.cfg 配置文件中加入 skipACL=yes,跳过 ACL 验证,重启服务后再修改 ACL 信息或者删除错误节点。本设置不建议在生产环境下使用!上面的设置方式都是针对当前节点的 ACL 的设置,一个一个的对每个节点去设置它们的 ACL 信息是一件非常繁琐的事情,所以我们可以使用 -R 参数来递归设置子节点的 ACL 信息:# 创建子节点 /imooc/mooc[zk: localhost:2181(CONNECTED) 8] create /imooc/mooc# 创建子节点 /imooc/mooc 成功Created /imooc/mooc# 创建子节点 /imooc/mooc/wiki[zk: localhost:2181(CONNECTED) 9] create /imooc/mooc/wiki# 创建子节点 /imooc/mooc/wiki 成功Created /imooc/mooc/wiki# 使用 digest 设置 /imooc 节点的 ACL,使用 —R 来递归设置子节点的 ACL 信息[zk: localhost:2181(CONNECTED) 10] setAcl -R /imooc digest:mooc:0xEep90zjLm6hbWMlQ2BGbaQWzI=:cdrwa# 查看 /imooc 节点的 ACL 信息[zk: localhost:2181(CONNECTED) 11] getAcl /imooc 'digest,'mooc:0xEep90zjLm6hbWMlQ2BGbaQWzI=: cdrwa# 查看 /imooc/mooc 节点的 ACL 信息[zk: localhost:2181(CONNECTED) 12] getAcl /imooc/mooc'digest,'mooc:0xEep90zjLm6hbWMlQ2BGbaQWzI=: cdrwa# 查看 /imooc/mooc/wiki 节点的 ACL 信息[zk: localhost:2181(CONNECTED) 13] getAcl /imooc/mooc/wiki'digest,'mooc:0xEep90zjLm6hbWMlQ2BGbaQWzI=: cdrwa我们发现 imooc 的 ACL 信息和它的子节点的 ACL 信息都是相同的,说明我们使用 -R 递归设置子节点的 ACL 信息成功了。成功的实现了节点 ACL 的设置之后,接下来我们来讲解 Zookeeper ACL 实现的原理。
从前面的流程中我们看到,与 CAS 认证中心集成过程中,Spring Security 用来构建资源服务,也就是 CAS 的认证客户端。此处我们来看如何通过 Spring Security 配置 CAS 认证客户端。3.2.1 服务票据认证集成的第一步是配置资源服务获取到 Token 之后,如何到 CAS 认证中心去验证。多数情况下,这一步是必须的。我们需要在 Spring 上下文中创建 ServiceProperties Bean 对象。该对象必须配置 service 属性,其值为一个 URL 地址,用来被过滤器 CasAuthenticationFilter 侦听。配置代码如下:<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties"><property name="service" value="https://localhost:8443/cas-sample/login/cas"/><property name="sendRenew" value="false"/></bean>接下来配置 CAS 认证相关过滤器信息,这些配置基本固定。<security:http entry-point-ref="casEntryPoint">...<security:custom-filter position="CAS_FILTER" ref="casFilter" /></security:http><bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter"><property name="authenticationManager" ref="authenticationManager"/></bean><bean id="casEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint"><property name="loginUrl" value="https://localhost:9443/cas/login"/><property name="serviceProperties" ref="serviceProperties"/></bean>完成这步后,我们继续配置 CAS 认证管理器,添加测试用的用户信息。<security:authentication-manager alias="authenticationManager"><security:authentication-provider ref="casAuthenticationProvider" /></security:authentication-manager><bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider"><property name="authenticationUserDetailsService"> <bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"> <constructor-arg ref="userService" /> </bean></property><property name="serviceProperties" ref="serviceProperties" /><property name="ticketValidator"> <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator"> <constructor-arg index="0" value="https://localhost:9443/cas" /> </bean></property><property name="key" value="an_id_for_this_auth_provider_only"/></bean><security:user-service id="userService"><security:user name="joe" password="{noop}joe" authorities="ROLE_USER" /></security:user-service>注意,CAS 体系下的认证是交由 CAS 认证中心完成的,这一步中配置的密码并不会用于认证,此处的配置是为了决定认证后该用户所具有的权限。至此,CAS 认证客户端的配置完成。3.2.2 单点注销CAS 认证协议中,包含了明确的单点注销流程,我们可以便捷的集成到我们的认证客户端之中,配置信息如下:<security:http entry-point-ref="casEntryPoint">...<security:logout logout-success-url="/cas-logout.jsp"/><security:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/><security:custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/></security:http><!-- 该过滤器用于接收来自 CAS 认证中心的登出请求。(由其他应用发起登出) --><bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/><!-- 该过滤器用于向 CAS 认证中心发送登出请求。(由本应用发起登出) --><bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter"><constructor-arg value="https://localhost:9443/cas/logout"/><constructor-arg> <bean class= "org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/></constructor-arg><property name="filterProcessesUrl" value="/logout/cas"/></bean>登出操作由某一 CAS 客户端发起,CAS 认证中心接收到之后,会向所有该用户已登录应用发起登出通知,最后实现全部应用的登出效果。
实例://字符串解码器pipeline.addLast(new StringDecoder());//字符串编码器pipeline.addLast(new StringEncoder());//业务Handler,需要传递“bootstrap”pipeline.addLast(new ClientHandler(bootstrap));public class ClientHandler extends ChannelInboundHandlerAdapter { private Bootstrap bootstrap; ClientHandler(Bootstrap bootstrap){ this.bootstrap=bootstrap; } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { bootstrap.connect("127.0.0.1",80).sync(); }}代码说明:连接断开时,客户端的 Handler 的 channelInactive () 会监听的到,在该方法里面实现断开重连;Handler 必须传递 bootstrap。
技巧 1如果我们的微服务监控平台没有任何数据,或者说,在打开微服务平台之后,各参数一直处于 loading 状态,这个时候,我们只需要在服务端调用任意一个服务接口即可,这样在微服务监控平台,我们就能看到被监控实例的参数了。技巧 2如果我们在访问 /actuator/hystrix.stream 路径时,系统找不到对应的路径,即报 404 异常,那么我们需要在对应项目的启动类中添加一个 Bean :@Beanpublic ServletRegistrationBean hystrixMetricsStreamServlet() { ServletRegistrationBean registration = new ServletRegistrationBean(new HystrixMetricsStreamServlet()); registration.addUrlMappings("/hystrix.stream"); return registration;}这样我们就能正常访问 /actuator/hystrix.stream 下的路径了。
在将 Swagger Codegen 的依赖引入到 Spring Boot 中去后,我们就可以使用 Maven 自带的命令来将上述配置信息分别生成服务端和客户端代码,命令如下:首先,将上述配置好的文件利用 Swagger Codegen 来生成服务端和客户端代码 java -jar swagger-codegen-cli.jar generate -i swagger.yaml -c swaggerConfig.json -l spring -o server代码解释:第一行,使用 generate 命令来将配置在 swagger.yaml 文件中的服务端代码进行生成。第一行,使用 -c 参数,表明使用 json 配置文件,并且该配置文件的名称为 swaggerConfig.json。第二行,使用 -l 参数,表明客户端所使用的语言为 spring 。第二行,使用 -o 参数来指定代码最终的存放位置,server 表示将生成的代码存放到名为 server 的文件夹下。然后我们使用 cd 命令来进到我们生成代码后所存放的目录: cd server最后我们将生成的代码打成 Jar 包: mvn package这是 Maven 自带的打包命令,执行该命令之后,Maven 会默认读取项目中的 pom 文件中配置的打包规则,即 packaging 节点,如果该节点没有配置任何规则,则 Maven 会默认打成 Jar 包 (这里我们配置了 Jar)。这样我们就可以在项目的 target 目录下,找到我们利用 Swagger Codegen 所生成的服务端和客户端代码的 Jar 包了,我们可以把该 Jar 包放到其他环境中使用,也可以供其他项目使用,这就是我们利用 Swagger Codegen 所生成的服务端和客户端代码的最终使用目的。
权威域名服务器:能够决定域名和 IP 的关系。本地域名服务器:一般由本地运营商提供,不能解析域名,通常是缓存域名解析和帮用户到权威域名服务器查询解析结果。公共域名服务器:跟本地域名服务器类似,只是它不是某个运营商提供的,是全网公用的。
选择 "开启服务:POP3/SMTP 服务"后,系统提示通过发送短信开启 POP3/SMTP 服务
通过上一节的学习,我们知道了如何通过 Git 命令来操作 GitHub 代码仓库。有些 Git 基础知识还不熟练的朋友可能会觉得用 Git 操作略显吃力。不要着急,我们今天将会讲解 GitHub 客户端的使用方法,通过客户端,与 GitHub 远程代码仓库的互动将会变得更加简单。
如果状态码是 4xx,服务器就应该向用户返回出错信息。一般来说,返回的信息是键值对形式的数据,将 error 作为键名,出错信息作为键值即可。比如,在一个提供查询学生信息的 API 中,要求客户端提供正确的 API key(可以理解为输入了正确的用户名和密码)才能访问,如果提供的 API key 不正确,此时服务器应拒绝访问,并返回错误信息。这样,客户端就知道了为何没能查到信息,修改成正确的 API key 即可。{ error: "Invalid API key"}
需要两个两个业务 Handler,分别是客户端(ClientChatGroupHandler)和服务端(ServerChatGroupHandler)。客户端 Handler,主要是通过判断实体类型来做不同的业务操作,当然也可以使用 SimpleChannelInboundHandler 去进行 Handler 拆分。public class ClientChatGroupHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { //在链接就绪时登录 login(ctx.channel()); } //主要是“接受服务端”的响应信息 @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if(msg instanceof LoginResBean){ LoginResBean res=(LoginResBean) msg; System.out.println("登录响应:"+res.getMsg()); if(res.getStatus()==0){ //登录成功 //1.给通道绑定身份 ctx.channel().attr(AttributeKey.valueOf("userid")).set(res.getUserid()); //2.显示操作类型【请看下面】 deal(ctx.channel()); }else{ //登录失败,继续登录 login(ctx.channel()); } }else if(msg instanceof GroupCreateResBean){ GroupCreateResBean res=(GroupCreateResBean)msg; System.out.println("创建响应群组:"+res.getMsg()); }else if(msg instanceof GroupListResBean){ GroupListResBean res=(GroupListResBean)msg; System.out.println("查看群组列表:"+res.getLists()); }else if(msg instanceof GroupAddResBean){ GroupAddResBean res=(GroupAddResBean)msg; System.out.println("加入群组响应:"+res.getMsg()); }else if(msg instanceof GroupQuitResBean){ GroupQuitResBean res=(GroupQuitResBean)msg; System.out.println("退群群组响应:"+res.getMsg()); }else if(msg instanceof GroupMemberResBean){ GroupMemberResBean res=(GroupMemberResBean)msg; if(res.getCode()==1){ System.out.println("查看成员列表:"+res.getMsg()); }else{ System.out.println("查看成员列表:"+res.getLists()); } }else if(msg instanceof GroupSendMsgResBean){ GroupSendMsgResBean res=(GroupSendMsgResBean)msg; System.out.println("群发消息响应:"+res.getMsg()); }else if(msg instanceof GroupRecMsgBean){ GroupRecMsgBean res=(GroupRecMsgBean)msg; System.out.println("收到消息fromuserid="+ res.getFromuserid()+ ",msg="+res.getMsg()); } }}通过子线程循环向输出控制台输出操作类型的方法,以下方法目前都是空方法,下面将详细讲解。private void deal(final Channel channel){ final Scanner scanner=new Scanner(System.in); new Thread(new Runnable() { public void run() { while (true){ System.out.println("请选择类型:0创建群组,1查看群组,2加入群组,3退出群组,4查看群成员,5群发消息"); int type=scanner.nextInt(); switch (type){ case 0: createGroup(scanner,channel); break; case 1: listGroup(scanner,channel); break; case 2: addGroup(scanner,channel); break; case 3: quitGroup(scanner,channel); break; case 4: listMembers(scanner,channel); break; case 5: sendMsgToGroup(scanner,channel); break; default: System.out.println("输入的类型不存在!"); } } } }).start(); }
Hystrix 中的服务监控平台,就是对微服务项目进行监控的平台,包括服务运行的状态、服务有无宕机、服务异常信息监控等内容,为开发者和运维者提供了比较友好地界面支持,开发者和运维者可以直接通过观察服务平台界面,来判断具体微服务的状态信息,从而更好地对微服务进行控制。默认的 Hystrix 中间件已经为我们封装好了微服务监控平台,但是需要通过引入依赖的方式来使用它,接下来就让我们来看一下如何搭建该服务监控平台吧。
Zookeeper 服务初始化的过程主要是实例化服务对象,下面我们来介绍会实例化哪些对象ServerStats: ServerStats 类用于统计 ZooKeeper 服务运行过程中的状态信息,包括接受到客户端的请求次数,处理客户端请求的次数,向客户端发送请求的次数以及出现请求延迟情况的次数。也就是说这个类会对 Zookeeper 服务的运行状态和性能进行监控;FileTxnSnapLog: 我们用 FileTxnSnapLog 类来实现 Zookeeper 服务的数据存储,对数据进行持久化操作。数据存储的路径会读取 zoo.cfg 配置文件的 dataDir;ServerCnxnFactory: 我们可以通过 ServerCnxnFactory 类来指定 Zookeeper 的通信框架。在 Zookeeper 3.4.0 版本后,引入了第三方 Netty 等框架供我们选择使用。经过一系列的对象实例化,Zookeeper 还需要从快照数据和事务日志中恢复数据,才真正的完成启动,这时就可以使用 Zookeeper 客户端来进行连接发送请求了。
Flask 是一个 Python 实现的 Web 开发微框架,但是这个“微”并不代表着 Flask 功能比较简陋、有所欠缺。微框架中的 “微” 意味着:Flask 旨在保持核心简单而易于扩展;Flask 不会替用户做出太多决策,比如使用何种数据库;Flask 的选项(比如使用何种模板引擎) 通常有多个,用户很容易替换。默认情况下,Flask 不包含数据库抽象层、模板引擎、身份认证或其它任何已有多种库可以胜任的功能,如下图所示。然而,Flask 支持用扩展来给应用添加这些功能,应用程序可以很方便的集成这些扩展。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。
方法一:官网下载打开 GitHub 客户端 官网,直接点击下载即可。方法二:离线下载对于网络不好的同学,官网下载的速度往往会特别慢,或者干脆直接失败。就可以尝试使用 离线安装包 进行安装。
ZkClient 是一个开源的客户端,在 Zookeeper 原生 API 接口的基础上进行了包装,更便于开发人员使用。内部实现了Session超时重连,Watcher反复注册等功能。想要使用 ZkClient,我们需要搭建 Java 开发环境,这里我们使用 IntelliJ IDEA 为开发工具,JDK 我们使用了长期维护的版本 JDK-11.0.8 。接下来我们开始搭建 ZkClient 运行的环境。