小幻 發表於 2019-5-2 21:02:00

基于.net core微服务(Consul、Ocelot、Docker、App.Metrics+InfluxDB+Grafana、Exceptionless、数据一致性、Jenkins)

<h2>1、微服务简介</h2>
<p>一种架构模式,提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(RESTful API)。每个服务都围绕着具体的业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。应尽量避免统一的、集中式的服管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。&nbsp;                    ——马丁•福勒</p>
<h3>1.1、.net core下的微服务构件</h3>
<ul>
<li>服务治理:Consul</li>
<li>API网关:Ocelot</li>
<li>作业调度:Quartz.NET,Hangfire</li>
<li>分布式日志:Exceptionless</li>
<li>ESB:Masstransit(RabbitMQ)</li>
<li>APM:Metrac.App,Buttfly</li>
</ul>
<h3>1.2、微架构</h3>
<p><img src="https://img2018.cnblogs.com/blog/991704/201903/991704-20190331113046831-1623413271.png" alt=""></p>
<h2>2、Consul</h2>
<p>http api官方文档地址:https://www.consul.io/api/index.html</p>
<p>Api本地url: http://localhost:8500/v1/agent/services</p>
<h3>2.1、Consul是什么</h3>
<p>是一个服务管理软件。支持多数据中心下,分布式高可用的,服务发现和配置共享。consul支持<strong>健康检查</strong>,<strong>允许存储键值对</strong>。一致性协议采用 Raft 算法,用来保证服务的高可用。成员管理和消息广播 采用GOSSIP协议,支持ACL访问控制。</p>
<p><strong>服务注册</strong>:一个服务将其位置信息在“中心注册节点”注册的过程。该服务一般会将它的主机IP地址以及端口号进行注册,有时也会有服务访问的认证信息,使用协议,版本号,以及关于环境的一些细节信息。</p>
<p><strong>服务发现</strong>:服务发现可以让一个应用或者组件发现其运行环境以及其它应用或组件的信息。用户配置一个服务发现工具就可以将实际容器跟运行配置分离开。常见配置信息包括:ip、端口号、名称等。</p>
<h3>2.2、述语</h3>
<ul>
<li>Agent<br>
<p style="margin: 0 0 0.0001pt 21.25pt; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial"><span style="font-size: 10.5pt; mso-bidi-font-size: 12.0pt; mso-ascii-font-family: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: 宋体; mso-hansi-theme-font: minor-fareast; mso-bidi-font-family: 'Times New Roman'; mso-bidi-theme-font: minor-bidi; mso-font-kerning: 1.0pt" lang="EN-US">Agent</span><span style="font-size: 10.5pt; mso-bidi-font-size: 12.0pt; mso-ascii-font-family: 宋体; mso-ascii-theme-font: minor-fareast; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: 宋体; mso-hansi-theme-font: minor-fareast; mso-bidi-font-family: 'Times New Roman'; mso-bidi-theme-font: minor-bidi; mso-font-kerning: 1.0pt">是长期运行在每个<span lang="EN-US">consul</span>集群成员节点上守护进程。通过命令<span lang="EN-US">consul agent</span>启动。<span lang="EN-US">Agent</span>有<span lang="EN-US">client</span>和<span lang="EN-US">server</span>两种模式。由于每个节点都必须运行<span lang="EN-US">agent</span>,所有节点要么是<span lang="EN-US">client</span>要么是<span lang="EN-US">server</span>。所有的<span lang="EN-US">Agent</span>都可以调用<span lang="EN-US">DNS</span>或<span lang="EN-US">HTTP API</span>,并负责检查和维护服务同步。</span></p>




































































</li>
<li>client<br>  运行client模式的Agent,将所有的RPCs转发到Server。Client是相对无状态的。Client唯一所做的是在后台参与LAN gossip pool。只消耗少量的资源,少量的网络带宽。</li>
<li>Server<br>  运行Server模式的Agent,参与Raft quorum,维护集群的状态,响应RPC查询,与其他数据中心交互WAN gossip,转发查询到Leader或远程数据中心。</li>
<li>Datacenter<br>  数据中心的定义似乎是显而易见的,有一些细节是必须考虑的。例如,在EC2,多个可用性区域是否被认为组成了单一的数据中心?我们定义数据中心是在同一个网络环境中——私有的,低延迟,高带宽。这不包括基于公共互联网环境,但是对于我们而言,在同一个EC2的多个可用性区域会被认为是一个的数据中心。</li>
<li>Consensus<br>  当本系列文档中,consensus,意味着leader election协议,以及事务的顺序。由于这些事务是基于一个有限状态机,consensus的定义意味着复制状态机的一致性。</li>
<li>Gossip <br>  consul是建立在Serf之上,提供了完成的Gossip协议,用于成员维护故障检测、事件广播。详细细节参见gossip documentation。这足以知道gossip是基于UDP协议实现随机的节点到节点的通信,主要是在UDP。</li>
<li>LAN Gossip<br>  指的是LAN gossip pool,包含位于同一个局域网或者数据中心的节点。</li>
<li>WAN Gossip<br>  指的是WAN gossip pool,只包含server节点,这些server主要分布在不同的数据中心或者通信是基于互联网或广域网的。</li>
<li>RPC<br>  远程过程调用。是允许client请求服务器的请求/响应机制。</li>




































































</ul>
<h3>2.3、部署结构图</h3>
<p><img src="https://img2018.cnblogs.com/blog/991704/201903/991704-20190331120434947-1335806623.png" alt=""></p>
<h3>2.4、命令</h3>
<ul>
<li>&nbsp;-advertise<br>通知展现地址用来改变我们给集群中的其他节点展现的地址,一般情况下-bind地址就是展现地址</li>
<li><strong>-bootstrap</strong><br>用来控制一个server是否在bootstrap模式,在一个datacenter中只能有一个server处于bootstrap模式,当一个server处于bootstrap模式时,可以自己选举为raft leader。&nbsp;&nbsp;</li>
<li>-bootstrap-expect<br>在一个datacenter中期望提供的server节点数目,当该值提供的时候,consul一直等到达到指定sever数目的时候才会引导整个集群,该标记不能和bootstrap公用</li>
<li><strong>-bind</strong><br>该地址用来在集群内部的通讯,集群内的所有节点到地址都必须是可达的,默认是0.0.0.0</li>
<li>-client<br>consul绑定在哪个client地址上,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1</li>
<li><strong>-config-file</strong><br>明确的指定要加载哪个配置文件</li>
<li><strong>-config-dir</strong><br>配置文件目录,里面所有以.json结尾的文件都会被加载</li>
<li><strong>-data-dir</strong><br>提供一个目录用来存放agent的状态,所有的agent允许都需要该目录,该目录必须是稳定的,系统重启后都继续存在</li>
<li>-datacenter<br>该标记控制agent允许的datacenter的名称,默认是dc1</li>
<li><strong>-encrypt</strong><br>指定secret key,使consul在通讯时进行加密,key可以通过consul keygen生成,同一个集群中的节点必须使用相同的key</li>
<li><strong>-join</strong><br>加入一个已经启动的agent的ip地址,可以多次指定多个agent的地址。如果consul不能加入任何指定的地址中,则agent会启动失败,默认agent启动时不会加入任何节点。</li>
<li>-retry-join<br>和join类似,但是允许你在第一次失败后进行尝试。</li>
<li>-retry-interval<br>两次join之间的时间间隔,默认是30s</li>
<li>-retry-max<br>尝试重复join的次数,默认是0,也就是无限次尝试</li>
<li>-log-level<br>consul agent启动后显示的日志信息级别。默认是info,可选:trace、debug、info、warn、err。</li>
<li>-node<br>节点在集群中的名称,在一个集群中必须是唯一的,默认是该节点的主机名</li>
<li>-protocol<br>consul使用的协议版本</li>
<li>-rejoin<br>使consul忽略先前的离开,在再次启动后仍旧尝试加入集群中。</li>
<li><strong>-server</strong><br>定义agent运行在server模式,每个集群至少有一个server,建议每个集群的server不要超过5个</li>
<li>-syslog<br>开启系统日志功能,只在linux/osx上生效</li>
<li>-ui-dir<br>提供存放web ui资源的路径,该目录必须是可读的</li>
<li>-pid-file<br>提供一个路径来存放pid文件,可以使用该文件进行SIGINT/SIGHUP(关闭/更新)agent</li>



































































</ul>
<h3>2.5、常用API</h3>
<p>consul的主要接口是RESTful HTTP API,该API可以用来增删查改nodes、services、checks、configguration。所有的endpoints主要分为以下类别:</p>
<ul>
<li><strong>kv</strong> - Key/Value存储</li>
<li><strong>agent</strong> - Agent控制</li>
<li><strong>catalog</strong> - 管理nodes和services</li>
<li><strong>health</strong> - 管理健康监测</li>
<li><strong>session</strong> - Session操作</li>
<li><strong>acl</strong> - ACL创建和管理</li>
<li><strong>event</strong> - 用户Events</li>
<li><strong>status</strong> - Consul系统状态</li>



































































