前言
《牧神記》有一句話說的好,破心中神。當(dāng)不再對(duì)分布式飒箭,微服務(wù),CLR畏懼迷茫的時(shí)候蜒灰,你就破了心中神弦蹂。
zipkin復(fù)習(xí)
上篇NetCore實(shí)踐篇:分布式監(jiān)控客戶端ZipkinTracer從入門到放棄之路,我們提到了zipkin的原理和架構(gòu)說明,以及用zipkintracer實(shí)踐失敗的記錄强窖。
今天我們來復(fù)習(xí)下凸椿。
zipkin作用
全鏈路追蹤工具(根據(jù)依賴關(guān)系)
查看每個(gè)接口、每個(gè)service的執(zhí)行速度(定位問題發(fā)生點(diǎn)或者尋找性能瓶頸)
zipkin工作原理
創(chuàng)造一些追蹤標(biāo)識(shí)符(tracingId翅溺,spanId脑漫,parentId)髓抑,最終將一個(gè)request的流程樹構(gòu)建出來
zipkin架構(gòu)
Collector接收各service傳輸?shù)臄?shù)據(jù);
Cassandra作為Storage的一種窿撬,默認(rèn)存儲(chǔ)在內(nèi)存中启昧,也支持ElasticSearch和mysql用于生產(chǎn)落庫;
Query負(fù)責(zé)查詢Storage中存儲(chǔ)的數(shù)據(jù),提供簡(jiǎn)單的JSON API獲取數(shù)據(jù)劈伴,主要提供給web UI使用密末;
Web 提供簡(jiǎn)單的web界面;
zipkin分布式跟蹤系統(tǒng)的目的
zipkin為分布式鏈路調(diào)用監(jiān)控系統(tǒng)跛璧,聚合各業(yè)務(wù)系統(tǒng)調(diào)用延遲數(shù)據(jù)严里,達(dá)到鏈路調(diào)用監(jiān)控跟蹤;
zipkin通過采集跟蹤數(shù)據(jù)可以幫助開發(fā)者深入了解在分布式系統(tǒng)中某一個(gè)特定的請(qǐng)求時(shí)如何執(zhí)行的追城;
參考如下
zipkin4net簡(jiǎn)介
zipkin4net是.NET客戶端庫刹碾。
它為您提供:
Zipkin 原語(跨度,注釋座柱,二進(jìn)制注釋迷帜,......)【Zipkin primitives (spans, annotations, binary annotations, ...)】
異步跟蹤發(fā)送
跟蹤傳輸抽象
簡(jiǎn)單用法
var logger = CreateLogger(); //它應(yīng)該實(shí)現(xiàn)ILogger
var sender = CreateYourTransport(); //它應(yīng)該實(shí)現(xiàn)IZipkinSender
TraceManager.SamplingRate = 1.0f; //全監(jiān)控
var tracer = new ZipkinTracer(sender);
TraceManager.RegisterTracer(tracer);
TraceManager.Start(logger);
//運(yùn)行你的程序
//當(dāng)關(guān)閉時(shí)。
TraceManager.Stop();
簡(jiǎn)介到此為止色洞,剩余您可參考zipkin4net戏锹。
Show me the Code
廢話少說,一杯代碼為敬火诸。
進(jìn)入代碼之前锦针,我先來演示下代碼結(jié)構(gòu)。這個(gè)結(jié)構(gòu)對(duì)應(yīng)我之前的代碼實(shí)踐置蜀。內(nèi)存隊(duì)列奈搜,爬蟲在我的博客內(nèi)都能找到博客對(duì)應(yīng)。
今天我們只說zipkin4Net的實(shí)踐盯荤。為了測(cè)試查看zipkin是否能夠匯集不同的站點(diǎn),我特意建立了兩個(gè)站點(diǎn)Demo.ZipKinWeb和Demo.ZipKinWeb2馋吗。類似下圖:
為了能真實(shí)落庫,我創(chuàng)建了FanQuick.Repository,用于提供mongodb存儲(chǔ)幫助秋秤。IRepository泛型接口聲明如下
namespace FanQuick.Repository
{
public interface IRepository<TDocument> where TDocument:EntityBase
{
IQueryable<TDocument> Queryable { get; }
bool Any(Expression<Func<TDocument, bool>> filter);
/// <summary>
/// 刪除
/// </summary>
/// <param name="filter"></param>
/// <returns></returns>
bool Delete(Expression<Func<TDocument, bool>> filter);
/// <summary>
/// 查詢
/// </summary>
/// <param name="filter"></param>
/// <returns></returns>
IEnumerable<TDocument> Find(Expression<Func<TDocument, bool>> filter);
/// <summary>
/// 新增
/// </summary>
/// <param name="document"></param>
void Insert(TDocument document);
/// <summary>
/// 批量插入
/// </summary>
/// <param name="documents"></param>
void Insert(IEnumerable<TDocument> documents);
/// <summary>
/// 統(tǒng)計(jì)宏粤。
/// </summary>
/// <param name="filter"></param>
/// <returns></returns>
long Count(Expression<Func<TDocument, bool>> filter);
TDocument FindOneAndDelete(Expression<Func<TDocument, bool>> filter);
TDocument FindOneAndUpdate(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update);
}
}
為了兩個(gè)站點(diǎn)能夠復(fù)用調(diào)用zipkin4net的通知,我將代碼抽離出來放到了 Demo.ZipkinCommon航缀。
可復(fù)用的抽象類CommonStartUp,代碼如下:重點(diǎn)關(guān)注下調(diào)用zipkin4net的代碼堰怨。并將抽象Run方法暴漏給了子類芥玉,需要子類實(shí)現(xiàn)。要特別注意备图,appsettings.json需要設(shè)置applicationName,不然發(fā)送到zipkin就是未命名服務(wù)灿巧,這就不能區(qū)分站點(diǎn)了!
namespace Demo.ZipkinCommon
{
public abstract class CommonStartup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public abstract void ConfigureServices(IServiceCollection services);
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
var config = ConfigureSettings.CreateConfiguration();
var applicationName = config["applicationName"];
//if (env.IsDevelopment())
//{
// app.UseDeveloperExceptionPage();
//}
//else
//{
// app.UseExceptionHandler("/Home/Error");
// app.UseHsts();
//}
var lifetime = app.ApplicationServices.GetService<IApplicationLifetime>();
lifetime.ApplicationStarted.Register(() =>
{
TraceManager.SamplingRate = 1.0f;
var logger = new TracingLogger(loggerFactory, "zipkin4net");
var httpSender = new HttpZipkinSender("http://weixinhe.cn:9411", "application/json");
var tracer = new ZipkinTracer(httpSender, new JSONSpanSerializer());
TraceManager.RegisterTracer(tracer);
TraceManager.Start(logger);
});
lifetime.ApplicationStopped.Register(() => TraceManager.Stop());
app.UseTracing(applicationName);
Run(app, config);
}
protected abstract void Run(IApplicationBuilder app, IConfiguration configuration);
}
}
讀取配置類赶袄,也獨(dú)立了出來,可支持讀取appsettings.json抠藕,每個(gè)站點(diǎn)需要把a(bǔ)ppsettings.json設(shè)置允許復(fù)制饿肺,不然會(huì)找不到文件!盾似!
namespace Demo.ZipkinCommon
{
public class ConfigureSettings
{
public static IConfiguration CreateConfiguration()
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
return builder.Build();
}
}
}
公用部分完成了敬辣。我們看看站點(diǎn)Demo.ZipKinWeb代碼。Startup繼承抽象類CommonStartup零院,并利用.netCore內(nèi)置依賴注入溉跃,將Service和倉(cāng)儲(chǔ)注入進(jìn)來。由于不支持直接注入泛型告抄,但支持type類型的注入撰茎,間接也解決了泛型注入問題。關(guān)于依賴注入的講解打洼,你可以參考上篇文中依賴注入部分龄糊,加深理解。
namespace Demo.ZipKinWeb
{
public class Startup : CommonStartup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public override void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddScoped(typeof(IRepository<>), typeof(BaseRepository<>));
services.AddScoped<IUserService, UserService>();
services.AddScoped<IAddressService, AddressService>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
protected override void Run(IApplicationBuilder app, IConfiguration configuration)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
為了實(shí)現(xiàn)聚合兩個(gè)站點(diǎn)的效果募疮,在Add的方法內(nèi)炫惩,特意調(diào)用一下另外個(gè)站點(diǎn)的get
[HttpPost]
public IActionResult Add([FromBody]User user)
{
_userService.AddUser(user);
//模擬調(diào)用其他站點(diǎn)請(qǐng)求。
var client = new RestClient($"{ConfigEx.WebSite}");
var request = new RestRequest($"/user/get", Method.POST);
request.AddParameter("id", user.Id); // adds to POST or URL querystring based on Method
IRestResponse response = client.Execute(request);
var content = response.Content;
// return Json(new { data = content });
return Content(content+_addressService.Test());
}
建好必要的Controller和Action后酝锅,將兩個(gè)站點(diǎn)都設(shè)為已啟動(dòng)诡必。就可以查看效果了。
postman是個(gè)測(cè)試接口的好工具搔扁,點(diǎn)擊Send爸舒。
打開我們的zipkin服務(wù)器鏈接,在WebUI上稿蹲,可以看到兩條請(qǐng)求數(shù)據(jù)扭勉。這是正確的,一條是Add,里面又調(diào)了另外一個(gè)站點(diǎn)的get,也能看到消耗的時(shí)間苛聘。
點(diǎn)擊去查看詳情涂炎,我們能看到更多數(shù)據(jù)。
然后繼續(xù)點(diǎn)擊 菜單中的Dependencies设哗,確發(fā)現(xiàn)是空值唱捣,按道理來講,請(qǐng)求了兩個(gè)站點(diǎn)网梢,又訪問了數(shù)據(jù)庫震缭。怎么會(huì)是空值呢?战虏?拣宰?
這個(gè)時(shí)候党涕,我只能又求助bing了。
zipkin Dependencies no data
果然網(wǎng)友是萬能的巡社。elasticsearch存儲(chǔ),zipkin依賴沒有數(shù)據(jù)
里面有位外國(guó)同仁提到了
當(dāng)你用你elasticsearch 或 Cassandra的時(shí)候膛堤,需要執(zhí)行zipkin-dependencies
(you need to run https://github.com/openzipkin/zipkin-dependencies when using elasticsearch or Cassandra)
zipkin-dependencies簡(jiǎn)介
這是一個(gè)Spark作業(yè),它將從您的數(shù)據(jù)存儲(chǔ)區(qū)收集跨度晌该,分析服務(wù)之間的鏈接肥荔,并存儲(chǔ)它們以供以后在Web UI中呈現(xiàn)(例如http://localhost:8080/dependency)。
什么是Spark?
Apache Spark 是專為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎气笙。
此作業(yè)以UTC時(shí)間分析當(dāng)天的所有跟蹤次企。這意味著您應(yīng)該將其安排在UTC午夜之前運(yùn)行。
支持所有Zipkin 存儲(chǔ)組件潜圃,包括Cassandra缸棵,MySQL和Elasticsearch。
這真是一個(gè)弱雞的設(shè)計(jì)谭期,作為內(nèi)存運(yùn)行的演示堵第,竟然不提供及時(shí)匯總分析,還要跑定時(shí)任務(wù)
依據(jù)官方提示隧出,按最快的方式進(jìn)行踏志。
wget -O zipkin-dependencies.jar 'https://search.maven.org/remote_content?g=io.zipkin.dependencies&a=zipkin-dependencies&v=LATEST'
STORAGE_TYPE=cassandra3 java -jar zipkin-dependencies.jar
或者用Docker啟動(dòng)
docker run --env STORAGE_TYPE=cassandra3 --env CASSANDRA_CONTACT_POINTS=host1,host2 openzipkin/zipkin-dependencies
用法
默認(rèn)情況下,此作業(yè)解析自UTC午夜以來的所有跟蹤胀瞪。您可以通過YYYY-mm-dd格式的參數(shù)解析不同日期的跟蹤针余,如2016-07-16。
# ex to run the job to process yesterday's traces on OS/X
STORAGE_TYPE=cassandra3 java -jar zipkin-dependencies.jar `date -uv-1d +%F`
# or on Linux
STORAGE_TYPE=cassandra3 java -jar zipkin-dependencies.jar `date -u -d '1 day ago' +%F`
執(zhí)行失敗
STORAGE_TYPE=cassandra3 java -jar zipkin-dependencies.jar `date -u -d '1 day ago' +%F`
18/09/14 20:24:50 INFO CassandraDependenciesJob: Running Dependencies job for 2018-09-13: 1536796800000000 ≤ Span.timestamp 1536883199999999
18/09/14 20:24:50 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
18/09/14 20:24:51 ERROR SparkContext: Error initializing SparkContext.
java.lang.IllegalArgumentException: System memory 466288640 must be at least 471859200. Please increase heap size using the --driver-memory option or spark.driver.memory in Spark configuration.
at org.apache.spark.memory.UnifiedMemoryManager$.getMaxMemory(UnifiedMemoryManager.scala:217)
at org.apache.spark.memory.UnifiedMemoryManager$.apply(UnifiedMemoryManager.scala:199)
at org.apache.spark.SparkEnv$.create(SparkEnv.scala:330)
at org.apache.spark.SparkEnv$.createDriverEnv(SparkEnv.scala:175)
at org.apache.spark.SparkContext.createSparkEnv(SparkContext.scala:256)
at org.apache.spark.SparkContext.<init>(SparkContext.scala:423)
at zipkin2.dependencies.cassandra3.CassandraDependenciesJob.run(CassandraDependenciesJob.java:181)
at zipkin2.dependencies.ZipkinDependenciesJob.main(ZipkinDependenciesJob.java:57)
Exception in thread "main" java.lang.IllegalArgumentException: System memory 466288640 must be at least 471859200. Please increase heap size using the --driver-memory option or spark.driver.memory in Spark configuration.
at org.apache.spark.memory.UnifiedMemoryManager$.getMaxMemory(UnifiedMemoryManager.scala:217)
at org.apache.spark.memory.UnifiedMemoryManager$.apply(UnifiedMemoryManager.scala:199)
at org.apache.spark.SparkEnv$.create(SparkEnv.scala:330)
at org.apache.spark.SparkEnv$.createDriverEnv(SparkEnv.scala:175)
at org.apache.spark.SparkContext.createSparkEnv(SparkContext.scala:256)
at org.apache.spark.SparkContext.<init>(SparkContext.scala:423)
at zipkin2.dependencies.cassandra3.CassandraDependenciesJob.run(CassandraDependenciesJob.java:181)
at zipkin2.dependencies.ZipkinDependenciesJob.main(ZipkinDependenciesJob.java:57)
意思是系統(tǒng)內(nèi)存太小了凄诞。圆雁。。渣渣帆谍。
搜索到相關(guān)鏈接伪朽,如下:
Zipkin 使用api調(diào)用沒有數(shù)據(jù) Zipkin api traces為空
Zinkin進(jìn)階篇-Zipkin-dependencies的應(yīng)用
zipkin提供的接口標(biāo)準(zhǔn)
spark內(nèi)存介紹
更簡(jiǎn)易的格式顯示內(nèi)存錯(cuò)誤信息
ERROR SparkContext: Error initializing SparkContext.
System memory..must be at least ... Please use a larger heap
spark 內(nèi)存管理
如何設(shè)置spark.executor.memory和堆大小
Spark Misconceptions
如何在Eclispe環(huán)境中設(shè)置spark的堆大小汛蝙?
里面似乎有個(gè)有用的答案
您可以通過編輯“ {SPARK_HOME} / conf /”坚洽,但是有一個(gè)文件“spark-defaults.conf.template”,您可以使用以下命令創(chuàng)建“spark-defaults.conf”文件:
cp spark-defaults.conf.template spark-defaults.conf
然后西土,編輯它:
# Example:
# spark.master spark://master:7077
# spark.eventLog.enabled true
# spark.eventLog.dir hdfs://namenode:8021/directory
# spark.serializer org.apache.spark.serializer.KryoSerializer
# spark.driver.memory 5g
# spark.executor.extraJavaOptions -XX:+PrintGCDetails -Dkey=value -Dnumbers="one two three"
spark.driver.memory
但我沒查到SPARK_HOME的環(huán)境變量讶舰。
Linux下設(shè)置和查看環(huán)境變量
繼續(xù)調(diào)整工作重心。
java.lang.IllegalArgumentException:系統(tǒng)內(nèi)存
里面作者或網(wǎng)友提到:
gc是可選的JAVA_OPTS=-verbose:gc -Xms1G -Xmx1G,https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html#BABDJJFI
JAVA_OPTS的一些介紹
JAVA_OPTS設(shè)置
談一談JVM內(nèi)存JAVA_OPTS參數(shù)
Tomcat之——內(nèi)存溢出設(shè)置JAVA_OPTS
JAVA_OPTS參數(shù)說明與配置
按照以上操作修改仍未成功。绘雁。。有某位仁兄知道處理辦法援所,可否告知庐舟?
罷了,罷了住拭,不留個(gè)尾巴挪略,怎么能引起我的求知欲。原本只是想簡(jiǎn)簡(jiǎn)單單看看zipkin,卻邁向了Spark,JVM之路滔岳,留個(gè)問題待以后深思杠娱。
下篇將繼續(xù)zipkin熟悉之路,持久化mysql,還有今天未結(jié)束的主題谱煤,zipkin-dependencies
總結(jié)
標(biāo)題是.NetCore,大部分是在找java問題摊求,我也是醉了。沒辦法用的監(jiān)控是java開源的刘离,不要抱怨室叉,繼續(xù)研究。這應(yīng)該是個(gè)小問題硫惕。這就是寫博客擴(kuò)展的學(xué)習(xí)范圍茧痕,原本不在我的計(jì)劃之類。堅(jiān)持就有收獲恼除,至少我現(xiàn)在知道了Spark的一些介紹踪旷,jvm的一些參數(shù)。
感謝觀看豁辉,本篇結(jié)束令野。