Akka(8): 分布式运算:Remoting-远程查找式
Akka是一种消息驱动运算模式,它实现跨JVM程序运算的方式是通过能跨JVM的消息系统来调动分布在不同JVM上ActorSystem中的Actor进行运算,前题是Akka的地址系统可以支持跨JVM定位。Akka的消息系统最高境界可以实现所谓的Actor位置透明化,这样在Akka编程中就无须关注Actor具体在哪个JVM上运行,分布式Actor编程从方式上跟普通Actor编程就不会有什么区别了。Akka的Remoting是一种点对点的跨JVM消息通道,让一个JVM上ActorSystem中的某个Actor可以连接另一个JVM上ActorSystem中的另一个Actor。两个JVM上的ActorSystem之间只需具备TCP网络连接功能就可以实现Akka Remoting了。Akka-Remoting还没有实现完全的位置透明化,因为用户还必须在代码里或者配置文件里指明目标Actor的具体地址。
Akka-Remoting提供了两种Actor之间的沟通方法:
1、远程查找:通过路径Path查找在远程机上已经创建存在的Actor,获取ActorRef后进行沟通
2、远程创建:在远程机上直接创建Actor作为沟通对象
Akka-Remoting的主要应用应该是把一些任务部署到远程机上去运算。发起方(Local JVM)在这里面的主要作用是任务分配,有点像Akka-Router。我们可以用下面的例子来示范:模拟一个计算器,可以进行连续的加减乘除,保留累计结果。我们会把这个计算器部署到远程机上,然后从本机与之沟通分配运算任务及获取运算结果。这个计算器就是个简单的Actor:
import akka.actor._ object Calculator {
sealed trait MathOps
case class Num(dnum: Double) extends MathOps
case class Add(dnum: Double) extends MathOps
case class Sub(dnum: Double) extends MathOps
case class Mul(dnum: Double) extends MathOps
case class Div(dnum: Double) extends MathOps sealed trait CalcOps
case object Clear extends CalcOps
case object GetResult extends CalcOps } class Calcultor extends Actor {
import Calculator._
var result: Double = 0.0 //internal state override def receive: Receive = {
case Num(d) => result = d
case Add(d) => result += d
case Sub(d) => result -= d
case Mul(d) => result *= d
case Div(d) => result = result / d case Clear => result = 0.0
case GetResult =>
sender() ! s"Result of calculation is: $result"
} }
就是一个简单的Actor实现,跟Remoting没什么关系。
下面我们会在一个远程机上部署这个Calculator Actor。 先看看这个示范的项目结构:remoteLookup/build.sbt
lazy val commonSettings = seq (
name := "RemoteLookupDemo",
version := "1.0",
scalaVersion := "2.11.8",
libraryDependencies := Seq(
"com.typesafe.akka" %% "akka-actor" % "2.5.2",
"com.typesafe.akka" %% "akka-remote" % "2.5.2"
)
) lazy val local = (project in file("."))
.settings(commonSettings)
.settings(
name := "localSystem"
).aggregate(messages,remote).dependsOn(messages) lazy val messages = (project in file("messages"))
.settings(commonSettings)
.settings(
name := "commands"
) lazy val remote = (project in file("remote"))
.settings(commonSettings)
.settings(
name := "remoteSystem"
).aggregate(messages).dependsOn(messages)
在这里我们分了三个项目:local是主项目,messages和remote是分项目(subprojects)。messages里只有OpsMessages.scala一个源文件:
package remoteLookup.messages object Messages {
sealed trait MathOps
case class Num(dnum: Double) extends MathOps
case class Add(dnum: Double) extends MathOps
case class Sub(dnum: Double) extends MathOps
case class Mul(dnum: Double) extends MathOps
case class Div(dnum: Double) extends MathOps sealed trait CalcOps
case object Clear extends CalcOps
case object GetResult extends CalcOps }
我们看到:这个文件是把上面的Calculator支持的消息拆了出来。这是因为Calculator Actor会在另一个JVM remote上部署,而我们会从local JVM里向Calculator发送操作消息,所以Messages必须是local和remote共享的。这个要求我们通过dependOn(messages)实现了。现在Calculator是在remote项目里定义的:remote/Calculator.scala
package remoteLookup.remote import akka.actor._
import remoteLookup.messages.Messages._ object CalcProps {
def props = Props(new Calcultor)
} class Calcultor extends Actor with ActorLogging { var result: Double = 0.0 //internal state override def receive: Receive = {
case Num(d) => result = d
case Add(d) => result += d
case Sub(d) => result -= d
case Mul(d) => result *= d
case Div(d) =>
val _ = result.toInt / d.toInt //yield ArithmeticException
result /= d
case Clear => result = 0.0
case GetResult =>
sender() ! s"Result of calculation is: $result"
} override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
log.info(s"Restarting calculator: ${reason.getMessage}")
super.preRestart(reason, message)
}
}
由于ArithmeticException默认的处理策略SupervisorStrategy是Restart,一旦输入Div(0.0)时会重启将result清零。我们可以在remote上加一个Supervisor来把异常处理策略改为Resume。
下面我们先在remote项目本地对Calculator的功能进行测试:remote/CalculatorRunner.scala
package remoteLookup.remote
import akka.actor._
import akka.pattern._
import remoteLookup.messages.Messages._ import scala.concurrent.duration._ class SupervisorActor extends Actor {
def decider: PartialFunction[Throwable,SupervisorStrategy.Directive] = {
case _: ArithmeticException => SupervisorStrategy.Resume
} override def supervisorStrategy: SupervisorStrategy =
OneForOneStrategy(maxNrOfRetries = , withinTimeRange = seconds){
decider.orElse(SupervisorStrategy.defaultDecider)
} val calcActor = context.actorOf(CalcProps.props,"calculator") override def receive: Receive = {
case msg@ _ => calcActor.forward(msg)
} } object CalculatorRunner extends App { val remoteSystem = ActorSystem("remoteSystem")
val calcActor = remoteSystem.actorOf(Props[SupervisorActor],"supervisorActor") import remoteSystem.dispatcher calcActor ! Clear
calcActor ! Num(13.0)
calcActor ! Mul(1.5) implicit val timeout = akka.util.Timeout( second) ((calcActor ? GetResult).mapTo[String]) foreach println
scala.io.StdIn.readLine() calcActor ! Div(0.0)
calcActor ! Div(1.5)
calcActor ! Add(100.0)
((calcActor ? GetResult).mapTo[String]) foreach println
scala.io.StdIn.readLine() remoteSystem.terminate() }
测试运算得出以下结果:
Result of calculation is: 19.5 Result of calculation is: 113.0
[WARN] [// ::10.720] [remoteSystem-akka.actor.default-dispatcher-] [akka://remoteSystem/user/parentActor/calculator] / by zero
supervisorActor实现了它应有的功能。
下面进行远程查找示范:首先,remote需要把Calculator向外发布。这可以通过配置文件设置实现:remote/src/main/resources/application.conf
akka {
actor {
provider = remote
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]
netty.tcp {
hostname = "127.0.0.1"
port =
}
log-sent-messages = on
log-received-messages = on
}
}
上面这段的意思是:所有向外公开Actor的地址前缀为:akka.tcp://remoteSystem@127.0.0.1:2552/user/???
那么Calculator的完整地址path应该就是:akka.tcp://remoteSystem@127.0.0.1:2552/user/supervisorActor/calculator
Akka-Remoting提供了两种远程查找方式:actorSelection.resolveOne方法和Identify消息确认。无论如何,local都需要进行Remoting配置: local/src/main/resources/application.conf
akka {
actor {
provider = remote
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]
netty.tcp {
hostname = "127.0.0.1"
port =
}
}
}
port=0的意思是由系统自动选择任何可用的端口。现在我们完成了Remoting设置,也得到了在远程机上Calculator的具体地址,应该足够进行远程Actor沟通了。我们先用actorSelection.resolveOne示范。resolveOne源代码如下:
/**
* Resolve the [[ActorRef]] matching this selection.
* The result is returned as a Future that is completed with the [[ActorRef]]
* if such an actor exists. It is completed with failure [[ActorNotFound]] if
* no such actor exists or the identification didn't complete within the
* supplied `timeout`.
*
* Under the hood it talks to the actor to verify its existence and acquire its
* [[ActorRef]].
*/
def resolveOne()(implicit timeout: Timeout): Future[ActorRef] = {
implicit val ec = ExecutionContexts.sameThreadExecutionContext
val p = Promise[ActorRef]()
this.ask(Identify(None)) onComplete {
case Success(ActorIdentity(_, Some(ref))) ⇒ p.success(ref)
case _ ⇒ p.failure(ActorNotFound(this))
}
p.future
}
resolveOne返回Future[ActorRef],我们可以用Future的函数组件(combinator)来操作:localAccessDemo.scala
import akka.actor._
import akka.util.Timeout
import scala.concurrent.duration._
import akka.pattern._
import remoteLookup.messages.Messages._ object LocalSelectionDemo extends App { val localSystem = ActorSystem("localSystem")
import localSystem.dispatcher val path = "akka.tcp://remoteSystem@127.0.0.1:2552/user/supervisorActor/calculator" implicit val timeout = Timeout( seconds)
for (calcActor : ActorRef <- localSystem.actorSelection(path).resolveOne()) { calcActor ! Clear
calcActor ! Num(13.0)
calcActor ! Mul(1.5)
((calcActor ? GetResult).mapTo[String]) foreach println calcActor ! Div(0.0)
calcActor ! Div(1.5)
calcActor ! Add(100.0)
((calcActor ? GetResult).mapTo[String]) foreach println } scala.io.StdIn.readLine()
localSystem.terminate() }
因为resolveOne返回的是个Future[x],我们可以用for来对嵌在Future内的x进行操作。现在remoteSystem只需要构建Calculator待用就行了:remote/CalculatorRunner.scala
package remoteLookup.remote
import akka.actor._
import akka.pattern._
import remoteLookup.messages.Messages._ import scala.concurrent.duration._ class SupervisorActor extends Actor {
def decider: PartialFunction[Throwable,SupervisorStrategy.Directive] = {
case _: ArithmeticException => SupervisorStrategy.Resume
} override def supervisorStrategy: SupervisorStrategy =
OneForOneStrategy(maxNrOfRetries = , withinTimeRange = seconds){
decider.orElse(SupervisorStrategy.defaultDecider)
} val calcActor = context.actorOf(CalcProps.props,"calculator") override def receive: Receive = {
case msg@ _ => calcActor.forward(msg)
} } object CalculatorRunner extends App { val remoteSystem = ActorSystem("remoteSystem")
val calcActor = remoteSystem.actorOf(Props[SupervisorActor],"supervisorActor")
/*
import remoteSystem.dispatcher calcActor ! Clear
calcActor ! Num(13.0)
calcActor ! Mul(1.5) implicit val timeout = akka.util.Timeout(1 second) ((calcActor ? GetResult).mapTo[String]) foreach println
scala.io.StdIn.readLine() calcActor ! Div(0.0)
calcActor ! Div(1.5)
calcActor ! Add(100.0)
((calcActor ? GetResult).mapTo[String]) foreach println
*/
scala.io.StdIn.readLine()
remoteSystem.terminate() }
注意:注销的操作转移到了localSelectionDemo里。
先运行remote项目:
INFO] [// ::37.955] [main] [akka.remote.Remoting] Starting remoting
[INFO] [// ::38.091] [main] [akka.remote.Remoting] Remoting started; listening on addresses :[akka.tcp://remoteSystem@127.0.0.1:2552]
[INFO] [// ::38.092] [main] [akka.remote.Remoting] Remoting now listens on addresses: [akka.tcp://remoteSystem@127.0.0.1:2552]
remoteSystem开始监视配置的公开地址。
用sbt run 运行local:
Result of calculation is: 19.5
Result of calculation is: 113.0
结果正确。supervisorActor的SupervisorStrategy起到了应有的作用。
remote项目输出显示也能证明:
[INFO] [// ::37.955] [main] [akka.remote.Remoting] Starting remoting
[INFO] [// ::38.091] [main] [akka.remote.Remoting] Remoting started; listening on addresses :[akka.tcp://remoteSystem@127.0.0.1:2552]
[INFO] [// ::38.092] [main] [akka.remote.Remoting] Remoting now listens on addresses: [akka.tcp://remoteSystem@127.0.0.1:2552]
[WARN] [// ::06.330] [remoteSystem-akka.actor.default-dispatcher-] [akka://remoteSystem/user/supervisorActor/calculator] / by zero
[ERROR] [// ::34.176] [remoteSystem-akka.remote.default-remote-dispatcher-] [akka.tcp://remoteSystem@127.0.0.1:2552/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2FlocalSystem%40127.0.0.1%3A60601-0/endpointWriter] AssociationError [akka.tcp://remoteSystem@127.0.0.1:2552] <- [akka.tcp://localSystem@127.0.0.1:60601]: Error [Shut down address: akka.tcp://localSystem@127.0.0.1:60601] [
akka.remote.ShutDownAssociation: Shut down address: akka.tcp://localSystem@127.0.0.1:60601
Caused by: akka.remote.transport.Transport$InvalidAssociationException: The remote system terminated the association because it is shutting down.
]
下面我们试着用Identify消息确认方式来复演上述例子。Akka是如下这样定义有关Identify消息确认的:
/**
* A message all Actors will understand, that when processed will reply with
* [[akka.actor.ActorIdentity]] containing the `ActorRef`. The `messageId`
* is returned in the `ActorIdentity` message as `correlationId`.
*/
@SerialVersionUID(1L)
final case class Identify(messageId: Any) extends AutoReceivedMessage with NotInfluenceReceiveTimeout /**
* Reply to [[akka.actor.Identify]]. Contains
* `Some(ref)` with the `ActorRef` of the actor replying to the request or
* `None` if no actor matched the request.
* The `correlationId` is taken from the `messageId` in
* the `Identify` message.
*/
@SerialVersionUID(1L)
final case class ActorIdentity(correlationId: Any, ref: Option[ActorRef]) {
if (ref.isDefined && ref.get == null) {
throw new IllegalArgumentException("ActorIdentity created with ref = Some(null) is not allowed, " +
"this could happen when serializing with Scala 2.12 and deserializing with Scala 2.11 which is not supported.")
} /**
* Java API: `ActorRef` of the actor replying to the request or
* null if no actor matched the request.
*/
@deprecated("Use getActorRef instead", "2.5.0")
def getRef: ActorRef = ref.orNull /**
* Java API: `ActorRef` of the actor replying to the request or
* not defined if no actor matched the request.
*/
def getActorRef: Optional[ActorRef] = {
import scala.compat.java8.OptionConverters._
ref.asJava
}
}
如果拿上面的例子,我们就会向远程机上的Calculator地址发送Identify(path),而Calculator返回ActorIdentity消息,参数包括correlationId = path, ref = Calculator的ActorRef。 下面是使用示范代码:
object LocalIdentifyDemo extends App { class RemoteCalc extends Actor with ActorLogging { val path = "akka.tcp://remoteSystem@127.0.0.1:2552/user/supervisorActor/calculator" context.actorSelection(path) ! Identify(path) //send req for ActorRef import context.dispatcher
implicit val timeout = Timeout( seconds) override def receive: Receive = {
case ActorIdentity(p,someRef) if p.equals(path) =>
someRef foreach { calcActor => calcActor ! Clear
calcActor ! Num(13.0)
calcActor ! Mul(1.5)
((calcActor ? GetResult).mapTo[String]) foreach println calcActor ! Div(0.0)
calcActor ! Div(1.5)
calcActor ! Add(100.0)
((calcActor ? GetResult).mapTo[String]) foreach println }
} } val localSystem = ActorSystem("localSystem")
val localActor = localSystem.actorOf(Props[RemoteCalc],"localActor") scala.io.StdIn.readLine()
localSystem.terminate() }
Identify消息确认机制是一种Actor沟通模式,所以我们需要构建一个RemoteCalc Actor,把程序包嵌在这个Actor里面。当receive收到确认消息ActorIdentity后获取ActorRef运算程序。
查看运算结果,正确。
下面是这次示范的完整源代码:
build.sbt
lazy val commonSettings = seq (
name := "RemoteLookupDemo",
version := "1.0",
scalaVersion := "2.11.8",
libraryDependencies := Seq(
"com.typesafe.akka" %% "akka-actor" % "2.5.2",
"com.typesafe.akka" %% "akka-remote" % "2.5.2"
)
) lazy val local = (project in file("."))
.settings(commonSettings)
.settings(
name := "remoteLookupDemo"
).aggregate(messages,remote).dependsOn(messages) lazy val messages = (project in file("messages"))
.settings(commonSettings)
.settings(
name := "commands"
) lazy val remote = (project in file("remote"))
.settings(commonSettings)
.settings(
name := "remoteSystem"
).aggregate(messages).dependsOn(messages)
messages/OpsMessages.scala
package remoteLookup.messages object Messages {
sealed trait MathOps
case class Num(dnum: Double) extends MathOps
case class Add(dnum: Double) extends MathOps
case class Sub(dnum: Double) extends MathOps
case class Mul(dnum: Double) extends MathOps
case class Div(dnum: Double) extends MathOps sealed trait CalcOps
case object Clear extends CalcOps
case object GetResult extends CalcOps }
remote/src/main/resources/application.conf
akka {
actor {
provider = remote
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]
netty.tcp {
hostname = "127.0.0.1"
port =
}
log-sent-messages = on
log-received-messages = on
}
}
remote/Calculator.scala
package remoteLookup.remote import akka.actor._
import remoteLookup.messages.Messages._ object CalcProps {
def props = Props(new Calcultor)
} class Calcultor extends Actor with ActorLogging { var result: Double = 0.0 //internal state override def receive: Receive = {
case Num(d) => result = d
case Add(d) => result += d
case Sub(d) => result -= d
case Mul(d) => result *= d
case Div(d) =>
val _ = result.toInt / d.toInt //yield ArithmeticException
result /= d
case Clear => result = 0.0
case GetResult =>
sender() ! s"Result of calculation is: $result"
} override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
log.info(s"Restarting calculator: ${reason.getMessage}")
super.preRestart(reason, message)
}
}
remote/CalculatorRunner.scala
package remoteLookup.remote
import akka.actor._
import akka.pattern._
import remoteLookup.messages.Messages._ import scala.concurrent.duration._ class SupervisorActor extends Actor {
def decider: PartialFunction[Throwable,SupervisorStrategy.Directive] = {
case _: ArithmeticException => SupervisorStrategy.Resume
} override def supervisorStrategy: SupervisorStrategy =
OneForOneStrategy(maxNrOfRetries = , withinTimeRange = seconds){
decider.orElse(SupervisorStrategy.defaultDecider)
} val calcActor = context.actorOf(CalcProps.props,"calculator") override def receive: Receive = {
case msg@ _ => calcActor.forward(msg)
} } object CalculatorRunner extends App { val remoteSystem = ActorSystem("remoteSystem")
val calcActor = remoteSystem.actorOf(Props[SupervisorActor],"supervisorActor")
/*
import remoteSystem.dispatcher calcActor ! Clear
calcActor ! Num(13.0)
calcActor ! Mul(1.5) implicit val timeout = akka.util.Timeout(1 second) ((calcActor ? GetResult).mapTo[String]) foreach println
scala.io.StdIn.readLine() calcActor ! Div(0.0)
calcActor ! Div(1.5)
calcActor ! Add(100.0)
((calcActor ? GetResult).mapTo[String]) foreach println
*/
scala.io.StdIn.readLine()
remoteSystem.terminate() }
local/src/main/resources/application.conf
akka {
actor {
provider = remote
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]
netty.tcp {
hostname = "127.0.0.1"
port =
}
}
}
local/localAccessDemo.scala
import akka.actor._
import akka.util.Timeout
import scala.concurrent.duration._
import akka.pattern._
import remoteLookup.messages.Messages._ object LocalSelectionDemo extends App { val localSystem = ActorSystem("localSystem")
import localSystem.dispatcher val path = "akka.tcp://remoteSystem@127.0.0.1:2552/user/supervisorActor/calculator" implicit val timeout = Timeout( seconds)
for (calcActor : ActorRef <- localSystem.actorSelection(path).resolveOne()) { calcActor ! Clear
calcActor ! Num(13.0)
calcActor ! Mul(1.5)
((calcActor ? GetResult).mapTo[String]) foreach println calcActor ! Div(0.0)
calcActor ! Div(1.5)
calcActor ! Add(100.0)
((calcActor ? GetResult).mapTo[String]) foreach println } scala.io.StdIn.readLine()
localSystem.terminate() } object LocalIdentifyDemo extends App { class RemoteCalc extends Actor with ActorLogging { val path = "akka.tcp://remoteSystem@127.0.0.1:2552/user/supervisorActor/calculator" context.actorSelection(path) ! Identify(path) //semd req for ActorRef import context.dispatcher
implicit val timeout = Timeout( seconds) override def receive: Receive = {
case ActorIdentity(p,someRef) if p.equals(path) =>
someRef foreach { calcActor => calcActor ! Clear
calcActor ! Num(13.0)
calcActor ! Mul(1.5)
((calcActor ? GetResult).mapTo[String]) foreach println calcActor ! Div(0.0)
calcActor ! Div(1.5)
calcActor ! Add(100.0)
((calcActor ? GetResult).mapTo[String]) foreach println }
} } val localSystem = ActorSystem("localSystem")
val localActor = localSystem.actorOf(Props[RemoteCalc],"localActor") scala.io.StdIn.readLine()
localSystem.terminate() }
Akka(8): 分布式运算:Remoting-远程查找式的更多相关文章
- Akka(9): 分布式运算:Remoting-远程构建式
上篇我们讨论了Akka-Remoting.我们说Akka-Remoting是一种点对点的通讯方式,能使两个不同JVM上Akka-ActorSystem上的两个Actor之间可以相互沟通.Akka-Re ...
- Akka(10): 分布式运算:集群-Cluster
Akka-Cluster可以在一部物理机或一组网络连接的服务器上搭建部署.用Akka开发同一版本的分布式程序可以在任何硬件环境中运行,这样我们就可以确定以Akka分布式程序作为标准的编程方式了. 在上 ...
- Akka(13): 分布式运算:Cluster-Sharding-运算的集群分片
通过上篇关于Cluster-Singleton的介绍,我们了解了Akka为分布式程序提供的编程支持:基于消息驱动的运算模式特别适合分布式程序编程,我们不需要特别的努力,只需要按照普通的Actor编程方 ...
- alpakka-kafka(9)-kafka在分布式运算中的应用
kafka具备的分布式.高吞吐.高可用特性,以及所提供的各种消息消费模式可以保证在一个多节点集群环境里消息被消费的安全性:即防止每条消息遗漏处理或重复消费.特别是exactly-once消费策略:可以 ...
- 大数据学习day18----第三阶段spark01--------0.前言(分布式运算框架的核心思想,MR与Spark的比较,spark可以怎么运行,spark提交到spark集群的方式)1. spark(standalone模式)的安装 2. Spark各个角色的功能 3.SparkShell的使用,spark编程入门(wordcount案例)
0.前言 0.1 分布式运算框架的核心思想(此处以MR运行在yarn上为例) 提交job时,resourcemanager(图中写成了master)会根据数据的量以及工作的复杂度,解析工作量,从而 ...
- Akka(11): 分布式运算:集群-均衡负载
在上篇讨论里我们主要介绍了Akka-Cluster的基本原理.同时我们也确认了几个使用Akka-Cluster的重点:首先,Akka-Cluster集群构建与Actor编程没有直接的关联.集群构建是A ...
- Akka(12): 分布式运算:Cluster-Singleton-让运算在集群节点中自动转移
在很多应用场景中都会出现在系统中需要某类Actor的唯一实例(only instance).这个实例在集群环境中可能在任何一个节点上,但保证它是唯一的.Akka的Cluster-Singleton提供 ...
- 使用AKKA做分布式爬虫的思路
上周公司其它小组在讨论做分布式爬虫,我也思考了一下.提了一个方案,就是使用akka分布式rpc框架来做,自己写master和worker程序,client向master提交begin任务或者其它爬虫需 ...
- storm drpc分布式本地和远程调用模式讲解
一.drpc 的介绍 1.rpc RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议. 2.drpc drp ...
随机推荐
- cmd 命令行模式操作数据库 添加查询 修改 删除 ( 表 字段 数据)
一 查看数据库.表.数据字段.数据 1 首先配置环境变量 进入mysql 或者通过一键集成工具 打开mysql命令行 或者mysql 可视化工具 打开命令行 进入这样的界面 不同的机器操作不同 ...
- Installing MySQL on Microsoft Windows Using a noinstall Zip Archive
这两天在自己的windows上安装了一下mySql数据库,安装使用的是5.7.18版本的 noinstall Zip Archive安装包mysql-5.7.18-win32.zip.由于5.7版本相 ...
- C# Webclient 和 Httpclient如何通过iis authentication 身份验证。
前言: 该博客产生的背景是客户那边有部署网站的方法是iis windows authentication身份验证,而系统中使用Webclient来调用别的系统的方法.在此情况下,原本可以使用的功能,都 ...
- 四、I/O
九.什么是I/O: 9.1.在Windows程序中,基础的运行单位为线程,为每一个线程分配一个处理器,可以让系统执行多个操作, 9.2.当线程进行一个I/O操作时,会被挂起,从而影响性能,为了解决这类 ...
- Java 通过先序后序序列生成二叉树
题目 二叉树的前序以及后续序列,以空格间隔每个元素,重构二叉树,最后输出二叉树的三种遍历方式的序列以验证. 输入: 1 2 3 4 5 6 7 8 9 10 3 2 5 4 1 7 8 6 10 9 ...
- SpringAOP原理
原理 AOP(Aspect Oriented Programming),也就是面向方面编程的技术.AOP基于IoC基础,是对OOP的有益补充.AOP将应用系统分为两部分,核心业务逻辑(Core bus ...
- js实用方法记录-js动态加载css、js脚本文件
js实用方法记录-动态加载css/js 附送一个加载iframe,h5打开app代码 1. 动态加载js文件到head标签并执行回调 方法调用:dynamicLoadJs('http://www.yi ...
- 【2017-05-22】WebForm内置对象:Application和ViewState、Repeater的Command用法
一.内置对象 1.Application 存贮在服务器端,占用服务器内存生命周期:永久 所有人访问的都是这一个对象 传值:传的是object类型可以传对象. string s =TextBox1.Te ...
- Longest Palindromic Substring2015年6月20日
Given a , and there exists one unique longest palindromic substring. 自己的解决方案; public class Solution ...
- Hierarchy Viewer工具使用
目前,在eclipse的ADT Android插件中,还不能启动Hierachy Viewer,但可以从Android SDK工具包中,通过命令行的方式可以启动,具体方法为,到Android SDK下 ...