</ul>
<p>&nbsp;</p>
<ul>
<li><strong>agent endpoints</strong>:agent endpoints用来和本地agent进行交互,一般用来服务注册和检查注册,支持以下接口<br>
<div class="cnblogs_code">
<pre>/v1/agent/<span style="color: rgba(0, 0, 0, 1)">checks : 返回本地agent注册的所有检查(包括配置文件和HTTP接口)
</span>/v1/agent/<span style="color: rgba(0, 0, 0, 1)">services : 返回本地agent注册的所有 服务
</span>/v1/agent/<span style="color: rgba(0, 0, 0, 1)">members : 返回agent在集群的gossip pool中看到的成员
</span>/v1/agent/<span style="color: rgba(0, 0, 0, 1)">self : 返回本地agent的配置和成员信息
</span>/v1/agent/join/&lt;address&gt;<span style="color: rgba(0, 0, 0, 1)"> : 触发本地agent加入node
</span>/v1/agent/force-leave/&lt;node&gt;&gt;<span style="color: rgba(0, 0, 0, 1)">: 强制删除node
</span>/v1/agent/check/<span style="color: rgba(0, 0, 0, 1)">register : 在本地agent增加一个检查项,使用PUT方法传输一个json格式的数据
</span>/v1/agent/check/deregister/&lt;checkID&gt;<span style="color: rgba(0, 0, 0, 1)"> : 注销一个本地agent的检查项
</span>/v1/agent/check/pass/&lt;checkID&gt;<span style="color: rgba(0, 0, 0, 1)"> : 设置一个本地检查项的状态为passing
</span>/v1/agent/check/warn/&lt;checkID&gt;<span style="color: rgba(0, 0, 0, 1)"> : 设置一个本地检查项的状态为warning
</span>/v1/agent/check/fail/&lt;checkID&gt;<span style="color: rgba(0, 0, 0, 1)"> : 设置一个本地检查项的状态为critical
</span>/v1/agent/service/<span style="color: rgba(0, 0, 0, 1)">register : 在本地agent增加一个新的服务项,使用PUT方法传输一个json格式的数据
</span>/v1/agent/service/deregister/&lt;serviceID&gt; : 注销一个本地agent的服务项</pre>
</div>
</li>
<li><strong>catalog endpoints</strong>:catalog endpoints用来注册/注销nodes、services、checks<br>
<div class="cnblogs_code">
<pre>/v1/catalog/register : Registers a <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> node, service, or check
</span>/v1/catalog/<span style="color: rgba(0, 0, 0, 1)">deregister : Deregisters a node, service, or check
</span>/v1/catalog/<span style="color: rgba(0, 0, 0, 1)">datacenters : Lists known datacenters
</span>/v1/catalog/nodes : Lists nodes <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> a given DC
</span>/v1/catalog/services : Lists services <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> a given DC
</span>/v1/catalog/service/&lt;service&gt; : Lists the nodes <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> a given service
</span>/v1/catalog/node/&lt;node&gt; : Lists the services provided by a node</pre>
</div>
</li>
<li><strong>health endpoints</strong>:health endpoints用来查询健康状况相关信息,该功能从catalog中单独分离出来<br>
<div class="cnblogs_code">
<pre>/v1/healt/node/&lt;node&gt;: 返回node所定义的检查,可用参数?dc=
/v1/health/checks/&lt;service&gt;: 返回和服务相关联的检查,可用参数?dc=
/v1/health/service/&lt;service&gt;<span style="color: rgba(0, 0, 0, 1)">: 返回给定datacenter中给定node中service
</span>/v1/health/state/&lt;state&gt;: 返回给定datacenter中指定状态的服务,state可以是<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">any</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">unknown</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">passing</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">warning</span><span style="color: rgba(128, 0, 0, 1)">"</span>, or <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">critical</span><span style="color: rgba(128, 0, 0, 1)">"</span>,可用参数?dc=</pre>
</div>
</li>
<li><strong>session endpoints</strong>:session endpoints用来create、update、destory、query sessions<br>
<div class="cnblogs_code">
<pre>/v1/session/create: Creates a <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> session
</span>/v1/session/destroy/&lt;session&gt;<span style="color: rgba(0, 0, 0, 1)">: Destroys a given session
</span>/v1/session/info/&lt;session&gt;<span style="color: rgba(0, 0, 0, 1)">: Queries a given session
</span>/v1/session/node/&lt;node&gt;<span style="color: rgba(0, 0, 0, 1)">: Lists sessions belonging to a node
</span>/v1/session/list: Lists all the active sessions</pre>
</div>
</li>
<li><strong>acl endpoints</strong>:acl endpoints用来create、update、destory、query acl<br>
<div class="cnblogs_code">
<pre>/v1/acl/create: Creates a <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> token with policy
</span>/v1/acl/<span style="color: rgba(0, 0, 0, 1)">update: Update the policy of a token
</span>/v1/acl/destroy/&lt;id&gt;<span style="color: rgba(0, 0, 0, 1)">: Destroys a given token
</span>/v1/acl/info/&lt;id&gt;<span style="color: rgba(0, 0, 0, 1)">: Queries the policy of a given token
</span>/v1/acl/clone/&lt;id&gt;: Creates a <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> token by cloning an existing token
</span>/v1/acl/list: Lists all the active tokens</pre>
</div>
</li>
<li><strong>event endpoints</strong>:event endpoints用来fire新的events、查询已有的events<br>
<div class="cnblogs_code">
<pre>/v1/<span style="color: rgba(0, 0, 255, 1)">event</span>/fire/&lt;name&gt;<span style="color: rgba(0, 0, 0, 1)">: 触发一个新的event,用户event需要name和其他可选的参数,使用PUT方法
</span>/v1/<span style="color: rgba(0, 0, 255, 1)">event</span>/list: 返回agent知道的events</pre>
</div>
</li>
<li><strong>status endpoints</strong>:status endpoints用来或者consul 集群的信息<br>
<div class="cnblogs_code">
<pre>/v1/status/<span style="color: rgba(0, 0, 0, 1)">leader : 返回当前集群的Raft leader
</span>/v1/status/peers : 返回当前集群中同事</pre>
</div>
</li>
</ul>
<h3>2.6、使用consul</h3>
<ul>
<li>启动<br>语法:<br>
<div class="cnblogs_code">
<pre>consul agent -server -datacenter=数据中心名称 -bootstrap -data-dir 数据存放路径 -config-file 配置文件路径 -ui-dir UI存放路径 -node=n1 -bind 本机IP</pre>
</div>
<p>注册成Windows服务</p>
<div class="cnblogs_code">
<pre>sc.exe create <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Consul</span><span style="color: rgba(128, 0, 0, 1)">"</span> binPath= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"><strong>E:\Consul\consule.exe</strong> agent -server -datacenter=数据中心名称 -bootstrap -data-dir 数据存放路径 -config-file 配置文件路径 -ui-dir UI存放路径 -node=n1 -bind 本机IP</span><span style="color: rgba(128, 0, 0, 1)">"</span></pre>
</div>
<p>示例:</p>
<div class="cnblogs_code">
<pre>consul agent -server -datacenter=dc1 -bootstrap -data-dir /tmp/consul -config-file ./conf -ui-dir ./dist -node=n1 -bind <span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span> </pre>
</div>
</li>
<li>查看集群成员<br>
<div class="cnblogs_code">
<pre>consul members</pre>
</div>
</li>
<li>把192.168.1.126加入集群<br>
<div class="cnblogs_code">
<pre>consul join <span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">1.126</span></pre>
</div>
</li>
<li>查看节点raft信息<br>
<div class="cnblogs_code">
<pre>consul <span style="color: rgba(0, 0, 255, 1)">operator</span> raft list-peers</pre>
</div>
</li>
</ul>
<h3>2.7、项目实例</h3>
<ul>
<li>项目准备<br>项目地址:https://github.com/786744873/HisMicroserviceSample<br>项目部署说明:分别部署&nbsp;<span class="cnblogs_code"><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">103.203</span></span>&nbsp;、&nbsp;<span class="cnblogs_code"><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">103.207</span></span>&nbsp;两台服务器<br><img src="https://img2018.cnblogs.com/blog/991704/201903/991704-20190331124446523-1276330235.png" alt=""></li>
<li>配置consul配置文件<br>文件结构:<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">│consul.exe

├─conf
│      service.json
│      watchs.json
│      xacl.json
│      
├─data
├─dist</span></pre>
</div>
<pre><span>service.json(服务发现配置):<br></span></pre>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">encrypt</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">7TnJPB4lKtjEcCWWjN6jSA==</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">加密秘钥</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">services</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [{
            </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BasicsService</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">服务id</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BasicsService</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">服务名称</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tags</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BasicsService</span><span style="color: rgba(128, 0, 0, 1)">"</span>],    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">服务标签</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">address</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><strong><span style="color: rgba(128, 0, 0, 1)">192.168.103.203</span></strong><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">服务地址</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">port</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">6801</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">端口</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">checks</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [{
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BasicsServiceCheck</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查id</span>
                <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BasicsServiceCheck</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查名称</span>
                <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://192.168.103.203:6801/health</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检车接口地址</span>
                <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">interval</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10s</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查周期</span>
                <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tls_skip_verify</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">跳过验证</span>
                <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">method</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">GET</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查请求方法</span>
                <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">timeout</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1s</span><span style="color: rgba(128, 0, 0, 1)">"</span>    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">请求超时时间</span>
<span style="color: rgba(0, 0, 0, 1)">            }]
      },
      {
            </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InvoicingService</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">服务id</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InvoicingService</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">服务名称</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tags</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InvoicingService</span><span style="color: rgba(128, 0, 0, 1)">"</span>],    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">服务标签</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">address</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><strong><span style="color: rgba(128, 0, 0, 1)">192.168.103.203</span></strong><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">服务地址</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">port</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">6802</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">端口</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">checks</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [{
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InvoicingServiceCheck</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查id</span>
                <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InvoicingServiceCheck</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查名称</span>
                <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://<strong>192.168.103.203</strong>:6802/health</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检车接口地址</span>
                <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">interval</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10s</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查周期</span>
                <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tls_skip_verify</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">跳过验证</span>
                <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">method</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">GET</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查请求方法</span>
                <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">timeout</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1s</span><span style="color: rgba(128, 0, 0, 1)">"</span>    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">请求超时时间</span>
<span style="color: rgba(0, 0, 0, 1)">            }]
      }
    ]
}</span></pre>
</div>
<pre><span>watchs.json(服务监控配置):<br></span></pre>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">watches</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [{
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">type</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">checks</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">监控触发类型</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">handler_type</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">异常通知类型</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">state</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">critical</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">监控触发状态</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http_handler_config</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
            </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">path</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://localhost:6801/notice</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">通知地址</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">method</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">POST</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">通知请求方式</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">timeout</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10s</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">通知超时时间</span>
            <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">header</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
                </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Authorization</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZ3N3IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiYWRtaW4iLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL2V4cGlyYXRpb24iOiIyMDIyLzEyLzMxIDEyOjM2OjEyIiwibmJmIjoxNTE0Njk0OTcyLCJleHAiOjE1MTQ3MzA5NzIsImlzcyI6ImdzdyIsImF1ZCI6ImdzdyJ9.jPu1yZ8jORN5QgCuPV50sYOKvX88GLSDiRX_0fpEzU4</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">]
            }    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">请求头</span>
<span style="color: rgba(0, 0, 0, 1)">      }
    }]
}</span></pre>
</div>
</li>
<li>分别启动&nbsp;<span class="cnblogs_code"><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">103.203</span></span>&nbsp;、&nbsp;<span class="cnblogs_code"><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">103.207</span></span>&nbsp;上的应用基础和进销存服务,然后再启动Consul,我们让&nbsp;<span class="cnblogs_code"><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">103.203</span></span>&nbsp;作为主Consul<br>第一台service(192.168.103.203):<br>
<div class="cnblogs_code">
<pre>consul agent -server -datacenter=dc1 <strong>-bootstrap</strong> -data-dir ./data -config-file ./conf -ui-dir ./dist -node=n1 -bind <strong><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">103.203</span></strong></pre>
</div>
<p>第二台service(192.168.103.207):</p>
<div class="cnblogs_code">
<pre>consul agent -server -datacenter=dc1 -data-dir ./data -config-file ./conf -ui-dir ./dist -node=n2 -bind <strong><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">103.207</span></strong></pre>
</div>
<p>然后可以通过访问192.168.103.203:8500进入UI页面查看信息</p>
</li>
<li>client<br>
<div class="cnblogs_code">
<pre>consul agent -datacenter=dc1 -data-dir /tmp/consul -node cn1</pre>
</div>
<p>Mac OX系统,进入consul所在目录执行:</p>
<div class="cnblogs_code">
<pre>Sudo scp consul /usr/local/bin/</pre>
</div>
</li>
</ul>
<h3>2.8、Consul DNS</h3>
<p>DnsAgent.exe作为DNS工具</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">[
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Pattern</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">^.*\\.consul$</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">NameServer</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">127.0.0.1:8600</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">QueryTimeout</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">1000</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CompressionMutation</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}
]</span></pre>
</div>
<p>访问地址:http://服务名称.service.consul</p>
<h2>3、Ocelot</h2>
<p>github地址:https://github.com/TomPallister/Ocelot</p>
<p>Ocelot的目标是使用.NET运行微服务/面向服务架构,我们需要一个统一的入口进入我们的服务,提供监控、鉴权、负载均衡等机制,也可以通过编写中间件的形式,来扩展Ocelot的功能。&nbsp; Ocelot是一堆特定顺序的中间件。</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201903/991704-20190331134909278-11044504.png" alt=""></p>
<h3>3.1、Ocelot使用</h3>
<ul>
<li>安装Ocelot<br>
<div class="cnblogs_code">
<pre>Install-Package Ocelot</pre>
</div>
</li>
<li>引入在Program.cs中加载配置文件<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> IWebHost BuildWebHost(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
{

    IWebHostBuilder builder </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> WebHostBuilder();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">注入WebHostBuilder</span>
    <span style="color: rgba(0, 0, 255, 1)">return</span> builder.ConfigureServices(service =&gt;<span style="color: rgba(0, 0, 0, 1)">
    {
      service.AddSingleton(builder);
    })
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">加载configuration配置文人年</span>
      .ConfigureAppConfiguration(conbuilder =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            conbuilder.AddJsonFile(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">appsettings.json</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            <strong>conbuilder.AddJsonFile(</strong></span><strong><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">configuration.json</span><span style="color: rgba(128, 0, 0, 1)">"</span></strong><span style="color: rgba(0, 0, 0, 1)"><strong>);</strong>
      })
      .UseContentRoot(Directory.GetCurrentDirectory())
      .UseKestrel()
      .UseUrls(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://*:6800</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
      .UseStartup</span>&lt;Startup&gt;<span style="color: rgba(0, 0, 0, 1)">()
      .Build();
}</span></pre>
</div>
</li>
<li>修改Startup.cs<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> ConfigureServices(IServiceCollection services)
{      
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">注入配置文件</span>
<span style="color: rgba(0, 0, 0, 1)">    services.AddOcelot(Configuration);
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加中间件</span>
<span style="color: rgba(0, 0, 0, 1)">    app.UseOcelot().Wait();
}</span></pre>
</div>
</li>
<li>创建配置文件(configuration.json)<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ReRoutes</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">路由配置</span>
<span style="color: rgba(0, 0, 0, 1)">    {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DownstreamPathTemplate</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/{url}</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">下游请求路由</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DownstreamScheme</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">下游请求方式,有http或https</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DownstreamHostAndPorts</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">下游请求的host和端口,为了配合负载均衡,可以配置多项</span>
<span style="color: rgba(0, 0, 0, 1)">      {
          </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Host</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">localhost</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
          </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Port</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">6801</span><span style="color: rgba(0, 0, 0, 1)">
      }
      ],
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UpstreamPathTemplate</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/basics/{url}</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">上游请求路由</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UpstreamHttpMethod</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Get</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Post</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Delete</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Put</span><span style="color: rgba(128, 0, 0, 1)">"</span> ],    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">上游请求谓词
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">"ServiceName": "BasicsService",    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Consul中注册服务的名称
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">"LoadBalancer": "RoundRobin",    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">负载均衡(可选)LeastConnection –请求空闲的UrlRoundRobin – 轮询请求NoLoadBalance – 无负载均衡
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">"UseServiceDiscovery": true,    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">是否启用负载均衡</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ReRouteIsCaseSensitive</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span>,    <span style="color: rgba(0, 128, 0, 1)">//
</span>      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">QoSOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span>: {    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">熔断设置(可选)</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ExceptionsAllowedBeforeBreaking</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">3</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">允许异常请求数</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DurationOfBreak</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">10</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">熔断时间,以秒为单位</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">TimeoutValue</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">5000</span>    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">请求超时数,以毫秒为单位</span>
<span style="color: rgba(0, 0, 0, 1)">      },
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">HttpHandlerOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span>: {    <span style="color: rgba(0, 128, 0, 1)">//
</span>      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AllowAutoRedirect</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span>,    <span style="color: rgba(0, 128, 0, 1)">//
</span>      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UseCookieContainer</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span>,    <span style="color: rgba(0, 128, 0, 1)">//
</span>      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UseTracing</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span>    <span style="color: rgba(0, 128, 0, 1)">//
</span><span style="color: rgba(0, 0, 0, 1)">      },
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AuthenticationOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span>: {    <span style="color: rgba(0, 128, 0, 1)">//
</span>      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AuthenticationProviderKey</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">""</span>,    <span style="color: rgba(0, 128, 0, 1)">//
</span>      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AllowedScopes</span><span style="color: rgba(128, 0, 0, 1)">"</span>: []    <span style="color: rgba(0, 128, 0, 1)">//
</span><span style="color: rgba(0, 0, 0, 1)">      },
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">RateLimitOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span>: {    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">限流设置(可选)</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ClientWhitelist</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">admin</span><span style="color: rgba(128, 0, 0, 1)">"</span> ],    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">白名单,不受限流控制的</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">EnableRateLimiting</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">true</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">是否启用限流</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Period</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1m</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">统计时间段:1s, 2m, 3h, 4d</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PeriodTimespan</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">15</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">间隔多少秒后可以重试</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Limit</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">100</span>    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设定时间段内允许的最大请求数</span>
<span style="color: rgba(0, 0, 0, 1)">      }
    },
    {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DownstreamPathTemplate</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/{url}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DownstreamScheme</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DownstreamHostAndPorts</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
      {
          </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Host</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">localhost</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
          </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Port</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">6802</span><span style="color: rgba(0, 0, 0, 1)">
      }
      ],
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UpstreamPathTemplate</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/invoicing/{url}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UpstreamHttpMethod</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Get</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Post</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Delete</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Put</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> ],
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">"ServiceName": "InvoicingService",
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">"LoadBalancer": "RoundRobin",
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">"UseServiceDiscovery": true,</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ReRouteIsCaseSensitive</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">QoSOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ExceptionsAllowedBeforeBreaking</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DurationOfBreak</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">TimeoutValue</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">5000</span><span style="color: rgba(0, 0, 0, 1)">
      },
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">HttpHandlerOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AllowAutoRedirect</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UseCookieContainer</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UseTracing</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
      },
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AuthenticationOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AuthenticationProviderKey</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AllowedScopes</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: []
      },
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">RateLimitOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ClientWhitelist</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">admin</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> ],
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">EnableRateLimiting</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Period</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1m</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PeriodTimespan</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">15</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Limit</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)">
      }
    },
    {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DownstreamPathTemplate</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/{url}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DownstreamScheme</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DownstreamHostAndPorts</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
      {
          </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Host</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">localhost</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
          </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Port</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">6806</span><span style="color: rgba(0, 0, 0, 1)">
      }
      ],
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UpstreamPathTemplate</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/authentication/{url}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UpstreamHttpMethod</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Get</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Post</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Delete</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Put</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> ],
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">"ServiceName": "AuthenticationService",
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">"LoadBalancer": "RoundRobin",
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">"UseServiceDiscovery": true,</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ReRouteIsCaseSensitive</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">QoSOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ExceptionsAllowedBeforeBreaking</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DurationOfBreak</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">TimeoutValue</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">5000</span><span style="color: rgba(0, 0, 0, 1)">
      },
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">HttpHandlerOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AllowAutoRedirect</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UseCookieContainer</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UseTracing</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
      },
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AuthenticationOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AuthenticationProviderKey</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">AllowedScopes</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: []
      },
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">RateLimitOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ClientWhitelist</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">admin</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> ],
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">EnableRateLimiting</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Period</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1m</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PeriodTimespan</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">15</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Limit</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)">
      }
    }

],
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">GlobalConfiguration</span><span style="color: rgba(128, 0, 0, 1)">"</span>: {    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">全局设置</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ServiceDiscoveryProvider</span><span style="color: rgba(128, 0, 0, 1)">"</span>: {<span style="color: rgba(0, 128, 0, 1)">//Consul服务地址,用于上方的服务发现</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Host</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">localhost</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Port</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">8500</span><span style="color: rgba(0, 0, 0, 1)">
    },
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">RateLimitOptions</span><span style="color: rgba(128, 0, 0, 1)">"</span>: {    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">全局限流设置(可选)</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ClientIdHeader</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">clientid</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">识别请求头,默认是 ClientId</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">QuotaExceededMessage</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">access is denied</span><span style="color: rgba(128, 0, 0, 1)">"</span>,    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">被限流后,当请求过载时返回的提示消息</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">HttpStatusCode</span><span style="color: rgba(128, 0, 0, 1)">"</span>:   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">600,当请求过载时返回的http状态码</span>
      <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DisableRateLimitHeaders</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span>    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">此值指定是否禁用X-Rate-Limit和Rety-After标头</span>
<span style="color: rgba(0, 0, 0, 1)">    }
}
}</span>&nbsp;</pre>
</div>
</li>
</ul>
<h2>4、Docker</h2>
<p>容器是一个打包了应用服务的环境。它是一个轻量级的虚拟机,每一个容器由一组特定的应用和必要的依赖库组成。</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407123203718-156144231.png" alt=""></p>
<h3>4.1、Docker-镜像常用命令&nbsp;</h3>
<div class="cnblogs_code">
<pre>docker images:查看本地镜像,docker images ubu*<span style="color: rgba(0, 0, 0, 1)">,通配符查看
docker inspect ubuntu:查看镜像详细信息
docker search aspnetcore:搜索docker hub上符合要求的镜像
docker pull microsoft</span>/<span style="color: rgba(0, 0, 0, 1)">aspnetcore:拉取镜像,在run时不用从docker hub拉取
docker rmi 镜像ID1 镜像ID2:删除镜像ID1和ID2,如果强制删除加</span>-f</pre>
</div>
<h3>4.2、Docker-容器常用命令</h3>
<div class="cnblogs_code">
<pre>docker create ubuntu:<span style="color: rgba(128, 0, 128, 1)">14.04</span><span style="color: rgba(0, 0, 0, 1)">:创建容器,处于停止状态
docker ps:查看运行的容器,加</span>-a查看所有容器。加-l查询出最后创建的容器,加-n=<span style="color: rgba(0, 0, 0, 1)">3查看最后创建的3个容器
docker start 容器名:运行已存在的容器
docker stop 容器名:停止容器
docker rm 容器名:删除容器,docker rm $(docker ps </span>-a -<span style="color: rgba(0, 0, 0, 1)">q)删除所有容器
docker run </span>-i -t --name ubuntu14 ubuntu:<span style="color: rgba(128, 0, 128, 1)">14.04</span> /bin/bash:运行一个ubuntu14.04的,带终端的容器,名字叫ubuntu14 ,-i用于打开容器的标准输入,-<span style="color: rgba(0, 0, 0, 1)">t让容器建立一个命令行终端
docker run </span>--name back_ubuntu14 -d ubuntu:<span style="color: rgba(128, 0, 128, 1)">14.04</span> /bin/sh -c <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">while true;do echo hello world;sleep 1;done</span><span style="color: rgba(128, 0, 0, 1)">"</span>:-<span style="color: rgba(0, 0, 0, 1)">d是后台开容器
docker attach 容器名:依附容器
docker logs </span>-f --tail=<span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">back_ubuntu14:查看最近的5条日志
docker top 容器名:查看容器进程
docker inspect 容器名:查看容器信息,查看具体子项docker inspect </span>--format=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">{{.NetworkSettings.IPAddress}}</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">back_ubuntu14
docker export 容器名 </span>&gt;<span style="color: rgba(0, 0, 0, 1)">容器存储名称.tar:导出容器
win powershell下docker export 容器ID </span>-<span style="color: rgba(0, 0, 0, 1)">o 名字.tar
docker import 容器存储名称.tar:导入镜像
docker commit </span>-m=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">abc</span><span style="color: rgba(128, 0, 0, 1)">"</span> --author=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">gsw</span><span style="color: rgba(128, 0, 0, 1)">"</span> 容器ID镜像名称:提交容器到本地镜像</pre>
</div>
<h3>4.4、Docker-Dockerfile</h3>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">FROM:指定待扩展的父级镜像。除了注释外,在文件开头必须是一个FROM指令,接下来的指令便在这个父级镜像的环境中运行,直到遇到下一个FROM指令。通过添加多个FROM指令,可以在同一个Dockerfile文件中创建多个镜像。
MAINTAINER:用来声明创建的镜像的作都信息。非必需
RUN:用来修改镜像命令,常用来安装库、程序 以及配置程序。一条RUN指令执行完毕后,会在当前镜像上创建一个新的镜像层,接下来的指令会在新的镜像上继续执行。
EXPOSE:用来指明容器内进程对外开放的端口,多个端口之间使用空格隔开。运行容器时,通过参数</span>-P(大写)即可将EXPOSE里所指定的端口映射到主机上国外的坠机端口,其队容器或主机就可以通过映射后的端口与此容器通信。同时,我们也可以通过-<span style="color: rgba(0, 0, 0, 1)">p(小写)参数将Dockerfile中EXPOSE中没有的端口设置成公开的。
ADD:向新镜像中添加文件,这个文件可以是一个主机文件,也可以是一个网络文件,也可以是一个文件夹。
VOLUME:在镜像里创建一个指定路径的挂载点,这个路径可以来自主机或都其他容器。多个容器可以通过同一个挂载点共享数据,即便其中一个容器已经停止,挂载点也仍然可以访问,只有当挂载点的容器引用全部消失时,挂载点才会自动删除。
WORKDIR:为接下来执行的指令指定一个新的工作目录,这个目录可以是绝对目录,也可以是相对目录。
ENV:设置容器运行的环境变量。在运行容器的时候,通过</span>-<span style="color: rgba(0, 0, 0, 1)">e参数可以修改这个环境变量值 ,也可以添加新的环境变量
CMD:用来设置启动容器时默认运行的命令。
ENTRYPOINT:与CMD类似,它也是用来指定容器启动时默认运行的命令。
USER:为容器的运行及接下来RUN、CMD、ENTRYPOINT等指令的运行指定用户或UID
ONBUILD:触发指令。构建镜像的时候,Docker的镜像构建器会将所有的ONBUILD指令指定的命令保存到镜像的元数据中,这些命令在当前镜像的构建的构建过程中并不会执行。只有新的镜像用用FRMO指令指定父镜像为这个镜像时,便会触发。</span></pre>
</div>
<h3>4.5、Docker生成asp.net core镜像和运行</h3>
<p>发布asp.net core项目,并在发布文件夹下创建Dockerfile文件,复制下面内容</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">#父镜像
FROM microsoft</span>/<span style="color: rgba(0, 0, 0, 1)">aspnetcore

#设置工作目录
WORKDIR </span>/<span style="color: rgba(0, 0, 0, 1)">app

#复制发布文件到</span>/<span style="color: rgba(0, 0, 0, 1)">app下
COPY . </span>/<span style="color: rgba(0, 0, 0, 1)">app

#设置端口
EXPOSE </span><span style="color: rgba(128, 0, 128, 1)">80</span><span style="color: rgba(0, 0, 0, 1)">

#使用dotnet XXXXXXXXX.dll来运行asp.net core项目,注意大小写
ENTRYPOINT [</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dotnet</span><span style="color: rgba(128, 0, 0, 1)">"</span>, “XXXXXXXXX.dll<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">]</span></pre>
</div>
<h4>4.6、Docker生成asp.net core镜像和运行</h4>
<div class="cnblogs_code">
<pre>docker&nbsp;build&nbsp;-<span style="color: rgba(0, 0, 0, 1)">t&nbsp;xxxxxxxxxxx:latest&nbsp;.
docker&nbsp;run&nbsp;</span>-it&nbsp;-p&nbsp;<span style="color: rgba(128, 0, 128, 1)">6801</span>:<span style="color: rgba(128, 0, 128, 1)">6801</span>&nbsp; xxxxxxxxxxx:latest</pre>
</div>
<p><strong>注意:</strong>docker内部web的端口, 上述命令中,第二个端口为docker内web的端口。</p>
<h2>5、App.Metrics+InfluxDB+Grafana</h2>
<p><strong>建议:建议在网关上进行监控,因为网关上监控可以监控所有</strong></p>
<p>App.Metrics:https://www.app-metrics.io</p>
<p>InfluxDB1.5.1-1:https://portal.influxdata.com</p>
<p>Grafana-5.0.4:https://grafana.com/get</p>
<h3>5.1、安装使用</h3>
<ul>
<li>下载 influxdb<br>https://portal.influxdata.com</li>
<li>下载&nbsp; Grafana<br>https://grafana.com/get</li>
<li>运行influxdb-版本号下的influxd.exe</li>
<li>运行grafana-版本号下,bin目录下grafana-server.exe</li>
<li>运行influxdb-版本号下的influx.exe,输入&nbsp;<span class="cnblogs_code">create database influxdbtest</span>&nbsp;创建数据库,同时&nbsp;<span class="cnblogs_code">create user <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">user1</span><span style="color: rgba(128, 0, 0, 1)">"</span> with password <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">123456</span><span style="color: rgba(128, 0, 0, 1)">'</span></span>&nbsp; 创建用户</li>
<li>配置Grafana,然后启动网关程序,登录localhost:3000查看监控信息,用户名密码是:admin</li>





























































</ul>
<h3>5.2、配置Grafana</h3>
<h4>5.2.1、配置数据源</h4>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407153452671-33241260.png" alt=""></p>
<h4>5.2.2、配置Dashboard</h4>
<p>我们采用模板导入模式,将项目引用&nbsp;<span class="cnblogs_code">App.Metrics</span>&nbsp;并访问&nbsp;<span class="cnblogs_code">App.Metrics</span>&nbsp;源地址:https://www.app-metrics.io/</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407154203826-1001444478.png" alt=""></p>
<p>获取到InfluxDB对应的仪表盘编号2125,然后输入使用该模板</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407154329933-1762067431.png" alt="" width="771" height="429"></p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407154429651-705168606.png" alt=""></p>
<p>导入成功后</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407154621267-575876501.png" alt="" width="787" height="383"></p>
<h3>5.3、App.Metrics监控数据采集</h3>
<ul>
<li>项目nuget引用<br>
<div class="cnblogs_code">
<pre>Install-<span style="color: rgba(0, 0, 0, 1)">Package App.Metrics
Install</span>-<span style="color: rgba(0, 0, 0, 1)">Package App.Metrics.AspNetCore.Endpoints
Install</span>-<span style="color: rgba(0, 0, 0, 1)">Package App.Metrics.AspNetCore.Reporting
Install</span>-<span style="color: rgba(0, 0, 0, 1)">Package App.Metrics.AspNetCore.Tracking
Install</span>-Package App.Metrics.Reporting.InfluxDB</pre>
</div>
</li>
<li>修改配置文件&nbsp;<span class="cnblogs_code">appsettings.json</span>&nbsp;<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InfluxDB</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">IsOpen</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">true</span>,<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">是否开启监控</span>
<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DataBaseName</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">influxdbtest</span><span style="color: rgba(128, 0, 0, 1)">"</span>,<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">数据库名称</span>
<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ConnectionString</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://localhost:8086</span><span style="color: rgba(128, 0, 0, 1)">"</span>,<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">数据库地址</span>
<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">username</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">user1</span><span style="color: rgba(128, 0, 0, 1)">"</span>,<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">用户名</span>
<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">password</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">123456</span><span style="color: rgba(128, 0, 0, 1)">"</span>,<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">密码</span>
<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">HIS</span><span style="color: rgba(128, 0, 0, 1)">"</span>,<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">自定义名字</span>
<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">env</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Ocelot</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">自定义环境</span>
}</pre>
</div>
</li>
<li>修改&nbsp;<span class="cnblogs_code">Startup.cs</span>&nbsp;<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> ConfigureServices(IServiceCollection services)
{
    ...
    </span><span style="color: rgba(0, 0, 255, 1)">#region</span> Metrics监控配置
    <span style="color: rgba(0, 0, 255, 1)">string</span> IsOpen = Configuration.GetSection(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InfluxDB:IsOpen</span><span style="color: rgba(128, 0, 0, 1)">"</span>).Value.ToLower();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">是否打开</span>
    <span style="color: rgba(0, 0, 255, 1)">if</span> (IsOpen == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">string</span> database = Configuration.GetSection(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InfluxDB</span><span style="color: rgba(128, 0, 0, 1)">"</span>)[<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DataBaseName</span><span style="color: rgba(128, 0, 0, 1)">"</span>];<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">数据库名称</span>
      <span style="color: rgba(0, 0, 255, 1)">string</span> InfluxDBConStr = Configuration.GetSection(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InfluxDB</span><span style="color: rgba(128, 0, 0, 1)">"</span>)[<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ConnectionString</span><span style="color: rgba(128, 0, 0, 1)">"</span>];<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">数据库地址</span>
      <span style="color: rgba(0, 0, 255, 1)">string</span> app = Configuration.GetSection(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InfluxDB</span><span style="color: rgba(128, 0, 0, 1)">"</span>)[<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app</span><span style="color: rgba(128, 0, 0, 1)">"</span>];<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">自定义名字</span>
      <span style="color: rgba(0, 0, 255, 1)">string</span> env = Configuration.GetSection(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InfluxDB</span><span style="color: rgba(128, 0, 0, 1)">"</span>)[<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">env</span><span style="color: rgba(128, 0, 0, 1)">"</span>];<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">自定义环境</span>
      <span style="color: rgba(0, 0, 255, 1)">string</span> username = Configuration.GetSection(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InfluxDB</span><span style="color: rgba(128, 0, 0, 1)">"</span>)[<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">username</span><span style="color: rgba(128, 0, 0, 1)">"</span>];<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">用户名</span>
      <span style="color: rgba(0, 0, 255, 1)">string</span> password = Configuration.GetSection(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InfluxDB</span><span style="color: rgba(128, 0, 0, 1)">"</span>)[<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">password</span><span style="color: rgba(128, 0, 0, 1)">"</span>];<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">密码</span>
      <span style="color: rgba(0, 0, 255, 1)">var</span> uri = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Uri(InfluxDBConStr);

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">配置metrics</span>
      <span style="color: rgba(0, 0, 255, 1)">var</span> metrics =<span style="color: rgba(0, 0, 0, 1)"> AppMetrics.CreateDefaultBuilder()
      .Configuration.Configure(
      options </span>=&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            options.AddAppTag(app);
            options.AddEnvTag(env);
      })
      .Report.ToInfluxDb(
      options </span>=&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            options.InfluxDb.BaseUri </span>=<span style="color: rgba(0, 0, 0, 1)"> uri;
            options.InfluxDb.Database </span>=<span style="color: rgba(0, 0, 0, 1)"> database;
            options.InfluxDb.UserName </span>=<span style="color: rgba(0, 0, 0, 1)"> username;
            options.InfluxDb.Password </span>=<span style="color: rgba(0, 0, 0, 1)"> password;
            options.HttpPolicy.BackoffPeriod </span>= TimeSpan.FromSeconds(<span style="color: rgba(128, 0, 128, 1)">30</span><span style="color: rgba(0, 0, 0, 1)">);
            options.HttpPolicy.FailuresBeforeBackoff </span>= <span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">;
            options.HttpPolicy.Timeout </span>= TimeSpan.FromSeconds(<span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">);
            options.FlushInterval </span>= TimeSpan.FromSeconds(<span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">);
      })
      .Build();

      services.AddMetrics(metrics);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">注入metrics</span>
      services.AddMetricsReportScheduler();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">报表</span>
      services.AddMetricsTrackingMiddleware();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">追踪</span>
      services.AddMetricsEndpoints();      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">终点    </span>
<span style="color: rgba(0, 0, 0, 1)">    }

    </span><span style="color: rgba(0, 0, 255, 1)">#endregion</span><span style="color: rgba(0, 0, 0, 1)">
    ...
}</span></pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    </span><span style="color: rgba(0, 0, 255, 1)">#region</span> 使用中间件Metrics
    <span style="color: rgba(0, 0, 255, 1)">string</span> IsOpen = Configuration.GetSection(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">InfluxDB</span><span style="color: rgba(128, 0, 0, 1)">"</span>)[<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">IsOpen</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">].ToLower();
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (IsOpen == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    {
      app.UseMetricsAllMiddleware();
      app.UseMetricsAllEndpoints();               
    }
    </span><span style="color: rgba(0, 0, 255, 1)">#endregion</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用中间件
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">await app.UseOcelot();</span>
}</pre>
</div>
<p>接下来就可以进行追踪了</p>
</li>
</ul>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407162117108-599766977.png" alt="" width="1369" height="673"></p>
<h3>5.4、APM-Grafana告警</h3>
<ul>
<li>打开grafana-版本号下,conf目录下的&nbsp;<span class="cnblogs_code">defaults.ini</span>&nbsp;,填写节点信息<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">
enabled </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
host </span>= smtp.<span style="color: rgba(128, 0, 128, 1)">163</span>.com:<span style="color: rgba(128, 0, 128, 1)">25</span><span style="color: rgba(0, 0, 0, 1)">
user </span>=<span style="color: rgba(0, 0, 0, 1)">ego_it
# If the password contains # or ; you have to wrap it with triple quotes. Ex </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">#password;</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
password </span>=<span style="color: rgba(0, 0, 0, 1)">******
cert_file </span>=<span style="color: rgba(0, 0, 0, 1)">
key_file </span>=<span style="color: rgba(0, 0, 0, 1)">
skip_verify </span>= <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
from_address </span>= ego_it@<span style="color: rgba(128, 0, 128, 1)">163</span><span style="color: rgba(0, 0, 0, 1)">.com
from_name </span>=<span style="color: rgba(0, 0, 0, 1)"> Grafana
ehlo_identity </span>=</pre>
</div>
</li>
<li>配置<br><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407165152088-1039821560.png" alt=""></li>
<li>添加报警触发条件<br><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407165601511-398956916.png" alt="" width="567" height="225">
<p>添加新的查询条件<br><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407170024405-2096792235.png" alt=""></p>
<p>创建alert<br><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407170126634-2039804567.png" alt=""></p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407171112878-137803132.png" alt="">&nbsp;</p>




















































</li>






















































</ul>
<h2>6、Exceptionless</h2>
<ul>
<li>在线方式<br>https://exceptionless.com/注册用户,新建Organizations和Project,并选项目类型。</li>
<li>离线方式<br>
<p>下载地址:https://github.com/exceptionless/Exceptionless/releases<br>      解压压缩包,运行Start.bat<br>      系统会自动下载elasticsearch和kibana<br><br></p>
<p>ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。</p>
<p>Kibana是一个开源的分析与可视化平台,设计出来用于和Elasticsearch一起使用的。你可以用kibana搜索、查看、交互存放在Elasticsearch索引里的数据,使用各种不同的图表、表格、地图等kibana能够很轻易地展示高级数据分析与可视化。</p>















































</li>















































</ul>
<h3>6.1、创建组织</h3>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407220454363-1596043274.png" alt=""></p>
<h3>6.2、创建项目</h3>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190407220533665-1150476865.png" alt=""></p>
<h3>6.3、集成Exceptionless 客户端</h3>
<div class="cnblogs_code">
<pre>Install-Package Exceptionless.AspNetCore</pre>
</div>
<p>通过 API 密钥执行&nbsp;&nbsp;<span class="cnblogs_code">app.UseExceptionless(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Qa3OzvEJC9FXo9SdwwFBv6bAkVbjWQKbV6hhtYEM</span><span style="color: rgba(128, 0, 0, 1)">"</span>)</span>&nbsp;&nbsp;方法</p>
<h3>6.4、示例代码</h3>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">#region</span> Exceptionless测试
<span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
{
    ExceptionlessClient.Default.SubmitLog(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">调试Exceptionless.Logging.LogLevel.Debu</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, Exceptionless.Logging.LogLevel.Debug);
    ExceptionlessClient.Default.SubmitLog(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">错误Exceptionless.Logging.LogLevel.Error</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, Exceptionless.Logging.LogLevel.Error);
    ExceptionlessClient.Default.SubmitLog(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">大错Exceptionless.Logging.LogLevel.fatal</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, Exceptionless.Logging.LogLevel.Fatal);
    ExceptionlessClient.Default.SubmitLog(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> Exceptionless.Logging.LogLevel.Info</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, Exceptionless.Logging.LogLevel.Info);
    ExceptionlessClient.Default.SubmitLog(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> Exceptionless.Logging.LogLevel.Off</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, Exceptionless.Logging.LogLevel.Off);
    ExceptionlessClient.Default.SubmitLog(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> Exceptionless.Logging.LogLevel.Other</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, Exceptionless.Logging.LogLevel.Other);
    ExceptionlessClient.Default.SubmitLog(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> Exceptionless.Logging.LogLevel.Trace</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, Exceptionless.Logging.LogLevel.Trace);
    ExceptionlessClient.Default.SubmitLog(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Exceptionless.Logging.LogLevel.Warn</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, Exceptionless.Logging.LogLevel.Warn);


    </span><span style="color: rgba(0, 0, 255, 1)">var</span> data = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Exceptionless.Models.DataDictionary();
    data.Add(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">data1key</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">data1value</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    ExceptionlessClient.Default.SubmitEvent(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Exceptionless.Models.Event {
      Count </span>= <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">,
      Date </span>=<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now,
      Data </span>= data, Geo = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">geo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      Message </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">message</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      ReferenceId </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">referencelId</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      Source </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">source</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      Tags </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Exceptionless.Models.TagSet() { <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tags</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> },
      Type </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">type</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      Value </span>= <span style="color: rgba(128, 0, 128, 1)">1.2m</span><span style="color: rgba(0, 0, 0, 1)"> });
    ExceptionlessClient.Default.SubmitFeatureUsage(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">feature</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    ExceptionlessClient.Default.SubmitNotFound(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">404 not found</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    ExceptionlessClient.Default.SubmitException(</span><span style="color: rgba(0, 0, 255, 1)">new</span> Exception(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">自定义异常</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">));

    </span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> DivideByZeroException(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">throw DivideByZeroException的异常:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now);
}
</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception exc)
{
    exc.ToExceptionless().Submit();
}
</span><span style="color: rgba(0, 0, 255, 1)">#endregion</span></pre>
</div>
<h3>6.5、本地部署</h3>
<p>本地部署官方wiki</p>
<p>下载Windows版本安装包,并进行解压,然后双击运行Start.bat即可</p>
<p>需要环境:</p>
<ul>
<li>.NET 4.6</li>
<li>Java 1.8+ (The JAVA_HOME environment variable must also be configured when using Windows.)</li>
<li>IIS Express 8+</li>
<li>PowerShell 3+</li>
</ul>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190408005959475-301678242.png" alt=""></p>
<h3>6.6、项目集成</h3>
<p>注意:本地化不能再使用&nbsp;<span class="cnblogs_code">app.UseExceptionless(apiKey: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tJxBWkCbgDLCMoKKqWII3Eyw4aJOsyOCgX26Yurm</span><span style="color: rgba(128, 0, 0, 1)">"</span>);</span>&nbsp;形式来上传日志数据,应采用另外的方式:配置文件方式</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Exceptionless</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ApiKey</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">tJxBWkCbgDLCMoKKqWII3Eyw4aJOsyOCgX26Yurm</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ServerUrl</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://localhost:50000</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DefaultData</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
},
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DefaultTags</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">xplat</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> ],
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Settings</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">FeatureXYZEnabled</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}
}</span></pre>
</div>
<p>然后修改&nbsp;<span class="cnblogs_code">Startup.cs</span>&nbsp;</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ...
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">app.UseExceptionless(apiKey: "tJxBWkCbgDLCMoKKqWII3Eyw4aJOsyOCgX26Yurm");
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">上方的方法本地化不适用</span>
<span style="color: rgba(0, 0, 0, 1)">    app.UseExceptionless(Configuration);
    ...
}</span></pre>
</div>
<p>搞定</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190408011048372-1289756004.png" alt=""></p>
<h3>6.7、查询语法</h3>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190408011210325-1643925285.png" alt=""></p>
<p>示例</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190408011304850-2139966505.png" alt=""></p>
<h3>6.8、常见问题</h3>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190408004614966-1563274955.png" alt=""></p>
<p>&nbsp;</p>
<p>Invoke-WebRequest : 请求被中止: 未能创建 SSL/TLS 安全通道。</p>
<p>elasticsearch-XXX”,因为该路径不存在。</p>
<p>解决方案:编辑Start-ElasticSearch.ps1,将所需的文件全部下载下来,然后解压进行拷贝,如下图,然后在双击运行Start.bat即可</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190408004748705-118175774.png" alt=""></p>
<p>帮助类:</p>
<div class="cnblogs_code"><img id="code_img_closed_1e657255-c762-4929-89f1-731f5be44d66" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_1e657255-c762-4929-89f1-731f5be44d66" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_1e657255-c762-4929-89f1-731f5be44d66" class="cnblogs_code_hide">
<pre><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(128, 128, 128, 1)">///</span>
<span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ExceptionLessLog
{
    </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> IsInit = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> ExceptionLessLog()
    {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">IsInit)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">#region</span> Exceptionless配置<span style="color: rgba(0, 0, 0, 1)">
            ExceptionlessClient.Default.Configuration.ApiKey </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">KwqNUJ5njrnOehQTSYY6yXXXXXXXXXXXXXXX</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
            ExceptionlessClient.Default.Configuration.ServerUrl </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://XXX.XXX.XXX.XXX:50000</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
            ExceptionlessClient.Default.Startup();
            </span><span style="color: rgba(0, 0, 255, 1)">#endregion</span><span style="color: rgba(0, 0, 0, 1)">
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">#region</span> 日志功能
    <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 跟踪
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Trace(<span style="color: rgba(0, 0, 255, 1)">string</span> message, <span style="color: rgba(0, 0, 255, 1)">params</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] tags)
    {
      ExceptionlessClient.Default.CreateLog(message, LogLevel.Trace).AddTags(tags).Submit();
    }

    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 调试
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Debug(<span style="color: rgba(0, 0, 255, 1)">string</span> message, <span style="color: rgba(0, 0, 255, 1)">params</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] tags)
    {
      ExceptionlessClient.Default.CreateLog(message, LogLevel.Debug).AddTags(tags).Submit();
    }

    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 信息
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Info(<span style="color: rgba(0, 0, 255, 1)">string</span> message, <span style="color: rgba(0, 0, 255, 1)">params</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] tags)
    {
      ExceptionlessClient.Default.CreateLog(message, LogLevel.Info).AddTags(tags).Submit();
    }

    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 警告
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Warn(<span style="color: rgba(0, 0, 255, 1)">string</span> message, <span style="color: rgba(0, 0, 255, 1)">params</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] tags)
    {
      ExceptionlessClient.Default.CreateLog(message, LogLevel.Warn).AddTags(tags).Submit();
    }

    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 错误
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Error(<span style="color: rgba(0, 0, 255, 1)">string</span> message, <span style="color: rgba(0, 0, 255, 1)">params</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] tags)
    {
      ExceptionlessClient.Default.CreateLog(message, LogLevel.Error).AddTags(tags).Submit();
    }
    </span><span style="color: rgba(0, 0, 255, 1)">#endregion</span>

    <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 异常捕获提交
    </span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="exception"&gt;&lt;/param&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="pluginContextData"&gt;&lt;/param&gt;</span>
    <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="client"&gt;&lt;/param&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Submit(<span style="color: rgba(0, 0, 255, 1)">this</span> Exception exception, ContextData pluginContextData = <span style="color: rgba(0, 0, 255, 1)">null</span>, ExceptionlessClient client = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
    {
      exception.ToExceptionless().Submit();
    }
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<h2>7、数据一致性</h2>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190408011528008-666282001.png" alt="" width="213" height="204"></p>
<ul>
<li>C:数据一致性(consistency):如果系统对一个写操作返回成功,那么之后的读请求都必须读到这个新数据;如果返回失败,那么所有读操作都不能读到这个数据,对调用者而言数据具有强一致性(strong consistency) (又叫原子性 atomic、线性一致性 linearizable consistency)</li>
<li>A:服务可用性(availability):所有读写请求在一定时间内得到响应,可终止、不会一直等待</li>
<li>P:分区容错性(partition-tolerance):在网络分区的情况下,被分隔的节点仍能正常对外服务</li>
</ul>
<h3>7.1、最终一致性</h3>
<ul>
<li>可用性,可靠性,</li>
<li>最终一致性:在微服务之间使用事件驱动通信和发布订阅系统实现最终一致性</li>
</ul>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190408012540894-5823289.png" alt="" width="694" height="243"></p>
<ul>
<li><strong>强一致性</strong>:当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。根据 CAP 理论,这种实现需要牺牲可用性。=&gt; 在传统单体式应用中,大部分都是强一致性的应用,想想我们写过多少工作单元模式的Code?</li>
<li><strong>弱一致性</strong>:系统并不保证续进程或者线程的访问都会返回最新的更新过的值。系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。</li>
<li><strong>最终一致性</strong>:弱一致性的特定形式。系统保证在没有后续更新的前提下,系统<strong>最终</strong>返回上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。</li>
<li>为保证可用性,互联网分布式架构中经常将<strong>强一致性需求</strong>转换成<strong>最终一致性</strong>的需求,并通过系统执行<strong>幂等性</strong>的保证,保证数据的<strong>最终一致性</strong>。</li>
</ul>
<p>  在微服务架构中,各个微服务之间通常会使用事件驱动通信和发布订阅系统实现最终一致性。</p>
<h3>7.2、最终一致性-补偿机制</h3>
<ul>
<li>Polly:实现重试,熔断机制</li>
<li>或提供后台任务调度实现补偿</li>
</ul>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190408012651593-790150137.png" alt="" width="728" height="216"></p>
<h3>7.3、幂等和防重</h3>
<ul>
<li>其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。</li>
<li>对重复删除或返回成功结果;防重可以在数据库级别处理也以以在MQ级别</li>
</ul>
<h3>7.4、MassTransit</h3>
<p>MassTransit&nbsp;是一个自由、开源、轻量级的消息总线,&nbsp;用于使用. NET&nbsp;框架创建分布式应用程序。MassTransit&nbsp;在现有消息传输上提供了一组广泛的功能,&nbsp;从而使开发人员能够友好地使用基于消息的会话模式异步连接服务。基于消息的通信是实现面向服务的体系结构的可靠和可扩展的方式。</p>
<p>  官网地址:http://masstransit-project.com/,GitHub地址:https://github.com/MassTransit/MassTransit&nbsp;(目前:1590Star,719Fork)</p>
<p>  类似的国外开源组件还有NServiceBus,没有用过,据说MassTransit比NServiceBus更加轻量级,并且在开发之初就选用了RabbitMQ作为消息传输组件,当然MassTransit还支持Azure Service Bus。类似的国内开源组件则有园友savorboard(杨晓东)的CAP</p>
<h3>7.5、最简单的发送/接收实例</h3>
<p>这里以MassTransit + RabbitMQ为例子,首先请确保安装了RabbitMQ,如果没有安装,可以阅读我的RabbitMQ在Windows环境下的安装与使用去把RabbitMQ先安装到你的电脑上。另外,RabbitMQ的背景知识也有一堆,有机会也还是要了解下Exchange,Channel、Queue等内容。</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190409000439976-316452160.png" alt="" width="476" height="264"></p>
<ul>
<li>准备两个控制台程序,一个为Sender(发送者),一个为Receiver(接收者),并分别通过NuGet安装MassTransit以及MassTransit.RabbitMQ<br>
<div class="cnblogs_code">
<pre>Install-<span style="color: rgba(0, 0, 0, 1)">Package MassTransit
Install</span>-Package MassTransit.RabbitMQ</pre>
</div>
</li>
<li>编写Sender<br>
<div class="cnblogs_code"><img id="code_img_closed_ae1a172b-c880-4e00-98c6-433c04dc5c54" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_ae1a172b-c880-4e00-98c6-433c04dc5c54" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_ae1a172b-c880-4e00-98c6-433c04dc5c54" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
    </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
    {
      Console.Title </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">客户端</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> bus = Bus.Factory.CreateUsingRabbitMq(cfg =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> host = cfg.Host(<span style="color: rgba(0, 0, 255, 1)">new</span> Uri(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/</span><span style="color: rgba(128, 0, 0, 1)">"</span>), hst =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                hst.Username(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                hst.Password(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            });

      });

      </span><span style="color: rgba(0, 0, 255, 1)">var</span> uri = <span style="color: rgba(0, 0, 255, 1)">new</span> Uri(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/wyt</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> mes =<span style="color: rgba(0, 0, 0, 1)"> Console.ReadLine();
      </span><span style="color: rgba(0, 0, 255, 1)">while</span> (<span style="color: rgba(0, 0, 255, 1)">null</span> !=<span style="color: rgba(0, 0, 0, 1)"> mes)
      {
            Task.Run(() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> SendCommand(bus, uri, mes)).Wait();
            mes </span>=<span style="color: rgba(0, 0, 0, 1)"> Console.ReadLine();

      }
      Console.ReadLine();

    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">async</span> <span style="color: rgba(0, 0, 255, 1)">void</span> SendCommand(IBusControl bus, Uri sendToUri, <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> mes)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> endPoint = <span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> bus.GetSendEndpoint(sendToUri);
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> command=<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Receiver.ABC()
      {
            Name </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
            Birthday </span>=<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now,
            Message </span>=<span style="color: rgba(0, 0, 0, 1)"> mes
      };

      </span><span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> endPoint.Send(command);

      Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">发送的实体 Name={command.Name},Birthday={command.Birthday},Message={command.Message}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    }
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
这里首先连接到我的RabbitMQ服务,然后向指定的Queue发送消息(这里是一个ABC类型的实例对象)。</li>
<li>编写Receiver<br>
<div class="cnblogs_code"><img id="code_img_closed_970994e6-3f89-427f-b080-5e2c033eb050" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_970994e6-3f89-427f-b080-5e2c033eb050" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_970994e6-3f89-427f-b080-5e2c033eb050" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
    </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
    {
      Console.Title </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">服务端</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建基于RabbitMq的bus</span>
      <span style="color: rgba(0, 0, 255, 1)">var</span> bus = Bus.Factory.CreateUsingRabbitMq(cfg =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> host = cfg.Host(<span style="color: rgba(0, 0, 255, 1)">new</span> Uri(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/</span><span style="color: rgba(128, 0, 0, 1)">"</span>), hst =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                hst.Username(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                hst.Password(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            });

            cfg.ReceiveEndpoint(host, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">wyt</span><span style="color: rgba(128, 0, 0, 1)">"</span>, e =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                e.Consumer</span>&lt;ConsumerABC&gt;<span style="color: rgba(0, 0, 0, 1)">();
                e.Consumer</span>&lt;ConsumerABC1&gt;<span style="color: rgba(0, 0, 0, 1)">();
            });
      });

      bus.Start();

      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">按任意键退出!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.ReadLine();
      bus.Stop();
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> ConsumerABC : IConsumer&lt;ABC&gt;<span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task Consume(ConsumeContext&lt;ABC&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">await</span> Console.Out.WriteLineAsync($<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">收到信息: {context.Message.Name},{context.Message.Birthday},{context.Message.Message}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> ConsumerABC1 : IConsumer&lt;ABC&gt;<span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task Consume(ConsumeContext&lt;ABC&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">await</span> Console.Out.WriteLineAsync($<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">收到信息1: {context.Message.Name},{context.Message.Birthday},{context.Message.Message}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    }

}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ABC
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> DateTime Birthday { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Message { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>对于Receiver,要做的事就只有两件:一是连接到RabbitMQ,二是告诉RabbitMQ我要接收哪个消息队列的什么类型的消息。</p>
</li>
<li>测试一下:<br><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190409004130486-692718907.png" alt=""></li>
































</ul>
<h3>7.6、一对一的发布/订阅实例(类似于RabbitMQ的工作模式)</h3>
<p>除了简单的发送/接收模式外,我们用的更多的是发布/订阅这种模式。</p>
<p><strong>注意:发布方如果发布时没有订阅方,发布的数据将会丢失</strong></p>
<ul>
<li>准备下图所示的类库和控制台项目,并对除Messages类库之外的其他项目安装MassTransit以及MassTransit.RabbitMQ。<br><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190409010300518-1134965662.png" alt=""></li>
<li>&nbsp;<span class="cnblogs_code">MEDemo_Entity</span>&nbsp;类库:准备需要传输的实体类信息<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> IEntity
{
   </span><span style="color: rgba(0, 0, 255, 1)">int</span> ID { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Entity:IEntity
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ID { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> DateTime Time { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyEntity:Entity
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> Age { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> YouEntity
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ID { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> DateTime Time { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> Age { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}</span></pre>
</div>
</li>
<li>&nbsp;<span class="cnblogs_code">MEDemo_Producer</span>&nbsp;:接收我的消息吧骚年们<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
{
    Console.Title </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">发布方</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">var</span> bus = Bus.Factory.CreateUsingRabbitMq(cfg =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
          </span><span style="color: rgba(0, 0, 255, 1)">var</span> host = cfg.Host(<span style="color: rgba(0, 0, 255, 1)">new</span> Uri(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost</span><span style="color: rgba(128, 0, 0, 1)">"</span>), hst =&gt;<span style="color: rgba(0, 0, 0, 1)">
          {
            hst.Username(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            hst.Password(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
          });

      });
    bus.Start();
    </span><span style="color: rgba(0, 0, 255, 1)">do</span><span style="color: rgba(0, 0, 0, 1)">
    {
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">请出请按q,否则请按其他键!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

      </span><span style="color: rgba(0, 0, 255, 1)">string</span> value =<span style="color: rgba(0, 0, 0, 1)"> Console.ReadLine();

      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (value.ToLower() == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">q</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
      }

      bus.<span style="color: rgba(255, 0, 0, 1)"><strong>Publish</strong></span>(</span><span style="color: rgba(0, 0, 255, 1)">new</span> Entity() { ID = <span style="color: rgba(128, 0, 128, 1)">1</span>, Name = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span>, Time =<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now });
    }
    </span><span style="color: rgba(0, 0, 255, 1)">while</span> (<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);

    bus.Stop();
}</span></pre>
</div>
<p>这里向RabbitMQ发布了两个不同类型的消息(Entity和IEntity)</p>
</li>
<li>&nbsp;<span class="cnblogs_code">MEDemo_ConsumerA</span>&nbsp;:我只接收Entity和IEntity类型的消息,其他的我不要<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
    </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
    {
      Console.Title</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">订阅方</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> bus = Bus.Factory.CreateUsingRabbitMq(cfg =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> host = cfg.Host(<span style="color: rgba(0, 0, 255, 1)">new</span> Uri(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/</span><span style="color: rgba(128, 0, 0, 1)">"</span>), hst =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                hst.Username(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                hst.Password(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            });
            cfg.ReceiveEndpoint(host, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">mewyt</span><span style="color: rgba(128, 0, 0, 1)">"</span>, e =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {                  
                e.Consumer</span>&lt;IEntityConsumer&gt;<span style="color: rgba(0, 0, 0, 1)">();
                e.Consumer</span>&lt;EntityConsumer&gt;<span style="color: rgba(0, 0, 0, 1)">();
                e.Consumer</span>&lt;MyEntityConsumer&gt;<span style="color: rgba(0, 0, 0, 1)">();
            });
            cfg.ReceiveEndpoint(host, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">mewyt1</span><span style="color: rgba(128, 0, 0, 1)">"</span>, e =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                e.Consumer</span>&lt;YouEntityConsumer&gt;<span style="color: rgba(0, 0, 0, 1)">();               
            });
      });

      bus.Start();      
      Console.ReadLine();
      bus.Stop();
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> IEntityConsumer : IConsumer&lt;IEntity&gt;<span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task Consume(ConsumeContext&lt;IEntity&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
    {         
      </span><span style="color: rgba(0, 0, 255, 1)">await</span> Console.Out.WriteLineAsync($<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">IEntityConsumer 类型 {context.Message.GetType()} {context.Message.ID}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

    }
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> EntityConsumer : IConsumer&lt;Entity&gt;<span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task Consume(ConsumeContext&lt;Entity&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">await</span> Console.Out.WriteLineAsync($<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">EntityConsumer类型 {context.Message.GetType()}{context.Message.ID} {context.Message.Name} {context.Message.Time}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    }
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MyEntityConsumer : IConsumer&lt;MyEntity&gt;<span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task Consume(ConsumeContext&lt;MyEntity&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">await</span> Console.Out.WriteLineAsync($<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">MyEntityConsumer 类型 {context.Message.GetType()}{context.Message.ID} {context.Message.Name} {context.Message.Time} {context.Message.Age}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> YouEntityConsumer : IConsumer&lt;YouEntity&gt;<span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task Consume(ConsumeContext&lt;YouEntity&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">await</span> Console.Out.WriteLineAsync($<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">YouEntityConsumer 类型 {context.Message.GetType()}{context.Message.ID} {context.Message.Name} {context.Message.Time} {context.Message.Age}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    }
}</span></pre>
</div>
</li>
<li>测试一下:启动两个MEDemo_ConsumerA,一个MEDemo_Producer<br><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190409011407842-1171273102.png" alt=""></li>































</ul>
<h3>7.6、一对多的发布/订阅实例(队列名不同即可)</h3>
<p><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190409013202053-1315548363.png" alt=""></p>
<ul>
<li>&nbsp;<span class="cnblogs_code">PSDemo_Entity</span>&nbsp;类库:准备需要传输的实体类信息<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> EntityA
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> DateTime Time { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> EntityB
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> DateTime Time { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> Age { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}</span></pre>
</div>
</li>
<li>&nbsp;<span class="cnblogs_code">PSDemo_Publisher</span>&nbsp;:发布消息<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
    </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
    {
       </span><span style="color: rgba(0, 0, 255, 1)">var</span> bus= Bus.Factory.CreateUsingRabbitMq(cfg =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> host = cfg.Host(<span style="color: rgba(0, 0, 255, 1)">new</span> Uri(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/</span><span style="color: rgba(128, 0, 0, 1)">"</span>), hst =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                hst.Username(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                hst.Password(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            });               
      });
      </span><span style="color: rgba(0, 0, 255, 1)">do</span><span style="color: rgba(0, 0, 0, 1)">
      {
            Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">请出请按q,否则请按其他键!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">string</span> value =<span style="color: rgba(0, 0, 0, 1)"> Console.ReadLine();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (value.ToLower() == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">q</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
            {
                </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
            }

            bus.Publish(</span><span style="color: rgba(0, 0, 255, 1)">new</span> PSDemo_Entity.<strong>EntityA</strong>() { Name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span>, Time =<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now });
            bus.Publish(</span><span style="color: rgba(0, 0, 255, 1)">new</span> PSDemo_Entity.<strong>EntityB</strong>() { Name = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">李四</span><span style="color: rgba(128, 0, 0, 1)">"</span>, Time = DateTime.Now,Age=<span style="color: rgba(128, 0, 128, 1)">22</span><span style="color: rgba(0, 0, 0, 1)"> });
      }
      </span><span style="color: rgba(0, 0, 255, 1)">while</span> (<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);      

      bus.Stop();
    }
}</span></pre>
</div>
</li>
<li>&nbsp;<span class="cnblogs_code">PSDemo_SubscriberA</span>&nbsp;:订阅EntityA和EntityB<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
    </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
    {
      Console.Title</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">订阅者A</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;

      </span><span style="color: rgba(0, 0, 255, 1)">var</span> bus= Bus.Factory.CreateUsingRabbitMq(cfg =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> host = cfg.Host(<span style="color: rgba(0, 0, 255, 1)">new</span> Uri(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/</span><span style="color: rgba(128, 0, 0, 1)">"</span>), hst =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                hst.Username(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                hst.Password(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            });

            cfg.ReceiveEndpoint(host, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(255, 0, 0, 1)">wytPSA</span><span style="color: rgba(128, 0, 0, 1)">"</span>, e =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                e.Consumer</span>&lt;<span style="color: rgba(255, 0, 0, 1)">ConsumerA</span>&gt;<span style="color: rgba(0, 0, 0, 1)">();
                e.Consumer</span>&lt;<span style="color: rgba(255, 0, 0, 1)">ConsumerB</span>&gt;<span style="color: rgba(0, 0, 0, 1)">();
            });
      });      

      bus.Start();      
      Console.ReadLine();
      bus.Stop();
    }
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> ConsumerA : IConsumer&lt;PSDemo_Entity.EntityA&gt;<span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task Consume(ConsumeContext&lt;PSDemo_Entity.EntityA&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">await</span> Console.Out.WriteLineAsync($<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">订阅者AConsumerA收到信息: {context.Message.Name}{context.Message.Time} 类型:{context.Message.GetType()}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    }
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> ConsumerB : IConsumer&lt;PSDemo_Entity.EntityB&gt;<span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task Consume(ConsumeContext&lt;PSDemo_Entity.EntityB&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">await</span> Console.Out.WriteLineAsync($<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">订阅者AConsumerB收到信息: {context.Message.Name}{context.Message.Time} 类型:{context.Message.GetType()}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    }
}</span></pre>
</div>
</li>
<li>&nbsp;<span class="cnblogs_code">PSDemo_SubscriberB</span>&nbsp;:订阅EntityA<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
    </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
    {
      Console.Title</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">订阅者B</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;

      </span><span style="color: rgba(0, 0, 255, 1)">var</span> bus = Bus.Factory.CreateUsingRabbitMq(cfg =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> host = cfg.Host(<span style="color: rgba(0, 0, 255, 1)">new</span> Uri(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/</span><span style="color: rgba(128, 0, 0, 1)">"</span>), hst =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                hst.Username(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                hst.Password(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            });

            cfg.ReceiveEndpoint(host, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(255, 0, 0, 1)">wytPSB</span><span style="color: rgba(128, 0, 0, 1)">"</span>, e =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                e.Consumer</span>&lt;<span style="color: rgba(255, 0, 0, 1)">ConsumerA</span>&gt;<span style="color: rgba(0, 0, 0, 1)">();
            });
      });

      bus.Start();   
      Console.ReadLine();
      bus.Stop();
    }
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> ConsumerA : IConsumer&lt;PSDemo_Entity.EntityA&gt;<span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task Consume(ConsumeContext&lt;PSDemo_Entity.EntityA&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">await</span> Console.Out.WriteLineAsync($<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">订阅者BConsumerA收到信息:{context.Message.Name}{context.Message.Time}类型:{context.Message.GetType()}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    }
}</span></pre>
</div>
</li>
<li>测试一下:启动PSDemo_SubscriberA和PSDemo_SubscriberB,一个PSDemo_Publisher<br><img src="https://img2018.cnblogs.com/blog/991704/201904/991704-20190409013808759-1749814257.png" alt="">
<p>&nbsp;</p>



























</li>





























</ul>
<h3>7.7、带返回状态消息的示例</h3>
<p>之前的例子都是发布之后,不管订阅者有没有收到以及收到后有没有处理成功(即有没有返回消息,类似于HTTP请求和响应),在MassTransit中提供了这样的一种模式,并且还可以结合GreenPipes的一些扩展方法实现重试、限流以及熔断机制。这一部分详见官方文档:http://masstransit-project.com/MassTransit/usage/request-response.html</p>
<ol>
<li>准备下图所示的三个项目:通过NuGet安装MassTransit以及MassTransit.RabbitMQ<br><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190501131654874-1966926968.png" alt=""></li>
<li>&nbsp;&nbsp;<span class="cnblogs_code">RRDemo_Entity.Entity</span>&nbsp;:准备请求和响应的消息传输类型<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> IRequestEntity
{
    </span><span style="color: rgba(0, 0, 255, 1)">int</span> ID { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> RequestEntity : IRequestEntity
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ID { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> IResponseEntity
{
    </span><span style="color: rgba(0, 0, 255, 1)">int</span> ID { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }

    </span><span style="color: rgba(0, 0, 255, 1)">int</span> RequestID { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ResponseEntity : IResponseEntity
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ID { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> RequestID { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
}</span></pre>
</div>
</li>
<li>&nbsp;<span class="cnblogs_code">RRDemo_Server.Program</span>&nbsp;请求接收端<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
    </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
    {
      Console.Title </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">应答方</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> bus = Bus.Factory.CreateUsingRabbitMq(cfg =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> host = cfg.Host(<span style="color: rgba(0, 0, 255, 1)">new</span> Uri(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/</span><span style="color: rgba(128, 0, 0, 1)">"</span>), hst =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                hst.Username(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                hst.Password(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            });
            cfg.ReceiveEndpoint(host, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">request_response_wyt</span><span style="color: rgba(128, 0, 0, 1)">"</span>, e =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                e.Consumer</span>&lt;RequestConsumer&gt;<span style="color: rgba(0, 0, 0, 1)">();
            });
      });
      bus.Start();   
      Console.ReadLine();
      bus.Stop();
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> RequestConsumer : IConsumer&lt;IRequestEntity&gt;<span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task Consume(ConsumeContext&lt;IRequestEntity&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
    {
      Console.ForegroundColor </span>=<span style="color: rgba(0, 0, 0, 1)"> ConsoleColor.Red;
      </span><span style="color: rgba(0, 0, 255, 1)">await</span> Console.Out.WriteLineAsync($<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">收到请求id={context.Message.ID} name={context.Message.Name}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.ResetColor();
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> response = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ResponseEntity
      {
            ID </span>= <span style="color: rgba(128, 0, 128, 1)">22</span><span style="color: rgba(0, 0, 0, 1)">,
            Name </span>= $<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">李四</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
            RequestID </span>=<span style="color: rgba(0, 0, 0, 1)"> context.Message.ID
      };
      Console.ForegroundColor </span>=<span style="color: rgba(0, 0, 0, 1)"> ConsoleColor.Green;
      Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">应答ID={response.ID},Name={response.Name},RequestID={response.RequestID}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.ResetColor();
      context.Respond(response);
    }
}</span></pre>
</div>
</li>
<li>&nbsp;<span class="cnblogs_code">RRDemo_Client.Program</span>&nbsp;请求发送端<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
{
    Console.Title </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">请求方</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">var</span> bus = Bus.Factory.CreateUsingRabbitMq(cfg =&gt;<span style="color: rgba(0, 0, 0, 1)">
    {
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> host = cfg.Host(<span style="color: rgba(0, 0, 255, 1)">new</span> Uri(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/</span><span style="color: rgba(128, 0, 0, 1)">"</span>), hst =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            hst.Username(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            hst.Password(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      });
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">重试</span>
      cfg.UseRetry(ret =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            ret.Interval(</span><span style="color: rgba(128, 0, 128, 1)">3</span>, <span style="color: rgba(128, 0, 128, 1)">10</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 消费失败后重试3次,每次间隔10s</span>
<span style="color: rgba(0, 0, 0, 1)">      });
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">限流</span>
      cfg.UseRateLimit(<span style="color: rgba(128, 0, 128, 1)">1000</span>, TimeSpan.FromSeconds(<span style="color: rgba(128, 0, 128, 1)">100</span>));<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1分钟以内最多1000次调用访问
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">熔断</span>
      cfg.UseCircuitBreaker(cb =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            cb.TrackingPeriod </span>= TimeSpan.FromSeconds(<span style="color: rgba(128, 0, 128, 1)">60</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">1分钟</span>
            cb.TripThreshold = <span style="color: rgba(128, 0, 128, 1)">15</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当失败的比例至少达到15%才会启动熔断</span>
            cb.ActiveThreshold = <span style="color: rgba(128, 0, 128, 1)">10</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当失败次数至少达到10次才会启动熔断</span>
            cb.ResetInterval = TimeSpan.FromMinutes(<span style="color: rgba(128, 0, 128, 1)">5</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 当在1分钟内消费失败率达到15%或调用了10次还是失败时,暂停5分钟的服务访问</span>
<span style="color: rgba(0, 0, 0, 1)">
      });
    });
    bus.Start();

    </span><span style="color: rgba(0, 0, 255, 1)">var</span> serviceAddress = <span style="color: rgba(0, 0, 255, 1)">new</span> Uri($<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/request_response_wyt</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">var</span> client = bus.CreateRequestClient&lt;IRequestEntity, IResponseEntity&gt;(serviceAddress, TimeSpan.FromHours(<span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">));
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建请求客户端,10H之内木有回馈则认为是超时(Timeout)</span>

    <span style="color: rgba(0, 0, 255, 1)">while</span> (<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">)
    {
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">请出请按q,否则请按其他键!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">string</span> value =<span style="color: rgba(0, 0, 0, 1)"> Console.ReadLine();
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (value.ToLower() == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">q</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
      }

      Task.Run(</span><span style="color: rgba(0, 0, 255, 1)">async</span> () =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> request = <span style="color: rgba(0, 0, 255, 1)">new</span> RequestEntity() { ID = <span style="color: rgba(128, 0, 128, 1)">1</span>, Name = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> };
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> response = <span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> client.Request(request);

            Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">请求ID={request.ID},Name={request.Name}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">应签ID={response.ID},Name={response.Name},RequestID={response.RequestID}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      }).Wait();
    }

}</span></pre>
</div>
</li>
<li>效果展示<br><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190501133231897-1780492713.png" alt="">
<p><strong>注意</strong>:这里的请求方关闭后应答方则无法将应答再回复给请求方,会丢失</p>























</li>
























</ol>
<h3>7.8、带Observer模式的发布/订阅示例</h3>
<p>在某些场景中,我们需要针对一个消息进行类似于AoP(面向切面编程)或者监控的操作,比如在发送消息之前和结束后记日志等操作,我们可以借助MassTransit中的Observer模式来实现。(在MassTransit的消息接收中,可以通过两种模式来实现:一种是基于实现IConsumer接口,另一种就是基于实现IObserver接口)关于这一部分,详见官方文档:http://masstransit-project.com/MassTransit/usage/observers.html</p>
<ul>
<li>准备以下图所示的项目:<br><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502121321435-190168354.png" alt=""></li>
<li>&nbsp;<span class="cnblogs_code">ObserverSubscriber</span>&nbsp;<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
    </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
    {
      Console.Title </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">订阅方</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> bus = Bus.Factory.CreateUsingRabbitMq(cfg =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> host = cfg.Host(<span style="color: rgba(0, 0, 255, 1)">new</span> Uri(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/</span><span style="color: rgba(128, 0, 0, 1)">"</span>), hst =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                hst.Username(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                hst.Password(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            });
            cfg.ReceiveEndpoint(host, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ObserverTest</span><span style="color: rgba(128, 0, 0, 1)">"</span>, e =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                e.Consumer</span>&lt;EntityConsumer&gt;<span style="color: rgba(0, 0, 0, 1)">();
            });
      });
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> observer = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ReceiveObserver();
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> handle =<span style="color: rgba(0, 0, 0, 1)"> bus.ConnectReceiveObserver(observer);
      bus.Start();
      Console.ReadLine();
      bus.Stop();
    }
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ReceiveObserver : IReceiveObserver
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Task PreReceive(ReceiveContext context)
    {

      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">------------------PreReceive--------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine(Encoding.Default.GetString(context.GetBody()));
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--------------------------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Task PostReceive(ReceiveContext context)
    {
   
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">-----------------PostReceive---------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine(Encoding.Default.GetString(context.GetBody()));
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--------------------------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> Task PostConsume&lt;T&gt;(ConsumeContext&lt;T&gt; context, TimeSpan duration, <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> consumerType)
      </span><span style="color: rgba(0, 0, 255, 1)">where</span> T : <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">
    {
   
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">------------------PostConsume--------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ID={ (context.Message as Entity).ID},Name={(context.Message as Entity).Name},Time={(context.Message as Entity).Time}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--------------------------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> Task ConsumeFault&lt;T&gt;(ConsumeContext&lt;T&gt; context, TimeSpan elapsed, <span style="color: rgba(0, 0, 255, 1)">string</span> consumerType, Exception exception) <span style="color: rgba(0, 0, 255, 1)">where</span> T : <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">
    {
   
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">-----------------ConsumeFault---------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ID={ (context.Message as Entity).ID},Name={(context.Message as Entity).Name},Time={(context.Message as Entity).Time}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--------------------------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Task ReceiveFault(ReceiveContext context, Exception exception)
    {            
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">----------------ReceiveFault----------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine(Encoding.Default.GetString(context.GetBody()));
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--------------------------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
    }
}


</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> EntityConsumer : IConsumer&lt;Entity&gt;<span style="color: rgba(0, 0, 0, 1)">
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task Consume(ConsumeContext&lt;Entity&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">await</span> Console.Out.WriteLineAsync($<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">IEntityConsumer 类型 {context.Message.GetType()} {context.Message.ID} {context.Message.Age} {context.Message.Name} {context.Message.Time}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

    }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Entity
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ID { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> Age { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> Name { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> DateTime Time { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }

}</span></pre>
</div>
</li>
<li>&nbsp;<span class="cnblogs_code">ObserverPublish</span>&nbsp;<br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
{
    </span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
    {
      Console.Title </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">发布方</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;

      </span><span style="color: rgba(0, 0, 255, 1)">var</span> bus = Bus.Factory.CreateUsingRabbitMq(cfg =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> host = cfg.Host(<span style="color: rgba(0, 0, 255, 1)">new</span> Uri(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost</span><span style="color: rgba(128, 0, 0, 1)">"</span>), hst =&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                hst.Username(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
                hst.Password(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">guest</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            });

      });
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> observer = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SendObserver();
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> handle =<span style="color: rgba(0, 0, 0, 1)"> bus.ConnectSendObserver(observer);

      </span><span style="color: rgba(0, 0, 255, 1)">var</span> observer1 = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> PublishObserver();
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> handle1 =<span style="color: rgba(0, 0, 0, 1)"> bus.ConnectPublishObserver(observer1);
      bus.Start();
      </span><span style="color: rgba(0, 0, 255, 1)">do</span><span style="color: rgba(0, 0, 0, 1)">
      {
            Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">请出请按q,否则请按其他键!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

            </span><span style="color: rgba(0, 0, 255, 1)">string</span> value =<span style="color: rgba(0, 0, 0, 1)"> Console.ReadLine();

            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (value.ToLower() == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">q</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
            {
                </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
            }

            bus.Publish(</span><span style="color: rgba(0, 0, 255, 1)">new</span> Entity() { ID = <span style="color: rgba(128, 0, 128, 1)">1</span>, Age = <span style="color: rgba(128, 0, 128, 1)">10</span>, Name = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span>, Time =<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now });
      }
      </span><span style="color: rgba(0, 0, 255, 1)">while</span> (<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);

      bus.Stop();
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> PublishObserver : IPublishObserver
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> Task PrePublish&lt;T&gt;(PublishContext&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
      </span><span style="color: rgba(0, 0, 255, 1)">where</span> T : <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">
    {
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">------------------PrePublish--------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ID={ (context.Message as Entity).ID},Name={(context.Message as Entity).Name},Time={(context.Message as Entity).Time}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--------------------------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> Task PostPublish&lt;T&gt;(PublishContext&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
      </span><span style="color: rgba(0, 0, 255, 1)">where</span> T : <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">
    {
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">------------------PostPublish--------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ID={ (context.Message as Entity).ID},Name={(context.Message as Entity).Name},Time={(context.Message as Entity).Time}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--------------------------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> Task PublishFault&lt;T&gt;(PublishContext&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)"> context, Exception exception)
      </span><span style="color: rgba(0, 0, 255, 1)">where</span> T : <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">
    {
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">------------------PublishFault--------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ID={ (context.Message as Entity).ID},Name={(context.Message as Entity).Name},Time={(context.Message as Entity).Time}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--------------------------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SendObserver : ISendObserver
{
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> Task PreSend&lt;T&gt;(SendContext&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
      </span><span style="color: rgba(0, 0, 255, 1)">where</span> T : <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">
    {
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">------------------PreSend--------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ID={ (context.Message as Entity).ID},Name={(context.Message as Entity).Name},Time={(context.Message as Entity).Time}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--------------------------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> Task PostSend&lt;T&gt;(SendContext&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)"> context)
      </span><span style="color: rgba(0, 0, 255, 1)">where</span> T : <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">
    {
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">------------------PostSend--------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ID={ (context.Message as Entity).ID},Name={(context.Message as Entity).Name},Time={(context.Message as Entity).Time}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--------------------------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> Task SendFault&lt;T&gt;(SendContext&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)"> context, Exception exception)
      </span><span style="color: rgba(0, 0, 255, 1)">where</span> T : <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">
    {
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">------------------SendFault--------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine($</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ID={ (context.Message as Entity).ID},Name={(context.Message as Entity).Name},Time={(context.Message as Entity).Time}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      Console.WriteLine(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--------------------------------------</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Task.CompletedTask;
    }
}</span></pre>
</div>
</li>
<li>效果展示<br>Publish:<br>
<div class="cnblogs_code"><img id="code_img_closed_9c4dfe94-168b-48c5-9c19-d909f2923a79" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_9c4dfe94-168b-48c5-9c19-d909f2923a79" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_9c4dfe94-168b-48c5-9c19-d909f2923a79" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 0, 1)">请出请按q,否则请按其他键!
</span><span style="color: rgba(128, 0, 128, 1)">111111</span><span style="color: rgba(0, 0, 0, 1)">
请出请按q,否则请按其他键!
</span>------------------PrePublish--------------------<span style="color: rgba(0, 0, 0, 1)">
ID</span>=<span style="color: rgba(128, 0, 128, 1)">1</span>,Name=张三,Time=<span style="color: rgba(128, 0, 128, 1)">2019</span>/<span style="color: rgba(128, 0, 128, 1)">5</span>/<span style="color: rgba(128, 0, 128, 1)">2</span> <span style="color: rgba(128, 0, 128, 1)">12</span>:<span style="color: rgba(128, 0, 128, 1)">23</span>:<span style="color: rgba(128, 0, 128, 1)">23</span>
--------------------------------------
------------------PreSend--------------------<span style="color: rgba(0, 0, 0, 1)">
ID</span>=<span style="color: rgba(128, 0, 128, 1)">1</span>,Name=张三,Time=<span style="color: rgba(128, 0, 128, 1)">2019</span>/<span style="color: rgba(128, 0, 128, 1)">5</span>/<span style="color: rgba(128, 0, 128, 1)">2</span> <span style="color: rgba(128, 0, 128, 1)">12</span>:<span style="color: rgba(128, 0, 128, 1)">23</span>:<span style="color: rgba(128, 0, 128, 1)">23</span>
--------------------------------------
------------------PostSend--------------------<span style="color: rgba(0, 0, 0, 1)">
ID</span>=<span style="color: rgba(128, 0, 128, 1)">1</span>,Name=张三,Time=<span style="color: rgba(128, 0, 128, 1)">2019</span>/<span style="color: rgba(128, 0, 128, 1)">5</span>/<span style="color: rgba(128, 0, 128, 1)">2</span> <span style="color: rgba(128, 0, 128, 1)">12</span>:<span style="color: rgba(128, 0, 128, 1)">23</span>:<span style="color: rgba(128, 0, 128, 1)">23</span>
--------------------------------------
------------------PostPublish--------------------<span style="color: rgba(0, 0, 0, 1)">
ID</span>=<span style="color: rgba(128, 0, 128, 1)">1</span>,Name=张三,Time=<span style="color: rgba(128, 0, 128, 1)">2019</span>/<span style="color: rgba(128, 0, 128, 1)">5</span>/<span style="color: rgba(128, 0, 128, 1)">2</span> <span style="color: rgba(128, 0, 128, 1)">12</span>:<span style="color: rgba(128, 0, 128, 1)">23</span>:<span style="color: rgba(128, 0, 128, 1)">23</span>
--------------------------------------</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
Subscribe:<br>
<div class="cnblogs_code"><img id="code_img_closed_32ba736c-3126-43e4-ae3f-ea63ab5a83ab" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_32ba736c-3126-43e4-ae3f-ea63ab5a83ab" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_32ba736c-3126-43e4-ae3f-ea63ab5a83ab" class="cnblogs_code_hide">
<pre>------------------PreReceive--------------------<span style="color: rgba(0, 0, 0, 1)">
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">messageId</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">36500000-a632-9828-3029-08d6ceb5ea32</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">conversationId</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">36500000-a632-9828-ef7f-08d6ceb5ea37</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">sourceAddress</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/bus-DESKTOP-PUOA6D7-dotnet-g3eyyyfggkcnt4wdbdmc7pxgn4?durable=false&amp;autodelete=true</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">destinationAddress</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/ObserverSubscriber:Entity</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">messageType</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">urn:message:ObserverSubscriber:Entity</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
],
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">message</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">age</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">time</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">2019-05-02T12:23:23.2223222+08:00</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
},
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">sentTime</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">2019-05-02T04:23:23.3522586Z</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">headers</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {},
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">host</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">machineName</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DESKTOP-PUOA6D7</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">processName</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dotnet</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">processId</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">25668</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">assembly</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ObserverPublish</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">assemblyVersion</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1.0.0.0</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">frameworkVersion</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">4.0.30319.42000</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">massTransitVersion</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">4.1.0.1470</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">operatingSystemVersion</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Microsoft Windows NT 6.2.9200.0</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}
}
</span>--------------------------------------<span style="color: rgba(0, 0, 0, 1)">
IEntityConsumer 类型 ObserverSubscriber.Entity </span><span style="color: rgba(128, 0, 128, 1)">1</span> <span style="color: rgba(128, 0, 128, 1)">10</span> 张三 <span style="color: rgba(128, 0, 128, 1)">2019</span>/<span style="color: rgba(128, 0, 128, 1)">5</span>/<span style="color: rgba(128, 0, 128, 1)">2</span> <span style="color: rgba(128, 0, 128, 1)">12</span>:<span style="color: rgba(128, 0, 128, 1)">23</span>:<span style="color: rgba(128, 0, 128, 1)">23</span>
------------------PostConsume--------------------<span style="color: rgba(0, 0, 0, 1)">
ID</span>=<span style="color: rgba(128, 0, 128, 1)">1</span>,Name=张三,Time=<span style="color: rgba(128, 0, 128, 1)">2019</span>/<span style="color: rgba(128, 0, 128, 1)">5</span>/<span style="color: rgba(128, 0, 128, 1)">2</span> <span style="color: rgba(128, 0, 128, 1)">12</span>:<span style="color: rgba(128, 0, 128, 1)">23</span>:<span style="color: rgba(128, 0, 128, 1)">23</span>
--------------------------------------
-----------------PostReceive---------------------<span style="color: rgba(0, 0, 0, 1)">
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">messageId</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">36500000-a632-9828-3029-08d6ceb5ea32</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">conversationId</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">36500000-a632-9828-ef7f-08d6ceb5ea37</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">sourceAddress</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/bus-DESKTOP-PUOA6D7-dotnet-g3eyyyfggkcnt4wdbdmc7pxgn4?durable=false&amp;autodelete=true</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">destinationAddress</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rabbitmq://localhost/ObserverSubscriber:Entity</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">messageType</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">urn:message:ObserverSubscriber:Entity</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
],
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">message</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">age</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">time</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">2019-05-02T12:23:23.2223222+08:00</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
},
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">sentTime</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">2019-05-02T04:23:23.3522586Z</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">headers</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {},
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">host</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">machineName</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DESKTOP-PUOA6D7</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">processName</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dotnet</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">processId</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">25668</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">assembly</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ObserverPublish</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">assemblyVersion</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1.0.0.0</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">frameworkVersion</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">4.0.30319.42000</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">massTransitVersion</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">4.1.0.1470</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">operatingSystemVersion</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Microsoft Windows NT 6.2.9200.0</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}
}
</span>--------------------------------------</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
</li>
</ul>
<h3>7.9、数据一致性示例</h3>
<p>详见:https://github.com/786744873/DataConsistentSample</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502150820093-1882337153.png" alt=""></p>
<p>&nbsp;</p>
<h2>8、Jenkins</h2>
<p>官方地址:https://jenkins.io/</p>
<p>Jenkins 是一款流行的开源持续集成(CI)与持续部署(CD)工具,广泛用于项目开发,具有自动化构建、测试和部署等功能。</p>
<p>  使用Jenkins的目的在于:</p>
<p>  (1)持续、自动地构建/测试软件项目。&nbsp;<br>  (2)监控软件开放流程,快速问题定位及处理,提升开发效率。</p>
<h3>8.1、Jenkins下载与安装</h3>
<p>这里我们下载Windows版本的</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502144039416-1787127423.png" alt="" width="279" height="348"></p>
<p>安装完成后会提示我们解锁 Jenkins</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502144129350-812381050.png" alt="" width="600" height="227"></p>
<p>这里选择<strong>安装推荐的插件</strong></p>
<p><strong><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502144630958-1135438208.png" alt="" width="623" height="347"></strong></p>
<p>创建管理账户 =&gt; 也可以直接使用admin账户继续</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502144924052-807312107.png" alt="" width="477" height="261"></p>
<p>配置Jenkins端口,默认8080,最好不要使用8080端口</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502145056594-1826837638.png" alt=""></p>
<p>修改Jenkins服务端口,改为8080--&gt;8081</p>
<p>修改安装目录下&nbsp;<span class="cnblogs_code">jenkins.xml</span>&nbsp;文件</p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502150113989-1735383372.png" alt=""></p>
<p>然后重启Jenkins服务</p>
<h3>8.2、持续集成Asp.Net Core项目</h3>
<ol>
<li>我们以Github上面的项目为例,github项目地址:https://github.com/786744873/first.git<br><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502150348868-767818407.png" alt="" width="672" height="629"></li>
<li>配置源代码<br><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502151219544-1190187689.png" alt=""></li>
<li>构建触发器(这里每半小时轮询一次)<br><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502151319994-2032373751.png" alt=""></li>
<li>构建<br><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502151408267-770870170.png" alt=""><br><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502151819149-1933047932.png" alt=""><br><br>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">cd CITest
cd CITest
dotnet restore
dotnet build
dotnet publish </span>-o <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">bin\Debug\netcoreapp2.0\publish</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
cd bin\Debug\netcoreapp2.</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">\publish
docker rm clitest </span>-<span style="color: rgba(0, 0, 0, 1)">f
docker rmi clitest </span>-<span style="color: rgba(0, 0, 0, 1)">f
docker build </span>-<span style="color: rgba(0, 0, 0, 1)">t clitest:latest .
docker run </span>-p <span style="color: rgba(128, 0, 128, 1)">4555</span>:<span style="color: rgba(128, 0, 128, 1)">4555</span> -d --name clitest clitest:latest</pre>
</div>
</li>
<li>保存,然后去配置构建邮件发送<br>Jenkins-&gt;系统管理-&gt;系统设置<br>设置系统管理员收件地址(实际上这边配置的是发件人的邮箱地址):<br><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502201459459-2052889206.png" alt="">
<p><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502201613057-1867497362.png" alt=""></p>
<p>&nbsp;</p>





</li>
<li>
<p>继续进行项目配置<br><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502202158887-1381426956.png" alt=""></p>
<p><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502202234050-1793733017.png" alt=""></p>





</li>
<li>构建项目<br><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502204128092-427450230.png" alt="">
<p><img src="https://img2018.cnblogs.com/blog/991704/201905/991704-20190502204354741-604278101.png" alt=""></p>
<p>&nbsp;</p>


</li>





</ol>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    <div>作者:一个大西瓜</div>
<div>出处:https://www.cnblogs.com/wyt007/
</div>
<p>-------------------------------------------</p>
<p>个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!</p>
<p>如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个<span>“推荐”</span>哦,博主在此感谢!</p>
<p></p>
<p>万水千山总是情,打赏一分行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主,哈哈哈(っ•̀ω•́)っ✎⁾⁾!</p>
<div align="left">
        <img src="https://www.cnblogs.com/images/cnblogs_com/wyt007/1375409/t_alipay.bmp">
        <img src="https://www.cnblogs.com/images/cnblogs_com/wyt007/1375409/t_wxpay.bmp">
</div><br><br>
来源:https://www.cnblogs.com/wyt007/p/10631109.html
頁: [1]
查看完整版本: 基于.net core微服务(Consul、Ocelot、Docker、App.Metrics+InfluxDB+Grafana、Exceptionless、数据一致性、Jenkins)